crudora 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +41 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +41 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Express } from 'express';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import http from 'http';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Base class for all Crudora models. Extend this to define your table schema,
|
|
@@ -297,20 +298,53 @@ interface CrudoraServerConfig {
|
|
|
297
298
|
* - Omit / `undefined` (default): enabled with 100 requests per minute per IP.
|
|
298
299
|
* - Pass a `RateLimitConfig` object to customise the window, limit, or key function.
|
|
299
300
|
* - Pass `false` to disable rate limiting entirely (e.g. when using an external proxy-level limiter).
|
|
301
|
+
*
|
|
302
|
+
* **Important:** This limiter is in-memory and per-process. In multi-instance deployments
|
|
303
|
+
* (load balancer, Kubernetes replicas), each instance tracks its own counter independently —
|
|
304
|
+
* the effective limit per client is `max × instanceCount`. Use a Redis-backed limiter
|
|
305
|
+
* (e.g. `rate-limiter-flexible`) and pass `rateLimit: false` to disable this one.
|
|
300
306
|
*/
|
|
301
307
|
rateLimit?: RateLimitConfig | false;
|
|
308
|
+
/**
|
|
309
|
+
* Socket-level request timeout in milliseconds.
|
|
310
|
+
* Requests that exceed this duration are terminated with a `503` response.
|
|
311
|
+
* - Omit / `0` (default): no timeout.
|
|
312
|
+
* - Recommended: `30_000` (30 s) for most APIs.
|
|
313
|
+
*/
|
|
314
|
+
timeout?: number;
|
|
315
|
+
/**
|
|
316
|
+
* Built-in health check endpoint.
|
|
317
|
+
* - `true` (default): mounts `GET /health` returning `{ status: 'ok' }`.
|
|
318
|
+
* - `string`: custom path, e.g. `'/healthz'`.
|
|
319
|
+
* - `false`: disable entirely.
|
|
320
|
+
*/
|
|
321
|
+
healthCheck?: boolean | string;
|
|
302
322
|
}
|
|
303
323
|
declare class CrudoraServer {
|
|
304
324
|
private app;
|
|
305
325
|
private crudora;
|
|
306
326
|
private config;
|
|
327
|
+
private httpServer;
|
|
307
328
|
constructor(config: CrudoraServerConfig);
|
|
308
329
|
private setupMiddleware;
|
|
309
330
|
registerModel(...modelClasses: ModelConstructor[]): this;
|
|
310
331
|
registerTable<T extends Model>(modelClass: ModelConstructor<T>, table: any): this;
|
|
311
332
|
generateRoutes(): this;
|
|
312
333
|
use(middleware: any): this;
|
|
313
|
-
|
|
334
|
+
/**
|
|
335
|
+
* Starts the HTTP server and returns the underlying `http.Server` instance.
|
|
336
|
+
* Use the returned server for graceful shutdown:
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* const httpServer = server.listen();
|
|
340
|
+
* process.on('SIGTERM', () => httpServer.close(() => process.exit(0)));
|
|
341
|
+
*/
|
|
342
|
+
listen(callback?: () => void): http.Server;
|
|
343
|
+
/**
|
|
344
|
+
* Returns the `http.Server` instance after `listen()` has been called, or `null` before.
|
|
345
|
+
* Useful when you need the server reference without calling listen again.
|
|
346
|
+
*/
|
|
347
|
+
getHttpServer(): http.Server | null;
|
|
314
348
|
getApp(): Express;
|
|
315
349
|
getCrudora(): Crudora;
|
|
316
350
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Express } from 'express';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import http from 'http';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Base class for all Crudora models. Extend this to define your table schema,
|
|
@@ -297,20 +298,53 @@ interface CrudoraServerConfig {
|
|
|
297
298
|
* - Omit / `undefined` (default): enabled with 100 requests per minute per IP.
|
|
298
299
|
* - Pass a `RateLimitConfig` object to customise the window, limit, or key function.
|
|
299
300
|
* - Pass `false` to disable rate limiting entirely (e.g. when using an external proxy-level limiter).
|
|
301
|
+
*
|
|
302
|
+
* **Important:** This limiter is in-memory and per-process. In multi-instance deployments
|
|
303
|
+
* (load balancer, Kubernetes replicas), each instance tracks its own counter independently —
|
|
304
|
+
* the effective limit per client is `max × instanceCount`. Use a Redis-backed limiter
|
|
305
|
+
* (e.g. `rate-limiter-flexible`) and pass `rateLimit: false` to disable this one.
|
|
300
306
|
*/
|
|
301
307
|
rateLimit?: RateLimitConfig | false;
|
|
308
|
+
/**
|
|
309
|
+
* Socket-level request timeout in milliseconds.
|
|
310
|
+
* Requests that exceed this duration are terminated with a `503` response.
|
|
311
|
+
* - Omit / `0` (default): no timeout.
|
|
312
|
+
* - Recommended: `30_000` (30 s) for most APIs.
|
|
313
|
+
*/
|
|
314
|
+
timeout?: number;
|
|
315
|
+
/**
|
|
316
|
+
* Built-in health check endpoint.
|
|
317
|
+
* - `true` (default): mounts `GET /health` returning `{ status: 'ok' }`.
|
|
318
|
+
* - `string`: custom path, e.g. `'/healthz'`.
|
|
319
|
+
* - `false`: disable entirely.
|
|
320
|
+
*/
|
|
321
|
+
healthCheck?: boolean | string;
|
|
302
322
|
}
|
|
303
323
|
declare class CrudoraServer {
|
|
304
324
|
private app;
|
|
305
325
|
private crudora;
|
|
306
326
|
private config;
|
|
327
|
+
private httpServer;
|
|
307
328
|
constructor(config: CrudoraServerConfig);
|
|
308
329
|
private setupMiddleware;
|
|
309
330
|
registerModel(...modelClasses: ModelConstructor[]): this;
|
|
310
331
|
registerTable<T extends Model>(modelClass: ModelConstructor<T>, table: any): this;
|
|
311
332
|
generateRoutes(): this;
|
|
312
333
|
use(middleware: any): this;
|
|
313
|
-
|
|
334
|
+
/**
|
|
335
|
+
* Starts the HTTP server and returns the underlying `http.Server` instance.
|
|
336
|
+
* Use the returned server for graceful shutdown:
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* const httpServer = server.listen();
|
|
340
|
+
* process.on('SIGTERM', () => httpServer.close(() => process.exit(0)));
|
|
341
|
+
*/
|
|
342
|
+
listen(callback?: () => void): http.Server;
|
|
343
|
+
/**
|
|
344
|
+
* Returns the `http.Server` instance after `listen()` has been called, or `null` before.
|
|
345
|
+
* Useful when you need the server reference without calling listen again.
|
|
346
|
+
*/
|
|
347
|
+
getHttpServer(): http.Server | null;
|
|
314
348
|
getApp(): Express;
|
|
315
349
|
getCrudora(): Crudora;
|
|
316
350
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1446,6 +1446,7 @@ var Crudora = class {
|
|
|
1446
1446
|
};
|
|
1447
1447
|
|
|
1448
1448
|
// src/core/crudoraServer.ts
|
|
1449
|
+
import http from "http";
|
|
1449
1450
|
import express from "express";
|
|
1450
1451
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1451
1452
|
function createRateLimiter(config) {
|
|
@@ -1492,6 +1493,7 @@ function createDefaultLogger() {
|
|
|
1492
1493
|
}
|
|
1493
1494
|
var CrudoraServer = class {
|
|
1494
1495
|
constructor(config) {
|
|
1496
|
+
this.httpServer = null;
|
|
1495
1497
|
const resolvedLogger = config.logger === void 0 ? createDefaultLogger() : config.logger;
|
|
1496
1498
|
const resolvedRateLimit = config.rateLimit === false ? false : {
|
|
1497
1499
|
windowMs: config.rateLimit?.windowMs ?? 6e4,
|
|
@@ -1505,6 +1507,8 @@ var CrudoraServer = class {
|
|
|
1505
1507
|
bodyParser: true,
|
|
1506
1508
|
bodyParserLimit: "100kb",
|
|
1507
1509
|
basePath: "/api",
|
|
1510
|
+
timeout: 0,
|
|
1511
|
+
healthCheck: true,
|
|
1508
1512
|
...config,
|
|
1509
1513
|
logger: resolvedLogger,
|
|
1510
1514
|
rateLimit: resolvedRateLimit
|
|
@@ -1528,6 +1532,19 @@ var CrudoraServer = class {
|
|
|
1528
1532
|
req.correlationId = randomUUID2();
|
|
1529
1533
|
next();
|
|
1530
1534
|
});
|
|
1535
|
+
if (this.config.timeout > 0) {
|
|
1536
|
+
const timeoutMs = this.config.timeout;
|
|
1537
|
+
this.app.use((_req, res, next) => {
|
|
1538
|
+
const timer = setTimeout(() => {
|
|
1539
|
+
if (!res.headersSent) {
|
|
1540
|
+
res.status(503).json({ success: false, error: { code: "TIMEOUT", message: "Request timed out" } });
|
|
1541
|
+
}
|
|
1542
|
+
}, timeoutMs);
|
|
1543
|
+
res.on("finish", () => clearTimeout(timer));
|
|
1544
|
+
res.on("close", () => clearTimeout(timer));
|
|
1545
|
+
next();
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1531
1548
|
if (this.config.rateLimit !== false) {
|
|
1532
1549
|
this.app.use(createRateLimiter(this.config.rateLimit));
|
|
1533
1550
|
}
|
|
@@ -1569,6 +1586,12 @@ var CrudoraServer = class {
|
|
|
1569
1586
|
return this;
|
|
1570
1587
|
}
|
|
1571
1588
|
generateRoutes() {
|
|
1589
|
+
if (this.config.healthCheck !== false) {
|
|
1590
|
+
const healthPath = typeof this.config.healthCheck === "string" ? this.config.healthCheck : "/health";
|
|
1591
|
+
this.app.get(healthPath, (_req, res) => {
|
|
1592
|
+
res.json({ success: true, data: { status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() } });
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1572
1595
|
this.crudora.generateRoutes(this.app, this.config.basePath);
|
|
1573
1596
|
return this;
|
|
1574
1597
|
}
|
|
@@ -1576,12 +1599,29 @@ var CrudoraServer = class {
|
|
|
1576
1599
|
this.app.use(middleware);
|
|
1577
1600
|
return this;
|
|
1578
1601
|
}
|
|
1602
|
+
/**
|
|
1603
|
+
* Starts the HTTP server and returns the underlying `http.Server` instance.
|
|
1604
|
+
* Use the returned server for graceful shutdown:
|
|
1605
|
+
*
|
|
1606
|
+
* @example
|
|
1607
|
+
* const httpServer = server.listen();
|
|
1608
|
+
* process.on('SIGTERM', () => httpServer.close(() => process.exit(0)));
|
|
1609
|
+
*/
|
|
1579
1610
|
listen(callback) {
|
|
1580
|
-
this.
|
|
1611
|
+
this.httpServer = http.createServer(this.app);
|
|
1612
|
+
this.httpServer.listen(this.config.port, () => {
|
|
1581
1613
|
console.log(`\u{1F680} Crudora server running on port ${this.config.port}`);
|
|
1582
1614
|
console.log(`\u{1F4DA} API available at http://localhost:${this.config.port}${this.config.basePath}`);
|
|
1583
1615
|
if (callback) callback();
|
|
1584
1616
|
});
|
|
1617
|
+
return this.httpServer;
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Returns the `http.Server` instance after `listen()` has been called, or `null` before.
|
|
1621
|
+
* Useful when you need the server reference without calling listen again.
|
|
1622
|
+
*/
|
|
1623
|
+
getHttpServer() {
|
|
1624
|
+
return this.httpServer;
|
|
1585
1625
|
}
|
|
1586
1626
|
getApp() {
|
|
1587
1627
|
return this.app;
|