@convex-dev/expo-push-notifications
Advanced tools
| import type { GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server"; | ||
| import type { GenericId } from "convex/values"; | ||
| import type { NotificationFields } from "../component/schema.js"; | ||
| import type { LogLevel } from "../logging/index.js"; | ||
| import type { ComponentApi } from "../component/_generated/component.js"; | ||
| /** | ||
| * This component uses Expo's push notification API | ||
| * (https://docs.expo.dev/push-notifications/overview/) | ||
| * to allow users to send each other push notifications. | ||
| * | ||
| * This component takes in a type parameter `UserType` that should | ||
| * correspond to the unique identifier you want to use when sending | ||
| * notifications in your app (e.g. `Id<"users">` or a branded string | ||
| * `type Email = string & { __isEmail: true }`). | ||
| */ | ||
| export declare class PushNotifications<UserType extends string = GenericId<"users">> { | ||
| component: ComponentApi; | ||
| private config; | ||
| constructor(component: ComponentApi, config?: { | ||
| logLevel?: LogLevel; | ||
| }); | ||
| /** | ||
| * Takes in an Expo Push Token fetched from the client (https://docs.expo.dev/versions/latest/sdk/notifications/#expopushtoken). | ||
| * | ||
| * This allows sending notifications for this user using this token. | ||
| */ | ||
| recordToken(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| pushToken: string; | ||
| }): Promise<null>; | ||
| /** | ||
| * This removes the push notification token for a user if it exists. | ||
| * | ||
| * Once this is run, notifications can no longer be sent to this user. | ||
| */ | ||
| removeToken(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Gets the status of a user: whether they have a token and whether notifications are paused. | ||
| */ | ||
| getStatusForUser(ctx: RunQueryCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<{ | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }>; | ||
| /** | ||
| * Sends a push notification to the user with the given token. | ||
| * | ||
| * If allowUnregisteredTokens is true, we will log when there is no token for | ||
| * a user and not attempt to send a notification. | ||
| * | ||
| * If allowUnregisteredTokens is false, we will throw a ConvexError if there is no | ||
| * token for a user. | ||
| * | ||
| * Notification delivery will be batched for efficient delivery. | ||
| * @returns The ID of the notification, to be used to query the status. | ||
| * Or null if the user has paused notifications. | ||
| * @throws ConvexError if the user has no token and allowUnregisteredTokens is false. | ||
| */ | ||
| sendPushNotification(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| notification: NotificationFields; | ||
| allowUnregisteredTokens?: boolean; | ||
| }): Promise<string | null>; | ||
| /** | ||
| * Sends push notifications to multiple users in batch. | ||
| * | ||
| * @param ctx The mutation context | ||
| * @param args Object containing list of {userId, notification} pairs and allowUnregisteredTokens flag | ||
| * @returns Promise resolving when all notifications are processed | ||
| */ | ||
| sendPushNotificationBatch(ctx: RunMutationCtx, args: { | ||
| notifications: Array<{ | ||
| userId: UserType; | ||
| notification: NotificationFields; | ||
| }>; | ||
| allowUnregisteredTokens?: boolean; | ||
| }): Promise<(string | null)[]>; | ||
| /** | ||
| * Gets the notification by ID returned from {@link sendPushNotification}. | ||
| * Returns null if there is no record of a notification with that ID. | ||
| */ | ||
| getNotification(ctx: RunQueryCtx, args: { | ||
| id: string; | ||
| }): Promise<{ | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| } | null>; | ||
| /** | ||
| * Gets the most recent notifications for a user, up to `limit` (default 1000) | ||
| */ | ||
| getNotificationsForUser(ctx: RunQueryCtx, args: { | ||
| userId: UserType; | ||
| limit?: number; | ||
| }): Promise<{ | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| id: string; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }[]>; | ||
| /** | ||
| * Deletes all notifications for a user. | ||
| */ | ||
| deleteNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Temporarily pause notifications for a user, for instance when the user is | ||
| * actively using the app, or able to see notifications elsewhere. | ||
| * | ||
| * Notifications sent while paused will be dropped and will not be retried. | ||
| */ | ||
| pauseNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Resume notifications for a user. | ||
| * @param ctx | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| unpauseNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Gracefully shut down the push notification sender. | ||
| * | ||
| * If notifications aren't being sent for some reason, this will attempt to gracefully | ||
| * cancel any running jobs. To restart the push notification sender, call restart(). | ||
| * | ||
| * @param ctx | ||
| * @returns | ||
| */ | ||
| shutdown(ctx: RunMutationCtx): Promise<{ | ||
| data?: any; | ||
| message: string; | ||
| }>; | ||
| /** | ||
| * Restart the push notification sender. | ||
| * | ||
| * Call `shutdown()` first to gracefully drain any jobs in progress. | ||
| * @param ctx | ||
| * @returns {boolean} true if the restart was successful, false if it was not (i.e. if there are still jobs in progress) | ||
| */ | ||
| restart(ctx: RunMutationCtx): Promise<boolean>; | ||
| } | ||
| type RunQueryCtx = { | ||
| runQuery: GenericQueryCtx<GenericDataModel>["runQuery"]; | ||
| }; | ||
| type RunMutationCtx = { | ||
| runMutation: GenericMutationCtx<GenericDataModel>["runMutation"]; | ||
| }; | ||
| export {}; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * This component uses Expo's push notification API | ||
| * (https://docs.expo.dev/push-notifications/overview/) | ||
| * to allow users to send each other push notifications. | ||
| * | ||
| * This component takes in a type parameter `UserType` that should | ||
| * correspond to the unique identifier you want to use when sending | ||
| * notifications in your app (e.g. `Id<"users">` or a branded string | ||
| * `type Email = string & { __isEmail: true }`). | ||
| */ | ||
| export class PushNotifications { | ||
| component; | ||
| config; | ||
| constructor(component, config) { | ||
| this.component = component; | ||
| this.component = component; | ||
| this.config = { | ||
| ...(config ?? {}), | ||
| logLevel: config?.logLevel ?? "ERROR", | ||
| }; | ||
| } | ||
| /** | ||
| * Takes in an Expo Push Token fetched from the client (https://docs.expo.dev/versions/latest/sdk/notifications/#expopushtoken). | ||
| * | ||
| * This allows sending notifications for this user using this token. | ||
| */ | ||
| recordToken(ctx, args) { | ||
| return ctx.runMutation(this.component.public.recordPushNotificationToken, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * This removes the push notification token for a user if it exists. | ||
| * | ||
| * Once this is run, notifications can no longer be sent to this user. | ||
| */ | ||
| removeToken(ctx, args) { | ||
| return ctx.runMutation(this.component.public.removePushNotificationToken, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the status of a user: whether they have a token and whether notifications are paused. | ||
| */ | ||
| getStatusForUser(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getStatusForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Sends a push notification to the user with the given token. | ||
| * | ||
| * If allowUnregisteredTokens is true, we will log when there is no token for | ||
| * a user and not attempt to send a notification. | ||
| * | ||
| * If allowUnregisteredTokens is false, we will throw a ConvexError if there is no | ||
| * token for a user. | ||
| * | ||
| * Notification delivery will be batched for efficient delivery. | ||
| * @returns The ID of the notification, to be used to query the status. | ||
| * Or null if the user has paused notifications. | ||
| * @throws ConvexError if the user has no token and allowUnregisteredTokens is false. | ||
| */ | ||
| sendPushNotification(ctx, args) { | ||
| return ctx.runMutation(this.component.public.sendPushNotification, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Sends push notifications to multiple users in batch. | ||
| * | ||
| * @param ctx The mutation context | ||
| * @param args Object containing list of {userId, notification} pairs and allowUnregisteredTokens flag | ||
| * @returns Promise resolving when all notifications are processed | ||
| */ | ||
| sendPushNotificationBatch(ctx, args) { | ||
| return ctx.runMutation(this.component.public.sendPushNotificationBatch, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the notification by ID returned from {@link sendPushNotification}. | ||
| * Returns null if there is no record of a notification with that ID. | ||
| */ | ||
| getNotification(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getNotification, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the most recent notifications for a user, up to `limit` (default 1000) | ||
| */ | ||
| getNotificationsForUser(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Deletes all notifications for a user. | ||
| */ | ||
| deleteNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.deleteNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Temporarily pause notifications for a user, for instance when the user is | ||
| * actively using the app, or able to see notifications elsewhere. | ||
| * | ||
| * Notifications sent while paused will be dropped and will not be retried. | ||
| */ | ||
| pauseNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.pauseNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Resume notifications for a user. | ||
| * @param ctx | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| unpauseNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.unpauseNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gracefully shut down the push notification sender. | ||
| * | ||
| * If notifications aren't being sent for some reason, this will attempt to gracefully | ||
| * cancel any running jobs. To restart the push notification sender, call restart(). | ||
| * | ||
| * @param ctx | ||
| * @returns | ||
| */ | ||
| shutdown(ctx) { | ||
| return ctx.runMutation(this.component.public.shutdown, { | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Restart the push notification sender. | ||
| * | ||
| * Call `shutdown()` first to gracefully drain any jobs in progress. | ||
| * @param ctx | ||
| * @returns {boolean} true if the restart was successful, false if it was not (i.e. if there are still jobs in progress) | ||
| */ | ||
| restart(ctx) { | ||
| return ctx.runMutation(this.component.public.restart, { | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type * as functions from "../functions.js"; | ||
| import type * as helpers from "../helpers.js"; | ||
| import type * as internal_ from "../internal.js"; | ||
| import type * as public_ from "../public.js"; | ||
| import type { ApiFromModules, FilterApi, FunctionReference } from "convex/server"; | ||
| declare const fullApi: ApiFromModules<{ | ||
| functions: typeof functions; | ||
| helpers: typeof helpers; | ||
| internal: typeof internal_; | ||
| public: typeof public_; | ||
| }>; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's public API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export declare const api: FilterApi<typeof fullApi, FunctionReference<any, "public">>; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's internal API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = internal.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export declare const internal: FilterApi<typeof fullApi, FunctionReference<any, "internal">>; | ||
| export declare const components: {}; | ||
| export {}; | ||
| //# sourceMappingURL=api.d.ts.map |
| {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,KAAK,OAAO,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,KAAK,SAAS,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,QAAA,MAAM,OAAO,EAAE,cAAc,CAAC;IAC5B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,QAAQ,EAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,EAAE,OAAO,OAAO,CAAC;CACxB,CAAiB,CAAC;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,EAAE,SAAS,CACzB,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CACjB,CAAC;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CACnB,CAAC;AAElB,eAAO,MAAM,UAAU,EAAqC,EAAE,CAAC"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { anyApi, componentsGeneric } from "convex/server"; | ||
| const fullApi = anyApi; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's public API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api = anyApi; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's internal API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = internal.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const internal = anyApi; | ||
| export const components = componentsGeneric(); | ||
| //# sourceMappingURL=api.js.map |
| {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAYH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,OAAO,GAKR,MAAa,CAAC;AAEnB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAGZ,MAAa,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAGjB,MAAa,CAAC;AAElB,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAAmB,CAAC"} |
| /** | ||
| * Generated `ComponentApi` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { FunctionReference } from "convex/server"; | ||
| /** | ||
| * A utility for referencing a Convex component's exposed API. | ||
| * | ||
| * Useful when expecting a parameter like `components.myComponent`. | ||
| * Usage: | ||
| * ```ts | ||
| * async function myFunction(ctx: QueryCtx, component: ComponentApi) { | ||
| * return ctx.runQuery(component.someFile.someQuery, { ...args }); | ||
| * } | ||
| * ``` | ||
| */ | ||
| export type ComponentApi<Name extends string | undefined = string | undefined> = { | ||
| public: { | ||
| deleteNotificationsForUser: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, null, Name>; | ||
| getNotification: FunctionReference<"query", "internal", { | ||
| id: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, null | { | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }, Name>; | ||
| getNotificationsForUser: FunctionReference<"query", "internal", { | ||
| limit?: number; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, Array<{ | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| id: string; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }>, Name>; | ||
| getStatusForUser: FunctionReference<"query", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, { | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }, Name>; | ||
| pauseNotificationsForUser: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, null, Name>; | ||
| recordPushNotificationToken: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| pushToken: string; | ||
| userId: string; | ||
| }, null, Name>; | ||
| removePushNotificationToken: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, null, Name>; | ||
| restart: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, boolean, Name>; | ||
| sendPushNotification: FunctionReference<"mutation", "internal", { | ||
| allowUnregisteredTokens?: boolean; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| notification: { | ||
| _contentAvailable?: boolean; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }; | ||
| userId: string; | ||
| }, string | null, Name>; | ||
| sendPushNotificationBatch: FunctionReference<"mutation", "internal", { | ||
| allowUnregisteredTokens?: boolean; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| notifications: Array<{ | ||
| notification: { | ||
| _contentAvailable?: boolean; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }; | ||
| userId: string; | ||
| }>; | ||
| }, Array<string | null>, Name>; | ||
| shutdown: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, { | ||
| data?: any; | ||
| message: string; | ||
| }, Name>; | ||
| unpauseNotificationsForUser: FunctionReference<"mutation", "internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, null, Name>; | ||
| }; | ||
| }; | ||
| //# sourceMappingURL=component.d.ts.map |
| {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/component.ts"],"names":[],"mappings":"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"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `ComponentApi` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| export {}; | ||
| //# sourceMappingURL=component.js.map |
| {"version":3,"file":"component.js","sourceRoot":"","sources":["../../../src/component/_generated/component.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG"} |
| /** | ||
| * Generated data model types. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { DataModelFromSchemaDefinition, DocumentByName, TableNamesInDataModel, SystemTableNames } from "convex/server"; | ||
| import type { GenericId } from "convex/values"; | ||
| import schema from "../schema.js"; | ||
| /** | ||
| * The names of all of your Convex tables. | ||
| */ | ||
| export type TableNames = TableNamesInDataModel<DataModel>; | ||
| /** | ||
| * The type of a document stored in Convex. | ||
| * | ||
| * @typeParam TableName - A string literal type of the table name (like "users"). | ||
| */ | ||
| export type Doc<TableName extends TableNames> = DocumentByName<DataModel, TableName>; | ||
| /** | ||
| * An identifier for a document in Convex. | ||
| * | ||
| * Convex documents are uniquely identified by their `Id`, which is accessible | ||
| * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids). | ||
| * | ||
| * Documents can be loaded using `db.get(id)` in query and mutation functions. | ||
| * | ||
| * IDs are just strings at runtime, but this type can be used to distinguish them from other | ||
| * strings when type checking. | ||
| * | ||
| * @typeParam TableName - A string literal type of the table name (like "users"). | ||
| */ | ||
| export type Id<TableName extends TableNames | SystemTableNames> = GenericId<TableName>; | ||
| /** | ||
| * A type describing your Convex data model. | ||
| * | ||
| * This type includes information about what tables you have, the type of | ||
| * documents stored in those tables, and the indexes defined on them. | ||
| * | ||
| * This type is used to parameterize methods like `queryGeneric` and | ||
| * `mutationGeneric` to make them type-safe. | ||
| */ | ||
| export type DataModel = DataModelFromSchemaDefinition<typeof schema>; | ||
| //# sourceMappingURL=dataModel.d.ts.map |
| {"version":3,"file":"dataModel.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/dataModel.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,6BAA6B,EAC7B,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,GAAG,CAAC,SAAS,SAAS,UAAU,IAAI,cAAc,CAC5D,SAAS,EACT,SAAS,CACV,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,EAAE,CAAC,SAAS,SAAS,UAAU,GAAG,gBAAgB,IAC5D,SAAS,CAAC,SAAS,CAAC,CAAC;AAEvB;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,GAAG,6BAA6B,CAAC,OAAO,MAAM,CAAC,CAAC"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated data model types. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import schema from "../schema.js"; | ||
| //# sourceMappingURL=dataModel.js.map |
| {"version":3,"file":"dataModel.js","sourceRoot":"","sources":["../../../src/component/_generated/dataModel.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AASH,OAAO,MAAM,MAAM,cAAc,CAAC"} |
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { ActionBuilder, HttpActionBuilder, MutationBuilder, QueryBuilder, GenericActionCtx, GenericMutationCtx, GenericQueryCtx, GenericDatabaseReader, GenericDatabaseWriter } from "convex/server"; | ||
| import type { DataModel } from "./dataModel.js"; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const query: QueryBuilder<DataModel, "public">; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const internalQuery: QueryBuilder<DataModel, "internal">; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const mutation: MutationBuilder<DataModel, "public">; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const internalMutation: MutationBuilder<DataModel, "internal">; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const action: ActionBuilder<DataModel, "public">; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const internalAction: ActionBuilder<DataModel, "internal">; | ||
| /** | ||
| * Define an HTTP action. | ||
| * | ||
| * The wrapped function will be used to respond to HTTP requests received | ||
| * by a Convex deployment if the requests matches the path and method where | ||
| * this action is routed. Be sure to route your httpAction in `convex/http.js`. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument | ||
| * and a Fetch API `Request` object as its second. | ||
| * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up. | ||
| */ | ||
| export declare const httpAction: HttpActionBuilder; | ||
| /** | ||
| * A set of services for use within Convex query functions. | ||
| * | ||
| * The query context is passed as the first argument to any Convex query | ||
| * function run on the server. | ||
| * | ||
| * If you're using code generation, use the `QueryCtx` type in `convex/_generated/server.d.ts` instead. | ||
| */ | ||
| export type QueryCtx = GenericQueryCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex mutation functions. | ||
| * | ||
| * The mutation context is passed as the first argument to any Convex mutation | ||
| * function run on the server. | ||
| * | ||
| * If you're using code generation, use the `MutationCtx` type in `convex/_generated/server.d.ts` instead. | ||
| */ | ||
| export type MutationCtx = GenericMutationCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex action functions. | ||
| * | ||
| * The action context is passed as the first argument to any Convex action | ||
| * function run on the server. | ||
| */ | ||
| export type ActionCtx = GenericActionCtx<DataModel>; | ||
| /** | ||
| * An interface to read from the database within Convex query functions. | ||
| * | ||
| * The two entry points are {@link DatabaseReader.get}, which fetches a single | ||
| * document by its {@link Id}, or {@link DatabaseReader.query}, which starts | ||
| * building a query. | ||
| */ | ||
| export type DatabaseReader = GenericDatabaseReader<DataModel>; | ||
| /** | ||
| * An interface to read from and write to the database within Convex mutation | ||
| * functions. | ||
| * | ||
| * Convex guarantees that all writes within a single mutation are | ||
| * executed atomically, so you never have to worry about partial writes leaving | ||
| * your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control) | ||
| * for the guarantees Convex provides your functions. | ||
| */ | ||
| export type DatabaseWriter = GenericDatabaseWriter<DataModel>; | ||
| //# sourceMappingURL=server.d.ts.map |
| {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/server.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAUvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAgB,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,YAAY,CAAC,SAAS,EAAE,UAAU,CACxC,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAmB,CAAC;AAE9E;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,CAC3C,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAiB,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,UAAU,CACzC,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAqC,CAAC;AAO/D;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { actionGeneric, httpActionGeneric, queryGeneric, mutationGeneric, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, } from "convex/server"; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query = queryGeneric; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery = internalQueryGeneric; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation = mutationGeneric; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation = internalMutationGeneric; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action = actionGeneric; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction = internalActionGeneric; | ||
| /** | ||
| * Define an HTTP action. | ||
| * | ||
| * The wrapped function will be used to respond to HTTP requests received | ||
| * by a Convex deployment if the requests matches the path and method where | ||
| * this action is routed. Be sure to route your httpAction in `convex/http.js`. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument | ||
| * and a Fetch API `Request` object as its second. | ||
| * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up. | ||
| */ | ||
| export const httpAction = httpActionGeneric; | ||
| //# sourceMappingURL=server.js.map |
| {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/component/_generated/server.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAaH,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAGvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAsC,YAAY,CAAC;AAErE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GACxB,oBAAoB,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAyC,eAAe,CAAC;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,uBAAuB,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAuC,aAAa,CAAC;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,qBAAqB,CAAC;AAExB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB,iBAAiB,CAAC"} |
| declare const _default: import("convex/server").ComponentDefinition<any>; | ||
| export default _default; | ||
| //# sourceMappingURL=convex.config.d.ts.map |
| {"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../src/component/convex.config.ts"],"names":[],"mappings":";AAEA,wBAAoD"} |
| import { defineComponent } from "convex/server"; | ||
| export default defineComponent("pushNotifications"); | ||
| //# sourceMappingURL=convex.config.js.map |
| {"version":3,"file":"convex.config.js","sourceRoot":"","sources":["../../src/component/convex.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAe,eAAe,CAAC,mBAAmB,CAAC,CAAC"} |
| import { type CustomCtx } from "convex-helpers/server/customFunctions"; | ||
| import { Logger } from "../logging/index.js"; | ||
| export declare const query: import("convex-helpers/server/customFunctions").CustomBuilder<"query", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericQueryCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public", object>; | ||
| export declare const mutation: import("convex-helpers/server/customFunctions").CustomBuilder<"mutation", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericMutationCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public", object>; | ||
| export declare const action: import("convex-helpers/server/customFunctions").CustomBuilder<"action", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericActionCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public", object>; | ||
| export declare const internalQuery: import("convex-helpers/server/customFunctions").CustomBuilder<"query", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericQueryCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal", object>; | ||
| export declare const internalMutation: import("convex-helpers/server/customFunctions").CustomBuilder<"mutation", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericMutationCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal", object>; | ||
| export declare const internalAction: import("convex-helpers/server/customFunctions").CustomBuilder<"action", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericActionCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal", object>; | ||
| export type MutationCtx = CustomCtx<typeof mutation>; | ||
| //# sourceMappingURL=functions.d.ts.map |
| {"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../src/component/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAGf,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAqB,MAAM,qBAAqB,CAAC;AAEhE,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAKhB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAKnB,CAAC;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAKjB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAKxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAK3B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAKzB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,QAAQ,CAAC,CAAC"} |
| import { customAction, customMutation, customQuery, } from "convex-helpers/server/customFunctions"; | ||
| import * as VanillaConvex from "./_generated/server.js"; | ||
| import { Logger, logLevelValidator } from "../logging/index.js"; | ||
| export const query = customQuery(VanillaConvex.query, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const mutation = customMutation(VanillaConvex.mutation, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const action = customAction(VanillaConvex.action, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalQuery = customQuery(VanillaConvex.internalQuery, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalMutation = customMutation(VanillaConvex.internalMutation, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalAction = customAction(VanillaConvex.internalAction, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=functions.js.map |
| {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../src/component/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,cAAc,EACd,WAAW,GACZ,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAC,QAAQ,EAAE;IAC7D,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,CAAC,MAAM,EAAE;IACvD,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC,aAAa,CAAC,aAAa,EAAE;IACpE,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC,aAAa,CAAC,gBAAgB,EAAE;IAC7E,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE;IACvE,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC"} |
| import type { MutationCtx } from "./functions.js"; | ||
| export declare function ensureCoordinator(ctx: MutationCtx): Promise<void>; | ||
| export declare const shutdownGracefully: (ctx: MutationCtx) => Promise<{ | ||
| inProgressSenders: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }[]; | ||
| }>; | ||
| //# sourceMappingURL=helpers.d.ts.map |
| {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/component/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,iBA6CvD;AAED,eAAO,MAAM,kBAAkB,GAAU,KAAK,WAAW;;;;;;;EA8CxD,CAAC"} |
| import { internal } from "./_generated/api.js"; | ||
| export async function ensureCoordinator(ctx) { | ||
| ctx.logger.debug("Ensuring there's a notification coordinator"); | ||
| const coordinators = await ctx.db.query("senderCoordinator").collect(); | ||
| const activeCoordinators = []; | ||
| for (const coordinator of coordinators) { | ||
| const job = await ctx.db.system.get(coordinator.jobId); | ||
| if (job === null || | ||
| !(job.state.kind === "pending" || job.state.kind === "inProgress")) { | ||
| await ctx.db.delete(coordinator._id); | ||
| } | ||
| else { | ||
| activeCoordinators.push(coordinator); | ||
| } | ||
| } | ||
| if (activeCoordinators.length === 1) { | ||
| ctx.logger.debug(`Found existing coordinator with ID ${activeCoordinators[0]._id}`); | ||
| return; | ||
| } | ||
| if (activeCoordinators.length > 1) { | ||
| ctx.logger.error(`Unexpected state: Too many coordinators ${activeCoordinators.length}`); | ||
| throw new Error(`Unexpected state: Too many coordinators ${activeCoordinators.length}`); | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config?.state === "shutting_down") { | ||
| ctx.logger.info("Shutting down, so not starting a new coordinator."); | ||
| return; | ||
| } | ||
| const coordinatorJobId = await ctx.scheduler.runAfter(250, internal.internal.coordinateSendingPushNotifications, { | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| const coordinatorId = await ctx.db.insert("senderCoordinator", { | ||
| jobId: coordinatorJobId, | ||
| }); | ||
| ctx.logger.debug(`Started a new coordinator ${coordinatorId}`); | ||
| } | ||
| export const shutdownGracefully = async (ctx) => { | ||
| const coordinator = await ctx.db.query("senderCoordinator").unique(); | ||
| if (coordinator === null) { | ||
| ctx.logger.debug("No coordinator found, no need to restart it"); | ||
| } | ||
| else { | ||
| ctx.logger.info(`Stopping coordinator ${coordinator._id}`); | ||
| await ctx.scheduler.cancel(coordinator.jobId); | ||
| await ctx.db.delete(coordinator._id); | ||
| } | ||
| const senders = await ctx.db.query("senders").collect(); | ||
| const inProgressSenders = []; | ||
| for (const sender of senders) { | ||
| const jobId = sender.jobId; | ||
| const job = await ctx.db.system.get(jobId); | ||
| if (job === null) { | ||
| ctx.logger.error(`Sender ${sender._id} has no job, cleaning up`); | ||
| await ctx.db.delete(sender._id); | ||
| continue; | ||
| } | ||
| switch (job.state.kind) { | ||
| case "pending": | ||
| ctx.logger.info(`Stopping sender ${sender._id}`); | ||
| await ctx.scheduler.cancel(sender.jobId); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| case "inProgress": | ||
| inProgressSenders.push(sender); | ||
| break; | ||
| case "failed": | ||
| case "success": | ||
| case "canceled": | ||
| case null: | ||
| ctx.logger.debug(`Sender ${sender._id} is already done, cleaning up`); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| default: { | ||
| const _typeCheck = job.state; | ||
| ctx.logger.error(`Unknown job state ${job.state.kind} for sender ${sender._id}. Cleaning it up. `); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| return { inProgressSenders }; | ||
| }; | ||
| //# sourceMappingURL=helpers.js.map |
| {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/component/helpers.ts"],"names":[],"mappings":"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"} |
| export declare const markNotificationState: import("convex/server").RegisteredMutation<"internal", { | ||
| notifications: { | ||
| state: "delivered" | "failed" | "maybe_delivered"; | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| }[]; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const coordinateSendingPushNotifications: import("convex/server").RegisteredMutation<"internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const checkForFailedAction: import("convex/server").RegisteredMutation<"internal", { | ||
| notificationIds: import("convex/values").GenericId<"notifications">[]; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const action_sendPushNotifications: import("convex/server").RegisteredAction<"internal", { | ||
| notifications: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| message: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| to: string; | ||
| }; | ||
| }[]; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| //# sourceMappingURL=internal.d.ts.map |
| {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/component/internal.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB;;;;;;;iBA6ChC,CAAC;AAOH,eAAO,MAAM,kCAAkC;;iBAsH7C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;iBAkB/B,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;iBAiHvC,CAAC"} |
| import { v } from "convex/values"; | ||
| import { internalAction, internalMutation } from "./functions.js"; | ||
| import { internal } from "./_generated/api.js"; | ||
| import { ensureCoordinator } from "./helpers.js"; | ||
| import { notificationFields } from "./schema.js"; | ||
| export const markNotificationState = internalMutation({ | ||
| args: { | ||
| notifications: v.array(v.object({ | ||
| _id: v.id("notifications"), | ||
| state: v.union(v.literal("delivered"), v.literal("failed"), v.literal("maybe_delivered")), | ||
| })), | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| }, | ||
| handler: async (ctx, { notifications, checkJobId }) => { | ||
| ctx.logger.debug(`Marking state for ${notifications.length} notifications`); | ||
| for (const notification of notifications) { | ||
| const { _id, state } = notification; | ||
| switch (state) { | ||
| case "delivered": | ||
| ctx.logger.debug(`Marking notification ${_id} as delivered`); | ||
| await ctx.db.patch(_id, { | ||
| state: "delivered", | ||
| }); | ||
| break; | ||
| case "failed": { | ||
| ctx.logger.debug(`Marking notification ${_id} as needing retry`); | ||
| const notification = await ctx.db.get(_id); | ||
| await ctx.db.patch(_id, { | ||
| state: "needs_retry", | ||
| numPreviousFailures: notification.numPreviousFailures + 1, | ||
| }); | ||
| break; | ||
| } | ||
| case "maybe_delivered": | ||
| ctx.logger.debug(`Marking notification ${_id} as maybe delivered`); | ||
| await ctx.db.patch(_id, { | ||
| state: "maybe_delivered", | ||
| }); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Cancelling scheduled check ${checkJobId}`); | ||
| await ctx.scheduler.cancel(checkJobId); | ||
| await ensureCoordinator(ctx); | ||
| }, | ||
| }); | ||
| const MAX_NOTIFICATIONS_PER_SEND = 100; | ||
| const MAX_SENDERS = 10; | ||
| const MAX_SENDER_DURATION_MS = 10_000; | ||
| const MAX_RETRY_ATTEMPTS = 5; | ||
| export const coordinateSendingPushNotifications = internalMutation({ | ||
| args: {}, | ||
| handler: async (ctx) => { | ||
| ctx.logger.debug("Coordinate sending push notifications"); | ||
| // Get notifications | ||
| const retryNotifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("state", (q) => q.eq("state", "needs_retry")) | ||
| .take(MAX_NOTIFICATIONS_PER_SEND); | ||
| const unsentNotifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("state", (q) => q.eq("state", "awaiting_delivery")) | ||
| .take(MAX_NOTIFICATIONS_PER_SEND - retryNotifications.length); | ||
| ctx.logger.debug(`Found ${retryNotifications.length} retry notifications and ${unsentNotifications.length} unsent notifications`); | ||
| const notificationsToProcess = [ | ||
| ...retryNotifications, | ||
| ...unsentNotifications, | ||
| ]; | ||
| if (notificationsToProcess.length === 0) { | ||
| // Nothing to do! | ||
| ctx.logger.info("No notifications to send, doing nothing"); | ||
| return; | ||
| } | ||
| const senders = await ctx.db.query("senders").collect(); | ||
| let numActiveSenders = 0; | ||
| for (const sender of senders) { | ||
| const senderJob = await ctx.db.system.get(sender.jobId); | ||
| if (senderJob?.state.kind === "inProgress" || | ||
| senderJob?.state.kind === "pending") { | ||
| numActiveSenders++; | ||
| } | ||
| else { | ||
| ctx.logger.debug(`Removing sender in state ${senderJob?.state.kind}`); | ||
| await ctx.db.delete(sender._id); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Found ${numActiveSenders} active senders`); | ||
| if (numActiveSenders >= MAX_SENDERS) { | ||
| // Don't add another sender yet | ||
| ctx.logger.debug(`Not starting another sender: already ${numActiveSenders}`); | ||
| ctx.logger.debug(`When one sender finishes, or fails, we'll coordinate sending these notifications.`); | ||
| return; | ||
| } | ||
| const notificationsToSend = notificationsToProcess.filter((n) => n.numPreviousFailures < MAX_RETRY_ATTEMPTS); | ||
| const notificationsToMarkAsUnableToDeliver = notificationsToProcess.filter((n) => n.numPreviousFailures >= MAX_RETRY_ATTEMPTS); | ||
| for (const notification of notificationsToMarkAsUnableToDeliver) { | ||
| if (notification.numPreviousFailures >= MAX_RETRY_ATTEMPTS) { | ||
| await ctx.db.patch(notification._id, { | ||
| state: "unable_to_deliver", | ||
| }); | ||
| } | ||
| } | ||
| for (const notification of notificationsToSend) { | ||
| await ctx.db.patch(notification._id, { | ||
| state: "in_progress", | ||
| }); | ||
| } | ||
| ctx.logger.debug(`Marking all notifications as in progress`); | ||
| const checkJobId = await ctx.scheduler.runAfter(MAX_SENDER_DURATION_MS, internal.internal.checkForFailedAction, { | ||
| notificationIds: notificationsToSend.map((n) => n._id), | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| const senderJobId = await ctx.scheduler.runAfter(0, internal.internal.action_sendPushNotifications, { | ||
| checkJobId, | ||
| notifications: notificationsToSend.map((n) => { | ||
| return { | ||
| message: { | ||
| to: n.token, | ||
| _contentAvailable: n.metadata._contentAvailable ?? undefined, | ||
| data: n.metadata.data ?? undefined, | ||
| title: n.metadata.title, | ||
| body: n.metadata.body ?? undefined, | ||
| ttl: n.metadata.ttl ?? undefined, | ||
| expiration: n.metadata.expiration ?? undefined, | ||
| priority: n.metadata.priority ?? undefined, | ||
| subtitle: n.metadata.subtitle ?? undefined, | ||
| sound: n.metadata.sound ?? undefined, | ||
| badge: n.metadata.badge ?? undefined, | ||
| interruptionLevel: n.metadata.interruptionLevel ?? undefined, | ||
| channelId: n.metadata.channelId ?? undefined, | ||
| categoryId: n.metadata.categoryId ?? undefined, | ||
| mutableContent: n.metadata.mutableContent ?? undefined, | ||
| }, | ||
| _id: n._id, | ||
| }; | ||
| }), | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| await ctx.db.insert("senders", { | ||
| jobId: senderJobId, | ||
| checkJobId, | ||
| }); | ||
| ctx.logger.debug(`Started a new sender ${senderJobId} with job ${senderJobId} and check job ${checkJobId}`); | ||
| }, | ||
| }); | ||
| export const checkForFailedAction = internalMutation({ | ||
| args: { | ||
| notificationIds: v.array(v.id("notifications")), | ||
| }, | ||
| handler: async (ctx, { notificationIds }) => { | ||
| console.warn(`Could not determine delivery status for ${notificationIds.length} notifications:`, notificationIds); | ||
| for (const notificationId of notificationIds) { | ||
| // We don't really know what happened to these notifications, | ||
| // so we can't safely retry these. | ||
| await ctx.db.patch(notificationId, { | ||
| state: "maybe_delivered", | ||
| }); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| }, | ||
| }); | ||
| export const action_sendPushNotifications = internalAction({ | ||
| args: { | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| notifications: v.array(v.object({ | ||
| message: v.object({ | ||
| to: v.string(), | ||
| ...notificationFields, | ||
| }), | ||
| _id: v.id("notifications"), | ||
| })), | ||
| }, | ||
| handler: async (ctx, args) => { | ||
| ctx.logger.debug(`Sending ${args.notifications.length} push notifications via Expo's API`); | ||
| ctx.logger.debug(`Notification IDs: ${JSON.stringify(args.notifications.map((n) => n._id))}`); | ||
| let response; | ||
| try { | ||
| // https://docs.expo.dev/push-notifications/sending-notifications/#http2-api | ||
| response = await fetch("https://exp.host/--/api/v2/push/send", { | ||
| method: "POST", | ||
| headers: { | ||
| Accept: "application/json", | ||
| "Accept-encoding": "gzip, deflate", | ||
| "Content-Type": "application/json", | ||
| }, | ||
| body: JSON.stringify(args.notifications.map((n) => n.message)), | ||
| }); | ||
| } | ||
| catch (_e) { | ||
| ctx.logger.error("Failed during during fetch for sending push notifications:", _e); | ||
| ctx.logger.debug(`Marking ${args.notifications.length} notifications as failed so they can be retried`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: args.notifications.map((n) => { | ||
| return { | ||
| _id: n._id, | ||
| // It's unlikely that the notifications were actually delivered | ||
| // if the fetch failed, so we mark them as failed. | ||
| state: "failed", | ||
| }; | ||
| }), | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| return; | ||
| } | ||
| if (!response.ok) { | ||
| ctx.logger.warn(`Push notification failed with status ${response.status} and body ${await response.text()}`); | ||
| ctx.logger.debug(`Marking ${args.notifications.length} notifications as maybe delivered. They won't be retried.`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: args.notifications.map((n) => { | ||
| return { | ||
| _id: n._id, | ||
| // We don't really know what happened to these notifications, | ||
| // so we mark them as maybe_delivered, so we don't retry them | ||
| // again and again. | ||
| state: "maybe_delivered", | ||
| }; | ||
| }), | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| } | ||
| const responseBody = await response.json(); | ||
| ctx.logger.debug(`Response from Expo's API: ${JSON.stringify(responseBody)}`); | ||
| const notificationStates = []; | ||
| for (let idx = 0; idx < args.notifications.length; idx++) { | ||
| const notification = args.notifications[idx]; | ||
| const responseItem = responseBody.data[idx]; | ||
| if (responseItem && responseItem.status === "ok") { | ||
| notificationStates.push({ | ||
| _id: notification._id, | ||
| state: "delivered", | ||
| }); | ||
| } | ||
| else { | ||
| notificationStates.push({ | ||
| _id: notification._id, | ||
| state: "failed", | ||
| }); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Successfully parsed response from Expo, and recording state`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: notificationStates, | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=internal.js.map |
| {"version":3,"file":"internal.js","sourceRoot":"","sources":["../../src/component/internal.ts"],"names":[],"mappings":"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"} |
| export declare const recordPushNotificationToken: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| pushToken: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const removePushNotificationToken: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const sendPushNotification: import("convex/server").RegisteredMutation<"public", { | ||
| allowUnregisteredTokens?: boolean | undefined; | ||
| userId: string; | ||
| notification: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<import("convex/values").GenericId<"notifications"> | null>>; | ||
| export declare const sendPushNotificationBatch: import("convex/server").RegisteredMutation<"public", { | ||
| allowUnregisteredTokens?: boolean | undefined; | ||
| notifications: { | ||
| userId: string; | ||
| notification: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| }[]; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<(import("convex/values").GenericId<"notifications"> | null)[]>>; | ||
| export declare const getNotification: import("convex/server").RegisteredQuery<"public", { | ||
| id: import("convex/values").GenericId<"notifications">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| numPreviousFailures: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| } | null>>; | ||
| export declare const getNotificationsForUser: import("convex/server").RegisteredQuery<"public", { | ||
| limit?: number | undefined; | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| numPreviousFailures: number; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| id: import("convex/values").GenericId<"notifications">; | ||
| }[]>>; | ||
| export declare const deleteNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const pauseNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const unpauseNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const getStatusForUser: import("convex/server").RegisteredQuery<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }>>; | ||
| export declare const shutdown: import("convex/server").RegisteredMutation<"public", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| message: string; | ||
| data?: undefined; | ||
| } | { | ||
| message: string; | ||
| data: { | ||
| inProgressSenderIds: import("convex/values").GenericId<"senders">[]; | ||
| }; | ||
| }>>; | ||
| export declare const restart: import("convex/server").RegisteredMutation<"public", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<boolean>>; | ||
| //# sourceMappingURL=public.d.ts.map |
| {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/component/public.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B;;;;iBAwBtC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;iBAgBtC,CAAC;AAQH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;sEAQ/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;0EAwBpC,CAAC;AAwCH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;UAoB1B,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;KAkClC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;iBAmCrC,CAAC;AAGH,eAAO,MAAM,yBAAyB;;;iBAiBpC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;iBAiBtC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;GAmB3B,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;GA6BnB,CAAC;AAEH,eAAO,MAAM,OAAO;;oBAwBlB,CAAC"} |
| import { ConvexError, v } from "convex/values"; | ||
| import { mutation, query } from "./functions.js"; | ||
| import { notificationFields, notificationState } from "./schema.js"; | ||
| import { ensureCoordinator, shutdownGracefully } from "./helpers.js"; | ||
| import { api } from "./_generated/api.js"; | ||
| const DEFAULT_LIMIT = 1000; | ||
| export const recordPushNotificationToken = mutation({ | ||
| args: { | ||
| userId: v.string(), | ||
| pushToken: v.string(), | ||
| }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId, pushToken }) => { | ||
| if (pushToken === "") { | ||
| ctx.logger.debug("Push token is empty, skipping"); | ||
| return; | ||
| } | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken !== null) { | ||
| ctx.logger.debug(`Push token already exists for user ${userId}, updating token`); | ||
| await ctx.db.patch(existingToken._id, { token: pushToken }); | ||
| return; | ||
| } | ||
| await ctx.db.insert("pushTokens", { userId, token: pushToken }); | ||
| }, | ||
| }); | ||
| export const removePushNotificationToken = mutation({ | ||
| args: { | ||
| userId: v.string(), | ||
| }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| await ctx.db.delete(existingToken._id); | ||
| }, | ||
| }); | ||
| const sendPushNotificationArgs = v.object({ | ||
| userId: v.string(), | ||
| notification: v.object(notificationFields), | ||
| allowUnregisteredTokens: v.optional(v.boolean()), | ||
| }); | ||
| export const sendPushNotification = mutation({ | ||
| args: sendPushNotificationArgs, | ||
| returns: v.union(v.id("notifications"), v.null()), | ||
| handler: async (ctx, args) => { | ||
| const result = await sendPushNotificationHandler(ctx, args); | ||
| await ensureCoordinator(ctx); | ||
| return result; | ||
| }, | ||
| }); | ||
| export const sendPushNotificationBatch = mutation({ | ||
| args: { | ||
| notifications: v.array(v.object({ | ||
| userId: v.string(), | ||
| notification: v.object(notificationFields), | ||
| })), | ||
| allowUnregisteredTokens: v.optional(v.boolean()), | ||
| }, | ||
| returns: v.array(v.union(v.id("notifications"), v.null())), | ||
| handler: async (ctx, args) => { | ||
| const results = []; | ||
| for (const { userId, notification } of args.notifications) { | ||
| const result = await sendPushNotificationHandler(ctx, { | ||
| userId, | ||
| notification, | ||
| allowUnregisteredTokens: args.allowUnregisteredTokens, | ||
| }); | ||
| results.push(result); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| return results; | ||
| }, | ||
| }); | ||
| async function sendPushNotificationHandler(ctx, args) { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| ctx.logger.error(`No push token found for user ${args.userId}, cannot send notification`); | ||
| if (args.allowUnregisteredTokens) { | ||
| return null; | ||
| } | ||
| throw new ConvexError({ | ||
| code: "NoPushToken", | ||
| message: "No push token found for user", | ||
| userId: args.userId, | ||
| notification: args.notification, | ||
| }); | ||
| } | ||
| if (token.notificationsPaused) { | ||
| ctx.logger.info(`Notifications are paused for user ${args.userId}, skipping`); | ||
| return null; | ||
| } | ||
| const id = await ctx.db.insert("notifications", { | ||
| token: token.token, | ||
| metadata: args.notification, | ||
| state: "awaiting_delivery", | ||
| numPreviousFailures: 0, | ||
| }); | ||
| ctx.logger.debug(`Recording notification for user ${args.userId}`); | ||
| return id; | ||
| } | ||
| export const getNotification = query({ | ||
| args: { id: v.id("notifications") }, | ||
| returns: v.union(v.null(), v.object({ | ||
| ...notificationFields, | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| _creationTime: v.number(), | ||
| })), | ||
| handler: async (ctx, args) => { | ||
| const notification = await ctx.db.get(args.id); | ||
| if (!notification) { | ||
| return null; | ||
| } | ||
| const { metadata, numPreviousFailures, state, _creationTime } = notification; | ||
| return { ...metadata, numPreviousFailures, state, _creationTime }; | ||
| }, | ||
| }); | ||
| export const getNotificationsForUser = query({ | ||
| args: { userId: v.string(), limit: v.optional(v.number()) }, | ||
| returns: v.array(v.object({ | ||
| ...notificationFields, | ||
| id: v.id("notifications"), | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| _creationTime: v.number(), | ||
| })), | ||
| handler: async (ctx, args) => { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| return []; | ||
| } | ||
| const notifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("token", (q) => q.eq("token", token.token)) | ||
| .order("desc") | ||
| .take(args.limit ?? DEFAULT_LIMIT); | ||
| return notifications.map(({ _id, metadata, state, numPreviousFailures, _creationTime }) => ({ | ||
| id: _id, | ||
| ...metadata, | ||
| state: state, | ||
| numPreviousFailures: numPreviousFailures, | ||
| _creationTime, | ||
| })); | ||
| }, | ||
| }); | ||
| export const deleteNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, args) => { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| ctx.logger.info("No push token found for user, nothing to delete"); | ||
| return; | ||
| } | ||
| const notifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("token", (q) => q.eq("token", token.token)) | ||
| .take(DEFAULT_LIMIT); | ||
| for (const notification of notifications) { | ||
| await ctx.db.delete(notification._id); | ||
| } | ||
| if (notifications.length > 0) { | ||
| ctx.logger.info(`Deleted ${notifications.length} notifications for user ${args.userId}`); | ||
| } | ||
| if (notifications.length === DEFAULT_LIMIT) { | ||
| ctx.logger.info(`Reached limit of ${DEFAULT_LIMIT} notifications for user ${args.userId},` + | ||
| ` scheduling another deletion`); | ||
| await ctx.scheduler.runAfter(0, api.public.deleteNotificationsForUser, { | ||
| ...args, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| } | ||
| }, | ||
| }); | ||
| // e.g. pause sending notifications while the user is active in the app | ||
| export const pauseNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| ctx.logger.info(`Pausing notifications for user ${userId}`); | ||
| await ctx.db.patch(existingToken._id, { | ||
| notificationsPaused: true, | ||
| }); | ||
| }, | ||
| }); | ||
| export const unpauseNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| ctx.logger.info(`Unpausing notifications for user ${userId}`); | ||
| await ctx.db.patch(existingToken._id, { | ||
| notificationsPaused: false, | ||
| }); | ||
| }, | ||
| }); | ||
| export const getStatusForUser = query({ | ||
| args: { userId: v.string() }, | ||
| returns: v.object({ hasToken: v.boolean(), paused: v.boolean() }), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, returning false`); | ||
| return { hasToken: false, paused: false }; | ||
| } | ||
| return { | ||
| hasToken: true, | ||
| paused: existingToken.notificationsPaused ?? false, | ||
| }; | ||
| }, | ||
| }); | ||
| export const shutdown = mutation({ | ||
| args: {}, | ||
| returns: v.object({ | ||
| message: v.string(), | ||
| data: v.optional(v.any()), | ||
| }), | ||
| handler: async (ctx) => { | ||
| const { inProgressSenders } = await shutdownGracefully(ctx); | ||
| if (inProgressSenders.length === 0) { | ||
| return { message: "success" }; | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config === null) { | ||
| ctx.logger.debug("No config found, creating it"); | ||
| await ctx.db.insert("config", { | ||
| state: "shutting_down", | ||
| }); | ||
| } | ||
| else { | ||
| await ctx.db.patch(config._id, { | ||
| state: "shutting_down", | ||
| }); | ||
| } | ||
| return { | ||
| message: `There are ${inProgressSenders.length} jobs currently sending notifications that will continue running. Wait a few seconds for them to finish and then restart the service.`, | ||
| data: { | ||
| inProgressSenderIds: inProgressSenders.map((sender) => sender._id), | ||
| }, | ||
| }; | ||
| }, | ||
| }); | ||
| export const restart = mutation({ | ||
| args: {}, | ||
| returns: v.boolean(), | ||
| handler: async (ctx) => { | ||
| const { inProgressSenders } = await shutdownGracefully(ctx); | ||
| if (inProgressSenders.length > 0) { | ||
| ctx.logger.error(`There are ${inProgressSenders.length} jobs currently sending notifications. Wait a few seconds for them to finish and try to restart again.`); | ||
| return false; | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config !== null) { | ||
| await ctx.db.patch(config._id, { | ||
| state: "running", | ||
| }); | ||
| } | ||
| else { | ||
| await ctx.db.insert("config", { | ||
| state: "running", | ||
| }); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| return true; | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=public.js.map |
| {"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/component/public.ts"],"names":[],"mappings":"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"} |
| export declare const notificationFields: { | ||
| _contentAvailable: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| data: import("convex/values").VAny<any, "optional", string>; | ||
| title: import("convex/values").VString<string | undefined, "optional">; | ||
| body: import("convex/values").VString<string | undefined, "optional">; | ||
| ttl: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| expiration: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| priority: import("convex/values").VUnion<"default" | "normal" | "high" | undefined, [import("convex/values").VLiteral<"default", "required">, import("convex/values").VLiteral<"normal", "required">, import("convex/values").VLiteral<"high", "required">], "optional", never>; | ||
| subtitle: import("convex/values").VString<string | undefined, "optional">; | ||
| sound: import("convex/values").VUnion<string | null | undefined, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "optional", never>; | ||
| badge: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| interruptionLevel: import("convex/values").VUnion<"active" | "critical" | "passive" | "time-sensitive" | undefined, [import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"critical", "required">, import("convex/values").VLiteral<"passive", "required">, import("convex/values").VLiteral<"time-sensitive", "required">], "optional", never>; | ||
| channelId: import("convex/values").VString<string | undefined, "optional">; | ||
| categoryId: import("convex/values").VString<string | undefined, "optional">; | ||
| mutableContent: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }; | ||
| /** | ||
| * Notification fields for push notifications. | ||
| */ | ||
| export type NotificationFields = { | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * When this is set to true, the notification will cause the iOS app to start in the background to run a background task. | ||
| * Your app needs to be configured to support this. | ||
| */ | ||
| _contentAvailable?: boolean; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * A JSON object delivered to your app. It may be up to about 4KiB; | ||
| * the total notification payload sent to Apple and Google must be at most 4KiB or else you will get a "Message Too Big" error. | ||
| */ | ||
| data?: any; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The title to display in the notification. Often displayed above the notification body. | ||
| * Maps to AndroidNotification.title and aps.alert.title. | ||
| */ | ||
| title: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The message to display in the notification. Maps to AndroidNotification.body and aps.alert.body. | ||
| */ | ||
| body?: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * Time to Live: the number of seconds for which the message may be kept around for redelivery | ||
| * if it hasn't been delivered yet. Defaults to undefined to use the respective defaults of each provider | ||
| * (1 month for Android/FCM as well as iOS/APNs). | ||
| */ | ||
| ttl?: number; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * Timestamp since the Unix epoch specifying when the message expires. | ||
| * Same effect as ttl (ttl takes precedence over expiration). | ||
| */ | ||
| expiration?: number; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The delivery priority of the message. | ||
| * Specify default or omit this field to use the default priority on each platform ("normal" on Android and "high" on iOS). | ||
| */ | ||
| priority?: "default" | "normal" | "high"; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * The subtitle to display in the notification below the title. | ||
| * Maps to aps.alert.subtitle. | ||
| */ | ||
| subtitle?: string; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Play a sound when the recipient receives this notification. Specify default to play the device's default notification sound, | ||
| * or omit this field to play no sound. Custom sounds need to be configured via the config plugin and | ||
| * then specified including the file extension. Example: bells_sound.wav. | ||
| */ | ||
| sound?: string | null; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Number to display in the badge on the app icon. Specify zero to clear the badge. | ||
| */ | ||
| badge?: number; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * The importance and delivery timing of a notification. | ||
| * The string values correspond to the UNNotificationInterruptionLevel enumeration cases. | ||
| */ | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| /** | ||
| * Android Only | ||
| * | ||
| * ID of the Notification Channel through which to display this notification. | ||
| * If an ID is specified but the corresponding channel does not exist on the device (that has not yet been created by your app), | ||
| * the notification will not be displayed to the user. | ||
| */ | ||
| channelId?: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * ID of the notification category that this notification is associated with. | ||
| */ | ||
| categoryId?: string; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Specifies whether this notification can be intercepted by the client app. | ||
| * Defaults to false. | ||
| */ | ||
| mutableContent?: boolean; | ||
| }; | ||
| export declare const notificationState: import("convex/values").VUnion<"awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver", [import("convex/values").VLiteral<"awaiting_delivery", "required">, import("convex/values").VLiteral<"in_progress", "required">, import("convex/values").VLiteral<"delivered", "required">, import("convex/values").VLiteral<"needs_retry", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"maybe_delivered", "required">, import("convex/values").VLiteral<"unable_to_deliver", "required">], "required", never>; | ||
| declare const _default: import("convex/server").SchemaDefinition<{ | ||
| notifications: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }, { | ||
| token: import("convex/values").VString<string, "required">; | ||
| metadata: import("convex/values").VObject<{ | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }, { | ||
| _contentAvailable: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| data: import("convex/values").VAny<any, "optional", string>; | ||
| title: import("convex/values").VString<string | undefined, "optional">; | ||
| body: import("convex/values").VString<string | undefined, "optional">; | ||
| ttl: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| expiration: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| priority: import("convex/values").VUnion<"default" | "normal" | "high" | undefined, [import("convex/values").VLiteral<"default", "required">, import("convex/values").VLiteral<"normal", "required">, import("convex/values").VLiteral<"high", "required">], "optional", never>; | ||
| subtitle: import("convex/values").VString<string | undefined, "optional">; | ||
| sound: import("convex/values").VUnion<string | null | undefined, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "optional", never>; | ||
| badge: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| interruptionLevel: import("convex/values").VUnion<"active" | "critical" | "passive" | "time-sensitive" | undefined, [import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"critical", "required">, import("convex/values").VLiteral<"passive", "required">, import("convex/values").VLiteral<"time-sensitive", "required">], "optional", never>; | ||
| channelId: import("convex/values").VString<string | undefined, "optional">; | ||
| categoryId: import("convex/values").VString<string | undefined, "optional">; | ||
| mutableContent: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }, "required", "_contentAvailable" | "data" | "title" | "body" | "ttl" | "expiration" | "priority" | "subtitle" | "sound" | "badge" | "interruptionLevel" | "channelId" | "categoryId" | "mutableContent" | `data.${string}`>; | ||
| state: import("convex/values").VUnion<"awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver", [import("convex/values").VLiteral<"awaiting_delivery", "required">, import("convex/values").VLiteral<"in_progress", "required">, import("convex/values").VLiteral<"delivered", "required">, import("convex/values").VLiteral<"needs_retry", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"maybe_delivered", "required">, import("convex/values").VLiteral<"unable_to_deliver", "required">], "required", never>; | ||
| numPreviousFailures: import("convex/values").VFloat64<number, "required">; | ||
| }, "required", "state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}`>, { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| }, {}, {}>; | ||
| pushTokens: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }, { | ||
| userId: import("convex/values").VString<string, "required">; | ||
| token: import("convex/values").VString<string, "required">; | ||
| notificationsPaused: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }, "required", "token" | "userId" | "notificationsPaused">, { | ||
| userId: ["userId", "_creationTime"]; | ||
| }, {}, {}>; | ||
| senders: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }, { | ||
| jobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| checkJobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| }, "required", "jobId" | "checkJobId">, {}, {}, {}>; | ||
| senderCoordinator: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }, { | ||
| jobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| }, "required", "jobId">, {}, {}, {}>; | ||
| config: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| state: "running" | "shutting_down"; | ||
| }, { | ||
| state: import("convex/values").VUnion<"running" | "shutting_down", [import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"shutting_down", "required">], "required", never>; | ||
| }, "required", "state">, {}, {}, {}>; | ||
| }, true>; | ||
| export default _default; | ||
| //# sourceMappingURL=schema.d.ts.map |
| {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;CAwB9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC;IAEX;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAEzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAEzE;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,imBAY7B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF,wBAwBG"} |
| import { defineSchema, defineTable } from "convex/server"; | ||
| import { v } from "convex/values"; | ||
| // https://docs.expo.dev/push-notifications/sending-notifications/#message-request-format | ||
| export const notificationFields = { | ||
| _contentAvailable: v.optional(v.boolean()), | ||
| data: v.optional(v.any()), | ||
| title: v.optional(v.string()), | ||
| body: v.optional(v.string()), | ||
| ttl: v.optional(v.number()), | ||
| expiration: v.optional(v.number()), | ||
| priority: v.optional(v.union(v.literal("default"), v.literal("normal"), v.literal("high"))), | ||
| subtitle: v.optional(v.string()), | ||
| sound: v.optional(v.union(v.string(), v.null())), | ||
| badge: v.optional(v.number()), | ||
| interruptionLevel: v.optional(v.union(v.literal("active"), v.literal("critical"), v.literal("passive"), v.literal("time-sensitive"))), | ||
| channelId: v.optional(v.string()), | ||
| categoryId: v.optional(v.string()), | ||
| mutableContent: v.optional(v.boolean()), | ||
| }; | ||
| export const notificationState = v.union(v.literal("awaiting_delivery"), v.literal("in_progress"), v.literal("delivered"), v.literal("needs_retry"), | ||
| // Expo returned a failure for this notification | ||
| v.literal("failed"), | ||
| // Failure before receiving confirmation of delivery, so not safe to retry | ||
| // without delivering twice | ||
| v.literal("maybe_delivered"), | ||
| // Exhausted retries to deliver | ||
| v.literal("unable_to_deliver")); | ||
| export default defineSchema({ | ||
| notifications: defineTable({ | ||
| token: v.string(), | ||
| metadata: v.object(notificationFields), | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| }) | ||
| .index("token", ["token"]) | ||
| .index("state", ["state"]), | ||
| pushTokens: defineTable({ | ||
| userId: v.string(), | ||
| token: v.string(), | ||
| notificationsPaused: v.optional(v.boolean()), | ||
| }).index("userId", ["userId"]), | ||
| senders: defineTable({ | ||
| jobId: v.id("_scheduled_functions"), | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| }), | ||
| senderCoordinator: defineTable({ | ||
| jobId: v.id("_scheduled_functions"), | ||
| }), | ||
| config: defineTable({ | ||
| state: v.union(v.literal("running"), v.literal("shutting_down")), | ||
| }), | ||
| }); | ||
| //# sourceMappingURL=schema.js.map |
| {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"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"} |
| import { type Infer } from "convex/values"; | ||
| export declare const logLevelValidator: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| export type LogLevel = Infer<typeof logLevelValidator>; | ||
| export declare const logWithLevel: (level: LogLevel, configuredLevel: LogLevel, ...args: unknown[]) => void; | ||
| export declare class Logger { | ||
| private configuredLevel; | ||
| constructor(configuredLevel: LogLevel); | ||
| get level(): "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| debug(...args: unknown[]): void; | ||
| info(...args: unknown[]): void; | ||
| warn(...args: unknown[]): void; | ||
| error(...args: unknown[]): void; | ||
| } | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAE9C,eAAO,MAAM,iBAAiB,oTAK7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEvD,eAAO,MAAM,YAAY,GACvB,OAAO,QAAQ,EACf,iBAAiB,QAAQ,EACzB,GAAG,MAAM,OAAO,EAAE,SAmBnB,CAAC;AAEF,qBAAa,MAAM;IACL,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,QAAQ;IAE7C,IAAI,KAAK,wCAER;IAED,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIxB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIvB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIvB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;CAGzB"} |
| import { v } from "convex/values"; | ||
| export const logLevelValidator = v.union(v.literal("DEBUG"), v.literal("INFO"), v.literal("WARN"), v.literal("ERROR")); | ||
| const orderedLevels = ["DEBUG", "INFO", "WARN", "ERROR"]; | ||
| export const logWithLevel = (level, configuredLevel, ...args) => { | ||
| if (orderedLevels.indexOf(level) < orderedLevels.indexOf(configuredLevel)) { | ||
| return; | ||
| } | ||
| switch (level) { | ||
| case "DEBUG": | ||
| console.debug(...args); | ||
| break; | ||
| case "INFO": | ||
| console.info(...args); | ||
| break; | ||
| case "WARN": | ||
| console.warn(...args); | ||
| break; | ||
| case "ERROR": | ||
| console.error(...args); | ||
| break; | ||
| } | ||
| }; | ||
| export class Logger { | ||
| configuredLevel; | ||
| constructor(configuredLevel) { | ||
| this.configuredLevel = configuredLevel; | ||
| } | ||
| get level() { | ||
| return this.configuredLevel; | ||
| } | ||
| debug(...args) { | ||
| logWithLevel("DEBUG", this.configuredLevel, ...args); | ||
| } | ||
| info(...args) { | ||
| logWithLevel("INFO", this.configuredLevel, ...args); | ||
| } | ||
| warn(...args) { | ||
| logWithLevel("WARN", this.configuredLevel, ...args); | ||
| } | ||
| error(...args) { | ||
| logWithLevel("ERROR", this.configuredLevel, ...args); | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAc,MAAM,eAAe,CAAC;AAE9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CACtC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAClB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CACnB,CAAC;AAGF,MAAM,aAAa,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAe,EACf,eAAyB,EACzB,GAAG,IAAe,EAClB,EAAE;IACF,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC1E,OAAO;IACT,CAAC;IACD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,MAAM;QACR,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,MAAM;IACV,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,MAAM;IACG;IAApB,YAAoB,eAAyB;QAAzB,oBAAe,GAAf,eAAe,CAAU;IAAG,CAAC;IAEjD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;CACF"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type * as functions from "../functions.js"; | ||
| import type * as helpers from "../helpers.js"; | ||
| import type * as internal_ from "../internal.js"; | ||
| import type * as public_ from "../public.js"; | ||
| import type { | ||
| ApiFromModules, | ||
| FilterApi, | ||
| FunctionReference, | ||
| } from "convex/server"; | ||
| import { anyApi, componentsGeneric } from "convex/server"; | ||
| const fullApi: ApiFromModules<{ | ||
| functions: typeof functions; | ||
| helpers: typeof helpers; | ||
| internal: typeof internal_; | ||
| public: typeof public_; | ||
| }> = anyApi as any; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's public API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api: FilterApi< | ||
| typeof fullApi, | ||
| FunctionReference<any, "public"> | ||
| > = anyApi as any; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's internal API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = internal.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const internal: FilterApi< | ||
| typeof fullApi, | ||
| FunctionReference<any, "internal"> | ||
| > = anyApi as any; | ||
| export const components = componentsGeneric() as unknown as {}; |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `ComponentApi` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { FunctionReference } from "convex/server"; | ||
| /** | ||
| * A utility for referencing a Convex component's exposed API. | ||
| * | ||
| * Useful when expecting a parameter like `components.myComponent`. | ||
| * Usage: | ||
| * ```ts | ||
| * async function myFunction(ctx: QueryCtx, component: ComponentApi) { | ||
| * return ctx.runQuery(component.someFile.someQuery, { ...args }); | ||
| * } | ||
| * ``` | ||
| */ | ||
| export type ComponentApi<Name extends string | undefined = string | undefined> = | ||
| { | ||
| public: { | ||
| deleteNotificationsForUser: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null, | ||
| Name | ||
| >; | ||
| getNotification: FunctionReference< | ||
| "query", | ||
| "internal", | ||
| { id: string; logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR" }, | ||
| null | { | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: | ||
| | "awaiting_delivery" | ||
| | "in_progress" | ||
| | "delivered" | ||
| | "needs_retry" | ||
| | "failed" | ||
| | "maybe_delivered" | ||
| | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }, | ||
| Name | ||
| >; | ||
| getNotificationsForUser: FunctionReference< | ||
| "query", | ||
| "internal", | ||
| { | ||
| limit?: number; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, | ||
| Array<{ | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| id: string; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: | ||
| | "awaiting_delivery" | ||
| | "in_progress" | ||
| | "delivered" | ||
| | "needs_retry" | ||
| | "failed" | ||
| | "maybe_delivered" | ||
| | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }>, | ||
| Name | ||
| >; | ||
| getStatusForUser: FunctionReference< | ||
| "query", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| { hasToken: boolean; paused: boolean }, | ||
| Name | ||
| >; | ||
| pauseNotificationsForUser: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null, | ||
| Name | ||
| >; | ||
| recordPushNotificationToken: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| pushToken: string; | ||
| userId: string; | ||
| }, | ||
| null, | ||
| Name | ||
| >; | ||
| removePushNotificationToken: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null, | ||
| Name | ||
| >; | ||
| restart: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR" }, | ||
| boolean, | ||
| Name | ||
| >; | ||
| sendPushNotification: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { | ||
| allowUnregisteredTokens?: boolean; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| notification: { | ||
| _contentAvailable?: boolean; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }; | ||
| userId: string; | ||
| }, | ||
| string | null, | ||
| Name | ||
| >; | ||
| sendPushNotificationBatch: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { | ||
| allowUnregisteredTokens?: boolean; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| notifications: Array<{ | ||
| notification: { | ||
| _contentAvailable?: boolean; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }; | ||
| userId: string; | ||
| }>; | ||
| }, | ||
| Array<string | null>, | ||
| Name | ||
| >; | ||
| shutdown: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR" }, | ||
| { data?: any; message: string }, | ||
| Name | ||
| >; | ||
| unpauseNotificationsForUser: FunctionReference< | ||
| "mutation", | ||
| "internal", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null, | ||
| Name | ||
| >; | ||
| }; | ||
| }; |
| /* eslint-disable */ | ||
| /** | ||
| * Generated data model types. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { | ||
| DataModelFromSchemaDefinition, | ||
| DocumentByName, | ||
| TableNamesInDataModel, | ||
| SystemTableNames, | ||
| } from "convex/server"; | ||
| import type { GenericId } from "convex/values"; | ||
| import schema from "../schema.js"; | ||
| /** | ||
| * The names of all of your Convex tables. | ||
| */ | ||
| export type TableNames = TableNamesInDataModel<DataModel>; | ||
| /** | ||
| * The type of a document stored in Convex. | ||
| * | ||
| * @typeParam TableName - A string literal type of the table name (like "users"). | ||
| */ | ||
| export type Doc<TableName extends TableNames> = DocumentByName< | ||
| DataModel, | ||
| TableName | ||
| >; | ||
| /** | ||
| * An identifier for a document in Convex. | ||
| * | ||
| * Convex documents are uniquely identified by their `Id`, which is accessible | ||
| * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids). | ||
| * | ||
| * Documents can be loaded using `db.get(id)` in query and mutation functions. | ||
| * | ||
| * IDs are just strings at runtime, but this type can be used to distinguish them from other | ||
| * strings when type checking. | ||
| * | ||
| * @typeParam TableName - A string literal type of the table name (like "users"). | ||
| */ | ||
| export type Id<TableName extends TableNames | SystemTableNames> = | ||
| GenericId<TableName>; | ||
| /** | ||
| * A type describing your Convex data model. | ||
| * | ||
| * This type includes information about what tables you have, the type of | ||
| * documents stored in those tables, and the indexes defined on them. | ||
| * | ||
| * This type is used to parameterize methods like `queryGeneric` and | ||
| * `mutationGeneric` to make them type-safe. | ||
| */ | ||
| export type DataModel = DataModelFromSchemaDefinition<typeof schema>; |
| /* eslint-disable */ | ||
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { | ||
| ActionBuilder, | ||
| HttpActionBuilder, | ||
| MutationBuilder, | ||
| QueryBuilder, | ||
| GenericActionCtx, | ||
| GenericMutationCtx, | ||
| GenericQueryCtx, | ||
| GenericDatabaseReader, | ||
| GenericDatabaseWriter, | ||
| } from "convex/server"; | ||
| import { | ||
| actionGeneric, | ||
| httpActionGeneric, | ||
| queryGeneric, | ||
| mutationGeneric, | ||
| internalActionGeneric, | ||
| internalMutationGeneric, | ||
| internalQueryGeneric, | ||
| } from "convex/server"; | ||
| import type { DataModel } from "./dataModel.js"; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query: QueryBuilder<DataModel, "public"> = queryGeneric; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery: QueryBuilder<DataModel, "internal"> = | ||
| internalQueryGeneric; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation: MutationBuilder<DataModel, "public"> = mutationGeneric; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation: MutationBuilder<DataModel, "internal"> = | ||
| internalMutationGeneric; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action: ActionBuilder<DataModel, "public"> = actionGeneric; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction: ActionBuilder<DataModel, "internal"> = | ||
| internalActionGeneric; | ||
| /** | ||
| * Define an HTTP action. | ||
| * | ||
| * The wrapped function will be used to respond to HTTP requests received | ||
| * by a Convex deployment if the requests matches the path and method where | ||
| * this action is routed. Be sure to route your httpAction in `convex/http.js`. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument | ||
| * and a Fetch API `Request` object as its second. | ||
| * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up. | ||
| */ | ||
| export const httpAction: HttpActionBuilder = httpActionGeneric; | ||
| type GenericCtx = | ||
| | GenericActionCtx<DataModel> | ||
| | GenericMutationCtx<DataModel> | ||
| | GenericQueryCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex query functions. | ||
| * | ||
| * The query context is passed as the first argument to any Convex query | ||
| * function run on the server. | ||
| * | ||
| * If you're using code generation, use the `QueryCtx` type in `convex/_generated/server.d.ts` instead. | ||
| */ | ||
| export type QueryCtx = GenericQueryCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex mutation functions. | ||
| * | ||
| * The mutation context is passed as the first argument to any Convex mutation | ||
| * function run on the server. | ||
| * | ||
| * If you're using code generation, use the `MutationCtx` type in `convex/_generated/server.d.ts` instead. | ||
| */ | ||
| export type MutationCtx = GenericMutationCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex action functions. | ||
| * | ||
| * The action context is passed as the first argument to any Convex action | ||
| * function run on the server. | ||
| */ | ||
| export type ActionCtx = GenericActionCtx<DataModel>; | ||
| /** | ||
| * An interface to read from the database within Convex query functions. | ||
| * | ||
| * The two entry points are {@link DatabaseReader.get}, which fetches a single | ||
| * document by its {@link Id}, or {@link DatabaseReader.query}, which starts | ||
| * building a query. | ||
| */ | ||
| export type DatabaseReader = GenericDatabaseReader<DataModel>; | ||
| /** | ||
| * An interface to read from and write to the database within Convex mutation | ||
| * functions. | ||
| * | ||
| * Convex guarantees that all writes within a single mutation are | ||
| * executed atomically, so you never have to worry about partial writes leaving | ||
| * your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control) | ||
| * for the guarantees Convex provides your functions. | ||
| */ | ||
| export type DatabaseWriter = GenericDatabaseWriter<DataModel>; |
+18
| /// <reference types="vite/client" /> | ||
| import type { TestConvex } from "convex-test"; | ||
| import type { GenericSchema, SchemaDefinition } from "convex/server"; | ||
| import schema from "./component/schema.js"; | ||
| const modules = import.meta.glob("./component/**/*.ts"); | ||
| /** | ||
| * Register the component with the test convex instance. | ||
| * @param t - The test convex instance, e.g. from calling `convexTest`. | ||
| * @param name - The name of the component, as registered in convex.config.ts. | ||
| */ | ||
| export function register( | ||
| t: TestConvex<SchemaDefinition<GenericSchema, boolean>>, | ||
| name: string = "pushNotifications", | ||
| ) { | ||
| t.registerComponent(name, schema, modules); | ||
| } | ||
| export default { register, schema, modules }; |
+49
-31
@@ -10,3 +10,3 @@ { | ||
| }, | ||
| "version": "0.2.7-alpha.0", | ||
| "version": "0.3.0", | ||
| "license": "Apache-2.0", | ||
@@ -21,11 +21,20 @@ "keywords": [ | ||
| "scripts": { | ||
| "build": "npm run build:esm && npm run build:cjs", | ||
| "build:esm": "tsc --project ./esm.json && echo '{\\n \"type\": \"module\"\\n}' > dist/esm/package.json", | ||
| "build:cjs": "tsc --project ./commonjs.json && echo '{\\n \"type\": \"commonjs\"\\n}' > dist/commonjs/package.json", | ||
| "dev": "cd example; npm run dev", | ||
| "alpha": "rm -rf dist && npm run build && npm run test && npm version prerelease --preid alpha && npm publish --tag alpha && git push --tags", | ||
| "release": "rm -rf dist && npm run build && npm run test && npm version patch && npm publish && git push --tags", | ||
| "test": "cd example && npm run lint", | ||
| "typecheck": "tsc --noEmit", | ||
| "prepare": "npm run build" | ||
| "dev": "run-p -r 'dev:*'", | ||
| "dev:backend": "convex dev --typecheck-components", | ||
| "dev:expo": "cd example && npx expo start", | ||
| "dev:build": "chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.ts' -c 'convex codegen --component-dir ./src/component && npm run build' --initial", | ||
| "setup": "npm install && cd example && npm install && cd .. && npm run dev:backend -- --until-success && printf 'EXPO_PUBLIC_CONVEX_URL=' >> example/.env.local && npx convex env get CONVEX_CLOUD_URL >> example/.env.local", | ||
| "clean": "rm -rf dist *.tsbuildinfo", | ||
| "build": "tsc --project ./tsconfig.build.json", | ||
| "typecheck": "tsc --noEmit && tsc -p example && tsc -p example/convex", | ||
| "lint": "eslint . && cd example && npm run lint", | ||
| "all": "run-p -r 'dev:*' 'test:watch'", | ||
| "test": "vitest run --typecheck", | ||
| "test:watch": "vitest --typecheck --clearScreen false", | ||
| "test:debug": "vitest --inspect-brk --no-file-parallelism", | ||
| "test:coverage": "vitest run --coverage --coverage.reporter=text", | ||
| "prepare": "npm run build", | ||
| "alpha": "npm run clean && npm ci && run-p test lint typecheck && npm version prerelease --preid alpha && npm publish --tag alpha && git push --tags", | ||
| "release": "npm run clean && npm ci && run-p test lint typecheck && npm version patch && npm publish && git push --tags", | ||
| "version": "pbcopy <<<$npm_package_version; vim CHANGELOG.md && prettier -w CHANGELOG.md && git add CHANGELOG.md" | ||
| }, | ||
@@ -39,23 +48,20 @@ "files": [ | ||
| ".": { | ||
| "import": { | ||
| "@convex-dev/component-source": "./src/client/index.ts", | ||
| "types": "./dist/esm/client/index.d.ts", | ||
| "default": "./dist/esm/client/index.js" | ||
| }, | ||
| "require": { | ||
| "@convex-dev/component-source": "./src/client/index.ts", | ||
| "types": "./dist/commonjs/client/index.d.ts", | ||
| "default": "./dist/commonjs/client/index.js" | ||
| } | ||
| "types": "./dist/client/index.d.ts", | ||
| "default": "./dist/client/index.js" | ||
| }, | ||
| "./test": "./src/test.ts", | ||
| "./_generated/component.js": { | ||
| "types": "./dist/component/_generated/component.d.ts" | ||
| }, | ||
| "./convex.config": { | ||
| "import": { | ||
| "@convex-dev/component-source": "./src/component/convex.config.ts", | ||
| "types": "./dist/esm/component/convex.config.d.ts", | ||
| "default": "./dist/esm/component/convex.config.js" | ||
| } | ||
| "types": "./dist/component/convex.config.d.ts", | ||
| "default": "./dist/component/convex.config.js" | ||
| }, | ||
| "./convex.config.js": { | ||
| "types": "./dist/component/convex.config.d.ts", | ||
| "default": "./dist/component/convex.config.js" | ||
| } | ||
| }, | ||
| "peerDependencies": { | ||
| "convex": ">=1.23.0 <1.35.0" | ||
| "convex": "^1.24.8" | ||
| }, | ||
@@ -66,13 +72,25 @@ "dependencies": { | ||
| "devDependencies": { | ||
| "@edge-runtime/vm": "5.0.0", | ||
| "@eslint/eslintrc": "^3.1.0", | ||
| "@eslint/js": "^9.9.1", | ||
| "@types/node": "^18.17.0", | ||
| "@types/node": "20.19.24", | ||
| "@typescript-eslint/eslint-plugin": "8.46.4", | ||
| "@vitejs/plugin-react": "^4.3.1", | ||
| "chokidar-cli": "3.0.0", | ||
| "convex": "1.29.0", | ||
| "convex-helpers": "0.1.104", | ||
| "convex-test": "^0.0.38", | ||
| "eslint": "^9.9.1", | ||
| "eslint-plugin-react-hooks": "^7.0.1", | ||
| "eslint-plugin-react-refresh": "^0.4.24", | ||
| "globals": "^15.9.0", | ||
| "npm-run-all2": "8.0.4", | ||
| "prettier": "3.2.5", | ||
| "typescript": "^5.8.3", | ||
| "typescript-eslint": "^8.4.0" | ||
| "typescript-eslint": "8.46.4", | ||
| "vite": "^7.1.12", | ||
| "vitest": "^3.2.4" | ||
| }, | ||
| "main": "./dist/commonjs/client/index.js", | ||
| "types": "./dist/commonjs/client/index.d.ts", | ||
| "module": "./dist/esm/client/index.js" | ||
| "types": "./dist/client/index.d.ts", | ||
| "module": "./dist/client/index.js" | ||
| } |
+29
-17
@@ -7,4 +7,6 @@ # Convex Push Notifications Component | ||
| This is a Convex component that integrates with [Expo's push notification API](https://docs.expo.dev/push-notifications/overview/) | ||
| to allow sending mobile push notifications to users of your app. It will batch calls to Expo's API and handle retrying delivery. | ||
| This is a Convex component that integrates with | ||
| [Expo's push notification API](https://docs.expo.dev/push-notifications/overview/) | ||
| to allow sending mobile push notifications to users of your app. It will batch | ||
| calls to Expo's API and handle retrying delivery. | ||
@@ -55,7 +57,8 @@ <details> | ||
| You'll need an existing Convex project to use the component. | ||
| Convex is a hosted backend platform, including a database, serverless functions, | ||
| and a ton more you can learn about [here](https://docs.convex.dev/get-started). | ||
| You'll need an existing Convex project to use the component. Convex is a hosted | ||
| backend platform, including a database, serverless functions, and a ton more you | ||
| can learn about [here](https://docs.convex.dev/get-started). | ||
| Run `npm create convex` or follow any of the [quickstarts](https://docs.convex.dev/home) to set one up. | ||
| Run `npm create convex` or follow any of the | ||
| [quickstarts](https://docs.convex.dev/home) to set one up. | ||
@@ -70,3 +73,4 @@ ## Installation | ||
| Create a `convex.config.ts` file in your app's `convex/` folder and install the component by calling `use`: | ||
| Create a `convex.config.ts` file in your app's `convex/` folder and install the | ||
| component by calling `use`: | ||
@@ -76,3 +80,3 @@ ```ts | ||
| import { defineApp } from "convex/server"; | ||
| import pushNotifications from "@convex-dev/expo-push-notifications/convex.config"; | ||
| import pushNotifications from "@convex-dev/expo-push-notifications/convex.config.js"; | ||
@@ -95,3 +99,4 @@ const app = defineApp(); | ||
| It takes in an optional type parameter (defaulting to `Id<"users">`) for the type to use as a unique identifier for push notification recipients: | ||
| It takes in an optional type parameter (defaulting to `Id<"users">`) for the | ||
| type to use as a unique identifier for push notification recipients: | ||
@@ -104,3 +109,3 @@ ```ts | ||
| const pushNotifications = new PushNotifications<Email>( | ||
| components.pushNotifications | ||
| components.pushNotifications, | ||
| ); | ||
@@ -111,3 +116,5 @@ ``` | ||
| Get a user's push notification token following the Expo documentation [here](https://docs.expo.dev/push-notifications/push-notifications-setup/#registering-for-push-notifications), and record it using a Convex mutation: | ||
| Get a user's push notification token following the Expo documentation | ||
| [here](https://docs.expo.dev/push-notifications/push-notifications-setup/#registering-for-push-notifications), | ||
| and record it using a Convex mutation: | ||
@@ -128,5 +135,7 @@ ```ts | ||
| You can pause and resume push notification sending for a user using the `pausePushNotifications` and `resumePushNotifications` methods. | ||
| You can pause and resume push notification sending for a user using the | ||
| `pausePushNotifications` and `resumePushNotifications` methods. | ||
| To determine if a user has a token and their pause status, you can use `getStatusForUser`. | ||
| To determine if a user has a token and their pause status, you can use | ||
| `getStatusForUser`. | ||
@@ -150,4 +159,5 @@ ## Send notifications | ||
| You can use the ID returned from `sendPushNotifications` to query the status of the notification using `getNotification`. | ||
| Using this in a query allows you to subscribe to the status of a notification. | ||
| You can use the ID returned from `sendPushNotifications` to query the status of | ||
| the notification using `getNotification`. Using this in a query allows you to | ||
| subscribe to the status of a notification. | ||
@@ -158,3 +168,4 @@ You can also view all notifications for a user with `getNotificationsForUser`. | ||
| To add more logging, provide `PushNotifications` with a `logLevel` in the constructor: | ||
| To add more logging, provide `PushNotifications` with a `logLevel` in the | ||
| constructor: | ||
@@ -167,4 +178,5 @@ ```ts | ||
| The push notification sender can be shutdown gracefully, and then restarted using the `shutdown` and `restart` methods. | ||
| The push notification sender can be shutdown gracefully, and then restarted | ||
| using the `shutdown` and `restart` methods. | ||
| <!-- END: Include on https://convex.dev/components --> |
+11
-40
@@ -1,4 +0,2 @@ | ||
| import { | ||
| Expand, | ||
| FunctionReference, | ||
| import type { | ||
| GenericDataModel, | ||
@@ -8,6 +6,6 @@ GenericMutationCtx, | ||
| } from "convex/server"; | ||
| import { GenericId } from "convex/values"; | ||
| import { api } from "../component/_generated/api.js"; | ||
| import { NotificationFields } from "../component/schema.js"; | ||
| import { LogLevel } from "../logging/index.js"; | ||
| import type { GenericId } from "convex/values"; | ||
| import type { NotificationFields } from "../component/schema.js"; | ||
| import type { LogLevel } from "../logging/index.js"; | ||
| import type { ComponentApi } from "../component/_generated/component.js"; | ||
@@ -29,6 +27,6 @@ /** | ||
| constructor( | ||
| public component: UseApi<typeof api>, | ||
| public component: ComponentApi, | ||
| config?: { | ||
| logLevel?: LogLevel; | ||
| } | ||
| }, | ||
| ) { | ||
@@ -49,3 +47,3 @@ this.component = component; | ||
| ctx: RunMutationCtx, | ||
| args: { userId: UserType; pushToken: string } | ||
| args: { userId: UserType; pushToken: string }, | ||
| ): Promise<null> { | ||
@@ -100,3 +98,3 @@ return ctx.runMutation(this.component.public.recordPushNotificationToken, { | ||
| allowUnregisteredTokens?: boolean; | ||
| } | ||
| }, | ||
| ) { | ||
@@ -124,3 +122,3 @@ return ctx.runMutation(this.component.public.sendPushNotification, { | ||
| allowUnregisteredTokens?: boolean; | ||
| } | ||
| }, | ||
| ) { | ||
@@ -149,3 +147,3 @@ return ctx.runMutation(this.component.public.sendPushNotificationBatch, { | ||
| ctx: RunQueryCtx, | ||
| args: { userId: UserType; limit?: number } | ||
| args: { userId: UserType; limit?: number }, | ||
| ) { | ||
@@ -231,28 +229,1 @@ return ctx.runQuery(this.component.public.getNotificationsForUser, { | ||
| }; | ||
| export type OpaqueIds<T> = | ||
| T extends GenericId<infer _T> | ||
| ? string | ||
| : T extends (infer U)[] | ||
| ? OpaqueIds<U>[] | ||
| : T extends object | ||
| ? { [K in keyof T]: OpaqueIds<T[K]> } | ||
| : T; | ||
| export type UseApi<API> = Expand<{ | ||
| [mod in keyof API]: API[mod] extends FunctionReference< | ||
| infer FType, | ||
| "public", | ||
| infer FArgs, | ||
| infer FReturnType, | ||
| infer FComponentPath | ||
| > | ||
| ? FunctionReference< | ||
| FType, | ||
| "internal", | ||
| OpaqueIds<FArgs>, | ||
| OpaqueIds<FReturnType>, | ||
| FComponentPath | ||
| > | ||
| : UseApi<API[mod]>; | ||
| }>; |
| import { | ||
| customAction, | ||
| CustomCtx, | ||
| type CustomCtx, | ||
| customMutation, | ||
@@ -5,0 +5,0 @@ customQuery, |
@@ -1,4 +0,4 @@ | ||
| import { MutationCtx } from "./functions.js"; | ||
| import type { MutationCtx } from "./functions.js"; | ||
| import { internal } from "./_generated/api.js"; | ||
| import { Doc } from "./_generated/dataModel.js"; | ||
| import type { Doc } from "./_generated/dataModel.js"; | ||
@@ -22,3 +22,3 @@ export async function ensureCoordinator(ctx: MutationCtx) { | ||
| ctx.logger.debug( | ||
| `Found existing coordinator with ID ${activeCoordinators[0]._id}` | ||
| `Found existing coordinator with ID ${activeCoordinators[0]._id}`, | ||
| ); | ||
@@ -29,6 +29,6 @@ return; | ||
| ctx.logger.error( | ||
| `Unexpected state: Too many coordinators ${activeCoordinators.length}` | ||
| `Unexpected state: Too many coordinators ${activeCoordinators.length}`, | ||
| ); | ||
| throw new Error( | ||
| `Unexpected state: Too many coordinators ${activeCoordinators.length}` | ||
| `Unexpected state: Too many coordinators ${activeCoordinators.length}`, | ||
| ); | ||
@@ -46,3 +46,3 @@ } | ||
| logLevel: ctx.logger.level, | ||
| } | ||
| }, | ||
| ); | ||
@@ -93,4 +93,3 @@ const coordinatorId = await ctx.db.insert("senderCoordinator", { | ||
| ctx.logger.error( | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| `Unknown job state ${(job.state as any).kind} for sender ${sender._id}. Cleaning it up. ` | ||
| `Unknown job state ${(job.state as any).kind} for sender ${sender._id}. Cleaning it up. `, | ||
| ); | ||
@@ -97,0 +96,0 @@ await ctx.db.delete(sender._id); |
@@ -1,5 +0,5 @@ | ||
| import { JSONValue, v } from "convex/values"; | ||
| import { v, type JSONValue } from "convex/values"; | ||
| import { internalAction, internalMutation } from "./functions.js"; | ||
| import { internal } from "./_generated/api.js"; | ||
| import { Id } from "./_generated/dataModel.js"; | ||
| import type { Id } from "./_generated/dataModel.js"; | ||
| import { ensureCoordinator } from "./helpers.js"; | ||
@@ -16,5 +16,5 @@ import { notificationFields } from "./schema.js"; | ||
| v.literal("failed"), | ||
| v.literal("maybe_delivered") | ||
| v.literal("maybe_delivered"), | ||
| ), | ||
| }) | ||
| }), | ||
| ), | ||
@@ -75,3 +75,3 @@ checkJobId: v.id("_scheduled_functions"), | ||
| ctx.logger.debug( | ||
| `Found ${retryNotifications.length} retry notifications and ${unsentNotifications.length} unsent notifications` | ||
| `Found ${retryNotifications.length} retry notifications and ${unsentNotifications.length} unsent notifications`, | ||
| ); | ||
@@ -106,6 +106,6 @@ const notificationsToProcess = [ | ||
| ctx.logger.debug( | ||
| `Not starting another sender: already ${numActiveSenders}` | ||
| `Not starting another sender: already ${numActiveSenders}`, | ||
| ); | ||
| ctx.logger.debug( | ||
| `When one sender finishes, or fails, we'll coordinate sending these notifications.` | ||
| `When one sender finishes, or fails, we'll coordinate sending these notifications.`, | ||
| ); | ||
@@ -115,6 +115,6 @@ return; | ||
| const notificationsToSend = notificationsToProcess.filter( | ||
| (n) => n.numPreviousFailures < MAX_RETRY_ATTEMPTS | ||
| (n) => n.numPreviousFailures < MAX_RETRY_ATTEMPTS, | ||
| ); | ||
| const notificationsToMarkAsUnableToDeliver = notificationsToProcess.filter( | ||
| (n) => n.numPreviousFailures >= MAX_RETRY_ATTEMPTS | ||
| (n) => n.numPreviousFailures >= MAX_RETRY_ATTEMPTS, | ||
| ); | ||
@@ -141,3 +141,3 @@ | ||
| logLevel: ctx.logger.level, | ||
| } | ||
| }, | ||
| ); | ||
@@ -173,3 +173,3 @@ | ||
| logLevel: ctx.logger.level, | ||
| } | ||
| }, | ||
| ); | ||
@@ -181,3 +181,3 @@ await ctx.db.insert("senders", { | ||
| ctx.logger.debug( | ||
| `Started a new sender ${senderJobId} with job ${senderJobId} and check job ${checkJobId}` | ||
| `Started a new sender ${senderJobId} with job ${senderJobId} and check job ${checkJobId}`, | ||
| ); | ||
@@ -194,3 +194,3 @@ }, | ||
| `Could not determine delivery status for ${notificationIds.length} notifications:`, | ||
| notificationIds | ||
| notificationIds, | ||
| ); | ||
@@ -215,6 +215,6 @@ for (const notificationId of notificationIds) { | ||
| to: v.string(), | ||
| ...notificationFields | ||
| ...notificationFields, | ||
| }), | ||
| _id: v.id("notifications"), | ||
| }) | ||
| }), | ||
| ), | ||
@@ -224,6 +224,6 @@ }, | ||
| ctx.logger.debug( | ||
| `Sending ${args.notifications.length} push notifications via Expo's API` | ||
| `Sending ${args.notifications.length} push notifications via Expo's API`, | ||
| ); | ||
| ctx.logger.debug( | ||
| `Notification IDs: ${JSON.stringify(args.notifications.map((n) => n._id))}` | ||
| `Notification IDs: ${JSON.stringify(args.notifications.map((n) => n._id))}`, | ||
| ); | ||
@@ -245,6 +245,6 @@ let response: Response; | ||
| "Failed during during fetch for sending push notifications:", | ||
| _e | ||
| _e, | ||
| ); | ||
| ctx.logger.debug( | ||
| `Marking ${args.notifications.length} notifications as failed so they can be retried` | ||
| `Marking ${args.notifications.length} notifications as failed so they can be retried`, | ||
| ); | ||
@@ -267,6 +267,6 @@ await ctx.runMutation(internal.internal.markNotificationState, { | ||
| ctx.logger.warn( | ||
| `Push notification failed with status ${response.status} and body ${await response.text()}` | ||
| `Push notification failed with status ${response.status} and body ${await response.text()}`, | ||
| ); | ||
| ctx.logger.debug( | ||
| `Marking ${args.notifications.length} notifications as maybe delivered. They won't be retried.` | ||
| `Marking ${args.notifications.length} notifications as maybe delivered. They won't be retried.`, | ||
| ); | ||
@@ -294,3 +294,3 @@ await ctx.runMutation(internal.internal.markNotificationState, { | ||
| ctx.logger.debug( | ||
| `Response from Expo's API: ${JSON.stringify(responseBody)}` | ||
| `Response from Expo's API: ${JSON.stringify(responseBody)}`, | ||
| ); | ||
@@ -318,3 +318,3 @@ | ||
| ctx.logger.debug( | ||
| `Successfully parsed response from Expo, and recording state` | ||
| `Successfully parsed response from Expo, and recording state`, | ||
| ); | ||
@@ -321,0 +321,0 @@ await ctx.runMutation(internal.internal.markNotificationState, { |
+15
-14
@@ -1,3 +0,3 @@ | ||
| import { ConvexError, Infer, v } from "convex/values"; | ||
| import { mutation, MutationCtx, query } from "./functions.js"; | ||
| import { ConvexError, v, type Infer } from "convex/values"; | ||
| import { mutation, query, type MutationCtx } from "./functions.js"; | ||
| import { notificationFields, notificationState } from "./schema.js"; | ||
@@ -26,3 +26,3 @@ import { ensureCoordinator, shutdownGracefully } from "./helpers.js"; | ||
| ctx.logger.debug( | ||
| `Push token already exists for user ${userId}, updating token` | ||
| `Push token already exists for user ${userId}, updating token`, | ||
| ); | ||
@@ -76,3 +76,3 @@ await ctx.db.patch(existingToken._id, { token: pushToken }); | ||
| notification: v.object(notificationFields), | ||
| }) | ||
| }), | ||
| ), | ||
@@ -99,3 +99,3 @@ allowUnregisteredTokens: v.optional(v.boolean()), | ||
| ctx: MutationCtx, | ||
| args: Infer<typeof sendPushNotificationArgs> | ||
| args: Infer<typeof sendPushNotificationArgs>, | ||
| ) { | ||
@@ -108,3 +108,3 @@ const token = await ctx.db | ||
| ctx.logger.error( | ||
| `No push token found for user ${args.userId}, cannot send notification` | ||
| `No push token found for user ${args.userId}, cannot send notification`, | ||
| ); | ||
@@ -123,3 +123,3 @@ if (args.allowUnregisteredTokens) { | ||
| ctx.logger.info( | ||
| `Notifications are paused for user ${args.userId}, skipping` | ||
| `Notifications are paused for user ${args.userId}, skipping`, | ||
| ); | ||
@@ -147,3 +147,3 @@ return null; | ||
| _creationTime: v.number(), | ||
| }) | ||
| }), | ||
| ), | ||
@@ -170,3 +170,3 @@ handler: async (ctx, args) => { | ||
| _creationTime: v.number(), | ||
| }) | ||
| }), | ||
| ), | ||
@@ -193,3 +193,3 @@ handler: async (ctx, args) => { | ||
| _creationTime, | ||
| }) | ||
| }), | ||
| ); | ||
@@ -201,2 +201,3 @@ }, | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, args) => { | ||
@@ -220,3 +221,3 @@ const token = await ctx.db | ||
| ctx.logger.info( | ||
| `Deleted ${notifications.length} notifications for user ${args.userId}` | ||
| `Deleted ${notifications.length} notifications for user ${args.userId}`, | ||
| ); | ||
@@ -227,3 +228,3 @@ } | ||
| `Reached limit of ${DEFAULT_LIMIT} notifications for user ${args.userId},` + | ||
| ` scheduling another deletion` | ||
| ` scheduling another deletion`, | ||
| ); | ||
@@ -287,3 +288,3 @@ await ctx.scheduler.runAfter(0, api.public.deleteNotificationsForUser, { | ||
| ctx.logger.debug( | ||
| `No push token found for user ${userId}, returning false` | ||
| `No push token found for user ${userId}, returning false`, | ||
| ); | ||
@@ -337,3 +338,3 @@ return { hasToken: false, paused: false }; | ||
| ctx.logger.error( | ||
| `There are ${inProgressSenders.length} jobs currently sending notifications. Wait a few seconds for them to finish and try to restart again.` | ||
| `There are ${inProgressSenders.length} jobs currently sending notifications. Wait a few seconds for them to finish and try to restart again.`, | ||
| ); | ||
@@ -340,0 +341,0 @@ return false; |
+29
-20
@@ -12,7 +12,16 @@ import { defineSchema, defineTable } from "convex/server"; | ||
| expiration: v.optional(v.number()), | ||
| priority: v.optional(v.union(v.literal("default"), v.literal("normal"), v.literal("high"))), | ||
| priority: v.optional( | ||
| v.union(v.literal("default"), v.literal("normal"), v.literal("high")), | ||
| ), | ||
| subtitle: v.optional(v.string()), | ||
| sound: v.optional(v.union(v.string(), v.null())), | ||
| badge: v.optional(v.number()), | ||
| interruptionLevel: v.optional(v.union(v.literal("active"), v.literal("critical"), v.literal("passive"), v.literal("time-sensitive"))), | ||
| interruptionLevel: v.optional( | ||
| v.union( | ||
| v.literal("active"), | ||
| v.literal("critical"), | ||
| v.literal("passive"), | ||
| v.literal("time-sensitive"), | ||
| ), | ||
| ), | ||
| channelId: v.optional(v.string()), | ||
@@ -29,3 +38,3 @@ categoryId: v.optional(v.string()), | ||
| * iOS Only | ||
| * | ||
| * | ||
| * When this is set to true, the notification will cause the iOS app to start in the background to run a background task. | ||
@@ -38,11 +47,11 @@ * Your app needs to be configured to support this. | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * A JSON object delivered to your app. It may be up to about 4KiB; | ||
| * the total notification payload sent to Apple and Google must be at most 4KiB or else you will get a "Message Too Big" error. | ||
| */ | ||
| data?: any | ||
| data?: any; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * The title to display in the notification. Often displayed above the notification body. | ||
@@ -55,3 +64,3 @@ * Maps to AndroidNotification.title and aps.alert.title. | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * The message to display in the notification. Maps to AndroidNotification.body and aps.alert.body. | ||
@@ -63,3 +72,3 @@ */ | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * Time to Live: the number of seconds for which the message may be kept around for redelivery | ||
@@ -73,3 +82,3 @@ * if it hasn't been delivered yet. Defaults to undefined to use the respective defaults of each provider | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * Timestamp since the Unix epoch specifying when the message expires. | ||
@@ -82,11 +91,11 @@ * Same effect as ttl (ttl takes precedence over expiration). | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * The delivery priority of the message. | ||
| * Specify default or omit this field to use the default priority on each platform ("normal" on Android and "high" on iOS). | ||
| */ | ||
| priority?: 'default' | 'normal' | 'high'; | ||
| priority?: "default" | "normal" | "high"; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * | ||
| * The subtitle to display in the notification below the title. | ||
@@ -99,3 +108,3 @@ * Maps to aps.alert.subtitle. | ||
| * iOS Only | ||
| * | ||
| * | ||
| * Play a sound when the recipient receives this notification. Specify default to play the device's default notification sound, | ||
@@ -109,3 +118,3 @@ * or omit this field to play no sound. Custom sounds need to be configured via the config plugin and | ||
| * iOS Only | ||
| * | ||
| * | ||
| * Number to display in the badge on the app icon. Specify zero to clear the badge. | ||
@@ -117,11 +126,11 @@ */ | ||
| * iOS Only | ||
| * | ||
| * | ||
| * The importance and delivery timing of a notification. | ||
| * The string values correspond to the UNNotificationInterruptionLevel enumeration cases. | ||
| */ | ||
| interruptionLevel?: 'active' | 'critical' | 'passive' | 'time-sensitive'; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive"; | ||
| /** | ||
| * Android Only | ||
| * | ||
| * | ||
| * ID of the Notification Channel through which to display this notification. | ||
@@ -135,3 +144,3 @@ * If an ID is specified but the corresponding channel does not exist on the device (that has not yet been created by your app), | ||
| * Android and iOS | ||
| * | ||
| * | ||
| * ID of the notification category that this notification is associated with. | ||
@@ -143,3 +152,3 @@ */ | ||
| * iOS Only | ||
| * | ||
| * | ||
| * Specifies whether this notification can be intercepted by the client app. | ||
@@ -162,3 +171,3 @@ * Defaults to false. | ||
| // Exhausted retries to deliver | ||
| v.literal("unable_to_deliver") | ||
| v.literal("unable_to_deliver"), | ||
| ); | ||
@@ -165,0 +174,0 @@ |
@@ -1,2 +0,2 @@ | ||
| import { Infer, v } from "convex/values"; | ||
| import { v, type Infer } from "convex/values"; | ||
@@ -7,3 +7,3 @@ export const logLevelValidator = v.union( | ||
| v.literal("WARN"), | ||
| v.literal("ERROR") | ||
| v.literal("ERROR"), | ||
| ); | ||
@@ -10,0 +10,0 @@ |
| import { Expand, FunctionReference, GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server"; | ||
| import { GenericId } from "convex/values"; | ||
| import { api } from "../component/_generated/api.js"; | ||
| import { NotificationFields } from "../component/schema.js"; | ||
| import { LogLevel } from "../logging/index.js"; | ||
| /** | ||
| * This component uses Expo's push notification API | ||
| * (https://docs.expo.dev/push-notifications/overview/) | ||
| * to allow users to send each other push notifications. | ||
| * | ||
| * This component takes in a type parameter `UserType` that should | ||
| * correspond to the unique identifier you want to use when sending | ||
| * notifications in your app (e.g. `Id<"users">` or a branded string | ||
| * `type Email = string & { __isEmail: true }`). | ||
| */ | ||
| export declare class PushNotifications<UserType extends string = GenericId<"users">> { | ||
| component: UseApi<typeof api>; | ||
| private config; | ||
| constructor(component: UseApi<typeof api>, config?: { | ||
| logLevel?: LogLevel; | ||
| }); | ||
| /** | ||
| * Takes in an Expo Push Token fetched from the client (https://docs.expo.dev/versions/latest/sdk/notifications/#expopushtoken). | ||
| * | ||
| * This allows sending notifications for this user using this token. | ||
| */ | ||
| recordToken(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| pushToken: string; | ||
| }): Promise<null>; | ||
| /** | ||
| * This removes the push notification token for a user if it exists. | ||
| * | ||
| * Once this is run, notifications can no longer be sent to this user. | ||
| */ | ||
| removeToken(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Gets the status of a user: whether they have a token and whether notifications are paused. | ||
| */ | ||
| getStatusForUser(ctx: RunQueryCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<{ | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }>; | ||
| /** | ||
| * Sends a push notification to the user with the given token. | ||
| * | ||
| * If allowUnregisteredTokens is true, we will log when there is no token for | ||
| * a user and not attempt to send a notification. | ||
| * | ||
| * If allowUnregisteredTokens is false, we will throw a ConvexError if there is no | ||
| * token for a user. | ||
| * | ||
| * Notification delivery will be batched for efficient delivery. | ||
| * @returns The ID of the notification, to be used to query the status. | ||
| * Or null if the user has paused notifications. | ||
| * @throws ConvexError if the user has no token and allowUnregisteredTokens is false. | ||
| */ | ||
| sendPushNotification(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| notification: NotificationFields; | ||
| allowUnregisteredTokens?: boolean; | ||
| }): Promise<string | null>; | ||
| /** | ||
| * Sends push notifications to multiple users in batch. | ||
| * | ||
| * @param ctx The mutation context | ||
| * @param args Object containing list of {userId, notification} pairs and allowUnregisteredTokens flag | ||
| * @returns Promise resolving when all notifications are processed | ||
| */ | ||
| sendPushNotificationBatch(ctx: RunMutationCtx, args: { | ||
| notifications: Array<{ | ||
| userId: UserType; | ||
| notification: NotificationFields; | ||
| }>; | ||
| allowUnregisteredTokens?: boolean; | ||
| }): Promise<(string | null)[]>; | ||
| /** | ||
| * Gets the notification by ID returned from {@link sendPushNotification}. | ||
| * Returns null if there is no record of a notification with that ID. | ||
| */ | ||
| getNotification(ctx: RunQueryCtx, args: { | ||
| id: string; | ||
| }): Promise<{ | ||
| numPreviousFailures: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| } | null>; | ||
| /** | ||
| * Gets the most recent notifications for a user, up to `limit` (default 1000) | ||
| */ | ||
| getNotificationsForUser(ctx: RunQueryCtx, args: { | ||
| userId: UserType; | ||
| limit?: number; | ||
| }): Promise<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| numPreviousFailures: number; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| id: string; | ||
| }[]>; | ||
| /** | ||
| * Deletes all notifications for a user. | ||
| */ | ||
| deleteNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Temporarily pause notifications for a user, for instance when the user is | ||
| * actively using the app, or able to see notifications elsewhere. | ||
| * | ||
| * Notifications sent while paused will be dropped and will not be retried. | ||
| */ | ||
| pauseNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Resume notifications for a user. | ||
| * @param ctx | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| unpauseNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Gracefully shut down the push notification sender. | ||
| * | ||
| * If notifications aren't being sent for some reason, this will attempt to gracefully | ||
| * cancel any running jobs. To restart the push notification sender, call restart(). | ||
| * | ||
| * @param ctx | ||
| * @returns | ||
| */ | ||
| shutdown(ctx: RunMutationCtx): Promise<{ | ||
| message: string; | ||
| data?: undefined; | ||
| } | { | ||
| message: string; | ||
| data: { | ||
| inProgressSenderIds: string[]; | ||
| }; | ||
| }>; | ||
| /** | ||
| * Restart the push notification sender. | ||
| * | ||
| * Call `shutdown()` first to gracefully drain any jobs in progress. | ||
| * @param ctx | ||
| * @returns {boolean} true if the restart was successful, false if it was not (i.e. if there are still jobs in progress) | ||
| */ | ||
| restart(ctx: RunMutationCtx): Promise<boolean>; | ||
| } | ||
| type RunQueryCtx = { | ||
| runQuery: GenericQueryCtx<GenericDataModel>["runQuery"]; | ||
| }; | ||
| type RunMutationCtx = { | ||
| runMutation: GenericMutationCtx<GenericDataModel>["runMutation"]; | ||
| }; | ||
| export type OpaqueIds<T> = T extends GenericId<infer _T> ? string : T extends (infer U)[] ? OpaqueIds<U>[] : T extends object ? { | ||
| [K in keyof T]: OpaqueIds<T[K]>; | ||
| } : T; | ||
| export type UseApi<API> = Expand<{ | ||
| [mod in keyof API]: API[mod] extends FunctionReference<infer FType, "public", infer FArgs, infer FReturnType, infer FComponentPath> ? FunctionReference<FType, "internal", OpaqueIds<FArgs>, OpaqueIds<FReturnType>, FComponentPath> : UseApi<API[mod]>; | ||
| }>; | ||
| export {}; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * This component uses Expo's push notification API | ||
| * (https://docs.expo.dev/push-notifications/overview/) | ||
| * to allow users to send each other push notifications. | ||
| * | ||
| * This component takes in a type parameter `UserType` that should | ||
| * correspond to the unique identifier you want to use when sending | ||
| * notifications in your app (e.g. `Id<"users">` or a branded string | ||
| * `type Email = string & { __isEmail: true }`). | ||
| */ | ||
| export class PushNotifications { | ||
| component; | ||
| config; | ||
| constructor(component, config) { | ||
| this.component = component; | ||
| this.component = component; | ||
| this.config = { | ||
| ...(config ?? {}), | ||
| logLevel: config?.logLevel ?? "ERROR", | ||
| }; | ||
| } | ||
| /** | ||
| * Takes in an Expo Push Token fetched from the client (https://docs.expo.dev/versions/latest/sdk/notifications/#expopushtoken). | ||
| * | ||
| * This allows sending notifications for this user using this token. | ||
| */ | ||
| recordToken(ctx, args) { | ||
| return ctx.runMutation(this.component.public.recordPushNotificationToken, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * This removes the push notification token for a user if it exists. | ||
| * | ||
| * Once this is run, notifications can no longer be sent to this user. | ||
| */ | ||
| removeToken(ctx, args) { | ||
| return ctx.runMutation(this.component.public.removePushNotificationToken, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the status of a user: whether they have a token and whether notifications are paused. | ||
| */ | ||
| getStatusForUser(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getStatusForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Sends a push notification to the user with the given token. | ||
| * | ||
| * If allowUnregisteredTokens is true, we will log when there is no token for | ||
| * a user and not attempt to send a notification. | ||
| * | ||
| * If allowUnregisteredTokens is false, we will throw a ConvexError if there is no | ||
| * token for a user. | ||
| * | ||
| * Notification delivery will be batched for efficient delivery. | ||
| * @returns The ID of the notification, to be used to query the status. | ||
| * Or null if the user has paused notifications. | ||
| * @throws ConvexError if the user has no token and allowUnregisteredTokens is false. | ||
| */ | ||
| sendPushNotification(ctx, args) { | ||
| return ctx.runMutation(this.component.public.sendPushNotification, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Sends push notifications to multiple users in batch. | ||
| * | ||
| * @param ctx The mutation context | ||
| * @param args Object containing list of {userId, notification} pairs and allowUnregisteredTokens flag | ||
| * @returns Promise resolving when all notifications are processed | ||
| */ | ||
| sendPushNotificationBatch(ctx, args) { | ||
| return ctx.runMutation(this.component.public.sendPushNotificationBatch, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the notification by ID returned from {@link sendPushNotification}. | ||
| * Returns null if there is no record of a notification with that ID. | ||
| */ | ||
| getNotification(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getNotification, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the most recent notifications for a user, up to `limit` (default 1000) | ||
| */ | ||
| getNotificationsForUser(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Deletes all notifications for a user. | ||
| */ | ||
| deleteNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.deleteNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Temporarily pause notifications for a user, for instance when the user is | ||
| * actively using the app, or able to see notifications elsewhere. | ||
| * | ||
| * Notifications sent while paused will be dropped and will not be retried. | ||
| */ | ||
| pauseNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.pauseNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Resume notifications for a user. | ||
| * @param ctx | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| unpauseNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.unpauseNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gracefully shut down the push notification sender. | ||
| * | ||
| * If notifications aren't being sent for some reason, this will attempt to gracefully | ||
| * cancel any running jobs. To restart the push notification sender, call restart(). | ||
| * | ||
| * @param ctx | ||
| * @returns | ||
| */ | ||
| shutdown(ctx) { | ||
| return ctx.runMutation(this.component.public.shutdown, { | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Restart the push notification sender. | ||
| * | ||
| * Call `shutdown()` first to gracefully drain any jobs in progress. | ||
| * @param ctx | ||
| * @returns {boolean} true if the restart was successful, false if it was not (i.e. if there are still jobs in progress) | ||
| */ | ||
| restart(ctx) { | ||
| return ctx.runMutation(this.component.public.restart, { | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * A utility for referencing Convex functions in your app's API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api: import("convex/server").AnyApi; | ||
| export const internal: import("convex/server").AnyApi; | ||
| export const components: import("convex/server").AnyChildComponents; | ||
| //# sourceMappingURL=api.d.ts.map |
| {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/component/_generated/api.js"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,iDAA0B;AAC1B,sDAA+B;AAC/B,oEAA8C"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { anyApi, componentsGeneric } from "convex/server"; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api = anyApi; | ||
| export const internal = anyApi; | ||
| export const components = componentsGeneric(); | ||
| //# sourceMappingURL=api.js.map |
| {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/component/_generated/api.js"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC/B,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC"} |
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query: import("convex/server").QueryBuilder<any, "public">; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery: import("convex/server").QueryBuilder<any, "internal">; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation: import("convex/server").MutationBuilder<any, "public">; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation: import("convex/server").MutationBuilder<any, "internal">; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action: import("convex/server").ActionBuilder<any, "public">; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction: import("convex/server").ActionBuilder<any, "internal">; | ||
| /** | ||
| * Define a Convex HTTP action. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object | ||
| * as its second. | ||
| * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`. | ||
| */ | ||
| export const httpAction: (func: (ctx: import("convex/server").GenericActionCtx<import("convex/server").GenericDataModel>, request: Request) => Promise<Response>) => import("convex/server").PublicHttpAction; | ||
| //# sourceMappingURL=server.d.ts.map |
| {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/component/_generated/server.js"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH,wEAAkC;AAElC;;;;;;;GAOG;AACH,kFAAkD;AAElD;;;;;;;GAOG;AACH,8EAAwC;AAExC;;;;;;;GAOG;AACH,wFAAwD;AAExD;;;;;;;;;;GAUG;AACH,0EAAoC;AAEpC;;;;;GAKG;AACH,oFAAoD;AAEpD;;;;;;GAMG;AACH,8MAA4C"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { actionGeneric, httpActionGeneric, queryGeneric, mutationGeneric, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, componentsGeneric, } from "convex/server"; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query = queryGeneric; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery = internalQueryGeneric; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation = mutationGeneric; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation = internalMutationGeneric; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action = actionGeneric; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction = internalActionGeneric; | ||
| /** | ||
| * Define a Convex HTTP action. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object | ||
| * as its second. | ||
| * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`. | ||
| */ | ||
| export const httpAction = httpActionGeneric; | ||
| //# sourceMappingURL=server.js.map |
| {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/component/_generated/server.js"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAEH,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,YAAY,CAAC;AAElC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,eAAe,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,aAAa,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,CAAC"} |
| declare const _default: import("convex/server").ComponentDefinition<any>; | ||
| export default _default; | ||
| //# sourceMappingURL=convex.config.d.ts.map |
| {"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":";AAEA,wBAAoD"} |
| import { defineComponent } from "convex/server"; | ||
| export default defineComponent("pushNotifications"); | ||
| //# sourceMappingURL=convex.config.js.map |
| {"version":3,"file":"convex.config.js","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAe,eAAe,CAAC,mBAAmB,CAAC,CAAC"} |
| import { CustomCtx } from "convex-helpers/server/customFunctions"; | ||
| import { Logger } from "../logging/index.js"; | ||
| export declare const query: import("convex-helpers/server/customFunctions").CustomBuilder<"query", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericQueryCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public">; | ||
| export declare const mutation: import("convex-helpers/server/customFunctions").CustomBuilder<"mutation", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericMutationCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public">; | ||
| export declare const action: import("convex-helpers/server/customFunctions").CustomBuilder<"action", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericActionCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public">; | ||
| export declare const internalQuery: import("convex-helpers/server/customFunctions").CustomBuilder<"query", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericQueryCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal">; | ||
| export declare const internalMutation: import("convex-helpers/server/customFunctions").CustomBuilder<"mutation", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericMutationCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal">; | ||
| export declare const internalAction: import("convex-helpers/server/customFunctions").CustomBuilder<"action", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericActionCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal">; | ||
| export type MutationCtx = CustomCtx<typeof mutation>; | ||
| //# sourceMappingURL=functions.d.ts.map |
| {"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/component/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAGV,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAqB,MAAM,qBAAqB,CAAC;AAEhE,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAKhB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAKnB,CAAC;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAKjB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAKxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAK3B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAKzB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,QAAQ,CAAC,CAAC"} |
| import { customAction, customMutation, customQuery, } from "convex-helpers/server/customFunctions"; | ||
| import * as VanillaConvex from "./_generated/server.js"; | ||
| import { Logger, logLevelValidator } from "../logging/index.js"; | ||
| export const query = customQuery(VanillaConvex.query, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const mutation = customMutation(VanillaConvex.mutation, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const action = customAction(VanillaConvex.action, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalQuery = customQuery(VanillaConvex.internalQuery, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalMutation = customMutation(VanillaConvex.internalMutation, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalAction = customAction(VanillaConvex.internalAction, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=functions.js.map |
| {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/component/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,cAAc,EACd,WAAW,GACZ,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAC,QAAQ,EAAE;IAC7D,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,CAAC,MAAM,EAAE;IACvD,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC,aAAa,CAAC,aAAa,EAAE;IACpE,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC,aAAa,CAAC,gBAAgB,EAAE;IAC7E,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE;IACvE,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC"} |
| import { MutationCtx } from "./functions.js"; | ||
| export declare function ensureCoordinator(ctx: MutationCtx): Promise<void>; | ||
| export declare const shutdownGracefully: (ctx: MutationCtx) => Promise<{ | ||
| inProgressSenders: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }[]; | ||
| }>; | ||
| //# sourceMappingURL=helpers.d.ts.map |
| {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/component/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7C,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,iBA6CvD;AAED,eAAO,MAAM,kBAAkB,GAAU,KAAK,WAAW;;;;;;;EA+CxD,CAAC"} |
| import { internal } from "./_generated/api.js"; | ||
| export async function ensureCoordinator(ctx) { | ||
| ctx.logger.debug("Ensuring there's a notification coordinator"); | ||
| const coordinators = await ctx.db.query("senderCoordinator").collect(); | ||
| const activeCoordinators = []; | ||
| for (const coordinator of coordinators) { | ||
| const job = await ctx.db.system.get(coordinator.jobId); | ||
| if (job === null || | ||
| !(job.state.kind === "pending" || job.state.kind === "inProgress")) { | ||
| await ctx.db.delete(coordinator._id); | ||
| } | ||
| else { | ||
| activeCoordinators.push(coordinator); | ||
| } | ||
| } | ||
| if (activeCoordinators.length === 1) { | ||
| ctx.logger.debug(`Found existing coordinator with ID ${activeCoordinators[0]._id}`); | ||
| return; | ||
| } | ||
| if (activeCoordinators.length > 1) { | ||
| ctx.logger.error(`Unexpected state: Too many coordinators ${activeCoordinators.length}`); | ||
| throw new Error(`Unexpected state: Too many coordinators ${activeCoordinators.length}`); | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config?.state === "shutting_down") { | ||
| ctx.logger.info("Shutting down, so not starting a new coordinator."); | ||
| return; | ||
| } | ||
| const coordinatorJobId = await ctx.scheduler.runAfter(250, internal.internal.coordinateSendingPushNotifications, { | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| const coordinatorId = await ctx.db.insert("senderCoordinator", { | ||
| jobId: coordinatorJobId, | ||
| }); | ||
| ctx.logger.debug(`Started a new coordinator ${coordinatorId}`); | ||
| } | ||
| export const shutdownGracefully = async (ctx) => { | ||
| const coordinator = await ctx.db.query("senderCoordinator").unique(); | ||
| if (coordinator === null) { | ||
| ctx.logger.debug("No coordinator found, no need to restart it"); | ||
| } | ||
| else { | ||
| ctx.logger.info(`Stopping coordinator ${coordinator._id}`); | ||
| await ctx.scheduler.cancel(coordinator.jobId); | ||
| await ctx.db.delete(coordinator._id); | ||
| } | ||
| const senders = await ctx.db.query("senders").collect(); | ||
| const inProgressSenders = []; | ||
| for (const sender of senders) { | ||
| const jobId = sender.jobId; | ||
| const job = await ctx.db.system.get(jobId); | ||
| if (job === null) { | ||
| ctx.logger.error(`Sender ${sender._id} has no job, cleaning up`); | ||
| await ctx.db.delete(sender._id); | ||
| continue; | ||
| } | ||
| switch (job.state.kind) { | ||
| case "pending": | ||
| ctx.logger.info(`Stopping sender ${sender._id}`); | ||
| await ctx.scheduler.cancel(sender.jobId); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| case "inProgress": | ||
| inProgressSenders.push(sender); | ||
| break; | ||
| case "failed": | ||
| case "success": | ||
| case "canceled": | ||
| case null: | ||
| ctx.logger.debug(`Sender ${sender._id} is already done, cleaning up`); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| default: { | ||
| const _typeCheck = job.state; | ||
| ctx.logger.error( | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| `Unknown job state ${job.state.kind} for sender ${sender._id}. Cleaning it up. `); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| return { inProgressSenders }; | ||
| }; | ||
| //# sourceMappingURL=helpers.js.map |
| {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/component/helpers.ts"],"names":[],"mappings":"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"} |
| export declare const markNotificationState: import("convex/server").RegisteredMutation<"internal", { | ||
| notifications: { | ||
| state: "delivered" | "failed" | "maybe_delivered"; | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| }[]; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const coordinateSendingPushNotifications: import("convex/server").RegisteredMutation<"internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const checkForFailedAction: import("convex/server").RegisteredMutation<"internal", { | ||
| notificationIds: import("convex/values").GenericId<"notifications">[]; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const action_sendPushNotifications: import("convex/server").RegisteredAction<"internal", { | ||
| notifications: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| message: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| to: string; | ||
| }; | ||
| }[]; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| //# sourceMappingURL=internal.d.ts.map |
| {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/component/internal.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB;;;;;;;iBA6ChC,CAAC;AAOH,eAAO,MAAM,kCAAkC;;iBAsH7C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;iBAkB/B,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;iBAiHvC,CAAC"} |
| import { v } from "convex/values"; | ||
| import { internalAction, internalMutation } from "./functions.js"; | ||
| import { internal } from "./_generated/api.js"; | ||
| import { ensureCoordinator } from "./helpers.js"; | ||
| import { notificationFields } from "./schema.js"; | ||
| export const markNotificationState = internalMutation({ | ||
| args: { | ||
| notifications: v.array(v.object({ | ||
| _id: v.id("notifications"), | ||
| state: v.union(v.literal("delivered"), v.literal("failed"), v.literal("maybe_delivered")), | ||
| })), | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| }, | ||
| handler: async (ctx, { notifications, checkJobId }) => { | ||
| ctx.logger.debug(`Marking state for ${notifications.length} notifications`); | ||
| for (const notification of notifications) { | ||
| const { _id, state } = notification; | ||
| switch (state) { | ||
| case "delivered": | ||
| ctx.logger.debug(`Marking notification ${_id} as delivered`); | ||
| await ctx.db.patch(_id, { | ||
| state: "delivered", | ||
| }); | ||
| break; | ||
| case "failed": { | ||
| ctx.logger.debug(`Marking notification ${_id} as needing retry`); | ||
| const notification = await ctx.db.get(_id); | ||
| await ctx.db.patch(_id, { | ||
| state: "needs_retry", | ||
| numPreviousFailures: notification.numPreviousFailures + 1, | ||
| }); | ||
| break; | ||
| } | ||
| case "maybe_delivered": | ||
| ctx.logger.debug(`Marking notification ${_id} as maybe delivered`); | ||
| await ctx.db.patch(_id, { | ||
| state: "maybe_delivered", | ||
| }); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Cancelling scheduled check ${checkJobId}`); | ||
| await ctx.scheduler.cancel(checkJobId); | ||
| await ensureCoordinator(ctx); | ||
| }, | ||
| }); | ||
| const MAX_NOTIFICATIONS_PER_SEND = 100; | ||
| const MAX_SENDERS = 10; | ||
| const MAX_SENDER_DURATION_MS = 10_000; | ||
| const MAX_RETRY_ATTEMPTS = 5; | ||
| export const coordinateSendingPushNotifications = internalMutation({ | ||
| args: {}, | ||
| handler: async (ctx) => { | ||
| ctx.logger.debug("Coordinate sending push notifications"); | ||
| // Get notifications | ||
| const retryNotifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("state", (q) => q.eq("state", "needs_retry")) | ||
| .take(MAX_NOTIFICATIONS_PER_SEND); | ||
| const unsentNotifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("state", (q) => q.eq("state", "awaiting_delivery")) | ||
| .take(MAX_NOTIFICATIONS_PER_SEND - retryNotifications.length); | ||
| ctx.logger.debug(`Found ${retryNotifications.length} retry notifications and ${unsentNotifications.length} unsent notifications`); | ||
| const notificationsToProcess = [ | ||
| ...retryNotifications, | ||
| ...unsentNotifications, | ||
| ]; | ||
| if (notificationsToProcess.length === 0) { | ||
| // Nothing to do! | ||
| ctx.logger.info("No notifications to send, doing nothing"); | ||
| return; | ||
| } | ||
| const senders = await ctx.db.query("senders").collect(); | ||
| let numActiveSenders = 0; | ||
| for (const sender of senders) { | ||
| const senderJob = await ctx.db.system.get(sender.jobId); | ||
| if (senderJob?.state.kind === "inProgress" || | ||
| senderJob?.state.kind === "pending") { | ||
| numActiveSenders++; | ||
| } | ||
| else { | ||
| ctx.logger.debug(`Removing sender in state ${senderJob?.state.kind}`); | ||
| await ctx.db.delete(sender._id); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Found ${numActiveSenders} active senders`); | ||
| if (numActiveSenders >= MAX_SENDERS) { | ||
| // Don't add another sender yet | ||
| ctx.logger.debug(`Not starting another sender: already ${numActiveSenders}`); | ||
| ctx.logger.debug(`When one sender finishes, or fails, we'll coordinate sending these notifications.`); | ||
| return; | ||
| } | ||
| const notificationsToSend = notificationsToProcess.filter((n) => n.numPreviousFailures < MAX_RETRY_ATTEMPTS); | ||
| const notificationsToMarkAsUnableToDeliver = notificationsToProcess.filter((n) => n.numPreviousFailures >= MAX_RETRY_ATTEMPTS); | ||
| for (const notification of notificationsToMarkAsUnableToDeliver) { | ||
| if (notification.numPreviousFailures >= MAX_RETRY_ATTEMPTS) { | ||
| await ctx.db.patch(notification._id, { | ||
| state: "unable_to_deliver", | ||
| }); | ||
| } | ||
| } | ||
| for (const notification of notificationsToSend) { | ||
| await ctx.db.patch(notification._id, { | ||
| state: "in_progress", | ||
| }); | ||
| } | ||
| ctx.logger.debug(`Marking all notifications as in progress`); | ||
| const checkJobId = await ctx.scheduler.runAfter(MAX_SENDER_DURATION_MS, internal.internal.checkForFailedAction, { | ||
| notificationIds: notificationsToSend.map((n) => n._id), | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| const senderJobId = await ctx.scheduler.runAfter(0, internal.internal.action_sendPushNotifications, { | ||
| checkJobId, | ||
| notifications: notificationsToSend.map((n) => { | ||
| return { | ||
| message: { | ||
| to: n.token, | ||
| _contentAvailable: n.metadata._contentAvailable ?? undefined, | ||
| data: n.metadata.data ?? undefined, | ||
| title: n.metadata.title, | ||
| body: n.metadata.body ?? undefined, | ||
| ttl: n.metadata.ttl ?? undefined, | ||
| expiration: n.metadata.expiration ?? undefined, | ||
| priority: n.metadata.priority ?? undefined, | ||
| subtitle: n.metadata.subtitle ?? undefined, | ||
| sound: n.metadata.sound ?? undefined, | ||
| badge: n.metadata.badge ?? undefined, | ||
| interruptionLevel: n.metadata.interruptionLevel ?? undefined, | ||
| channelId: n.metadata.channelId ?? undefined, | ||
| categoryId: n.metadata.categoryId ?? undefined, | ||
| mutableContent: n.metadata.mutableContent ?? undefined, | ||
| }, | ||
| _id: n._id, | ||
| }; | ||
| }), | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| await ctx.db.insert("senders", { | ||
| jobId: senderJobId, | ||
| checkJobId, | ||
| }); | ||
| ctx.logger.debug(`Started a new sender ${senderJobId} with job ${senderJobId} and check job ${checkJobId}`); | ||
| }, | ||
| }); | ||
| export const checkForFailedAction = internalMutation({ | ||
| args: { | ||
| notificationIds: v.array(v.id("notifications")), | ||
| }, | ||
| handler: async (ctx, { notificationIds }) => { | ||
| console.warn(`Could not determine delivery status for ${notificationIds.length} notifications:`, notificationIds); | ||
| for (const notificationId of notificationIds) { | ||
| // We don't really know what happened to these notifications, | ||
| // so we can't safely retry these. | ||
| await ctx.db.patch(notificationId, { | ||
| state: "maybe_delivered", | ||
| }); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| }, | ||
| }); | ||
| export const action_sendPushNotifications = internalAction({ | ||
| args: { | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| notifications: v.array(v.object({ | ||
| message: v.object({ | ||
| to: v.string(), | ||
| ...notificationFields | ||
| }), | ||
| _id: v.id("notifications"), | ||
| })), | ||
| }, | ||
| handler: async (ctx, args) => { | ||
| ctx.logger.debug(`Sending ${args.notifications.length} push notifications via Expo's API`); | ||
| ctx.logger.debug(`Notification IDs: ${JSON.stringify(args.notifications.map((n) => n._id))}`); | ||
| let response; | ||
| try { | ||
| // https://docs.expo.dev/push-notifications/sending-notifications/#http2-api | ||
| response = await fetch("https://exp.host/--/api/v2/push/send", { | ||
| method: "POST", | ||
| headers: { | ||
| Accept: "application/json", | ||
| "Accept-encoding": "gzip, deflate", | ||
| "Content-Type": "application/json", | ||
| }, | ||
| body: JSON.stringify(args.notifications.map((n) => n.message)), | ||
| }); | ||
| } | ||
| catch (_e) { | ||
| ctx.logger.error("Failed during during fetch for sending push notifications:", _e); | ||
| ctx.logger.debug(`Marking ${args.notifications.length} notifications as failed so they can be retried`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: args.notifications.map((n) => { | ||
| return { | ||
| _id: n._id, | ||
| // It's unlikely that the notifications were actually delivered | ||
| // if the fetch failed, so we mark them as failed. | ||
| state: "failed", | ||
| }; | ||
| }), | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| return; | ||
| } | ||
| if (!response.ok) { | ||
| ctx.logger.warn(`Push notification failed with status ${response.status} and body ${await response.text()}`); | ||
| ctx.logger.debug(`Marking ${args.notifications.length} notifications as maybe delivered. They won't be retried.`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: args.notifications.map((n) => { | ||
| return { | ||
| _id: n._id, | ||
| // We don't really know what happened to these notifications, | ||
| // so we mark them as maybe_delivered, so we don't retry them | ||
| // again and again. | ||
| state: "maybe_delivered", | ||
| }; | ||
| }), | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| } | ||
| const responseBody = await response.json(); | ||
| ctx.logger.debug(`Response from Expo's API: ${JSON.stringify(responseBody)}`); | ||
| const notificationStates = []; | ||
| for (let idx = 0; idx < args.notifications.length; idx++) { | ||
| const notification = args.notifications[idx]; | ||
| const responseItem = responseBody.data[idx]; | ||
| if (responseItem && responseItem.status === "ok") { | ||
| notificationStates.push({ | ||
| _id: notification._id, | ||
| state: "delivered", | ||
| }); | ||
| } | ||
| else { | ||
| notificationStates.push({ | ||
| _id: notification._id, | ||
| state: "failed", | ||
| }); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Successfully parsed response from Expo, and recording state`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: notificationStates, | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=internal.js.map |
| {"version":3,"file":"internal.js","sourceRoot":"","sources":["../../../src/component/internal.ts"],"names":[],"mappings":"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"} |
| export declare const recordPushNotificationToken: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| pushToken: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const removePushNotificationToken: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const sendPushNotification: import("convex/server").RegisteredMutation<"public", { | ||
| allowUnregisteredTokens?: boolean | undefined; | ||
| userId: string; | ||
| notification: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<import("convex/values").GenericId<"notifications"> | null>>; | ||
| export declare const sendPushNotificationBatch: import("convex/server").RegisteredMutation<"public", { | ||
| allowUnregisteredTokens?: boolean | undefined; | ||
| notifications: { | ||
| userId: string; | ||
| notification: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| }[]; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<(import("convex/values").GenericId<"notifications"> | null)[]>>; | ||
| export declare const getNotification: import("convex/server").RegisteredQuery<"public", { | ||
| id: import("convex/values").GenericId<"notifications">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| numPreviousFailures: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| } | null>>; | ||
| export declare const getNotificationsForUser: import("convex/server").RegisteredQuery<"public", { | ||
| limit?: number | undefined; | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| numPreviousFailures: number; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| id: import("convex/values").GenericId<"notifications">; | ||
| }[]>>; | ||
| export declare const deleteNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const pauseNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const unpauseNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const getStatusForUser: import("convex/server").RegisteredQuery<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }>>; | ||
| export declare const shutdown: import("convex/server").RegisteredMutation<"public", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| message: string; | ||
| data?: undefined; | ||
| } | { | ||
| message: string; | ||
| data: { | ||
| inProgressSenderIds: import("convex/values").GenericId<"senders">[]; | ||
| }; | ||
| }>>; | ||
| export declare const restart: import("convex/server").RegisteredMutation<"public", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<boolean>>; | ||
| //# sourceMappingURL=public.d.ts.map |
| {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/component/public.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B;;;;iBAwBtC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;iBAgBtC,CAAC;AAQH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;sEAQ/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;0EAwBpC,CAAC;AAwCH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;UAoB1B,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;KAkClC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;iBAkCrC,CAAC;AAGH,eAAO,MAAM,yBAAyB;;;iBAiBpC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;iBAiBtC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;GAmB3B,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;GA6BnB,CAAC;AAEH,eAAO,MAAM,OAAO;;oBAwBlB,CAAC"} |
| import { ConvexError, v } from "convex/values"; | ||
| import { mutation, query } from "./functions.js"; | ||
| import { notificationFields, notificationState } from "./schema.js"; | ||
| import { ensureCoordinator, shutdownGracefully } from "./helpers.js"; | ||
| import { api } from "./_generated/api.js"; | ||
| const DEFAULT_LIMIT = 1000; | ||
| export const recordPushNotificationToken = mutation({ | ||
| args: { | ||
| userId: v.string(), | ||
| pushToken: v.string(), | ||
| }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId, pushToken }) => { | ||
| if (pushToken === "") { | ||
| ctx.logger.debug("Push token is empty, skipping"); | ||
| return; | ||
| } | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken !== null) { | ||
| ctx.logger.debug(`Push token already exists for user ${userId}, updating token`); | ||
| await ctx.db.patch(existingToken._id, { token: pushToken }); | ||
| return; | ||
| } | ||
| await ctx.db.insert("pushTokens", { userId, token: pushToken }); | ||
| }, | ||
| }); | ||
| export const removePushNotificationToken = mutation({ | ||
| args: { | ||
| userId: v.string(), | ||
| }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| await ctx.db.delete(existingToken._id); | ||
| }, | ||
| }); | ||
| const sendPushNotificationArgs = v.object({ | ||
| userId: v.string(), | ||
| notification: v.object(notificationFields), | ||
| allowUnregisteredTokens: v.optional(v.boolean()), | ||
| }); | ||
| export const sendPushNotification = mutation({ | ||
| args: sendPushNotificationArgs, | ||
| returns: v.union(v.id("notifications"), v.null()), | ||
| handler: async (ctx, args) => { | ||
| const result = await sendPushNotificationHandler(ctx, args); | ||
| await ensureCoordinator(ctx); | ||
| return result; | ||
| }, | ||
| }); | ||
| export const sendPushNotificationBatch = mutation({ | ||
| args: { | ||
| notifications: v.array(v.object({ | ||
| userId: v.string(), | ||
| notification: v.object(notificationFields), | ||
| })), | ||
| allowUnregisteredTokens: v.optional(v.boolean()), | ||
| }, | ||
| returns: v.array(v.union(v.id("notifications"), v.null())), | ||
| handler: async (ctx, args) => { | ||
| const results = []; | ||
| for (const { userId, notification } of args.notifications) { | ||
| const result = await sendPushNotificationHandler(ctx, { | ||
| userId, | ||
| notification, | ||
| allowUnregisteredTokens: args.allowUnregisteredTokens, | ||
| }); | ||
| results.push(result); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| return results; | ||
| }, | ||
| }); | ||
| async function sendPushNotificationHandler(ctx, args) { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| ctx.logger.error(`No push token found for user ${args.userId}, cannot send notification`); | ||
| if (args.allowUnregisteredTokens) { | ||
| return null; | ||
| } | ||
| throw new ConvexError({ | ||
| code: "NoPushToken", | ||
| message: "No push token found for user", | ||
| userId: args.userId, | ||
| notification: args.notification, | ||
| }); | ||
| } | ||
| if (token.notificationsPaused) { | ||
| ctx.logger.info(`Notifications are paused for user ${args.userId}, skipping`); | ||
| return null; | ||
| } | ||
| const id = await ctx.db.insert("notifications", { | ||
| token: token.token, | ||
| metadata: args.notification, | ||
| state: "awaiting_delivery", | ||
| numPreviousFailures: 0, | ||
| }); | ||
| ctx.logger.debug(`Recording notification for user ${args.userId}`); | ||
| return id; | ||
| } | ||
| export const getNotification = query({ | ||
| args: { id: v.id("notifications") }, | ||
| returns: v.union(v.null(), v.object({ | ||
| ...notificationFields, | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| _creationTime: v.number(), | ||
| })), | ||
| handler: async (ctx, args) => { | ||
| const notification = await ctx.db.get(args.id); | ||
| if (!notification) { | ||
| return null; | ||
| } | ||
| const { metadata, numPreviousFailures, state, _creationTime } = notification; | ||
| return { ...metadata, numPreviousFailures, state, _creationTime }; | ||
| }, | ||
| }); | ||
| export const getNotificationsForUser = query({ | ||
| args: { userId: v.string(), limit: v.optional(v.number()) }, | ||
| returns: v.array(v.object({ | ||
| ...notificationFields, | ||
| id: v.id("notifications"), | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| _creationTime: v.number(), | ||
| })), | ||
| handler: async (ctx, args) => { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| return []; | ||
| } | ||
| const notifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("token", (q) => q.eq("token", token.token)) | ||
| .order("desc") | ||
| .take(args.limit ?? DEFAULT_LIMIT); | ||
| return notifications.map(({ _id, metadata, state, numPreviousFailures, _creationTime }) => ({ | ||
| id: _id, | ||
| ...metadata, | ||
| state: state, | ||
| numPreviousFailures: numPreviousFailures, | ||
| _creationTime, | ||
| })); | ||
| }, | ||
| }); | ||
| export const deleteNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| handler: async (ctx, args) => { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| ctx.logger.info("No push token found for user, nothing to delete"); | ||
| return; | ||
| } | ||
| const notifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("token", (q) => q.eq("token", token.token)) | ||
| .take(DEFAULT_LIMIT); | ||
| for (const notification of notifications) { | ||
| await ctx.db.delete(notification._id); | ||
| } | ||
| if (notifications.length > 0) { | ||
| ctx.logger.info(`Deleted ${notifications.length} notifications for user ${args.userId}`); | ||
| } | ||
| if (notifications.length === DEFAULT_LIMIT) { | ||
| ctx.logger.info(`Reached limit of ${DEFAULT_LIMIT} notifications for user ${args.userId},` + | ||
| ` scheduling another deletion`); | ||
| await ctx.scheduler.runAfter(0, api.public.deleteNotificationsForUser, { | ||
| ...args, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| } | ||
| }, | ||
| }); | ||
| // e.g. pause sending notifications while the user is active in the app | ||
| export const pauseNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| ctx.logger.info(`Pausing notifications for user ${userId}`); | ||
| await ctx.db.patch(existingToken._id, { | ||
| notificationsPaused: true, | ||
| }); | ||
| }, | ||
| }); | ||
| export const unpauseNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| ctx.logger.info(`Unpausing notifications for user ${userId}`); | ||
| await ctx.db.patch(existingToken._id, { | ||
| notificationsPaused: false, | ||
| }); | ||
| }, | ||
| }); | ||
| export const getStatusForUser = query({ | ||
| args: { userId: v.string() }, | ||
| returns: v.object({ hasToken: v.boolean(), paused: v.boolean() }), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, returning false`); | ||
| return { hasToken: false, paused: false }; | ||
| } | ||
| return { | ||
| hasToken: true, | ||
| paused: existingToken.notificationsPaused ?? false, | ||
| }; | ||
| }, | ||
| }); | ||
| export const shutdown = mutation({ | ||
| args: {}, | ||
| returns: v.object({ | ||
| message: v.string(), | ||
| data: v.optional(v.any()), | ||
| }), | ||
| handler: async (ctx) => { | ||
| const { inProgressSenders } = await shutdownGracefully(ctx); | ||
| if (inProgressSenders.length === 0) { | ||
| return { message: "success" }; | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config === null) { | ||
| ctx.logger.debug("No config found, creating it"); | ||
| await ctx.db.insert("config", { | ||
| state: "shutting_down", | ||
| }); | ||
| } | ||
| else { | ||
| await ctx.db.patch(config._id, { | ||
| state: "shutting_down", | ||
| }); | ||
| } | ||
| return { | ||
| message: `There are ${inProgressSenders.length} jobs currently sending notifications that will continue running. Wait a few seconds for them to finish and then restart the service.`, | ||
| data: { | ||
| inProgressSenderIds: inProgressSenders.map((sender) => sender._id), | ||
| }, | ||
| }; | ||
| }, | ||
| }); | ||
| export const restart = mutation({ | ||
| args: {}, | ||
| returns: v.boolean(), | ||
| handler: async (ctx) => { | ||
| const { inProgressSenders } = await shutdownGracefully(ctx); | ||
| if (inProgressSenders.length > 0) { | ||
| ctx.logger.error(`There are ${inProgressSenders.length} jobs currently sending notifications. Wait a few seconds for them to finish and try to restart again.`); | ||
| return false; | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config !== null) { | ||
| await ctx.db.patch(config._id, { | ||
| state: "running", | ||
| }); | ||
| } | ||
| else { | ||
| await ctx.db.insert("config", { | ||
| state: "running", | ||
| }); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| return true; | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=public.js.map |
| {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/component/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,CAAC,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAe,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IAClD,IAAI,EAAE;QACJ,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB;IACD,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;IACjB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE;QAC5C,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;YACrB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aAClD,MAAM,EAAE,CAAC;QACZ,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,sCAAsC,MAAM,kBAAkB,CAC/D,CAAC;YACF,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IAClD,IAAI,EAAE;QACJ,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;KACnB;IACD,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;IACjB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACjC,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aAClD,MAAM,EAAE,CAAC;QACZ,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,MAAM,iBAAiB,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;QACD,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;IAC1C,uBAAuB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;CACjD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC3C,IAAI,EAAE,wBAAwB;IAC9B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5D,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE;QACJ,aAAa,EAAE,CAAC,CAAC,KAAK,CACpB,CAAC,CAAC,MAAM,CAAC;YACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;YAClB,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;SAC3C,CAAC,CACH;QACD,uBAAuB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;KACjD;IACD,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC1D,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAAC,GAAG,EAAE;gBACpD,MAAM;gBACN,YAAY;gBACZ,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;aACtD,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QACD,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAC,CAAC;AAEH,KAAK,UAAU,2BAA2B,CACxC,GAAgB,EAChB,IAA4C;IAE5C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,EAAE;SACvB,KAAK,CAAC,YAAY,CAAC;SACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;SACvD,MAAM,EAAE,CAAC;IACZ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,gCAAgC,IAAI,CAAC,MAAM,4BAA4B,CACxE,CAAC;QACF,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,WAAW,CAAC;YACpB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,8BAA8B;YACvC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC9B,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,qCAAqC,IAAI,CAAC,MAAM,YAAY,CAC7D,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE;QAC9C,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,IAAI,CAAC,YAAY;QAC3B,KAAK,EAAE,mBAAmB;QAC1B,mBAAmB,EAAE,CAAC;KACvB,CAAC,CAAC;IACH,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACnE,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;IACnC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE;IACnC,OAAO,EAAE,CAAC,CAAC,KAAK,CACd,CAAC,CAAC,IAAI,EAAE,EACR,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,kBAAkB;QACrB,KAAK,EAAE,iBAAiB;QACxB,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE;QAC/B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;KAC1B,CAAC,CACH;IACD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,EAAE,GAC3D,YAAY,CAAC;QACf,OAAO,EAAE,GAAG,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;IACpE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAC;IAC3C,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;IAC3D,OAAO,EAAE,CAAC,CAAC,KAAK,CACd,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,kBAAkB;QACrB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC;QACzB,KAAK,EAAE,iBAAiB;QACxB,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE;QAC/B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;KAC1B,CAAC,CACH;IACD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,EAAE;aACvB,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;aACvD,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,eAAe,CAAC;aACtB,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;aACrD,KAAK,CAAC,MAAM,CAAC;aACb,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC;QACrC,OAAO,aAAa,CAAC,GAAG,CACtB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;YACjE,EAAE,EAAE,GAAG;YACP,GAAG,QAAQ;YACX,KAAK,EAAE,KAAK;YACZ,mBAAmB,EAAE,mBAAmB;YACxC,aAAa;SACd,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IACjD,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC5B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,EAAE;aACvB,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;aACvD,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,eAAe,CAAC;aACtB,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;aACrD,IAAI,CAAC,aAAa,CAAC,CAAC;QACvB,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;YACzC,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,WAAW,aAAa,CAAC,MAAM,2BAA2B,IAAI,CAAC,MAAM,EAAE,CACxE,CAAC;QACJ,CAAC;QACD,IAAI,aAAa,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAC3C,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,oBAAoB,aAAa,2BAA2B,IAAI,CAAC,MAAM,GAAG;gBACxE,8BAA8B,CACjC,CAAC;YACF,MAAM,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,0BAA0B,EAAE;gBACrE,GAAG,IAAI;gBACP,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAC,CAAC;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;IACjB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACjC,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aAClD,MAAM,EAAE,CAAC;QACZ,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,MAAM,iBAAiB,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC;QAC5D,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE;YACpC,mBAAmB,EAAE,IAAI;SAC1B,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IAClD,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;IACjB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACjC,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aAClD,MAAM,EAAE,CAAC;QACZ,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,MAAM,iBAAiB,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,MAAM,EAAE,CAAC,CAAC;QAC9D,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE;YACpC,mBAAmB,EAAE,KAAK;SAC3B,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;IACpC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACjC,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,EAAE;aAC/B,KAAK,CAAC,YAAY,CAAC;aACnB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aAClD,MAAM,EAAE,CAAC;QACZ,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,gCAAgC,MAAM,mBAAmB,CAC1D,CAAC;YACF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QACD,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,aAAa,CAAC,mBAAmB,IAAI,KAAK;SACnD,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;KAC1B,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAC5D,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QAChC,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;QACrD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YACjD,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE;gBAC5B,KAAK,EAAE,eAAe;aACvB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE;gBAC7B,KAAK,EAAE,eAAe;aACvB,CAAC,CAAC;QACL,CAAC;QACD,OAAO;YACL,OAAO,EAAE,aAAa,iBAAiB,CAAC,MAAM,uIAAuI;YACrL,IAAI,EAAE;gBACJ,mBAAmB,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;aACnE;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC;IAC9B,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAC5D,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,aAAa,iBAAiB,CAAC,MAAM,wGAAwG,CAC9I,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;QACrD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE;gBAC7B,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE;gBAC5B,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;QACD,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC,CAAC"} |
| export declare const notificationFields: { | ||
| _contentAvailable: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| data: import("convex/values").VAny<any, "optional", string>; | ||
| title: import("convex/values").VString<string | undefined, "optional">; | ||
| body: import("convex/values").VString<string | undefined, "optional">; | ||
| ttl: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| expiration: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| priority: import("convex/values").VUnion<"default" | "normal" | "high" | undefined, [import("convex/values").VLiteral<"default", "required">, import("convex/values").VLiteral<"normal", "required">, import("convex/values").VLiteral<"high", "required">], "optional", never>; | ||
| subtitle: import("convex/values").VString<string | undefined, "optional">; | ||
| sound: import("convex/values").VUnion<string | null | undefined, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "optional", never>; | ||
| badge: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| interruptionLevel: import("convex/values").VUnion<"active" | "critical" | "passive" | "time-sensitive" | undefined, [import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"critical", "required">, import("convex/values").VLiteral<"passive", "required">, import("convex/values").VLiteral<"time-sensitive", "required">], "optional", never>; | ||
| channelId: import("convex/values").VString<string | undefined, "optional">; | ||
| categoryId: import("convex/values").VString<string | undefined, "optional">; | ||
| mutableContent: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }; | ||
| /** | ||
| * Notification fields for push notifications. | ||
| */ | ||
| export type NotificationFields = { | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * When this is set to true, the notification will cause the iOS app to start in the background to run a background task. | ||
| * Your app needs to be configured to support this. | ||
| */ | ||
| _contentAvailable?: boolean; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * A JSON object delivered to your app. It may be up to about 4KiB; | ||
| * the total notification payload sent to Apple and Google must be at most 4KiB or else you will get a "Message Too Big" error. | ||
| */ | ||
| data?: any; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The title to display in the notification. Often displayed above the notification body. | ||
| * Maps to AndroidNotification.title and aps.alert.title. | ||
| */ | ||
| title: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The message to display in the notification. Maps to AndroidNotification.body and aps.alert.body. | ||
| */ | ||
| body?: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * Time to Live: the number of seconds for which the message may be kept around for redelivery | ||
| * if it hasn't been delivered yet. Defaults to undefined to use the respective defaults of each provider | ||
| * (1 month for Android/FCM as well as iOS/APNs). | ||
| */ | ||
| ttl?: number; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * Timestamp since the Unix epoch specifying when the message expires. | ||
| * Same effect as ttl (ttl takes precedence over expiration). | ||
| */ | ||
| expiration?: number; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The delivery priority of the message. | ||
| * Specify default or omit this field to use the default priority on each platform ("normal" on Android and "high" on iOS). | ||
| */ | ||
| priority?: 'default' | 'normal' | 'high'; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * The subtitle to display in the notification below the title. | ||
| * Maps to aps.alert.subtitle. | ||
| */ | ||
| subtitle?: string; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Play a sound when the recipient receives this notification. Specify default to play the device's default notification sound, | ||
| * or omit this field to play no sound. Custom sounds need to be configured via the config plugin and | ||
| * then specified including the file extension. Example: bells_sound.wav. | ||
| */ | ||
| sound?: string | null; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Number to display in the badge on the app icon. Specify zero to clear the badge. | ||
| */ | ||
| badge?: number; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * The importance and delivery timing of a notification. | ||
| * The string values correspond to the UNNotificationInterruptionLevel enumeration cases. | ||
| */ | ||
| interruptionLevel?: 'active' | 'critical' | 'passive' | 'time-sensitive'; | ||
| /** | ||
| * Android Only | ||
| * | ||
| * ID of the Notification Channel through which to display this notification. | ||
| * If an ID is specified but the corresponding channel does not exist on the device (that has not yet been created by your app), | ||
| * the notification will not be displayed to the user. | ||
| */ | ||
| channelId?: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * ID of the notification category that this notification is associated with. | ||
| */ | ||
| categoryId?: string; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Specifies whether this notification can be intercepted by the client app. | ||
| * Defaults to false. | ||
| */ | ||
| mutableContent?: boolean; | ||
| }; | ||
| export declare const notificationState: import("convex/values").VUnion<"awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver", [import("convex/values").VLiteral<"awaiting_delivery", "required">, import("convex/values").VLiteral<"in_progress", "required">, import("convex/values").VLiteral<"delivered", "required">, import("convex/values").VLiteral<"needs_retry", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"maybe_delivered", "required">, import("convex/values").VLiteral<"unable_to_deliver", "required">], "required", never>; | ||
| declare const _default: import("convex/server").SchemaDefinition<{ | ||
| notifications: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }, { | ||
| token: import("convex/values").VString<string, "required">; | ||
| metadata: import("convex/values").VObject<{ | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }, { | ||
| _contentAvailable: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| data: import("convex/values").VAny<any, "optional", string>; | ||
| title: import("convex/values").VString<string | undefined, "optional">; | ||
| body: import("convex/values").VString<string | undefined, "optional">; | ||
| ttl: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| expiration: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| priority: import("convex/values").VUnion<"default" | "normal" | "high" | undefined, [import("convex/values").VLiteral<"default", "required">, import("convex/values").VLiteral<"normal", "required">, import("convex/values").VLiteral<"high", "required">], "optional", never>; | ||
| subtitle: import("convex/values").VString<string | undefined, "optional">; | ||
| sound: import("convex/values").VUnion<string | null | undefined, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "optional", never>; | ||
| badge: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| interruptionLevel: import("convex/values").VUnion<"active" | "critical" | "passive" | "time-sensitive" | undefined, [import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"critical", "required">, import("convex/values").VLiteral<"passive", "required">, import("convex/values").VLiteral<"time-sensitive", "required">], "optional", never>; | ||
| channelId: import("convex/values").VString<string | undefined, "optional">; | ||
| categoryId: import("convex/values").VString<string | undefined, "optional">; | ||
| mutableContent: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }, "required", "_contentAvailable" | "data" | "title" | "body" | "ttl" | "expiration" | "priority" | "subtitle" | "sound" | "badge" | "interruptionLevel" | "channelId" | "categoryId" | "mutableContent" | `data.${string}`>; | ||
| state: import("convex/values").VUnion<"awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver", [import("convex/values").VLiteral<"awaiting_delivery", "required">, import("convex/values").VLiteral<"in_progress", "required">, import("convex/values").VLiteral<"delivered", "required">, import("convex/values").VLiteral<"needs_retry", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"maybe_delivered", "required">, import("convex/values").VLiteral<"unable_to_deliver", "required">], "required", never>; | ||
| numPreviousFailures: import("convex/values").VFloat64<number, "required">; | ||
| }, "required", "state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}`>, { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| }, {}, {}>; | ||
| pushTokens: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }, { | ||
| userId: import("convex/values").VString<string, "required">; | ||
| token: import("convex/values").VString<string, "required">; | ||
| notificationsPaused: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }, "required", "token" | "userId" | "notificationsPaused">, { | ||
| userId: ["userId", "_creationTime"]; | ||
| }, {}, {}>; | ||
| senders: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }, { | ||
| jobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| checkJobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| }, "required", "jobId" | "checkJobId">, {}, {}, {}>; | ||
| senderCoordinator: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }, { | ||
| jobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| }, "required", "jobId">, {}, {}, {}>; | ||
| config: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| state: "running" | "shutting_down"; | ||
| }, { | ||
| state: import("convex/values").VUnion<"running" | "shutting_down", [import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"shutting_down", "required">], "required", never>; | ||
| }, "required", "state">, {}, {}, {}>; | ||
| }, true>; | ||
| export default _default; | ||
| //# sourceMappingURL=schema.d.ts.map |
| {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;CAe9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,GAAG,CAAA;IAEV;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAEzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAEzE;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,imBAY7B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF,wBAwBG"} |
| import { defineSchema, defineTable } from "convex/server"; | ||
| import { v } from "convex/values"; | ||
| // https://docs.expo.dev/push-notifications/sending-notifications/#message-request-format | ||
| export const notificationFields = { | ||
| _contentAvailable: v.optional(v.boolean()), | ||
| data: v.optional(v.any()), | ||
| title: v.optional(v.string()), | ||
| body: v.optional(v.string()), | ||
| ttl: v.optional(v.number()), | ||
| expiration: v.optional(v.number()), | ||
| priority: v.optional(v.union(v.literal("default"), v.literal("normal"), v.literal("high"))), | ||
| subtitle: v.optional(v.string()), | ||
| sound: v.optional(v.union(v.string(), v.null())), | ||
| badge: v.optional(v.number()), | ||
| interruptionLevel: v.optional(v.union(v.literal("active"), v.literal("critical"), v.literal("passive"), v.literal("time-sensitive"))), | ||
| channelId: v.optional(v.string()), | ||
| categoryId: v.optional(v.string()), | ||
| mutableContent: v.optional(v.boolean()), | ||
| }; | ||
| export const notificationState = v.union(v.literal("awaiting_delivery"), v.literal("in_progress"), v.literal("delivered"), v.literal("needs_retry"), | ||
| // Expo returned a failure for this notification | ||
| v.literal("failed"), | ||
| // Failure before receiving confirmation of delivery, so not safe to retry | ||
| // without delivering twice | ||
| v.literal("maybe_delivered"), | ||
| // Exhausted retries to deliver | ||
| v.literal("unable_to_deliver")); | ||
| export default defineSchema({ | ||
| notifications: defineTable({ | ||
| token: v.string(), | ||
| metadata: v.object(notificationFields), | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| }) | ||
| .index("token", ["token"]) | ||
| .index("state", ["state"]), | ||
| pushTokens: defineTable({ | ||
| userId: v.string(), | ||
| token: v.string(), | ||
| notificationsPaused: v.optional(v.boolean()), | ||
| }).index("userId", ["userId"]), | ||
| senders: defineTable({ | ||
| jobId: v.id("_scheduled_functions"), | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| }), | ||
| senderCoordinator: defineTable({ | ||
| jobId: v.id("_scheduled_functions"), | ||
| }), | ||
| config: defineTable({ | ||
| state: v.union(v.literal("running"), v.literal("shutting_down")), | ||
| }), | ||
| }); | ||
| //# sourceMappingURL=schema.js.map |
| {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"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"} |
| import { Infer } from "convex/values"; | ||
| export declare const logLevelValidator: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| export type LogLevel = Infer<typeof logLevelValidator>; | ||
| export declare const logWithLevel: (level: LogLevel, configuredLevel: LogLevel, ...args: unknown[]) => void; | ||
| export declare class Logger { | ||
| private configuredLevel; | ||
| constructor(configuredLevel: LogLevel); | ||
| get level(): "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| debug(...args: unknown[]): void; | ||
| info(...args: unknown[]): void; | ||
| warn(...args: unknown[]): void; | ||
| error(...args: unknown[]): void; | ||
| } | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAK,MAAM,eAAe,CAAC;AAEzC,eAAO,MAAM,iBAAiB,oTAK7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEvD,eAAO,MAAM,YAAY,GACvB,OAAO,QAAQ,EACf,iBAAiB,QAAQ,EACzB,GAAG,MAAM,OAAO,EAAE,SAmBnB,CAAC;AAEF,qBAAa,MAAM;IACL,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,QAAQ;IAE7C,IAAI,KAAK,wCAER;IAED,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIxB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIvB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIvB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;CAGzB"} |
| import { v } from "convex/values"; | ||
| export const logLevelValidator = v.union(v.literal("DEBUG"), v.literal("INFO"), v.literal("WARN"), v.literal("ERROR")); | ||
| const orderedLevels = ["DEBUG", "INFO", "WARN", "ERROR"]; | ||
| export const logWithLevel = (level, configuredLevel, ...args) => { | ||
| if (orderedLevels.indexOf(level) < orderedLevels.indexOf(configuredLevel)) { | ||
| return; | ||
| } | ||
| switch (level) { | ||
| case "DEBUG": | ||
| console.debug(...args); | ||
| break; | ||
| case "INFO": | ||
| console.info(...args); | ||
| break; | ||
| case "WARN": | ||
| console.warn(...args); | ||
| break; | ||
| case "ERROR": | ||
| console.error(...args); | ||
| break; | ||
| } | ||
| }; | ||
| export class Logger { | ||
| configuredLevel; | ||
| constructor(configuredLevel) { | ||
| this.configuredLevel = configuredLevel; | ||
| } | ||
| get level() { | ||
| return this.configuredLevel; | ||
| } | ||
| debug(...args) { | ||
| logWithLevel("DEBUG", this.configuredLevel, ...args); | ||
| } | ||
| info(...args) { | ||
| logWithLevel("INFO", this.configuredLevel, ...args); | ||
| } | ||
| warn(...args) { | ||
| logWithLevel("WARN", this.configuredLevel, ...args); | ||
| } | ||
| error(...args) { | ||
| logWithLevel("ERROR", this.configuredLevel, ...args); | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,CAAC,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CACtC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAClB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CACnB,CAAC;AAGF,MAAM,aAAa,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAe,EACf,eAAyB,EACzB,GAAG,IAAe,EAClB,EAAE;IACF,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC1E,OAAO;IACT,CAAC;IACD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,MAAM;QACR,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,MAAM;IACV,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,MAAM;IACG;IAApB,YAAoB,eAAyB;QAAzB,oBAAe,GAAf,eAAe,CAAU;IAAG,CAAC;IAEjD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;CACF"} |
| { | ||
| "type": "commonjs" | ||
| } |
| import { Expand, FunctionReference, GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server"; | ||
| import { GenericId } from "convex/values"; | ||
| import { api } from "../component/_generated/api.js"; | ||
| import { NotificationFields } from "../component/schema.js"; | ||
| import { LogLevel } from "../logging/index.js"; | ||
| /** | ||
| * This component uses Expo's push notification API | ||
| * (https://docs.expo.dev/push-notifications/overview/) | ||
| * to allow users to send each other push notifications. | ||
| * | ||
| * This component takes in a type parameter `UserType` that should | ||
| * correspond to the unique identifier you want to use when sending | ||
| * notifications in your app (e.g. `Id<"users">` or a branded string | ||
| * `type Email = string & { __isEmail: true }`). | ||
| */ | ||
| export declare class PushNotifications<UserType extends string = GenericId<"users">> { | ||
| component: UseApi<typeof api>; | ||
| private config; | ||
| constructor(component: UseApi<typeof api>, config?: { | ||
| logLevel?: LogLevel; | ||
| }); | ||
| /** | ||
| * Takes in an Expo Push Token fetched from the client (https://docs.expo.dev/versions/latest/sdk/notifications/#expopushtoken). | ||
| * | ||
| * This allows sending notifications for this user using this token. | ||
| */ | ||
| recordToken(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| pushToken: string; | ||
| }): Promise<null>; | ||
| /** | ||
| * This removes the push notification token for a user if it exists. | ||
| * | ||
| * Once this is run, notifications can no longer be sent to this user. | ||
| */ | ||
| removeToken(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Gets the status of a user: whether they have a token and whether notifications are paused. | ||
| */ | ||
| getStatusForUser(ctx: RunQueryCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<{ | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }>; | ||
| /** | ||
| * Sends a push notification to the user with the given token. | ||
| * | ||
| * If allowUnregisteredTokens is true, we will log when there is no token for | ||
| * a user and not attempt to send a notification. | ||
| * | ||
| * If allowUnregisteredTokens is false, we will throw a ConvexError if there is no | ||
| * token for a user. | ||
| * | ||
| * Notification delivery will be batched for efficient delivery. | ||
| * @returns The ID of the notification, to be used to query the status. | ||
| * Or null if the user has paused notifications. | ||
| * @throws ConvexError if the user has no token and allowUnregisteredTokens is false. | ||
| */ | ||
| sendPushNotification(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| notification: NotificationFields; | ||
| allowUnregisteredTokens?: boolean; | ||
| }): Promise<string | null>; | ||
| /** | ||
| * Sends push notifications to multiple users in batch. | ||
| * | ||
| * @param ctx The mutation context | ||
| * @param args Object containing list of {userId, notification} pairs and allowUnregisteredTokens flag | ||
| * @returns Promise resolving when all notifications are processed | ||
| */ | ||
| sendPushNotificationBatch(ctx: RunMutationCtx, args: { | ||
| notifications: Array<{ | ||
| userId: UserType; | ||
| notification: NotificationFields; | ||
| }>; | ||
| allowUnregisteredTokens?: boolean; | ||
| }): Promise<(string | null)[]>; | ||
| /** | ||
| * Gets the notification by ID returned from {@link sendPushNotification}. | ||
| * Returns null if there is no record of a notification with that ID. | ||
| */ | ||
| getNotification(ctx: RunQueryCtx, args: { | ||
| id: string; | ||
| }): Promise<{ | ||
| numPreviousFailures: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| } | null>; | ||
| /** | ||
| * Gets the most recent notifications for a user, up to `limit` (default 1000) | ||
| */ | ||
| getNotificationsForUser(ctx: RunQueryCtx, args: { | ||
| userId: UserType; | ||
| limit?: number; | ||
| }): Promise<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| numPreviousFailures: number; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| id: string; | ||
| }[]>; | ||
| /** | ||
| * Deletes all notifications for a user. | ||
| */ | ||
| deleteNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Temporarily pause notifications for a user, for instance when the user is | ||
| * actively using the app, or able to see notifications elsewhere. | ||
| * | ||
| * Notifications sent while paused will be dropped and will not be retried. | ||
| */ | ||
| pauseNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Resume notifications for a user. | ||
| * @param ctx | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| unpauseNotificationsForUser(ctx: RunMutationCtx, args: { | ||
| userId: UserType; | ||
| }): Promise<null>; | ||
| /** | ||
| * Gracefully shut down the push notification sender. | ||
| * | ||
| * If notifications aren't being sent for some reason, this will attempt to gracefully | ||
| * cancel any running jobs. To restart the push notification sender, call restart(). | ||
| * | ||
| * @param ctx | ||
| * @returns | ||
| */ | ||
| shutdown(ctx: RunMutationCtx): Promise<{ | ||
| message: string; | ||
| data?: undefined; | ||
| } | { | ||
| message: string; | ||
| data: { | ||
| inProgressSenderIds: string[]; | ||
| }; | ||
| }>; | ||
| /** | ||
| * Restart the push notification sender. | ||
| * | ||
| * Call `shutdown()` first to gracefully drain any jobs in progress. | ||
| * @param ctx | ||
| * @returns {boolean} true if the restart was successful, false if it was not (i.e. if there are still jobs in progress) | ||
| */ | ||
| restart(ctx: RunMutationCtx): Promise<boolean>; | ||
| } | ||
| type RunQueryCtx = { | ||
| runQuery: GenericQueryCtx<GenericDataModel>["runQuery"]; | ||
| }; | ||
| type RunMutationCtx = { | ||
| runMutation: GenericMutationCtx<GenericDataModel>["runMutation"]; | ||
| }; | ||
| export type OpaqueIds<T> = T extends GenericId<infer _T> ? string : T extends (infer U)[] ? OpaqueIds<U>[] : T extends object ? { | ||
| [K in keyof T]: OpaqueIds<T[K]>; | ||
| } : T; | ||
| export type UseApi<API> = Expand<{ | ||
| [mod in keyof API]: API[mod] extends FunctionReference<infer FType, "public", infer FArgs, infer FReturnType, infer FComponentPath> ? FunctionReference<FType, "internal", OpaqueIds<FArgs>, OpaqueIds<FReturnType>, FComponentPath> : UseApi<API[mod]>; | ||
| }>; | ||
| export {}; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * This component uses Expo's push notification API | ||
| * (https://docs.expo.dev/push-notifications/overview/) | ||
| * to allow users to send each other push notifications. | ||
| * | ||
| * This component takes in a type parameter `UserType` that should | ||
| * correspond to the unique identifier you want to use when sending | ||
| * notifications in your app (e.g. `Id<"users">` or a branded string | ||
| * `type Email = string & { __isEmail: true }`). | ||
| */ | ||
| export class PushNotifications { | ||
| component; | ||
| config; | ||
| constructor(component, config) { | ||
| this.component = component; | ||
| this.component = component; | ||
| this.config = { | ||
| ...(config ?? {}), | ||
| logLevel: config?.logLevel ?? "ERROR", | ||
| }; | ||
| } | ||
| /** | ||
| * Takes in an Expo Push Token fetched from the client (https://docs.expo.dev/versions/latest/sdk/notifications/#expopushtoken). | ||
| * | ||
| * This allows sending notifications for this user using this token. | ||
| */ | ||
| recordToken(ctx, args) { | ||
| return ctx.runMutation(this.component.public.recordPushNotificationToken, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * This removes the push notification token for a user if it exists. | ||
| * | ||
| * Once this is run, notifications can no longer be sent to this user. | ||
| */ | ||
| removeToken(ctx, args) { | ||
| return ctx.runMutation(this.component.public.removePushNotificationToken, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the status of a user: whether they have a token and whether notifications are paused. | ||
| */ | ||
| getStatusForUser(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getStatusForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Sends a push notification to the user with the given token. | ||
| * | ||
| * If allowUnregisteredTokens is true, we will log when there is no token for | ||
| * a user and not attempt to send a notification. | ||
| * | ||
| * If allowUnregisteredTokens is false, we will throw a ConvexError if there is no | ||
| * token for a user. | ||
| * | ||
| * Notification delivery will be batched for efficient delivery. | ||
| * @returns The ID of the notification, to be used to query the status. | ||
| * Or null if the user has paused notifications. | ||
| * @throws ConvexError if the user has no token and allowUnregisteredTokens is false. | ||
| */ | ||
| sendPushNotification(ctx, args) { | ||
| return ctx.runMutation(this.component.public.sendPushNotification, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Sends push notifications to multiple users in batch. | ||
| * | ||
| * @param ctx The mutation context | ||
| * @param args Object containing list of {userId, notification} pairs and allowUnregisteredTokens flag | ||
| * @returns Promise resolving when all notifications are processed | ||
| */ | ||
| sendPushNotificationBatch(ctx, args) { | ||
| return ctx.runMutation(this.component.public.sendPushNotificationBatch, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the notification by ID returned from {@link sendPushNotification}. | ||
| * Returns null if there is no record of a notification with that ID. | ||
| */ | ||
| getNotification(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getNotification, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gets the most recent notifications for a user, up to `limit` (default 1000) | ||
| */ | ||
| getNotificationsForUser(ctx, args) { | ||
| return ctx.runQuery(this.component.public.getNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Deletes all notifications for a user. | ||
| */ | ||
| deleteNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.deleteNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Temporarily pause notifications for a user, for instance when the user is | ||
| * actively using the app, or able to see notifications elsewhere. | ||
| * | ||
| * Notifications sent while paused will be dropped and will not be retried. | ||
| */ | ||
| pauseNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.pauseNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Resume notifications for a user. | ||
| * @param ctx | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| unpauseNotificationsForUser(ctx, args) { | ||
| return ctx.runMutation(this.component.public.unpauseNotificationsForUser, { | ||
| ...args, | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Gracefully shut down the push notification sender. | ||
| * | ||
| * If notifications aren't being sent for some reason, this will attempt to gracefully | ||
| * cancel any running jobs. To restart the push notification sender, call restart(). | ||
| * | ||
| * @param ctx | ||
| * @returns | ||
| */ | ||
| shutdown(ctx) { | ||
| return ctx.runMutation(this.component.public.shutdown, { | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| /** | ||
| * Restart the push notification sender. | ||
| * | ||
| * Call `shutdown()` first to gracefully drain any jobs in progress. | ||
| * @param ctx | ||
| * @returns {boolean} true if the restart was successful, false if it was not (i.e. if there are still jobs in progress) | ||
| */ | ||
| restart(ctx) { | ||
| return ctx.runMutation(this.component.public.restart, { | ||
| logLevel: this.config.logLevel, | ||
| }); | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * A utility for referencing Convex functions in your app's API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api: import("convex/server").AnyApi; | ||
| export const internal: import("convex/server").AnyApi; | ||
| export const components: import("convex/server").AnyChildComponents; | ||
| //# sourceMappingURL=api.d.ts.map |
| {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/component/_generated/api.js"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,iDAA0B;AAC1B,sDAA+B;AAC/B,oEAA8C"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { anyApi, componentsGeneric } from "convex/server"; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api = anyApi; | ||
| export const internal = anyApi; | ||
| export const components = componentsGeneric(); | ||
| //# sourceMappingURL=api.js.map |
| {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/component/_generated/api.js"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC/B,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC"} |
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query: import("convex/server").QueryBuilder<any, "public">; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery: import("convex/server").QueryBuilder<any, "internal">; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation: import("convex/server").MutationBuilder<any, "public">; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation: import("convex/server").MutationBuilder<any, "internal">; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action: import("convex/server").ActionBuilder<any, "public">; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction: import("convex/server").ActionBuilder<any, "internal">; | ||
| /** | ||
| * Define a Convex HTTP action. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object | ||
| * as its second. | ||
| * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`. | ||
| */ | ||
| export const httpAction: (func: (ctx: import("convex/server").GenericActionCtx<import("convex/server").GenericDataModel>, request: Request) => Promise<Response>) => import("convex/server").PublicHttpAction; | ||
| //# sourceMappingURL=server.d.ts.map |
| {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/component/_generated/server.js"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH,wEAAkC;AAElC;;;;;;;GAOG;AACH,kFAAkD;AAElD;;;;;;;GAOG;AACH,8EAAwC;AAExC;;;;;;;GAOG;AACH,wFAAwD;AAExD;;;;;;;;;;GAUG;AACH,0EAAoC;AAEpC;;;;;GAKG;AACH,oFAAoD;AAEpD;;;;;;GAMG;AACH,8MAA4C"} |
| /* eslint-disable */ | ||
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { actionGeneric, httpActionGeneric, queryGeneric, mutationGeneric, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, componentsGeneric, } from "convex/server"; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query = queryGeneric; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery = internalQueryGeneric; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation = mutationGeneric; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation = internalMutationGeneric; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action = actionGeneric; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction = internalActionGeneric; | ||
| /** | ||
| * Define a Convex HTTP action. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object | ||
| * as its second. | ||
| * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`. | ||
| */ | ||
| export const httpAction = httpActionGeneric; | ||
| //# sourceMappingURL=server.js.map |
| {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/component/_generated/server.js"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAEH,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,YAAY,CAAC;AAElC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,eAAe,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,aAAa,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,CAAC"} |
| declare const _default: import("convex/server").ComponentDefinition<any>; | ||
| export default _default; | ||
| //# sourceMappingURL=convex.config.d.ts.map |
| {"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":";AAEA,wBAAoD"} |
| import { defineComponent } from "convex/server"; | ||
| export default defineComponent("pushNotifications"); | ||
| //# sourceMappingURL=convex.config.js.map |
| {"version":3,"file":"convex.config.js","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAe,eAAe,CAAC,mBAAmB,CAAC,CAAC"} |
| import { CustomCtx } from "convex-helpers/server/customFunctions"; | ||
| import { Logger } from "../logging/index.js"; | ||
| export declare const query: import("convex-helpers/server/customFunctions").CustomBuilder<"query", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericQueryCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public">; | ||
| export declare const mutation: import("convex-helpers/server/customFunctions").CustomBuilder<"mutation", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericMutationCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public">; | ||
| export declare const action: import("convex-helpers/server/customFunctions").CustomBuilder<"action", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericActionCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "public">; | ||
| export declare const internalQuery: import("convex-helpers/server/customFunctions").CustomBuilder<"query", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericQueryCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal">; | ||
| export declare const internalMutation: import("convex-helpers/server/customFunctions").CustomBuilder<"mutation", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericMutationCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal">; | ||
| export declare const internalAction: import("convex-helpers/server/customFunctions").CustomBuilder<"action", { | ||
| logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| }, { | ||
| logger: Logger; | ||
| }, {}, import("convex/server").GenericActionCtx<{ | ||
| notifications: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| _creationTime: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }; | ||
| fieldPaths: ("state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}` | "_creationTime") | "_id"; | ||
| indexes: { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| pushTokens: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"pushTokens">; | ||
| _creationTime: number; | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }; | ||
| fieldPaths: ("token" | "_creationTime" | "userId" | "notificationsPaused") | "_id"; | ||
| indexes: { | ||
| userId: ["userId", "_creationTime"]; | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senders: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId" | "checkJobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| senderCoordinator: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"senderCoordinator">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }; | ||
| fieldPaths: "_id" | ("_creationTime" | "jobId"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| config: { | ||
| document: { | ||
| _id: import("convex/values").GenericId<"config">; | ||
| _creationTime: number; | ||
| state: "running" | "shutting_down"; | ||
| }; | ||
| fieldPaths: "_id" | ("state" | "_creationTime"); | ||
| indexes: { | ||
| by_id: ["_id"]; | ||
| by_creation_time: ["_creationTime"]; | ||
| }; | ||
| searchIndexes: {}; | ||
| vectorIndexes: {}; | ||
| }; | ||
| }>, "internal">; | ||
| export type MutationCtx = CustomCtx<typeof mutation>; | ||
| //# sourceMappingURL=functions.d.ts.map |
| {"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/component/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAGV,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAqB,MAAM,qBAAqB,CAAC;AAEhE,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAKhB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAKnB,CAAC;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAKjB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAKxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAK3B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAKzB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,QAAQ,CAAC,CAAC"} |
| import { customAction, customMutation, customQuery, } from "convex-helpers/server/customFunctions"; | ||
| import * as VanillaConvex from "./_generated/server.js"; | ||
| import { Logger, logLevelValidator } from "../logging/index.js"; | ||
| export const query = customQuery(VanillaConvex.query, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const mutation = customMutation(VanillaConvex.mutation, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const action = customAction(VanillaConvex.action, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalQuery = customQuery(VanillaConvex.internalQuery, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalMutation = customMutation(VanillaConvex.internalMutation, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| export const internalAction = customAction(VanillaConvex.internalAction, { | ||
| args: { logLevel: logLevelValidator }, | ||
| input: async (ctx, args) => { | ||
| return { ctx: { logger: new Logger(args.logLevel) }, args: {} }; | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=functions.js.map |
| {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/component/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,cAAc,EACd,WAAW,GACZ,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,aAAa,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAC,QAAQ,EAAE;IAC7D,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,CAAC,MAAM,EAAE;IACvD,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC,aAAa,CAAC,aAAa,EAAE;IACpE,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC,aAAa,CAAC,gBAAgB,EAAE;IAC7E,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE;IACvE,IAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE;IACrC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,CAAC;CACF,CAAC,CAAC"} |
| import { MutationCtx } from "./functions.js"; | ||
| export declare function ensureCoordinator(ctx: MutationCtx): Promise<void>; | ||
| export declare const shutdownGracefully: (ctx: MutationCtx) => Promise<{ | ||
| inProgressSenders: { | ||
| _id: import("convex/values").GenericId<"senders">; | ||
| _creationTime: number; | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }[]; | ||
| }>; | ||
| //# sourceMappingURL=helpers.d.ts.map |
| {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/component/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7C,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,iBA6CvD;AAED,eAAO,MAAM,kBAAkB,GAAU,KAAK,WAAW;;;;;;;EA+CxD,CAAC"} |
| import { internal } from "./_generated/api.js"; | ||
| export async function ensureCoordinator(ctx) { | ||
| ctx.logger.debug("Ensuring there's a notification coordinator"); | ||
| const coordinators = await ctx.db.query("senderCoordinator").collect(); | ||
| const activeCoordinators = []; | ||
| for (const coordinator of coordinators) { | ||
| const job = await ctx.db.system.get(coordinator.jobId); | ||
| if (job === null || | ||
| !(job.state.kind === "pending" || job.state.kind === "inProgress")) { | ||
| await ctx.db.delete(coordinator._id); | ||
| } | ||
| else { | ||
| activeCoordinators.push(coordinator); | ||
| } | ||
| } | ||
| if (activeCoordinators.length === 1) { | ||
| ctx.logger.debug(`Found existing coordinator with ID ${activeCoordinators[0]._id}`); | ||
| return; | ||
| } | ||
| if (activeCoordinators.length > 1) { | ||
| ctx.logger.error(`Unexpected state: Too many coordinators ${activeCoordinators.length}`); | ||
| throw new Error(`Unexpected state: Too many coordinators ${activeCoordinators.length}`); | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config?.state === "shutting_down") { | ||
| ctx.logger.info("Shutting down, so not starting a new coordinator."); | ||
| return; | ||
| } | ||
| const coordinatorJobId = await ctx.scheduler.runAfter(250, internal.internal.coordinateSendingPushNotifications, { | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| const coordinatorId = await ctx.db.insert("senderCoordinator", { | ||
| jobId: coordinatorJobId, | ||
| }); | ||
| ctx.logger.debug(`Started a new coordinator ${coordinatorId}`); | ||
| } | ||
| export const shutdownGracefully = async (ctx) => { | ||
| const coordinator = await ctx.db.query("senderCoordinator").unique(); | ||
| if (coordinator === null) { | ||
| ctx.logger.debug("No coordinator found, no need to restart it"); | ||
| } | ||
| else { | ||
| ctx.logger.info(`Stopping coordinator ${coordinator._id}`); | ||
| await ctx.scheduler.cancel(coordinator.jobId); | ||
| await ctx.db.delete(coordinator._id); | ||
| } | ||
| const senders = await ctx.db.query("senders").collect(); | ||
| const inProgressSenders = []; | ||
| for (const sender of senders) { | ||
| const jobId = sender.jobId; | ||
| const job = await ctx.db.system.get(jobId); | ||
| if (job === null) { | ||
| ctx.logger.error(`Sender ${sender._id} has no job, cleaning up`); | ||
| await ctx.db.delete(sender._id); | ||
| continue; | ||
| } | ||
| switch (job.state.kind) { | ||
| case "pending": | ||
| ctx.logger.info(`Stopping sender ${sender._id}`); | ||
| await ctx.scheduler.cancel(sender.jobId); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| case "inProgress": | ||
| inProgressSenders.push(sender); | ||
| break; | ||
| case "failed": | ||
| case "success": | ||
| case "canceled": | ||
| case null: | ||
| ctx.logger.debug(`Sender ${sender._id} is already done, cleaning up`); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| default: { | ||
| const _typeCheck = job.state; | ||
| ctx.logger.error( | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| `Unknown job state ${job.state.kind} for sender ${sender._id}. Cleaning it up. `); | ||
| await ctx.db.delete(sender._id); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| return { inProgressSenders }; | ||
| }; | ||
| //# sourceMappingURL=helpers.js.map |
| {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/component/helpers.ts"],"names":[],"mappings":"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"} |
| export declare const markNotificationState: import("convex/server").RegisteredMutation<"internal", { | ||
| notifications: { | ||
| state: "delivered" | "failed" | "maybe_delivered"; | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| }[]; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const coordinateSendingPushNotifications: import("convex/server").RegisteredMutation<"internal", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const checkForFailedAction: import("convex/server").RegisteredMutation<"internal", { | ||
| notificationIds: import("convex/values").GenericId<"notifications">[]; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const action_sendPushNotifications: import("convex/server").RegisteredAction<"internal", { | ||
| notifications: { | ||
| _id: import("convex/values").GenericId<"notifications">; | ||
| message: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| to: string; | ||
| }; | ||
| }[]; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| //# sourceMappingURL=internal.d.ts.map |
| {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/component/internal.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB;;;;;;;iBA6ChC,CAAC;AAOH,eAAO,MAAM,kCAAkC;;iBAsH7C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;iBAkB/B,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;iBAiHvC,CAAC"} |
| import { v } from "convex/values"; | ||
| import { internalAction, internalMutation } from "./functions.js"; | ||
| import { internal } from "./_generated/api.js"; | ||
| import { ensureCoordinator } from "./helpers.js"; | ||
| import { notificationFields } from "./schema.js"; | ||
| export const markNotificationState = internalMutation({ | ||
| args: { | ||
| notifications: v.array(v.object({ | ||
| _id: v.id("notifications"), | ||
| state: v.union(v.literal("delivered"), v.literal("failed"), v.literal("maybe_delivered")), | ||
| })), | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| }, | ||
| handler: async (ctx, { notifications, checkJobId }) => { | ||
| ctx.logger.debug(`Marking state for ${notifications.length} notifications`); | ||
| for (const notification of notifications) { | ||
| const { _id, state } = notification; | ||
| switch (state) { | ||
| case "delivered": | ||
| ctx.logger.debug(`Marking notification ${_id} as delivered`); | ||
| await ctx.db.patch(_id, { | ||
| state: "delivered", | ||
| }); | ||
| break; | ||
| case "failed": { | ||
| ctx.logger.debug(`Marking notification ${_id} as needing retry`); | ||
| const notification = await ctx.db.get(_id); | ||
| await ctx.db.patch(_id, { | ||
| state: "needs_retry", | ||
| numPreviousFailures: notification.numPreviousFailures + 1, | ||
| }); | ||
| break; | ||
| } | ||
| case "maybe_delivered": | ||
| ctx.logger.debug(`Marking notification ${_id} as maybe delivered`); | ||
| await ctx.db.patch(_id, { | ||
| state: "maybe_delivered", | ||
| }); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Cancelling scheduled check ${checkJobId}`); | ||
| await ctx.scheduler.cancel(checkJobId); | ||
| await ensureCoordinator(ctx); | ||
| }, | ||
| }); | ||
| const MAX_NOTIFICATIONS_PER_SEND = 100; | ||
| const MAX_SENDERS = 10; | ||
| const MAX_SENDER_DURATION_MS = 10_000; | ||
| const MAX_RETRY_ATTEMPTS = 5; | ||
| export const coordinateSendingPushNotifications = internalMutation({ | ||
| args: {}, | ||
| handler: async (ctx) => { | ||
| ctx.logger.debug("Coordinate sending push notifications"); | ||
| // Get notifications | ||
| const retryNotifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("state", (q) => q.eq("state", "needs_retry")) | ||
| .take(MAX_NOTIFICATIONS_PER_SEND); | ||
| const unsentNotifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("state", (q) => q.eq("state", "awaiting_delivery")) | ||
| .take(MAX_NOTIFICATIONS_PER_SEND - retryNotifications.length); | ||
| ctx.logger.debug(`Found ${retryNotifications.length} retry notifications and ${unsentNotifications.length} unsent notifications`); | ||
| const notificationsToProcess = [ | ||
| ...retryNotifications, | ||
| ...unsentNotifications, | ||
| ]; | ||
| if (notificationsToProcess.length === 0) { | ||
| // Nothing to do! | ||
| ctx.logger.info("No notifications to send, doing nothing"); | ||
| return; | ||
| } | ||
| const senders = await ctx.db.query("senders").collect(); | ||
| let numActiveSenders = 0; | ||
| for (const sender of senders) { | ||
| const senderJob = await ctx.db.system.get(sender.jobId); | ||
| if (senderJob?.state.kind === "inProgress" || | ||
| senderJob?.state.kind === "pending") { | ||
| numActiveSenders++; | ||
| } | ||
| else { | ||
| ctx.logger.debug(`Removing sender in state ${senderJob?.state.kind}`); | ||
| await ctx.db.delete(sender._id); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Found ${numActiveSenders} active senders`); | ||
| if (numActiveSenders >= MAX_SENDERS) { | ||
| // Don't add another sender yet | ||
| ctx.logger.debug(`Not starting another sender: already ${numActiveSenders}`); | ||
| ctx.logger.debug(`When one sender finishes, or fails, we'll coordinate sending these notifications.`); | ||
| return; | ||
| } | ||
| const notificationsToSend = notificationsToProcess.filter((n) => n.numPreviousFailures < MAX_RETRY_ATTEMPTS); | ||
| const notificationsToMarkAsUnableToDeliver = notificationsToProcess.filter((n) => n.numPreviousFailures >= MAX_RETRY_ATTEMPTS); | ||
| for (const notification of notificationsToMarkAsUnableToDeliver) { | ||
| if (notification.numPreviousFailures >= MAX_RETRY_ATTEMPTS) { | ||
| await ctx.db.patch(notification._id, { | ||
| state: "unable_to_deliver", | ||
| }); | ||
| } | ||
| } | ||
| for (const notification of notificationsToSend) { | ||
| await ctx.db.patch(notification._id, { | ||
| state: "in_progress", | ||
| }); | ||
| } | ||
| ctx.logger.debug(`Marking all notifications as in progress`); | ||
| const checkJobId = await ctx.scheduler.runAfter(MAX_SENDER_DURATION_MS, internal.internal.checkForFailedAction, { | ||
| notificationIds: notificationsToSend.map((n) => n._id), | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| const senderJobId = await ctx.scheduler.runAfter(0, internal.internal.action_sendPushNotifications, { | ||
| checkJobId, | ||
| notifications: notificationsToSend.map((n) => { | ||
| return { | ||
| message: { | ||
| to: n.token, | ||
| _contentAvailable: n.metadata._contentAvailable ?? undefined, | ||
| data: n.metadata.data ?? undefined, | ||
| title: n.metadata.title, | ||
| body: n.metadata.body ?? undefined, | ||
| ttl: n.metadata.ttl ?? undefined, | ||
| expiration: n.metadata.expiration ?? undefined, | ||
| priority: n.metadata.priority ?? undefined, | ||
| subtitle: n.metadata.subtitle ?? undefined, | ||
| sound: n.metadata.sound ?? undefined, | ||
| badge: n.metadata.badge ?? undefined, | ||
| interruptionLevel: n.metadata.interruptionLevel ?? undefined, | ||
| channelId: n.metadata.channelId ?? undefined, | ||
| categoryId: n.metadata.categoryId ?? undefined, | ||
| mutableContent: n.metadata.mutableContent ?? undefined, | ||
| }, | ||
| _id: n._id, | ||
| }; | ||
| }), | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| await ctx.db.insert("senders", { | ||
| jobId: senderJobId, | ||
| checkJobId, | ||
| }); | ||
| ctx.logger.debug(`Started a new sender ${senderJobId} with job ${senderJobId} and check job ${checkJobId}`); | ||
| }, | ||
| }); | ||
| export const checkForFailedAction = internalMutation({ | ||
| args: { | ||
| notificationIds: v.array(v.id("notifications")), | ||
| }, | ||
| handler: async (ctx, { notificationIds }) => { | ||
| console.warn(`Could not determine delivery status for ${notificationIds.length} notifications:`, notificationIds); | ||
| for (const notificationId of notificationIds) { | ||
| // We don't really know what happened to these notifications, | ||
| // so we can't safely retry these. | ||
| await ctx.db.patch(notificationId, { | ||
| state: "maybe_delivered", | ||
| }); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| }, | ||
| }); | ||
| export const action_sendPushNotifications = internalAction({ | ||
| args: { | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| notifications: v.array(v.object({ | ||
| message: v.object({ | ||
| to: v.string(), | ||
| ...notificationFields | ||
| }), | ||
| _id: v.id("notifications"), | ||
| })), | ||
| }, | ||
| handler: async (ctx, args) => { | ||
| ctx.logger.debug(`Sending ${args.notifications.length} push notifications via Expo's API`); | ||
| ctx.logger.debug(`Notification IDs: ${JSON.stringify(args.notifications.map((n) => n._id))}`); | ||
| let response; | ||
| try { | ||
| // https://docs.expo.dev/push-notifications/sending-notifications/#http2-api | ||
| response = await fetch("https://exp.host/--/api/v2/push/send", { | ||
| method: "POST", | ||
| headers: { | ||
| Accept: "application/json", | ||
| "Accept-encoding": "gzip, deflate", | ||
| "Content-Type": "application/json", | ||
| }, | ||
| body: JSON.stringify(args.notifications.map((n) => n.message)), | ||
| }); | ||
| } | ||
| catch (_e) { | ||
| ctx.logger.error("Failed during during fetch for sending push notifications:", _e); | ||
| ctx.logger.debug(`Marking ${args.notifications.length} notifications as failed so they can be retried`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: args.notifications.map((n) => { | ||
| return { | ||
| _id: n._id, | ||
| // It's unlikely that the notifications were actually delivered | ||
| // if the fetch failed, so we mark them as failed. | ||
| state: "failed", | ||
| }; | ||
| }), | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| return; | ||
| } | ||
| if (!response.ok) { | ||
| ctx.logger.warn(`Push notification failed with status ${response.status} and body ${await response.text()}`); | ||
| ctx.logger.debug(`Marking ${args.notifications.length} notifications as maybe delivered. They won't be retried.`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: args.notifications.map((n) => { | ||
| return { | ||
| _id: n._id, | ||
| // We don't really know what happened to these notifications, | ||
| // so we mark them as maybe_delivered, so we don't retry them | ||
| // again and again. | ||
| state: "maybe_delivered", | ||
| }; | ||
| }), | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| } | ||
| const responseBody = await response.json(); | ||
| ctx.logger.debug(`Response from Expo's API: ${JSON.stringify(responseBody)}`); | ||
| const notificationStates = []; | ||
| for (let idx = 0; idx < args.notifications.length; idx++) { | ||
| const notification = args.notifications[idx]; | ||
| const responseItem = responseBody.data[idx]; | ||
| if (responseItem && responseItem.status === "ok") { | ||
| notificationStates.push({ | ||
| _id: notification._id, | ||
| state: "delivered", | ||
| }); | ||
| } | ||
| else { | ||
| notificationStates.push({ | ||
| _id: notification._id, | ||
| state: "failed", | ||
| }); | ||
| } | ||
| } | ||
| ctx.logger.debug(`Successfully parsed response from Expo, and recording state`); | ||
| await ctx.runMutation(internal.internal.markNotificationState, { | ||
| notifications: notificationStates, | ||
| checkJobId: args.checkJobId, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=internal.js.map |
| {"version":3,"file":"internal.js","sourceRoot":"","sources":["../../../src/component/internal.ts"],"names":[],"mappings":"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"} |
| export declare const recordPushNotificationToken: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| pushToken: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const removePushNotificationToken: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const sendPushNotification: import("convex/server").RegisteredMutation<"public", { | ||
| allowUnregisteredTokens?: boolean | undefined; | ||
| userId: string; | ||
| notification: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<import("convex/values").GenericId<"notifications"> | null>>; | ||
| export declare const sendPushNotificationBatch: import("convex/server").RegisteredMutation<"public", { | ||
| allowUnregisteredTokens?: boolean | undefined; | ||
| notifications: { | ||
| userId: string; | ||
| notification: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| }[]; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<(import("convex/values").GenericId<"notifications"> | null)[]>>; | ||
| export declare const getNotification: import("convex/server").RegisteredQuery<"public", { | ||
| id: import("convex/values").GenericId<"notifications">; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| numPreviousFailures: number; | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| } | null>>; | ||
| export declare const getNotificationsForUser: import("convex/server").RegisteredQuery<"public", { | ||
| limit?: number | undefined; | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| numPreviousFailures: number; | ||
| _creationTime: number; | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| id: import("convex/values").GenericId<"notifications">; | ||
| }[]>>; | ||
| export declare const deleteNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const pauseNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const unpauseNotificationsForUser: import("convex/server").RegisteredMutation<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<void>>; | ||
| export declare const getStatusForUser: import("convex/server").RegisteredQuery<"public", { | ||
| userId: string; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| hasToken: boolean; | ||
| paused: boolean; | ||
| }>>; | ||
| export declare const shutdown: import("convex/server").RegisteredMutation<"public", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<{ | ||
| message: string; | ||
| data?: undefined; | ||
| } | { | ||
| message: string; | ||
| data: { | ||
| inProgressSenderIds: import("convex/values").GenericId<"senders">[]; | ||
| }; | ||
| }>>; | ||
| export declare const restart: import("convex/server").RegisteredMutation<"public", { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| }, Promise<boolean>>; | ||
| //# sourceMappingURL=public.d.ts.map |
| {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/component/public.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B;;;;iBAwBtC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;iBAgBtC,CAAC;AAQH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;sEAQ/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;0EAwBpC,CAAC;AAwCH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;UAoB1B,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;KAkClC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;iBAkCrC,CAAC;AAGH,eAAO,MAAM,yBAAyB;;;iBAiBpC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;iBAiBtC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;GAmB3B,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;GA6BnB,CAAC;AAEH,eAAO,MAAM,OAAO;;oBAwBlB,CAAC"} |
| import { ConvexError, v } from "convex/values"; | ||
| import { mutation, query } from "./functions.js"; | ||
| import { notificationFields, notificationState } from "./schema.js"; | ||
| import { ensureCoordinator, shutdownGracefully } from "./helpers.js"; | ||
| import { api } from "./_generated/api.js"; | ||
| const DEFAULT_LIMIT = 1000; | ||
| export const recordPushNotificationToken = mutation({ | ||
| args: { | ||
| userId: v.string(), | ||
| pushToken: v.string(), | ||
| }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId, pushToken }) => { | ||
| if (pushToken === "") { | ||
| ctx.logger.debug("Push token is empty, skipping"); | ||
| return; | ||
| } | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken !== null) { | ||
| ctx.logger.debug(`Push token already exists for user ${userId}, updating token`); | ||
| await ctx.db.patch(existingToken._id, { token: pushToken }); | ||
| return; | ||
| } | ||
| await ctx.db.insert("pushTokens", { userId, token: pushToken }); | ||
| }, | ||
| }); | ||
| export const removePushNotificationToken = mutation({ | ||
| args: { | ||
| userId: v.string(), | ||
| }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| await ctx.db.delete(existingToken._id); | ||
| }, | ||
| }); | ||
| const sendPushNotificationArgs = v.object({ | ||
| userId: v.string(), | ||
| notification: v.object(notificationFields), | ||
| allowUnregisteredTokens: v.optional(v.boolean()), | ||
| }); | ||
| export const sendPushNotification = mutation({ | ||
| args: sendPushNotificationArgs, | ||
| returns: v.union(v.id("notifications"), v.null()), | ||
| handler: async (ctx, args) => { | ||
| const result = await sendPushNotificationHandler(ctx, args); | ||
| await ensureCoordinator(ctx); | ||
| return result; | ||
| }, | ||
| }); | ||
| export const sendPushNotificationBatch = mutation({ | ||
| args: { | ||
| notifications: v.array(v.object({ | ||
| userId: v.string(), | ||
| notification: v.object(notificationFields), | ||
| })), | ||
| allowUnregisteredTokens: v.optional(v.boolean()), | ||
| }, | ||
| returns: v.array(v.union(v.id("notifications"), v.null())), | ||
| handler: async (ctx, args) => { | ||
| const results = []; | ||
| for (const { userId, notification } of args.notifications) { | ||
| const result = await sendPushNotificationHandler(ctx, { | ||
| userId, | ||
| notification, | ||
| allowUnregisteredTokens: args.allowUnregisteredTokens, | ||
| }); | ||
| results.push(result); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| return results; | ||
| }, | ||
| }); | ||
| async function sendPushNotificationHandler(ctx, args) { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| ctx.logger.error(`No push token found for user ${args.userId}, cannot send notification`); | ||
| if (args.allowUnregisteredTokens) { | ||
| return null; | ||
| } | ||
| throw new ConvexError({ | ||
| code: "NoPushToken", | ||
| message: "No push token found for user", | ||
| userId: args.userId, | ||
| notification: args.notification, | ||
| }); | ||
| } | ||
| if (token.notificationsPaused) { | ||
| ctx.logger.info(`Notifications are paused for user ${args.userId}, skipping`); | ||
| return null; | ||
| } | ||
| const id = await ctx.db.insert("notifications", { | ||
| token: token.token, | ||
| metadata: args.notification, | ||
| state: "awaiting_delivery", | ||
| numPreviousFailures: 0, | ||
| }); | ||
| ctx.logger.debug(`Recording notification for user ${args.userId}`); | ||
| return id; | ||
| } | ||
| export const getNotification = query({ | ||
| args: { id: v.id("notifications") }, | ||
| returns: v.union(v.null(), v.object({ | ||
| ...notificationFields, | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| _creationTime: v.number(), | ||
| })), | ||
| handler: async (ctx, args) => { | ||
| const notification = await ctx.db.get(args.id); | ||
| if (!notification) { | ||
| return null; | ||
| } | ||
| const { metadata, numPreviousFailures, state, _creationTime } = notification; | ||
| return { ...metadata, numPreviousFailures, state, _creationTime }; | ||
| }, | ||
| }); | ||
| export const getNotificationsForUser = query({ | ||
| args: { userId: v.string(), limit: v.optional(v.number()) }, | ||
| returns: v.array(v.object({ | ||
| ...notificationFields, | ||
| id: v.id("notifications"), | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| _creationTime: v.number(), | ||
| })), | ||
| handler: async (ctx, args) => { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| return []; | ||
| } | ||
| const notifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("token", (q) => q.eq("token", token.token)) | ||
| .order("desc") | ||
| .take(args.limit ?? DEFAULT_LIMIT); | ||
| return notifications.map(({ _id, metadata, state, numPreviousFailures, _creationTime }) => ({ | ||
| id: _id, | ||
| ...metadata, | ||
| state: state, | ||
| numPreviousFailures: numPreviousFailures, | ||
| _creationTime, | ||
| })); | ||
| }, | ||
| }); | ||
| export const deleteNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| handler: async (ctx, args) => { | ||
| const token = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", args.userId)) | ||
| .unique(); | ||
| if (token === null) { | ||
| ctx.logger.info("No push token found for user, nothing to delete"); | ||
| return; | ||
| } | ||
| const notifications = await ctx.db | ||
| .query("notifications") | ||
| .withIndex("token", (q) => q.eq("token", token.token)) | ||
| .take(DEFAULT_LIMIT); | ||
| for (const notification of notifications) { | ||
| await ctx.db.delete(notification._id); | ||
| } | ||
| if (notifications.length > 0) { | ||
| ctx.logger.info(`Deleted ${notifications.length} notifications for user ${args.userId}`); | ||
| } | ||
| if (notifications.length === DEFAULT_LIMIT) { | ||
| ctx.logger.info(`Reached limit of ${DEFAULT_LIMIT} notifications for user ${args.userId},` + | ||
| ` scheduling another deletion`); | ||
| await ctx.scheduler.runAfter(0, api.public.deleteNotificationsForUser, { | ||
| ...args, | ||
| logLevel: ctx.logger.level, | ||
| }); | ||
| } | ||
| }, | ||
| }); | ||
| // e.g. pause sending notifications while the user is active in the app | ||
| export const pauseNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| ctx.logger.info(`Pausing notifications for user ${userId}`); | ||
| await ctx.db.patch(existingToken._id, { | ||
| notificationsPaused: true, | ||
| }); | ||
| }, | ||
| }); | ||
| export const unpauseNotificationsForUser = mutation({ | ||
| args: { userId: v.string() }, | ||
| returns: v.null(), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, doing nothing`); | ||
| return; | ||
| } | ||
| ctx.logger.info(`Unpausing notifications for user ${userId}`); | ||
| await ctx.db.patch(existingToken._id, { | ||
| notificationsPaused: false, | ||
| }); | ||
| }, | ||
| }); | ||
| export const getStatusForUser = query({ | ||
| args: { userId: v.string() }, | ||
| returns: v.object({ hasToken: v.boolean(), paused: v.boolean() }), | ||
| handler: async (ctx, { userId }) => { | ||
| const existingToken = await ctx.db | ||
| .query("pushTokens") | ||
| .withIndex("userId", (q) => q.eq("userId", userId)) | ||
| .unique(); | ||
| if (existingToken === null) { | ||
| ctx.logger.debug(`No push token found for user ${userId}, returning false`); | ||
| return { hasToken: false, paused: false }; | ||
| } | ||
| return { | ||
| hasToken: true, | ||
| paused: existingToken.notificationsPaused ?? false, | ||
| }; | ||
| }, | ||
| }); | ||
| export const shutdown = mutation({ | ||
| args: {}, | ||
| returns: v.object({ | ||
| message: v.string(), | ||
| data: v.optional(v.any()), | ||
| }), | ||
| handler: async (ctx) => { | ||
| const { inProgressSenders } = await shutdownGracefully(ctx); | ||
| if (inProgressSenders.length === 0) { | ||
| return { message: "success" }; | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config === null) { | ||
| ctx.logger.debug("No config found, creating it"); | ||
| await ctx.db.insert("config", { | ||
| state: "shutting_down", | ||
| }); | ||
| } | ||
| else { | ||
| await ctx.db.patch(config._id, { | ||
| state: "shutting_down", | ||
| }); | ||
| } | ||
| return { | ||
| message: `There are ${inProgressSenders.length} jobs currently sending notifications that will continue running. Wait a few seconds for them to finish and then restart the service.`, | ||
| data: { | ||
| inProgressSenderIds: inProgressSenders.map((sender) => sender._id), | ||
| }, | ||
| }; | ||
| }, | ||
| }); | ||
| export const restart = mutation({ | ||
| args: {}, | ||
| returns: v.boolean(), | ||
| handler: async (ctx) => { | ||
| const { inProgressSenders } = await shutdownGracefully(ctx); | ||
| if (inProgressSenders.length > 0) { | ||
| ctx.logger.error(`There are ${inProgressSenders.length} jobs currently sending notifications. Wait a few seconds for them to finish and try to restart again.`); | ||
| return false; | ||
| } | ||
| const config = await ctx.db.query("config").unique(); | ||
| if (config !== null) { | ||
| await ctx.db.patch(config._id, { | ||
| state: "running", | ||
| }); | ||
| } | ||
| else { | ||
| await ctx.db.insert("config", { | ||
| state: "running", | ||
| }); | ||
| } | ||
| await ensureCoordinator(ctx); | ||
| return true; | ||
| }, | ||
| }); | ||
| //# sourceMappingURL=public.js.map |
| {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/component/public.ts"],"names":[],"mappings":"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"} |
| export declare const notificationFields: { | ||
| _contentAvailable: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| data: import("convex/values").VAny<any, "optional", string>; | ||
| title: import("convex/values").VString<string | undefined, "optional">; | ||
| body: import("convex/values").VString<string | undefined, "optional">; | ||
| ttl: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| expiration: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| priority: import("convex/values").VUnion<"default" | "normal" | "high" | undefined, [import("convex/values").VLiteral<"default", "required">, import("convex/values").VLiteral<"normal", "required">, import("convex/values").VLiteral<"high", "required">], "optional", never>; | ||
| subtitle: import("convex/values").VString<string | undefined, "optional">; | ||
| sound: import("convex/values").VUnion<string | null | undefined, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "optional", never>; | ||
| badge: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| interruptionLevel: import("convex/values").VUnion<"active" | "critical" | "passive" | "time-sensitive" | undefined, [import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"critical", "required">, import("convex/values").VLiteral<"passive", "required">, import("convex/values").VLiteral<"time-sensitive", "required">], "optional", never>; | ||
| channelId: import("convex/values").VString<string | undefined, "optional">; | ||
| categoryId: import("convex/values").VString<string | undefined, "optional">; | ||
| mutableContent: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }; | ||
| /** | ||
| * Notification fields for push notifications. | ||
| */ | ||
| export type NotificationFields = { | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * When this is set to true, the notification will cause the iOS app to start in the background to run a background task. | ||
| * Your app needs to be configured to support this. | ||
| */ | ||
| _contentAvailable?: boolean; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * A JSON object delivered to your app. It may be up to about 4KiB; | ||
| * the total notification payload sent to Apple and Google must be at most 4KiB or else you will get a "Message Too Big" error. | ||
| */ | ||
| data?: any; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The title to display in the notification. Often displayed above the notification body. | ||
| * Maps to AndroidNotification.title and aps.alert.title. | ||
| */ | ||
| title: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The message to display in the notification. Maps to AndroidNotification.body and aps.alert.body. | ||
| */ | ||
| body?: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * Time to Live: the number of seconds for which the message may be kept around for redelivery | ||
| * if it hasn't been delivered yet. Defaults to undefined to use the respective defaults of each provider | ||
| * (1 month for Android/FCM as well as iOS/APNs). | ||
| */ | ||
| ttl?: number; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * Timestamp since the Unix epoch specifying when the message expires. | ||
| * Same effect as ttl (ttl takes precedence over expiration). | ||
| */ | ||
| expiration?: number; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * The delivery priority of the message. | ||
| * Specify default or omit this field to use the default priority on each platform ("normal" on Android and "high" on iOS). | ||
| */ | ||
| priority?: 'default' | 'normal' | 'high'; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * The subtitle to display in the notification below the title. | ||
| * Maps to aps.alert.subtitle. | ||
| */ | ||
| subtitle?: string; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Play a sound when the recipient receives this notification. Specify default to play the device's default notification sound, | ||
| * or omit this field to play no sound. Custom sounds need to be configured via the config plugin and | ||
| * then specified including the file extension. Example: bells_sound.wav. | ||
| */ | ||
| sound?: string | null; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Number to display in the badge on the app icon. Specify zero to clear the badge. | ||
| */ | ||
| badge?: number; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * The importance and delivery timing of a notification. | ||
| * The string values correspond to the UNNotificationInterruptionLevel enumeration cases. | ||
| */ | ||
| interruptionLevel?: 'active' | 'critical' | 'passive' | 'time-sensitive'; | ||
| /** | ||
| * Android Only | ||
| * | ||
| * ID of the Notification Channel through which to display this notification. | ||
| * If an ID is specified but the corresponding channel does not exist on the device (that has not yet been created by your app), | ||
| * the notification will not be displayed to the user. | ||
| */ | ||
| channelId?: string; | ||
| /** | ||
| * Android and iOS | ||
| * | ||
| * ID of the notification category that this notification is associated with. | ||
| */ | ||
| categoryId?: string; | ||
| /** | ||
| * iOS Only | ||
| * | ||
| * Specifies whether this notification can be intercepted by the client app. | ||
| * Defaults to false. | ||
| */ | ||
| mutableContent?: boolean; | ||
| }; | ||
| export declare const notificationState: import("convex/values").VUnion<"awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver", [import("convex/values").VLiteral<"awaiting_delivery", "required">, import("convex/values").VLiteral<"in_progress", "required">, import("convex/values").VLiteral<"delivered", "required">, import("convex/values").VLiteral<"needs_retry", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"maybe_delivered", "required">, import("convex/values").VLiteral<"unable_to_deliver", "required">], "required", never>; | ||
| declare const _default: import("convex/server").SchemaDefinition<{ | ||
| notifications: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| state: "awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver"; | ||
| token: string; | ||
| metadata: { | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }; | ||
| numPreviousFailures: number; | ||
| }, { | ||
| token: import("convex/values").VString<string, "required">; | ||
| metadata: import("convex/values").VObject<{ | ||
| _contentAvailable?: boolean | undefined; | ||
| data?: any; | ||
| title?: string | undefined; | ||
| body?: string | undefined; | ||
| ttl?: number | undefined; | ||
| expiration?: number | undefined; | ||
| priority?: "default" | "normal" | "high" | undefined; | ||
| subtitle?: string | undefined; | ||
| sound?: string | null | undefined; | ||
| badge?: number | undefined; | ||
| interruptionLevel?: "active" | "critical" | "passive" | "time-sensitive" | undefined; | ||
| channelId?: string | undefined; | ||
| categoryId?: string | undefined; | ||
| mutableContent?: boolean | undefined; | ||
| }, { | ||
| _contentAvailable: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| data: import("convex/values").VAny<any, "optional", string>; | ||
| title: import("convex/values").VString<string | undefined, "optional">; | ||
| body: import("convex/values").VString<string | undefined, "optional">; | ||
| ttl: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| expiration: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| priority: import("convex/values").VUnion<"default" | "normal" | "high" | undefined, [import("convex/values").VLiteral<"default", "required">, import("convex/values").VLiteral<"normal", "required">, import("convex/values").VLiteral<"high", "required">], "optional", never>; | ||
| subtitle: import("convex/values").VString<string | undefined, "optional">; | ||
| sound: import("convex/values").VUnion<string | null | undefined, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "optional", never>; | ||
| badge: import("convex/values").VFloat64<number | undefined, "optional">; | ||
| interruptionLevel: import("convex/values").VUnion<"active" | "critical" | "passive" | "time-sensitive" | undefined, [import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"critical", "required">, import("convex/values").VLiteral<"passive", "required">, import("convex/values").VLiteral<"time-sensitive", "required">], "optional", never>; | ||
| channelId: import("convex/values").VString<string | undefined, "optional">; | ||
| categoryId: import("convex/values").VString<string | undefined, "optional">; | ||
| mutableContent: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }, "required", "_contentAvailable" | "data" | "title" | "body" | "ttl" | "expiration" | "priority" | "subtitle" | "sound" | "badge" | "interruptionLevel" | "channelId" | "categoryId" | "mutableContent" | `data.${string}`>; | ||
| state: import("convex/values").VUnion<"awaiting_delivery" | "in_progress" | "delivered" | "needs_retry" | "failed" | "maybe_delivered" | "unable_to_deliver", [import("convex/values").VLiteral<"awaiting_delivery", "required">, import("convex/values").VLiteral<"in_progress", "required">, import("convex/values").VLiteral<"delivered", "required">, import("convex/values").VLiteral<"needs_retry", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"maybe_delivered", "required">, import("convex/values").VLiteral<"unable_to_deliver", "required">], "required", never>; | ||
| numPreviousFailures: import("convex/values").VFloat64<number, "required">; | ||
| }, "required", "state" | "token" | "metadata" | "numPreviousFailures" | "metadata._contentAvailable" | "metadata.data" | "metadata.title" | "metadata.body" | "metadata.ttl" | "metadata.expiration" | "metadata.priority" | "metadata.subtitle" | "metadata.sound" | "metadata.badge" | "metadata.interruptionLevel" | "metadata.channelId" | "metadata.categoryId" | "metadata.mutableContent" | `metadata.data.${string}`>, { | ||
| token: ["token", "_creationTime"]; | ||
| state: ["state", "_creationTime"]; | ||
| }, {}, {}>; | ||
| pushTokens: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| notificationsPaused?: boolean | undefined; | ||
| token: string; | ||
| userId: string; | ||
| }, { | ||
| userId: import("convex/values").VString<string, "required">; | ||
| token: import("convex/values").VString<string, "required">; | ||
| notificationsPaused: import("convex/values").VBoolean<boolean | undefined, "optional">; | ||
| }, "required", "token" | "userId" | "notificationsPaused">, { | ||
| userId: ["userId", "_creationTime"]; | ||
| }, {}, {}>; | ||
| senders: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| checkJobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }, { | ||
| jobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| checkJobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| }, "required", "jobId" | "checkJobId">, {}, {}, {}>; | ||
| senderCoordinator: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| jobId: import("convex/values").GenericId<"_scheduled_functions">; | ||
| }, { | ||
| jobId: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">; | ||
| }, "required", "jobId">, {}, {}, {}>; | ||
| config: import("convex/server").TableDefinition<import("convex/values").VObject<{ | ||
| state: "running" | "shutting_down"; | ||
| }, { | ||
| state: import("convex/values").VUnion<"running" | "shutting_down", [import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"shutting_down", "required">], "required", never>; | ||
| }, "required", "state">, {}, {}, {}>; | ||
| }, true>; | ||
| export default _default; | ||
| //# sourceMappingURL=schema.d.ts.map |
| {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;CAe9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,GAAG,CAAA;IAEV;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAEzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAEzE;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,imBAY7B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF,wBAwBG"} |
| import { defineSchema, defineTable } from "convex/server"; | ||
| import { v } from "convex/values"; | ||
| // https://docs.expo.dev/push-notifications/sending-notifications/#message-request-format | ||
| export const notificationFields = { | ||
| _contentAvailable: v.optional(v.boolean()), | ||
| data: v.optional(v.any()), | ||
| title: v.optional(v.string()), | ||
| body: v.optional(v.string()), | ||
| ttl: v.optional(v.number()), | ||
| expiration: v.optional(v.number()), | ||
| priority: v.optional(v.union(v.literal("default"), v.literal("normal"), v.literal("high"))), | ||
| subtitle: v.optional(v.string()), | ||
| sound: v.optional(v.union(v.string(), v.null())), | ||
| badge: v.optional(v.number()), | ||
| interruptionLevel: v.optional(v.union(v.literal("active"), v.literal("critical"), v.literal("passive"), v.literal("time-sensitive"))), | ||
| channelId: v.optional(v.string()), | ||
| categoryId: v.optional(v.string()), | ||
| mutableContent: v.optional(v.boolean()), | ||
| }; | ||
| export const notificationState = v.union(v.literal("awaiting_delivery"), v.literal("in_progress"), v.literal("delivered"), v.literal("needs_retry"), | ||
| // Expo returned a failure for this notification | ||
| v.literal("failed"), | ||
| // Failure before receiving confirmation of delivery, so not safe to retry | ||
| // without delivering twice | ||
| v.literal("maybe_delivered"), | ||
| // Exhausted retries to deliver | ||
| v.literal("unable_to_deliver")); | ||
| export default defineSchema({ | ||
| notifications: defineTable({ | ||
| token: v.string(), | ||
| metadata: v.object(notificationFields), | ||
| state: notificationState, | ||
| numPreviousFailures: v.number(), | ||
| }) | ||
| .index("token", ["token"]) | ||
| .index("state", ["state"]), | ||
| pushTokens: defineTable({ | ||
| userId: v.string(), | ||
| token: v.string(), | ||
| notificationsPaused: v.optional(v.boolean()), | ||
| }).index("userId", ["userId"]), | ||
| senders: defineTable({ | ||
| jobId: v.id("_scheduled_functions"), | ||
| checkJobId: v.id("_scheduled_functions"), | ||
| }), | ||
| senderCoordinator: defineTable({ | ||
| jobId: v.id("_scheduled_functions"), | ||
| }), | ||
| config: defineTable({ | ||
| state: v.union(v.literal("running"), v.literal("shutting_down")), | ||
| }), | ||
| }); | ||
| //# sourceMappingURL=schema.js.map |
| {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"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"} |
| import { Infer } from "convex/values"; | ||
| export declare const logLevelValidator: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>; | ||
| export type LogLevel = Infer<typeof logLevelValidator>; | ||
| export declare const logWithLevel: (level: LogLevel, configuredLevel: LogLevel, ...args: unknown[]) => void; | ||
| export declare class Logger { | ||
| private configuredLevel; | ||
| constructor(configuredLevel: LogLevel); | ||
| get level(): "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| debug(...args: unknown[]): void; | ||
| info(...args: unknown[]): void; | ||
| warn(...args: unknown[]): void; | ||
| error(...args: unknown[]): void; | ||
| } | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAK,MAAM,eAAe,CAAC;AAEzC,eAAO,MAAM,iBAAiB,oTAK7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEvD,eAAO,MAAM,YAAY,GACvB,OAAO,QAAQ,EACf,iBAAiB,QAAQ,EACzB,GAAG,MAAM,OAAO,EAAE,SAmBnB,CAAC;AAEF,qBAAa,MAAM;IACL,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,QAAQ;IAE7C,IAAI,KAAK,wCAER;IAED,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIxB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIvB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAIvB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;CAGzB"} |
| import { v } from "convex/values"; | ||
| export const logLevelValidator = v.union(v.literal("DEBUG"), v.literal("INFO"), v.literal("WARN"), v.literal("ERROR")); | ||
| const orderedLevels = ["DEBUG", "INFO", "WARN", "ERROR"]; | ||
| export const logWithLevel = (level, configuredLevel, ...args) => { | ||
| if (orderedLevels.indexOf(level) < orderedLevels.indexOf(configuredLevel)) { | ||
| return; | ||
| } | ||
| switch (level) { | ||
| case "DEBUG": | ||
| console.debug(...args); | ||
| break; | ||
| case "INFO": | ||
| console.info(...args); | ||
| break; | ||
| case "WARN": | ||
| console.warn(...args); | ||
| break; | ||
| case "ERROR": | ||
| console.error(...args); | ||
| break; | ||
| } | ||
| }; | ||
| export class Logger { | ||
| configuredLevel; | ||
| constructor(configuredLevel) { | ||
| this.configuredLevel = configuredLevel; | ||
| } | ||
| get level() { | ||
| return this.configuredLevel; | ||
| } | ||
| debug(...args) { | ||
| logWithLevel("DEBUG", this.configuredLevel, ...args); | ||
| } | ||
| info(...args) { | ||
| logWithLevel("INFO", this.configuredLevel, ...args); | ||
| } | ||
| warn(...args) { | ||
| logWithLevel("WARN", this.configuredLevel, ...args); | ||
| } | ||
| error(...args) { | ||
| logWithLevel("ERROR", this.configuredLevel, ...args); | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,CAAC,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CACtC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAClB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CACnB,CAAC;AAGF,MAAM,aAAa,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAe,EACf,eAAyB,EACzB,GAAG,IAAe,EAClB,EAAE;IACF,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC1E,OAAO;IACT,CAAC;IACD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,MAAM;QACR,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,MAAM;IACV,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,MAAM;IACG;IAApB,YAAoB,eAAyB;QAAzB,oBAAe,GAAf,eAAe,CAAU;IAAG,CAAC;IAEjD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;CACF"} |
| { | ||
| "type": "module" | ||
| } |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type * as functions from "../functions.js"; | ||
| import type * as helpers from "../helpers.js"; | ||
| import type * as internal_ from "../internal.js"; | ||
| import type * as public_ from "../public.js"; | ||
| import type { | ||
| ApiFromModules, | ||
| FilterApi, | ||
| FunctionReference, | ||
| } from "convex/server"; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| declare const fullApi: ApiFromModules<{ | ||
| functions: typeof functions; | ||
| helpers: typeof helpers; | ||
| internal: typeof internal_; | ||
| public: typeof public_; | ||
| }>; | ||
| export type Mounts = { | ||
| public: { | ||
| deleteNotificationsForUser: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| any | ||
| >; | ||
| getNotification: FunctionReference< | ||
| "query", | ||
| "public", | ||
| { id: string; logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR" }, | ||
| null | { | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: | ||
| | "awaiting_delivery" | ||
| | "in_progress" | ||
| | "delivered" | ||
| | "needs_retry" | ||
| | "failed" | ||
| | "maybe_delivered" | ||
| | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| } | ||
| >; | ||
| getNotificationsForUser: FunctionReference< | ||
| "query", | ||
| "public", | ||
| { | ||
| limit?: number; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| userId: string; | ||
| }, | ||
| Array<{ | ||
| _contentAvailable?: boolean; | ||
| _creationTime: number; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| id: string; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| numPreviousFailures: number; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| state: | ||
| | "awaiting_delivery" | ||
| | "in_progress" | ||
| | "delivered" | ||
| | "needs_retry" | ||
| | "failed" | ||
| | "maybe_delivered" | ||
| | "unable_to_deliver"; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }> | ||
| >; | ||
| getStatusForUser: FunctionReference< | ||
| "query", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| { hasToken: boolean; paused: boolean } | ||
| >; | ||
| pauseNotificationsForUser: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null | ||
| >; | ||
| recordPushNotificationToken: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| pushToken: string; | ||
| userId: string; | ||
| }, | ||
| null | ||
| >; | ||
| removePushNotificationToken: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null | ||
| >; | ||
| restart: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR" }, | ||
| boolean | ||
| >; | ||
| sendPushNotification: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { | ||
| allowUnregisteredTokens?: boolean; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| notification: { | ||
| _contentAvailable?: boolean; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }; | ||
| userId: string; | ||
| }, | ||
| string | null | ||
| >; | ||
| sendPushNotificationBatch: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { | ||
| allowUnregisteredTokens?: boolean; | ||
| logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; | ||
| notifications: Array<{ | ||
| notification: { | ||
| _contentAvailable?: boolean; | ||
| badge?: number; | ||
| body?: string; | ||
| categoryId?: string; | ||
| channelId?: string; | ||
| data?: any; | ||
| expiration?: number; | ||
| interruptionLevel?: | ||
| | "active" | ||
| | "critical" | ||
| | "passive" | ||
| | "time-sensitive"; | ||
| mutableContent?: boolean; | ||
| priority?: "default" | "normal" | "high"; | ||
| sound?: string | null; | ||
| subtitle?: string; | ||
| title?: string; | ||
| ttl?: number; | ||
| }; | ||
| userId: string; | ||
| }>; | ||
| }, | ||
| Array<string | null> | ||
| >; | ||
| shutdown: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR" }, | ||
| { data?: any; message: string } | ||
| >; | ||
| unpauseNotificationsForUser: FunctionReference< | ||
| "mutation", | ||
| "public", | ||
| { logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR"; userId: string }, | ||
| null | ||
| >; | ||
| }; | ||
| }; | ||
| // For now fullApiWithMounts is only fullApi which provides | ||
| // jump-to-definition in component client code. | ||
| // Use Mounts for the same type without the inference. | ||
| declare const fullApiWithMounts: typeof fullApi; | ||
| export declare const api: FilterApi< | ||
| typeof fullApiWithMounts, | ||
| FunctionReference<any, "public"> | ||
| >; | ||
| export declare const internal: FilterApi< | ||
| typeof fullApiWithMounts, | ||
| FunctionReference<any, "internal"> | ||
| >; | ||
| export declare const components: {}; |
| /* eslint-disable */ | ||
| /** | ||
| * Generated `api` utility. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { anyApi, componentsGeneric } from "convex/server"; | ||
| /** | ||
| * A utility for referencing Convex functions in your app's API. | ||
| * | ||
| * Usage: | ||
| * ```js | ||
| * const myFunctionReference = api.myModule.myFunction; | ||
| * ``` | ||
| */ | ||
| export const api = anyApi; | ||
| export const internal = anyApi; | ||
| export const components = componentsGeneric(); |
| /* eslint-disable */ | ||
| /** | ||
| * Generated data model types. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import type { | ||
| DataModelFromSchemaDefinition, | ||
| DocumentByName, | ||
| TableNamesInDataModel, | ||
| SystemTableNames, | ||
| } from "convex/server"; | ||
| import type { GenericId } from "convex/values"; | ||
| import schema from "../schema.js"; | ||
| /** | ||
| * The names of all of your Convex tables. | ||
| */ | ||
| export type TableNames = TableNamesInDataModel<DataModel>; | ||
| /** | ||
| * The type of a document stored in Convex. | ||
| * | ||
| * @typeParam TableName - A string literal type of the table name (like "users"). | ||
| */ | ||
| export type Doc<TableName extends TableNames> = DocumentByName< | ||
| DataModel, | ||
| TableName | ||
| >; | ||
| /** | ||
| * An identifier for a document in Convex. | ||
| * | ||
| * Convex documents are uniquely identified by their `Id`, which is accessible | ||
| * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids). | ||
| * | ||
| * Documents can be loaded using `db.get(id)` in query and mutation functions. | ||
| * | ||
| * IDs are just strings at runtime, but this type can be used to distinguish them from other | ||
| * strings when type checking. | ||
| * | ||
| * @typeParam TableName - A string literal type of the table name (like "users"). | ||
| */ | ||
| export type Id<TableName extends TableNames | SystemTableNames> = | ||
| GenericId<TableName>; | ||
| /** | ||
| * A type describing your Convex data model. | ||
| * | ||
| * This type includes information about what tables you have, the type of | ||
| * documents stored in those tables, and the indexes defined on them. | ||
| * | ||
| * This type is used to parameterize methods like `queryGeneric` and | ||
| * `mutationGeneric` to make them type-safe. | ||
| */ | ||
| export type DataModel = DataModelFromSchemaDefinition<typeof schema>; |
| /* eslint-disable */ | ||
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { | ||
| ActionBuilder, | ||
| AnyComponents, | ||
| HttpActionBuilder, | ||
| MutationBuilder, | ||
| QueryBuilder, | ||
| GenericActionCtx, | ||
| GenericMutationCtx, | ||
| GenericQueryCtx, | ||
| GenericDatabaseReader, | ||
| GenericDatabaseWriter, | ||
| FunctionReference, | ||
| } from "convex/server"; | ||
| import type { DataModel } from "./dataModel.js"; | ||
| type GenericCtx = | ||
| | GenericActionCtx<DataModel> | ||
| | GenericMutationCtx<DataModel> | ||
| | GenericQueryCtx<DataModel>; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const query: QueryBuilder<DataModel, "public">; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const internalQuery: QueryBuilder<DataModel, "internal">; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const mutation: MutationBuilder<DataModel, "public">; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const internalMutation: MutationBuilder<DataModel, "internal">; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const action: ActionBuilder<DataModel, "public">; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export declare const internalAction: ActionBuilder<DataModel, "internal">; | ||
| /** | ||
| * Define an HTTP action. | ||
| * | ||
| * This function will be used to respond to HTTP requests received by a Convex | ||
| * deployment if the requests matches the path and method where this action | ||
| * is routed. Be sure to route your action in `convex/http.js`. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up. | ||
| */ | ||
| export declare const httpAction: HttpActionBuilder; | ||
| /** | ||
| * A set of services for use within Convex query functions. | ||
| * | ||
| * The query context is passed as the first argument to any Convex query | ||
| * function run on the server. | ||
| * | ||
| * This differs from the {@link MutationCtx} because all of the services are | ||
| * read-only. | ||
| */ | ||
| export type QueryCtx = GenericQueryCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex mutation functions. | ||
| * | ||
| * The mutation context is passed as the first argument to any Convex mutation | ||
| * function run on the server. | ||
| */ | ||
| export type MutationCtx = GenericMutationCtx<DataModel>; | ||
| /** | ||
| * A set of services for use within Convex action functions. | ||
| * | ||
| * The action context is passed as the first argument to any Convex action | ||
| * function run on the server. | ||
| */ | ||
| export type ActionCtx = GenericActionCtx<DataModel>; | ||
| /** | ||
| * An interface to read from the database within Convex query functions. | ||
| * | ||
| * The two entry points are {@link DatabaseReader.get}, which fetches a single | ||
| * document by its {@link Id}, or {@link DatabaseReader.query}, which starts | ||
| * building a query. | ||
| */ | ||
| export type DatabaseReader = GenericDatabaseReader<DataModel>; | ||
| /** | ||
| * An interface to read from and write to the database within Convex mutation | ||
| * functions. | ||
| * | ||
| * Convex guarantees that all writes within a single mutation are | ||
| * executed atomically, so you never have to worry about partial writes leaving | ||
| * your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control) | ||
| * for the guarantees Convex provides your functions. | ||
| */ | ||
| export type DatabaseWriter = GenericDatabaseWriter<DataModel>; |
| /* eslint-disable */ | ||
| /** | ||
| * Generated utilities for implementing server-side Convex query and mutation functions. | ||
| * | ||
| * THIS CODE IS AUTOMATICALLY GENERATED. | ||
| * | ||
| * To regenerate, run `npx convex dev`. | ||
| * @module | ||
| */ | ||
| import { | ||
| actionGeneric, | ||
| httpActionGeneric, | ||
| queryGeneric, | ||
| mutationGeneric, | ||
| internalActionGeneric, | ||
| internalMutationGeneric, | ||
| internalQueryGeneric, | ||
| componentsGeneric, | ||
| } from "convex/server"; | ||
| /** | ||
| * Define a query in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to read your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const query = queryGeneric; | ||
| /** | ||
| * Define a query that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to read from your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The query function. It receives a {@link QueryCtx} as its first argument. | ||
| * @returns The wrapped query. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalQuery = internalQueryGeneric; | ||
| /** | ||
| * Define a mutation in this Convex app's public API. | ||
| * | ||
| * This function will be allowed to modify your Convex database and will be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const mutation = mutationGeneric; | ||
| /** | ||
| * Define a mutation that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * This function will be allowed to modify your Convex database. It will not be accessible from the client. | ||
| * | ||
| * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. | ||
| * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalMutation = internalMutationGeneric; | ||
| /** | ||
| * Define an action in this Convex app's public API. | ||
| * | ||
| * An action is a function which can execute any JavaScript code, including non-deterministic | ||
| * code and code with side-effects, like calling third-party services. | ||
| * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. | ||
| * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. | ||
| * | ||
| * @param func - The action. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped action. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const action = actionGeneric; | ||
| /** | ||
| * Define an action that is only accessible from other Convex functions (but not from the client). | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument. | ||
| * @returns The wrapped function. Include this as an `export` to name it and make it accessible. | ||
| */ | ||
| export const internalAction = internalActionGeneric; | ||
| /** | ||
| * Define a Convex HTTP action. | ||
| * | ||
| * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object | ||
| * as its second. | ||
| * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`. | ||
| */ | ||
| export const httpAction = httpActionGeneric; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
172
7.5%7
-30%7
-22.22%234578
-34.98%20
185.71%64
-34.69%4327
-32.45%