@devbro/pashmak 0.1.55 → 0.1.57

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.
Files changed (64) hide show
  1. package/dist/cjs/app/console/DefaultCommand.js +52 -0
  2. package/dist/cjs/app/console/KeyGenerateCommand.js +52 -0
  3. package/dist/cjs/app/console/StartCommand.js +52 -0
  4. package/dist/cjs/app/console/generate/GenerateApiDocsCommand.js +52 -0
  5. package/dist/cjs/app/console/generate/GenerateControllerCommand.js +52 -0
  6. package/dist/cjs/app/console/generate/index.js +52 -0
  7. package/dist/cjs/app/console/index.js +320 -70
  8. package/dist/cjs/app/console/migrate/GenerateMigrateCommand.js +52 -0
  9. package/dist/cjs/app/console/migrate/MigrateCommand.js +52 -0
  10. package/dist/cjs/app/console/migrate/MigrateRollbackCommand.js +52 -0
  11. package/dist/cjs/app/console/migrate/index.js +52 -0
  12. package/dist/cjs/app/console/project/CreateProjectCommand.js +263 -65
  13. package/dist/cjs/app/console/project/base_project/src/config/caches.ts.tpl +11 -1
  14. package/dist/cjs/app/console/project/base_project/src/config/databases.ts.tpl +8 -6
  15. package/dist/cjs/app/console/project/base_project/src/config/default.mts.tpl +13 -20
  16. package/dist/cjs/app/console/project/base_project/src/config/loggers.ts.tpl +13 -3
  17. package/dist/cjs/app/console/project/base_project/src/config/storages.ts.tpl +1 -2
  18. package/dist/cjs/app/console/project/base_project/src/initialize.ts.tpl +48 -16
  19. package/dist/cjs/app/console/project/base_project/src/routes.ts.tpl +2 -2
  20. package/dist/cjs/app/console/queue/GenerateQueueMigrateCommand.js +52 -0
  21. package/dist/cjs/bin/pashmak_cli.js +265 -66
  22. package/dist/cjs/cache/MultiCache.js +71 -0
  23. package/dist/cjs/{cache.js → cache/cache.js} +54 -2
  24. package/dist/cjs/facades.js +52 -0
  25. package/dist/cjs/factories.js +52 -0
  26. package/dist/cjs/http.js +52 -0
  27. package/dist/cjs/index.js +1900 -2056
  28. package/dist/cjs/middlewares.js +112 -2
  29. package/dist/cjs/queue.js +52 -0
  30. package/dist/esm/app/console/project/CreateProjectCommand.d.mts +15 -2
  31. package/dist/esm/app/console/project/CreateProjectCommand.mjs +265 -67
  32. package/dist/esm/app/console/project/CreateProjectCommand.mjs.map +1 -1
  33. package/dist/esm/app/console/project/base_project/src/config/caches.ts.tpl +11 -1
  34. package/dist/esm/app/console/project/base_project/src/config/databases.ts.tpl +8 -6
  35. package/dist/esm/app/console/project/base_project/src/config/default.mts.tpl +13 -20
  36. package/dist/esm/app/console/project/base_project/src/config/loggers.ts.tpl +13 -3
  37. package/dist/esm/app/console/project/base_project/src/config/storages.ts.tpl +1 -2
  38. package/dist/esm/app/console/project/base_project/src/initialize.ts.tpl +48 -16
  39. package/dist/esm/app/console/project/base_project/src/routes.ts.tpl +2 -2
  40. package/dist/esm/bin/pashmak_cli.mjs +2 -1
  41. package/dist/esm/bin/pashmak_cli.mjs.map +1 -1
  42. package/dist/esm/cache/MultiCache.d.mts +14 -0
  43. package/dist/esm/cache/MultiCache.mjs +47 -0
  44. package/dist/esm/cache/MultiCache.mjs.map +1 -0
  45. package/dist/esm/{cache.mjs → cache/cache.mjs} +1 -1
  46. package/dist/esm/cache/cache.mjs.map +1 -0
  47. package/dist/esm/config.mjs.map +1 -1
  48. package/dist/esm/factories.mjs +9 -0
  49. package/dist/esm/factories.mjs.map +1 -1
  50. package/dist/esm/index.d.mts +1 -7
  51. package/dist/esm/index.mjs +1 -32
  52. package/dist/esm/index.mjs.map +1 -1
  53. package/dist/esm/middlewares.d.mts +12 -1
  54. package/dist/esm/middlewares.mjs +52 -0
  55. package/dist/esm/middlewares.mjs.map +1 -1
  56. package/package.json +4 -2
  57. package/dist/cjs/app/console/project/base_project/package.json.tpl +0 -74
  58. package/dist/cjs/app/console/project/base_project/src/config/test.ts.tpl +0 -1
  59. package/dist/esm/app/console/project/base_project/package.json.tpl +0 -74
  60. package/dist/esm/app/console/project/base_project/src/config/test.ts.tpl +0 -1
  61. package/dist/esm/cache.mjs.map +0 -1
  62. /package/dist/cjs/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl} +0 -0
  63. /package/dist/esm/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl} +0 -0
  64. /package/dist/esm/{cache.d.mts → cache/cache.d.mts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/app/console/project/CreateProjectCommand.mts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { Case } from \"change-case-all\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\nimport { fileURLToPath } from \"url\";\nimport handlebars from \"handlebars\";\nimport { execSync } from \"child_process\";\nimport { select, Separator } from \"@inquirer/prompts\";\n\nexport class CreateProjectCommand extends Command {\n static paths = [[`create`, `project`]];\n\n static usage = Command.Usage({\n category: `Project`,\n description: `Create a new project`,\n details: `\n This command creates a new project with the specified name at the given path.\n If no path is provided, the project will be created in the current directory.\n `,\n examples: [\n [\n `Create a new project in specified directory`,\n `create project --path /path/to/my-project --git`,\n ],\n [\n `Create a new project at a specific path with git initialized`,\n `create project --path /path/to/my-project --git`,\n ],\n ],\n });\n\n projectPath = Option.String(\"--path\", { required: true });\n\n git = Option.Boolean(`--git`, false, {\n description: `Initialize a git repository in the new project`,\n });\n\n async folderExists(folderPath: string): Promise<boolean> {\n try {\n const stats = await fs.stat(folderPath);\n return stats.isDirectory();\n } catch (error: any) {\n if (error.code === \"ENOENT\") {\n return false; // Folder does not exist\n }\n throw error; // Other errors (e.g., permission issues)\n }\n }\n\n async execute() {\n // Create the project directory path by joining the specified path and project name\n const projectPath = path.join(this.projectPath);\n // Check if directory already exists\n try {\n await fs.access(projectPath);\n console.error(`Error: Directory ${projectPath} already exists.`);\n return 1;\n } catch {\n // Directory doesn't exist, we can proceed\n }\n\n // ask what library to use for validation: yup or zod or none\n const validation_library = await select({\n message: \"Select a package you want for validation\",\n choices: [\n {\n name: \"Yup\",\n value: \"yup\",\n description: \"https://github.com/jquense/yup\",\n },\n {\n name: \"Zod\",\n value: \"zod\",\n description: \"https://zod.dev/\",\n },\n new Separator(),\n {\n name: \"None\",\n value: \"none\",\n disabled: false,\n },\n ],\n });\n\n await fs.mkdir(projectPath, { recursive: true });\n console.log(`Created project directory at: ${projectPath}`);\n\n const dirname =\n typeof __dirname === \"undefined\"\n ? path.dirname(fileURLToPath(import.meta.url))\n : __dirname;\n\n let basePath = path.join(dirname, `./base_project`);\n if ((await this.folderExists(basePath)) === false) {\n // we are running a compiled code that was bundled and the code is running from ./dist/bin/ folder.\n basePath = path.join(dirname, `../app/console/project/base_project`);\n }\n\n console.log(`Using base project path: ${basePath}`);\n //copy content of ./base_project to the new project directory\n const baseProjectPath = basePath;\n\n await this.processTplFolder(baseProjectPath, projectPath, {\n validation_library,\n });\n console.log(`Copied base project files to: ${projectPath}`);\n\n //modify package.json with foldername\n const packageJsonPath = path.join(projectPath, `package.json`);\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));\n packageJson.name = Case.snake(path.basename(projectPath));\n await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n console.log(`Updated package.json with project name: ${packageJson.name}`);\n\n if (this.git) {\n try {\n execSync(\n 'git init; git add --all; git commit --allow-empty -m \"chore: first commit for pashmak\"',\n {\n cwd: projectPath,\n },\n );\n } catch (error) {\n console.error(`Failed to create project.`, error);\n return 1;\n }\n }\n }\n\n async processTplFolder(src: string, dest: string, data: any = {}) {\n const files = await fs.readdir(src, { withFileTypes: true });\n for (const file of files) {\n const srcPath = path.join(src, file.name);\n const destPath =\n file.isFile() && file.name.endsWith(\".tpl\")\n ? path.join(dest, file.name.substring(0, file.name.length - 4))\n : path.join(dest, file.name);\n\n if (file.isDirectory()) {\n await fs.mkdir(destPath, { recursive: true });\n await this.processTplFolder(srcPath, destPath, data);\n } else if (file.name.endsWith(\".tpl\")) {\n await this.processTplFile(srcPath, destPath, data);\n } else {\n throw new Error(\n \"unexpected non tpl file: \" + srcPath + \" \" + file.name,\n );\n }\n }\n }\n\n async processTplFile(src: string, dest: string, data: any = {}) {\n handlebars.registerHelper(\"eq\", (a, b) => a === b);\n\n const compiledTemplate = handlebars.compile(\n (await fs.readFile(src)).toString(),\n );\n const template = await compiledTemplate(data);\n await fs.writeFile(dest, template);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/app/console/project/CreateProjectCommand.mts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { Case } from \"change-case-all\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\nimport { fileURLToPath } from \"url\";\nimport handlebars from \"handlebars\";\nimport { execSync } from \"child_process\";\nimport { select, Separator, input } from \"@inquirer/prompts\";\n\nexport class CreateProjectCommand extends Command {\n static paths = [[`create`, `project`]];\n\n static usage = Command.Usage({\n category: `Project`,\n description: `Create a new project`,\n details: `\n This command creates a new project interactively.\n You will be prompted for the project path and other configuration options.\n `,\n examples: [[`Create a new project`, `create project`]],\n });\n\n projectPath: string = \"\";\n executor: string = \"\";\n packageManager: string = \"\";\n linter: string = \"\";\n validation_library: string = \"\";\n database_type: string = \"\";\n\n async folderExists(folderPath: string): Promise<boolean> {\n try {\n const stats = await fs.stat(folderPath);\n return stats.isDirectory();\n } catch (error: any) {\n if (error.code === \"ENOENT\") {\n return false; // Folder does not exist\n }\n throw error; // Other errors (e.g., permission issues)\n }\n }\n\n async execute() {\n //setup project\n await this.setupProjectPath();\n await this.setupGit();\n await this.setupExecutorAndPackageManager();\n await this.setupLinter();\n await this.setupGeneralPackages();\n await this.setupBaseProject();\n await this.installPackages();\n }\n\n async processTplFolder(src: string, dest: string, data: any = {}) {\n const files = await fs.readdir(src, { withFileTypes: true });\n for (const file of files) {\n const srcPath = path.join(src, file.name);\n const destPath =\n file.isFile() && file.name.endsWith(\".tpl\")\n ? path.join(dest, file.name.substring(0, file.name.length - 4))\n : path.join(dest, file.name);\n\n if (file.isDirectory()) {\n await fs.mkdir(destPath, { recursive: true });\n await this.processTplFolder(srcPath, destPath, data);\n } else if (file.name.endsWith(\".tpl\")) {\n await this.processTplFile(srcPath, destPath, data);\n } else {\n throw new Error(\n \"unexpected non tpl file: \" + srcPath + \" \" + file.name,\n );\n }\n }\n }\n\n async processTplFile(src: string, dest: string, data: any = {}) {\n handlebars.registerHelper(\"eq\", (a, b) => a === b);\n\n const compiledTemplate = handlebars.compile(\n (await fs.readFile(src)).toString(),\n );\n const template = await compiledTemplate(data);\n await fs.writeFile(dest, template);\n }\n\n async setupProjectPath() {\n // Ask for project path\n const pathInput = await input({\n message: \"Enter project path (leave empty to use current directory):\",\n default: \"\",\n });\n\n // Create the project directory path\n this.projectPath = pathInput.trim()\n ? path.resolve(pathInput.trim())\n : process.cwd();\n\n // Create directory if it doesn't exist\n await fs.mkdir(this.projectPath, { recursive: true });\n\n // Check if directory is empty\n const files = await fs.readdir(this.projectPath);\n if (files.length > 0) {\n throw new Error(\n `Directory ${this.projectPath} is not empty. Please use an empty directory.`,\n );\n }\n }\n\n async setupExecutorAndPackageManager() {\n // ask what executor to use\n this.executor = await select({\n message: \"Select a TypeScript executor\",\n choices: [\n {\n name: \"Bun\",\n value: \"bun\",\n description: \"Fast all-in-one JavaScript runtime\",\n },\n {\n name: \"TSX\",\n value: \"tsx\",\n description:\n \"TypeScript execute (tsx) - Node.js enhanced with esbuild\",\n },\n ],\n });\n\n // ask what package manager to use (skip if executor is bun)\n this.packageManager =\n this.executor === \"bun\"\n ? \"bun\"\n : await select({\n message: \"Select a package manager\",\n choices: [\n {\n name: \"Yarn\",\n value: \"yarn\",\n description: \"Fast, reliable, and secure dependency management\",\n },\n {\n name: \"npm\",\n value: \"npm\",\n description: \"Node package manager (default)\",\n },\n {\n name: \"Bun\",\n value: \"bun\",\n description: \"Ultra-fast package manager built into Bun\",\n },\n ],\n default: \"yarn\",\n });\n\n // use executor as package manager to start a new project\n // run command to init a project with the selected executor and package manager\n execSync(`${this.packageManager} init -y`, {\n stdio: \"inherit\",\n cwd: this.projectPath,\n });\n\n // add commands to package.json based on the selected executor\n const packageJsonPath = path.join(this.projectPath, `package.json`);\n let packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));\n packageJson.type = \"module\";\n packageJson.scripts = packageJson.scripts || {};\n packageJson.scripts.prepare = \"husky init\";\n packageJson.scripts.clean = \"rm -rf dist\";\n if (this.executor === \"bun\") {\n packageJson.scripts.dev = \"bun run dev\";\n packageJson.scripts.start = \"bun run pdev\";\n packageJson.scripts.build = \"bun run build\";\n packageJson.scripts.test = \"vitest\";\n packageJson.scripts[\"test:watch\"] = \"vitest --watch\";\n packageJson.scripts[\"test:coverage\"] = \"vitest run --coverage\";\n } else if (this.executor === \"tsx\") {\n packageJson.scripts.dev =\n \"tsx --watch -r tsconfig-paths/register src/index.ts start --all | npx pino-pretty\";\n packageJson.scripts.start = \"tsx dist/index.js\";\n packageJson.scripts.build = \"tsc\";\n packageJson.scripts.test = \"vitest\";\n packageJson.scripts[\"test:watch\"] = \"vitest --watch\";\n packageJson.scripts[\"test:coverage\"] = \"vitest run --coverage\";\n }\n //save back to package.json\n await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n }\n\n async setupLinter() {\n // ask what linter to use\n this.linter = await select({\n message: \"Select a linter\",\n choices: [\n {\n name: \"Biome\",\n value: \"biome\",\n description:\n \"Fast formatter and linter for JavaScript, TypeScript, and more\",\n },\n {\n name: \"ESLint\",\n value: \"eslint\",\n description: \"Find and fix problems in your JavaScript code\",\n },\n ],\n });\n\n // add linter configuration to package.json based on the selected linter\n const packageJsonPath = path.join(this.projectPath, `package.json`);\n let packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));\n if (this.linter === \"biome\") {\n packageJson.scripts.lint = \"biome check . --ext .ts,.tsx\";\n packageJson.scripts.format = \"biome format . --ext .ts,.tsx --write\";\n this.addPackage(\"@biomejs/biome\", true);\n } else if (this.linter === \"eslint\") {\n packageJson.scripts.lint = \"eslint . --ext .ts,.tsx\";\n packageJson.scripts.format = \"eslint . --ext .ts,.tsx --fix\";\n this.addPackage(\"eslint\", true);\n }\n //save back to package.json\n await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n }\n\n async setupGeneralPackages() {\n // ask what library to use for validation: yup or zod or none\n this.validation_library = await select({\n message: \"Select a package you want for validation\",\n choices: [\n {\n name: \"Yup\",\n value: \"yup\",\n description: \"https://github.com/jquense/yup\",\n },\n {\n name: \"Zod\",\n value: \"zod\",\n description: \"https://zod.dev/\",\n },\n new Separator(),\n {\n name: \"None\",\n value: \"none\",\n disabled: false,\n },\n ],\n });\n\n // run commands to install the selected validation library\n this.validation_library === \"none\" ||\n (await this.addPackage(this.validation_library));\n\n this.database_type = await select({\n message: \"Select a database type (you can add more databases later)\",\n choices: [\n {\n name: \"PostgreSQL\",\n value: \"postgresql\",\n description:\n \"A powerful, open source object-relational database system\",\n },\n {\n name: \"MySQL\",\n value: \"mysql\",\n description: \"The world's most popular open source database\",\n },\n {\n name: \"SQLite\",\n value: \"sqlite\",\n description:\n \"A C library that provides a lightweight disk-based database\",\n },\n ],\n });\n\n if (this.database_type === \"postgresql\") {\n await this.addPackage(\"pg pg-cursor\");\n } else if (this.database_type === \"mysql\") {\n await this.addPackage(\"mysql2\");\n } else if (this.database_type === \"sqlite\") {\n await this.addPackage(\"sqlite3\");\n }\n\n // add other packages\n await this.addPackage(\"@devbro/pashmak tsconfig-paths dotenv \");\n await this.addPackage(\n \"husky vitest supertest @types/supertest pino-pretty typescript tsx\",\n true,\n );\n }\n\n async setupBaseProject() {\n console.log(`Using project directory: ${this.projectPath}`);\n\n const dirname =\n typeof __dirname === \"undefined\"\n ? path.dirname(fileURLToPath(import.meta.url))\n : __dirname;\n\n let basePath = path.join(dirname, `./base_project`);\n if ((await this.folderExists(basePath)) === false) {\n // we are running a compiled code that was bundled and the code is running from ./dist/bin/ folder.\n basePath = path.join(dirname, `../app/console/project/base_project`);\n }\n\n console.log(`Using base project path: ${basePath}`);\n //copy content of ./base_project to the new project directory\n const baseProjectPath = basePath;\n\n await this.processTplFolder(baseProjectPath, this.projectPath, {\n validation_library: this.validation_library,\n executor: this.executor,\n package_manager: this.packageManager,\n linter: this.linter,\n database_type: this.database_type,\n });\n console.log(`Copied base project files to: ${this.projectPath}`);\n\n //modify package.json with foldername\n const packageJsonPath = path.join(this.projectPath, \"package.json\");\n let packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));\n packageJson.name = Case.snake(path.basename(this.projectPath));\n\n await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n console.log(`Updated package.json with project name: ${packageJson.name}`);\n }\n\n async addPackage(packageName: string, dev: boolean = false) {\n let install_command = \"\";\n switch (this.packageManager) {\n case \"bun\":\n install_command = `bun add ${packageName}${dev ? \" -d\" : \"\"}`;\n break;\n case \"yarn\":\n install_command = `yarn add ${packageName}${dev ? \" -D\" : \"\"} --no-install`;\n break;\n case \"npm\":\n install_command = `npm install ${packageName}${dev ? \" --save-dev\" : \"\"} --package-lock-only`;\n break;\n }\n\n execSync(install_command, {\n stdio: \"inherit\",\n cwd: this.projectPath,\n });\n }\n\n async installPackages() {\n const install_command =\n this.packageManager === \"bun\"\n ? `bun install`\n : this.packageManager === \"yarn\"\n ? `yarn`\n : `npm install`;\n\n execSync(install_command, {\n stdio: \"inherit\",\n cwd: this.projectPath,\n });\n }\n\n async setupGit() {\n // ask if user wants to initialize git repository\n const initGit = await select({\n message: \"Initialize a git repository?\",\n choices: [\n {\n name: \"Yes\",\n value: true,\n description: \"Initialize git and create first commit\",\n },\n {\n name: \"No\",\n value: false,\n description: \"Skip git initialization\",\n },\n ],\n });\n\n if (initGit) {\n const gitignoreContent =\n [\n \"node_modules/\",\n \"dist/\",\n \".env\",\n \".env.*\",\n \"!.env.example\",\n \"*.log\",\n \"coverage/\",\n \".DS_Store\",\n ].join(\"\\n\") + \"\\n\";\n\n await fs.writeFile(\n path.join(this.projectPath, \".gitignore\"),\n gitignoreContent,\n );\n\n execSync(\n `git init; git add --all; git commit --allow-empty -m \"chore: first commit\"`,\n {\n cwd: this.projectPath,\n },\n );\n }\n }\n\n async catch(error: unknown) {\n if (Error.isError(error)) {\n console.error(error.message);\n } else {\n console.error(error);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,15 @@
1
1
  export default {
2
2
  default: {
3
- type: 'disabled',
3
+ provider: 'disabled',
4
+ config: {},
5
+ },
6
+ };
7
+
8
+ export const $prod = {
9
+ default: {
10
+ provider: 'redis',
11
+ config: {
12
+ url: 'redis://redis:6379',
13
+ },
4
14
  },
5
15
  };
@@ -1,10 +1,12 @@
1
1
  export default {
2
2
  default: {
3
- host: process.env.DB_HOST,
4
- database: process.env.DB_NAME || 'test_db',
5
- user: process.env.DB_USER,
6
- password: process.env.DB_PASSWORD,
7
- port: parseInt(process.env.DB_PORT || '5432'),
8
- name: 'db',
3
+ provider: 'postgresql',
4
+ config: {
5
+ host: process.env.DB_HOST,
6
+ database: process.env.DB_NAME || 'test_db',
7
+ user: process.env.DB_USER,
8
+ password: process.env.DB_PASSWORD,
9
+ port: parseInt(process.env.DB_PORT || '5432'),
10
+ },
9
11
  },
10
12
  };
@@ -3,18 +3,24 @@ import os from 'os';
3
3
  import { getEnv } from '@devbro/pashmak/helper';
4
4
  import { dirname } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
- import { loadConfig } from '@devbro/pashmak/config';
6
+ import { loadConfigData, DotPaths } from '@devbro/pashmak/config';
7
+ import * as databases_config from './databases';
8
+ import * as storages_config from './storages';
9
+ import * as mailers_config from './mailers';
10
+ import * as queues_config from './queues';
11
+ import * as caches_config from './caches';
12
+ import * as loggers_config from './loggers';
7
13
 
8
14
  const __filename = fileURLToPath(import.meta.url);
9
15
  const __dirname = dirname(__filename);
10
16
 
11
17
  const project_configs = {
12
- databases: await loadConfig('./databases'),
13
- storages: await loadConfig('./storages'),
14
- mailer: await loadConfig('./mailer'),
15
- loggers: await loadConfig('./loggers'),
16
- queues: await loadConfig('./queues'),
17
- caches: await loadConfig('./caches'),
18
+ databases: loadConfigData(databases_config),
19
+ storages: loadConfigData(storages_config),
20
+ mailer: loadConfigData(mailers_config),
21
+ loggers: loadConfigData(loggers_config),
22
+ queues: loadConfigData(queues_config),
23
+ caches: loadConfigData(caches_config),
18
24
  base_url: getEnv('BASE_URL', 'http://localhost:' + getEnv('PORT', '3000')),
19
25
  port: getEnv('PORT', 3000),
20
26
  file_upload_path: path.join(os.tmpdir(), ''),
@@ -43,19 +49,6 @@ export const $test = {
43
49
  // Test environment overrides
44
50
  };
45
51
 
46
- export const $prod = {
47
- port: getEnv('PORT', 80),
48
- debug_mode: false,
49
- };
50
-
51
-
52
- type DotPaths<T> = {
53
- [K in keyof T & string]:
54
- T[K] extends Record<string, any>
55
- ? K | `${K}.${DotPaths<T[K]>}`
56
- : K
57
- }[keyof T & string];
58
-
59
52
  declare module '@devbro/neko-config' {
60
53
  interface ConfigKeys extends Record<DotPaths<typeof project_configs>, string> {
61
54
  }
@@ -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: process.env.NODE_ENV === 'test' ? 'silent' : 'info',
7
- extrasFunction: (message: LogMessage) => {
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
- } as LocalStorageProviderConfig,
9
+ },
11
10
  },
12
11
  };
@@ -1,24 +1,56 @@
1
- import dotenv from 'dotenv';
1
+ import dotenv from "dotenv";
2
2
  dotenv.config();
3
3
 
4
- import { bootstrap } from '@devbro/pashmak';
5
- import { dirname } from 'path';
6
- import { fileURLToPath } from 'url';
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 './app/console';
14
- import './routes';
15
- import './schedules';
8
+ import { httpServer, logger } from "@devbro/pashmak/facades";
9
+ import { startQueueListeners } from "@/app/queues";
10
+ import { HttpError } from "@devbro/pashmak/http";
16
11
 
17
- const config_data = await loadConfig(dirname(fileURLToPath(import.meta.url)) + '/config/default');
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
- await bootstrap({
20
- root_dir: dirname(fileURLToPath(import.meta.url)),
21
- config_data,
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
- "/api/v1/meow",
12
+ "/",
13
13
  async (req: any, res: any) => {
14
- return { message: "meow meow!" };
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,MAAMF,GAAAA;AAChB,CAAA;","names":["Cli","node","app","args","process","argv","cli","binaryLabel","binaryName","binaryVersion","CreateProjectCommand","register","runExit","then","catch","err","console","error"]}
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"]}
@@ -0,0 +1,14 @@
1
+ import { JSONValue, JSONObject } from '@devbro/neko-helper';
2
+ import { CacheProviderInterface } from '@devbro/neko-cache';
3
+
4
+ declare class MultiCache implements CacheProviderInterface {
5
+ private caches;
6
+ constructor(caches: CacheProviderInterface[]);
7
+ get(key: string): Promise<JSONValue | JSONObject | undefined>;
8
+ put(key: string, value: JSONObject | JSONValue, ttl?: number): Promise<void>;
9
+ delete(key: string): Promise<void>;
10
+ has(key: string): Promise<boolean>;
11
+ increment(key: string, amount?: number): Promise<number>;
12
+ }
13
+
14
+ export { MultiCache };
@@ -0,0 +1,47 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ class MultiCache {
4
+ constructor(caches) {
5
+ this.caches = caches;
6
+ }
7
+ static {
8
+ __name(this, "MultiCache");
9
+ }
10
+ async get(key) {
11
+ for (const cache of this.caches) {
12
+ const value = await cache.get(key);
13
+ if (value !== void 0) {
14
+ return value;
15
+ }
16
+ }
17
+ return void 0;
18
+ }
19
+ async put(key, value, ttl) {
20
+ await Promise.all(this.caches.map((cache) => cache.put(key, value, ttl)));
21
+ }
22
+ async delete(key) {
23
+ await Promise.all(this.caches.map((cache) => cache.delete(key)));
24
+ }
25
+ async has(key) {
26
+ for (const cache of this.caches) {
27
+ if (await cache.has(key)) {
28
+ return true;
29
+ }
30
+ }
31
+ return false;
32
+ }
33
+ async increment(key, amount) {
34
+ let rc = void 0;
35
+ for (const cache of this.caches) {
36
+ let rc2 = await cache.increment(key, amount);
37
+ if (rc === void 0) {
38
+ rc = rc2;
39
+ }
40
+ }
41
+ return rc;
42
+ }
43
+ }
44
+ export {
45
+ MultiCache
46
+ };
47
+ //# sourceMappingURL=MultiCache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cache/MultiCache.mts"],"sourcesContent":["import { JSONObject, JSONValue } from \"@devbro/neko-helper\";\nimport { CacheProviderInterface } from \"@devbro/neko-cache\";\n\nexport class MultiCache implements CacheProviderInterface {\n constructor(private caches: CacheProviderInterface[]) {}\n\n async get(key: string): Promise<JSONValue | JSONObject | undefined> {\n for (const cache of this.caches) {\n const value = await cache.get(key);\n if (value !== undefined) {\n return value;\n }\n }\n return undefined;\n }\n async put(\n key: string,\n value: JSONObject | JSONValue,\n ttl?: number,\n ): Promise<void> {\n await Promise.all(this.caches.map((cache) => cache.put(key, value, ttl)));\n }\n async delete(key: string): Promise<void> {\n await Promise.all(this.caches.map((cache) => cache.delete(key)));\n }\n async has(key: string): Promise<boolean> {\n for (const cache of this.caches) {\n if (await cache.has(key)) {\n return true;\n }\n }\n return false;\n }\n\n async increment(key: string, amount?: number): Promise<number> {\n let rc = undefined;\n for (const cache of this.caches) {\n let rc2 = await cache.increment(key, amount);\n if (rc === undefined) {\n rc = rc2;\n }\n }\n\n return rc!;\n }\n}\n"],"mappings":";;AAGO,MAAM,WAA6C;AAAA,EACxD,YAAoB,QAAkC;AAAlC;AAAA,EAAmC;AAAA,EAJzD,OAG0D;AAAA;AAAA;AAAA,EAGxD,MAAM,IAAI,KAA0D;AAClE,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,QAAQ,MAAM,MAAM,IAAI,GAAG;AACjC,UAAI,UAAU,QAAW;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EACA,MAAM,IACJ,KACA,OACA,KACe;AACf,UAAM,QAAQ,IAAI,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI,KAAK,OAAO,GAAG,CAAC,CAAC;AAAA,EAC1E;AAAA,EACA,MAAM,OAAO,KAA4B;AACvC,UAAM,QAAQ,IAAI,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,EACjE;AAAA,EACA,MAAM,IAAI,KAA+B;AACvC,eAAW,SAAS,KAAK,QAAQ;AAC/B,UAAI,MAAM,MAAM,IAAI,GAAG,GAAG;AACxB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,KAAa,QAAkC;AAC7D,QAAI,KAAK;AACT,eAAW,SAAS,KAAK,QAAQ;AAC/B,UAAI,MAAM,MAAM,MAAM,UAAU,KAAK,MAAM;AAC3C,UAAI,OAAO,QAAW;AACpB,aAAK;AAAA,MACP;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
  export * from "@devbro/neko-cache";
4
- import { cache } from "./facades.mjs";
4
+ import { cache } from "../facades.mjs";
5
5
  async function cacheQuery(q, options = {}) {
6
6
  options.ttl = options.ttl ?? 3600;
7
7
  options.cache_label = options.cache_label ?? "default";
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cache/cache.mts"],"sourcesContent":["export * from \"@devbro/neko-cache\";\n\nimport { Query } from \"@devbro/neko-sql\";\nimport { cache } from \"../facades.mjs\";\nimport { JSONValue } from \"@devbro/neko-helper\";\n\nexport type CacheQueryOptions = {\n ttl?: number;\n tags?: string[];\n cache_label?: string;\n};\n\nexport async function cacheQuery(\n q: Query,\n options: CacheQueryOptions = {},\n): ReturnType<Query[\"get\"]> {\n options.ttl = options.ttl ?? 3600; // default TTL 1 hour\n options.cache_label = options.cache_label ?? \"default\";\n const sql = q.toSql();\n\n return await cache(options.cache_label).remember(\n sql as JSONValue,\n async () => await q.get(),\n options,\n );\n}\n"],"mappings":";;AAAA,cAAc;AAGd,SAAS,aAAa;AAStB,eAAsB,WACpB,GACA,UAA6B,CAAC,GACJ;AAC1B,UAAQ,MAAM,QAAQ,OAAO;AAC7B,UAAQ,cAAc,QAAQ,eAAe;AAC7C,QAAM,MAAM,EAAE,MAAM;AAEpB,SAAO,MAAM,MAAM,QAAQ,WAAW,EAAE;AAAA,IACtC;AAAA,IACA,YAAY,MAAM,EAAE,IAAI;AAAA,IACxB;AAAA,EACF;AACF;AAbsB;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config.mts"],"sourcesContent":["export * from \"@devbro/neko-config\";\n"],"mappings":"AAAA,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../src/config.mts"],"sourcesContent":["export * from \"@devbro/neko-config\";"],"mappings":"AAAA,cAAc;","names":[]}
@@ -32,6 +32,8 @@ import {
32
32
  FTPStorageProvider,
33
33
  SFTPStorageProvider
34
34
  } from "@devbro/neko-storage";
35
+ import { MultiCache } from "./cache/MultiCache.mts";
36
+ import { cache } from "./facades.mts";
35
37
  class FlexibleFactory {
36
38
  static {
37
39
  __name(this, "FlexibleFactory");
@@ -102,6 +104,13 @@ CacheProviderFactory.register("redis", (opt) => {
102
104
  CacheProviderFactory.register("file", (opt) => {
103
105
  return new FileCacheProvider(opt);
104
106
  });
107
+ CacheProviderFactory.register("multi", (opt) => {
108
+ const caches = [];
109
+ for (const c of opt.caches) {
110
+ caches.push(cache(c));
111
+ }
112
+ return new MultiCache(caches);
113
+ });
105
114
  CacheProviderFactory.register("disabled", (opt) => {
106
115
  return new DisabledCacheProvider();
107
116
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/factories.mts"],"sourcesContent":["import {\n SESProvider,\n SMTPProvider,\n MemoryProvider,\n MailerProviderFactory,\n} from \"@devbro/neko-mailer\";\nimport {\n MemoryTransport,\n QueueTransportFactory,\n AwsSqsTransport,\n AmqpTransport,\n RedisTransport,\n AsyncTransport,\n AzureServiceBusTransport,\n GooglePubSubTransport,\n} from \"@devbro/neko-queue\";\nimport { DatabaseTransport } from \"./queue.mjs\";\nimport {\n CacheProviderInterface,\n MemoryCacheProvider,\n RedisCacheProvider,\n FileCacheProvider,\n DisabledCacheProvider,\n} from \"@devbro/neko-cache\";\nimport {\n AWSS3StorageProvider,\n LocalStorageProvider,\n StorageProviderFactory,\n GCPStorageProvider,\n AzureBlobStorageProvider,\n FTPStorageProvider,\n SFTPStorageProvider,\n} from \"@devbro/neko-storage\";\n\nexport class FlexibleFactory<T> {\n registry: Map<string, any> = new Map();\n\n register<T>(key: string, ctor: (...args: any[]) => T) {\n this.registry.set(key, ctor);\n }\n\n create<T>(key: string, ...args: any[]): T {\n const ctor = this.registry.get(key);\n if (!ctor) {\n throw new Error(`No factory registered for key: ${key}`);\n }\n return ctor(...args);\n }\n}\n\nMailerProviderFactory.register(\"ses\", (opt) => {\n return new SESProvider(opt);\n});\n\nMailerProviderFactory.register(\"smtp\", (opt) => {\n return new SMTPProvider(opt);\n});\n\nMailerProviderFactory.register(\"memory\", (opt) => {\n return new MemoryProvider();\n});\n\n// Queue\n\nQueueTransportFactory.register(\"database\", (opt) => {\n return new DatabaseTransport(opt);\n});\n\nQueueTransportFactory.register(\"memory\", (opt) => {\n return new MemoryTransport(opt);\n});\n\nQueueTransportFactory.register(\"sqs\", (opt) => {\n return new AwsSqsTransport(opt);\n});\n\nQueueTransportFactory.register(\"amqp\", (opt) => {\n return new AmqpTransport(opt);\n});\n\nQueueTransportFactory.register(\"redis\", (opt) => {\n return new RedisTransport(opt);\n});\n\nQueueTransportFactory.register(\"async\", (opt) => {\n return new AsyncTransport();\n});\n\nQueueTransportFactory.register(\"azure_service_bus\", (opt) => {\n return new AzureServiceBusTransport(opt);\n});\n\nQueueTransportFactory.register(\"google_pubsub\", (opt) => {\n return new GooglePubSubTransport(opt);\n});\n\n// CACHE\nexport class CacheProviderFactory {\n static instance: FlexibleFactory<CacheProviderInterface> =\n new FlexibleFactory<CacheProviderInterface>();\n\n static register(\n key: string,\n factory: (...args: any[]) => CacheProviderInterface,\n ): void {\n CacheProviderFactory.instance.register(key, factory);\n }\n\n static create<T>(key: string, ...args: any[]): CacheProviderInterface {\n return CacheProviderFactory.instance.create(key, ...args);\n }\n}\n\nCacheProviderFactory.register(\"memory\", (opt) => {\n return new MemoryCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"redis\", (opt) => {\n return new RedisCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"file\", (opt) => {\n return new FileCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"disabled\", (opt) => {\n return new DisabledCacheProvider();\n});\n\n/* STORAGE */\n\nStorageProviderFactory.register(\"local\", (opt) => {\n return new LocalStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"s3\", (opt) => {\n return new AWSS3StorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"gcp\", (opt) => {\n return new GCPStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"azure\", (opt) => {\n return new AzureBlobStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"ftp\", (opt) => {\n return new FTPStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"sftp\", (opt) => {\n return new SFTPStorageProvider(opt);\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/factories.mts"],"sourcesContent":["import {\n SESProvider,\n SMTPProvider,\n MemoryProvider,\n MailerProviderFactory,\n} from \"@devbro/neko-mailer\";\nimport {\n MemoryTransport,\n QueueTransportFactory,\n AwsSqsTransport,\n AmqpTransport,\n RedisTransport,\n AsyncTransport,\n AzureServiceBusTransport,\n GooglePubSubTransport,\n} from \"@devbro/neko-queue\";\nimport { DatabaseTransport } from \"./queue.mjs\";\nimport {\n CacheProviderInterface,\n MemoryCacheProvider,\n RedisCacheProvider,\n FileCacheProvider,\n DisabledCacheProvider,\n} from \"@devbro/neko-cache\";\nimport {\n AWSS3StorageProvider,\n LocalStorageProvider,\n StorageProviderFactory,\n GCPStorageProvider,\n AzureBlobStorageProvider,\n FTPStorageProvider,\n SFTPStorageProvider,\n} from \"@devbro/neko-storage\";\nimport { MultiCache } from \"./cache/MultiCache.mts\";\nimport { cache } from \"./facades.mts\";\n\nexport class FlexibleFactory<T> {\n registry: Map<string, any> = new Map();\n\n register<T>(key: string, ctor: (...args: any[]) => T) {\n this.registry.set(key, ctor);\n }\n\n create<T>(key: string, ...args: any[]): T {\n const ctor = this.registry.get(key);\n if (!ctor) {\n throw new Error(`No factory registered for key: ${key}`);\n }\n return ctor(...args);\n }\n}\n\nMailerProviderFactory.register(\"ses\", (opt) => {\n return new SESProvider(opt);\n});\n\nMailerProviderFactory.register(\"smtp\", (opt) => {\n return new SMTPProvider(opt);\n});\n\nMailerProviderFactory.register(\"memory\", (opt) => {\n return new MemoryProvider();\n});\n\n// Queue\n\nQueueTransportFactory.register(\"database\", (opt) => {\n return new DatabaseTransport(opt);\n});\n\nQueueTransportFactory.register(\"memory\", (opt) => {\n return new MemoryTransport(opt);\n});\n\nQueueTransportFactory.register(\"sqs\", (opt) => {\n return new AwsSqsTransport(opt);\n});\n\nQueueTransportFactory.register(\"amqp\", (opt) => {\n return new AmqpTransport(opt);\n});\n\nQueueTransportFactory.register(\"redis\", (opt) => {\n return new RedisTransport(opt);\n});\n\nQueueTransportFactory.register(\"async\", (opt) => {\n return new AsyncTransport();\n});\n\nQueueTransportFactory.register(\"azure_service_bus\", (opt) => {\n return new AzureServiceBusTransport(opt);\n});\n\nQueueTransportFactory.register(\"google_pubsub\", (opt) => {\n return new GooglePubSubTransport(opt);\n});\n\n// CACHE\nexport class CacheProviderFactory {\n static instance: FlexibleFactory<CacheProviderInterface> =\n new FlexibleFactory<CacheProviderInterface>();\n\n static register(\n key: string,\n factory: (...args: any[]) => CacheProviderInterface,\n ): void {\n CacheProviderFactory.instance.register(key, factory);\n }\n\n static create<T>(key: string, ...args: any[]): CacheProviderInterface {\n return CacheProviderFactory.instance.create(key, ...args);\n }\n}\n\nCacheProviderFactory.register(\"memory\", (opt) => {\n return new MemoryCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"redis\", (opt) => {\n return new RedisCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"file\", (opt) => {\n return new FileCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"multi\", (opt) => {\n const caches: CacheProviderInterface[] = [];\n for (const c of opt.caches) {\n caches.push(cache(c));\n }\n\n return new MultiCache(caches);\n});\n\nCacheProviderFactory.register(\"disabled\", (opt) => {\n return new DisabledCacheProvider();\n});\n\n/* STORAGE */\n\nStorageProviderFactory.register(\"local\", (opt) => {\n return new LocalStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"s3\", (opt) => {\n return new AWSS3StorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"gcp\", (opt) => {\n return new GCPStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"azure\", (opt) => {\n return new AzureBlobStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"ftp\", (opt) => {\n return new FTPStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"sftp\", (opt) => {\n return new SFTPStorageProvider(opt);\n});\n"],"mappings":"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","names":[]}
@@ -1,8 +1,2 @@
1
- export { config } from '@devbro/neko-config';
2
1
 
3
- declare function bootstrap(options: {
4
- root_dir: string;
5
- config_data: object;
6
- }): Promise<void>;
7
-
8
- export { bootstrap };
2
+ export { }
@@ -1,33 +1,2 @@
1
- var __defProp = Object.defineProperty;
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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import { context_provider } from \"@devbro/neko-context\";\nimport { Middleware } from \"@devbro/neko-router\";\nimport { runNext } from \"@devbro/neko-router\";\nimport { Request, Response } from \"@devbro/neko-router\";\nimport { config } from \"@devbro/neko-config\";\n\nexport { config };\nexport async function bootstrap(options: {\n root_dir: string;\n config_data: object;\n}): Promise<void> {\n // This function is used to bootstrap the application.\n // It can be used to initialize the application, load configuration, etc.\n // Currently, it does nothing but can be extended in the future.\n\n console.log(\"Bootstrapping application...\");\n console.log(`Root directory: ${options.root_dir}`);\n\n config.load(options.config_data || {});\n\n console.log(\"Loading application modules...\");\n await import(`./app/console/index.mjs`);\n console.log(\"Loading Database Provider ...\");\n const { DatabaseServiceProvider } = await import(\n \"./DatabaseServiceProvider.mjs\"\n );\n\n console.log(\"Setting up pre-loader for context provider...\");\n context_provider.setPreLoader(async (f: Function) => {\n const middlewares: Middleware[] = [];\n // do I need to use ServiceProvider like a middleware or can I get rid of this logic?\n middlewares.push(DatabaseServiceProvider.getInstance());\n\n return await runNext(\n middlewares,\n {} as Request,\n {} as Response,\n // @ts-ignore\n f,\n );\n });\n console.log(\"Application bootstrapped successfully.\");\n}\n"],"mappings":";;AAAA,SAASA,wBAAwB;AAEjC,SAASC,eAAe;AAExB,SAASC,cAAc;AAGvB,eAAsBC,UAAUC,SAG/B;AAKCC,UAAQC,IAAI,8BAAA;AACZD,UAAQC,IAAI,mBAAmBF,QAAQG,QAAQ,EAAE;AAEjDL,SAAOM,KAAKJ,QAAQK,eAAe,CAAC,CAAA;AAEpCJ,UAAQC,IAAI,gCAAA;AACZ,QAAM,OAAO,yBAAyB;AACtCD,UAAQC,IAAI,+BAAA;AACZ,QAAM,EAAEI,wBAAuB,IAAK,MAAM,OACxC,+BAAA;AAGFL,UAAQC,IAAI,+CAAA;AACZN,mBAAiBW,aAAa,OAAOC,MAAAA;AACnC,UAAMC,cAA4B,CAAA;AAElCA,gBAAYC,KAAKJ,wBAAwBK,YAAW,CAAA;AAEpD,WAAO,MAAMd;MACXY;MACA,CAAC;MACD,CAAC;;MAEDD;IAAAA;EAEJ,CAAA;AACAP,UAAQC,IAAI,wCAAA;AACd;AAnCsBH;","names":["context_provider","runNext","config","bootstrap","options","console","log","root_dir","load","config_data","DatabaseServiceProvider","setPreLoader","f","middlewares","push","getInstance"]}
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 };
@@ -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