Bots to use with the firehose/jetstream

build with tsup

bskybot fe540e2c 4cb2a77c

-1
.gitignore
··· 1 1 node_modules/ 2 - dist/ 3 2 reactions.db 4 3 bot/index.ts 5 4 .DS_Store
+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
··· 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
··· 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 + {"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
··· 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 + {"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":"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","names":["AtpAgent","AtpAgent","AtpAgent","AtpAgent"]}
+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
··· 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
··· 1 + import { defineConfig } from "tsup"; 2 + 3 + export default defineConfig({ 4 + entry: ["src/index.ts"], 5 + format: ["cjs", "esm"], // Build for commonJS and ESmodules 6 + dts: true, // Generate declaration file (.d.ts) 7 + splitting: false, 8 + sourcemap: true, 9 + clean: true, 10 + });