easy-ping 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +548 -427
- package/dist/adapter-B7R4rXtJ.d.cts +17 -0
- package/dist/adapter-B7R4rXtJ.d.ts +17 -0
- package/dist/{adapter-BfLe2J0t.d.cts → adapter-D3lTy-4E.d.cts} +6 -32
- package/dist/{adapter-BfLe2J0t.d.ts → adapter-D3lTy-4E.d.ts} +6 -32
- package/dist/adapters/drizzle.cjs +1 -2
- package/dist/adapters/drizzle.cjs.map +1 -1
- package/dist/adapters/drizzle.d.cts +1 -1
- package/dist/adapters/drizzle.d.ts +1 -1
- package/dist/adapters/drizzle.js +3 -4
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/mongodb.cjs +144 -5
- package/dist/adapters/mongodb.cjs.map +1 -1
- package/dist/adapters/mongodb.d.cts +43 -18
- package/dist/adapters/mongodb.d.ts +43 -18
- package/dist/adapters/mongodb.js +77 -8
- package/dist/adapters/mongodb.js.map +1 -1
- package/dist/adapters/mysql.cjs +605 -0
- package/dist/adapters/mysql.cjs.map +1 -0
- package/dist/adapters/mysql.d.cts +38 -0
- package/dist/adapters/mysql.d.ts +38 -0
- package/dist/adapters/mysql.js +51 -0
- package/dist/adapters/mysql.js.map +1 -0
- package/dist/adapters/postgres.cjs +162 -9
- package/dist/adapters/postgres.cjs.map +1 -1
- package/dist/adapters/postgres.d.cts +44 -54
- package/dist/adapters/postgres.d.ts +44 -54
- package/dist/adapters/postgres.js +82 -42
- package/dist/adapters/postgres.js.map +1 -1
- package/dist/adapters/sqlite.cjs +593 -0
- package/dist/adapters/sqlite.cjs.map +1 -0
- package/dist/adapters/sqlite.d.cts +37 -0
- package/dist/adapters/sqlite.d.ts +37 -0
- package/dist/adapters/sqlite.js +53 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -14
- package/dist/browser.d.ts +2 -14
- package/dist/browser.js.map +1 -1
- package/dist/chunk-2EYKPF5A.js +393 -0
- package/dist/chunk-2EYKPF5A.js.map +1 -0
- package/dist/{chunk-3Y2MBUAW.js → chunk-3VOQOGDR.js} +4 -3
- package/dist/chunk-3VOQOGDR.js.map +1 -0
- package/dist/{chunk-PSJHXZPR.js → chunk-AEYYTE5I.js} +2 -2
- package/dist/chunk-AEYYTE5I.js.map +1 -0
- package/dist/chunk-CK5UPVYP.js +48 -0
- package/dist/chunk-CK5UPVYP.js.map +1 -0
- package/dist/{chunk-W6I3B2CI.js → chunk-E4IZ2CQC.js} +2 -2
- package/dist/{chunk-W6I3B2CI.js.map → chunk-E4IZ2CQC.js.map} +1 -1
- package/dist/chunk-HY47TQMY.js +52 -0
- package/dist/chunk-HY47TQMY.js.map +1 -0
- package/dist/{chunk-CYKAM7LE.js → chunk-JKTMUMQK.js} +31 -6
- package/dist/chunk-JKTMUMQK.js.map +1 -0
- package/dist/chunk-M4R77BJD.js +64 -0
- package/dist/chunk-M4R77BJD.js.map +1 -0
- package/dist/chunk-ORZKH224.js +75 -0
- package/dist/chunk-ORZKH224.js.map +1 -0
- package/dist/{chunk-DG3ZL5NP.js → chunk-USQ6CQTJ.js} +88 -3
- package/dist/chunk-USQ6CQTJ.js.map +1 -0
- package/dist/{chunk-YEMRRMJQ.js → chunk-XIDVLYNQ.js} +14 -4
- package/dist/chunk-XIDVLYNQ.js.map +1 -0
- package/dist/client.cjs +288 -17
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +53 -1
- package/dist/client.d.ts +53 -1
- package/dist/client.js +288 -17
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +239 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -57
- package/dist/index.d.ts +53 -57
- package/dist/index.js +60 -13
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +26 -5
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +28 -6
- package/dist/node.js.map +1 -1
- package/dist/{plugin-C9Hoxus2.d.ts → plugin-CHd2ZiGC.d.cts} +5 -21
- package/dist/{plugin-CiMsGlQe.d.cts → plugin-Cg9usuUi.d.ts} +5 -21
- package/dist/plugins/digests.cjs +1 -4
- package/dist/plugins/digests.cjs.map +1 -1
- package/dist/plugins/digests.d.cts +6 -31
- package/dist/plugins/digests.d.ts +6 -31
- package/dist/plugins/digests.js +1 -4
- package/dist/plugins/digests.js.map +1 -1
- package/dist/plugins/preferences-client.cjs.map +1 -1
- package/dist/plugins/preferences-client.d.cts +2 -2
- package/dist/plugins/preferences-client.d.ts +2 -2
- package/dist/plugins/preferences-client.js +1 -1
- package/dist/plugins/preferences-react.cjs.map +1 -1
- package/dist/plugins/preferences-react.js.map +1 -1
- package/dist/plugins/preferences.cjs +1 -2
- package/dist/plugins/preferences.cjs.map +1 -1
- package/dist/plugins/preferences.d.cts +2 -2
- package/dist/plugins/preferences.d.ts +2 -2
- package/dist/plugins/preferences.js +3 -3
- package/dist/plugins/preferences.js.map +1 -1
- package/dist/plugins/push.cjs +1 -2
- package/dist/plugins/push.cjs.map +1 -1
- package/dist/plugins/push.d.cts +6 -26
- package/dist/plugins/push.d.ts +6 -26
- package/dist/plugins/push.js +4 -4
- package/dist/plugins/push.js.map +1 -1
- package/dist/providers/web-push.cjs.map +1 -1
- package/dist/providers/web-push.d.cts +3 -10
- package/dist/providers/web-push.d.ts +3 -10
- package/dist/providers/web-push.js.map +1 -1
- package/dist/react.cjs +311 -19
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +53 -4
- package/dist/react.d.ts +53 -4
- package/dist/react.js +311 -19
- package/dist/react.js.map +1 -1
- package/dist/schema.cjs +119 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +20 -14
- package/dist/schema.d.ts +20 -14
- package/dist/schema.js +4 -2
- package/dist/signals-kPmOlKDX.d.cts +27 -0
- package/dist/signals-kPmOlKDX.d.ts +27 -0
- package/dist/sw.cjs +39 -0
- package/dist/sw.cjs.map +1 -0
- package/dist/sw.d.cts +52 -0
- package/dist/sw.d.ts +52 -0
- package/dist/sw.js +36 -0
- package/dist/sw.js.map +1 -0
- package/dist/testing.cjs +3 -19
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +4 -22
- package/dist/testing.d.ts +4 -22
- package/dist/testing.js +3 -19
- package/dist/testing.js.map +1 -1
- package/package.json +17 -1
- package/dist/chunk-3Y2MBUAW.js.map +0 -1
- package/dist/chunk-CYKAM7LE.js.map +0 -1
- package/dist/chunk-DG3ZL5NP.js.map +0 -1
- package/dist/chunk-PSJHXZPR.js.map +0 -1
- package/dist/chunk-YEMRRMJQ.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/mongodb/adapter.ts","../../src/adapters/mongodb/indexes.ts"],"names":["options","spec"],"mappings":"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","file":"mongodb.js","sourcesContent":["import type {\n ClaimArgs,\n ClaimedDelivery,\n DatabaseAdapter,\n DeliveryRelease,\n FeedPage,\n FeedQuery,\n InsertNotification,\n} from \"../../core/adapter\";\nimport { decodeBase64Url, encodeBase64Url } from \"../../core/base64url\";\nimport { isOperator, type QueryOptions, type WhereClause } from \"../../core/store\";\nimport type { Channel, DeliveryRecord, DeliveryStatus, NotificationRecord } from \"../../core/types\";\n\ntype Document = Record<string, unknown>;\n\n/**\n * Minimal structural view of the pieces of the Mongo driver this uses.\n *\n * Typed structurally rather than against the real `Db` so `mongodb` stays an\n * optional peer dependency: an app on Postgres never installs it, and its\n * types are not needed to typecheck this file.\n */\ntype MongoCollection = {\n insertMany(docs: Document[], options?: unknown): Promise<unknown>;\n insertOne(doc: Document, options?: unknown): Promise<unknown>;\n find(filter: Document, options?: Document): { toArray(): Promise<Document[]> };\n findOne(filter: Document, options?: Document): Promise<Document | null>;\n findOneAndUpdate(\n filter: Document,\n update: Document | Document[],\n options?: Document,\n ): Promise<Document | null>;\n updateOne(\n filter: Document,\n update: Document | Document[],\n options?: Document,\n ): Promise<{\n matchedCount: number;\n modifiedCount: number;\n upsertedCount?: number;\n }>;\n updateMany(\n filter: Document,\n update: Document | Document[],\n options?: Document,\n ): Promise<{\n matchedCount: number;\n modifiedCount: number;\n }>;\n deleteMany(filter: Document, options?: Document): Promise<{ deletedCount: number }>;\n countDocuments(filter: Document, options?: Document): Promise<number>;\n createIndex(spec: Document, options?: Document): Promise<string>;\n};\n\ntype MongoDb = {\n collection(name: string): MongoCollection;\n};\n\ntype MongoSession = {\n withTransaction<T>(fn: () => Promise<T>): Promise<T>;\n endSession(): Promise<void>;\n};\n\ntype MongoClient = {\n startSession(): MongoSession;\n};\n\nexport type MongoAdapterOptions = {\n /** Prefixes every collection name, matching the SQL adapter's table prefix. */\n prefix?: string;\n /**\n * The MongoClient the db came from. Supplying it makes createNotifications\n * atomic; without it a crash between the two writes can leave a notification\n * with no deliveries. Transactions need a replica set, so it is opt-in — a\n * standalone mongod rejects the session outright.\n */\n client?: unknown;\n};\n\nconst str = (value: unknown): string => String(value);\nconst nullableStr = (value: unknown): string | null => (value == null ? null : String(value));\nconst num = (value: unknown): number => Number(value);\nconst date = (value: unknown): Date => (value instanceof Date ? value : new Date(String(value)));\nconst nullableDate = (value: unknown): Date | null =>\n value == null ? null : value instanceof Date ? value : new Date(String(value));\n\nconst encodeCursor = (createdAt: Date, id: string) =>\n encodeBase64Url(`${createdAt.toISOString()}|${id}`);\n\nfunction decodeCursor(cursor: string): { createdAt: Date; id: string } | null {\n const decoded = decodeBase64Url(cursor);\n if (!decoded) return null;\n\n const [iso, id] = decoded.split(\"|\");\n if (!iso || !id) return null;\n\n const createdAt = new Date(iso);\n return Number.isNaN(createdAt.getTime()) ? null : { createdAt, id };\n}\n\n/** Documents carry the id as `_id`; the rest of the library never sees that. */\nfunction toNotification(doc: Document): NotificationRecord {\n return {\n id: str(doc._id),\n userId: str(doc.userId),\n type: str(doc.type),\n payload: doc.payload,\n actorId: nullableStr(doc.actorId),\n groupKey: nullableStr(doc.groupKey),\n dedupeKey: nullableStr(doc.dedupeKey),\n seenAt: nullableDate(doc.seenAt),\n readAt: nullableDate(doc.readAt),\n archivedAt: nullableDate(doc.archivedAt),\n createdAt: date(doc.createdAt),\n };\n}\n\nfunction toDelivery(doc: Document): DeliveryRecord {\n return {\n id: str(doc._id),\n notificationId: str(doc.notificationId),\n channel: str(doc.channel) as Channel,\n status: str(doc.status) as DeliveryStatus,\n attempts: num(doc.attempts),\n maxAttempts: num(doc.maxAttempts),\n notBefore: date(doc.notBefore),\n claimedAt: nullableDate(doc.claimedAt),\n claimedBy: nullableStr(doc.claimedBy),\n lastError: nullableStr(doc.lastError),\n updatedAt: date(doc.updatedAt),\n };\n}\n\n/** The store hands `id`; documents key on `_id`. */\nconst toMongoField = (field: string) => (field === \"id\" ? \"_id\" : field);\n\n/** Translates a WhereClause into a Mongo filter. */\nfunction toFilter(where: WhereClause): Document {\n const filter: Document = {};\n\n for (const [field, condition] of Object.entries(where)) {\n const key = toMongoField(field);\n\n if (condition === null) {\n filter[key] = null;\n continue;\n }\n\n if (!isOperator(condition)) {\n // The store already refuses these; this is the last line before the\n // driver, where `{ $ne: null }` stops being data and becomes a query.\n if (typeof condition === \"object\" && !(condition instanceof Date)) {\n throw new Error(`mongo filter on \"${field}\" received an object; only scalars are bound`);\n }\n filter[key] = condition;\n continue;\n }\n\n const operator = condition as Record<string, unknown>;\n if (\"in\" in operator) filter[key] = { $in: operator.in };\n else if (\"lt\" in operator) filter[key] = { $lt: operator.lt };\n else if (\"lte\" in operator) filter[key] = { $lte: operator.lte };\n else if (\"gt\" in operator) filter[key] = { $gt: operator.gt };\n else if (\"gte\" in operator) filter[key] = { $gte: operator.gte };\n else if (\"not\" in operator) {\n // $ne null also matches a missing field, which is what \"not null\" means.\n filter[key] = { $ne: operator.not };\n }\n }\n\n return filter;\n}\n\n/** A duplicate on a unique index, rather than a real write failure. */\nconst isDuplicateKey = (error: unknown): boolean => {\n const code = (error as { code?: number; writeErrors?: { code?: number }[] })?.code;\n if (code === 11000) return true;\n const writeErrors = (error as { writeErrors?: { code?: number }[] })?.writeErrors;\n return Array.isArray(writeErrors) && writeErrors.some((entry) => entry?.code === 11000);\n};\n\nexport function mongoAdapter(db: unknown, options: MongoAdapterOptions = {}): DatabaseAdapter {\n const database = db as MongoDb;\n const prefix = options.prefix ?? \"\";\n\n const client = options.client as MongoClient | undefined;\n\n const notifications = () => database.collection(`${prefix}notification`);\n const deliveries = () => database.collection(`${prefix}notification_delivery`);\n\n /**\n * Runs `fn` in a transaction when a client was supplied, and plainly\n * otherwise. The session must reach every command inside, so `fn` receives\n * it — a write that omits it silently runs outside the transaction.\n *\n * One transaction per notification, not per batch: a duplicate key aborts\n * the transaction it happens in, and dedupe is the expected path here, so a\n * batch-wide transaction would throw away the notifications around it.\n */\n async function atomically<T>(fn: (session?: MongoSession) => Promise<T>): Promise<T> {\n if (!client) return fn();\n\n const session = client.startSession();\n try {\n return await session.withTransaction(() => fn(session));\n } finally {\n await session.endSession();\n }\n }\n\n return {\n name: \"mongodb\",\n // Documents keep the declared camelCase, and store objects natively.\n naming: \"preserve\",\n serializesJson: false,\n\n async createNotifications(input: readonly InsertNotification[]) {\n if (input.length === 0) return { created: [], deduped: [] };\n\n const created: string[] = [];\n const deduped: string[] = [];\n\n for (const row of input) {\n const now = new Date();\n\n try {\n await atomically(async (session) => {\n const options = session ? { session } : undefined;\n\n // The notification goes in first: it carries the unique dedupe\n // index, so a duplicate is rejected before any delivery is written.\n await notifications().insertOne(\n {\n _id: row.id,\n userId: row.userId,\n type: row.type,\n payload: row.payload ?? null,\n actorId: row.actorId ?? null,\n groupKey: row.groupKey ?? null,\n dedupeKey: row.dedupeKey ?? null,\n seenAt: null,\n readAt: null,\n archivedAt: null,\n createdAt: now,\n },\n options,\n );\n\n if (row.deliveries.length > 0) {\n await deliveries().insertMany(\n row.deliveries.map((delivery) => ({\n _id: delivery.id,\n notificationId: row.id,\n channel: delivery.channel,\n status: \"pending\",\n attempts: 0,\n maxAttempts: delivery.maxAttempts,\n notBefore: delivery.notBefore,\n claimedAt: null,\n claimedBy: null,\n lastError: null,\n updatedAt: now,\n })),\n options,\n );\n }\n });\n\n created.push(row.id);\n } catch (error) {\n if (!isDuplicateKey(error)) throw error;\n deduped.push(row.id);\n }\n }\n\n return { created, deduped };\n },\n\n async claimPendingDeliveries(args: ClaimArgs): Promise<readonly ClaimedDelivery[]> {\n const now = args.now ?? new Date();\n const staleBefore = new Date(now.getTime() - args.leaseMs);\n\n const eligible: Document = {\n $and: [\n {\n $or: [{ status: \"pending\" }, { status: \"claimed\", claimedAt: { $lt: staleBefore } }],\n },\n { notBefore: { $lte: now } },\n { $expr: { $lt: [\"$attempts\", \"$maxAttempts\"] } },\n ],\n };\n\n if (args.channels && args.channels.length > 0) {\n (eligible.$and as Document[]).push({ channel: { $in: [...args.channels] } });\n }\n if (args.ids && args.ids.length > 0) {\n (eligible.$and as Document[]).push({ _id: { $in: [...args.ids] } });\n }\n\n // findOneAndUpdate is atomic per document, so two concurrent callers\n // cannot be handed the same delivery. updateMany would be one round trip\n // but gives no way to learn which documents this call actually won.\n const claimed: Document[] = [];\n for (let taken = 0; taken < args.limit; taken += 1) {\n const doc = await deliveries().findOneAndUpdate(\n eligible,\n { $set: { status: \"claimed\", claimedAt: now, claimedBy: args.claimToken } },\n { sort: { notBefore: 1, _id: 1 }, returnDocument: \"after\" },\n );\n if (!doc) break;\n claimed.push(doc);\n }\n\n if (claimed.length === 0) return [];\n\n // One lookup for the batch rather than one per delivery.\n const parents = await notifications()\n .find({ _id: { $in: claimed.map((doc) => doc.notificationId) } })\n .toArray();\n const byId = new Map(parents.map((doc) => [str(doc._id), doc]));\n\n return claimed.flatMap((doc) => {\n const parent = byId.get(str(doc.notificationId));\n if (!parent) return [];\n\n return [\n {\n id: str(doc._id),\n notificationId: str(doc.notificationId),\n channel: str(doc.channel) as Channel,\n attempts: num(doc.attempts),\n maxAttempts: num(doc.maxAttempts),\n notification: {\n userId: str(parent.userId),\n type: str(parent.type),\n payload: parent.payload,\n actorId: nullableStr(parent.actorId),\n },\n },\n ];\n });\n },\n\n async releaseDeliveries(releases: readonly DeliveryRelease[]) {\n if (releases.length === 0) return;\n const now = new Date();\n\n for (const { id, outcome, nextAttemptAt } of releases) {\n const failed = outcome.result === \"failed\";\n const skipped = outcome.result === \"skipped\";\n const retryable = failed && outcome.retryable;\n\n // An aggregation-pipeline update so the terminal-vs-retry decision\n // reads maxAttempts from the document itself, as the SQL CASE does.\n await deliveries().updateOne({ _id: id }, [\n {\n $set: {\n attempts: failed ? { $add: [\"$attempts\", 1] } : \"$attempts\",\n status: failed\n ? {\n $cond: [\n { $and: [retryable, { $lt: [{ $add: [\"$attempts\", 1] }, \"$maxAttempts\"] }] },\n \"pending\",\n \"failed\",\n ],\n }\n : skipped\n ? \"skipped\"\n : \"sent\",\n // $literal: an error message starting with \"$\" would otherwise\n // be read as a field path.\n lastError: failed\n ? { $literal: outcome.error.slice(0, 2000) }\n : skipped\n ? { $literal: outcome.reason.slice(0, 2000) }\n : null,\n notBefore: nextAttemptAt ?? \"$notBefore\",\n // Written unconditionally: if the lease expired and another\n // worker re-sent, the duplicate already happened and the true\n // terminal state beats leaving the row wedged in \"claimed\".\n claimedAt: null,\n claimedBy: null,\n updatedAt: now,\n },\n },\n ]);\n }\n },\n\n async listNotifications(query: FeedQuery): Promise<FeedPage> {\n const cursor = query.cursor ? decodeCursor(query.cursor) : null;\n\n const filter: Document = { userId: query.userId, archivedAt: null };\n if (query.unreadOnly) filter.readAt = null;\n\n if (cursor) {\n // Matches the SQL row comparison (createdAt, id) < (cursor, cursorId).\n filter.$or = [\n { createdAt: { $lt: cursor.createdAt } },\n { createdAt: cursor.createdAt, _id: { $lt: cursor.id } },\n ];\n }\n\n const docs = await notifications()\n .find(filter, { sort: { createdAt: -1, _id: -1 }, limit: query.limit + 1 })\n .toArray();\n\n const page = docs.slice(0, query.limit).map(toNotification);\n const last = page.at(-1);\n\n return {\n notifications: page,\n nextCursor:\n docs.length > query.limit && last ? encodeCursor(last.createdAt, last.id) : null,\n };\n },\n\n async countUnseen(userId: string) {\n return notifications().countDocuments({ userId, seenAt: null, archivedAt: null });\n },\n\n async markSeen(userId: string, before: Date) {\n await notifications().updateMany(\n { userId, seenAt: null, createdAt: { $lte: before } },\n { $set: { seenAt: new Date() } },\n );\n },\n\n async markRead(userId: string, notificationIds: readonly string[]) {\n if (notificationIds.length === 0) return 0;\n\n // Scoped by userId as well as id, and idempotent: re-marking a read\n // notification reports success rather than a 404.\n const filter = { userId, _id: { $in: [...notificationIds] } };\n await notifications().updateMany(\n { ...filter, readAt: null },\n {\n $set: { readAt: new Date() },\n },\n );\n\n return notifications().countDocuments(filter);\n },\n\n async markAllRead(userId: string) {\n const result = await notifications().updateMany(\n { userId, readAt: null },\n { $set: { readAt: new Date() } },\n );\n return result.modifiedCount;\n },\n\n async getFailedDeliveries(args: { since: Date; limit: number }) {\n const docs = await deliveries()\n .find(\n { status: \"failed\", updatedAt: { $gte: args.since } },\n { sort: { updatedAt: -1 }, limit: args.limit },\n )\n .toArray();\n\n return docs.map(toDelivery);\n },\n\n async queryTable(table: string, where: WhereClause, options: QueryOptions) {\n const find: Document = {};\n if (options.limit) find.limit = options.limit;\n if (options.orderBy) {\n const direction = options.orderBy.direction === \"desc\" ? -1 : 1;\n find.sort = { [toMongoField(options.orderBy.field)]: direction };\n }\n\n const docs = await database.collection(table).find(toFilter(where), find).toArray();\n\n // `_id` is a storage detail; plugins declared the field as `id`.\n return docs.map(({ _id, ...rest }) => (_id === undefined ? rest : { id: _id, ...rest }));\n },\n\n async insertRows(\n table: string,\n rows: readonly Record<string, unknown>[],\n onConflict?: readonly string[],\n ) {\n if (rows.length === 0) return 0;\n\n const documents = rows.map(({ id, ...rest }) =>\n id === undefined ? { ...rest } : { _id: id, ...rest },\n );\n\n if (!onConflict || onConflict.length === 0) {\n await database.collection(table).insertMany(documents as Document[]);\n return documents.length;\n }\n\n // Upsert keyed on the conflict fields, matching ON CONFLICT DO UPDATE.\n let written = 0;\n for (const document of documents as Document[]) {\n const key: Document = {};\n for (const field of onConflict) key[toMongoField(field)] = document[toMongoField(field)];\n\n // _id goes in $setOnInsert, never $set: Mongo rejects an update that\n // would modify it, so a conflicting upsert must leave it alone.\n const { _id, ...updatable } = document;\n const update: Document = { $set: updatable };\n if (_id !== undefined) update.$setOnInsert = { _id };\n\n const result = await database.collection(table).updateOne(key, update, { upsert: true });\n written += result.matchedCount + (result.upsertedCount ?? 0);\n }\n return written;\n },\n\n async updateRows(table: string, where: WhereClause, set: Record<string, unknown>) {\n const assignments: Document = {};\n for (const [field, value] of Object.entries(set)) assignments[toMongoField(field)] = value;\n if (Object.keys(assignments).length === 0) return 0;\n\n const result = await database\n .collection(table)\n .updateMany(toFilter(where), { $set: assignments });\n return result.matchedCount;\n },\n\n async deleteRows(table: string, where: WhereClause) {\n const result = await database.collection(table).deleteMany(toFilter(where));\n return result.deletedCount;\n },\n };\n}\n","import type { FieldDeclaration, SchemaDeclaration } from \"../../core/plugin\";\nimport { coreSchema } from \"../../schema/declaration\";\n\ntype IndexSpec = Record<string, 1 | -1>;\n\ntype IndexOptions = {\n name: string;\n unique?: boolean;\n partialFilterExpression?: Record<string, unknown>;\n};\n\ntype IndexableDb = {\n collection(name: string): {\n createIndex(spec: IndexSpec, options: IndexOptions): Promise<string>;\n };\n};\n\nconst BSON_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"string\",\n number: \"number\",\n boolean: \"bool\",\n date: \"date\",\n json: \"object\",\n};\n\n/**\n * Applies a SchemaDeclaration's indexes to Mongo. The document counterpart of\n * renderPostgresDdl — there are no tables to create, only indexes, and the\n * declaration is the same source of truth.\n *\n * A unique index over a nullable field gets a partial filter. Postgres treats\n * every NULL as distinct, so unlimited rows may leave dedupeKey unset; a plain\n * Mongo unique index treats them as one value and would allow exactly one.\n */\nexport async function createPluginIndexes(\n db: unknown,\n schema: SchemaDeclaration,\n prefix = \"\",\n): Promise<void> {\n const database = db as IndexableDb;\n\n for (const table of Object.values(schema)) {\n const collection = database.collection(prefix + table.tableName);\n\n // A single \"id\" key is stored as _id, which is already unique.\n if (table.primaryKey && table.primaryKey.length > 0 && table.primaryKey[0] !== \"id\") {\n const spec: IndexSpec = {};\n for (const field of table.primaryKey) spec[field] = 1;\n await collection.createIndex(spec, {\n name: `${table.tableName}_pk`,\n unique: true,\n });\n }\n\n for (const declaration of table.indexes ?? []) {\n const spec: IndexSpec = {};\n for (const field of declaration.on) spec[field] = 1;\n\n const options: IndexOptions = {\n name: prefix + (declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`),\n };\n\n if (declaration.unique) {\n options.unique = true;\n\n const partial: Record<string, unknown> = {};\n for (const field of declaration.on) {\n const spec = table.fields[field];\n if (spec && !spec.required) partial[field] = { $type: BSON_TYPE[spec.type] };\n }\n if (Object.keys(partial).length > 0) options.partialFilterExpression = partial;\n }\n\n await collection.createIndex(spec, options);\n }\n }\n}\n\n/** Creates the indexes the core tables need. Call once at startup. */\nexport const createMongoIndexes = (db: unknown, options: { prefix?: string } = {}) =>\n createPluginIndexes(db, coreSchema, options.prefix ?? \"\");\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/mongodb/adapter.ts","../../src/adapters/mongodb/indexes.ts","../../src/adapters/mongodb/signals.ts"],"names":["options","spec"],"mappings":"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","file":"mongodb.js","sourcesContent":["import type {\n ClaimArgs,\n ClaimedDelivery,\n DatabaseAdapter,\n DeliveryRelease,\n FeedPage,\n FeedQuery,\n InsertNotification,\n} from \"../../core/adapter\";\nimport { decodeBase64Url, encodeBase64Url } from \"../../core/base64url\";\nimport { isOperator, type QueryOptions, type WhereClause } from \"../../core/store\";\nimport type { Channel, DeliveryRecord, DeliveryStatus, NotificationRecord } from \"../../core/types\";\n\ntype Document = Record<string, unknown>;\n\n/** Structural, so `mongodb` stays an optional peer dependency. */\ntype MongoCollection = {\n insertMany(docs: Document[], options?: unknown): Promise<unknown>;\n insertOne(doc: Document, options?: unknown): Promise<unknown>;\n find(filter: Document, options?: Document): { toArray(): Promise<Document[]> };\n findOne(filter: Document, options?: Document): Promise<Document | null>;\n findOneAndUpdate(\n filter: Document,\n update: Document | Document[],\n options?: Document,\n ): Promise<Document | null>;\n updateOne(\n filter: Document,\n update: Document | Document[],\n options?: Document,\n ): Promise<{\n matchedCount: number;\n modifiedCount: number;\n upsertedCount?: number;\n }>;\n updateMany(\n filter: Document,\n update: Document | Document[],\n options?: Document,\n ): Promise<{\n matchedCount: number;\n modifiedCount: number;\n }>;\n deleteMany(filter: Document, options?: Document): Promise<{ deletedCount: number }>;\n countDocuments(filter: Document, options?: Document): Promise<number>;\n createIndex(spec: Document, options?: Document): Promise<string>;\n};\n\ntype MongoDb = {\n collection(name: string): MongoCollection;\n};\n\ntype MongoSession = {\n withTransaction<T>(fn: () => Promise<T>): Promise<T>;\n endSession(): Promise<void>;\n};\n\ntype MongoClient = {\n startSession(): MongoSession;\n};\n\nexport type MongoAdapterOptions = {\n /** Prefixes every collection name, matching the SQL adapter's table prefix. */\n prefix?: string;\n /** Makes createNotifications atomic. Needs a replica set, so it is opt-in. */\n client?: unknown;\n};\n\nconst str = (value: unknown): string => String(value);\nconst nullableStr = (value: unknown): string | null => (value == null ? null : String(value));\nconst num = (value: unknown): number => Number(value);\nconst date = (value: unknown): Date => (value instanceof Date ? value : new Date(String(value)));\nconst nullableDate = (value: unknown): Date | null =>\n value == null ? null : value instanceof Date ? value : new Date(String(value));\n\nconst encodeCursor = (createdAt: Date, id: string) =>\n encodeBase64Url(`${createdAt.toISOString()}|${id}`);\n\nfunction decodeCursor(cursor: string): { createdAt: Date; id: string } | null {\n const decoded = decodeBase64Url(cursor);\n if (!decoded) return null;\n\n const [iso, id] = decoded.split(\"|\");\n if (!iso || !id) return null;\n\n const createdAt = new Date(iso);\n return Number.isNaN(createdAt.getTime()) ? null : { createdAt, id };\n}\n\n/** Documents carry the id as `_id`; the rest of the library never sees that. */\nfunction toNotification(doc: Document): NotificationRecord {\n return {\n id: str(doc._id),\n userId: str(doc.userId),\n type: str(doc.type),\n payload: doc.payload,\n actorId: nullableStr(doc.actorId),\n groupKey: nullableStr(doc.groupKey),\n dedupeKey: nullableStr(doc.dedupeKey),\n seenAt: nullableDate(doc.seenAt),\n readAt: nullableDate(doc.readAt),\n archivedAt: nullableDate(doc.archivedAt),\n createdAt: date(doc.createdAt),\n };\n}\n\nfunction toDelivery(doc: Document): DeliveryRecord {\n return {\n id: str(doc._id),\n notificationId: str(doc.notificationId),\n channel: str(doc.channel) as Channel,\n status: str(doc.status) as DeliveryStatus,\n attempts: num(doc.attempts),\n maxAttempts: num(doc.maxAttempts),\n notBefore: date(doc.notBefore),\n claimedAt: nullableDate(doc.claimedAt),\n claimedBy: nullableStr(doc.claimedBy),\n lastError: nullableStr(doc.lastError),\n updatedAt: date(doc.updatedAt),\n };\n}\n\n/** The store hands `id`; documents key on `_id`. */\nconst toMongoField = (field: string) => (field === \"id\" ? \"_id\" : field);\n\nfunction toFilter(where: WhereClause): Document {\n const filter: Document = {};\n\n for (const [field, condition] of Object.entries(where)) {\n const key = toMongoField(field);\n\n if (condition === null) {\n filter[key] = null;\n continue;\n }\n\n if (!isOperator(condition)) {\n // Last line before the driver, where `{ $ne: null }` becomes a query.\n if (typeof condition === \"object\" && !(condition instanceof Date)) {\n throw new Error(`mongo filter on \"${field}\" received an object; only scalars are bound`);\n }\n filter[key] = condition;\n continue;\n }\n\n const operator = condition as Record<string, unknown>;\n if (\"in\" in operator) filter[key] = { $in: operator.in };\n else if (\"lt\" in operator) filter[key] = { $lt: operator.lt };\n else if (\"lte\" in operator) filter[key] = { $lte: operator.lte };\n else if (\"gt\" in operator) filter[key] = { $gt: operator.gt };\n else if (\"gte\" in operator) filter[key] = { $gte: operator.gte };\n else if (\"not\" in operator) {\n // $ne null also matches a missing field, which is what \"not null\" means.\n filter[key] = { $ne: operator.not };\n }\n }\n\n return filter;\n}\n\n/** A duplicate on a unique index, rather than a real write failure. */\nconst isDuplicateKey = (error: unknown): boolean => {\n const code = (error as { code?: number; writeErrors?: { code?: number }[] })?.code;\n if (code === 11000) return true;\n const writeErrors = (error as { writeErrors?: { code?: number }[] })?.writeErrors;\n return Array.isArray(writeErrors) && writeErrors.some((entry) => entry?.code === 11000);\n};\n\nexport function mongoAdapter(db: unknown, options: MongoAdapterOptions = {}): DatabaseAdapter {\n const database = db as MongoDb;\n const prefix = options.prefix ?? \"\";\n\n const client = options.client as MongoClient | undefined;\n\n const notifications = () => database.collection(`${prefix}notification`);\n const deliveries = () => database.collection(`${prefix}notification_delivery`);\n\n /** One transaction per notification: a duplicate key aborts the transaction it happens in, and dedupe is the expected path. */\n async function atomically<T>(fn: (session?: MongoSession) => Promise<T>): Promise<T> {\n if (!client) return fn();\n\n const session = client.startSession();\n try {\n return await session.withTransaction(() => fn(session));\n } finally {\n await session.endSession();\n }\n }\n\n return {\n name: \"mongodb\",\n // Documents keep the declared camelCase, and store objects natively.\n naming: \"preserve\",\n serializesJson: false,\n\n async createNotifications(input: readonly InsertNotification[]) {\n if (input.length === 0) return { created: [], deduped: [] };\n\n const created: string[] = [];\n const deduped: string[] = [];\n\n for (const row of input) {\n const now = new Date();\n\n try {\n await atomically(async (session) => {\n const options = session ? { session } : undefined;\n\n // Notification first: it carries the unique dedupe index.\n await notifications().insertOne(\n {\n _id: row.id,\n userId: row.userId,\n type: row.type,\n payload: row.payload ?? null,\n actorId: row.actorId ?? null,\n groupKey: row.groupKey ?? null,\n dedupeKey: row.dedupeKey ?? null,\n seenAt: null,\n readAt: null,\n archivedAt: null,\n createdAt: now,\n },\n options,\n );\n\n if (row.deliveries.length > 0) {\n await deliveries().insertMany(\n row.deliveries.map((delivery) => ({\n _id: delivery.id,\n notificationId: row.id,\n channel: delivery.channel,\n status: \"pending\",\n attempts: 0,\n maxAttempts: delivery.maxAttempts,\n notBefore: delivery.notBefore,\n claimedAt: null,\n claimedBy: null,\n lastError: null,\n updatedAt: now,\n })),\n options,\n );\n }\n });\n\n created.push(row.id);\n } catch (error) {\n if (!isDuplicateKey(error)) throw error;\n deduped.push(row.id);\n }\n }\n\n return { created, deduped };\n },\n\n async claimPendingDeliveries(args: ClaimArgs): Promise<readonly ClaimedDelivery[]> {\n const now = args.now ?? new Date();\n const staleBefore = new Date(now.getTime() - args.leaseMs);\n\n const eligible: Document = {\n $and: [\n {\n $or: [{ status: \"pending\" }, { status: \"claimed\", claimedAt: { $lt: staleBefore } }],\n },\n { notBefore: { $lte: now } },\n { $expr: { $lt: [\"$attempts\", \"$maxAttempts\"] } },\n ],\n };\n\n if (args.channels && args.channels.length > 0) {\n (eligible.$and as Document[]).push({ channel: { $in: [...args.channels] } });\n }\n if (args.ids && args.ids.length > 0) {\n (eligible.$and as Document[]).push({ _id: { $in: [...args.ids] } });\n }\n\n // findOneAndUpdate is atomic per document; updateMany cannot say which rows this call won.\n const claimed: Document[] = [];\n for (let taken = 0; taken < args.limit; taken += 1) {\n const doc = await deliveries().findOneAndUpdate(\n eligible,\n { $set: { status: \"claimed\", claimedAt: now, claimedBy: args.claimToken } },\n { sort: { notBefore: 1, _id: 1 }, returnDocument: \"after\" },\n );\n if (!doc) break;\n claimed.push(doc);\n }\n\n if (claimed.length === 0) return [];\n\n const parents = await notifications()\n .find({ _id: { $in: claimed.map((doc) => doc.notificationId) } })\n .toArray();\n const byId = new Map(parents.map((doc) => [str(doc._id), doc]));\n\n return claimed.flatMap((doc) => {\n const parent = byId.get(str(doc.notificationId));\n if (!parent) return [];\n\n return [\n {\n id: str(doc._id),\n notificationId: str(doc.notificationId),\n channel: str(doc.channel) as Channel,\n attempts: num(doc.attempts),\n maxAttempts: num(doc.maxAttempts),\n notification: {\n userId: str(parent.userId),\n type: str(parent.type),\n payload: parent.payload,\n actorId: nullableStr(parent.actorId),\n },\n },\n ];\n });\n },\n\n async releaseDeliveries(releases: readonly DeliveryRelease[]) {\n if (releases.length === 0) return;\n const now = new Date();\n\n for (const { id, outcome, nextAttemptAt } of releases) {\n const failed = outcome.result === \"failed\";\n const skipped = outcome.result === \"skipped\";\n const retryable = failed && outcome.retryable;\n\n // Pipeline update, so the retry decision reads maxAttempts from the document.\n await deliveries().updateOne({ _id: id }, [\n {\n $set: {\n attempts: failed ? { $add: [\"$attempts\", 1] } : \"$attempts\",\n status: failed\n ? {\n $cond: [\n { $and: [retryable, { $lt: [{ $add: [\"$attempts\", 1] }, \"$maxAttempts\"] }] },\n \"pending\",\n \"failed\",\n ],\n }\n : skipped\n ? \"skipped\"\n : \"sent\",\n // $literal: an error starting with \"$\" would be read as a field path.\n lastError: failed\n ? { $literal: outcome.error.slice(0, 2000) }\n : skipped\n ? { $literal: outcome.reason.slice(0, 2000) }\n : null,\n notBefore: nextAttemptAt ?? \"$notBefore\",\n // Unconditional: terminal state beats a wedged row. RFC 0003 §6.\n claimedAt: null,\n claimedBy: null,\n updatedAt: now,\n },\n },\n ]);\n }\n },\n\n async listNotifications(query: FeedQuery): Promise<FeedPage> {\n const cursor = query.cursor ? decodeCursor(query.cursor) : null;\n\n const filter: Document = { userId: query.userId, archivedAt: null };\n if (query.unreadOnly) filter.readAt = null;\n\n if (cursor) {\n // Matches the SQL row comparison (createdAt, id) < (cursor, cursorId).\n filter.$or = [\n { createdAt: { $lt: cursor.createdAt } },\n { createdAt: cursor.createdAt, _id: { $lt: cursor.id } },\n ];\n }\n\n const docs = await notifications()\n .find(filter, { sort: { createdAt: -1, _id: -1 }, limit: query.limit + 1 })\n .toArray();\n\n const page = docs.slice(0, query.limit).map(toNotification);\n const last = page.at(-1);\n\n return {\n notifications: page,\n nextCursor:\n docs.length > query.limit && last ? encodeCursor(last.createdAt, last.id) : null,\n };\n },\n\n async countUnseen(userId: string) {\n return notifications().countDocuments({ userId, seenAt: null, archivedAt: null });\n },\n\n async markSeen(userId: string, before: Date) {\n await notifications().updateMany(\n { userId, seenAt: null, createdAt: { $lte: before } },\n { $set: { seenAt: new Date() } },\n );\n },\n\n async markRead(userId: string, notificationIds: readonly string[]) {\n if (notificationIds.length === 0) return 0;\n\n // Scoped by userId; idempotent, so no 404 on a re-mark.\n const filter = { userId, _id: { $in: [...notificationIds] } };\n await notifications().updateMany(\n { ...filter, readAt: null },\n {\n $set: { readAt: new Date() },\n },\n );\n\n return notifications().countDocuments(filter);\n },\n\n async markAllRead(userId: string) {\n const result = await notifications().updateMany(\n { userId, readAt: null },\n { $set: { readAt: new Date() } },\n );\n return result.modifiedCount;\n },\n\n async getFailedDeliveries(args: { since: Date; limit: number }) {\n const docs = await deliveries()\n .find(\n { status: \"failed\", updatedAt: { $gte: args.since } },\n { sort: { updatedAt: -1 }, limit: args.limit },\n )\n .toArray();\n\n return docs.map(toDelivery);\n },\n\n async queryTable(table: string, where: WhereClause, options: QueryOptions) {\n const find: Document = {};\n if (options.limit) find.limit = options.limit;\n if (options.orderBy) {\n const direction = options.orderBy.direction === \"desc\" ? -1 : 1;\n find.sort = { [toMongoField(options.orderBy.field)]: direction };\n }\n\n const docs = await database.collection(table).find(toFilter(where), find).toArray();\n\n // `_id` is a storage detail; plugins declared the field as `id`.\n return docs.map(({ _id, ...rest }) => (_id === undefined ? rest : { id: _id, ...rest }));\n },\n\n async insertRows(\n table: string,\n rows: readonly Record<string, unknown>[],\n onConflict?: readonly string[],\n ) {\n if (rows.length === 0) return 0;\n\n const documents = rows.map(({ id, ...rest }) =>\n id === undefined ? { ...rest } : { _id: id, ...rest },\n );\n\n if (!onConflict || onConflict.length === 0) {\n await database.collection(table).insertMany(documents as Document[]);\n return documents.length;\n }\n\n let written = 0;\n for (const document of documents as Document[]) {\n const key: Document = {};\n for (const field of onConflict) key[toMongoField(field)] = document[toMongoField(field)];\n\n // _id only in $setOnInsert: Mongo rejects an update that would modify it.\n const { _id, ...updatable } = document;\n const update: Document = { $set: updatable };\n if (_id !== undefined) update.$setOnInsert = { _id };\n\n const result = await database.collection(table).updateOne(key, update, { upsert: true });\n written += result.matchedCount + (result.upsertedCount ?? 0);\n }\n return written;\n },\n\n async updateRows(table: string, where: WhereClause, set: Record<string, unknown>) {\n const assignments: Document = {};\n for (const [field, value] of Object.entries(set)) assignments[toMongoField(field)] = value;\n if (Object.keys(assignments).length === 0) return 0;\n\n const result = await database\n .collection(table)\n .updateMany(toFilter(where), { $set: assignments });\n return result.matchedCount;\n },\n\n async deleteRows(table: string, where: WhereClause) {\n const result = await database.collection(table).deleteMany(toFilter(where));\n return result.deletedCount;\n },\n };\n}\n","import type { FieldDeclaration, SchemaDeclaration } from \"../../core/plugin\";\nimport { coreSchema } from \"../../schema/declaration\";\n\ntype IndexSpec = Record<string, 1 | -1>;\n\ntype IndexOptions = {\n name: string;\n unique?: boolean;\n partialFilterExpression?: Record<string, unknown>;\n};\n\ntype IndexableDb = {\n collection(name: string): {\n createIndex(spec: IndexSpec, options: IndexOptions): Promise<string>;\n };\n};\n\nconst BSON_TYPE: Record<FieldDeclaration[\"type\"], string> = {\n string: \"string\",\n number: \"number\",\n boolean: \"bool\",\n date: \"date\",\n json: \"object\",\n};\n\n/** Applies a SchemaDeclaration's indexes. A unique index over a nullable field gets a partial filter, since Mongo treats all NULLs as one value. */\nexport async function createPluginIndexes(\n db: unknown,\n schema: SchemaDeclaration,\n prefix = \"\",\n): Promise<void> {\n const database = db as IndexableDb;\n\n for (const table of Object.values(schema)) {\n const collection = database.collection(prefix + table.tableName);\n\n // A single \"id\" key is stored as _id, which is already unique.\n if (table.primaryKey && table.primaryKey.length > 0 && table.primaryKey[0] !== \"id\") {\n const spec: IndexSpec = {};\n for (const field of table.primaryKey) spec[field] = 1;\n await collection.createIndex(spec, {\n name: `${table.tableName}_pk`,\n unique: true,\n });\n }\n\n for (const declaration of table.indexes ?? []) {\n const spec: IndexSpec = {};\n for (const field of declaration.on) spec[field] = 1;\n\n const options: IndexOptions = {\n name: prefix + (declaration.name ?? `${table.tableName}_${declaration.on.join(\"_\")}_idx`),\n };\n\n if (declaration.unique) {\n options.unique = true;\n\n const partial: Record<string, unknown> = {};\n for (const field of declaration.on) {\n const spec = table.fields[field];\n if (spec && !spec.required) partial[field] = { $type: BSON_TYPE[spec.type] };\n }\n if (Object.keys(partial).length > 0) options.partialFilterExpression = partial;\n }\n\n await collection.createIndex(spec, options);\n }\n }\n}\n\n/** Creates the indexes the core tables need. Call once at startup. */\nexport const createMongoIndexes = (db: unknown, options: { prefix?: string } = {}) =>\n createPluginIndexes(db, coreSchema, options.prefix ?? \"\");\n","import { createBridgedSignals, type Signals } from \"../../core/signals\";\n\ntype SignalDocument = { channel: string; origin: string; at: Date };\n\ntype ChangeStreamLike = {\n on(event: \"change\", handler: (change: { fullDocument?: SignalDocument }) => void): unknown;\n on(event: \"error\", handler: (error: unknown) => void): unknown;\n close(): Promise<unknown>;\n};\n\n/** Structural, so `mongodb` stays an optional peer dependency. */\nexport type MongoSignalsDb = {\n createCollection(name: string, options: { capped: boolean; size: number }): Promise<unknown>;\n collection(name: string): {\n insertOne(doc: SignalDocument): Promise<unknown>;\n watch(pipeline?: unknown[], options?: Record<string, unknown>): ChangeStreamLike;\n };\n};\n\nexport type MongoSignalsOptions = {\n /** Capped collection the signals pass through. Default `easy_ping_signals`. */\n collection?: string;\n /** Capped size in bytes. Old signals fall off the end; nobody reads history. Default 1 MiB. */\n size?: number;\n onError?: (error: unknown) => void;\n};\n\nconst originId = () => Math.random().toString(36).slice(2, 10);\n\n/**\n * Cross-replica wake-ups over a change stream on a capped collection.\n * Needs a replica set, which the adapter's transactions need anyway.\n * RFC 0006 §4C.\n */\nexport function mongoSignals(db: MongoSignalsDb, options: MongoSignalsOptions = {}): Signals {\n const name = options.collection ?? \"easy_ping_signals\";\n const onError = options.onError ?? (() => {});\n const origin = originId();\n const handlers = new Map<string, Set<() => void>>();\n let ready: Promise<void> | undefined;\n let stream: ChangeStreamLike | undefined;\n\n const ensureCollection = () => {\n ready ??= db.createCollection(name, { capped: true, size: options.size ?? 1024 * 1024 }).then(\n () => {},\n (error: unknown) => {\n // 48: NamespaceExists. Another replica got there first.\n if ((error as { code?: number })?.code === 48) return;\n ready = undefined;\n throw error;\n },\n );\n return ready;\n };\n\n const ensureWatching = async () => {\n if (stream) return;\n await ensureCollection();\n if (stream) return;\n const opened = db\n .collection(name)\n .watch([{ $match: { operationType: \"insert\" } }], { fullDocument: \"updateLookup\" });\n stream = opened;\n opened.on(\"change\", (change) => {\n const doc = change.fullDocument;\n if (!doc || doc.origin === origin) return;\n for (const handler of handlers.get(doc.channel) ?? []) handler();\n });\n opened.on(\"error\", (error) => {\n onError(error);\n if (stream === opened) stream = undefined;\n });\n };\n\n const bridged = createBridgedSignals(\n {\n publish: async (logical) => {\n await ensureCollection();\n await db.collection(name).insertOne({ channel: logical, origin, at: new Date() });\n },\n subscribe: async (logical, handler) => {\n let set = handlers.get(logical);\n if (!set) {\n set = new Set();\n handlers.set(logical, set);\n }\n set.add(handler);\n await ensureWatching();\n return () => {\n set?.delete(handler);\n if (set?.size === 0) handlers.delete(logical);\n };\n },\n },\n onError,\n );\n\n return {\n ...bridged,\n close: async () => {\n const open = stream;\n stream = undefined;\n handlers.clear();\n await open?.close();\n },\n };\n}\n"]}
|