├── .travis.yml ├── docs ├── npm-start.png └── create-cycle-app.png ├── .gitignore ├── lerna.json ├── packages ├── cycle-scripts │ ├── template │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── favicon.png │ │ │ └── index.html │ │ ├── custom-typings.d.ts │ │ ├── src │ │ │ ├── javascript │ │ │ │ ├── app.test.js │ │ │ │ ├── index.js │ │ │ │ └── app.jsx │ │ │ └── typescript │ │ │ │ ├── app.test.ts │ │ │ │ ├── app.tsx │ │ │ │ ├── index.ts │ │ │ │ └── interfaces.ts │ │ ├── config │ │ │ ├── javascript.js │ │ │ └── typescript.js │ │ ├── tsconfig.json │ │ └── gitignore │ ├── scripts │ │ ├── init.js │ │ ├── test.js │ │ ├── init │ │ │ ├── questions.js │ │ │ ├── success.js │ │ │ └── setup.js │ │ ├── eject.js │ │ ├── start.js │ │ ├── build.js │ │ └── utils │ │ │ └── createWebpackCompiler.js │ ├── configs │ │ ├── dependencies.js │ │ ├── javascript │ │ │ ├── webpack.config.prod.js │ │ │ └── webpack.config.dev.js │ │ ├── typescript │ │ │ ├── webpack.config.prod.js │ │ │ └── webpack.config.dev.js │ │ └── webpackDevServer.config.js │ ├── index.js │ ├── LICENSE │ ├── README.md │ └── package.json └── create-cycle-app │ ├── README.md │ ├── src │ ├── shouldUseYarn.js │ ├── isSafeToCreateApp.js │ ├── getPackageName.js │ ├── createAppDir.js │ ├── createPackageJson.js │ ├── initQuestions.js │ ├── createApp.js │ └── installScripts.js │ ├── test │ ├── unit │ │ ├── initQuestions.spec.js │ │ ├── getPackageName.spec.js │ │ ├── createAppDir.spec.js │ │ ├── createPackageJson.spec.js │ │ ├── isSafeToCreateApp.spec.js │ │ └── installScripts.spec.js │ └── integration │ │ ├── __snapshots__ │ │ └── createCycleApp.spec.js.snap │ │ └── createCycleApp.spec.js │ ├── index.js │ ├── package.json │ └── CHANGELOG.md ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .editorconfig ├── AUTHORS.md ├── bin └── update-authors.sh ├── CONTRIBUTING.md ├── LICENSE ├── package.json └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'node' 4 | -------------------------------------------------------------------------------- /docs/npm-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyclejs-community/create-cycle-app/HEAD/docs/npm-start.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | 4 | # Dependency directories 5 | node_modules 6 | 7 | # OS fs specifics 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /docs/create-cycle-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyclejs-community/create-cycle-app/HEAD/docs/create-cycle-app.png -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.0.0-beta.36", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "independent" 7 | } 8 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyclejs-community/create-cycle-app/HEAD/packages/cycle-scripts/template/public/favicon.ico -------------------------------------------------------------------------------- /packages/cycle-scripts/template/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyclejs-community/create-cycle-app/HEAD/packages/cycle-scripts/template/public/favicon.png -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/cycle-scripts/template/custom-typings.d.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line 2 | /// 3 | 4 | declare var Snabbdom: any; //Automaticly imported into every file 5 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/javascript/app.test.js: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `// import assert from 'assert' 2 | 3 | // describe('App', function () { 4 | // it('should test something', function () { 5 | // // TODO: Add your tests here 6 | // }) 7 | // }) 8 | ` 9 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/typescript/app.test.ts: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `// import assert from 'assert' 2 | 3 | // describe('App', function () { 4 | // it('should test something', function () { 5 | // // TODO: Add your tests here 6 | // }) 7 | // }) 8 | ` 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/javascript/index.js: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `import {run} from '${replacements.run}' 2 | import {makeDOMDriver} from '@cycle/dom' 3 | import {App} from './app' 4 | 5 | const main = App 6 | 7 | const drivers = { 8 | DOM: makeDOMDriver('#root') 9 | } 10 | 11 | run(main, drivers) 12 | ` 13 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/javascript/app.jsx: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `${replacements.import} 2 | 3 | export function App (sources) { 4 | const vtree$ = ${replacements.stream}.of( 5 |
My Awesome Cycle.js app
6 | ) 7 | const sinks = { 8 | DOM: vtree$ 9 | } 10 | return sinks 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/typescript/app.tsx: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `${replacements.import} 2 | import {Sources, Sinks} from './interfaces' 3 | 4 | export function App(sources : Sources) : Sinks { 5 | const vtree$ = ${replacements.stream}.of( 6 |
My Awesome Cycle.js app
7 | ) 8 | 9 | return { 10 | DOM: vtree$ 11 | } 12 | } 13 | ` 14 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Cycle App 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/typescript/index.ts: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `import {run} from '${replacements.run}' 2 | import {makeDOMDriver} from '@cycle/dom' 3 | import {Component} from './interfaces' 4 | 5 | import {App} from './app' 6 | 7 | const main : Component = App 8 | 9 | const drivers = { 10 | DOM: makeDOMDriver('#root') 11 | } 12 | 13 | run(main, drivers) 14 | ` 15 | -------------------------------------------------------------------------------- /packages/cycle-scripts/scripts/init.js: -------------------------------------------------------------------------------- 1 | const questions = require('./init/questions') 2 | const setup = require('./init/setup') 3 | 4 | module.exports = function init (appPath, appName, options) { 5 | if (options.answers) { 6 | return setup(appPath, appName, options) 7 | } 8 | return questions(answers => { 9 | options.answers = answers 10 | setup(appPath, appName, options) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/src/typescript/interfaces.ts: -------------------------------------------------------------------------------- 1 | module.exports = replacements => `${replacements.import} 2 | ${replacements.typeImport} 3 | import {DOMSource, VNode} from '@cycle/dom' 4 | 5 | export type Sources = { 6 | DOM : DOMSource; 7 | } 8 | 9 | export type Sinks = { 10 | DOM : ${replacements.streamType}; 11 | } 12 | 13 | export type Component = (s : Sources) => Sinks; 14 | ` 15 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/config/javascript.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | xstream: { 3 | run: '@cycle/run', 4 | import: 'import xs from \'xstream\'', 5 | stream: 'xs' 6 | }, 7 | rxjs: { 8 | run: '@cycle/rxjs-run', 9 | import: 'import Rx from \'rxjs/Rx\'', 10 | stream: 'Rx.Observable' 11 | }, 12 | most: { 13 | run: '@cycle/most-run', 14 | import: 'import * as most from \'most\'', 15 | stream: 'most' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/cycle-scripts/template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "module": "ES6", 5 | "moduleResolution": "node", 6 | "target": "ES5", 7 | "sourceMap": true, 8 | "jsx": "react", 9 | "jsxFactory": "Snabbdom.createElement", 10 | "noImplicitReturns": true, 11 | "strict": true, 12 | "allowJs": true, 13 | "lib": ["ES6", "ES5", "DOM"] 14 | }, 15 | "exclude": ["node_modules"] 16 | } 17 | -------------------------------------------------------------------------------- /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/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/cycle-scripts/scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | const spawn = require('cross-spawn') 5 | const chalk = require('chalk') 6 | 7 | const mocha = path.resolve(process.cwd(), 'node_modules', '.bin', 'mocha') 8 | 9 | const args = [ 10 | '--colors', 11 | '--require', 12 | 'babel-register', 13 | !process.env.CI && (console.log(chalk.green.bold('Enabling watch mode')) || '--watch'), 14 | 'src/**/*.test.js' 15 | ].filter(Boolean) 16 | 17 | spawn(mocha, args, {stdio: 'inherit'}) 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/cycle-scripts/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | 4 | const spawn = require('cross-spawn') 5 | const script = process.argv[2] 6 | const args = process.argv.slice(3) 7 | 8 | switch (script) { 9 | case 'start': 10 | case 'test': 11 | case 'build': 12 | case 'eject': 13 | const result = spawn.sync( 14 | 'node', 15 | [require.resolve('./scripts/' + script)].concat(args), 16 | {stdio: 'inherit'} 17 | ) 18 | process.exit(result.status) 19 | break 20 | default: 21 | console.log('Unknown script "' + script + '".') 22 | console.log('Perhaps you need to upgrade cycle-scripts?') 23 | break 24 | } 25 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/cycle-scripts/template/config/typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | xstream: { 3 | run: '@cycle/run', 4 | import: 'import xs from \'xstream\'', 5 | typeImport: 'import {Stream} from \'xstream\'', 6 | stream: 'xs', 7 | streamType: 'Stream' 8 | }, 9 | rxjs: { 10 | run: '@cycle/rxjs-run', 11 | import: 'import * as Rx from \'rxjs\'', 12 | typeImport: 'import {Observable} from \'rxjs\'', 13 | stream: 'Rx.Observable', 14 | streamType: 'Observable' 15 | }, 16 | most: { 17 | run: '@cycle/most-run', 18 | import: 'import * as most from \'most\'', 19 | typeImport: 'import {Stream} from \'most\'', 20 | stream: 'most', 21 | streamType: 'Stream' 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/cycle-scripts/template/gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/abad92dac5a4306f72242dae3bca6e277bce3615/Node.gitignore 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Compiled binary addons (http://nodejs.org/api/addons.html) 30 | build/Release 31 | 32 | # Dependency directories 33 | node_modules 34 | jspm_packages 35 | 36 | # Optional npm cache directory 37 | .npm 38 | 39 | # Optional eslint cache 40 | .eslintcache 41 | 42 | # Optional REPL history 43 | .node_repl_history 44 | 45 | # Output of 'npm pack' 46 | *.tgz 47 | 48 | build 49 | -------------------------------------------------------------------------------- /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/scripts/init/questions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const inquirer = require('inquirer') 4 | 5 | const questions = [ 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 = callback => inquirer.prompt(questions).then(callback) 45 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/cycle-scripts/scripts/init/success.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk') 2 | 3 | module.exports = (appName, appPath) => { 4 | console.log() 5 | console.log(`Success! Created ${appName} at ${appPath}`) 6 | console.log('Inside that directory, you can run several commands:') 7 | console.log() 8 | console.log(chalk.cyan(' npm start')) 9 | console.log(' Starts the development server') 10 | console.log() 11 | console.log(chalk.cyan(' npm test')) 12 | console.log(' Start the test runner') 13 | console.log() 14 | console.log(chalk.cyan(' npm run build')) 15 | console.log(' Bundles the app into static files for production') 16 | console.log() 17 | console.log(chalk.cyan(' npm run eject')) 18 | console.log(' Removes this tool and copies build dependencies, configuration files') 19 | console.log(' and scripts into the app directory. If you do this, you can\'t go back!') 20 | console.log() 21 | console.log('We suggest that you begin by typing:') 22 | console.log() 23 | console.log(chalk.cyan(` cd ${appName}`)) 24 | console.log(chalk.cyan(' npm start')) 25 | console.log() 26 | console.log('If you have questions, issues or feedback about Cycle.js and create-cycle-app, please, join us on the Gitter:') 27 | console.log() 28 | console.log(chalk.cyan(' https://gitter.im/cyclejs/cyclejs')) 29 | console.log() 30 | console.log('Happy cycling!') 31 | console.log() 32 | } 33 | -------------------------------------------------------------------------------- /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/cycle-scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cycle-scripts", 3 | "version": "2.1.1", 4 | "description": "create-cycle-app core flavor", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Maybe later\"" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/cyclejs-community/create-cycle-app.git" 12 | }, 13 | "author": "Nick Balestra ", 14 | "contributors": [ 15 | { 16 | "name": "Geovani Souza", 17 | "email": "geovanisouza92@gmail.com" 18 | }, 19 | { 20 | "name": "Nick Balestra", 21 | "email": "nick@balestra.ch" 22 | } 23 | ], 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/cyclejs-community/create-cycle-app/issues" 27 | }, 28 | "homepage": "https://github.com/cyclejs-community/create-cycle-app#readme", 29 | "bin": { 30 | "cycle-scripts": "./index.js" 31 | }, 32 | "dependencies": { 33 | "babel-core": "^6.26.0", 34 | "babel-loader": "^7.1.2", 35 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 36 | "babel-plugin-transform-react-jsx": "^6.24.1", 37 | "babel-preset-env": "^1.6.0", 38 | "chalk": "^2.1.0", 39 | "cross-spawn": "^5.1.0", 40 | "fs-extra": "^4.0.2", 41 | "html-webpack-plugin": "^2.30.1", 42 | "inquirer": "^3.3.0", 43 | "jest": "^21.2.1", 44 | "react-dev-utils": "^4.1.0", 45 | "snabbdom-pragma": "^2.5.0", 46 | "webpack": "^3.6.0", 47 | "webpack-dev-server": "^2.9.1" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /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/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/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/cycle-scripts/scripts/eject.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const chalk = require('chalk') 6 | const inquirer = require('inquirer') 7 | 8 | const appPath = path.join(process.cwd()) 9 | const appScriptsPath = path.join(process.cwd(), 'scripts') 10 | const flavorPackageJson = require(path.join(__dirname, '..', 'package.json')) 11 | const appPackageJson = require(path.join(appPath, 'package.json')) 12 | const language = appPackageJson.cca.language 13 | 14 | const ejectConfirmation = { 15 | type: 'confirm', 16 | name: 'doEject', 17 | default: false, 18 | message: 'Are you sure you want to eject? This action is permanent.' 19 | } 20 | 21 | // Ask the user for confirmation before ejecting. 22 | inquirer.prompt([ejectConfirmation]).then(answers => { 23 | // Abort in case of negative answer (default) 24 | if (!answers.doEject) { 25 | console.log(chalk.cyan('Eject aborted!')) 26 | return process.exit(0) 27 | } 28 | 29 | // STEP 1 - Prepare package.json 30 | // Declaring new scripts 31 | const scripts = { 32 | start: 'node scripts/start.js', 33 | test: 'node scripts/test.js', 34 | build: 'node scripts/build.js' 35 | } 36 | // Remove flavor from devpendencies 37 | delete appPackageJson.devDependencies[flavorPackageJson.name] 38 | // Remove cca settings 39 | delete appPackageJson.cca 40 | // Flavor's dependencies -> application devDependency. 41 | // We merge flavor's dependencies with application's devDepependencies 42 | const devDependencies = Object.assign( 43 | {}, 44 | appPackageJson.devDependencies, 45 | flavorPackageJson.dependencies 46 | ) 47 | // New package.json content 48 | const packageJsonContent = Object.assign( 49 | {}, 50 | appPackageJson, 51 | { 52 | scripts, 53 | devDependencies 54 | } 55 | ) 56 | // Overide application's package.json with the new content 57 | fs.writeFileSync( 58 | path.join(appPath, 'package.json'), 59 | JSON.stringify(packageJsonContent, null, 2) 60 | ) 61 | 62 | // STEP 2 - Copy scripts 63 | function copyScript (script) { 64 | fs.copySync(path.join(__dirname, script), path.join(appScriptsPath, script)) 65 | } 66 | // Make sure appScriptsPath exists 67 | fs.ensureDirSync(appScriptsPath) 68 | // Copy over start, test and build scripts 69 | copyScript('start.js') 70 | copyScript('test.js') 71 | copyScript('build.js') 72 | 73 | // STEP 3 - Copy utils 74 | fs.copySync(path.join(__dirname, 'utils'), path.join(appScriptsPath, 'utils')) 75 | 76 | // STEP 4 - Copy configs 77 | fs.copySync(path.join(__dirname, '../', 'configs', language), path.join(appPath, 'configs')) 78 | fs.copySync(path.join(__dirname, '../', 'configs', 'webpackDevServer.config.js'), path.join(appPath, 'configs', 'webpackDevServer.config.js')) 79 | 80 | // TODO sucess message 81 | }) 82 | -------------------------------------------------------------------------------- /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/cycle-scripts/scripts/start.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BSD License 3 | * For create-react-app software 4 | * 5 | * Copyright (c) 2016-present, Facebook, Inc. All rights reserved. 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * Neither the name Facebook nor the names of its contributors may be used to 17 | * endorse or promote products derived from this software without specific 18 | * prior written permission. 19 | * 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | 'use strict' 34 | 35 | const WebpackDevServer = require('webpack-dev-server') 36 | const chalk = require('chalk') 37 | const path = require('path') 38 | 39 | const devServerConfig = require('../configs/webpackDevServer.config') 40 | const createWebpackCompiler = require('./utils/createWebpackCompiler') 41 | const openBrowser = require('react-dev-utils/openBrowser') 42 | const notEjected = require(path.join(process.cwd(), 'package.json')).cca 43 | 44 | const config = require(path.join( 45 | '../configs/', 46 | notEjected 47 | ? notEjected.language 48 | : '', 49 | 'webpack.config.dev') 50 | ) 51 | process.env.NODE_ENV = 'development' 52 | 53 | const cli = 'npm' 54 | const protocol = devServerConfig.https ? 'https' : 'http' 55 | const host = devServerConfig.host 56 | const port = devServerConfig.port 57 | 58 | function run (port) { 59 | const compiler = createWebpackCompiler( 60 | config, 61 | function onReady (showInstructions) { 62 | if (!showInstructions) { 63 | return 64 | } 65 | console.log() 66 | console.log('The app is running at:') 67 | console.log() 68 | console.log(` ${chalk.cyan(`${protocol}://${host}:${port}/`)}`) 69 | console.log() 70 | console.log('Note that the development build is not optimized.') 71 | console.log( 72 | `To create a production build, use ${chalk.cyan(`${cli} run build`)}.` 73 | ) 74 | console.log() 75 | } 76 | ) 77 | 78 | const devServer = new WebpackDevServer(compiler, devServerConfig) 79 | 80 | devServer.listen(port, err => { 81 | if (err) { 82 | return console.log(err) 83 | } 84 | 85 | console.log(chalk.cyan('Starting the development server...')) 86 | console.log() 87 | 88 | openBrowser(`${protocol}://${host}:${port}/`) 89 | }) 90 | } 91 | 92 | run(port) 93 | -------------------------------------------------------------------------------- /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/cycle-scripts/configs/javascript/webpack.config.prod.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 path = require('path') 8 | const HtmlWebpackPlugin = require('html-webpack-plugin') 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 | // Your app's code 23 | paths.appIndex 24 | ] 25 | }, 26 | output: { 27 | // This is the productin JS bundle containing code from all our entry points. 28 | filename: 'bundle.js', 29 | // The output path where webpack will write the bundle 30 | path: paths.appBuild 31 | }, 32 | resolve: { 33 | extensions: ['.js', '.ts', '.tsx', '.jsx', '.json'] 34 | }, 35 | module: { 36 | rules: [ 37 | { 38 | // We use babel-loader to transipile every .js or .jsx file 39 | test: /\.jsx?$/, 40 | loader: 'babel-loader', 41 | // Including over excluding as a whitelist is easier to maintain than a blacklist. 42 | // as per http://stackoverflow.com/questions/31675025/how-to-exclude-nested-node-module-folders-from-a-loader-in-webpack 43 | include: paths.appSrc, 44 | options: { 45 | // This is a feature of `babel-loader` for webpack (not Babel itself). 46 | // It enables caching results in ./node_modules/.cache/babel-loader/ 47 | // directory for faster rebuilds. 48 | cacheDirectory: true, 49 | // Instead of relying on a babelrc file to configure babel (or in package.json configs) 50 | // We speficy here which presets to use. In the future this could be moved to it's own 51 | // package as create-react-app does with their 'babel-preset-react-app module. 52 | // As uglify doesn't support es6 code yet, the uglify param will tell babel plugin to transpile to es5 53 | // in order for the output to be uglified. 54 | presets: [ 55 | [ 'env', { 56 | 'targets': { 57 | 'browsers': ['last 2 versions'], 58 | uglify: true 59 | } 60 | }] 61 | ], 62 | plugins: [ 63 | // https://cycle.js.org/getting-started.html#getting-started-coding-consider-jsx 64 | // This allow us to use JSX to create virtual dom elements instead of Snabbdom helpers like div(), input(), .. 65 | ['transform-react-jsx', { pragma: 'Snabbdom.createElement' }], 66 | // Allow Babel to transform rest properties for object destructuring assignment and spread properties for object literals. 67 | ['transform-object-rest-spread'] 68 | ] 69 | } 70 | } 71 | ] 72 | }, 73 | plugins: [ 74 | // Generates an `index.html` file with the