AbsoluteJS

@absolutejs/sync-pack-notifications

@absolutejs/sync-pack-notificationsv0.2.4betaData & Sync

Per-actor inbox pack for @absolutejs/sync — notify, mark-read, scoped reads, optional TTL auto-archive

#Installation

BASH
bun add @absolutejs/sync-pack-notifications

#Capabilities

Overview

Per-actor inbox pack for @absolutejs/sync. Each actor sees only their own rows; notify is the host-trusted insert path; markRead and markAllRead are client-callable owner-only mutations. Optional autoArchiveAfterDays deletes rows past TTL via a cron schedule.

The pack exposes

Surface — Name — What it does

Collection — notifications — Each actor sees their own rows; moderators see all

Mutation — notifications:notify — Insert one row for a target actor (host-trusted)

Show 3 more

Mutation — notifications:markRead — Stamp readAt on one row — owner only

Mutation — notifications:markAllRead — Bulk-mark every unread row in the caller's inbox

Schedule — notifications:cleanup — (Only if autoArchiveAfterDays set) deletes expired

Storage

Default: per-instance in-memory store. For a persistent backend pass a custom store:

getById is required (used by markRead to verify ownership before update). expired is required when autoArchiveAfterDays is set.

Multiple instances

Pass prefix to coexist with another notifications pack instance (e.g. a separate "system" inbox vs the regular one):

Outcomes

What you can build

Build on the supported package contract

Use @absolutejs/sync-pack-notifications through its supported public entry points.

Hardening checklist

Production guidance

Make every external boundary explicitPin the deployed @absolutejs/sync-pack-notifications version, replace example or memory-backed dependencies with durable implementations, bound external calls, protect credentials, and emit enough evidence to retry or recover safely.

Follow in order

Troubleshooting path

1
Trace from the first failed boundary
Reproduce the smallest canonical @absolutejs/sync-pack-notifications example, confirm the supported entry point and version in the API explorer, then inspect the first boundary that did not produce its documented result.

#@absolutejs/sync-pack-notifications quick start

Partial snippet

# @absolutejs/sync-pack-notifications

BASH
bun add @absolutejs/sync-pack-notifications

#Usage

Partial snippet

Working example for Usage.

TS
import { createSyncEngine } from '@absolutejs/sync/engine';
import { createNotificationsPack } from '@absolutejs/sync-pack-notifications';

const engine = createSyncEngine();
engine.registerPack(
	createNotificationsPack({
		getActorId: (ctx) => ctx.session.userId,
		// `notify` is the trusted insert path. Mark the ctx your host
		// uses to call notify as a moderator so the row-author permission
		// check passes. (In a real app this is a server-only "system"
		// trust flag, not isModerator.)
		canModerate: (ctx) => ctx.session.systemTrusted === true,
		// Optional: archive rows after 30 days. Cleanup schedule fires
		// hourly by default.
		autoArchiveAfterDays: 30,
	}),
);

// From any server-side path (a webhook, a schedule, another mutation):
await engine.runMutation(
	'notifications:notify',
	{
		actorId: 'alice',
		kind: 'mention',
		title: 'You were mentioned',
		body: 'in @doc-123 by bob',
		href: '/docs/123#comment-456',
	},
	{ session: { systemTrusted: true } },
);

#Row shape

Partial snippet

Working example for Row shape.

TS
type NotificationRow = {
	id: string;
	actorId: string;       // whose inbox
	kind: string;          // app-level tag: "mention", "reply", "system", ...
	title: string;
	body: string;
	href: string | null;   // optional jump-to URL
	createdAt: number;
	readAt: number | null; // null = unread
	expiresAt: number | null;
};

#Storage

Partial snippet

Default: per-instance in-memory store. For a persistent backend pass a custom store:

TS
import {
	createNotificationsPack,
	type NotificationsStore,
} from '@absolutejs/sync-pack-notifications';

const store: NotificationsStore = {
	getById: (id) => /* SELECT * FROM notifications WHERE id = $1 */,
	expired: (now) => /* SELECT * FROM notifications WHERE expires_at <= $1 */,
	reader: { all: () => /* SELECT */ },
	writer: { insert, update, delete },
};

#Public entry points

Supported entry points declared by this package manifest.

Package entry point declared in package.json.

@absolutejs/sync-pack-notifications@absolutejs/sync-pack-notifications/manifest@absolutejs/sync-pack-notifications/manifest.json

#Package commands

Scripts declared by this package manifest.

bun run buildrm -rf dist && bun build src/index.ts src/manifest.ts --outdir dist --sourcemap --target=bun --external @absolutejs/sync && tsc --project tsconfig.build.json && absolute-manifest emit
bun run formatprettier --write "./**/*.{ts,json,md}"
bun run testbun test
bun run typechecktsc --noEmit

#API reference

Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.

6 symbols
NotificationRowtypePermalinkSource

One notification for one actor.

TS
type NotificationRow = {
    id: string;
    /** Whose inbox this belongs to. */
    actorId: string;
    /** App-level type tag — host can route on it (e.g. "mention", "reply"). */
    kind: string;
    title: string;
    body: string;
    /** Optional URL the client jumps to when the notification is clicked. */
    href: string | null;
    createdAt: number;
    readAt: number | null;
    /** Epoch ms after which the row is eligible for cleanup. Null = keep forever. */
    expiresAt: number | null;
};
Exported from @absolutejs/sync-pack-notifications