├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── AUTHORS.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bin └── update-authors.sh ├── docs ├── create-cycle-app.png └── npm-start.png ├── lerna.json ├── package.json └── packages ├── create-cycle-app ├── CHANGELOG.md ├── README.md ├── index.js ├── package.json ├── src │ ├── createApp.js │ ├── createAppDir.js │ ├── createPackageJson.js │ ├── getPackageName.js │ ├── initQuestions.js │ ├── installScripts.js │ ├── isSafeToCreateApp.js │ └── shouldUseYarn.js └── test │ ├── integration │ ├── __snapshots__ │ │ └── createCycleApp.spec.js.snap │ └── createCycleApp.spec.js │ └── unit │ ├── createAppDir.spec.js │ ├── createPackageJson.spec.js │ ├── getPackageName.spec.js │ ├── initQuestions.spec.js │ ├── installScripts.spec.js │ └── isSafeToCreateApp.spec.js └── cycle-scripts ├── LICENSE ├── README.md ├── configs ├── dependencies.js ├── javascript │ ├── webpack.config.dev.js │ └── webpack.config.prod.js ├── typescript │ ├── webpack.config.dev.js │ └── webpack.config.prod.js └── webpackDevServer.config.js ├── index.js ├── package.json ├── scripts ├── build.js ├── eject.js ├── init.js ├── init │ ├── questions.js │ ├── setup.js │ └── success.js ├── start.js ├── test.js └── utils │ └── createWebpackCompiler.js └── template ├── config ├── javascript.js └── typescript.js ├── custom-typings.d.ts ├── gitignore ├── public ├── favicon.ico ├── favicon.png └── index.html ├── src ├── javascript │ ├── app.jsx │ ├── app.test.js │ └── index.js └── typescript │ ├── app.test.ts │ ├── app.tsx │ ├── index.ts │ └── interfaces.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Code to reproduce the issue:** 2 | 3 | 4 | **Expected behavior:** 5 | 6 | 7 | **Actual behavior:** 8 | 9 | 10 | **Versions of packages used:** 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | - [ ] I ran `npm test` for the package I'm modifying 7 | - [ ] I used `npm run commit` instead of `git commit` 8 | - [ ] I have rebased my branch onto master before merging 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | 4 | # Dependency directories 5 | node_modules 6 | 7 | # OS fs specifics 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'node' 4 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Authors 2 | 3 | #### Ordered by first contribution. 4 | 5 | - Geovani de Souza (geovanisouza92@gmail.com) 6 | - Nick Johnstone (ncwjohnstone@gmail.com) 7 | - Nick Balestra (nick@balestra.ch) 8 | - Cesar Figueroa (cesar.figueroa@me.com) 9 | - Justin Zimmerman (jzimmerman@redventures.com) 10 | - Steve Lee (steve@opendirective.com) 11 | 12 | #### Generated by bin/update-authors.sh. 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | First of all, thank you for contributing. It’s appreciated. 2 | 3 | # To submit a pull request 4 | 5 | 1. Open a GitHub issue before doing significant amount of work. 6 | 2. Clone the repo. If it was already cloned, then git pull to get the latest from master. 7 | 4. Run `npm install`. 8 | 5. Write code. 9 | 6. Run `npm test` to lint and test. Don’t commit before fixing all errors and warnings. 10 | 7. Commit using `npm run commit` and follow the CLI instructions. 11 | 8. Make a pull request. 12 | 13 | # To release new versions 14 | 15 | 1. Check that you have npm publishing rights before anything else. 16 | 2. Run `npm run check-release`. 17 | 3. Run `npm run release`. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2016-present, Geovani Souza 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Create Cycle App 2 | 3 | Create [Cycle.js](https://cycle.js.org/) apps with no build configuration. 4 | 5 | * [Principles](#principles) – The philosophy behind create-cycle-app 6 | * [Why Use This](#why-use-this) – When to use create-cycle-app 7 | * [Getting Started](#getting-started) – How to create a new app. 8 | * [Custom Flavors](#flavors) – How to develop and publish new flavors 9 | 10 | ## Quick Start 11 | 12 | ```sh 13 | $ npm install -g create-cycle-app 14 | $ create-cycle-app my-awesome-cycle-app 15 | ``` 16 | 17 | Once your app has been created a success message with further info will be displayed: 18 | 19 | create-cycle-app-success 20 | 21 | Then, simply follow the suggestion in your terminal and type: 22 | 23 | ```sh 24 | $ cd my-awesome-cycle-app/ 25 | $ npm start 26 | ``` 27 | 28 | ’npm-start’ 29 | 30 | Open your browser at [http://localhost:8000](http://localhost:8000) to see your app. 31 | 32 | Once you’re ready to deploy to production, create a minified bundle with 33 | 34 | ```sh 35 | $ npm run build 36 | ``` 37 | 38 | ## Principles 39 | 40 | * **One dependency:** The first and only dependency needed to create a Cycle.js project, hiding tooling complexity and providing smart defaults. Just update `create-cycle-app` to get selected changes to the core flavors. 41 | 42 | * **Zero Configuration:** There are no configuration files. Configuring both development and production builds is handled for you so you can focus on writing code. 43 | 44 | * **Many Flavors:** We like to be together not the same, that’s why create-cycle-app comes with 1 core flavors but allows you to provide your own from any registry such as GitHub or your own. 45 | 46 | * **No Lock-In:** Specifically made for beginners and to provide fast bootstrap for new projects, create-cycle-app doesn't have the ambition to be __the__ tool for working with Cycle.js projects. With that in mind, it's easy to leave `create-cycle-app` defaults and follow your own steps, by running `npm run eject`. 47 | 48 | ## Why Use This? 49 | 50 | **If you’re getting started** with Cycle.js, use `create-cycle-app` to automate the build of your app. There is no configuration file, and `cycle-scripts-` is the only extra build dependency in your `package.json`. Your environment will have everything you need to build a Cycle.js app. 51 | 52 | **If you’re a power user** simply use it as a boilerplate generator, by passing in your own flavor. 53 | 54 | 55 | ## Getting Started 56 | 57 | ### Installation 58 | 59 | Installing globally provides a create-cycle-app command for creating new projects. 60 | 61 | ```sh 62 | $ npm install --g create-cycle-app 63 | ``` 64 | 65 | **We recommend** to use Node >= 6 and npm >= 3 for faster installation speed and better disk usage. You can use a node version manager(i.e [nodenv](https://github.com/nodenv/nodenv), [nvm](https://github.com/creationix/nvm), [n](https://github.com/tj/n)) to easily switch Node versions among different projects. 66 | 67 | ### Creating an App 68 | 69 | To create a new cycle.js app, run: 70 | 71 | ``` 72 | $ create-cycle-app my-awesome-cycle-app 73 | $ cd my-awesome-cycle-app 74 | ``` 75 | 76 | It will create a directory called `my-awesome-cycle-app` inside the current folder. 77 | Inside that directory, it will generate the following initial project structure* and install the required dependencies. 78 | 79 | ``` 80 | my-awesome-cycle-app/ 81 | ├── node_modules/ 82 | ├── public/ 83 | │ ├── favicon.ico 84 | │ └── index.html 85 | ├── src/ 86 | │ ├── app.js 87 | │ ├── app.test.js 88 | │ └── index.js 89 | └── package.json 90 | ``` 91 | 92 | _* Generated structure and files may change depending on the flavor being used, The above structure hold true for the core flavor._ 93 | 94 | No configuration or complicated folder structures, just the files you need to build your cycle app. 95 | Once the installation is done, you can run the following commands from within the project folder: 96 | 97 | ### `npm start` 98 | 99 | Runs the app in development mode by starting the development server. 100 | 101 | Server will be listening on port 8000 102 | 103 | ### `npm test` 104 | Run the default test tool. 105 | 106 | (Some flavors could create a test folder, but this folder is gitignored) 107 | 108 | ### `npm run build` 109 | 110 | Generate a production-ready build content, on the build folder (this folder is gitignored) 111 | 112 | ### `npm run eject` 113 | 114 | Copy dependencies and configurations to the project folder, update package.json and remove the dependency on the flavored cycle-scripts. 115 | 116 | **This is irreversible.** 117 | 118 | ## Flavors 119 | Each flavor represents a pair of programming language and builds tool. All the underlying dependencies and configuration are hidden behind the flavor. All flavors must adhere to the same basic structure and commands. Please make sure to check a specific flavor documentation for more details. 120 | 121 | ### Core flavor 122 | 123 | Create-cycle-app come packed with 1 core flavor: 124 | 125 | * [cycle-scripts](https://github.com/cyclejs-community/create-cycle-app/blob/master/packages/cycle-scripts) 126 | 127 | ### Custom flavour 128 | 129 | Custom flavors allow generating starting projects to fulfil specific needs. 130 | They can be published to npm, or being used locally via the create-cycle-app CLI. 131 | 132 | #### How to use custom flavors 133 | 134 | ##### Providing your own 135 | When creating a project, you can inform which flavor you want to use with the `--flavor` flag: 136 | 137 | ```sh 138 | $ create-cycle-app --flavor 139 | ``` 140 | Some examples of how a flavor could be specified: 141 | 142 | ``` 143 | $ create-cycle-app my-app --flavor cycle-scripts-es-webpack 144 | 145 | $ create-cycle-app my-app --flavor cycle-scripts-es-webpack@x.y.z 146 | 147 | $ create-cycle-app my-app --flavor ./relative/path/to/cycle-scripts-es-webpack 148 | ``` 149 | 150 | ##### Flavors: 151 | 152 | - Check [available flavors](https://github.com/cyclejs-community/create-cycle-app-flavors) 153 | 154 | ## Contributing 155 | 156 | We'd love to have your help on `create-cycle-app`. See [CONTRIBUTING.md](CONTRIBUTING.md) for more information on what we're looking for and how to get started. 157 | 158 | ## Acknowledgements 159 | 160 | A simple thank you goes a long way. That's why we would like to thank the [create-react-app](https://github.com/facebookincubator/create-react-app) team: you have been a fantastic inspiration and a great example for this project. 161 | We would also like to thank the [standard project](https://github.com/feross/standard) for their update-authors script. 162 | 163 | ## Alternatives 164 | 165 | Create-cycle-app doesn't have the ambition to be __the__ tool for working with Cycle.js projects. You might want to explore alternatives. Check [awesome-cycle](https://github.com/cyclejs-community/awesome-cyclejs#boilerplates) for a list of boilerplates. 166 | -------------------------------------------------------------------------------- /bin/update-authors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Update AUTHORS.md based on git history. 3 | 4 | git log --reverse --format='%aN (%aE)' | perl -we ' 5 | BEGIN { 6 | %seen = (), @authors = (); 7 | } 8 | while (<>) { 9 | next if $seen{$_}; 10 | next if /(support\@greenkeeper.io)/; 11 | $seen{$_} = push @authors, "- ", $_; 12 | } 13 | END { 14 | print "# Authors\n\n"; 15 | print "#### Ordered by first contribution.\n\n"; 16 | print @authors, "\n"; 17 | print "#### Generated by bin/update-authors.sh.\n"; 18 | } 19 | ' > AUTHORS.md 20 | -------------------------------------------------------------------------------- /docs/create-cycle-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyclejs-community/create-cycle-app/32d60a5b6ac9fd9b4fab31eaf469d3e197036b90/docs/create-cycle-app.png -------------------------------------------------------------------------------- /docs/npm-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyclejs-community/create-cycle-app/32d60a5b6ac9fd9b4fab31eaf469d3e197036b90/docs/npm-start.png -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.0.0-beta.36", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "independent" 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-cycle-app", 3 | "version": "3.0.0", 4 | "description": "Create Cycle.js apps with zero configuration.", 5 | "private": true, 6 | "scripts": { 7 | "update-authors": "./bin/update-authors.sh", 8 | "precommit": "standard && npm run test", 9 | "postinstall": "lerna bootstrap", 10 | "test": "lerna run test", 11 | "publish": "lerna publish", 12 | "updated": "lerna updated" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/cyclejs-community/create-cycle-app.git" 17 | }, 18 | "author": "Geovani Souza ", 19 | "contributors": [ 20 | { 21 | "name": "Geovani Souza", 22 | "email": "geovanisouza92@gmail.com" 23 | }, 24 | { 25 | "name": "Nick Balestra", 26 | "email": "nick@balestra.ch" 27 | } 28 | ], 29 | "license": "ISC", 30 | "bugs": { 31 | "url": "https://github.com/cyclejs-community/create-cycle-app/issues" 32 | }, 33 | "homepage": "https://github.com/cyclejs-community/create-cycle-app#readme", 34 | "standard": { 35 | "globals": [ 36 | "describe", 37 | "test", 38 | "it", 39 | "expect", 40 | "jest", 41 | "beforeEach", 42 | "afterEach" 43 | ] 44 | }, 45 | "devDependencies": { 46 | "husky": "^0.13.1", 47 | "lerna": "2.0.0-beta.36", 48 | "standard": "^8.3.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/create-cycle-app/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v2.0.0 (2016-11-01) 2 | --- 3 | 4 | 5 | ## Breaking Changes 6 | 7 | - feat(create-cycle-app): Allow to select stream library only for core flavors [ea188047](https://github.com/cyclejs-community/create-cycle-app/commits/ea1880479f7e846fe1ff3eef388774ec74c383fb) 8 | 9 | 10 | # v1.0.0 (2016-10-21) 11 | --- 12 | 13 | 14 | ## Breaking Changes 15 | 16 | - feat(create-cycle-app): Removed communityFlavors registry [5031510e](https://github.com/cyclejs-community/create-cycle-app/commits/5031510e01f3774687d11c698d4de9844768ed91) 17 | - feat(create-cycle-app): Discovery now search for flavors on npm [51689bb8](https://github.com/cyclejs-community/create-cycle-app/commits/51689bb890d9c4465bb62891219b3fe6ba50ee78) 18 | 19 | ## Features 20 | 21 | - feat(create-cycle-app): Added dependency [3b09d484](https://github.com/cyclejs-community/create-cycle-app/commits/3b09d484ae04643d6a61287ad9390b305bc7f243) 22 | 23 | 24 | # v0.5.0 (2016-10-19) 25 | --- 26 | 27 | 28 | ## Features 29 | 30 | - feat(create-cycle-app): Change interaction while asking the flavor [829456e4](https://github.com/cyclejs-community/create-cycle-app/commits/829456e4689555cadb73be758f2c33ea1d080601) 31 | - feat(create-cycle-app): Separating flavors list from code [396d9427](https://github.com/cyclejs-community/create-cycle-app/commits/396d94279ee2564593f6561145f6346fcf2e9077) 32 | - feat(create-cycle-app): community vs core flavor discovery mechanism [38314428](https://github.com/cyclejs-community/create-cycle-app/commits/38314428c229b7924080da0d82f20adcdc78f79c) 33 | - feat(create-cycle-app): Added community registry file [747e7a7b](https://github.com/cyclejs-community/create-cycle-app/commits/747e7a7ba9a38554b4747e4176a2528a16d000c9) 34 | 35 | 36 | # v0.4.4 (2016-10-10) 37 | --- 38 | 39 | 40 | ## Bug Fixes 41 | 42 | - fix(create-cycle-app): bin script [1ea5dac1](https://github.com/geovanisouza92/create-cycle-app/commits/1ea5dac1addd67cefce3b0bdcf3c6b6fca5ed0e7) 43 | 44 | 45 | # v0.4.3 (2016-10-09) 46 | --- 47 | 48 | 49 | ## Bug Fixes 50 | 51 | - fix(create-cycle-app): Flavor resolution [0024e346](https://github.com/geovanisouza92/create-cycle-app/commits/0024e346bb43cb95edc491e3626dc983c097f4c5) 52 | 53 | 54 | # v0.4.2 (2016-10-09) 55 | --- 56 | 57 | 58 | ## Bug Fixes 59 | 60 | - fix(create-cycle-app): Missing shebang [ff853d86](https://github.com/geovanisouza92/create-cycle-app/commits/ff853d86a8408c071a884023fe67937a27bcfa42) 61 | - fix(create-cycle-app): Handling various syntaxes of flavor [ce1c0873](https://github.com/geovanisouza92/create-cycle-app/commits/ce1c087305b326ecb774ec45c91cec85c0104ed5) 62 | 63 | 64 | # v0.4.1 (2016-10-09) 65 | --- 66 | 67 | 68 | ## Bug Fixes 69 | 70 | - fix(create-cycle-app): Path resolution for installation from file or folder [1585f2f9](https://github.com/geovanisouza92/create-cycle-app/commits/1585f2f9d9a524d6fb57a82dd3206b568f30dc37) 71 | 72 | 73 | # v0.4.0 (2016-10-09) 74 | --- 75 | 76 | 77 | ## Features 78 | 79 | - feat(create-cycle-app): Select the stream library + some refactoring [c6aca323](https://github.com/geovanisouza92/create-cycle-app/commits/c6aca323e12acefdb868f9504d22b808635f2fe3) 80 | 81 | 82 | # v0.3.0 (2016-10-09) 83 | --- 84 | 85 | 86 | ## Features 87 | 88 | - feat(create-cycle-app): Auto discover flavors [87d3ed59](https://github.com/geovanisouza92/create-cycle-app/commits/87d3ed599bea37164d5aadf912836357c96dfe53) 89 | 90 | 91 | # v0.2.0 (2016-10-08) 92 | --- 93 | 94 | 95 | ## Features 96 | 97 | - feat(create-cycle-app): Adding the proper create-cycle-app command/script [70ffc405](https://github.com/geovanisouza92/create-cycle-app/commits/70ffc405e4a26dffafc6b75d7ff091df94c81bc7) 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /packages/create-cycle-app/README.md: -------------------------------------------------------------------------------- 1 | 2 | # create-cycle-app 3 | 4 | Create [Cycle.js](https://cycle.js.org/) apps with no build configuration. 5 | 6 | [Learn more](https://github.com/cyclejs-community/create-cycle-app). 7 | -------------------------------------------------------------------------------- /packages/create-cycle-app/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | 4 | const path = require('path') 5 | const chalk = require('chalk') 6 | const argv = require('minimist')(process.argv.slice(2)) 7 | const createApp = require('./src/createApp') 8 | const VERSION = require(path.resolve(__dirname, 'package.json')).version 9 | 10 | const validCommands = { 11 | 'verbose': true, 12 | 'flavor': true, 13 | 'yarn': true, 14 | 'pnpm': true, 15 | 'forceprompt': true 16 | } 17 | 18 | // Command line prelude (version and usage) 19 | const commands = argv._ 20 | if (commands.length === 0) { 21 | if (argv.version) { 22 | console.log(chalk.green(`create-cycle-app version: ${VERSION}`)) 23 | process.exit() 24 | } 25 | console.error(chalk.red('Usage: create-cycle-app [--flavor] [--verbose] [--yarn | --pnpm]')) 26 | process.exit(1) 27 | } 28 | 29 | Object.keys(argv) 30 | .filter(cmd => cmd !== '_') 31 | .every(cmd => { 32 | if (!validCommands[cmd]) { 33 | console.error(chalk.red(`Invalid command: ${cmd}`)) 34 | process.exit(1) 35 | return false 36 | } 37 | return true 38 | }) 39 | 40 | const flavor = argv.flavor || 'core' 41 | const verbose = argv.verbose || false 42 | const cli = argv.yarn ? 'yarn' : (argv.pnpm ? 'pnpm' : 'npm') 43 | const forceprompt = argv.forceprompt || false 44 | const name = commands[0] 45 | 46 | // Parse the command line options and run the setup 47 | createApp(name, verbose, flavor, cli, forceprompt) 48 | -------------------------------------------------------------------------------- /packages/create-cycle-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-cycle-app", 3 | "version": "5.0.0", 4 | "description": "Create Cycle.js with no build configuration.", 5 | "scripts": { 6 | "test": "exit 0 || jest" 7 | }, 8 | "keywords": [], 9 | "author": "Geovani Souza ", 10 | "contributors": [ 11 | { 12 | "name": "Geovani Souza", 13 | "email": "geovanisouza92@gmail.com" 14 | }, 15 | { 16 | "name": "Nick Balestra", 17 | "email": "nick@balestra.ch" 18 | } 19 | ], 20 | "license": "ISC", 21 | "bin": { 22 | "create-cycle-app": "./index.js" 23 | }, 24 | "dependencies": { 25 | "@cycle/dom": "^18.3.0", 26 | "@cycle/http": "^14.4.0", 27 | "@cycle/isolate": "^3.1.0", 28 | "@cycle/run": "^3.3.0", 29 | "@cycle/time": "^0.10.1", 30 | "chalk": "^2.1.0", 31 | "cross-spawn": "^5.1.0", 32 | "cycle-onionify": "^4.0.0", 33 | "inquirer": "^3.3.0", 34 | "minimist": "^1.2.0", 35 | "xstream": "^11.0.0" 36 | }, 37 | "devDependencies": { 38 | "cycle-restart": "^0.2.2", 39 | "cyclejs-test-helpers": "^1.4.0", 40 | "fs-extra": "^4.0.2", 41 | "html-looks-like": "^1.0.3", 42 | "jest": "^21.2.1", 43 | "jsverify": "^0.8.3", 44 | "snabbdom-to-html": "^3.3.0" 45 | }, 46 | "repository": { 47 | "type": "git", 48 | "url": "git+https://github.com/cyclejs-community/create-cycle-app.git" 49 | }, 50 | "bugs": { 51 | "url": "https://github.com/cyclejs-community/create-cycle-app/issues" 52 | }, 53 | "homepage": "https://github.com/cyclejs-community/create-cycle-app#readme" 54 | } 55 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/createApp.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | 5 | const createAppDir = require('./createAppDir') 6 | const initQuestions = require('./initQuestions') 7 | const installScripts = require('./installScripts') 8 | const createPackageJson = require('./createPackageJson') 9 | const shouldUseYarn = require('./shouldUseYarn') 10 | 11 | module.exports = function createApp (name, verbose, flavor, cli, forceprompt) { 12 | // The path where the cycle app will be created 13 | const appPath = path.resolve(name) 14 | // The name of the cycle app to create 15 | const appName = path.basename(appPath) 16 | // Which CLi to use (yarn or npm) 17 | if (shouldUseYarn()) { 18 | cli = 'yarn' 19 | } 20 | // console.log(cli) 21 | // If no --flavor is passed (flavor === 'core') 22 | // We prompt for language and stream library 23 | // We set the flavor to be 'cycle-scripts' 24 | if (flavor === 'core') { 25 | flavor = 'cycle-scripts-one-fits-all@>=6.0.0' 26 | } 27 | if (forceprompt) { 28 | if (flavor === 'core') { 29 | flavor = 'cycle-scripts@>=2.0.0' 30 | } 31 | initQuestions(answers => { 32 | createAppDir(appPath) 33 | createPackageJson(appPath, appName) 34 | installScripts(appPath, appName, { flavor, verbose, answers, cli }) 35 | }) 36 | // If a --flavor is passed we don't prompt the user 37 | // We delegate every task to the flavor's init() method itself. 38 | } else { 39 | createAppDir(appPath) 40 | createPackageJson(appPath, appName) 41 | installScripts(appPath, appName, { flavor, verbose, answers: false, cli }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/createAppDir.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const console = require('console') 5 | const fs = require('fs') 6 | 7 | const isSafeToCreateApp = require('./isSafeToCreateApp') 8 | 9 | module.exports = function createProjectIn (appPath) { 10 | if (!fs.existsSync(appPath)) { 11 | fs.mkdirSync(appPath) 12 | return 13 | } 14 | 15 | if (isSafeToCreateApp(appPath)) { 16 | return 17 | } else { 18 | console.log(chalk.red(`The directory \`${appPath}\` contains file(s) that could conflict. Aborting.`)) 19 | process.exit(1) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/createPackageJson.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const console = require('console') 5 | const fs = require('fs') 6 | const path = require('path') 7 | 8 | module.exports = function createPackageJson (appPath, appName) { 9 | // Prepare package.json 10 | const content = { 11 | name: appName, 12 | version: '0.1.0', 13 | private: true 14 | } 15 | const packageJsonContent = JSON.stringify(content, null, 2) 16 | 17 | // Write package.json in the app folder 18 | console.log(chalk.green(`Creating a new Cycle.js app in ${appPath}.`)) 19 | console.log() 20 | fs.writeFileSync( 21 | path.join(appPath, 'package.json'), 22 | packageJsonContent 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/getPackageName.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | 5 | const packageRegex = /(@[\w-]+\/)?[\w-]+/ 6 | 7 | module.exports = function getPackageName (installPackage) { 8 | if (/.tgz$/.test(installPackage)) { 9 | return installPackage.match(/^(.*)-.*tgz$/)[1] 10 | } else if (/^\.\/|\//.test(installPackage)) { 11 | return require(path.resolve(installPackage, 'package.json')).name 12 | } else { 13 | return installPackage.match(packageRegex)[0] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/initQuestions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const inquirer = require('inquirer') 4 | 5 | const initQuestions = [ 6 | { 7 | type: 'list', 8 | name: 'language', 9 | default: 0, 10 | choices: [ 11 | { 12 | name: 'JavaScript', 13 | value: 'javascript' 14 | }, 15 | { 16 | name: 'TypeScript', 17 | value: 'typescript' 18 | } 19 | ], 20 | message: 'Which language do you want to use to write your cycle app?' 21 | }, 22 | { 23 | type: 'list', 24 | name: 'streamLib', 25 | default: 0, 26 | choices: [ 27 | { 28 | name: 'XStream, tailored for Cycle.js', 29 | value: 'xstream' 30 | }, 31 | { 32 | name: 'Most.js, a blazing fast stream library', 33 | value: 'most' 34 | }, 35 | { 36 | name: 'RxJS', 37 | value: 'rxjs' 38 | } 39 | ], 40 | message: 'Which reactive stream library do you want to use?' 41 | } 42 | ] 43 | 44 | module.exports = cb => { 45 | inquirer.prompt(initQuestions).then(cb) 46 | } 47 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/installScripts.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const spawn = require('cross-spawn') 5 | const console = require('console') 6 | const path = require('path') 7 | 8 | const getPackageName = require('./getPackageName') 9 | 10 | module.exports = function installScripts (appFolder, appName, options) { 11 | const verbose = options.verbose 12 | const flavor = options.flavor 13 | const cli = options.cli 14 | 15 | // Check if the the the flavor to be used is local 16 | const local = /^\.\/|^\//.test(flavor) 17 | // Get the right name of the flavor package 18 | const packageName = getPackageName(flavor) 19 | // Install dependencies 20 | const npmArgs = [ 21 | 'install', 22 | verbose && '--verbose', 23 | '--save-dev', 24 | '--save-exact', 25 | flavor 26 | ].filter(a => a) 27 | 28 | const args = { 29 | npm: npmArgs, 30 | pnpm: npmArgs, 31 | yarn: [ 32 | 'add', 33 | '--exact', 34 | '--dev', 35 | verbose && '--verbose', 36 | local ? 'file:' + flavor : flavor 37 | ].filter(a => a) 38 | } 39 | 40 | // Trigger npm installation 41 | console.log(chalk.green('Installing packages. This might take a couple minutes.')) 42 | console.log(chalk.green(`Installing ${packageName} from ${(local ? 'local' : cli)} ...`)) 43 | console.log() 44 | 45 | const proc = spawn(cli, args[cli], {stdio: 'inherit', cwd: appFolder}) 46 | proc.on('error', (e) => console.log(e)) 47 | proc.on('close', function (code) { 48 | if (code !== 0) { 49 | console.error(chalk.red(`${cli} \`${args[cli].join(' ')}\` failed`)) 50 | return 51 | } 52 | 53 | const initScriptPath = path.resolve( 54 | appFolder, 55 | 'node_modules', 56 | packageName, 57 | 'scripts', 58 | 'init.js' 59 | ) 60 | const init = require(initScriptPath) 61 | 62 | // Execute the flavor's specific initialization 63 | init(appFolder, appName, options) 64 | }) 65 | } 66 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/isSafeToCreateApp.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | 5 | module.exports = function isSafeToCreateApp (appFolder) { 6 | const whitelist = [ 7 | '.DS_Store', 8 | 'Thumbs.db', 9 | '.git', 10 | '.gitignore', 11 | '.idea', 12 | 'README.md', 13 | 'LICENSE' 14 | ] 15 | return fs.readdirSync(appFolder) 16 | .every((file) => { 17 | return whitelist.indexOf(file) >= 0 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /packages/create-cycle-app/src/shouldUseYarn.js: -------------------------------------------------------------------------------- 1 | const execSync = require('child_process').execSync 2 | 3 | module.exports = function shouldUseYarn () { 4 | try { 5 | execSync('npm --version', { stdio: 'ignore' }) 6 | return false 7 | } catch (e) { 8 | return true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/integration/__snapshots__/createCycleApp.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`create-cycle-app when invoked with the the correct arguments it generate a correct package.json file 1`] = ` 4 | "{ 5 | "name": "MYCYCLEAPP", 6 | "version": "0.1.0", 7 | "private": true, 8 | "devDependencies": { 9 | "cycle-scripts": "1.0.3" 10 | }, 11 | "dependencies": {}, 12 | "scripts": { 13 | "start": "cycle-scripts start", 14 | "test": "cycle-scripts test", 15 | "build": "cycle-scripts build", 16 | "eject": "cycle-scripts eject" 17 | }, 18 | "babel": { 19 | "presets": [ 20 | "es2015" 21 | ] 22 | } 23 | }" 24 | `; 25 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/integration/createCycleApp.spec.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra') 2 | const path = require('path') 3 | const appName = path.resolve(__dirname, 'MYCYCLEAPP') 4 | const spawn = require('cross-spawn') 5 | 6 | describe('create-cycle-app', () => { 7 | describe('when invoked with the wrong arguments', () => { 8 | test('should throw an error', () => { 9 | expect( 10 | spawn.sync('node', [ 11 | path.resolve(__dirname, '../../index.js'), 12 | appName, 13 | '--flavour', 14 | 'cycle-scripts@1.0.3', 15 | '--noyarn' 16 | ]) 17 | ).toThrowError() 18 | }) 19 | 20 | test('should throw an error', () => { 21 | expect( 22 | spawn.sync('node', [ 23 | path.resolve(__dirname, '../../index.js'), 24 | appName, 25 | '--verbos' 26 | ]) 27 | ).toThrowError() 28 | }) 29 | }) 30 | 31 | describe('when invoked with the the correct arguments', () => { 32 | let dir 33 | 34 | beforeEach((done) => { 35 | spawn.sync('node', [ 36 | path.resolve(__dirname, '../../index.js'), 37 | appName, 38 | '--flavor', 39 | 'cycle-scripts@1.0.3' 40 | ]) 41 | dir = fs.readdirSync(appName) 42 | done() 43 | }) 44 | 45 | afterEach(() => { 46 | fs.removeSync(appName) 47 | }) 48 | 49 | test('it generate the correct folder structure and install dependencies', () => { 50 | expect(dir).toEqual(expect.arrayContaining([ 51 | '.gitignore', 52 | 'node_modules', 53 | 'package.json', 54 | 'public', 55 | 'src' 56 | ])) 57 | }) 58 | 59 | test('it generate a correct package.json file', () => { 60 | expect(fs.readFileSync(path.join(appName, 'package.json'), 'UTF8')).toMatchSnapshot() 61 | }) 62 | }) 63 | }) 64 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/unit/createAppDir.spec.js: -------------------------------------------------------------------------------- 1 | jest.mock('fs') 2 | const fs = require('fs') 3 | jest.mock('../../src/isSafeToCreateApp') 4 | const isSafeToCreateApp = require('../../src/isSafeToCreateApp') 5 | 6 | const createAppDir = require('../../src/createAppDir') 7 | 8 | describe('createAppDir module', () => { 9 | afterEach(() => { 10 | fs.existsSync.mockClear() 11 | isSafeToCreateApp.mockClear() 12 | }) 13 | 14 | describe('when calling it and the directory does not exist', () => { 15 | test('should create it', (done) => { 16 | fs.existsSync.mockReturnValue(false) 17 | createAppDir('./appFolder') 18 | expect(fs.existsSync).toBeCalledWith('./appFolder') 19 | expect(fs.mkdirSync).toBeCalledWith('./appFolder') 20 | expect(isSafeToCreateApp).not.toBeCalled() 21 | done() 22 | }) 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/unit/createPackageJson.spec.js: -------------------------------------------------------------------------------- 1 | const createPackageJson = require('../../src/createPackageJson') 2 | jest.mock('fs') 3 | const fs = require('fs') 4 | jest.mock('console') 5 | const console = require('console') 6 | const chalk = require('chalk') 7 | 8 | describe('createPackageJson module', () => { 9 | describe('when calling it', () => { 10 | test('should correctly prepare package.json and write it to disk', () => { 11 | createPackageJson('testPath', 'testName') 12 | 13 | expect(fs.writeFileSync.mock.calls[0][0]).toBe('testPath/package.json') 14 | expect(fs.writeFileSync.mock.calls[0][1]).toBe(JSON.stringify({ 15 | name: 'testName', 16 | version: '0.1.0', 17 | private: true 18 | }, null, 2)) 19 | expect(console.log).toHaveBeenCalledTimes(2) 20 | expect(console.log).toHaveBeenCalledWith(chalk.green('Creating a new Cycle.js app in testPath.')) 21 | }) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/unit/getPackageName.spec.js: -------------------------------------------------------------------------------- 1 | const getPackageName = require('../../src/getPackageName') 2 | 3 | describe('getPackageName module', () => { 4 | test('should return the unaltered package name if alrady given', () => { 5 | expect(getPackageName('cycle-scripts')).toBe('cycle-scripts') 6 | expect(getPackageName('are-we-there-yet-1.1.2.tgz')).toBe('are-we-there-yet') 7 | expect(getPackageName('cycle-scripts@next')).toBe('cycle-scripts') 8 | }) 9 | test('should return the correct package name if inside a .tgz', () => { 10 | expect(getPackageName('are-we-there-yet-1.1.2.tgz')).toBe('are-we-there-yet') 11 | }) 12 | test('should return the correct package name if uses a @/ naming', () => { 13 | expect(getPackageName('cycle-scripts@next')).toBe('cycle-scripts') 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/unit/initQuestions.spec.js: -------------------------------------------------------------------------------- 1 | const initQuestions = require('../../src/initQuestions') 2 | jest.mock('inquirer') 3 | const inquirer = require('inquirer') 4 | 5 | describe('initQuedstion module', () => { 6 | describe('when calling it', () => { 7 | test('should prompt for question', () => { 8 | const callback = jest.fn() 9 | const answer = {language: 'javascript', streamLib: 'xstream'} 10 | inquirer.prompt.mockReturnValue({ 11 | then: jest.fn(answers => callback(answer)) 12 | }) 13 | initQuestions(callback) 14 | expect(callback).toBeCalledWith(answer) 15 | expect(inquirer.prompt).toBeCalled() 16 | }) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/unit/installScripts.spec.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | jest.mock('cross-spawn') 3 | const spawn = require('cross-spawn') 4 | spawn.mockImplementation(() => ({ on: jest.fn() })) 5 | jest.mock('../../src/getPackageName') 6 | const getPackageName = require('../../src/getPackageName') 7 | jest.mock('console') 8 | const consoleMock = require('console') 9 | const installScripts = require('../../src/installScripts') 10 | // installScripts(appFolder, appName, { flavor, verbose, answers: false }) 11 | describe('installScripts module', () => { 12 | test('should be a function with arity 3', () => { 13 | expect(typeof installScripts).toBe('function') 14 | expect(installScripts.length).toBe(3) 15 | }) 16 | 17 | describe('when invoked with a flavor published on npm', () => { 18 | getPackageName.mockImplementation(name => name) 19 | installScripts('./', 'appName', { flavor: 'cycle-scripts', cli: 'npm' }) 20 | 21 | test('should call getPackageName with the name of the npm module', () => { 22 | expect(getPackageName).toBeCalledWith('cycle-scripts') 23 | }) 24 | 25 | test('should call spawn with the correct arguments', () => { 26 | expect(spawn).toBeCalledWith( 27 | 'npm', 28 | [ 29 | 'install', 30 | '--save-dev', 31 | '--save-exact', 32 | 'cycle-scripts' 33 | ], 34 | {'cwd': './', 'stdio': 'inherit'} 35 | ) 36 | }) 37 | 38 | test('should console log the correct information', () => { 39 | expect(consoleMock.log.mock.calls[0][0]).toContain( 40 | 'Installing packages. This might take a couple minutes.', 41 | ) 42 | expect(consoleMock.log.mock.calls[1][0]).toContain( 43 | 'Installing cycle-scripts from npm ...', 44 | ) 45 | expect(consoleMock.log.mock.calls[2][0]).toBe() 46 | }) 47 | }) 48 | 49 | describe('when invoked with a local flavor', () => { 50 | getPackageName.mockImplementation(name => path.basename(name)) 51 | installScripts('./', 'appName', { flavor: './cycle-scripts', cli: 'npm' }) 52 | 53 | test('should console log the correct information', () => { 54 | expect(consoleMock.log.mock.calls[4][0]).toContain( 55 | 'Installing cycle-scripts from local', 56 | ) 57 | }) 58 | 59 | test('should call spawn with the correct arguments', () => { 60 | expect(spawn.mock.calls[1][1][3]).toContain('./cycle-scripts') 61 | }) 62 | }) 63 | 64 | describe('when invoked with a verbose flag', () => { 65 | getPackageName.mockImplementation(name => name) 66 | installScripts('./', 'appName', { flavor: 'cycle-scripts', verbose: true, cli: 'npm' }) 67 | 68 | test('should call spawn with the correct arguments', () => { 69 | expect(spawn.mock.calls[2]).toMatchObject([ 70 | 'npm', 71 | [ 72 | 'install', 73 | '--verbose', 74 | '--save-dev', 75 | '--save-exact', 76 | 'cycle-scripts' 77 | ], 78 | {'cwd': './', 'stdio': 'inherit'} 79 | ]) 80 | }) 81 | }) 82 | }) 83 | -------------------------------------------------------------------------------- /packages/create-cycle-app/test/unit/isSafeToCreateApp.spec.js: -------------------------------------------------------------------------------- 1 | jest.mock('fs') 2 | const fs = require('fs') 3 | const isSafeToCreateApp = require('../../src/isSafeToCreateApp') 4 | const whiteList = [ 5 | '.DS_Store', 6 | 'Thumbs.db', 7 | '.git', 8 | '.gitignore', 9 | '.idea', 10 | 'README.md', 11 | 'LICENSE' 12 | ] 13 | 14 | describe('isSafeToCreateApp module', () => { 15 | describe('when calling it with a directory containing files not white-listened', () => { 16 | test('should return false', () => { 17 | fs.readdirSync.mockImplementation(() => whiteList.concat('index.js')) 18 | const isSafe = isSafeToCreateApp('./someFolder') 19 | expect(isSafe).toBe(false) 20 | }) 21 | }) 22 | 23 | describe('when calling it with a directory containing only white-listened files', () => { 24 | test('should return true', () => { 25 | fs.readdirSync.mockImplementation(() => whiteList) 26 | const isSafe = isSafeToCreateApp('./someFolder') 27 | expect(isSafe).toBe(true) 28 | }) 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /packages/cycle-scripts/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2017 Nick Balestra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/cycle-scripts/README.md: -------------------------------------------------------------------------------- 1 | # cycle-scripts 2 | 3 | [Cycle-app](https://github.com/cyclejs-community/create-cycle-app) core flavor. 4 | 5 | ## Language 6 | 7 | ES6 ( Babel ) configured with: 8 | * [ES2015 preset](https://babeljs.io/docs/plugins/preset-es2015/) 9 | 10 | ## Bundler 11 | 12 | Webpack configured with 13 | * [Webpack dev server](https://webpack.github.io/docs/webpack-dev-server.html) 14 | * [Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html) 15 | 16 | ## Scripts 17 | 18 | - `npm start`: Start development server listening on port 8000 19 | - `npm test`: Run the default test tool 20 | - `npm run build`: Generate a production-ready build content, on the `build` folder (this folder is *gitignored*) 21 | - `npm run eject`: Copy flavor's dependencies and configurations to the project folder, update `package.json` and remove the dependency on the flavored `cycle-scripts`. This is irreversible. 22 | 23 | 24 | ## Boilerplate: 25 | 26 | The flavor generate the following file structure: 27 | 28 | ``` 29 | my-awesome-cycle-app/ 30 | ├── node_modules/ 31 | ├── public/ 32 | │ ├── favicon.ico 33 | │ └── index.html 34 | ├── src/ 35 | │ ├── app.js 36 | │ ├── app.test.js 37 | │ └── index.js 38 | └── package.json 39 | ``` 40 | 41 | ### Config files 42 | * .babelrc (Added on the root after running the eject script) 43 | -------------------------------------------------------------------------------- /packages/cycle-scripts/configs/dependencies.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | basics: [ 3 | '@cycle/dom@18.3.0' 4 | ], 5 | language: { 6 | javascript: [], 7 | typescript: [ 8 | 'typescript@2.5.3', 9 | 'awesome-typescript-loader@3.2.3' 10 | ] 11 | }, 12 | streamLib: { 13 | xstream: [ 14 | '@cycle/run@3.3.0', 15 | 'xstream@11.0.0' 16 | ], 17 | rxjs: [ 18 | '@cycle/rxjs-run@7.1.0', 19 | 'rxjs@5.4.3' 20 | ], 21 | most: [ 22 | '@cycle/most-run@7.2.0', 23 | 'most@1.7.2' 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/cycle-scripts/configs/javascript/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // Silence webpack2 deprecation warnings 4 | // https://github.com/vuejs/vue-loader/issues/666 5 | process.noDeprecation = true 6 | 7 | const HtmlWebpackPlugin = require('html-webpack-plugin') 8 | const path = require('path') 9 | const webpack = require('webpack') 10 | 11 | // Paths to be used for webpack configuration 12 | const paths = { 13 | appSrc: path.join(process.cwd(), 'src'), 14 | appIndex: path.join(process.cwd(), 'src', 'index.js'), 15 | appBuild: path.join(process.cwd(), 'build'), 16 | public: '/' 17 | } 18 | 19 | module.exports = { 20 | entry: { 21 | main: [ 22 | // Include an alternative client for WebpackDevServer. A client's job is to 23 | // connect to WebpackDevServer by a socket and get notified about changes. 24 | // When you save a file, the client will either apply hot updates (in case 25 | // of CSS changes), or refresh the page (in case of JS changes). When you 26 | // make a syntax error, this client will display a syntax error overlay. 27 | // Note: instead of the default WebpackDevServer client, we use a custom one 28 | // to bring better experience from Create React App users. You can replace 29 | // the line below with these two lines if you prefer the stock client: 30 | // require.resolve('webpack-dev-server/client') + '?/', 31 | // require.resolve('webpack/hot/dev-server'), 32 | require.resolve('react-dev-utils/webpackHotDevClient'), 33 | // Your app's code 34 | paths.appIndex 35 | ] 36 | }, 37 | resolve: { 38 | extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'] 39 | }, 40 | output: { 41 | // This does not produce a real file. It's just the virtual path that is 42 | // served by WebpackDevServer in development. This is the JS bundle 43 | // containing code from all our entry points, and the Webpack runtime. 44 | filename: 'static/js/bundle.js', 45 | // Not used in dev but WebpackDevServer crashes without it: 46 | path: paths.appBuild, 47 | // The URL that app is served from. We use "/" in development. 48 | publicPath: paths.public 49 | }, 50 | module: { 51 | rules: [ 52 | { 53 | // We use babel-loader to transipile every .js or .jsx file 54 | test: /\.jsx?$/, 55 | loader: 'babel-loader', 56 | // Including over excluding as a whitelist is easier to maintain than a blacklist. 57 | // as per http://stackoverflow.com/questions/31675025/how-to-exclude-nested-node-module-folders-from-a-loader-in-webpack 58 | include: paths.appSrc, 59 | options: { 60 | // This is a feature of `babel-loader` for webpack (not Babel itself). 61 | // It enables caching results in ./node_modules/.cache/babel-loader/ 62 | // directory for faster rebuilds. 63 | cacheDirectory: true, 64 | // Instead of relying on a babelrc file to configure babel (or in package.json configs) 65 | // We speficy here which presets to use. In the future this could be moved to it's own 66 | // package as create-react-app does with their 'babel-preset-react-app module 67 | babelrc: false, 68 | presets: [ 69 | [ 'env', { 70 | 'targets': { 71 | 'browsers': ['last 2 versions'] 72 | } 73 | }] 74 | ], 75 | plugins: [ 76 | // https://cycle.js.org/getting-started.html#getting-started-coding-consider-jsx 77 | // This allow us to use JSX to create virtual dom elements instead of Snabbdom helpers like div(), input(), .. 78 | ['transform-react-jsx', { pragma: 'Snabbdom.createElement' }], 79 | // Allow Babel to transform rest properties for object destructuring assignment and spread properties for object literals. 80 | ['transform-object-rest-spread'] 81 | ] 82 | } 83 | } 84 | ] 85 | }, 86 | plugins: [ 87 | // This is necessary to emit hot updates (currently CSS only): 88 | new webpack.HotModuleReplacementPlugin(), 89 | // Generates an `index.html` file with the