@devbro/pashmak 0.1.10 → 0.1.12
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/app/console/migrate/MigrateCommand.d.mts +1 -0
- package/dist/app/console/migrate/MigrateCommand.mjs +33 -16
- package/dist/app/console/migrate/MigrateCommand.mjs.map +1 -1
- package/dist/app/console/migrate/MigrateRollbackCommand.d.mts +1 -1
- package/dist/app/console/migrate/MigrateRollbackCommand.mjs +5 -6
- package/dist/app/console/migrate/MigrateRollbackCommand.mjs.map +1 -1
- package/dist/app/console/migrate/make_migration.tpl +5 -5
- package/dist/app/console/queue/GenerateMigrateCommand.d.mts +9 -0
- package/dist/app/console/queue/GenerateMigrateCommand.mjs +51 -0
- package/dist/app/console/queue/GenerateMigrateCommand.mjs.map +1 -0
- package/dist/app/console/queue/queue_migration.tpl +19 -0
- package/dist/bin/app/console/DefaultCommand.cjs +254 -25
- package/dist/bin/app/console/KeyGenerateCommand.cjs +254 -25
- package/dist/bin/app/console/StartCommand.cjs +257 -28
- package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +254 -25
- package/dist/bin/app/console/generate/index.cjs +254 -25
- package/dist/bin/app/console/index.cjs +293 -48
- package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +254 -25
- package/dist/bin/app/console/migrate/MigrateCommand.cjs +288 -42
- package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +258 -30
- package/dist/bin/app/console/migrate/index.cjs +291 -46
- package/dist/bin/app/console/queue/GenerateMigrateCommand.cjs +752 -0
- package/dist/bin/facades.cjs +257 -26
- package/dist/bin/factories.cjs +707 -0
- package/dist/bin/index.cjs +312 -54
- package/dist/bin/middlewares.cjs +255 -26
- package/dist/bin/queue.cjs +99 -0
- package/dist/bin/router.cjs +95 -5
- package/dist/facades.d.mts +3 -1
- package/dist/facades.mjs +15 -27
- package/dist/facades.mjs.map +1 -1
- package/dist/factories.d.mts +20 -0
- package/dist/factories.mjs +83 -0
- package/dist/factories.mjs.map +1 -0
- package/dist/queue.d.mts +15 -0
- package/dist/queue.mjs +73 -0
- package/dist/queue.mjs.map +1 -0
- package/dist/router.mjs +1 -1
- package/dist/router.mjs.map +1 -1
- package/package.json +10 -3
package/dist/bin/middlewares.cjs
CHANGED
|
@@ -41,6 +41,9 @@ module.exports = __toCommonJS(middlewares_exports);
|
|
|
41
41
|
var import_neko_context = require("@devbro/neko-context");
|
|
42
42
|
var import_errors = require("@devbro/neko-http/errors");
|
|
43
43
|
|
|
44
|
+
// ../neko-router/dist/CompiledRoute.mjs
|
|
45
|
+
var import_stream = require("stream");
|
|
46
|
+
|
|
44
47
|
// ../neko-router/dist/Middleware.mjs
|
|
45
48
|
var Middleware = class {
|
|
46
49
|
static {
|
|
@@ -118,6 +121,9 @@ var CompiledRoute = class {
|
|
|
118
121
|
if (typeof value.toJson === "function") {
|
|
119
122
|
return traverse(value.toJson());
|
|
120
123
|
}
|
|
124
|
+
if (typeof value.toJSON === "function") {
|
|
125
|
+
return traverse(value.toJSON());
|
|
126
|
+
}
|
|
121
127
|
if (Array.isArray(value)) {
|
|
122
128
|
return value.map(traverse);
|
|
123
129
|
}
|
|
@@ -142,7 +148,7 @@ var CompiledRoute = class {
|
|
|
142
148
|
}
|
|
143
149
|
return String(obj);
|
|
144
150
|
}
|
|
145
|
-
processResponseBody(res, controller_rc) {
|
|
151
|
+
async processResponseBody(res, controller_rc) {
|
|
146
152
|
if (controller_rc && res.writableEnded) {
|
|
147
153
|
throw new Error("cannot write to response, response has already ended");
|
|
148
154
|
}
|
|
@@ -151,18 +157,36 @@ var CompiledRoute = class {
|
|
|
151
157
|
}
|
|
152
158
|
if (controller_rc) {
|
|
153
159
|
const header_content_type = res.getHeader("Content-Type");
|
|
154
|
-
if (
|
|
160
|
+
if (controller_rc instanceof import_stream.Stream || Buffer.isBuffer(controller_rc)) {
|
|
161
|
+
await this.writeAsync(res, controller_rc);
|
|
162
|
+
res.end();
|
|
163
|
+
} else if (!header_content_type && typeof controller_rc === "object") {
|
|
155
164
|
res.setHeader("Content-Type", "application/json");
|
|
165
|
+
res.end(this.convertToString(controller_rc));
|
|
156
166
|
} else if (!header_content_type) {
|
|
157
167
|
res.setHeader("Content-Type", "text/plain");
|
|
168
|
+
res.end(this.convertToString(controller_rc));
|
|
169
|
+
} else {
|
|
170
|
+
res.end(this.convertToString(controller_rc));
|
|
158
171
|
}
|
|
159
|
-
res.end(this.convertToString(controller_rc));
|
|
160
172
|
return;
|
|
161
173
|
} else {
|
|
162
174
|
res.statusCode = [200].includes(res.statusCode) ? 204 : res.statusCode;
|
|
163
175
|
res.end();
|
|
164
176
|
}
|
|
165
177
|
}
|
|
178
|
+
async writeAsync(res, chunk) {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
const ok = res.write(chunk, (err) => {
|
|
181
|
+
if (err) reject(err);
|
|
182
|
+
});
|
|
183
|
+
if (ok) {
|
|
184
|
+
resolve(0);
|
|
185
|
+
} else {
|
|
186
|
+
res.once("drain", resolve);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
166
190
|
async runMiddlewares(middlewares, req, res) {
|
|
167
191
|
let index = 0;
|
|
168
192
|
const me = this;
|
|
@@ -220,7 +244,7 @@ var Route = class {
|
|
|
220
244
|
i = start;
|
|
221
245
|
} else if (char === "*") {
|
|
222
246
|
let start = i + 1;
|
|
223
|
-
while (start < path2.length && /[a-zA-Z0-9_]/.test(path2[start])) {
|
|
247
|
+
while (start < path2.length && /[a-zA-Z0-9_\.]/.test(path2[start])) {
|
|
224
248
|
start++;
|
|
225
249
|
}
|
|
226
250
|
tokens.push({ type: "WILDCARD", value: path2.slice(i + 1, start) });
|
|
@@ -290,6 +314,10 @@ var Route = class {
|
|
|
290
314
|
params: r.groups || {}
|
|
291
315
|
};
|
|
292
316
|
}
|
|
317
|
+
prependMiddleware(middlewares) {
|
|
318
|
+
this.middlewares = [].concat(middlewares, this.middlewares);
|
|
319
|
+
return this;
|
|
320
|
+
}
|
|
293
321
|
addMiddleware(middlewares) {
|
|
294
322
|
this.middlewares = this.middlewares.concat(middlewares);
|
|
295
323
|
return this;
|
|
@@ -304,6 +332,62 @@ var Route = class {
|
|
|
304
332
|
|
|
305
333
|
// ../neko-router/dist/Router.mjs
|
|
306
334
|
var import_path = __toESM(require("path"), 1);
|
|
335
|
+
|
|
336
|
+
// ../node_modules/url-join/lib/url-join.js
|
|
337
|
+
function normalize(strArray) {
|
|
338
|
+
var resultArray = [];
|
|
339
|
+
if (strArray.length === 0) {
|
|
340
|
+
return "";
|
|
341
|
+
}
|
|
342
|
+
if (typeof strArray[0] !== "string") {
|
|
343
|
+
throw new TypeError("Url must be a string. Received " + strArray[0]);
|
|
344
|
+
}
|
|
345
|
+
if (strArray[0].match(/^[^/:]+:\/*$/) && strArray.length > 1) {
|
|
346
|
+
var first = strArray.shift();
|
|
347
|
+
strArray[0] = first + strArray[0];
|
|
348
|
+
}
|
|
349
|
+
if (strArray[0].match(/^file:\/\/\//)) {
|
|
350
|
+
strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1:///");
|
|
351
|
+
} else {
|
|
352
|
+
strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1://");
|
|
353
|
+
}
|
|
354
|
+
for (var i = 0; i < strArray.length; i++) {
|
|
355
|
+
var component = strArray[i];
|
|
356
|
+
if (typeof component !== "string") {
|
|
357
|
+
throw new TypeError("Url must be a string. Received " + component);
|
|
358
|
+
}
|
|
359
|
+
if (component === "") {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (i > 0) {
|
|
363
|
+
component = component.replace(/^[\/]+/, "");
|
|
364
|
+
}
|
|
365
|
+
if (i < strArray.length - 1) {
|
|
366
|
+
component = component.replace(/[\/]+$/, "");
|
|
367
|
+
} else {
|
|
368
|
+
component = component.replace(/[\/]+$/, "/");
|
|
369
|
+
}
|
|
370
|
+
resultArray.push(component);
|
|
371
|
+
}
|
|
372
|
+
var str = resultArray.join("/");
|
|
373
|
+
str = str.replace(/\/(\?|&|#[^!])/g, "$1");
|
|
374
|
+
var parts = str.split("?");
|
|
375
|
+
str = parts.shift() + (parts.length > 0 ? "?" : "") + parts.join("&");
|
|
376
|
+
return str;
|
|
377
|
+
}
|
|
378
|
+
__name(normalize, "normalize");
|
|
379
|
+
function urlJoin() {
|
|
380
|
+
var input;
|
|
381
|
+
if (typeof arguments[0] === "object") {
|
|
382
|
+
input = arguments[0];
|
|
383
|
+
} else {
|
|
384
|
+
input = [].slice.call(arguments);
|
|
385
|
+
}
|
|
386
|
+
return normalize(input);
|
|
387
|
+
}
|
|
388
|
+
__name(urlJoin, "urlJoin");
|
|
389
|
+
|
|
390
|
+
// ../neko-router/dist/Router.mjs
|
|
307
391
|
var Router = class {
|
|
308
392
|
static {
|
|
309
393
|
__name(this, "Router");
|
|
@@ -328,6 +412,12 @@ var Router = class {
|
|
|
328
412
|
}).addMiddleware([...controller.baseMiddlewares, ...route.middlewares]);
|
|
329
413
|
}
|
|
330
414
|
}
|
|
415
|
+
addRouter(path2, router2) {
|
|
416
|
+
for (const route of router2.routes) {
|
|
417
|
+
let path22 = urlJoin("/", path2, route.path);
|
|
418
|
+
this.addRoute(route.methods, path22, route.handler).addMiddleware(router2.getMiddlewares()).addMiddleware(route.getMiddlewares());
|
|
419
|
+
}
|
|
420
|
+
}
|
|
331
421
|
addGlobalMiddleware(middlewares) {
|
|
332
422
|
this.middlewares = this.middlewares.concat(middlewares);
|
|
333
423
|
}
|
|
@@ -368,7 +458,7 @@ var import_neko_scheduler = require("@devbro/neko-scheduler");
|
|
|
368
458
|
var import_neko_helper = require("@devbro/neko-helper");
|
|
369
459
|
var import_neko_context2 = require("@devbro/neko-context");
|
|
370
460
|
var import_neko_storage = require("@devbro/neko-storage");
|
|
371
|
-
var
|
|
461
|
+
var import_neko_mailer2 = require("@devbro/neko-mailer");
|
|
372
462
|
var import_neko_config = require("@devbro/neko-config");
|
|
373
463
|
var import_clipanion = require("clipanion");
|
|
374
464
|
|
|
@@ -379,6 +469,153 @@ __reExport(http_exports, require("@devbro/neko-http"));
|
|
|
379
469
|
// src/facades.mts
|
|
380
470
|
var yup = __toESM(require("yup"), 1);
|
|
381
471
|
var import_neko_logger = require("@devbro/neko-logger");
|
|
472
|
+
|
|
473
|
+
// src/factories.mts
|
|
474
|
+
var import_neko_mailer = require("@devbro/neko-mailer");
|
|
475
|
+
var import_neko_queue = require("@devbro/neko-queue");
|
|
476
|
+
var import_neko_queue2 = require("@devbro/neko-queue");
|
|
477
|
+
|
|
478
|
+
// src/queue.mts
|
|
479
|
+
var queue_exports = {};
|
|
480
|
+
__export(queue_exports, {
|
|
481
|
+
DatabaseTransport: () => DatabaseTransport
|
|
482
|
+
});
|
|
483
|
+
__reExport(queue_exports, require("@devbro/neko-queue"));
|
|
484
|
+
var import_neko_sql = require("@devbro/neko-sql");
|
|
485
|
+
var DatabaseTransport = class {
|
|
486
|
+
// default to 100 messages per fetch
|
|
487
|
+
constructor(db_config) {
|
|
488
|
+
this.db_config = db_config;
|
|
489
|
+
}
|
|
490
|
+
static {
|
|
491
|
+
__name(this, "DatabaseTransport");
|
|
492
|
+
}
|
|
493
|
+
listenInterval = 6e4;
|
|
494
|
+
// default to 1 minute
|
|
495
|
+
messageLimit = 100;
|
|
496
|
+
setListenInterval(interval) {
|
|
497
|
+
this.listenInterval = interval;
|
|
498
|
+
}
|
|
499
|
+
setMessageLimit(limit) {
|
|
500
|
+
this.messageLimit = limit;
|
|
501
|
+
}
|
|
502
|
+
async dispatch(channel, message) {
|
|
503
|
+
const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
|
|
504
|
+
try {
|
|
505
|
+
await conn.connect();
|
|
506
|
+
let q = conn.getQuery();
|
|
507
|
+
await q.table("queue_messages").insert({
|
|
508
|
+
channel,
|
|
509
|
+
message,
|
|
510
|
+
processed: false,
|
|
511
|
+
created_at: /* @__PURE__ */ new Date(),
|
|
512
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
513
|
+
last_tried_at: null,
|
|
514
|
+
process_message: ""
|
|
515
|
+
});
|
|
516
|
+
} finally {
|
|
517
|
+
await conn.disconnect();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
async listen(channel, callback) {
|
|
521
|
+
return new Promise(async (resolve, reject) => {
|
|
522
|
+
setInterval(async () => {
|
|
523
|
+
const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
|
|
524
|
+
try {
|
|
525
|
+
await conn.connect();
|
|
526
|
+
let q = conn.getQuery();
|
|
527
|
+
let messages = await q.table("queue_messages").whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.messageLimit).orderBy("last_tried_at", "asc").get();
|
|
528
|
+
for (let msg of messages) {
|
|
529
|
+
try {
|
|
530
|
+
await callback(msg.message);
|
|
531
|
+
await q.table("queue_messages").whereOp("id", "=", msg.id).update({
|
|
532
|
+
processed: true,
|
|
533
|
+
updated_at: /* @__PURE__ */ new Date()
|
|
534
|
+
});
|
|
535
|
+
} catch (error) {
|
|
536
|
+
await q.table("queue_messages").whereOp("id", "=", msg.id).update({
|
|
537
|
+
processed: false,
|
|
538
|
+
last_tried_at: /* @__PURE__ */ new Date(),
|
|
539
|
+
process_message: error.message || "Error processing message"
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
} finally {
|
|
544
|
+
await conn.disconnect();
|
|
545
|
+
}
|
|
546
|
+
}, this.listenInterval);
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// src/factories.mts
|
|
552
|
+
var FlexibleFactory = class {
|
|
553
|
+
static {
|
|
554
|
+
__name(this, "FlexibleFactory");
|
|
555
|
+
}
|
|
556
|
+
registry = /* @__PURE__ */ new Map();
|
|
557
|
+
register(key, ctor) {
|
|
558
|
+
this.registry.set(key, ctor);
|
|
559
|
+
}
|
|
560
|
+
create(key, ...args) {
|
|
561
|
+
const ctor = this.registry.get(key);
|
|
562
|
+
if (!ctor) {
|
|
563
|
+
throw new Error(`No factory registered for key: ${key}`);
|
|
564
|
+
}
|
|
565
|
+
return new ctor(...args);
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
var MailerFactory = class _MailerFactory {
|
|
569
|
+
static {
|
|
570
|
+
__name(this, "MailerFactory");
|
|
571
|
+
}
|
|
572
|
+
static instance = new FlexibleFactory();
|
|
573
|
+
static register(key, factory) {
|
|
574
|
+
_MailerFactory.instance.register(key, factory);
|
|
575
|
+
}
|
|
576
|
+
static create(key, ...args) {
|
|
577
|
+
return _MailerFactory.instance.create(key, ...args);
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
MailerFactory.register("logger", (opt) => {
|
|
581
|
+
return new import_neko_mailer.FunctionProvider((mail) => {
|
|
582
|
+
logger().info({
|
|
583
|
+
msg: "Sending email",
|
|
584
|
+
mail
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
MailerFactory.register("SES", (opt) => {
|
|
589
|
+
return new import_neko_mailer.SESProvider(opt);
|
|
590
|
+
});
|
|
591
|
+
MailerFactory.register("SMTP", (opt) => {
|
|
592
|
+
return new import_neko_mailer.SMTPProvider(opt);
|
|
593
|
+
});
|
|
594
|
+
MailerFactory.register("MEMORY", (opt) => {
|
|
595
|
+
return new import_neko_mailer.MemoryProvider();
|
|
596
|
+
});
|
|
597
|
+
var QueueFactory = class _QueueFactory {
|
|
598
|
+
static {
|
|
599
|
+
__name(this, "QueueFactory");
|
|
600
|
+
}
|
|
601
|
+
static instance = new FlexibleFactory();
|
|
602
|
+
static register(key, factory) {
|
|
603
|
+
_QueueFactory.instance.register(key, factory);
|
|
604
|
+
}
|
|
605
|
+
static create(key, ...args) {
|
|
606
|
+
return _QueueFactory.instance.create(key, ...args);
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
QueueFactory.register("database", (opt) => {
|
|
610
|
+
let transport = new DatabaseTransport(opt);
|
|
611
|
+
return new import_neko_queue.QueueConnection(transport);
|
|
612
|
+
});
|
|
613
|
+
QueueFactory.register("memory", (opt) => {
|
|
614
|
+
let transport = new import_neko_queue2.MemoryTransport(opt);
|
|
615
|
+
return new import_neko_queue.QueueConnection(transport);
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// src/facades.mts
|
|
382
619
|
var router = (0, import_neko_helper.createSingleton)(() => new Router());
|
|
383
620
|
var scheduler = (0, import_neko_helper.createSingleton)(() => {
|
|
384
621
|
const rc = new import_neko_scheduler.Scheduler();
|
|
@@ -449,27 +686,19 @@ var logger = (0, import_neko_helper.createSingleton)((label) => {
|
|
|
449
686
|
});
|
|
450
687
|
var mailer = (0, import_neko_helper.createSingleton)((label) => {
|
|
451
688
|
const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
|
|
452
|
-
let provider
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
provider = new import_neko_mailer.MemoryProvider();
|
|
466
|
-
}
|
|
467
|
-
if (!provider) {
|
|
468
|
-
throw new Error(
|
|
469
|
-
`cannot initiate mailer provider: ${mailer_config?.provider}`
|
|
470
|
-
);
|
|
471
|
-
}
|
|
472
|
-
const rc = new import_neko_mailer.Mailer(provider);
|
|
689
|
+
let provider = MailerFactory.create(
|
|
690
|
+
mailer_config.provider,
|
|
691
|
+
mailer_config.config
|
|
692
|
+
);
|
|
693
|
+
const rc = new import_neko_mailer2.Mailer(provider);
|
|
694
|
+
return rc;
|
|
695
|
+
});
|
|
696
|
+
var queue = (0, import_neko_helper.createSingleton)(async (label) => {
|
|
697
|
+
const queue_config = import_neko_config.config.get(["queues", label].join("."));
|
|
698
|
+
if (!queue_config) {
|
|
699
|
+
throw new Error(`Queue configuration for '${label}' not found`);
|
|
700
|
+
}
|
|
701
|
+
const rc = await QueueFactory.create(queue_config.type, queue_config);
|
|
473
702
|
return rc;
|
|
474
703
|
});
|
|
475
704
|
|
|
@@ -0,0 +1,99 @@
|
|
|
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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/queue.mts
|
|
23
|
+
var queue_exports = {};
|
|
24
|
+
__export(queue_exports, {
|
|
25
|
+
DatabaseTransport: () => DatabaseTransport
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(queue_exports);
|
|
28
|
+
__reExport(queue_exports, require("@devbro/neko-queue"), module.exports);
|
|
29
|
+
var import_neko_sql = require("@devbro/neko-sql");
|
|
30
|
+
var DatabaseTransport = class {
|
|
31
|
+
// default to 100 messages per fetch
|
|
32
|
+
constructor(db_config) {
|
|
33
|
+
this.db_config = db_config;
|
|
34
|
+
}
|
|
35
|
+
static {
|
|
36
|
+
__name(this, "DatabaseTransport");
|
|
37
|
+
}
|
|
38
|
+
listenInterval = 6e4;
|
|
39
|
+
// default to 1 minute
|
|
40
|
+
messageLimit = 100;
|
|
41
|
+
setListenInterval(interval) {
|
|
42
|
+
this.listenInterval = interval;
|
|
43
|
+
}
|
|
44
|
+
setMessageLimit(limit) {
|
|
45
|
+
this.messageLimit = limit;
|
|
46
|
+
}
|
|
47
|
+
async dispatch(channel, message) {
|
|
48
|
+
const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
|
|
49
|
+
try {
|
|
50
|
+
await conn.connect();
|
|
51
|
+
let q = conn.getQuery();
|
|
52
|
+
await q.table("queue_messages").insert({
|
|
53
|
+
channel,
|
|
54
|
+
message,
|
|
55
|
+
processed: false,
|
|
56
|
+
created_at: /* @__PURE__ */ new Date(),
|
|
57
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
58
|
+
last_tried_at: null,
|
|
59
|
+
process_message: ""
|
|
60
|
+
});
|
|
61
|
+
} finally {
|
|
62
|
+
await conn.disconnect();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async listen(channel, callback) {
|
|
66
|
+
return new Promise(async (resolve, reject) => {
|
|
67
|
+
setInterval(async () => {
|
|
68
|
+
const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
|
|
69
|
+
try {
|
|
70
|
+
await conn.connect();
|
|
71
|
+
let q = conn.getQuery();
|
|
72
|
+
let messages = await q.table("queue_messages").whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.messageLimit).orderBy("last_tried_at", "asc").get();
|
|
73
|
+
for (let msg of messages) {
|
|
74
|
+
try {
|
|
75
|
+
await callback(msg.message);
|
|
76
|
+
await q.table("queue_messages").whereOp("id", "=", msg.id).update({
|
|
77
|
+
processed: true,
|
|
78
|
+
updated_at: /* @__PURE__ */ new Date()
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
await q.table("queue_messages").whereOp("id", "=", msg.id).update({
|
|
82
|
+
processed: false,
|
|
83
|
+
last_tried_at: /* @__PURE__ */ new Date(),
|
|
84
|
+
process_message: error.message || "Error processing message"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} finally {
|
|
89
|
+
await conn.disconnect();
|
|
90
|
+
}
|
|
91
|
+
}, this.listenInterval);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
96
|
+
0 && (module.exports = {
|
|
97
|
+
DatabaseTransport,
|
|
98
|
+
...require("@devbro/neko-queue")
|
|
99
|
+
});
|
package/dist/bin/router.cjs
CHANGED
|
@@ -54,6 +54,9 @@ module.exports = __toCommonJS(router_exports);
|
|
|
54
54
|
var import_neko_context = require("@devbro/neko-context");
|
|
55
55
|
var import_errors = require("@devbro/neko-http/errors");
|
|
56
56
|
|
|
57
|
+
// ../neko-router/dist/CompiledRoute.mjs
|
|
58
|
+
var import_stream = require("stream");
|
|
59
|
+
|
|
57
60
|
// ../neko-router/dist/Middleware.mjs
|
|
58
61
|
var Middleware = class {
|
|
59
62
|
static {
|
|
@@ -131,6 +134,9 @@ var CompiledRoute = class {
|
|
|
131
134
|
if (typeof value.toJson === "function") {
|
|
132
135
|
return traverse(value.toJson());
|
|
133
136
|
}
|
|
137
|
+
if (typeof value.toJSON === "function") {
|
|
138
|
+
return traverse(value.toJSON());
|
|
139
|
+
}
|
|
134
140
|
if (Array.isArray(value)) {
|
|
135
141
|
return value.map(traverse);
|
|
136
142
|
}
|
|
@@ -155,7 +161,7 @@ var CompiledRoute = class {
|
|
|
155
161
|
}
|
|
156
162
|
return String(obj);
|
|
157
163
|
}
|
|
158
|
-
processResponseBody(res, controller_rc) {
|
|
164
|
+
async processResponseBody(res, controller_rc) {
|
|
159
165
|
if (controller_rc && res.writableEnded) {
|
|
160
166
|
throw new Error("cannot write to response, response has already ended");
|
|
161
167
|
}
|
|
@@ -164,18 +170,36 @@ var CompiledRoute = class {
|
|
|
164
170
|
}
|
|
165
171
|
if (controller_rc) {
|
|
166
172
|
const header_content_type = res.getHeader("Content-Type");
|
|
167
|
-
if (
|
|
173
|
+
if (controller_rc instanceof import_stream.Stream || Buffer.isBuffer(controller_rc)) {
|
|
174
|
+
await this.writeAsync(res, controller_rc);
|
|
175
|
+
res.end();
|
|
176
|
+
} else if (!header_content_type && typeof controller_rc === "object") {
|
|
168
177
|
res.setHeader("Content-Type", "application/json");
|
|
178
|
+
res.end(this.convertToString(controller_rc));
|
|
169
179
|
} else if (!header_content_type) {
|
|
170
180
|
res.setHeader("Content-Type", "text/plain");
|
|
181
|
+
res.end(this.convertToString(controller_rc));
|
|
182
|
+
} else {
|
|
183
|
+
res.end(this.convertToString(controller_rc));
|
|
171
184
|
}
|
|
172
|
-
res.end(this.convertToString(controller_rc));
|
|
173
185
|
return;
|
|
174
186
|
} else {
|
|
175
187
|
res.statusCode = [200].includes(res.statusCode) ? 204 : res.statusCode;
|
|
176
188
|
res.end();
|
|
177
189
|
}
|
|
178
190
|
}
|
|
191
|
+
async writeAsync(res, chunk) {
|
|
192
|
+
return new Promise((resolve, reject) => {
|
|
193
|
+
const ok = res.write(chunk, (err) => {
|
|
194
|
+
if (err) reject(err);
|
|
195
|
+
});
|
|
196
|
+
if (ok) {
|
|
197
|
+
resolve(0);
|
|
198
|
+
} else {
|
|
199
|
+
res.once("drain", resolve);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
179
203
|
async runMiddlewares(middlewares, req, res) {
|
|
180
204
|
let index = 0;
|
|
181
205
|
const me = this;
|
|
@@ -336,7 +360,7 @@ var Route = class {
|
|
|
336
360
|
i = start;
|
|
337
361
|
} else if (char === "*") {
|
|
338
362
|
let start = i + 1;
|
|
339
|
-
while (start < path2.length && /[a-zA-Z0-9_]/.test(path2[start])) {
|
|
363
|
+
while (start < path2.length && /[a-zA-Z0-9_\.]/.test(path2[start])) {
|
|
340
364
|
start++;
|
|
341
365
|
}
|
|
342
366
|
tokens.push({ type: "WILDCARD", value: path2.slice(i + 1, start) });
|
|
@@ -406,6 +430,10 @@ var Route = class {
|
|
|
406
430
|
params: r.groups || {}
|
|
407
431
|
};
|
|
408
432
|
}
|
|
433
|
+
prependMiddleware(middlewares) {
|
|
434
|
+
this.middlewares = [].concat(middlewares, this.middlewares);
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
409
437
|
addMiddleware(middlewares) {
|
|
410
438
|
this.middlewares = this.middlewares.concat(middlewares);
|
|
411
439
|
return this;
|
|
@@ -420,6 +448,62 @@ var Route = class {
|
|
|
420
448
|
|
|
421
449
|
// ../neko-router/dist/Router.mjs
|
|
422
450
|
var import_path = __toESM(require("path"), 1);
|
|
451
|
+
|
|
452
|
+
// ../node_modules/url-join/lib/url-join.js
|
|
453
|
+
function normalize(strArray) {
|
|
454
|
+
var resultArray = [];
|
|
455
|
+
if (strArray.length === 0) {
|
|
456
|
+
return "";
|
|
457
|
+
}
|
|
458
|
+
if (typeof strArray[0] !== "string") {
|
|
459
|
+
throw new TypeError("Url must be a string. Received " + strArray[0]);
|
|
460
|
+
}
|
|
461
|
+
if (strArray[0].match(/^[^/:]+:\/*$/) && strArray.length > 1) {
|
|
462
|
+
var first = strArray.shift();
|
|
463
|
+
strArray[0] = first + strArray[0];
|
|
464
|
+
}
|
|
465
|
+
if (strArray[0].match(/^file:\/\/\//)) {
|
|
466
|
+
strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1:///");
|
|
467
|
+
} else {
|
|
468
|
+
strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1://");
|
|
469
|
+
}
|
|
470
|
+
for (var i = 0; i < strArray.length; i++) {
|
|
471
|
+
var component = strArray[i];
|
|
472
|
+
if (typeof component !== "string") {
|
|
473
|
+
throw new TypeError("Url must be a string. Received " + component);
|
|
474
|
+
}
|
|
475
|
+
if (component === "") {
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
if (i > 0) {
|
|
479
|
+
component = component.replace(/^[\/]+/, "");
|
|
480
|
+
}
|
|
481
|
+
if (i < strArray.length - 1) {
|
|
482
|
+
component = component.replace(/[\/]+$/, "");
|
|
483
|
+
} else {
|
|
484
|
+
component = component.replace(/[\/]+$/, "/");
|
|
485
|
+
}
|
|
486
|
+
resultArray.push(component);
|
|
487
|
+
}
|
|
488
|
+
var str = resultArray.join("/");
|
|
489
|
+
str = str.replace(/\/(\?|&|#[^!])/g, "$1");
|
|
490
|
+
var parts = str.split("?");
|
|
491
|
+
str = parts.shift() + (parts.length > 0 ? "?" : "") + parts.join("&");
|
|
492
|
+
return str;
|
|
493
|
+
}
|
|
494
|
+
__name(normalize, "normalize");
|
|
495
|
+
function urlJoin() {
|
|
496
|
+
var input;
|
|
497
|
+
if (typeof arguments[0] === "object") {
|
|
498
|
+
input = arguments[0];
|
|
499
|
+
} else {
|
|
500
|
+
input = [].slice.call(arguments);
|
|
501
|
+
}
|
|
502
|
+
return normalize(input);
|
|
503
|
+
}
|
|
504
|
+
__name(urlJoin, "urlJoin");
|
|
505
|
+
|
|
506
|
+
// ../neko-router/dist/Router.mjs
|
|
423
507
|
var Router = class {
|
|
424
508
|
static {
|
|
425
509
|
__name(this, "Router");
|
|
@@ -444,6 +528,12 @@ var Router = class {
|
|
|
444
528
|
}).addMiddleware([...controller.baseMiddlewares, ...route.middlewares]);
|
|
445
529
|
}
|
|
446
530
|
}
|
|
531
|
+
addRouter(path2, router) {
|
|
532
|
+
for (const route of router.routes) {
|
|
533
|
+
let path22 = urlJoin("/", path2, route.path);
|
|
534
|
+
this.addRoute(route.methods, path22, route.handler).addMiddleware(router.getMiddlewares()).addMiddleware(route.getMiddlewares());
|
|
535
|
+
}
|
|
536
|
+
}
|
|
447
537
|
addGlobalMiddleware(middlewares) {
|
|
448
538
|
this.middlewares = this.middlewares.concat(middlewares);
|
|
449
539
|
}
|
|
@@ -505,7 +595,7 @@ function Model(model, paramName) {
|
|
|
505
595
|
return createParamDecorator(async () => {
|
|
506
596
|
let rc = await model.find((0, import_neko_context.ctx)().get("request").params[paramName]);
|
|
507
597
|
if (!rc) {
|
|
508
|
-
throw new import_errors.HttpNotFoundError("Object not found");
|
|
598
|
+
throw new import_errors.HttpNotFoundError("Object not found", "OBJECT_NOT_FOUND");
|
|
509
599
|
}
|
|
510
600
|
return rc;
|
|
511
601
|
});
|
package/dist/facades.d.mts
CHANGED
|
@@ -7,6 +7,7 @@ import { Storage } from '@devbro/neko-storage';
|
|
|
7
7
|
import { Mailer } from '@devbro/neko-mailer';
|
|
8
8
|
import { HttpServer } from '@devbro/neko-http';
|
|
9
9
|
import { Logger } from '@devbro/neko-logger';
|
|
10
|
+
import { QueueConnection } from '@devbro/neko-queue';
|
|
10
11
|
|
|
11
12
|
declare const router: (label?: string, ...args: any[]) => Router;
|
|
12
13
|
declare const scheduler: (label?: string, ...args: any[]) => Scheduler;
|
|
@@ -16,5 +17,6 @@ declare const cli: (label?: string, ...args: any[]) => Cli<clipanion.BaseContext
|
|
|
16
17
|
declare const httpServer: (label?: string, ...args: any[]) => HttpServer;
|
|
17
18
|
declare const logger: (label?: string, ...args: any[]) => Logger;
|
|
18
19
|
declare const mailer: (label?: string, ...args: any[]) => Mailer;
|
|
20
|
+
declare const queue: (label?: string, ...args: any[]) => Promise<QueueConnection<any>>;
|
|
19
21
|
|
|
20
|
-
export { cli, db, httpServer, logger, mailer, router, scheduler, storage };
|
|
22
|
+
export { cli, db, httpServer, logger, mailer, queue, router, scheduler, storage };
|