@agendajs/postgres-backend 1.0.0 → 3.0.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/README.md +38 -0
- package/dist/PostgresBackend.d.ts +7 -1
- package/dist/PostgresBackend.js +16 -0
- package/dist/PostgresBackend.js.map +1 -1
- package/dist/PostgresJobLogger.d.ts +57 -0
- package/dist/PostgresJobLogger.js +224 -0
- package/dist/PostgresJobLogger.js.map +1 -0
- package/dist/PostgresNotificationChannel.d.ts +12 -1
- package/dist/PostgresNotificationChannel.js +77 -2
- package/dist/PostgresNotificationChannel.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -155,6 +155,44 @@ CREATE INDEX agenda_jobs_next_run_at_idx
|
|
|
155
155
|
ON agenda_jobs (next_run_at) WHERE next_run_at IS NOT NULL;
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
+
## Job Logging
|
|
159
|
+
|
|
160
|
+
PostgresBackend includes a built-in `PostgresJobLogger` that stores structured job lifecycle events in a dedicated table (`agenda_logs` by default). The logger is lightweight and only creates its table on first use.
|
|
161
|
+
|
|
162
|
+
### Automatic Usage
|
|
163
|
+
|
|
164
|
+
When you enable logging in Agenda, the backend's built-in logger is used automatically:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const agenda = new Agenda({
|
|
168
|
+
backend: new PostgresBackend({ connectionString: 'postgresql://...' }),
|
|
169
|
+
logging: true // Uses PostgresJobLogger automatically
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Standalone Usage
|
|
174
|
+
|
|
175
|
+
You can also use `PostgresJobLogger` independently — for example, to log to PostgreSQL while using a different backend for storage:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { PostgresJobLogger } from '@agendajs/postgres-backend';
|
|
179
|
+
import { Pool } from 'pg';
|
|
180
|
+
|
|
181
|
+
const logger = new PostgresJobLogger({
|
|
182
|
+
pool: new Pool({ connectionString: 'postgresql://...' }),
|
|
183
|
+
logTableName: 'agenda_logs' // Optional: table name (default: 'agenda_logs')
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Use with any backend
|
|
187
|
+
import { MongoBackend } from '@agendajs/mongo-backend';
|
|
188
|
+
const agenda = new Agenda({
|
|
189
|
+
backend: new MongoBackend({ mongo: db }),
|
|
190
|
+
logging: logger
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
See the [Agenda README](https://github.com/agenda/agenda#persistent-job-logging) for full logging documentation.
|
|
195
|
+
|
|
158
196
|
## Manual Schema Management
|
|
159
197
|
|
|
160
198
|
If you prefer to manage the schema yourself (set `ensureSchema: false`):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgendaBackend, JobRepository, NotificationChannel } from 'agenda';
|
|
1
|
+
import type { AgendaBackend, JobRepository, NotificationChannel, JobLogger } from 'agenda';
|
|
2
2
|
import type { PostgresBackendConfig } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* PostgreSQL backend for Agenda
|
|
@@ -41,6 +41,7 @@ export declare class PostgresBackend implements AgendaBackend {
|
|
|
41
41
|
readonly name = "PostgreSQL";
|
|
42
42
|
private _repository;
|
|
43
43
|
private _notificationChannel?;
|
|
44
|
+
private _logger;
|
|
44
45
|
private config;
|
|
45
46
|
private _ownsConnection;
|
|
46
47
|
constructor(config: PostgresBackendConfig);
|
|
@@ -53,6 +54,11 @@ export declare class PostgresBackend implements AgendaBackend {
|
|
|
53
54
|
* True if created from connectionString/poolConfig, false if pool was passed in.
|
|
54
55
|
*/
|
|
55
56
|
get ownsConnection(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The job logger for persistent event logging.
|
|
59
|
+
* Always available; Agenda decides whether to activate it via its `logging` config.
|
|
60
|
+
*/
|
|
61
|
+
get logger(): JobLogger;
|
|
56
62
|
/**
|
|
57
63
|
* The notification channel for real-time notifications via LISTEN/NOTIFY
|
|
58
64
|
* Returns undefined if notifications are disabled
|
package/dist/PostgresBackend.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
2
|
import { PostgresJobRepository } from './PostgresJobRepository.js';
|
|
3
|
+
import { PostgresJobLogger } from './PostgresJobLogger.js';
|
|
3
4
|
import { PostgresNotificationChannel } from './PostgresNotificationChannel.js';
|
|
4
5
|
const log = debug('agenda:postgres:backend');
|
|
5
6
|
/**
|
|
@@ -43,6 +44,7 @@ export class PostgresBackend {
|
|
|
43
44
|
name = 'PostgreSQL';
|
|
44
45
|
_repository;
|
|
45
46
|
_notificationChannel;
|
|
47
|
+
_logger;
|
|
46
48
|
config;
|
|
47
49
|
_ownsConnection;
|
|
48
50
|
constructor(config) {
|
|
@@ -60,6 +62,11 @@ export class PostgresBackend {
|
|
|
60
62
|
}
|
|
61
63
|
});
|
|
62
64
|
}
|
|
65
|
+
// Always create the logger (lightweight; only initializes on first use when Agenda activates it)
|
|
66
|
+
this._logger = new PostgresJobLogger({
|
|
67
|
+
tableName: config.logTableName,
|
|
68
|
+
ensureSchema: config.ensureSchema
|
|
69
|
+
});
|
|
63
70
|
log('PostgresBackend created with config: %O', {
|
|
64
71
|
tableName: config.tableName || 'agenda_jobs',
|
|
65
72
|
channelName: config.channelName || 'agenda_jobs',
|
|
@@ -81,6 +88,13 @@ export class PostgresBackend {
|
|
|
81
88
|
get ownsConnection() {
|
|
82
89
|
return this._ownsConnection;
|
|
83
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* The job logger for persistent event logging.
|
|
93
|
+
* Always available; Agenda decides whether to activate it via its `logging` config.
|
|
94
|
+
*/
|
|
95
|
+
get logger() {
|
|
96
|
+
return this._logger;
|
|
97
|
+
}
|
|
84
98
|
/**
|
|
85
99
|
* The notification channel for real-time notifications via LISTEN/NOTIFY
|
|
86
100
|
* Returns undefined if notifications are disabled
|
|
@@ -103,6 +117,8 @@ export class PostgresBackend {
|
|
|
103
117
|
if (this._notificationChannel) {
|
|
104
118
|
this._notificationChannel.setPool(this._repository.getPool());
|
|
105
119
|
}
|
|
120
|
+
// Initialize the job logger with the shared pool
|
|
121
|
+
await this._logger.setPool(this._repository.getPool());
|
|
106
122
|
// Note: notification channel is connected by Agenda.start()
|
|
107
123
|
// when it's needed, so we don't connect it here
|
|
108
124
|
log('PostgresBackend connected');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostgresBackend.js","sourceRoot":"","sources":["../src/PostgresBackend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAG/E,MAAM,GAAG,GAAG,KAAK,CAAC,yBAAyB,CAAC,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,OAAO,eAAe;IAClB,IAAI,GAAG,YAAY,CAAC;IAErB,WAAW,CAAwB;IACnC,oBAAoB,CAA+B;IACnD,MAAM,CAAwB;IAC9B,eAAe,CAAU;IAEjC,YAAY,MAA6B;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,6DAA6D;QAC7D,IAAI,CAAC,eAAe,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAEpC,oBAAoB;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAErD,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAClC,IAAI,CAAC,oBAAoB,GAAG,IAAI,2BAA2B,CAAC;gBAC3D,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,SAAS,EAAE;oBACV,OAAO,EAAE,IAAI;iBACb;aACD,CAAC,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,yCAAyC,EAAE;YAC9C,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,aAAa;YAC5C,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,aAAa;YAChD,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;YACzC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,IAAI,KAAK;YAC1D,cAAc,EAAE,IAAI,CAAC,eAAe;SACpC,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,IAAI,cAAc;QACjB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,IAAI,mBAAmB;QACtB,OAAO,IAAI,CAAC,oBAAoB,CAAC;IAClC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO;QACZ,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAElC,qDAAqD;QACrD,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAEjC,wDAAwD;QACxD,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,4DAA4D;QAC5D,gDAAgD;QAEhD,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAClC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU;QACf,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAErC,wDAAwD;QACxD,mDAAmD;QACnD,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAEpC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IACrC,CAAC;CACD"}
|
|
1
|
+
{"version":3,"file":"PostgresBackend.js","sourceRoot":"","sources":["../src/PostgresBackend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Pool } from 'pg';
|
|
2
|
+
import type { JobLogger, JobLogEntry, JobLogQuery, JobLogQueryResult } from 'agenda';
|
|
3
|
+
/**
|
|
4
|
+
* SQL schema for the job logs table.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getCreateLogsTableSQL(tableName: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* SQL indexes for the job logs table.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getCreateLogsIndexesSQL(tableName: string): string[];
|
|
11
|
+
/**
|
|
12
|
+
* PostgreSQL implementation of JobLogger.
|
|
13
|
+
* Stores job lifecycle events in a dedicated PostgreSQL table.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Via backend (automatic connection sharing):
|
|
18
|
+
* import { PostgresBackend } from '@agendajs/postgres-backend';
|
|
19
|
+
*
|
|
20
|
+
* const backend = new PostgresBackend({
|
|
21
|
+
* connectionString: 'postgresql://...',
|
|
22
|
+
* logging: true // enables PostgresJobLogger with 'agenda_logs' table
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Standalone (e.g., log to Postgres while using Mongo for storage):
|
|
26
|
+
* import { PostgresJobLogger } from '@agendajs/postgres-backend';
|
|
27
|
+
* import { Pool } from 'pg';
|
|
28
|
+
*
|
|
29
|
+
* const logger = new PostgresJobLogger({ pool: new Pool({ connectionString: '...' }) });
|
|
30
|
+
* const agenda = new Agenda({
|
|
31
|
+
* backend: new MongoBackend({ address: 'mongodb://...' }),
|
|
32
|
+
* logging: logger
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class PostgresJobLogger implements JobLogger {
|
|
37
|
+
private pool;
|
|
38
|
+
private readonly tableName;
|
|
39
|
+
private readonly ensureSchema;
|
|
40
|
+
private initialized;
|
|
41
|
+
constructor(options?: {
|
|
42
|
+
pool?: Pool;
|
|
43
|
+
tableName?: string;
|
|
44
|
+
ensureSchema?: boolean;
|
|
45
|
+
} | string);
|
|
46
|
+
/**
|
|
47
|
+
* Set the pool and initialize the table schema.
|
|
48
|
+
* Called by PostgresBackend after the repository connects,
|
|
49
|
+
* or automatically when a pool is provided in the constructor.
|
|
50
|
+
*/
|
|
51
|
+
setPool(pool: Pool): Promise<void>;
|
|
52
|
+
private ensureInitialized;
|
|
53
|
+
log(entry: Omit<JobLogEntry, '_id'>): Promise<void>;
|
|
54
|
+
getLogs(query?: JobLogQuery): Promise<JobLogQueryResult>;
|
|
55
|
+
clearLogs(query?: JobLogQuery): Promise<number>;
|
|
56
|
+
private buildWhere;
|
|
57
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
const log = debug('agenda:postgres:logger');
|
|
3
|
+
/**
|
|
4
|
+
* SQL schema for the job logs table.
|
|
5
|
+
*/
|
|
6
|
+
export function getCreateLogsTableSQL(tableName) {
|
|
7
|
+
return `
|
|
8
|
+
CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
9
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
10
|
+
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
11
|
+
level VARCHAR(10) NOT NULL,
|
|
12
|
+
event VARCHAR(30) NOT NULL,
|
|
13
|
+
job_id VARCHAR(255),
|
|
14
|
+
job_name VARCHAR(255) NOT NULL,
|
|
15
|
+
message TEXT NOT NULL,
|
|
16
|
+
duration INTEGER,
|
|
17
|
+
error TEXT,
|
|
18
|
+
fail_count INTEGER,
|
|
19
|
+
retry_delay INTEGER,
|
|
20
|
+
retry_attempt INTEGER,
|
|
21
|
+
agenda_name VARCHAR(255),
|
|
22
|
+
meta JSONB
|
|
23
|
+
);
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* SQL indexes for the job logs table.
|
|
28
|
+
*/
|
|
29
|
+
export function getCreateLogsIndexesSQL(tableName) {
|
|
30
|
+
return [
|
|
31
|
+
`CREATE INDEX IF NOT EXISTS "${tableName}_timestamp_idx"
|
|
32
|
+
ON "${tableName}" (timestamp DESC)`,
|
|
33
|
+
`CREATE INDEX IF NOT EXISTS "${tableName}_job_id_idx"
|
|
34
|
+
ON "${tableName}" (job_id, timestamp DESC)`,
|
|
35
|
+
`CREATE INDEX IF NOT EXISTS "${tableName}_job_name_idx"
|
|
36
|
+
ON "${tableName}" (job_name, timestamp DESC)`
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* PostgreSQL implementation of JobLogger.
|
|
41
|
+
* Stores job lifecycle events in a dedicated PostgreSQL table.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* // Via backend (automatic connection sharing):
|
|
46
|
+
* import { PostgresBackend } from '@agendajs/postgres-backend';
|
|
47
|
+
*
|
|
48
|
+
* const backend = new PostgresBackend({
|
|
49
|
+
* connectionString: 'postgresql://...',
|
|
50
|
+
* logging: true // enables PostgresJobLogger with 'agenda_logs' table
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* // Standalone (e.g., log to Postgres while using Mongo for storage):
|
|
54
|
+
* import { PostgresJobLogger } from '@agendajs/postgres-backend';
|
|
55
|
+
* import { Pool } from 'pg';
|
|
56
|
+
*
|
|
57
|
+
* const logger = new PostgresJobLogger({ pool: new Pool({ connectionString: '...' }) });
|
|
58
|
+
* const agenda = new Agenda({
|
|
59
|
+
* backend: new MongoBackend({ address: 'mongodb://...' }),
|
|
60
|
+
* logging: logger
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export class PostgresJobLogger {
|
|
65
|
+
pool;
|
|
66
|
+
tableName;
|
|
67
|
+
ensureSchema;
|
|
68
|
+
initialized = false;
|
|
69
|
+
constructor(options) {
|
|
70
|
+
if (typeof options === 'string') {
|
|
71
|
+
// Legacy: constructor(tableName)
|
|
72
|
+
this.tableName = options;
|
|
73
|
+
this.ensureSchema = true;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.tableName = options?.tableName ?? 'agenda_logs';
|
|
77
|
+
this.ensureSchema = options?.ensureSchema ?? true;
|
|
78
|
+
if (options?.pool) {
|
|
79
|
+
this.pool = options.pool;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Set the pool and initialize the table schema.
|
|
85
|
+
* Called by PostgresBackend after the repository connects,
|
|
86
|
+
* or automatically when a pool is provided in the constructor.
|
|
87
|
+
*/
|
|
88
|
+
async setPool(pool) {
|
|
89
|
+
this.pool = pool;
|
|
90
|
+
await this.ensureInitialized();
|
|
91
|
+
}
|
|
92
|
+
async ensureInitialized() {
|
|
93
|
+
if (this.initialized || !this.pool || !this.ensureSchema)
|
|
94
|
+
return;
|
|
95
|
+
this.initialized = true;
|
|
96
|
+
log('creating schema for %s table', this.tableName);
|
|
97
|
+
const client = await this.pool.connect();
|
|
98
|
+
try {
|
|
99
|
+
await client.query(getCreateLogsTableSQL(this.tableName));
|
|
100
|
+
for (const sql of getCreateLogsIndexesSQL(this.tableName)) {
|
|
101
|
+
await client.query(sql);
|
|
102
|
+
}
|
|
103
|
+
log('schema created for %s table', this.tableName);
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
client.release();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async log(entry) {
|
|
110
|
+
if (!this.pool) {
|
|
111
|
+
log('pool not initialized, skipping log entry');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await this.ensureInitialized();
|
|
115
|
+
await this.pool.query(`INSERT INTO "${this.tableName}"
|
|
116
|
+
(timestamp, level, event, job_id, job_name, message, duration, error, fail_count, retry_delay, retry_attempt, agenda_name, meta)
|
|
117
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`, [
|
|
118
|
+
entry.timestamp,
|
|
119
|
+
entry.level,
|
|
120
|
+
entry.event,
|
|
121
|
+
entry.jobId ?? null,
|
|
122
|
+
entry.jobName,
|
|
123
|
+
entry.message,
|
|
124
|
+
entry.duration ?? null,
|
|
125
|
+
entry.error ?? null,
|
|
126
|
+
entry.failCount ?? null,
|
|
127
|
+
entry.retryDelay ?? null,
|
|
128
|
+
entry.retryAttempt ?? null,
|
|
129
|
+
entry.agendaName ?? null,
|
|
130
|
+
entry.meta ? JSON.stringify(entry.meta) : null
|
|
131
|
+
]);
|
|
132
|
+
}
|
|
133
|
+
async getLogs(query) {
|
|
134
|
+
if (!this.pool) {
|
|
135
|
+
return { entries: [], total: 0 };
|
|
136
|
+
}
|
|
137
|
+
const { where, params } = this.buildWhere(query);
|
|
138
|
+
const sort = query?.sort === 'asc' ? 'ASC' : 'DESC';
|
|
139
|
+
const limit = query?.limit ?? 50;
|
|
140
|
+
const offset = query?.offset ?? 0;
|
|
141
|
+
const entriesQuery = `
|
|
142
|
+
SELECT * FROM "${this.tableName}"
|
|
143
|
+
${where}
|
|
144
|
+
ORDER BY timestamp ${sort}
|
|
145
|
+
LIMIT $${params.length + 1} OFFSET $${params.length + 2}
|
|
146
|
+
`;
|
|
147
|
+
const countQuery = `SELECT COUNT(*)::int as total FROM "${this.tableName}" ${where}`;
|
|
148
|
+
const [entriesResult, countResult] = await Promise.all([
|
|
149
|
+
this.pool.query(entriesQuery, [...params, limit, offset]),
|
|
150
|
+
this.pool.query(countQuery, params)
|
|
151
|
+
]);
|
|
152
|
+
const entries = entriesResult.rows.map(row => ({
|
|
153
|
+
_id: row.id,
|
|
154
|
+
timestamp: row.timestamp,
|
|
155
|
+
level: row.level,
|
|
156
|
+
event: row.event,
|
|
157
|
+
jobId: row.job_id ?? undefined,
|
|
158
|
+
jobName: row.job_name,
|
|
159
|
+
message: row.message,
|
|
160
|
+
duration: row.duration ?? undefined,
|
|
161
|
+
error: row.error ?? undefined,
|
|
162
|
+
failCount: row.fail_count ?? undefined,
|
|
163
|
+
retryDelay: row.retry_delay ?? undefined,
|
|
164
|
+
retryAttempt: row.retry_attempt ?? undefined,
|
|
165
|
+
agendaName: row.agenda_name ?? undefined,
|
|
166
|
+
meta: row.meta ?? undefined
|
|
167
|
+
}));
|
|
168
|
+
return { entries, total: countResult.rows[0].total };
|
|
169
|
+
}
|
|
170
|
+
async clearLogs(query) {
|
|
171
|
+
if (!this.pool) {
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
const { where, params } = this.buildWhere(query);
|
|
175
|
+
const result = await this.pool.query(`DELETE FROM "${this.tableName}" ${where}`, params);
|
|
176
|
+
return result.rowCount ?? 0;
|
|
177
|
+
}
|
|
178
|
+
buildWhere(query) {
|
|
179
|
+
if (!query)
|
|
180
|
+
return { where: '', params: [] };
|
|
181
|
+
const conditions = [];
|
|
182
|
+
const params = [];
|
|
183
|
+
let paramIndex = 1;
|
|
184
|
+
if (query.jobId) {
|
|
185
|
+
conditions.push(`job_id = $${paramIndex++}`);
|
|
186
|
+
params.push(query.jobId);
|
|
187
|
+
}
|
|
188
|
+
if (query.jobName) {
|
|
189
|
+
conditions.push(`job_name = $${paramIndex++}`);
|
|
190
|
+
params.push(query.jobName);
|
|
191
|
+
}
|
|
192
|
+
if (query.level) {
|
|
193
|
+
if (Array.isArray(query.level)) {
|
|
194
|
+
conditions.push(`level = ANY($${paramIndex++})`);
|
|
195
|
+
params.push(query.level);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
conditions.push(`level = $${paramIndex++}`);
|
|
199
|
+
params.push(query.level);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (query.event) {
|
|
203
|
+
if (Array.isArray(query.event)) {
|
|
204
|
+
conditions.push(`event = ANY($${paramIndex++})`);
|
|
205
|
+
params.push(query.event);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
conditions.push(`event = $${paramIndex++}`);
|
|
209
|
+
params.push(query.event);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (query.from) {
|
|
213
|
+
conditions.push(`timestamp >= $${paramIndex++}`);
|
|
214
|
+
params.push(query.from);
|
|
215
|
+
}
|
|
216
|
+
if (query.to) {
|
|
217
|
+
conditions.push(`timestamp <= $${paramIndex++}`);
|
|
218
|
+
params.push(query.to);
|
|
219
|
+
}
|
|
220
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
221
|
+
return { where, params };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=PostgresJobLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresJobLogger.js","sourceRoot":"","sources":["../src/PostgresJobLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Pool } from 'pg';
|
|
2
|
-
import type { JobNotification, NotificationChannelConfig } from 'agenda';
|
|
2
|
+
import type { JobNotification, NotificationChannelConfig, JobStateNotification } from 'agenda';
|
|
3
3
|
import { BaseNotificationChannel } from 'agenda';
|
|
4
4
|
/**
|
|
5
5
|
* Configuration for PostgresNotificationChannel
|
|
@@ -21,6 +21,8 @@ export declare class PostgresNotificationChannel extends BaseNotificationChannel
|
|
|
21
21
|
private ownPool;
|
|
22
22
|
private connectionString?;
|
|
23
23
|
private listenClient?;
|
|
24
|
+
/** State channel name (derived from main channel name) */
|
|
25
|
+
private get stateChannelName();
|
|
24
26
|
constructor(config?: PostgresNotificationChannelConfig);
|
|
25
27
|
/**
|
|
26
28
|
* Set the pool (used when created by PostgresBackend)
|
|
@@ -30,12 +32,21 @@ export declare class PostgresNotificationChannel extends BaseNotificationChannel
|
|
|
30
32
|
private handleConnectionLoss;
|
|
31
33
|
disconnect(): Promise<void>;
|
|
32
34
|
publish(notification: JobNotification): Promise<void>;
|
|
35
|
+
publishState(notification: JobStateNotification): Promise<void>;
|
|
33
36
|
/**
|
|
34
37
|
* Serialize notification to JSON string for NOTIFY payload
|
|
35
38
|
*/
|
|
36
39
|
private serializeNotification;
|
|
40
|
+
/**
|
|
41
|
+
* Serialize state notification to JSON string for NOTIFY payload
|
|
42
|
+
*/
|
|
43
|
+
private serializeStateNotification;
|
|
37
44
|
/**
|
|
38
45
|
* Parse notification from JSON string received via LISTEN
|
|
39
46
|
*/
|
|
40
47
|
private parseNotification;
|
|
48
|
+
/**
|
|
49
|
+
* Parse state notification from JSON string received via LISTEN
|
|
50
|
+
*/
|
|
51
|
+
private parseStateNotification;
|
|
41
52
|
}
|
|
@@ -13,6 +13,10 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
13
13
|
ownPool = false;
|
|
14
14
|
connectionString;
|
|
15
15
|
listenClient;
|
|
16
|
+
/** State channel name (derived from main channel name) */
|
|
17
|
+
get stateChannelName() {
|
|
18
|
+
return `${this.config.channelName}:state`;
|
|
19
|
+
}
|
|
16
20
|
constructor(config = {}) {
|
|
17
21
|
super(config);
|
|
18
22
|
if (config.pool) {
|
|
@@ -63,6 +67,19 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
63
67
|
this.emit('error', error);
|
|
64
68
|
}
|
|
65
69
|
}
|
|
70
|
+
else if (msg.channel === this.stateChannelName && msg.payload) {
|
|
71
|
+
try {
|
|
72
|
+
const notification = this.parseStateNotification(msg.payload);
|
|
73
|
+
log('received state notification: %O', notification);
|
|
74
|
+
this.notifyStateHandlers(notification).catch(err => {
|
|
75
|
+
this.emit('error', err);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
log('error parsing state notification: %O', error);
|
|
80
|
+
this.emit('error', error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
66
83
|
});
|
|
67
84
|
// Handle connection errors
|
|
68
85
|
this.listenClient.on('error', error => {
|
|
@@ -73,9 +90,10 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
73
90
|
this.handleConnectionLoss();
|
|
74
91
|
}
|
|
75
92
|
});
|
|
76
|
-
// Start listening
|
|
93
|
+
// Start listening to both channels
|
|
77
94
|
await this.listenClient.query(`LISTEN "${this.config.channelName}"`);
|
|
78
|
-
|
|
95
|
+
await this.listenClient.query(`LISTEN "${this.stateChannelName}"`);
|
|
96
|
+
log('listening on channels: %s, %s', this.config.channelName, this.stateChannelName);
|
|
79
97
|
this.setState('connected');
|
|
80
98
|
}
|
|
81
99
|
catch (error) {
|
|
@@ -105,6 +123,7 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
105
123
|
if (this.listenClient) {
|
|
106
124
|
try {
|
|
107
125
|
await this.listenClient.query(`UNLISTEN "${this.config.channelName}"`);
|
|
126
|
+
await this.listenClient.query(`UNLISTEN "${this.stateChannelName}"`);
|
|
108
127
|
}
|
|
109
128
|
catch {
|
|
110
129
|
// Ignore UNLISTEN errors (connection might be dead)
|
|
@@ -123,6 +142,7 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
123
142
|
this.pool = undefined;
|
|
124
143
|
}
|
|
125
144
|
this.handlers.clear();
|
|
145
|
+
this.stateHandlers.clear();
|
|
126
146
|
this.setState('disconnected');
|
|
127
147
|
}
|
|
128
148
|
async publish(notification) {
|
|
@@ -139,6 +159,20 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
139
159
|
const escapedPayload = payload.replace(/'/g, "''");
|
|
140
160
|
await this.pool.query(`NOTIFY "${this.config.channelName}", '${escapedPayload}'`);
|
|
141
161
|
}
|
|
162
|
+
async publishState(notification) {
|
|
163
|
+
if (this._state !== 'connected') {
|
|
164
|
+
throw new Error('Cannot publish state: channel not connected');
|
|
165
|
+
}
|
|
166
|
+
if (!this.pool) {
|
|
167
|
+
throw new Error('Cannot publish state: no pool available');
|
|
168
|
+
}
|
|
169
|
+
const payload = this.serializeStateNotification(notification);
|
|
170
|
+
log('publishing state notification: %s', payload);
|
|
171
|
+
// NOTIFY doesn't support parameterized queries, so we must escape the payload
|
|
172
|
+
// PostgreSQL escapes single quotes by doubling them
|
|
173
|
+
const escapedPayload = payload.replace(/'/g, "''");
|
|
174
|
+
await this.pool.query(`NOTIFY "${this.stateChannelName}", '${escapedPayload}'`);
|
|
175
|
+
}
|
|
142
176
|
/**
|
|
143
177
|
* Serialize notification to JSON string for NOTIFY payload
|
|
144
178
|
*/
|
|
@@ -152,6 +186,26 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
152
186
|
source: notification.source
|
|
153
187
|
});
|
|
154
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Serialize state notification to JSON string for NOTIFY payload
|
|
191
|
+
*/
|
|
192
|
+
serializeStateNotification(notification) {
|
|
193
|
+
return JSON.stringify({
|
|
194
|
+
type: notification.type,
|
|
195
|
+
jobId: notification.jobId,
|
|
196
|
+
jobName: notification.jobName,
|
|
197
|
+
timestamp: notification.timestamp.toISOString(),
|
|
198
|
+
source: notification.source,
|
|
199
|
+
progress: notification.progress,
|
|
200
|
+
error: notification.error,
|
|
201
|
+
failCount: notification.failCount,
|
|
202
|
+
retryAt: notification.retryAt?.toISOString(),
|
|
203
|
+
retryAttempt: notification.retryAttempt,
|
|
204
|
+
duration: notification.duration,
|
|
205
|
+
lastRunAt: notification.lastRunAt?.toISOString(),
|
|
206
|
+
lastFinishedAt: notification.lastFinishedAt?.toISOString()
|
|
207
|
+
});
|
|
208
|
+
}
|
|
155
209
|
/**
|
|
156
210
|
* Parse notification from JSON string received via LISTEN
|
|
157
211
|
*/
|
|
@@ -166,5 +220,26 @@ export class PostgresNotificationChannel extends BaseNotificationChannel {
|
|
|
166
220
|
source: data.source
|
|
167
221
|
};
|
|
168
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Parse state notification from JSON string received via LISTEN
|
|
225
|
+
*/
|
|
226
|
+
parseStateNotification(payload) {
|
|
227
|
+
const data = JSON.parse(payload);
|
|
228
|
+
return {
|
|
229
|
+
type: data.type,
|
|
230
|
+
jobId: toJobId(data.jobId),
|
|
231
|
+
jobName: data.jobName,
|
|
232
|
+
timestamp: new Date(data.timestamp),
|
|
233
|
+
source: data.source,
|
|
234
|
+
progress: data.progress,
|
|
235
|
+
error: data.error,
|
|
236
|
+
failCount: data.failCount,
|
|
237
|
+
retryAt: data.retryAt ? new Date(data.retryAt) : undefined,
|
|
238
|
+
retryAttempt: data.retryAttempt,
|
|
239
|
+
duration: data.duration,
|
|
240
|
+
lastRunAt: data.lastRunAt ? new Date(data.lastRunAt) : undefined,
|
|
241
|
+
lastFinishedAt: data.lastFinishedAt ? new Date(data.lastFinishedAt) : undefined
|
|
242
|
+
};
|
|
243
|
+
}
|
|
169
244
|
}
|
|
170
245
|
//# sourceMappingURL=PostgresNotificationChannel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostgresNotificationChannel.js","sourceRoot":"","sources":["../src/PostgresNotificationChannel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAc,MAAM,IAAI,CAAC;AAEtC,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE1D,MAAM,GAAG,GAAG,KAAK,CAAC,8BAA8B,CAAC,CAAC;AAYlD;;;;;GAKG;AACH,MAAM,OAAO,2BAA4B,SAAQ,uBAAuB;IAC/D,IAAI,CAAQ;IACZ,OAAO,GAAY,KAAK,CAAC;IACzB,gBAAgB,CAAU;IAC1B,YAAY,CAAc;IAElC,YAAY,SAA4C,EAAE;QACzD,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACtB,CAAC;aAAM,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;YAChD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,CAAC;IACF,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAU;QACjB,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,GAAG,CAAC,iCAAiC,CAAC,CAAC;QACvC,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtB,IAAI,CAAC;YACJ,4BAA4B;YAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACzC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACrB,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;YAClF,CAAC;YAED,wCAAwC;YACxC,IAAI,CAAC,YAAY,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAE9C,8BAA8B;YAC9B,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,CAAC,EAAE;gBAC1C,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBAC5D,IAAI,CAAC;wBACJ,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBACzD,GAAG,CAAC,2BAA2B,EAAE,YAAY,CAAC,CAAC;wBAC/C,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;4BAC7C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;wBACzB,CAAC,CAAC,CAAC;oBACJ,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBAChB,GAAG,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;wBAC7C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAc,CAAC,CAAC;oBACpC,CAAC;gBACF,CAAC;YACF,CAAC,CAAC,CAAC;YAEH,2BAA2B;YAC3B,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;gBACrC,GAAG,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAE1B,8CAA8C;gBAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBACjC,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC7B,CAAC;YACF,CAAC,CAAC,CAAC;YAEH,
|
|
1
|
+
{"version":3,"file":"PostgresNotificationChannel.js","sourceRoot":"","sources":["../src/PostgresNotificationChannel.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
*/
|
|
27
27
|
export { PostgresBackend } from './PostgresBackend.js';
|
|
28
28
|
export { PostgresJobRepository } from './PostgresJobRepository.js';
|
|
29
|
+
export { PostgresJobLogger } from './PostgresJobLogger.js';
|
|
29
30
|
export { PostgresNotificationChannel } from './PostgresNotificationChannel.js';
|
|
30
31
|
export type { PostgresBackendConfig, PostgresJobRow } from './types.js';
|
|
31
32
|
export type { PostgresNotificationChannelConfig } from './PostgresNotificationChannel.js';
|
|
32
33
|
export { getCreateTableSQL, getCreateIndexesSQL, getDropTableSQL, getUpdateTimestampTriggerSQL } from './schema.js';
|
|
34
|
+
export { getCreateLogsTableSQL, getCreateLogsIndexesSQL } from './PostgresJobLogger.js';
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
*/
|
|
27
27
|
export { PostgresBackend } from './PostgresBackend.js';
|
|
28
28
|
export { PostgresJobRepository } from './PostgresJobRepository.js';
|
|
29
|
+
export { PostgresJobLogger } from './PostgresJobLogger.js';
|
|
29
30
|
export { PostgresNotificationChannel } from './PostgresNotificationChannel.js';
|
|
30
31
|
// Re-export schema utilities for advanced use cases
|
|
31
32
|
export { getCreateTableSQL, getCreateIndexesSQL, getDropTableSQL, getUpdateTimestampTriggerSQL } from './schema.js';
|
|
33
|
+
export { getCreateLogsTableSQL, getCreateLogsIndexesSQL } from './PostgresJobLogger.js';
|
|
32
34
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAK/E,oDAAoD;AACpD,OAAO,EACN,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,4BAA4B,EAC5B,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAK/E,oDAAoD;AACpD,OAAO,EACN,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,4BAA4B,EAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export interface PostgresBackendConfig {
|
|
|
23
23
|
};
|
|
24
24
|
/** Disable LISTEN/NOTIFY notification channel (default: false) */
|
|
25
25
|
disableNotifications?: boolean;
|
|
26
|
+
/** Table name for log entries (default: 'agenda_logs'). */
|
|
27
|
+
logTableName?: string;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* Internal row type matching PostgreSQL column names
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agendajs/postgres-backend",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "PostgreSQL backend for Agenda job scheduler with LISTEN/NOTIFY support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"pg": "^8.13.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"agenda": "6.
|
|
46
|
+
"agenda": "6.2.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/debug": "^4.1.12",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@vitest/coverage-v8": "^3.1.0",
|
|
53
53
|
"tsx": "^4.21.0",
|
|
54
54
|
"vitest": "^3.1.0",
|
|
55
|
-
"agenda": "6.
|
|
55
|
+
"agenda": "6.2.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsc -b",
|