AbsoluteJS

@absolutejs/sync-pack-utils

@absolutejs/sync-pack-utilsv0.1.3betaData & Sync

Shared helpers for @absolutejs/sync packs — resolveActor, requireRowOwner/Moderator, createInMemoryStore, and other patterns extracted from the official packs

#Installation

BASH
bun add @absolutejs/sync-pack-utils

#Capabilities

Overview

Shared helpers for @absolutejs/sync packs. Each helper closes one repeated pattern that showed up across the six official packs (presence, comments, digest, notifications, favorites, counters). The goal: make new packs — first- or third-party — cheaper to write and consistent with what's already shipped.

API

Actor resolution

Permission builders

requireRowOwner and requireOwnerOrModerator are higher-order — call them once at pack-build time to receive the per-row predicate the engine expects. Both reject when getActorId(ctx) is undefined (anonymous callers can't own a row).

Show 7 more

In-memory store

createInMemoryStore<Row>() returns:

reader: TableReader<CollectionContext> — all() returns [...rows.values()]

writer: TableWriter<Row> — upsert-by-id; delete removes by row.id

getById(id) — point lookup

rows: Map — direct access (treat as read-only)

Every official pack uses this as its default backing store and exposes a store?: ... config field so consumers can swap in a Postgres / Drizzle / Redis implementation when they need persistence.

What's intentionally not here

prefixed(prefix, ...): just use template literals.

${prefix} is fine.

defineActorPack(...): a Convex-style abstraction that wraps

Show 3 more

defineSyncPack with permission defaults. Decided against — it'd hide the engine surface, which is the thing pack authors learn first.

Validators / Zod adapters: out of scope; sync's field helper +

schema is the validation layer.

Pairing with @absolutejs/sync/testing

Pack tests typically pair with @absolutejs/sync/testing (added in sync 1.9.2):

Versioning

This package stays 0.x indefinitely while the ecosystem settles. When the six official packs are stable, the helpers will follow.

Outcomes

What you can build

Build on the supported package contract

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

Hardening checklist

Production guidance

Make every external boundary explicitPin the deployed @absolutejs/sync-pack-utils 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-utils 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-utils quick start

Partial snippet

# @absolutejs/sync-pack-utils

BASH
bun add @absolutejs/sync-pack-utils

#Actor resolution

Partial snippet

Working example for Actor resolution.

TS
import {
	defaultGetActorId,
	resolveActor,
} from '@absolutejs/sync-pack-utils';

// (ctx) => ctx.userId — the conventional default.
const getActorId = config.getActorId ?? defaultGetActorId<MyCtx>();

// Inside a mutation handler: throws UnauthorizedError if no actor id.
// The context string ends up in the error message so logs name the op.
const actorId = resolveActor(getActorId, ctx, 'mypack:create');

#Permission builders

Partial snippet

Working example for Permission builders.

TS
import {
	requireRowOwner,
	requireOwnerOrModerator,
} from '@absolutejs/sync-pack-utils';

permissions: {
	[table]: {
		read: ...,
		// Owner-only writes — uses row.actorId by default; override the
		// field name for packs that use authorId, userId, etc.
		insert: requireRowOwner(getActorId, 'actorId'),
		update: requireRowOwner(getActorId, 'actorId'),
		// Owner OR moderator delete. Falls back to store.getById when
		// actions.delete supplied only the row key (the common case).
		delete: requireOwnerOrModerator({
			actorIdField: 'actorId',
			canModerate,        // optional
			getActorId,
			store,              // { getById }
		}),
	},
},

#Public entry points

Supported entry points declared by this package manifest.

Package entry point declared in package.json.

@absolutejs/sync-pack-utils@absolutejs/sync-pack-utils/manifest@absolutejs/sync-pack-utils/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
defaultGetActorIdvaluePermalinkSource

The conventional default — (ctx) => ctx.userId. Use as the fallback when a pack's config doesn't supply its own getActorId.

TS
const defaultGetActorId: <Ctx = CollectionContext>() => ((ctx: Ctx) => string | undefined);
Exported from @absolutejs/sync-pack-utils