├── .gitignore ├── composer.json ├── composer.lock ├── data └── dataTypeGithubDump.js ├── package.json ├── readme.md ├── src ├── Commands │ └── PipeDreamBuild.php ├── Controllers │ ├── PipeDreamAPIController.php │ └── PipeDreamWebController.php ├── LaravelCreateServiceProvider.php ├── ProjectFileManager.php ├── public │ ├── data │ │ └── .gitignore │ └── img │ │ ├── build.gif │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── logo_with_text.png │ │ ├── screenshots │ │ ├── api.png │ │ ├── build.png │ │ ├── design.png │ │ └── review.png │ │ └── video_splash_joke.png ├── resources │ ├── css │ │ └── app.css │ ├── js │ │ ├── app.js │ │ └── app_backup.js │ └── views │ │ └── spa.blade.php └── routes │ └── routes.php ├── webpack.mix.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /vendor 3 | .vscode 4 | mix-manifest.json 5 | .idea/* 6 | /src/public/css 7 | /src/public/js 8 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pipe-dream/laravel-create", 3 | "type": "package", 4 | "description": "Watch how this package DESTROYS all other generators. Boilerplate repos HATE it!", 5 | "keywords": [ 6 | "laravel", 7 | "package" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^7.1.3" 12 | }, 13 | "require-dev": { 14 | 15 | }, 16 | "config": { 17 | "optimize-autoloader": true, 18 | "preferred-install": "dist", 19 | "sort-packages": true 20 | }, 21 | "extra": { 22 | "laravel": { 23 | "providers": [ 24 | "PipeDream\\LaravelCreate\\LaravelCreateServiceProvider" 25 | ] 26 | } 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "PipeDream\\LaravelCreate\\": "src/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Tests\\": "tests/" 36 | } 37 | }, 38 | "minimum-stability": "dev", 39 | "prefer-stable": true, 40 | "scripts": { 41 | "post-autoload-dump": [ 42 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 43 | "@php ../../../artisan package:discover --ansi" 44 | ], 45 | "post-update-cmd": [ 46 | 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "6271b7b57e0963bc8dbcc8736b2b9145", 8 | "packages": [], 9 | "packages-dev": [], 10 | "aliases": [], 11 | "minimum-stability": "dev", 12 | "stability-flags": [], 13 | "prefer-stable": true, 14 | "prefer-lowest": false, 15 | "platform": { 16 | "php": "^7.1.3" 17 | }, 18 | "platform-dev": [] 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "@pipe-dream/core": "^1.1.0", 14 | "@pipe-dream/example-file-factory": "^1.0.3", 15 | "@pipe-dream/laravel-file-factory": "^1.1.0", 16 | "cross-env": "^5.1", 17 | "laravel-mix": "^4.0.14", 18 | "laravel-mix-purgecss": "^4.1", 19 | "laravel-mix-tailwind": "^0.1.0", 20 | "lodash": "^4.17.5", 21 | "popper.js": "^1.12", 22 | "resolve-url-loader": "^2.3.1", 23 | "sass": "^1.15.2", 24 | "sass-loader": "^7.1.0", 25 | "vue": "^2.5.17", 26 | "vue-template-compiler": "^2.6.4" 27 | }, 28 | "dependencies": { 29 | "brace": "^0.11.0", 30 | "change-case": "^3.1.0", 31 | "collect.js": "^4.6.5", 32 | "deepmerge": "^3.2.0", 33 | "pluralize": "^7.0.0", 34 | "vue-highlightjs": "^1.3.3", 35 | "vue-textarea-autosize": "^1.0.4", 36 | "vuex": "^3.1.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | [![Latest Stable Version](https://img.shields.io/packagist/v/pipe-dream/laravel-create.svg)](https://packagist.org/packages/pipe-dream/laravel-create) 3 | [![Total Downloads](https://img.shields.io/packagist/dt/pipe-dream/laravel.svg)](https://packagist.org/packages/pipe-dream/laravel) 4 | [![License](https://img.shields.io/packagist/l/pipe-dream/laravel-create.svg)](https://packagist.org/packages/pipe-dream/laravel-create) 5 | 6 | 7 | Create new web projects really fast. By giving Pipe Dream a minimum of input in form of a sketch/entity list it will predict your application schema and feed it into a set of pipes. These pipes will generate all the files needed to get started really quick. 8 | 9 | 10 | 11 | 12 | 13 | ## Installation 14 | 15 | Install Pipe Dream 16 | ```bash 17 | composer require --dev pipe-dream/laravel-create 18 | ``` 19 | 20 | Install the Laravel File Factory 21 | ```bash 22 | npm install --dev @pipe-dream/laravel-file-factory 23 | ``` 24 | More File Factories can be found [here](https://github.com/topics/pipe-dream-file-factory) 25 | 26 | Build Pipe Dream 27 | ```bash 28 | php artisan pipedream:build 29 | ``` 30 | 31 | Thats it, now open your browser and go to `/pipe-dream` and start designing. 32 | 33 | ## Usage 34 | If you havent already, [watch the 2 minute video](https://www.youtube.com/watch?v=doUlmZdvP1o). 35 | 36 | * List your models and tables in the sketch window. Note the schema is created in real-time and is being displayed on the right side of the screen. 37 | 38 | 39 | 40 | * Here are some pointers on the sketch syntax 41 | ```js 42 | // use PascalCase for models 43 | Garage 44 | location 45 | capacity 46 | 47 | // Separate your entities into chunks 48 | Car 49 | color 50 | user_id // foreign key 51 | 52 | // use snake_case model1_model2 to setup a ManyToMany relationship 53 | car_garage 54 | 55 | // use button to add a default user system 56 | User 57 | name 58 | email 59 | email_verified_at 60 | password 61 | remember_token 62 | 63 | // use snake_case to create a table 64 | password_resets 65 | email 66 | token 67 | ``` 68 | 69 | * Review the list of files that are going to be created. 70 | 71 | 72 | 73 | * Commit the files to disk. 74 | 75 | 76 | 77 | * You are now ready to migrate and seed. Go ahead and check out the API (at `/api`), that contains placeholder values 78 | 79 | 80 | 81 | ## Contributing 82 | PRs and issues are welcome. In addition to the issue section we have a [Trello board](https://trello.com/b/R11mhfdy/pipe-dream) listing things that we need help with. 83 | To get started and to learn more about the platform check out [pipe-dream/docs](https://github.com/pipe-dream/docs) 84 | 85 | ## License 86 | MIT 87 | 88 | ## Stay tuned! 89 | Follow me on twitter: [@ajthinking](https://twitter.com/ajthinking) 90 | 91 | Help me continue this work | Patreon 92 | -------------------------------------------------------------------------------- /src/Commands/PipeDreamBuild.php: -------------------------------------------------------------------------------- 1 | info("Rebuilding PipeDream..."); 34 | 35 | $appJSPath = __DIR__ . "/../resources/js/app.js"; 36 | $appJSOriginal = file_get_contents(__DIR__ . "/../resources/js/app_backup.js"); 37 | $PDFolder = __DIR__ . "/../../"; 38 | $app = file_get_contents($appJSPath); 39 | $nodeModules = base_path() . DIRECTORY_SEPARATOR . "node_modules"; 40 | 41 | $level1 = Collect(glob($nodeModules . DIRECTORY_SEPARATOR . "*/package.json")); 42 | $level2 = Collect(glob($nodeModules . DIRECTORY_SEPARATOR . "*/*/package.json")); 43 | $modules = $level1->merge($level2); 44 | 45 | $this->info("\nDiscovering PipeDream packages"); 46 | $bar = $this->output->createProgressBar(); 47 | $bar->start(); 48 | 49 | $pipeDreamModules = []; 50 | $master = []; 51 | foreach ($modules as $module) { 52 | $bar->advance(); 53 | $p = json_decode(file_get_contents($module), true); 54 | if (!array_key_exists('PipeDream', $p)) continue; 55 | if (array_key_exists('PipeDreamMaster', $p) && $p['PipeDreamMaster'] === true) { 56 | $master[rtrim($module, "/package.json")] = $p["PipeDream"]; 57 | continue; 58 | } 59 | $pipeDreamModules[rtrim($module, "/package.json")] = $p["PipeDream"]; 60 | } 61 | 62 | $pipeDreamModules = array_merge($master, $pipeDreamModules); 63 | 64 | $bar->finish(); 65 | $this->info("\n"); 66 | if (count($pipeDreamModules) === 0) { 67 | $this->error("No PipeDream modules found!"); 68 | return; 69 | } 70 | foreach ($pipeDreamModules as $pipeDreamModule) { 71 | $this->info("Discovered package: " . $pipeDreamModule); 72 | } 73 | $overwritten = str_replace("/* file factories will be automatically added */", implode(", ", $pipeDreamModules), $app); 74 | array_walk($pipeDreamModules, function (&$v, $path) { 75 | $v = 'import {' . $v . '} from "' . str_replace('\\', '/', $path) . '"'; 76 | }); 77 | $overwritten = str_replace("/* imports will be automatically added */", implode(";\n", $pipeDreamModules), $overwritten); 78 | 79 | file_put_contents($appJSPath, $overwritten); 80 | 81 | if(!file_exists($PDFolder . "node_modules")){ 82 | $this->info("Building PipeDream Node modules..."); 83 | exec("cd " . $PDFolder . " && npm install"); 84 | } 85 | 86 | $this->info("Compiling..."); 87 | if (!exec("cd " . $PDFolder . " && npm run dev")) { 88 | $this->info("!!!Something went wrong when compiling!!!"); 89 | file_put_contents($appJSPath, $app); 90 | exit(0); 91 | } 92 | $this->info("PipeDream was built successfully, go build something awesome!"); 93 | // set app.js back to the template for the next update 94 | file_put_contents($appJSPath, $appJSOriginal); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Controllers/PipeDreamAPIController.php: -------------------------------------------------------------------------------- 1 | args = json_decode(request()->getContent()); 20 | } 21 | 22 | public function build() 23 | { 24 | // Setup project - sandboxed or regular 25 | $this->setupProjectEnvironment(); 26 | 27 | // Optionally reverse the previous design iteration 28 | // This is useful to remove previous mistakes and timestamp conflicts 29 | // $this->args->reverseHistory ? $this->project->reverseHistory() : null; 30 | 31 | // Write the files generated 32 | $this->project->write($this->args->reviewFiles); 33 | 34 | // If there are user/password_reset tables already present 35 | $this->project->deleteDuplicateDefaultMigrations($this->args->reviewFiles); 36 | 37 | // Save the changes we made 38 | // $this->project->persistHistory(); 39 | 40 | // Ensure migrations are autoloaded 41 | exec('cd .. && composer dumpautoload'); 42 | // whats wrong with this package command??!! 43 | //Artisan::call('dump-autoload'); 44 | 45 | return response([ 46 | 'message' => 'Successfully stored files!', 47 | ], 200); 48 | } 49 | 50 | private function setupProjectEnvironment() 51 | { 52 | $this->project = ProjectFileManager::make( 53 | env('PIPEDREAM_IS_SANDBOXED') 54 | ); 55 | } 56 | 57 | private function pathToFileName($path) 58 | { 59 | return substr($path, strrpos($path, '/') + 1); 60 | } 61 | 62 | public function save(){ 63 | return collect("Save not implemented yet"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Controllers/PipeDreamWebController.php: -------------------------------------------------------------------------------- 1 | with([ 15 | 'settings' => [ 16 | 'isSandboxed' => env('PIPEDREAM_IS_SANDBOXED', false), 17 | 'appName' => request()->path(), 18 | 'workbench_data' => json_decode("{}") // not implemented 19 | ], 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/LaravelCreateServiceProvider.php: -------------------------------------------------------------------------------- 1 | commands([ 18 | PipeDreamBuild::class, 19 | ]); 20 | } 21 | 22 | /** 23 | * Bootstrap any application services. 24 | * 25 | * @return void 26 | */ 27 | public function boot() 28 | { 29 | $this->loadRoutesFrom(__DIR__.'/routes/routes.php'); 30 | $this->loadViewsFrom(__DIR__.'/resources/views', 'pipe-dream'); 31 | $this->registerStorages(); 32 | } 33 | 34 | /* 35 | * Laravels default publish feature is annoying for user 36 | * Composer has no post-require-hook (to do it after package install) 37 | * So resorting to do it every new page load 38 | * Please fix this 39 | */ 40 | public static function publishAssets() 41 | { 42 | \File::copyDirectory( 43 | __DIR__.'/public', 44 | public_path('vendor/pipe-dream/laravel-create') 45 | ); 46 | 47 | \File::copy( 48 | __DIR__.'/../data/dataTypeGithubDump.js', 49 | public_path('vendor/pipe-dream/laravel-create/data/github.js') 50 | ); 51 | } 52 | 53 | private function registerStorages() 54 | { 55 | $this->app['config']['filesystems.disks.self'] = [ 56 | 'driver' => 'local', 57 | 'root' => base_path(), 58 | ]; 59 | 60 | $this->app['config']['filesystems.disks.pipe-dream'] = [ 61 | 'driver' => 'local', 62 | 'root' => storage_path('pipe-dream'), 63 | ]; 64 | 65 | $this->app['config']['filesystems.disks.pipe-dream.sandbox'] = [ 66 | 'driver' => 'local', 67 | 'root' => storage_path('pipe-dream/sandbox'), 68 | ]; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/ProjectFileManager.php: -------------------------------------------------------------------------------- 1 | isSandboxed = $isSandboxed; 13 | if ($this->isSandboxed) { 14 | $this->setupSandboxProject(); 15 | } 16 | $this->history = []; 17 | } 18 | 19 | public static function make($isSandboxed) 20 | { 21 | return new self($isSandboxed); 22 | } 23 | 24 | public function write($files) 25 | { 26 | // $this->recordCurrentStateFor($files); 27 | 28 | collect($files)->each(function ($file) { 29 | $this->storage()->put($file->path, $file->content); 30 | }); 31 | } 32 | 33 | public function delete($files) 34 | { 35 | // $this->recordCurrentStateFor($files); 36 | 37 | collect($files)->each(function ($file) { 38 | $this->storage()->delete($file->path); 39 | }); 40 | } 41 | 42 | public function reverseHistory() 43 | { 44 | collect($this->loadHistory())->each(function ($content, $path) { 45 | if ($content == null) { 46 | return $this->storage()->delete($path); 47 | } 48 | 49 | $this->storage()->put($path, $content); 50 | }); 51 | } 52 | 53 | public function persistHistory() 54 | { 55 | $this->storage()->put( 56 | 'pipe-dream-history.json', 57 | json_encode($this->history) 58 | ); 59 | } 60 | 61 | public function deleteDuplicateDefaultMigrations($files) 62 | { 63 | if(collect($files)->pluck('path')->filter(function($path) { 64 | return preg_match('/create_users_table/', $path); 65 | })->isNotEmpty()) { 66 | $this->delete([ 67 | json_decode('{"path": "database/migrations/2014_10_12_000000_create_users_table.php"}') 68 | ]); 69 | } 70 | 71 | if(collect($files)->pluck('path')->filter(function($path) { 72 | return preg_match('/create_password_resets_table/', $path); 73 | })->isNotEmpty()) { 74 | $this->delete([ 75 | json_decode('{"path": "database/migrations/2014_10_12_100000_create_password_resets_table.php"}') 76 | ]); 77 | } 78 | } 79 | 80 | /*********** PRIVATE ************************************************** */ 81 | private function setupSandboxProject() 82 | { 83 | app()['config']['filesystems.disks.pipe-dream-sandbox-project'] = [ 84 | 'driver' => 'local', 85 | 'root' => storage_path('pipe-dream/sandbox/test-project'), 86 | ]; 87 | 88 | if (!Storage::disk('pipe-dream')->exists('sandbox/test-project')) { 89 | File::copyDirectory( 90 | storage_path('pipe-dream/laravel-including-vendors'), 91 | storage_path('pipe-dream/sandbox/test-project') 92 | ); 93 | } 94 | } 95 | 96 | private function loadHistory() 97 | { 98 | return $this->storage()->has('pipe-dream-history.json') ? 99 | json_decode($this->storage()->get('pipe-dream-history.json')) : []; 100 | } 101 | 102 | private function storage() 103 | { 104 | return Storage::disk( 105 | $this->isSandboxed ? 'pipe-dream-sandbox-project' : 'self' 106 | ); 107 | } 108 | 109 | private function recordCurrentStateFor($files) 110 | { 111 | collect($files)->each(function ($file) { 112 | $this->history[$file->path] = 113 | $this->storage()->has($file->path) ? 114 | $this->storage()->get($file->path) : 115 | null; 116 | }); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/public/data/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/data/.gitignore -------------------------------------------------------------------------------- /src/public/img/build.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/build.gif -------------------------------------------------------------------------------- /src/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/logo.png -------------------------------------------------------------------------------- /src/public/img/logo.svg: -------------------------------------------------------------------------------- 1 | Resurs 5 -------------------------------------------------------------------------------- /src/public/img/logo_with_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/logo_with_text.png -------------------------------------------------------------------------------- /src/public/img/screenshots/api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/screenshots/api.png -------------------------------------------------------------------------------- /src/public/img/screenshots/build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/screenshots/build.png -------------------------------------------------------------------------------- /src/public/img/screenshots/design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/screenshots/design.png -------------------------------------------------------------------------------- /src/public/img/screenshots/review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/screenshots/review.png -------------------------------------------------------------------------------- /src/public/img/video_splash_joke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipe-dream/laravel-create/70a183a375bb9f965f673c621474c6c1235e5cd7/src/public/img/video_splash_joke.png -------------------------------------------------------------------------------- /src/resources/css/app.css: -------------------------------------------------------------------------------- 1 | @import "~@pipe-dream/core/dist/pipe-dream.css"; 2 | -------------------------------------------------------------------------------- /src/resources/js/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import {PipeDream} from '@pipe-dream/core' 4 | import {Schema} from "@pipe-dream/core/"; 5 | import {PipeDreamVueTools} from '@pipe-dream/core' 6 | /* imports will be automatically added */ 7 | /* setup Vue to use Vuex and Pipe Dream components */ 8 | Vue.use(Vuex) 9 | Vue.use(PipeDreamVueTools) 10 | Vue.config.debug = true 11 | window.Vue = Vue 12 | 13 | /* Create Pipe Dream default store 14 | * Attach it to window to make it accessible inside core and file factories */ 15 | 16 | window.store = new Vuex.Store( 17 | new PipeDream({ 18 | fileFactories: [ 19 | /* file factories will be automatically added */ 20 | ], 21 | ...window.__ENV__ 22 | }).defaultStore 23 | ) 24 | 25 | /* Let's go */ 26 | new Vue({ 27 | el: '#app', 28 | store, 29 | mounted(){ 30 | //console.log(Schema.refresh(true)) 31 | store.dispatch('compileSchema', Schema); 32 | } 33 | }) 34 | -------------------------------------------------------------------------------- /src/resources/js/app_backup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import {PipeDream} from '@pipe-dream/core' 4 | import {Schema} from "@pipe-dream/core/"; 5 | import {PipeDreamVueTools} from '@pipe-dream/core' 6 | /* imports will be automatically added */ 7 | /* setup Vue to use Vuex and Pipe Dream components */ 8 | Vue.use(Vuex) 9 | Vue.use(PipeDreamVueTools) 10 | Vue.config.debug = true 11 | window.Vue = Vue 12 | 13 | /* Create Pipe Dream default store 14 | * Attach it to window to make it accessible inside core and file factories */ 15 | 16 | window.store = new Vuex.Store( 17 | new PipeDream({ 18 | fileFactories: [ 19 | /* file factories will be automatically added */ 20 | ], 21 | ...window.__ENV__ 22 | }).defaultStore 23 | ) 24 | 25 | /* Let's go */ 26 | new Vue({ 27 | el: '#app', 28 | store, 29 | mounted(){ 30 | //console.log(Schema.refresh(true)) 31 | store.dispatch('compileSchema', Schema); 32 | } 33 | }) 34 | -------------------------------------------------------------------------------- /src/resources/views/spa.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {{ config('app.name', 'Laravel') }} 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 |
24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/routes/routes.php: -------------------------------------------------------------------------------- 1 |