UNPKG

@angular-experts/resource

Version:

### The missing create, update, delete (CUD) support for Angular resource

180 lines (175 loc) 6.94 kB
import * as _angular_core from '@angular/core'; import { Observable, mergeMap } from 'rxjs'; type RequestType = 'create' | 'update' | 'remove'; type Behavior = 'concat' | 'merge' | 'switch' | 'exhaust'; /** * Strategy for handling resource requests * * - `'pessimistic'` - wait for server response, then reload the entire collection * - `'optimistic'` - update UI immediately and assume success * - `'incremental'` - patch returned item into the existing collection after server confirms */ type Strategy = 'optimistic' | 'pessimistic' | 'incremental'; interface RestResourceOptions<T, ID> { /** * Whether to log verbose information to the console. * This is useful for debugging and understanding the resource's behavior. * * @default false */ verbose?: boolean; /** * A reactive function which determines the request to be made. * Whenever the params change, the loader will be triggered to fetch a new value for the resource. * * (works the same way as Angular's `resource`) * * @returns A string containing URL query parameters or undefined */ params?: () => string | undefined; /** * Function to extract the ID from an item when the ID is not stored in the `id` field. * Used to identify items for update and remove operations. * * @param item The item from which to extract the ID * @returns The ID of the item */ idSelector?: (item: T) => ID; /** * The default strategy for the resource for every request type, * it can be overridden by the request-type specific strategy * * - `'pessimistic'` - wait for server response, then reload the entire collection * - `'optimistic'` - update UI immediately and assume success * - `'incremental'` - patch returned item into the existing collection after server confirms * * @default 'pessimistic' */ strategy?: Strategy; create?: { /** * Defines how create requests are handled when multiple requests are made. * Controls the RxJS flattening operator used for the HTTP request. * * @default 'concat' */ behavior?: Behavior; /** * Determines whether changes are applied optimistically (before server confirmation) * or pessimistically (after server confirmation) for create operations. * * @default The value of the global strategy option */ strategy?: Strategy; /** * Optionally generate a new item ID (if the target API does not handle this) * and set it on the item. * * @property generator A function that returns a new ID (e.g., UUID or auto-increment). * Used when the backend does not assign one automatically. * * @property setter (Optional) A function that sets the generated ID onto the item, * especially useful when the item’s ID field is not named `id`. * * @example * { * id: { * generator: () => uuid(), * setter: (id, item) => { * item.nonstandardId = id * } * } * } * */ id?: { /** * A function that generates a new unique ID. * @example * () => uuid() */ generator: () => ID; /** * (Optional) Custom logic for assigning the generated ID to the item. * * @param id The generated ID * @param item The item object to modify * * @example * setter: (id, item) => { * item.nonstandardId = id * } */ setter?: (id: ID, item: Partial<T>) => void; }; }; update?: { /** * Defines how update requests are handled when multiple requests are made. * Controls the RxJS flattening operator used for the HTTP request. * * @default 'concat' */ behavior?: Behavior; /** * Determines whether changes are applied optimistically (before server confirmation) * or pessimistically (after server confirmation) for update operations. * * @default The value of the global strategy option */ strategy?: Strategy; }; remove?: { /** * Defines how remove requests are handled when multiple requests are made. * Controls the RxJS flattening operator used for the HTTP request. * * @default 'concat' */ behavior?: Behavior; /** * Determines whether changes are applied optimistically (before server confirmation) * or pessimistically (after server confirmation) for remove operations. * * @default The value of the global strategy option */ strategy?: Strategy; }; } declare const LOG_PREFIX = "[@angular-experts/resource]"; declare function restResource<T, ID, E extends Error = Error>(apiEndpoint: string, options?: RestResourceOptions<T, ID>): { loadingInitial: _angular_core.Signal<boolean>; loading: _angular_core.Signal<boolean>; loadingCreate: _angular_core.WritableSignal<boolean>; loadingUpdate: _angular_core.WritableSignal<boolean>; loadingRemove: _angular_core.WritableSignal<boolean>; errorRead: _angular_core.Signal<Error | undefined>; errorCreate: _angular_core.WritableSignal<E | undefined>; errorUpdate: _angular_core.WritableSignal<E | undefined>; errorRemove: _angular_core.WritableSignal<E | undefined>; /** * The value of the resource, ONLY if the resource is a single item. * * This is useful when building a resource to manage a single entity, eg detail view. * * @returns Signal of single item or undefined (also returns undefined if resource has more than one item) */ value: _angular_core.Signal<T | undefined>; /** * The values of the resource (eg list of 0 to n items). * * @returns Signal of a list of items or undefined (also returns undefined if resource has no items) */ values: _angular_core.WritableSignal<T[] | undefined>; hasValue: _angular_core.Signal<boolean>; hasValues: _angular_core.Signal<boolean>; reload: () => boolean; create: (item: Partial<T>) => void; update: (item: T) => void; remove: (item: T) => void; destroy: () => void; }; declare function streamify<T extends unknown[]>(impl: (stream: Observable<T>) => Observable<unknown>): (...args: T) => void; declare function behaviorToOperator(behavior?: Behavior): typeof mergeMap; export { LOG_PREFIX, behaviorToOperator, restResource, streamify }; export type { Behavior, RequestType, RestResourceOptions, Strategy };