@absolutejs/sync-pack-utils 0.1.2 → 0.1.4
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/dist/index.d.ts +1 -1
- package/dist/index.js.map +2 -2
- package/dist/manifest.d.ts +9 -1
- package/dist/manifest.js +1082 -6722
- package/dist/manifest.js.map +31 -31
- package/dist/manifest.json +1 -1
- package/package.json +68 -68
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* standard shapes already shipped by presence / comments / digest /
|
|
8
8
|
* notifications / favorites / counters.
|
|
9
9
|
*/
|
|
10
|
-
import { type CollectionContext, type TableReader, type TableWriter } from
|
|
10
|
+
import { type CollectionContext, type TableReader, type TableWriter } from "@absolutejs/sync/engine";
|
|
11
11
|
/**
|
|
12
12
|
* The conventional default — `(ctx) => ctx.userId`. Use as the fallback when
|
|
13
13
|
* a pack's config doesn't supply its own `getActorId`.
|
package/dist/index.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * `@absolutejs/sync-pack-utils` — shared helpers extracted from the six\n * official `@absolutejs/sync` packs.\n *\n * Each helper closes one repeated pattern. The goal is to make new packs\n * (first- and third-party) cheaper to write and stop drift from the\n * standard shapes already shipped by presence / comments / digest /\n * notifications / favorites / counters.\n */\n\nimport {\n
|
|
5
|
+
"/**\n * `@absolutejs/sync-pack-utils` — shared helpers extracted from the six\n * official `@absolutejs/sync` packs.\n *\n * Each helper closes one repeated pattern. The goal is to make new packs\n * (first- and third-party) cheaper to write and stop drift from the\n * standard shapes already shipped by presence / comments / digest /\n * notifications / favorites / counters.\n */\n\nimport {\n UnauthorizedError,\n type CollectionContext,\n type TableReader,\n type TableWriter,\n} from \"@absolutejs/sync/engine\";\n\n// ─── Actor resolution ────────────────────────────────────────────────────────\n\n/**\n * The conventional default — `(ctx) => ctx.userId`. Use as the fallback when\n * a pack's config doesn't supply its own `getActorId`.\n *\n * @example\n * const getActorId = config.getActorId ?? defaultGetActorId<MyCtx>();\n */\nexport const defaultGetActorId =\n <Ctx = CollectionContext>(): ((ctx: Ctx) => string | undefined) =>\n (ctx) =>\n (ctx as { userId?: string }).userId;\n\n/**\n * Resolve the caller's actor id from a ctx, or throw {@link UnauthorizedError}\n * with a descriptive message. Use inside mutation handlers that require an\n * actor; the message embeds your `context` string so error reports name the\n * pack and operation.\n *\n * @example\n * const actorId = resolveActor(getActorId, ctx, 'comments:create');\n */\nexport const resolveActor = <Ctx = CollectionContext>(\n getActorId: (ctx: Ctx) => string | undefined,\n ctx: unknown,\n context: string,\n): string => {\n const actorId = getActorId(ctx as Ctx);\n if (actorId === undefined || actorId === \"\") {\n throw new UnauthorizedError(`${context} (no actor id)`);\n }\n return actorId;\n};\n\n// ─── Permission builders ─────────────────────────────────────────────────────\n\n/**\n * Permission validator that requires `row[actorIdField] === getActorId(ctx)`.\n * Use for `insert` and `update` on rows the actor owns; the handler stamps\n * the actor on the row, so this is the canonical row-ownership check.\n *\n * @example\n * permissions: {\n * notifications: {\n * insert: requireRowOwner(getActorId, 'actorId'),\n * update: requireRowOwner(getActorId, 'actorId'),\n * },\n * },\n */\nexport const requireRowOwner =\n <Ctx = CollectionContext>(\n getActorId: (ctx: Ctx) => string | undefined,\n actorIdField: string = \"actorId\",\n ) =>\n (ctx: unknown, row: unknown): boolean => {\n const callerId = getActorId(ctx as Ctx);\n if (callerId === undefined) return false;\n const rowActor = (row as Record<string, unknown>)[actorIdField];\n return rowActor === callerId;\n };\n\n/**\n * Permission validator for delete (or any op) that accepts the row OR\n * just its id. Falls back to `store.getById(row.id)` when the row's actor\n * field isn't on the supplied subject — sync's engine passes only the\n * key to `actions.delete({ id })`, so this pattern is needed for every\n * owner-gated delete.\n *\n * Returns true when the row's owner matches the caller OR `canModerate(ctx)`\n * is `true`.\n *\n * @example\n * permissions: {\n * notifications: {\n * delete: requireOwnerOrModerator({\n * getActorId,\n * canModerate,\n * store, // { getById }\n * actorIdField: 'actorId',\n * }),\n * },\n * },\n */\nexport const requireOwnerOrModerator =\n <Ctx = CollectionContext>(options: {\n getActorId: (ctx: Ctx) => string | undefined;\n canModerate?: (ctx: Ctx) => boolean;\n store: { getById: (id: string) => unknown };\n actorIdField?: string;\n }) =>\n (ctx: unknown, row: unknown): boolean => {\n const {\n getActorId,\n canModerate,\n store,\n actorIdField = \"actorId\",\n } = options;\n const callerId = getActorId(ctx as Ctx);\n if (callerId === undefined) return false;\n const supplied = row as Record<string, unknown>;\n const ownerId =\n supplied[actorIdField] !== undefined\n ? supplied[actorIdField]\n : (() => {\n const id = supplied.id;\n if (typeof id !== \"string\") return undefined;\n const stored = store.getById(id) as\n | Record<string, unknown>\n | undefined;\n return stored?.[actorIdField];\n })();\n if (ownerId === undefined) return false;\n if (ownerId === callerId) return true;\n return canModerate !== undefined ? canModerate(ctx as Ctx) : false;\n };\n\n// ─── In-memory store ────────────────────────────────────────────────────────\n\n/**\n * Standard in-memory store for a pack table. Every row needs an `id: string`\n * (the table's primary key); the writer is upsert-by-id. Used by every\n * official pack as the default backing store.\n */\nexport type InMemoryStore<Row extends { id: string }> = {\n reader: TableReader<CollectionContext>;\n writer: TableWriter<Row, CollectionContext, unknown>;\n /** Lookup by id — convenient for permission and mutation handlers. */\n getById: (id: string) => Row | undefined;\n /** Direct read of the underlying Map for advanced use; treat as read-only. */\n rows: Map<string, Row>;\n};\n\n/**\n * Build a fresh, isolated in-memory store. Each call gets its own Map, so\n * two pack instances on the same engine don't share state.\n *\n * @example\n * const store = config.store ?? createInMemoryStore<NotificationRow>();\n */\nexport const createInMemoryStore = <\n Row extends { id: string },\n>(): InMemoryStore<Row> => {\n const rows = new Map<string, Row>();\n return {\n getById: (id) => rows.get(id),\n reader: {\n all: () => [...rows.values()],\n },\n rows,\n writer: {\n delete: (row) => {\n rows.delete((row as { id: string }).id);\n },\n insert: (data) => {\n rows.set(data.id, data);\n return data;\n },\n update: (data) => {\n const prior = rows.get(data.id);\n const merged = { ...(prior ?? {}), ...data } as Row;\n rows.set(data.id, merged);\n return merged;\n },\n },\n };\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAUA;AAAA;AAAA;AAgBO,IAAM,
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAUA;AAAA;AAAA;AAgBO,IAAM,oBACX,MACA,CAAC,QACE,IAA4B;AAW1B,IAAM,eAAe,CAC1B,YACA,KACA,YACW;AAAA,EACX,MAAM,UAAU,WAAW,GAAU;AAAA,EACrC,IAAI,YAAY,aAAa,YAAY,IAAI;AAAA,IAC3C,MAAM,IAAI,kBAAkB,GAAG,uBAAuB;AAAA,EACxD;AAAA,EACA,OAAO;AAAA;AAkBF,IAAM,kBACX,CACE,YACA,eAAuB,cAEzB,CAAC,KAAc,QAA0B;AAAA,EACvC,MAAM,WAAW,WAAW,GAAU;AAAA,EACtC,IAAI,aAAa;AAAA,IAAW,OAAO;AAAA,EACnC,MAAM,WAAY,IAAgC;AAAA,EAClD,OAAO,aAAa;AAAA;AAyBjB,IAAM,0BACX,CAA0B,YAM1B,CAAC,KAAc,QAA0B;AAAA,EACvC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,MACb;AAAA,EACJ,MAAM,WAAW,WAAW,GAAU;AAAA,EACtC,IAAI,aAAa;AAAA,IAAW,OAAO;AAAA,EACnC,MAAM,WAAW;AAAA,EACjB,MAAM,UACJ,SAAS,kBAAkB,YACvB,SAAS,iBACR,MAAM;AAAA,IACL,MAAM,KAAK,SAAS;AAAA,IACpB,IAAI,OAAO,OAAO;AAAA,MAAU;AAAA,IAC5B,MAAM,SAAS,MAAM,QAAQ,EAAE;AAAA,IAG/B,OAAO,SAAS;AAAA,KACf;AAAA,EACT,IAAI,YAAY;AAAA,IAAW,OAAO;AAAA,EAClC,IAAI,YAAY;AAAA,IAAU,OAAO;AAAA,EACjC,OAAO,gBAAgB,YAAY,YAAY,GAAU,IAAI;AAAA;AA0B1D,IAAM,sBAAsB,MAER;AAAA,EACzB,MAAM,OAAO,IAAI;AAAA,EACjB,OAAO;AAAA,IACL,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE;AAAA,IAC5B,QAAQ;AAAA,MACN,KAAK,MAAM,CAAC,GAAG,KAAK,OAAO,CAAC;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ,CAAC,QAAQ;AAAA,QACf,KAAK,OAAQ,IAAuB,EAAE;AAAA;AAAA,MAExC,QAAQ,CAAC,SAAS;AAAA,QAChB,KAAK,IAAI,KAAK,IAAI,IAAI;AAAA,QACtB,OAAO;AAAA;AAAA,MAET,QAAQ,CAAC,SAAS;AAAA,QAChB,MAAM,QAAQ,KAAK,IAAI,KAAK,EAAE;AAAA,QAC9B,MAAM,SAAS,KAAM,SAAS,CAAC,MAAO,KAAK;AAAA,QAC3C,KAAK,IAAI,KAAK,IAAI,MAAM;AAAA,QACxB,OAAO;AAAA;AAAA,IAEX;AAAA,EACF;AAAA;",
|
|
8
8
|
"debugId": "D8470548C2FCAD2164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1 +1,9 @@
|
|
|
1
|
-
export declare const manifest: import("@absolutejs/manifest").PackageManifest<Record<never, never>, never
|
|
1
|
+
export declare const manifest: Omit<import("@absolutejs/manifest").PackageManifest<Record<never, never>, never>, "contract" | "settings" | "tools"> & (({
|
|
2
|
+
contract: 1;
|
|
3
|
+
tools?: Record<string, import("@absolutejs/manifest").LegacyManifestTool<never>> | undefined;
|
|
4
|
+
} | {
|
|
5
|
+
contract: 2;
|
|
6
|
+
tools?: Record<string, import("@absolutejs/manifest").AuthorizedManifestTool<never>> | undefined;
|
|
7
|
+
}) & {
|
|
8
|
+
settings: import("@sinclair/typebox").TObject<{}>;
|
|
9
|
+
});
|