added make:model command 😎

Only simple model generation without relations.

 - updated docs TINY/TOM_MODELS_DIR
This commit is contained in:
silverqx
2022-06-25 09:44:36 +02:00
parent aa4808473a
commit 9dcb3facf8
20 changed files with 654 additions and 63 deletions
+3 -1
View File
@@ -181,7 +181,7 @@ feature_option_dependent(TOM_EXAMPLE
)
# Depends on the TOM_EXAMPLE option so defined here
tiny_init_tom_migrations_dir()
tiny_init_tom_database_dirs()
# TinyORM library header and source files
# ---
@@ -311,6 +311,8 @@ if(TOM_EXAMPLE)
# Will be stringified in the tom/application.cpp
TINYTOM_MIGRATIONS_DIR=${TOM_MIGRATIONS_DIR}
# Will be stringified in the tom/application.cpp
TINYTOM_MODELS_DIR=${TOM_MODELS_DIR}
# Will be stringified in the tom/application.cpp
TINYTOM_SEEDERS_DIR=${TOM_SEEDERS_DIR}
)
endif()
+14 -3
View File
@@ -158,6 +158,8 @@ macro(tiny_init_tiny_variables_pre)
set(TomExample_folder examples/tom)
# Tom migrations folder for the make:migration command
set(TomMigrations_folder database/migrations)
# Tom models folder for the make:model command
set(TomModels_folder database/models)
# Tom seeders folder for the make:seeder command
set(TomSeeders_folder database/seeders)
@@ -252,8 +254,8 @@ constants")
endmacro()
# Initialize the default migrations path for the make:migration command
macro(tiny_init_tom_migrations_dir)
# Initialize the default database paths for the make:migration/model/seeder commands
macro(tiny_init_tom_database_dirs)
if(TOM_EXAMPLE)
# Provide the default migrations path for the make:migration command
@@ -262,6 +264,12 @@ macro(tiny_init_tom_migrations_dir)
set(TOM_MIGRATIONS_DIR ${TomMigrations_folder})
endif()
# Provide the default models path for the make:models command
if(NOT DEFINED TOM_MODELS_DIR)
# Relative path to the pwd
set(TOM_MODELS_DIR ${TomSeeders_folder})
endif()
# Provide the default seeders path for the make:seeders command
if(NOT DEFINED TOM_SEEDERS_DIR)
# Relative path to the pwd
@@ -272,10 +280,13 @@ macro(tiny_init_tom_migrations_dir)
set(TOM_MIGRATIONS_DIR "${TOM_MIGRATIONS_DIR}" CACHE PATH
"Default migrations path for the make:migration command")
set(TOM_MODELS_DIR "${TOM_MODELS_DIR}" CACHE PATH
"Default models path for the make:model command")
set(TOM_SEEDERS_DIR "${TOM_SEEDERS_DIR}" CACHE PATH
"Default seeders path for the make:seeder command")
mark_as_advanced(TOM_MIGRATIONS_DIR TOM_SEEDERS_DIR)
mark_as_advanced(TOM_MIGRATIONS_DIR TOM_MODELS_DIR TOM_SEEDERS_DIR)
endif()
endmacro()
+5
View File
@@ -266,12 +266,15 @@ function(tinytom_sources out_headers out_sources)
commands/integratecommand.hpp
commands/listcommand.hpp
commands/make/migrationcommand.hpp
commands/make/modelcommand.hpp
# commands/make/projectcommand.hpp
commands/make/seedercommand.hpp
commands/make/stubs/migrationstubs.hpp
commands/make/stubs/modelstubs.hpp
commands/make/stubs/projectstubs.hpp
commands/make/stubs/seederstubs.hpp
commands/make/support/migrationcreator.hpp
commands/make/support/modelcreator.hpp
commands/make/support/seedercreator.hpp
commands/make/support/tableguesser.hpp
commands/migrations/freshcommand.hpp
@@ -326,9 +329,11 @@ function(tinytom_sources out_headers out_sources)
commands/integratecommand.cpp
commands/listcommand.cpp
commands/make/migrationcommand.cpp
commands/make/modelcommand.cpp
# commands/make/projectcommand.cpp
commands/make/seedercommand.cpp
commands/make/support/migrationcreator.cpp
commands/make/support/modelcreator.cpp
commands/make/support/seedercreator.cpp
commands/make/support/tableguesser.cpp
commands/migrations/freshcommand.cpp
+3
View File
@@ -8,6 +8,9 @@
# Will be stringified in the tom/application.cpp
#DEFINES += TINYTOM_MIGRATIONS_DIR="\"database/migrations\""
# Default models path as the string for the make:model command
#DEFINES += TINYTOM_MODELS_DIR="\"database/models\""
# Default seeders path as the string for the make:seeder command
#DEFINES += TINYTOM_SEEDERS_DIR="\"database/seeders\""
+3 -1
View File
@@ -278,7 +278,8 @@ But a special situation is when you are building your application / library and
| `TINYORM_TESTS_CODE` | Enable code needed by unit tests, eg. connection overriding in the `Orm::Tiny::Model`.<br/><small>Defined when [`build_tests`](#build_tests) <small>(qmake)</small> / [`BUILD_TESTS`](#BUILD_TESTS) <small>(cmake)</small> configuration `build option` is enabled.</small> |
| `TINYORM_DISABLE_THREAD_LOCAL` | Remove all [`thread_local`](https://en.cppreference.com/w/c/language/storage_duration) storage duration specifiers, it disables threading support.<br/><small>Defined when [`disable_thread_local`](#disable_thread_local) <small>(qmake)</small> / [`DISABLE_THREAD_LOCAL`](#DISABLE_THREAD_LOCAL) <small>(cmake)</small> configuration `build option` is enabled.</small> |
| `TINYTOM_MIGRATIONS_DIR` | Default migrations path for the `make:migration` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/migrations` <small>(relative to the pwd)</small></small><br/><small>Defined by [`TOM_MIGRATIONS_DIR`](#TOM_MIGRATIONS_DIR) <small>(cmake)</small> configuration build option.<br/><small>(qmake note) You can use `DEFINES += TINYTOM_MIGRATIONS_DIR="\"database/migrations\""` on the command-line or set it in the __main__ [`conf.pri`](https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L4-L9) file.</small></small> |
| `TINYTOM_SEEDERS_DIR` | Default seeders path for the `make:seeder` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/seeders` <small>(relative to the pwd)</small></small><br/><small>Defined by [`TOM_SEEDERS_DIR`](#TOM_SEEDERS_DIR) <small>(cmake)</small> configuration build option.<br/><small>(qmake note) You can use `DEFINES += TINYTOM_SEEDERS_DIR="\"database/seeders\""` on the command-line or set it in the __main__ [`conf.pri`](https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L11-L12) file.</small></small> |
| `TINYTOM_MODELS_DIR` | Default models path for the `make:model` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/models` <small>(relative to the pwd)</small></small><br/><small>Defined by [`TOM_MODELS_DIR`](#TOM_MODELS_DIR) <small>(cmake)</small> configuration build option.<br/><small>(qmake note) You can use `DEFINES += TINYTOM_MODELS_DIR="\"database/models\""` on the command-line or set it in the __main__ [`conf.pri`](https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L11-L12) file.</small></small> |
| `TINYTOM_SEEDERS_DIR` | Default seeders path for the `make:seeder` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/seeders` <small>(relative to the pwd)</small></small><br/><small>Defined by [`TOM_SEEDERS_DIR`](#TOM_SEEDERS_DIR) <small>(cmake)</small> configuration build option.<br/><small>(qmake note) You can use `DEFINES += TINYTOM_SEEDERS_DIR="\"database/seeders\""` on the command-line or set it in the __main__ [`conf.pri`](https://github.com/silverqx/TinyORM/blob/main/conf.pri.example#L14-L15) file.</small></small> |
| `TINYORM_USING_PCH` | Defined if building with precompiled headers.<br/><small>Controlled by [`qmake`](#precompile_header) / [`CMake`](#CMAKE_DISABLE_PRECOMPILE_HEADERS).</small> |
</APITable>
@@ -391,6 +392,7 @@ CMake multi-config generators like `Ninja Multi-Config` or `Visual Studio 16 201
| `TOM` | `ON` | Controls the compilation of all `Tom-related` source code, when this option is `disabled`, then it also excludes `Tom-related` unit tests. |
| `TOM_EXAMPLE` | `OFF` | Build the <abbr title='TinyORM Migrations'>`Tom`</abbr> command-line application example (console application). |
| `TOM_MIGRATIONS_DIR` | `-` | Default migrations path for the `make:migration` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/migrations` <small>(relative to the pwd)</small></small> |
| `TOM_MODELS_DIR` | `-` | Default models path for the `make:model` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/models` <small>(relative to the pwd)</small></small> |
| `TOM_SEEDERS_DIR` | `-` | Default seeders path for the `make:seeder` command, can be an absolute or relative path (to the <abbr title='Current working directory'>pwd</abbr>).<br/><small>Default value: `database/seeders` <small>(relative to the pwd)</small></small> |
| `VERBOSE_CONFIGURE` | `OFF` | Show information about `PACKAGES_FOUND` / `PACKAGES_NOT_FOUND` in the CMake configure output. |
+3
View File
@@ -19,12 +19,15 @@ headersList += \
$$PWD/tom/commands/integratecommand.hpp \
$$PWD/tom/commands/listcommand.hpp \
$$PWD/tom/commands/make/migrationcommand.hpp \
$$PWD/tom/commands/make/modelcommand.hpp \
# $$PWD/tom/commands/make/projectcommand.hpp \
$$PWD/tom/commands/make/seedercommand.hpp \
$$PWD/tom/commands/make/stubs/migrationstubs.hpp \
$$PWD/tom/commands/make/stubs/modelstubs.hpp \
$$PWD/tom/commands/make/stubs/projectstubs.hpp \
$$PWD/tom/commands/make/stubs/seederstubs.hpp \
$$PWD/tom/commands/make/support/migrationcreator.hpp \
$$PWD/tom/commands/make/support/modelcreator.hpp \
$$PWD/tom/commands/make/support/seedercreator.hpp \
$$PWD/tom/commands/make/support/tableguesser.hpp \
$$PWD/tom/commands/migrations/freshcommand.hpp \
+9
View File
@@ -122,6 +122,8 @@ namespace Concerns
/*! Get the default migrations path used by the make:migration command. */
inline const fspath &getMigrationsPath() const noexcept;
/*! Get the default models path used by the make:model command. */
inline const fspath &getModelsPath() const noexcept;
/*! Get the default seeders path used by the make:seeder command. */
inline const fspath &getSeedersPath() const noexcept;
@@ -279,6 +281,8 @@ namespace Concerns
QString m_migrationTable;
/*! Migrations path for the make:migration command. */
std::filesystem::path m_migrationsPath;
/*! Models path for the make:model command. */
std::filesystem::path m_modelsPath;
/*! Seeders path for the make:seeder command. */
std::filesystem::path m_seedersPath;
@@ -367,6 +371,11 @@ namespace Concerns
return m_migrationsPath;
}
const std::filesystem::path &Application::getModelsPath() const noexcept
{
return m_modelsPath;
}
const std::filesystem::path &Application::getSeedersPath() const noexcept
{
return m_seedersPath;
@@ -0,0 +1,83 @@
#pragma once
#ifndef TOM_COMMANDS_MAKE_MODELCOMMAND_HPP
#define TOM_COMMANDS_MAKE_MODELCOMMAND_HPP
#include <orm/macros/systemheader.hpp>
TINY_SYSTEM_HEADER
#include "tom/commands/command.hpp"
#include "tom/commands/make/support/modelcreator.hpp"
#include "tom/tomconstants.hpp"
TINYORM_BEGIN_COMMON_NAMESPACE
namespace Tom::Commands::Make
{
/*! Create a new model class. */
class ModelCommand : public Command
{
Q_DISABLE_COPY(ModelCommand)
/*! Alias for the filesystem path. */
using fspath = std::filesystem::path;
/*! Alias for the command line option values. */
using CmdOptions = Support::ModelCreator::CmdOptions;
public:
/*! Constructor. */
ModelCommand(Application &application, QCommandLineParser &parser);
/*! Virtual destructor. */
inline ~ModelCommand() override = default;
/*! The console command name. */
inline QString name() const override;
/*! The console command description. */
inline QString description() const override;
/*! The console command positional arguments signature. */
const std::vector<PositionalArgument> &positionalArguments() const override;
/*! The signature of the console command. */
QList<QCommandLineOption> optionsSignature() const override;
/*! Execute the console command. */
int run() override;
protected:
/*! Prepare a model class name. */
static QString prepareModelClassname(QString &&className);
/*! Write the model file to the disk. */
void writeModel(const QString &className) const;
/*! Create command line options instance. */
CmdOptions createCmdOptions() const;
/*! Get the model path (either specified by the --path option or the default
location). */
fspath getModelPath() const;
/*! The model creator instance. */
Support::ModelCreator m_creator {};
private:
/*! Throw if the model name constains a namespace or path. */
static void throwIfContainsNamespaceOrPath(const QString &className);
};
/* public */
QString ModelCommand::name() const
{
return Constants::MakeModel;
}
QString ModelCommand::description() const
{
return QStringLiteral("Create a new model class");
}
} // namespace Tom::Commands::Make
TINYORM_END_COMMON_NAMESPACE
#endif // TOM_COMMANDS_MAKE_MODELCOMMAND_HPP
@@ -0,0 +1,67 @@
#pragma once
#ifndef TOM_COMMANDS_MAKE_STUBS_MODELSTUBS_HPP
#define TOM_COMMANDS_MAKE_STUBS_MODELSTUBS_HPP
#include <orm/macros/systemheader.hpp>
TINY_SYSTEM_HEADER
#include <orm/macros/commonnamespace.hpp>
TINYORM_BEGIN_COMMON_NAMESPACE
namespace Tom::Commands::Make::Stubs
{
/*! Model stub. */
inline const auto *const ModelStub =
R"TTT(#pragma once
#ifndef MODELS_{{ macroguard }}_HPP
#define MODELS_{{ macroguard }}_HPP
#include "orm/tiny/model.hpp"
namespace Models
{
using Orm::Tiny::Model;
// NOLINTNEXTLINE(misc-no-recursion)
class {{ class }} final : public Model<{{ class }}>
{
friend Model;
using Model::Model;{{ privateSection }}
};
} // namespace Models
#endif // MODELS_{{ macroguard }}_HPP
)TTT";
/*! Model private section stub. */
inline const auto *const ModelPrivateStub =
R"(
private:)";
/*! Model connection stub. */
inline const auto *const ModelConnectionStub =
R"(
/*! The connection name for the model. */
QString u_connection {"{{ connection }}"};)";
/*! Model table stub. */
inline const auto *const ModelTableStub =
R"(
/*! The table associated with the model. */
QString u_table {"{{ table }}"};)";
/*! Model disable timestamps stub. */
inline const auto *const ModelDisableTimestampsStub =
R"(
/*! Indicates whether the model should be timestamped. */
bool u_timestamps = false;)";
} // namespace Tom::Commands::Make::Stubs
TINYORM_END_COMMON_NAMESPACE
#endif // TOM_COMMANDS_MAKE_STUBS_MODELSTUBS_HPP
@@ -0,0 +1,73 @@
#pragma once
#ifndef TOM_COMMANDS_MAKE_SUPPORT_MODELCREATOR_HPP
#define TOM_COMMANDS_MAKE_SUPPORT_MODELCREATOR_HPP
#include <orm/macros/systemheader.hpp>
TINY_SYSTEM_HEADER
#include <QString>
#include <filesystem>
#include <orm/macros/commonnamespace.hpp>
TINYORM_BEGIN_COMMON_NAMESPACE
namespace Tom::Commands::Make::Support
{
/*! Model file generator (used by the make:model command). */
class ModelCreator
{
Q_DISABLE_COPY(ModelCreator)
/*! Alias for the filesystem path. */
using fspath = std::filesystem::path;
public:
/*! Default constructor. */
inline ModelCreator() = default;
/*! Default destructor. */
inline ~ModelCreator() = default;
/*! Struct to hold command line option values. */
struct CmdOptions
{
/*! The connection name for the model. */
QString connection;
/*! The table associated with the model. */
QString table;
/*! Disable timestamping of the model. */
bool disableTimestamps;
};
/*! Create a new model at the given path. */
fspath create(const QString &className, CmdOptions &&cmdOptions,
fspath &&modelsPath) const;
protected:
/*! Get the full path to the model. */
static fspath getPath(const QString &basename, const fspath &path);
/*! Ensure a directory exists. */
static void ensureDirectoryExists(const fspath &path);
/*! Populate the place-holders in the model stub. */
static std::string populateStub(const QString &className,
CmdOptions &&cmdOptions);
/*! Create model's private section. */
static QString createPrivateSection(const CmdOptions &cmdOptions);
private:
/*! Ensure that a model with the given name doesn't already exist. */
void throwIfModelAlreadyExists(
const QString &className, const QString &basename,
const fspath &modelsPath) const;
};
} // namespace Tom::Commands::Make::Support
TINYORM_END_COMMON_NAMESPACE
#endif // TOM_COMMANDS_MAKE_SUPPORT_MODELCREATOR_HPP
+7
View File
@@ -21,6 +21,13 @@ TINY_SYSTEM_HEADER
# define TINYTOM_MIGRATIONS_DIR database/migrations
#endif
/* Default models path for the make:model command, the path can be absolute or
relative (to the pwd at runtime) and will be stringified in the tom/application.cpp. */
#ifndef TINYTOM_MODELS_DIR
// NOLINTNEXTLINE(bugprone-macro-parentheses)
# define TINYTOM_MODELS_DIR database/models
#endif
/* Default seeders path for the make:seeder command, the path can be absolute or
relative (to the pwd at runtime) and will be stringified in the tom/application.cpp. */
#ifndef TINYTOM_SEEDERS_DIR
+9 -1
View File
@@ -55,6 +55,7 @@ namespace Tom::Constants
SHAREDLIB_EXPORT extern const QString step_;
SHAREDLIB_EXPORT extern const QString path_;
// Default value names
SHAREDLIB_EXPORT extern const QString env_up;
SHAREDLIB_EXPORT extern const QString class_up;
SHAREDLIB_EXPORT extern const QString database_up;
SHAREDLIB_EXPORT extern const QString seeder_up;
@@ -64,6 +65,9 @@ namespace Tom::Constants
SHAREDLIB_EXPORT extern const QString word_up;
SHAREDLIB_EXPORT extern const QString cword_up;
SHAREDLIB_EXPORT extern const QString path_up;
SHAREDLIB_EXPORT extern const QString create_up;
SHAREDLIB_EXPORT extern const QString table_up;
SHAREDLIB_EXPORT extern const QString connection_up;
// complete
SHAREDLIB_EXPORT extern const QString commandline;
SHAREDLIB_EXPORT extern const QString position;
@@ -76,11 +80,14 @@ namespace Tom::Constants
// db:wipe
SHAREDLIB_EXPORT extern const QString drop_views;
SHAREDLIB_EXPORT extern const QString drop_types;
// make:migration
// make:migration, make:model, make:seeder
SHAREDLIB_EXPORT extern const QString create_;
SHAREDLIB_EXPORT extern const QString table_;
SHAREDLIB_EXPORT extern const QString realpath_;
SHAREDLIB_EXPORT extern const QString fullpath;
// make:model
SHAREDLIB_EXPORT extern const QString connection_;
SHAREDLIB_EXPORT extern const QString disable_timestamps;
// migrate:refresh
SHAREDLIB_EXPORT extern const QString step_migrate;
// integrate
@@ -108,6 +115,7 @@ namespace Tom::Constants
SHAREDLIB_EXPORT extern const QString &Env;
SHAREDLIB_EXPORT extern const QString &Help;
SHAREDLIB_EXPORT extern const QString MakeMigration;
SHAREDLIB_EXPORT extern const QString MakeModel;
SHAREDLIB_EXPORT extern const QString MakeProject;
SHAREDLIB_EXPORT extern const QString MakeSeeder;
SHAREDLIB_EXPORT extern const QString &Migrate;
+32 -24
View File
@@ -54,36 +54,43 @@ namespace Tom::Constants
inline const QString step_ = QStringLiteral("step");
inline const QString path_ = QStringLiteral("path");
// Default value names
inline const QString class_up = QStringLiteral("CLASS");
inline const QString database_up = QStringLiteral("DATABASE");
inline const QString seeder_up = QStringLiteral("SEEDER");
inline const QString step_up = QStringLiteral("STEP");
inline const QString commandline_up = QStringLiteral("COMMANDLINE");
inline const QString position_up = QStringLiteral("POSITION");
inline const QString word_up = QStringLiteral("WORD");
inline const QString cword_up = QStringLiteral("CWORD");
inline const QString path_up = QStringLiteral("PATH");
inline const QString env_up = QStringLiteral("ENV");
inline const QString class_up = QStringLiteral("CLASS");
inline const QString database_up = QStringLiteral("DATABASE");
inline const QString seeder_up = QStringLiteral("SEEDER");
inline const QString step_up = QStringLiteral("STEP");
inline const QString commandline_up = QStringLiteral("COMMANDLINE");
inline const QString position_up = QStringLiteral("POSITION");
inline const QString word_up = QStringLiteral("WORD");
inline const QString cword_up = QStringLiteral("CWORD");
inline const QString path_up = QStringLiteral("PATH");
inline const QString create_up = QStringLiteral("CREATE");
inline const QString table_up = QStringLiteral("TABLE");
inline const QString connection_up = QStringLiteral("CONNECTION");
// complete
inline const QString commandline = QStringLiteral("commandline");
inline const QString position = QStringLiteral("position");
inline const QString word_ = QStringLiteral("word");
inline const QString cword_ = QStringLiteral("cword");
inline const QString commandline = QStringLiteral("commandline");
inline const QString position = QStringLiteral("position");
inline const QString word_ = QStringLiteral("word");
inline const QString cword_ = QStringLiteral("cword");
// list
inline const QString raw_ = QStringLiteral("raw");
inline const QString raw_ = QStringLiteral("raw");
// db:seed
inline const QString class_ = QStringLiteral("class");
inline const QString class_ = QStringLiteral("class");
// db:wipe
inline const QString drop_views = QStringLiteral("drop-views");
inline const QString drop_types = QStringLiteral("drop-types");
// make:migration
inline const QString create_ = QStringLiteral("create");
inline const QString table_ = QStringLiteral("table");
inline const QString realpath_ = QStringLiteral("realpath");
inline const QString fullpath = QStringLiteral("fullpath");
inline const QString drop_views = QStringLiteral("drop-views");
inline const QString drop_types = QStringLiteral("drop-types");
// make:migration, make:model, make:seeder
inline const QString create_ = QStringLiteral("create");
inline const QString table_ = QStringLiteral("table");
inline const QString realpath_ = QStringLiteral("realpath");
inline const QString fullpath = QStringLiteral("fullpath");
// make:model
inline const QString connection_ = QStringLiteral("connection");
inline const QString disable_timestamps = QStringLiteral("disable-timestamps");
// migrate:refresh
inline const QString step_migrate = QStringLiteral("step-migrate");
inline const QString step_migrate = QStringLiteral("step-migrate");
// integrate
inline const QString stdout_ = QStringLiteral("stdout");
inline const QString stdout_ = QStringLiteral("stdout");
// Namespace names
inline const QString NsGlobal = QStringLiteral("global");
@@ -107,6 +114,7 @@ namespace Tom::Constants
inline const QString &Env = Tom::Constants::env;
inline const QString &Help = Tom::Constants::help;
inline const QString MakeMigration = QStringLiteral("make:migration");
inline const QString MakeModel = QStringLiteral("make:model");
inline const QString MakeProject = QStringLiteral("make:project");
inline const QString MakeSeeder = QStringLiteral("make:seeder");
inline const QString &Migrate = Tom::Constants::NsMigrate;
+2
View File
@@ -14,9 +14,11 @@ sourcesList += \
$$PWD/tom/commands/integratecommand.cpp \
$$PWD/tom/commands/listcommand.cpp \
$$PWD/tom/commands/make/migrationcommand.cpp \
$$PWD/tom/commands/make/modelcommand.cpp \
# $$PWD/tom/commands/make/projectcommand.cpp \
$$PWD/tom/commands/make/seedercommand.cpp \
$$PWD/tom/commands/make/support/migrationcreator.cpp \
$$PWD/tom/commands/make/support/modelcreator.cpp \
$$PWD/tom/commands/make/support/seedercreator.cpp \
$$PWD/tom/commands/make/support/tableguesser.cpp \
$$PWD/tom/commands/migrations/freshcommand.cpp \
+14 -6
View File
@@ -20,6 +20,7 @@
#include "tom/commands/integratecommand.hpp"
#include "tom/commands/listcommand.hpp"
#include "tom/commands/make/migrationcommand.hpp"
#include "tom/commands/make/modelcommand.hpp"
//#include "tom/commands/make/projectcommand.hpp"
#include "tom/commands/make/seedercommand.hpp"
#include "tom/commands/migrations/freshcommand.hpp"
@@ -55,6 +56,7 @@ using Tom::Commands::InspireCommand;
using Tom::Commands::IntegrateCommand;
using Tom::Commands::ListCommand;
using Tom::Commands::Make::MigrationCommand;
using Tom::Commands::Make::ModelCommand;
//using Tom::Commands::Make::ProjectCommand;
using Tom::Commands::Make::SeederCommand;
using Tom::Commands::Migrations::FreshCommand;
@@ -74,6 +76,7 @@ using Tom::Constants::Inspire;
using Tom::Constants::Integrate;
using Tom::Constants::List;
using Tom::Constants::MakeMigration;
using Tom::Constants::MakeModel;
//using Tom::Constants::MakeProject;
using Tom::Constants::MakeSeeder;
using Tom::Constants::Migrate;
@@ -91,6 +94,7 @@ using Tom::Constants::NsMigrate;
using Tom::Constants::NsNamespaced;
using Tom::Constants::ansi;
using Tom::Constants::env;
using Tom::Constants::env_up;
using Tom::Constants::help;
using Tom::Constants::noansi;
using Tom::Constants::nointeraction;
@@ -127,6 +131,7 @@ Application::Application(int &argc, char **argv, std::shared_ptr<DatabaseManager
, m_environmentEnvName(environmentEnvName)
, m_migrationTable(std::move(migrationTable))
, m_migrationsPath(initializePath(TINYORM_STRINGIFY(TINYTOM_MIGRATIONS_DIR)))
, m_modelsPath(initializePath(TINYORM_STRINGIFY(TINYTOM_MODELS_DIR)))
, m_seedersPath(initializePath(TINYORM_STRINGIFY(TINYTOM_SEEDERS_DIR)))
, m_migrations(std::move(migrations))
, m_seeders(std::move(seeders))
@@ -252,7 +257,7 @@ void Application::initializeParser(QCommandLineParser &parser)
{ ansi, QStringLiteral("Force ANSI output")},
{ noansi, QStringLiteral("Disable ANSI output")},
{ env, QStringLiteral("The environment the command should run "
"under"), env.toUpper()}, // Value
"under"), env_up}, // Value
{{"h", help}, QStringLiteral("Display help for the given command. When "
"no command is given display help for the "
"<info>list</info> command")},
@@ -440,6 +445,9 @@ Application::createCommand(const QString &command, const OptionalParserRef parse
if (command == MakeMigration)
return std::make_unique<MigrationCommand>(*this, parserRef);
if (command == MakeModel)
return std::make_unique<ModelCommand>(*this, parserRef);
// if (command == MakeProject)
// return std::make_unique<ProjectCommand>(*this, parserRef);
@@ -567,7 +575,7 @@ Application::commandNames() const
// db
DbSeed, DbWipe,
// make
MakeMigration, /*MakeProject,*/ MakeSeeder,
MakeMigration, MakeModel, /*MakeProject,*/ MakeSeeder,
// migrate
MigrateFresh, MigrateInstall, MigrateRefresh, MigrateReset, MigrateRollback,
MigrateStatus,
@@ -612,10 +620,10 @@ const std::vector<std::tuple<int, int>> &Application::commandsIndexes() const
{0, 7}, // "" - also global
{0, 7}, // global
{7, 9}, // db
{9, 11}, // make
{11, 17}, // migrate
{7, 17}, // namespaced
{0, 17}, // all
{9, 12}, // make
{12, 18}, // migrate
{7, 18}, // namespaced
{0, 18}, // all
};
return cached;
@@ -22,11 +22,13 @@ using Orm::Constants::UNDERSCORE;
using StringUtils = Orm::Tiny::Utils::String;
using Tom::Constants::create_;
using Tom::Constants::create_up;
using Tom::Constants::fullpath;
using Tom::Constants::path_;
using Tom::Constants::path_up;
using Tom::Constants::realpath_;
using Tom::Constants::table_;
using Tom::Constants::table_up;
using Tom::Constants::DateTimePrefix;
using TomUtils = Tom::Utils;
@@ -54,8 +56,8 @@ const std::vector<PositionalArgument> &MigrationCommand::positionalArguments() c
QList<QCommandLineOption> MigrationCommand::optionsSignature() const
{
return {
{create_, QStringLiteral("The table to be created"), create_.toUpper()}, // Value
{table_, QStringLiteral("The table to migrate"), table_.toUpper()}, // Value
{create_, QStringLiteral("The table to be created"), create_up}, // Value
{table_, QStringLiteral("The table to migrate"), table_up}, // Value
{path_, QStringLiteral("The location where the migration file should be "
"created"), path_up}, // Value
{realpath_, QStringLiteral("Indicate that any provided migration file paths are "
+146
View File
@@ -0,0 +1,146 @@
#include "tom/commands/make/modelcommand.hpp"
#include <orm/constants.hpp>
#include <orm/tiny/utils/string.hpp>
#include "tom/application.hpp"
#include "tom/exceptions/invalidargumenterror.hpp"
#include "tom/tomconstants.hpp"
namespace fs = std::filesystem;
using fspath = std::filesystem::path;
using Orm::Constants::NAME;
using StringUtils = Orm::Tiny::Utils::String;
using Tom::Constants::connection_;
using Tom::Constants::connection_up;
using Tom::Constants::fullpath;
using Tom::Constants::path_;
using Tom::Constants::path_up;
using Tom::Constants::realpath_;
using Tom::Constants::table_;
using Tom::Constants::table_up;
using Tom::Constants::disable_timestamps;
TINYORM_BEGIN_COMMON_NAMESPACE
namespace Tom::Commands::Make
{
/* public */
ModelCommand::ModelCommand(Application &application, QCommandLineParser &parser)
: Command(application, parser)
{}
const std::vector<PositionalArgument> &ModelCommand::positionalArguments() const
{
static const std::vector<PositionalArgument> cached {
{NAME, QStringLiteral("The name of the model class (required StudlyCase)")},
};
return cached;
}
QList<QCommandLineOption> ModelCommand::optionsSignature() const
{
return {
{connection_, QStringLiteral("The connection name for the model"),
connection_up}, // Value
{table_, QStringLiteral("The table associated with the model"),
table_up}, // Value
{disable_timestamps, QStringLiteral("Disable timestamping of the model")},
{path_, QStringLiteral("The location where the model file should "
"be created"), path_up}, // Value
{realpath_, QStringLiteral("Indicate that any provided model file "
"paths are pre-resolved absolute paths")},
{fullpath, QStringLiteral("Output the full path of the created model")},
};
}
int ModelCommand::run()
{
Command::run();
const auto className = prepareModelClassname(argument(NAME));
// Ready to write the model to the disk 🧨✨
writeModel(className);
return EXIT_SUCCESS;
}
/* protected */
QString ModelCommand::prepareModelClassname(QString &&className)
{
// Validate the model name
throwIfContainsNamespaceOrPath(className);
return StringUtils::studly(std::move(className));
}
void ModelCommand::writeModel(const QString &className) const
{
auto modelFilePath = m_creator.create(className, createCmdOptions(), getModelPath());
// make_preferred() returns reference and filename() creates a new fs::path instance
const auto modelFile = isSet(fullpath) ? modelFilePath.make_preferred()
: modelFilePath.filename();
info(QStringLiteral("Created Model: "), false);
note(QString::fromStdString(modelFile.string()));
}
ModelCommand::CmdOptions ModelCommand::createCmdOptions() const
{
return {
value(connection_),
value(table_),
isSet(disable_timestamps),
};
}
fspath ModelCommand::getModelPath() const
{
// Default location
if (!isSet(path_))
return application().getModelsPath();
auto targetPath = value(path_).toStdString();
// The 'path' argument contains an absolute path
if (isSet(realpath_))
return {std::move(targetPath)};
// The 'path' argument contains a relative path
auto modelsPath = fs::current_path() / std::move(targetPath);
// Validate
if (fs::exists(modelsPath) && !fs::is_directory(modelsPath))
throw Exceptions::InvalidArgumentError(
QStringLiteral("Models path '%1' exists and it's not a directory.")
.arg(modelsPath.c_str()));
return modelsPath;
}
void ModelCommand::throwIfContainsNamespaceOrPath(const QString &className)
{
if (!className.contains(QStringLiteral("::")) && !className.contains(QChar('/')) &&
!className.contains(QChar('\\'))
)
return;
throw Exceptions::InvalidArgumentError(
"Namespace or path is not allowed in the model name");
}
} // namespace Tom::Commands::Make
TINYORM_END_COMMON_NAMESPACE
+3 -1
View File
@@ -17,6 +17,7 @@ using StringUtils = Orm::Tiny::Utils::String;
using Tom::Constants::fullpath;
using Tom::Constants::path_;
using Tom::Constants::path_up;
using Tom::Constants::realpath_;
TINYORM_BEGIN_COMMON_NAMESPACE
@@ -43,7 +44,7 @@ QList<QCommandLineOption> SeederCommand::optionsSignature() const
{
return {
{path_, QStringLiteral("The location where the seeder file should be "
"created"), path_.toUpper()}, // Value
"created"), path_up}, // Value
{realpath_, QStringLiteral("Indicate that any provided seeder file paths are "
"pre-resolved absolute paths")},
{fullpath, QStringLiteral("Output the full path of the created seeder")},
@@ -86,6 +87,7 @@ QString SeederCommand::prepareSeederClassname(QString &&className)
// Change Xyzseeder to XyzSeeder
className[className.size() - Seeder_lc_size] = QChar('S');
// CUR stackoverflow, still confused about this moves, when I assign a new value silverqx
return std::move(className);
}
@@ -0,0 +1,142 @@
#include "tom/commands/make/support/modelcreator.hpp"
#include <fstream>
#include <orm/constants.hpp>
#include <orm/tiny/utils/string.hpp>
#include "tom/commands/make/stubs/modelstubs.hpp"
#include "tom/exceptions/invalidargumenterror.hpp"
namespace fs = std::filesystem;
using fspath = std::filesystem::path;
using Orm::Constants::NEWLINE;
using StringUtils = Orm::Tiny::Utils::String;
using Tom::Commands::Make::Stubs::ModelConnectionStub;
using Tom::Commands::Make::Stubs::ModelDisableTimestampsStub;
//using Tom::Commands::Make::Stubs::ModelPrivateStub;
using Tom::Commands::Make::Stubs::ModelStub;
using Tom::Commands::Make::Stubs::ModelTableStub;
TINYORM_BEGIN_COMMON_NAMESPACE
namespace Tom::Commands::Make::Support
{
/* public */
fspath ModelCreator::create(const QString &className, CmdOptions &&cmdOptions,
fspath &&modelsPath) const
{
const auto basename = className.toLower();
auto modelPath = getPath(basename, modelsPath);
throwIfModelAlreadyExists(className, basename, modelsPath);
ensureDirectoryExists(modelsPath);
// Output it as binary stream to force line endings to LF
std::ofstream(modelPath, std::ios::out | std::ios::binary)
<< populateStub(className, std::move(cmdOptions));
return modelPath;
}
/* protected */
fspath ModelCreator::getPath(const QString &basename, const fspath &path)
{
return path / (basename.toStdString() + ".hpp");
}
void ModelCreator::ensureDirectoryExists(const fspath &path)
{
if (fs::exists(path) && fs::is_directory(path))
return;
fs::create_directories(path);
}
std::string ModelCreator::populateStub(const QString &className, CmdOptions &&cmdOptions)
{
const auto privateSection = createPrivateSection(cmdOptions);
const auto macroGuard = className.toUpper();
QString stub(ModelStub);
stub.replace(QStringLiteral("DummyClass"), className)
.replace(QStringLiteral("{{ class }}"), className)
.replace(QStringLiteral("{{class}}"), className)
.replace(QStringLiteral("{{ macroguard }}"), macroGuard)
.replace(QStringLiteral("{{macroguard}}"), macroGuard)
.replace(QStringLiteral("{{ privateSection }}"), privateSection)
.replace(QStringLiteral("{{privateSection}}"), privateSection);
return stub.toStdString();
}
QString ModelCreator::createPrivateSection(const CmdOptions &cmdOptions)
{
const auto &[connection, table, disableTimestamps] = cmdOptions;
QString privateSection;
if (!connection.isEmpty())
privateSection += QString(ModelConnectionStub)
.replace(QStringLiteral("{{ connection }}"), connection)
.replace(QStringLiteral("{{connection}}"), connection);
if (!table.isEmpty())
privateSection += QString(ModelTableStub)
.replace(QStringLiteral("{{ table }}"), table)
.replace(QStringLiteral("{{table}}"), table);
if (disableTimestamps)
privateSection += ModelDisableTimestampsStub;
if (!privateSection.isEmpty())
privateSection.prepend(NEWLINE);
return privateSection;
}
/* private */
void ModelCreator::throwIfModelAlreadyExists(
const QString &className, const QString &basename,
const fspath &modelsPath) const
{
// Nothing to check
if (!fs::exists(modelsPath))
return;
using options = fs::directory_options;
for (const auto &entry :
fs::directory_iterator(modelsPath, options::skip_permission_denied)
) {
// Check only files
if (!entry.is_regular_file())
continue;
// Extract base filename without the extension
auto entryName = QString::fromStdString(entry.path().stem().string());
if (entryName == basename)
throw Exceptions::InvalidArgumentError(
QStringLiteral("A '%1' model already exists.").arg(className));
}
}
} // namespace Tom::Commands::Make::Support
TINYORM_END_COMMON_NAMESPACE
+32 -24
View File
@@ -43,36 +43,43 @@ namespace Tom::Constants
const QString step_ = QStringLiteral("step");
const QString path_ = QStringLiteral("path");
// Default value names
const QString class_up = QStringLiteral("CLASS");
const QString database_up = QStringLiteral("DATABASE");
const QString seeder_up = QStringLiteral("SEEDER");
const QString step_up = QStringLiteral("STEP");
const QString commandline_up = QStringLiteral("COMMANDLINE");
const QString position_up = QStringLiteral("POSITION");
const QString word_up = QStringLiteral("WORD");
const QString cword_up = QStringLiteral("CWORD");
const QString path_up = QStringLiteral("PATH");
const QString env_up = QStringLiteral("ENV");
const QString class_up = QStringLiteral("CLASS");
const QString database_up = QStringLiteral("DATABASE");
const QString seeder_up = QStringLiteral("SEEDER");
const QString step_up = QStringLiteral("STEP");
const QString commandline_up = QStringLiteral("COMMANDLINE");
const QString position_up = QStringLiteral("POSITION");
const QString word_up = QStringLiteral("WORD");
const QString cword_up = QStringLiteral("CWORD");
const QString path_up = QStringLiteral("PATH");
const QString create_up = QStringLiteral("CREATE");
const QString table_up = QStringLiteral("TABLE");
const QString connection_up = QStringLiteral("CONNECTION");
// complete
const QString commandline = QStringLiteral("commandline");
const QString position = QStringLiteral("position");
const QString word_ = QStringLiteral("word");
const QString cword_ = QStringLiteral("cword");
const QString commandline = QStringLiteral("commandline");
const QString position = QStringLiteral("position");
const QString word_ = QStringLiteral("word");
const QString cword_ = QStringLiteral("cword");
// list
const QString raw_ = QStringLiteral("raw");
const QString raw_ = QStringLiteral("raw");
// db:seed
const QString class_ = QStringLiteral("class");
const QString class_ = QStringLiteral("class");
// db:wipe
const QString drop_views = QStringLiteral("drop-views");
const QString drop_types = QStringLiteral("drop-types");
// make:migration
const QString create_ = QStringLiteral("create");
const QString table_ = QStringLiteral("table");
const QString realpath_ = QStringLiteral("realpath");
const QString fullpath = QStringLiteral("fullpath");
const QString drop_views = QStringLiteral("drop-views");
const QString drop_types = QStringLiteral("drop-types");
// make:migration, make:model, make:seeder
const QString create_ = QStringLiteral("create");
const QString table_ = QStringLiteral("table");
const QString realpath_ = QStringLiteral("realpath");
const QString fullpath = QStringLiteral("fullpath");
// make:model
const QString connection_ = QStringLiteral("connection");
const QString disable_timestamps = QStringLiteral("disable-timestamps");
// migrate:refresh
const QString step_migrate = QStringLiteral("step-migrate");
const QString step_migrate = QStringLiteral("step-migrate");
// integrate
const QString stdout_ = QStringLiteral("stdout");
const QString stdout_ = QStringLiteral("stdout");
// Namespace names
const QString NsGlobal = QStringLiteral("global");
@@ -96,6 +103,7 @@ namespace Tom::Constants
const QString &Env = Tom::Constants::env;
const QString &Help = Tom::Constants::help;
const QString MakeMigration = QStringLiteral("make:migration");
const QString MakeModel = QStringLiteral("make:model");
const QString MakeProject = QStringLiteral("make:project");
const QString MakeSeeder = QStringLiteral("make:seeder");
const QString &Migrate = Tom::Constants::NsMigrate;