Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@convex-dev/expo-push-notifications

Package Overview
Dependencies
Maintainers
11
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@convex-dev/expo-push-notifications - npm Package Compare versions

Comparing version
0.2.7-alpha.0
to
0.3.0
+185
dist/client/index.d.ts
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>;
/// <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 -->

@@ -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, {

@@ -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;

@@ -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":"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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": "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":"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": "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;