feathers-utils 10.2.0 → 10.3.0
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/{hooks-tfw03iVM.mjs → hooks-DpFQfcFa.mjs} +65 -65
- package/dist/{hooks-tfw03iVM.mjs.map → hooks-DpFQfcFa.mjs.map} +1 -1
- package/dist/hooks.d.mts +48 -48
- package/dist/hooks.mjs +4 -4
- package/dist/{index-CKAzIogj.d.mts → index-C6MN6wag.d.mts} +162 -105
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +7 -7
- package/dist/{internal.utils-BMzV_-xp.mjs → internal.utils-BBB-b6Ud.mjs} +16 -2
- package/dist/internal.utils-BBB-b6Ud.mjs.map +1 -0
- package/dist/{mutate-result.util-Dqzepn1M.mjs → mutate-result.util-C0nY6L7i.mjs} +2 -2
- package/dist/{mutate-result.util-Dqzepn1M.mjs.map → mutate-result.util-C0nY6L7i.mjs.map} +1 -1
- package/dist/{predicates-puYa4nkf.mjs → predicates-NOnUyMic.mjs} +53 -53
- package/dist/{predicates-puYa4nkf.mjs.map → predicates-NOnUyMic.mjs.map} +1 -1
- package/dist/predicates.d.mts +18 -18
- package/dist/predicates.mjs +1 -1
- package/dist/{resolve-B9hRleHY.mjs → resolve-BflgIVD8.mjs} +2 -2
- package/dist/{resolve-B9hRleHY.mjs.map → resolve-BflgIVD8.mjs.map} +1 -1
- package/dist/resolvers.mjs +1 -1
- package/dist/{transform-result.hook-B65pTRJO.mjs → transform-result.hook-V2QYN2K0.mjs} +2 -2
- package/dist/{transform-result.hook-B65pTRJO.mjs.map → transform-result.hook-V2QYN2K0.mjs.map} +1 -1
- package/dist/transformers.mjs +3 -3
- package/dist/{utils-BAIcSl7u.mjs → utils-DByCpAsf.mjs} +386 -209
- package/dist/utils-DByCpAsf.mjs.map +1 -0
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +4 -4
- package/package.json +1 -1
- package/src/common/index.ts +1 -0
- package/src/common/is-empty-object.ts +38 -0
- package/src/hooks/index.ts +1 -1
- package/src/predicates/index.ts +3 -3
- package/src/utils/add-to-query/add-to-query.util.ts +19 -1
- package/src/utils/index.ts +5 -4
- package/src/utils/merge-query/dedupe-branches.ts +42 -0
- package/src/utils/merge-query/extract-query-filters.ts +80 -0
- package/src/utils/merge-query/has-conflict.ts +39 -0
- package/src/utils/merge-query/logical-branches.ts +39 -0
- package/src/utils/merge-query/merge-query-bodies.ts +136 -0
- package/src/utils/merge-query/merge-query.util.ts +102 -0
- package/src/utils/merge-query/merge-select.ts +64 -0
- package/dist/internal.utils-BMzV_-xp.mjs.map +0 -1
- package/dist/utils-BAIcSl7u.mjs.map +0 -1
package/dist/hooks.d.mts
CHANGED
|
@@ -249,6 +249,54 @@ declare function createRelated<H extends HookContext = HookContext>(options: May
|
|
|
249
249
|
*/
|
|
250
250
|
declare const debug: <H extends HookContext = HookContext>(msg: string, ...fieldNames: string[]) => (context: H, next?: NextFunction) => Promise<void>;
|
|
251
251
|
//#endregion
|
|
252
|
+
//#region src/hooks/disable-pagination/disable-pagination.hook.d.ts
|
|
253
|
+
/**
|
|
254
|
+
* Disables pagination when `query.$limit` is `-1` or `'-1'`.
|
|
255
|
+
* Removes the `$limit` from the query and sets `params.paginate = false`.
|
|
256
|
+
* Must be used as a `before` or `around` hook on the `find` method.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* import { disablePagination } from 'feathers-utils/hooks'
|
|
261
|
+
*
|
|
262
|
+
* app.service('users').hooks({
|
|
263
|
+
* before: { find: [disablePagination()] }
|
|
264
|
+
* })
|
|
265
|
+
* // Then call: app.service('users').find({ query: { $limit: -1 } })
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @see https://utils.feathersjs.com/hooks/disable-pagination.html
|
|
269
|
+
*/
|
|
270
|
+
declare const disablePagination: <H extends HookContext = HookContext>() => {
|
|
271
|
+
(context: H): void;
|
|
272
|
+
(context: H, next: NextFunction): Promise<void>;
|
|
273
|
+
};
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/hooks/disallow/disallow.hook.d.ts
|
|
276
|
+
/**
|
|
277
|
+
* Prevents access to a service method completely or for specific transports.
|
|
278
|
+
* When called without arguments, the method is blocked for all callers.
|
|
279
|
+
* When called with transport names, only those transports are blocked.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* import { disallow } from 'feathers-utils/hooks'
|
|
284
|
+
*
|
|
285
|
+
* app.service('users').hooks({
|
|
286
|
+
* before: {
|
|
287
|
+
* remove: [disallow('external')], // block external access
|
|
288
|
+
* update: [disallow()], // block completely
|
|
289
|
+
* }
|
|
290
|
+
* })
|
|
291
|
+
* ```
|
|
292
|
+
*
|
|
293
|
+
* @see https://utils.feathersjs.com/hooks/disallow.html
|
|
294
|
+
*/
|
|
295
|
+
declare const disallow: <H extends HookContext = HookContext>(transports?: MaybeArray<TransportName>) => {
|
|
296
|
+
(context: H): void;
|
|
297
|
+
(context: H, next: NextFunction): Promise<void>;
|
|
298
|
+
};
|
|
299
|
+
//#endregion
|
|
252
300
|
//#region src/hooks/find-or-create/find-or-create.hook.d.ts
|
|
253
301
|
/**
|
|
254
302
|
* The valid `uniqueBy` paths for a service's create data. Falls back to a plain
|
|
@@ -303,54 +351,6 @@ interface FindOrCreateOptions<H extends HookContext = HookContext, Services exte
|
|
|
303
351
|
*/
|
|
304
352
|
declare function findOrCreate<H extends HookContext = HookContext>(options: FindOrCreateOptions<H>): (context: H, next?: NextFunction) => Promise<void>;
|
|
305
353
|
//#endregion
|
|
306
|
-
//#region src/hooks/disable-pagination/disable-pagination.hook.d.ts
|
|
307
|
-
/**
|
|
308
|
-
* Disables pagination when `query.$limit` is `-1` or `'-1'`.
|
|
309
|
-
* Removes the `$limit` from the query and sets `params.paginate = false`.
|
|
310
|
-
* Must be used as a `before` or `around` hook on the `find` method.
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* ```ts
|
|
314
|
-
* import { disablePagination } from 'feathers-utils/hooks'
|
|
315
|
-
*
|
|
316
|
-
* app.service('users').hooks({
|
|
317
|
-
* before: { find: [disablePagination()] }
|
|
318
|
-
* })
|
|
319
|
-
* // Then call: app.service('users').find({ query: { $limit: -1 } })
|
|
320
|
-
* ```
|
|
321
|
-
*
|
|
322
|
-
* @see https://utils.feathersjs.com/hooks/disable-pagination.html
|
|
323
|
-
*/
|
|
324
|
-
declare const disablePagination: <H extends HookContext = HookContext>() => {
|
|
325
|
-
(context: H): void;
|
|
326
|
-
(context: H, next: NextFunction): Promise<void>;
|
|
327
|
-
};
|
|
328
|
-
//#endregion
|
|
329
|
-
//#region src/hooks/disallow/disallow.hook.d.ts
|
|
330
|
-
/**
|
|
331
|
-
* Prevents access to a service method completely or for specific transports.
|
|
332
|
-
* When called without arguments, the method is blocked for all callers.
|
|
333
|
-
* When called with transport names, only those transports are blocked.
|
|
334
|
-
*
|
|
335
|
-
* @example
|
|
336
|
-
* ```ts
|
|
337
|
-
* import { disallow } from 'feathers-utils/hooks'
|
|
338
|
-
*
|
|
339
|
-
* app.service('users').hooks({
|
|
340
|
-
* before: {
|
|
341
|
-
* remove: [disallow('external')], // block external access
|
|
342
|
-
* update: [disallow()], // block completely
|
|
343
|
-
* }
|
|
344
|
-
* })
|
|
345
|
-
* ```
|
|
346
|
-
*
|
|
347
|
-
* @see https://utils.feathersjs.com/hooks/disallow.html
|
|
348
|
-
*/
|
|
349
|
-
declare const disallow: <H extends HookContext = HookContext>(transports?: MaybeArray<TransportName>) => {
|
|
350
|
-
(context: H): void;
|
|
351
|
-
(context: H, next: NextFunction): Promise<void>;
|
|
352
|
-
};
|
|
353
|
-
//#endregion
|
|
354
354
|
//#region src/hooks/mute-event/mute-event.hook.d.ts
|
|
355
355
|
type MuteEventOptions<H extends HookContext = HookContext> = {
|
|
356
356
|
/**
|
package/dist/hooks.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as combine, a as iffElse, i as iff, n as
|
|
2
|
-
import { C as checkMulti, S as checkRequired, _ as
|
|
3
|
-
import { n as transformQuery, r as transformData, t as transformResult } from "./transform-result.hook-
|
|
4
|
-
import { i as resolveData, n as resolveQuery, r as resolveResult, t as resolve } from "./resolve-
|
|
1
|
+
import { _ as combine, a as iffElse, i as iff, n as throwIf, r as skippable, t as unless } from "./predicates-NOnUyMic.mjs";
|
|
2
|
+
import { C as checkMulti, S as checkRequired, _ as findOrCreate, a as softDelete, b as debug, c as setQueryDefaults, d as rateLimit, f as preventChanges, g as muteEvent, h as onDelete, i as stashable, l as setField, m as paramsForServer, n as throwIfIsProvider, o as setSlug, p as paramsFromClient, r as throwIfIsMulti, s as setResult, t as traverse, u as setData, v as disallow, w as cache, x as createRelated, y as disablePagination } from "./hooks-DpFQfcFa.mjs";
|
|
3
|
+
import { n as transformQuery, r as transformData, t as transformResult } from "./transform-result.hook-V2QYN2K0.mjs";
|
|
4
|
+
import { i as resolveData, n as resolveQuery, r as resolveResult, t as resolve } from "./resolve-BflgIVD8.mjs";
|
|
5
5
|
export { cache, checkMulti, checkRequired, combine, createRelated, debug, disablePagination, disallow, findOrCreate, iff, iff as when, iffElse, muteEvent, onDelete, paramsForServer, paramsFromClient, preventChanges, rateLimit, resolve, resolveData, resolveQuery, resolveResult, setData, setField, setQueryDefaults, setResult, setSlug, skippable, softDelete, stashable, throwIf, throwIfIsMulti, throwIfIsProvider, transformData, transformQuery, transformResult, traverse, unless };
|
|
@@ -23,45 +23,13 @@ type SkipHookName = 'all' | HookType | `${HookType}:${string}` | (string & {});
|
|
|
23
23
|
*/
|
|
24
24
|
declare const addSkip: <H extends HookContext>(context: H, hooks: MaybeArray<SkipHookName>) => void;
|
|
25
25
|
//#endregion
|
|
26
|
-
//#region src/utils/chunk-find/chunk-find.util.d.ts
|
|
27
|
-
type PaginateOption$1 = {
|
|
28
|
-
default?: number;
|
|
29
|
-
max?: number;
|
|
30
|
-
};
|
|
31
|
-
type ChunkFindOptions<P extends Params = Params> = {
|
|
32
|
-
params?: P & {
|
|
33
|
-
paginate?: PaginateOption$1;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Use `for await` to iterate over chunks (pages) of results from a `find` method.
|
|
38
|
-
*
|
|
39
|
-
* This function is useful for processing large datasets in batches without loading everything into memory at once.
|
|
40
|
-
* It uses pagination to fetch results in chunks, yielding each page's data array.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* import { chunkFind } from 'feathers-utils/utils'
|
|
45
|
-
*
|
|
46
|
-
* const app = feathers()
|
|
47
|
-
*
|
|
48
|
-
* // Assuming 'users' service has many records
|
|
49
|
-
* for await (const users of chunkFind(app, 'users', {
|
|
50
|
-
* params: { query: { active: true }, // Custom query parameters
|
|
51
|
-
* } })) {
|
|
52
|
-
* console.log(users) // Process each chunk of user records
|
|
53
|
-
* }
|
|
54
|
-
* ```
|
|
55
|
-
*
|
|
56
|
-
* @see https://utils.feathersjs.com/utils/chunk-find.html
|
|
57
|
-
*/
|
|
58
|
-
declare function chunkFind<Services, Path extends KeyOf<Services>, Service extends Services[Path] = Services[Path], P extends Params = InferFindParams<Service>, Item = InferFindResultSingle<Service>>(app: Application<Services>, servicePath: Path, options?: ChunkFindOptions<P>): AsyncGenerator<Item[], void, unknown>;
|
|
59
|
-
//#endregion
|
|
60
26
|
//#region src/utils/add-to-query/add-to-query.util.d.ts
|
|
61
27
|
/**
|
|
62
28
|
* Safely merges properties into a Feathers query object. If a property already exists
|
|
63
29
|
* with a different value, it wraps both in a `$and` array to preserve both conditions.
|
|
64
|
-
* If the exact same key-value pair already exists, no changes are made.
|
|
30
|
+
* If the exact same key-value pair already exists, no changes are made. When the added
|
|
31
|
+
* query is itself a pure `$and` (`{ $and: [...] }`), its branches are flattened into the
|
|
32
|
+
* target's `$and` rather than nested.
|
|
65
33
|
*
|
|
66
34
|
* @example
|
|
67
35
|
* ```ts
|
|
@@ -143,6 +111,40 @@ declare function checkContext<H extends HookContext, const T extends HookType$1
|
|
|
143
111
|
method: M;
|
|
144
112
|
}>;
|
|
145
113
|
//#endregion
|
|
114
|
+
//#region src/utils/chunk-find/chunk-find.util.d.ts
|
|
115
|
+
type PaginateOption$1 = {
|
|
116
|
+
default?: number;
|
|
117
|
+
max?: number;
|
|
118
|
+
};
|
|
119
|
+
type ChunkFindOptions<P extends Params = Params> = {
|
|
120
|
+
params?: P & {
|
|
121
|
+
paginate?: PaginateOption$1;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Use `for await` to iterate over chunks (pages) of results from a `find` method.
|
|
126
|
+
*
|
|
127
|
+
* This function is useful for processing large datasets in batches without loading everything into memory at once.
|
|
128
|
+
* It uses pagination to fetch results in chunks, yielding each page's data array.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { chunkFind } from 'feathers-utils/utils'
|
|
133
|
+
*
|
|
134
|
+
* const app = feathers()
|
|
135
|
+
*
|
|
136
|
+
* // Assuming 'users' service has many records
|
|
137
|
+
* for await (const users of chunkFind(app, 'users', {
|
|
138
|
+
* params: { query: { active: true }, // Custom query parameters
|
|
139
|
+
* } })) {
|
|
140
|
+
* console.log(users) // Process each chunk of user records
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @see https://utils.feathersjs.com/utils/chunk-find.html
|
|
145
|
+
*/
|
|
146
|
+
declare function chunkFind<Services, Path extends KeyOf<Services>, Service extends Services[Path] = Services[Path], P extends Params = InferFindParams<Service>, Item = InferFindResultSingle<Service>>(app: Application<Services>, servicePath: Path, options?: ChunkFindOptions<P>): AsyncGenerator<Item[], void, unknown>;
|
|
147
|
+
//#endregion
|
|
146
148
|
//#region src/utils/context-to-json/context-to-json.util.d.ts
|
|
147
149
|
/**
|
|
148
150
|
* Converts a FeathersJS HookContext to a plain JSON object by calling `toJSON()` if available.
|
|
@@ -308,6 +310,61 @@ type IterateFindOptions<P extends Params = Params> = {
|
|
|
308
310
|
*/
|
|
309
311
|
declare function iterateFind<Services, Path extends KeyOf<Services>, Service extends Services[Path] = Services[Path], P extends Params = InferFindParams<Service>, Item = InferFindResultSingle<Service>>(app: Application<Services>, servicePath: Path, options?: IterateFindOptions<P>): AsyncGenerator<Item, void, unknown>;
|
|
310
312
|
//#endregion
|
|
313
|
+
//#region src/utils/merge-query/merge-query.util.d.ts
|
|
314
|
+
type MergeQueryMode = 'target' | 'source' | 'combine' | 'intersect';
|
|
315
|
+
interface MergeQueryOptions {
|
|
316
|
+
/**
|
|
317
|
+
* How to merge query properties that both queries constrain.
|
|
318
|
+
*
|
|
319
|
+
* - `combine` (default): broaden — the two queries always become branches of an `$or`.
|
|
320
|
+
* - `intersect`: narrow — non-conflicting properties merge flat, conflicts become an `$and`.
|
|
321
|
+
* - `target`: keep the target's value on conflict.
|
|
322
|
+
* - `source`: keep the source's value on conflict.
|
|
323
|
+
*/
|
|
324
|
+
mode?: MergeQueryMode;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Properties are combined with a logical operator rather than merged at the value
|
|
328
|
+
* level, so the result is always a valid query: `combine` always wraps the two
|
|
329
|
+
* queries in `$or` (broaden — OR has no flat form), while `intersect` merges
|
|
330
|
+
* non-conflicting properties flat and wraps conflicts in `$and` (narrow). The
|
|
331
|
+
* special filters `$select`, `$limit`, `$skip` and `$sort` are merged separately.
|
|
332
|
+
* Inputs are never mutated.
|
|
333
|
+
*
|
|
334
|
+
* This is well suited to merging a client-provided query with a server-side
|
|
335
|
+
* restriction inside a hook.
|
|
336
|
+
*
|
|
337
|
+
* @param target Query to be merged into
|
|
338
|
+
* @param source Query to be merged from
|
|
339
|
+
* @param options
|
|
340
|
+
* @returns the merged query
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```ts
|
|
344
|
+
* import { mergeQuery } from 'feathers-utils/utils'
|
|
345
|
+
*
|
|
346
|
+
* // combine (default): the two queries always become an $or
|
|
347
|
+
* mergeQuery({ id: 1 }, { id: 2 })
|
|
348
|
+
* // => { $or: [{ id: 1 }, { id: 2 }] }
|
|
349
|
+
*
|
|
350
|
+
* mergeQuery({ status: 'active' }, { authorId: 5 })
|
|
351
|
+
* // => { $or: [{ status: 'active' }, { authorId: 5 }] }
|
|
352
|
+
* ```
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```ts
|
|
356
|
+
* // intersect: non-conflicting properties merge flat, conflicts become an $and
|
|
357
|
+
* mergeQuery({ status: 'active' }, { authorId: 5 }, { mode: 'intersect' })
|
|
358
|
+
* // => { status: 'active', authorId: 5 }
|
|
359
|
+
*
|
|
360
|
+
* mergeQuery({ id: 1 }, { id: 2 }, { mode: 'intersect' })
|
|
361
|
+
* // => { $and: [{ id: 1 }, { id: 2 }] }
|
|
362
|
+
* ```
|
|
363
|
+
*
|
|
364
|
+
* @see https://utils.feathersjs.com/utils/merge-query.html
|
|
365
|
+
*/
|
|
366
|
+
declare function mergeQuery(target: Query, source: Query, options?: MergeQueryOptions): Query;
|
|
367
|
+
//#endregion
|
|
311
368
|
//#region src/utils/patch-batch/patch-batch.util.d.ts
|
|
312
369
|
type PatchBatchOptions<IdKey extends string> = {
|
|
313
370
|
/** the key of the id property */id?: IdKey;
|
|
@@ -340,6 +397,48 @@ type PatchBatchResultItem<T = Record<string, unknown>, P = Params> = [Id | null,
|
|
|
340
397
|
*/
|
|
341
398
|
declare function patchBatch<T extends Record<string, any>, IdKey extends KeyOf<T>, P extends Params, R extends Omit<T, IdKey> = Omit<T, IdKey>>(items: T[], options?: PatchBatchOptions<IdKey>): PatchBatchResultItem<R, P>[];
|
|
342
399
|
//#endregion
|
|
400
|
+
//#region src/utils/query-defaults/query-defaults.util.d.ts
|
|
401
|
+
/**
|
|
402
|
+
* Adds default properties to a Feathers query — but only for fields the query does
|
|
403
|
+
* not already constrain. Presence is checked with {@link queryHasProperty}, so a field
|
|
404
|
+
* referenced anywhere (including nested in `$and`/`$or`/`$nor`) is left untouched and
|
|
405
|
+
* the caller keeps control over it. The query is treated as the `data` equivalent of
|
|
406
|
+
* the `defaults` transformer. Each default is applied independently (per-field).
|
|
407
|
+
*
|
|
408
|
+
* @example
|
|
409
|
+
* ```ts
|
|
410
|
+
* import { queryDefaults } from 'feathers-utils/utils'
|
|
411
|
+
*
|
|
412
|
+
* queryDefaults({ status: 'active' }, { isTemplate: false })
|
|
413
|
+
* // => { status: 'active', isTemplate: false }
|
|
414
|
+
*
|
|
415
|
+
* queryDefaults({ $or: [{ isTemplate: true }] }, { isTemplate: false })
|
|
416
|
+
* // => { $or: [{ isTemplate: true }] } (untouched — already referenced)
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* @see https://utils.feathersjs.com/utils/query-defaults.html
|
|
420
|
+
*/
|
|
421
|
+
declare const queryDefaults: (query: Query | undefined, defaults: Query) => Query;
|
|
422
|
+
//#endregion
|
|
423
|
+
//#region src/utils/query-has-property/query-has-property.util.d.ts
|
|
424
|
+
/**
|
|
425
|
+
* Checks whether a Feathers query contains one or more properties — including
|
|
426
|
+
* properties nested inside `$and`/`$or`/`$nor` arrays. Returns `true` as soon as
|
|
427
|
+
* any of the given property names is found. The query is not mutated.
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* ```ts
|
|
431
|
+
* import { queryHasProperty } from 'feathers-utils/utils'
|
|
432
|
+
*
|
|
433
|
+
* queryHasProperty({ isTemplate: true }, 'isTemplate') // true
|
|
434
|
+
* queryHasProperty({ $or: [{ isTemplate: true }] }, 'isTemplate') // true
|
|
435
|
+
* queryHasProperty({ age: { $gt: 18 } }, ['isTemplate', 'status']) // false
|
|
436
|
+
* ```
|
|
437
|
+
*
|
|
438
|
+
* @see https://utils.feathersjs.com/utils/query-has-property.html
|
|
439
|
+
*/
|
|
440
|
+
declare const queryHasProperty: (query: Query, property: MaybeArray<string>) => boolean;
|
|
441
|
+
//#endregion
|
|
343
442
|
//#region src/utils/replace-data/replace-data.util.d.ts
|
|
344
443
|
/**
|
|
345
444
|
* Replaces `context.data` wholesale with the given items, preserving the original
|
|
@@ -403,6 +502,32 @@ declare function replaceResult<H extends HookContext = HookContext>(context: H,
|
|
|
403
502
|
*/
|
|
404
503
|
declare const skipResult: <H extends HookContext = HookContext>(context: H) => H;
|
|
405
504
|
//#endregion
|
|
505
|
+
//#region src/utils/sort-query-properties/sort-query-properties.util.d.ts
|
|
506
|
+
/**
|
|
507
|
+
* Recursively normalizes a Feathers query object for order-independent comparison.
|
|
508
|
+
* Sorts object keys and sorts arrays within `$or`, `$and`, `$nor`, `$not`, `$in`,
|
|
509
|
+
* and `$nin` operators so that different orderings produce the same result.
|
|
510
|
+
*
|
|
511
|
+
* This is useful for generating stable cache keys where
|
|
512
|
+
* `{ $or: [{ a: 1 }, { b: 2 }] }` and `{ $or: [{ b: 2 }, { a: 1 }] }`
|
|
513
|
+
* should be treated as equivalent.
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* ```ts
|
|
517
|
+
* import { sortQueryProperties } from 'feathers-utils/utils'
|
|
518
|
+
*
|
|
519
|
+
* const normalized = sortQueryProperties({
|
|
520
|
+
* $or: [{ name: 'Jane' }, { name: 'John' }],
|
|
521
|
+
* age: { $in: [30, 25] },
|
|
522
|
+
* })
|
|
523
|
+
* // => { $or: [{ name: 'John' }, { name: 'Jane' }], age: { $in: [25, 30] } }
|
|
524
|
+
* // (sorted by stable stringify comparison)
|
|
525
|
+
* ```
|
|
526
|
+
*
|
|
527
|
+
* @see https://utils.feathersjs.com/utils/sort-query-properties.html
|
|
528
|
+
*/
|
|
529
|
+
declare const sortQueryProperties: <Q extends Query>(query: Q) => Q;
|
|
530
|
+
//#endregion
|
|
406
531
|
//#region src/utils/to-paginated/to-paginated.util.d.ts
|
|
407
532
|
/**
|
|
408
533
|
* Ensures a result is in Feathers paginated format (`{ total, limit, skip, data }`).
|
|
@@ -438,32 +563,6 @@ declare function toPaginated<R>(result: R[] | Paginated<R>): Paginated<R>;
|
|
|
438
563
|
*/
|
|
439
564
|
declare const transformParams: <P extends Params = Params>(params: P, fn: TransformParamsFn<P> | undefined) => P;
|
|
440
565
|
//#endregion
|
|
441
|
-
//#region src/utils/sort-query-properties/sort-query-properties.util.d.ts
|
|
442
|
-
/**
|
|
443
|
-
* Recursively normalizes a Feathers query object for order-independent comparison.
|
|
444
|
-
* Sorts object keys and sorts arrays within `$or`, `$and`, `$nor`, `$not`, `$in`,
|
|
445
|
-
* and `$nin` operators so that different orderings produce the same result.
|
|
446
|
-
*
|
|
447
|
-
* This is useful for generating stable cache keys where
|
|
448
|
-
* `{ $or: [{ a: 1 }, { b: 2 }] }` and `{ $or: [{ b: 2 }, { a: 1 }] }`
|
|
449
|
-
* should be treated as equivalent.
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* ```ts
|
|
453
|
-
* import { sortQueryProperties } from 'feathers-utils/utils'
|
|
454
|
-
*
|
|
455
|
-
* const normalized = sortQueryProperties({
|
|
456
|
-
* $or: [{ name: 'Jane' }, { name: 'John' }],
|
|
457
|
-
* age: { $in: [30, 25] },
|
|
458
|
-
* })
|
|
459
|
-
* // => { $or: [{ name: 'John' }, { name: 'Jane' }], age: { $in: [25, 30] } }
|
|
460
|
-
* // (sorted by stable stringify comparison)
|
|
461
|
-
* ```
|
|
462
|
-
*
|
|
463
|
-
* @see https://utils.feathersjs.com/utils/sort-query-properties.html
|
|
464
|
-
*/
|
|
465
|
-
declare const sortQueryProperties: <Q extends Query>(query: Q) => Q;
|
|
466
|
-
//#endregion
|
|
467
566
|
//#region src/utils/wait-for-service-event/wait-for-service-event.util.d.ts
|
|
468
567
|
/**
|
|
469
568
|
* The standard Feathers service events, plus any custom event name a service
|
|
@@ -578,48 +677,6 @@ type WalkQueryCallback = (options: WalkQueryOptions) => any;
|
|
|
578
677
|
*/
|
|
579
678
|
declare const walkQuery: <Q extends Query>(query: Q, walker: WalkQueryCallback) => Q;
|
|
580
679
|
//#endregion
|
|
581
|
-
//#region src/utils/query-has-property/query-has-property.util.d.ts
|
|
582
|
-
/**
|
|
583
|
-
* Checks whether a Feathers query contains one or more properties — including
|
|
584
|
-
* properties nested inside `$and`/`$or`/`$nor` arrays. Returns `true` as soon as
|
|
585
|
-
* any of the given property names is found. The query is not mutated.
|
|
586
|
-
*
|
|
587
|
-
* @example
|
|
588
|
-
* ```ts
|
|
589
|
-
* import { queryHasProperty } from 'feathers-utils/utils'
|
|
590
|
-
*
|
|
591
|
-
* queryHasProperty({ isTemplate: true }, 'isTemplate') // true
|
|
592
|
-
* queryHasProperty({ $or: [{ isTemplate: true }] }, 'isTemplate') // true
|
|
593
|
-
* queryHasProperty({ age: { $gt: 18 } }, ['isTemplate', 'status']) // false
|
|
594
|
-
* ```
|
|
595
|
-
*
|
|
596
|
-
* @see https://utils.feathersjs.com/utils/query-has-property.html
|
|
597
|
-
*/
|
|
598
|
-
declare const queryHasProperty: (query: Query, property: MaybeArray<string>) => boolean;
|
|
599
|
-
//#endregion
|
|
600
|
-
//#region src/utils/query-defaults/query-defaults.util.d.ts
|
|
601
|
-
/**
|
|
602
|
-
* Adds default properties to a Feathers query — but only for fields the query does
|
|
603
|
-
* not already constrain. Presence is checked with {@link queryHasProperty}, so a field
|
|
604
|
-
* referenced anywhere (including nested in `$and`/`$or`/`$nor`) is left untouched and
|
|
605
|
-
* the caller keeps control over it. The query is treated as the `data` equivalent of
|
|
606
|
-
* the `defaults` transformer. Each default is applied independently (per-field).
|
|
607
|
-
*
|
|
608
|
-
* @example
|
|
609
|
-
* ```ts
|
|
610
|
-
* import { queryDefaults } from 'feathers-utils/utils'
|
|
611
|
-
*
|
|
612
|
-
* queryDefaults({ status: 'active' }, { isTemplate: false })
|
|
613
|
-
* // => { status: 'active', isTemplate: false }
|
|
614
|
-
*
|
|
615
|
-
* queryDefaults({ $or: [{ isTemplate: true }] }, { isTemplate: false })
|
|
616
|
-
* // => { $or: [{ isTemplate: true }] } (untouched — already referenced)
|
|
617
|
-
* ```
|
|
618
|
-
*
|
|
619
|
-
* @see https://utils.feathersjs.com/utils/query-defaults.html
|
|
620
|
-
*/
|
|
621
|
-
declare const queryDefaults: (query: Query | undefined, defaults: Query) => Query;
|
|
622
|
-
//#endregion
|
|
623
680
|
//#region src/utils/zip-data-result/zip-data-result.util.d.ts
|
|
624
681
|
type ZipDataResultOptions = {
|
|
625
682
|
onMismatch?: (context: HookContext) => void;
|
|
@@ -645,5 +702,5 @@ type ZipDataResultItem<D, R> = {
|
|
|
645
702
|
*/
|
|
646
703
|
declare function zipDataResult<H extends HookContext, D extends DataSingleHookContext<H> = DataSingleHookContext<H>, R extends ResultSingleHookContext<H> = ResultSingleHookContext<H>>(context: H, options?: ZipDataResultOptions): ZipDataResultItem<D, R>[];
|
|
647
704
|
//#endregion
|
|
648
|
-
export {
|
|
649
|
-
//# sourceMappingURL=index-
|
|
705
|
+
export { getResultIsArray as A, IsContextOptions as B, patchBatch as C, iterateFind as D, mergeQuery as E, defineHooks as F, addToQuery as H, contextToJson as I, chunkFind as L, getExposedMethods as M, GetDataIsArrayReturn as N, GetResultIsArrayOptions as O, getDataIsArray as P, CheckContextOptions as R, PatchBatchResultItem as S, MergeQueryOptions as T, SkipHookName as U, isContext as V, addSkip as W, replaceResult as _, WalkQueryOptions as a, queryDefaults as b, WaitForServiceEventDefaults as c, waitForServiceEvent as d, transformParams as f, ReplaceResultOptions as g, skipResult as h, WalkQueryCallback as i, getPaginate as j, GetResultIsArrayReturn as k, WaitForServiceEventOptions as l, sortQueryProperties as m, ZipDataResultOptions as n, walkQuery as o, toPaginated as p, zipDataResult as r, ServiceEventName as s, ZipDataResultItem as t, WaitForServiceEventResult as u, replaceData as v, MergeQueryMode as w, PatchBatchOptions as x, queryHasProperty as y, checkContext as z };
|
|
706
|
+
//# sourceMappingURL=index-C6MN6wag.d.mts.map
|
package/dist/index.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ import { a as IffHook, i as skippable, n as ThrowIfOptions, o as iff, r as throw
|
|
|
4
4
|
import { i as transformData, n as transformResult, r as transformQuery, t as TransformResultOptions } from "./transform-result.hook-C9wMLWs2.mjs";
|
|
5
5
|
import { i as resolveData, n as resolveQuery, r as resolveResult, t as resolve } from "./resolve-Cmxskunj.mjs";
|
|
6
6
|
import { CacheEvent, CacheOptions, CheckMultiOptions, CreateRelatedOptions, FindOrCreateOptions, HookSetDataOptions, MuteEventOptions, OnDeleteAction, OnDeleteOptions, ParamsForServerOptions, PreventChangesOptions, RateLimitOptions, SetFieldOptions, SetResultOptions, SoftDeleteOptionFunction, SoftDeleteOptions, StashableOptions, ThrowIfIsIsProviderOptions, ThrowIfIsMultiOptions, TraverseOptions, cache, checkMulti, checkRequired, combine, createRelated, debug, disablePagination, disallow, findOrCreate, muteEvent, onDelete, paramsForServer, paramsFromClient, paramsFromClientOptions, preventChanges, rateLimit, setData, setField, setQueryDefaults, setResult, setSlug, softDelete, stashable, throwIfIsMulti, throwIfIsProvider, traverse } from "./hooks.mjs";
|
|
7
|
-
import { A as
|
|
7
|
+
import { A as getResultIsArray, C as patchBatch, D as iterateFind, E as mergeQuery, F as defineHooks, H as addToQuery, I as contextToJson, L as chunkFind, M as getExposedMethods, N as GetDataIsArrayReturn, O as GetResultIsArrayOptions, P as getDataIsArray, R as CheckContextOptions, S as PatchBatchResultItem, T as MergeQueryOptions, U as SkipHookName, W as addSkip, _ as replaceResult, a as WalkQueryOptions, b as queryDefaults, c as WaitForServiceEventDefaults, d as waitForServiceEvent, f as transformParams, g as ReplaceResultOptions, h as skipResult, i as WalkQueryCallback, j as getPaginate, k as GetResultIsArrayReturn, l as WaitForServiceEventOptions, m as sortQueryProperties, n as ZipDataResultOptions, o as walkQuery, p as toPaginated, r as zipDataResult, s as ServiceEventName, t as ZipDataResultItem, u as WaitForServiceEventResult, v as replaceData, w as MergeQueryMode, x as PatchBatchOptions, y as queryHasProperty, z as checkContext } from "./index-C6MN6wag.mjs";
|
|
8
8
|
import { n as mutateResult, r as mutateData, t as MutateResultOptions } from "./mutate-result.util-DR9JMsvl.mjs";
|
|
9
9
|
import { Paginated, PaginationOptions } from "@feathersjs/feathers";
|
|
10
10
|
|
|
@@ -15,5 +15,5 @@ type PaginatedOrArray<R, P = undefined> = P extends {
|
|
|
15
15
|
paginate: PaginationOptions;
|
|
16
16
|
} ? Paginated<R> : Paginated<R> | R[];
|
|
17
17
|
//#endregion
|
|
18
|
-
export { CacheEvent, CacheOptions, CheckContextOptions, CheckMultiOptions, ContextFunction, ContextFunctionAsync, ContextFunctionSync, CreateRelatedOptions, DataSingleHookContext, DefaultsInput, DispatchOption, FieldKey, FindOrCreateOptions, GetDataIsArrayReturn, GetResultIsArrayOptions, GetResultIsArrayReturn, GetService, HookFunction, HookSetDataOptions, HookType, IffHook, InferCreateData, InferCreateDataFromPath, InferCreateDataSingle, InferCreateDataSingleFromPath, InferCreateResult, InferCreateResultFromPath, InferCreateResultSingle, InferCreateResultSingleFromPath, InferDataFromPath, InferFindParams, InferFindResult, InferFindResultFromPath, InferFindResultSingle, InferGetResult, InferGetResultFromPath, InferPatchData, InferPatchDataFromPath, InferPatchResult, InferPatchResultFromPath, InferRemoveResult, InferRemoveResultFromPath, InferResultFromPath, InferUpdateData, InferUpdateDataFromPath, InferUpdateResult, InferUpdateResultFromPath, MethodName, MutateResultOptions, MuteEventOptions, OnDeleteAction, OnDeleteOptions, PaginatedOrArray, ParamsForServerOptions, PatchBatchOptions, PatchBatchResultItem, PredicateContextAsync, PredicateContextSync, PredicateFn, PredicateItemWithContext, PreventChangesOptions, RateLimitOptions, ReplaceResultOptions, ResultSingleHookContext, ServiceEventName, SetFieldOptions, SetResultOptions, SkipHookName, SoftDeleteOptionFunction, SoftDeleteOptions, StashableOptions, StringFieldKey, ThrowIfIsIsProviderOptions, ThrowIfIsMultiOptions, ThrowIfOptions, TransformParamsFn, TransformResultOptions, TransformerFn, TransformerInputFn, TransportName, TraverseOptions, UnwrapPaginated, UnwrapPaginatedOrArray, WaitForServiceEventDefaults, WaitForServiceEventOptions, WaitForServiceEventResult, WalkQueryCallback, WalkQueryOptions, ZipDataResultItem, ZipDataResultOptions, addSkip, addToQuery, cache, checkContext, checkMulti, checkRequired, chunkFind, combine, contextToJson, createRelated, debug, defineHooks, disablePagination, disallow, findOrCreate, getDataIsArray, getExposedMethods, getPaginate, getResultIsArray, hookTypes, iff, iff as when, iffElse, iterateFind, methodNames, mutateData, mutateResult, muteEvent, onDelete, paramsForServer, paramsFromClient, paramsFromClientOptions, patchBatch, preventChanges, queryDefaults, queryHasProperty, rateLimit, replaceData, replaceResult, resolve, resolveData, resolveQuery, resolveResult, setData, setField, setQueryDefaults, setResult, setSlug, skipResult, skippable, softDelete, sortQueryProperties, stashable, throwIf, throwIfIsMulti, throwIfIsProvider, toPaginated, transformData, transformParams, transformQuery, transformResult, traverse, unless, waitForServiceEvent, walkQuery, zipDataResult };
|
|
18
|
+
export { CacheEvent, CacheOptions, CheckContextOptions, CheckMultiOptions, ContextFunction, ContextFunctionAsync, ContextFunctionSync, CreateRelatedOptions, DataSingleHookContext, DefaultsInput, DispatchOption, FieldKey, FindOrCreateOptions, GetDataIsArrayReturn, GetResultIsArrayOptions, GetResultIsArrayReturn, GetService, HookFunction, HookSetDataOptions, HookType, IffHook, InferCreateData, InferCreateDataFromPath, InferCreateDataSingle, InferCreateDataSingleFromPath, InferCreateResult, InferCreateResultFromPath, InferCreateResultSingle, InferCreateResultSingleFromPath, InferDataFromPath, InferFindParams, InferFindResult, InferFindResultFromPath, InferFindResultSingle, InferGetResult, InferGetResultFromPath, InferPatchData, InferPatchDataFromPath, InferPatchResult, InferPatchResultFromPath, InferRemoveResult, InferRemoveResultFromPath, InferResultFromPath, InferUpdateData, InferUpdateDataFromPath, InferUpdateResult, InferUpdateResultFromPath, MergeQueryMode, MergeQueryOptions, MethodName, MutateResultOptions, MuteEventOptions, OnDeleteAction, OnDeleteOptions, PaginatedOrArray, ParamsForServerOptions, PatchBatchOptions, PatchBatchResultItem, PredicateContextAsync, PredicateContextSync, PredicateFn, PredicateItemWithContext, PreventChangesOptions, RateLimitOptions, ReplaceResultOptions, ResultSingleHookContext, ServiceEventName, SetFieldOptions, SetResultOptions, SkipHookName, SoftDeleteOptionFunction, SoftDeleteOptions, StashableOptions, StringFieldKey, ThrowIfIsIsProviderOptions, ThrowIfIsMultiOptions, ThrowIfOptions, TransformParamsFn, TransformResultOptions, TransformerFn, TransformerInputFn, TransportName, TraverseOptions, UnwrapPaginated, UnwrapPaginatedOrArray, WaitForServiceEventDefaults, WaitForServiceEventOptions, WaitForServiceEventResult, WalkQueryCallback, WalkQueryOptions, ZipDataResultItem, ZipDataResultOptions, addSkip, addToQuery, cache, checkContext, checkMulti, checkRequired, chunkFind, combine, contextToJson, createRelated, debug, defineHooks, disablePagination, disallow, findOrCreate, getDataIsArray, getExposedMethods, getPaginate, getResultIsArray, hookTypes, iff, iff as when, iffElse, iterateFind, mergeQuery, methodNames, mutateData, mutateResult, muteEvent, onDelete, paramsForServer, paramsFromClient, paramsFromClientOptions, patchBatch, preventChanges, queryDefaults, queryHasProperty, rateLimit, replaceData, replaceResult, resolve, resolveData, resolveQuery, resolveResult, setData, setField, setQueryDefaults, setResult, setSlug, skipResult, skippable, softDelete, sortQueryProperties, stashable, throwIf, throwIfIsMulti, throwIfIsProvider, toPaginated, transformData, transformParams, transformQuery, transformResult, traverse, unless, waitForServiceEvent, walkQuery, zipDataResult };
|
|
19
19
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { _ as combine, a as iffElse, f as getPaginate, i as iff, n as
|
|
2
|
-
import { _ as
|
|
3
|
-
import { C as checkMulti, S as checkRequired, _ as
|
|
4
|
-
import { a as getResultIsArray, i as replaceData, n as replaceResult, o as getDataIsArray, r as mutateData, t as mutateResult } from "./mutate-result.util-
|
|
5
|
-
import { n as transformQuery, r as transformData, t as transformResult } from "./transform-result.hook-
|
|
6
|
-
import { i as resolveData, n as resolveQuery, r as resolveResult, t as resolve } from "./resolve-
|
|
1
|
+
import { _ as combine, a as iffElse, f as getPaginate, i as iff, n as throwIf, r as skippable, t as unless } from "./predicates-NOnUyMic.mjs";
|
|
2
|
+
import { _ as addToQuery, a as skipResult, c as walkQuery, d as iterateFind, f as getExposedMethods, g as checkContext, h as chunkFind, i as toPaginated, l as patchBatch, m as contextToJson, n as waitForServiceEvent, o as queryDefaults, p as defineHooks, r as transformParams, s as queryHasProperty, t as zipDataResult, u as mergeQuery, v as addSkip, y as sortQueryProperties } from "./utils-DByCpAsf.mjs";
|
|
3
|
+
import { C as checkMulti, S as checkRequired, _ as findOrCreate, a as softDelete, b as debug, c as setQueryDefaults, d as rateLimit, f as preventChanges, g as muteEvent, h as onDelete, i as stashable, l as setField, m as paramsForServer, n as throwIfIsProvider, o as setSlug, p as paramsFromClient, r as throwIfIsMulti, s as setResult, t as traverse, u as setData, v as disallow, w as cache, x as createRelated, y as disablePagination } from "./hooks-DpFQfcFa.mjs";
|
|
4
|
+
import { a as getResultIsArray, i as replaceData, n as replaceResult, o as getDataIsArray, r as mutateData, t as mutateResult } from "./mutate-result.util-C0nY6L7i.mjs";
|
|
5
|
+
import { n as transformQuery, r as transformData, t as transformResult } from "./transform-result.hook-V2QYN2K0.mjs";
|
|
6
|
+
import { i as resolveData, n as resolveQuery, r as resolveResult, t as resolve } from "./resolve-BflgIVD8.mjs";
|
|
7
7
|
//#region src/types.ts
|
|
8
8
|
const hookTypes = [
|
|
9
9
|
"around",
|
|
@@ -20,6 +20,6 @@ const methodNames = [
|
|
|
20
20
|
"remove"
|
|
21
21
|
];
|
|
22
22
|
//#endregion
|
|
23
|
-
export { addSkip, addToQuery, cache, checkContext, checkMulti, checkRequired, chunkFind, combine, contextToJson, createRelated, debug, defineHooks, disablePagination, disallow, findOrCreate, getDataIsArray, getExposedMethods, getPaginate, getResultIsArray, hookTypes, iff, iff as when, iffElse, iterateFind, methodNames, mutateData, mutateResult, muteEvent, onDelete, paramsForServer, paramsFromClient, patchBatch, preventChanges, queryDefaults, queryHasProperty, rateLimit, replaceData, replaceResult, resolve, resolveData, resolveQuery, resolveResult, setData, setField, setQueryDefaults, setResult, setSlug, skipResult, skippable, softDelete, sortQueryProperties, stashable, throwIf, throwIfIsMulti, throwIfIsProvider, toPaginated, transformData, transformParams, transformQuery, transformResult, traverse, unless, waitForServiceEvent, walkQuery, zipDataResult };
|
|
23
|
+
export { addSkip, addToQuery, cache, checkContext, checkMulti, checkRequired, chunkFind, combine, contextToJson, createRelated, debug, defineHooks, disablePagination, disallow, findOrCreate, getDataIsArray, getExposedMethods, getPaginate, getResultIsArray, hookTypes, iff, iff as when, iffElse, iterateFind, mergeQuery, methodNames, mutateData, mutateResult, muteEvent, onDelete, paramsForServer, paramsFromClient, patchBatch, preventChanges, queryDefaults, queryHasProperty, rateLimit, replaceData, replaceResult, resolve, resolveData, resolveQuery, resolveResult, setData, setField, setQueryDefaults, setResult, setSlug, skipResult, skippable, softDelete, sortQueryProperties, stashable, throwIf, throwIfIsMulti, throwIfIsProvider, toPaginated, transformData, transformParams, transformQuery, transformResult, traverse, unless, waitForServiceEvent, walkQuery, zipDataResult };
|
|
24
24
|
|
|
25
25
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -15,6 +15,20 @@ function traverse(items, converter) {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
//#endregion
|
|
18
|
+
//#region src/common/is-empty-object.ts
|
|
19
|
+
/**
|
|
20
|
+
* Returns `true` only for a plain empty object (`{}`). Arrays, `null`, primitives
|
|
21
|
+
* and non-empty objects are all `false`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* isEmptyObject({}) // => true
|
|
26
|
+
* isEmptyObject({ a: 1 }) // => false
|
|
27
|
+
* isEmptyObject([]) // => false
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
const isEmptyObject = (obj) => !!obj && typeof obj === "object" && !Array.isArray(obj) && Object.keys(obj).length === 0;
|
|
31
|
+
//#endregion
|
|
18
32
|
//#region src/common/index.ts
|
|
19
33
|
/**
|
|
20
34
|
* Type guard that checks if a value is a `Promise` instance.
|
|
@@ -50,6 +64,6 @@ const early = (context, next) => {
|
|
|
50
64
|
if (next) return next(context);
|
|
51
65
|
};
|
|
52
66
|
//#endregion
|
|
53
|
-
export {
|
|
67
|
+
export { isEmptyObject as a, isPromise as i, hasOwnProperty as n, traverse as o, toArray as r, early as t };
|
|
54
68
|
|
|
55
|
-
//# sourceMappingURL=internal.utils-
|
|
69
|
+
//# sourceMappingURL=internal.utils-BBB-b6Ud.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.utils-BBB-b6Ud.mjs","names":[],"sources":["../src/common/traverse.ts","../src/common/is-empty-object.ts","../src/common/index.ts","../src/internal.utils.ts"],"sourcesContent":["import _traverse from 'neotraverse'\n\n/**\n * Recursively traverses items (or an array of items) and applies a converter function\n * to every node using `neotraverse`. Modifications happen in place.\n *\n * @example\n * ```ts\n * traverse(items, function () { if (this.key === 'secret') this.remove() })\n * ```\n */\nexport function traverse<T extends Record<string, any>>(\n items: T | T[],\n converter: (item: T) => void,\n) {\n ;(Array.isArray(items) ? items : [items]).forEach((item) => {\n _traverse(item).forEach(converter) // replacement is in place\n })\n}\n","/**\n * Returns `true` only for a plain empty object (`{}`). Arrays, `null`, primitives\n * and non-empty objects are all `false`.\n *\n * @example\n * ```ts\n * isEmptyObject({}) // => true\n * isEmptyObject({ a: 1 }) // => false\n * isEmptyObject([]) // => false\n * ```\n */\nexport const isEmptyObject = (obj: unknown): boolean =>\n !!obj &&\n typeof obj === 'object' &&\n !Array.isArray(obj) &&\n Object.keys(obj).length === 0\n\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest\n\n describe('isEmptyObject', () => {\n it('is true only for a plain empty object', () => {\n expect(isEmptyObject({})).toBe(true)\n })\n\n it('is false for a non-empty object', () => {\n expect(isEmptyObject({ a: 1 })).toBe(false)\n })\n\n it('is false for arrays, null, undefined and primitives', () => {\n expect(isEmptyObject([])).toBe(false)\n expect(isEmptyObject(null)).toBe(false)\n expect(isEmptyObject(undefined)).toBe(false)\n expect(isEmptyObject('')).toBe(false)\n expect(isEmptyObject(0)).toBe(false)\n })\n })\n}\n","/**\n * Type guard that checks if a value is a `Promise` instance.\n *\n * @example\n * ```ts\n * const result = maybeSyncFn()\n * if (isPromise(result)) {\n * await result\n * }\n * ```\n */\nexport function isPromise(p: any): p is Promise<any> {\n return p instanceof Promise\n}\n\nexport { traverse } from './traverse.js'\nexport { clone } from './clone.js'\nexport { isEmptyObject } from './is-empty-object.js'\n","import type { HookContext } from '@feathersjs/feathers'\n\nexport const hasOwnProperty = (\n obj: Record<string, unknown>,\n ...keys: string[]\n): boolean => {\n return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x))\n}\n\nexport type MaybeArray<T> = T | readonly T[]\nexport type UnpackMaybeArray<T> = T extends readonly (infer E)[] ? E : T\n/**\n * Normalizes a value or array into an array. The returned array MUST be treated\n * as read-only — when the input is already an array it is returned as-is (no copy)\n * to avoid a per-call allocation on hook hot paths.\n */\nexport const toArray = <T>(value: T | readonly T[]): T[] =>\n Array.isArray(value) ? (value as T[]) : [value as T]\n\nexport type Promisable<T> = T | Promise<T>\nexport type KeyOf<T> = Extract<keyof T, string>\n\nexport type UnwrapArray<T> = T extends Array<infer U> ? U : T\n\nexport type IsAny<T> = 0 extends 1 & T ? true : false\n\nexport type AnyFallback<T, Fallback> = IsAny<T> extends true ? Fallback : T\n\nexport type NeverFallback<Never, Fallback> = [Never] extends [never]\n ? Fallback\n : Never\n\nexport type KeyOfOrDotNotation<D> = KeyOf<D> | `${KeyOf<D>}.${string}`\n\n/**+\n * Can be used to early return a hook.\n *\n * If it's an around hook, it will call `next` if provided.\n */\nexport const early = <H extends HookContext>(\n context: H,\n next?: (context: H) => Promisable<void>,\n): Promisable<void> => {\n if (next) {\n return next(context)\n }\n return\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,SACd,OACA,WACA;CACC,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK,EAAA,CAAG,SAAS,SAAS;EAC1D,UAAU,IAAI,CAAC,CAAC,QAAQ,SAAS;CACnC,CAAC;AACH;;;;;;;;;;;;;;ACPA,MAAa,iBAAiB,QAC5B,CAAC,CAAC,OACF,OAAO,QAAQ,YACf,CAAC,MAAM,QAAQ,GAAG,KAClB,OAAO,KAAK,GAAG,CAAC,CAAC,WAAW;;;;;;;;;;;;;;ACJ9B,SAAgB,UAAU,GAA2B;CACnD,OAAO,aAAa;AACtB;;;ACXA,MAAa,kBACX,KACA,GAAG,SACS;CACZ,OAAO,KAAK,MAAM,MAAM,OAAO,UAAU,eAAe,KAAK,KAAK,CAAC,CAAC;AACtE;;;;;;AASA,MAAa,WAAc,UACzB,MAAM,QAAQ,KAAK,IAAK,QAAgB,CAAC,KAAU;;;;;;AAsBrD,MAAa,SACX,SACA,SACqB;CACrB,IAAI,MACF,OAAO,KAAK,OAAO;AAGvB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as isPromise } from "./internal.utils-
|
|
1
|
+
import { i as isPromise } from "./internal.utils-BBB-b6Ud.mjs";
|
|
2
2
|
import { copy } from "fast-copy";
|
|
3
3
|
//#region src/utils/get-data-is-array/get-data-is-array.util.ts
|
|
4
4
|
/**
|
|
@@ -220,4 +220,4 @@ function mutateResult(context, transformer, options) {
|
|
|
220
220
|
//#endregion
|
|
221
221
|
export { getResultIsArray as a, replaceData as i, replaceResult as n, getDataIsArray as o, mutateData as r, mutateResult as t };
|
|
222
222
|
|
|
223
|
-
//# sourceMappingURL=mutate-result.util-
|
|
223
|
+
//# sourceMappingURL=mutate-result.util-C0nY6L7i.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutate-result.util-Dqzepn1M.mjs","names":[],"sources":["../src/utils/get-data-is-array/get-data-is-array.util.ts","../src/utils/get-result-is-array/get-result-is-array.util.ts","../src/utils/replace-data/replace-data.util.ts","../src/utils/mutate-data/mutate-data.util.ts","../src/utils/replace-result/replace-result.util.ts","../src/utils/mutate-result/mutate-result.util.ts"],"sourcesContent":["import type { HookContext } from '@feathersjs/feathers'\nimport type { DataSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport type GetDataIsArrayReturn<H extends HookContext = HookContext> = {\n isArray: boolean\n data: DataSingleHookContext<H>[]\n}\n\n/**\n * Normalizes `context.data` into an array for uniform processing.\n * Returns `{ data, isArray }` where `data` is always an array and `isArray` indicates\n * whether the original value was already an array.\n *\n * @example\n * ```ts\n * import { getDataIsArray } from 'feathers-utils/utils'\n *\n * const { data, isArray } = getDataIsArray(context)\n * data.forEach(item => { /* process each item *\\/ })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/get-data-is-array.html\n */\nexport function getDataIsArray<H extends HookContext = HookContext>(\n context: H,\n): GetDataIsArrayReturn<H> {\n if (!context.data) {\n return {\n isArray: false,\n data: [],\n }\n }\n\n const isArray = Array.isArray(context.data)\n\n return {\n isArray,\n data: isArray ? context.data : [context.data],\n }\n}\n","import type { HookContext } from '@feathersjs/feathers'\nimport { copy } from 'fast-copy'\nimport type { ResultSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport type GetResultIsArrayOptions = {\n dispatch?: boolean\n}\n\nexport type GetResultIsArrayReturn<H extends HookContext = HookContext> = {\n isArray: boolean\n result: ResultSingleHookContext<H>[]\n key: 'dispatch' | 'result'\n}\n\n/**\n * Normalizes `context.result` (or `context.dispatch`) into an array for uniform processing.\n * Handles paginated results by extracting the `data` array. Returns `{ result, isArray, key }`\n * where `key` indicates whether `'result'` or `'dispatch'` was used.\n *\n * @example\n * ```ts\n * import { getResultIsArray } from 'feathers-utils/utils'\n *\n * const { result, isArray } = getResultIsArray(context)\n * result.forEach(item => { /* process each item *\\/ })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/get-result-is-array.html\n */\nexport function getResultIsArray<H extends HookContext = HookContext>(\n context: H,\n options?: GetResultIsArrayOptions,\n): GetResultIsArrayReturn<H> {\n const { dispatch = false } = options || {}\n\n const isDispatch: boolean = dispatch && context.dispatch !== undefined\n\n const result = dispatch\n ? isDispatch\n ? context.dispatch\n : copy(context.result)\n : context.result\n\n if (!result) {\n return {\n isArray: false,\n result: [],\n key: isDispatch ? 'dispatch' : 'result',\n }\n }\n\n const items = context.method === 'find' ? result.data || result : result\n\n const isArray = Array.isArray(items)\n\n return {\n isArray,\n result: isArray ? items : items ? [items] : [],\n key: isDispatch ? 'dispatch' : 'result',\n }\n}\n","import type { HookContext } from \"@feathersjs/feathers\";\nimport type { DataSingleHookContext } from \"../../utility-types/hook-context.js\";\n\n/**\n * Replaces `context.data` wholesale with the given items, preserving the original\n * single-vs-array shape. This is the explicit inverse of `getDataIsArray`: get the\n * data as an array, modify or replace the items, then write them back.\n *\n * @example\n * ```ts\n * import { getDataIsArray, replaceData } from 'feathers-utils/utils'\n *\n * const { data } = getDataIsArray(context)\n * const next = data.map((item) => ({ ...item, slug: slugify(item.name) }))\n * replaceData(context, next)\n * ```\n *\n * @see https://utils.feathersjs.com/utils/replace-data.html\n */\nexport function replaceData<H extends HookContext = HookContext>(\n context: H,\n data: DataSingleHookContext<H>[],\n): H {\n context.data = Array.isArray(context.data) ? data : data[0];\n return context;\n}\n","import type { HookContext } from '@feathersjs/feathers'\nimport { getDataIsArray } from '../get-data-is-array/get-data-is-array.util.js'\nimport { replaceData } from '../replace-data/replace-data.util.js'\nimport { isPromise } from '../../common/index.js'\nimport type { Promisable } from '../../internal.utils.js'\nimport type { TransformerInputFn } from '../../types.js'\n\n/**\n * Applies a transformer function to each item in `context.data`, updating it in place.\n * If the transformer returns a new object, it replaces the original item.\n * Correctly handles both single-item and array data, preserving the original shape.\n *\n * @example\n * ```ts\n * import { mutateData } from 'feathers-utils/utils'\n *\n * await mutateData(context, (item) => { item.name = item.name.trim() })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/mutate-data.html\n */\nexport function mutateData<H extends HookContext = HookContext>(\n context: H,\n transformer: TransformerInputFn<any, H>,\n): Promisable<H> {\n if (!context.data) {\n return context\n }\n\n // single-item fast path: avoid allocating a wrapper array + a mapped array\n // for the common single create/update/patch case.\n if (!Array.isArray(context.data)) {\n const item = context.data\n const result = transformer(item, { context, i: 0 })\n\n if (isPromise(result)) {\n return result.then((res: any) => {\n context.data = res ?? item\n return context\n })\n }\n\n context.data = result ?? item\n return context\n }\n\n const { data } = getDataIsArray(context)\n\n if (!data.length) {\n return context\n }\n\n let hasPromises = false\n\n const results = data.map((item, i) => {\n const result = transformer(item, { context, i })\n\n if (isPromise(result)) {\n hasPromises = true\n return result.then((res: any) => res ?? item)\n }\n\n return result ?? item\n })\n\n function mutate(data: any) {\n // delegate the array writeback (single is handled by the fast path above)\n return replaceData(context, data)\n }\n\n if (hasPromises) {\n return Promise.all(results).then(mutate)\n } else {\n return mutate(results)\n }\n}\n","import type { HookContext } from \"@feathersjs/feathers\";\nimport { copy } from \"fast-copy\";\nimport { getResultIsArray } from \"../get-result-is-array/get-result-is-array.util.js\";\nimport type { DispatchOption } from \"../../types.js\";\nimport type { ResultSingleHookContext } from \"../../utility-types/hook-context.js\";\n\nexport type ReplaceResultOptions = {\n /**\n * Also (or only) write to `context.dispatch`. `true` writes dispatch, `'both'`\n * writes both `result` and `dispatch`. When dispatch is requested and not yet\n * present, it is seeded from a clone of `context.result`.\n */\n dispatch?: DispatchOption;\n};\n\n/**\n * Replaces `context.result` (and/or `context.dispatch`) wholesale with the given\n * items, preserving the original shape: single item, array, or paginated `{ data }`.\n * This is the explicit inverse of `getResultIsArray`.\n *\n * @example\n * ```ts\n * import { getResultIsArray, replaceResult } from 'feathers-utils/utils'\n *\n * const { result } = getResultIsArray(context)\n * replaceResult(context, result.filter((item) => item.public))\n * ```\n *\n * @see https://utils.feathersjs.com/utils/replace-result.html\n */\nexport function replaceResult<H extends HookContext = HookContext>(\n context: H,\n result: ResultSingleHookContext<H>[],\n options?: ReplaceResultOptions,\n): H {\n if (!!options?.dispatch && !context.dispatch) {\n context.dispatch = copy(context.result);\n }\n\n const write = (dispatch: boolean) => {\n const { isArray, key } = getResultIsArray(context, { dispatch });\n\n if (!isArray) {\n context[key] = result[0];\n } else if (!Array.isArray(context[key]) && context[key]?.data) {\n context[key].data = result;\n } else {\n context[key] = result;\n }\n };\n\n if (options?.dispatch === \"both\") {\n write(true);\n write(false);\n } else {\n write(!!options?.dispatch);\n }\n\n return context;\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { getResultIsArray } from '../get-result-is-array/get-result-is-array.util.js'\nimport { replaceResult } from '../replace-result/replace-result.util.js'\nimport { isPromise } from '../../common/index.js'\nimport { copy } from 'fast-copy'\nimport type { Promisable } from '../../internal.utils.js'\nimport type { DispatchOption, TransformerInputFn } from '../../types.js'\n\nexport type MutateResultOptions = {\n next?: NextFunction\n transform?: (items: any[]) => any[]\n dispatch?: DispatchOption\n}\n\n/**\n * Applies a transformer function to each item in `context.result` (and optionally `context.dispatch`).\n * Handles paginated results, single items, and arrays transparently.\n * Use the `dispatch` option to control whether result, dispatch, or both are transformed.\n *\n * @example\n * ```ts\n * import { mutateResult } from 'feathers-utils/utils'\n *\n * await mutateResult(context, (item) => { delete item.password })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/mutate-result.html\n */\nexport function mutateResult<H extends HookContext = HookContext>(\n context: H,\n transformer: TransformerInputFn<any, H>,\n options?: MutateResultOptions,\n): Promisable<H> {\n if (!!options?.dispatch && !context.dispatch) {\n context.dispatch = copy(context.result)\n }\n\n function forResult(dispatch: boolean): Promisable<H> {\n const { result } = getResultIsArray(context, { dispatch })\n\n if (!result.length) {\n return context\n }\n\n let hasPromises = false\n\n const results = result.map((item, i) => {\n const result = transformer(item, { context, i })\n\n if (isPromise(result)) {\n hasPromises = true\n return result.then((res: any) => res ?? item)\n }\n\n return result ?? item\n })\n\n function mutate(r: any) {\n if (options?.transform) {\n r = options.transform(r)\n }\n\n // delegate the single/array/paginated writeback to replaceResult\n return replaceResult(context, r, { dispatch })\n }\n\n if (hasPromises) {\n return Promise.all(results).then(mutate)\n } else {\n return mutate(results)\n }\n }\n\n function run(): Promisable<H> {\n if (options?.dispatch === 'both') {\n const a = forResult(true)\n const b = forResult(false)\n\n if (isPromise(a) || isPromise(b)) {\n return Promise.all([a, b]).then(() => context)\n }\n\n return context\n }\n\n return forResult(options?.dispatch ?? false)\n }\n\n if (options?.next) {\n return options.next().then(run)\n }\n\n return run()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mutate-result.util-C0nY6L7i.mjs","names":[],"sources":["../src/utils/get-data-is-array/get-data-is-array.util.ts","../src/utils/get-result-is-array/get-result-is-array.util.ts","../src/utils/replace-data/replace-data.util.ts","../src/utils/mutate-data/mutate-data.util.ts","../src/utils/replace-result/replace-result.util.ts","../src/utils/mutate-result/mutate-result.util.ts"],"sourcesContent":["import type { HookContext } from '@feathersjs/feathers'\nimport type { DataSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport type GetDataIsArrayReturn<H extends HookContext = HookContext> = {\n isArray: boolean\n data: DataSingleHookContext<H>[]\n}\n\n/**\n * Normalizes `context.data` into an array for uniform processing.\n * Returns `{ data, isArray }` where `data` is always an array and `isArray` indicates\n * whether the original value was already an array.\n *\n * @example\n * ```ts\n * import { getDataIsArray } from 'feathers-utils/utils'\n *\n * const { data, isArray } = getDataIsArray(context)\n * data.forEach(item => { /* process each item *\\/ })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/get-data-is-array.html\n */\nexport function getDataIsArray<H extends HookContext = HookContext>(\n context: H,\n): GetDataIsArrayReturn<H> {\n if (!context.data) {\n return {\n isArray: false,\n data: [],\n }\n }\n\n const isArray = Array.isArray(context.data)\n\n return {\n isArray,\n data: isArray ? context.data : [context.data],\n }\n}\n","import type { HookContext } from '@feathersjs/feathers'\nimport { copy } from 'fast-copy'\nimport type { ResultSingleHookContext } from '../../utility-types/hook-context.js'\n\nexport type GetResultIsArrayOptions = {\n dispatch?: boolean\n}\n\nexport type GetResultIsArrayReturn<H extends HookContext = HookContext> = {\n isArray: boolean\n result: ResultSingleHookContext<H>[]\n key: 'dispatch' | 'result'\n}\n\n/**\n * Normalizes `context.result` (or `context.dispatch`) into an array for uniform processing.\n * Handles paginated results by extracting the `data` array. Returns `{ result, isArray, key }`\n * where `key` indicates whether `'result'` or `'dispatch'` was used.\n *\n * @example\n * ```ts\n * import { getResultIsArray } from 'feathers-utils/utils'\n *\n * const { result, isArray } = getResultIsArray(context)\n * result.forEach(item => { /* process each item *\\/ })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/get-result-is-array.html\n */\nexport function getResultIsArray<H extends HookContext = HookContext>(\n context: H,\n options?: GetResultIsArrayOptions,\n): GetResultIsArrayReturn<H> {\n const { dispatch = false } = options || {}\n\n const isDispatch: boolean = dispatch && context.dispatch !== undefined\n\n const result = dispatch\n ? isDispatch\n ? context.dispatch\n : copy(context.result)\n : context.result\n\n if (!result) {\n return {\n isArray: false,\n result: [],\n key: isDispatch ? 'dispatch' : 'result',\n }\n }\n\n const items = context.method === 'find' ? result.data || result : result\n\n const isArray = Array.isArray(items)\n\n return {\n isArray,\n result: isArray ? items : items ? [items] : [],\n key: isDispatch ? 'dispatch' : 'result',\n }\n}\n","import type { HookContext } from \"@feathersjs/feathers\";\nimport type { DataSingleHookContext } from \"../../utility-types/hook-context.js\";\n\n/**\n * Replaces `context.data` wholesale with the given items, preserving the original\n * single-vs-array shape. This is the explicit inverse of `getDataIsArray`: get the\n * data as an array, modify or replace the items, then write them back.\n *\n * @example\n * ```ts\n * import { getDataIsArray, replaceData } from 'feathers-utils/utils'\n *\n * const { data } = getDataIsArray(context)\n * const next = data.map((item) => ({ ...item, slug: slugify(item.name) }))\n * replaceData(context, next)\n * ```\n *\n * @see https://utils.feathersjs.com/utils/replace-data.html\n */\nexport function replaceData<H extends HookContext = HookContext>(\n context: H,\n data: DataSingleHookContext<H>[],\n): H {\n context.data = Array.isArray(context.data) ? data : data[0];\n return context;\n}\n","import type { HookContext } from '@feathersjs/feathers'\nimport { getDataIsArray } from '../get-data-is-array/get-data-is-array.util.js'\nimport { replaceData } from '../replace-data/replace-data.util.js'\nimport { isPromise } from '../../common/index.js'\nimport type { Promisable } from '../../internal.utils.js'\nimport type { TransformerInputFn } from '../../types.js'\n\n/**\n * Applies a transformer function to each item in `context.data`, updating it in place.\n * If the transformer returns a new object, it replaces the original item.\n * Correctly handles both single-item and array data, preserving the original shape.\n *\n * @example\n * ```ts\n * import { mutateData } from 'feathers-utils/utils'\n *\n * await mutateData(context, (item) => { item.name = item.name.trim() })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/mutate-data.html\n */\nexport function mutateData<H extends HookContext = HookContext>(\n context: H,\n transformer: TransformerInputFn<any, H>,\n): Promisable<H> {\n if (!context.data) {\n return context\n }\n\n // single-item fast path: avoid allocating a wrapper array + a mapped array\n // for the common single create/update/patch case.\n if (!Array.isArray(context.data)) {\n const item = context.data\n const result = transformer(item, { context, i: 0 })\n\n if (isPromise(result)) {\n return result.then((res: any) => {\n context.data = res ?? item\n return context\n })\n }\n\n context.data = result ?? item\n return context\n }\n\n const { data } = getDataIsArray(context)\n\n if (!data.length) {\n return context\n }\n\n let hasPromises = false\n\n const results = data.map((item, i) => {\n const result = transformer(item, { context, i })\n\n if (isPromise(result)) {\n hasPromises = true\n return result.then((res: any) => res ?? item)\n }\n\n return result ?? item\n })\n\n function mutate(data: any) {\n // delegate the array writeback (single is handled by the fast path above)\n return replaceData(context, data)\n }\n\n if (hasPromises) {\n return Promise.all(results).then(mutate)\n } else {\n return mutate(results)\n }\n}\n","import type { HookContext } from \"@feathersjs/feathers\";\nimport { copy } from \"fast-copy\";\nimport { getResultIsArray } from \"../get-result-is-array/get-result-is-array.util.js\";\nimport type { DispatchOption } from \"../../types.js\";\nimport type { ResultSingleHookContext } from \"../../utility-types/hook-context.js\";\n\nexport type ReplaceResultOptions = {\n /**\n * Also (or only) write to `context.dispatch`. `true` writes dispatch, `'both'`\n * writes both `result` and `dispatch`. When dispatch is requested and not yet\n * present, it is seeded from a clone of `context.result`.\n */\n dispatch?: DispatchOption;\n};\n\n/**\n * Replaces `context.result` (and/or `context.dispatch`) wholesale with the given\n * items, preserving the original shape: single item, array, or paginated `{ data }`.\n * This is the explicit inverse of `getResultIsArray`.\n *\n * @example\n * ```ts\n * import { getResultIsArray, replaceResult } from 'feathers-utils/utils'\n *\n * const { result } = getResultIsArray(context)\n * replaceResult(context, result.filter((item) => item.public))\n * ```\n *\n * @see https://utils.feathersjs.com/utils/replace-result.html\n */\nexport function replaceResult<H extends HookContext = HookContext>(\n context: H,\n result: ResultSingleHookContext<H>[],\n options?: ReplaceResultOptions,\n): H {\n if (!!options?.dispatch && !context.dispatch) {\n context.dispatch = copy(context.result);\n }\n\n const write = (dispatch: boolean) => {\n const { isArray, key } = getResultIsArray(context, { dispatch });\n\n if (!isArray) {\n context[key] = result[0];\n } else if (!Array.isArray(context[key]) && context[key]?.data) {\n context[key].data = result;\n } else {\n context[key] = result;\n }\n };\n\n if (options?.dispatch === \"both\") {\n write(true);\n write(false);\n } else {\n write(!!options?.dispatch);\n }\n\n return context;\n}\n","import type { HookContext, NextFunction } from '@feathersjs/feathers'\nimport { getResultIsArray } from '../get-result-is-array/get-result-is-array.util.js'\nimport { replaceResult } from '../replace-result/replace-result.util.js'\nimport { isPromise } from '../../common/index.js'\nimport { copy } from 'fast-copy'\nimport type { Promisable } from '../../internal.utils.js'\nimport type { DispatchOption, TransformerInputFn } from '../../types.js'\n\nexport type MutateResultOptions = {\n next?: NextFunction\n transform?: (items: any[]) => any[]\n dispatch?: DispatchOption\n}\n\n/**\n * Applies a transformer function to each item in `context.result` (and optionally `context.dispatch`).\n * Handles paginated results, single items, and arrays transparently.\n * Use the `dispatch` option to control whether result, dispatch, or both are transformed.\n *\n * @example\n * ```ts\n * import { mutateResult } from 'feathers-utils/utils'\n *\n * await mutateResult(context, (item) => { delete item.password })\n * ```\n *\n * @see https://utils.feathersjs.com/utils/mutate-result.html\n */\nexport function mutateResult<H extends HookContext = HookContext>(\n context: H,\n transformer: TransformerInputFn<any, H>,\n options?: MutateResultOptions,\n): Promisable<H> {\n if (!!options?.dispatch && !context.dispatch) {\n context.dispatch = copy(context.result)\n }\n\n function forResult(dispatch: boolean): Promisable<H> {\n const { result } = getResultIsArray(context, { dispatch })\n\n if (!result.length) {\n return context\n }\n\n let hasPromises = false\n\n const results = result.map((item, i) => {\n const result = transformer(item, { context, i })\n\n if (isPromise(result)) {\n hasPromises = true\n return result.then((res: any) => res ?? item)\n }\n\n return result ?? item\n })\n\n function mutate(r: any) {\n if (options?.transform) {\n r = options.transform(r)\n }\n\n // delegate the single/array/paginated writeback to replaceResult\n return replaceResult(context, r, { dispatch })\n }\n\n if (hasPromises) {\n return Promise.all(results).then(mutate)\n } else {\n return mutate(results)\n }\n }\n\n function run(): Promisable<H> {\n if (options?.dispatch === 'both') {\n const a = forResult(true)\n const b = forResult(false)\n\n if (isPromise(a) || isPromise(b)) {\n return Promise.all([a, b]).then(() => context)\n }\n\n return context\n }\n\n return forResult(options?.dispatch ?? false)\n }\n\n if (options?.next) {\n return options.next().then(run)\n }\n\n return run()\n}\n"],"mappings":"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"}
|