@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
@@ -592,6 +592,51 @@ var DatabaseTransport = class {
592
592
  // src/factories.mts
593
593
  var import_neko_cache = require("@devbro/neko-cache");
594
594
  var import_neko_storage = require("@devbro/neko-storage");
595
+
596
+ // src/cache/MultiCache.mts
597
+ var MultiCache = class {
598
+ constructor(caches) {
599
+ this.caches = caches;
600
+ }
601
+ static {
602
+ __name(this, "MultiCache");
603
+ }
604
+ async get(key) {
605
+ for (const cache2 of this.caches) {
606
+ const value = await cache2.get(key);
607
+ if (value !== void 0) {
608
+ return value;
609
+ }
610
+ }
611
+ return void 0;
612
+ }
613
+ async put(key, value, ttl) {
614
+ await Promise.all(this.caches.map((cache2) => cache2.put(key, value, ttl)));
615
+ }
616
+ async delete(key) {
617
+ await Promise.all(this.caches.map((cache2) => cache2.delete(key)));
618
+ }
619
+ async has(key) {
620
+ for (const cache2 of this.caches) {
621
+ if (await cache2.has(key)) {
622
+ return true;
623
+ }
624
+ }
625
+ return false;
626
+ }
627
+ async increment(key, amount) {
628
+ let rc = void 0;
629
+ for (const cache2 of this.caches) {
630
+ let rc2 = await cache2.increment(key, amount);
631
+ if (rc === void 0) {
632
+ rc = rc2;
633
+ }
634
+ }
635
+ return rc;
636
+ }
637
+ };
638
+
639
+ // src/factories.mts
595
640
  var FlexibleFactory = class {
596
641
  static {
597
642
  __name(this, "FlexibleFactory");
@@ -662,6 +707,13 @@ CacheProviderFactory.register("redis", (opt) => {
662
707
  CacheProviderFactory.register("file", (opt) => {
663
708
  return new import_neko_cache.FileCacheProvider(opt);
664
709
  });
710
+ CacheProviderFactory.register("multi", (opt) => {
711
+ const caches = [];
712
+ for (const c of opt.caches) {
713
+ caches.push(cache(c));
714
+ }
715
+ return new MultiCache(caches);
716
+ });
665
717
  CacheProviderFactory.register("disabled", (opt) => {
666
718
  return new import_neko_cache.DisabledCacheProvider();
667
719
  });
@@ -46,24 +46,17 @@ var CreateProjectCommand = class extends import_clipanion.Command {
46
46
  category: `Project`,
47
47
  description: `Create a new project`,
48
48
  details: `
49
- This command creates a new project with the specified name at the given path.
50
- If no path is provided, the project will be created in the current directory.
49
+ This command creates a new project interactively.
50
+ You will be prompted for the project path and other configuration options.
51
51
  `,
52
- examples: [
53
- [
54
- `Create a new project in specified directory`,
55
- `create project --path /path/to/my-project --git`
56
- ],
57
- [
58
- `Create a new project at a specific path with git initialized`,
59
- `create project --path /path/to/my-project --git`
60
- ]
61
- ]
62
- });
63
- projectPath = import_clipanion.Option.String("--path", { required: true });
64
- git = import_clipanion.Option.Boolean(`--git`, false, {
65
- description: `Initialize a git repository in the new project`
52
+ examples: [[`Create a new project`, `create project`]]
66
53
  });
54
+ projectPath = "";
55
+ executor = "";
56
+ packageManager = "";
57
+ linter = "";
58
+ validation_library = "";
59
+ database_type = "";
67
60
  async folderExists(folderPath) {
68
61
  try {
69
62
  const stats = await fs.stat(folderPath);
@@ -76,14 +69,148 @@ var CreateProjectCommand = class extends import_clipanion.Command {
76
69
  }
77
70
  }
78
71
  async execute() {
79
- const projectPath = import_path.default.join(this.projectPath);
80
- try {
81
- await fs.access(projectPath);
82
- console.error(`Error: Directory ${projectPath} already exists.`);
83
- return 1;
84
- } catch {
72
+ await this.setupProjectPath();
73
+ await this.setupGit();
74
+ await this.setupExecutorAndPackageManager();
75
+ await this.setupLinter();
76
+ await this.setupGeneralPackages();
77
+ await this.setupBaseProject();
78
+ await this.installPackages();
79
+ }
80
+ async processTplFolder(src, dest, data = {}) {
81
+ const files = await fs.readdir(src, { withFileTypes: true });
82
+ for (const file of files) {
83
+ const srcPath = import_path.default.join(src, file.name);
84
+ const destPath = file.isFile() && file.name.endsWith(".tpl") ? import_path.default.join(dest, file.name.substring(0, file.name.length - 4)) : import_path.default.join(dest, file.name);
85
+ if (file.isDirectory()) {
86
+ await fs.mkdir(destPath, { recursive: true });
87
+ await this.processTplFolder(srcPath, destPath, data);
88
+ } else if (file.name.endsWith(".tpl")) {
89
+ await this.processTplFile(srcPath, destPath, data);
90
+ } else {
91
+ throw new Error(
92
+ "unexpected non tpl file: " + srcPath + " " + file.name
93
+ );
94
+ }
95
+ }
96
+ }
97
+ async processTplFile(src, dest, data = {}) {
98
+ import_handlebars.default.registerHelper("eq", (a, b) => a === b);
99
+ const compiledTemplate = import_handlebars.default.compile(
100
+ (await fs.readFile(src)).toString()
101
+ );
102
+ const template = await compiledTemplate(data);
103
+ await fs.writeFile(dest, template);
104
+ }
105
+ async setupProjectPath() {
106
+ const pathInput = await (0, import_prompts.input)({
107
+ message: "Enter project path (leave empty to use current directory):",
108
+ default: ""
109
+ });
110
+ this.projectPath = pathInput.trim() ? import_path.default.resolve(pathInput.trim()) : process.cwd();
111
+ await fs.mkdir(this.projectPath, { recursive: true });
112
+ const files = await fs.readdir(this.projectPath);
113
+ if (files.length > 0) {
114
+ throw new Error(
115
+ `Directory ${this.projectPath} is not empty. Please use an empty directory.`
116
+ );
117
+ }
118
+ }
119
+ async setupExecutorAndPackageManager() {
120
+ this.executor = await (0, import_prompts.select)({
121
+ message: "Select a TypeScript executor",
122
+ choices: [
123
+ {
124
+ name: "Bun",
125
+ value: "bun",
126
+ description: "Fast all-in-one JavaScript runtime"
127
+ },
128
+ {
129
+ name: "TSX",
130
+ value: "tsx",
131
+ description: "TypeScript execute (tsx) - Node.js enhanced with esbuild"
132
+ }
133
+ ]
134
+ });
135
+ this.packageManager = this.executor === "bun" ? "bun" : await (0, import_prompts.select)({
136
+ message: "Select a package manager",
137
+ choices: [
138
+ {
139
+ name: "Yarn",
140
+ value: "yarn",
141
+ description: "Fast, reliable, and secure dependency management"
142
+ },
143
+ {
144
+ name: "npm",
145
+ value: "npm",
146
+ description: "Node package manager (default)"
147
+ },
148
+ {
149
+ name: "Bun",
150
+ value: "bun",
151
+ description: "Ultra-fast package manager built into Bun"
152
+ }
153
+ ],
154
+ default: "yarn"
155
+ });
156
+ (0, import_child_process.execSync)(`${this.packageManager} init -y`, {
157
+ stdio: "inherit",
158
+ cwd: this.projectPath
159
+ });
160
+ const packageJsonPath = import_path.default.join(this.projectPath, `package.json`);
161
+ let packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));
162
+ packageJson.type = "module";
163
+ packageJson.scripts = packageJson.scripts || {};
164
+ packageJson.scripts.prepare = "husky init";
165
+ packageJson.scripts.clean = "rm -rf dist";
166
+ if (this.executor === "bun") {
167
+ packageJson.scripts.dev = "bun run dev";
168
+ packageJson.scripts.start = "bun run pdev";
169
+ packageJson.scripts.build = "bun run build";
170
+ packageJson.scripts.test = "vitest";
171
+ packageJson.scripts["test:watch"] = "vitest --watch";
172
+ packageJson.scripts["test:coverage"] = "vitest run --coverage";
173
+ } else if (this.executor === "tsx") {
174
+ packageJson.scripts.dev = "tsx --watch -r tsconfig-paths/register src/index.ts start --all | npx pino-pretty";
175
+ packageJson.scripts.start = "tsx dist/index.js";
176
+ packageJson.scripts.build = "tsc";
177
+ packageJson.scripts.test = "vitest";
178
+ packageJson.scripts["test:watch"] = "vitest --watch";
179
+ packageJson.scripts["test:coverage"] = "vitest run --coverage";
180
+ }
181
+ await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
182
+ }
183
+ async setupLinter() {
184
+ this.linter = await (0, import_prompts.select)({
185
+ message: "Select a linter",
186
+ choices: [
187
+ {
188
+ name: "Biome",
189
+ value: "biome",
190
+ description: "Fast formatter and linter for JavaScript, TypeScript, and more"
191
+ },
192
+ {
193
+ name: "ESLint",
194
+ value: "eslint",
195
+ description: "Find and fix problems in your JavaScript code"
196
+ }
197
+ ]
198
+ });
199
+ const packageJsonPath = import_path.default.join(this.projectPath, `package.json`);
200
+ let packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));
201
+ if (this.linter === "biome") {
202
+ packageJson.scripts.lint = "biome check . --ext .ts,.tsx";
203
+ packageJson.scripts.format = "biome format . --ext .ts,.tsx --write";
204
+ this.addPackage("@biomejs/biome", true);
205
+ } else if (this.linter === "eslint") {
206
+ packageJson.scripts.lint = "eslint . --ext .ts,.tsx";
207
+ packageJson.scripts.format = "eslint . --ext .ts,.tsx --fix";
208
+ this.addPackage("eslint", true);
85
209
  }
86
- const validation_library = await (0, import_prompts.select)({
210
+ await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
211
+ }
212
+ async setupGeneralPackages() {
213
+ this.validation_library = await (0, import_prompts.select)({
87
214
  message: "Select a package you want for validation",
88
215
  choices: [
89
216
  {
@@ -104,8 +231,42 @@ var CreateProjectCommand = class extends import_clipanion.Command {
104
231
  }
105
232
  ]
106
233
  });
107
- await fs.mkdir(projectPath, { recursive: true });
108
- console.log(`Created project directory at: ${projectPath}`);
234
+ this.validation_library === "none" || await this.addPackage(this.validation_library);
235
+ this.database_type = await (0, import_prompts.select)({
236
+ message: "Select a database type (you can add more databases later)",
237
+ choices: [
238
+ {
239
+ name: "PostgreSQL",
240
+ value: "postgresql",
241
+ description: "A powerful, open source object-relational database system"
242
+ },
243
+ {
244
+ name: "MySQL",
245
+ value: "mysql",
246
+ description: "The world's most popular open source database"
247
+ },
248
+ {
249
+ name: "SQLite",
250
+ value: "sqlite",
251
+ description: "A C library that provides a lightweight disk-based database"
252
+ }
253
+ ]
254
+ });
255
+ if (this.database_type === "postgresql") {
256
+ await this.addPackage("pg pg-cursor");
257
+ } else if (this.database_type === "mysql") {
258
+ await this.addPackage("mysql2");
259
+ } else if (this.database_type === "sqlite") {
260
+ await this.addPackage("sqlite3");
261
+ }
262
+ await this.addPackage("@devbro/pashmak tsconfig-paths dotenv ");
263
+ await this.addPackage(
264
+ "husky vitest supertest @types/supertest pino-pretty typescript tsx",
265
+ true
266
+ );
267
+ }
268
+ async setupBaseProject() {
269
+ console.log(`Using project directory: ${this.projectPath}`);
109
270
  const dirname = typeof __dirname === "undefined" ? import_path.default.dirname((0, import_url.fileURLToPath)(import_meta.url)) : __dirname;
110
271
  let basePath = import_path.default.join(dirname, `./base_project`);
111
272
  if (await this.folderExists(basePath) === false) {
@@ -113,53 +274,90 @@ var CreateProjectCommand = class extends import_clipanion.Command {
113
274
  }
114
275
  console.log(`Using base project path: ${basePath}`);
115
276
  const baseProjectPath = basePath;
116
- await this.processTplFolder(baseProjectPath, projectPath, {
117
- validation_library
277
+ await this.processTplFolder(baseProjectPath, this.projectPath, {
278
+ validation_library: this.validation_library,
279
+ executor: this.executor,
280
+ package_manager: this.packageManager,
281
+ linter: this.linter,
282
+ database_type: this.database_type
118
283
  });
119
- console.log(`Copied base project files to: ${projectPath}`);
120
- const packageJsonPath = import_path.default.join(projectPath, `package.json`);
121
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));
122
- packageJson.name = import_change_case_all.Case.snake(import_path.default.basename(projectPath));
284
+ console.log(`Copied base project files to: ${this.projectPath}`);
285
+ const packageJsonPath = import_path.default.join(this.projectPath, "package.json");
286
+ let packageJson = JSON.parse(await fs.readFile(packageJsonPath, `utf-8`));
287
+ packageJson.name = import_change_case_all.Case.snake(import_path.default.basename(this.projectPath));
123
288
  await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
124
289
  console.log(`Updated package.json with project name: ${packageJson.name}`);
125
- if (this.git) {
126
- try {
127
- (0, import_child_process.execSync)(
128
- 'git init; git add --all; git commit --allow-empty -m "chore: first commit for pashmak"',
129
- {
130
- cwd: projectPath
131
- }
132
- );
133
- } catch (error) {
134
- console.error(`Failed to create project.`, error);
135
- return 1;
136
- }
290
+ }
291
+ async addPackage(packageName, dev = false) {
292
+ let install_command = "";
293
+ switch (this.packageManager) {
294
+ case "bun":
295
+ install_command = `bun add ${packageName}${dev ? " -d" : ""}`;
296
+ break;
297
+ case "yarn":
298
+ install_command = `yarn add ${packageName}${dev ? " -D" : ""} --no-install`;
299
+ break;
300
+ case "npm":
301
+ install_command = `npm install ${packageName}${dev ? " --save-dev" : ""} --package-lock-only`;
302
+ break;
137
303
  }
304
+ (0, import_child_process.execSync)(install_command, {
305
+ stdio: "inherit",
306
+ cwd: this.projectPath
307
+ });
138
308
  }
139
- async processTplFolder(src, dest, data = {}) {
140
- const files = await fs.readdir(src, { withFileTypes: true });
141
- for (const file of files) {
142
- const srcPath = import_path.default.join(src, file.name);
143
- const destPath = file.isFile() && file.name.endsWith(".tpl") ? import_path.default.join(dest, file.name.substring(0, file.name.length - 4)) : import_path.default.join(dest, file.name);
144
- if (file.isDirectory()) {
145
- await fs.mkdir(destPath, { recursive: true });
146
- await this.processTplFolder(srcPath, destPath, data);
147
- } else if (file.name.endsWith(".tpl")) {
148
- await this.processTplFile(srcPath, destPath, data);
149
- } else {
150
- throw new Error(
151
- "unexpected non tpl file: " + srcPath + " " + file.name
152
- );
153
- }
309
+ async installPackages() {
310
+ const install_command = this.packageManager === "bun" ? `bun install` : this.packageManager === "yarn" ? `yarn` : `npm install`;
311
+ (0, import_child_process.execSync)(install_command, {
312
+ stdio: "inherit",
313
+ cwd: this.projectPath
314
+ });
315
+ }
316
+ async setupGit() {
317
+ const initGit = await (0, import_prompts.select)({
318
+ message: "Initialize a git repository?",
319
+ choices: [
320
+ {
321
+ name: "Yes",
322
+ value: true,
323
+ description: "Initialize git and create first commit"
324
+ },
325
+ {
326
+ name: "No",
327
+ value: false,
328
+ description: "Skip git initialization"
329
+ }
330
+ ]
331
+ });
332
+ if (initGit) {
333
+ const gitignoreContent = [
334
+ "node_modules/",
335
+ "dist/",
336
+ ".env",
337
+ ".env.*",
338
+ "!.env.example",
339
+ "*.log",
340
+ "coverage/",
341
+ ".DS_Store"
342
+ ].join("\n") + "\n";
343
+ await fs.writeFile(
344
+ import_path.default.join(this.projectPath, ".gitignore"),
345
+ gitignoreContent
346
+ );
347
+ (0, import_child_process.execSync)(
348
+ `git init; git add --all; git commit --allow-empty -m "chore: first commit"`,
349
+ {
350
+ cwd: this.projectPath
351
+ }
352
+ );
154
353
  }
155
354
  }
156
- async processTplFile(src, dest, data = {}) {
157
- import_handlebars.default.registerHelper("eq", (a, b) => a === b);
158
- const compiledTemplate = import_handlebars.default.compile(
159
- (await fs.readFile(src)).toString()
160
- );
161
- const template = await compiledTemplate(data);
162
- await fs.writeFile(dest, template);
355
+ async catch(error) {
356
+ if (Error.isError(error)) {
357
+ console.error(error.message);
358
+ } else {
359
+ console.error(error);
360
+ }
163
361
  }
164
362
  };
165
363
 
@@ -173,5 +371,6 @@ var cli = new import_clipanion2.Cli({
173
371
  cli.register(CreateProjectCommand);
174
372
  cli.runExit(args).then(() => {
175
373
  }).catch((err) => {
176
- console.error(err);
374
+ console.error("Fatal error:", err.message);
375
+ process.exit(1);
177
376
  });
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/cache/MultiCache.mts
22
+ var MultiCache_exports = {};
23
+ __export(MultiCache_exports, {
24
+ MultiCache: () => MultiCache
25
+ });
26
+ module.exports = __toCommonJS(MultiCache_exports);
27
+ var MultiCache = class {
28
+ constructor(caches) {
29
+ this.caches = caches;
30
+ }
31
+ static {
32
+ __name(this, "MultiCache");
33
+ }
34
+ async get(key) {
35
+ for (const cache of this.caches) {
36
+ const value = await cache.get(key);
37
+ if (value !== void 0) {
38
+ return value;
39
+ }
40
+ }
41
+ return void 0;
42
+ }
43
+ async put(key, value, ttl) {
44
+ await Promise.all(this.caches.map((cache) => cache.put(key, value, ttl)));
45
+ }
46
+ async delete(key) {
47
+ await Promise.all(this.caches.map((cache) => cache.delete(key)));
48
+ }
49
+ async has(key) {
50
+ for (const cache of this.caches) {
51
+ if (await cache.has(key)) {
52
+ return true;
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+ async increment(key, amount) {
58
+ let rc = void 0;
59
+ for (const cache of this.caches) {
60
+ let rc2 = await cache.increment(key, amount);
61
+ if (rc === void 0) {
62
+ rc = rc2;
63
+ }
64
+ }
65
+ return rc;
66
+ }
67
+ };
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ MultiCache
71
+ });
@@ -29,7 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  ));
30
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
31
 
32
- // src/cache.mts
32
+ // src/cache/cache.mts
33
33
  var cache_exports = {};
34
34
  __export(cache_exports, {
35
35
  cacheQuery: () => cacheQuery
@@ -593,6 +593,51 @@ var DatabaseTransport = class {
593
593
  // src/factories.mts
594
594
  var import_neko_cache = require("@devbro/neko-cache");
595
595
  var import_neko_storage = require("@devbro/neko-storage");
596
+
597
+ // src/cache/MultiCache.mts
598
+ var MultiCache = class {
599
+ constructor(caches) {
600
+ this.caches = caches;
601
+ }
602
+ static {
603
+ __name(this, "MultiCache");
604
+ }
605
+ async get(key) {
606
+ for (const cache2 of this.caches) {
607
+ const value = await cache2.get(key);
608
+ if (value !== void 0) {
609
+ return value;
610
+ }
611
+ }
612
+ return void 0;
613
+ }
614
+ async put(key, value, ttl) {
615
+ await Promise.all(this.caches.map((cache2) => cache2.put(key, value, ttl)));
616
+ }
617
+ async delete(key) {
618
+ await Promise.all(this.caches.map((cache2) => cache2.delete(key)));
619
+ }
620
+ async has(key) {
621
+ for (const cache2 of this.caches) {
622
+ if (await cache2.has(key)) {
623
+ return true;
624
+ }
625
+ }
626
+ return false;
627
+ }
628
+ async increment(key, amount) {
629
+ let rc = void 0;
630
+ for (const cache2 of this.caches) {
631
+ let rc2 = await cache2.increment(key, amount);
632
+ if (rc === void 0) {
633
+ rc = rc2;
634
+ }
635
+ }
636
+ return rc;
637
+ }
638
+ };
639
+
640
+ // src/factories.mts
596
641
  var FlexibleFactory = class {
597
642
  static {
598
643
  __name(this, "FlexibleFactory");
@@ -663,6 +708,13 @@ CacheProviderFactory.register("redis", (opt) => {
663
708
  CacheProviderFactory.register("file", (opt) => {
664
709
  return new import_neko_cache.FileCacheProvider(opt);
665
710
  });
711
+ CacheProviderFactory.register("multi", (opt) => {
712
+ const caches = [];
713
+ for (const c of opt.caches) {
714
+ caches.push(cache(c));
715
+ }
716
+ return new MultiCache(caches);
717
+ });
666
718
  CacheProviderFactory.register("disabled", (opt) => {
667
719
  return new import_neko_cache.DisabledCacheProvider();
668
720
  });
@@ -803,7 +855,7 @@ var cache = wrapSingletonWithAccessors(
803
855
  })
804
856
  );
805
857
 
806
- // src/cache.mts
858
+ // src/cache/cache.mts
807
859
  async function cacheQuery(q, options = {}) {
808
860
  options.ttl = options.ttl ?? 3600;
809
861
  options.cache_label = options.cache_label ?? "default";
@@ -601,6 +601,51 @@ var DatabaseTransport = class {
601
601
  // src/factories.mts
602
602
  var import_neko_cache = require("@devbro/neko-cache");
603
603
  var import_neko_storage = require("@devbro/neko-storage");
604
+
605
+ // src/cache/MultiCache.mts
606
+ var MultiCache = class {
607
+ constructor(caches) {
608
+ this.caches = caches;
609
+ }
610
+ static {
611
+ __name(this, "MultiCache");
612
+ }
613
+ async get(key) {
614
+ for (const cache2 of this.caches) {
615
+ const value = await cache2.get(key);
616
+ if (value !== void 0) {
617
+ return value;
618
+ }
619
+ }
620
+ return void 0;
621
+ }
622
+ async put(key, value, ttl) {
623
+ await Promise.all(this.caches.map((cache2) => cache2.put(key, value, ttl)));
624
+ }
625
+ async delete(key) {
626
+ await Promise.all(this.caches.map((cache2) => cache2.delete(key)));
627
+ }
628
+ async has(key) {
629
+ for (const cache2 of this.caches) {
630
+ if (await cache2.has(key)) {
631
+ return true;
632
+ }
633
+ }
634
+ return false;
635
+ }
636
+ async increment(key, amount) {
637
+ let rc = void 0;
638
+ for (const cache2 of this.caches) {
639
+ let rc2 = await cache2.increment(key, amount);
640
+ if (rc === void 0) {
641
+ rc = rc2;
642
+ }
643
+ }
644
+ return rc;
645
+ }
646
+ };
647
+
648
+ // src/factories.mts
604
649
  var FlexibleFactory = class {
605
650
  static {
606
651
  __name(this, "FlexibleFactory");
@@ -671,6 +716,13 @@ CacheProviderFactory.register("redis", (opt) => {
671
716
  CacheProviderFactory.register("file", (opt) => {
672
717
  return new import_neko_cache.FileCacheProvider(opt);
673
718
  });
719
+ CacheProviderFactory.register("multi", (opt) => {
720
+ const caches = [];
721
+ for (const c of opt.caches) {
722
+ caches.push(cache(c));
723
+ }
724
+ return new MultiCache(caches);
725
+ });
674
726
  CacheProviderFactory.register("disabled", (opt) => {
675
727
  return new import_neko_cache.DisabledCacheProvider();
676
728
  });