+320
dist/index.d.mts
+320
dist/index.d.mts
···
1
+
import { AtpAgent, AtpAgentOptions } from '@atproto/api';
2
+
import { CronJob } from 'cron';
3
+
import WebSocket from 'ws';
4
+
5
+
type Cron = {
6
+
scheduleExpression: string;
7
+
callback: (() => void) | null;
8
+
timeZone: string;
9
+
};
10
+
type BotReply = {
11
+
keyword: string;
12
+
exclude?: string[];
13
+
messages: string[];
14
+
};
15
+
type Bot = {
16
+
identifier: string;
17
+
password: string;
18
+
username?: string;
19
+
service: string;
20
+
};
21
+
type ActionBot = Bot & {
22
+
action: (agent: AtpAgent) => Promise<void>;
23
+
};
24
+
type CronBot = ActionBot & {
25
+
cronJob: Cron;
26
+
};
27
+
type KeywordBot = Bot & {
28
+
replies: BotReply[];
29
+
};
30
+
31
+
type Post = {
32
+
uri: string;
33
+
cid: string;
34
+
authorDid: string;
35
+
authorHandle?: string;
36
+
text: string;
37
+
rootUri: string;
38
+
rootCid: string;
39
+
createdAt?: Date;
40
+
};
41
+
type UriCid = {
42
+
cid: string;
43
+
uri: string;
44
+
};
45
+
46
+
/**
47
+
* Represents a message received over WebSocket.
48
+
*
49
+
* - `did`: The Decentralized Identifier (DID) of the entity that created or owns the data.
50
+
* - `time_us`: A timestamp in microseconds.
51
+
* - `kind`: A string indicating the kind of message.
52
+
* - `commit`: An object containing information about a particular commit or record creation event.
53
+
* - `rev`: The revision identifier of the commit.
54
+
* - `operation`: The type of operation performed (e.g., "create", "update", etc.).
55
+
* - `collection`: The name of the collection that the record belongs to.
56
+
* - `rkey`: The record key within the collection.
57
+
* - `record`: An object describing the record itself.
58
+
* - `'$type'`: The record's type.
59
+
* - `createdAt`: A timestamp indicating when the record was created.
60
+
* - `subject`: A string associated with the record, often referencing another entity.
61
+
* - `reply`: Optional object containing `root` and `parent` references (both `UriCid`)
62
+
* if the record is a reply to another post.
63
+
* - `text`: The textual content of the record.
64
+
* - `cid`: The content identifier (CID) of the commit.
65
+
*/
66
+
type WebsocketMessage = {
67
+
did: string;
68
+
time_us: number;
69
+
kind: string;
70
+
commit: {
71
+
rev: string;
72
+
operation: string;
73
+
collection: string;
74
+
rkey: string;
75
+
record: {
76
+
'$type': string;
77
+
createdAt: string;
78
+
subject: string;
79
+
reply?: {
80
+
root: UriCid;
81
+
parent: UriCid;
82
+
};
83
+
text: string;
84
+
};
85
+
cid: string;
86
+
};
87
+
};
88
+
89
+
declare class ActionBotAgent extends AtpAgent {
90
+
opts: AtpAgentOptions;
91
+
actionBot: ActionBot;
92
+
constructor(opts: AtpAgentOptions, actionBot: ActionBot);
93
+
doAction(): Promise<void>;
94
+
}
95
+
declare const useActionBotAgent: (actionBot: ActionBot) => Promise<ActionBotAgent | null>;
96
+
97
+
declare class CronBotAgent extends AtpAgent {
98
+
opts: AtpAgentOptions;
99
+
cronBot: CronBot;
100
+
job: CronJob;
101
+
constructor(opts: AtpAgentOptions, cronBot: CronBot);
102
+
}
103
+
declare const useCronBotAgent: (cronBot: CronBot) => Promise<CronBotAgent | null>;
104
+
105
+
declare class KeywordBotAgent extends AtpAgent {
106
+
opts: AtpAgentOptions;
107
+
keywordBot: KeywordBot;
108
+
constructor(opts: AtpAgentOptions, keywordBot: KeywordBot);
109
+
likeAndReplyIfFollower(post: Post): Promise<void>;
110
+
}
111
+
declare function buildReplyToPost(root: UriCid, parent: UriCid, message: string): {
112
+
$type: "app.bsky.feed.post";
113
+
text: string;
114
+
reply: {
115
+
root: UriCid;
116
+
parent: UriCid;
117
+
};
118
+
};
119
+
declare function filterBotReplies(text: string, botReplies: BotReply[]): BotReply[];
120
+
declare const useKeywordBotAgent: (keywordBot: KeywordBot) => Promise<KeywordBotAgent | null>;
121
+
122
+
interface WebSocketClientOptions {
123
+
/** The URL of the WebSocket server to connect to. */
124
+
url: string;
125
+
/** The interval in milliseconds to wait before attempting to reconnect when the connection closes. Default is 5000ms. */
126
+
reconnectInterval?: number;
127
+
/** The interval in milliseconds for sending ping messages (heartbeats) to keep the connection alive. Default is 10000ms. */
128
+
pingInterval?: number;
129
+
}
130
+
/**
131
+
* A WebSocket client that automatically attempts to reconnect upon disconnection
132
+
* and periodically sends ping messages (heartbeats) to ensure the connection remains alive.
133
+
*
134
+
* Extend this class and override the protected `onOpen`, `onMessage`, `onError`, and `onClose` methods
135
+
* to implement custom handling of WebSocket events.
136
+
*/
137
+
declare class WebSocketClient {
138
+
private url;
139
+
private reconnectInterval;
140
+
private pingInterval;
141
+
private ws;
142
+
private pingTimeout;
143
+
/**
144
+
* Creates a new instance of `WebSocketClient`.
145
+
*
146
+
* @param options - Configuration options for the WebSocket client, including URL, reconnect interval, and ping interval.
147
+
*/
148
+
constructor(options: WebSocketClientOptions);
149
+
/**
150
+
* Initiates a WebSocket connection to the specified URL.
151
+
*
152
+
* This method sets up event listeners for `open`, `message`, `error`, and `close` events.
153
+
* When the connection opens, it starts the heartbeat mechanism.
154
+
* On close, it attempts to reconnect after a specified interval.
155
+
*/
156
+
private run;
157
+
/**
158
+
* Attempts to reconnect to the WebSocket server after the specified `reconnectInterval`.
159
+
* It clears all event listeners on the old WebSocket and initiates a new connection.
160
+
*/
161
+
private reconnect;
162
+
/**
163
+
* Starts sending periodic ping messages to the server.
164
+
*
165
+
* This function uses `setInterval` to send a ping at the configured `pingInterval`.
166
+
* If the WebSocket is not open, pings are not sent.
167
+
*/
168
+
private startHeartbeat;
169
+
/**
170
+
* Stops sending heartbeat pings by clearing the ping interval.
171
+
*/
172
+
private stopHeartbeat;
173
+
/**
174
+
* Called when the WebSocket connection is successfully opened.
175
+
*
176
+
* Override this method in a subclass to implement custom logic on connection.
177
+
*/
178
+
protected onOpen(): void;
179
+
/**
180
+
* Called when a WebSocket message is received.
181
+
*
182
+
* @param data - The data received from the WebSocket server.
183
+
*
184
+
* Override this method in a subclass to implement custom message handling.
185
+
*/
186
+
protected onMessage(data: WebSocket.Data): void;
187
+
/**
188
+
* Called when a WebSocket error occurs.
189
+
*
190
+
* @param error - The error that occurred.
191
+
*
192
+
* Override this method in a subclass to implement custom error handling.
193
+
*/
194
+
protected onError(error: Error): void;
195
+
/**
196
+
* Called when the WebSocket connection is closed.
197
+
*
198
+
* Override this method in a subclass to implement custom logic on disconnection.
199
+
*/
200
+
protected onClose(): void;
201
+
/**
202
+
* Sends data to the connected WebSocket server, if the connection is open.
203
+
*
204
+
* @param data - The data to send.
205
+
*/
206
+
send(data: any): void;
207
+
/**
208
+
* Closes the WebSocket connection gracefully.
209
+
*/
210
+
close(): void;
211
+
}
212
+
213
+
/**
214
+
* Represents a subscription to a Jetstream feed over WebSocket.
215
+
*
216
+
* This class extends `WebSocketClient` to automatically handle reconnections and heartbeats.
217
+
* It invokes a provided callback function whenever a message is received from the Jetstream server.
218
+
*/
219
+
declare class JetstreamSubscription extends WebSocketClient {
220
+
service: string;
221
+
interval: number;
222
+
private onMessageCallback?;
223
+
/**
224
+
* Creates a new `JetstreamSubscription`.
225
+
*
226
+
* @param service - The URL of the Jetstream server to connect to.
227
+
* @param interval - The interval (in milliseconds) for reconnect attempts.
228
+
* @param onMessageCallback - An optional callback function that is invoked whenever a message is received from the server.
229
+
*/
230
+
constructor(service: string, interval: number, onMessageCallback?: ((data: WebSocket.Data) => void) | undefined);
231
+
/**
232
+
* Called when the WebSocket connection is successfully opened.
233
+
* Logs a message indicating that the connection to the Jetstream server has been established.
234
+
*/
235
+
protected onOpen(): void;
236
+
/**
237
+
* Called when a WebSocket message is received.
238
+
*
239
+
* If an `onMessageCallback` was provided, it is invoked with the received data.
240
+
*
241
+
* @param data - The data received from the Jetstream server.
242
+
*/
243
+
protected onMessage(data: WebSocket.Data): void;
244
+
/**
245
+
* Called when a WebSocket error occurs.
246
+
* Logs the error message indicating that Jetstream encountered an error.
247
+
*
248
+
* @param error - The error that occurred.
249
+
*/
250
+
protected onError(error: Error): void;
251
+
/**
252
+
* Called when the WebSocket connection is closed.
253
+
* Logs a message indicating that the Jetstream connection has closed.
254
+
*/
255
+
protected onClose(): void;
256
+
}
257
+
258
+
/**
259
+
* A simple logging utility class providing static methods for various log levels.
260
+
* Each log message is prefixed with a timestamp and log level.
261
+
*/
262
+
declare class Logger {
263
+
/**
264
+
* Logs an informational message to the console.
265
+
*
266
+
* @param message - The message to be logged.
267
+
* @param context - Optional additional context (object or string) to log alongside the message.
268
+
*/
269
+
static info(message: string, context?: object | string): void;
270
+
/**
271
+
* Logs a warning message to the console.
272
+
*
273
+
* @param message - The message to be logged.
274
+
* @param context - Optional additional context (object or string) to log alongside the message.
275
+
*/
276
+
static warn(message: string, context?: object | string): void;
277
+
/**
278
+
* Logs an error message to the console.
279
+
*
280
+
* @param message - The message to be logged.
281
+
* @param context - Optional additional context (object or string) to log alongside the message.
282
+
*/
283
+
static error(message: string, context?: object | string): void;
284
+
/**
285
+
* Logs a debug message to the console.
286
+
*
287
+
* @param message - The message to be logged.
288
+
* @param context - Optional additional context (object or string) to log alongside the message.
289
+
*/
290
+
static debug(message: string, context?: object | string): void;
291
+
}
292
+
293
+
/**
294
+
* Returns the given string if it is defined; otherwise returns `undefined`.
295
+
*
296
+
* @param val - The optional string value to check.
297
+
* @returns The given string if defined, or `undefined` if `val` is falsy.
298
+
*/
299
+
declare const maybeStr: (val?: string) => string | undefined;
300
+
/**
301
+
* Parses the given string as an integer if it is defined and a valid integer; otherwise returns `undefined`.
302
+
*
303
+
* @param val - The optional string value to parse.
304
+
* @returns The parsed integer if successful, or `undefined` if the string is falsy or not a valid integer.
305
+
*/
306
+
declare const maybeInt: (val?: string) => number | undefined;
307
+
308
+
/**
309
+
* Converts a raw WebSocket message into a `FeedEntry` object, if possible.
310
+
*
311
+
* This function checks if the incoming WebSocket data is structured like a feed commit message
312
+
* with the required properties for a created post. If the data matches the expected shape,
313
+
* it extracts and returns a `FeedEntry` object. Otherwise, it returns `null`.
314
+
*
315
+
* @param data - The raw WebSocket data.
316
+
* @returns A `FeedEntry` object if the data represents a newly created post, otherwise `null`.
317
+
*/
318
+
declare function websocketToFeedEntry(data: WebSocket.Data): Post | null;
319
+
320
+
export { type ActionBot, ActionBotAgent, type Bot, type BotReply, type CronBot, CronBotAgent, JetstreamSubscription, type KeywordBot, KeywordBotAgent, Logger, type Post, type UriCid, WebSocketClient, type WebsocketMessage, buildReplyToPost, filterBotReplies, maybeInt, maybeStr, useActionBotAgent, useCronBotAgent, useKeywordBotAgent, websocketToFeedEntry };
+320
dist/index.d.ts
+320
dist/index.d.ts
···
1
+
import { AtpAgent, AtpAgentOptions } from '@atproto/api';
2
+
import { CronJob } from 'cron';
3
+
import WebSocket from 'ws';
4
+
5
+
type Cron = {
6
+
scheduleExpression: string;
7
+
callback: (() => void) | null;
8
+
timeZone: string;
9
+
};
10
+
type BotReply = {
11
+
keyword: string;
12
+
exclude?: string[];
13
+
messages: string[];
14
+
};
15
+
type Bot = {
16
+
identifier: string;
17
+
password: string;
18
+
username?: string;
19
+
service: string;
20
+
};
21
+
type ActionBot = Bot & {
22
+
action: (agent: AtpAgent) => Promise<void>;
23
+
};
24
+
type CronBot = ActionBot & {
25
+
cronJob: Cron;
26
+
};
27
+
type KeywordBot = Bot & {
28
+
replies: BotReply[];
29
+
};
30
+
31
+
type Post = {
32
+
uri: string;
33
+
cid: string;
34
+
authorDid: string;
35
+
authorHandle?: string;
36
+
text: string;
37
+
rootUri: string;
38
+
rootCid: string;
39
+
createdAt?: Date;
40
+
};
41
+
type UriCid = {
42
+
cid: string;
43
+
uri: string;
44
+
};
45
+
46
+
/**
47
+
* Represents a message received over WebSocket.
48
+
*
49
+
* - `did`: The Decentralized Identifier (DID) of the entity that created or owns the data.
50
+
* - `time_us`: A timestamp in microseconds.
51
+
* - `kind`: A string indicating the kind of message.
52
+
* - `commit`: An object containing information about a particular commit or record creation event.
53
+
* - `rev`: The revision identifier of the commit.
54
+
* - `operation`: The type of operation performed (e.g., "create", "update", etc.).
55
+
* - `collection`: The name of the collection that the record belongs to.
56
+
* - `rkey`: The record key within the collection.
57
+
* - `record`: An object describing the record itself.
58
+
* - `'$type'`: The record's type.
59
+
* - `createdAt`: A timestamp indicating when the record was created.
60
+
* - `subject`: A string associated with the record, often referencing another entity.
61
+
* - `reply`: Optional object containing `root` and `parent` references (both `UriCid`)
62
+
* if the record is a reply to another post.
63
+
* - `text`: The textual content of the record.
64
+
* - `cid`: The content identifier (CID) of the commit.
65
+
*/
66
+
type WebsocketMessage = {
67
+
did: string;
68
+
time_us: number;
69
+
kind: string;
70
+
commit: {
71
+
rev: string;
72
+
operation: string;
73
+
collection: string;
74
+
rkey: string;
75
+
record: {
76
+
'$type': string;
77
+
createdAt: string;
78
+
subject: string;
79
+
reply?: {
80
+
root: UriCid;
81
+
parent: UriCid;
82
+
};
83
+
text: string;
84
+
};
85
+
cid: string;
86
+
};
87
+
};
88
+
89
+
declare class ActionBotAgent extends AtpAgent {
90
+
opts: AtpAgentOptions;
91
+
actionBot: ActionBot;
92
+
constructor(opts: AtpAgentOptions, actionBot: ActionBot);
93
+
doAction(): Promise<void>;
94
+
}
95
+
declare const useActionBotAgent: (actionBot: ActionBot) => Promise<ActionBotAgent | null>;
96
+
97
+
declare class CronBotAgent extends AtpAgent {
98
+
opts: AtpAgentOptions;
99
+
cronBot: CronBot;
100
+
job: CronJob;
101
+
constructor(opts: AtpAgentOptions, cronBot: CronBot);
102
+
}
103
+
declare const useCronBotAgent: (cronBot: CronBot) => Promise<CronBotAgent | null>;
104
+
105
+
declare class KeywordBotAgent extends AtpAgent {
106
+
opts: AtpAgentOptions;
107
+
keywordBot: KeywordBot;
108
+
constructor(opts: AtpAgentOptions, keywordBot: KeywordBot);
109
+
likeAndReplyIfFollower(post: Post): Promise<void>;
110
+
}
111
+
declare function buildReplyToPost(root: UriCid, parent: UriCid, message: string): {
112
+
$type: "app.bsky.feed.post";
113
+
text: string;
114
+
reply: {
115
+
root: UriCid;
116
+
parent: UriCid;
117
+
};
118
+
};
119
+
declare function filterBotReplies(text: string, botReplies: BotReply[]): BotReply[];
120
+
declare const useKeywordBotAgent: (keywordBot: KeywordBot) => Promise<KeywordBotAgent | null>;
121
+
122
+
interface WebSocketClientOptions {
123
+
/** The URL of the WebSocket server to connect to. */
124
+
url: string;
125
+
/** The interval in milliseconds to wait before attempting to reconnect when the connection closes. Default is 5000ms. */
126
+
reconnectInterval?: number;
127
+
/** The interval in milliseconds for sending ping messages (heartbeats) to keep the connection alive. Default is 10000ms. */
128
+
pingInterval?: number;
129
+
}
130
+
/**
131
+
* A WebSocket client that automatically attempts to reconnect upon disconnection
132
+
* and periodically sends ping messages (heartbeats) to ensure the connection remains alive.
133
+
*
134
+
* Extend this class and override the protected `onOpen`, `onMessage`, `onError`, and `onClose` methods
135
+
* to implement custom handling of WebSocket events.
136
+
*/
137
+
declare class WebSocketClient {
138
+
private url;
139
+
private reconnectInterval;
140
+
private pingInterval;
141
+
private ws;
142
+
private pingTimeout;
143
+
/**
144
+
* Creates a new instance of `WebSocketClient`.
145
+
*
146
+
* @param options - Configuration options for the WebSocket client, including URL, reconnect interval, and ping interval.
147
+
*/
148
+
constructor(options: WebSocketClientOptions);
149
+
/**
150
+
* Initiates a WebSocket connection to the specified URL.
151
+
*
152
+
* This method sets up event listeners for `open`, `message`, `error`, and `close` events.
153
+
* When the connection opens, it starts the heartbeat mechanism.
154
+
* On close, it attempts to reconnect after a specified interval.
155
+
*/
156
+
private run;
157
+
/**
158
+
* Attempts to reconnect to the WebSocket server after the specified `reconnectInterval`.
159
+
* It clears all event listeners on the old WebSocket and initiates a new connection.
160
+
*/
161
+
private reconnect;
162
+
/**
163
+
* Starts sending periodic ping messages to the server.
164
+
*
165
+
* This function uses `setInterval` to send a ping at the configured `pingInterval`.
166
+
* If the WebSocket is not open, pings are not sent.
167
+
*/
168
+
private startHeartbeat;
169
+
/**
170
+
* Stops sending heartbeat pings by clearing the ping interval.
171
+
*/
172
+
private stopHeartbeat;
173
+
/**
174
+
* Called when the WebSocket connection is successfully opened.
175
+
*
176
+
* Override this method in a subclass to implement custom logic on connection.
177
+
*/
178
+
protected onOpen(): void;
179
+
/**
180
+
* Called when a WebSocket message is received.
181
+
*
182
+
* @param data - The data received from the WebSocket server.
183
+
*
184
+
* Override this method in a subclass to implement custom message handling.
185
+
*/
186
+
protected onMessage(data: WebSocket.Data): void;
187
+
/**
188
+
* Called when a WebSocket error occurs.
189
+
*
190
+
* @param error - The error that occurred.
191
+
*
192
+
* Override this method in a subclass to implement custom error handling.
193
+
*/
194
+
protected onError(error: Error): void;
195
+
/**
196
+
* Called when the WebSocket connection is closed.
197
+
*
198
+
* Override this method in a subclass to implement custom logic on disconnection.
199
+
*/
200
+
protected onClose(): void;
201
+
/**
202
+
* Sends data to the connected WebSocket server, if the connection is open.
203
+
*
204
+
* @param data - The data to send.
205
+
*/
206
+
send(data: any): void;
207
+
/**
208
+
* Closes the WebSocket connection gracefully.
209
+
*/
210
+
close(): void;
211
+
}
212
+
213
+
/**
214
+
* Represents a subscription to a Jetstream feed over WebSocket.
215
+
*
216
+
* This class extends `WebSocketClient` to automatically handle reconnections and heartbeats.
217
+
* It invokes a provided callback function whenever a message is received from the Jetstream server.
218
+
*/
219
+
declare class JetstreamSubscription extends WebSocketClient {
220
+
service: string;
221
+
interval: number;
222
+
private onMessageCallback?;
223
+
/**
224
+
* Creates a new `JetstreamSubscription`.
225
+
*
226
+
* @param service - The URL of the Jetstream server to connect to.
227
+
* @param interval - The interval (in milliseconds) for reconnect attempts.
228
+
* @param onMessageCallback - An optional callback function that is invoked whenever a message is received from the server.
229
+
*/
230
+
constructor(service: string, interval: number, onMessageCallback?: ((data: WebSocket.Data) => void) | undefined);
231
+
/**
232
+
* Called when the WebSocket connection is successfully opened.
233
+
* Logs a message indicating that the connection to the Jetstream server has been established.
234
+
*/
235
+
protected onOpen(): void;
236
+
/**
237
+
* Called when a WebSocket message is received.
238
+
*
239
+
* If an `onMessageCallback` was provided, it is invoked with the received data.
240
+
*
241
+
* @param data - The data received from the Jetstream server.
242
+
*/
243
+
protected onMessage(data: WebSocket.Data): void;
244
+
/**
245
+
* Called when a WebSocket error occurs.
246
+
* Logs the error message indicating that Jetstream encountered an error.
247
+
*
248
+
* @param error - The error that occurred.
249
+
*/
250
+
protected onError(error: Error): void;
251
+
/**
252
+
* Called when the WebSocket connection is closed.
253
+
* Logs a message indicating that the Jetstream connection has closed.
254
+
*/
255
+
protected onClose(): void;
256
+
}
257
+
258
+
/**
259
+
* A simple logging utility class providing static methods for various log levels.
260
+
* Each log message is prefixed with a timestamp and log level.
261
+
*/
262
+
declare class Logger {
263
+
/**
264
+
* Logs an informational message to the console.
265
+
*
266
+
* @param message - The message to be logged.
267
+
* @param context - Optional additional context (object or string) to log alongside the message.
268
+
*/
269
+
static info(message: string, context?: object | string): void;
270
+
/**
271
+
* Logs a warning message to the console.
272
+
*
273
+
* @param message - The message to be logged.
274
+
* @param context - Optional additional context (object or string) to log alongside the message.
275
+
*/
276
+
static warn(message: string, context?: object | string): void;
277
+
/**
278
+
* Logs an error message to the console.
279
+
*
280
+
* @param message - The message to be logged.
281
+
* @param context - Optional additional context (object or string) to log alongside the message.
282
+
*/
283
+
static error(message: string, context?: object | string): void;
284
+
/**
285
+
* Logs a debug message to the console.
286
+
*
287
+
* @param message - The message to be logged.
288
+
* @param context - Optional additional context (object or string) to log alongside the message.
289
+
*/
290
+
static debug(message: string, context?: object | string): void;
291
+
}
292
+
293
+
/**
294
+
* Returns the given string if it is defined; otherwise returns `undefined`.
295
+
*
296
+
* @param val - The optional string value to check.
297
+
* @returns The given string if defined, or `undefined` if `val` is falsy.
298
+
*/
299
+
declare const maybeStr: (val?: string) => string | undefined;
300
+
/**
301
+
* Parses the given string as an integer if it is defined and a valid integer; otherwise returns `undefined`.
302
+
*
303
+
* @param val - The optional string value to parse.
304
+
* @returns The parsed integer if successful, or `undefined` if the string is falsy or not a valid integer.
305
+
*/
306
+
declare const maybeInt: (val?: string) => number | undefined;
307
+
308
+
/**
309
+
* Converts a raw WebSocket message into a `FeedEntry` object, if possible.
310
+
*
311
+
* This function checks if the incoming WebSocket data is structured like a feed commit message
312
+
* with the required properties for a created post. If the data matches the expected shape,
313
+
* it extracts and returns a `FeedEntry` object. Otherwise, it returns `null`.
314
+
*
315
+
* @param data - The raw WebSocket data.
316
+
* @returns A `FeedEntry` object if the data represents a newly created post, otherwise `null`.
317
+
*/
318
+
declare function websocketToFeedEntry(data: WebSocket.Data): Post | null;
319
+
320
+
export { type ActionBot, ActionBotAgent, type Bot, type BotReply, type CronBot, CronBotAgent, JetstreamSubscription, type KeywordBot, KeywordBotAgent, Logger, type Post, type UriCid, WebSocketClient, type WebsocketMessage, buildReplyToPost, filterBotReplies, maybeInt, maybeStr, useActionBotAgent, useCronBotAgent, useKeywordBotAgent, websocketToFeedEntry };
+486
dist/index.js
+486
dist/index.js
···
1
+
"use strict";
2
+
var __create = Object.create;
3
+
var __defProp = Object.defineProperty;
4
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+
var __getOwnPropNames = Object.getOwnPropertyNames;
6
+
var __getProtoOf = Object.getPrototypeOf;
7
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+
var __export = (target, all) => {
9
+
for (var name in all)
10
+
__defProp(target, name, { get: all[name], enumerable: true });
11
+
};
12
+
var __copyProps = (to, from, except, desc) => {
13
+
if (from && typeof from === "object" || typeof from === "function") {
14
+
for (let key of __getOwnPropNames(from))
15
+
if (!__hasOwnProp.call(to, key) && key !== except)
16
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+
}
18
+
return to;
19
+
};
20
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+
// If the importer is in node compatibility mode or this is not an ESM
22
+
// file that has been converted to a CommonJS file using a Babel-
23
+
// compatible transform (i.e. "__esModule" has not been set), then set
24
+
// "default" to the CommonJS "module.exports" for node compatibility.
25
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+
mod
27
+
));
28
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
var __async = (__this, __arguments, generator) => {
30
+
return new Promise((resolve, reject) => {
31
+
var fulfilled = (value) => {
32
+
try {
33
+
step(generator.next(value));
34
+
} catch (e) {
35
+
reject(e);
36
+
}
37
+
};
38
+
var rejected = (value) => {
39
+
try {
40
+
step(generator.throw(value));
41
+
} catch (e) {
42
+
reject(e);
43
+
}
44
+
};
45
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
46
+
step((generator = generator.apply(__this, __arguments)).next());
47
+
});
48
+
};
49
+
50
+
// src/index.ts
51
+
var index_exports = {};
52
+
__export(index_exports, {
53
+
ActionBotAgent: () => ActionBotAgent,
54
+
CronBotAgent: () => CronBotAgent,
55
+
JetstreamSubscription: () => JetstreamSubscription,
56
+
KeywordBotAgent: () => KeywordBotAgent,
57
+
Logger: () => Logger,
58
+
WebSocketClient: () => WebSocketClient,
59
+
buildReplyToPost: () => buildReplyToPost,
60
+
filterBotReplies: () => filterBotReplies,
61
+
maybeInt: () => maybeInt,
62
+
maybeStr: () => maybeStr,
63
+
useActionBotAgent: () => useActionBotAgent,
64
+
useCronBotAgent: () => useCronBotAgent,
65
+
useKeywordBotAgent: () => useKeywordBotAgent,
66
+
websocketToFeedEntry: () => websocketToFeedEntry
67
+
});
68
+
module.exports = __toCommonJS(index_exports);
69
+
70
+
// src/bots/actionBot.ts
71
+
var import_api = require("@atproto/api");
72
+
73
+
// src/utils/logger.ts
74
+
var Logger = class {
75
+
/**
76
+
* Logs an informational message to the console.
77
+
*
78
+
* @param message - The message to be logged.
79
+
* @param context - Optional additional context (object or string) to log alongside the message.
80
+
*/
81
+
static info(message, context) {
82
+
console.log(`${(/* @__PURE__ */ new Date()).toLocaleString()} [INFO]: ${message}`, context || "");
83
+
}
84
+
/**
85
+
* Logs a warning message to the console.
86
+
*
87
+
* @param message - The message to be logged.
88
+
* @param context - Optional additional context (object or string) to log alongside the message.
89
+
*/
90
+
static warn(message, context) {
91
+
console.log(`${(/* @__PURE__ */ new Date()).toLocaleString()} [WARNING]: ${message}`, context || "");
92
+
}
93
+
/**
94
+
* Logs an error message to the console.
95
+
*
96
+
* @param message - The message to be logged.
97
+
* @param context - Optional additional context (object or string) to log alongside the message.
98
+
*/
99
+
static error(message, context) {
100
+
console.error(`${(/* @__PURE__ */ new Date()).toLocaleString()} [ERROR]: ${message}`, context || "");
101
+
}
102
+
/**
103
+
* Logs a debug message to the console.
104
+
*
105
+
* @param message - The message to be logged.
106
+
* @param context - Optional additional context (object or string) to log alongside the message.
107
+
*/
108
+
static debug(message, context) {
109
+
console.debug(`${(/* @__PURE__ */ new Date()).toLocaleString()} [DEBUG]: ${message}`, context || "");
110
+
}
111
+
};
112
+
113
+
// src/bots/actionBot.ts
114
+
var ActionBotAgent = class extends import_api.AtpAgent {
115
+
constructor(opts, actionBot) {
116
+
super(opts);
117
+
this.opts = opts;
118
+
this.actionBot = actionBot;
119
+
Logger.info(`Initialize cronbot ${actionBot.identifier}`);
120
+
}
121
+
doAction() {
122
+
return __async(this, null, function* () {
123
+
this.actionBot.action(this);
124
+
});
125
+
}
126
+
};
127
+
var useActionBotAgent = (actionBot) => __async(void 0, null, function* () {
128
+
const agent = new ActionBotAgent({ service: actionBot.service }, actionBot);
129
+
try {
130
+
const login = yield agent.login({ identifier: actionBot.identifier, password: actionBot.password });
131
+
if (!login.success) {
132
+
return null;
133
+
}
134
+
Logger.info(`Start cronbot ${actionBot.identifier}`);
135
+
return agent;
136
+
} catch (error) {
137
+
Logger.error("Failed to initialize bot:", `${error}, ${actionBot.identifier}`);
138
+
return null;
139
+
}
140
+
});
141
+
142
+
// src/bots/cronBot.ts
143
+
var import_api2 = require("@atproto/api");
144
+
var import_cron = require("cron");
145
+
var CronBotAgent = class extends import_api2.AtpAgent {
146
+
constructor(opts, cronBot) {
147
+
super(opts);
148
+
this.opts = opts;
149
+
this.cronBot = cronBot;
150
+
Logger.info(`Initialize cronbot ${cronBot.identifier}`);
151
+
this.job = new import_cron.CronJob(
152
+
cronBot.cronJob.scheduleExpression,
153
+
() => __async(this, null, function* () {
154
+
return cronBot.action(this);
155
+
}),
156
+
cronBot.cronJob.callback,
157
+
false,
158
+
cronBot.cronJob.timeZone
159
+
);
160
+
}
161
+
};
162
+
var useCronBotAgent = (cronBot) => __async(void 0, null, function* () {
163
+
const agent = new CronBotAgent({ service: cronBot.service }, cronBot);
164
+
try {
165
+
const login = yield agent.login({ identifier: cronBot.identifier, password: cronBot.password });
166
+
if (!login.success) {
167
+
return null;
168
+
}
169
+
Logger.info(`Start cronbot ${cronBot.identifier}`);
170
+
agent.job.start();
171
+
return agent;
172
+
} catch (error) {
173
+
Logger.error("Failed to initialize bot:", `${error}, ${cronBot.identifier}`);
174
+
return null;
175
+
}
176
+
});
177
+
178
+
// src/bots/keywordBot.ts
179
+
var import_api3 = require("@atproto/api");
180
+
var KeywordBotAgent = class extends import_api3.AtpAgent {
181
+
constructor(opts, keywordBot) {
182
+
super(opts);
183
+
this.opts = opts;
184
+
this.keywordBot = keywordBot;
185
+
}
186
+
likeAndReplyIfFollower(post) {
187
+
return __async(this, null, function* () {
188
+
var _a;
189
+
if (post.authorDid === this.assertDid) {
190
+
return;
191
+
}
192
+
const replies = filterBotReplies(post.text, this.keywordBot.replies);
193
+
if (replies.length < 1) {
194
+
return;
195
+
}
196
+
try {
197
+
const actorProfile = yield this.getProfile({ actor: post.authorDid });
198
+
if (actorProfile.success) {
199
+
if (!((_a = actorProfile.data.viewer) == null ? void 0 : _a.followedBy)) {
200
+
return;
201
+
}
202
+
const replyCfg = replies[Math.floor(Math.random() * replies.length)];
203
+
const message = replyCfg.messages[Math.floor(Math.random() * replyCfg.messages.length)];
204
+
const reply = buildReplyToPost(
205
+
{ uri: post.rootUri, cid: post.rootCid },
206
+
{ uri: post.uri, cid: post.cid },
207
+
message
208
+
);
209
+
yield Promise.all([this.like(post.uri, post.cid), this.post(reply)]);
210
+
Logger.info(`Replied to post: ${post.uri}`, this.keywordBot.identifier);
211
+
}
212
+
} catch (error) {
213
+
Logger.error("Error while replying:", `${error}, ${this.keywordBot.identifier}`);
214
+
}
215
+
});
216
+
}
217
+
};
218
+
function buildReplyToPost(root, parent, message) {
219
+
return {
220
+
$type: "app.bsky.feed.post",
221
+
text: message,
222
+
reply: {
223
+
"root": root,
224
+
"parent": parent
225
+
}
226
+
};
227
+
}
228
+
function filterBotReplies(text, botReplies) {
229
+
return botReplies.filter((reply) => {
230
+
const keyword = reply.keyword.toLowerCase();
231
+
const keywordFound = text.toLowerCase().includes(keyword);
232
+
if (!keywordFound) {
233
+
return false;
234
+
}
235
+
if (Array.isArray(reply.exclude) && reply.exclude.length > 0) {
236
+
for (const excludeWord of reply.exclude) {
237
+
if (text.toLowerCase().includes(excludeWord.toLowerCase())) {
238
+
return false;
239
+
}
240
+
}
241
+
}
242
+
return true;
243
+
});
244
+
}
245
+
var useKeywordBotAgent = (keywordBot) => __async(void 0, null, function* () {
246
+
const agent = new KeywordBotAgent({ service: keywordBot.service }, keywordBot);
247
+
try {
248
+
const login = yield agent.login({ identifier: keywordBot.identifier, password: keywordBot.password });
249
+
if (!login.success) {
250
+
return null;
251
+
}
252
+
return agent;
253
+
} catch (error) {
254
+
Logger.error("Failed to initialize bot:", `${error}, ${keywordBot.identifier}`);
255
+
return null;
256
+
}
257
+
});
258
+
259
+
// src/utils/websocketClient.ts
260
+
var import_ws = __toESM(require("ws"));
261
+
var WebSocketClient = class {
262
+
/**
263
+
* Creates a new instance of `WebSocketClient`.
264
+
*
265
+
* @param options - Configuration options for the WebSocket client, including URL, reconnect interval, and ping interval.
266
+
*/
267
+
constructor(options) {
268
+
this.ws = null;
269
+
this.pingTimeout = null;
270
+
this.url = options.url;
271
+
this.reconnectInterval = options.reconnectInterval || 5e3;
272
+
this.pingInterval = options.pingInterval || 1e4;
273
+
this.run();
274
+
}
275
+
/**
276
+
* Initiates a WebSocket connection to the specified URL.
277
+
*
278
+
* This method sets up event listeners for `open`, `message`, `error`, and `close` events.
279
+
* When the connection opens, it starts the heartbeat mechanism.
280
+
* On close, it attempts to reconnect after a specified interval.
281
+
*/
282
+
run() {
283
+
this.ws = new import_ws.default(this.url);
284
+
this.ws.on("open", () => {
285
+
Logger.info("WebSocket connected");
286
+
this.startHeartbeat();
287
+
this.onOpen();
288
+
});
289
+
this.ws.on("message", (data) => {
290
+
this.onMessage(data);
291
+
});
292
+
this.ws.on("error", (error) => {
293
+
Logger.error("WebSocket error:", error);
294
+
this.onError(error);
295
+
});
296
+
this.ws.on("close", () => {
297
+
Logger.info("WebSocket disconnected");
298
+
this.stopHeartbeat();
299
+
this.onClose();
300
+
this.reconnect();
301
+
});
302
+
}
303
+
/**
304
+
* Attempts to reconnect to the WebSocket server after the specified `reconnectInterval`.
305
+
* It clears all event listeners on the old WebSocket and initiates a new connection.
306
+
*/
307
+
reconnect() {
308
+
if (this.ws) {
309
+
this.ws.removeAllListeners();
310
+
this.ws = null;
311
+
}
312
+
setTimeout(() => this.run(), this.reconnectInterval);
313
+
}
314
+
/**
315
+
* Starts sending periodic ping messages to the server.
316
+
*
317
+
* This function uses `setInterval` to send a ping at the configured `pingInterval`.
318
+
* If the WebSocket is not open, pings are not sent.
319
+
*/
320
+
startHeartbeat() {
321
+
this.pingTimeout = setInterval(() => {
322
+
if (this.ws && this.ws.readyState === import_ws.default.OPEN) {
323
+
this.ws.ping();
324
+
}
325
+
}, this.pingInterval);
326
+
}
327
+
/**
328
+
* Stops sending heartbeat pings by clearing the ping interval.
329
+
*/
330
+
stopHeartbeat() {
331
+
if (this.pingTimeout) {
332
+
clearInterval(this.pingTimeout);
333
+
this.pingTimeout = null;
334
+
}
335
+
}
336
+
/**
337
+
* Called when the WebSocket connection is successfully opened.
338
+
*
339
+
* Override this method in a subclass to implement custom logic on connection.
340
+
*/
341
+
onOpen() {
342
+
}
343
+
/**
344
+
* Called when a WebSocket message is received.
345
+
*
346
+
* @param data - The data received from the WebSocket server.
347
+
*
348
+
* Override this method in a subclass to implement custom message handling.
349
+
*/
350
+
onMessage(data) {
351
+
}
352
+
/**
353
+
* Called when a WebSocket error occurs.
354
+
*
355
+
* @param error - The error that occurred.
356
+
*
357
+
* Override this method in a subclass to implement custom error handling.
358
+
*/
359
+
onError(error) {
360
+
}
361
+
/**
362
+
* Called when the WebSocket connection is closed.
363
+
*
364
+
* Override this method in a subclass to implement custom logic on disconnection.
365
+
*/
366
+
onClose() {
367
+
}
368
+
/**
369
+
* Sends data to the connected WebSocket server, if the connection is open.
370
+
*
371
+
* @param data - The data to send.
372
+
*/
373
+
send(data) {
374
+
if (this.ws && this.ws.readyState === import_ws.default.OPEN) {
375
+
this.ws.send(data);
376
+
}
377
+
}
378
+
/**
379
+
* Closes the WebSocket connection gracefully.
380
+
*/
381
+
close() {
382
+
if (this.ws) {
383
+
this.ws.close();
384
+
}
385
+
}
386
+
};
387
+
388
+
// src/utils/jetstreamSubscription.ts
389
+
var JetstreamSubscription = class extends WebSocketClient {
390
+
/**
391
+
* Creates a new `JetstreamSubscription`.
392
+
*
393
+
* @param service - The URL of the Jetstream server to connect to.
394
+
* @param interval - The interval (in milliseconds) for reconnect attempts.
395
+
* @param onMessageCallback - An optional callback function that is invoked whenever a message is received from the server.
396
+
*/
397
+
constructor(service, interval, onMessageCallback) {
398
+
super({ url: service, reconnectInterval: interval });
399
+
this.service = service;
400
+
this.interval = interval;
401
+
this.onMessageCallback = onMessageCallback;
402
+
}
403
+
/**
404
+
* Called when the WebSocket connection is successfully opened.
405
+
* Logs a message indicating that the connection to the Jetstream server has been established.
406
+
*/
407
+
onOpen() {
408
+
Logger.info("Connected to Jetstream server.");
409
+
}
410
+
/**
411
+
* Called when a WebSocket message is received.
412
+
*
413
+
* If an `onMessageCallback` was provided, it is invoked with the received data.
414
+
*
415
+
* @param data - The data received from the Jetstream server.
416
+
*/
417
+
onMessage(data) {
418
+
if (this.onMessageCallback) {
419
+
this.onMessageCallback(data);
420
+
}
421
+
}
422
+
/**
423
+
* Called when a WebSocket error occurs.
424
+
* Logs the error message indicating that Jetstream encountered an error.
425
+
*
426
+
* @param error - The error that occurred.
427
+
*/
428
+
onError(error) {
429
+
Logger.error("Jetstream encountered an error:", error);
430
+
}
431
+
/**
432
+
* Called when the WebSocket connection is closed.
433
+
* Logs a message indicating that the Jetstream connection has closed.
434
+
*/
435
+
onClose() {
436
+
Logger.info("Jetstream connection closed.");
437
+
}
438
+
};
439
+
440
+
// src/utils/strings.ts
441
+
var maybeStr = (val) => {
442
+
if (!val) return void 0;
443
+
return val;
444
+
};
445
+
var maybeInt = (val) => {
446
+
if (!val) return void 0;
447
+
const int = parseInt(val, 10);
448
+
if (isNaN(int)) return void 0;
449
+
return int;
450
+
};
451
+
452
+
// src/utils/wsToFeed.ts
453
+
function websocketToFeedEntry(data) {
454
+
var _a, _b, _c, _d;
455
+
const message = data;
456
+
if (!message.commit || !message.commit.record || !message.commit.record["$type"] || !message.did || !message.commit.cid || !message.commit.rkey || message.commit.operation !== "create") {
457
+
return null;
458
+
}
459
+
const messageUri = `at://${message.did}/${message.commit.record["$type"]}/${message.commit.rkey}`;
460
+
return {
461
+
cid: message.commit.cid,
462
+
uri: messageUri,
463
+
authorDid: message.did,
464
+
text: message.commit.record.text,
465
+
rootCid: (_b = (_a = message.commit.record.reply) == null ? void 0 : _a.root.cid) != null ? _b : message.commit.cid,
466
+
rootUri: (_d = (_c = message.commit.record.reply) == null ? void 0 : _c.root.uri) != null ? _d : messageUri
467
+
};
468
+
}
469
+
// Annotate the CommonJS export names for ESM import in node:
470
+
0 && (module.exports = {
471
+
ActionBotAgent,
472
+
CronBotAgent,
473
+
JetstreamSubscription,
474
+
KeywordBotAgent,
475
+
Logger,
476
+
WebSocketClient,
477
+
buildReplyToPost,
478
+
filterBotReplies,
479
+
maybeInt,
480
+
maybeStr,
481
+
useActionBotAgent,
482
+
useCronBotAgent,
483
+
useKeywordBotAgent,
484
+
websocketToFeedEntry
485
+
});
486
+
//# sourceMappingURL=index.js.map
+1
dist/index.js.map
+1
dist/index.js.map
···
1
+
{"version":3,"sources":["../src/index.ts","../src/bots/actionBot.ts","../src/utils/logger.ts","../src/bots/cronBot.ts","../src/bots/keywordBot.ts","../src/utils/websocketClient.ts","../src/utils/jetstreamSubscription.ts","../src/utils/strings.ts","../src/utils/wsToFeed.ts"],"sourcesContent":["export * from \"./types/bot\"\nexport * from \"./types/message\"\nexport * from \"./types/post\"\nexport * from \"./bots/actionBot\"\nexport * from \"./bots/cronBot\"\nexport * from \"./bots/keywordBot\"\nexport * from \"./utils/jetstreamSubscription\"\nexport * from \"./utils/logger\"\nexport * from \"./utils/strings\"\nexport * from \"./utils/websocketClient\"\nexport * from \"./utils/wsToFeed\"\n","import { AtpAgent, AtpAgentOptions } from '@atproto/api';\nimport { Logger } from '../utils/logger';\nimport type { ActionBot } from '../types/bot';\n\nexport class ActionBotAgent extends AtpAgent {\n constructor(public opts: AtpAgentOptions, public actionBot: ActionBot) {\n super(opts);\n Logger.info(`Initialize cronbot ${actionBot.identifier}`);\n }\n\n async doAction(): Promise<void> {\n this.actionBot.action(this);\n }\n}\n\nexport const useActionBotAgent = async (actionBot: ActionBot): Promise<ActionBotAgent | null> => {\n const agent = new ActionBotAgent({ service: actionBot.service }, actionBot);\n \n try {\n const login = await agent.login({ identifier: actionBot.identifier, password: actionBot.password! });\n if (!login.success) {\n return null;\n }\n Logger.info(`Start cronbot ${actionBot.identifier}`);\n return agent;\n } catch (error) {\n Logger.error(\"Failed to initialize bot:\", `${error}, ${actionBot.identifier}`);\n return null;\n }\n};","/**\n * A simple logging utility class providing static methods for various log levels.\n * Each log message is prefixed with a timestamp and log level.\n */\nexport class Logger {\n /**\n * Logs an informational message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static info(message: string, context?: object | string) {\n console.log(`${new Date().toLocaleString()} [INFO]: ${message}`, context || '');\n }\n\n /**\n * Logs a warning message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static warn(message: string, context?: object | string) {\n console.log(`${new Date().toLocaleString()} [WARNING]: ${message}`, context || '');\n }\n\n /**\n * Logs an error message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static error(message: string, context?: object | string) {\n console.error(`${new Date().toLocaleString()} [ERROR]: ${message}`, context || '');\n }\n\n /**\n * Logs a debug message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static debug(message: string, context?: object | string) {\n console.debug(`${new Date().toLocaleString()} [DEBUG]: ${message}`, context || '');\n }\n}","import { AtpAgent, AtpAgentOptions } from '@atproto/api';\nimport { CronJob } from 'cron';\nimport { Logger } from '../utils/logger';\nimport type { CronBot } from '../types/bot';\n\nexport class CronBotAgent extends AtpAgent {\n public job: CronJob;\n\n constructor(public opts: AtpAgentOptions, public cronBot: CronBot) {\n super(opts);\n Logger.info(`Initialize cronbot ${cronBot.identifier}`);\n\n this.job = new CronJob(\n cronBot.cronJob.scheduleExpression,\n async () => cronBot.action(this),\n cronBot.cronJob.callback,\n false,\n cronBot.cronJob.timeZone,\n );\n }\n}\n\nexport const useCronBotAgent = async (cronBot: CronBot): Promise<CronBotAgent | null> => {\n const agent = new CronBotAgent({ service: cronBot.service }, cronBot);\n \n try {\n const login = await agent.login({ identifier: cronBot.identifier, password: cronBot.password! });\n if (!login.success) {\n return null;\n }\n Logger.info(`Start cronbot ${cronBot.identifier}`);\n agent.job.start();\n return agent;\n } catch (error) {\n Logger.error(\"Failed to initialize bot:\", `${error}, ${cronBot.identifier}`);\n return null;\n }\n};","import { AtpAgent, AtpAgentOptions } from '@atproto/api';\nimport type { BotReply, KeywordBot } from '../types/bot';\nimport type { Post, UriCid } from \"../types/post\";\nimport { Logger } from '../utils/logger';\n\n\nexport class KeywordBotAgent extends AtpAgent {\n constructor(public opts: AtpAgentOptions, public keywordBot: KeywordBot) {\n super(opts);\n }\n \n async likeAndReplyIfFollower(post: Post): Promise<void> {\n if (post.authorDid === this.assertDid) {\n return;\n }\n\n const replies = filterBotReplies(post.text, this.keywordBot.replies);\n if (replies.length < 1) {\n return;\n }\n\n try {\n const actorProfile = await this.getProfile({actor: post.authorDid});\n\n if(actorProfile.success) {\n \n if (!actorProfile.data.viewer?.followedBy) {\n return;\n }\n\n const replyCfg = replies[Math.floor(Math.random() * replies.length)];\n const message = replyCfg.messages[Math.floor(Math.random() * replyCfg.messages.length)];\n const reply = buildReplyToPost(\n { uri: post.rootUri, cid: post.rootCid },\n { uri: post.uri, cid: post.cid },\n message\n );\n\n await Promise.all([this.like(post.uri, post.cid), this.post(reply)]);\n Logger.info(`Replied to post: ${post.uri}`, this.keywordBot.identifier);\n }\n } catch (error) {\n Logger.error(\"Error while replying:\", `${error}, ${this.keywordBot.identifier}`);\n }\n }\n}\n\nexport function buildReplyToPost (root: UriCid, parent: UriCid, message: string) { \n return {\n $type: \"app.bsky.feed.post\" as \"app.bsky.feed.post\",\n text: message,\n reply: {\n \"root\": root,\n \"parent\": parent\n }\n };\n}\n\nexport function filterBotReplies(text: string, botReplies: BotReply[]) {\n return botReplies.filter(reply => {\n const keyword = reply.keyword.toLowerCase();\n const keywordFound = text.toLowerCase().includes(keyword);\n if (!keywordFound) {\n return false;\n }\n\n if (Array.isArray(reply.exclude) && reply.exclude.length > 0) {\n for (const excludeWord of reply.exclude) {\n if (text.toLowerCase().includes(excludeWord.toLowerCase())) {\n return false;\n }\n }\n }\n\n return true;\n });\n}\n\nexport const useKeywordBotAgent = async (keywordBot: KeywordBot): Promise<KeywordBotAgent | null> => {\n const agent = new KeywordBotAgent({ service: keywordBot.service }, keywordBot);\n\n try {\n const login = await agent.login({ identifier: keywordBot.identifier, password: keywordBot.password! });\n\n if (!login.success) { \n return null;\n }\n\n return agent;\n } catch (error) {\n Logger.error(\"Failed to initialize bot:\", `${error}, ${keywordBot.identifier}`);\n return null;\n }\n};","import WebSocket from 'ws';\nimport { Logger } from './logger';\n\ninterface WebSocketClientOptions {\n /** The URL of the WebSocket server to connect to. */\n url: string;\n /** The interval in milliseconds to wait before attempting to reconnect when the connection closes. Default is 5000ms. */\n reconnectInterval?: number;\n /** The interval in milliseconds for sending ping messages (heartbeats) to keep the connection alive. Default is 10000ms. */\n pingInterval?: number;\n}\n\n/**\n * A WebSocket client that automatically attempts to reconnect upon disconnection\n * and periodically sends ping messages (heartbeats) to ensure the connection remains alive.\n * \n * Extend this class and override the protected `onOpen`, `onMessage`, `onError`, and `onClose` methods\n * to implement custom handling of WebSocket events.\n */\nexport class WebSocketClient {\n private url: string;\n private reconnectInterval: number;\n private pingInterval: number;\n private ws: WebSocket | null = null;\n private pingTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new instance of `WebSocketClient`.\n * \n * @param options - Configuration options for the WebSocket client, including URL, reconnect interval, and ping interval.\n */\n constructor(options: WebSocketClientOptions) {\n this.url = options.url;\n this.reconnectInterval = options.reconnectInterval || 5000;\n this.pingInterval = options.pingInterval || 10000; \n this.run();\n }\n\n /**\n * Initiates a WebSocket connection to the specified URL.\n * \n * This method sets up event listeners for `open`, `message`, `error`, and `close` events.\n * When the connection opens, it starts the heartbeat mechanism.\n * On close, it attempts to reconnect after a specified interval.\n */\n private run() {\n this.ws = new WebSocket(this.url);\n\n this.ws.on('open', () => {\n Logger.info('WebSocket connected');\n this.startHeartbeat();\n this.onOpen();\n });\n\n this.ws.on('message', (data: WebSocket.Data) => {\n this.onMessage(data);\n });\n\n this.ws.on('error', (error) => {\n Logger.error('WebSocket error:', error);\n this.onError(error);\n });\n\n this.ws.on('close', () => {\n Logger.info('WebSocket disconnected');\n this.stopHeartbeat();\n this.onClose();\n this.reconnect();\n });\n }\n\n /**\n * Attempts to reconnect to the WebSocket server after the specified `reconnectInterval`.\n * It clears all event listeners on the old WebSocket and initiates a new connection.\n */\n private reconnect() {\n if (this.ws) {\n this.ws.removeAllListeners();\n this.ws = null;\n }\n\n setTimeout(() => this.run(), this.reconnectInterval);\n }\n\n /**\n * Starts sending periodic ping messages to the server.\n * \n * This function uses `setInterval` to send a ping at the configured `pingInterval`.\n * If the WebSocket is not open, pings are not sent.\n */\n private startHeartbeat() {\n this.pingTimeout = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.ping(); \n }\n }, this.pingInterval);\n }\n\n /**\n * Stops sending heartbeat pings by clearing the ping interval.\n */\n private stopHeartbeat() {\n if (this.pingTimeout) {\n clearInterval(this.pingTimeout);\n this.pingTimeout = null;\n }\n }\n\n /**\n * Called when the WebSocket connection is successfully opened.\n * \n * Override this method in a subclass to implement custom logic on connection.\n */\n protected onOpen() {\n // Custom logic for connection open\n }\n\n /**\n * Called when a WebSocket message is received.\n * \n * @param data - The data received from the WebSocket server.\n * \n * Override this method in a subclass to implement custom message handling.\n */\n protected onMessage(data: WebSocket.Data) {\n // Custom logic for handling received messages\n }\n\n /**\n * Called when a WebSocket error occurs.\n * \n * @param error - The error that occurred.\n * \n * Override this method in a subclass to implement custom error handling.\n */\n protected onError(error: Error) {\n // Custom logic for handling errors\n }\n\n /**\n * Called when the WebSocket connection is closed.\n * \n * Override this method in a subclass to implement custom logic on disconnection.\n */\n protected onClose() {\n // Custom logic for handling connection close\n }\n\n /**\n * Sends data to the connected WebSocket server, if the connection is open.\n * \n * @param data - The data to send.\n */\n public send(data: any) {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(data);\n }\n }\n\n /**\n * Closes the WebSocket connection gracefully.\n */\n public close() {\n if (this.ws) {\n this.ws.close();\n }\n }\n}","import WebSocket from 'ws';\nimport { WebSocketClient } from './websocketClient';\nimport { Logger } from './logger';\n\n/**\n * Represents a subscription to a Jetstream feed over WebSocket.\n * \n * This class extends `WebSocketClient` to automatically handle reconnections and heartbeats.\n * It invokes a provided callback function whenever a message is received from the Jetstream server.\n */\nexport class JetstreamSubscription extends WebSocketClient {\n /**\n * Creates a new `JetstreamSubscription`.\n * \n * @param service - The URL of the Jetstream server to connect to.\n * @param interval - The interval (in milliseconds) for reconnect attempts.\n * @param onMessageCallback - An optional callback function that is invoked whenever a message is received from the server.\n */\n constructor(\n public service: string,\n public interval: number,\n private onMessageCallback?: (data: WebSocket.Data) => void\n ) {\n super({url: service, reconnectInterval: interval});\n }\n\n /**\n * Called when the WebSocket connection is successfully opened.\n * Logs a message indicating that the connection to the Jetstream server has been established.\n */\n protected onOpen() {\n Logger.info('Connected to Jetstream server.');\n }\n\n /**\n * Called when a WebSocket message is received.\n * \n * If an `onMessageCallback` was provided, it is invoked with the received data.\n * \n * @param data - The data received from the Jetstream server.\n */\n protected onMessage(data: WebSocket.Data) {\n if (this.onMessageCallback) {\n this.onMessageCallback(data);\n }\n }\n\n /**\n * Called when a WebSocket error occurs.\n * Logs the error message indicating that Jetstream encountered an error.\n * \n * @param error - The error that occurred.\n */\n protected onError(error: Error) {\n Logger.error('Jetstream encountered an error:', error);\n }\n\n /**\n * Called when the WebSocket connection is closed.\n * Logs a message indicating that the Jetstream connection has closed.\n */\n protected onClose() {\n Logger.info('Jetstream connection closed.');\n }\n}\n","/**\n * Returns the given string if it is defined; otherwise returns `undefined`.\n * \n * @param val - The optional string value to check.\n * @returns The given string if defined, or `undefined` if `val` is falsy.\n */\nexport const maybeStr = (val?: string): string | undefined => {\n if (!val) return undefined;\n return val;\n}\n\n/**\n* Parses the given string as an integer if it is defined and a valid integer; otherwise returns `undefined`.\n* \n* @param val - The optional string value to parse.\n* @returns The parsed integer if successful, or `undefined` if the string is falsy or not a valid integer.\n*/\nexport const maybeInt = (val?: string): number | undefined => {\n if (!val) return undefined;\n const int = parseInt(val, 10);\n if (isNaN(int)) return undefined;\n return int;\n}","import WebSocket from 'ws';\nimport { Post } from \"../types/post\";\nimport { WebsocketMessage } from '../types/message';\n;\n\n/**\n * Converts a raw WebSocket message into a `FeedEntry` object, if possible.\n * \n * This function checks if the incoming WebSocket data is structured like a feed commit message\n * with the required properties for a created post. If the data matches the expected shape,\n * it extracts and returns a `FeedEntry` object. Otherwise, it returns `null`.\n * \n * @param data - The raw WebSocket data.\n * @returns A `FeedEntry` object if the data represents a newly created post, otherwise `null`.\n */\nexport function websocketToFeedEntry(data: WebSocket.Data): Post | null {\n const message = data as WebsocketMessage;\n if(!message.commit || !message.commit.record || !message.commit.record['$type'] || !message.did || !message.commit.cid || !message.commit.rkey || message.commit.operation !== \"create\") {\n return null;\n }\n const messageUri = `at://${message.did}/${message.commit.record['$type']}/${message.commit.rkey}`;\n return {\n cid: message.commit.cid,\n uri: messageUri,\n authorDid: message.did,\n text: message.commit.record.text,\n rootCid: message.commit.record.reply?.root.cid ?? message.commit.cid,\n rootUri: message.commit.record.reply?.root.uri ?? messageUri,\n };\n}"],"mappings":"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","names":["import_api","import_api","WebSocket"]}
+437
dist/index.mjs
+437
dist/index.mjs
···
1
+
var __async = (__this, __arguments, generator) => {
2
+
return new Promise((resolve, reject) => {
3
+
var fulfilled = (value) => {
4
+
try {
5
+
step(generator.next(value));
6
+
} catch (e) {
7
+
reject(e);
8
+
}
9
+
};
10
+
var rejected = (value) => {
11
+
try {
12
+
step(generator.throw(value));
13
+
} catch (e) {
14
+
reject(e);
15
+
}
16
+
};
17
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
18
+
step((generator = generator.apply(__this, __arguments)).next());
19
+
});
20
+
};
21
+
22
+
// src/bots/actionBot.ts
23
+
import { AtpAgent } from "@atproto/api";
24
+
25
+
// src/utils/logger.ts
26
+
var Logger = class {
27
+
/**
28
+
* Logs an informational message to the console.
29
+
*
30
+
* @param message - The message to be logged.
31
+
* @param context - Optional additional context (object or string) to log alongside the message.
32
+
*/
33
+
static info(message, context) {
34
+
console.log(`${(/* @__PURE__ */ new Date()).toLocaleString()} [INFO]: ${message}`, context || "");
35
+
}
36
+
/**
37
+
* Logs a warning message to the console.
38
+
*
39
+
* @param message - The message to be logged.
40
+
* @param context - Optional additional context (object or string) to log alongside the message.
41
+
*/
42
+
static warn(message, context) {
43
+
console.log(`${(/* @__PURE__ */ new Date()).toLocaleString()} [WARNING]: ${message}`, context || "");
44
+
}
45
+
/**
46
+
* Logs an error message to the console.
47
+
*
48
+
* @param message - The message to be logged.
49
+
* @param context - Optional additional context (object or string) to log alongside the message.
50
+
*/
51
+
static error(message, context) {
52
+
console.error(`${(/* @__PURE__ */ new Date()).toLocaleString()} [ERROR]: ${message}`, context || "");
53
+
}
54
+
/**
55
+
* Logs a debug message to the console.
56
+
*
57
+
* @param message - The message to be logged.
58
+
* @param context - Optional additional context (object or string) to log alongside the message.
59
+
*/
60
+
static debug(message, context) {
61
+
console.debug(`${(/* @__PURE__ */ new Date()).toLocaleString()} [DEBUG]: ${message}`, context || "");
62
+
}
63
+
};
64
+
65
+
// src/bots/actionBot.ts
66
+
var ActionBotAgent = class extends AtpAgent {
67
+
constructor(opts, actionBot) {
68
+
super(opts);
69
+
this.opts = opts;
70
+
this.actionBot = actionBot;
71
+
Logger.info(`Initialize cronbot ${actionBot.identifier}`);
72
+
}
73
+
doAction() {
74
+
return __async(this, null, function* () {
75
+
this.actionBot.action(this);
76
+
});
77
+
}
78
+
};
79
+
var useActionBotAgent = (actionBot) => __async(void 0, null, function* () {
80
+
const agent = new ActionBotAgent({ service: actionBot.service }, actionBot);
81
+
try {
82
+
const login = yield agent.login({ identifier: actionBot.identifier, password: actionBot.password });
83
+
if (!login.success) {
84
+
return null;
85
+
}
86
+
Logger.info(`Start cronbot ${actionBot.identifier}`);
87
+
return agent;
88
+
} catch (error) {
89
+
Logger.error("Failed to initialize bot:", `${error}, ${actionBot.identifier}`);
90
+
return null;
91
+
}
92
+
});
93
+
94
+
// src/bots/cronBot.ts
95
+
import { AtpAgent as AtpAgent2 } from "@atproto/api";
96
+
import { CronJob } from "cron";
97
+
var CronBotAgent = class extends AtpAgent2 {
98
+
constructor(opts, cronBot) {
99
+
super(opts);
100
+
this.opts = opts;
101
+
this.cronBot = cronBot;
102
+
Logger.info(`Initialize cronbot ${cronBot.identifier}`);
103
+
this.job = new CronJob(
104
+
cronBot.cronJob.scheduleExpression,
105
+
() => __async(this, null, function* () {
106
+
return cronBot.action(this);
107
+
}),
108
+
cronBot.cronJob.callback,
109
+
false,
110
+
cronBot.cronJob.timeZone
111
+
);
112
+
}
113
+
};
114
+
var useCronBotAgent = (cronBot) => __async(void 0, null, function* () {
115
+
const agent = new CronBotAgent({ service: cronBot.service }, cronBot);
116
+
try {
117
+
const login = yield agent.login({ identifier: cronBot.identifier, password: cronBot.password });
118
+
if (!login.success) {
119
+
return null;
120
+
}
121
+
Logger.info(`Start cronbot ${cronBot.identifier}`);
122
+
agent.job.start();
123
+
return agent;
124
+
} catch (error) {
125
+
Logger.error("Failed to initialize bot:", `${error}, ${cronBot.identifier}`);
126
+
return null;
127
+
}
128
+
});
129
+
130
+
// src/bots/keywordBot.ts
131
+
import { AtpAgent as AtpAgent3 } from "@atproto/api";
132
+
var KeywordBotAgent = class extends AtpAgent3 {
133
+
constructor(opts, keywordBot) {
134
+
super(opts);
135
+
this.opts = opts;
136
+
this.keywordBot = keywordBot;
137
+
}
138
+
likeAndReplyIfFollower(post) {
139
+
return __async(this, null, function* () {
140
+
var _a;
141
+
if (post.authorDid === this.assertDid) {
142
+
return;
143
+
}
144
+
const replies = filterBotReplies(post.text, this.keywordBot.replies);
145
+
if (replies.length < 1) {
146
+
return;
147
+
}
148
+
try {
149
+
const actorProfile = yield this.getProfile({ actor: post.authorDid });
150
+
if (actorProfile.success) {
151
+
if (!((_a = actorProfile.data.viewer) == null ? void 0 : _a.followedBy)) {
152
+
return;
153
+
}
154
+
const replyCfg = replies[Math.floor(Math.random() * replies.length)];
155
+
const message = replyCfg.messages[Math.floor(Math.random() * replyCfg.messages.length)];
156
+
const reply = buildReplyToPost(
157
+
{ uri: post.rootUri, cid: post.rootCid },
158
+
{ uri: post.uri, cid: post.cid },
159
+
message
160
+
);
161
+
yield Promise.all([this.like(post.uri, post.cid), this.post(reply)]);
162
+
Logger.info(`Replied to post: ${post.uri}`, this.keywordBot.identifier);
163
+
}
164
+
} catch (error) {
165
+
Logger.error("Error while replying:", `${error}, ${this.keywordBot.identifier}`);
166
+
}
167
+
});
168
+
}
169
+
};
170
+
function buildReplyToPost(root, parent, message) {
171
+
return {
172
+
$type: "app.bsky.feed.post",
173
+
text: message,
174
+
reply: {
175
+
"root": root,
176
+
"parent": parent
177
+
}
178
+
};
179
+
}
180
+
function filterBotReplies(text, botReplies) {
181
+
return botReplies.filter((reply) => {
182
+
const keyword = reply.keyword.toLowerCase();
183
+
const keywordFound = text.toLowerCase().includes(keyword);
184
+
if (!keywordFound) {
185
+
return false;
186
+
}
187
+
if (Array.isArray(reply.exclude) && reply.exclude.length > 0) {
188
+
for (const excludeWord of reply.exclude) {
189
+
if (text.toLowerCase().includes(excludeWord.toLowerCase())) {
190
+
return false;
191
+
}
192
+
}
193
+
}
194
+
return true;
195
+
});
196
+
}
197
+
var useKeywordBotAgent = (keywordBot) => __async(void 0, null, function* () {
198
+
const agent = new KeywordBotAgent({ service: keywordBot.service }, keywordBot);
199
+
try {
200
+
const login = yield agent.login({ identifier: keywordBot.identifier, password: keywordBot.password });
201
+
if (!login.success) {
202
+
return null;
203
+
}
204
+
return agent;
205
+
} catch (error) {
206
+
Logger.error("Failed to initialize bot:", `${error}, ${keywordBot.identifier}`);
207
+
return null;
208
+
}
209
+
});
210
+
211
+
// src/utils/websocketClient.ts
212
+
import WebSocket from "ws";
213
+
var WebSocketClient = class {
214
+
/**
215
+
* Creates a new instance of `WebSocketClient`.
216
+
*
217
+
* @param options - Configuration options for the WebSocket client, including URL, reconnect interval, and ping interval.
218
+
*/
219
+
constructor(options) {
220
+
this.ws = null;
221
+
this.pingTimeout = null;
222
+
this.url = options.url;
223
+
this.reconnectInterval = options.reconnectInterval || 5e3;
224
+
this.pingInterval = options.pingInterval || 1e4;
225
+
this.run();
226
+
}
227
+
/**
228
+
* Initiates a WebSocket connection to the specified URL.
229
+
*
230
+
* This method sets up event listeners for `open`, `message`, `error`, and `close` events.
231
+
* When the connection opens, it starts the heartbeat mechanism.
232
+
* On close, it attempts to reconnect after a specified interval.
233
+
*/
234
+
run() {
235
+
this.ws = new WebSocket(this.url);
236
+
this.ws.on("open", () => {
237
+
Logger.info("WebSocket connected");
238
+
this.startHeartbeat();
239
+
this.onOpen();
240
+
});
241
+
this.ws.on("message", (data) => {
242
+
this.onMessage(data);
243
+
});
244
+
this.ws.on("error", (error) => {
245
+
Logger.error("WebSocket error:", error);
246
+
this.onError(error);
247
+
});
248
+
this.ws.on("close", () => {
249
+
Logger.info("WebSocket disconnected");
250
+
this.stopHeartbeat();
251
+
this.onClose();
252
+
this.reconnect();
253
+
});
254
+
}
255
+
/**
256
+
* Attempts to reconnect to the WebSocket server after the specified `reconnectInterval`.
257
+
* It clears all event listeners on the old WebSocket and initiates a new connection.
258
+
*/
259
+
reconnect() {
260
+
if (this.ws) {
261
+
this.ws.removeAllListeners();
262
+
this.ws = null;
263
+
}
264
+
setTimeout(() => this.run(), this.reconnectInterval);
265
+
}
266
+
/**
267
+
* Starts sending periodic ping messages to the server.
268
+
*
269
+
* This function uses `setInterval` to send a ping at the configured `pingInterval`.
270
+
* If the WebSocket is not open, pings are not sent.
271
+
*/
272
+
startHeartbeat() {
273
+
this.pingTimeout = setInterval(() => {
274
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
275
+
this.ws.ping();
276
+
}
277
+
}, this.pingInterval);
278
+
}
279
+
/**
280
+
* Stops sending heartbeat pings by clearing the ping interval.
281
+
*/
282
+
stopHeartbeat() {
283
+
if (this.pingTimeout) {
284
+
clearInterval(this.pingTimeout);
285
+
this.pingTimeout = null;
286
+
}
287
+
}
288
+
/**
289
+
* Called when the WebSocket connection is successfully opened.
290
+
*
291
+
* Override this method in a subclass to implement custom logic on connection.
292
+
*/
293
+
onOpen() {
294
+
}
295
+
/**
296
+
* Called when a WebSocket message is received.
297
+
*
298
+
* @param data - The data received from the WebSocket server.
299
+
*
300
+
* Override this method in a subclass to implement custom message handling.
301
+
*/
302
+
onMessage(data) {
303
+
}
304
+
/**
305
+
* Called when a WebSocket error occurs.
306
+
*
307
+
* @param error - The error that occurred.
308
+
*
309
+
* Override this method in a subclass to implement custom error handling.
310
+
*/
311
+
onError(error) {
312
+
}
313
+
/**
314
+
* Called when the WebSocket connection is closed.
315
+
*
316
+
* Override this method in a subclass to implement custom logic on disconnection.
317
+
*/
318
+
onClose() {
319
+
}
320
+
/**
321
+
* Sends data to the connected WebSocket server, if the connection is open.
322
+
*
323
+
* @param data - The data to send.
324
+
*/
325
+
send(data) {
326
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
327
+
this.ws.send(data);
328
+
}
329
+
}
330
+
/**
331
+
* Closes the WebSocket connection gracefully.
332
+
*/
333
+
close() {
334
+
if (this.ws) {
335
+
this.ws.close();
336
+
}
337
+
}
338
+
};
339
+
340
+
// src/utils/jetstreamSubscription.ts
341
+
var JetstreamSubscription = class extends WebSocketClient {
342
+
/**
343
+
* Creates a new `JetstreamSubscription`.
344
+
*
345
+
* @param service - The URL of the Jetstream server to connect to.
346
+
* @param interval - The interval (in milliseconds) for reconnect attempts.
347
+
* @param onMessageCallback - An optional callback function that is invoked whenever a message is received from the server.
348
+
*/
349
+
constructor(service, interval, onMessageCallback) {
350
+
super({ url: service, reconnectInterval: interval });
351
+
this.service = service;
352
+
this.interval = interval;
353
+
this.onMessageCallback = onMessageCallback;
354
+
}
355
+
/**
356
+
* Called when the WebSocket connection is successfully opened.
357
+
* Logs a message indicating that the connection to the Jetstream server has been established.
358
+
*/
359
+
onOpen() {
360
+
Logger.info("Connected to Jetstream server.");
361
+
}
362
+
/**
363
+
* Called when a WebSocket message is received.
364
+
*
365
+
* If an `onMessageCallback` was provided, it is invoked with the received data.
366
+
*
367
+
* @param data - The data received from the Jetstream server.
368
+
*/
369
+
onMessage(data) {
370
+
if (this.onMessageCallback) {
371
+
this.onMessageCallback(data);
372
+
}
373
+
}
374
+
/**
375
+
* Called when a WebSocket error occurs.
376
+
* Logs the error message indicating that Jetstream encountered an error.
377
+
*
378
+
* @param error - The error that occurred.
379
+
*/
380
+
onError(error) {
381
+
Logger.error("Jetstream encountered an error:", error);
382
+
}
383
+
/**
384
+
* Called when the WebSocket connection is closed.
385
+
* Logs a message indicating that the Jetstream connection has closed.
386
+
*/
387
+
onClose() {
388
+
Logger.info("Jetstream connection closed.");
389
+
}
390
+
};
391
+
392
+
// src/utils/strings.ts
393
+
var maybeStr = (val) => {
394
+
if (!val) return void 0;
395
+
return val;
396
+
};
397
+
var maybeInt = (val) => {
398
+
if (!val) return void 0;
399
+
const int = parseInt(val, 10);
400
+
if (isNaN(int)) return void 0;
401
+
return int;
402
+
};
403
+
404
+
// src/utils/wsToFeed.ts
405
+
function websocketToFeedEntry(data) {
406
+
var _a, _b, _c, _d;
407
+
const message = data;
408
+
if (!message.commit || !message.commit.record || !message.commit.record["$type"] || !message.did || !message.commit.cid || !message.commit.rkey || message.commit.operation !== "create") {
409
+
return null;
410
+
}
411
+
const messageUri = `at://${message.did}/${message.commit.record["$type"]}/${message.commit.rkey}`;
412
+
return {
413
+
cid: message.commit.cid,
414
+
uri: messageUri,
415
+
authorDid: message.did,
416
+
text: message.commit.record.text,
417
+
rootCid: (_b = (_a = message.commit.record.reply) == null ? void 0 : _a.root.cid) != null ? _b : message.commit.cid,
418
+
rootUri: (_d = (_c = message.commit.record.reply) == null ? void 0 : _c.root.uri) != null ? _d : messageUri
419
+
};
420
+
}
421
+
export {
422
+
ActionBotAgent,
423
+
CronBotAgent,
424
+
JetstreamSubscription,
425
+
KeywordBotAgent,
426
+
Logger,
427
+
WebSocketClient,
428
+
buildReplyToPost,
429
+
filterBotReplies,
430
+
maybeInt,
431
+
maybeStr,
432
+
useActionBotAgent,
433
+
useCronBotAgent,
434
+
useKeywordBotAgent,
435
+
websocketToFeedEntry
436
+
};
437
+
//# sourceMappingURL=index.mjs.map
+1
dist/index.mjs.map
+1
dist/index.mjs.map
···
1
+
{"version":3,"sources":["../src/bots/actionBot.ts","../src/utils/logger.ts","../src/bots/cronBot.ts","../src/bots/keywordBot.ts","../src/utils/websocketClient.ts","../src/utils/jetstreamSubscription.ts","../src/utils/strings.ts","../src/utils/wsToFeed.ts"],"sourcesContent":["import { AtpAgent, AtpAgentOptions } from '@atproto/api';\nimport { Logger } from '../utils/logger';\nimport type { ActionBot } from '../types/bot';\n\nexport class ActionBotAgent extends AtpAgent {\n constructor(public opts: AtpAgentOptions, public actionBot: ActionBot) {\n super(opts);\n Logger.info(`Initialize cronbot ${actionBot.identifier}`);\n }\n\n async doAction(): Promise<void> {\n this.actionBot.action(this);\n }\n}\n\nexport const useActionBotAgent = async (actionBot: ActionBot): Promise<ActionBotAgent | null> => {\n const agent = new ActionBotAgent({ service: actionBot.service }, actionBot);\n \n try {\n const login = await agent.login({ identifier: actionBot.identifier, password: actionBot.password! });\n if (!login.success) {\n return null;\n }\n Logger.info(`Start cronbot ${actionBot.identifier}`);\n return agent;\n } catch (error) {\n Logger.error(\"Failed to initialize bot:\", `${error}, ${actionBot.identifier}`);\n return null;\n }\n};","/**\n * A simple logging utility class providing static methods for various log levels.\n * Each log message is prefixed with a timestamp and log level.\n */\nexport class Logger {\n /**\n * Logs an informational message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static info(message: string, context?: object | string) {\n console.log(`${new Date().toLocaleString()} [INFO]: ${message}`, context || '');\n }\n\n /**\n * Logs a warning message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static warn(message: string, context?: object | string) {\n console.log(`${new Date().toLocaleString()} [WARNING]: ${message}`, context || '');\n }\n\n /**\n * Logs an error message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static error(message: string, context?: object | string) {\n console.error(`${new Date().toLocaleString()} [ERROR]: ${message}`, context || '');\n }\n\n /**\n * Logs a debug message to the console.\n *\n * @param message - The message to be logged.\n * @param context - Optional additional context (object or string) to log alongside the message.\n */\n static debug(message: string, context?: object | string) {\n console.debug(`${new Date().toLocaleString()} [DEBUG]: ${message}`, context || '');\n }\n}","import { AtpAgent, AtpAgentOptions } from '@atproto/api';\nimport { CronJob } from 'cron';\nimport { Logger } from '../utils/logger';\nimport type { CronBot } from '../types/bot';\n\nexport class CronBotAgent extends AtpAgent {\n public job: CronJob;\n\n constructor(public opts: AtpAgentOptions, public cronBot: CronBot) {\n super(opts);\n Logger.info(`Initialize cronbot ${cronBot.identifier}`);\n\n this.job = new CronJob(\n cronBot.cronJob.scheduleExpression,\n async () => cronBot.action(this),\n cronBot.cronJob.callback,\n false,\n cronBot.cronJob.timeZone,\n );\n }\n}\n\nexport const useCronBotAgent = async (cronBot: CronBot): Promise<CronBotAgent | null> => {\n const agent = new CronBotAgent({ service: cronBot.service }, cronBot);\n \n try {\n const login = await agent.login({ identifier: cronBot.identifier, password: cronBot.password! });\n if (!login.success) {\n return null;\n }\n Logger.info(`Start cronbot ${cronBot.identifier}`);\n agent.job.start();\n return agent;\n } catch (error) {\n Logger.error(\"Failed to initialize bot:\", `${error}, ${cronBot.identifier}`);\n return null;\n }\n};","import { AtpAgent, AtpAgentOptions } from '@atproto/api';\nimport type { BotReply, KeywordBot } from '../types/bot';\nimport type { Post, UriCid } from \"../types/post\";\nimport { Logger } from '../utils/logger';\n\n\nexport class KeywordBotAgent extends AtpAgent {\n constructor(public opts: AtpAgentOptions, public keywordBot: KeywordBot) {\n super(opts);\n }\n \n async likeAndReplyIfFollower(post: Post): Promise<void> {\n if (post.authorDid === this.assertDid) {\n return;\n }\n\n const replies = filterBotReplies(post.text, this.keywordBot.replies);\n if (replies.length < 1) {\n return;\n }\n\n try {\n const actorProfile = await this.getProfile({actor: post.authorDid});\n\n if(actorProfile.success) {\n \n if (!actorProfile.data.viewer?.followedBy) {\n return;\n }\n\n const replyCfg = replies[Math.floor(Math.random() * replies.length)];\n const message = replyCfg.messages[Math.floor(Math.random() * replyCfg.messages.length)];\n const reply = buildReplyToPost(\n { uri: post.rootUri, cid: post.rootCid },\n { uri: post.uri, cid: post.cid },\n message\n );\n\n await Promise.all([this.like(post.uri, post.cid), this.post(reply)]);\n Logger.info(`Replied to post: ${post.uri}`, this.keywordBot.identifier);\n }\n } catch (error) {\n Logger.error(\"Error while replying:\", `${error}, ${this.keywordBot.identifier}`);\n }\n }\n}\n\nexport function buildReplyToPost (root: UriCid, parent: UriCid, message: string) { \n return {\n $type: \"app.bsky.feed.post\" as \"app.bsky.feed.post\",\n text: message,\n reply: {\n \"root\": root,\n \"parent\": parent\n }\n };\n}\n\nexport function filterBotReplies(text: string, botReplies: BotReply[]) {\n return botReplies.filter(reply => {\n const keyword = reply.keyword.toLowerCase();\n const keywordFound = text.toLowerCase().includes(keyword);\n if (!keywordFound) {\n return false;\n }\n\n if (Array.isArray(reply.exclude) && reply.exclude.length > 0) {\n for (const excludeWord of reply.exclude) {\n if (text.toLowerCase().includes(excludeWord.toLowerCase())) {\n return false;\n }\n }\n }\n\n return true;\n });\n}\n\nexport const useKeywordBotAgent = async (keywordBot: KeywordBot): Promise<KeywordBotAgent | null> => {\n const agent = new KeywordBotAgent({ service: keywordBot.service }, keywordBot);\n\n try {\n const login = await agent.login({ identifier: keywordBot.identifier, password: keywordBot.password! });\n\n if (!login.success) { \n return null;\n }\n\n return agent;\n } catch (error) {\n Logger.error(\"Failed to initialize bot:\", `${error}, ${keywordBot.identifier}`);\n return null;\n }\n};","import WebSocket from 'ws';\nimport { Logger } from './logger';\n\ninterface WebSocketClientOptions {\n /** The URL of the WebSocket server to connect to. */\n url: string;\n /** The interval in milliseconds to wait before attempting to reconnect when the connection closes. Default is 5000ms. */\n reconnectInterval?: number;\n /** The interval in milliseconds for sending ping messages (heartbeats) to keep the connection alive. Default is 10000ms. */\n pingInterval?: number;\n}\n\n/**\n * A WebSocket client that automatically attempts to reconnect upon disconnection\n * and periodically sends ping messages (heartbeats) to ensure the connection remains alive.\n * \n * Extend this class and override the protected `onOpen`, `onMessage`, `onError`, and `onClose` methods\n * to implement custom handling of WebSocket events.\n */\nexport class WebSocketClient {\n private url: string;\n private reconnectInterval: number;\n private pingInterval: number;\n private ws: WebSocket | null = null;\n private pingTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new instance of `WebSocketClient`.\n * \n * @param options - Configuration options for the WebSocket client, including URL, reconnect interval, and ping interval.\n */\n constructor(options: WebSocketClientOptions) {\n this.url = options.url;\n this.reconnectInterval = options.reconnectInterval || 5000;\n this.pingInterval = options.pingInterval || 10000; \n this.run();\n }\n\n /**\n * Initiates a WebSocket connection to the specified URL.\n * \n * This method sets up event listeners for `open`, `message`, `error`, and `close` events.\n * When the connection opens, it starts the heartbeat mechanism.\n * On close, it attempts to reconnect after a specified interval.\n */\n private run() {\n this.ws = new WebSocket(this.url);\n\n this.ws.on('open', () => {\n Logger.info('WebSocket connected');\n this.startHeartbeat();\n this.onOpen();\n });\n\n this.ws.on('message', (data: WebSocket.Data) => {\n this.onMessage(data);\n });\n\n this.ws.on('error', (error) => {\n Logger.error('WebSocket error:', error);\n this.onError(error);\n });\n\n this.ws.on('close', () => {\n Logger.info('WebSocket disconnected');\n this.stopHeartbeat();\n this.onClose();\n this.reconnect();\n });\n }\n\n /**\n * Attempts to reconnect to the WebSocket server after the specified `reconnectInterval`.\n * It clears all event listeners on the old WebSocket and initiates a new connection.\n */\n private reconnect() {\n if (this.ws) {\n this.ws.removeAllListeners();\n this.ws = null;\n }\n\n setTimeout(() => this.run(), this.reconnectInterval);\n }\n\n /**\n * Starts sending periodic ping messages to the server.\n * \n * This function uses `setInterval` to send a ping at the configured `pingInterval`.\n * If the WebSocket is not open, pings are not sent.\n */\n private startHeartbeat() {\n this.pingTimeout = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.ping(); \n }\n }, this.pingInterval);\n }\n\n /**\n * Stops sending heartbeat pings by clearing the ping interval.\n */\n private stopHeartbeat() {\n if (this.pingTimeout) {\n clearInterval(this.pingTimeout);\n this.pingTimeout = null;\n }\n }\n\n /**\n * Called when the WebSocket connection is successfully opened.\n * \n * Override this method in a subclass to implement custom logic on connection.\n */\n protected onOpen() {\n // Custom logic for connection open\n }\n\n /**\n * Called when a WebSocket message is received.\n * \n * @param data - The data received from the WebSocket server.\n * \n * Override this method in a subclass to implement custom message handling.\n */\n protected onMessage(data: WebSocket.Data) {\n // Custom logic for handling received messages\n }\n\n /**\n * Called when a WebSocket error occurs.\n * \n * @param error - The error that occurred.\n * \n * Override this method in a subclass to implement custom error handling.\n */\n protected onError(error: Error) {\n // Custom logic for handling errors\n }\n\n /**\n * Called when the WebSocket connection is closed.\n * \n * Override this method in a subclass to implement custom logic on disconnection.\n */\n protected onClose() {\n // Custom logic for handling connection close\n }\n\n /**\n * Sends data to the connected WebSocket server, if the connection is open.\n * \n * @param data - The data to send.\n */\n public send(data: any) {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(data);\n }\n }\n\n /**\n * Closes the WebSocket connection gracefully.\n */\n public close() {\n if (this.ws) {\n this.ws.close();\n }\n }\n}","import WebSocket from 'ws';\nimport { WebSocketClient } from './websocketClient';\nimport { Logger } from './logger';\n\n/**\n * Represents a subscription to a Jetstream feed over WebSocket.\n * \n * This class extends `WebSocketClient` to automatically handle reconnections and heartbeats.\n * It invokes a provided callback function whenever a message is received from the Jetstream server.\n */\nexport class JetstreamSubscription extends WebSocketClient {\n /**\n * Creates a new `JetstreamSubscription`.\n * \n * @param service - The URL of the Jetstream server to connect to.\n * @param interval - The interval (in milliseconds) for reconnect attempts.\n * @param onMessageCallback - An optional callback function that is invoked whenever a message is received from the server.\n */\n constructor(\n public service: string,\n public interval: number,\n private onMessageCallback?: (data: WebSocket.Data) => void\n ) {\n super({url: service, reconnectInterval: interval});\n }\n\n /**\n * Called when the WebSocket connection is successfully opened.\n * Logs a message indicating that the connection to the Jetstream server has been established.\n */\n protected onOpen() {\n Logger.info('Connected to Jetstream server.');\n }\n\n /**\n * Called when a WebSocket message is received.\n * \n * If an `onMessageCallback` was provided, it is invoked with the received data.\n * \n * @param data - The data received from the Jetstream server.\n */\n protected onMessage(data: WebSocket.Data) {\n if (this.onMessageCallback) {\n this.onMessageCallback(data);\n }\n }\n\n /**\n * Called when a WebSocket error occurs.\n * Logs the error message indicating that Jetstream encountered an error.\n * \n * @param error - The error that occurred.\n */\n protected onError(error: Error) {\n Logger.error('Jetstream encountered an error:', error);\n }\n\n /**\n * Called when the WebSocket connection is closed.\n * Logs a message indicating that the Jetstream connection has closed.\n */\n protected onClose() {\n Logger.info('Jetstream connection closed.');\n }\n}\n","/**\n * Returns the given string if it is defined; otherwise returns `undefined`.\n * \n * @param val - The optional string value to check.\n * @returns The given string if defined, or `undefined` if `val` is falsy.\n */\nexport const maybeStr = (val?: string): string | undefined => {\n if (!val) return undefined;\n return val;\n}\n\n/**\n* Parses the given string as an integer if it is defined and a valid integer; otherwise returns `undefined`.\n* \n* @param val - The optional string value to parse.\n* @returns The parsed integer if successful, or `undefined` if the string is falsy or not a valid integer.\n*/\nexport const maybeInt = (val?: string): number | undefined => {\n if (!val) return undefined;\n const int = parseInt(val, 10);\n if (isNaN(int)) return undefined;\n return int;\n}","import WebSocket from 'ws';\nimport { Post } from \"../types/post\";\nimport { WebsocketMessage } from '../types/message';\n;\n\n/**\n * Converts a raw WebSocket message into a `FeedEntry` object, if possible.\n * \n * This function checks if the incoming WebSocket data is structured like a feed commit message\n * with the required properties for a created post. If the data matches the expected shape,\n * it extracts and returns a `FeedEntry` object. Otherwise, it returns `null`.\n * \n * @param data - The raw WebSocket data.\n * @returns A `FeedEntry` object if the data represents a newly created post, otherwise `null`.\n */\nexport function websocketToFeedEntry(data: WebSocket.Data): Post | null {\n const message = data as WebsocketMessage;\n if(!message.commit || !message.commit.record || !message.commit.record['$type'] || !message.did || !message.commit.cid || !message.commit.rkey || message.commit.operation !== \"create\") {\n return null;\n }\n const messageUri = `at://${message.did}/${message.commit.record['$type']}/${message.commit.rkey}`;\n return {\n cid: message.commit.cid,\n uri: messageUri,\n authorDid: message.did,\n text: message.commit.record.text,\n rootCid: message.commit.record.reply?.root.cid ?? message.commit.cid,\n rootUri: message.commit.record.reply?.root.uri ?? messageUri,\n };\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAiC;;;ACInC,IAAM,SAAN,MAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,OAAO,KAAK,SAAiB,SAA2B;AACpD,YAAQ,IAAI,IAAG,oBAAI,KAAK,GAAE,eAAe,CAAC,YAAY,OAAO,IAAI,WAAW,EAAE;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,KAAK,SAAiB,SAA2B;AACpD,YAAQ,IAAI,IAAG,oBAAI,KAAK,GAAE,eAAe,CAAC,eAAe,OAAO,IAAI,WAAW,EAAE;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,MAAM,SAAiB,SAA2B;AACrD,YAAQ,MAAM,IAAG,oBAAI,KAAK,GAAE,eAAe,CAAC,aAAa,OAAO,IAAI,WAAW,EAAE;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,MAAM,SAAiB,SAA2B;AACrD,YAAQ,MAAM,IAAG,oBAAI,KAAK,GAAE,eAAe,CAAC,aAAa,OAAO,IAAI,WAAW,EAAE;AAAA,EACrF;AACJ;;;ADxCO,IAAM,iBAAN,cAA6B,SAAS;AAAA,EAC3C,YAAmB,MAA8B,WAAsB;AACrE,UAAM,IAAI;AADO;AAA8B;AAE/C,WAAO,KAAK,sBAAsB,UAAU,UAAU,EAAE;AAAA,EAC1D;AAAA,EAEM,WAA0B;AAAA;AAC9B,WAAK,UAAU,OAAO,IAAI;AAAA,IAC5B;AAAA;AACF;AAEO,IAAM,oBAAoB,CAAO,cAAyD;AAC/F,QAAM,QAAQ,IAAI,eAAe,EAAE,SAAS,UAAU,QAAQ,GAAG,SAAS;AAE1E,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,MAAM,EAAE,YAAY,UAAU,YAAY,UAAU,UAAU,SAAU,CAAC;AACnG,QAAI,CAAC,MAAM,SAAS;AAClB,aAAO;AAAA,IACT;AACA,WAAO,KAAK,iBAAiB,UAAU,UAAU,EAAE;AACnD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,MAAM,6BAA6B,GAAG,KAAK,KAAK,UAAU,UAAU,EAAE;AAC7E,WAAO;AAAA,EACT;AACF;;;AE7BA,SAAS,YAAAA,iBAAiC;AAC1C,SAAS,eAAe;AAIjB,IAAM,eAAN,cAA2BC,UAAS;AAAA,EAGzC,YAAmB,MAA8B,SAAkB;AACjE,UAAM,IAAI;AADO;AAA8B;AAE/C,WAAO,KAAK,sBAAsB,QAAQ,UAAU,EAAE;AAEtD,SAAK,MAAM,IAAI;AAAA,MACb,QAAQ,QAAQ;AAAA,MAChB,MAAS;AAAG,uBAAQ,OAAO,IAAI;AAAA;AAAA,MAC/B,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,QAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;AAEO,IAAM,kBAAkB,CAAO,YAAmD;AACvF,QAAM,QAAQ,IAAI,aAAa,EAAE,SAAS,QAAQ,QAAQ,GAAG,OAAO;AAEpE,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,MAAM,EAAE,YAAY,QAAQ,YAAY,UAAU,QAAQ,SAAU,CAAC;AAC/F,QAAI,CAAC,MAAM,SAAS;AAClB,aAAO;AAAA,IACT;AACA,WAAO,KAAK,iBAAiB,QAAQ,UAAU,EAAE;AACjD,UAAM,IAAI,MAAM;AAChB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,MAAM,6BAA6B,GAAG,KAAK,KAAK,QAAQ,UAAU,EAAE;AAC3E,WAAO;AAAA,EACT;AACF;;;ACrCA,SAAS,YAAAC,iBAAiC;AAMnC,IAAM,kBAAN,cAA8BC,UAAS;AAAA,EAC1C,YAAmB,MAA8B,YAAwB;AACrE,UAAM,IAAI;AADK;AAA8B;AAAA,EAEjD;AAAA,EAEM,uBAAuB,MAA2B;AAAA;AAX5D;AAYQ,UAAI,KAAK,cAAc,KAAK,WAAW;AACnC;AAAA,MACJ;AAEA,YAAM,UAAU,iBAAiB,KAAK,MAAM,KAAK,WAAW,OAAO;AACnE,UAAI,QAAQ,SAAS,GAAG;AACpB;AAAA,MACJ;AAEA,UAAI;AACA,cAAM,eAAe,MAAM,KAAK,WAAW,EAAC,OAAO,KAAK,UAAS,CAAC;AAElE,YAAG,aAAa,SAAS;AAErB,cAAI,GAAC,kBAAa,KAAK,WAAlB,mBAA0B,aAAY;AACvC;AAAA,UACJ;AAEA,gBAAM,WAAW,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC;AACnE,gBAAM,UAAU,SAAS,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,SAAS,SAAS,MAAM,CAAC;AACtF,gBAAM,QAAQ;AAAA,YACV,EAAE,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ;AAAA,YACvC,EAAE,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI;AAAA,YAC/B;AAAA,UACJ;AAEA,gBAAM,QAAQ,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,GAAG,KAAK,KAAK,KAAK,CAAC,CAAC;AACnE,iBAAO,KAAK,oBAAoB,KAAK,GAAG,IAAI,KAAK,WAAW,UAAU;AAAA,QAC1E;AAAA,MACJ,SAAS,OAAO;AACZ,eAAO,MAAM,yBAAyB,GAAG,KAAK,KAAK,KAAK,WAAW,UAAU,EAAE;AAAA,MACnF;AAAA,IACJ;AAAA;AACJ;AAEO,SAAS,iBAAkB,MAAc,QAAgB,SAAiB;AAC7E,SAAO;AAAA,IACH,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,MACH,QAAQ;AAAA,MACR,UAAU;AAAA,IACd;AAAA,EACJ;AACJ;AAEO,SAAS,iBAAiB,MAAc,YAAwB;AACnE,SAAO,WAAW,OAAO,WAAS;AAC9B,UAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,UAAM,eAAe,KAAK,YAAY,EAAE,SAAS,OAAO;AACxD,QAAI,CAAC,cAAc;AACf,aAAO;AAAA,IACX;AAEA,QAAI,MAAM,QAAQ,MAAM,OAAO,KAAK,MAAM,QAAQ,SAAS,GAAG;AAC1D,iBAAW,eAAe,MAAM,SAAS;AACrC,YAAI,KAAK,YAAY,EAAE,SAAS,YAAY,YAAY,CAAC,GAAG;AACxD,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX,CAAC;AACL;AAEO,IAAM,qBAAqB,CAAO,eAA4D;AACjG,QAAM,QAAQ,IAAI,gBAAgB,EAAE,SAAS,WAAW,QAAQ,GAAG,UAAU;AAE7E,MAAI;AACA,UAAM,QAAQ,MAAM,MAAM,MAAM,EAAE,YAAY,WAAW,YAAY,UAAU,WAAW,SAAU,CAAC;AAErG,QAAI,CAAC,MAAM,SAAS;AAChB,aAAO;AAAA,IACX;AAEA,WAAO;AAAA,EACX,SAAS,OAAO;AACZ,WAAO,MAAM,6BAA6B,GAAG,KAAK,KAAK,WAAW,UAAU,EAAE;AAC9E,WAAO;AAAA,EACX;AACJ;;;AC7FA,OAAO,eAAe;AAmBf,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYzB,YAAY,SAAiC;AAR7C,SAAQ,KAAuB;AAC/B,SAAQ,cAAqC;AAQzC,SAAK,MAAM,QAAQ;AACnB,SAAK,oBAAoB,QAAQ,qBAAqB;AACtD,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,IAAI;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,MAAM;AACV,SAAK,KAAK,IAAI,UAAU,KAAK,GAAG;AAEhC,SAAK,GAAG,GAAG,QAAQ,MAAM;AACrB,aAAO,KAAK,qBAAqB;AACjC,WAAK,eAAe;AACpB,WAAK,OAAO;AAAA,IAChB,CAAC;AAED,SAAK,GAAG,GAAG,WAAW,CAAC,SAAyB;AAC5C,WAAK,UAAU,IAAI;AAAA,IACvB,CAAC;AAED,SAAK,GAAG,GAAG,SAAS,CAAC,UAAU;AAC3B,aAAO,MAAM,oBAAoB,KAAK;AACtC,WAAK,QAAQ,KAAK;AAAA,IACtB,CAAC;AAED,SAAK,GAAG,GAAG,SAAS,MAAM;AACtB,aAAO,KAAK,wBAAwB;AACpC,WAAK,cAAc;AACnB,WAAK,QAAQ;AACb,WAAK,UAAU;AAAA,IACnB,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY;AAChB,QAAI,KAAK,IAAI;AACT,WAAK,GAAG,mBAAmB;AAC3B,WAAK,KAAK;AAAA,IACd;AAEA,eAAW,MAAM,KAAK,IAAI,GAAG,KAAK,iBAAiB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,iBAAiB;AACrB,SAAK,cAAc,YAAY,MAAM;AACjC,UAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AAClD,aAAK,GAAG,KAAK;AAAA,MACjB;AAAA,IACJ,GAAG,KAAK,YAAY;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB;AACpB,QAAI,KAAK,aAAa;AAClB,oBAAc,KAAK,WAAW;AAC9B,WAAK,cAAc;AAAA,IACvB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,SAAS;AAAA,EAEnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,UAAU,MAAsB;AAAA,EAE1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,QAAQ,OAAc;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,UAAU;AAAA,EAEpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,KAAK,MAAW;AACnB,QAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AAClD,WAAK,GAAG,KAAK,IAAI;AAAA,IACrB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ;AACX,QAAI,KAAK,IAAI;AACT,WAAK,GAAG,MAAM;AAAA,IAClB;AAAA,EACJ;AACJ;;;AC7JO,IAAM,wBAAN,cAAoC,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvD,YACW,SACA,UACC,mBACV;AACE,UAAM,EAAC,KAAK,SAAS,mBAAmB,SAAQ,CAAC;AAJ1C;AACA;AACC;AAAA,EAGZ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,SAAS;AACf,WAAO,KAAK,gCAAgC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,UAAU,MAAsB;AACtC,QAAI,KAAK,mBAAmB;AACxB,WAAK,kBAAkB,IAAI;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,QAAQ,OAAc;AAC5B,WAAO,MAAM,mCAAmC,KAAK;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,UAAU;AAChB,WAAO,KAAK,8BAA8B;AAAA,EAC9C;AACJ;;;AC1DO,IAAM,WAAW,CAAC,QAAqC;AAC5D,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO;AACT;AAQO,IAAM,WAAW,CAAC,QAAqC;AAC5D,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,SAAS,KAAK,EAAE;AAC5B,MAAI,MAAM,GAAG,EAAG,QAAO;AACvB,SAAO;AACT;;;ACPO,SAAS,qBAAqB,MAAmC;AAfxE;AAgBI,QAAM,UAAU;AAChB,MAAG,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAAO,UAAU,CAAC,QAAQ,OAAO,OAAO,OAAO,KAAK,CAAC,QAAQ,OAAO,CAAC,QAAQ,OAAO,OAAO,CAAC,QAAQ,OAAO,QAAQ,QAAQ,OAAO,cAAc,UAAU;AACrL,WAAO;AAAA,EACX;AACA,QAAM,aAAa,QAAQ,QAAQ,GAAG,IAAI,QAAQ,OAAO,OAAO,OAAO,CAAC,IAAI,QAAQ,OAAO,IAAI;AAC/F,SAAO;AAAA,IACH,KAAK,QAAQ,OAAO;AAAA,IACpB,KAAK;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,MAAM,QAAQ,OAAO,OAAO;AAAA,IAC5B,UAAS,mBAAQ,OAAO,OAAO,UAAtB,mBAA6B,KAAK,QAAlC,YAAyC,QAAQ,OAAO;AAAA,IACjE,UAAS,mBAAQ,OAAO,OAAO,UAAtB,mBAA6B,KAAK,QAAlC,YAAyC;AAAA,EACtD;AACJ;","names":["AtpAgent","AtpAgent","AtpAgent","AtpAgent"]}
+9
-3
package.json
+9
-3
package.json
···
1
1
{
2
2
"name": "bskybot",
3
-
"version": "1.1.0",
3
+
"version": "1.1.1",
4
4
"description": "Create bluesky bots via configuration.",
5
5
"repository": "git@github.com:bskybot/bskybots.git",
6
6
"author": "bskybot <bot@eineseite.at>",
7
7
"license": "MIT",
8
8
"main": "index.js",
9
-
"keywords": ["bskybot", "bluesky", "bot", "typescript"],
9
+
"keywords": [
10
+
"bskybot",
11
+
"bluesky",
12
+
"bot",
13
+
"typescript"
14
+
],
10
15
"scripts": {
11
-
"build": "tsc"
16
+
"build": "tsup"
12
17
},
13
18
"dependencies": {
14
19
"@atproto/api": "^0.14.16",
···
20
25
"@types/node": "^22.13.14",
21
26
"globals": "^15.15.0",
22
27
"ts-node": "^10.9.2",
28
+
"tsup": "^8.4.0",
23
29
"typescript": "^5.8.2"
24
30
}
25
31
}
+1052
pnpm-lock.yaml
+1052
pnpm-lock.yaml
···
30
30
ts-node:
31
31
specifier: ^10.9.2
32
32
version: 10.9.2(@types/node@22.13.14)(typescript@5.8.2)
33
+
tsup:
34
+
specifier: ^8.4.0
35
+
version: 8.4.0(typescript@5.8.2)
33
36
typescript:
34
37
specifier: ^5.8.2
35
38
version: 5.8.2
···
55
58
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
56
59
engines: {node: '>=12'}
57
60
61
+
'@esbuild/aix-ppc64@0.25.2':
62
+
resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==}
63
+
engines: {node: '>=18'}
64
+
cpu: [ppc64]
65
+
os: [aix]
66
+
67
+
'@esbuild/android-arm64@0.25.2':
68
+
resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==}
69
+
engines: {node: '>=18'}
70
+
cpu: [arm64]
71
+
os: [android]
72
+
73
+
'@esbuild/android-arm@0.25.2':
74
+
resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==}
75
+
engines: {node: '>=18'}
76
+
cpu: [arm]
77
+
os: [android]
78
+
79
+
'@esbuild/android-x64@0.25.2':
80
+
resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==}
81
+
engines: {node: '>=18'}
82
+
cpu: [x64]
83
+
os: [android]
84
+
85
+
'@esbuild/darwin-arm64@0.25.2':
86
+
resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==}
87
+
engines: {node: '>=18'}
88
+
cpu: [arm64]
89
+
os: [darwin]
90
+
91
+
'@esbuild/darwin-x64@0.25.2':
92
+
resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==}
93
+
engines: {node: '>=18'}
94
+
cpu: [x64]
95
+
os: [darwin]
96
+
97
+
'@esbuild/freebsd-arm64@0.25.2':
98
+
resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==}
99
+
engines: {node: '>=18'}
100
+
cpu: [arm64]
101
+
os: [freebsd]
102
+
103
+
'@esbuild/freebsd-x64@0.25.2':
104
+
resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==}
105
+
engines: {node: '>=18'}
106
+
cpu: [x64]
107
+
os: [freebsd]
108
+
109
+
'@esbuild/linux-arm64@0.25.2':
110
+
resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==}
111
+
engines: {node: '>=18'}
112
+
cpu: [arm64]
113
+
os: [linux]
114
+
115
+
'@esbuild/linux-arm@0.25.2':
116
+
resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==}
117
+
engines: {node: '>=18'}
118
+
cpu: [arm]
119
+
os: [linux]
120
+
121
+
'@esbuild/linux-ia32@0.25.2':
122
+
resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==}
123
+
engines: {node: '>=18'}
124
+
cpu: [ia32]
125
+
os: [linux]
126
+
127
+
'@esbuild/linux-loong64@0.25.2':
128
+
resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==}
129
+
engines: {node: '>=18'}
130
+
cpu: [loong64]
131
+
os: [linux]
132
+
133
+
'@esbuild/linux-mips64el@0.25.2':
134
+
resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==}
135
+
engines: {node: '>=18'}
136
+
cpu: [mips64el]
137
+
os: [linux]
138
+
139
+
'@esbuild/linux-ppc64@0.25.2':
140
+
resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==}
141
+
engines: {node: '>=18'}
142
+
cpu: [ppc64]
143
+
os: [linux]
144
+
145
+
'@esbuild/linux-riscv64@0.25.2':
146
+
resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==}
147
+
engines: {node: '>=18'}
148
+
cpu: [riscv64]
149
+
os: [linux]
150
+
151
+
'@esbuild/linux-s390x@0.25.2':
152
+
resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==}
153
+
engines: {node: '>=18'}
154
+
cpu: [s390x]
155
+
os: [linux]
156
+
157
+
'@esbuild/linux-x64@0.25.2':
158
+
resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==}
159
+
engines: {node: '>=18'}
160
+
cpu: [x64]
161
+
os: [linux]
162
+
163
+
'@esbuild/netbsd-arm64@0.25.2':
164
+
resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==}
165
+
engines: {node: '>=18'}
166
+
cpu: [arm64]
167
+
os: [netbsd]
168
+
169
+
'@esbuild/netbsd-x64@0.25.2':
170
+
resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==}
171
+
engines: {node: '>=18'}
172
+
cpu: [x64]
173
+
os: [netbsd]
174
+
175
+
'@esbuild/openbsd-arm64@0.25.2':
176
+
resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==}
177
+
engines: {node: '>=18'}
178
+
cpu: [arm64]
179
+
os: [openbsd]
180
+
181
+
'@esbuild/openbsd-x64@0.25.2':
182
+
resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==}
183
+
engines: {node: '>=18'}
184
+
cpu: [x64]
185
+
os: [openbsd]
186
+
187
+
'@esbuild/sunos-x64@0.25.2':
188
+
resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==}
189
+
engines: {node: '>=18'}
190
+
cpu: [x64]
191
+
os: [sunos]
192
+
193
+
'@esbuild/win32-arm64@0.25.2':
194
+
resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==}
195
+
engines: {node: '>=18'}
196
+
cpu: [arm64]
197
+
os: [win32]
198
+
199
+
'@esbuild/win32-ia32@0.25.2':
200
+
resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==}
201
+
engines: {node: '>=18'}
202
+
cpu: [ia32]
203
+
os: [win32]
204
+
205
+
'@esbuild/win32-x64@0.25.2':
206
+
resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==}
207
+
engines: {node: '>=18'}
208
+
cpu: [x64]
209
+
os: [win32]
210
+
211
+
'@isaacs/cliui@8.0.2':
212
+
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
213
+
engines: {node: '>=12'}
214
+
215
+
'@jridgewell/gen-mapping@0.3.8':
216
+
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
217
+
engines: {node: '>=6.0.0'}
218
+
58
219
'@jridgewell/resolve-uri@3.1.2':
59
220
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
221
+
engines: {node: '>=6.0.0'}
222
+
223
+
'@jridgewell/set-array@1.2.1':
224
+
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
60
225
engines: {node: '>=6.0.0'}
61
226
62
227
'@jridgewell/sourcemap-codec@1.5.0':
63
228
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
64
229
230
+
'@jridgewell/trace-mapping@0.3.25':
231
+
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
232
+
65
233
'@jridgewell/trace-mapping@0.3.9':
66
234
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
67
235
236
+
'@pkgjs/parseargs@0.11.0':
237
+
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
238
+
engines: {node: '>=14'}
239
+
240
+
'@rollup/rollup-android-arm-eabi@4.39.0':
241
+
resolution: {integrity: sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==}
242
+
cpu: [arm]
243
+
os: [android]
244
+
245
+
'@rollup/rollup-android-arm64@4.39.0':
246
+
resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==}
247
+
cpu: [arm64]
248
+
os: [android]
249
+
250
+
'@rollup/rollup-darwin-arm64@4.39.0':
251
+
resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==}
252
+
cpu: [arm64]
253
+
os: [darwin]
254
+
255
+
'@rollup/rollup-darwin-x64@4.39.0':
256
+
resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==}
257
+
cpu: [x64]
258
+
os: [darwin]
259
+
260
+
'@rollup/rollup-freebsd-arm64@4.39.0':
261
+
resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==}
262
+
cpu: [arm64]
263
+
os: [freebsd]
264
+
265
+
'@rollup/rollup-freebsd-x64@4.39.0':
266
+
resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==}
267
+
cpu: [x64]
268
+
os: [freebsd]
269
+
270
+
'@rollup/rollup-linux-arm-gnueabihf@4.39.0':
271
+
resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==}
272
+
cpu: [arm]
273
+
os: [linux]
274
+
275
+
'@rollup/rollup-linux-arm-musleabihf@4.39.0':
276
+
resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==}
277
+
cpu: [arm]
278
+
os: [linux]
279
+
280
+
'@rollup/rollup-linux-arm64-gnu@4.39.0':
281
+
resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==}
282
+
cpu: [arm64]
283
+
os: [linux]
284
+
285
+
'@rollup/rollup-linux-arm64-musl@4.39.0':
286
+
resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==}
287
+
cpu: [arm64]
288
+
os: [linux]
289
+
290
+
'@rollup/rollup-linux-loongarch64-gnu@4.39.0':
291
+
resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==}
292
+
cpu: [loong64]
293
+
os: [linux]
294
+
295
+
'@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
296
+
resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==}
297
+
cpu: [ppc64]
298
+
os: [linux]
299
+
300
+
'@rollup/rollup-linux-riscv64-gnu@4.39.0':
301
+
resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==}
302
+
cpu: [riscv64]
303
+
os: [linux]
304
+
305
+
'@rollup/rollup-linux-riscv64-musl@4.39.0':
306
+
resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==}
307
+
cpu: [riscv64]
308
+
os: [linux]
309
+
310
+
'@rollup/rollup-linux-s390x-gnu@4.39.0':
311
+
resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==}
312
+
cpu: [s390x]
313
+
os: [linux]
314
+
315
+
'@rollup/rollup-linux-x64-gnu@4.39.0':
316
+
resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==}
317
+
cpu: [x64]
318
+
os: [linux]
319
+
320
+
'@rollup/rollup-linux-x64-musl@4.39.0':
321
+
resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==}
322
+
cpu: [x64]
323
+
os: [linux]
324
+
325
+
'@rollup/rollup-win32-arm64-msvc@4.39.0':
326
+
resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==}
327
+
cpu: [arm64]
328
+
os: [win32]
329
+
330
+
'@rollup/rollup-win32-ia32-msvc@4.39.0':
331
+
resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==}
332
+
cpu: [ia32]
333
+
os: [win32]
334
+
335
+
'@rollup/rollup-win32-x64-msvc@4.39.0':
336
+
resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==}
337
+
cpu: [x64]
338
+
os: [win32]
339
+
68
340
'@tsconfig/node10@1.0.11':
69
341
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
70
342
···
77
349
'@tsconfig/node16@1.0.4':
78
350
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
79
351
352
+
'@types/estree@1.0.7':
353
+
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
354
+
80
355
'@types/luxon@3.4.2':
81
356
resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==}
82
357
···
92
367
engines: {node: '>=0.4.0'}
93
368
hasBin: true
94
369
370
+
ansi-regex@5.0.1:
371
+
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
372
+
engines: {node: '>=8'}
373
+
374
+
ansi-regex@6.1.0:
375
+
resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
376
+
engines: {node: '>=12'}
377
+
378
+
ansi-styles@4.3.0:
379
+
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
380
+
engines: {node: '>=8'}
381
+
382
+
ansi-styles@6.2.1:
383
+
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
384
+
engines: {node: '>=12'}
385
+
386
+
any-promise@1.3.0:
387
+
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
388
+
95
389
arg@4.1.3:
96
390
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
97
391
98
392
await-lock@2.2.2:
99
393
resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==}
394
+
395
+
balanced-match@1.0.2:
396
+
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
397
+
398
+
brace-expansion@2.0.1:
399
+
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
400
+
401
+
bundle-require@5.1.0:
402
+
resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
403
+
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
404
+
peerDependencies:
405
+
esbuild: '>=0.18'
406
+
407
+
cac@6.7.14:
408
+
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
409
+
engines: {node: '>=8'}
410
+
411
+
chokidar@4.0.3:
412
+
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
413
+
engines: {node: '>= 14.16.0'}
414
+
415
+
color-convert@2.0.1:
416
+
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
417
+
engines: {node: '>=7.0.0'}
418
+
419
+
color-name@1.1.4:
420
+
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
421
+
422
+
commander@4.1.1:
423
+
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
424
+
engines: {node: '>= 6'}
425
+
426
+
consola@3.4.2:
427
+
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
428
+
engines: {node: ^14.18.0 || >=16.10.0}
100
429
101
430
create-require@1.1.1:
102
431
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
···
105
434
resolution: {integrity: sha512-HETm5kgivcdfboOmBIzq0cfC9c5bRilWZ1p7PWwnOMmbWviwIU6mPgZbeqbj5i0AzNan6P68WDTDEDezhKjOng==}
106
435
engines: {node: '>=18.x'}
107
436
437
+
cross-spawn@7.0.6:
438
+
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
439
+
engines: {node: '>= 8'}
440
+
441
+
debug@4.4.0:
442
+
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
443
+
engines: {node: '>=6.0'}
444
+
peerDependencies:
445
+
supports-color: '*'
446
+
peerDependenciesMeta:
447
+
supports-color:
448
+
optional: true
449
+
108
450
diff@4.0.2:
109
451
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
110
452
engines: {node: '>=0.3.1'}
111
453
454
+
eastasianwidth@0.2.0:
455
+
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
456
+
457
+
emoji-regex@8.0.0:
458
+
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
459
+
460
+
emoji-regex@9.2.2:
461
+
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
462
+
463
+
esbuild@0.25.2:
464
+
resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==}
465
+
engines: {node: '>=18'}
466
+
hasBin: true
467
+
468
+
fdir@6.4.3:
469
+
resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
470
+
peerDependencies:
471
+
picomatch: ^3 || ^4
472
+
peerDependenciesMeta:
473
+
picomatch:
474
+
optional: true
475
+
476
+
foreground-child@3.3.1:
477
+
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
478
+
engines: {node: '>=14'}
479
+
480
+
fsevents@2.3.3:
481
+
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
482
+
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
483
+
os: [darwin]
484
+
485
+
glob@10.4.5:
486
+
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
487
+
hasBin: true
488
+
112
489
globals@15.15.0:
113
490
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
114
491
engines: {node: '>=18'}
···
116
493
graphemer@1.4.0:
117
494
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
118
495
496
+
is-fullwidth-code-point@3.0.0:
497
+
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
498
+
engines: {node: '>=8'}
499
+
500
+
isexe@2.0.0:
501
+
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
502
+
119
503
iso-datestring-validator@2.2.2:
120
504
resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==}
121
505
506
+
jackspeak@3.4.3:
507
+
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
508
+
509
+
joycon@3.1.1:
510
+
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
511
+
engines: {node: '>=10'}
512
+
513
+
lilconfig@3.1.3:
514
+
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
515
+
engines: {node: '>=14'}
516
+
517
+
lines-and-columns@1.2.4:
518
+
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
519
+
520
+
load-tsconfig@0.2.5:
521
+
resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
522
+
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
523
+
524
+
lodash.sortby@4.7.0:
525
+
resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
526
+
527
+
lru-cache@10.4.3:
528
+
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
529
+
122
530
luxon@3.6.0:
123
531
resolution: {integrity: sha512-WE7p0p7W1xji9qxkLYsvcIxZyfP48GuFrWIBQZIsbjCyf65dG1rv4n83HcOyEyhvzxJCrUoObCRNFgRNIQ5KNA==}
124
532
engines: {node: '>=12'}
···
126
534
make-error@1.3.6:
127
535
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
128
536
537
+
minimatch@9.0.5:
538
+
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
539
+
engines: {node: '>=16 || 14 >=14.17'}
540
+
541
+
minipass@7.1.2:
542
+
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
543
+
engines: {node: '>=16 || 14 >=14.17'}
544
+
545
+
ms@2.1.3:
546
+
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
547
+
129
548
multiformats@9.9.0:
130
549
resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==}
131
550
551
+
mz@2.7.0:
552
+
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
553
+
554
+
object-assign@4.1.1:
555
+
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
556
+
engines: {node: '>=0.10.0'}
557
+
558
+
package-json-from-dist@1.0.1:
559
+
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
560
+
561
+
path-key@3.1.1:
562
+
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
563
+
engines: {node: '>=8'}
564
+
565
+
path-scurry@1.11.1:
566
+
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
567
+
engines: {node: '>=16 || 14 >=14.18'}
568
+
569
+
picocolors@1.1.1:
570
+
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
571
+
572
+
picomatch@4.0.2:
573
+
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
574
+
engines: {node: '>=12'}
575
+
576
+
pirates@4.0.7:
577
+
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
578
+
engines: {node: '>= 6'}
579
+
580
+
postcss-load-config@6.0.1:
581
+
resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
582
+
engines: {node: '>= 18'}
583
+
peerDependencies:
584
+
jiti: '>=1.21.0'
585
+
postcss: '>=8.0.9'
586
+
tsx: ^4.8.1
587
+
yaml: ^2.4.2
588
+
peerDependenciesMeta:
589
+
jiti:
590
+
optional: true
591
+
postcss:
592
+
optional: true
593
+
tsx:
594
+
optional: true
595
+
yaml:
596
+
optional: true
597
+
598
+
punycode@2.3.1:
599
+
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
600
+
engines: {node: '>=6'}
601
+
602
+
readdirp@4.1.2:
603
+
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
604
+
engines: {node: '>= 14.18.0'}
605
+
606
+
resolve-from@5.0.0:
607
+
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
608
+
engines: {node: '>=8'}
609
+
610
+
rollup@4.39.0:
611
+
resolution: {integrity: sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==}
612
+
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
613
+
hasBin: true
614
+
615
+
shebang-command@2.0.0:
616
+
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
617
+
engines: {node: '>=8'}
618
+
619
+
shebang-regex@3.0.0:
620
+
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
621
+
engines: {node: '>=8'}
622
+
623
+
signal-exit@4.1.0:
624
+
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
625
+
engines: {node: '>=14'}
626
+
627
+
source-map@0.8.0-beta.0:
628
+
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
629
+
engines: {node: '>= 8'}
630
+
631
+
string-width@4.2.3:
632
+
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
633
+
engines: {node: '>=8'}
634
+
635
+
string-width@5.1.2:
636
+
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
637
+
engines: {node: '>=12'}
638
+
639
+
strip-ansi@6.0.1:
640
+
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
641
+
engines: {node: '>=8'}
642
+
643
+
strip-ansi@7.1.0:
644
+
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
645
+
engines: {node: '>=12'}
646
+
647
+
sucrase@3.35.0:
648
+
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
649
+
engines: {node: '>=16 || 14 >=14.17'}
650
+
hasBin: true
651
+
652
+
thenify-all@1.6.0:
653
+
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
654
+
engines: {node: '>=0.8'}
655
+
656
+
thenify@3.3.1:
657
+
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
658
+
659
+
tinyexec@0.3.2:
660
+
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
661
+
662
+
tinyglobby@0.2.12:
663
+
resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==}
664
+
engines: {node: '>=12.0.0'}
665
+
132
666
tlds@1.256.0:
133
667
resolution: {integrity: sha512-ZmyVB9DAw+FFTmLElGYJgdZFsKLYd/I59Bg9NHkCGPwAbVZNRilFWDMAdX8UG+bHuv7kfursd5XGqo/9wi26lA==}
134
668
hasBin: true
135
669
670
+
tr46@1.0.1:
671
+
resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
672
+
673
+
tree-kill@1.2.2:
674
+
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
675
+
hasBin: true
676
+
677
+
ts-interface-checker@0.1.13:
678
+
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
679
+
136
680
ts-node@10.9.2:
137
681
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
138
682
hasBin: true
···
147
691
'@swc/wasm':
148
692
optional: true
149
693
694
+
tsup@8.4.0:
695
+
resolution: {integrity: sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==}
696
+
engines: {node: '>=18'}
697
+
hasBin: true
698
+
peerDependencies:
699
+
'@microsoft/api-extractor': ^7.36.0
700
+
'@swc/core': ^1
701
+
postcss: ^8.4.12
702
+
typescript: '>=4.5.0'
703
+
peerDependenciesMeta:
704
+
'@microsoft/api-extractor':
705
+
optional: true
706
+
'@swc/core':
707
+
optional: true
708
+
postcss:
709
+
optional: true
710
+
typescript:
711
+
optional: true
712
+
150
713
typescript@5.8.2:
151
714
resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
152
715
engines: {node: '>=14.17'}
···
160
723
161
724
v8-compile-cache-lib@3.0.1:
162
725
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
726
+
727
+
webidl-conversions@4.0.2:
728
+
resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
729
+
730
+
whatwg-url@7.1.0:
731
+
resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
732
+
733
+
which@2.0.2:
734
+
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
735
+
engines: {node: '>= 8'}
736
+
hasBin: true
737
+
738
+
wrap-ansi@7.0.0:
739
+
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
740
+
engines: {node: '>=10'}
741
+
742
+
wrap-ansi@8.1.0:
743
+
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
744
+
engines: {node: '>=12'}
163
745
164
746
ws@8.18.1:
165
747
resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==}
···
219
801
dependencies:
220
802
'@jridgewell/trace-mapping': 0.3.9
221
803
804
+
'@esbuild/aix-ppc64@0.25.2':
805
+
optional: true
806
+
807
+
'@esbuild/android-arm64@0.25.2':
808
+
optional: true
809
+
810
+
'@esbuild/android-arm@0.25.2':
811
+
optional: true
812
+
813
+
'@esbuild/android-x64@0.25.2':
814
+
optional: true
815
+
816
+
'@esbuild/darwin-arm64@0.25.2':
817
+
optional: true
818
+
819
+
'@esbuild/darwin-x64@0.25.2':
820
+
optional: true
821
+
822
+
'@esbuild/freebsd-arm64@0.25.2':
823
+
optional: true
824
+
825
+
'@esbuild/freebsd-x64@0.25.2':
826
+
optional: true
827
+
828
+
'@esbuild/linux-arm64@0.25.2':
829
+
optional: true
830
+
831
+
'@esbuild/linux-arm@0.25.2':
832
+
optional: true
833
+
834
+
'@esbuild/linux-ia32@0.25.2':
835
+
optional: true
836
+
837
+
'@esbuild/linux-loong64@0.25.2':
838
+
optional: true
839
+
840
+
'@esbuild/linux-mips64el@0.25.2':
841
+
optional: true
842
+
843
+
'@esbuild/linux-ppc64@0.25.2':
844
+
optional: true
845
+
846
+
'@esbuild/linux-riscv64@0.25.2':
847
+
optional: true
848
+
849
+
'@esbuild/linux-s390x@0.25.2':
850
+
optional: true
851
+
852
+
'@esbuild/linux-x64@0.25.2':
853
+
optional: true
854
+
855
+
'@esbuild/netbsd-arm64@0.25.2':
856
+
optional: true
857
+
858
+
'@esbuild/netbsd-x64@0.25.2':
859
+
optional: true
860
+
861
+
'@esbuild/openbsd-arm64@0.25.2':
862
+
optional: true
863
+
864
+
'@esbuild/openbsd-x64@0.25.2':
865
+
optional: true
866
+
867
+
'@esbuild/sunos-x64@0.25.2':
868
+
optional: true
869
+
870
+
'@esbuild/win32-arm64@0.25.2':
871
+
optional: true
872
+
873
+
'@esbuild/win32-ia32@0.25.2':
874
+
optional: true
875
+
876
+
'@esbuild/win32-x64@0.25.2':
877
+
optional: true
878
+
879
+
'@isaacs/cliui@8.0.2':
880
+
dependencies:
881
+
string-width: 5.1.2
882
+
string-width-cjs: string-width@4.2.3
883
+
strip-ansi: 7.1.0
884
+
strip-ansi-cjs: strip-ansi@6.0.1
885
+
wrap-ansi: 8.1.0
886
+
wrap-ansi-cjs: wrap-ansi@7.0.0
887
+
888
+
'@jridgewell/gen-mapping@0.3.8':
889
+
dependencies:
890
+
'@jridgewell/set-array': 1.2.1
891
+
'@jridgewell/sourcemap-codec': 1.5.0
892
+
'@jridgewell/trace-mapping': 0.3.25
893
+
222
894
'@jridgewell/resolve-uri@3.1.2': {}
223
895
896
+
'@jridgewell/set-array@1.2.1': {}
897
+
224
898
'@jridgewell/sourcemap-codec@1.5.0': {}
225
899
900
+
'@jridgewell/trace-mapping@0.3.25':
901
+
dependencies:
902
+
'@jridgewell/resolve-uri': 3.1.2
903
+
'@jridgewell/sourcemap-codec': 1.5.0
904
+
226
905
'@jridgewell/trace-mapping@0.3.9':
227
906
dependencies:
228
907
'@jridgewell/resolve-uri': 3.1.2
229
908
'@jridgewell/sourcemap-codec': 1.5.0
230
909
910
+
'@pkgjs/parseargs@0.11.0':
911
+
optional: true
912
+
913
+
'@rollup/rollup-android-arm-eabi@4.39.0':
914
+
optional: true
915
+
916
+
'@rollup/rollup-android-arm64@4.39.0':
917
+
optional: true
918
+
919
+
'@rollup/rollup-darwin-arm64@4.39.0':
920
+
optional: true
921
+
922
+
'@rollup/rollup-darwin-x64@4.39.0':
923
+
optional: true
924
+
925
+
'@rollup/rollup-freebsd-arm64@4.39.0':
926
+
optional: true
927
+
928
+
'@rollup/rollup-freebsd-x64@4.39.0':
929
+
optional: true
930
+
931
+
'@rollup/rollup-linux-arm-gnueabihf@4.39.0':
932
+
optional: true
933
+
934
+
'@rollup/rollup-linux-arm-musleabihf@4.39.0':
935
+
optional: true
936
+
937
+
'@rollup/rollup-linux-arm64-gnu@4.39.0':
938
+
optional: true
939
+
940
+
'@rollup/rollup-linux-arm64-musl@4.39.0':
941
+
optional: true
942
+
943
+
'@rollup/rollup-linux-loongarch64-gnu@4.39.0':
944
+
optional: true
945
+
946
+
'@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
947
+
optional: true
948
+
949
+
'@rollup/rollup-linux-riscv64-gnu@4.39.0':
950
+
optional: true
951
+
952
+
'@rollup/rollup-linux-riscv64-musl@4.39.0':
953
+
optional: true
954
+
955
+
'@rollup/rollup-linux-s390x-gnu@4.39.0':
956
+
optional: true
957
+
958
+
'@rollup/rollup-linux-x64-gnu@4.39.0':
959
+
optional: true
960
+
961
+
'@rollup/rollup-linux-x64-musl@4.39.0':
962
+
optional: true
963
+
964
+
'@rollup/rollup-win32-arm64-msvc@4.39.0':
965
+
optional: true
966
+
967
+
'@rollup/rollup-win32-ia32-msvc@4.39.0':
968
+
optional: true
969
+
970
+
'@rollup/rollup-win32-x64-msvc@4.39.0':
971
+
optional: true
972
+
231
973
'@tsconfig/node10@1.0.11': {}
232
974
233
975
'@tsconfig/node12@1.0.11': {}
···
235
977
'@tsconfig/node14@1.0.3': {}
236
978
237
979
'@tsconfig/node16@1.0.4': {}
980
+
981
+
'@types/estree@1.0.7': {}
238
982
239
983
'@types/luxon@3.4.2': {}
240
984
···
248
992
249
993
acorn@8.14.1: {}
250
994
995
+
ansi-regex@5.0.1: {}
996
+
997
+
ansi-regex@6.1.0: {}
998
+
999
+
ansi-styles@4.3.0:
1000
+
dependencies:
1001
+
color-convert: 2.0.1
1002
+
1003
+
ansi-styles@6.2.1: {}
1004
+
1005
+
any-promise@1.3.0: {}
1006
+
251
1007
arg@4.1.3: {}
252
1008
253
1009
await-lock@2.2.2: {}
254
1010
1011
+
balanced-match@1.0.2: {}
1012
+
1013
+
brace-expansion@2.0.1:
1014
+
dependencies:
1015
+
balanced-match: 1.0.2
1016
+
1017
+
bundle-require@5.1.0(esbuild@0.25.2):
1018
+
dependencies:
1019
+
esbuild: 0.25.2
1020
+
load-tsconfig: 0.2.5
1021
+
1022
+
cac@6.7.14: {}
1023
+
1024
+
chokidar@4.0.3:
1025
+
dependencies:
1026
+
readdirp: 4.1.2
1027
+
1028
+
color-convert@2.0.1:
1029
+
dependencies:
1030
+
color-name: 1.1.4
1031
+
1032
+
color-name@1.1.4: {}
1033
+
1034
+
commander@4.1.1: {}
1035
+
1036
+
consola@3.4.2: {}
1037
+
255
1038
create-require@1.1.1: {}
256
1039
257
1040
cron@4.1.3:
···
259
1042
'@types/luxon': 3.4.2
260
1043
luxon: 3.6.0
261
1044
1045
+
cross-spawn@7.0.6:
1046
+
dependencies:
1047
+
path-key: 3.1.1
1048
+
shebang-command: 2.0.0
1049
+
which: 2.0.2
1050
+
1051
+
debug@4.4.0:
1052
+
dependencies:
1053
+
ms: 2.1.3
1054
+
262
1055
diff@4.0.2: {}
263
1056
1057
+
eastasianwidth@0.2.0: {}
1058
+
1059
+
emoji-regex@8.0.0: {}
1060
+
1061
+
emoji-regex@9.2.2: {}
1062
+
1063
+
esbuild@0.25.2:
1064
+
optionalDependencies:
1065
+
'@esbuild/aix-ppc64': 0.25.2
1066
+
'@esbuild/android-arm': 0.25.2
1067
+
'@esbuild/android-arm64': 0.25.2
1068
+
'@esbuild/android-x64': 0.25.2
1069
+
'@esbuild/darwin-arm64': 0.25.2
1070
+
'@esbuild/darwin-x64': 0.25.2
1071
+
'@esbuild/freebsd-arm64': 0.25.2
1072
+
'@esbuild/freebsd-x64': 0.25.2
1073
+
'@esbuild/linux-arm': 0.25.2
1074
+
'@esbuild/linux-arm64': 0.25.2
1075
+
'@esbuild/linux-ia32': 0.25.2
1076
+
'@esbuild/linux-loong64': 0.25.2
1077
+
'@esbuild/linux-mips64el': 0.25.2
1078
+
'@esbuild/linux-ppc64': 0.25.2
1079
+
'@esbuild/linux-riscv64': 0.25.2
1080
+
'@esbuild/linux-s390x': 0.25.2
1081
+
'@esbuild/linux-x64': 0.25.2
1082
+
'@esbuild/netbsd-arm64': 0.25.2
1083
+
'@esbuild/netbsd-x64': 0.25.2
1084
+
'@esbuild/openbsd-arm64': 0.25.2
1085
+
'@esbuild/openbsd-x64': 0.25.2
1086
+
'@esbuild/sunos-x64': 0.25.2
1087
+
'@esbuild/win32-arm64': 0.25.2
1088
+
'@esbuild/win32-ia32': 0.25.2
1089
+
'@esbuild/win32-x64': 0.25.2
1090
+
1091
+
fdir@6.4.3(picomatch@4.0.2):
1092
+
optionalDependencies:
1093
+
picomatch: 4.0.2
1094
+
1095
+
foreground-child@3.3.1:
1096
+
dependencies:
1097
+
cross-spawn: 7.0.6
1098
+
signal-exit: 4.1.0
1099
+
1100
+
fsevents@2.3.3:
1101
+
optional: true
1102
+
1103
+
glob@10.4.5:
1104
+
dependencies:
1105
+
foreground-child: 3.3.1
1106
+
jackspeak: 3.4.3
1107
+
minimatch: 9.0.5
1108
+
minipass: 7.1.2
1109
+
package-json-from-dist: 1.0.1
1110
+
path-scurry: 1.11.1
1111
+
264
1112
globals@15.15.0: {}
265
1113
266
1114
graphemer@1.4.0: {}
267
1115
1116
+
is-fullwidth-code-point@3.0.0: {}
1117
+
1118
+
isexe@2.0.0: {}
1119
+
268
1120
iso-datestring-validator@2.2.2: {}
269
1121
1122
+
jackspeak@3.4.3:
1123
+
dependencies:
1124
+
'@isaacs/cliui': 8.0.2
1125
+
optionalDependencies:
1126
+
'@pkgjs/parseargs': 0.11.0
1127
+
1128
+
joycon@3.1.1: {}
1129
+
1130
+
lilconfig@3.1.3: {}
1131
+
1132
+
lines-and-columns@1.2.4: {}
1133
+
1134
+
load-tsconfig@0.2.5: {}
1135
+
1136
+
lodash.sortby@4.7.0: {}
1137
+
1138
+
lru-cache@10.4.3: {}
1139
+
270
1140
luxon@3.6.0: {}
271
1141
272
1142
make-error@1.3.6: {}
273
1143
1144
+
minimatch@9.0.5:
1145
+
dependencies:
1146
+
brace-expansion: 2.0.1
1147
+
1148
+
minipass@7.1.2: {}
1149
+
1150
+
ms@2.1.3: {}
1151
+
274
1152
multiformats@9.9.0: {}
275
1153
1154
+
mz@2.7.0:
1155
+
dependencies:
1156
+
any-promise: 1.3.0
1157
+
object-assign: 4.1.1
1158
+
thenify-all: 1.6.0
1159
+
1160
+
object-assign@4.1.1: {}
1161
+
1162
+
package-json-from-dist@1.0.1: {}
1163
+
1164
+
path-key@3.1.1: {}
1165
+
1166
+
path-scurry@1.11.1:
1167
+
dependencies:
1168
+
lru-cache: 10.4.3
1169
+
minipass: 7.1.2
1170
+
1171
+
picocolors@1.1.1: {}
1172
+
1173
+
picomatch@4.0.2: {}
1174
+
1175
+
pirates@4.0.7: {}
1176
+
1177
+
postcss-load-config@6.0.1:
1178
+
dependencies:
1179
+
lilconfig: 3.1.3
1180
+
1181
+
punycode@2.3.1: {}
1182
+
1183
+
readdirp@4.1.2: {}
1184
+
1185
+
resolve-from@5.0.0: {}
1186
+
1187
+
rollup@4.39.0:
1188
+
dependencies:
1189
+
'@types/estree': 1.0.7
1190
+
optionalDependencies:
1191
+
'@rollup/rollup-android-arm-eabi': 4.39.0
1192
+
'@rollup/rollup-android-arm64': 4.39.0
1193
+
'@rollup/rollup-darwin-arm64': 4.39.0
1194
+
'@rollup/rollup-darwin-x64': 4.39.0
1195
+
'@rollup/rollup-freebsd-arm64': 4.39.0
1196
+
'@rollup/rollup-freebsd-x64': 4.39.0
1197
+
'@rollup/rollup-linux-arm-gnueabihf': 4.39.0
1198
+
'@rollup/rollup-linux-arm-musleabihf': 4.39.0
1199
+
'@rollup/rollup-linux-arm64-gnu': 4.39.0
1200
+
'@rollup/rollup-linux-arm64-musl': 4.39.0
1201
+
'@rollup/rollup-linux-loongarch64-gnu': 4.39.0
1202
+
'@rollup/rollup-linux-powerpc64le-gnu': 4.39.0
1203
+
'@rollup/rollup-linux-riscv64-gnu': 4.39.0
1204
+
'@rollup/rollup-linux-riscv64-musl': 4.39.0
1205
+
'@rollup/rollup-linux-s390x-gnu': 4.39.0
1206
+
'@rollup/rollup-linux-x64-gnu': 4.39.0
1207
+
'@rollup/rollup-linux-x64-musl': 4.39.0
1208
+
'@rollup/rollup-win32-arm64-msvc': 4.39.0
1209
+
'@rollup/rollup-win32-ia32-msvc': 4.39.0
1210
+
'@rollup/rollup-win32-x64-msvc': 4.39.0
1211
+
fsevents: 2.3.3
1212
+
1213
+
shebang-command@2.0.0:
1214
+
dependencies:
1215
+
shebang-regex: 3.0.0
1216
+
1217
+
shebang-regex@3.0.0: {}
1218
+
1219
+
signal-exit@4.1.0: {}
1220
+
1221
+
source-map@0.8.0-beta.0:
1222
+
dependencies:
1223
+
whatwg-url: 7.1.0
1224
+
1225
+
string-width@4.2.3:
1226
+
dependencies:
1227
+
emoji-regex: 8.0.0
1228
+
is-fullwidth-code-point: 3.0.0
1229
+
strip-ansi: 6.0.1
1230
+
1231
+
string-width@5.1.2:
1232
+
dependencies:
1233
+
eastasianwidth: 0.2.0
1234
+
emoji-regex: 9.2.2
1235
+
strip-ansi: 7.1.0
1236
+
1237
+
strip-ansi@6.0.1:
1238
+
dependencies:
1239
+
ansi-regex: 5.0.1
1240
+
1241
+
strip-ansi@7.1.0:
1242
+
dependencies:
1243
+
ansi-regex: 6.1.0
1244
+
1245
+
sucrase@3.35.0:
1246
+
dependencies:
1247
+
'@jridgewell/gen-mapping': 0.3.8
1248
+
commander: 4.1.1
1249
+
glob: 10.4.5
1250
+
lines-and-columns: 1.2.4
1251
+
mz: 2.7.0
1252
+
pirates: 4.0.7
1253
+
ts-interface-checker: 0.1.13
1254
+
1255
+
thenify-all@1.6.0:
1256
+
dependencies:
1257
+
thenify: 3.3.1
1258
+
1259
+
thenify@3.3.1:
1260
+
dependencies:
1261
+
any-promise: 1.3.0
1262
+
1263
+
tinyexec@0.3.2: {}
1264
+
1265
+
tinyglobby@0.2.12:
1266
+
dependencies:
1267
+
fdir: 6.4.3(picomatch@4.0.2)
1268
+
picomatch: 4.0.2
1269
+
276
1270
tlds@1.256.0: {}
1271
+
1272
+
tr46@1.0.1:
1273
+
dependencies:
1274
+
punycode: 2.3.1
1275
+
1276
+
tree-kill@1.2.2: {}
1277
+
1278
+
ts-interface-checker@0.1.13: {}
277
1279
278
1280
ts-node@10.9.2(@types/node@22.13.14)(typescript@5.8.2):
279
1281
dependencies:
···
293
1295
v8-compile-cache-lib: 3.0.1
294
1296
yn: 3.1.1
295
1297
1298
+
tsup@8.4.0(typescript@5.8.2):
1299
+
dependencies:
1300
+
bundle-require: 5.1.0(esbuild@0.25.2)
1301
+
cac: 6.7.14
1302
+
chokidar: 4.0.3
1303
+
consola: 3.4.2
1304
+
debug: 4.4.0
1305
+
esbuild: 0.25.2
1306
+
joycon: 3.1.1
1307
+
picocolors: 1.1.1
1308
+
postcss-load-config: 6.0.1
1309
+
resolve-from: 5.0.0
1310
+
rollup: 4.39.0
1311
+
source-map: 0.8.0-beta.0
1312
+
sucrase: 3.35.0
1313
+
tinyexec: 0.3.2
1314
+
tinyglobby: 0.2.12
1315
+
tree-kill: 1.2.2
1316
+
optionalDependencies:
1317
+
typescript: 5.8.2
1318
+
transitivePeerDependencies:
1319
+
- jiti
1320
+
- supports-color
1321
+
- tsx
1322
+
- yaml
1323
+
296
1324
typescript@5.8.2: {}
297
1325
298
1326
uint8arrays@3.0.0:
···
302
1330
undici-types@6.20.0: {}
303
1331
304
1332
v8-compile-cache-lib@3.0.1: {}
1333
+
1334
+
webidl-conversions@4.0.2: {}
1335
+
1336
+
whatwg-url@7.1.0:
1337
+
dependencies:
1338
+
lodash.sortby: 4.7.0
1339
+
tr46: 1.0.1
1340
+
webidl-conversions: 4.0.2
1341
+
1342
+
which@2.0.2:
1343
+
dependencies:
1344
+
isexe: 2.0.0
1345
+
1346
+
wrap-ansi@7.0.0:
1347
+
dependencies:
1348
+
ansi-styles: 4.3.0
1349
+
string-width: 4.2.3
1350
+
strip-ansi: 6.0.1
1351
+
1352
+
wrap-ansi@8.1.0:
1353
+
dependencies:
1354
+
ansi-styles: 6.2.1
1355
+
string-width: 5.1.2
1356
+
strip-ansi: 7.1.0
305
1357
306
1358
ws@8.18.1: {}
307
1359
+10
tsup.config.ts
+10
tsup.config.ts