@cequrebackends/cequre-ts 0.11.4

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 (60) hide show
  1. package/dist/adapters/bun/bun-cron.d.ts +20 -0
  2. package/dist/adapters/bun/bun-media.d.ts +9 -0
  3. package/dist/adapters/bun/bun-redis-cache.d.ts +33 -0
  4. package/dist/adapters/bun/bun-response.d.ts +13 -0
  5. package/dist/adapters/bun/bun-server.d.ts +6 -0
  6. package/dist/adapters/bun/bun-storage.d.ts +10 -0
  7. package/dist/adapters/bun/bun-websocket.d.ts +104 -0
  8. package/dist/adapters/bun/index.d.ts +9 -0
  9. package/dist/adapters/bun/index.js +547 -0
  10. package/dist/adapters/node/index.d.ts +9 -0
  11. package/dist/adapters/node/index.js +902 -0
  12. package/dist/adapters/node/node-cron.d.ts +20 -0
  13. package/dist/adapters/node/node-media.d.ts +9 -0
  14. package/dist/adapters/node/node-redis-cache.d.ts +32 -0
  15. package/dist/adapters/node/node-response.d.ts +13 -0
  16. package/dist/adapters/node/node-server.d.ts +6 -0
  17. package/dist/adapters/node/node-storage.d.ts +10 -0
  18. package/dist/adapters/node/node-websocket.d.ts +102 -0
  19. package/dist/index-17yswtmg.js +175 -0
  20. package/dist/index-kyvy0s1x.js +2662 -0
  21. package/dist/index-mfqj7cwr.js +165 -0
  22. package/dist/index-rf1kdn5b.js +732 -0
  23. package/dist/index.d.ts +18 -0
  24. package/dist/index.js +3152 -0
  25. package/dist/interface-map.d.ts +175 -0
  26. package/dist/shared/core/adapter.d.ts +84 -0
  27. package/dist/shared/core/base-sql-adapter.d.ts +34 -0
  28. package/dist/shared/core/cache.d.ts +8 -0
  29. package/dist/shared/core/email.d.ts +53 -0
  30. package/dist/shared/core/index.d.ts +12 -0
  31. package/dist/shared/core/index.js +47 -0
  32. package/dist/shared/core/openapi.d.ts +24 -0
  33. package/dist/shared/core/plugins.d.ts +2 -0
  34. package/dist/shared/core/request.d.ts +32 -0
  35. package/dist/shared/core/sdk.d.ts +3 -0
  36. package/dist/shared/core/stream.d.ts +24 -0
  37. package/dist/shared/core/types-generator.d.ts +0 -0
  38. package/dist/shared/core/types.d.ts +304 -0
  39. package/dist/shared/core/ulid.d.ts +5 -0
  40. package/dist/shared/core/validator.d.ts +32 -0
  41. package/dist/shared/main/access-evaluator.d.ts +13 -0
  42. package/dist/shared/main/access.d.ts +34 -0
  43. package/dist/shared/main/aot.d.ts +3 -0
  44. package/dist/shared/main/hooks.d.ts +76 -0
  45. package/dist/shared/main/population.d.ts +13 -0
  46. package/dist/shared/main/router.d.ts +112 -0
  47. package/dist/shared/main/runtime.d.ts +195 -0
  48. package/dist/shared/main/sse.d.ts +87 -0
  49. package/dist/shared/utils/crypto.d.ts +23 -0
  50. package/dist/shared/utils/durable-queue.d.ts +20 -0
  51. package/dist/shared/utils/duration.d.ts +15 -0
  52. package/dist/shared/utils/error.d.ts +52 -0
  53. package/dist/shared/utils/kv/adapters/memory.d.ts +20 -0
  54. package/dist/shared/utils/kv/adapters/sqlite.d.ts +32 -0
  55. package/dist/shared/utils/kv/index.d.ts +37 -0
  56. package/dist/shared/utils/kv/types.d.ts +38 -0
  57. package/dist/shared/utils/logger.d.ts +42 -0
  58. package/dist/shared/utils/queue-manager.d.ts +64 -0
  59. package/dist/shared/utils/url.d.ts +13 -0
  60. package/package.json +63 -0
@@ -0,0 +1,195 @@
1
+ import type { CequreAST, StorageProvider, CacheStore, CequrePlugin } from "../core/types";
2
+ import type { CequreAdapter, WhereClause } from "../core/adapter";
3
+ import { type DurableStreamStore } from "../core/stream";
4
+ import type { AccessRules, AuthUser, CequreRequestContext } from "./access";
5
+ import type { Hooks } from "./hooks";
6
+ import { CequreRouter } from "./router";
7
+ import { type CequreMonitoringAPI } from "@cequrebackends/cequre-plugin-monitoring";
8
+ import { RateLimiter } from "@cequrebackends/cequre-plugin-security";
9
+ import { type CequreMailer } from "../core/email";
10
+ import { AsyncLocalStorage } from "node:async_hooks";
11
+ import { JWTAuthenticator } from "@cequrebackends/cequre-plugin-security";
12
+ import { type CequreAuditEvent } from "@cequrebackends/cequre-plugin-security";
13
+ /**
14
+ * AsyncLocalStorage for propagating the request ID from the router
15
+ * to the runtime's audit calls without threading it through every
16
+ * method signature. Set by the router in `runRequest`, read by
17
+ * `audit()` and the CRUD wrappers.
18
+ */
19
+ export declare const requestContextStorage: AsyncLocalStorage<string | undefined>;
20
+ export interface CequreConfig {
21
+ adapter: CequreAdapter;
22
+ storageProvider?: StorageProvider;
23
+ cache?: CacheStore;
24
+ plugins?: CequrePlugin[];
25
+ email?: import("../core/types").EmailConfig;
26
+ streamStore?: DurableStreamStore;
27
+ /** KV store config for rate limiter. Defaults to memory (single-instance). Use redis for multi-instance. */
28
+ kv?: {
29
+ driver: "memory" | "sqlite" | "redis";
30
+ redis?: {
31
+ host?: string;
32
+ port?: number;
33
+ url?: string;
34
+ };
35
+ sqlite?: {
36
+ path?: string;
37
+ };
38
+ };
39
+ serverProvider?: import("../core/types").ServerProvider;
40
+ cronProvider?: import("../core/types").CronProvider;
41
+ realtimeProvider?: import("../core/types").RealtimeProvider;
42
+ }
43
+ import { CequreDurableQueue } from "../utils/durable-queue";
44
+ export declare class CequreRuntime<TCollections extends Record<string, any> = Record<string, any>> {
45
+ schema: CequreAST;
46
+ adapter: CequreAdapter;
47
+ router: CequreRouter<TCollections>;
48
+ rateLimiter: RateLimiter;
49
+ storage: StorageProvider;
50
+ cache: CacheStore;
51
+ queue: CequreDurableQueue;
52
+ plugins: CequrePlugin[];
53
+ mailer?: CequreMailer;
54
+ streamStore: DurableStreamStore;
55
+ serverProvider?: import("../core/types").ServerProvider;
56
+ cronManager: import("../core/types").CronProvider;
57
+ realtimeProvider?: import("../core/types").RealtimeProvider;
58
+ monitoring?: CequreMonitoringAPI;
59
+ auditEnabled: boolean;
60
+ private auditKeyPromise?;
61
+ private auditRetentionTimer?;
62
+ private encryptionKeyPromise?;
63
+ authEngine?: JWTAuthenticator;
64
+ readonly isTransaction: boolean;
65
+ private inFlightRequests;
66
+ private shuttingDown;
67
+ private idempotencyKV?;
68
+ lockoutKV: import("../utils/kv").CequreKV;
69
+ hooksMap: Map<string, Hooks<any, any, AuthUser>>;
70
+ private _access;
71
+ private _cacheKeyRegistry;
72
+ setAuthEngine(engine: JWTAuthenticator): void;
73
+ enableAudit(keyPromise: Promise<CryptoKey>, retentionDays?: number): void;
74
+ enableEncryption(keyPromise: Promise<CryptoKey>): void;
75
+ setMonitoring(api: CequreMonitoringAPI): void;
76
+ constructor(schema: CequreAST, config: CequreConfig);
77
+ get prefix(): string;
78
+ /** The raw prefix without version (e.g. "/api"). */
79
+ get rawPrefix(): string;
80
+ /** The current API version, or null if not configured. */
81
+ get apiVersion(): string | null;
82
+ /** Whether this version is deprecated (sends Deprecation/Sunset headers). */
83
+ get isDeprecatedVersion(): boolean;
84
+ access<K extends keyof TCollections, TAuthUser extends AuthUser = AuthUser>(collection: K, rules: AccessRules<TCollections[K], TCollections, TAuthUser>): void;
85
+ hooks<K extends keyof TCollections, TAuthUser extends AuthUser = AuthUser>(collection: K, hooks: Hooks<TCollections[K], TCollections, TAuthUser>): void;
86
+ checkLockout(collection: string, email: string, lockoutConfig?: {
87
+ maxAttempts?: number;
88
+ durationMinutes?: number;
89
+ }): Promise<{
90
+ locked: boolean;
91
+ remainingMs?: number;
92
+ }>;
93
+ recordFailedLogin(collection: string, email: string, lockoutConfig?: {
94
+ maxAttempts?: number;
95
+ durationMinutes?: number;
96
+ }): Promise<void>;
97
+ clearFailedLogins(collection: string, email: string): Promise<void>;
98
+ private resolveEnvVariables;
99
+ getContext(req: Request): Promise<CequreRequestContext>;
100
+ checkAccess(collection: string, action: keyof AccessRules, ctx: CequreRequestContext): Promise<WhereClause<any> | void>;
101
+ private runBeforeHooks;
102
+ private runAfterHooks;
103
+ private _registerCacheKey;
104
+ private initPlugins;
105
+ buildRoutes(): Promise<void>;
106
+ private auditLock;
107
+ /**
108
+ * Deletes audit log entries older than `retentionDays`.
109
+ * Called on a 24h interval by the retention timer, or can be invoked manually.
110
+ * Returns the count of deleted entries.
111
+ */
112
+ purgeOldAuditEntries(retentionDays: number): Promise<number>;
113
+ audit(event: CequreAuditEvent): Promise<void>;
114
+ private _doAudit;
115
+ /**
116
+ * Returns fields with role restrictions for a collection.
117
+ * Map: fieldName → roles that CAN access (empty array = no restriction).
118
+ */
119
+ private getRestrictedFields;
120
+ /**
121
+ * Strips fields the user's role is not allowed to access.
122
+ * Pass null userRole to strip all role-restricted fields (unauthenticated).
123
+ */
124
+ private filterFields;
125
+ /**
126
+ * Strips fields the user's role is not allowed to read.
127
+ * Pass null user to strip all role-restricted fields (unauthenticated).
128
+ */
129
+ private filterReadableFields;
130
+ /**
131
+ * Strips fields the user's role is not allowed to write.
132
+ * Returns the filtered data object.
133
+ */
134
+ private filterWritableFields;
135
+ /**
136
+ * Strips password and @omit fields from incoming data.
137
+ * These fields are never accepted in CRUD create/update —
138
+ * password only lives in auth endpoints, @omit fields are server-managed.
139
+ */
140
+ stripForbiddenFields(collection: string, data: Record<string, any>): Record<string, any>;
141
+ /**
142
+ * Returns the set of field names marked `encrypt: true` for a collection or global.
143
+ */
144
+ private getEncryptedFields;
145
+ /**
146
+ * Encrypts marked fields in a data object before writing to the adapter.
147
+ */
148
+ private encryptDataFields;
149
+ /**
150
+ * Decrypts encrypted fields in a document (or array of documents) after reading from the adapter.
151
+ */
152
+ private decryptDataFields;
153
+ secureCreate(collection: string, data: any): Promise<any>;
154
+ secureUpdate(collection: string, id: string, data: any): Promise<any>;
155
+ secureFind(collection: string, query: any): Promise<any>;
156
+ secureFindById(collection: string, id: string, query?: any): Promise<any>;
157
+ transaction<R>(callback: (trx: CequreRuntime<TCollections>) => Promise<R>): Promise<R>;
158
+ find<K extends keyof Omit<TCollections, "__populated">, D extends number = 0>(collection: K, query?: Omit<import("../core/adapter").QueryArgs<TCollections[K]>, "depth"> & {
159
+ depth?: D;
160
+ }): Promise<import("../core/adapter").PaginatedResult<D extends 0 ? TCollections[K] : "__populated" extends keyof TCollections ? (K extends keyof TCollections["__populated"] ? TCollections["__populated"][K] : TCollections[K]) : TCollections[K]>>;
161
+ findById<K extends keyof Omit<TCollections, "__populated">, D extends number = 0>(collection: K, id: string, query?: Omit<import("../core/adapter").QueryArgs<TCollections[K]>, "depth"> & {
162
+ depth?: D;
163
+ }): Promise<(D extends 0 ? TCollections[K] : "__populated" extends keyof TCollections ? (K extends keyof TCollections["__populated"] ? TCollections["__populated"][K] : TCollections[K]) : TCollections[K]) | null>;
164
+ create<K extends keyof TCollections>(collection: K, data: Partial<TCollections[K]>): Promise<TCollections[K]>;
165
+ update<K extends keyof TCollections>(collection: K, id: string, data: Partial<TCollections[K]>): Promise<TCollections[K]>;
166
+ delete<K extends keyof TCollections>(collection: K, id: string): Promise<void>;
167
+ /**
168
+ * Data Subject Erasure API (GDPR / SOC 2 Compliance)
169
+ * This is a backend-only method that permanently deletes a user record and
170
+ * attempts to cascade-delete or anonymize related PII across the system.
171
+ * It also revokes any active refresh tokens for the user.
172
+ */
173
+ eraseUser<K extends keyof TCollections>(collection: K, userId: string): Promise<void>;
174
+ count<K extends keyof TCollections>(collection: K, query?: Pick<import("../core/adapter").QueryArgs<TCollections[K]>, "where">): Promise<number>;
175
+ syncDatabaseSchema(): Promise<void>;
176
+ /**
177
+ * Schedule a recurring cron job
178
+ * @param name Unique identifier for the job
179
+ * @param schedule Cron expression (e.g. "0 * * * *")
180
+ * @param handler Async function to execute on schedule
181
+ */
182
+ cron(name: string, schedule: string, handler: (app: CequreRuntime<TCollections>) => unknown): void;
183
+ fetch(req: Request): Promise<Response>;
184
+ start(options?: {
185
+ port?: number;
186
+ drainTimeoutMs?: number;
187
+ tls?: {
188
+ cert: any;
189
+ key: any;
190
+ ca?: any;
191
+ passphrase?: string;
192
+ serverName?: string;
193
+ };
194
+ }): Promise<any>;
195
+ }
@@ -0,0 +1,87 @@
1
+ import type { AuthUser } from "./access";
2
+ type MaybePromise<T> = T | Promise<T>;
3
+ type BroadcastOptions = {
4
+ exclude?: string[];
5
+ };
6
+ type SSEConnection = {
7
+ id: string;
8
+ controller: ReadableStreamDefaultController<Uint8Array>;
9
+ channels: Set<string>;
10
+ request: Request;
11
+ user: AuthUser | null;
12
+ connectedAt: number;
13
+ };
14
+ type ConnectionInfo = {
15
+ id: string;
16
+ request: Request;
17
+ user: AuthUser | null;
18
+ };
19
+ type SubscribeInfo = ConnectionInfo & {
20
+ channel: string;
21
+ };
22
+ export declare class SSEManager {
23
+ private connections;
24
+ private channels;
25
+ private metadata;
26
+ register(connection: SSEConnection): void;
27
+ remove(id: string): void;
28
+ subscribe(id: string, channel: string): void;
29
+ unsubscribe(id: string, channel: string): void;
30
+ sendTo(id: string, payload: unknown): boolean;
31
+ broadcastToChannel(channel: string, payload: unknown, { exclude }?: BroadcastOptions): number;
32
+ broadcastAll(payload: unknown, { exclude }?: BroadcastOptions): number;
33
+ setMeta(id: string, key: string, value: unknown): void;
34
+ getMeta(id: string, key: string): unknown;
35
+ getChannelMembers(channel: string): string[];
36
+ getConnectionChannels(id: string): string[];
37
+ listChannels(): string[];
38
+ get connectionCount(): number;
39
+ get channelCount(): number;
40
+ getStats(): {
41
+ connections: number;
42
+ channels: {
43
+ [k: string]: number;
44
+ };
45
+ };
46
+ }
47
+ export declare const sseManager: SSEManager;
48
+ export declare function createBunSSERoute({ path, heartbeat, resolveUser, onConnect, onSubscribe, }?: {
49
+ path?: string;
50
+ heartbeat?: {
51
+ interval?: number;
52
+ event?: string;
53
+ data?: unknown;
54
+ } | false;
55
+ resolveUser?: (request: Request) => MaybePromise<AuthUser | null>;
56
+ onConnect?: (info: ConnectionInfo) => MaybePromise<boolean | string>;
57
+ onSubscribe?: (info: SubscribeInfo) => MaybePromise<boolean | string>;
58
+ }): (request: Request) => Promise<Response>;
59
+ export declare class CequreSSE {
60
+ static get manager(): SSEManager;
61
+ static route(options?: Parameters<typeof createBunSSERoute>[0]): (request: Request) => Promise<Response>;
62
+ static register(connection: SSEConnection): void;
63
+ static remove(id: string): void;
64
+ static subscribe(id: string, channel: string): void;
65
+ static unsubscribe(id: string, channel: string): void;
66
+ static sendTo(id: string, payload: unknown): boolean;
67
+ static broadcastToChannel(channel: string, payload: unknown, opts?: {
68
+ exclude?: string[];
69
+ }): number;
70
+ static broadcastAll(payload: unknown, opts?: {
71
+ exclude?: string[];
72
+ }): number;
73
+ static setMeta(id: string, key: string, value: unknown): void;
74
+ static getMeta(id: string, key: string): unknown;
75
+ static getChannelMembers(channel: string): string[];
76
+ static getConnectionChannels(id: string): string[];
77
+ static listChannels(): string[];
78
+ static get connectionCount(): number;
79
+ static get channelCount(): number;
80
+ static getStats(): {
81
+ connections: number;
82
+ channels: {
83
+ [k: string]: number;
84
+ };
85
+ };
86
+ }
87
+ export {};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared crypto utilities used across the Cequre runtime.
3
+ *
4
+ * Centralises SHA-256 hex hashing and constant-time string comparison
5
+ * so that security modules (auth, audit, MFA) don't each roll their own.
6
+ */
7
+ /**
8
+ * Deterministic SHA-256 hex hash of a string.
9
+ *
10
+ * ```ts
11
+ * const hash = await sha256Hex("hello");
12
+ * // "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
13
+ * ```
14
+ */
15
+ export declare function sha256Hex(input: string): Promise<string>;
16
+ /**
17
+ * Constant-time string comparison to prevent timing attacks.
18
+ *
19
+ * Returns `true` iff both strings are byte-for-byte equal.
20
+ * The comparison always iterates over the full length of `a`
21
+ * (or returns `false` immediately on length mismatch).
22
+ */
23
+ export declare function timingSafeEqual(a: string, b: string): boolean;
@@ -0,0 +1,20 @@
1
+ import type { CequreAdapter } from "../core/adapter";
2
+ import type { StorageProvider } from "../core/types";
3
+ export interface CequreJob<T = any> {
4
+ id: string;
5
+ task: string;
6
+ payload: T;
7
+ status: string;
8
+ retries: number;
9
+ error?: string;
10
+ }
11
+ export declare class CequreDurableQueue {
12
+ private adapter;
13
+ private storage?;
14
+ private intervalId?;
15
+ constructor(adapter: CequreAdapter, storage?: StorageProvider | undefined);
16
+ enqueue<T = any>(task: string, payload: T): Promise<void>;
17
+ startWorker(intervalMs?: number): void;
18
+ stopWorker(): void;
19
+ processNextBatch(): Promise<void>;
20
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Parse a shorthand duration string (e.g. `"5m"`, `"2h"`, `"1d"`) into seconds.
3
+ *
4
+ * Supported units: `s` (seconds), `m` (minutes), `h` (hours), `d` (days).
5
+ * Falls back to `86400` (1 day) for unparseable input.
6
+ *
7
+ * ```ts
8
+ * parseDuration("30s"); // 30
9
+ * parseDuration("5m"); // 300
10
+ * parseDuration("2h"); // 7200
11
+ * parseDuration("1d"); // 86400
12
+ * parseDuration("bad"); // 86400 (fallback)
13
+ * ```
14
+ */
15
+ export declare function parseDuration(duration: string): number;
@@ -0,0 +1,52 @@
1
+ export declare class CequreError extends Error {
2
+ code: string;
3
+ status: number;
4
+ constructor(message: string, code?: string, status?: number);
5
+ toJSON(): {
6
+ error: string;
7
+ message: string;
8
+ };
9
+ static BadRequest: (message?: string) => CequreError;
10
+ static Unauthorized: (message?: string) => CequreError;
11
+ static NotImplemented: (message?: string) => CequreError;
12
+ static NotConfigured: (message?: string) => CequreError;
13
+ static Forbidden: (message?: string) => CequreError;
14
+ static NotFound: (message?: string) => CequreError;
15
+ static Conflict: (message?: string) => CequreError;
16
+ static TooManyRequests: (message?: string) => CequreError;
17
+ static SubscriptionRequired: (message?: string) => CequreError;
18
+ static Internal: (message?: string) => CequreError;
19
+ }
20
+ export interface CequreErrorResponse {
21
+ code: string;
22
+ message: string;
23
+ statusCode: number;
24
+ timestamp: string;
25
+ path?: string;
26
+ }
27
+ import type { ConstraintType, ParsedConstraintError, CequreAdapter } from "../core/adapter";
28
+ /**
29
+ * Parse a database constraint error message and extract structured information.
30
+ * Relies on the provided database adapter to parse its specific errors.
31
+ */
32
+ export declare function parseConstraintError(error: unknown, adapter?: CequreAdapter): ParsedConstraintError | null;
33
+ /**
34
+ * Get a user-friendly message for a parsed constraint error.
35
+ */
36
+ export declare function getConstraintErrorMessage(parsed: ParsedConstraintError): string;
37
+ /**
38
+ * Get the appropriate HTTP status code for a constraint error type.
39
+ */
40
+ export declare function getConstraintErrorStatus(type: ConstraintType): number;
41
+ /**
42
+ * Build a structured error response body from any thrown value.
43
+ * - CequreError → uses its code/status/message directly.
44
+ * - Plain Error → exposes message only in development (hides internals in production).
45
+ * - Database constraint errors → parsed and converted to user-friendly messages.
46
+ * - Unknown → generic 500 message.
47
+ */
48
+ export declare function buildErrorResponse(error: unknown, request?: Request, adapter?: CequreAdapter): CequreErrorResponse;
49
+ /**
50
+ * Convert any thrown value to a JSON `Response` with the correct HTTP status.
51
+ */
52
+ export declare function toErrorResponse(error: unknown, request?: Request, adapter?: CequreAdapter): Response;
@@ -0,0 +1,20 @@
1
+ import type { KVAdapter } from "../types";
2
+ export declare class MemoryAdapter implements KVAdapter {
3
+ private store;
4
+ get<T = unknown>(key: string): T | null;
5
+ getMany<T = unknown>(keys: string[]): Map<string, T>;
6
+ set(key: string, value: unknown, ttl?: number): void;
7
+ setMany(entries: Array<{
8
+ key: string;
9
+ value: unknown;
10
+ ttl?: number;
11
+ }>): void;
12
+ delete(key: string): boolean;
13
+ deleteMany(keys: string[]): number;
14
+ has(key: string): boolean;
15
+ keys(prefix?: string): string[];
16
+ count(): number;
17
+ clear(): void;
18
+ cleanup(): number;
19
+ close(): void;
20
+ }
@@ -0,0 +1,32 @@
1
+ import type { KVAdapter } from "../types";
2
+ export declare class SQLiteAdapter implements KVAdapter {
3
+ private db;
4
+ private stmtGet;
5
+ private stmtSet;
6
+ private stmtDel;
7
+ private stmtHas;
8
+ private stmtKeys;
9
+ private stmtKeysPrefix;
10
+ private stmtClear;
11
+ private stmtCleanup;
12
+ private stmtCount;
13
+ constructor(options?: {
14
+ path?: string;
15
+ });
16
+ get<T = unknown>(key: string): Promise<T | null>;
17
+ getMany<T = unknown>(keys: string[]): Promise<Map<string, T>>;
18
+ set(key: string, value: unknown, ttl?: number): Promise<void>;
19
+ setMany(entries: Array<{
20
+ key: string;
21
+ value: unknown;
22
+ ttl?: number;
23
+ }>): Promise<void>;
24
+ delete(key: string): Promise<boolean>;
25
+ deleteMany(keys: string[]): Promise<number>;
26
+ has(key: string): Promise<boolean>;
27
+ keys(prefix?: string): Promise<string[]>;
28
+ count(): Promise<number>;
29
+ clear(): Promise<void>;
30
+ cleanup(): number;
31
+ close(): void;
32
+ }
@@ -0,0 +1,37 @@
1
+ import type { KVAdapter, KVOptions } from "./types";
2
+ export * from "./types";
3
+ /**
4
+ * A lightweight async key-value store facade that proxies to various drivers
5
+ * (Memory, SQLite, Redis) based on configuration.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { CequreKV } from "@cequrebackends/cequre-ts";
10
+ *
11
+ * const kv = new CequreKV({ driver: "memory" });
12
+ * await kv.set("user:1", { name: "Alice" }, 3600); // TTL 1 hour
13
+ * const user = await kv.get<{ name: string }>("user:1");
14
+ * ```
15
+ */
16
+ export declare class CequreKV implements KVAdapter {
17
+ private adapter;
18
+ private cleanupTimer;
19
+ private isCleanupNative;
20
+ constructor(options?: KVOptions);
21
+ get<T = unknown>(key: string): Promise<T | null>;
22
+ getMany<T = unknown>(keys: string[]): Promise<Map<string, T>>;
23
+ set(key: string, value: unknown, ttl?: number): Promise<void>;
24
+ setMany(entries: Array<{
25
+ key: string;
26
+ value: unknown;
27
+ ttl?: number;
28
+ }>): Promise<void>;
29
+ delete(key: string): Promise<boolean>;
30
+ deleteMany(keys: string[]): Promise<number>;
31
+ has(key: string): Promise<boolean>;
32
+ keys(prefix?: string): Promise<string[]>;
33
+ count(): Promise<number>;
34
+ clear(): Promise<void>;
35
+ cleanup(): Promise<number>;
36
+ close(): Promise<void>;
37
+ }
@@ -0,0 +1,38 @@
1
+ export type KVDriverType = "memory" | "sqlite" | "redis";
2
+ export interface KVOptions {
3
+ /** The storage driver to use. Default: "sqlite" */
4
+ driver?: KVDriverType;
5
+ /**
6
+ * Interval in milliseconds for automatic cleanup of expired entries (Memory/SQLite).
7
+ * Set to 0 to disable periodic cleanup. Default: 60_000 (1 minute)
8
+ */
9
+ cleanupInterval?: number;
10
+ /** Configuration for the SQLite driver */
11
+ sqlite?: {
12
+ /** Path to the SQLite database file. Default: "./data/cequre-kv.sqlite" */
13
+ path?: string;
14
+ };
15
+ /** Configuration for the Redis driver */
16
+ redis?: {
17
+ /** Redis connection URL. Default: "redis://localhost:6379" */
18
+ url?: string;
19
+ };
20
+ }
21
+ export interface KVAdapter {
22
+ get<T>(key: string): Promise<T | null> | T | null;
23
+ getMany<T>(keys: string[]): Promise<Map<string, T>> | Map<string, T>;
24
+ set(key: string, value: unknown, ttl?: number): Promise<void> | void;
25
+ setMany(entries: Array<{
26
+ key: string;
27
+ value: unknown;
28
+ ttl?: number;
29
+ }>): Promise<void> | void;
30
+ delete(key: string): Promise<boolean> | boolean;
31
+ deleteMany(keys: string[]): Promise<number> | number;
32
+ has(key: string): Promise<boolean> | boolean;
33
+ keys(prefix?: string): Promise<string[]> | string[];
34
+ count(): Promise<number> | number;
35
+ clear(): Promise<void> | void;
36
+ cleanup(): Promise<number> | number;
37
+ close(): Promise<void> | void;
38
+ }
@@ -0,0 +1,42 @@
1
+ import pino from "pino";
2
+ export declare const logger: pino.Logger<never, boolean>;
3
+ export interface ErrorLogEntry {
4
+ key: string;
5
+ timestamp: number;
6
+ level: string;
7
+ message: string;
8
+ error?: string;
9
+ stack?: string;
10
+ }
11
+ /**
12
+ * CequreErrorLogs - Store and retrieve error logs using CequreKV
13
+ */
14
+ export declare class CequreErrorLogs {
15
+ /**
16
+ * Get error logs from KV store.
17
+ *
18
+ * @param options.limit Max number of logs to return. Default: 100
19
+ * @param options.since Return logs after this timestamp (ms). Default: all
20
+ */
21
+ static get(options?: {
22
+ limit?: number;
23
+ since?: number;
24
+ }): Promise<ErrorLogEntry[]>;
25
+ /**
26
+ * Get error log count.
27
+ */
28
+ static count(): Promise<number>;
29
+ /**
30
+ * Clear all error logs.
31
+ */
32
+ static clear(): Promise<void>;
33
+ }
34
+ /**
35
+ * Creates a child logger scoped to a specific module / component.
36
+ *
37
+ * ```ts
38
+ * const log = createLogger("rest");
39
+ * log.info({ collection: "posts" }, "Route registered");
40
+ * ```
41
+ */
42
+ export declare function createLogger(component: string): import("pino").Logger;
@@ -0,0 +1,64 @@
1
+ import type { ConnectionOptions, JobsOptions, QueueOptions, WorkerOptions } from "bullmq";
2
+ export interface BullMQConfig {
3
+ connection: ConnectionOptions;
4
+ prefix?: string;
5
+ }
6
+ export interface QueueSystemConfig {
7
+ bullmq: BullMQConfig;
8
+ defaultQueueOptions?: Omit<QueueOptions, "connection" | "prefix">;
9
+ defaultWorkerOptions?: Omit<WorkerOptions, "connection" | "prefix">;
10
+ }
11
+ export interface QueueJob<T = unknown> {
12
+ id?: string;
13
+ name: string;
14
+ data: T;
15
+ getState?: () => Promise<string>;
16
+ }
17
+ export interface QueueEventsLike {
18
+ disconnect(): Promise<void>;
19
+ }
20
+ export interface WorkerLike {
21
+ close(): Promise<void>;
22
+ waitUntilReady?: () => Promise<void>;
23
+ }
24
+ export interface QueueLike<T = unknown> {
25
+ add(name: string, data: T, opts?: JobOptions): Promise<QueueJob<T>>;
26
+ addBulk(jobs: BulkJobDefinition<T>[]): Promise<QueueJob<T>[]>;
27
+ getRepeatableJobs(): Promise<{
28
+ name: string;
29
+ key: string;
30
+ }[]>;
31
+ removeRepeatableByKey(key: string): Promise<boolean>;
32
+ disconnect(): Promise<void>;
33
+ }
34
+ export type JobOptions = JobsOptions;
35
+ export type JobHandler<T = unknown, R = unknown> = (job: QueueJob<T>) => Promise<R> | R;
36
+ export interface QueueDefinition {
37
+ name: string;
38
+ options?: Omit<QueueOptions, "connection" | "prefix">;
39
+ }
40
+ export interface BulkJobDefinition<T = unknown> {
41
+ name: string;
42
+ data: T;
43
+ opts?: JobOptions;
44
+ }
45
+ export declare class CequreQueueManager {
46
+ private static instance;
47
+ private readonly queues;
48
+ private readonly workers;
49
+ private readonly queueEvents;
50
+ private readonly config;
51
+ private closing;
52
+ private constructor();
53
+ private getBullMQBaseOptions;
54
+ static initialize(config: QueueSystemConfig): CequreQueueManager;
55
+ static getInstance(): CequreQueueManager;
56
+ getQueue<T = unknown>(name: string): QueueLike<T>;
57
+ addJob<T = unknown>(queueName: string, jobName: string, data: T, opts?: JobOptions): Promise<QueueJob<T>>;
58
+ addBulk<T = unknown>(queueName: string, jobs: BulkJobDefinition<T>[]): Promise<QueueJob<T>[]>;
59
+ registerWorker<T = unknown>(queueName: string, handler: JobHandler<T>, options?: Omit<WorkerOptions, "connection" | "prefix">): Promise<WorkerLike>;
60
+ getQueueEvents(name: string): QueueEventsLike;
61
+ static _reset(): void;
62
+ static _resetAndClose(): Promise<void>;
63
+ close(): Promise<void>;
64
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Extract the pathname from a URL string without allocating a `URL` object.
3
+ *
4
+ * Handles full URLs (`http://host/api/users?foo=1`), path-only strings
5
+ * (`/api/users?foo=1`), and edge cases like hash fragments.
6
+ *
7
+ * ```ts
8
+ * extractPathname("http://localhost:3000/api/users/123?name=John"); // "/api/users/123"
9
+ * extractPathname("/api/users?limit=10"); // "/api/users"
10
+ * extractPathname("/"); // "/"
11
+ * ```
12
+ */
13
+ export declare function extractPathname(url: string): string;