@neutron-build/data 0.1.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/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/cache/index.d.ts +14 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +29 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/nucleus.d.ts +46 -0
- package/dist/cache/nucleus.d.ts.map +1 -0
- package/dist/cache/nucleus.js +50 -0
- package/dist/cache/nucleus.js.map +1 -0
- package/dist/cache/redis.d.ts +28 -0
- package/dist/cache/redis.d.ts.map +1 -0
- package/dist/cache/redis.js +52 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -0
- package/dist/db/drizzle.d.ts +23 -0
- package/dist/db/drizzle.d.ts.map +1 -0
- package/dist/db/drizzle.js +124 -0
- package/dist/db/drizzle.js.map +1 -0
- package/dist/db/index.d.ts +7 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +32 -0
- package/dist/db/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/lazy-import.d.ts +2 -0
- package/dist/internal/lazy-import.d.ts.map +1 -0
- package/dist/internal/lazy-import.js +11 -0
- package/dist/internal/lazy-import.js.map +1 -0
- package/dist/jobs/index.d.ts +6 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +5 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/queue/bullmq.d.ts +42 -0
- package/dist/queue/bullmq.d.ts.map +1 -0
- package/dist/queue/bullmq.js +80 -0
- package/dist/queue/bullmq.js.map +1 -0
- package/dist/queue/index.d.ts +21 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +43 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/ratelimit/index.d.ts +12 -0
- package/dist/ratelimit/index.d.ts.map +1 -0
- package/dist/ratelimit/index.js +28 -0
- package/dist/ratelimit/index.js.map +1 -0
- package/dist/realtime/index.d.ts +12 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +31 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/nucleus.d.ts +33 -0
- package/dist/realtime/nucleus.d.ts.map +1 -0
- package/dist/realtime/nucleus.js +62 -0
- package/dist/realtime/nucleus.js.map +1 -0
- package/dist/realtime/redis.d.ts +54 -0
- package/dist/realtime/redis.d.ts.map +1 -0
- package/dist/realtime/redis.js +138 -0
- package/dist/realtime/redis.js.map +1 -0
- package/dist/session/index.d.ts +19 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +31 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/redis.d.ts +12 -0
- package/dist/session/redis.d.ts.map +1 -0
- package/dist/session/redis.js +22 -0
- package/dist/session/redis.js.map +1 -0
- package/dist/storage/index.d.ts +17 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +13 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/nucleus.d.ts +40 -0
- package/dist/storage/nucleus.d.ts.map +1 -0
- package/dist/storage/nucleus.js +45 -0
- package/dist/storage/nucleus.js.map +1 -0
- package/dist/storage/s3.d.ts +30 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +123 -0
- package/dist/storage/s3.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-import.d.ts","sourceRoot":"","sources":["../../src/internal/lazy-import.ts"],"names":[],"mappings":"AAOA,wBAAsB,UAAU,CAAC,OAAO,EACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CASlB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const dynamicImport = new Function("specifier", "return import(specifier);");
|
|
2
|
+
export async function lazyImport(specifier, installHint) {
|
|
3
|
+
try {
|
|
4
|
+
return (await dynamicImport(specifier));
|
|
5
|
+
}
|
|
6
|
+
catch (error) {
|
|
7
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
8
|
+
throw new Error(`Missing optional dependency "${specifier}". ${installHint}. Original error: ${reason}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=lazy-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-import.js","sourceRoot":"","sources":["../../src/internal/lazy-import.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG,IAAI,QAAQ,CAChC,WAAW,EACX,2BAA2B,CACT,CAAC;AAErB,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAAiB,EACjB,WAAmB;IAEnB,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAY,CAAC;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,MAAM,IAAI,KAAK,CACb,gCAAgC,SAAS,MAAM,WAAW,qBAAqB,MAAM,EAAE,CACxF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,WAAgB,GAAG,WAAW,CAEjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAoB,MAAM,mBAAmB,CAAC;AAM1E,MAAM,UAAU,UAAU,CAAC,UAAuB,EAAE;IAClD,OAAO,OAAO,CAAC,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Job, JobHandler, QueueDriver } from "./index.js";
|
|
2
|
+
export interface BullMqQueueDriverOptions {
|
|
3
|
+
url?: string;
|
|
4
|
+
queueName?: string;
|
|
5
|
+
prefix?: string;
|
|
6
|
+
concurrency?: number;
|
|
7
|
+
}
|
|
8
|
+
interface RedisLikeConnection {
|
|
9
|
+
quit(): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface BullMqQueueLike {
|
|
12
|
+
add(name: string, payload: unknown): Promise<{
|
|
13
|
+
id: string | number | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
interface BullMqWorkerLike {
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
type BullMqWorkerCtor = new (queueName: string, processor: (job: {
|
|
21
|
+
id?: string | number;
|
|
22
|
+
name: string;
|
|
23
|
+
data: unknown;
|
|
24
|
+
timestamp?: number;
|
|
25
|
+
}) => Promise<void>, options?: Record<string, unknown>) => BullMqWorkerLike;
|
|
26
|
+
export declare class BullMqQueueDriver implements QueueDriver {
|
|
27
|
+
private readonly queue;
|
|
28
|
+
private readonly WorkerCtor;
|
|
29
|
+
private readonly workerOptions;
|
|
30
|
+
private readonly queueName;
|
|
31
|
+
private readonly connection;
|
|
32
|
+
private readonly handlers;
|
|
33
|
+
private worker;
|
|
34
|
+
constructor(queue: BullMqQueueLike, WorkerCtor: BullMqWorkerCtor, workerOptions: Record<string, unknown>, queueName: string, connection: RedisLikeConnection);
|
|
35
|
+
add<TPayload = unknown>(name: string, payload: TPayload): Promise<Job<TPayload>>;
|
|
36
|
+
process<TPayload = unknown>(name: string, handler: JobHandler<TPayload>): Promise<void>;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
private ensureWorker;
|
|
39
|
+
}
|
|
40
|
+
export declare function createBullMqQueueDriver(options?: BullMqQueueDriverOptions): Promise<BullMqQueueDriver>;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=bullmq.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bullmq.d.ts","sourceRoot":"","sources":["../../src/queue/bullmq.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG/D,MAAM,WAAW,wBAAwB;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,mBAAmB;IAC3B,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED,UAAU,eAAe;IACvB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IAClF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,gBAAgB;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,KAAK,gBAAgB,GAAG,KACtB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,CAAC,GAAG,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EAC5G,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,gBAAgB,CAAC;AAOtB,qBAAa,iBAAkB,YAAW,WAAW;IAKjD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAR7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,MAAM,CAAiC;gBAG5B,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,gBAAgB,EAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,mBAAmB;IAG5C,GAAG,CAAC,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAUhF,OAAO,CAAC,QAAQ,GAAG,OAAO,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IAKV,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,YAAY;CAsB3B;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA0C5B"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { lazyImport } from "../internal/lazy-import.js";
|
|
2
|
+
export class BullMqQueueDriver {
|
|
3
|
+
queue;
|
|
4
|
+
WorkerCtor;
|
|
5
|
+
workerOptions;
|
|
6
|
+
queueName;
|
|
7
|
+
connection;
|
|
8
|
+
handlers = new Map();
|
|
9
|
+
worker = null;
|
|
10
|
+
constructor(queue, WorkerCtor, workerOptions, queueName, connection) {
|
|
11
|
+
this.queue = queue;
|
|
12
|
+
this.WorkerCtor = WorkerCtor;
|
|
13
|
+
this.workerOptions = workerOptions;
|
|
14
|
+
this.queueName = queueName;
|
|
15
|
+
this.connection = connection;
|
|
16
|
+
}
|
|
17
|
+
async add(name, payload) {
|
|
18
|
+
const result = await this.queue.add(name, payload);
|
|
19
|
+
return {
|
|
20
|
+
id: String(result.id ?? ""),
|
|
21
|
+
name,
|
|
22
|
+
payload,
|
|
23
|
+
createdAt: Date.now(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async process(name, handler) {
|
|
27
|
+
this.handlers.set(name, handler);
|
|
28
|
+
await this.ensureWorker();
|
|
29
|
+
}
|
|
30
|
+
async close() {
|
|
31
|
+
if (this.worker) {
|
|
32
|
+
await this.worker.close();
|
|
33
|
+
this.worker = null;
|
|
34
|
+
}
|
|
35
|
+
await this.queue.close();
|
|
36
|
+
await this.connection.quit();
|
|
37
|
+
}
|
|
38
|
+
async ensureWorker() {
|
|
39
|
+
if (this.worker) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.worker = new this.WorkerCtor(this.queueName, async (job) => {
|
|
43
|
+
const handler = this.handlers.get(job.name);
|
|
44
|
+
if (!handler) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
await handler({
|
|
48
|
+
id: String(job.id ?? ""),
|
|
49
|
+
name: job.name,
|
|
50
|
+
payload: job.data,
|
|
51
|
+
createdAt: Number(job.timestamp || Date.now()),
|
|
52
|
+
});
|
|
53
|
+
}, this.workerOptions);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function createBullMqQueueDriver(options = {}) {
|
|
57
|
+
const redisModule = await lazyImport("ioredis", "Install with `pnpm add ioredis bullmq` (or npm/yarn equivalent)");
|
|
58
|
+
const bullMqModule = await lazyImport("bullmq", "Install with `pnpm add bullmq ioredis` (or npm/yarn equivalent)");
|
|
59
|
+
if (!redisModule.default || !bullMqModule.Queue || !bullMqModule.Worker) {
|
|
60
|
+
throw new Error("Failed to initialize BullMQ queue driver.");
|
|
61
|
+
}
|
|
62
|
+
const url = options.url || process.env.DRAGONFLY_URL || process.env.REDIS_URL || "redis://127.0.0.1:6379";
|
|
63
|
+
const queueName = options.queueName || "neutron";
|
|
64
|
+
const prefix = options.prefix || "neutron";
|
|
65
|
+
const concurrency = options.concurrency ?? 8;
|
|
66
|
+
const connection = new redisModule.default(url, {
|
|
67
|
+
lazyConnect: false,
|
|
68
|
+
maxRetriesPerRequest: null,
|
|
69
|
+
});
|
|
70
|
+
const queue = new bullMqModule.Queue(queueName, {
|
|
71
|
+
connection,
|
|
72
|
+
prefix,
|
|
73
|
+
});
|
|
74
|
+
return new BullMqQueueDriver(queue, bullMqModule.Worker, {
|
|
75
|
+
connection,
|
|
76
|
+
prefix,
|
|
77
|
+
concurrency,
|
|
78
|
+
}, queueName, connection);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=bullmq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bullmq.js","sourceRoot":"","sources":["../../src/queue/bullmq.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface Job<TPayload = unknown> {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
payload: TPayload;
|
|
5
|
+
createdAt: number;
|
|
6
|
+
}
|
|
7
|
+
export type JobHandler<TPayload = unknown> = (job: Job<TPayload>) => Promise<void> | void;
|
|
8
|
+
export interface QueueDriver {
|
|
9
|
+
add<TPayload = unknown>(name: string, payload: TPayload): Promise<Job<TPayload>>;
|
|
10
|
+
process<TPayload = unknown>(name: string, handler: JobHandler<TPayload>): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class InMemoryQueueDriver implements QueueDriver {
|
|
13
|
+
private idCounter;
|
|
14
|
+
private handlers;
|
|
15
|
+
private jobs;
|
|
16
|
+
private draining;
|
|
17
|
+
add<TPayload = unknown>(name: string, payload: TPayload): Promise<Job<TPayload>>;
|
|
18
|
+
process<TPayload = unknown>(name: string, handler: JobHandler<TPayload>): Promise<void>;
|
|
19
|
+
private drain;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/queue/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,CAAC,QAAQ,GAAG,OAAO;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,CAAC,QAAQ,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1F,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF;AAED,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAS;IAEnB,GAAG,CAAC,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAYhF,OAAO,CAAC,QAAQ,GAAG,OAAO,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;YAKF,KAAK;CAoBpB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class InMemoryQueueDriver {
|
|
2
|
+
idCounter = 0;
|
|
3
|
+
handlers = new Map();
|
|
4
|
+
jobs = [];
|
|
5
|
+
draining = false;
|
|
6
|
+
async add(name, payload) {
|
|
7
|
+
const job = {
|
|
8
|
+
id: String(++this.idCounter),
|
|
9
|
+
name,
|
|
10
|
+
payload,
|
|
11
|
+
createdAt: Date.now(),
|
|
12
|
+
};
|
|
13
|
+
this.jobs.push(job);
|
|
14
|
+
await this.drain();
|
|
15
|
+
return job;
|
|
16
|
+
}
|
|
17
|
+
async process(name, handler) {
|
|
18
|
+
this.handlers.set(name, handler);
|
|
19
|
+
await this.drain();
|
|
20
|
+
}
|
|
21
|
+
async drain() {
|
|
22
|
+
if (this.draining) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.draining = true;
|
|
26
|
+
try {
|
|
27
|
+
for (let i = 0; i < this.jobs.length;) {
|
|
28
|
+
const job = this.jobs[i];
|
|
29
|
+
const handler = this.handlers.get(job.name);
|
|
30
|
+
if (!handler) {
|
|
31
|
+
i += 1;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
this.jobs.splice(i, 1);
|
|
35
|
+
await handler(job);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
this.draining = false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/queue/index.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,mBAAmB;IACtB,SAAS,GAAG,CAAC,CAAC;IACd,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC9C,IAAI,GAAe,EAAE,CAAC;IACtB,QAAQ,GAAG,KAAK,CAAC;IAEzB,KAAK,CAAC,GAAG,CAAqB,IAAY,EAAE,OAAiB;QAC3D,MAAM,GAAG,GAAkB;YACzB,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;YAC5B,IAAI;YACJ,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,OAAO,CACX,IAAY,EACZ,OAA6B;QAE7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAA0B,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC;YACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAI,CAAC;gBACvC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,CAAC,IAAI,CAAC,CAAC;oBACP,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACvB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CacheClient } from "../cache/index.js";
|
|
2
|
+
export interface SlidingWindowOptions {
|
|
3
|
+
limit: number;
|
|
4
|
+
windowSec: number;
|
|
5
|
+
}
|
|
6
|
+
export interface SlidingWindowResult {
|
|
7
|
+
allowed: boolean;
|
|
8
|
+
remaining: number;
|
|
9
|
+
retryAfterSec: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function enforceSlidingWindow(cache: CacheClient, key: string, options: SlidingWindowOptions): Promise<SlidingWindowResult>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ratelimit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA6B9B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export async function enforceSlidingWindow(cache, key, options) {
|
|
2
|
+
const limit = Math.max(1, Math.floor(options.limit));
|
|
3
|
+
const windowSec = Math.max(1, Math.floor(options.windowSec));
|
|
4
|
+
const windowMs = windowSec * 1000;
|
|
5
|
+
const now = Date.now();
|
|
6
|
+
const currentWindow = Math.floor(now / windowMs);
|
|
7
|
+
const previousWindow = currentWindow - 1;
|
|
8
|
+
const currentKey = `rl:${key}:${currentWindow}`;
|
|
9
|
+
const previousKey = `rl:${key}:${previousWindow}`;
|
|
10
|
+
// Use atomic increments where available (Redis-backed clients), then compute
|
|
11
|
+
// weighted usage using current and previous windows.
|
|
12
|
+
const currentCount = await cache.incr(currentKey, windowSec * 2);
|
|
13
|
+
const previousRaw = await cache.get(previousKey);
|
|
14
|
+
const previousParsed = previousRaw ? Number.parseInt(previousRaw, 10) : 0;
|
|
15
|
+
const previousCount = Number.isFinite(previousParsed) ? previousParsed : 0;
|
|
16
|
+
const currentWindowStartedAt = currentWindow * windowMs;
|
|
17
|
+
const elapsedInWindow = now - currentWindowStartedAt;
|
|
18
|
+
const previousWindowWeight = Math.max(0, (windowMs - elapsedInWindow) / windowMs);
|
|
19
|
+
const used = currentCount + previousCount * previousWindowWeight;
|
|
20
|
+
const remaining = Math.max(0, Math.floor(limit - used));
|
|
21
|
+
const retryAfterSec = Math.max(1, Math.ceil((windowMs - elapsedInWindow) / 1000));
|
|
22
|
+
return {
|
|
23
|
+
allowed: used <= limit,
|
|
24
|
+
remaining,
|
|
25
|
+
retryAfterSec,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ratelimit/index.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAkB,EAClB,GAAW,EACX,OAA6B;IAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,aAAa,GAAG,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;IAChD,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IAElD,6EAA6E;IAC7E,qDAAqD;IACrD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;IACjE,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3E,MAAM,sBAAsB,GAAG,aAAa,GAAG,QAAQ,CAAC;IACxD,MAAM,eAAe,GAAG,GAAG,GAAG,sBAAsB,CAAC;IACrD,MAAM,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,QAAQ,GAAG,eAAe,CAAC,GAAG,QAAQ,CAAC,CAAC;IAClF,MAAM,IAAI,GAAG,YAAY,GAAG,aAAa,GAAG,oBAAoB,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;IACxD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,eAAe,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAElF,OAAO;QACL,OAAO,EAAE,IAAI,IAAI,KAAK;QACtB,SAAS;QACT,aAAa;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Subscriber = (payload: unknown) => void;
|
|
2
|
+
export interface RealtimeBus {
|
|
3
|
+
publish(channel: string, payload: unknown): Promise<void>;
|
|
4
|
+
subscribe(channel: string, subscriber: Subscriber): () => void;
|
|
5
|
+
}
|
|
6
|
+
export declare class InMemoryRealtimeBus implements RealtimeBus {
|
|
7
|
+
private channels;
|
|
8
|
+
publish(channel: string, payload: unknown): Promise<void>;
|
|
9
|
+
subscribe(channel: string, subscriber: Subscriber): () => void;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/realtime/index.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,IAAI,CAAC;CAChE;AAED,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,QAAQ,CAAsC;IAEhD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,IAAI;CAmB/D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class InMemoryRealtimeBus {
|
|
2
|
+
channels = new Map();
|
|
3
|
+
async publish(channel, payload) {
|
|
4
|
+
const subs = this.channels.get(channel);
|
|
5
|
+
if (!subs) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
for (const subscriber of subs) {
|
|
9
|
+
subscriber(payload);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
subscribe(channel, subscriber) {
|
|
13
|
+
let subs = this.channels.get(channel);
|
|
14
|
+
if (!subs) {
|
|
15
|
+
subs = new Set();
|
|
16
|
+
this.channels.set(channel, subs);
|
|
17
|
+
}
|
|
18
|
+
subs.add(subscriber);
|
|
19
|
+
return () => {
|
|
20
|
+
const existing = this.channels.get(channel);
|
|
21
|
+
if (!existing) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
existing.delete(subscriber);
|
|
25
|
+
if (existing.size === 0) {
|
|
26
|
+
this.channels.delete(channel);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/realtime/index.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,mBAAmB;IACtB,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEtD,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,OAAgB;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,KAAK,MAAM,UAAU,IAAI,IAAI,EAAE,CAAC;YAC9B,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,SAAS,CAAC,OAAe,EAAE,UAAsB;QAC/C,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,GAAG,EAAc,CAAC;YAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAErB,OAAO,GAAG,EAAE;YACV,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5B,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RealtimeBus } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* PubSub-like interface matching the subset of @neutron-build/nucleus PubSubModel.
|
|
4
|
+
*/
|
|
5
|
+
export interface NucleusPubSubLike {
|
|
6
|
+
publish(channel: string, message: string): Promise<number>;
|
|
7
|
+
}
|
|
8
|
+
export interface NucleusRealtimeBusOptions {
|
|
9
|
+
/** A PubSub model instance (from `@neutron-build/nucleus`). */
|
|
10
|
+
pubsub: NucleusPubSubLike;
|
|
11
|
+
}
|
|
12
|
+
type Subscriber = (payload: unknown) => void;
|
|
13
|
+
/**
|
|
14
|
+
* RealtimeBus implementation backed by Nucleus PubSub.
|
|
15
|
+
*
|
|
16
|
+
* Publish calls are delegated to Nucleus. Subscribe is handled in-process
|
|
17
|
+
* (the PubSub SQL interface does not support server-push subscriptions).
|
|
18
|
+
* Messages published from this process are delivered to local subscribers
|
|
19
|
+
* immediately.
|
|
20
|
+
*/
|
|
21
|
+
export declare class NucleusRealtimeBus implements RealtimeBus {
|
|
22
|
+
private readonly pubsub;
|
|
23
|
+
private readonly channels;
|
|
24
|
+
constructor(options: NucleusRealtimeBusOptions);
|
|
25
|
+
publish(channel: string, payload: unknown): Promise<void>;
|
|
26
|
+
subscribe(channel: string, subscriber: Subscriber): () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Factory function matching the pattern of `createRedisRealtimeBus`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createNucleusRealtimeBus(options: NucleusRealtimeBusOptions): NucleusRealtimeBus;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=nucleus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nucleus.d.ts","sourceRoot":"","sources":["../../src/realtime/nucleus.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,yBAAyB;IACxC,+DAA+D;IAC/D,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,KAAK,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAE7C;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;gBAEnD,OAAO,EAAE,yBAAyB;IAIxC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAa/D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,IAAI;CAiB/D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CAE/F"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// RealtimeBus backed by Nucleus PubSub model
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// When the application connects to Nucleus, this adapter bridges
|
|
6
|
+
// neutron-data's RealtimeBus interface to the PubSub model's SQL functions.
|
|
7
|
+
//
|
|
8
|
+
// Note: Nucleus PubSub.publish() is fire-and-forget over SQL. Subscription
|
|
9
|
+
// on the server side requires a persistent connection (LISTEN/NOTIFY or
|
|
10
|
+
// Nucleus's native streaming). This adapter uses polling for subscribe().
|
|
11
|
+
// For production use, prefer the Redis bus or Nucleus's native streaming API.
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
/**
|
|
14
|
+
* RealtimeBus implementation backed by Nucleus PubSub.
|
|
15
|
+
*
|
|
16
|
+
* Publish calls are delegated to Nucleus. Subscribe is handled in-process
|
|
17
|
+
* (the PubSub SQL interface does not support server-push subscriptions).
|
|
18
|
+
* Messages published from this process are delivered to local subscribers
|
|
19
|
+
* immediately.
|
|
20
|
+
*/
|
|
21
|
+
export class NucleusRealtimeBus {
|
|
22
|
+
pubsub;
|
|
23
|
+
channels = new Map();
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this.pubsub = options.pubsub;
|
|
26
|
+
}
|
|
27
|
+
async publish(channel, payload) {
|
|
28
|
+
const message = JSON.stringify(payload);
|
|
29
|
+
await this.pubsub.publish(channel, message);
|
|
30
|
+
// Also deliver to local in-process subscribers
|
|
31
|
+
const subs = this.channels.get(channel);
|
|
32
|
+
if (subs) {
|
|
33
|
+
for (const subscriber of subs) {
|
|
34
|
+
subscriber(payload);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
subscribe(channel, subscriber) {
|
|
39
|
+
let subs = this.channels.get(channel);
|
|
40
|
+
if (!subs) {
|
|
41
|
+
subs = new Set();
|
|
42
|
+
this.channels.set(channel, subs);
|
|
43
|
+
}
|
|
44
|
+
subs.add(subscriber);
|
|
45
|
+
return () => {
|
|
46
|
+
const existing = this.channels.get(channel);
|
|
47
|
+
if (!existing)
|
|
48
|
+
return;
|
|
49
|
+
existing.delete(subscriber);
|
|
50
|
+
if (existing.size === 0) {
|
|
51
|
+
this.channels.delete(channel);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Factory function matching the pattern of `createRedisRealtimeBus`.
|
|
58
|
+
*/
|
|
59
|
+
export function createNucleusRealtimeBus(options) {
|
|
60
|
+
return new NucleusRealtimeBus(options);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=nucleus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nucleus.js","sourceRoot":"","sources":["../../src/realtime/nucleus.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAC9E,EAAE;AACF,iEAAiE;AACjE,4EAA4E;AAC5E,EAAE;AACF,2EAA2E;AAC3E,wEAAwE;AACxE,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAkB9E;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IACZ,MAAM,CAAoB;IAC1B,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAE/D,YAAY,OAAkC;QAC5C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,OAAgB;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAE5C,+CAA+C;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,UAAU,IAAI,IAAI,EAAE,CAAC;gBAC9B,UAAU,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,CAAC,OAAe,EAAE,UAAsB;QAC/C,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,GAAG,EAAc,CAAC;YAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAErB,OAAO,GAAG,EAAE;YACV,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,CAAC,QAAQ;gBAAE,OAAO;YACtB,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5B,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAkC;IACzE,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { RealtimeBus } from "./index.js";
|
|
2
|
+
type Subscriber = (payload: unknown) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Minimal interface for the ioredis publisher connection.
|
|
5
|
+
* Only the methods we actually call are declared.
|
|
6
|
+
*/
|
|
7
|
+
interface RedisPublisherLike {
|
|
8
|
+
publish(channel: string, message: string): Promise<number>;
|
|
9
|
+
duplicate(): RedisSubscriberLike;
|
|
10
|
+
quit(): Promise<unknown>;
|
|
11
|
+
status: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Minimal interface for the ioredis subscriber connection.
|
|
15
|
+
* In ioredis, once `subscribe()` is called the connection enters
|
|
16
|
+
* subscriber mode and can only issue (p)subscribe/(p)unsubscribe.
|
|
17
|
+
*/
|
|
18
|
+
interface RedisSubscriberLike {
|
|
19
|
+
subscribe(...channels: string[]): Promise<unknown>;
|
|
20
|
+
unsubscribe(...channels: string[]): Promise<unknown>;
|
|
21
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
22
|
+
removeAllListeners(event?: string): this;
|
|
23
|
+
quit(): Promise<unknown>;
|
|
24
|
+
status: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RedisRealtimeBusOptions {
|
|
27
|
+
/** Redis connection URL. Falls back to DRAGONFLY_URL / REDIS_URL / localhost. */
|
|
28
|
+
url?: string;
|
|
29
|
+
/** Supply your own ioredis client to use as the publisher connection. */
|
|
30
|
+
publisherClient?: RedisPublisherLike;
|
|
31
|
+
/** Optional channel prefix, e.g. "neutron:" → publish to "neutron:my-channel". */
|
|
32
|
+
channelPrefix?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare class RedisRealtimeBus implements RealtimeBus {
|
|
35
|
+
private readonly publisher;
|
|
36
|
+
private subscriber;
|
|
37
|
+
private readonly channels;
|
|
38
|
+
private readonly channelPrefix;
|
|
39
|
+
private closed;
|
|
40
|
+
constructor(publisher: RedisPublisherLike, channelPrefix?: string);
|
|
41
|
+
publish(channel: string, payload: unknown): Promise<void>;
|
|
42
|
+
subscribe(channel: string, subscriber: Subscriber): () => void;
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Lazily create the subscriber connection by duplicating the publisher.
|
|
46
|
+
* ioredis's `duplicate()` creates a new connection with the same options,
|
|
47
|
+
* which is exactly what we need for subscriber-mode isolation.
|
|
48
|
+
*/
|
|
49
|
+
private ensureSubscriber;
|
|
50
|
+
private prefixed;
|
|
51
|
+
}
|
|
52
|
+
export declare function createRedisRealtimeBus(options?: RedisRealtimeBusOptions): Promise<RedisRealtimeBus>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=redis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/realtime/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,KAAK,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAE7C;;;GAGG;AACH,UAAU,kBAAkB;IAC1B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,SAAS,IAAI,mBAAmB,CAAC;IACjC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,UAAU,mBAAmB;IAC3B,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,WAAW,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAChE,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,MAAM,CAAS;gBAGrB,SAAS,EAAE,kBAAkB,EAC7B,aAAa,SAAK;IAOd,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,IAAI;IAiDxD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAoCxB,OAAO,CAAC,QAAQ;CAGjB;AAID,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAkC3B"}
|