clone

a deno framework for local-first web apps that open instantly, work offline and sync when users choose

docs(jsdoc): add examples and parameter docs to the primary API surface

Dami committed fa69306
Fifteen high-traffic exports gain @example, @param, and @returns tags:
defineLofiApp and LofiAppConfig, bootLofi, the Preact hooks and
components, the two-client testing fixture and readiness wait, and the
access templates. Examples are adapted from the reference app and the
user guides so they match real usage.
commit
fa6930656f8cab8250a20ec86e658814707fb5c0
parent
0041cc696ef65b4a718d417659590118fb12e196
author
Dami <dami.etoile@gmail.com>
9 files changed, +260 -11
Mpackage/access/policies.ts82+++++++++++++++++++++++++++++-
Mpackage/preact/DeviceStatus.tsx15+++++-
Mpackage/preact/PwaActions.tsx29++++++++++-
Mpackage/preact/RuntimeRecovery.tsx14+++++-
Mpackage/preact/live-data.ts47++++++++++++++++-
Mpackage/runtime/app.ts32+++++++++++-
Mpackage/runtime/boot.ts19+++++++-
Mpackage/testing/fixture.ts18+++++++
Mpackage/testing/readiness.ts15+++++
M package/access/policies.ts +79 -3
@@ -27,12 +27,43 @@ export type GroupAccessTemplate = {
2727 /** Any built-in access policy template accepted by {@link defineAccessPolicies}. */2828 export type AccessTemplate = PrivateAccessTemplate | SharedAccessTemplate | GroupAccessTemplate;2929 30-/** Declares owner-only read and mutation policy for one resource table. */30+/**31+ * Declares owner-only read and mutation policy for one resource table.32+ *33+ * @example34+ * ```ts35+ * import { defineAccessPolicies, privateAccess } from "@nzip/lofi/access";36+ * import { app } from "./schema.ts";37+ *38+ * export default defineAccessPolicies(app, [privateAccess({ resource: app.notes })]);39+ * ```40+ *41+ * @param config The resource table whose rows are visible and mutable only to their creator.42+ * @returns A template for {@link defineAccessPolicies}.43+ */3144 export function privateAccess(config: { resource: AccessTable }): PrivateAccessTemplate {3245 return { kind: "private", ...config };3346 }3447 35-/** Declares owner plus explicit read/edit grants for one resource table. */48+/**49+ * Declares owner plus explicit read/edit grants for one resource table.50+ *51+ * The grant table must be declared with the `sharedGrantTable` helper (or match52+ * its column shape) and reference the resource table.53+ *54+ * @example55+ * ```ts56+ * import { defineAccessPolicies, sharedAccess } from "@nzip/lofi/access";57+ * import { app } from "./schema.ts";58+ *59+ * export default defineAccessPolicies(app, [60+ * sharedAccess({ resource: app.notes, grants: app.noteGrants }),61+ * ]);62+ * ```63+ *64+ * @param config The shared resource table and its grant table.65+ * @returns A template for {@link defineAccessPolicies}.66+ */3667 export function sharedAccess(config: {3768 resource: AccessTable;3869 grants: AccessTable;
@@ -40,7 +71,30 @@ export function sharedAccess(config: {
4071 return { kind: "shared", ...config };4172 }4273 43-/** Declares fixed-role membership policy for one or more group-owned resources. */74+/**75+ * Declares fixed-role membership policy for one or more group-owned resources.76+ *77+ * The membership table must be declared with the `groupMembershipTable` helper78+ * (or match its column shape), and each resource table must carry the `groupId`79+ * column referencing the group table.80+ *81+ * @example82+ * ```ts83+ * import { defineAccessPolicies, groupAccess } from "@nzip/lofi/access";84+ * import { app } from "./schema.ts";85+ *86+ * export default defineAccessPolicies(app, [groupAccess({87+ * groups: app.workspaces,88+ * members: app.workspaceMembers,89+ * resources: app.documents,90+ * groupId: "workspaceId",91+ * })]);92+ * ```93+ *94+ * @param config The group table, membership table, group-owned resource table(s), and the95+ * resource column that references the group.96+ * @returns A template for {@link defineAccessPolicies}.97+ */4498 export function groupAccess(config: {4599 groups: AccessTable;46100 members: AccessTable;
@@ -133,6 +187,28 @@ export type RawAccessPolicyExtension = (context: RawAccessPolicyContext) => void
133187 /**134188 * Compiles the three narrow templates through Jazz's own policy builder. The135189 * optional callback is the raw Jazz-policy escape hatch for app-specific rules.190+ *191+ * @example192+ * ```ts193+ * import { defineAccessPolicies, groupAccess, sharedAccess } from "@nzip/lofi/access";194+ * import { app } from "./schema.ts";195+ *196+ * export default defineAccessPolicies(app, [197+ * sharedAccess({ resource: app.notes, grants: app.noteGrants }),198+ * groupAccess({199+ * groups: app.workspaces,200+ * members: app.workspaceMembers,201+ * resources: app.documents,202+ * groupId: "workspaceId",203+ * }),204+ * ]);205+ * ```206+ *207+ * @param app The raw Jazz app returned by `s.defineApp`.208+ * @param templates At least one {@link privateAccess}, {@link sharedAccess}, or209+ * {@link groupAccess} template; every table needs a policy.210+ * @param raw Optional raw-policy callback for app-specific rules beyond the templates.211+ * @returns Compiled permissions suitable as the app's default policy export.136212 */137213 export function defineAccessPolicies<TApp extends object>(138214 app: TApp,
M package/preact/DeviceStatus.tsx +14 -1
M package/preact/PwaActions.tsx +27 -2
@@ -10,7 +10,20 @@ import {
1010 export { pwaFailureMessage } from "../runtime/pwa.ts";1111 export type { PwaController, PwaFailureCode, PwaState, PwaUpdateState } from "../runtime/pwa.ts";1212 13-/** Subscribes a Preact component to an isolated or shared PWA controller. */13+/**14+ * Subscribes a Preact component to an isolated or shared PWA controller.15+ *16+ * @example17+ * ```tsx18+ * import { usePwaState } from "@nzip/lofi/preact";19+ *20+ * const pwa = usePwaState();21+ * const updateReady = pwa.update === "ready";22+ * ```23+ *24+ * @param controller The controller to observe; defaults to the package-wide PWA controller.25+ * @returns The current install/update state, kept live via subscription.26+ */1427 export function usePwaState(controller: PwaController = pwaController): PwaState {1528 const [state, setState] = useState<PwaState>(controller.getState());1629 useEffect(() => controller.subscribe(setState), [controller]);
@@ -25,7 +38,19 @@ export interface PwaActionsProps {
2538 readonly title?: string;2639 }2740 28-/** A composable install/update surface that keeps browser event handling package-owned. */41+/**42+ * A composable install/update surface that keeps browser event handling package-owned.43+ *44+ * @example45+ * ```tsx46+ * import { PwaActions } from "@nzip/lofi/preact";47+ *48+ * <PwaActions title="Install this app" />;49+ * ```50+ *51+ * @param props An optional controller override and heading text.52+ * @returns The install/update section, or `null` when no action or status is relevant.53+ */2954 export function PwaActions({3055 controller = pwaController,3156 title = "Install & updates",
M package/preact/RuntimeRecovery.tsx +13 -1
M package/preact/live-data.ts +45 -2
@@ -18,7 +18,30 @@ const loading = <T extends TableRow>(): LiveQuerySnapshot<T> => ({
1818 error: null,1919 });2020 21-/** Subscribes a Preact component to any typed Jazz query. */21+/**22+ * Subscribes a Preact component to any typed Jazz query.23+ *24+ * Equivalent mounted queries share one Jazz subscription. The snapshot preserves25+ * the exact row type produced by the builder, including `select` and `include`26+ * projections. An empty `rows` array with `status: "ready"` is an empty result,27+ * not a loading signal.28+ *29+ * @example30+ * ```ts31+ * import { useLiveQuery } from "@nzip/lofi/preact";32+ * import { app } from "../app.ts";33+ *34+ * const records = useLiveQuery(35+ * () => app.schema.records.where({ workspaceId, archived: false }),36+ * [workspaceId],37+ * );38+ * // records.status is "loading" | "ready" | "error"; records.rows is typed.39+ * ```40+ *41+ * @param createQuery Builds the typed Jazz query; re-invoked when dependencies change.42+ * @param dependencies Values that, when changed, release the query and open a replacement.43+ * @returns The live snapshot: `status`, exact typed `rows`, and `error`.44+ */2245 export function useLiveQuery<T extends TableRow>(2346 createQuery: () => QueryBuilder<T>,2447 dependencies: readonly unknown[],
@@ -53,7 +76,27 @@ export type TableMutations<T extends TableRow, Init> = TableMutationSnapshot & {
5376 remove(id: string): Promise<void>;5477 };5578 56-/** Binds one typed Jazz table to stable insert, update, and remove methods. */79+/**80+ * Binds one typed Jazz table to stable insert, update, and remove methods.81+ *82+ * Mutation promises resolve after local durability; when managed sync is active,83+ * global confirmation continues in the background and updates the shared84+ * table-scoped `pending`, `durability`, and `error` state.85+ *86+ * @example87+ * ```ts88+ * import { useTableMutations } from "@nzip/lofi/preact";89+ * import { app } from "../app.ts";90+ *91+ * const records = useTableMutations(app.schema.records);92+ * const created = await records.insert({ title: "Release notes", archived: false });93+ * await records.update(created.id, { archived: true });94+ * await records.remove(created.id);95+ * ```96+ *97+ * @param table The typed schema table to mutate, e.g. `app.schema.records`.98+ * @returns Stable `insert`, `update`, and `remove` methods plus the shared mutation state.99+ */57100 export function useTableMutations<T extends TableRow, Init>(58101 table: TableProxy<T, Init>,59102 ): TableMutations<T, Init> {
M package/runtime/app.ts +31 -1
M package/runtime/boot.ts +18 -1
M package/testing/fixture.ts +18 -0
M package/testing/readiness.ts +15 -0