@devbro/pashmak 0.1.55 → 0.1.56
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/cjs/app/console/index.js +268 -70
- package/dist/cjs/app/console/project/CreateProjectCommand.js +263 -65
- package/dist/cjs/app/console/project/base_project/src/config/caches.ts.tpl +11 -1
- package/dist/cjs/app/console/project/base_project/src/config/databases.ts.tpl +8 -6
- package/dist/cjs/app/console/project/base_project/src/config/default.mts.tpl +13 -20
- package/dist/cjs/app/console/project/base_project/src/config/loggers.ts.tpl +13 -3
- package/dist/cjs/app/console/project/base_project/src/config/storages.ts.tpl +1 -2
- package/dist/cjs/app/console/project/base_project/src/initialize.ts.tpl +48 -16
- package/dist/cjs/app/console/project/base_project/src/routes.ts.tpl +2 -2
- package/dist/cjs/bin/pashmak_cli.js +265 -66
- package/dist/cjs/index.js +1785 -1993
- package/dist/cjs/middlewares.js +60 -2
- package/dist/esm/app/console/project/CreateProjectCommand.d.mts +15 -2
- package/dist/esm/app/console/project/CreateProjectCommand.mjs +265 -67
- package/dist/esm/app/console/project/CreateProjectCommand.mjs.map +1 -1
- package/dist/esm/app/console/project/base_project/src/config/caches.ts.tpl +11 -1
- package/dist/esm/app/console/project/base_project/src/config/databases.ts.tpl +8 -6
- package/dist/esm/app/console/project/base_project/src/config/default.mts.tpl +13 -20
- package/dist/esm/app/console/project/base_project/src/config/loggers.ts.tpl +13 -3
- package/dist/esm/app/console/project/base_project/src/config/storages.ts.tpl +1 -2
- package/dist/esm/app/console/project/base_project/src/initialize.ts.tpl +48 -16
- package/dist/esm/app/console/project/base_project/src/routes.ts.tpl +2 -2
- package/dist/esm/bin/pashmak_cli.mjs +2 -1
- package/dist/esm/bin/pashmak_cli.mjs.map +1 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/index.d.mts +1 -7
- package/dist/esm/index.mjs +1 -32
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/middlewares.d.mts +12 -1
- package/dist/esm/middlewares.mjs +52 -0
- package/dist/esm/middlewares.mjs.map +1 -1
- package/package.json +4 -2
- package/dist/cjs/app/console/project/base_project/package.json.tpl +0 -74
- package/dist/cjs/app/console/project/base_project/src/config/test.ts.tpl +0 -1
- package/dist/esm/app/console/project/base_project/package.json.tpl +0 -74
- package/dist/esm/app/console/project/base_project/src/config/test.ts.tpl +0 -1
- /package/dist/cjs/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl} +0 -0
- /package/dist/esm/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl} +0 -0
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { ctxSafe } from '@devbro/pashmak/context';
|
|
2
|
-
import { LogMessage } from '@devbro/pashmak/logger';
|
|
3
2
|
|
|
4
3
|
export default {
|
|
5
4
|
default: {
|
|
6
|
-
level:
|
|
7
|
-
extrasFunction: (message:
|
|
5
|
+
level: 'info',
|
|
6
|
+
extrasFunction: (message: any) => {
|
|
7
|
+
let requestId = ctxSafe()?.get('requestId');
|
|
8
|
+
requestId && (message.requestId = requestId);
|
|
9
|
+
return message;
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const $test = {
|
|
15
|
+
default: {
|
|
16
|
+
level: 'silent',
|
|
17
|
+
extrasFunction: (message: any) => {
|
|
8
18
|
let requestId = ctxSafe()?.get('requestId');
|
|
9
19
|
requestId && (message.requestId = requestId);
|
|
10
20
|
return message;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LocalStorageProviderConfig } from '@devbro/pashmak/storage';
|
|
2
1
|
import path from 'path';
|
|
3
2
|
import os from 'os';
|
|
4
3
|
|
|
@@ -7,6 +6,6 @@ export default {
|
|
|
7
6
|
provider: 'local',
|
|
8
7
|
config: {
|
|
9
8
|
basePath: path.join(os.tmpdir(), '/app-storage/'),
|
|
10
|
-
}
|
|
9
|
+
},
|
|
11
10
|
},
|
|
12
11
|
};
|
|
@@ -1,24 +1,56 @@
|
|
|
1
|
-
import dotenv from
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
2
|
dotenv.config();
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import { loadConfig } from '@devbro/pashmak/config';
|
|
8
|
-
import { httpServer, logger, mailer } from '@devbro/pashmak/facades';
|
|
9
|
-
import { startQueueListeners } from '@/app/queues';
|
|
10
|
-
import { HttpError } from '@devbro/pashmak/http';
|
|
11
|
-
{{#if (eq validation_library "yup")}}import * as yup from 'yup';{{/if}}{{#if (eq validation_library "zod")}}import { z, ZodError } from 'zod';{{/if}}
|
|
4
|
+
import { config, loadConfigData } from "@devbro/pashmak/config";
|
|
5
|
+
import * as config_data from "./config/default.mts";
|
|
6
|
+
await config.load(loadConfigData(config_data));
|
|
12
7
|
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
8
|
+
import { httpServer, logger } from "@devbro/pashmak/facades";
|
|
9
|
+
import { startQueueListeners } from "@/app/queues";
|
|
10
|
+
import { HttpError } from "@devbro/pashmak/http";
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
import * as yup from "yup";
|
|
13
|
+
import { Request, Response, Middleware } from "@devbro/neko-router";
|
|
14
|
+
import { DatabaseProviderMiddleware } from "@devbro/pashmak/middlewares";
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
import "@devbro/pashmak";
|
|
17
|
+
|
|
18
|
+
import "./app/console";
|
|
19
|
+
import "./routes";
|
|
20
|
+
import "./schedules";
|
|
21
|
+
|
|
22
|
+
import { context_provider } from "@devbro/neko-context";
|
|
23
|
+
|
|
24
|
+
import { Connection } from "@devbro/neko-sql";
|
|
25
|
+
import { Global } from "@devbro/pashmak/global";
|
|
26
|
+
import { ctx } from "@devbro/pashmak/context";
|
|
27
|
+
import { BaseModel } from "@devbro/pashmak/orm";
|
|
28
|
+
|
|
29
|
+
context_provider.setPreLoader(async (f: Function) => {
|
|
30
|
+
const middlewares: Middleware[] = [];
|
|
31
|
+
const m = DatabaseProviderMiddleware.getInstance();
|
|
32
|
+
middlewares.push(m);
|
|
33
|
+
|
|
34
|
+
await m.call({} as Request, {} as Response, f as () => Promise<void>);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
Global.set(
|
|
38
|
+
"database.default",
|
|
39
|
+
DatabaseProviderMiddleware.getInstance().getConnection(
|
|
40
|
+
config.get("databases.default") as any,
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
BaseModel.setConnection(() => {
|
|
45
|
+
const key = ["database", "default"];
|
|
46
|
+
let rc: Connection | undefined;
|
|
47
|
+
|
|
48
|
+
if (ctx.isActive()) {
|
|
49
|
+
rc = ctx().get<Connection>(key);
|
|
50
|
+
} else if (Global.has(key)) {
|
|
51
|
+
rc = Global.get<Connection>(key);
|
|
52
|
+
}
|
|
53
|
+
return rc!;
|
|
22
54
|
});
|
|
23
55
|
|
|
24
56
|
httpServer().setErrorHandler(async (err: Error, req: any, res: any) => {
|
|
@@ -9,9 +9,9 @@ const router = routerFunc();
|
|
|
9
9
|
router.addGlobalMiddleware(loggerMiddleware);
|
|
10
10
|
router.addRoute(
|
|
11
11
|
["GET", "HEAD"],
|
|
12
|
-
"/
|
|
12
|
+
"/",
|
|
13
13
|
async (req: any, res: any) => {
|
|
14
|
-
return { message: "
|
|
14
|
+
return { message: "Welcome to Pashmak!" };
|
|
15
15
|
},
|
|
16
16
|
).addMiddleware([]);
|
|
17
17
|
|
|
@@ -10,6 +10,7 @@ import { CreateProjectCommand } from "../app/console/project/CreateProjectComman
|
|
|
10
10
|
cli.register(CreateProjectCommand);
|
|
11
11
|
cli.runExit(args).then(() => {
|
|
12
12
|
}).catch((err) => {
|
|
13
|
-
console.error(err);
|
|
13
|
+
console.error("Fatal error:", err.message);
|
|
14
|
+
process.exit(1);
|
|
14
15
|
});
|
|
15
16
|
//# sourceMappingURL=pashmak_cli.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/bin/pashmak_cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Cli } from \"clipanion\";\n\nconst [node, app, ...args] = process.argv;\nconst cli = new Cli({\n binaryLabel: `Pashmak CLI`,\n binaryName: `${node} ${app}`,\n binaryVersion: `1.0.0`,\n});\n\nimport { CreateProjectCommand } from \"../app/console/project/CreateProjectCommand.mjs\";\n\ncli.register(CreateProjectCommand);\n\ncli\n .runExit(args)\n .then(() => {})\n .catch((err: any) => {\n console.error(err);\n });\n"],"mappings":";AAEA,SAASA,WAAW;AAEpB,MAAM,CAACC,MAAMC,KAAK,GAAGC,IAAAA,IAAQC,QAAQC;AACrC,MAAMC,MAAM,IAAIN,IAAI;EAClBO,aAAa;EACbC,YAAY,GAAGP,IAAAA,IAAQC,GAAAA;EACvBO,eAAe;AACjB,CAAA;AAEA,SAASC,4BAA4B;AAErCJ,IAAIK,SAASD,oBAAAA;AAEbJ,IACGM,QAAQT,IAAAA,EACRU,KAAK,MAAA;AAAO,CAAA,EACZC,MAAM,CAACC,QAAAA;AACNC,UAAQC,
|
|
1
|
+
{"version":3,"sources":["../../../src/bin/pashmak_cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Cli } from \"clipanion\";\n\nconst [node, app, ...args] = process.argv;\nconst cli = new Cli({\n binaryLabel: `Pashmak CLI`,\n binaryName: `${node} ${app}`,\n binaryVersion: `1.0.0`,\n});\n\nimport { CreateProjectCommand } from \"../app/console/project/CreateProjectCommand.mjs\";\n\ncli.register(CreateProjectCommand);\n\ncli\n .runExit(args)\n .then(() => {})\n .catch((err: any) => {\n console.error(\"Fatal error:\", err.message);\n process.exit(1);\n });\n"],"mappings":";AAEA,SAASA,WAAW;AAEpB,MAAM,CAACC,MAAMC,KAAK,GAAGC,IAAAA,IAAQC,QAAQC;AACrC,MAAMC,MAAM,IAAIN,IAAI;EAClBO,aAAa;EACbC,YAAY,GAAGP,IAAAA,IAAQC,GAAAA;EACvBO,eAAe;AACjB,CAAA;AAEA,SAASC,4BAA4B;AAErCJ,IAAIK,SAASD,oBAAAA;AAEbJ,IACGM,QAAQT,IAAAA,EACRU,KAAK,MAAA;AAAO,CAAA,EACZC,MAAM,CAACC,QAAAA;AACNC,UAAQC,MAAM,gBAAgBF,IAAIG,OAAO;AACzCd,UAAQe,KAAK,CAAA;AACf,CAAA;","names":["Cli","node","app","args","process","argv","cli","binaryLabel","binaryName","binaryVersion","CreateProjectCommand","register","runExit","then","catch","err","console","error","message","exit"]}
|
package/dist/esm/config.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config.mts"],"sourcesContent":["export * from \"@devbro/neko-config\"
|
|
1
|
+
{"version":3,"sources":["../../src/config.mts"],"sourcesContent":["export * from \"@devbro/neko-config\";"],"mappings":"AAAA,cAAc;","names":[]}
|
package/dist/esm/index.d.mts
CHANGED
package/dist/esm/index.mjs
CHANGED
|
@@ -1,33 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
import { context_provider } from "@devbro/neko-context";
|
|
4
|
-
import { runNext } from "@devbro/neko-router";
|
|
5
|
-
import { config } from "@devbro/neko-config";
|
|
6
|
-
async function bootstrap(options) {
|
|
7
|
-
console.log("Bootstrapping application...");
|
|
8
|
-
console.log(`Root directory: ${options.root_dir}`);
|
|
9
|
-
config.load(options.config_data || {});
|
|
10
|
-
console.log("Loading application modules...");
|
|
11
|
-
await import("./app/console/index.mjs");
|
|
12
|
-
console.log("Loading Database Provider ...");
|
|
13
|
-
const { DatabaseServiceProvider } = await import("./DatabaseServiceProvider.mjs");
|
|
14
|
-
console.log("Setting up pre-loader for context provider...");
|
|
15
|
-
context_provider.setPreLoader(async (f) => {
|
|
16
|
-
const middlewares = [];
|
|
17
|
-
middlewares.push(DatabaseServiceProvider.getInstance());
|
|
18
|
-
return await runNext(
|
|
19
|
-
middlewares,
|
|
20
|
-
{},
|
|
21
|
-
{},
|
|
22
|
-
// @ts-ignore
|
|
23
|
-
f
|
|
24
|
-
);
|
|
25
|
-
});
|
|
26
|
-
console.log("Application bootstrapped successfully.");
|
|
27
|
-
}
|
|
28
|
-
__name(bootstrap, "bootstrap");
|
|
29
|
-
export {
|
|
30
|
-
bootstrap,
|
|
31
|
-
config
|
|
32
|
-
};
|
|
1
|
+
import "./app/console/index.mjs";
|
|
33
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import './app/console/index.mjs';\n"],"mappings":"AAAA,OAAO;","names":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Request, Response, Middleware } from '@devbro/neko-router';
|
|
2
|
+
import { PostgresqlConfig, MysqlConfig, SqliteConfig, Connection } from '@devbro/neko-sql';
|
|
2
3
|
|
|
3
4
|
declare function cors(options?: {
|
|
4
5
|
allowedOrigins?: (string | RegExp)[];
|
|
@@ -47,5 +48,15 @@ declare class RateLimiterMiddleware extends Middleware {
|
|
|
47
48
|
constructor(params: RateLimiterMiddlewareParams);
|
|
48
49
|
call(req: Request, res: Response, next: () => Promise<void>): Promise<void>;
|
|
49
50
|
}
|
|
51
|
+
declare class DatabaseProviderMiddleware extends Middleware {
|
|
52
|
+
call(req: Request, res: Response, next: () => Promise<void>): Promise<void>;
|
|
53
|
+
private static instance;
|
|
54
|
+
register(): Promise<void>;
|
|
55
|
+
static getInstance(): DatabaseProviderMiddleware;
|
|
56
|
+
getConnection(db_config: {
|
|
57
|
+
provider: string;
|
|
58
|
+
config: PostgresqlConfig | MysqlConfig | SqliteConfig;
|
|
59
|
+
}): Connection;
|
|
60
|
+
}
|
|
50
61
|
|
|
51
|
-
export { RateLimiterMiddleware, type RateLimiterMiddlewareParams, cors, dbTransaction };
|
|
62
|
+
export { DatabaseProviderMiddleware, RateLimiterMiddleware, type RateLimiterMiddlewareParams, cors, dbTransaction };
|
package/dist/esm/middlewares.mjs
CHANGED
|
@@ -3,6 +3,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
3
3
|
import { Middleware } from "@devbro/neko-router";
|
|
4
4
|
import { db, cache } from "./facades.mjs";
|
|
5
5
|
import { HttpTooManyRequestsError } from "@devbro/neko-http";
|
|
6
|
+
import { config } from "@devbro/neko-config";
|
|
7
|
+
import { ctx } from "./context.mjs";
|
|
8
|
+
import { MysqlConnection, PostgresqlConnection, SqliteConnection } from "@devbro/neko-sql";
|
|
6
9
|
function cors(options = {}) {
|
|
7
10
|
return async (req, res, next) => {
|
|
8
11
|
const allowedOrigins = options.allowedOrigins || ["*"];
|
|
@@ -91,7 +94,56 @@ class RateLimiterMiddleware extends Middleware {
|
|
|
91
94
|
return;
|
|
92
95
|
}
|
|
93
96
|
}
|
|
97
|
+
class DatabaseProviderMiddleware extends Middleware {
|
|
98
|
+
static {
|
|
99
|
+
__name(this, "DatabaseProviderMiddleware");
|
|
100
|
+
}
|
|
101
|
+
async call(req, res, next) {
|
|
102
|
+
const db_configs = config.get("databases");
|
|
103
|
+
const conns = [];
|
|
104
|
+
try {
|
|
105
|
+
for (const [name, db_config] of Object.entries(db_configs)) {
|
|
106
|
+
if (ctx().get(["database", name])) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const conn = await this.getConnection(db_config);
|
|
110
|
+
ctx().set(["database", name], conn);
|
|
111
|
+
conns.push(conn);
|
|
112
|
+
}
|
|
113
|
+
await next();
|
|
114
|
+
} finally {
|
|
115
|
+
for (const conn of conns) {
|
|
116
|
+
await conn.disconnect();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
static instance;
|
|
121
|
+
async register() {
|
|
122
|
+
}
|
|
123
|
+
static getInstance() {
|
|
124
|
+
if (!DatabaseProviderMiddleware.instance) {
|
|
125
|
+
DatabaseProviderMiddleware.instance = new DatabaseProviderMiddleware();
|
|
126
|
+
}
|
|
127
|
+
return DatabaseProviderMiddleware.instance;
|
|
128
|
+
}
|
|
129
|
+
getConnection(db_config) {
|
|
130
|
+
if (db_config.provider === "postgresql") {
|
|
131
|
+
const conn = new PostgresqlConnection(db_config.config);
|
|
132
|
+
return conn;
|
|
133
|
+
}
|
|
134
|
+
if (db_config.provider === "sqlite") {
|
|
135
|
+
const conn = new SqliteConnection(db_config.config);
|
|
136
|
+
return conn;
|
|
137
|
+
}
|
|
138
|
+
if (db_config.provider === "mysql") {
|
|
139
|
+
const conn = new MysqlConnection(db_config.config);
|
|
140
|
+
return conn;
|
|
141
|
+
}
|
|
142
|
+
throw new Error(`Unsupported database provider: ${db_config.provider}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
94
145
|
export {
|
|
146
|
+
DatabaseProviderMiddleware,
|
|
95
147
|
RateLimiterMiddleware,
|
|
96
148
|
cors,
|
|
97
149
|
dbTransaction
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/middlewares.mts"],"sourcesContent":["import { Middleware, Request, Response } from \"@devbro/neko-router\";\nimport { logger, db, cache } from \"./facades.mjs\";\nimport { HttpTooManyRequestsError } from \"@devbro/neko-http\";\n\nexport function cors(\n options: { allowedOrigins?: (string | RegExp)[] } = {},\n): (req: Request, res: Response, next: () => Promise<void>) => Promise<void> {\n return async (\n req: Request,\n res: Response,\n next: () => Promise<void>,\n ): Promise<void> => {\n const allowedOrigins = options.allowedOrigins || [\"*\"];\n const origin = req.headers.origin || \"*\";\n\n for (const allowedOrigin of allowedOrigins) {\n if (typeof allowedOrigin === \"string\" && allowedOrigin === origin) {\n res.setHeader(\"Access-Control-Allow-Origin\", allowedOrigin);\n break;\n } else if (\n allowedOrigin instanceof RegExp &&\n allowedOrigin.test(origin)\n ) {\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n break;\n } else if (allowedOrigin === \"*\") {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n break;\n }\n }\n\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n await next();\n };\n}\n\nexport async function dbTransaction(\n req: Request,\n res: Response,\n next: () => Promise<void>,\n): Promise<void> {\n try {\n await db().beginTransaction();\n await next();\n await db().commit();\n } catch (err) {\n await db().rollback();\n throw err;\n }\n}\n\nexport type RateLimiterMiddlewareParams = {\n generateIdentifier: (req: Request) => string;\n maxRequests: number;\n windowTimeSize: number;\n windowCount: number;\n};\n\n/**\n * Rate limiter middleware using a sliding window algorithm.\n *\n * This middleware tracks request counts across multiple time windows to prevent abuse.\n * It uses atomic cache increments to ensure accurate counting in concurrent environments.\n *\n * @example\n * ```typescript\n * // Basic usage with defaults (200 requests per 2 minutes)\n * authnedRouter.addGlobalMiddleware(RateLimiterMiddleware);\n *\n * // Custom configuration\n * authnedRouter.addGlobalMiddleware(RateLimiterMiddleware.getInstance({\n * generateIdentifier: (req) => req.headers['x-api-key'] || req.socket.remoteAddress,\n * maxRequests: 200, // Allow 200 requests\n * windowTimeSize: 30, // in 30 second windows\n * windowCount: 4 // looking back 4 windows (total: 120 seconds)\n * }));\n * ```\n *\n * @param params.generateIdentifier - Function to generate unique identifier for rate limiting (default: IP address)\n * @param params.maxRequests - Maximum number of requests allowed across all windows (default: 200)\n * @param params.windowTimeSize - Size of each time window in seconds (default: 30)\n * @param params.windowCount - Number of previous windows to check (default: 4)\n *\n * The total time period checked is `windowTimeSize * windowCount` seconds.\n * Default configuration: 200 requests per 120 seconds (30s × 4 windows).\n *\n * @throws {HttpTooManyRequestsError} When rate limit is exceeded\n */\nexport class RateLimiterMiddleware extends Middleware {\n static singletonInstance: Middleware | undefined = undefined;\n static getInstance(\n params: Partial<RateLimiterMiddlewareParams> = {},\n ): Middleware {\n if (RateLimiterMiddleware.singletonInstance) {\n return RateLimiterMiddleware.singletonInstance;\n }\n let default_params: RateLimiterMiddlewareParams = {\n generateIdentifier: (req: Request) =>\n req.socket.remoteAddress || \"unknown\",\n maxRequests: 200,\n windowTimeSize: 30,\n windowCount: 4,\n };\n const merged_params = { ...default_params, ...params };\n return (RateLimiterMiddleware.singletonInstance = new RateLimiterMiddleware(\n merged_params,\n ));\n }\n\n constructor(private params: RateLimiterMiddlewareParams) {\n super();\n }\n\n async call(\n req: Request,\n res: Response,\n next: () => Promise<void>,\n ): Promise<void> {\n let window = parseInt(\n (Date.now() / 1000 / this.params.windowTimeSize).toString(),\n );\n let key = `rate_limiter:${this.params.generateIdentifier(req)}:${window}`;\n let count: number = (await cache().get(key)) || 0;\n if (!count) {\n await cache().put(\n key,\n 1,\n this.params.windowTimeSize * (this.params.windowCount + 1),\n );\n count = 1;\n } else {\n count = await cache().increment(key, 1);\n }\n\n for (let i = 1; i < this.params.windowCount; i++) {\n count += parseInt(\n (await cache().get(\n `rate_limiter:${this.params.generateIdentifier(req)}:${window - i}`,\n )) || \"0\",\n );\n }\n\n if (count > this.params.maxRequests) {\n throw new HttpTooManyRequestsError(\n \"Too many requests. Please try again later.\",\n );\n }\n\n await next();\n return;\n }\n}\n"],"mappings":";;AAAA,SAAS,kBAAqC;AAC9C,SAAiB,IAAI,aAAa;AAClC,SAAS,gCAAgC;AAElC,SAAS,KACd,UAAoD,CAAC,GACsB;AAC3E,SAAO,OACL,KACA,KACA,SACkB;AAClB,UAAM,iBAAiB,QAAQ,kBAAkB,CAAC,GAAG;AACrD,UAAM,SAAS,IAAI,QAAQ,UAAU;AAErC,eAAW,iBAAiB,gBAAgB;AAC1C,UAAI,OAAO,kBAAkB,YAAY,kBAAkB,QAAQ;AACjE,YAAI,UAAU,+BAA+B,aAAa;AAC1D;AAAA,MACF,WACE,yBAAyB,UACzB,cAAc,KAAK,MAAM,GACzB;AACA,YAAI,UAAU,+BAA+B,MAAM;AACnD;AAAA,MACF,WAAW,kBAAkB,KAAK;AAChC,YAAI,UAAU,+BAA+B,GAAG;AAChD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,gCAAgC,GAAG;AACjD,UAAM,KAAK;AAAA,EACb;AACF;AA9BgB;AAgChB,eAAsB,cACpB,KACA,KACA,MACe;AACf,MAAI;AACF,UAAM,GAAG,EAAE,iBAAiB;AAC5B,UAAM,KAAK;AACX,UAAM,GAAG,EAAE,OAAO;AAAA,EACpB,SAAS,KAAK;AACZ,UAAM,GAAG,EAAE,SAAS;AACpB,UAAM;AAAA,EACR;AACF;AAbsB;AAoDf,MAAM,8BAA8B,WAAW;AAAA,EAqBpD,YAAoB,QAAqC;AACvD,UAAM;AADY;AAAA,EAEpB;AAAA,EA/GF,OAwFsD;AAAA;AAAA;AAAA,EACpD,OAAO,oBAA4C;AAAA,EACnD,OAAO,YACL,SAA+C,CAAC,GACpC;AACZ,QAAI,sBAAsB,mBAAmB;AAC3C,aAAO,sBAAsB;AAAA,IAC/B;AACA,QAAI,iBAA8C;AAAA,MAChD,oBAAoB,wBAAC,QACnB,IAAI,OAAO,iBAAiB,WADV;AAAA,MAEpB,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AACA,UAAM,gBAAgB,EAAE,GAAG,gBAAgB,GAAG,OAAO;AACrD,WAAQ,sBAAsB,oBAAoB,IAAI;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA,EAMA,MAAM,KACJ,KACA,KACA,MACe;AACf,QAAI,SAAS;AAAA,OACV,KAAK,IAAI,IAAI,MAAO,KAAK,OAAO,gBAAgB,SAAS;AAAA,IAC5D;AACA,QAAI,MAAM,gBAAgB,KAAK,OAAO,mBAAmB,GAAG,CAAC,IAAI,MAAM;AACvE,QAAI,QAAiB,MAAM,MAAM,EAAE,IAAI,GAAG,KAAM;AAChD,QAAI,CAAC,OAAO;AACV,YAAM,MAAM,EAAE;AAAA,QACZ;AAAA,QACA;AAAA,QACA,KAAK,OAAO,kBAAkB,KAAK,OAAO,cAAc;AAAA,MAC1D;AACA,cAAQ;AAAA,IACV,OAAO;AACL,cAAQ,MAAM,MAAM,EAAE,UAAU,KAAK,CAAC;AAAA,IACxC;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,aAAa,KAAK;AAChD,eAAS;AAAA,QACN,MAAM,MAAM,EAAE;AAAA,UACb,gBAAgB,KAAK,OAAO,mBAAmB,GAAG,CAAC,IAAI,SAAS,CAAC;AAAA,QACnE,KAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,QAAQ,KAAK,OAAO,aAAa;AACnC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK;AACX;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/middlewares.mts"],"sourcesContent":["import { Middleware, Request, Response } from \"@devbro/neko-router\";\nimport { logger, db, cache } from \"./facades.mjs\";\nimport { HttpTooManyRequestsError } from \"@devbro/neko-http\";\nimport { config } from \"@devbro/neko-config\";\nimport { Connection } from \"@devbro/neko-sql\";\nimport { Global } from './global.mjs';\nimport { ctx } from './context.mjs';\nimport { BaseModel } from \"@devbro/neko-orm\";\nimport { MysqlConnection, PostgresqlConnection, SqliteConnection, SqliteConfig, PostgresqlConfig, MysqlConfig } from \"@devbro/neko-sql\";\n\nexport function cors(\n options: { allowedOrigins?: (string | RegExp)[] } = {},\n): (req: Request, res: Response, next: () => Promise<void>) => Promise<void> {\n return async (\n req: Request,\n res: Response,\n next: () => Promise<void>,\n ): Promise<void> => {\n const allowedOrigins = options.allowedOrigins || [\"*\"];\n const origin = req.headers.origin || \"*\";\n\n for (const allowedOrigin of allowedOrigins) {\n if (typeof allowedOrigin === \"string\" && allowedOrigin === origin) {\n res.setHeader(\"Access-Control-Allow-Origin\", allowedOrigin);\n break;\n } else if (\n allowedOrigin instanceof RegExp &&\n allowedOrigin.test(origin)\n ) {\n res.setHeader(\"Access-Control-Allow-Origin\", origin);\n break;\n } else if (allowedOrigin === \"*\") {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n break;\n }\n }\n\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n await next();\n };\n}\n\nexport async function dbTransaction(\n req: Request,\n res: Response,\n next: () => Promise<void>,\n): Promise<void> {\n try {\n await db().beginTransaction();\n await next();\n await db().commit();\n } catch (err) {\n await db().rollback();\n throw err;\n }\n}\n\nexport type RateLimiterMiddlewareParams = {\n generateIdentifier: (req: Request) => string;\n maxRequests: number;\n windowTimeSize: number;\n windowCount: number;\n};\n\n/**\n * Rate limiter middleware using a sliding window algorithm.\n *\n * This middleware tracks request counts across multiple time windows to prevent abuse.\n * It uses atomic cache increments to ensure accurate counting in concurrent environments.\n *\n * @example\n * ```typescript\n * // Basic usage with defaults (200 requests per 2 minutes)\n * authnedRouter.addGlobalMiddleware(RateLimiterMiddleware);\n *\n * // Custom configuration\n * authnedRouter.addGlobalMiddleware(RateLimiterMiddleware.getInstance({\n * generateIdentifier: (req) => req.headers['x-api-key'] || req.socket.remoteAddress,\n * maxRequests: 200, // Allow 200 requests\n * windowTimeSize: 30, // in 30 second windows\n * windowCount: 4 // looking back 4 windows (total: 120 seconds)\n * }));\n * ```\n *\n * @param params.generateIdentifier - Function to generate unique identifier for rate limiting (default: IP address)\n * @param params.maxRequests - Maximum number of requests allowed across all windows (default: 200)\n * @param params.windowTimeSize - Size of each time window in seconds (default: 30)\n * @param params.windowCount - Number of previous windows to check (default: 4)\n *\n * The total time period checked is `windowTimeSize * windowCount` seconds.\n * Default configuration: 200 requests per 120 seconds (30s × 4 windows).\n *\n * @throws {HttpTooManyRequestsError} When rate limit is exceeded\n */\nexport class RateLimiterMiddleware extends Middleware {\n static singletonInstance: Middleware | undefined = undefined;\n static getInstance(\n params: Partial<RateLimiterMiddlewareParams> = {},\n ): Middleware {\n if (RateLimiterMiddleware.singletonInstance) {\n return RateLimiterMiddleware.singletonInstance;\n }\n let default_params: RateLimiterMiddlewareParams = {\n generateIdentifier: (req: Request) =>\n req.socket.remoteAddress || \"unknown\",\n maxRequests: 200,\n windowTimeSize: 30,\n windowCount: 4,\n };\n const merged_params = { ...default_params, ...params };\n return (RateLimiterMiddleware.singletonInstance = new RateLimiterMiddleware(\n merged_params,\n ));\n }\n\n constructor(private params: RateLimiterMiddlewareParams) {\n super();\n }\n\n async call(\n req: Request,\n res: Response,\n next: () => Promise<void>,\n ): Promise<void> {\n let window = parseInt(\n (Date.now() / 1000 / this.params.windowTimeSize).toString(),\n );\n let key = `rate_limiter:${this.params.generateIdentifier(req)}:${window}`;\n let count: number = (await cache().get(key)) || 0;\n if (!count) {\n await cache().put(\n key,\n 1,\n this.params.windowTimeSize * (this.params.windowCount + 1),\n );\n count = 1;\n } else {\n count = await cache().increment(key, 1);\n }\n\n for (let i = 1; i < this.params.windowCount; i++) {\n count += parseInt(\n (await cache().get(\n `rate_limiter:${this.params.generateIdentifier(req)}:${window - i}`,\n )) || \"0\",\n );\n }\n\n if (count > this.params.maxRequests) {\n throw new HttpTooManyRequestsError(\n \"Too many requests. Please try again later.\",\n );\n }\n\n await next();\n return;\n }\n}\n\nexport class DatabaseProviderMiddleware extends Middleware {\n async call(\n req: Request,\n res: Response,\n next: () => Promise<void>,\n ): Promise<void> {\n const db_configs: Record<string, { provider: string; config: PostgresqlConfig | MysqlConfig | SqliteConfig }> =\n config.get(\"databases\");\n\n const conns = [];\n try {\n for (const [name, db_config] of Object.entries(db_configs)) {\n if(ctx().get([\"database\", name])) {\n return;\n }\n const conn = await this.getConnection(db_config);\n ctx().set([\"database\", name], conn);\n conns.push(conn);\n }\n await next();\n } finally {\n for (const conn of conns) {\n await conn.disconnect();\n }\n }\n }\n\n private static instance: DatabaseProviderMiddleware;\n\n async register(): Promise<void> {}\n\n static getInstance(): DatabaseProviderMiddleware {\n if (!DatabaseProviderMiddleware.instance) {\n DatabaseProviderMiddleware.instance = new DatabaseProviderMiddleware();\n }\n return DatabaseProviderMiddleware.instance;\n }\n\n getConnection(db_config: {\n provider: string;\n config: PostgresqlConfig | MysqlConfig | SqliteConfig;\n }): Connection {\n if (db_config.provider === \"postgresql\") {\n const conn = new PostgresqlConnection(db_config.config as PostgresqlConfig);\n return conn;\n }\n\n if (db_config.provider === \"sqlite\") {\n const conn = new SqliteConnection(db_config.config as SqliteConfig);\n return conn;\n }\n\n if(db_config.provider === \"mysql\") {\n const conn = new MysqlConnection(db_config.config as MysqlConfig);\n return conn;\n }\n\n throw new Error(`Unsupported database provider: ${db_config.provider}`);\n }\n}\n"],"mappings":";;AAAA,SAAS,kBAAqC;AAC9C,SAAiB,IAAI,aAAa;AAClC,SAAS,gCAAgC;AACzC,SAAS,cAAc;AAGvB,SAAS,WAAW;AAEpB,SAAS,iBAAiB,sBAAsB,wBAAqE;AAE9G,SAAS,KACd,UAAoD,CAAC,GACsB;AAC3E,SAAO,OACL,KACA,KACA,SACkB;AAClB,UAAM,iBAAiB,QAAQ,kBAAkB,CAAC,GAAG;AACrD,UAAM,SAAS,IAAI,QAAQ,UAAU;AAErC,eAAW,iBAAiB,gBAAgB;AAC1C,UAAI,OAAO,kBAAkB,YAAY,kBAAkB,QAAQ;AACjE,YAAI,UAAU,+BAA+B,aAAa;AAC1D;AAAA,MACF,WACE,yBAAyB,UACzB,cAAc,KAAK,MAAM,GACzB;AACA,YAAI,UAAU,+BAA+B,MAAM;AACnD;AAAA,MACF,WAAW,kBAAkB,KAAK;AAChC,YAAI,UAAU,+BAA+B,GAAG;AAChD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,gCAAgC,GAAG;AACjD,UAAM,KAAK;AAAA,EACb;AACF;AA9BgB;AAgChB,eAAsB,cACpB,KACA,KACA,MACe;AACf,MAAI;AACF,UAAM,GAAG,EAAE,iBAAiB;AAC5B,UAAM,KAAK;AACX,UAAM,GAAG,EAAE,OAAO;AAAA,EACpB,SAAS,KAAK;AACZ,UAAM,GAAG,EAAE,SAAS;AACpB,UAAM;AAAA,EACR;AACF;AAbsB;AAoDf,MAAM,8BAA8B,WAAW;AAAA,EAqBpD,YAAoB,QAAqC;AACvD,UAAM;AADY;AAAA,EAEpB;AAAA,EArHF,OA8FsD;AAAA;AAAA;AAAA,EACpD,OAAO,oBAA4C;AAAA,EACnD,OAAO,YACL,SAA+C,CAAC,GACpC;AACZ,QAAI,sBAAsB,mBAAmB;AAC3C,aAAO,sBAAsB;AAAA,IAC/B;AACA,QAAI,iBAA8C;AAAA,MAChD,oBAAoB,wBAAC,QACnB,IAAI,OAAO,iBAAiB,WADV;AAAA,MAEpB,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AACA,UAAM,gBAAgB,EAAE,GAAG,gBAAgB,GAAG,OAAO;AACrD,WAAQ,sBAAsB,oBAAoB,IAAI;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA,EAMA,MAAM,KACJ,KACA,KACA,MACe;AACf,QAAI,SAAS;AAAA,OACV,KAAK,IAAI,IAAI,MAAO,KAAK,OAAO,gBAAgB,SAAS;AAAA,IAC5D;AACA,QAAI,MAAM,gBAAgB,KAAK,OAAO,mBAAmB,GAAG,CAAC,IAAI,MAAM;AACvE,QAAI,QAAiB,MAAM,MAAM,EAAE,IAAI,GAAG,KAAM;AAChD,QAAI,CAAC,OAAO;AACV,YAAM,MAAM,EAAE;AAAA,QACZ;AAAA,QACA;AAAA,QACA,KAAK,OAAO,kBAAkB,KAAK,OAAO,cAAc;AAAA,MAC1D;AACA,cAAQ;AAAA,IACV,OAAO;AACL,cAAQ,MAAM,MAAM,EAAE,UAAU,KAAK,CAAC;AAAA,IACxC;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,aAAa,KAAK;AAChD,eAAS;AAAA,QACN,MAAM,MAAM,EAAE;AAAA,UACb,gBAAgB,KAAK,OAAO,mBAAmB,GAAG,CAAC,IAAI,SAAS,CAAC;AAAA,QACnE,KAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,QAAQ,KAAK,OAAO,aAAa;AACnC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,KAAK;AACX;AAAA,EACF;AACF;AAEO,MAAM,mCAAmC,WAAW;AAAA,EA/J3D,OA+J2D;AAAA;AAAA;AAAA,EACzD,MAAM,KACJ,KACA,KACA,MACe;AACf,UAAM,aACJ,OAAO,IAAI,WAAW;AAExB,UAAM,QAAQ,CAAC;AACf,QAAI;AACF,iBAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,YAAG,IAAI,EAAE,IAAI,CAAC,YAAY,IAAI,CAAC,GAAG;AAChC;AAAA,QACF;AACA,cAAM,OAAO,MAAM,KAAK,cAAc,SAAS;AAC/C,YAAI,EAAE,IAAI,CAAC,YAAY,IAAI,GAAG,IAAI;AAClC,cAAM,KAAK,IAAI;AAAA,MACjB;AACA,YAAM,KAAK;AAAA,IACb,UAAE;AACA,iBAAW,QAAQ,OAAO;AACxB,cAAM,KAAK,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAe;AAAA,EAEf,MAAM,WAA0B;AAAA,EAAC;AAAA,EAEjC,OAAO,cAA0C;AAC/C,QAAI,CAAC,2BAA2B,UAAU;AACxC,iCAA2B,WAAW,IAAI,2BAA2B;AAAA,IACvE;AACA,WAAO,2BAA2B;AAAA,EACpC;AAAA,EAEA,cAAc,WAGC;AACb,QAAI,UAAU,aAAa,cAAc;AACvC,YAAM,OAAO,IAAI,qBAAqB,UAAU,MAA0B;AAC1E,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,aAAa,UAAU;AACnC,YAAM,OAAO,IAAI,iBAAiB,UAAU,MAAsB;AAClE,aAAO;AAAA,IACT;AAEA,QAAG,UAAU,aAAa,SAAS;AACjC,YAAM,OAAO,IAAI,gBAAgB,UAAU,MAAqB;AAChE,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,MAAM,kCAAkC,UAAU,QAAQ,EAAE;AAAA,EACxE;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devbro/pashmak",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.56",
|
|
4
4
|
"description": "Pashmak framework, the framework that aims to be the easiest framework for all",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.mjs",
|
|
@@ -112,7 +112,8 @@
|
|
|
112
112
|
"format": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0 ",
|
|
113
113
|
"prepare": "husky",
|
|
114
114
|
"prettier": "prettier --write .",
|
|
115
|
-
"clean": "rm -rf dist"
|
|
115
|
+
"clean": "rm -rf dist",
|
|
116
|
+
"cli": "tsx -r tsconfig-paths/register src/bin/pashmak_cli.ts"
|
|
116
117
|
},
|
|
117
118
|
"author": "Farzad Meow Khalafi",
|
|
118
119
|
"license": "MIT",
|
|
@@ -120,6 +121,7 @@
|
|
|
120
121
|
"@swc/core": "^1.12.9",
|
|
121
122
|
"@types/yup": "^0.32.0",
|
|
122
123
|
"globby": "^14.1.0",
|
|
124
|
+
"tsconfig-paths": "^4.2.0",
|
|
123
125
|
"typescript": "^5.9.3"
|
|
124
126
|
},
|
|
125
127
|
"dependencies": {
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "test-app",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "testing application for the entire repo",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"type": "module",
|
|
9
|
-
"files": [
|
|
10
|
-
"dist"
|
|
11
|
-
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "tsup",
|
|
14
|
-
"start": "tsx dist/index.js",
|
|
15
|
-
"test": "vitest run",
|
|
16
|
-
"test:watch": "vitest watch",
|
|
17
|
-
"test:coverage": "vitest run --coverage",
|
|
18
|
-
"format": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0 ",
|
|
19
|
-
"prepare": "husky",
|
|
20
|
-
"prettier": "prettier --write .",
|
|
21
|
-
"dev": "nodemon --watch src --ext ts,tsx,json --signal SIGTERM --exec \"clear && tsx -r tsconfig-paths/register src/index.ts start --all | npx pino-pretty\"",
|
|
22
|
-
"pdev": "tsx -r tsconfig-paths/register src/index.ts",
|
|
23
|
-
"clean": "rm -rf dist"
|
|
24
|
-
},
|
|
25
|
-
"author": "???",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@swc/core": "^1.12.9",
|
|
29
|
-
"@types/config": "^3.3.5",
|
|
30
|
-
"@types/jsonwebtoken": "^9.0.9",
|
|
31
|
-
"@types/supertest": "^6.0.2",
|
|
32
|
-
"@types/yup": "^0.32.0",
|
|
33
|
-
"nodemon": "^3.1.10",
|
|
34
|
-
"supertest": "^6.3.3",
|
|
35
|
-
"tsx": "^4.20.3",
|
|
36
|
-
"typescript": "^5.8.3",
|
|
37
|
-
"pino-pretty": "^13.0.0",
|
|
38
|
-
"husky": "^9.1.7",
|
|
39
|
-
"vitest": "^3.2.4"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@devbro/pashmak": "0.1.*",
|
|
43
|
-
"bcryptjs": "^3.0.2",
|
|
44
|
-
"clipanion": "^4.0.0-rc.4",
|
|
45
|
-
"jsonwebtoken": "^9.0.0",
|
|
46
|
-
"tsconfig-paths": "^4.2.0",
|
|
47
|
-
{{#if (eq validation_library "yup")}}
|
|
48
|
-
"yup": "^1.6.1",
|
|
49
|
-
{{/if}}
|
|
50
|
-
{{#if (eq validation_library "zod")}}
|
|
51
|
-
"zod": "^4.1.12",
|
|
52
|
-
{{/if}}
|
|
53
|
-
"dotenv": "^16.5.0"
|
|
54
|
-
},
|
|
55
|
-
"directories": {
|
|
56
|
-
"doc": "docs",
|
|
57
|
-
"test": "tests"
|
|
58
|
-
},
|
|
59
|
-
"repository": {
|
|
60
|
-
"type": "git",
|
|
61
|
-
"url": "git+ssh://git@github.com/devbro1/pashmak.git"
|
|
62
|
-
},
|
|
63
|
-
"keywords": [
|
|
64
|
-
"pashmak"
|
|
65
|
-
],
|
|
66
|
-
"bugs": {
|
|
67
|
-
"url": "https://github.com/devbro1/pashmak/issues"
|
|
68
|
-
},
|
|
69
|
-
"homepage": "https://devbro1.github.io/pashmak/",
|
|
70
|
-
"tags": {
|
|
71
|
-
"needsCompile": true,
|
|
72
|
-
"canPublishToNpm": false
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default {};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "test-app",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "testing application for the entire repo",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"type": "module",
|
|
9
|
-
"files": [
|
|
10
|
-
"dist"
|
|
11
|
-
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "tsup",
|
|
14
|
-
"start": "tsx dist/index.js",
|
|
15
|
-
"test": "vitest run",
|
|
16
|
-
"test:watch": "vitest watch",
|
|
17
|
-
"test:coverage": "vitest run --coverage",
|
|
18
|
-
"format": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0 ",
|
|
19
|
-
"prepare": "husky",
|
|
20
|
-
"prettier": "prettier --write .",
|
|
21
|
-
"dev": "nodemon --watch src --ext ts,tsx,json --signal SIGTERM --exec \"clear && tsx -r tsconfig-paths/register src/index.ts start --all | npx pino-pretty\"",
|
|
22
|
-
"pdev": "tsx -r tsconfig-paths/register src/index.ts",
|
|
23
|
-
"clean": "rm -rf dist"
|
|
24
|
-
},
|
|
25
|
-
"author": "???",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@swc/core": "^1.12.9",
|
|
29
|
-
"@types/config": "^3.3.5",
|
|
30
|
-
"@types/jsonwebtoken": "^9.0.9",
|
|
31
|
-
"@types/supertest": "^6.0.2",
|
|
32
|
-
"@types/yup": "^0.32.0",
|
|
33
|
-
"nodemon": "^3.1.10",
|
|
34
|
-
"supertest": "^6.3.3",
|
|
35
|
-
"tsx": "^4.20.3",
|
|
36
|
-
"typescript": "^5.8.3",
|
|
37
|
-
"pino-pretty": "^13.0.0",
|
|
38
|
-
"husky": "^9.1.7",
|
|
39
|
-
"vitest": "^3.2.4"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@devbro/pashmak": "0.1.*",
|
|
43
|
-
"bcryptjs": "^3.0.2",
|
|
44
|
-
"clipanion": "^4.0.0-rc.4",
|
|
45
|
-
"jsonwebtoken": "^9.0.0",
|
|
46
|
-
"tsconfig-paths": "^4.2.0",
|
|
47
|
-
{{#if (eq validation_library "yup")}}
|
|
48
|
-
"yup": "^1.6.1",
|
|
49
|
-
{{/if}}
|
|
50
|
-
{{#if (eq validation_library "zod")}}
|
|
51
|
-
"zod": "^4.1.12",
|
|
52
|
-
{{/if}}
|
|
53
|
-
"dotenv": "^16.5.0"
|
|
54
|
-
},
|
|
55
|
-
"directories": {
|
|
56
|
-
"doc": "docs",
|
|
57
|
-
"test": "tests"
|
|
58
|
-
},
|
|
59
|
-
"repository": {
|
|
60
|
-
"type": "git",
|
|
61
|
-
"url": "git+ssh://git@github.com/devbro1/pashmak.git"
|
|
62
|
-
},
|
|
63
|
-
"keywords": [
|
|
64
|
-
"pashmak"
|
|
65
|
-
],
|
|
66
|
-
"bugs": {
|
|
67
|
-
"url": "https://github.com/devbro1/pashmak/issues"
|
|
68
|
-
},
|
|
69
|
-
"homepage": "https://devbro1.github.io/pashmak/",
|
|
70
|
-
"tags": {
|
|
71
|
-
"needsCompile": true,
|
|
72
|
-
"canPublishToNpm": false
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default {};
|
/package/dist/cjs/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl}
RENAMED
|
File without changes
|
/package/dist/esm/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl}
RENAMED
|
File without changes
|