├── docs
├── .vitepress
│ ├── cache
│ │ └── deps
│ │ │ ├── package.json
│ │ │ ├── _metadata.json
│ │ │ ├── @theme_index.js.map
│ │ │ └── @theme_index.js
│ └── config.js
├── guide
│ ├── roadmap.md
│ ├── about.md
│ ├── license.md
│ ├── search.md
│ ├── remove.md
│ ├── soft-deletes.md
│ ├── authentication.md
│ ├── gotchas.md
│ ├── nesting.md
│ ├── install.md
│ ├── options.md
│ ├── crud.md
│ ├── customization.md
│ └── index.md
├── badges.md
├── index.md
├── readme.php
├── LICENSE.md
└── CONTRIBUTING.md
├── config
└── crud.php
├── src
├── template
│ └── stubs
│ │ ├── views
│ │ ├── bootstrap
│ │ │ ├── partials
│ │ │ │ ├── display
│ │ │ │ │ ├── boolean.blade.php
│ │ │ │ │ ├── string.blade.php
│ │ │ │ │ ├── text.blade.php
│ │ │ │ │ └── json.blade.php
│ │ │ │ ├── inputs
│ │ │ │ │ ├── json.blade.php
│ │ │ │ │ ├── textarea.blade.php
│ │ │ │ │ ├── input.blade.php
│ │ │ │ │ ├── select.blade.php
│ │ │ │ │ ├── boolean.blade.php
│ │ │ │ │ └── related.blade.php
│ │ │ │ ├── render
│ │ │ │ │ ├── breadcrumbs.blade.php
│ │ │ │ │ ├── form.blade.php
│ │ │ │ │ ├── cards.blade.php
│ │ │ │ │ ├── show.blade.php
│ │ │ │ │ ├── chat.blade.php
│ │ │ │ │ └── table.blade.php
│ │ │ │ └── buttons
│ │ │ │ │ ├── actions-expanded.blade.php
│ │ │ │ │ ├── actions-trash.blade.php
│ │ │ │ │ └── actions.blade.php
│ │ │ ├── layout.blade.php
│ │ │ ├── create.blade.php
│ │ │ ├── edit.blade.php
│ │ │ ├── show.blade.php
│ │ │ ├── create-edit.blade.php
│ │ │ └── index.blade.php
│ │ ├── larastrap
│ │ │ ├── partials
│ │ │ │ ├── display
│ │ │ │ │ ├── boolean.blade.php
│ │ │ │ │ ├── string.blade.php
│ │ │ │ │ ├── text.blade.php
│ │ │ │ │ └── json.blade.php
│ │ │ │ ├── render
│ │ │ │ │ ├── form.blade.php
│ │ │ │ │ ├── breadcrumbs.blade.php
│ │ │ │ │ ├── cards.blade.php
│ │ │ │ │ ├── show.blade.php
│ │ │ │ │ ├── chat.blade.php
│ │ │ │ │ └── table.blade.php
│ │ │ │ ├── inputs
│ │ │ │ │ ├── input.blade.php
│ │ │ │ │ ├── json.blade.php
│ │ │ │ │ ├── textarea.blade.php
│ │ │ │ │ ├── select.blade.php
│ │ │ │ │ ├── boolean.blade.php
│ │ │ │ │ └── related.blade.php
│ │ │ │ └── buttons
│ │ │ │ │ ├── actions-expanded.blade.php
│ │ │ │ │ ├── actions-trash.blade.php
│ │ │ │ │ └── actions.blade.php
│ │ │ ├── layout.blade.php
│ │ │ ├── edit.blade.php
│ │ │ ├── create.blade.php
│ │ │ ├── show.blade.php
│ │ │ ├── create-edit.blade.php
│ │ │ └── index.blade.php
│ │ └── tailwind
│ │ │ ├── partials
│ │ │ ├── display
│ │ │ │ ├── boolean.blade.php
│ │ │ │ ├── string.blade.php
│ │ │ │ ├── text.blade.php
│ │ │ │ └── json.blade.php
│ │ │ ├── inputs
│ │ │ │ ├── json.blade.php
│ │ │ │ ├── textarea.blade.php
│ │ │ │ ├── input.blade.php
│ │ │ │ ├── select.blade.php
│ │ │ │ ├── boolean.blade.php
│ │ │ │ └── related.blade.php
│ │ │ ├── render
│ │ │ │ ├── form.blade.php
│ │ │ │ ├── breadcrumbs.blade.php
│ │ │ │ ├── cards.blade.php
│ │ │ │ ├── show.blade.php
│ │ │ │ ├── chat.blade.php
│ │ │ │ └── table.blade.php
│ │ │ └── buttons
│ │ │ │ ├── actions-trash.blade.php
│ │ │ │ └── actions.blade.php
│ │ │ ├── edit.blade.php
│ │ │ ├── create.blade.php
│ │ │ ├── create-edit.blade.php
│ │ │ ├── index.blade.php
│ │ │ ├── show.blade.php
│ │ │ └── layout.blade.php
│ │ ├── Models
│ │ └── _model_.php
│ │ ├── routes
│ │ └── _route_.php
│ │ ├── Policies
│ │ └── _policy_.php
│ │ └── Controllers
│ │ └── _controller_.php
├── Crud.php
├── Formatters
│ └── Formatter.php
├── Utils
│ ├── TextUtils.php
│ ├── RouteUtils.php
│ ├── NameUtils.php
│ ├── FileUtils.php
│ └── SchemaUtils.php
├── ServiceProvider.php
├── Generators
│ ├── Templates.php
│ ├── PolicyGen.php
│ ├── ModelGen.php
│ ├── RouteGen.php
│ ├── BaseGen.php
│ ├── ViewGen.php
│ └── ControllerGen.php
└── Commands
│ ├── CrudTemplate.php
│ ├── CrudBase.php
│ ├── CrudRemove.php
│ └── CrudGenerate.php
├── package.json
├── .github
├── ISSUE_TEMPLATE
│ └── bug-reporting.md
└── workflows
│ └── deploy.yml
├── database
└── migrations
│ ├── replies_table.php
│ ├── leads_table.php
│ ├── tickets_table.php
│ └── users_table.php
├── composer.json
├── LICENSE.md
├── .phpunit.result.cache
└── yarn.lock
/docs/.vitepress/cache/deps/package.json:
--------------------------------------------------------------------------------
1 | {"type":"module"}
--------------------------------------------------------------------------------
/config/crud.php:
--------------------------------------------------------------------------------
1 | NULL,
5 | ];
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/display/boolean.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_var_->_col_ ? "Yes" : "No" }}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/display/string.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_var_->_col_ ?: "(blank)" }}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/display/boolean.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_var_->_col_ ? "Yes" : "No" }}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/display/string.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_var_->_col_ ?: "(blank)" }}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/display/boolean.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_var_->_col_ ? "Yes" : "No" }}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/display/string.blade.php:
--------------------------------------------------------------------------------
1 | {{ $_var_->_col_ ?: "(blank)" }}
2 |
--------------------------------------------------------------------------------
/docs/guide/roadmap.md:
--------------------------------------------------------------------------------
1 | # Roadmap
2 |
3 | - Add support for Livewire
4 | - Add support for Laravel Jetstream
5 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/display/text.blade.php:
--------------------------------------------------------------------------------
1 | {{ Str::limit($_var_->_col_, 50) ?: "(blank)"}}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/display/text.blade.php:
--------------------------------------------------------------------------------
1 | {{ Str::limit($_var_->_col_, 50) ?: "(blank)"}}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/display/text.blade.php:
--------------------------------------------------------------------------------
1 | {{ Str::limit($_var_->_col_, 50) ?: "(blank)"}}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/render/form.blade.php:
--------------------------------------------------------------------------------
1 | @foreach($fields as $field)
2 | {!! $input($field) !!}
3 | @endforeach
4 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/inputs/input.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/inputs/json.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/inputs/textarea.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/inputs/json.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/render/breadcrumbs.blade.php:
--------------------------------------------------------------------------------
1 |
{!! $anchortext !!}
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/render/breadcrumbs.blade.php:
--------------------------------------------------------------------------------
1 | {!! $anchortext !!}
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/display/json.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/display/json.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/inputs/select.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/inputs/boolean.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/inputs/textarea.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/inputs/input.blade.php:
--------------------------------------------------------------------------------
1 | $errors->has('_id_')])>
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/display/json.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/guide/about.md:
--------------------------------------------------------------------------------
1 | # About
2 |
3 | **Found any bugs?** Report them on the [issue tracker](https://github.com/san-kumar/laravel-crud/issues).
4 |
5 | **Want to contribute?** Fork the project on GitHub and send a
6 | pull request.
7 |
8 | **Like the project?** Star it on GitHub.
9 |
--------------------------------------------------------------------------------
/src/Crud.php:
--------------------------------------------------------------------------------
1 | {{_val_}}
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/inputs/textarea.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/guide/license.md:
--------------------------------------------------------------------------------
1 | # License
2 |
3 | The software is licensed using a MIT License. It means you
4 | can do whatever you want with it (including using it for
5 | commercial purposes freely), as long as you include the
6 | original copyright and license notice in any copy of the
7 | software/source.
8 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/render/form.blade.php:
--------------------------------------------------------------------------------
1 | @foreach($fields as $field)
2 |
3 | {{$field->name}}:
4 | {!! $input($field) !!}
5 | {!! $err($field) !!}
6 |
7 | @endforeach
8 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/inputs/input.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/inputs/select.blade.php:
--------------------------------------------------------------------------------
1 | $errors->has('_id_')])>
2 | Select _name_
3 | @foreach(_enums_ as $value => $label )
4 | {{ $label }}
5 | @endforeach
6 |
7 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/inputs/related.blade.php:
--------------------------------------------------------------------------------
1 |
2 | Create new _label_
3 |
--------------------------------------------------------------------------------
/src/Formatters/Formatter.php:
--------------------------------------------------------------------------------
1 | hasSoftDeletes()) {
11 | $str = preg_replace('#//@softdelete.*?@endsoftdelete#s', '', $str);
12 | }
13 |
14 | return $str;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/render/form.blade.php:
--------------------------------------------------------------------------------
1 | @foreach($fields as $field)
2 |
3 |
4 | {{$field->name}}:
5 | {!! $input($field) !!}
6 | {!! $err($field) !!}
7 |
8 |
9 | @endforeach
10 |
--------------------------------------------------------------------------------
/src/template/stubs/Models/_model_.php:
--------------------------------------------------------------------------------
1 | ",
7 | "license": "MIT",
8 | "scripts": {
9 | "docs:dev": "vitepress dev docs --host localhost",
10 | "docs:build": "vitepress build docs",
11 | "docs:preview": "vitepress preview docs"
12 | },
13 | "devDependencies": {
14 | "vitepress": "^1.0.0-alpha.33",
15 | "vue": "^3.2.45"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/docs/guide/search.md:
--------------------------------------------------------------------------------
1 | # Inbuilt search
2 |
3 | A very simple search is added to the list view by default.
4 | It searches the first text column of the table and filters
5 | the results.
6 |
7 | This generated search code is just a placeholder, and you
8 | should customize it as per your own needs.
9 |
10 | > 
11 | > (Inbuilt search)
12 |
13 | To modify the search algorithm just edit the `index` method
14 | of the Resource controller for that route.
--------------------------------------------------------------------------------
/src/template/stubs/routes/_route_.php:
--------------------------------------------------------------------------------
1 | group(function () {
7 | Route::resource('_parentrouteurlwithvars_', _controller_::class, [/*_asroute_*/]);
8 | //@softdelete
9 | Route::put('_routeurlwithvars_/restore', [_controller_::class, 'restore'])->name('_route_.restore');
10 | Route::delete('_routeurlwithvars_/purge', [_controller_::class, 'purge'])->name('_route_.purge');
11 | //@endsoftdelete
12 | });
13 |
--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/_metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "hash": "576f85bf",
3 | "browserHash": "2852436b",
4 | "optimized": {
5 | "vue": {
6 | "src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
7 | "file": "vue.js",
8 | "fileHash": "2b8c4af0",
9 | "needsInterop": false
10 | },
11 | "@theme/index": {
12 | "src": "../../../../node_modules/vitepress/dist/client/theme-default/index.js",
13 | "file": "@theme_index.js",
14 | "fileHash": "eaeed8d1",
15 | "needsInterop": false
16 | }
17 | },
18 | "chunks": {}
19 | }
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/inputs/select.blade.php:
--------------------------------------------------------------------------------
1 |
2 | Select _name_
3 | @foreach(_enums_ as $value => $label )
4 | {{ $label }}
5 | @endforeach
6 |
7 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/inputs/boolean.blade.php:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-reporting.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: bug reporting
3 | about: How to report an issue
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | Before submitting a bug report please make sure to include the following information
11 |
12 | 1. Have you set the mysql password in the .env file?
13 |
14 | 2. Have you created the db migrations using `artisan migrate`?
15 |
16 | 3. Can laravel can connect to your mysql db?
17 |
18 | 4. Are you able to see the output for `User:all()`?
19 |
20 | 5. Can you see the tables you've created in the mysql database? (using phpmyadmin or mysql client)
21 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/inputs/related.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Select _name_
4 | @foreach($_relateds_ as $_related_)
5 | id ? "selected" : "" }}>{{ $_related_->_readable_ }}
6 | @endforeach
7 |
8 |
9 |
New
10 |
11 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/buttons/actions-expanded.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/buttons/actions-expanded.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/render/breadcrumbs.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {!! $anchortext !!}
7 |
8 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/render/cards.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | @@foreach ($_vars_ as $_var_)
4 |
5 |
6 |
_title_ #@{{ $_var_->id }}
7 |
@{{ $_var_->_readable_ }}
8 |
9 |
16 |
17 | @@endforeach
18 |
19 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/render/cards.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | @@foreach ($_vars_ as $_var_)
4 |
5 |
6 |
_title_ #@{{ $_var_->id }}
7 |
@{{ $_var_->_readable_ }}
8 |
9 |
16 |
17 | @@endforeach
18 |
19 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/buttons/actions-trash.blade.php:
--------------------------------------------------------------------------------
1 | @@if($_var_->trashed())
2 |
7 |
12 | @@else
13 | {!! $render('buttons/actions') !!}
14 | @@endif
15 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/buttons/actions-trash.blade.php:
--------------------------------------------------------------------------------
1 | @@if($_var_->trashed())
2 |
7 |
12 | @@else
13 | {!! $render('buttons/actions') !!}
14 | @@endif
15 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | with:
14 | fetch-depth: 0
15 | - uses: actions/setup-node@v3
16 | with:
17 | node-version: 16
18 | cache: yarn
19 | - run: yarn install --frozen-lockfile
20 |
21 | - name: Build
22 | run: yarn docs:build
23 |
24 | - name: Deploy
25 | uses: peaceiris/actions-gh-pages@v3
26 | with:
27 | github_token: ${{ secrets.GITHUB_TOKEN }}
28 | publish_dir: docs/.vitepress/dist
29 | # cname: example.com # if wanna deploy to custom domain
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/inputs/boolean.blade.php:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/docs/guide/remove.md:
--------------------------------------------------------------------------------
1 | # Removing the generated CRUD files
2 |
3 | ## Remove files
4 |
5 | Laravel CRUD Generator allows you to remove the generated
6 | files using the `artisan crud:remove` command.
7 |
8 | ```bash
9 | $ php artisan crud:remove customers.tickets.replies
10 | ```
11 |
12 | This will remove all the files generated by
13 | the `crud:generate` for this table.
14 |
15 | ## Backup
16 |
17 | If you want to keep the generated files, you can use the
18 | `--backup` option to move the files into a Zip archive
19 | instead.
20 |
21 | ```bash
22 | $ php artisan crud:remove customers.tickets.replies --backup=backup.zip
23 | ```
24 |
25 | This too will remove the files from the disk but will also
26 | create a Zip archive of all the removed files too.
27 |
28 |
--------------------------------------------------------------------------------
/docs/badges.md:
--------------------------------------------------------------------------------
1 | [](LICENSE.md)
2 | [](https://circleci.com/gh/san-kumar/laravel-crud)
3 | [](https://raw.githack.com/san-kumar/laravel-crud/main/build/coverage/index.html)
4 | [](https://packagist.org/packages/san-kumar/laravel-crud)
5 | [](https://img.shields.io/packagist/dt/san-kumar/laravel-crud.svg?style=flat-square)
6 |
7 |
--------------------------------------------------------------------------------
/src/Utils/TextUtils.php:
--------------------------------------------------------------------------------
1 | $value) {
10 | $k = "_{$key}_";
11 | $text = str_replace("/*\$$k*/", "\$$value", $text);
12 | $text = str_replace("/*$k*/", $value, $text);
13 | $text = str_replace($k, $value, $text);
14 | }
15 |
16 | return preg_replace('/(\s*\n){2,}/', "\n\n", $text);
17 | }
18 |
19 | public static function arrayExport($arr) {
20 | return sprintf('[%s]', implode(', ', array_map(fn($v) => is_string($v) ? sprintf('"%s" => "%s"', $v, Str::title($v)) : $v, $arr)));
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/render/cards.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | @@foreach ($_vars_ as $_var_)
4 |
5 |
6 |
_title_ #@{{ $_var_->id }}
7 |
@{{ $_var_->_readable_ }}
8 |
9 |
10 | @if(!empty($hasSoftDelete))
11 | {!! $render('buttons/actions-trash') !!}
12 | @else
13 | {!! $render('buttons/actions') !!}
14 | @endif
15 |
16 |
17 | @@endforeach
18 |
19 |
--------------------------------------------------------------------------------
/docs/guide/soft-deletes.md:
--------------------------------------------------------------------------------
1 | # Soft deletes
2 |
3 | Laravel provides a simple way to implement soft deletes on
4 | your Eloquent models. Soft deletes allow you to keep a
5 | record of a model's deletion without actually deleting the
6 | model from your database. This allows you to restore the
7 | model at a later time if needed.
8 |
9 | Laravel CRUD generator handles tables with soft deletes
10 | automatically and generates the appropriate code for you to
11 | restore or purge deleted records.
12 |
13 | > 
14 | > (Handling soft deletes)
15 |
16 | To show deleted records in the list view, just append
17 | `?trashed=1` to the URL (this link isn't added to the
18 | navigation menu by default, so you have to add it manually).
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/render/show.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ID:
5 | @{{$_var_->id}}
6 |
7 | @foreach ($fields as $field)
8 |
9 | {{ $field->name }}:
10 | {!! $display($field) !!}
11 |
12 | @endforeach
13 | @if($hasTimestamps)
14 |
15 | Created at
16 | @{{Carbon\Carbon::parse($_var_->created_at)->format('d/m/Y H:i:s')}}
17 |
18 |
19 | Updated at
20 | @{{Carbon\Carbon::parse($_var_->updated_at)->format('d/m/Y H:i:s')}}
21 |
22 | @endif
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/render/show.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ID:
5 | @{{$_var_->id}}
6 |
7 | @foreach ($fields as $field)
8 |
9 | {{ $field->name }}:
10 | {!! $display($field) !!}
11 |
12 | @endforeach
13 | @if($hasTimestamps)
14 |
15 | Created at
16 | @{{Carbon\Carbon::parse($_var_->created_at)->format('d/m/Y H:i:s')}}
17 |
18 |
19 | Updated at
20 | @{{Carbon\Carbon::parse($_var_->updated_at)->format('d/m/Y H:i:s')}}
21 |
22 | @endif
23 |
24 |
25 |
--------------------------------------------------------------------------------
/database/migrations/replies_table.php:
--------------------------------------------------------------------------------
1 | id();
16 | $table->integer('ticket_id');
17 | $table->text('body');
18 | $table->boolean('is_admin')->default(FALSE);
19 | $table->timestamps();
20 | });
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down() {
29 | Schema::dropIfExists('replies');
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/render/show.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ID:
5 | @{{$_var_->id}}
6 |
7 | @foreach ($fields as $field)
8 |
9 | {{ $field->name }}:
10 | {!! $display($field) !!}
11 |
12 | @endforeach
13 | @if($hasTimestamps)
14 |
15 | Created at
16 | @{{Carbon\Carbon::parse($_var_->created_at)->format('d/m/Y H:i:s')}}
17 |
18 |
19 | Updated at
20 | @{{Carbon\Carbon::parse($_var_->updated_at)->format('d/m/Y H:i:s')}}
21 |
22 | @endif
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/buttons/actions.blade.php:
--------------------------------------------------------------------------------
1 | @@lang('Show')
2 |
3 |
4 |
14 |
15 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/buttons/actions.blade.php:
--------------------------------------------------------------------------------
1 | @@lang('Show')
2 |
3 |
4 |
14 |
15 |
--------------------------------------------------------------------------------
/database/migrations/leads_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->integer('user_id');
19 | $table->string('name');
20 | $table->string('email');
21 |
22 | $table->timestamps();
23 | $table->softDeletes();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('leads');
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/database/migrations/tickets_table.php:
--------------------------------------------------------------------------------
1 | id();
16 | $table->integer('lead_id');
17 | $table->integer('user_id');
18 | $table->string('subject');
19 | $table->json('extra_data')->nullable();
20 | $table->timestamps();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down() {
30 | Schema::dropIfExists('tickets');
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/database/migrations/users_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->string('name');
19 | $table->string('email')->unique();
20 | $table->timestamp('email_verified_at')->nullable();
21 | $table->string('password');
22 | $table->rememberToken();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('users');
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/render/chat.blade.php:
--------------------------------------------------------------------------------
1 | @@for($i = 0, $_var_ = $_vars_[0]; $i < count($_vars_); $i++, $_var_ = $_vars_[$i])
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 | @{{ $_var_->_readable_ }}
13 |
14 |
15 |
16 |
17 | @@endfor
18 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/render/chat.blade.php:
--------------------------------------------------------------------------------
1 | @@for($i = 0, $_var_ = $_vars_[0]; $i < count($_vars_); $i++, $_var_ = $_vars_[$i])
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 | @{{ $_var_->_readable_ }}
13 |
14 |
15 |
16 |
17 | @@endfor
18 |
--------------------------------------------------------------------------------
/src/ServiceProvider.php:
--------------------------------------------------------------------------------
1 | commands([
13 | Commands\CrudGenerate::class,
14 | Commands\CrudRemove::class,
15 | Commands\CrudTemplate::class,
16 | ]);
17 | }
18 |
19 | /**
20 | * {@inheritdoc}
21 | */
22 | public function boot() {
23 | $this->publishes([
24 | __DIR__ . '/../config/crud.php' => config_path('crud.php'),
25 | ]);
26 | }
27 |
28 | /**
29 | * {@inheritdoc}
30 | */
31 | public function provides() {
32 | return [
33 | Commands\CrudGenerate::class,
34 | Commands\CrudRemove::class,
35 | Commands\CrudTemplate::class,
36 | ];
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: Laravel CRUD
6 | text: Generate CRUD for your db tables instantly!
7 | tagline: Zero learning curve. Save time. Avoid errors.
8 | actions:
9 | - theme: brand
10 | text: Get Started
11 | link: /guide/index
12 | - theme: alt
13 | text: View on GitHub
14 | link: https://github.com/san-kumar/laravel-crud
15 |
16 | features:
17 | - icon: ⚡️
18 | title: Nested Tables Support
19 | details: Generate CRUD for nested tables. For example, generate CRUD for comments inside a blog post.
20 | link: /test
21 | - icon: 🖖
22 | title: Bootstrap 5 and Tailwind CSS
23 | details: Supports both Bootstrap 5 and Tailwind CSS or you can use your own CSS framework.
24 | link: /test
25 | - icon: 🛠️
26 | title: Models, Gates, Policies, Views, Controllers, Routes and more
27 | details: Generate everything you need with one single "artisan crud:generate" command
28 | link: /test
29 | ---
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/partials/render/table.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @foreach($fields as $field)
5 | {{ $field->name }}
6 | @endforeach
7 | Actions
8 |
9 |
10 |
11 | @@foreach ($_vars_ as $_var_)
12 |
13 | @foreach($fields as $field)
14 | {!! $display($field) !!}
15 | @endforeach
16 |
17 |
18 | @if(!empty($hasSoftDelete))
19 | {!! $render('buttons/actions-trash') !!}
20 | @else
21 | {!! $render('buttons/actions') !!}
22 | @endif
23 |
24 |
25 | @@endforeach
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/partials/render/table.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @foreach($fields as $field)
5 | {{ $field->name }}
6 | @endforeach
7 | Actions
8 |
9 |
10 |
11 | @@foreach ($_vars_ as $_var_)
12 |
13 | @foreach($fields as $field)
14 | {!! $display($field) !!}
15 | @endforeach
16 |
17 |
18 | @if(!empty($hasSoftDelete))
19 | {!! $render('buttons/actions-trash') !!}
20 | @else
21 | {!! $render('buttons/actions') !!}
22 | @endif
23 |
24 |
25 | @@endforeach
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/inputs/related.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Select _name_
4 | @foreach($_relateds_ as $_related_)
5 | id ? "selected" : "" }}>{{ $_related_->_readable_ }}
6 | @endforeach
7 |
8 |
9 |
New
10 |
11 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/buttons/actions-trash.blade.php:
--------------------------------------------------------------------------------
1 | @@if($_var_->trashed())
2 |
3 |
8 |
13 |
14 | @@else
15 | {!! $render('buttons/actions') !!}
16 | @@endif
17 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "san-kumar/laravel-crud",
3 | "description": "Laravel CRUD generator: Generate CRUD for any db table with the crud:generate command.",
4 | "keywords": [
5 | "artisan",
6 | "laravel",
7 | "crud",
8 | "view",
9 | "templates",
10 | "blade"
11 | ],
12 | "license": "MIT",
13 | "authors": [
14 | {
15 | "name": "San Kumar",
16 | "email": "sanchitbh@gmail.com",
17 | "homepage": "https://dayandnight.in"
18 | }
19 | ],
20 | "require": {
21 | "php": "^8.0",
22 | "doctrine/dbal": "^3.5"
23 | },
24 | "require-dev": {
25 | "laravel/framework": "^8.0 || ^9.0",
26 | "phpunit/phpunit": "^9.0 || ^10.0",
27 | "mockery/mockery": "^1.4",
28 | "orchestra/testbench": "*"
29 | },
30 | "autoload": {
31 | "psr-4": {
32 | "San\\Crud\\": "src/"
33 | }
34 | },
35 | "autoload-dev": {
36 | "psr-4": {
37 | "San\\Crud\\Tests\\": "tests/"
38 | }
39 | },
40 | "extra": {
41 | "laravel": {
42 | "providers": [
43 | "San\\Crud\\ServiceProvider"
44 | ]
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/docs/readme.php:
--------------------------------------------------------------------------------
1 | ## Please see the [**full documentation here**](https://san-kumar.github.io/laravel-crud/).\n\n";
17 | $content = preg_replace("/## Introduction\n/", "## Introduction\n\n" . file_get_contents(__DIR__ . '/badges.md') . "\n\n$docs", $content);
18 | $content = preg_replace_callback("/:::warning(.*?):::/ms", fn($match) => "> " . join("\n> ", explode("\n", $match[1])), $content);
19 | $content = preg_replace("#\(/guide#", "(https://san-kumar.github.io/laravel-crud/guide", $content);
20 |
21 | file_put_contents(__DIR__ . '/../README.md', $content);
22 | } else {
23 | echo "No files found";
24 | }
25 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/buttons/actions.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/layout.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_layout_')
2 |
3 | @section('_section_')
4 | @if(isset($showErrors))
5 | @if ($errors->any())
6 |
7 |
8 |
9 | @foreach ($errors->all() as $error)
10 | {{ $error }}
11 | @endforeach
12 |
13 |
14 |
15 | @endif
16 |
17 | @if (session('success') || session('error'))
18 |
19 |
20 | {{ session('success') ? : session('error') }}
21 |
22 |
23 |
24 | @endif
25 | @endif
26 |
27 | @yield('_vars_.content')
28 | @endsection
29 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/layout.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_layout_')
2 |
3 | @section('_section_')
4 | @if(isset($showErrors))
5 | @if ($errors->any())
6 |
7 |
8 |
9 | @foreach ($errors->all() as $error)
10 | {{ $error }}
11 | @endforeach
12 |
13 |
14 |
15 | @endif
16 |
17 | @if (session('success') || session('error'))
18 |
19 |
20 | {{ session('success') ? : session('error') }}
21 |
22 |
23 |
24 | @endif
25 | @endif
26 |
27 | @yield('_vars_.content')
28 | @endsection
29 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | Copyright (c) San Kumar
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 |
--------------------------------------------------------------------------------
/docs/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | Copyright (c) San Kumar
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 |
--------------------------------------------------------------------------------
/docs/guide/authentication.md:
--------------------------------------------------------------------------------
1 | # Authentication
2 |
3 | Laravel CRUD generator uses the default Laravel
4 | authentication
5 | package [laravel/ui](https://laravel.com/docs/7.x/authentication#included-routing)
6 | for handling user authentication. The CRUD generator will
7 | automatically add authentication to routes (using the
8 | `auth` middleware) and generate Policy classes for Models.
9 |
10 | ## `user_id` field in table
11 |
12 | If you generate CRUD for any table that has a `user_id`
13 | field, then the generated CRUD will automatically generate a
14 | Policy file for the Model and add the
15 | [`authorizeResource`](https://laravel.com/docs/7.x/authorization#authorizing-actions-using-policies)
16 | method to the Resource Controller.
17 |
18 | ## `user_id` in parent tables
19 |
20 | If you generate CRUD for a table that has a `user_id` field
21 | in the parent tables (i.e. `authors.posts.comments` has a
22 | `user_id` field in the `authors` table), then the generated
23 | CRUD will automatically generate a Policy file for
24 | the `Authors` Model and add it to your Resource Controller
25 | in the appropriate places.
26 |
27 | This way access to `posts` and `comments` will be restricted
28 | to the owner of the `authors` table only.
29 |
30 |
--------------------------------------------------------------------------------
/docs/guide/gotchas.md:
--------------------------------------------------------------------------------
1 | # Known Gotchas
2 |
3 | ## Laravel Jetstream
4 |
5 | Laravel CRUD generator doesn't seem to work with
6 | [Laravel jetstream](https://jetstream.laravel.com/)
7 | just yet. If you are using jetstream, you can still use the
8 | package, but you will have to manually modify some generated
9 | code to fix the layout and authentication issues.
10 |
11 | ## Inbuilt search
12 |
13 | A very simple search is added to the list view by default.
14 | It searches the first text column of the table and filters
15 | the results. But this generated search code is just a
16 | rudimentary placeholder, and you should customize the search
17 | algorithm as per your own needs.
18 |
19 | ## Opinionated code
20 |
21 | While the package tries to be as flexible as possible, it
22 | still generates some opinionated code. For example, the
23 | generated CRUD uses Laravel's `Policy` classes for handling
24 | authorization. But you may prefer to use something else
25 | like `spatie/laravel-permission`, which can be done but
26 | requires you
27 | to [create your own templates](/guide/customization).
28 |
29 | ## Alpha version
30 |
31 | You should only use it with new projects. If you are using
32 | it in an existing project, make sure to back up (or commit)
33 | any project changes before running the command.
34 |
--------------------------------------------------------------------------------
/src/Generators/Templates.php:
--------------------------------------------------------------------------------
1 | path/stubs/$suffix", ['php']);
17 | return array_values(array_filter($files, fn($file) => !\str_contains($file, 'partials')));
18 | }
19 |
20 | public function getFirstStub(string $suffix) {
21 | $stubs = $this->getStubs($suffix);
22 | return $stubs[0] ?? NULL;
23 | }
24 |
25 | public function getDest(string $type, mixed $stub, array $replacements = [], string $suffix = '') {
26 | $dest = \str_contains($type, 'views/') ? resource_path('views') . "/$suffix" : ($type === 'routes' ? base_path("routes/crud") : ($type === 'Controllers' ? app_path('Http/Controllers') : app_path($type)));
27 | $str = sprintf('%s/%s', $dest, basename($stub));
28 | return TextUtils::replaceBlanks($str, $replacements);
29 | }
30 |
31 | public function templatePath() {
32 | return $this->path;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
30 | @endsection
31 |
--------------------------------------------------------------------------------
/src/Utils/RouteUtils.php:
--------------------------------------------------------------------------------
1 | sprintf("'%s'", $var), (array) $vars)) ?: '[]');
13 | return sprintf("route('%s', %s)", $name, $args);
14 | } else { //fallback code to handle undefined routes to prevent errors
15 | $parts = explode('.', $name);
16 | $values = array_values((array) $vars);
17 |
18 | $path = [sprintf("'%s'", rtrim("/" . trim($prefix ?: '', '/'), '/'))];
19 |
20 | for ($i = 0; $i < count($parts); $i++) {
21 | if ($parts[$i] === 'index') continue;
22 |
23 | if ($parts[$i] !== 'show') {
24 | $path[] = sprintf("'%s'", $parts[$i]);
25 | }
26 |
27 | if (!empty($values[$i])) {
28 | $path[] = is_scalar($vars) ? $values[$i] : sprintf("$%s?->id ?: 0", $values[$i]);
29 | }
30 | }
31 |
32 | return sprintf("implode('/', [%s])", join(',', $path));
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Utils/NameUtils.php:
--------------------------------------------------------------------------------
1 | Str::studly(Str::singular($tableName)), (array) $tables));
14 | }
15 |
16 | public static function getModelName(string|array $tables) {
17 | return self::studlyCase((array) $tables);
18 | }
19 |
20 | public static function getControllerName(string|array $tables) {
21 | return self::studlyCase((array) $tables) . 'Controller';
22 | }
23 |
24 | public static function getRouteName(string|array $tables) {
25 | return join('.', array_map(fn($tableName) => Str::kebab(Str::plural($tableName)), (array) $tables));
26 | }
27 |
28 | public static function getVariableName(string $table) {
29 | return Str::singular(self::getVariableNamePlural($table));
30 | }
31 |
32 | public static function getVariableNamePlural(string $table) {
33 | return Str::camel($table);
34 | }
35 |
36 | public static function getPolicyName(string|array $tables) {
37 | return self::studlyCase((array) $tables) . 'Policy';
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
12 |
13 |
14 |
15 | _edit_
16 |
17 |
23 |
24 |
25 |
26 |
27 | @endsection
28 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
29 | @endsection
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
12 |
13 |
14 |
15 |
16 | _create_
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 | @endsection
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/render/chat.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/show.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
14 |
15 |
16 | _show_
17 |
18 |
19 |
27 |
28 |
29 | @endsection
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/show.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
14 |
15 |
16 | _show_
17 |
18 |
19 |
27 |
28 |
29 | @endsection
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/create-edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
12 |
13 |
14 |
15 | _edit_
16 |
17 |
23 |
24 |
25 |
26 |
27 | @endsection
28 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/create-edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
29 | @endsection
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/bootstrap/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
11 |
19 |
20 |
21 | _index_
22 |
23 | {{ $_vars_->withQueryString()->links() }}
24 |
25 |
28 |
29 |
30 | @endsection
31 |
--------------------------------------------------------------------------------
/src/template/stubs/views/larastrap/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
11 |
19 |
20 |
21 | _index_
22 |
23 | {{ $_vars_->withQueryString()->links() }}
24 |
25 |
28 |
29 |
30 | @endsection
31 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/partials/render/table.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @foreach($fields as $field)
5 | {{ $field->name }}
6 | @endforeach
7 | Actions
8 |
9 |
10 |
11 | @@foreach ($_vars_ as $_var_)
12 |
13 | @foreach($fields as $field)
14 |
15 | {{ $field->name }}
16 | {!! $display($field) !!}
17 |
18 | @endforeach
19 |
20 |
21 | @if(!empty($hasSoftDelete))
22 | {!! $render('buttons/actions-trash') !!}
23 | @else
24 | {!! $render('buttons/actions') !!}
25 | @endif
26 |
27 |
28 | @@endforeach
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/Utils/FileUtils.php:
--------------------------------------------------------------------------------
1 | isFile()) continue;
15 | if (count($filter) > 0 && !in_array($file->getExtension(), $filter)) continue;
16 |
17 | $files[] = $file->getRealPath();
18 | }
19 |
20 | return $files ?? [];
21 | }
22 |
23 | public static function recursiveCopy($src, $dest, $force = FALSE) {
24 | $files = self::getFiles($src);
25 | $count = 0;
26 |
27 | foreach ($files as $file) {
28 | $target = $dest . DIRECTORY_SEPARATOR . str_replace($src, '', $file);
29 |
30 | if (file_exists($target) && !$force) {
31 | continue;
32 | } else {
33 | $dir = dirname($target);
34 | if (!is_dir($dir)) {
35 | mkdir($dir, 0755, TRUE);
36 | }
37 |
38 | copy($file, $target);
39 | $count++;
40 | }
41 | }
42 |
43 | return $count;
44 | }
45 |
46 | public static function writeFile(string $dest, string $str) {
47 | $dir = dirname($dest);
48 | if (!is_dir($dir)) {
49 | mkdir($dir, 0777, TRUE);
50 | }
51 |
52 | return file_put_contents($dest, $str);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/docs/guide/nesting.md:
--------------------------------------------------------------------------------
1 | # Relational tables and nesting
2 |
3 | In addition to generating simple CRUD for a single table,
4 | you can also generate CRUD for tables related to each other.
5 |
6 | ## Example #1
7 |
8 | For example, let's say we have the following tables:
9 |
10 | - Authors
11 | - Posts
12 | - Comments
13 |
14 | To generate CRUD for these tables you can use the dot
15 | notation to specify the parent tables like this:
16 | `authors.posts.comments`.
17 |
18 | ```bash
19 |
20 | ```bash
21 | # Create CRUD for authors table
22 | $ php artisan crud:generate authors
23 |
24 | # Create CRUD for posts table
25 | $ php artisan crud:generate authors.posts
26 |
27 | # Create CRUD for comments table
28 | $ php artisan crud:generate authors.posts.comments
29 | ```
30 |
31 | This will generate CRUD files for the `authors` table, so
32 | you can view, create, edit and delete authors using the
33 | `/authors` route.
34 |
35 | Then for each author, you can view, create, edit and delete
36 | posts using the `/authors/{author}/posts` route.
37 |
38 | And for each post, you can view, create, edit and delete
39 | comments using the `/authors/{author}/posts/{post}/comments`
40 | route.
41 |
42 | ## Example #2
43 |
44 | On the other hand, if you want to generate CRUD for the
45 | `posts` table without nesting it under the `authors` route,
46 | you can do this:
47 |
48 | ```bash
49 | # Create CRUD for posts table
50 | $ php artisan crud:generate posts
51 |
52 | # Create CRUD for comments table
53 | $ php artisan crud:generate posts.comments
54 | ```
55 |
56 | So now you can view, create, edit and delete all posts
57 | regardless of the author using the `/posts` route and then
58 | for each post, you can view, create, edit and delete
59 | comments using the `/posts/{post}/comments` route.
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
11 |
26 |
27 |
28 | @endsection
29 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
11 |
12 |
27 |
28 |
29 | @endsection
30 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/create-edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
11 |
26 |
27 |
28 | @endsection
29 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
16 |
17 |
18 | _index_
19 |
20 | {{ $_vars_->withQueryString()->links() }}
21 |
22 |
25 |
26 |
27 | @endsection
28 |
--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/@theme_index.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "sources": ["../../../../node_modules/vitepress/dist/client/theme-default/index.js"],
4 | "sourcesContent": ["import './styles/fonts.css';\r\nimport './styles/vars.css';\r\nimport './styles/base.css';\r\nimport './styles/utils.css';\r\nimport './styles/components/custom-block.css';\r\nimport './styles/components/vp-code.css';\r\nimport './styles/components/vp-code-group.css';\r\nimport './styles/components/vp-doc.css';\r\nimport './styles/components/vp-sponsor.css';\r\nimport VPBadge from './components/VPBadge.vue';\r\nimport Layout from './Layout.vue';\r\nimport NotFound from './NotFound.vue';\r\nexport { default as VPHomeHero } from './components/VPHomeHero.vue';\r\nexport { default as VPHomeFeatures } from './components/VPHomeFeatures.vue';\r\nexport { default as VPHomeSponsors } from './components/VPHomeSponsors.vue';\r\nexport { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue';\r\nexport { default as VPTeamPage } from './components/VPTeamPage.vue';\r\nexport { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue';\r\nexport { default as VPTeamPageSection } from './components/VPTeamPageSection.vue';\r\nexport { default as VPTeamMembers } from './components/VPTeamMembers.vue';\r\nconst theme = {\r\n Layout,\r\n NotFound,\r\n enhanceApp: ({ app }) => {\r\n app.component('Badge', VPBadge);\r\n }\r\n};\r\nexport default theme;\r\n"],
5 | "mappings": ";AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,cAAc;AACrB,SAAoB,WAAXA,gBAA6B;AACtC,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAqC;AAC9C,SAAoB,WAAXA,gBAA6B;AACtC,SAAoB,WAAXA,gBAAkC;AAC3C,SAAoB,WAAXA,gBAAoC;AAC7C,SAAoB,WAAXA,gBAAgC;AACzC,IAAM,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,EACA,YAAY,CAAC,EAAE,IAAI,MAAM;AACrB,QAAI,UAAU,SAAS,OAAO;AAAA,EAClC;AACJ;AACA,IAAO,wBAAQ;",
6 | "names": ["default"]
7 | }
8 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/show.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_route_.layout')
2 |
3 | @section('_vars_.content')
4 |
5 |
6 |
7 |
8 | _breadcrumbs_
9 |
10 |
11 |
Back
12 |
13 |
14 |
15 | _show_
16 |
17 |
18 |
26 |
27 |
28 | @endsection
29 |
--------------------------------------------------------------------------------
/src/Commands/CrudTemplate.php:
--------------------------------------------------------------------------------
1 | option('output') ?: 'templates');
32 | $dest = sprintf('%s/%s', $base, $this->argument('name'));
33 | $force = $this->option('force');
34 |
35 | if (is_dir($dest) && !$force) {
36 | $this->error("Template '$dest' already exists");
37 | return Command::FAILURE;
38 | }
39 |
40 | $src = realpath(__DIR__ . '/../template');
41 | if (!is_dir($src)) {
42 | $this->error("Template source '$src' not found");
43 | return Command::FAILURE;
44 | }
45 |
46 | $count = FileUtils::recursiveCopy($src, $dest, $force);
47 | $this->info("Created $count files in '$dest'");
48 |
49 | return Command::SUCCESS;
50 | }
51 |
52 | protected function getOptions() {
53 | return [
54 | ['output', 'o', InputOption::VALUE_REQUIRED, 'Output directory name (default: "templates")'],
55 | ['force', 'f', InputOption::VALUE_NONE, 'Overwrite existing files'],
56 | ];
57 | }
58 |
59 | /**
60 | * {@inheritdoc}
61 | */
62 | protected function getArguments() {
63 | return [
64 | ['name', InputArgument::REQUIRED, 'The name of the new template'],
65 | ];
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/docs/guide/install.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | ## Install with Composer
4 |
5 | Via [composer](http://getcomposer.org):
6 |
7 | ```bash
8 | $ composer require san-kumar/laravel-crud --dev
9 | ```
10 |
11 | ## Generate files
12 |
13 | :::warning Important!
14 |
15 | Make sure to create the db tables and run migrations before
16 | starting the crud generator.
17 | :::
18 |
19 | After installing the package you should see a
20 | new `crud:generate` command in your Artisan commands list.
21 |
22 | To generate the Controller, Model, Policy, routes, etc use
23 | the following command:
24 |
25 | ```bash
26 | # Create CRUD for authors table
27 | $ php artisan crud:generate authors
28 |
29 | # Create CRUD for the authors > posts table
30 | $ php artisan crud:generate authors.posts
31 |
32 | # Create CRUD for the authors > posts > comments table
33 | $ php artisan crud:generate authors.posts.comments
34 | ```
35 |
36 | ## Including the generated routes
37 |
38 | By default, the generated routes are placed in
39 | the `./routes/crud/` directory. To include the generated
40 | routes just open your `routes/web.php` file and add the
41 | following line at the end of the file:
42 |
43 | ```php
44 | /* inside routes/web.php */
45 |
46 | \San\Crud\Crud::routes();
47 | ```
48 |
49 | This will `glob` all the generated route files and include
50 | them in the `routes/web.php` file for you.
51 |
52 | Alternatively, you can copy-paste the generated routes from
53 | the `./routes/crud/` directory to your `routes/web.php`
54 | file. This way you make any changes to the generated route
55 | code as per your needs.
56 |
57 | ## Location of the generated files
58 |
59 | The `crud:generate` command will generate the following
60 | files and place them in the appropriate directories:
61 |
62 | - Resource Controller
63 | - `app/Http/Controllers/[Name].php`
64 | - Model
65 | - `app/Model/[Name].php`
66 | - Policy
67 | - `app/Policies/[Name]Policy.php`
68 | - Routes
69 | - `routes/crud/[name].php`
70 | - Views
71 | - `resources/views/[name]/(index|edit|create|show).blade.php`
72 |
73 | By default, the generated code will not overwrite any
74 | existing files. If you want to overwrite the existing files,
75 | you can use the `--force` option.
76 |
--------------------------------------------------------------------------------
/docs/guide/options.md:
--------------------------------------------------------------------------------
1 | # Options
2 |
3 | ### CSS Framework: Bootstrap 5, and TailwindCSS.
4 |
5 | You can choose between Bootstrap 5 and Tailwind CSS or you
6 | can use your own CSS framework. By default, Bootstrap 5 is
7 | used when nothing is specified.
8 |
9 | ```bash
10 | # Create CRUD for authors table using Tailwind CSS
11 | $ php artisan crud:generate authors --css=tailwind
12 |
13 | # Shortcut for Tailwind CSS
14 | $ php artisan crud:generate authors -t
15 | ```
16 |
17 | ```bash
18 | # Create CRUD for authors table using layout 'layouts/admin.blade.php'
19 | $ php artisan crud:generate authors --layout=admin
20 | $ php artisan crud:generate authors --section=mysection
21 | ```
22 |
23 | ### Prefix
24 |
25 | You can add a route prefix for the generated CRUD by passing
26 | a `--prefix` option.
27 |
28 | ```bash
29 | # Create CRUD for authors table using Tailwind CSS
30 | $ php artisan crud:generate authors --prefix=admin
31 | ```
32 |
33 | This will change the route from `/authors` to
34 | `/admin/authors` in all the generated files.
35 |
36 | ### Index templates
37 |
38 | You can choose between 3 ready-made index templates: table,
39 | cards and chat. By default, the table template is used.
40 |
41 | ```bash
42 | # Create CRUD for authors table using cards template
43 | $ php artisan crud:generate authors -i cards
44 |
45 | # Create CRUD for authors table using chat template
46 | $ php artisan crud:generate authors -i chat
47 | ```
48 |
49 | Please see the [index page here](/guide/index.md#screenshots)
50 | for screenshots.
51 |
52 | ### Single create and edit form
53 |
54 | In some cases, you may want to use a single form for both
55 | creating and editing a resource. You can do that by passing
56 | `--merge-forms` option.
57 |
58 | ```bash
59 | # Create CRUD for authors table using a single form
60 | $ php artisan crud:generate authors --merge-forms
61 | ```
62 |
63 | This will generate a single `view` file called
64 | `create-edit.blade.php` and update the controller code
65 | accordingly so that it can be used for both creating and
66 | editing a resource.
67 |
68 | ### Layout and section names
69 |
70 | By default, the generated views use `layouts/app.blade.php`
71 | for layout and `content` for section name. You can change
72 | these default names by passing your own layout and section
73 | names.
74 |
75 |
--------------------------------------------------------------------------------
/docs/guide/crud.md:
--------------------------------------------------------------------------------
1 | # Create and Edit records
2 |
3 | Laravel CRUD generator can automatically generate the FORM
4 | for creating and editing records. It can also generate the
5 | validation rules for the form.
6 |
7 | ## Form fields
8 |
9 | The form fields are generated based on the database table
10 | columns. The following column types are supported:
11 |
12 | > 
13 | > (Example of generated fields)
14 |
15 | - `string` (input type text)
16 | - `text` (textarea)
17 | - `integer` (input type number)
18 | - `enum` (select)
19 | - `boolean` (radio buttons)
20 | - `relation` (select with hydrated options)
21 | - and so on...
22 |
23 | It can also infer the field type from the column names. For
24 | example, if the column name is `email`, the field type will
25 | be `email`.
26 |
27 | ## Validation rules
28 |
29 | By default, all non-nullable fields are required. Columns
30 | with a `unique` index are also validated to be unique in the
31 | table.
32 |
33 | Some additional validation rules are also added based on the
34 | column name. For example, if the column name is `email`, the
35 | validation rule will be `email`.
36 |
37 | ## Relation fields
38 |
39 | If the table has any foreign key columns, the generator will
40 | automatically add a select field for that column. The
41 | options for the select field will be hydrated from the
42 | related table.
43 |
44 | For example, if your table has a `country_id` column and if
45 | the `country` table exists: the generator will add a select
46 | field for country (as shown in the image above) and the
47 | options for that select field will be hydrated from
48 | the `countries` table (if the country table has a `user_id`
49 | column, the options will be filtered by the current user).
50 |
51 | ## Quick note about relation fields
52 |
53 | You do need to add relation fields manually or create any
54 | foreign key columns in the database. The relation is
55 | inferred from the column name only. Any column name that
56 | matches the pattern `*_id` are considered relation.
57 |
58 | For example, if the column name is `country_id`, the
59 | generator will look for a `countries` table and add if that
60 | exists (and if the current user has permission to access
61 | that table) it will add a select field for that column and
62 | hydrate the options from the `countries` table.
63 |
--------------------------------------------------------------------------------
/docs/guide/customization.md:
--------------------------------------------------------------------------------
1 | # Customization
2 |
3 | ## Using your own templates
4 |
5 | At the heart of Laravel CRUD generator are the templates
6 | files that are used to generate the CRUD files.
7 |
8 | The templates files included with this package are stored in
9 | the `./vendor/san-kumar/laravel-crud/src/template`
10 | directory.
11 |
12 | It contains all the stub files that are used to generate the
13 | Controller, Model, Policy, routes, etc.
14 |
15 | ## Customizing the templates
16 |
17 | You can customize the templates by copying the template into
18 | a new directory and then modifying the template files.
19 |
20 | To make this simple Laravel CRUD generator provides an
21 | artisan command that will copy the template files into a new
22 | directory for you.
23 |
24 | ```bash
25 | # Copy the template files into a new directory
26 | $ php artisan crud:template newname
27 | ```
28 |
29 | This will copy the template files into a new directory
30 | `./templates/newname/` directory.
31 |
32 | It you want to specify a different directory to copy the
33 | template files into you can use the `--directory` or
34 | `-d` option.
35 |
36 | ```bash
37 | # Copy the template files into a new directory
38 | $ php artisan crud:template newname -d etc/templates
39 | ```
40 |
41 | This will copy the template files into a new directory
42 | `./etc/templates/newname/` directory.
43 |
44 | ## Using your own templates
45 |
46 | To use your own templates you need to specify the template
47 | directory in the `config/crud.php` file.
48 |
49 | ```php
50 | // config/crud.php
51 |
52 | return [
53 | 'template_dir' => 'etc/templates/newname',
54 | ];
55 |
56 | ```
57 |
58 | Alternatively you can specify the template directory using
59 | the `--template` or `-t` option while generating the CRUD.
60 |
61 | ```bash
62 | # Generate the CRUD using the new template
63 | $ php artisan crud:generate Post --template etc/templates/newname
64 | ```
65 |
66 | ## Customizing the templates
67 |
68 | You will need to modify the template files in the new
69 | directory to customize the generated files.
70 |
71 | You will find multiple variables that are used in the
72 | template files that are replaced with the actual values when
73 | the files are generated.
74 |
75 | To see the full list of variables that are used in the
76 | template files check out the source code for
77 | [GenerateCrud.php](https://github.com/san-kumar/laravel-crud/blob/main/src/Commands/CrudGenerate.php#L49)
78 |
79 |
--------------------------------------------------------------------------------
/src/template/stubs/views/tailwind/layout.blade.php:
--------------------------------------------------------------------------------
1 | @extends('_layout_')
2 |
3 | @section('_section_')
4 | @if(isset($showErrors))
5 | @if ($errors->any())
6 |
7 |
8 | @foreach ($errors->all() as $error)
9 |
10 |
11 |
12 |
13 | {{ $error }}
14 |
15 | @endforeach
16 |
17 |
18 | @endif
19 |
20 | @if (session('success'))
21 |
22 |
23 |
24 |
25 |
26 |
{{session('success')}}
27 |
28 |
29 | @endif
30 |
31 | @if (session('error'))
32 |
33 |
34 |
35 |
36 |
37 |
{{session('error')}}
38 |
39 |
40 | @endif
41 | @endif
42 |
43 | @yield('_vars_.content')
44 | @endsection
45 |
--------------------------------------------------------------------------------
/src/template/stubs/Policies/_policy_.php:
--------------------------------------------------------------------------------
1 | tables));
12 | }
13 |
14 | public function getPolicyName() {
15 | return NameUtils::getPolicyName($this->mainTable());
16 | }
17 |
18 | public function getControllerPolicy() {
19 | return sprintf("public function __construct() {\n\t\t\$this->authorizeResource(%s::class, '%s');\n\t}", $this->getMainModelName(), $this->getMainVarName());
20 | }
21 |
22 | public function getPolicyReadArgs() {
23 | return $this->getPolicyArgs([]);
24 | }
25 |
26 | public function getPolicyArgs($tables) {
27 | foreach (array_merge(['User'], (array) $tables) as $table) {
28 | $args[] = sprintf('%s $%s', NameUtils::getModelName((array) $table), NameUtils::getVariableName($table));
29 | }
30 |
31 | return join(', ', $args ?? []);
32 | }
33 |
34 | public function getPolicyReadRules() {
35 | return $this->getPolicyRules([]);
36 | }
37 |
38 | public function getPolicyRules($tables) {
39 | foreach ((array) $tables as $table) {
40 | if (SchemaUtils::getUserIdField($this->getTableNameFromAlias($table))) {
41 | $checks[] = sprintf('($%s->user_id == $user->id)', NameUtils::getVariableName($table));
42 | }
43 | }
44 |
45 | return empty($checks) ? "return true;" : sprintf('return ($user->id > 0) && %s;', join(' && ', $checks));
46 | }
47 |
48 | public function getPolicyWriteArgs() {
49 | return $this->getPolicyArgs($this->mainTable());
50 | }
51 |
52 | public function getPolicyWriteRules() {
53 | return $this->getPolicyRules($this->mainTable());
54 | }
55 |
56 | public function getParentAuthorization() {
57 | return $this->getPolicyAuthorization($this->parentTables(), 'view');
58 | }
59 |
60 | public function getPolicyAuthorization($tables, $fn) {
61 | foreach ((array) $tables as $table) {
62 | $checks[] = sprintf("\$this->authorize('%s', [%s::class, \$%s]);", $fn, NameUtils::getModelName($table), NameUtils::getVariableName($table));
63 | }
64 |
65 | return empty($checks) ? "" : join("\n\t\t", $checks);
66 | }
67 |
68 | public function getModelAuthorization() {
69 | return $this->getPolicyAuthorization($this->mainTable(), 'delete');
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Commands/CrudBase.php:
--------------------------------------------------------------------------------
1 | getConfig('template_dir');
15 |
16 | if (!empty($customDir)) {
17 | if (!is_dir($customDir)) {
18 | $this->error("Template directory '$customDir' does not exist");
19 | exit(1);
20 | }
21 |
22 | return $customDir;
23 | }
24 |
25 | return $this->getConfig('template_dir', __DIR__ . '/../template');
26 | }
27 |
28 | protected function getConfig($path = NULL, $default = NULL) {
29 | $config = config('crud') ?: [];
30 |
31 | return !empty($path) ? (data_get($config, $path) ?: $default) : $config;
32 | }
33 |
34 | protected function getCssFramework() {
35 | if (preg_match('/^(tailwind|larastrap)$/', $this->option('css'))) {
36 | return $this->option('css');
37 | }
38 |
39 | if ($this->option('tailwind')) {
40 | return 'tailwind';
41 | }
42 |
43 | return $this->getConfig('css', 'bootstrap');
44 | }
45 |
46 | protected function getTables($checkExists = TRUE) {
47 | $tables = array_values(array_filter(array_map('trim', preg_split('/\.\s*/', $this->argument('table')))));
48 | $aliases = $this->getTableAliases();
49 |
50 | if ($checkExists) {
51 | foreach ($tables as $table) {
52 | if (!SchemaUtils::tableExists($aliases[$table] ?? $table)) {
53 | $this->warn("Table $table does not exist in the database. Did you forget to run migrations?");
54 | }
55 | }
56 | }
57 |
58 | return $tables;
59 | }
60 |
61 | protected function getTableAliases() {
62 | if (!$this->hasOption('alias')) return [];
63 |
64 | $aliases = $this->option('alias');
65 |
66 | foreach ($aliases as $alias) {
67 | [$a, $t] = explode('=', $alias);
68 | if (!empty($a) && !empty($t)) {
69 | if (SchemaUtils::tableExists($t)) {
70 | $results[$a] = $t;
71 | } else {
72 | $this->warn("Table $t (alias $a) does not exist in the database. Did you forget to run migrations?");
73 | }
74 | }
75 | }
76 |
77 | return $results ?? [];
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Generators/ModelGen.php:
--------------------------------------------------------------------------------
1 | sprintf('use App\Models\%s;', NameUtils::getModelName((array) $table)), $this->tables));
12 | }
13 |
14 | public function getModelName() {
15 | return NameUtils::getModelName($this->mainTable());
16 | }
17 |
18 | public function getSoftDelete() {
19 | return $this->hasSoftDeletes() ? 'use \Illuminate\Database\Eloquent\SoftDeletes;' : '';
20 | }
21 |
22 | public function getFillable() {
23 | foreach ($this->getFillableFields() as $field) {
24 | $fillable[] = $field['id'];
25 | }
26 |
27 | return join(', ', array_map(fn($f) => sprintf('"%s"', $f), $fillable ?? []));
28 | }
29 |
30 | public function getBelongsTo() {
31 | foreach (SchemaUtils::getTableFieldsWithIds($this->mainTableReal(), ['user_id']) as $field) {
32 | $relations[] = sprintf("public function %s() {\n\t\treturn \$this->belongsTo(%s::class);\n\t}", $field['relation'], NameUtils::getModelName((array) $field['related_table']));
33 | }
34 |
35 | return join("\n\n", $relations ?? []);
36 | }
37 |
38 | public function getHasMany() {
39 | $tables = SchemaUtils::getTables($this->mainTableReal());
40 |
41 | foreach ($tables as $table) {
42 | $fields = SchemaUtils::getTableFieldsWithIds($this->getTableNameFromAlias($table), ['user_id']);
43 | foreach ($fields as $field) {
44 | if ($field['related_table'] == $this->mainTableReal()) {
45 | $fKey = $field['id'];
46 | $relations[] = sprintf("public function %s() {\n\t\treturn \$this->hasMany(%s::class, '%s');\n\t}", NameUtils::getVariableNamePlural($table), NameUtils::getModelName((array) $table), $fKey);
47 | }
48 | }
49 | }
50 |
51 | return join("\n\n", $relations ?? []);
52 | }
53 |
54 | public function getCasts() {
55 | foreach (SchemaUtils::getTableFields($this->mainTableReal(), ['user_id']) as $field) {
56 | if ($field['type'] == 'json') {
57 | $casts[] = sprintf("'%s' => AsArrayObject::class", $field['id']);
58 | } elseif (preg_match('/^date/', $field['type'])) {
59 | $casts[] = sprintf("'%s' => 'datetime'", $field['id']);
60 | }
61 | }
62 |
63 | return !empty($casts) ? sprintf("protected \$casts = [\n\t\t%s\n\t];", join(",\n\t\t", $casts)) : '';
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/docs/.vitepress/config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | title: 'Laravel Crud Generator',
3 | host: 'localhost',
4 | description: 'Laravel CRUD generator: Generate CRUD for any db table with the crud:generate command.',
5 | //base: 'https://san-kumar.github.io/laravel-crud/',
6 | base: '/laravel-crud/',
7 | appearance: 'dark',
8 | themeConfig: {
9 | nav: [
10 | {text: 'Getting started', link: '/guide'},
11 | {
12 | text: 'Artisan commands',
13 | items: [
14 | {text: 'artisan crud:generate', link: '/guide/'},
15 | {text: 'artisan crud:template', link: '/guide/customization'},
16 | {text: 'artisan crud:remove', link: '/guide/remove'},
17 | ]
18 | }
19 | ],
20 | sidebar: [
21 | {
22 | text: 'Introduction',
23 | items: [
24 | {text: 'Index', link: '/guide/'},
25 | {text: 'Installation', link: '/guide/install'},
26 | {text: 'Options', link: '/guide/options'},
27 | ]
28 | },
29 | {
30 | text: 'Details',
31 | items: [
32 | {text: 'Nested parents', link: '/guide/nesting'},
33 | {text: 'Authentication', link: '/guide/authentication'},
34 | {text: 'Create / edit form', link: '/guide/crud'},
35 | {text: 'Soft deletes', link: '/guide/soft-deletes'},
36 | {text: 'Inbuilt search', link: '/guide/search'},
37 | {text: 'Customization', link: '/guide/customization'},
38 | ]
39 | },
40 | {
41 | text: 'Appendix',
42 | items: [
43 | {text: 'Gotchas', link: '/guide/gotchas'},
44 | {text: 'CRUD removal', link: '/guide/remove'},
45 | {text: 'License', link: '/guide/license'},
46 | {text: 'Roadmap', link: '/guide/roadmap'},
47 | {text: 'About', link: '/guide/about'},
48 | ]
49 | },
50 | ],
51 | editLink: {
52 | pattern: 'https://github.com/san-kumar/laravel-crud/docs/:path'
53 | },
54 | search: {
55 | maxSuggestions: 10
56 | },
57 | footer: {
58 | message: 'Released under the MIT License.',
59 | copyright: 'Copyright © 2022-present San Kumar'
60 | },
61 | socialLinks: [
62 | { icon: 'github', link: 'https://github.com/san-kumar/laravel-crud' }
63 | ],
64 | }
65 | };
66 |
--------------------------------------------------------------------------------
/docs/guide/index.md:
--------------------------------------------------------------------------------
1 | # Laravel CRUD Generator
2 |
3 | 
4 |
5 | ## Introduction
6 |
7 | This package adds a **crud:generate** command to Artisan in
8 | your Laravel project. With this command you can generate
9 | CRUD (Create, Read, Update, Delete) for your db tables
10 | instantly!
11 |
12 | The generated CRUD includes a Controller, Model, Policy,
13 | routes, validations, and 4 view files (index, create, edit,
14 | show). It also supports relations between tables, so you can
15 | generate nested CRUDs, for example: generating CRUD for
16 | comments inside a blog post.
17 |
18 | The output is fully customizable and supports
19 | both [Bootstrap 5](https://getbootstrap.com/docs/5.0/getting-started/introduction/)
20 | and [Tailwind CSS](https://tailwindcss.com/).
21 |
22 | ## Demo Video
23 |
24 | [](https://www.youtube.com/watch?v=N_N2FqPDLvQ)
25 |
26 | ## Screenshots
27 |
28 | ### Index page
29 |
30 | Laravel-crud can generate nested CRUDs. For example, you can
31 | generate CRUD for customers > tickets > replies by simply
32 | running:
33 |
34 | ```bash
35 | $ php artisan crud:generate customers.tickets.replies
36 | ```
37 |
38 | #### Table layout
39 |
40 | > 
41 | > (Automatically generated index page with responsive table
42 | > layout)
43 |
44 | The generated views are fully customizable and template
45 | based. For example, you can change the look of the index
46 | page by using different templates like table, cards or
47 | chat (included in the package).
48 |
49 | #### Card layout
50 |
51 | ```bash
52 | $ php artisan crud:generate customers.tickets.replies -i cards
53 | ```
54 |
55 | > 
56 | > (Card layout)
57 |
58 | #### Chat layout
59 |
60 | ```bash
61 | $ php artisan crud:generate customers.tickets.replies -i chat
62 | ```
63 |
64 | > 
65 | > (Chat layout)
66 |
67 | #### Create / Edit Forms
68 |
69 | Laravel CRUD generator can automatically generate the FORM
70 | for creating and editing records. It can also generate the
71 | validation rules for the form.
72 |
73 | > 
74 | > (Example of generated fields)
75 |
76 | ## Heads up!
77 |
78 | :::warning The package is still in _alpha_
79 |
80 | You should only use it with new projects. If you are using
81 | it in an existing project, make sure to back up (or commit)
82 | any project changes before running the command.
83 | :::
84 |
85 | The aim of the CRUD generator is to save you time by
86 | generating common boilerplate CRUD code for any database
87 | table instantly.
88 |
89 | But this code is **not** intended to be used as-is. You
90 | should always customize the generated code to fit your needs
91 | and manually review the generated files before deploying it
92 | to production.
93 |
--------------------------------------------------------------------------------
/src/Generators/RouteGen.php:
--------------------------------------------------------------------------------
1 | tables);
14 | }
15 |
16 | public function getParentRouteName() {
17 | return NameUtils::getRouteName($this->parentTables());
18 | }
19 |
20 | public function getRouteUrl() {
21 | return $this->withRoutePrefix(str_replace('.', '/', $this->getRouteName()));
22 | }
23 |
24 | public function getRouteUrlWithoutPrefix() {
25 | return str_replace('.', '/', $this->getRouteName());
26 | }
27 |
28 | public function getRouteUrlWithPlaceholders() {
29 | return $this->getUrlWithPlaceholders($this->tables);
30 | }
31 |
32 | public function getParentRouteUrlWithPlaceholders() {
33 | return $this->getUrlWithPlaceholders($this->parentTables(), $this->mainTable());
34 | }
35 |
36 | public function getUrlWithPlaceholders($tables, $suffix = '') {
37 | foreach ((array) $tables as $table) {
38 | $parts[] = sprintf('%s/{%s}', $table, NameUtils::getVariableName($table));
39 | }
40 |
41 | if (!empty($suffix)) {
42 | $parts[] = $suffix;
43 | }
44 |
45 | return $this->withRoutePrefix(implode('/', $parts ?? []));
46 | }
47 |
48 | public function getRouteUrlWithId() {
49 | foreach ((array) $this->tables as $table) {
50 | if ($table == $this->mainTable()) {
51 | $parts[] = sprintf('%s/{%s_id}', $table, NameUtils::getVariableName($table));
52 | } else {
53 | $parts[] = sprintf('%s/{%s}', $table, NameUtils::getVariableName($table));
54 | }
55 | }
56 |
57 | return $this->withRoutePrefix(implode('/', $parts));
58 | }
59 |
60 | public function getParentRouteUrl() {
61 | return $this->withRoutePrefix(str_replace('.', '/', $this->getParentRouteName()));
62 | }
63 |
64 | public function getRouteVars() {
65 | return sprintf('[%s]', join(', ', array_map(fn($table) => sprintf("'%s' => $%s", NameUtils::getVariableName($table), NameUtils::getVariableName($table)), $this->tables)));
66 | }
67 |
68 | public function getRouteVarsWithId() {
69 | foreach ($this->tables as $table) {
70 | if ($table == $this->mainTable()) {
71 | $vars[] = sprintf("'%s_id' => $%s->id", NameUtils::getVariableName($table), NameUtils::getVariableName($table));
72 | } else {
73 | $vars[] = sprintf("'%s' => $%s", NameUtils::getVariableName($table), NameUtils::getVariableName($table));
74 | }
75 | }
76 |
77 | return sprintf('[%s]', join(', ', $vars ?? []));
78 | }
79 |
80 | public function getAsRoute() {
81 | return $this->hasParentTable() ? sprintf('"as" => "%s",', $this->getParentRouteName()) : '';
82 | }
83 |
84 | public function withRoutePrefix(string $route) {
85 | return empty($this->routePrefix) ? $route : sprintf('%s/%s', trim($this->routePrefix, '/'), $route);
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/@theme_index.js:
--------------------------------------------------------------------------------
1 | // node_modules/vitepress/dist/client/theme-default/index.js
2 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/fonts.css";
3 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/vars.css";
4 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/base.css";
5 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/utils.css";
6 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css";
7 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css";
8 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css";
9 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css";
10 | import "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css";
11 | import VPBadge from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
12 | import Layout from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/Layout.vue";
13 | import NotFound from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/NotFound.vue";
14 | import { default as default2 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue";
15 | import { default as default3 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue";
16 | import { default as default4 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue";
17 | import { default as default5 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue";
18 | import { default as default6 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue";
19 | import { default as default7 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue";
20 | import { default as default8 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue";
21 | import { default as default9 } from "/home/san/laravel/plugins/php/laravel-crud/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue";
22 | var theme = {
23 | Layout,
24 | NotFound,
25 | enhanceApp: ({ app }) => {
26 | app.component("Badge", VPBadge);
27 | }
28 | };
29 | var theme_default_default = theme;
30 | export {
31 | default5 as VPDocAsideSponsors,
32 | default3 as VPHomeFeatures,
33 | default2 as VPHomeHero,
34 | default4 as VPHomeSponsors,
35 | default9 as VPTeamMembers,
36 | default6 as VPTeamPage,
37 | default8 as VPTeamPageSection,
38 | default7 as VPTeamPageTitle,
39 | theme_default_default as default
40 | };
41 | //# sourceMappingURL=@theme_index.js.map
42 |
--------------------------------------------------------------------------------
/docs/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 | Thank you for considering to contribute to this repository! This file will walk you through all the steps to ensure both
3 | you and I have a good time submitting and reviewing your contribution. First off, some basic rules and reading material:
4 |
5 | - Submit your work in a new branch and make the PR to the master branch.
6 | - [Write a short & descriptive commit message](http://chris.beams.io/posts/git-commit/).
7 | - Rebase before committing the final change.
8 | - Stick to [PSR-2](http://www.php-fig.org/psr/psr-2/).
9 | - Add tests if necessary and ensure all the tests are green on the final commit.
10 | - Make sure the CI tools used by the repository are all in order. If one fails, you should make it pass.
11 |
12 | ## Contributing
13 | Here are the steps to follow to contribute to this repository:
14 |
15 | - [Fork this repository on GitHub](#fork-this-repository).
16 | - [Clone your fork to your local machine](#clone-your-fork).
17 | - [Create a feature branch](#create-a-branch).
18 | - [Add an 'upstream' remote](#add-a-remote).
19 | - [Regularly pull & rebase from the upstream remote](#pull-and-rebase).
20 | - [Work on feature branch](#working-on-branch).
21 | - [Submit a pull request to the master branch](#submitting-pull-request).
22 |
23 | ### Fork this repository
24 | Fork the repository right here on GitHub. To learn more about forking a repository, visit
25 | [GitHub's help article](https://help.github.com/articles/fork-a-repo/).
26 |
27 | ### Clone your fork
28 | Clone your repository on your local machine to start work on your pull request.
29 |
30 | ```bash
31 | $ git clone git@github.com:/.git
32 | # Or if you prefer HTTPS:
33 | $ git clone https://github.com//.git
34 |
35 | $ cd
36 | ```
37 |
38 | ### Create a branch
39 | Make your own feature branch in order not to clutter up master.
40 |
41 | ```bash
42 | # Think of a good name for your branch:
43 | # fix/typo-in-readme
44 | # feature/some-feature
45 | # bug/some-bug-you-are-fixing
46 | $ git checkout -b
47 | ```
48 |
49 | ### Add a remote
50 | Add an 'upstream' remote to pull from and to stay up to date with the work being done in there.
51 |
52 | ```bash
53 | # List all current remotes
54 | $ git remote -v
55 | origin git@github.com//.git (fetch)
56 | origin git@github.com//.git (push)
57 |
58 | # Add a new remote called 'upstream'
59 | $ git remote add upstream git@github.com:san-kumar/.git
60 | # Or if you prefer HTTPS:
61 | $ git remote add upstream https://github.com/san-kumar/.git
62 |
63 | # The new remote should now be in the list
64 | $ git remote -v
65 | origin git@github.com//.git (fetch)
66 | origin git@github.com//.git (push)
67 | upstream git@github.com/san-kumar/.git (fetch)
68 | upstream git@github.com/san-kumar/.git (push)
69 | ```
70 |
71 | ### Pull and rebase
72 | Pull from upstream to stay up to date with what others might be doing in this repository. Any merge conflicts that arise
73 | are your responsibility to resolve.
74 |
75 | ```bash
76 | $ git pull --rebase upstream master
77 | ```
78 |
79 | ### Working on branch
80 | Do your magic and make your fix. I can't help you with this :wink:. Once you're happy with the result and all tests pass,
81 | go ahead and push to your feature branch.
82 |
83 | ```bash
84 | $ git push origin
85 | ```
86 |
87 | ### Submitting pull request
88 | Now, let's head back over to this repository on GitHub and submit the pull request!
89 |
--------------------------------------------------------------------------------
/src/Commands/CrudRemove.php:
--------------------------------------------------------------------------------
1 | getTables();
37 |
38 | $cgen = new ControllerGen($tables, $tables);
39 | $mgen = new ModelGen($tables, $tables);
40 | $rgen = new RouteGen($tables, $tables);
41 | $vgen = new ViewGen($tables, $tables);
42 | $pgen = new PolicyGen($tables, $tables);
43 |
44 | $blanks = [
45 | 'controller' => $cgen->getControllerName(),
46 | 'model' => $mgen->getModelName(),
47 | 'route' => $rgen->getRouteName(),
48 | 'policy' => $pgen->getPolicyName(),
49 | ];
50 |
51 | $files = new Templates($this->getTemplateDir());
52 | $cssFramework = 'bootstrap';
53 | $interactive = $this->option('interactive');
54 |
55 | if ($zipFile = $this->option('backup')) {
56 | if (!class_exists('ZipArchive')) {
57 | $this->error('ZipArchive class not found. Please install php-zip extension.');
58 | return COMMAND::FAILURE;
59 | }
60 |
61 | $zip = new \ZipArchive();
62 | $result = $zip->open($zipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
63 |
64 | if (($result !== TRUE) || !is_writable(dirname($zipFile))) {
65 | $this->error('Cannot create zip file: ' . $zipFile);
66 | return COMMAND::FAILURE;
67 | }
68 | }
69 |
70 | foreach ($this->getStubTypes($cssFramework) as $type) {
71 | $stubs = $files->getStubs($type);
72 |
73 | foreach ($stubs as $stub) {
74 | $dest = $files->getDest($type, $stub, $blanks, $rgen->getRouteUrl());
75 |
76 | if (file_exists($dest)) {
77 | if ($interactive && !$this->confirm("Delete $dest?")) {
78 | continue;
79 | }
80 |
81 | if (!empty($zip)) {
82 | $zip->addFromString(file_get_contents($dest), sprintf('%s/%s', $type, basename($dest)));
83 | }
84 |
85 | $this->info("Removing file $dest");
86 |
87 | unlink($dest);
88 | }
89 | }
90 | }
91 |
92 | if (!empty($zip) && ($zip->numFiles > 0)) {
93 | $zip->close();
94 | $this->info(sprintf("Backup created at: %s", realpath($zipFile)));
95 | }
96 |
97 | return Command::SUCCESS;
98 | }
99 |
100 | protected function getOptions() {
101 | return [
102 | ['backup', 'b', InputOption::VALUE_REQUIRED, 'Name of zip file to backup files before removing'],
103 | ['interactive', 'i', InputOption::VALUE_NONE, 'Ask for confirmation before removing each file'],
104 | ];
105 | }
106 |
107 | /**
108 | * {@inheritdoc}
109 | */
110 | protected function getArguments() {
111 | return [
112 | ['table', InputArgument::REQUIRED, 'Remove all generated files for the given tables'],
113 | ];
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/Generators/BaseGen.php:
--------------------------------------------------------------------------------
1 | getVarNamePlural());
14 | }
15 |
16 | public function getVarNamePlural() {
17 | return NameUtils::getVariableNamePlural($this->mainTable());
18 | }
19 |
20 | public function mainTable() {
21 | return $this->tables[count($this->tables) - 1];
22 | }
23 |
24 | public function getTitle() {
25 | return Str::singular($this->getTitlePlural());
26 | }
27 |
28 | public function getTitlePlural() {
29 | return NameUtils::titleCase($this->mainTable());
30 | }
31 |
32 | public function getParentVarName() {
33 | return Str::singular($this->getParentVarNamePlural());
34 | }
35 |
36 | public function getParentVarNamePlural() {
37 | return NameUtils::getVariableNamePlural($this->parentTable());
38 | }
39 |
40 | public function parentTable() {
41 | return $this->tables[count($this->tables) - 2];
42 | }
43 |
44 | public function getMainModelName() {
45 | return NameUtils::getModelName((array) $this->mainTable());
46 | }
47 |
48 | public function getMainVarName() {
49 | return NameUtils::getVariableName($this->mainTable());
50 | }
51 |
52 | public function hasParentTable() {
53 | return count($this->tables) > 1;
54 | }
55 |
56 | public function parentTables() {
57 | return array_slice($this->tables, 0, -1);
58 | }
59 |
60 | public function getVars(array $tables, array $extraVars = []) {
61 | $vars = $this->getRawVars($tables, $extraVars);
62 |
63 | return !empty($vars) ? sprintf("compact(%s)", join(', ', array_map(fn($var) => sprintf("'%s'", $var), $vars))) : '[]';
64 | }
65 |
66 | public function getRawVars(array $tables, ?array $extraVars = []) {
67 | foreach ($tables as $table) {
68 | $vars[] = NameUtils::getVariableName($table);
69 | }
70 |
71 | return array_merge($vars ?? [], (array) $extraVars);
72 | }
73 |
74 | protected function hasUserId() {
75 | return SchemaUtils::getUserIdField($this->mainTableReal());
76 | }
77 |
78 | public function mainTableReal() {
79 | return $this->getTableNameFromAlias($this->mainTable());
80 | }
81 |
82 | public function getTableNameFromAlias($tableName) {
83 | return $this->aliases[$tableName] ?? $tableName;
84 | }
85 |
86 | public function getAliasFromTableName($tableName) {
87 | return array_search($tableName, $this->aliases) ?: $tableName;
88 | }
89 |
90 | protected function hasTimestamps() {
91 | return SchemaUtils::hasTimestamps($this->mainTableReal());
92 | }
93 |
94 | protected function hasSoftDeletes() {
95 | return SchemaUtils::hasSoftDelete($this->mainTableReal());
96 | }
97 |
98 | protected function getFirstReadableField($key = NULL) {
99 | return SchemaUtils::firstHumanReadableField($this->mainTableReal(), $key) ?: 'id';
100 | }
101 |
102 | protected function getFillableFields($exceptColumns = ['user_id']) {
103 | foreach (SchemaUtils::getTableFields($this->mainTableReal(), $exceptColumns) as $field) {
104 | if (in_array($field['related_table'] ?? '', $this->realTables())) continue;
105 | $fillable[] = $field;
106 | }
107 |
108 | return $fillable ?? [];
109 | }
110 |
111 | public function realTables() {
112 | return array_map(fn($table) => $this->getTableNameFromAlias($table), $this->tables);
113 | }
114 |
115 | protected function getExternallyRelatedFields() {
116 | $fields = SchemaUtils::getTableFieldsWithIds($this->mainTableReal(), ['user_id']);
117 |
118 | foreach ($fields as $field) {
119 | if (in_array($field['related_table'], $this->realTables())) continue;
120 | $externallyRelatedFields[] = $field;
121 | }
122 |
123 | return $externallyRelatedFields ?? [];
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/Utils/SchemaUtils.php:
--------------------------------------------------------------------------------
1 | getDoctrineSchemaManager()->listTableNames();
10 | if ($withViews) {
11 | $views = DB::connection()->getDoctrineSchemaManager()->listViews();
12 | $tables = array_merge($tables, array_keys($views));
13 | }
14 |
15 | return array_values(array_filter($tables, fn($table) => !in_array($table, (array) $exclude)));
16 | }
17 |
18 | public static function getTableFields(string $tableName, array $excludedColumns = [], array $alwaysIgnoredColumns = ['id', 'created_at', 'updated_at', 'deleted_at']) {
19 | // ugly enum hack as doctrine does not support enum types
20 | // https://www.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/mysql-enums.html#solution-1-mapping-to-varchars
21 |
22 | DB::connection()->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'guid');
23 |
24 | $columns = DB::getDoctrineSchemaManager()->listTableColumns($tableName);
25 | $ignoredColumns = array_merge((array) $excludedColumns, (array) $alwaysIgnoredColumns);
26 | $indexes = DB::getDoctrineSchemaManager()->listTableIndexes($tableName);
27 | $uniqueColumns = [];
28 |
29 | foreach ($indexes as $index) {
30 | if ($index->isUnique() && count($index->getColumns()) === 1) {
31 | $uniqueColumns = array_merge($uniqueColumns, $index->getColumns());
32 | }
33 | }
34 |
35 | foreach ($columns as $column) {
36 | if (in_array($column->getName(), $ignoredColumns)) continue;
37 |
38 | $field = [
39 | 'id' => $column->getName(),
40 | 'type' => $column->getType()->getName(),
41 | 'name' => \Str::title(str_replace('_', ' ', $column->getName())),
42 | 'nullable' => !$column->getNotnull(),
43 | 'default' => $column->getDefault(),
44 | ];
45 |
46 | if ($field['type'] == 'guid') {
47 | try {
48 | $enums = DB::select("SHOW COLUMNS FROM $tableName WHERE Field = '$field[id]'");
49 | $field['values'] = explode(',', str_replace("'", '', substr($enums[0]->Type, 5, -1)));
50 | } catch (\Throwable $e) {
51 | echo '';
52 | }
53 | }
54 |
55 | if (preg_match('/^(.*?)_id$/', $field['id'], $matches)) {
56 | $relatedTable = \Str::plural($matches[1]);
57 | if (self::tableExists($relatedTable)) {
58 | $field['relation'] = $matches[1];
59 | $field['related_table'] = $relatedTable;
60 | }
61 | }
62 |
63 | //check if column is unique index
64 | if (in_array($field['id'], $uniqueColumns)) {
65 | $field['unique'] = TRUE;
66 | }
67 |
68 | $fields[] = $field;
69 | }
70 |
71 | return $fields ?? [];
72 | }
73 |
74 | public static function firstHumanReadableField(string $table, string $key = NULL) {
75 | $all = self::getTableFields($table);
76 | if (empty($all)) return NULL;
77 |
78 | foreach ($all as $f) {
79 | if (preg_match('/_id$/', $f['id'])) continue;
80 | if (preg_match('/(string|text)/', $f['type'])) return $key ? $f[$key] : $f;
81 | $last = $f['id'];
82 | }
83 |
84 | $result = $last ?? $all[0];
85 | return $key ? $result[$key] : $result;
86 | }
87 |
88 | public static function getTableFieldsWithIds(string $table, array $excludedColumns = []) {
89 | return array_values(array_filter(self::getTableFields($table, $excludedColumns), fn($f) => !empty($f['relation'])));
90 | }
91 |
92 | public static function getUserIdField(string $tableName, $userIdField = 'user_id') {
93 | if (!self::tableExists($tableName)) return NULL;
94 | return \Schema::hasColumn($tableName, $userIdField) ? $userIdField : NULL;
95 | }
96 |
97 | public static function hasTable(string $tableName) {
98 | return self::tableExists($tableName);
99 | }
100 |
101 | public static function hasTimestamps(string $tableName) {
102 | if (!self::tableExists($tableName)) return FALSE;
103 | return \Schema::hasColumn($tableName, 'created_at') && \Schema::hasColumn($tableName, 'updated_at');
104 | }
105 |
106 | public static function hasSoftDelete(string $tableName) {
107 | if (!self::tableExists($tableName)) return FALSE;
108 | return \Schema::hasColumn($tableName, 'deleted_at');
109 | }
110 |
111 | public static function tableExists(string $tableName) {
112 | return \Schema::hasTable($tableName);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/template/stubs/Controllers/_controller_.php:
--------------------------------------------------------------------------------
1 | validate(/*_cvalidatecreate_*/);
58 |
59 | try {
60 |
61 | $_var_ = new _model_();
62 | /*_cstore_*/
63 | $_var_->save();
64 |
65 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('success', __('_title_ created successfully.'));
66 | } catch (\Throwable $e) {
67 | return redirect()->route('_route_.create', /*_cparentvars_*/)->withInput($request->input())->withErrors(['error' => $e->getMessage()]);
68 | }
69 | }
70 |
71 | /**
72 | * Display the specified resource.
73 | *
74 | * @param \App\Models\_model_ $_var_
75 | *
76 | * @return \Illuminate\Contracts\Support\Renderable
77 | */
78 | public function show(/*_callargs_*/) {
79 | /*_pauthorize_*/
80 |
81 | return view('_route_.show', /*_callvars_*/);
82 | }
83 |
84 | /**
85 | * Show the form for editing the specified resource.
86 | *
87 | * @param \App\Models\_model_ $_var_
88 | *
89 | * @return \Illuminate\Contracts\Support\Renderable
90 | */
91 | public function edit(/*_callargs_*/) {
92 | /*_pauthorize_*/
93 |
94 | /*_cselects_*/
95 |
96 | return view('_route_._editview_', /*_ceditvars_*/);
97 | }
98 |
99 | /**
100 | * Update the specified resource in storage.
101 | *
102 | * @param \Illuminate\Http\Request $request
103 | *
104 | * @return \Illuminate\Http\RedirectResponse
105 | */
106 | public function update(Request $request, /*_callargs_*/) {
107 | /*_pauthorize_*/
108 |
109 | $request->validate(/*_cvalidateedit_*/);
110 |
111 | try {
112 | /*_cedit_*/
113 | $_var_->save();
114 |
115 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('success', __('_title_ edited successfully.'));
116 | } catch (\Throwable $e) {
117 | return redirect()->route('_route_.edit', /*_callvars_*/)->withInput($request->input())->withErrors(['error' => $e->getMessage()]);
118 | }
119 | }
120 |
121 | /**
122 | * Remove the specified resource from storage.
123 | *
124 | * @param \App\Models\_model_ $_var_
125 | *
126 | * @return \Illuminate\Http\RedirectResponse
127 | */
128 | public function destroy(/*_callargs_*/) {
129 | /*_pauthorize_*/
130 |
131 | try {
132 | $_var_->delete();
133 |
134 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('success', __('_title_ deleted successfully'));
135 | } catch (\Throwable $e) {
136 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('error', 'Cannot delete _title_: ' . $e->getMessage());
137 | }
138 | }
139 |
140 | //@softdelete
141 |
142 | /**
143 | * Restore the specified deleted resource from storage.
144 | *
145 | * @param \App\Models\_model_ $_var_
146 | *
147 | * @return \Illuminate\Http\RedirectResponse
148 | */
149 | public function restore(/*_cparentargs_*/ int $_var__id,) {
150 | /*_pauthorize_*/
151 |
152 | /*_cfindbyid_*/
153 | /*_mauthorize_*/
154 |
155 | if (!empty($_var_)) {
156 | $_var_->restore();
157 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('success', __('_title_ restored successfully'));
158 | } else {
159 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('error', '_title_ not found');
160 | }
161 | }
162 |
163 | /**
164 | * Permanently delete the specified resource from storage.
165 | *
166 | * @param \App\Models\_model_ $_var_
167 | *
168 | * @return \Illuminate\Http\RedirectResponse
169 | */
170 | public function purge(/*_cparentargs_*/ int $_var__id,) {
171 | /*_pauthorize_*/
172 |
173 | /*_cfindbyid_*/
174 | /*_mauthorize_*/
175 |
176 | if (!empty($_var_)) {
177 | $_var_->forceDelete();
178 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('success', __('_title_ purged successfully'));
179 | } else {
180 | return redirect()->route('_route_.index', /*_cparentvars_*/)->with('error', __('_title_ not found'));
181 | }
182 | }
183 | //@endsoftdelete
184 | }
185 |
--------------------------------------------------------------------------------
/src/Generators/ViewGen.php:
--------------------------------------------------------------------------------
1 | getVarName();
18 | }
19 |
20 | public function getBreadcrumbs($template, $path) {
21 | $index = 1;
22 | $total = (count($this->tables) * 2) - 1;
23 |
24 | foreach ($this->tables as $table) {
25 | $tables[] = $table;
26 |
27 | if (!empty($lastTables)) {
28 | $lastTable = $lastTables[count($lastTables) - 1];
29 | $href = RouteUtils::makeRoute(NameUtils::getRouteName($lastTables) . '.show', $this->getRawVars($lastTables), $this->routePrefix);
30 | $anchorText = sprintf('%s #{{ $%s->id }}', NameUtils::titleCase($lastTable), NameUtils::getVariableName($lastTable));
31 | $links[] = $this->render($template, $path, [], ['href' => "{{ $href }}", 'anchortext' => $anchorText, 'index' => $index++, 'total' => $total]);
32 | }
33 |
34 | $href = RouteUtils::makeRoute(NameUtils::getRouteName($tables) . '.index', $this->getRawVars(array_slice($tables, 0, -1)), $this->routePrefix);
35 | $anchorText = NameUtils::titleCase($table);
36 | $links[] = $this->render($template, $path, [], ['href' => "{{ $href }}", 'anchortext' => $anchorText, 'index' => $index++, 'total' => $total]);
37 |
38 | $lastTables[] = $table;
39 | }
40 |
41 | return join("\n\t\t\t\t\t\t", $links ?? []);
42 | }
43 |
44 | public function genForm(string $template, string $path, array $replacements, bool $edit) {
45 | $input = function ($f) use ($edit, $path) {
46 | $type = (!empty($f->values) ? 'select' : (preg_match('/text/i', $f->type) ? 'textarea' : (preg_match('/bool/i', $f->type) ? 'boolean' : (preg_match('/json/i', $f->type) ? 'json' : 'input'))));
47 | $default = !empty($f->default) ? " ?? '$f->default'" : NULL;
48 | $val = $edit ? sprintf('@old(\'%s\', %s)%s', $f->id, $f->type === 'json' ? "json_encode(\$_var_->{$f->id})" : "\$_var_->{$f->id}", $default) : sprintf('@old(\'%s\')%s', $f->id, $default);
49 | $inputType = preg_match('/int|double|float|decimal/i', $f->type) ? 'number' : (preg_match('/url/i', $f->id) ? 'url' :(preg_match('/color/i', $f->id) ? 'color' : (preg_match('/mail/i', $f->id) ? 'email' : (preg_match('/password/i', $f->id) ? 'password' : (preg_match('/datetime/i', $f->type) ? 'datetime-local' : (preg_match('/date/i', $f->type) ? 'date' : (preg_match('/time/i', $f->type) ? 'time' : 'text')))))));
50 | $laraType = $inputType === 'datetime-local' ? 'datetime' : $inputType;
51 | $vars = ['_id_' => $f->id, '_name_' => $f->name, '_label_' => $f->name, '_enums_' => TextUtils::arrayExport($f->values ?? [], TRUE), '_val_' => $val, '_type_' => $inputType, '_laratype_' => $laraType, '_required_' => $f->nullable ? '' : 'required'];
52 |
53 | if (!empty($f->relation)) {
54 | $type = 'related';
55 | $vars['_related_'] = NameUtils::getVariableName($f->related_table);
56 | $vars['_relateds_'] = NameUtils::getVariableNamePlural($f->related_table);
57 | $vars['_readable_'] = SchemaUtils::firstHumanReadableField($this->getTableNameFromAlias($f->related_table), 'id') ?: 'id';
58 | $vars['_relatedroute_'] = RouteUtils::makeRoute($vars['_relateds_'] . '.create', [], $this->routePrefix);
59 | }
60 |
61 | return trim(strtr(file_get_contents("$path/inputs/$type.blade.php"), $vars));
62 | };
63 |
64 | $err = function ($f) {
65 | return sprintf("@if(\$errors->has('%s'))\n\t\t\t{{\$errors->first('%s')}}
\n\t\t@endif", $f->id, $f->id);
66 | };
67 |
68 | return $this->render($template, $path, $replacements, ['input' => $input, 'err' => $err]);
69 | }
70 |
71 | public function genIndex(string $template, string $path = '', array $replacements = []) {
72 | $display = function ($f) use ($path) {
73 | if (!empty($f->relation)) {
74 | if ($index = array_search($f->related_table, $this->parentTables())) {
75 | $tables = array_slice($this->parentTables(), 0, $index + 1);
76 |
77 | return sprintf('{{$_var_?->%s?->%s ?: "(blank)"}} ',
78 | RouteUtils::makeRoute(NameUtils::getRouteName($tables) . '.show', $this->getRawVars($tables), $this->routePrefix), $f->relation, SchemaUtils::firstHumanReadableField($this->getTableNameFromAlias($f->related_table), 'id') ?? 'id');
79 | } else {
80 | return sprintf('{{$_var_?->%s?->%s ?: "(blank)"}} ',
81 | RouteUtils::makeRoute(NameUtils::getRouteName($f->related_table) . '.show', "\$_var_->$f->id ?: 0", $this->routePrefix), $f->relation, SchemaUtils::firstHumanReadableField($this->getTableNameFromAlias($f->related_table), 'id') ?? 'id');
82 | }
83 | } else {
84 | $type = preg_match('/(json|boolean|text)/', $f->type) ? $f->type : 'string';
85 | return trim(strtr(file_get_contents("$path/display/$type.blade.php"), ['_col_' => $f->id]));
86 | }
87 | };
88 |
89 |
90 | return $this->render($template, $path, $replacements, ['display' => $display]);
91 | }
92 |
93 | protected function render($f, $path, $replacements, $vars) {
94 | $fields = array_map(fn($f) => (object) array_merge($f, ['name' => preg_replace('/ Id$/', '', $f['name'])]), $this->getFillableFields(['user_id']));
95 | $readable = $this->getFirstReadableField('id');
96 | $vars = array_merge(['fields' => $fields, 'hasSoftDelete' => $this->hasSoftDeletes(), 'hasTimestamps' => $this->hasTimestamps(), 'render' => fn($f) => call_user_func_array([$this, 'render'], [$f, $path, $replacements, $vars])], (array) $vars);
97 | $template = file_get_contents("$path/$f.blade.php");
98 | $str = BladeCompiler::render($template, $vars);
99 | $str = TextUtils::replaceBlanks($str, array_merge((array) $replacements, ['readable' => $readable]));
100 |
101 | return $str;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Generators/ControllerGen.php:
--------------------------------------------------------------------------------
1 | tables);
15 | }
16 |
17 | public function getControllerAllArgs() {
18 | return $this->getControllerArgs($this->tables);
19 | }
20 |
21 | public function getControllerArgs(array $tables) {
22 | $value = join(', ', array_map(fn($table) => sprintf('%s $%s', NameUtils::getModelName((array) $table), NameUtils::getVariableName($table)), $tables));
23 | return !empty($value) ? "$value," : "";
24 | }
25 |
26 | public function getControllerParentArgs() {
27 | return $this->getControllerArgs($this->parentTables());
28 | }
29 |
30 | public function getFindById() {
31 | return sprintf('$%s = %s::withTrashed()%s->find($%s_id);', $this->getVarName(), $this->getMainModelName(),
32 | $this->hasUserId() ? "->where('user_id', auth()->id())" : "", $this->getMainVarName());
33 | }
34 |
35 | public function getQuery() {
36 | if ($this->hasParentTable()) {
37 | $code[] = sprintf('$%s = $%s->%s();', $this->getVarNamePlural(), $this->getParentVarName(), $this->mainTable());
38 | } else {
39 | $code[] = sprintf('$%s = %s::query();', $this->getVarNamePlural(), $this->getMainModelName());
40 | }
41 |
42 | foreach (array_slice($this->tables, -2) as $table) {
43 | $realTable = $this->getTableNameFromAlias($table);
44 | if ($userIdField = SchemaUtils::getUserIdField($realTable)) {
45 | $code[] = sprintf("\t\t\$%s->where('%s', auth()->id());", $realTable === $this->mainTableReal() ? NameUtils::getVariableNamePlural($table) : NameUtils::getVariableName($table), $userIdField);
46 | }
47 | }
48 |
49 | if ($this->hasSoftDeletes()) {
50 | $code[] = sprintf("\n\t\tif (!!\$request->trashed) {\n\t\t\t\$%s->withTrashed();\n\t\t}", $this->getVarNamePlural());
51 | }
52 |
53 | return join("\n", $code);
54 | }
55 |
56 | public function getSearch() {
57 | return sprintf("if(!empty(\$request->search)) {\n\t\t\t\$%s->where('%s', 'like', '%%' . \$request->search . '%%');\n\t\t}", $this->getVarNamePlural(), SchemaUtils::firstHumanReadableField($this->mainTableReal(), 'id') ?: 'id');
58 | }
59 |
60 | public function getPager() {
61 | return sprintf('$%s = $%s->paginate(10);', $this->getVarNamePlural(), $this->getVarNamePlural());
62 | }
63 |
64 | public function getIndexVars() {
65 | return $this->getVars($this->parentTables(), (array) $this->getVarNamePlural());
66 | }
67 |
68 | public function getAllVars() {
69 | return $this->getVars($this->tables);
70 | }
71 |
72 | public function getParentVars() {
73 | return $this->getVars($this->parentTables());
74 | }
75 |
76 | public function getCreateVar() {
77 | return $this->singleForm ? sprintf('$%s = new %s();', $this->getVarName(), $this->getMainModelName()) : '';
78 | }
79 |
80 | public function getCreateVars() {
81 | $extraVars = (array) array_map(fn($field) => $field['related_table'], (array) $this->getExternallyRelatedFields());
82 | $createVar = $this->singleForm ? [$this->getVarName()] : [];
83 | $result = $this->getVars($this->parentTables(), array_merge($extraVars, $createVar));
84 |
85 | return $result;
86 | }
87 |
88 | public function getEditVars() {
89 | return $this->getVars($this->tables, (array) array_map(fn($field) => $field['related_table'], (array) $this->getExternallyRelatedFields()));
90 | }
91 |
92 | public function getCreateView() {
93 | return $this->singleForm ? 'create-edit' : 'create';
94 | }
95 |
96 | public function getEditView() {
97 | return $this->singleForm ? 'create-edit' : 'edit';
98 | }
99 |
100 | public function getWith() {
101 | foreach ($this->getExternallyRelatedFields() as $field) {
102 | $code[] = sprintf('$%s->with(\'%s\');', $this->getVarNamePlural(), $field['relation']);
103 | }
104 |
105 | return join("\n\t\t", $code ?? []);
106 | }
107 |
108 | public function getSelects() {
109 | foreach ($this->getExternallyRelatedFields() as $field) {
110 | $realTable = $this->getTableNameFromAlias($field['related_table']);
111 | if (SchemaUtils::getUserIdField($realTable)) {
112 | $code[] = sprintf("\$%s = \App\Models\%s::where('%s', auth()->id())->get();", NameUtils::getVariableNamePlural($realTable), NameUtils::getModelName($realTable), SchemaUtils::getUserIdField($realTable));
113 | } else {
114 | $code[] = sprintf("\$%s = \App\Models\%s::all();", NameUtils::getVariableNamePlural($realTable), NameUtils::getModelName($realTable));
115 | }
116 | }
117 |
118 | return join("\n\t\t", $code ?? []);
119 | }
120 |
121 | public function getValidations(bool $edit) {
122 | foreach ($this->getFillableFields() as $field) {
123 | if (preg_match('/boolean|timestamp/', $field['type'])) continue;
124 |
125 | $requirements = [];
126 |
127 | if (!$field['nullable']) {
128 | $requirements[] = 'required';
129 | }
130 |
131 | if (preg_match('/email$/i', $field['id'])) {
132 | $requirements[] = 'email';
133 | } elseif (preg_match('/(url)/i', $field['id'])) {
134 | $requirements[] = 'url';
135 | } elseif (preg_match('/(integer|float|double|decimal)/i', $field['type'])) {
136 | $requirements[] = 'numeric';
137 | } elseif (preg_match('/(date|datetime)/i', $field['type'])) {
138 | $requirements[] = 'date';
139 | }
140 |
141 | if (!empty($field['unique'])) {
142 | $unique = "unique:{$this->mainTableReal()},{$field['id']}";
143 | if ($edit) {
144 | $unique .= ",\${$this->getVarName()}->id";
145 | }
146 |
147 | $requirements[] = $unique;
148 | }
149 |
150 | $validations[$field['id']] = join('|', $requirements);
151 | }
152 |
153 | if (!empty($validations)) {
154 | $keyValues = array_map(fn($key, $value) => sprintf('"%s" => "%s"', $key, $value), array_keys($validations), $validations);
155 | return sprintf("[%s]", join(", ", $keyValues));
156 | } else {
157 | return '[]';
158 | }
159 | }
160 |
161 | public function getStore($edit) {
162 | foreach (SchemaUtils::getTableFields($this->mainTableReal()) as $field) {
163 | if ($field['id'] === 'user_id') {
164 | if (!$edit) $fills[] = sprintf("\$%s->user_id = auth()->id();", $this->getVarName());
165 | } else if (in_array($field['related_table'] ?? '', $this->realTables())) {
166 | if (!$edit) {
167 | $fills[] = sprintf("\$%s->%s = \$%s->id;", $this->getVarName(), $field['id'], NameUtils::getVariableName($this->getAliasFromTableName($field['related_table'])));
168 | }
169 | } else {
170 | $bool = preg_match('/bool/', $field['type']) ? '!!' : '';
171 | $fills[] = sprintf("\$%s->%s = %s\$request->%s;", $this->getVarName(), $field['id'], $bool, $field['id']);
172 | }
173 | }
174 |
175 | return join("\n\t\t", $fills ?? []);
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/src/Commands/CrudGenerate.php:
--------------------------------------------------------------------------------
1 | getTables();
41 | $aliases = $this->getTableAliases();
42 |
43 | $routePrefix = $this->option('prefix');
44 | $singleForm = $this->option('merge-forms');
45 |
46 | $cgen = new ControllerGen($tables, $aliases, $singleForm);
47 | $mgen = new ModelGen($tables, $aliases);
48 | $rgen = new RouteGen($tables, $aliases, $routePrefix);
49 | $vgen = new ViewGen($tables, $aliases, $routePrefix);
50 | $pgen = new PolicyGen($tables, $aliases);
51 |
52 | $blanks = [
53 | 'var' => $cgen->getVarName(),
54 | 'vars' => $cgen->getVarNamePlural(),
55 | 'title' => $cgen->getTitle(),
56 | 'titles' => $cgen->getTitlePlural(),
57 |
58 | 'controller' => $cgen->getControllerName(),
59 | 'cquery' => $cgen->getQuery(),
60 | 'cfindbyid' => $cgen->getFindById(),
61 | 'cwith' => $cgen->getWith(),
62 | 'csearch' => $cgen->getSearch(),
63 | 'cpager' => $cgen->getPager(),
64 |
65 | 'cparentargs' => $cgen->getControllerParentArgs(),
66 | 'callargs' => $cgen->getControllerAllArgs(),
67 |
68 | 'cselects' => $cgen->getSelects(),
69 | 'cindexvars' => $cgen->getIndexVars(),
70 | 'callvars' => $cgen->getAllVars(),
71 | 'cparentvars' => $cgen->getParentVars(),
72 | 'ccreatevar' => $cgen->getCreateVar(),
73 | 'ccreatevars' => $cgen->getCreateVars(),
74 | 'ceditvars' => $cgen->getEditVars(),
75 | 'createview' => $cgen->getCreateView(),
76 | 'editview' => $cgen->getEditView(),
77 |
78 | 'cvalidatecreate' => $cgen->getValidations(FALSE),
79 | 'cvalidateedit' => $cgen->getValidations(TRUE),
80 | 'cstore' => $cgen->getStore(FALSE),
81 | 'cedit' => $cgen->getStore(TRUE),
82 |
83 | 'model' => $mgen->getModelName(),
84 | 'usesmodels' => $mgen->getUsesModels(),
85 | 'softdelete' => $mgen->getSoftDelete(),
86 | 'fillable' => $mgen->getFillable(),
87 | 'belongsto' => $mgen->getBelongsTo(),
88 | 'hasmany' => $mgen->getHasMany(),
89 | 'casts' => $mgen->getCasts(),
90 | 'tablename' => $mgen->mainTableReal(),
91 |
92 | 'route' => $rgen->getRouteName(),
93 | 'routevars' => $rgen->getRouteVars(),
94 | 'routevarswithid' => $rgen->getRouteVarsWithId(),
95 | 'routeurl' => $rgen->getRouteUrl(),
96 | 'parentrouteurl' => $rgen->getParentRouteUrl(),
97 | 'routeurlwithvars' => $rgen->getRouteUrlWithPlaceholders(),
98 | 'routeurlwithid' => $rgen->getRouteUrlWithId(),
99 | 'parentrouteurlwithvars' => $rgen->getParentRouteUrlWithPlaceholders(),
100 |
101 | 'asroute' => $rgen->getAsRoute(),
102 |
103 | 'policy' => $pgen->getPolicyName(),
104 | 'cpolicy' => $pgen->getControllerPolicy(),
105 | 'policyreadargs' => $pgen->getPolicyReadArgs(),
106 | 'policyreadrules' => $pgen->getPolicyReadRules(),
107 | 'policywriteargs' => $pgen->getPolicyWriteArgs(),
108 | 'policywriterules' => $pgen->getPolicyWriteRules(),
109 |
110 | 'view' => $vgen->getViewName(),
111 |
112 | 'authorize' => $pgen->getControllerPolicy(),
113 | 'pauthorize' => $pgen->getParentAuthorization(),
114 | 'mauthorize' => $pgen->getModelAuthorization(),
115 |
116 | 'layout' => sprintf('layouts.%s', $this->option('layout') ?: 'app'),
117 | 'section' => $this->option('section') ?: 'content',
118 | ];
119 |
120 | $files = new Templates($this->getTemplateDir());
121 | $indexView = preg_match('/^(cards|chat)$/', $this->option('index')) ? $this->option('index') : 'table';
122 |
123 | $cssFramework = $this->getCssFramework();
124 | $partialsDir = "{$files->templatePath()}/stubs/views/$cssFramework/partials";
125 |
126 | $blanks['breadcrumbs'] = $vgen->getBreadcrumbs('render/breadcrumbs', $partialsDir);
127 | $blanks['index'] = $vgen->genIndex("render/$indexView", $partialsDir, $blanks);
128 | $blanks['create'] = $vgen->genForm('render/form', $partialsDir, $blanks, FALSE);
129 | $blanks['edit'] = $vgen->genForm('render/form', $partialsDir, $blanks, TRUE);
130 | $blanks['show'] = $vgen->genIndex('render/show', $partialsDir, $blanks);
131 |
132 | $formatter = new Formatter($tables, $aliases);
133 | $forceOverwrite = $this->option('force');
134 |
135 | foreach ($this->getStubTypes($cssFramework) as $type) {
136 | $stubs = $files->getStubs($type);
137 |
138 | foreach ($stubs as $stub) {
139 | $str = TextUtils::replaceBlanks(file_get_contents($stub), $blanks);
140 | $str = $formatter->fixSoftDelete($str);
141 |
142 | $dest = $files->getDest($type, $stub, $blanks, $rgen->getRouteUrlWithoutPrefix());
143 |
144 | if ($forceOverwrite || !file_exists($dest)) {
145 | $this->info("Writing $dest");
146 | FileUtils::writeFile($dest, $str);
147 | } else {
148 | $this->warn("File already exists (skipping):\n$dest");
149 | }
150 | }
151 | }
152 |
153 | return Command::SUCCESS;
154 | }
155 |
156 | protected function getOptions() {
157 | return [
158 | ['css', 'c', InputOption::VALUE_REQUIRED, 'Which css framework to use: bootstrap, larastrap or tailwind (default: bootstrap)'],
159 | ['prefix', 'p', InputOption::VALUE_REQUIRED, 'The prefix for the route name (default: none)'],
160 | ['index', 'i', InputOption::VALUE_REQUIRED, 'The index view to use: "table", "cards" or "chat" (default table)'],
161 | ['layout', 'l', InputOption::VALUE_REQUIRED, 'The @layout name used by the views (default "app")'],
162 | ['section', 's', InputOption::VALUE_REQUIRED, 'The @section name used by the views (default "content")'],
163 | ['tailwind', 't', InputOption::VALUE_NONE, 'Use Tailwind CSS instead of Bootstrap 5 (shorthand for --css=tailwind)'],
164 | ['template', 'd', InputOption::VALUE_REQUIRED, 'The template directory (if you want to use custom templates)'],
165 | ['alias', 'a', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The alias for the table name (e.g. --alias some_alias=table_name --alias some_other_alias=another_table)'],
166 | ['merge-forms', 'm', InputOption::VALUE_NONE, 'Merge create and edit views into a single form'],
167 | ['force', 'f', InputOption::VALUE_NONE, 'Force overwriting of existing files'],
168 | ];
169 | }
170 |
171 | /**
172 | * {@inheritdoc}
173 | */
174 | protected function getArguments() {
175 | return [
176 | ['table', InputArgument::REQUIRED, 'The name of the table (with parent tables separated by a dot)'],
177 | ];
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/.phpunit.result.cache:
--------------------------------------------------------------------------------
1 | {"version":1,"defects":{"San\\Crud\\Tests\\Utils\\TextUtilsTest::testReplaceBlanks":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetVarName":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetParentVarNamePlural":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetTitle":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetTitlePlural":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetVars":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetVarNamePlural":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetParentVarName":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetIndexVars":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetWith":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerAllArgs":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetSearch":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetValidations":3,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetQuery":3,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerArgs":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetParentVars":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerName":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetCreateVars":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetSelects":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetEditVars":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetStore":3,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetAllVars":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetPager":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerParentArgs":4,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetFindById":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetHasMany":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetCasts":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetFillable":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetModelName":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetBelongsTo":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetSoftDelete":4,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetUsesModels":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetUsesPolicies":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetControllerPolicy":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyWriteArgs":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyReadArgs":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetParentAuthorization":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyRules":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyWriteRules":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetModelAuthorization":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyAuthorization":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyName":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyArgs":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteUrlWithPlaceholders":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetParentRouteName":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteName":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteUrl":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetParentRouteUrlWithPlaceholders":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteVars":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteUrlWithId":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetParentRouteUrl":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteVarsWithId":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetAsRoute":4,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetUrlWithPlaceholders":4,"San\\Crud\\Tests\\Generators\\TemplatesTest::testGetStubs":4,"San\\Crud\\Tests\\Generators\\TemplatesTest::testGetFirstStub":4,"San\\Crud\\Tests\\Generators\\TemplatesTest::testGetDest":4,"San\\Crud\\Tests\\Utils\\FileUtilsTest::testGetFiles":4,"San\\Crud\\Tests\\Utils\\FileUtilsTest::testWriteFile":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetVariableNamePlural":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetVariableName":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetPolicyName":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testStudlyCase":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetModelName":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetControllerName":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testTitleCase":4,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetRouteName":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testHasTimestamps":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testFirstHumanReadableField":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testHasTable":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetTables":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetTableFields":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetTableFieldsWithIds":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetUserIdField":4,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testHasSoftDelete":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testMainTable":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testHasParentTable":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testParentTable":4,"San\\Crud\\Tests\\Generators\\BaseGenTest::testParentTables":4,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyReadRules":4,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGetInfo":4,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGenIndex":4,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGenForm":4,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGetBreadcrumbs":3,"San\\Crud\\Tests\\Utils\\TextUtilsTest::testArrayExport":4,"San\\Crud\\Tests\\Formatters\\FormatterTest::testFixSoftDelete":4,"San\\Crud\\Tests\\Commands\\MakeCrudTest::testHandle":4,"San\\Crud\\Tests\\Commands\\MakeCrudTest::testGetTables":2,"San\\Crud\\Tests\\Generators\\TemplatesTest::testInvalidPath":4,"San\\Crud\\Tests\\Utils\\RouteUtilsTest::testMakeRoute":3,"San\\Crud\\Tests\\Commands\\CrudRemoveTest::testHandle":4,"San\\Crud\\Tests\\Commands\\CrudTemplateTest::testHandle":3},"times":{"San\\Crud\\Tests\\Utils\\TextUtilsTest::testReplaceBlanks":0.016,"San\\Crud\\Tests\\Utils\\TextUtilsTest::testArrayExport":0.015,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetVarName":0.016,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetParentVarNamePlural":0.015,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetTitle":0.017,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetTitlePlural":0.016,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetVars":0.014,"San\\Crud\\Tests\\Generators\\BaseGenTest::testMainTable":0.014,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetVarNamePlural":0.014,"San\\Crud\\Tests\\Generators\\BaseGenTest::testHasParentTable":0.015,"San\\Crud\\Tests\\Generators\\BaseGenTest::testParentTable":0.014,"San\\Crud\\Tests\\Generators\\BaseGenTest::testParentTables":0.015,"San\\Crud\\Tests\\Generators\\BaseGenTest::testGetParentVarName":0.016,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetIndexVars":0.016,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetWith":0.016,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerAllArgs":0.015,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetSearch":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetValidations":0.016,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetQuery":0.015,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerArgs":0.016,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetParentVars":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerName":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetCreateVars":0.019,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetSelects":0.02,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetEditVars":0.016,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetStore":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetAllVars":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetPager":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetControllerParentArgs":0.017,"San\\Crud\\Tests\\Generators\\ControllerGenTest::testGetFindById":0.017,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetHasMany":0.02,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetCasts":0.016,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetFillable":0.015,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetModelName":0.016,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetBelongsTo":0.017,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetSoftDelete":0.015,"San\\Crud\\Tests\\Generators\\ModelGenTest::testGetUsesModels":0.016,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetUsesPolicies":0.015,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetControllerPolicy":0.015,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyWriteArgs":0.015,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyReadArgs":0.015,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyReadRules":0.015,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetParentAuthorization":0.014,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyRules":0.016,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyWriteRules":0.016,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetModelAuthorization":0.014,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyAuthorization":0.016,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyName":0.015,"San\\Crud\\Tests\\Generators\\PolicyGenTest::testGetPolicyArgs":0.015,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteUrlWithPlaceholders":0.016,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetParentRouteName":0.016,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteName":0.02,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteUrl":0.016,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetParentRouteUrlWithPlaceholders":0.015,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteVars":0.014,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteUrlWithId":0.015,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetParentRouteUrl":0.013,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetRouteVarsWithId":0.015,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetAsRoute":0.014,"San\\Crud\\Tests\\Generators\\RouteGenTest::testGetUrlWithPlaceholders":0.016,"San\\Crud\\Tests\\Generators\\TemplatesTest::testGetStubs":0.016,"San\\Crud\\Tests\\Generators\\TemplatesTest::testGetFirstStub":0.015,"San\\Crud\\Tests\\Generators\\TemplatesTest::testGetDest":0.016,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGetInfo":0.124,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGenIndex":0.024,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGenForm":0.018,"San\\Crud\\Tests\\Generators\\ViewGenTest::testGetBreadcrumbs":0.035,"San\\Crud\\Tests\\Utils\\FileUtilsTest::testGetFiles":0.016,"San\\Crud\\Tests\\Utils\\FileUtilsTest::testWriteFile":0.016,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetVariableNamePlural":0.016,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetVariableName":0.015,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetPolicyName":0.014,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testStudlyCase":0.015,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetModelName":0.014,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetControllerName":0.015,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testTitleCase":0.014,"San\\Crud\\Tests\\Utils\\NameUtilsTest::testGetRouteName":0.015,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testHasTimestamps":0.021,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testFirstHumanReadableField":0.016,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testHasTable":0.016,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetTables":0.016,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetTableFields":0.017,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetTableFieldsWithIds":0.017,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testGetUserIdField":0.015,"San\\Crud\\Tests\\Utils\\SchemaUtilsTest::testHasSoftDelete":0.014,"San\\Crud\\Tests\\Formatters\\FormatterTest::testFixSoftDelete":0.016,"San\\Crud\\Tests\\Commands\\MakeCrudTest::testHandle":0.272,"San\\Crud\\Tests\\Commands\\MakeCrudTest::testGetTables":0.026,"San\\Crud\\Tests\\Generators\\TemplatesTest::testInvalidPath":0.016,"San\\Crud\\Tests\\Utils\\RouteUtilsTest::testMakeRoute":0.016,"San\\Crud\\Tests\\Utils\\FileUtilsTest::testRecursiveCopy":0.016,"San\\Crud\\Tests\\Commands\\CrudRemoveTest::testHandle":0.046,"San\\Crud\\Tests\\Commands\\CrudTemplateTest::testHandle":0.019,"San\\Crud\\Tests\\Commands\\CrudGenerateTest::testHandle":0.176}}
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@algolia/autocomplete-core@1.7.2":
6 | version "1.7.2"
7 | resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.2.tgz#8abbed88082f611997538760dffcb43b33b1fd1d"
8 | integrity sha512-eclwUDC6qfApNnEfu1uWcL/rudQsn59tjEoUYZYE2JSXZrHLRjBUGMxiCoknobU2Pva8ejb0eRxpIYDtVVqdsw==
9 | dependencies:
10 | "@algolia/autocomplete-shared" "1.7.2"
11 |
12 | "@algolia/autocomplete-preset-algolia@1.7.2":
13 | version "1.7.2"
14 | resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.2.tgz#9cd4f64b3d64399657ee2dc2b7e0a939e0713a26"
15 | integrity sha512-+RYEG6B0QiGGfRb2G3MtPfyrl0dALF3cQNTWBzBX6p5o01vCCGTTinAm2UKG3tfc2CnOMAtnPLkzNZyJUpnVJw==
16 | dependencies:
17 | "@algolia/autocomplete-shared" "1.7.2"
18 |
19 | "@algolia/autocomplete-shared@1.7.2":
20 | version "1.7.2"
21 | resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.2.tgz#daa23280e78d3b42ae9564d12470ae034db51a89"
22 | integrity sha512-QCckjiC7xXHIUaIL3ektBtjJ0w7tTA3iqKcAE/Hjn1lZ5omp7i3Y4e09rAr9ZybqirL7AbxCLLq0Ra5DDPKeug==
23 |
24 | "@algolia/cache-browser-local-storage@4.14.3":
25 | version "4.14.3"
26 | resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.3.tgz#b9e0da012b2f124f785134a4d468ee0841b2399d"
27 | integrity sha512-hWH1yCxgG3+R/xZIscmUrWAIBnmBFHH5j30fY/+aPkEZWt90wYILfAHIOZ1/Wxhho5SkPfwFmT7ooX2d9JeQBw==
28 | dependencies:
29 | "@algolia/cache-common" "4.14.3"
30 |
31 | "@algolia/cache-common@4.14.3":
32 | version "4.14.3"
33 | resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.3.tgz#a78e9faee3dfec018eab7b0996e918e06b476ac7"
34 | integrity sha512-oZJofOoD9FQOwiGTzyRnmzvh3ZP8WVTNPBLH5xU5JNF7drDbRT0ocVT0h/xB2rPHYzOeXRrLaQQBwRT/CKom0Q==
35 |
36 | "@algolia/cache-in-memory@4.14.3":
37 | version "4.14.3"
38 | resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.3.tgz#96cefb942aeb80e51e6a7e29f25f4f7f3439b736"
39 | integrity sha512-ES0hHQnzWjeioLQf5Nq+x1AWdZJ50znNPSH3puB/Y4Xsg4Av1bvLmTJe7SY2uqONaeMTvL0OaVcoVtQgJVw0vg==
40 | dependencies:
41 | "@algolia/cache-common" "4.14.3"
42 |
43 | "@algolia/client-account@4.14.3":
44 | version "4.14.3"
45 | resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.3.tgz#6d7d032a65c600339ce066505c77013d9a9e4966"
46 | integrity sha512-PBcPb0+f5Xbh5UfLZNx2Ow589OdP8WYjB4CnvupfYBrl9JyC1sdH4jcq/ri8osO/mCZYjZrQsKAPIqW/gQmizQ==
47 | dependencies:
48 | "@algolia/client-common" "4.14.3"
49 | "@algolia/client-search" "4.14.3"
50 | "@algolia/transporter" "4.14.3"
51 |
52 | "@algolia/client-analytics@4.14.3":
53 | version "4.14.3"
54 | resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.3.tgz#ca409d00a8fff98fdcc215dc96731039900055dc"
55 | integrity sha512-eAwQq0Hb/aauv9NhCH5Dp3Nm29oFx28sayFN2fdOWemwSeJHIl7TmcsxVlRsO50fsD8CtPcDhtGeD3AIFLNvqw==
56 | dependencies:
57 | "@algolia/client-common" "4.14.3"
58 | "@algolia/client-search" "4.14.3"
59 | "@algolia/requester-common" "4.14.3"
60 | "@algolia/transporter" "4.14.3"
61 |
62 | "@algolia/client-common@4.14.3":
63 | version "4.14.3"
64 | resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.3.tgz#c44e48652b2121a20d7a40cfd68d095ebb4191a8"
65 | integrity sha512-jkPPDZdi63IK64Yg4WccdCsAP4pHxSkr4usplkUZM5C1l1oEpZXsy2c579LQ0rvwCs5JFmwfNG4ahOszidfWPw==
66 | dependencies:
67 | "@algolia/requester-common" "4.14.3"
68 | "@algolia/transporter" "4.14.3"
69 |
70 | "@algolia/client-personalization@4.14.3":
71 | version "4.14.3"
72 | resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.3.tgz#8f71325035aa2a5fa7d1d567575235cf1d6c654f"
73 | integrity sha512-UCX1MtkVNgaOL9f0e22x6tC9e2H3unZQlSUdnVaSKpZ+hdSChXGaRjp2UIT7pxmPqNCyv51F597KEX5WT60jNg==
74 | dependencies:
75 | "@algolia/client-common" "4.14.3"
76 | "@algolia/requester-common" "4.14.3"
77 | "@algolia/transporter" "4.14.3"
78 |
79 | "@algolia/client-search@4.14.3":
80 | version "4.14.3"
81 | resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.3.tgz#cf1e77549f5c3e73408ffe6441ede985fde69da0"
82 | integrity sha512-I2U7xBx5OPFdPLA8AXKUPPxGY3HDxZ4r7+mlZ8ZpLbI8/ri6fnu6B4z3wcL7sgHhDYMwnAE8Xr0AB0h3Hnkp4A==
83 | dependencies:
84 | "@algolia/client-common" "4.14.3"
85 | "@algolia/requester-common" "4.14.3"
86 | "@algolia/transporter" "4.14.3"
87 |
88 | "@algolia/logger-common@4.14.3":
89 | version "4.14.3"
90 | resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.3.tgz#87d4725e7f56ea5a39b605771b7149fff62032a7"
91 | integrity sha512-kUEAZaBt/J3RjYi8MEBT2QEexJR2kAE2mtLmezsmqMQZTV502TkHCxYzTwY2dE7OKcUTxi4OFlMuS4GId9CWPw==
92 |
93 | "@algolia/logger-console@4.14.3":
94 | version "4.14.3"
95 | resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.3.tgz#1f19f8f0a5ef11f01d1f9545290eb6a89b71fb8a"
96 | integrity sha512-ZWqAlUITktiMN2EiFpQIFCJS10N96A++yrexqC2Z+3hgF/JcKrOxOdT4nSCQoEPvU4Ki9QKbpzbebRDemZt/hw==
97 | dependencies:
98 | "@algolia/logger-common" "4.14.3"
99 |
100 | "@algolia/requester-browser-xhr@4.14.3":
101 | version "4.14.3"
102 | resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.3.tgz#bcf55cba20f58fd9bc95ee55793b5219f3ce8888"
103 | integrity sha512-AZeg2T08WLUPvDncl2XLX2O67W5wIO8MNaT7z5ii5LgBTuk/rU4CikTjCe2xsUleIZeFl++QrPAi4Bdxws6r/Q==
104 | dependencies:
105 | "@algolia/requester-common" "4.14.3"
106 |
107 | "@algolia/requester-common@4.14.3":
108 | version "4.14.3"
109 | resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.3.tgz#2d02fbe01afb7ae5651ae8dfe62d6c089f103714"
110 | integrity sha512-RrRzqNyKFDP7IkTuV3XvYGF9cDPn9h6qEDl595lXva3YUk9YSS8+MGZnnkOMHvjkrSCKfoLeLbm/T4tmoIeclw==
111 |
112 | "@algolia/requester-node-http@4.14.3":
113 | version "4.14.3"
114 | resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.3.tgz#72389e1c2e5d964702451e75e368eefe85a09d8f"
115 | integrity sha512-O5wnPxtDRPuW2U0EaOz9rMMWdlhwP0J0eSL1Z7TtXF8xnUeeUyNJrdhV5uy2CAp6RbhM1VuC3sOJcIR6Av+vbA==
116 | dependencies:
117 | "@algolia/requester-common" "4.14.3"
118 |
119 | "@algolia/transporter@4.14.3":
120 | version "4.14.3"
121 | resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.3.tgz#5593036bd9cf2adfd077fdc3e81d2e6118660a7a"
122 | integrity sha512-2qlKlKsnGJ008exFRb5RTeTOqhLZj0bkMCMVskxoqWejs2Q2QtWmsiH98hDfpw0fmnyhzHEt0Z7lqxBYp8bW2w==
123 | dependencies:
124 | "@algolia/cache-common" "4.14.3"
125 | "@algolia/logger-common" "4.14.3"
126 | "@algolia/requester-common" "4.14.3"
127 |
128 | "@babel/parser@^7.16.4":
129 | version "7.20.5"
130 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8"
131 | integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==
132 |
133 | "@docsearch/css@3.3.0", "@docsearch/css@^3.3.0":
134 | version "3.3.0"
135 | resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.3.0.tgz#d698e48302d12240d7c2f7452ccb2d2239a8cd80"
136 | integrity sha512-rODCdDtGyudLj+Va8b6w6Y85KE85bXRsps/R4Yjwt5vueXKXZQKYw0aA9knxLBT6a/bI/GMrAcmCR75KYOM6hg==
137 |
138 | "@docsearch/js@^3.3.0":
139 | version "3.3.0"
140 | resolved "https://registry.yarnpkg.com/@docsearch/js/-/js-3.3.0.tgz#c8f614b722cc8a6375e83f9c27557e9398d6a4d4"
141 | integrity sha512-oFXWRPNvPxAzBhnFJ9UCFIYZiQNc3Yrv6912nZHw/UIGxsyzKpNRZgHq8HDk1niYmOSoLKtVFcxkccpQmYGFyg==
142 | dependencies:
143 | "@docsearch/react" "3.3.0"
144 | preact "^10.0.0"
145 |
146 | "@docsearch/react@3.3.0":
147 | version "3.3.0"
148 | resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.3.0.tgz#b8ac8e7f49b9bf2f96d34c24bc1cfd097ec0eead"
149 | integrity sha512-fhS5adZkae2SSdMYEMVg6pxI5a/cE+tW16ki1V0/ur4Fdok3hBRkmN/H8VvlXnxzggkQIIRIVvYPn00JPjen3A==
150 | dependencies:
151 | "@algolia/autocomplete-core" "1.7.2"
152 | "@algolia/autocomplete-preset-algolia" "1.7.2"
153 | "@docsearch/css" "3.3.0"
154 | algoliasearch "^4.0.0"
155 |
156 | "@esbuild/android-arm64@0.16.10":
157 | version "0.16.10"
158 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.10.tgz#d784d8f13dbef50492ea55456fb50651e4036fbf"
159 | integrity sha512-47Y+NwVKTldTlDhSgJHZ/RpvBQMUDG7eKihqaF/u6g7s0ZPz4J1vy8A3rwnnUOF2CuDn7w7Gj/QcMoWz3U3SJw==
160 |
161 | "@esbuild/android-arm@0.16.10":
162 | version "0.16.10"
163 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.10.tgz#becf6b5647c091b039121db8c17300a7dfd1ab4a"
164 | integrity sha512-RmJjQTRrO6VwUWDrzTBLmV4OJZTarYsiepLGlF2rYTVB701hSorPywPGvP6d8HCuuRibyXa5JX4s3jN2kHEtjQ==
165 |
166 | "@esbuild/android-x64@0.16.10":
167 | version "0.16.10"
168 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.10.tgz#648cacbb13a5047380a038e5d6d895015e31b525"
169 | integrity sha512-C4PfnrBMcuAcOurQzpF1tTtZz94IXO5JmICJJ3NFJRHbXXsQUg9RFG45KvydKqtFfBaFLCHpduUkUfXwIvGnRg==
170 |
171 | "@esbuild/darwin-arm64@0.16.10":
172 | version "0.16.10"
173 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.10.tgz#3ca7fd9a456d11752df77df6c030f2d08f27bda9"
174 | integrity sha512-bH/bpFwldyOKdi9HSLCLhhKeVgRYr9KblchwXgY2NeUHBB/BzTUHtUSBgGBmpydB1/4E37m+ggXXfSrnD7/E7g==
175 |
176 | "@esbuild/darwin-x64@0.16.10":
177 | version "0.16.10"
178 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.10.tgz#7eb71b8da4106627f01553def517d3c5e5942592"
179 | integrity sha512-OXt7ijoLuy+AjDSKQWu+KdDFMBbdeaL6wtgMKtDUXKWHiAMKHan5+R1QAG6HD4+K0nnOvEJXKHeA9QhXNAjOTQ==
180 |
181 | "@esbuild/freebsd-arm64@0.16.10":
182 | version "0.16.10"
183 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.10.tgz#c69c78ee1d17d35ad2cf76a1bb67788000a84b43"
184 | integrity sha512-shSQX/3GHuspE3Uxtq5kcFG/zqC+VuMnJkqV7LczO41cIe6CQaXHD3QdMLA4ziRq/m0vZo7JdterlgbmgNIAlQ==
185 |
186 | "@esbuild/freebsd-x64@0.16.10":
187 | version "0.16.10"
188 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.10.tgz#a9804ab1b9366f915812af24ad5cfc1c0db01441"
189 | integrity sha512-5YVc1zdeaJGASijZmTzSO4h6uKzsQGG3pkjI6fuXvolhm3hVRhZwnHJkforaZLmzvNv5Tb7a3QL2FAVmrgySIA==
190 |
191 | "@esbuild/linux-arm64@0.16.10":
192 | version "0.16.10"
193 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.10.tgz#d9a9ddfcb28ed8cced688bc112ef66283d6fa77f"
194 | integrity sha512-2aqeNVxIaRfPcIaMZIFoblLh588sWyCbmj1HHCCs9WmeNWm+EIN0SmvsmPvTa/TsNZFKnxTcvkX2eszTcCqIrA==
195 |
196 | "@esbuild/linux-arm@0.16.10":
197 | version "0.16.10"
198 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.10.tgz#f32cdac1d3319c83ae7f9f31238dd1284ee6bba2"
199 | integrity sha512-c360287ZWI2miBnvIj23bPyVctgzeMT2kQKR+x94pVqIN44h3GF8VMEs1SFPH1UgyDr3yBbx3vowDS1SVhyVhA==
200 |
201 | "@esbuild/linux-ia32@0.16.10":
202 | version "0.16.10"
203 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.10.tgz#1e023478e42f3a01cad48f4af50120d4b639af03"
204 | integrity sha512-sqMIEWeyrLGU7J5RB5fTkLRIFwsgsQ7ieWXlDLEmC2HblPYGb3AucD7inw2OrKFpRPKsec1l+lssiM3+NV5aOw==
205 |
206 | "@esbuild/linux-loong64@0.16.10":
207 | version "0.16.10"
208 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.10.tgz#f9098865a69d1d6e2f8bda51c7f9d4240f20b771"
209 | integrity sha512-O7Pd5hLEtTg37NC73pfhUOGTjx/+aXu5YoSq3ahCxcN7Bcr2F47mv+kG5t840thnsEzrv0oB70+LJu3gUgchvg==
210 |
211 | "@esbuild/linux-mips64el@0.16.10":
212 | version "0.16.10"
213 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.10.tgz#574725ad2ea81b7783b7ba7d1ab3475f8fdd8d32"
214 | integrity sha512-FN8mZOH7531iPHM0kaFhAOqqNHoAb6r/YHW2ZIxNi0a85UBi2DO4Vuyn7t1p4UN8a4LoAnLOT1PqNgHkgBJgbA==
215 |
216 | "@esbuild/linux-ppc64@0.16.10":
217 | version "0.16.10"
218 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.10.tgz#11da658c54514a693813af56bb28951d563a90c3"
219 | integrity sha512-Dg9RiqdvHOAWnOKIOTsIx8dFX9EDlY2IbPEY7YFzchrCiTZmMkD7jWA9UdZbNUygPjdmQBVPRCrLydReFlX9yg==
220 |
221 | "@esbuild/linux-riscv64@0.16.10":
222 | version "0.16.10"
223 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.10.tgz#3af4600adbd6c5a4a6f1da05771f4aa6774baab2"
224 | integrity sha512-XMqtpjwzbmlar0BJIxmzu/RZ7EWlfVfH68Vadrva0Wj5UKOdKvqskuev2jY2oPV3aoQUyXwnMbMrFmloO2GfAw==
225 |
226 | "@esbuild/linux-s390x@0.16.10":
227 | version "0.16.10"
228 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.10.tgz#9e3377aaf0191a9d6628e806a279085ec4391f3e"
229 | integrity sha512-fu7XtnoeRNFMx8DjK3gPWpFBDM2u5ba+FYwg27SjMJwKvJr4bDyKz5c+FLXLUSSAkMAt/UL+cUbEbra+rYtUgw==
230 |
231 | "@esbuild/linux-x64@0.16.10":
232 | version "0.16.10"
233 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.10.tgz#7c41d4d697ce674e0083e7baa6231468f4650d85"
234 | integrity sha512-61lcjVC/RldNNMUzQQdyCWjCxp9YLEQgIxErxU9XluX7juBdGKb0pvddS0vPNuCvotRbzijZ1pzII+26haWzbA==
235 |
236 | "@esbuild/netbsd-x64@0.16.10":
237 | version "0.16.10"
238 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.10.tgz#ebac59e3986834af04bbafcee7b0c1f31cd477c6"
239 | integrity sha512-JeZXCX3viSA9j4HqSoygjssdqYdfHd6yCFWyfSekLbz4Ef+D2EjvsN02ZQPwYl5a5gg/ehdHgegHhlfOFP0HCA==
240 |
241 | "@esbuild/openbsd-x64@0.16.10":
242 | version "0.16.10"
243 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.10.tgz#9eaa6cac3b80db45090c0946e62de5b5689c61d1"
244 | integrity sha512-3qpxQKuEVIIg8SebpXsp82OBrqjPV/OwNWmG+TnZDr3VGyChNnGMHccC1xkbxCHDQNnnXjxhMQNyHmdFJbmbRA==
245 |
246 | "@esbuild/sunos-x64@0.16.10":
247 | version "0.16.10"
248 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.10.tgz#31e5e4b814ef43d300e26511e486a4716a390d5f"
249 | integrity sha512-z+q0xZ+et/7etz7WoMyXTHZ1rB8PMSNp/FOqURLJLOPb3GWJ2aj4oCqFCjPwEbW1rsT7JPpxeH/DwGAWk/I1Bg==
250 |
251 | "@esbuild/win32-arm64@0.16.10":
252 | version "0.16.10"
253 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.10.tgz#ca58472dc03ca79e6d03f8a31113979ff253d94f"
254 | integrity sha512-+YYu5sbQ9npkNT9Dec+tn1F/kjg6SMgr6bfi/6FpXYZvCRfu2YFPZGb+3x8K30s8eRxFpoG4sGhiSUkr1xbHEw==
255 |
256 | "@esbuild/win32-ia32@0.16.10":
257 | version "0.16.10"
258 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.10.tgz#c572df2c65ab118feed0a5da5a4a193846d74e43"
259 | integrity sha512-Aw7Fupk7XNehR1ftHGYwUteyJ2q+em/aE+fVU3YMTBN2V5A7Z4aVCSV+SvCp9HIIHZavPFBpbdP3VfjQpdf6Xg==
260 |
261 | "@esbuild/win32-x64@0.16.10":
262 | version "0.16.10"
263 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.10.tgz#0e9c6a5e69c10d96aff2386b7ee9646138c2a831"
264 | integrity sha512-qddWullt3sC1EIpfHvCRBq3H4g3L86DZpD6n8k2XFjFVyp01D++uNbN1hT/JRsHxTbyyemZcpwL5aRlJwc/zFw==
265 |
266 | "@types/web-bluetooth@^0.0.16":
267 | version "0.0.16"
268 | resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8"
269 | integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==
270 |
271 | "@vitejs/plugin-vue@^4.0.0":
272 | version "4.0.0"
273 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz#93815beffd23db46288c787352a8ea31a0c03e5e"
274 | integrity sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==
275 |
276 | "@vue/compiler-core@3.2.45":
277 | version "3.2.45"
278 | resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.45.tgz#d9311207d96f6ebd5f4660be129fb99f01ddb41b"
279 | integrity sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==
280 | dependencies:
281 | "@babel/parser" "^7.16.4"
282 | "@vue/shared" "3.2.45"
283 | estree-walker "^2.0.2"
284 | source-map "^0.6.1"
285 |
286 | "@vue/compiler-dom@3.2.45":
287 | version "3.2.45"
288 | resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz#c43cc15e50da62ecc16a42f2622d25dc5fd97dce"
289 | integrity sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==
290 | dependencies:
291 | "@vue/compiler-core" "3.2.45"
292 | "@vue/shared" "3.2.45"
293 |
294 | "@vue/compiler-sfc@3.2.45":
295 | version "3.2.45"
296 | resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz#7f7989cc04ec9e7c55acd406827a2c4e96872c70"
297 | integrity sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==
298 | dependencies:
299 | "@babel/parser" "^7.16.4"
300 | "@vue/compiler-core" "3.2.45"
301 | "@vue/compiler-dom" "3.2.45"
302 | "@vue/compiler-ssr" "3.2.45"
303 | "@vue/reactivity-transform" "3.2.45"
304 | "@vue/shared" "3.2.45"
305 | estree-walker "^2.0.2"
306 | magic-string "^0.25.7"
307 | postcss "^8.1.10"
308 | source-map "^0.6.1"
309 |
310 | "@vue/compiler-ssr@3.2.45":
311 | version "3.2.45"
312 | resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz#bd20604b6e64ea15344d5b6278c4141191c983b2"
313 | integrity sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==
314 | dependencies:
315 | "@vue/compiler-dom" "3.2.45"
316 | "@vue/shared" "3.2.45"
317 |
318 | "@vue/devtools-api@^6.4.5":
319 | version "6.4.5"
320 | resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.4.5.tgz#d54e844c1adbb1e677c81c665ecef1a2b4bb8380"
321 | integrity sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==
322 |
323 | "@vue/reactivity-transform@3.2.45":
324 | version "3.2.45"
325 | resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz#07ac83b8138550c83dfb50db43cde1e0e5e8124d"
326 | integrity sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==
327 | dependencies:
328 | "@babel/parser" "^7.16.4"
329 | "@vue/compiler-core" "3.2.45"
330 | "@vue/shared" "3.2.45"
331 | estree-walker "^2.0.2"
332 | magic-string "^0.25.7"
333 |
334 | "@vue/reactivity@3.2.45":
335 | version "3.2.45"
336 | resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.45.tgz#412a45b574de601be5a4a5d9a8cbd4dee4662ff0"
337 | integrity sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==
338 | dependencies:
339 | "@vue/shared" "3.2.45"
340 |
341 | "@vue/runtime-core@3.2.45":
342 | version "3.2.45"
343 | resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.45.tgz#7ad7ef9b2519d41062a30c6fa001ec43ac549c7f"
344 | integrity sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==
345 | dependencies:
346 | "@vue/reactivity" "3.2.45"
347 | "@vue/shared" "3.2.45"
348 |
349 | "@vue/runtime-dom@3.2.45":
350 | version "3.2.45"
351 | resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz#1a2ef6ee2ad876206fbbe2a884554bba2d0faf59"
352 | integrity sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==
353 | dependencies:
354 | "@vue/runtime-core" "3.2.45"
355 | "@vue/shared" "3.2.45"
356 | csstype "^2.6.8"
357 |
358 | "@vue/server-renderer@3.2.45":
359 | version "3.2.45"
360 | resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.45.tgz#ca9306a0c12b0530a1a250e44f4a0abac6b81f3f"
361 | integrity sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==
362 | dependencies:
363 | "@vue/compiler-ssr" "3.2.45"
364 | "@vue/shared" "3.2.45"
365 |
366 | "@vue/shared@3.2.45":
367 | version "3.2.45"
368 | resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.45.tgz#a3fffa7489eafff38d984e23d0236e230c818bc2"
369 | integrity sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==
370 |
371 | "@vueuse/core@^9.8.2":
372 | version "9.8.2"
373 | resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-9.8.2.tgz#a142281bb33368c74668a180a813c7c8d91f89d8"
374 | integrity sha512-aWiCmcYIpPt7xjuqYiceODEMHchDYthrJ4AqI+FXPZrR23PZOqdiktbUVyQl2kGlR3H4i9UJ/uimQrwhz9UouQ==
375 | dependencies:
376 | "@types/web-bluetooth" "^0.0.16"
377 | "@vueuse/metadata" "9.8.2"
378 | "@vueuse/shared" "9.8.2"
379 | vue-demi "*"
380 |
381 | "@vueuse/metadata@9.8.2":
382 | version "9.8.2"
383 | resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-9.8.2.tgz#864905e351a88165717c66d35d4b59a84bed2ae1"
384 | integrity sha512-N4E/BKS+9VsUeD4WLVRU1J2kCOLh+iikBcMtipFcTyL204132vDYHs27zLAVabJYGnhC0dIVGdhg9pbOZiY2TQ==
385 |
386 | "@vueuse/shared@9.8.2":
387 | version "9.8.2"
388 | resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-9.8.2.tgz#fd05866e5626218c9b0758b0422c666676cc4559"
389 | integrity sha512-ACjrPQzowd5dnabNJt9EoGVobco9/ENiA5qP53vjiuxndlJYuc/UegwhXC7KdQbPX4F45a50+45K3g1wNqOzmA==
390 | dependencies:
391 | vue-demi "*"
392 |
393 | algoliasearch@^4.0.0:
394 | version "4.14.3"
395 | resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.3.tgz#f02a77a4db17de2f676018938847494b692035e7"
396 | integrity sha512-GZTEuxzfWbP/vr7ZJfGzIl8fOsoxN916Z6FY2Egc9q2TmZ6hvq5KfAxY89pPW01oW/2HDEKA8d30f9iAH9eXYg==
397 | dependencies:
398 | "@algolia/cache-browser-local-storage" "4.14.3"
399 | "@algolia/cache-common" "4.14.3"
400 | "@algolia/cache-in-memory" "4.14.3"
401 | "@algolia/client-account" "4.14.3"
402 | "@algolia/client-analytics" "4.14.3"
403 | "@algolia/client-common" "4.14.3"
404 | "@algolia/client-personalization" "4.14.3"
405 | "@algolia/client-search" "4.14.3"
406 | "@algolia/logger-common" "4.14.3"
407 | "@algolia/logger-console" "4.14.3"
408 | "@algolia/requester-browser-xhr" "4.14.3"
409 | "@algolia/requester-common" "4.14.3"
410 | "@algolia/requester-node-http" "4.14.3"
411 | "@algolia/transporter" "4.14.3"
412 |
413 | body-scroll-lock@4.0.0-beta.0:
414 | version "4.0.0-beta.0"
415 | resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz#4f78789d10e6388115c0460cd6d7d4dd2bbc4f7e"
416 | integrity sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==
417 |
418 | csstype@^2.6.8:
419 | version "2.6.21"
420 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
421 | integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
422 |
423 | esbuild@^0.16.3:
424 | version "0.16.10"
425 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.10.tgz#d485c28f1626a3f9c1796c952e4cd0561f0031bb"
426 | integrity sha512-z5dIViHoVnw2l+NCJ3zj5behdXjYvXne9gL18OOivCadXDUhyDkeSvEtLcGVAJW2fNmh33TDUpsi704XYlDodw==
427 | optionalDependencies:
428 | "@esbuild/android-arm" "0.16.10"
429 | "@esbuild/android-arm64" "0.16.10"
430 | "@esbuild/android-x64" "0.16.10"
431 | "@esbuild/darwin-arm64" "0.16.10"
432 | "@esbuild/darwin-x64" "0.16.10"
433 | "@esbuild/freebsd-arm64" "0.16.10"
434 | "@esbuild/freebsd-x64" "0.16.10"
435 | "@esbuild/linux-arm" "0.16.10"
436 | "@esbuild/linux-arm64" "0.16.10"
437 | "@esbuild/linux-ia32" "0.16.10"
438 | "@esbuild/linux-loong64" "0.16.10"
439 | "@esbuild/linux-mips64el" "0.16.10"
440 | "@esbuild/linux-ppc64" "0.16.10"
441 | "@esbuild/linux-riscv64" "0.16.10"
442 | "@esbuild/linux-s390x" "0.16.10"
443 | "@esbuild/linux-x64" "0.16.10"
444 | "@esbuild/netbsd-x64" "0.16.10"
445 | "@esbuild/openbsd-x64" "0.16.10"
446 | "@esbuild/sunos-x64" "0.16.10"
447 | "@esbuild/win32-arm64" "0.16.10"
448 | "@esbuild/win32-ia32" "0.16.10"
449 | "@esbuild/win32-x64" "0.16.10"
450 |
451 | estree-walker@^2.0.2:
452 | version "2.0.2"
453 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
454 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
455 |
456 | fsevents@~2.3.2:
457 | version "2.3.2"
458 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
459 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
460 |
461 | function-bind@^1.1.1:
462 | version "1.1.1"
463 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
464 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
465 |
466 | has@^1.0.3:
467 | version "1.0.3"
468 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
469 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
470 | dependencies:
471 | function-bind "^1.1.1"
472 |
473 | is-core-module@^2.9.0:
474 | version "2.11.0"
475 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
476 | integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
477 | dependencies:
478 | has "^1.0.3"
479 |
480 | jsonc-parser@^3.2.0:
481 | version "3.2.0"
482 | resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
483 | integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==
484 |
485 | magic-string@^0.25.7:
486 | version "0.25.9"
487 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
488 | integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
489 | dependencies:
490 | sourcemap-codec "^1.4.8"
491 |
492 | nanoid@^3.3.4:
493 | version "3.3.4"
494 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
495 | integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
496 |
497 | path-parse@^1.0.7:
498 | version "1.0.7"
499 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
500 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
501 |
502 | picocolors@^1.0.0:
503 | version "1.0.0"
504 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
505 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
506 |
507 | postcss@^8.1.10, postcss@^8.4.20:
508 | version "8.4.20"
509 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56"
510 | integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==
511 | dependencies:
512 | nanoid "^3.3.4"
513 | picocolors "^1.0.0"
514 | source-map-js "^1.0.2"
515 |
516 | preact@^10.0.0:
517 | version "10.11.3"
518 | resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19"
519 | integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==
520 |
521 | resolve@^1.22.1:
522 | version "1.22.1"
523 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
524 | integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
525 | dependencies:
526 | is-core-module "^2.9.0"
527 | path-parse "^1.0.7"
528 | supports-preserve-symlinks-flag "^1.0.0"
529 |
530 | rollup@^3.7.0:
531 | version "3.8.0"
532 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.8.0.tgz#f61dc3ae02467d842687bd55b17a047c93b456ad"
533 | integrity sha512-+UR6PnUslneJNiJfLSzy4XH6R50ZGF0MS7UCv20ftXrktF/TkvZDwiBtXX65esblLR5p8w6LmXgPwt2f2B8SoQ==
534 | optionalDependencies:
535 | fsevents "~2.3.2"
536 |
537 | shiki@^0.12.1:
538 | version "0.12.1"
539 | resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.12.1.tgz#26fce51da12d055f479a091a5307470786f300cd"
540 | integrity sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==
541 | dependencies:
542 | jsonc-parser "^3.2.0"
543 | vscode-oniguruma "^1.7.0"
544 | vscode-textmate "^8.0.0"
545 |
546 | source-map-js@^1.0.2:
547 | version "1.0.2"
548 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
549 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
550 |
551 | source-map@^0.6.1:
552 | version "0.6.1"
553 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
554 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
555 |
556 | sourcemap-codec@^1.4.8:
557 | version "1.4.8"
558 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
559 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
560 |
561 | supports-preserve-symlinks-flag@^1.0.0:
562 | version "1.0.0"
563 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
564 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
565 |
566 | vite@^4.0.2:
567 | version "4.0.3"
568 | resolved "https://registry.yarnpkg.com/vite/-/vite-4.0.3.tgz#de27ad3f263a03ae9419cdc8bc07721eadcba8b9"
569 | integrity sha512-HvuNv1RdE7deIfQb8mPk51UKjqptO/4RXZ5yXSAvurd5xOckwS/gg8h9Tky3uSbnjYTgUm0hVCet1cyhKd73ZA==
570 | dependencies:
571 | esbuild "^0.16.3"
572 | postcss "^8.4.20"
573 | resolve "^1.22.1"
574 | rollup "^3.7.0"
575 | optionalDependencies:
576 | fsevents "~2.3.2"
577 |
578 | vitepress@^1.0.0-alpha.33:
579 | version "1.0.0-alpha.33"
580 | resolved "https://registry.yarnpkg.com/vitepress/-/vitepress-1.0.0-alpha.33.tgz#5002ce435ad98b8e0c259e9df7770542bb3676c3"
581 | integrity sha512-EhMDqWLllYr5mXqAz4GCQ1o/bu5umQ6C2d8voiSaTHMkYCxsGc31ETykflM6NOhGx6yccwXygrYIIeN1l6BUEA==
582 | dependencies:
583 | "@docsearch/css" "^3.3.0"
584 | "@docsearch/js" "^3.3.0"
585 | "@vitejs/plugin-vue" "^4.0.0"
586 | "@vue/devtools-api" "^6.4.5"
587 | "@vueuse/core" "^9.8.2"
588 | body-scroll-lock "4.0.0-beta.0"
589 | shiki "^0.12.1"
590 | vite "^4.0.2"
591 | vue "^3.2.45"
592 |
593 | vscode-oniguruma@^1.7.0:
594 | version "1.7.0"
595 | resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b"
596 | integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==
597 |
598 | vscode-textmate@^8.0.0:
599 | version "8.0.0"
600 | resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d"
601 | integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==
602 |
603 | vue-demi@*:
604 | version "0.13.11"
605 | resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
606 | integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
607 |
608 | vue@^3.2.45:
609 | version "3.2.45"
610 | resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.45.tgz#94a116784447eb7dbd892167784619fef379b3c8"
611 | integrity sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==
612 | dependencies:
613 | "@vue/compiler-dom" "3.2.45"
614 | "@vue/compiler-sfc" "3.2.45"
615 | "@vue/runtime-dom" "3.2.45"
616 | "@vue/server-renderer" "3.2.45"
617 | "@vue/shared" "3.2.45"
618 |
--------------------------------------------------------------------------------