Initial commit
This commit is contained in:
28
docs/Commands/index.md
Normal file
28
docs/Commands/index.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Commands
|
||||
|
||||
```
|
||||
Description:
|
||||
The MycroForge CLI tool.
|
||||
|
||||
Usage:
|
||||
m4g [command] [options]
|
||||
|
||||
Options:
|
||||
--version Show version information
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
init <name> Initialize a new project
|
||||
i, install <packages> Install packages and update the requirements.txt
|
||||
u, uninstall <packages> Uninstall packages and update the requirements.txt
|
||||
hydrate Initialize venv and install dependencies from requirements.txt
|
||||
add Add features to the project
|
||||
g, generate Generate common items
|
||||
api API related commands
|
||||
db Database related commands
|
||||
p, plugin Plugin related commands
|
||||
```
|
||||
22
docs/Commands/m4g_add/index.md
Normal file
22
docs/Commands/m4g_add/index.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g add
|
||||
|
||||
```
|
||||
Description:
|
||||
Add features to the project
|
||||
|
||||
Usage:
|
||||
m4g add [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
api Add FastAPI to the project
|
||||
db Add SQLAlchemy & Alembic to the project
|
||||
git Add git to the project
|
||||
gitignore Add a default .gitignore file to the project
|
||||
```
|
||||
17
docs/Commands/m4g_add/m4g_add_api.md
Normal file
17
docs/Commands/m4g_add/m4g_add_api.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g add api
|
||||
|
||||
```
|
||||
Description:
|
||||
Add FastAPI to the project
|
||||
|
||||
Usage:
|
||||
m4g add api [options]
|
||||
|
||||
Options:
|
||||
--api-port <api-port> The API port
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
19
docs/Commands/m4g_add/m4g_add_db.md
Normal file
19
docs/Commands/m4g_add/m4g_add_db.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g add db
|
||||
|
||||
```
|
||||
Description:
|
||||
Add SQLAlchemy & Alembic to the project
|
||||
|
||||
Usage:
|
||||
m4g add db [options]
|
||||
|
||||
Options:
|
||||
--database-host-port, --dbh-port <database-host-port> The database host port
|
||||
--database-ui-port, --dbu-port <database-ui-port> The database UI port
|
||||
--database-ui-platform, --dbu-platform <linux_amd64|linux_arm32v5|linux_arm32v6|linux_arm32v7|linux_arm64v8> The docker platform for the PhpMyAdmin image
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_add/m4g_add_git.md
Normal file
16
docs/Commands/m4g_add/m4g_add_git.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g add git
|
||||
|
||||
```
|
||||
Description:
|
||||
Add git to the project
|
||||
|
||||
Usage:
|
||||
m4g add git [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_add/m4g_add_gitignore.md
Normal file
16
docs/Commands/m4g_add/m4g_add_gitignore.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g add gitignore
|
||||
|
||||
```
|
||||
Description:
|
||||
Add a default .gitignore file to the project
|
||||
|
||||
Usage:
|
||||
m4g add gitignore [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
20
docs/Commands/m4g_api/index.md
Normal file
20
docs/Commands/m4g_api/index.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g api
|
||||
|
||||
```
|
||||
Description:
|
||||
API related commands
|
||||
|
||||
Usage:
|
||||
m4g api [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
run Run your app
|
||||
g, generate Generate an API item
|
||||
```
|
||||
20
docs/Commands/m4g_api/m4g_api_generate/index.md
Normal file
20
docs/Commands/m4g_api/m4g_api_generate/index.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g api generate
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate an API item
|
||||
|
||||
Usage:
|
||||
m4g api generate [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
r, router <name> Generate an api router
|
||||
crud <entity> Generated CRUD functionality for an entity
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g api generate crud
|
||||
|
||||
```
|
||||
Description:
|
||||
Generated CRUD functionality for an entity
|
||||
|
||||
Usage:
|
||||
m4g api generate crud <entity> [options]
|
||||
|
||||
Arguments:
|
||||
<entity> The entity to target
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g api generate router
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate an api router
|
||||
|
||||
Usage:
|
||||
m4g api generate router <name> [options]
|
||||
|
||||
Arguments:
|
||||
<name> The name of the api router
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_api/m4g_api_run.md
Normal file
16
docs/Commands/m4g_api/m4g_api_run.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g api run
|
||||
|
||||
```
|
||||
Description:
|
||||
Run your app
|
||||
|
||||
Usage:
|
||||
m4g api run [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
24
docs/Commands/m4g_db/index.md
Normal file
24
docs/Commands/m4g_db/index.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db
|
||||
|
||||
```
|
||||
Description:
|
||||
Database related commands
|
||||
|
||||
Usage:
|
||||
m4g db [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
run Runs the services defined in db.docker-compose.yml
|
||||
stop Stops db.docker-compose.yml
|
||||
migrate Apply migrations to the database
|
||||
rollback Rollback the last migration
|
||||
g, generate Generate a database item
|
||||
link Define relationships between entities
|
||||
```
|
||||
20
docs/Commands/m4g_db/m4g_db_generate/index.md
Normal file
20
docs/Commands/m4g_db/m4g_db_generate/index.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db generate
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate a database item
|
||||
|
||||
Usage:
|
||||
m4g db generate [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
e, entity <name> Generate and database entity
|
||||
m, migration <name> Generate a migration
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db generate entity
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate and database entity
|
||||
|
||||
Usage:
|
||||
m4g db generate entity <name> [options]
|
||||
|
||||
Arguments:
|
||||
<name> The name of the database entity
|
||||
|
||||
Supported formats:
|
||||
Entity
|
||||
path/relative/to/entities:Entity
|
||||
|
||||
Options:
|
||||
-c, --column <column> Specify the fields to add.
|
||||
|
||||
Format:
|
||||
<name>:<native_type>:<orm_type>
|
||||
|
||||
<name> = Name of the column
|
||||
<native_type> = The native Python type
|
||||
<orm_type> = The SQLAlchemy type
|
||||
|
||||
Example:
|
||||
first_name:str:String(255)
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db generate migration
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate a migration
|
||||
|
||||
Usage:
|
||||
m4g db generate migration <name> [options]
|
||||
|
||||
Arguments:
|
||||
<name> The name of the migration
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
21
docs/Commands/m4g_db/m4g_db_link/index.md
Normal file
21
docs/Commands/m4g_db/m4g_db_link/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db link
|
||||
|
||||
```
|
||||
Description:
|
||||
Define relationships between entities
|
||||
|
||||
Usage:
|
||||
m4g db link [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
one <entity> Define a 1:n relation
|
||||
many <entity> Define a n:m relation
|
||||
|
||||
```
|
||||
21
docs/Commands/m4g_db/m4g_db_link/m4g_db_link_many.md
Normal file
21
docs/Commands/m4g_db/m4g_db_link/m4g_db_link_many.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db link many
|
||||
|
||||
```
|
||||
Description:
|
||||
Define a n:m relation
|
||||
|
||||
Usage:
|
||||
m4g db link many <entity> [options]
|
||||
|
||||
Arguments:
|
||||
<entity> The left side of the relation
|
||||
|
||||
Options:
|
||||
--to-one <to-one> The right side of the relation
|
||||
--to-many <to-many> The right side of the relation
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
21
docs/Commands/m4g_db/m4g_db_link/m4g_db_link_one.md
Normal file
21
docs/Commands/m4g_db/m4g_db_link/m4g_db_link_one.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db link one
|
||||
|
||||
```
|
||||
Description:
|
||||
Define a 1:n relation
|
||||
|
||||
Usage:
|
||||
m4g db link one <entity> [options]
|
||||
|
||||
Arguments:
|
||||
<entity> The left side of the relation
|
||||
|
||||
Options:
|
||||
--to-one <to-one> The right side of the relation
|
||||
--to-many <to-many> The right side of the relation
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_db/m4g_db_migrate.md
Normal file
16
docs/Commands/m4g_db/m4g_db_migrate.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db migrate
|
||||
|
||||
```
|
||||
Description:
|
||||
Apply migrations to the database
|
||||
|
||||
Usage:
|
||||
m4g db migrate [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_db/m4g_db_rollback.md
Normal file
16
docs/Commands/m4g_db/m4g_db_rollback.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db rollback
|
||||
|
||||
```
|
||||
Description:
|
||||
Rollback the last migration
|
||||
|
||||
Usage:
|
||||
m4g db rollback [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_db/m4g_db_run.md
Normal file
16
docs/Commands/m4g_db/m4g_db_run.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db run
|
||||
|
||||
```
|
||||
Description:
|
||||
Runs the services defined in db.docker-compose.yml
|
||||
|
||||
Usage:
|
||||
m4g db run [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_db/m4g_db_stop.md
Normal file
16
docs/Commands/m4g_db/m4g_db_stop.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g db stop
|
||||
|
||||
```
|
||||
Description:
|
||||
Stops db.docker-compose.yml
|
||||
|
||||
Usage:
|
||||
m4g db stop [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
20
docs/Commands/m4g_generate/index.md
Normal file
20
docs/Commands/m4g_generate/index.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g generate
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate common items
|
||||
|
||||
Usage:
|
||||
m4g generate [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
s, service <name> Generate a service
|
||||
venv Generate a venv
|
||||
```
|
||||
20
docs/Commands/m4g_generate/m4g_generate_service.md
Normal file
20
docs/Commands/m4g_generate/m4g_generate_service.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g generate service
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate a service
|
||||
|
||||
Usage:
|
||||
m4g generate service <name> [options]
|
||||
|
||||
Arguments:
|
||||
<name> The name of the service
|
||||
|
||||
Options:
|
||||
--with-session Create a service that uses database sessions
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_generate/m4g_generate_vend.md
Normal file
16
docs/Commands/m4g_generate/m4g_generate_vend.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g generate venv
|
||||
|
||||
```
|
||||
Description:
|
||||
Generate a venv
|
||||
|
||||
Usage:
|
||||
m4g generate venv [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_hydrate.md
Normal file
16
docs/Commands/m4g_hydrate.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g hydrate
|
||||
|
||||
```
|
||||
Description:
|
||||
Initialize venv and install dependencies from requirements.txt
|
||||
|
||||
Usage:
|
||||
m4g hydrate [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
24
docs/Commands/m4g_init.md
Normal file
24
docs/Commands/m4g_init.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g init
|
||||
|
||||
```
|
||||
Description:
|
||||
Initialize a new project
|
||||
|
||||
Usage:
|
||||
m4g init <name> [options]
|
||||
|
||||
Arguments:
|
||||
<name> The name of your project
|
||||
|
||||
Options:
|
||||
--without <api|db|git|gitignore> Features to exclude
|
||||
--api-port <api-port> The API port
|
||||
--database-host-port, --dbh-port <database-host-port> The database host port
|
||||
--database-ui-port, --dbu-port <database-ui-port> The database UI port
|
||||
--database-ui-platform, --dbu-platform <amd64|arm32v5|arm32v6|arm32v7|arm64v8> The docker platform for the PhpMyAdmin image
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
19
docs/Commands/m4g_install.md
Normal file
19
docs/Commands/m4g_install.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g install
|
||||
|
||||
```
|
||||
Description:
|
||||
Install packages and update the requirements.txt
|
||||
|
||||
Usage:
|
||||
m4g install [<packages>...] [options]
|
||||
|
||||
Arguments:
|
||||
<packages> The names of the packages to install
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
22
docs/Commands/m4g_plugin/index.md
Normal file
22
docs/Commands/m4g_plugin/index.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g plugin
|
||||
|
||||
```
|
||||
Description:
|
||||
Plugin related commands
|
||||
|
||||
Usage:
|
||||
m4g plugin [command] [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
|
||||
Commands:
|
||||
init <name> Initialize a basic plugin project
|
||||
l, list, ls List all installed plugins
|
||||
i, install Install a plugin
|
||||
u, uninstall <name> Uninstall a plugin
|
||||
```
|
||||
19
docs/Commands/m4g_plugin/m4g_plugin_init.md
Normal file
19
docs/Commands/m4g_plugin/m4g_plugin_init.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g plugin init
|
||||
|
||||
```
|
||||
Description:
|
||||
Initialize a basic plugin project
|
||||
|
||||
Usage:
|
||||
m4g plugin init <name> [options]
|
||||
|
||||
Arguments:
|
||||
<name> The name of your project
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
17
docs/Commands/m4g_plugin/m4g_plugin_install.md
Normal file
17
docs/Commands/m4g_plugin/m4g_plugin_install.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g plugin install
|
||||
|
||||
```
|
||||
Description:
|
||||
Install a plugin
|
||||
|
||||
Usage:
|
||||
m4g plugin install [options]
|
||||
|
||||
Options:
|
||||
-p, --platform <linux_arm|linux_arm64|linux_x64|osx_arm64|osx_x64> (REQUIRED) The platform to target when building the plugin
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
16
docs/Commands/m4g_plugin/m4g_plugin_list.md
Normal file
16
docs/Commands/m4g_plugin/m4g_plugin_list.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g plugin list
|
||||
|
||||
```
|
||||
Description:
|
||||
List all installed plugins
|
||||
|
||||
Usage:
|
||||
m4g plugin list [options]
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
19
docs/Commands/m4g_plugin/m4g_plugin_uninstall.md
Normal file
19
docs/Commands/m4g_plugin/m4g_plugin_uninstall.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g plugin uninstall
|
||||
|
||||
```
|
||||
Description:
|
||||
Uninstall a plugin
|
||||
|
||||
Usage:
|
||||
m4g plugin uninstall [<name>...] [options]
|
||||
|
||||
Arguments:
|
||||
<name> The names of the plugins you want to uninstall
|
||||
|
||||
Options:
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
20
docs/Commands/m4g_uninstall.md
Normal file
20
docs/Commands/m4g_uninstall.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# m4g uninstall
|
||||
|
||||
```
|
||||
Description:
|
||||
Uninstall packages and update the requirements.txt
|
||||
|
||||
Usage:
|
||||
m4g uninstall [<packages>...] [options]
|
||||
|
||||
Arguments:
|
||||
<packages> The names of the packages to uninstall
|
||||
|
||||
Options:
|
||||
-y, --yes Don’t ask for confirmation of uninstall deletions
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
178
docs/command_plugins.md
Normal file
178
docs/command_plugins.md
Normal file
@@ -0,0 +1,178 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Command plugins
|
||||
|
||||
MycroForge has a plugin system that allows you to extend the CLI with your own commands.
|
||||
This section will guide you through the process of creating your own extension to the `m4g` command.
|
||||
MycroForge is written in C# sharp and this is the same for plugins, so decent knowledge about `C#` & `.NET` is required.
|
||||
In this tutorial we will create a command plugin that extens the `m4g` command with a `dotenv` sub command.
|
||||
What this command will do is generate a `.env` file in the current directory and print a message to the console.
|
||||
|
||||
## Setup
|
||||
|
||||
To start creating command plugins for MycroFroge, make sure you've added the devdisciples package repository.
|
||||
This can be done by running the following command.
|
||||
|
||||
```
|
||||
dotnet nuget add source --name devdisciples https://git.devdisciples.com/api/packages/devdisciples/nuget/index.json
|
||||
```
|
||||
|
||||
Run the following command to add the `MycroForge.PluginTemplate.Package`.
|
||||
|
||||
```
|
||||
dotnet add package --source devdisciples --version 1.0.0 MycroForge.PluginTemplate.Package
|
||||
```
|
||||
|
||||
## Initialize a plugin package
|
||||
|
||||
Generate a template plugin project by running the following command.
|
||||
|
||||
```
|
||||
m4g plugin init My.Dotenv.Plugin
|
||||
```
|
||||
|
||||
This should generate the following folder structure.
|
||||
|
||||
```
|
||||
My.Dotenv.Plugin
|
||||
┣ 📜HelloWorldCommand.cs
|
||||
┣ 📜HelloWorldCommandPlugin.cs
|
||||
┗ 📜My.Dotenv.Plugin.csproj
|
||||
```
|
||||
|
||||
Rename the following files. Also rename the classes in these files, the easiest way in `vscode` is to right click the class name and select the `Rename symbol` action. Note that this action does not (necessarily) rename the files!
|
||||
|
||||
```
|
||||
HelloWorldCommand.cs => DotenvCommand.cs
|
||||
HelloWorldCommandPlugin.cs => DotenvCommandPlugin.cs
|
||||
```
|
||||
|
||||
Modify `Name` property in `DotenvCommandPlugin.cs`.
|
||||
|
||||
```cs
|
||||
// Before
|
||||
public class DotenvCommandPlugin : ICommandPlugin
|
||||
{
|
||||
public string Name => "My.Plugin";
|
||||
|
||||
public void RegisterServices(IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<ISubCommandOf<RootCommand>, HelloWorldCommand>();
|
||||
}
|
||||
}
|
||||
|
||||
// After
|
||||
public class DotenvCommandPlugin : ICommandPlugin
|
||||
{
|
||||
public string Name => "My.Dotenv.Plugin";
|
||||
|
||||
public void RegisterServices(IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<ISubCommandOf<RootCommand>, HelloWorldCommand>();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Modify `DotenvCommand.cs`.
|
||||
|
||||
```cs
|
||||
// Before
|
||||
public class DotenvCommand : Command, ISubCommandOf<RootCommand>
|
||||
{
|
||||
private readonly Argument<string> NameArgument =
|
||||
new(name: "name", description: "The name of the person to greet");
|
||||
|
||||
private readonly Option<bool> AllCapsOption =
|
||||
new(aliases: ["-a", "--all-caps"], description: "Print the name in all caps");
|
||||
|
||||
private readonly ProjectContext _context;
|
||||
|
||||
public DotenvCommand(ProjectContext context) :
|
||||
base("hello", "An example command generated by dotnet new using the m4gp template")
|
||||
{
|
||||
_context = context;
|
||||
AddArgument(NameArgument);
|
||||
AddOption(AllCapsOption);
|
||||
this.SetHandler(ExecuteAsync, NameArgument, AllCapsOption);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(string name, bool allCaps)
|
||||
{
|
||||
name = allCaps ? name.ToUpper() : name;
|
||||
|
||||
await _context.CreateFile("hello_world.txt",
|
||||
$"Hello {name}!",
|
||||
"This file was generated by your custom command!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// After
|
||||
public class DotenvCommand : Command, ISubCommandOf<RootCommand>
|
||||
{
|
||||
private readonly Argument<string> VarsArgument =
|
||||
new(name: "vars", description: "Env vars to include in the .env file separated by ';'");
|
||||
|
||||
private readonly Option<bool> PrintOption =
|
||||
new(aliases: ["-o", "--overwrite"], description: "Overwrite the .env file if it exists");
|
||||
|
||||
private readonly ProjectContext _context;
|
||||
|
||||
public DotenvCommand(ProjectContext context) :
|
||||
// dotenv = the name of the sub command that will be added to the m4g command
|
||||
base("dotenv", "Generate a .env file in the current directory")
|
||||
{
|
||||
_context = context;
|
||||
AddArgument(VarsArgument);
|
||||
AddOption(PrintOption);
|
||||
this.SetHandler(ExecuteAsync, VarsArgument, PrintOption);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(string vars, bool overwrite)
|
||||
{
|
||||
var path = Path.Join(Environment.CurrentDirectory, ".env");
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
if (overwrite)
|
||||
{
|
||||
await _context.WriteFile(".env", content);
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"File {path} already exists, add the -o or --overwrite flag to overwrite it.");
|
||||
}
|
||||
|
||||
var content = string.Join(Environment.NewLine, vars.Split(';'));
|
||||
await _context.CreateFile(".env", content);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Install the plugin
|
||||
|
||||
Open a terminal an make sure you're in the root directory of the plugin, i.e. the `My.Dotenv.Plugin` folder.
|
||||
Run the following command to install the plugin.
|
||||
|
||||
```
|
||||
m4g plugin install --platform <platform=linux_arm|linux_arm64|linux_x64|osx_arm64|osx_x64>
|
||||
```
|
||||
|
||||
Make sure to choose the right platform option for your machine.
|
||||
If everything went well then running `m4g` should now also show a `dotenv` command.
|
||||
|
||||
## Test the plugin
|
||||
|
||||
Try running `m4g dotenv "FIRSTNAME=JOHN;LASTNAME=JOE"`, this should generate a `.env` in the current directory with the vars you specified.
|
||||
|
||||
## Uninstall the plugin
|
||||
|
||||
Uninstall the plugin by running `m4g plugin install My.Dotenv.Plugin`.
|
||||
|
||||
## Resources
|
||||
|
||||
For examples of how the core commands are implemented, you can take a look at the commands in the [MycroForge.CLI.Commands](https://git.devdisciples.com/devdisciples/mycroforge/src/branch/main/MycroForge.CLI/Commands) namespace.
|
||||
|
||||
The MycroForge.CLI project uses [SystemCommand.Line](https://learn.microsoft.com/en-us/dotnet/standard/commandline/get-started-tutorial) for the CLI support, check out the Microsoft documentation for more info.
|
||||
78
docs/getting_started.md
Normal file
78
docs/getting_started.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Getting Started
|
||||
|
||||
## Requirements
|
||||
|
||||
To use MycroForge, ensure you have the following dependencies installed:
|
||||
|
||||
- [**bash**](https://www.gnu.org/software/bash/)
|
||||
- [**git**](https://git-scm.com/)
|
||||
- [**Python 3.10**](https://www.python.org/downloads/release/python-3100/)
|
||||
- [**Docker**](https://www.docker.com/)
|
||||
- [**.NET 8**](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||
- [**XCode Command Line Tools (MacOS only)**](https://mac.install.guide/commandlinetools/)
|
||||
|
||||
## Prior knowledge
|
||||
|
||||
Since this tool is meant to generate FastAPI & SQLAlchemy code, you should have decent knowledge of both frameworks. If not, then please follow the links below to learn more about them.
|
||||
- [FastAPI](https://fastapi.tiangolo.com/)
|
||||
- [SQLAlchemy](https://www.sqlalchemy.org/)
|
||||
|
||||
### Adding the Package Registry
|
||||
|
||||
Before installing MycroForge, add the package registry by running the following command:
|
||||
|
||||
```
|
||||
dotnet nuget add source --name devdisciples https://git.devdisciples.com/api/packages/devdisciples/nuget/index.json
|
||||
```
|
||||
|
||||
### Install
|
||||
|
||||
```
|
||||
dotnet tool install -g MycroForge.CLI
|
||||
```
|
||||
|
||||
### Uninstall
|
||||
|
||||
```
|
||||
dotnet tool install -g MycroForge.CLI
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
MycroForge is designed to run in a POSIX compliant environment. It has been tested on Windows using WSL2 with Ubuntu 22.04.03. So it is recommended to run MycroForge within the same or a similar WSL2 distribution for optimal performance.
|
||||
|
||||
### MacOS
|
||||
|
||||
#### Post install steps
|
||||
After installing MycroForge, the dotnet CLI will show a message with some instructions to make the `m4g` command available in `zsh`.
|
||||
It should look similar to the example below.
|
||||
|
||||
```sh
|
||||
Tools directory '/Users/username/.dotnet/tools' is not currently on the PATH environment variable.
|
||||
If you are using zsh, you can add it to your profile by running the following command:
|
||||
|
||||
cat << \EOF >> ~/.zprofile
|
||||
# Add .NET Core SDK tools
|
||||
export PATH="$PATH:/Users/username/.dotnet/tools"
|
||||
EOF
|
||||
|
||||
And run zsh -l to make it available for current session.
|
||||
|
||||
You can only add it to the current session by running the following command:
|
||||
|
||||
export PATH="$PATH:/Users/username/.dotnet/tools"
|
||||
```
|
||||
|
||||
### Known issues
|
||||
|
||||
#### FastAPI swagger blank screen (MacOS only)
|
||||
|
||||
If you see a blank screen when opening the FastAPI Swagger documentation, then make sure you've activated the Safari developer tools.
|
||||
|
||||
#### Database container doesn't start after running `m4g db run`
|
||||
|
||||
If the database, i.e. the mariadb container, doesn't successfully start after running `m4g db run` the first time, then try running it again. This often works, but yeah...it's hacky. However, at the time of writing it's unknown what causes this.
|
||||
16
docs/intro.md
Normal file
16
docs/intro.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
|
||||
# Intro
|
||||
|
||||
Welcome to **MycroForge** – an opinionated CLI tool designed to streamline the development of FastAPI and SQLAlchemy-based backends. With MycroForge, you can effortlessly create backend projects through a convenient command line interface.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Project Skeleton Generation:** Quickly generate a well-structured project skeleton tailored for FastAPI and SQLAlchemy, ensuring you start with best practices.
|
||||
- **Database Entities:** Easily create and manage database entities, simplifying your database interactions.
|
||||
- **Migrations:** Handle database migrations seamlessly, allowing for smooth transitions and updates.
|
||||
- **Routers:** Generate and manage routers to keep your application modular and organized.
|
||||
- **CRUD Functionality:** Automatically generate basic CRUD (Create, Read, Update, Delete) operations to accelerate your development process.
|
||||
111
docs/project_layout.md
Normal file
111
docs/project_layout.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Project layout
|
||||
|
||||
When you generate a new project with `m4g init <project_name>`, it will create a folder like the example below.
|
||||
|
||||
```
|
||||
📦<project_name>
|
||||
┣ 📂.git
|
||||
┣ 📂.venv
|
||||
┣ 📂api
|
||||
┃ ┗ 📂routers
|
||||
┃ ┃ ┗ 📜hello.py
|
||||
┣ 📂db
|
||||
┃ ┣ 📂engine
|
||||
┃ ┃ ┗ 📜async_session.py
|
||||
┃ ┣ 📂entities
|
||||
┃ ┃ ┗ 📜entity_base.py
|
||||
┃ ┣ 📂versions
|
||||
┃ ┣ 📜README
|
||||
┃ ┣ 📜env.py
|
||||
┃ ┣ 📜script.py.mako
|
||||
┃ ┗ 📜settings.py
|
||||
┣ 📜.gitignore
|
||||
┣ 📜alembic.ini
|
||||
┣ 📜db.docker-compose.yml
|
||||
┣ 📜m4g.json
|
||||
┣ 📜main.py
|
||||
┗ 📜requirements.txt
|
||||
```
|
||||
|
||||
Let's go through these one by one.
|
||||
|
||||
### .git
|
||||
|
||||
The `m4g init` command will initialize new projects with git by default.
|
||||
If you don't want to use git you can pass the option `--without git` to `m4g init`.
|
||||
|
||||
### .venv
|
||||
|
||||
To promote isolation of Python dependencies, new projects are initialized with a virtual environment by default.
|
||||
When you clone a MycroForge repository from git, it won't have a `.venv` folder yet.
|
||||
You can run `m4g hydrate` in the root folder of the project to restore the dependencies.
|
||||
|
||||
### api/routers/hello.py
|
||||
|
||||
This file defines a basic example router, which is imported and mapped in `main.py`. This router is just an example and
|
||||
can be removed or modified at you discretion.
|
||||
|
||||
### db/engine/async_session.py
|
||||
|
||||
This file defines the `async_session` function, which can be used to open an asynchronous session to a database.
|
||||
|
||||
### db/entities/entity_base.py
|
||||
|
||||
This file contains an automatically generated entity base class that derives from the DeclarativeBase.
|
||||
All entities must inherit from this class, so that SQLAlchemy & alembic can track them. The entities directory is also
|
||||
where all newly generated entities will be stored.
|
||||
|
||||
### db/versions
|
||||
|
||||
This is where the generated database migrations will be stored.
|
||||
|
||||
### db/README
|
||||
|
||||
This README file is automatically generated by the alembic init command.
|
||||
|
||||
### db/env.py
|
||||
|
||||
This is the database environment file that is used by alembic to interact with the database.
|
||||
If you take a closer look at the imports, you'll see that the file has been modified to assign `EntityBase.metadata` to
|
||||
a variable called `target_metadata`, this will allow alembic to track changes in your entities. You'll also find that
|
||||
the `DbSettings` class is used to get the connectionstring. Any time you generate a new database entity, or create a
|
||||
many-to-many relation between two entities, this file will also be modified to include the generated classes.
|
||||
|
||||
### db/script.py.mako
|
||||
|
||||
This file is automatically generated by the alembic init command.
|
||||
|
||||
### db/settings.py
|
||||
|
||||
This file defines the `DbSettings` class, that is responsible for retrieving the database connectionstring.
|
||||
You will probably want to modify this class to retrieve the connectionstring from a secret manager at some point.
|
||||
|
||||
### .gitignore
|
||||
|
||||
The default .gitignore file that is generated by the `m4g init` command. Modify this file at your discretion.
|
||||
|
||||
### alembic.ini
|
||||
|
||||
This file is automatically generated by the alembic init command.
|
||||
|
||||
### db.docker-compose.yml
|
||||
|
||||
A docker compose file for running a database locally.
|
||||
|
||||
### m4g.json
|
||||
|
||||
This file contains some configs that are used by the CLI, for example the ports to map to the API and database.
|
||||
|
||||
### main.py
|
||||
|
||||
The entrypoint for the application. When generating entities, many-to-many relations or routers, this file will be
|
||||
modified to include the generated files.
|
||||
|
||||
### requirements.txt
|
||||
|
||||
The requirements file containing the Python dependencies.
|
||||
Whenever you run `m4g install` or `m4g uninstall` this file will be updated too.
|
||||
331
docs/tutorial.md
Normal file
331
docs/tutorial.md
Normal file
@@ -0,0 +1,331 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Tutorial
|
||||
|
||||
In this tutorial, we'll build a simple todo app to demonstrate the capabilities of the MycroForge CLI.
|
||||
By the end, you should have a solid foundation to start exploring and using MycroForge for your projects.
|
||||
|
||||
## General notes
|
||||
|
||||
The commands in this tutorial assume that you are running them from the root directory of your MycroForge project.
|
||||
|
||||
## Initialize the Project
|
||||
|
||||
Open a terminal and navigate (`cd`) to the directory where your project should be created.
|
||||
Run the following command to initialize a new project and open it in VSCode:
|
||||
|
||||
```bash
|
||||
m4g init todo-app
|
||||
```
|
||||
|
||||
## Setup the database
|
||||
|
||||
Our todo app needs to keep track of todos, so it needs a storage mechanism of some sorts. A database should be one
|
||||
of the first things, if not THE first thing, that comes to mind. Luckily, MycroForge provides you with a locally hosted
|
||||
database for you project out of the box. This setup, is powered by docker compose and can be examined by opening the
|
||||
`db.docker-compose.yml` file in the project. Follow along to learn how to use the docker based database when developing
|
||||
locally.
|
||||
|
||||
### Run the database
|
||||
|
||||
The first step is to start the database, you can do this by running the following command in a terminal.
|
||||
|
||||
```bash
|
||||
m4g db run
|
||||
```
|
||||
|
||||
This command starts the services defined in the `db.docker-compose.yml` file.
|
||||
You can verify that the services are up by running `docker container ls`. If everything went well, then the previous
|
||||
command should output the service names defined in `db.docker-compose.yml`.
|
||||
|
||||
Go to [PhpMyAdmin (i.e. http://localhost:5051)](http://localhost:5051). You should now be able to login with the
|
||||
following credentials.
|
||||
- user: root
|
||||
- pass: password
|
||||
|
||||
When you're done developing, you can shut down the local database by running `m4g db stop`
|
||||
|
||||
:::info
|
||||
|
||||
If you're running on MacOS, Docker might complain about a platform mismatch for PhpMyAdmin.
|
||||
In that case you might need to specify the platform for the PhpMyAdmin image.
|
||||
You can do this by passing the `--dbu-platform` flag to `m4g init`.
|
||||
Run `m4g init -?` for all the available options.
|
||||
If you've already initialized a project, you can also change the platform prefix of the PhpMyAdmin image in the `db.docker-compose.yml`.
|
||||
|
||||
:::
|
||||
|
||||
### Create the entities
|
||||
|
||||
Now that the database is running, we can start creating our entities. Run the commands below to create the `Todo` &
|
||||
`Tag` entities.
|
||||
|
||||
```bash
|
||||
m4g db generate entity Tag --column "description:str:String(255)"
|
||||
```
|
||||
|
||||
```bash
|
||||
m4g db generate entity Todo --column "description:str:String(255)" -c "is_done:bool:Boolean()"
|
||||
```
|
||||
|
||||
After running these commands, you should find the generated entities in the `db/entities` folder of your project.
|
||||
You should also see that the `main.py` & `db/env.py` files have been modified to include the newly generated entity.
|
||||
|
||||
For more information about the `m4g db generate entity` command, you can run `m4g db generate entity -?`.
|
||||
|
||||
### Define a many-to-many relation between Todo & Tag
|
||||
|
||||
To allow for relations between `Todo` & `Tag`, we'll define a many-to-many relation between the two entities.
|
||||
This relation makes sense, because a `Todo` can have many `Tags` and a `Tag` could belong to many `Todos`.
|
||||
You can generate this relation by running the following command from you terminal.
|
||||
Creating a one-to-many relation would also make sense, but for the purpose of demonstration we're going to demonstrate
|
||||
the many-to-many relation, because this one is the most complex, since it requires an additional mapping to be included
|
||||
in the database schema.
|
||||
|
||||
```bash
|
||||
m4g db link many Todo --to-many Tag
|
||||
```
|
||||
|
||||
After running this command you should see that both the `Todo` and `Tag` entities now have a new field referencing the
|
||||
a `List` containing instances of the other entity.
|
||||
|
||||
For more information about the `m4g db link` command try running `m4g db link -?`. Note that you can do the same thing
|
||||
for all sub commands, so if you want to know more about `m4g db link many` you can simply run `m4g db link many -?` to
|
||||
examine the command. The same is true for all the other commands as well.
|
||||
|
||||
### Generate the migration
|
||||
|
||||
Now that we've generated our entities, it's time to generate a migration that will apply these changes in the database.
|
||||
Generate the initial migration by running the following command.
|
||||
|
||||
```bash
|
||||
m4g db generate migration initial_migration
|
||||
```
|
||||
|
||||
After running this command, you should see the new migration in the `db/version` directory.
|
||||
|
||||
### Apply the migration
|
||||
|
||||
The last step for the database setup is to actually apply the new migration to the database. This can be done by running
|
||||
the following command.
|
||||
|
||||
```bash
|
||||
m4g db migrate
|
||||
```
|
||||
|
||||
After running this command, you should now see a populated schema when visiting [PhpMyAdmin](http://localhost:5051).
|
||||
If for whatever reason you want to undo the last migration, you can simply run `m4g db rollback`.
|
||||
|
||||
## Setup the API
|
||||
|
||||
### Generate CRUD for Tag & Todo
|
||||
|
||||
Our API should provide use with basic endpoint to manage the `Todo` & `Tag` entities, i.e. CRUD functionality.
|
||||
Writing this code can be boring, since it's pretty much boilerplate with some custom additions sprinkled here and there.
|
||||
Fortunately, MycroForge can generate a good chunk of this boring code on your behalf. Run the following commands to
|
||||
generate CRUD functionality for the `Todo` & `Tag` classes.
|
||||
|
||||
```bash
|
||||
m4g api generate crud Tag
|
||||
```
|
||||
|
||||
```bash
|
||||
m4g api generate crud Todo
|
||||
```
|
||||
|
||||
After running this command you should see that the `api/requests`,`api/routers` & `api/services` now contain the
|
||||
relevant classes need to support the generated CRUD functionality. This could should be relatively straightforward, so
|
||||
we won't dive into it, but feel free to take a break and explore what the generated code actually does. Another thing to
|
||||
note, is that the generated routers are also automatically included in `main.py`.
|
||||
|
||||
### Modify the generated Todo request classes
|
||||
|
||||
Since we have a many-to-many relationship between `Todo` & `Tag`, the generated CRUD functionality isn't quite ready
|
||||
yet. We need to be able to specify which `Tags` to add to a `Todo` when creating or updating it.
|
||||
To do this, we will allow for a `tag_ids` field in both the `CreateTodoRequest` & the `UpdateTodoRequest`.
|
||||
This field will contain the ids of the `Tags` that are associated with a `Todo`.
|
||||
|
||||
Modify `CreateTodoRequest` in `api/requests/create_todo_request.py`.
|
||||
|
||||
```python
|
||||
# Before
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class CreateTodoRequest(BaseModel):
|
||||
description: str = None
|
||||
is_done: bool = None
|
||||
|
||||
# After
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class CreateTodoRequest(BaseModel):
|
||||
description: str = None
|
||||
is_done: bool = None
|
||||
tag_ids: Optional[List[int]] = []
|
||||
```
|
||||
|
||||
Modify `UpdateTodoRequest` in `api/requests/update_todo_request.py`, you might need to import `List` from `typing`.
|
||||
|
||||
```python
|
||||
# Before
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class UpdateTodoRequest(BaseModel):
|
||||
description: Optional[str] = None
|
||||
is_done: Optional[bool] = None
|
||||
|
||||
# After
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class UpdateTodoRequest(BaseModel):
|
||||
description: Optional[str] = None
|
||||
is_done: Optional[bool] = None
|
||||
tag_ids: Optional[List[int]] = []
|
||||
```
|
||||
|
||||
### Modify generated TodoService
|
||||
|
||||
The `TodoService` will also need to be updated to accomodate the management of `tag_ids`.
|
||||
|
||||
Add the following imports in `api/services/todo_service.py`.
|
||||
|
||||
```python
|
||||
from sqlalchemy.orm import selectinload
|
||||
from db.entities.tag import Tag
|
||||
```
|
||||
|
||||
Modify `TodoService.list`
|
||||
|
||||
```python
|
||||
# Before
|
||||
async def list(self) -> List[Todo]:
|
||||
async with async_session() as session:
|
||||
stmt = select(Todo)
|
||||
results = (await session.scalars(stmt)).all()
|
||||
return results
|
||||
|
||||
# After
|
||||
async def list(self) -> List[Todo]:
|
||||
async with async_session() as session:
|
||||
stmt = select(Todo).options(selectinload(Todo.tags))
|
||||
results = (await session.scalars(stmt)).all()
|
||||
return results
|
||||
```
|
||||
|
||||
Modify `TodoService.get_by_id`
|
||||
|
||||
```python
|
||||
# Before
|
||||
async def get_by_id(self, id: int) -> Optional[Todo]:
|
||||
async with async_session() as session:
|
||||
stmt = select(Todo).where(Todo.id == id)
|
||||
result = (await session.scalars(stmt)).first()
|
||||
return result
|
||||
|
||||
# After
|
||||
async def get_by_id(self, id: int) -> Optional[Todo]:
|
||||
async with async_session() as session:
|
||||
stmt = select(Todo).where(Todo.id == id).options(selectinload(Todo.tags))
|
||||
result = (await session.scalars(stmt)).first()
|
||||
return result
|
||||
```
|
||||
|
||||
Modify `TodoService.create`
|
||||
|
||||
```python
|
||||
# Before
|
||||
async def create(self, data: Dict[str, Any]) -> None:
|
||||
async with async_session() as session:
|
||||
entity = Todo(**data)
|
||||
session.add(entity)
|
||||
await session.commit()
|
||||
|
||||
# After
|
||||
async def create(self, data: Dict[str, Any]) -> None:
|
||||
tag_ids = []
|
||||
|
||||
if "tag_ids" in data.keys():
|
||||
tag_ids = data["tag_ids"]
|
||||
del data["tag_ids"]
|
||||
|
||||
async with async_session() as session:
|
||||
entity = Todo(**data)
|
||||
|
||||
if len(tag_ids) > 0:
|
||||
stmt = select(Tag).where(Tag.id.in_(tag_ids))
|
||||
result = (await session.scalars(stmt)).all()
|
||||
entity.tags = list(result)
|
||||
|
||||
session.add(entity)
|
||||
await session.commit()
|
||||
```
|
||||
|
||||
Modify `TodoService.update`
|
||||
|
||||
```python
|
||||
# Before
|
||||
async def update(self, id: int, data: Dict[str, Any]) -> bool:
|
||||
tag_ids = []
|
||||
|
||||
if "tag_ids" in data.keys():
|
||||
tag_ids = data["tag_ids"]
|
||||
del data["tag_ids"]
|
||||
|
||||
async with async_session() as session:
|
||||
stmt = select(Todo).where(Todo.id == id)
|
||||
entity = (await session.scalars(stmt)).first()
|
||||
|
||||
if entity is None:
|
||||
return False
|
||||
else:
|
||||
for key, value in data.items():
|
||||
setattr(entity, key, value)
|
||||
await session.commit()
|
||||
return True
|
||||
|
||||
# After
|
||||
async def update(self, id: int, data: Dict[str, Any]) -> bool:
|
||||
tag_ids = []
|
||||
|
||||
if "tag_ids" in data.keys():
|
||||
tag_ids = data["tag_ids"]
|
||||
del data["tag_ids"]
|
||||
|
||||
async with async_session() as session:
|
||||
stmt = select(Todo).where(Todo.id == id).options(selectinload(Todo.tags))
|
||||
entity = (await session.scalars(stmt)).first()
|
||||
|
||||
if entity is None:
|
||||
return False
|
||||
else:
|
||||
for key, value in data.items():
|
||||
setattr(entity, key, value)
|
||||
|
||||
if len(tag_ids) > 0:
|
||||
stmt = select(Tag).where(Tag.id.in_(tag_ids))
|
||||
result = (await session.scalars(stmt)).all()
|
||||
entity.tags = list(result)
|
||||
else:
|
||||
entity.tags = []
|
||||
|
||||
await session.commit()
|
||||
return True
|
||||
```
|
||||
|
||||
## Test the API!
|
||||
|
||||
Run the following command.
|
||||
```bash
|
||||
m4g api run
|
||||
```
|
||||
|
||||
Go to http://localhost:5000/docs and test your Todo API!
|
||||
Reference in New Issue
Block a user