ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// A module event, delivered: `notes.NoteCreated` tells the project's other members that a note was added.
//
// The event is a record of the transaction that wrote the note (core/notes.ts), so a note that rolled back
// tells nobody. The relay delivers at least once per subscriber. On the Postgres, MariaDB and MongoDB
// profiles it hands the record to this subscriber inside its own transaction, bound as
// `NOTIFICATIONS_REPOS` (JOB_REPOS), and records the delivery in that transaction too, so the inbox rows and
// the claim commit together: exactly once. On Convex, delivery is at least once only; there, and after any
// repeat, the record-derived `key` makes a second delivery find the row and add nothing.
// The inbox, its read state and its rendering are the notifications kit's; a producer supplies only the
// recipient, the occurrence, the text and a link inside the organization.
//
// Who is told: the project's named members (`project_memberships`, which a restricted project always has,
// its creator first), never the author. A project open to the whole workspace has none, and telling every
// member of the workspace about every note would be noise.
import { type EventContext, internal } from "@conusai-kit/core"
import { DATA_SOURCE } from "@conusai-kit/data"
import { FILES_REGISTRY, FILES_SCOPE } from "@conusai-kit/files"
import { createI18n, moduleCatalogues, negotiateLocale } from "@conusai-kit/i18n"
import { deliverNotification, NOTIFICATIONS_REPOS } from "@conusai-kit/notifications"
import { organizations, projectMemberships, projects, users, workspaces } from "@conusai-kit/tenancy"
type NoteCreated = { orgId: string; workspaceId: string; projectId: string; noteId: string; createdBy: string }
/** A message lookup relative to the module (`notification.created`), as the pages' label builders take. */
export type Translate = (key: string, values?: Record<string, string | number>) => string
/** The texts of the notification, named here so `__tests__/i18n.test.ts` checks them in both languages. */
export function notificationLabels(t: Translate, project: string) {
return { created: t("notification.created", { project }) }
}
export async function notifyNoteCreated(event: { name: string; payload: NoteCreated }, ctx: EventContext) {
const { payload } = event
const tx = ctx.container.resolve(NOTIFICATIONS_REPOS)
if (tx.scope.orgId !== payload.orgId) {
throw internal(`a notes event of organization ${payload.orgId} was delivered in ${tx.scope.orgId}`)
}
const recipients: string[] = []
for (let cursor: string | undefined; ; ) {
const page = await tx.of(projectMemberships).list({
where: [{ field: "projectId", op: "eq", value: payload.projectId }],
...(cursor === undefined ? {} : { cursor }),
})
for (const row of page.items) if (row.userId !== payload.createdBy) recipients.push(row.userId)
if (!page.hasMore || page.cursor === undefined) break
cursor = page.cursor
}
if (recipients.length === 0) return
// The link names the project by its slugs. A project is a workspace's row, so it is read in the
// workspace's scope, as the relay's system actor: a read, outside the delivery's transaction.
const relay = ctx.container.resolve(FILES_SCOPE)
const inWorkspace = {
level: "workspace" as const,
actor: relay.actor,
orgId: payload.orgId,
workspaceId: payload.workspaceId,
}
const [org, workspace, project] = await Promise.all([
tx.global(organizations).require(payload.orgId),
tx.of(workspaces).require(payload.workspaceId),
ctx.container.resolve(DATA_SOURCE).forScope(inWorkspace).of(projects).require(payload.projectId),
])
const href = `/${org.slug}/${workspace.slug}/${project.slug}/notes/${payload.noteId}`
const catalogues = moduleCatalogues(ctx.container.resolve(FILES_REGISTRY))
for (const recipientId of recipients) {
const person = await tx.global(users).get(recipientId)
const i18n = createI18n(negotiateLocale({ ...(person ? { userLocale: person.locale } : {}) }), catalogues)
const labels = notificationLabels((key, values) => i18n.message(`notes.${key}`, values), project.name)
// `custom` is the kit's code for an app's own copy, which it stores as written: in the recipient's language.
await deliverNotification(tx, {
recipientId,
key: `notes:${payload.noteId}:created`,
category: "notice",
code: "custom",
title: labels.created,
href,
})
}
}