@h3ravel/database 11.15.0-alpha.15 → 11.17.0-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/package.json +8 -10
- package/dist/index.cjs +0 -730
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference path="./app.globals.d.ts" />
|
|
2
2
|
import { Command } from "@h3ravel/musket";
|
|
3
|
+
import { ServiceProvider } from "@h3ravel/support";
|
|
3
4
|
import { Model as Model$1, QueryBuilder, Seeder as Seeder$1 } from "@h3ravel/arquebus";
|
|
5
|
+
import { UrlRoutable } from "@h3ravel/contracts";
|
|
4
6
|
import { Knex } from "knex";
|
|
5
7
|
import { IBuilder, IQueryBuilder, Relation } from "@h3ravel/arquebus/types";
|
|
6
|
-
import { UrlRoutable } from "@h3ravel/contracts";
|
|
7
|
-
import { ServiceProvider } from "@h3ravel/support";
|
|
8
8
|
import { Application } from "@h3ravel/core";
|
|
9
9
|
|
|
10
10
|
//#region src/Commands/MakeCommand.d.ts
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FileSystem, Logger, Resolver, TaskManager, mix } from "@h3ravel/shared";
|
|
1
|
+
import { FileSystem, Logger, Resolver, TaskManager, importFile, mix } from "@h3ravel/shared";
|
|
2
2
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { Command } from "@h3ravel/musket";
|
|
4
4
|
import { Arr, ServiceProvider, Str } from "@h3ravel/support";
|
|
@@ -319,7 +319,7 @@ var MigrateCommand = class extends Command {
|
|
|
319
319
|
const packagePath = FileSystem.findModulePkg(name) ?? null;
|
|
320
320
|
if (!packagePath) throw new Error("Package not found");
|
|
321
321
|
/** Get the package,json and instanciate the migration creator */
|
|
322
|
-
const pkgJson = await
|
|
322
|
+
const pkgJson = JSON.parse(await readFile(npath.join(packagePath, "package.json"), "utf8"));
|
|
323
323
|
const creator = new MigrationCreator(npath.join(packagePath, pkgJson.migrations ?? "migrations"));
|
|
324
324
|
const info = Logger.parse([[" Publishing migrations from", "white"], [`${pkgJson.name}@${pkgJson.version}`, ["italic", "gray"]]], " ", false);
|
|
325
325
|
Logger.info(`INFO: ${info}`);
|
|
@@ -406,7 +406,7 @@ var SeedCommand = class extends Command {
|
|
|
406
406
|
*/
|
|
407
407
|
if (!await FileSystem.fileExists(path)) this.error(`ERROR: Seeder ${Logger.log(`[${file}]`, "bold", false)} not found.`);
|
|
408
408
|
} else path = String(f1 ?? f2);
|
|
409
|
-
const { default: seeder } = await
|
|
409
|
+
const { default: seeder } = await importFile(path);
|
|
410
410
|
if (seeder) {
|
|
411
411
|
this.info("INFO: Seeding database.");
|
|
412
412
|
this.newLine();
|
package/package.json
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h3ravel/database",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.17.0-alpha.16",
|
|
4
4
|
"description": "Modeling data and migration system for H3ravel.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.cjs",
|
|
7
6
|
"types": "./dist/index.d.ts",
|
|
8
|
-
"module": "./dist/index.js",
|
|
9
7
|
"h3ravel": {
|
|
10
8
|
"providers": [
|
|
11
9
|
"DatabaseServiceProvider"
|
|
@@ -41,22 +39,22 @@
|
|
|
41
39
|
"laravel"
|
|
42
40
|
],
|
|
43
41
|
"dependencies": {
|
|
44
|
-
"@h3ravel/arquebus": "^1.29.0-alpha.
|
|
45
|
-
"@h3ravel/musket": "^1.29.0-alpha.
|
|
42
|
+
"@h3ravel/arquebus": "^1.29.0-alpha.15",
|
|
43
|
+
"@h3ravel/musket": "^1.29.0-alpha.15",
|
|
46
44
|
"sqlite3": "^6.0.1"
|
|
47
45
|
},
|
|
48
46
|
"peerDependencies": {
|
|
49
|
-
"@h3ravel/core": "^
|
|
50
|
-
"@h3ravel/shared": "^
|
|
51
|
-
"@h3ravel/filesystem": "^
|
|
52
|
-
"@h3ravel/support": "^
|
|
47
|
+
"@h3ravel/core": "^2.0.0-alpha.16",
|
|
48
|
+
"@h3ravel/shared": "^2.0.0-alpha.16",
|
|
49
|
+
"@h3ravel/filesystem": "^2.0.0-alpha.16",
|
|
50
|
+
"@h3ravel/support": "^2.0.0-alpha.16"
|
|
53
51
|
},
|
|
54
52
|
"devDependencies": {
|
|
55
53
|
"typescript": "^6.0.0"
|
|
56
54
|
},
|
|
57
55
|
"scripts": {
|
|
58
56
|
"build": "tsdown --config-loader unrun",
|
|
59
|
-
"dev": "
|
|
57
|
+
"dev": "tsdown --watch --config-loader unrun",
|
|
60
58
|
"start": "node dist/index.js",
|
|
61
59
|
"lint": "eslint . --ext .ts",
|
|
62
60
|
"test": "jest --passWithNoTests",
|
package/dist/index.cjs
DELETED
|
@@ -1,730 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region \0rolldown/runtime.js
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
-
get: ((k) => from[k]).bind(null, key),
|
|
14
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
-
value: mod,
|
|
21
|
-
enumerable: true
|
|
22
|
-
}) : target, mod));
|
|
23
|
-
//#endregion
|
|
24
|
-
let _h3ravel_shared = require("@h3ravel/shared");
|
|
25
|
-
let node_fs_promises = require("node:fs/promises");
|
|
26
|
-
let _h3ravel_musket = require("@h3ravel/musket");
|
|
27
|
-
let _h3ravel_support = require("@h3ravel/support");
|
|
28
|
-
let dayjs = require("dayjs");
|
|
29
|
-
dayjs = __toESM(dayjs, 1);
|
|
30
|
-
let node_path = require("node:path");
|
|
31
|
-
node_path = __toESM(node_path, 1);
|
|
32
|
-
let _h3ravel_arquebus_migrations = require("@h3ravel/arquebus/migrations");
|
|
33
|
-
let _h3ravel_arquebus_relations = require("@h3ravel/arquebus/relations");
|
|
34
|
-
let _h3ravel_arquebus = require("@h3ravel/arquebus");
|
|
35
|
-
let _h3ravel_contracts = require("@h3ravel/contracts");
|
|
36
|
-
//#region src/Utils/TableGuesser.ts
|
|
37
|
-
var TableGuesser = class TableGuesser {
|
|
38
|
-
static CREATE_PATTERNS = [/^create_(\w+)_table$/, /^create_(\w+)$/];
|
|
39
|
-
static CHANGE_PATTERNS = [/.+_(to|from|in)_(\w+)_table$/, /.+_(to|from|in)_(\w+)$/];
|
|
40
|
-
static guess(migration) {
|
|
41
|
-
for (const pattern of TableGuesser.CREATE_PATTERNS) {
|
|
42
|
-
const matches = migration.match(pattern);
|
|
43
|
-
if (matches) return [matches[1], true];
|
|
44
|
-
}
|
|
45
|
-
for (const pattern of TableGuesser.CHANGE_PATTERNS) {
|
|
46
|
-
const matches = migration.match(pattern);
|
|
47
|
-
if (matches) return [matches[2], false];
|
|
48
|
-
}
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region src/Commands/MakeCommand.ts
|
|
54
|
-
var MakeCommand = class extends _h3ravel_musket.Command {
|
|
55
|
-
/**
|
|
56
|
-
* The name and signature of the console command.
|
|
57
|
-
*
|
|
58
|
-
* @var string
|
|
59
|
-
*/
|
|
60
|
-
signature = `#make:
|
|
61
|
-
{migration : Generates a new database migration class.
|
|
62
|
-
| {--t|table : The table to migrate}
|
|
63
|
-
| {--c|create : The table to be created}
|
|
64
|
-
| {--l|type=ts : The file type to generate}
|
|
65
|
-
}
|
|
66
|
-
{factory : Create a new model factory.
|
|
67
|
-
| {--force : Create the factory even if it already exists}
|
|
68
|
-
| {--l|type=ts : The file type to generate}
|
|
69
|
-
}
|
|
70
|
-
{seeder : Create a new seeder class.
|
|
71
|
-
| {--force : Create the seeder even if it already exists}
|
|
72
|
-
| {--l|type=ts : The file type to generate}
|
|
73
|
-
}
|
|
74
|
-
{model : Create a new Eloquent model class.
|
|
75
|
-
| {--api : Indicates if the generated controller should be an API resource controller}
|
|
76
|
-
| {--c|controller : Create a new controller for the model}
|
|
77
|
-
| {--f|factory : Create a new factory for the model}
|
|
78
|
-
| {--m|migration : Create a new migration file for the model}
|
|
79
|
-
| {--r|resource : Indicates if the generated controller should be a resource controller}
|
|
80
|
-
| {--a|all : Generate a migration, seeder, factory, policy, resource controller, and form request classes for the model}
|
|
81
|
-
| {--s|seed : Create a new seeder for the model}
|
|
82
|
-
| {--l|type=ts : The file type to generate}
|
|
83
|
-
| {--force : Create the model even if it already exists}
|
|
84
|
-
}
|
|
85
|
-
{^name : The name of the [name] to generate}
|
|
86
|
-
`;
|
|
87
|
-
/**
|
|
88
|
-
* The console command description.
|
|
89
|
-
*
|
|
90
|
-
* @var string
|
|
91
|
-
*/
|
|
92
|
-
description = "Generate component classes";
|
|
93
|
-
async handle() {
|
|
94
|
-
const command = this.dictionary.baseCommand ?? this.dictionary.name;
|
|
95
|
-
if (!this.argument("name")) this.program.error("Please provide a valid name for the " + command);
|
|
96
|
-
const methods = {
|
|
97
|
-
migration: "makeMigration",
|
|
98
|
-
factory: "makeFactory",
|
|
99
|
-
seeder: "makeSeeder",
|
|
100
|
-
model: "makeModel"
|
|
101
|
-
};
|
|
102
|
-
console.log("");
|
|
103
|
-
await this[methods[command]]();
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Generate a new database migration class
|
|
107
|
-
*/
|
|
108
|
-
async makeMigration() {
|
|
109
|
-
const type = this.option("type", "ts");
|
|
110
|
-
const name = this.argument("name");
|
|
111
|
-
const datePrefix = (0, dayjs.default)().format("YYYY_MM_DD_HHmmss");
|
|
112
|
-
const path = database_path(`migrations/${datePrefix}_${name}.${type}`);
|
|
113
|
-
const dbPkgPath = _h3ravel_shared.FileSystem.findModulePkg("@h3ravel/database", this.kernel.cwd) ?? "";
|
|
114
|
-
let create = this.option("create", false);
|
|
115
|
-
let table = this.option("table");
|
|
116
|
-
if (!table && typeof create === "string") {
|
|
117
|
-
table = create;
|
|
118
|
-
create = true;
|
|
119
|
-
}
|
|
120
|
-
if (!table) {
|
|
121
|
-
const guessed = TableGuesser.guess(name);
|
|
122
|
-
table = guessed[0];
|
|
123
|
-
create = !!guessed[1];
|
|
124
|
-
}
|
|
125
|
-
let stub = await (0, node_fs_promises.readFile)(node_path.default.join(dbPkgPath, this.getStubName("migration", type, {
|
|
126
|
-
table,
|
|
127
|
-
create
|
|
128
|
-
})), "utf-8");
|
|
129
|
-
if (table !== null) stub = stub.replace(/DummyTable|{{\s*table\s*}}/g, table);
|
|
130
|
-
_h3ravel_shared.Logger.info("INFO: Creating Migration");
|
|
131
|
-
await this.kernel.ensureDirectoryExists(node_path.default.dirname(path));
|
|
132
|
-
await (0, node_fs_promises.writeFile)(path, stub);
|
|
133
|
-
_h3ravel_shared.Logger.split("INFO: Migration Created", _h3ravel_shared.Logger.log(node_path.default.basename(path), "gray", false));
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Create a new model factory
|
|
137
|
-
*/
|
|
138
|
-
makeFactory() {
|
|
139
|
-
_h3ravel_shared.Logger.success("Factory support is not yet available");
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Create a new seeder class
|
|
143
|
-
*/
|
|
144
|
-
async makeSeeder() {
|
|
145
|
-
const type = this.option("type", "ts");
|
|
146
|
-
const name = this.argument("name");
|
|
147
|
-
const force = this.option("force");
|
|
148
|
-
const path = database_path(`seeders/${_h3ravel_support.Str.snake(name)}.${type}`);
|
|
149
|
-
/** Check if the model already exists */
|
|
150
|
-
if (!force && await _h3ravel_shared.FileSystem.fileExists(path)) _h3ravel_shared.Logger.error(`ERORR: ${name} already exists`);
|
|
151
|
-
const dbPkgPath = _h3ravel_shared.FileSystem.findModulePkg("@h3ravel/database", this.kernel.cwd) ?? "";
|
|
152
|
-
let stub = await (0, node_fs_promises.readFile)(node_path.default.join(dbPkgPath, this.getStubName("seeder", type)), "utf-8");
|
|
153
|
-
stub = stub.replace(/{{ name }}/g, name);
|
|
154
|
-
await (0, node_fs_promises.writeFile)(path, stub);
|
|
155
|
-
_h3ravel_shared.Logger.info(`INFO: Seeder ${_h3ravel_shared.Logger.log(`[${node_path.default.relative(process.cwd(), path)}]`, "bold", false)} created successfully.`);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Generate a new Arquebus model class
|
|
159
|
-
*/
|
|
160
|
-
async makeModel() {
|
|
161
|
-
const type = this.option("type", "ts");
|
|
162
|
-
const name = this.argument("name");
|
|
163
|
-
const force = this.option("force");
|
|
164
|
-
const path = app_path(`Models/${_h3ravel_support.Str.lower(name)}.${type}`);
|
|
165
|
-
/** The model is scoped to a path make sure to create the associated directories */
|
|
166
|
-
if (name.includes("/")) await (0, node_fs_promises.mkdir)(_h3ravel_support.Str.beforeLast(path, "/"), { recursive: true });
|
|
167
|
-
/** Check if the model already exists */
|
|
168
|
-
if (!force && await _h3ravel_shared.FileSystem.fileExists(path)) _h3ravel_shared.Logger.error(`ERORR: ${name} model already exists`);
|
|
169
|
-
const dbPkgPath = _h3ravel_shared.FileSystem.findModulePkg("@h3ravel/database", this.kernel.cwd) ?? "";
|
|
170
|
-
let stub = await (0, node_fs_promises.readFile)(node_path.default.join(dbPkgPath, `dist/stubs/model-${type}.stub`), "utf-8");
|
|
171
|
-
stub = stub.replace(/{{ name }}/g, name);
|
|
172
|
-
await (0, node_fs_promises.writeFile)(path, stub);
|
|
173
|
-
_h3ravel_shared.Logger.info(`INFO: Model ${_h3ravel_shared.Logger.log(`[${node_path.default.relative(process.cwd(), path)}]`, "bold", false)} created successfully.`);
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Ge the database migration file name
|
|
177
|
-
*
|
|
178
|
-
* @param table
|
|
179
|
-
* @param create
|
|
180
|
-
* @param type
|
|
181
|
-
* @returns
|
|
182
|
-
*/
|
|
183
|
-
getStubName(type, ext = "ts", { table, create } = {}) {
|
|
184
|
-
let stub;
|
|
185
|
-
if (type === "migration") {
|
|
186
|
-
if (!table) stub = `migration-${ext}.stub`;
|
|
187
|
-
else if (create) stub = `migration.create-${ext}.stub`;
|
|
188
|
-
else stub = `migration.update-${ext}.stub`;
|
|
189
|
-
return "dist/stubs/" + stub;
|
|
190
|
-
} else return `dist/stubs/${type}-${ext}.stub`;
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/Commands/MigrateCommand.ts
|
|
195
|
-
var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
196
|
-
/**
|
|
197
|
-
* The current database connection
|
|
198
|
-
*/
|
|
199
|
-
connection;
|
|
200
|
-
/**
|
|
201
|
-
* The base path for all database operations
|
|
202
|
-
*/
|
|
203
|
-
databasePath = database_path();
|
|
204
|
-
/**
|
|
205
|
-
* The name and signature of the console command.
|
|
206
|
-
*
|
|
207
|
-
* @var string
|
|
208
|
-
*/
|
|
209
|
-
signature = `migrate:
|
|
210
|
-
{fresh : Drop all tables and re-run all migrations. | {--seed : Indicates if the seed task should be re-run} | {--seeder : The file name of the root seeder}}
|
|
211
|
-
{install : Create the migration repository.}
|
|
212
|
-
{refresh : Reset and re-run all migrations. | {--seed : Indicates if the seed task should be re-run} | {--seeder : The file name of the root seeder}}
|
|
213
|
-
{reset : Rollback all database migrations.}
|
|
214
|
-
{rollback : Rollback the last database migration.}
|
|
215
|
-
{status : Show the status of each migration.}
|
|
216
|
-
{publish : Publish any migration files from installed packages. | {package : The package to publish migrations from}}
|
|
217
|
-
{^--c|connection=mysql : The database connection to use : [mysql, sqlite, mariadb, pgsql]}
|
|
218
|
-
{--seed : Seed the database}
|
|
219
|
-
{--seeder : The file name of the root seeder}
|
|
220
|
-
{^--force : Force the operation to run when in production}
|
|
221
|
-
`;
|
|
222
|
-
/**
|
|
223
|
-
* The console command description.
|
|
224
|
-
*
|
|
225
|
-
* @var string
|
|
226
|
-
*/
|
|
227
|
-
description = "Run all pending migrations.";
|
|
228
|
-
/**
|
|
229
|
-
* Execute the console command.
|
|
230
|
-
*/
|
|
231
|
-
async handle() {
|
|
232
|
-
const force = this.option("force");
|
|
233
|
-
const command = this.dictionary.name ?? this.dictionary.baseCommand;
|
|
234
|
-
if (env("APP_ENV") === "production" && !force) this.error("INFO: Unable to run migration, your app is currently in production.");
|
|
235
|
-
this.connection = Object.entries(arquebusConfig(config("database"))).find(([client]) => client === config("database.default"))?.at(1);
|
|
236
|
-
this.connection.migrations = {
|
|
237
|
-
path: "migrations",
|
|
238
|
-
table: "migrations"
|
|
239
|
-
};
|
|
240
|
-
await this[{
|
|
241
|
-
migrate: "migrateRun",
|
|
242
|
-
fresh: "migrateFresh",
|
|
243
|
-
install: "migrateInstall",
|
|
244
|
-
refresh: "migrateRefresh",
|
|
245
|
-
reset: "migrateReset",
|
|
246
|
-
rollback: "migrateRollback",
|
|
247
|
-
status: "migrateStatus",
|
|
248
|
-
publish: "migratePublish"
|
|
249
|
-
}[command]]();
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Run all pending migrations.
|
|
253
|
-
*/
|
|
254
|
-
async migrateRun() {
|
|
255
|
-
try {
|
|
256
|
-
await new _h3ravel_arquebus_migrations.Migrate(this.databasePath).run(this.connection, this.options(), true);
|
|
257
|
-
if (this.option("seed")) await this.runSeeders();
|
|
258
|
-
} catch (e) {
|
|
259
|
-
_h3ravel_shared.Logger.error("ERROR: " + e);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Drop all tables and re-run all migrations.
|
|
264
|
-
*/
|
|
265
|
-
async migrateFresh() {
|
|
266
|
-
try {
|
|
267
|
-
await new _h3ravel_arquebus_migrations.Migrate(this.databasePath).fresh(this.connection, this.options(), true);
|
|
268
|
-
if (this.option("seed")) await this.runSeeders();
|
|
269
|
-
} catch (e) {
|
|
270
|
-
_h3ravel_shared.Logger.error("ERROR: " + e);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Reset and re-run all migrations.
|
|
275
|
-
*/
|
|
276
|
-
async migrateRefresh() {
|
|
277
|
-
try {
|
|
278
|
-
await new _h3ravel_arquebus_migrations.Migrate(this.databasePath).refresh(this.connection, this.options(), true);
|
|
279
|
-
if (this.option("seed")) await this.runSeeders();
|
|
280
|
-
} catch (e) {
|
|
281
|
-
_h3ravel_shared.Logger.error("ERROR: " + e);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Create the migration repository.
|
|
286
|
-
*/
|
|
287
|
-
async migrateInstall() {
|
|
288
|
-
try {
|
|
289
|
-
const migrate = new _h3ravel_arquebus_migrations.Migrate(this.databasePath);
|
|
290
|
-
const { migrator } = await migrate.setupConnection(this.connection);
|
|
291
|
-
await migrate.prepareDatabase(migrator);
|
|
292
|
-
_h3ravel_shared.Logger.success("Migration repository installed.");
|
|
293
|
-
} catch (e) {
|
|
294
|
-
_h3ravel_shared.Logger.error("ERROR: " + e);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Rollback all database migrations.
|
|
299
|
-
*/
|
|
300
|
-
async migrateReset() {
|
|
301
|
-
try {
|
|
302
|
-
await new _h3ravel_arquebus_migrations.Migrate(this.databasePath).reset(this.connection, this.options(), true);
|
|
303
|
-
} catch (e) {
|
|
304
|
-
_h3ravel_shared.Logger.error("ERROR: " + e);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Rollback the last database migration.
|
|
309
|
-
*/
|
|
310
|
-
async migrateRollback() {
|
|
311
|
-
try {
|
|
312
|
-
await new _h3ravel_arquebus_migrations.Migrate(this.databasePath).rollback(this.connection, this.options(), true);
|
|
313
|
-
} catch (e) {
|
|
314
|
-
_h3ravel_shared.Logger.error("ERROR: " + e);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Show the status of each migration.
|
|
319
|
-
*/
|
|
320
|
-
async migrateStatus() {
|
|
321
|
-
const migrations = await new _h3ravel_arquebus_migrations.Migrate(this.databasePath, void 0, (msg, sts) => {
|
|
322
|
-
const hint = _h3ravel_shared.Logger.parse([[" Did you forget to run", "white"], ["`musket migrate:install`?", "grey"]], " ", false);
|
|
323
|
-
if (sts) _h3ravel_shared.Logger[sts](msg + hint, sts === "error", true);
|
|
324
|
-
}).status(this.connection, this.options(), true);
|
|
325
|
-
try {
|
|
326
|
-
if (migrations.length > 0) {
|
|
327
|
-
_h3ravel_shared.Logger.twoColumnDetail("Migration name", "Batch / Status");
|
|
328
|
-
migrations.forEach((migration) => {
|
|
329
|
-
const status = migration.ran ? _h3ravel_shared.Logger.parse([[`[${migration.batch}]`, "white"], ["Ran", "green"]], " ", false) : _h3ravel_shared.Logger.parse([["Pending", "yellow"]], "", false);
|
|
330
|
-
_h3ravel_shared.Logger.twoColumnDetail(migration.name, status);
|
|
331
|
-
});
|
|
332
|
-
} else _h3ravel_shared.Logger.info("No migrations found");
|
|
333
|
-
} catch (e) {
|
|
334
|
-
_h3ravel_shared.Logger.error(["ERROR: " + e, "Did you run musket migrate:install"]);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Publish any migration files from installed packages.
|
|
339
|
-
*/
|
|
340
|
-
async migratePublish() {
|
|
341
|
-
const name = this.argument("package");
|
|
342
|
-
try {
|
|
343
|
-
/** Find the requested package */
|
|
344
|
-
const packagePath = _h3ravel_shared.FileSystem.findModulePkg(name) ?? null;
|
|
345
|
-
if (!packagePath) throw new Error("Package not found");
|
|
346
|
-
/** Get the package,json and instanciate the migration creator */
|
|
347
|
-
const pkgJson = await import(node_path.default.join(packagePath, "package.json"));
|
|
348
|
-
const creator = new _h3ravel_arquebus_migrations.MigrationCreator(node_path.default.join(packagePath, pkgJson.migrations ?? "migrations"));
|
|
349
|
-
const info = _h3ravel_shared.Logger.parse([[" Publishing migrations from", "white"], [`${pkgJson.name}@${pkgJson.version}`, ["italic", "gray"]]], " ", false);
|
|
350
|
-
_h3ravel_shared.Logger.info(`INFO: ${info}`);
|
|
351
|
-
try {
|
|
352
|
-
/** Publish any existing migrations */
|
|
353
|
-
await creator.publish(this.databasePath, (fileName) => {
|
|
354
|
-
_h3ravel_shared.Logger.twoColumnDetail(fileName, _h3ravel_shared.Logger.parse([["PUBLISHED", "green"]], "", false));
|
|
355
|
-
});
|
|
356
|
-
} catch {
|
|
357
|
-
_h3ravel_shared.Logger.error([`ERROR: ${name} has no publishable migrations.`]);
|
|
358
|
-
}
|
|
359
|
-
} catch (e) {
|
|
360
|
-
const hint = _h3ravel_shared.Logger.parse([[" Did you forget to run", "white"], [`\`${await _h3ravel_shared.Resolver.getPakageInstallCommand(name)}\``, "grey"]], " ", false);
|
|
361
|
-
const error = _h3ravel_shared.Logger.parse([
|
|
362
|
-
["Package `", "white"],
|
|
363
|
-
[name, "grey"],
|
|
364
|
-
["` not found", "white"]
|
|
365
|
-
], "", false);
|
|
366
|
-
_h3ravel_shared.Logger.error([
|
|
367
|
-
"ERROR: " + error,
|
|
368
|
-
hint + "?",
|
|
369
|
-
String(e)
|
|
370
|
-
]);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Run database seeders
|
|
375
|
-
*/
|
|
376
|
-
async runSeeders() {
|
|
377
|
-
await new SeedCommand(this.app, this.kernel).setInput({
|
|
378
|
-
class: this.option("seeder", "DatabaseSeeder"),
|
|
379
|
-
force: this.option("force")
|
|
380
|
-
}, [], [], {}, this.program).handle();
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
//#endregion
|
|
384
|
-
//#region src/Commands/SeedCommand.ts
|
|
385
|
-
var SeedCommand = class extends _h3ravel_musket.Command {
|
|
386
|
-
/**
|
|
387
|
-
* The current query builder instance
|
|
388
|
-
*/
|
|
389
|
-
queryBuilder;
|
|
390
|
-
/**
|
|
391
|
-
* The current database connection name
|
|
392
|
-
*/
|
|
393
|
-
connection;
|
|
394
|
-
/**
|
|
395
|
-
* The name and signature of the console command.
|
|
396
|
-
*
|
|
397
|
-
* @var string
|
|
398
|
-
*/
|
|
399
|
-
signature = `db:seed
|
|
400
|
-
{--class=DatabaseSeeder : The file name of the root seeder}
|
|
401
|
-
{--d|database? : The database connection to use}
|
|
402
|
-
{--force : Force the operation to run when in production}
|
|
403
|
-
`;
|
|
404
|
-
/**
|
|
405
|
-
* The console command description.
|
|
406
|
-
*
|
|
407
|
-
* @var string
|
|
408
|
-
*/
|
|
409
|
-
description = "Seed the database with records.";
|
|
410
|
-
/**
|
|
411
|
-
* Execute the console command.
|
|
412
|
-
*/
|
|
413
|
-
async handle() {
|
|
414
|
-
const file = this.option("class");
|
|
415
|
-
const force = this.option("force");
|
|
416
|
-
const database = this.option("database");
|
|
417
|
-
this.newLine();
|
|
418
|
-
if (env("APP_ENV") === "production" && !force) this.error("INFO: Unable to run seeders, your app is currently in production.");
|
|
419
|
-
this.connection = database ?? config("database.default");
|
|
420
|
-
this.queryBuilder = DB.instance(this.connection);
|
|
421
|
-
if (!this.connection) this.error("ERROR: Unknown database connection.");
|
|
422
|
-
let path = node_path.default.join(process.cwd(), file);
|
|
423
|
-
const [f1, f2] = [_h3ravel_shared.FileSystem.resolveFileUp(_h3ravel_support.Str.snake(file), ["js", "ts"], database_path("seeders")), _h3ravel_shared.FileSystem.resolveFileUp(_h3ravel_support.Str.studly(file), ["js", "ts"], database_path("seeders"))];
|
|
424
|
-
if (!f1 && !f2) {
|
|
425
|
-
/**
|
|
426
|
-
* Try to find the path assuming it's relative to cwd
|
|
427
|
-
*/
|
|
428
|
-
if (!await _h3ravel_shared.FileSystem.fileExists(path)) path = database_path(node_path.default.join("seeders", file));
|
|
429
|
-
/**
|
|
430
|
-
* Now try to find the path knowing it's relative to database_path
|
|
431
|
-
*/
|
|
432
|
-
if (!await _h3ravel_shared.FileSystem.fileExists(path)) this.error(`ERROR: Seeder ${_h3ravel_shared.Logger.log(`[${file}]`, "bold", false)} not found.`);
|
|
433
|
-
} else path = String(f1 ?? f2);
|
|
434
|
-
const { default: seeder } = await import(path);
|
|
435
|
-
if (seeder) {
|
|
436
|
-
this.info("INFO: Seeding database.");
|
|
437
|
-
this.newLine();
|
|
438
|
-
await new seeder(this.app, this).run(this.queryBuilder);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
//#endregion
|
|
443
|
-
//#region src/Configuration.ts
|
|
444
|
-
const arquebusConfig = (config) => {
|
|
445
|
-
const sqliteDatabase = config.connections.sqlite.database;
|
|
446
|
-
return {
|
|
447
|
-
sqlite: {
|
|
448
|
-
client: config.connections.sqlite.driver,
|
|
449
|
-
connection: {
|
|
450
|
-
filename: sqliteDatabase === ":memory:" ? sqliteDatabase : database_path(sqliteDatabase),
|
|
451
|
-
debug: config.connections.sqlite.debug,
|
|
452
|
-
flags: config.connections.sqlite.flags,
|
|
453
|
-
options: config.connections.sqlite.options,
|
|
454
|
-
expirationChecker: config.connections.sqlite.expirationChecker
|
|
455
|
-
},
|
|
456
|
-
useNullAsDefault: config.connections.sqlite.useNullAsDefault
|
|
457
|
-
},
|
|
458
|
-
mysql: {
|
|
459
|
-
client: config.connections.mysql.driver,
|
|
460
|
-
connection: {
|
|
461
|
-
host: config.connections.mysql.host ?? "localhost",
|
|
462
|
-
port: config.connections.mysql.port ?? 3306,
|
|
463
|
-
user: config.connections.mysql.username ?? "root",
|
|
464
|
-
password: config.connections.mysql.password,
|
|
465
|
-
database: config.connections.mysql.database,
|
|
466
|
-
charset: config.connections.mysql.charset,
|
|
467
|
-
socketPath: config.connections.mysql.unix_socket,
|
|
468
|
-
localAddress: config.connections.mysql.url
|
|
469
|
-
}
|
|
470
|
-
},
|
|
471
|
-
mariadb: {
|
|
472
|
-
client: config.connections.mariadb.driver,
|
|
473
|
-
connection: {
|
|
474
|
-
host: config.connections.mariadb.host ?? "localhost",
|
|
475
|
-
port: config.connections.mariadb.port ?? 3306,
|
|
476
|
-
user: config.connections.mariadb.username ?? "root",
|
|
477
|
-
password: config.connections.mariadb.password,
|
|
478
|
-
database: config.connections.mariadb.database,
|
|
479
|
-
charset: config.connections.mariadb.charset,
|
|
480
|
-
socketPath: config.connections.mariadb.unix_socket,
|
|
481
|
-
localAddress: config.connections.mariadb.url,
|
|
482
|
-
expirationChecker: config.connections.mariadb.expirationChecker
|
|
483
|
-
}
|
|
484
|
-
},
|
|
485
|
-
pgsql: {
|
|
486
|
-
client: "pg",
|
|
487
|
-
connection: {
|
|
488
|
-
host: config.connections.pgsql.host ?? "localhost",
|
|
489
|
-
port: config.connections.pgsql.port ?? 3306,
|
|
490
|
-
user: config.connections.pgsql.username ?? "root",
|
|
491
|
-
password: config.connections.pgsql.password,
|
|
492
|
-
database: config.connections.pgsql.database,
|
|
493
|
-
charset: config.connections.mysql.charset,
|
|
494
|
-
connectionString: config.connections.pgsql.url,
|
|
495
|
-
expirationChecker: config.connections.pgsql.expirationChecker
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
};
|
|
499
|
-
};
|
|
500
|
-
//#endregion
|
|
501
|
-
//#region src/Model.ts
|
|
502
|
-
var Model = class Model extends (0, _h3ravel_shared.mix)(_h3ravel_contracts.UrlRoutable, _h3ravel_arquebus.Model) {
|
|
503
|
-
/**
|
|
504
|
-
* Retrieve the model for a bound value.
|
|
505
|
-
*
|
|
506
|
-
* @param value
|
|
507
|
-
* @param field
|
|
508
|
-
*/
|
|
509
|
-
resolveRouteBinding(value, field) {
|
|
510
|
-
return this.resolveRouteBindingQuery(this.newQuery(), value, field).first();
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* Retrieve the model for a bound value.
|
|
514
|
-
*
|
|
515
|
-
* @param query
|
|
516
|
-
* @param value
|
|
517
|
-
* @param field
|
|
518
|
-
*/
|
|
519
|
-
resolveRouteBindingQuery(query, value, field = null) {
|
|
520
|
-
return query.where(field ?? this.getRouteKeyName(), value);
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Retrieve the model for a bound value.
|
|
524
|
-
*
|
|
525
|
-
* @param value
|
|
526
|
-
* @param field
|
|
527
|
-
*/
|
|
528
|
-
resolveSoftDeletableRouteBinding(value, field) {
|
|
529
|
-
return this.resolveRouteBindingQuery(this.newQuery(), value, field).withTrashed().first();
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Retrieve the child model for a bound value.
|
|
533
|
-
*
|
|
534
|
-
* @param childType
|
|
535
|
-
* @param value
|
|
536
|
-
* @param field
|
|
537
|
-
*/
|
|
538
|
-
resolveChildRouteBinding(childType, value, field) {
|
|
539
|
-
return this.resolveChildRouteBindingQuery(childType, value, field).first();
|
|
540
|
-
}
|
|
541
|
-
/**
|
|
542
|
-
* Retrieve the child model for a bound value.
|
|
543
|
-
*
|
|
544
|
-
* @param childType
|
|
545
|
-
* @param value
|
|
546
|
-
* @param field
|
|
547
|
-
*/
|
|
548
|
-
resolveSoftDeletableChildRouteBinding(childType, value, field) {
|
|
549
|
-
return this.resolveChildRouteBindingQuery(childType, value, field).withTrashed().first();
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Retrieve the child model query for a bound value.
|
|
553
|
-
*
|
|
554
|
-
* @param childType
|
|
555
|
-
* @param value
|
|
556
|
-
* @param field
|
|
557
|
-
*/
|
|
558
|
-
resolveChildRouteBindingQuery(childType, value, field) {
|
|
559
|
-
const relationship = this[this.childRouteBindingRelationshipName(childType)]();
|
|
560
|
-
field = field || relationship.getRelated().getRouteKeyName();
|
|
561
|
-
if (relationship instanceof _h3ravel_arquebus_relations.HasManyThrough || relationship instanceof _h3ravel_arquebus_relations.BelongsToMany) field = relationship.getRelated().qualifyColumn(field);
|
|
562
|
-
return relationship instanceof Model ? relationship.resolveRouteBindingQuery(relationship.newQuery(), value, field) : relationship.getRelated().resolveRouteBindingQuery(relationship, value, field);
|
|
563
|
-
}
|
|
564
|
-
/**
|
|
565
|
-
* Retrieve the child route model binding relationship name for the given child type.
|
|
566
|
-
*
|
|
567
|
-
* @param childType
|
|
568
|
-
*/
|
|
569
|
-
childRouteBindingRelationshipName(childType) {
|
|
570
|
-
return _h3ravel_support.Str.plural(_h3ravel_support.Str.camel(childType));
|
|
571
|
-
}
|
|
572
|
-
/**
|
|
573
|
-
* Get the value of the model's route key.
|
|
574
|
-
*/
|
|
575
|
-
getRouteKey() {
|
|
576
|
-
return this.getAttribute(this.getRouteKeyName());
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Get the route key for the model.
|
|
580
|
-
*/
|
|
581
|
-
getRouteKeyName() {
|
|
582
|
-
return this.getKeyName();
|
|
583
|
-
}
|
|
584
|
-
};
|
|
585
|
-
//#endregion
|
|
586
|
-
//#region src/Providers/DatabaseServiceProvider.ts
|
|
587
|
-
/**
|
|
588
|
-
* Database connection, ORM, migrations.
|
|
589
|
-
*
|
|
590
|
-
* Register DatabaseManager and QueryBuilder if required.
|
|
591
|
-
* Set up ORM models and relationships.
|
|
592
|
-
* Register migration and seeder commands.
|
|
593
|
-
*
|
|
594
|
-
*/
|
|
595
|
-
var DatabaseServiceProvider = class extends _h3ravel_support.ServiceProvider {
|
|
596
|
-
static priority = 994;
|
|
597
|
-
register() {
|
|
598
|
-
const config = this.app.make("config");
|
|
599
|
-
const connection = Object.entries(arquebusConfig(config.get("database"))).find(([client]) => client === config.get("database.default"))?.at(1);
|
|
600
|
-
if (connection) _h3ravel_arquebus.arquebus.addConnection(connection);
|
|
601
|
-
this.app.singleton("db", () => _h3ravel_arquebus.arquebus.fire());
|
|
602
|
-
/** Register Musket Commands */
|
|
603
|
-
this.registerCommands([
|
|
604
|
-
MigrateCommand,
|
|
605
|
-
MakeCommand,
|
|
606
|
-
SeedCommand
|
|
607
|
-
]);
|
|
608
|
-
}
|
|
609
|
-
};
|
|
610
|
-
//#endregion
|
|
611
|
-
//#region src/Query/DB.ts
|
|
612
|
-
var DB = class DB {
|
|
613
|
-
connection;
|
|
614
|
-
constructor(connection) {
|
|
615
|
-
if (connection) this.connection = connection;
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* New instance
|
|
619
|
-
*/
|
|
620
|
-
static table(name) {
|
|
621
|
-
return new DB().builder().table(name);
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Builder table instance
|
|
625
|
-
*/
|
|
626
|
-
static instance(connection) {
|
|
627
|
-
return new DB(connection).builder();
|
|
628
|
-
}
|
|
629
|
-
/**
|
|
630
|
-
* Builder transaction instance
|
|
631
|
-
*/
|
|
632
|
-
static transaction(callback) {
|
|
633
|
-
return new DB().builder().transaction(callback);
|
|
634
|
-
}
|
|
635
|
-
builder() {
|
|
636
|
-
return _h3ravel_arquebus.arquebus.getInstance().connection(this.connection);
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
//#endregion
|
|
640
|
-
//#region src/Seeder.ts
|
|
641
|
-
var Seeder = class Seeder extends _h3ravel_arquebus.Seeder {
|
|
642
|
-
app;
|
|
643
|
-
command;
|
|
644
|
-
/**
|
|
645
|
-
* Seeders that have been called at least one time.
|
|
646
|
-
*/
|
|
647
|
-
static called = [];
|
|
648
|
-
constructor(app, command) {
|
|
649
|
-
super();
|
|
650
|
-
this.app = app;
|
|
651
|
-
this.command = command;
|
|
652
|
-
}
|
|
653
|
-
async run(_conn, ..._args) {}
|
|
654
|
-
/**
|
|
655
|
-
* Run the given seeder class.
|
|
656
|
-
*
|
|
657
|
-
* @param className
|
|
658
|
-
* @param silent
|
|
659
|
-
* @param parameters
|
|
660
|
-
*
|
|
661
|
-
* @return this
|
|
662
|
-
*/
|
|
663
|
-
async call(className, silent = false, parameters = []) {
|
|
664
|
-
const classes = _h3ravel_support.Arr.wrap(className);
|
|
665
|
-
for (let i = 0; i < classes.length; i++) {
|
|
666
|
-
const instance = this.resolve(classes[i]);
|
|
667
|
-
const name = instance.constructor.name;
|
|
668
|
-
if (silent === false) await _h3ravel_shared.TaskManager.advancedTaskRunner([[name, "RUNNING"], [name, "DONE"]], async () => await instance.run(this.command.queryBuilder, ...parameters));
|
|
669
|
-
else await instance.run(this.command.queryBuilder, ...parameters);
|
|
670
|
-
Seeder.called.push(instance);
|
|
671
|
-
}
|
|
672
|
-
return this;
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* Resolve an instance of the given seeder class.
|
|
676
|
-
*
|
|
677
|
-
* @param className
|
|
678
|
-
*
|
|
679
|
-
* @return Seeder
|
|
680
|
-
*/
|
|
681
|
-
resolve(className) {
|
|
682
|
-
const instance = new className(this.app);
|
|
683
|
-
if (this.command) instance.setCommand(this.command);
|
|
684
|
-
return instance;
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Run the given seeder class.
|
|
688
|
-
*
|
|
689
|
-
* @param className
|
|
690
|
-
* @param silent
|
|
691
|
-
* @param parameters
|
|
692
|
-
*
|
|
693
|
-
* @return void
|
|
694
|
-
*/
|
|
695
|
-
async callWith(className, parameters) {
|
|
696
|
-
await this.call(className, false, parameters);
|
|
697
|
-
}
|
|
698
|
-
/**
|
|
699
|
-
* Silently run the given seeder class.
|
|
700
|
-
*
|
|
701
|
-
* @param className
|
|
702
|
-
* @param parameters
|
|
703
|
-
*
|
|
704
|
-
* @return void
|
|
705
|
-
*/
|
|
706
|
-
async callSilent(className, parameters = []) {
|
|
707
|
-
await this.call(className, true, parameters);
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Set the console command instance.
|
|
711
|
-
*
|
|
712
|
-
* @param command
|
|
713
|
-
*
|
|
714
|
-
* @return this
|
|
715
|
-
*/
|
|
716
|
-
setCommand(command) {
|
|
717
|
-
this.command = command;
|
|
718
|
-
return this;
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
|
-
//#endregion
|
|
722
|
-
exports.DB = DB;
|
|
723
|
-
exports.DatabaseServiceProvider = DatabaseServiceProvider;
|
|
724
|
-
exports.MakeCommand = MakeCommand;
|
|
725
|
-
exports.MigrateCommand = MigrateCommand;
|
|
726
|
-
exports.Model = Model;
|
|
727
|
-
exports.SeedCommand = SeedCommand;
|
|
728
|
-
exports.Seeder = Seeder;
|
|
729
|
-
exports.TableGuesser = TableGuesser;
|
|
730
|
-
exports.arquebusConfig = arquebusConfig;
|