@devbro/pashmak 0.1.0
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/README.md +11 -0
- package/dist/DatabaseServiceProvider.d.ts +13 -0
- package/dist/DatabaseServiceProvider.js +55 -0
- package/dist/DatabaseServiceProvider.js.map +1 -0
- package/dist/app/console/DefaultCommand.d.ts +9 -0
- package/dist/app/console/DefaultCommand.js +35 -0
- package/dist/app/console/DefaultCommand.js.map +1 -0
- package/dist/app/console/KeyGenerateCommand.d.ts +13 -0
- package/dist/app/console/KeyGenerateCommand.js +79 -0
- package/dist/app/console/KeyGenerateCommand.js.map +1 -0
- package/dist/app/console/StartCommand.d.ts +11 -0
- package/dist/app/console/StartCommand.js +49 -0
- package/dist/app/console/StartCommand.js.map +1 -0
- package/dist/app/console/generate/GenerateControllerCommand.d.ts +9 -0
- package/dist/app/console/generate/GenerateControllerCommand.js +56 -0
- package/dist/app/console/generate/GenerateControllerCommand.js.map +1 -0
- package/dist/app/console/generate/controller.tpl +30 -0
- package/dist/app/console/generate/index.d.ts +2 -0
- package/dist/app/console/generate/index.js +2 -0
- package/dist/app/console/generate/index.js.map +1 -0
- package/dist/app/console/index.d.ts +9 -0
- package/dist/app/console/index.js +7 -0
- package/dist/app/console/index.js.map +1 -0
- package/dist/app/console/migrate/MakeMigrateCommand.d.ts +9 -0
- package/dist/app/console/migrate/MakeMigrateCommand.js +51 -0
- package/dist/app/console/migrate/MakeMigrateCommand.js.map +1 -0
- package/dist/app/console/migrate/MigrateCommand.d.ts +9 -0
- package/dist/app/console/migrate/MigrateCommand.js +93 -0
- package/dist/app/console/migrate/MigrateCommand.js.map +1 -0
- package/dist/app/console/migrate/MigrateRollbackCommand.d.ts +9 -0
- package/dist/app/console/migrate/MigrateRollbackCommand.js +57 -0
- package/dist/app/console/migrate/MigrateRollbackCommand.js.map +1 -0
- package/dist/app/console/migrate/index.d.ts +4 -0
- package/dist/app/console/migrate/index.js +4 -0
- package/dist/app/console/migrate/index.js.map +1 -0
- package/dist/app/console/migrate/make_migration.tpl +15 -0
- package/dist/app/console/project/CreateProjectCommand.d.ts +14 -0
- package/dist/app/console/project/CreateProjectCommand.js +106 -0
- package/dist/app/console/project/CreateProjectCommand.js.map +1 -0
- package/dist/app/console/project/base_project/README.md.tpl +1 -0
- package/dist/app/console/project/base_project/package.json.tpl +67 -0
- package/dist/app/console/project/base_project/src/app/console/YourFirstCommand.ts.tpl +23 -0
- package/dist/app/console/project/base_project/src/app/console/index.ts.tpl +1 -0
- package/dist/app/console/project/base_project/src/app/controllers/HelloController.ts.tpl +16 -0
- package/dist/app/console/project/base_project/src/app/models/README.md.tpl +1 -0
- package/dist/app/console/project/base_project/src/boot.ts.tpl +0 -0
- package/dist/app/console/project/base_project/src/config/databases.ts.tpl +8 -0
- package/dist/app/console/project/base_project/src/config/default.ts.tpl +41 -0
- package/dist/app/console/project/base_project/src/config/loggers.ts.tpl +11 -0
- package/dist/app/console/project/base_project/src/config/storages.ts.tpl +7 -0
- package/dist/app/console/project/base_project/src/config/test.ts.tpl +1 -0
- package/dist/app/console/project/base_project/src/database/migrations/2025_05_30_41329_create_sample.ts.tpl +13 -0
- package/dist/app/console/project/base_project/src/helpers.ts.tpl +28 -0
- package/dist/app/console/project/base_project/src/index.ts.tpl +12 -0
- package/dist/app/console/project/base_project/src/initialize.ts.tpl +7 -0
- package/dist/app/console/project/base_project/src/middlewares.ts.tpl +16 -0
- package/dist/app/console/project/base_project/src/routes.ts.tpl +18 -0
- package/dist/app/console/project/base_project/src/schedules.ts.tpl +22 -0
- package/dist/app/console/project/base_project/tests/basic_test.spec.ts.tpl +27 -0
- package/dist/app/console/project/base_project/tsconfig.json.tpl +23 -0
- package/dist/app/console/project/base_project/tsup.config.ts.tpl +25 -0
- package/dist/app/console/project/base_project/vitest.config.ts.tpl +17 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +1 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/facades.d.ts +18 -0
- package/dist/facades.js +122 -0
- package/dist/facades.js.map +1 -0
- package/dist/helper.d.ts +1 -0
- package/dist/helper.js +2 -0
- package/dist/helper.js.map +1 -0
- package/dist/http.d.ts +1 -0
- package/dist/http.js +2 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +2 -0
- package/dist/logger.js.map +1 -0
- package/dist/orm.d.ts +1 -0
- package/dist/orm.js +2 -0
- package/dist/orm.js.map +1 -0
- package/dist/pashmak_cli.d.ts +1 -0
- package/dist/pashmak_cli.js +9 -0
- package/dist/pashmak_cli.js.map +1 -0
- package/dist/router.d.ts +9 -0
- package/dist/router.js +37 -0
- package/dist/router.js.map +1 -0
- package/dist/sql.d.ts +1 -0
- package/dist/sql.js +2 -0
- package/dist/sql.js.map +1 -0
- package/package.json +134 -0
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Middleware, Request, Response } from '@devbro/neko-router';
|
|
2
|
+
import { PostgresqlConnection } from '@devbro/neko-sql';
|
|
3
|
+
import { PoolConfig } from 'pg';
|
|
4
|
+
|
|
5
|
+
declare class DatabaseServiceProvider extends Middleware {
|
|
6
|
+
call(req: Request, res: Response, next: () => Promise<void>): Promise<void>;
|
|
7
|
+
private static instance;
|
|
8
|
+
register(): Promise<void>;
|
|
9
|
+
static getInstance(): DatabaseServiceProvider;
|
|
10
|
+
getConnection(db_config: PoolConfig): Promise<PostgresqlConnection>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { DatabaseServiceProvider };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { Middleware } from "@devbro/neko-router";
|
|
4
|
+
import { PostgresqlConnection } from "@devbro/neko-sql";
|
|
5
|
+
import { BaseModel } from "@devbro/neko-orm";
|
|
6
|
+
import { ctx } from "@devbro/neko-context";
|
|
7
|
+
import { config } from "@devbro/neko-config";
|
|
8
|
+
class DatabaseServiceProvider extends Middleware {
|
|
9
|
+
static {
|
|
10
|
+
__name(this, "DatabaseServiceProvider");
|
|
11
|
+
}
|
|
12
|
+
async call(req, res, next) {
|
|
13
|
+
const db_configs = config.get("databases");
|
|
14
|
+
const conns = [];
|
|
15
|
+
try {
|
|
16
|
+
for (const [name, db_config] of Object.entries(db_configs)) {
|
|
17
|
+
const conn = await this.getConnection(db_config);
|
|
18
|
+
ctx().set([
|
|
19
|
+
"database",
|
|
20
|
+
name
|
|
21
|
+
], conn);
|
|
22
|
+
conns.push(conn);
|
|
23
|
+
}
|
|
24
|
+
BaseModel.setConnection(() => ctx().getOrThrow([
|
|
25
|
+
"database",
|
|
26
|
+
"default"
|
|
27
|
+
]));
|
|
28
|
+
await next();
|
|
29
|
+
} finally {
|
|
30
|
+
for (const conn of conns) {
|
|
31
|
+
await conn.disconnect();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
static instance;
|
|
36
|
+
async register() {
|
|
37
|
+
}
|
|
38
|
+
static getInstance() {
|
|
39
|
+
if (!DatabaseServiceProvider.instance) {
|
|
40
|
+
DatabaseServiceProvider.instance = new DatabaseServiceProvider();
|
|
41
|
+
}
|
|
42
|
+
return DatabaseServiceProvider.instance;
|
|
43
|
+
}
|
|
44
|
+
async getConnection(db_config) {
|
|
45
|
+
const conn = new PostgresqlConnection(db_config);
|
|
46
|
+
if (!await conn.connect()) {
|
|
47
|
+
throw new Error("Failed to connect to the database");
|
|
48
|
+
}
|
|
49
|
+
return conn;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
DatabaseServiceProvider
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=DatabaseServiceProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/DatabaseServiceProvider.ts"],"sourcesContent":["import { Middleware } from \"@devbro/neko-router\";\nimport { Request, Response } from \"@devbro/neko-router\";\nimport { PostgresqlConnection } from \"@devbro/neko-sql\";\nimport { PoolConfig } from \"pg\";\nimport { Connection } from \"@devbro/neko-sql\";\nimport { BaseModel } from \"@devbro/neko-orm\";\nimport { ctx } from \"@devbro/neko-context\";\nimport { config } from \"@devbro/neko-config\";\n\nexport class DatabaseServiceProvider extends Middleware {\n async call(\n req: Request,\n res: Response,\n next: () => Promise<void>,\n ): Promise<void> {\n const db_configs: Record<string, PoolConfig & { name: string }> =\n config.get(\"databases\");\n\n const conns = [];\n try {\n for (const [name, db_config] of Object.entries(db_configs)) {\n const conn = await this.getConnection(db_config);\n ctx().set([\"database\", name], conn);\n conns.push(conn);\n }\n BaseModel.setConnection(() =>\n ctx().getOrThrow<Connection>([\"database\", \"default\"]),\n );\n await next();\n } finally {\n for (const conn of conns) {\n await conn.disconnect();\n }\n }\n }\n\n private static instance: DatabaseServiceProvider;\n\n async register(): Promise<void> {}\n\n static getInstance(): DatabaseServiceProvider {\n if (!DatabaseServiceProvider.instance) {\n DatabaseServiceProvider.instance = new DatabaseServiceProvider();\n }\n return DatabaseServiceProvider.instance;\n }\n\n async getConnection(db_config: PoolConfig): Promise<PostgresqlConnection> {\n const conn = new PostgresqlConnection(db_config);\n if (!(await conn.connect())) {\n throw new Error(\"Failed to connect to the database\");\n }\n return conn;\n }\n}\n"],"mappings":";;AAAA,SAASA,kBAAkB;AAE3B,SAASC,4BAA4B;AAGrC,SAASC,iBAAiB;AAC1B,SAASC,WAAW;AACpB,SAASC,cAAc;AAEhB,MAAMC,gCAAgCL,WAAAA;EAT7C,OAS6CA;;;EAC3C,MAAMM,KACJC,KACAC,KACAC,MACe;AACf,UAAMC,aACJN,OAAOO,IAAI,WAAA;AAEb,UAAMC,QAAQ,CAAA;AACd,QAAI;AACF,iBAAW,CAACC,MAAMC,SAAAA,KAAcC,OAAOC,QAAQN,UAAAA,GAAa;AAC1D,cAAMO,OAAO,MAAM,KAAKC,cAAcJ,SAAAA;AACtCX,YAAAA,EAAMgB,IAAI;UAAC;UAAYN;WAAOI,IAAAA;AAC9BL,cAAMQ,KAAKH,IAAAA;MACb;AACAf,gBAAUmB,cAAc,MACtBlB,IAAAA,EAAMmB,WAAuB;QAAC;QAAY;OAAU,CAAA;AAEtD,YAAMb,KAAAA;IACR,UAAA;AACE,iBAAWQ,QAAQL,OAAO;AACxB,cAAMK,KAAKM,WAAU;MACvB;IACF;EACF;EAEA,OAAeC;EAEf,MAAMC,WAA0B;EAAC;EAEjC,OAAOC,cAAuC;AAC5C,QAAI,CAACrB,wBAAwBmB,UAAU;AACrCnB,8BAAwBmB,WAAW,IAAInB,wBAAAA;IACzC;AACA,WAAOA,wBAAwBmB;EACjC;EAEA,MAAMN,cAAcJ,WAAsD;AACxE,UAAMG,OAAO,IAAIhB,qBAAqBa,SAAAA;AACtC,QAAI,CAAE,MAAMG,KAAKU,QAAO,GAAK;AAC3B,YAAM,IAAIC,MAAM,mCAAA;IAClB;AACA,WAAOX;EACT;AACF;","names":["Middleware","PostgresqlConnection","BaseModel","ctx","config","DatabaseServiceProvider","call","req","res","next","db_configs","get","conns","name","db_config","Object","entries","conn","getConnection","set","push","setConnection","getOrThrow","disconnect","instance","register","getInstance","connect","Error"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { Command } from "clipanion";
|
|
4
|
+
import { cli } from "../../facades";
|
|
5
|
+
class DefaultCommand extends Command {
|
|
6
|
+
static {
|
|
7
|
+
__name(this, "DefaultCommand");
|
|
8
|
+
}
|
|
9
|
+
static usage = Command.Usage({
|
|
10
|
+
category: `Main`,
|
|
11
|
+
description: `server management command line.`,
|
|
12
|
+
details: `
|
|
13
|
+
The base command for running and managing your server.
|
|
14
|
+
|
|
15
|
+
Make sure you understand how things work.
|
|
16
|
+
`,
|
|
17
|
+
examples: []
|
|
18
|
+
});
|
|
19
|
+
async execute() {
|
|
20
|
+
const commandList = cli().registrations;
|
|
21
|
+
const paths = [];
|
|
22
|
+
commandList.forEach((index, val) => paths.push(index.builder.paths[0]?.join(" ") || ""));
|
|
23
|
+
console.log("Available commands:");
|
|
24
|
+
for (const cmd of paths) {
|
|
25
|
+
if (cmd) {
|
|
26
|
+
console.log(cmd);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
cli().register(DefaultCommand);
|
|
32
|
+
export {
|
|
33
|
+
DefaultCommand
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=DefaultCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/app/console/DefaultCommand.ts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { cli } from \"../../facades\";\n\nexport class DefaultCommand extends Command {\n static usage = Command.Usage({\n category: `Main`,\n description: `server management command line.`,\n details: `\n The base command for running and managing your server.\n\n Make sure you understand how things work.\n `,\n examples: [],\n });\n\n async execute() {\n // @ts-ignore\n const commandList = cli().registrations; //.definitions().map((def:any) => def.paths.map((path:any) => path.join(' '))).flat();\n\n const paths: string[] = [];\n commandList.forEach((index, val) =>\n paths.push(index.builder.paths[0]?.join(\" \") || \"\"),\n );\n\n console.log(\"Available commands:\");\n for (const cmd of paths) {\n if(cmd) {\n console.log(cmd);\n }\n }\n }\n}\n\ncli().register(DefaultCommand);\n"],"mappings":";;AAAA,SAASA,eAAuB;AAChC,SAASC,WAAW;AAEb,MAAMC,uBAAuBF,QAAAA;EAHpC,OAGoCA;;;EAClC,OAAOG,QAAQH,QAAQI,MAAM;IAC3BC,UAAU;IACVC,aAAa;IACbC,SAAS;;;;;IAKTC,UAAU,CAAA;EACZ,CAAA;EAEA,MAAMC,UAAU;AAEd,UAAMC,cAAcT,IAAAA,EAAMU;AAE1B,UAAMC,QAAkB,CAAA;AACxBF,gBAAYG,QAAQ,CAACC,OAAOC,QAC1BH,MAAMI,KAAKF,MAAMG,QAAQL,MAAM,CAAA,GAAIM,KAAK,GAAA,KAAQ,EAAA,CAAA;AAGlDC,YAAQC,IAAI,qBAAA;AACZ,eAAWC,OAAOT,OAAO;AACvB,UAAGS,KAAK;AACNF,gBAAQC,IAAIC,GAAAA;MACd;IACF;EACF;AACF;AAEApB,IAAAA,EAAMqB,SAASpB,cAAAA;","names":["Command","cli","DefaultCommand","usage","Usage","category","description","details","examples","execute","commandList","registrations","paths","forEach","index","val","push","builder","join","console","log","cmd","register"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as clipanion from 'clipanion';
|
|
2
|
+
import { Command } from 'clipanion';
|
|
3
|
+
|
|
4
|
+
declare class KeyGenerateCommand extends Command {
|
|
5
|
+
static paths: string[][];
|
|
6
|
+
static usage: clipanion.Usage;
|
|
7
|
+
rotate: boolean;
|
|
8
|
+
execute(): Promise<void>;
|
|
9
|
+
addEnvParam(file: string, key: string, value: string): string;
|
|
10
|
+
stripPemHeaders(pem: string): string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { KeyGenerateCommand };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { Command, Option } from "clipanion";
|
|
4
|
+
import { generateKeyPairSync } from "crypto";
|
|
5
|
+
import fs from "fs/promises";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { logger, cli } from "../../facades";
|
|
8
|
+
class KeyGenerateCommand extends Command {
|
|
9
|
+
static {
|
|
10
|
+
__name(this, "KeyGenerateCommand");
|
|
11
|
+
}
|
|
12
|
+
static paths = [
|
|
13
|
+
[
|
|
14
|
+
`key`,
|
|
15
|
+
"generate"
|
|
16
|
+
]
|
|
17
|
+
];
|
|
18
|
+
static usage = Command.Usage({
|
|
19
|
+
category: `Main`,
|
|
20
|
+
description: `generate keys`,
|
|
21
|
+
details: `
|
|
22
|
+
This command generates RSA key pair for JWT signing.
|
|
23
|
+
Use --rotate flag to preserve old public key.
|
|
24
|
+
`,
|
|
25
|
+
examples: [
|
|
26
|
+
[
|
|
27
|
+
`Generate new keys`,
|
|
28
|
+
`key generate`
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
`Rotate existing keys`,
|
|
32
|
+
`key generate --rotate`
|
|
33
|
+
]
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
rotate = Option.Boolean(`--rotate`, false, {
|
|
37
|
+
description: `Rotate existing keys (backup old keys before replacement)`
|
|
38
|
+
});
|
|
39
|
+
async execute() {
|
|
40
|
+
logger().info("generating keys for jwt token and adding to .env file");
|
|
41
|
+
const { publicKey, privateKey } = generateKeyPairSync("rsa", {
|
|
42
|
+
modulusLength: 2048,
|
|
43
|
+
publicKeyEncoding: {
|
|
44
|
+
type: "spki",
|
|
45
|
+
format: "pem"
|
|
46
|
+
},
|
|
47
|
+
privateKeyEncoding: {
|
|
48
|
+
type: "pkcs8",
|
|
49
|
+
format: "pem"
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
let envfile = await fs.readFile(path.join(process.cwd(), ".env"), "utf-8");
|
|
53
|
+
let old_public_key = envfile.match(/^jwt_secret_public=(.*)/m);
|
|
54
|
+
envfile = this.addEnvParam(envfile, "jwt_secret_public", this.stripPemHeaders(publicKey));
|
|
55
|
+
envfile = this.addEnvParam(envfile, "jwt_secret_private", this.stripPemHeaders(privateKey));
|
|
56
|
+
if (this.rotate && old_public_key && old_public_key[1]) {
|
|
57
|
+
envfile = this.addEnvParam(envfile, "jwt_secret_public_retired", old_public_key[1]);
|
|
58
|
+
}
|
|
59
|
+
await fs.writeFile(path.join(process.cwd(), ".env"), envfile, "utf-8");
|
|
60
|
+
}
|
|
61
|
+
addEnvParam(file, key, value) {
|
|
62
|
+
let regex = new RegExp(`^${key}=.*`, "gm");
|
|
63
|
+
file = file.replace(regex, `${key}=${value}`);
|
|
64
|
+
const match = file.match(regex);
|
|
65
|
+
if (!match) {
|
|
66
|
+
file = file + `
|
|
67
|
+
${key}=${value}`;
|
|
68
|
+
}
|
|
69
|
+
return file;
|
|
70
|
+
}
|
|
71
|
+
stripPemHeaders(pem) {
|
|
72
|
+
return pem.replace(/-----BEGIN [\w\s]+-----/g, "").replace(/-----END [\w\s]+-----/g, "").replace(/\r?\n|\r/g, "");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
cli().register(KeyGenerateCommand);
|
|
76
|
+
export {
|
|
77
|
+
KeyGenerateCommand
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=KeyGenerateCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/app/console/KeyGenerateCommand.ts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { generateKeyPairSync } from \"crypto\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { logger, cli } from \"../../facades\";\n\nexport class KeyGenerateCommand extends Command {\n static paths = [[`key`, \"generate\"]];\n\n static usage = Command.Usage({\n category: `Main`,\n description: `generate keys`,\n details: `\n This command generates RSA key pair for JWT signing.\n Use --rotate flag to preserve old public key.\n `,\n examples: [\n [`Generate new keys`, `key generate`],\n [`Rotate existing keys`, `key generate --rotate`],\n ],\n });\n\n rotate = Option.Boolean(`--rotate`, false, {\n description: `Rotate existing keys (backup old keys before replacement)`,\n });\n\n async execute() {\n logger().info(\"generating keys for jwt token and adding to .env file\");\n const { publicKey, privateKey } = generateKeyPairSync(\"rsa\", {\n modulusLength: 2048, // 2048-bit key is standard for RS256\n publicKeyEncoding: {\n type: \"spki\",\n format: \"pem\",\n },\n privateKeyEncoding: {\n type: \"pkcs8\",\n format: \"pem\",\n },\n });\n\n let envfile = await fs.readFile(path.join(process.cwd(), \".env\"), \"utf-8\");\n let old_public_key = envfile.match(/^jwt_secret_public=(.*)/m);\n\n envfile = this.addEnvParam(\n envfile,\n \"jwt_secret_public\",\n this.stripPemHeaders(publicKey),\n );\n envfile = this.addEnvParam(\n envfile,\n \"jwt_secret_private\",\n this.stripPemHeaders(privateKey),\n );\n\n if (this.rotate && old_public_key && old_public_key[1]) {\n envfile = this.addEnvParam(\n envfile,\n \"jwt_secret_public_retired\",\n old_public_key[1],\n );\n }\n\n await fs.writeFile(path.join(process.cwd(), \".env\"), envfile, \"utf-8\");\n }\n\n addEnvParam(file: string, key: string, value: string) {\n let regex = new RegExp(`^${key}=.*`, \"gm\");\n file = file.replace(regex, `${key}=${value}`);\n const match = file.match(regex);\n\n if (!match) {\n file = file + `\\n${key}=${value}`;\n }\n return file;\n }\n\n stripPemHeaders(pem: string) {\n return pem\n .replace(/-----BEGIN [\\w\\s]+-----/g, \"\")\n .replace(/-----END [\\w\\s]+-----/g, \"\")\n .replace(/\\r?\\n|\\r/g, \"\");\n }\n}\n\ncli().register(KeyGenerateCommand);\n"],"mappings":";;AAAA,SAASA,SAASC,cAAc;AAChC,SAASC,2BAA2B;AACpC,OAAOC,QAAQ;AACf,OAAOC,UAAU;AACjB,SAASC,QAAQC,WAAW;AAErB,MAAMC,2BAA2BP,QAAAA;EANxC,OAMwCA;;;EACtC,OAAOQ,QAAQ;IAAC;MAAC;MAAO;;;EAExB,OAAOC,QAAQT,QAAQU,MAAM;IAC3BC,UAAU;IACVC,aAAa;IACbC,SAAS;;;;IAITC,UAAU;MACR;QAAC;QAAqB;;MACtB;QAAC;QAAwB;;;EAE7B,CAAA;EAEAC,SAASd,OAAOe,QAAQ,YAAY,OAAO;IACzCJ,aAAa;EACf,CAAA;EAEA,MAAMK,UAAU;AACdZ,WAAAA,EAASa,KAAK,uDAAA;AACd,UAAM,EAAEC,WAAWC,WAAU,IAAKlB,oBAAoB,OAAO;MAC3DmB,eAAe;MACfC,mBAAmB;QACjBC,MAAM;QACNC,QAAQ;MACV;MACAC,oBAAoB;QAClBF,MAAM;QACNC,QAAQ;MACV;IACF,CAAA;AAEA,QAAIE,UAAU,MAAMvB,GAAGwB,SAASvB,KAAKwB,KAAKC,QAAQC,IAAG,GAAI,MAAA,GAAS,OAAA;AAClE,QAAIC,iBAAiBL,QAAQM,MAAM,0BAAA;AAEnCN,cAAU,KAAKO,YACbP,SACA,qBACA,KAAKQ,gBAAgBf,SAAAA,CAAAA;AAEvBO,cAAU,KAAKO,YACbP,SACA,sBACA,KAAKQ,gBAAgBd,UAAAA,CAAAA;AAGvB,QAAI,KAAKL,UAAUgB,kBAAkBA,eAAe,CAAA,GAAI;AACtDL,gBAAU,KAAKO,YACbP,SACA,6BACAK,eAAe,CAAA,CAAE;IAErB;AAEA,UAAM5B,GAAGgC,UAAU/B,KAAKwB,KAAKC,QAAQC,IAAG,GAAI,MAAA,GAASJ,SAAS,OAAA;EAChE;EAEAO,YAAYG,MAAcC,KAAaC,OAAe;AACpD,QAAIC,QAAQ,IAAIC,OAAO,IAAIH,GAAAA,OAAU,IAAA;AACrCD,WAAOA,KAAKK,QAAQF,OAAO,GAAGF,GAAAA,IAAOC,KAAAA,EAAO;AAC5C,UAAMN,QAAQI,KAAKJ,MAAMO,KAAAA;AAEzB,QAAI,CAACP,OAAO;AACVI,aAAOA,OAAO;EAAKC,GAAAA,IAAOC,KAAAA;IAC5B;AACA,WAAOF;EACT;EAEAF,gBAAgBQ,KAAa;AAC3B,WAAOA,IACJD,QAAQ,4BAA4B,EAAA,EACpCA,QAAQ,0BAA0B,EAAA,EAClCA,QAAQ,aAAa,EAAA;EAC1B;AACF;AAEAnC,IAAAA,EAAMqC,SAASpC,kBAAAA;","names":["Command","Option","generateKeyPairSync","fs","path","logger","cli","KeyGenerateCommand","paths","usage","Usage","category","description","details","examples","rotate","Boolean","execute","info","publicKey","privateKey","modulusLength","publicKeyEncoding","type","format","privateKeyEncoding","envfile","readFile","join","process","cwd","old_public_key","match","addEnvParam","stripPemHeaders","writeFile","file","key","value","regex","RegExp","replace","pem","register"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { Command, Option } from "clipanion";
|
|
4
|
+
import { config } from "@devbro/neko-config";
|
|
5
|
+
import { cli, httpServer, logger, scheduler } from "../../facades";
|
|
6
|
+
import { PostgresqlConnection } from "@devbro/neko-sql";
|
|
7
|
+
class StartCommand extends Command {
|
|
8
|
+
static {
|
|
9
|
+
__name(this, "StartCommand");
|
|
10
|
+
}
|
|
11
|
+
scheduler = Option.Boolean(`--scheduler`, false);
|
|
12
|
+
http = Option.Boolean(`--http`, false);
|
|
13
|
+
all = Option.Boolean("--all", false);
|
|
14
|
+
static paths = [
|
|
15
|
+
[
|
|
16
|
+
`start`
|
|
17
|
+
]
|
|
18
|
+
];
|
|
19
|
+
async execute() {
|
|
20
|
+
if ([
|
|
21
|
+
this.all,
|
|
22
|
+
this.http,
|
|
23
|
+
this.scheduler
|
|
24
|
+
].filter((x) => x).length == 0) {
|
|
25
|
+
this.context.stdout.write(`No service was selected. please check -h for details
|
|
26
|
+
`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
logger().info(`Starting Server
|
|
30
|
+
`);
|
|
31
|
+
PostgresqlConnection.defaults.idleTimeoutMillis = 1e4;
|
|
32
|
+
if (this.scheduler || this.all) {
|
|
33
|
+
logger().info(`starting scheduler
|
|
34
|
+
`);
|
|
35
|
+
scheduler().start();
|
|
36
|
+
}
|
|
37
|
+
if (this.http || this.all) {
|
|
38
|
+
const server = httpServer();
|
|
39
|
+
await server.listen(config.get("port"), () => {
|
|
40
|
+
logger().info("Server is running on http://localhost:" + config.get("port"));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
cli().register(StartCommand);
|
|
46
|
+
export {
|
|
47
|
+
StartCommand
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=StartCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/app/console/StartCommand.ts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { config } from \"@devbro/neko-config\";\n\nimport { cli, httpServer, logger, scheduler } from \"../../facades\";\nimport { PostgresqlConnection } from \"@devbro/neko-sql\";\n\nexport class StartCommand extends Command {\n scheduler = Option.Boolean(`--scheduler`, false);\n http = Option.Boolean(`--http`, false);\n all = Option.Boolean(\"--all\", false);\n static paths = [[`start`]];\n\n async execute() {\n if ([this.all, this.http, this.scheduler].filter((x) => x).length == 0) {\n this.context.stdout.write(\n `No service was selected. please check -h for details\\n`,\n );\n return;\n }\n\n logger().info(`Starting Server\\n`);\n\n PostgresqlConnection.defaults.idleTimeoutMillis = 10000;\n\n if (this.scheduler || this.all) {\n logger().info(`starting scheduler\\n`);\n scheduler().start();\n }\n\n if (this.http || this.all) {\n const server = httpServer();\n await server.listen(config.get(\"port\"), () => {\n logger().info(\n \"Server is running on http://localhost:\" + config.get(\"port\"),\n );\n });\n }\n }\n}\n\ncli().register(StartCommand);\n"],"mappings":";;AAAA,SAASA,SAASC,cAAc;AAChC,SAASC,cAAc;AAEvB,SAASC,KAAKC,YAAYC,QAAQC,iBAAiB;AACnD,SAASC,4BAA4B;AAE9B,MAAMC,qBAAqBR,QAAAA;EANlC,OAMkCA;;;EAChCM,YAAYL,OAAOQ,QAAQ,eAAe,KAAA;EAC1CC,OAAOT,OAAOQ,QAAQ,UAAU,KAAA;EAChCE,MAAMV,OAAOQ,QAAQ,SAAS,KAAA;EAC9B,OAAOG,QAAQ;IAAC;MAAC;;;EAEjB,MAAMC,UAAU;AACd,QAAI;MAAC,KAAKF;MAAK,KAAKD;MAAM,KAAKJ;MAAWQ,OAAO,CAACC,MAAMA,CAAAA,EAAGC,UAAU,GAAG;AACtE,WAAKC,QAAQC,OAAOC,MAClB;CAAwD;AAE1D;IACF;AAEAd,WAAAA,EAASe,KAAK;CAAmB;AAEjCb,yBAAqBc,SAASC,oBAAoB;AAElD,QAAI,KAAKhB,aAAa,KAAKK,KAAK;AAC9BN,aAAAA,EAASe,KAAK;CAAsB;AACpCd,gBAAAA,EAAYiB,MAAK;IACnB;AAEA,QAAI,KAAKb,QAAQ,KAAKC,KAAK;AACzB,YAAMa,SAASpB,WAAAA;AACf,YAAMoB,OAAOC,OAAOvB,OAAOwB,IAAI,MAAA,GAAS,MAAA;AACtCrB,eAAAA,EAASe,KACP,2CAA2ClB,OAAOwB,IAAI,MAAA,CAAA;MAE1D,CAAA;IACF;EACF;AACF;AAEAvB,IAAAA,EAAMwB,SAASnB,YAAAA;","names":["Command","Option","config","cli","httpServer","logger","scheduler","PostgresqlConnection","StartCommand","Boolean","http","all","paths","execute","filter","x","length","context","stdout","write","info","defaults","idleTimeoutMillis","start","server","listen","get","register"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { cli } from "../../../facades";
|
|
4
|
+
import { Command, Option } from "clipanion";
|
|
5
|
+
import { Case } from "change-case-all";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import * as fs from "fs/promises";
|
|
8
|
+
import { config } from "@devbro/neko-config";
|
|
9
|
+
import handlebars from "handlebars";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
import pluralize from "pluralize";
|
|
12
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
class GenerateControllerCommand extends Command {
|
|
14
|
+
static {
|
|
15
|
+
__name(this, "GenerateControllerCommand");
|
|
16
|
+
}
|
|
17
|
+
static paths = [
|
|
18
|
+
[
|
|
19
|
+
`make`,
|
|
20
|
+
`controller`
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
`generate`,
|
|
24
|
+
`controller`
|
|
25
|
+
]
|
|
26
|
+
];
|
|
27
|
+
name = Option.String({
|
|
28
|
+
required: true
|
|
29
|
+
});
|
|
30
|
+
async execute() {
|
|
31
|
+
const rootDir = process.cwd();
|
|
32
|
+
const date = /* @__PURE__ */ new Date();
|
|
33
|
+
const year = date.getFullYear();
|
|
34
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
35
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
36
|
+
const secondsOfDay = String(date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()).padStart(5, "0");
|
|
37
|
+
const fixed_name = Case.snake(this.name);
|
|
38
|
+
const filename = `${Case.capital(this.name)}Controller.ts`;
|
|
39
|
+
this.context.stdout.write(`creating migration file ${filename}
|
|
40
|
+
`);
|
|
41
|
+
await fs.mkdir(config.get("migration.path"), {
|
|
42
|
+
recursive: true
|
|
43
|
+
});
|
|
44
|
+
const compiledTemplate = handlebars.compile((await fs.readFile(path.join(__dirname, "./controller.tpl"))).toString());
|
|
45
|
+
const template = await compiledTemplate({
|
|
46
|
+
className: Case.pascal(this.name),
|
|
47
|
+
routeName: Case.kebab(pluralize(this.name))
|
|
48
|
+
});
|
|
49
|
+
await fs.writeFile(path.join(rootDir, "src/app/controllers", filename), template);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
cli().register(GenerateControllerCommand);
|
|
53
|
+
export {
|
|
54
|
+
GenerateControllerCommand
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=GenerateControllerCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/console/generate/GenerateControllerCommand.ts"],"sourcesContent":["import { cli } from \"../../../facades\";\nimport { Command, Option } from \"clipanion\";\nimport { Case } from \"change-case-all\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport handlebars from \"handlebars\";\nimport { fileURLToPath } from \"url\";\nimport pluralize from \"pluralize\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport class GenerateControllerCommand extends Command {\n static paths = [\n [`make`, `controller`],\n [`generate`, `controller`],\n ];\n\n name = Option.String({ required: true });\n\n async execute() {\n const rootDir = process.cwd();\n\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const secondsOfDay = String(\n date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds(),\n ).padStart(5, \"0\");\n\n const fixed_name = Case.snake(this.name);\n const filename = `${Case.capital(this.name)}Controller.ts`;\n this.context.stdout.write(`creating migration file ${filename}\\n`);\n\n await fs.mkdir(config.get(\"migration.path\"), { recursive: true });\n\n const compiledTemplate = handlebars.compile(\n (await fs.readFile(path.join(__dirname, \"./controller.tpl\"))).toString(),\n );\n const template = await compiledTemplate({\n className: Case.pascal(this.name),\n routeName: Case.kebab(pluralize(this.name)),\n });\n\n await fs.writeFile(\n path.join(rootDir, \"src/app/controllers\", filename),\n template,\n );\n }\n}\n\ncli().register(GenerateControllerCommand);\n"],"mappings":";;AAAA,SAASA,WAAW;AACpB,SAASC,SAASC,cAAc;AAChC,SAASC,YAAY;AACrB,OAAOC,UAAU;AACjB,YAAYC,QAAQ;AACpB,SAASC,cAAc;AACvB,OAAOC,gBAAgB;AACvB,SAASC,qBAAqB;AAC9B,OAAOC,eAAe;AAEtB,MAAMC,YAAYN,KAAKO,QAAQH,cAAc,YAAYI,GAAG,CAAA;AAErD,MAAMC,kCAAkCZ,QAAAA;EAZ/C,OAY+CA;;;EAC7C,OAAOa,QAAQ;IACb;MAAC;MAAQ;;IACT;MAAC;MAAY;;;EAGfC,OAAOb,OAAOc,OAAO;IAAEC,UAAU;EAAK,CAAA;EAEtC,MAAMC,UAAU;AACd,UAAMC,UAAUC,QAAQC,IAAG;AAE3B,UAAMC,OAAO,oBAAIC,KAAAA;AACjB,UAAMC,OAAOF,KAAKG,YAAW;AAC7B,UAAMC,QAAQV,OAAOM,KAAKK,SAAQ,IAAK,CAAA,EAAGC,SAAS,GAAG,GAAA;AACtD,UAAMC,MAAMb,OAAOM,KAAKQ,QAAO,CAAA,EAAIF,SAAS,GAAG,GAAA;AAC/C,UAAMG,eAAef,OACnBM,KAAKU,SAAQ,IAAK,OAAOV,KAAKW,WAAU,IAAK,KAAKX,KAAKY,WAAU,CAAA,EACjEN,SAAS,GAAG,GAAA;AAEd,UAAMO,aAAahC,KAAKiC,MAAM,KAAKrB,IAAI;AACvC,UAAMsB,WAAW,GAAGlC,KAAKmC,QAAQ,KAAKvB,IAAI,CAAA;AAC1C,SAAKwB,QAAQC,OAAOC,MAAM,2BAA2BJ,QAAAA;CAAY;AAEjE,UAAMhC,GAAGqC,MAAMpC,OAAOqC,IAAI,gBAAA,GAAmB;MAAEC,WAAW;IAAK,CAAA;AAE/D,UAAMC,mBAAmBtC,WAAWuC,SACjC,MAAMzC,GAAG0C,SAAS3C,KAAK4C,KAAKtC,WAAW,kBAAA,CAAA,GAAsBuC,SAAQ,CAAA;AAExE,UAAMC,WAAW,MAAML,iBAAiB;MACtCM,WAAWhD,KAAKiD,OAAO,KAAKrC,IAAI;MAChCsC,WAAWlD,KAAKmD,MAAM7C,UAAU,KAAKM,IAAI,CAAA;IAC3C,CAAA;AAEA,UAAMV,GAAGkD,UACPnD,KAAK4C,KAAK7B,SAAS,uBAAuBkB,QAAAA,GAC1Ca,QAAAA;EAEJ;AACF;AAEAlD,IAAAA,EAAMwD,SAAS3C,yBAAAA;","names":["cli","Command","Option","Case","path","fs","config","handlebars","fileURLToPath","pluralize","__dirname","dirname","url","GenerateControllerCommand","paths","name","String","required","execute","rootDir","process","cwd","date","Date","year","getFullYear","month","getMonth","padStart","day","getDate","secondsOfDay","getHours","getMinutes","getSeconds","fixed_name","snake","filename","capital","context","stdout","write","mkdir","get","recursive","compiledTemplate","compile","readFile","join","toString","template","className","pascal","routeName","kebab","writeFile","register"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { db, storage, logger } from "@devbro/pashmak/facades";
|
|
2
|
+
import { ctx } from "@devbro/pashmak/context";
|
|
3
|
+
import { Request, Response, Model, Param, ValidatedRequest, BaseController, Controller, Get, Post, Put, Delete } from "@devbro/pashmak/router";
|
|
4
|
+
|
|
5
|
+
@Controller("/api/v1/{{routeName}}")
|
|
6
|
+
export class {{className}}Controller extends BaseController {
|
|
7
|
+
@Get()
|
|
8
|
+
async list() {
|
|
9
|
+
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Post()
|
|
13
|
+
async create() {
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Get({ path: "/:id" })
|
|
18
|
+
async get(@Param("id") id: string) {
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Put({ path: "/:id" })
|
|
23
|
+
async update(@Param("id") id: string) {
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Delete({ path: "/:id" })
|
|
28
|
+
delete(@Param("id") id: string) {
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/console/generate/index.ts"],"sourcesContent":["export * from \"./GenerateControllerCommand\";\n"],"mappings":"AAAA,cAAc;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { MigrateCommand } from './migrate/MigrateCommand.js';
|
|
2
|
+
export { MakeMigrateCommand } from './migrate/MakeMigrateCommand.js';
|
|
3
|
+
export { MigrateRollbackCommand } from './migrate/MigrateRollbackCommand.js';
|
|
4
|
+
export { StartCommand } from './StartCommand.js';
|
|
5
|
+
export { DefaultCommand } from './DefaultCommand.js';
|
|
6
|
+
export { KeyGenerateCommand } from './KeyGenerateCommand.js';
|
|
7
|
+
export { GenerateControllerCommand } from './generate/GenerateControllerCommand.js';
|
|
8
|
+
export { CreateProjectCommand } from './project/CreateProjectCommand.js';
|
|
9
|
+
import 'clipanion';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/app/console/index.ts"],"sourcesContent":["export * from \"./migrate\";\nexport * from \"./StartCommand\";\nexport * from \"./DefaultCommand\";\nexport * from \"./KeyGenerateCommand\";\nexport * from \"./generate\";\nexport * from \"./project/CreateProjectCommand\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { cli } from "../../../facades";
|
|
4
|
+
import { Command, Option } from "clipanion";
|
|
5
|
+
import { Case } from "change-case-all";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import * as fs from "fs/promises";
|
|
8
|
+
import { config } from "@devbro/neko-config";
|
|
9
|
+
import handlebars from "handlebars";
|
|
10
|
+
class MakeMigrateCommand extends Command {
|
|
11
|
+
static {
|
|
12
|
+
__name(this, "MakeMigrateCommand");
|
|
13
|
+
}
|
|
14
|
+
static paths = [
|
|
15
|
+
[
|
|
16
|
+
`make`,
|
|
17
|
+
`migrate`
|
|
18
|
+
],
|
|
19
|
+
[
|
|
20
|
+
"make",
|
|
21
|
+
"migration"
|
|
22
|
+
]
|
|
23
|
+
];
|
|
24
|
+
name = Option.String({
|
|
25
|
+
required: true
|
|
26
|
+
});
|
|
27
|
+
async execute() {
|
|
28
|
+
const date = /* @__PURE__ */ new Date();
|
|
29
|
+
const year = date.getFullYear();
|
|
30
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
31
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
32
|
+
const secondsOfDay = String(date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()).padStart(5, "0");
|
|
33
|
+
const fixed_name = Case.snake(this.name);
|
|
34
|
+
const filename = `${year}_${month}_${day}_${secondsOfDay}_${fixed_name}.ts`;
|
|
35
|
+
this.context.stdout.write(`creating migration file ${filename}
|
|
36
|
+
`);
|
|
37
|
+
await fs.mkdir(config.get("migration.path"), {
|
|
38
|
+
recursive: true
|
|
39
|
+
});
|
|
40
|
+
const compiledTemplate = handlebars.compile((await fs.readFile(path.join(__dirname, "./make_migration.tpl"))).toString());
|
|
41
|
+
const template = await compiledTemplate({
|
|
42
|
+
className: Case.pascal(this.name)
|
|
43
|
+
});
|
|
44
|
+
await fs.writeFile(path.join(config.get("migration.path"), filename), template);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
cli().register(MakeMigrateCommand);
|
|
48
|
+
export {
|
|
49
|
+
MakeMigrateCommand
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=MakeMigrateCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/console/migrate/MakeMigrateCommand.ts"],"sourcesContent":["import { cli } from \"../../../facades\";\nimport { Command, Option } from \"clipanion\";\nimport { Case } from \"change-case-all\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport handlebars from \"handlebars\";\n\nexport class MakeMigrateCommand extends Command {\n static paths = [\n [`make`, `migrate`],\n [\"make\", \"migration\"],\n ];\n\n name = Option.String({ required: true });\n\n async execute() {\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const secondsOfDay = String(\n date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds(),\n ).padStart(5, \"0\");\n\n const fixed_name = Case.snake(this.name);\n const filename = `${year}_${month}_${day}_${secondsOfDay}_${fixed_name}.ts`;\n this.context.stdout.write(`creating migration file ${filename}\\n`);\n\n await fs.mkdir(config.get(\"migration.path\"), { recursive: true });\n\n const compiledTemplate = handlebars.compile(\n (\n await fs.readFile(path.join(__dirname, \"./make_migration.tpl\"))\n ).toString(),\n );\n const template = await compiledTemplate({\n className: Case.pascal(this.name),\n });\n\n await fs.writeFile(\n path.join(config.get(\"migration.path\"), filename),\n template,\n );\n }\n}\n\ncli().register(MakeMigrateCommand);\n"],"mappings":";;AAAA,SAASA,WAAW;AACpB,SAASC,SAASC,cAAc;AAChC,SAASC,YAAY;AACrB,OAAOC,UAAU;AACjB,YAAYC,QAAQ;AACpB,SAASC,cAAc;AACvB,OAAOC,gBAAgB;AAEhB,MAAMC,2BAA2BP,QAAAA;EARxC,OAQwCA;;;EACtC,OAAOQ,QAAQ;IACb;MAAC;MAAQ;;IACT;MAAC;MAAQ;;;EAGXC,OAAOR,OAAOS,OAAO;IAAEC,UAAU;EAAK,CAAA;EAEtC,MAAMC,UAAU;AACd,UAAMC,OAAO,oBAAIC,KAAAA;AACjB,UAAMC,OAAOF,KAAKG,YAAW;AAC7B,UAAMC,QAAQP,OAAOG,KAAKK,SAAQ,IAAK,CAAA,EAAGC,SAAS,GAAG,GAAA;AACtD,UAAMC,MAAMV,OAAOG,KAAKQ,QAAO,CAAA,EAAIF,SAAS,GAAG,GAAA;AAC/C,UAAMG,eAAeZ,OACnBG,KAAKU,SAAQ,IAAK,OAAOV,KAAKW,WAAU,IAAK,KAAKX,KAAKY,WAAU,CAAA,EACjEN,SAAS,GAAG,GAAA;AAEd,UAAMO,aAAaxB,KAAKyB,MAAM,KAAKlB,IAAI;AACvC,UAAMmB,WAAW,GAAGb,IAAAA,IAAQE,KAAAA,IAASG,GAAAA,IAAOE,YAAAA,IAAgBI,UAAAA;AAC5D,SAAKG,QAAQC,OAAOC,MAAM,2BAA2BH,QAAAA;CAAY;AAEjE,UAAMxB,GAAG4B,MAAM3B,OAAO4B,IAAI,gBAAA,GAAmB;MAAEC,WAAW;IAAK,CAAA;AAE/D,UAAMC,mBAAmB7B,WAAW8B,SAEhC,MAAMhC,GAAGiC,SAASlC,KAAKmC,KAAKC,WAAW,sBAAA,CAAA,GACvCC,SAAQ,CAAA;AAEZ,UAAMC,WAAW,MAAMN,iBAAiB;MACtCO,WAAWxC,KAAKyC,OAAO,KAAKlC,IAAI;IAClC,CAAA;AAEA,UAAML,GAAGwC,UACPzC,KAAKmC,KAAKjC,OAAO4B,IAAI,gBAAA,GAAmBL,QAAAA,GACxCa,QAAAA;EAEJ;AACF;AAEA1C,IAAAA,EAAM8C,SAAStC,kBAAAA;","names":["cli","Command","Option","Case","path","fs","config","handlebars","MakeMigrateCommand","paths","name","String","required","execute","date","Date","year","getFullYear","month","getMonth","padStart","day","getDate","secondsOfDay","getHours","getMinutes","getSeconds","fixed_name","snake","filename","context","stdout","write","mkdir","get","recursive","compiledTemplate","compile","readFile","join","__dirname","toString","template","className","pascal","writeFile","register"]}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { cli, db as database, logger } from "../../../facades";
|
|
4
|
+
import { Command, Option } from "clipanion";
|
|
5
|
+
import { context_provider } from "@devbro/neko-context";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import fs from "fs/promises";
|
|
8
|
+
import { config } from "@devbro/neko-config";
|
|
9
|
+
class MigrateCommand extends Command {
|
|
10
|
+
static {
|
|
11
|
+
__name(this, "MigrateCommand");
|
|
12
|
+
}
|
|
13
|
+
static paths = [
|
|
14
|
+
[
|
|
15
|
+
`migrate`
|
|
16
|
+
]
|
|
17
|
+
];
|
|
18
|
+
fresh = Option.Boolean("--fresh", false);
|
|
19
|
+
async execute() {
|
|
20
|
+
await context_provider.run(async () => {
|
|
21
|
+
const db = database();
|
|
22
|
+
const schema = db.getSchema();
|
|
23
|
+
if (this.fresh) {
|
|
24
|
+
logger().info("dropping all tables!!");
|
|
25
|
+
let retry = true;
|
|
26
|
+
let retry_count = 0;
|
|
27
|
+
while (retry && retry_count < 10) {
|
|
28
|
+
retry = false;
|
|
29
|
+
retry_count++;
|
|
30
|
+
const tables = await schema.tables();
|
|
31
|
+
for (const table of tables) {
|
|
32
|
+
logger().info(`dropping table ${table.name}`);
|
|
33
|
+
try {
|
|
34
|
+
await schema.dropTable(table.name);
|
|
35
|
+
} catch {
|
|
36
|
+
logger().info(`failed to drop ${table.name}`);
|
|
37
|
+
retry = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!await schema.tableExists("migrations")) {
|
|
43
|
+
await schema.createTable("migrations", (blueprint) => {
|
|
44
|
+
blueprint.id();
|
|
45
|
+
blueprint.timestamps();
|
|
46
|
+
blueprint.string("filename");
|
|
47
|
+
blueprint.integer("batch");
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const migrationsDir = config.get("migration.path");
|
|
51
|
+
let files = [];
|
|
52
|
+
const dirEntries = await fs.readdir(migrationsDir);
|
|
53
|
+
files = dirEntries.filter((entry) => entry.endsWith(".ts") || entry.endsWith(".js")).sort();
|
|
54
|
+
let batch_number = await db.runQuery({
|
|
55
|
+
sql: "select max(batch) as next_batch from migrations",
|
|
56
|
+
bindings: []
|
|
57
|
+
});
|
|
58
|
+
batch_number = batch_number[0].next_batch || 0;
|
|
59
|
+
batch_number++;
|
|
60
|
+
const migrations = await db.runQuery({
|
|
61
|
+
sql: "select * from migrations order by created_at ASC",
|
|
62
|
+
bindings: []
|
|
63
|
+
});
|
|
64
|
+
const completed_migrations = migrations.map((r) => r.filename);
|
|
65
|
+
const pending_migrations = files.filter((file) => !completed_migrations.includes(file));
|
|
66
|
+
let migrated_count = 0;
|
|
67
|
+
for (const class_to_migrate of pending_migrations) {
|
|
68
|
+
logger().info(`migrating up ${class_to_migrate}`);
|
|
69
|
+
const ClassToMigrate = (await import(path.join(migrationsDir, class_to_migrate))).default;
|
|
70
|
+
const c = new ClassToMigrate();
|
|
71
|
+
await c.up(db.getSchema());
|
|
72
|
+
await db.runQuery({
|
|
73
|
+
sql: "insert into migrations (filename, batch) values ($1,$2)",
|
|
74
|
+
bindings: [
|
|
75
|
+
class_to_migrate,
|
|
76
|
+
batch_number
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
migrated_count++;
|
|
80
|
+
}
|
|
81
|
+
if (migrated_count === 0) {
|
|
82
|
+
logger().warn("no migrations to run!");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
logger().info(`migrated ${migrated_count} migrations successfully!`);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
cli().register(MigrateCommand);
|
|
90
|
+
export {
|
|
91
|
+
MigrateCommand
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=MigrateCommand.js.map
|