coll-fns 1.0.0 → 1.1.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/README.md +361 -80
- package/dist/coll-fns.cjs +1 -1
- package/dist/coll-fns.cjs.map +1 -1
- package/dist/coll-fns.mjs +1 -1
- package/dist/coll-fns.mjs.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
# coll-fns
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Work with MongoDB collections using declarative joins and reusable hooks—fetch related docs without boilerplate and keep cross-collection logic in one place.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Skip the repetitive glue code for joining collections and wiring related data. Define your relationships once, then ask for only the fields you need in a nested tree at query time. You keep flexibility (less denormalization needed) while still fetching children efficiently—often better than ad-hoc code copied across endpoints.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Hooks let you centralize cross-collection side effects and validations (e.g., propagate changes, enforce rules) so you don't repeat that logic in every mutation path.
|
|
10
|
+
|
|
11
|
+
**Works identically on Meteor server (async) and client (sync)** with the same code, and supports any MongoDB-compatible backend you plug in.
|
|
10
12
|
|
|
11
13
|
## Key Features
|
|
12
14
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
15
|
+
- **Powerful Join System**: Define relationships between collections with automatic field resolution and nested joins
|
|
16
|
+
- **Extensible Hooks**: React to CRUD operations with before/after hooks for validation, transformation, and side effects
|
|
17
|
+
- **Isomorphic by Design**: Write once, run anywhere - same API for client-side (sync) and server-side (async) code
|
|
18
|
+
- **Protocol-based Architecture**: Switch between different database backends seamlessly
|
|
19
|
+
- **Advanced Field Projections**: Support for nested fields, dot notation, and MongoDB-style projections
|
|
20
|
+
- **Promise/async Support**: Works with both synchronous and asynchronous protocols
|
|
21
|
+
- **TypeScript-ready**: Includes JSDoc types for better IDE support
|
|
20
22
|
|
|
21
23
|
## Installation
|
|
22
24
|
|
|
@@ -34,6 +36,7 @@ import {
|
|
|
34
36
|
update,
|
|
35
37
|
remove,
|
|
36
38
|
count,
|
|
39
|
+
join,
|
|
37
40
|
protocols,
|
|
38
41
|
} from "coll-fns";
|
|
39
42
|
|
|
@@ -46,12 +49,75 @@ await insert(UsersCollection, { name: "Alice", age: 25 });
|
|
|
46
49
|
await update(UsersCollection, { name: "Alice" }, { $set: { age: 26 } });
|
|
47
50
|
const total = await count(UsersCollection, {});
|
|
48
51
|
await remove(UsersCollection, { name: "Alice" });
|
|
52
|
+
|
|
53
|
+
// Define a join to fetch authors with posts
|
|
54
|
+
join(PostsCollection, {
|
|
55
|
+
author: {
|
|
56
|
+
Coll: UsersCollection,
|
|
57
|
+
on: ["authorId", "_id"],
|
|
58
|
+
single: true,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Use the join in a fetch
|
|
63
|
+
const posts = await fetchList(
|
|
64
|
+
PostsCollection,
|
|
65
|
+
{},
|
|
66
|
+
{
|
|
67
|
+
fields: {
|
|
68
|
+
title: 1,
|
|
69
|
+
content: 1,
|
|
70
|
+
"+": { author: 1 },
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
// Result: Each post includes its author's name and email
|
|
49
75
|
```
|
|
50
76
|
|
|
51
77
|
## Joins: The Power Feature
|
|
52
78
|
|
|
53
79
|
One of the most powerful features of `coll-fns` is its ability to define declarative joins between collections, eliminating the need for manual data fetching and aggregation.
|
|
54
80
|
|
|
81
|
+
Joins must be **pre-registered globally** for a collection using the `join()` function. Once defined, they're available for all fetch operations on that collection.
|
|
82
|
+
|
|
83
|
+
### Defining and Using Joins
|
|
84
|
+
|
|
85
|
+
Register joins once (typically during initialization) and reference them in fetch calls:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { join, fetchList } from "coll-fns";
|
|
89
|
+
|
|
90
|
+
// Define joins globally for a collection (usually in initialization code)
|
|
91
|
+
join(PostsCollection, {
|
|
92
|
+
author: {
|
|
93
|
+
Coll: UsersCollection,
|
|
94
|
+
on: ["authorId", "_id"],
|
|
95
|
+
single: true,
|
|
96
|
+
},
|
|
97
|
+
comments: {
|
|
98
|
+
Coll: CommentsCollection,
|
|
99
|
+
on: ["_id", "postId"],
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Now use fetch without re-specifying the join definitions
|
|
104
|
+
const posts = await fetchList(
|
|
105
|
+
PostsCollection,
|
|
106
|
+
{ status: "published" },
|
|
107
|
+
{
|
|
108
|
+
fields: {
|
|
109
|
+
title: 1,
|
|
110
|
+
content: 1,
|
|
111
|
+
"+": { author: 1, comments: 1 }, // Reference pre-defined joins
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// Result: Each post includes author and comments as defined
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Note on `fields` in join definitions:** The optional `fields` property within a join definition specifies which fields of the _joined_ collection to include. It's particularly useful when using function-based joins (where `on` is a function) because the parent document may not have all required linking keys fetched by default. For simple array-based joins, `fields` is optional — omit it to fetch all fields from the joined collection.
|
|
120
|
+
|
|
55
121
|
### Basic Join Example
|
|
56
122
|
|
|
57
123
|
```js
|
|
@@ -59,13 +125,6 @@ const posts = await fetchList(
|
|
|
59
125
|
PostsCollection,
|
|
60
126
|
{},
|
|
61
127
|
{
|
|
62
|
-
joins: {
|
|
63
|
-
author: {
|
|
64
|
-
coll: UsersCollection,
|
|
65
|
-
on: ["authorId", "_id"], // [local field, foreign field]
|
|
66
|
-
fields: { name: 1, avatar: 1, email: 1 },
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
128
|
fields: {
|
|
70
129
|
title: 1,
|
|
71
130
|
content: 1,
|
|
@@ -75,23 +134,29 @@ const posts = await fetchList(
|
|
|
75
134
|
);
|
|
76
135
|
|
|
77
136
|
// Result: Each post includes an 'author' object with name, avatar, and email
|
|
137
|
+
// (assuming 'author' was pre-registered via join(PostsCollection, { author: { ... } }))
|
|
78
138
|
```
|
|
79
139
|
|
|
80
140
|
### One-to-Many Joins
|
|
81
141
|
|
|
82
142
|
```js
|
|
143
|
+
import { join, fetchList } from "coll-fns";
|
|
144
|
+
|
|
145
|
+
// Pre-register the join
|
|
146
|
+
join(PostsCollection, {
|
|
147
|
+
comments: {
|
|
148
|
+
Coll: CommentsCollection,
|
|
149
|
+
on: ["_id", "postId"],
|
|
150
|
+
// Note: 'single' defaults to false, so joined docs are returned as an array
|
|
151
|
+
fields: { text: 1, createdAt: 1 },
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Use in fetch
|
|
83
156
|
const posts = await fetchList(
|
|
84
157
|
PostsCollection,
|
|
85
158
|
{},
|
|
86
159
|
{
|
|
87
|
-
joins: {
|
|
88
|
-
comments: {
|
|
89
|
-
coll: CommentsCollection,
|
|
90
|
-
on: ["_id", "postId"],
|
|
91
|
-
many: true, // Returns an array of related documents
|
|
92
|
-
fields: { text: 1, createdAt: 1 },
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
160
|
fields: {
|
|
96
161
|
title: 1,
|
|
97
162
|
"+": { comments: 1 },
|
|
@@ -104,33 +169,41 @@ const posts = await fetchList(
|
|
|
104
169
|
|
|
105
170
|
### Nested Joins
|
|
106
171
|
|
|
107
|
-
Joins can be nested to fetch deeply related data:
|
|
172
|
+
Joins can be nested to fetch deeply related data. Register all joins upfront:
|
|
108
173
|
|
|
109
174
|
```js
|
|
175
|
+
import { join, fetchList } from "coll-fns";
|
|
176
|
+
|
|
177
|
+
// Pre-register joins for PostsCollection
|
|
178
|
+
join(PostsCollection, {
|
|
179
|
+
author: {
|
|
180
|
+
Coll: UsersCollection,
|
|
181
|
+
on: ["authorId", "_id"],
|
|
182
|
+
single: true,
|
|
183
|
+
fields: { name: 1, avatar: 1 },
|
|
184
|
+
},
|
|
185
|
+
comments: {
|
|
186
|
+
Coll: CommentsCollection,
|
|
187
|
+
on: ["_id", "postId"],
|
|
188
|
+
fields: { text: 1, "+": { user: 1 } },
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Pre-register joins for CommentsCollection
|
|
193
|
+
join(CommentsCollection, {
|
|
194
|
+
user: {
|
|
195
|
+
Coll: UsersCollection,
|
|
196
|
+
on: ["userId", "_id"],
|
|
197
|
+
single: true,
|
|
198
|
+
fields: { name: 1, avatar: 1 },
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Use in fetch - nested joins are resolved automatically
|
|
110
203
|
const posts = await fetchList(
|
|
111
204
|
PostsCollection,
|
|
112
205
|
{},
|
|
113
206
|
{
|
|
114
|
-
joins: {
|
|
115
|
-
author: {
|
|
116
|
-
coll: UsersCollection,
|
|
117
|
-
on: ["authorId", "_id"],
|
|
118
|
-
fields: { name: 1, avatar: 1 },
|
|
119
|
-
},
|
|
120
|
-
comments: {
|
|
121
|
-
coll: CommentsCollection,
|
|
122
|
-
on: ["_id", "postId"],
|
|
123
|
-
many: true,
|
|
124
|
-
fields: { text: 1, "+": { user: 1 } },
|
|
125
|
-
joins: {
|
|
126
|
-
user: {
|
|
127
|
-
coll: UsersCollection,
|
|
128
|
-
on: ["userId", "_id"],
|
|
129
|
-
fields: { name: 1, avatar: 1 },
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
207
|
fields: {
|
|
135
208
|
title: 1,
|
|
136
209
|
content: 1,
|
|
@@ -147,25 +220,21 @@ const posts = await fetchList(
|
|
|
147
220
|
Control the depth of recursive joins to prevent infinite loops:
|
|
148
221
|
|
|
149
222
|
```js
|
|
223
|
+
import { join, fetchList } from "coll-fns";
|
|
224
|
+
|
|
225
|
+
// Pre-register recursive join
|
|
226
|
+
join(UsersCollection, {
|
|
227
|
+
friends: {
|
|
228
|
+
Coll: UsersCollection,
|
|
229
|
+
on: ["friendIds", "_id"],
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Use in fetch - specify depth in fields with '+' prefix
|
|
150
234
|
const users = await fetchList(
|
|
151
235
|
UsersCollection,
|
|
152
236
|
{},
|
|
153
237
|
{
|
|
154
|
-
joins: {
|
|
155
|
-
friends: {
|
|
156
|
-
coll: UsersCollection,
|
|
157
|
-
on: ["friendIds", "_id"],
|
|
158
|
-
many: true,
|
|
159
|
-
fields: { name: 1, "+": { friends: 1 } },
|
|
160
|
-
joins: {
|
|
161
|
-
friends: {
|
|
162
|
-
coll: UsersCollection,
|
|
163
|
-
on: ["friendIds", "_id"],
|
|
164
|
-
many: true,
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
238
|
fields: {
|
|
170
239
|
name: 1,
|
|
171
240
|
"+": { friends: 2 }, // Limit to 2 levels deep
|
|
@@ -174,6 +243,37 @@ const users = await fetchList(
|
|
|
174
243
|
);
|
|
175
244
|
```
|
|
176
245
|
|
|
246
|
+
### Function-Based Joins with `fields`
|
|
247
|
+
|
|
248
|
+
When using function-based joins (where `on` is a function), the `fields` property declares which fields the parent document needs for the join to work:
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
import { join, fetchList } from "coll-fns";
|
|
252
|
+
|
|
253
|
+
// Join comments where the parent doc's userId field is used to compute the selector
|
|
254
|
+
join(PostsCollection, {
|
|
255
|
+
userComments: {
|
|
256
|
+
Coll: CommentsCollection,
|
|
257
|
+
// Function form: receives parent doc, returns selector for joined collection
|
|
258
|
+
on: (post) => ({ userId: post.userId, postId: post._id }),
|
|
259
|
+
// Declare which parent fields are required for the join function
|
|
260
|
+
fields: { userId: 1 },
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Use in fetch
|
|
265
|
+
const posts = await fetchList(
|
|
266
|
+
PostsCollection,
|
|
267
|
+
{},
|
|
268
|
+
{
|
|
269
|
+
fields: {
|
|
270
|
+
title: 1,
|
|
271
|
+
"+": { userComments: 1 },
|
|
272
|
+
},
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
```
|
|
276
|
+
|
|
177
277
|
## Hooks: Extensibility Made Easy
|
|
178
278
|
|
|
179
279
|
Hooks allow you to react to CRUD operations, enabling validation, transformation, logging, and side effects without modifying your core business logic.
|
|
@@ -282,6 +382,180 @@ hook(UsersCollection, "update", "after", (result, selector, modifier) => {
|
|
|
282
382
|
});
|
|
283
383
|
```
|
|
284
384
|
|
|
385
|
+
## Error Handling
|
|
386
|
+
|
|
387
|
+
`coll-fns` provides multiple mechanisms for handling errors in database operations and validations.
|
|
388
|
+
|
|
389
|
+
### Throwing Errors in Hooks
|
|
390
|
+
|
|
391
|
+
Hooks can throw errors to prevent operations from completing. This is useful for validation, authorization checks, and data integrity:
|
|
392
|
+
|
|
393
|
+
```js
|
|
394
|
+
import { hook } from "coll-fns";
|
|
395
|
+
|
|
396
|
+
// Prevent invalid operations by throwing in before hooks
|
|
397
|
+
hook(UsersCollection, "insert", "before", (doc) => {
|
|
398
|
+
if (!doc.email || !doc.email.includes("@")) {
|
|
399
|
+
throw new Error("Invalid email format");
|
|
400
|
+
}
|
|
401
|
+
return doc;
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// Usage
|
|
405
|
+
try {
|
|
406
|
+
await insert(UsersCollection, { name: "John", email: "invalid" });
|
|
407
|
+
} catch (error) {
|
|
408
|
+
console.error("Insert failed:", error.message);
|
|
409
|
+
// Output: Insert failed: Invalid email format
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Async/Await Error Handling
|
|
414
|
+
|
|
415
|
+
All operations support both sync and async protocols. Use standard try/catch for async operations:
|
|
416
|
+
|
|
417
|
+
```js
|
|
418
|
+
import { fetchList, update, remove } from "coll-fns";
|
|
419
|
+
|
|
420
|
+
async function safeUpdatePosts() {
|
|
421
|
+
try {
|
|
422
|
+
const posts = await fetchList(PostsCollection, { status: "draft" });
|
|
423
|
+
console.log(`Found ${posts.length} draft posts`);
|
|
424
|
+
|
|
425
|
+
for (const post of posts) {
|
|
426
|
+
await update(
|
|
427
|
+
PostsCollection,
|
|
428
|
+
{ _id: post._id },
|
|
429
|
+
{ $set: { status: "published" } }
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
} catch (error) {
|
|
433
|
+
console.error("Update operation failed:", error);
|
|
434
|
+
// Handle database error, network issue, validation error, etc.
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Join Validation Errors
|
|
440
|
+
|
|
441
|
+
Joins are validated when registered globally. Invalid join definitions throw errors immediately:
|
|
442
|
+
|
|
443
|
+
```js
|
|
444
|
+
import { join } from "coll-fns";
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
// Missing required 'Coll' property
|
|
448
|
+
join(PostsCollection, {
|
|
449
|
+
author: {
|
|
450
|
+
on: ["authorId", "_id"], // Error: Missing Coll
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
} catch (error) {
|
|
454
|
+
console.error(error.message);
|
|
455
|
+
// Output: Collection 'Coll' for 'author' join is required.
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
try {
|
|
459
|
+
// Missing required 'on' condition
|
|
460
|
+
join(PostsCollection, {
|
|
461
|
+
comments: {
|
|
462
|
+
Coll: CommentsCollection,
|
|
463
|
+
// Error: Missing on
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
} catch (error) {
|
|
467
|
+
console.error(error.message);
|
|
468
|
+
// Output: Join 'comments' has no 'on' condition specified.
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Authorization in Hooks
|
|
473
|
+
|
|
474
|
+
Use hooks to enforce authorization rules and throw errors for unauthorized operations:
|
|
475
|
+
|
|
476
|
+
```js
|
|
477
|
+
hook(PostsCollection, "update", "before", (selector, modifier, options) => {
|
|
478
|
+
const currentUserId = getCurrentUserId();
|
|
479
|
+
const [post] = fetchOne(PostsCollection, selector);
|
|
480
|
+
|
|
481
|
+
if (!post) {
|
|
482
|
+
throw new Error("Post not found");
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (post.authorId !== currentUserId) {
|
|
486
|
+
throw new Error("Unauthorized: You can only edit your own posts");
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return [selector, modifier, options];
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Usage
|
|
493
|
+
try {
|
|
494
|
+
await update(
|
|
495
|
+
PostsCollection,
|
|
496
|
+
{ _id: "123" },
|
|
497
|
+
{ $set: { title: "New Title" } }
|
|
498
|
+
);
|
|
499
|
+
} catch (error) {
|
|
500
|
+
if (error.message.includes("Unauthorized")) {
|
|
501
|
+
// Handle authorization error
|
|
502
|
+
} else if (error.message === "Post not found") {
|
|
503
|
+
// Handle not found error
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Handling Join Fetch Errors
|
|
509
|
+
|
|
510
|
+
When joins fail during fetch operations, errors propagate through the promise chain:
|
|
511
|
+
|
|
512
|
+
```js
|
|
513
|
+
import { join, fetchList } from "coll-fns";
|
|
514
|
+
|
|
515
|
+
// Pre-register the join
|
|
516
|
+
join(PostsCollection, {
|
|
517
|
+
author: {
|
|
518
|
+
Coll: UsersCollection,
|
|
519
|
+
on: ["authorId", "_id"],
|
|
520
|
+
single: true,
|
|
521
|
+
},
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
// Use in fetch
|
|
525
|
+
try {
|
|
526
|
+
const posts = await fetchList(
|
|
527
|
+
PostsCollection,
|
|
528
|
+
{},
|
|
529
|
+
{
|
|
530
|
+
fields: { title: 1, "+": { author: 1 } },
|
|
531
|
+
}
|
|
532
|
+
);
|
|
533
|
+
} catch (error) {
|
|
534
|
+
console.error("Failed to fetch posts with authors:", error);
|
|
535
|
+
// Errors from nested joins are propagated here
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Protocol-Level Error Handling
|
|
540
|
+
|
|
541
|
+
When a protocol method is not implemented, `coll-fns` throws a descriptive error:
|
|
542
|
+
|
|
543
|
+
```js
|
|
544
|
+
import { setProtocol, fetchList } from "coll-fns";
|
|
545
|
+
|
|
546
|
+
// Using incomplete protocol
|
|
547
|
+
setProtocol({
|
|
548
|
+
// Missing required methods
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
try {
|
|
552
|
+
await fetchList(SomeCollection, {});
|
|
553
|
+
} catch (error) {
|
|
554
|
+
console.error(error.message);
|
|
555
|
+
// Output: 'findList' method must be defined with 'setProtocol'.
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
285
559
|
## Meteor Integration: Isomorphic by Design
|
|
286
560
|
|
|
287
561
|
`coll-fns` was specifically designed to solve Meteor's challenge of writing code that works both on the client (synchronous) and server (asynchronous) with the same API.
|
|
@@ -311,23 +585,24 @@ Meteor.methods({
|
|
|
311
585
|
|
|
312
586
|
```js
|
|
313
587
|
// client/main.js
|
|
314
|
-
import { setProtocol, protocols } from "coll-fns";
|
|
588
|
+
import { setProtocol, protocols, join } from "coll-fns";
|
|
315
589
|
|
|
316
590
|
setProtocol(protocols.meteorSync);
|
|
317
591
|
|
|
592
|
+
// Pre-register joins (same as server)
|
|
593
|
+
join(PostsCollection, {
|
|
594
|
+
author: {
|
|
595
|
+
Coll: UsersCollection,
|
|
596
|
+
on: ["authorId", "_id"],
|
|
597
|
+
single: true,
|
|
598
|
+
},
|
|
599
|
+
});
|
|
600
|
+
|
|
318
601
|
// Same API, synchronous execution
|
|
319
602
|
const posts = fetchList(
|
|
320
603
|
PostsCollection,
|
|
321
604
|
{},
|
|
322
|
-
{
|
|
323
|
-
joins: {
|
|
324
|
-
author: {
|
|
325
|
-
coll: UsersCollection,
|
|
326
|
-
on: ["authorId", "_id"],
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
fields: { title: 1, "+": { author: 1 } },
|
|
330
|
-
}
|
|
605
|
+
{ fields: { title: 1, "+": { author: 1 } } }
|
|
331
606
|
);
|
|
332
607
|
```
|
|
333
608
|
|
|
@@ -335,7 +610,17 @@ const posts = fetchList(
|
|
|
335
610
|
|
|
336
611
|
```js
|
|
337
612
|
// imports/api/posts.js
|
|
338
|
-
import { fetchList } from "coll-fns";
|
|
613
|
+
import { join, fetchList } from "coll-fns";
|
|
614
|
+
|
|
615
|
+
// Pre-register joins once
|
|
616
|
+
join(PostsCollection, {
|
|
617
|
+
author: {
|
|
618
|
+
Coll: UsersCollection,
|
|
619
|
+
on: ["authorId", "_id"],
|
|
620
|
+
single: true,
|
|
621
|
+
fields: { name: 1, avatar: 1 },
|
|
622
|
+
},
|
|
623
|
+
});
|
|
339
624
|
|
|
340
625
|
// This function works on both client and server!
|
|
341
626
|
export function getPostsWithAuthors() {
|
|
@@ -343,14 +628,11 @@ export function getPostsWithAuthors() {
|
|
|
343
628
|
PostsCollection,
|
|
344
629
|
{},
|
|
345
630
|
{
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
fields: { name: 1, avatar: 1 },
|
|
351
|
-
},
|
|
631
|
+
fields: {
|
|
632
|
+
title: 1,
|
|
633
|
+
content: 1,
|
|
634
|
+
"+": { author: 1 },
|
|
352
635
|
},
|
|
353
|
-
fields: { title: 1, content: 1, "+": { author: 1 } },
|
|
354
636
|
}
|
|
355
637
|
);
|
|
356
638
|
}
|
|
@@ -383,7 +665,6 @@ const users = await fetchList(
|
|
|
383
665
|
- `sort`: Sort specification
|
|
384
666
|
- `limit`: Maximum number of documents
|
|
385
667
|
- `skip`: Number of documents to skip
|
|
386
|
-
- `joins`: Join definitions for related collections
|
|
387
668
|
|
|
388
669
|
#### `fetchOne(collection, selector, options)`
|
|
389
670
|
|
package/dist/coll-fns.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function n(){return n=Object.assign?Object.assign.bind():function(n){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var e in t)({}).hasOwnProperty.call(t,e)&&(n[e]=t[e])}return n},n.apply(null,arguments)}function r(n,r){if(null==n)return{};var t={};for(var e in n)if({}.hasOwnProperty.call(n,e)){if(-1!==r.indexOf(e))continue;t[e]=n[e]}return t}function t(n){var r=function(n){if("object"!=typeof n||!n)return n;var r=n[Symbol.toPrimitive];if(void 0!==r){var t=r.call(n,"string");if("object"!=typeof t)return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)}(n);return"symbol"==typeof r?r:r+""}var e={count:function(){throw new Error("'count' method must be defined with 'setProtocol'.")},cursor:function(){throw new Error("'cursor' method must be defined with 'setProtocol'.")},findList:function(){throw new Error("'findList' method must be defined with 'setProtocol'.")},getTransform:function(){},insert:function(){throw new Error("'insert' method must be defined with 'setProtocol'.")},remove:function(){throw new Error("'remove' method must be defined with 'setProtocol'.")},update:function(){throw new Error("'update' method must be defined with 'setProtocol'.")}},o=e;function i(n){return n?"function"==typeof n?n(o):"object"==typeof n?n:o:o}var u=function(n){return{}.toString.call(n).split(" ")[1].slice(0,-1).toLowerCase()},f=function(n){return Array.isArray(n)},c=function(n){return"function"==typeof n},l=function(n){return n&&!f(n)&&"object"===u(n)};function d(n){return c(null==n?void 0:n.then)}function s(n,r){return p(function(r){var t=r[0];return[n[t]||t,r[1]]},r)}function a(n,r){var t=n.split("."),e=t[0],o=function(n,r){(null==r||r>n.length)&&(r=n.length);for(var t=0,e=Array(r);t<r;t++)e[t]=n[t];return e}(t).slice(1),i=r[e];if(o.length<1)return i;var u=o.join(".");return l(i)?a(u,i):f(i)?i.flatMap(function(n){var r=a(u,n);return f(r)?r:[r]}):i}function v(n,r){if(f(n)){var t=n;return t.some(d)?Promise.all(t).then(function(n){return r(n,!0)}):r(t,!1)}return d(n)?n.then(function(n){return r(n,!0)}):r(n,!1)}function p(n,r){if(void 0===r)return function(r){return p(n,r)};if(f(r))return r.map(n);if(!l(r))throw new TypeError("'map' only works on array or plain object");return Object.fromEntries(Object.entries(r).map(n))}function m(n,r){if(void 0===r)return function(r){return m(n,r)};if(f(r))return r.filter(n);if(!l(r))throw new TypeError("'filter' only works on array or plain object");return Object.fromEntries(Object.entries(r).filter(n))}var h=["array","function","object"],y=h.join("', '"),b=new Map,w=null;function j(n){return b.get(n)||{}}function g(){return w}var _=["+"];function O(n,r){return void 0===r&&(r=!1),l(n)?r?x(n):n:n?void 0:{}}function x(r,t){var e;if(!r)return r;var o=Object.keys(r);return o.some(function(n){return n.startsWith("$")})?t?((e={})[t]=r,e):r:o.reduce(function(e,o){var i=o.indexOf(".");if(i>=0){var u=o.slice(0,i),f=r[u];if(f&&!l(f))return e}var c,d=r[o],s=t?[t,o].join("."):o;return l(d)?n({},e,x(d,s)):n({},e,((c={})[s]=!!d,c))},void 0)}function k(e,o){var i;if(void 0===o&&(o={}),!l(e))return{_:O(e)};var u=function(e,o){void 0===o&&(o={});var i=Object.keys(o),u=g();if(u){var f=e[u],c=r(e,[u].map(t));return n(f?{"+":m(function(n){return i.includes(n[0])},f)}:{"+":void 0},c)}return Object.entries(e).reduce(function(r,t){var e,o,u=t[0],f=t[1];return i.includes(u)?n({},r,{"+":n({},r["+"]||{},(o={},o[u]=f,o))}):n({},r,((e={})[u]=f,e))},{})}(e,o),f=u["+"],c=r(u,_);if(!f)return{_:O(c,!0),"+":void 0};if(!c||null==(i=Object.keys(c))||!i.length)return{_:O(c,!0),"+":f};var d=Object.keys(f).reduce(function(r,t){var e,i=o[t],u=i.on,f=i.fields,c=Array.isArray(u)?((e={})[u[0]]=1,e):void 0;return c||f?n({},r,c,f):r},c);return{_:O(d,!0),"+":f}}function E(n,r){if(!C(n)&&!C(r))return n||r?P(A(n),A(r)):{}}function P(r,t){void 0===r&&(r={}),void 0===t&&(t={});for(var e=n({},r),o=0,i=Object.entries(t||{});o<i.length;o++){var u=i[o],f=u[0],c=u[1],d=e[f];e[f]=l(d)&&l(c)?P(d,c):c}return e}function C(n){return void 0===n||!!n&&!l(n)}function A(n){return l(n)?m(function(n){return n[1]},n):{}}function T(r,t){var e,o,i,u;if(!l(t))return t;var f=g(),c=f?null==(e=t[f])?void 0:e[r]:t[r];if("number"!=typeof c)return t;if(Infinity===c)return t;var d=c-1;return n({},t,f?((u={})[f]=n({},t[f],((i={})[r]=d,i)),u):((o={})[r]=d,o))}var F=["fields","transform"],L=["_key","Coll","on","single","postFetch","limit"],M=["_key","Coll","on","single","postFetch","limit"];function S(t,e,o){void 0===e&&(e={}),void 0===o&&(o={});var d=i(),s=d.count,p=d.findList,m=d.getTransform,h=j(t),y=m(t),b=o.fields,w=o.transform,g=void 0===w?y:w,_=r(o,F),x=function(n){return c(g)?g(n):n},E=k(b,h),P=E._,C=E["+"],A=void 0===C?{}:C,M=Object.keys(A);return!h||null==M||!M.length||b&&!l(b)?v(p(t,e,n({},_,{fields:P,transform:null})),function(n){return n.map(x)}):v(p(t,e,n({},_,{fields:P,transform:null})),function(e){var i=M.reduce(function(r,t){var e,o=h[t];if(!o)return r;var i=u(o.on),f=n({},o,{_key:t});return n({},r,((e={})[i]=[].concat(r[i]||[],[f]),e))},{}),d=i.array,p=i.object,m=void 0===p?[]:p,y=i.function,w=void 0===y?[]:y;return v((void 0===d?[]:d).reduce(function(e,i){var d=i._key,p=i.Coll,m=i.on,h=i.single,y=i.postFetch,w=r(i,L);return v(e,function(r){var e,i,_=m[0],x=m[1],E=m[2],P=void 0===E?{}:E,C=f(_),F=C?r.flatMap(function(n){return n[_[0]]}):r.map(function(n){return n[_]}),L=f(x),M=n({},P,L?((e={})[x[0]]={$elemMatch:{$in:F}},e):((i={})[x]={$in:F},i)),I=p===t&&A[d]>1;return v(I&&s(t,M),function(t){var e,i=I&&!t,s=I?T(d,b):A[d],m=k(s,j(p)||{})._,E=!m||Object.keys(m).length<=0,P=l(s)&&!E&&"_id"!==x?n({},s,((e={})[x]=1,e)):s,F=n({},o,w,{fields:O(P),limit:void 0,transform:I?g:void 0});return v(i?[]:S(p,M,F),function(t){var e=L?{}:t.reduce(function(r,t){var e,o=a(x,t);return f(o)?o.reduce(function(r,e){var o;return n({},r,((o={})[e]=[].concat(r[e]||[],[t]),o))},r):n({},r,((e={})[o]=[].concat(r[o]||[],[t]),e))},{});return r.map(function(r){var o,i,f,l,s=[];L?s=t.filter(function(n){var t,e=n[x[0]]||[];return C?(t=e,(r[_[0]]||[]).some(function(n){return t.indexOf(n)>=0})):e.includes(r[_])}):C?(i="_id",f=(r[_[0]]||[]).flatMap(function(n){return e[n]||[]}),l=c(i)?i:"string"===u(i)?function(n){return n[i]}:function(n){return n},s=f.reduce(function(n,r){var t=l(r);return n.find(function(n){return l(n)===t})?n:[].concat(n,[r])},[])):s=e[r[_]]||[];var a=h?s[0]:s,v=c(y)?y(a,r):a;return n({},r,((o={})[d]=v,o))})})})})},e),function(n){return v(m.map(function(n){return J({Coll:t,join:n,fields:A[n._key],subSelector:n.on,options:_,parentFields:b})}),function(r){return v(n.map(function(n){var e=r.reduce(function(n,r){return r(n)},n);return v(w.reduce(function(r,e){var o=e.on;return v([r,J({Coll:t,join:e,fields:A[e._key],subSelector:c(o)?o(n):o,options:_,parentFields:b})],function(n){return(0,n[1])(n[0])})},e),function(n){return x(n)})}),function(n){return n})})})})}function I(r,t,e){return void 0===e&&(e={}),v(S(r,t,n({},e,{limit:1})),function(n){return n[0]})}function J(t){var e=t.Coll,o=t.join,u=o._key,f=o.Coll,l=o.single,d=o.postFetch,s=o.limit,a=r(o,M),p=t.fields,m=t.subSelector,h=t.options,y=t.parentFields,b=i(),w=f===e;return v(w&&(0,b.count)(e,m),function(r){var t=w&&(!p||!r),e=w?T(u,y):p,o=n({},h,a,{fields:O(e),limit:l?1:s||void 0});return v(t?[]:S(f,m,o),function(r){return function(t){var e,o=l?r[0]:r,i=c(d)?d(o,t):o;return n({},t,((e={})[u]=i,e))}})})}var $=["beforeInsert","beforeUpdate","beforeRemove","onInserted","onUpdated","onRemoved"],R=new Map;function U(n,r){var t=R.get(n)||{};return r?t[r]:t}function D(n,r){var t=U(n,r);if(t)return function(n){if(void 0===n&&(n=[]),n.length){var r=n.reduce(function(n,r){return{fields:E(n.fields,r.fields),before:n.before||r.before}},{fields:null,before:void 0});return{fields:r.fields,fn:function(){var r=[].slice.call(arguments);return v(n.map(function(n){return q.apply(void 0,[n].concat(r))}).filter(c).map(function(n){return n.apply(void 0,r)}),function(n){return n})},before:r.before}}}(t)}function q(n){var r=n.fn,t=n.unless,e=n.when,o=[].slice.call(arguments,1);if(!(null==t?void 0:t.apply(void 0,o))&&(!e||e.apply(void 0,o)))return r}var z=["multi"],W=["multi"],B=["multi"],G={__proto__:null,meteorAsync:{count:function(n,r,t){var e=n.rawCollection();return e.countDocuments?e.countDocuments(r):n.find(r,t).countAsync()},cursor:function(n,r,t){return n.find(r,t)},findList:function(n,r,t){return n.find(r,t).fetchAsync()},getTransform:function(n){return n._transform},insert:function(n,r){return n.insertAsync(r)},remove:function(n,r){return n.removeAsync(r)},update:function(r,t,e,o){return r.updateAsync(t,e,n({multi:!0},o))}},meteorSync:{count:function(n,r,t){return n.find(r,t).count()},cursor:function(n,r,t){return n.find(r,t)},findList:function(n,r,t){return n.find(r,t).fetch()},getTransform:function(n){return n._transform},insert:function(n,r){return n.insert(r)},remove:function(n,r){return n.remove(r)},update:function(r,t,e,o){return r.update(t,e,n({multi:!0},o))}},node:{count:function(n,r,t){return void 0===r&&(r={}),void 0===t&&(t={}),n.countDocuments(r||{},t)},cursor:function(n,r,t){void 0===r&&(r={}),void 0===t&&(t={});var e=s({fields:"projection"},t||{});return n.find(r||{},e)},findList:function(n,r,t){void 0===r&&(r={}),void 0===t&&(t={});var e=s({fields:"projection"},t||{});return n.find(r||{},e).toArray()},getTransform:function(n){return"function"==typeof(null==n?void 0:n.transform)?n.transform:void 0},insert:function(n,r,t){return n.insertOne(r,t).then(function(n){return null==n?void 0:n.insertedId})},remove:function(n,t,e){void 0===t&&(t={}),void 0===e&&(e={});var o=e||{},i=o.multi,u=void 0===i||i,f=r(o,W);return(u?n.deleteMany(t||{},f):n.deleteOne(t||{},f)).then(function(n){var r;return null!=(r=null==n?void 0:n.deletedCount)?r:0})},update:function(n,t,e,o){void 0===t&&(t={}),void 0===e&&(e={}),void 0===o&&(o={});var i=o||{},u=i.multi,f=void 0===u||u,c=r(i,B);return(f?n.updateMany(t||{},e||{},c):n.updateOne(t||{},e||{},c)).then(function(n){var r,t;return null!=(r=null!=(t=null==n?void 0:n.modifiedCount)?t:null==n?void 0:n.upsertedCount)?r:0})}}};exports.count=function(n,r){return v((0,i().count)(n,r),function(n){return n})},exports.exists=function(n,r){return v(I(n,r,{fields:{_id:1}}),function(n){return!!n})},exports.fetchIds=function(r,t,e){return v(S(r,t,n({},e,{fields:{_id:1}})),function(n){return n.map(function(n){return n._id})})},exports.fetchList=S,exports.fetchOne=I,exports.flattenFields=x,exports.getJoinPrefix=g,exports.getJoins=j,exports.getProtocol=i,exports.hook=function(r,t){Object.entries(t).forEach(function(t){var e=t[0],o=t[1];if(!f(o))throw new TypeError("'"+e+"' hooks must be an array");o.forEach(function(t){return function(r,t,e){var o;if(!$.includes(t))throw new TypeError("'"+t+"' is not a valid hook type");if(!c(null==e?void 0:e.fn))throw new TypeError("'hook' must be a function or contain a 'fn' key");var i=U(r),u=[].concat(i[t]||[],[e]);R.set(r,n({},i,((o={})[t]=u,o)))}(r,e,t)})})},exports.insert=function(n,r){var t=i(),e=D(n,"beforeInsert");return v(c(null==e?void 0:e.fn)&&e.fn(r),function(){var e=D(n,"onInserted");return v(t.insert(n,r),function(r){if(!e)return r;var t=e.fields,o=e.fn,i=t?Object.keys(t):[];return v(1===i.length&&"_id"===i[0]?{_id:r}:I(n,{_id:r},{fields:t}),function(n){return o(n),r})})})},exports.join=function(r,t){t?(Object.entries(t).forEach(function(n){var r=n[0],t=n[1],e=t.on,o=t.fields;if(!t.Coll)throw new Error("Collection 'Coll' for '"+r+"' join is required.");if(!e)throw new Error("Join '"+r+"' has no 'on' condition specified.");var i=u(e);if(!h.includes(i))throw new Error("Join '"+r+"' has an unrecognized 'on' condition type of '"+i+"'. Should be one of '"+y+"'.");c(e)&&!o&&function(){var n;console&&console.warn&&(n=console).warn.apply(n,[].slice.call(arguments))}("Join '"+r+"' is defined with a function 'on', but no 'fields' are explicitely specified. This could lead to failed joins if the keys necessary for the join are not specified at query time.")}),b.set(r,n({},b.get(r),t))):b.set(r,void 0)},exports.protocols=G,exports.remove=function(n,r){var t=i(),e=D(n,"beforeRemove"),o=D(n,"onRemoved"),u=function(){var n=[].slice.call(arguments).filter(function(n){return n});return n.length?n.reduce(function(n,r){return E(n,r.fields)},null):null}(e,o);return v(null===u?[]:S(n,r,{fields:u}),function(i){return v(c(null==e?void 0:e.fn)&&e.fn(i),function(){var e=t.remove(n,r);return e&&c(null==o?void 0:o.fn)?(i.forEach(function(n){return o.fn(n)}),e):e})})},exports.setJoinPrefix=function(n){w=n},exports.setProtocol=function(r){void 0===r&&(r={}),o=n({},e,r)},exports.update=function(t,e,o,u){var f=void 0===u?{}:u,l=f.multi,d=void 0===l||l,s=r(f,z),a=i(),p=D(t,"beforeUpdate"),m=D(t,"onUpdated"),h=n({multi:d},s),y=function(n,r){if(!n&&!r)return null;if(!r)return null==n?void 0:n.fields;var t=r.before?r.fields:{_id:1};return n?E(n.fields,t):t}(p,m);return v(null===y?[]:S(t,e,{fields:y,limit:d?void 0:1}),function(n){return v(c(null==p?void 0:p.fn)&&p.fn(n,o),function(){return v(a.update(t,e,o,h),function(r){if(!r||!c(null==m?void 0:m.fn))return r;var e=function(n){return void 0===n&&(n=[]),Object.fromEntries(n.map(function(n){return[n._id,n]}))}(n);return v(S(t,{_id:{$in:Object.keys(e)}},{fields:m.fields}),function(n){return n.forEach(function(n){m.fn(n,e[n._id])}),r})})})})},exports.updateProtocol=function(r){o="function"==typeof r?r(o):n({},o,r)};
|
|
1
|
+
function n(){return n=Object.assign?Object.assign.bind():function(n){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var e in t)({}).hasOwnProperty.call(t,e)&&(n[e]=t[e])}return n},n.apply(null,arguments)}function r(n,r){if(null==n)return{};var t={};for(var e in n)if({}.hasOwnProperty.call(n,e)){if(-1!==r.indexOf(e))continue;t[e]=n[e]}return t}function t(n){var r=function(n){if("object"!=typeof n||!n)return n;var r=n[Symbol.toPrimitive];if(void 0!==r){var t=r.call(n,"string");if("object"!=typeof t)return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)}(n);return"symbol"==typeof r?r:r+""}var e=function(){},o=function(n){return{}.toString.call(n).split(" ")[1].slice(0,-1).toLowerCase()},i=function(n){return Array.isArray(n)},u=function(n){return"function"==typeof n},f=function(n){return n&&!i(n)&&"object"===o(n)};function c(n){return u(null==n?void 0:n.then)}function l(n,r){return v(function(r){var t=r[0];return[n[t]||t,r[1]]},r)}var d=function(){var n;return console&&console.warn&&(n=console).warn.apply(n,[].slice.call(arguments))};function a(n,r){var t=n.split("."),e=t[0],o=function(n,r){(null==r||r>n.length)&&(r=n.length);for(var t=0,e=Array(r);t<r;t++)e[t]=n[t];return e}(t).slice(1),u=r[e];if(o.length<1)return u;var c=o.join(".");return f(u)?a(c,u):i(u)?u.flatMap(function(n){var r=a(c,n);return i(r)?r:[r]}):u}function s(n,r){if(void 0===r&&(r=e),i(n)){var t=n;return t.some(c)?Promise.all(t).then(function(n){return r(n,!0)}):r(t,!1)}return c(n)?n.then(function(n){return r(n,!0)}):r(n,!1)}function v(n,r){if(void 0===r)return function(r){return v(n,r)};if(i(r))return r.map(n);if(!f(r))throw new TypeError("'map' only works on array or plain object");return Object.fromEntries(Object.entries(r).map(n))}function p(n,r){if(void 0===r)return function(r){return p(n,r)};if(i(r))return r.filter(n);if(!f(r))throw new TypeError("'filter' only works on array or plain object");return Object.fromEntries(Object.entries(r).filter(n))}function m(n,r){try{n()}catch(n){u(r)&&r(n)}}var h={count:function(){throw new Error("'count' method must be defined with 'setProtocol'.")},cursor:function(){throw new Error("'cursor' method must be defined with 'setProtocol'.")},findList:function(){throw new Error("'findList' method must be defined with 'setProtocol'.")},getName:function(){return d("'getName' method should be defined with 'setProtocol'."),""},getTransform:function(){},insert:function(){throw new Error("'insert' method must be defined with 'setProtocol'.")},remove:function(){throw new Error("'remove' method must be defined with 'setProtocol'.")},update:function(){throw new Error("'update' method must be defined with 'setProtocol'.")}},y=h;function b(n){return n?"function"==typeof n?n(y):"object"==typeof n?n:y:y}var w=["array","function","object"],g=w.join("', '"),j=new Map,_=null;function O(n){return j.get(n)||{}}function k(){return _}var E=["+"];function x(n,r){return void 0===r&&(r=!1),f(n)?r?P(n):n:n?void 0:{}}function P(r,t){var e;if(!r)return r;var o=Object.keys(r);return o.some(function(n){return n.startsWith("$")})?t?((e={})[t]=r,e):r:o.reduce(function(e,o){var i=o.indexOf(".");if(i>=0){var u=o.slice(0,i),c=r[u];if(c&&!f(c))return e}var l,d=r[o],a=t?[t,o].join("."):o;return f(d)?n({},e,P(d,a)):n({},e,((l={})[a]=!!d,l))},void 0)}function C(e,o){var i;if(void 0===o&&(o={}),!f(e))return{_:x(e)};var u=function(e,o){void 0===o&&(o={});var i=Object.keys(o),u=k();if(u){var f=e[u],c=r(e,[u].map(t));return n(f?{"+":p(function(n){return i.includes(n[0])},f)}:{"+":void 0},c)}return Object.entries(e).reduce(function(r,t){var e,o,u=t[0],f=t[1];return i.includes(u)?n({},r,{"+":n({},r["+"]||{},(o={},o[u]=f,o))}):n({},r,((e={})[u]=f,e))},{})}(e,o),c=u["+"],l=r(u,E);if(!c)return{_:x(l,!0),"+":void 0};if(!l||null==(i=Object.keys(l))||!i.length)return{_:x(l,!0),"+":c};var d=Object.keys(c).reduce(function(r,t){var e,i=o[t],u=i.on,f=i.fields,c=Array.isArray(u)?((e={})[u[0]]=1,e):void 0;return c||f?n({},r,c,f):r},l);return{_:x(d,!0),"+":c}}function T(n,r){if(!I(n)&&!I(r))return n||r?A(N(n),N(r)):{}}function A(r,t){void 0===r&&(r={}),void 0===t&&(t={});for(var e=n({},r),o=0,i=Object.entries(t||{});o<i.length;o++){var u=i[o],c=u[0],l=u[1],d=e[c];e[c]=f(d)&&f(l)?A(d,l):l}return e}function I(n){return void 0===n||!!n&&!f(n)}function N(n){return f(n)?p(function(n){return n[1]},n):{}}function F(r,t){var e,o,i,u;if(!f(t))return t;var c=k(),l=c?null==(e=t[c])?void 0:e[r]:t[r];if("number"!=typeof l)return t;if(Infinity===l)return t;var d=l-1;return n({},t,c?((u={})[c]=n({},t[c],((i={})[r]=d,i)),u):((o={})[r]=d,o))}var L=["fields","transform"],M=["_key","Coll","on","single","postFetch","limit"],S=["_key","Coll","on","single","postFetch","limit"];function J(t,e,c){void 0===e&&(e={}),void 0===c&&(c={});var l=b(),d=l.count,v=l.findList,p=l.getTransform,m=O(t),h=p(t),y=c.fields,w=c.transform,g=void 0===w?h:w,j=r(c,L),_=function(n){return u(g)?g(n):n},k=C(y,m),E=k._,P=k["+"],T=void 0===P?{}:P,A=Object.keys(T);return!m||null==A||!A.length||y&&!f(y)?s(v(t,e,n({},j,{fields:E,transform:null})),function(n){return n.map(_)}):s(v(t,e,n({},j,{fields:E,transform:null})),function(e){var l=A.reduce(function(r,t){var e,i=m[t];if(!i)return r;var u=o(i.on),f=n({},i,{_key:t});return n({},r,((e={})[u]=[].concat(r[u]||[],[f]),e))},{}),v=l.array,p=l.object,h=void 0===p?[]:p,b=l.function,w=void 0===b?[]:b;return s((void 0===v?[]:v).reduce(function(e,l){var v=l._key,p=l.Coll,m=l.on,h=l.single,b=l.postFetch,w=r(l,M);return s(e,function(r){var e,l,j=m[0],_=m[1],k=m[2],E=void 0===k?{}:k,P=i(j),A=P?r.flatMap(function(n){return n[j[0]]}):r.map(function(n){return n[j]}),I=i(_),N=n({},E,I?((e={})[_[0]]={$elemMatch:{$in:A}},e):((l={})[_]={$in:A},l)),L=p===t&&T[v]>1;return s(L&&d(t,N),function(t){var e,l=L&&!t,d=L?F(v,y):T[v],m=C(d,O(p)||{})._,k=!m||Object.keys(m).length<=0,E=f(d)&&!k&&"_id"!==_?n({},d,((e={})[_]=1,e)):d,A=n({},c,w,{fields:x(E),limit:void 0,transform:L?g:void 0});return s(l?[]:J(p,N,A),function(t){var e=I?{}:t.reduce(function(r,t){var e,o=a(_,t);return i(o)?o.reduce(function(r,e){var o;return n({},r,((o={})[e]=[].concat(r[e]||[],[t]),o))},r):n({},r,((e={})[o]=[].concat(r[o]||[],[t]),e))},{});return r.map(function(r){var i,f,c,l,d=[];I?d=t.filter(function(n){var t,e=n[_[0]]||[];return P?(t=e,(r[j[0]]||[]).some(function(n){return t.indexOf(n)>=0})):e.includes(r[j])}):P?(f="_id",c=(r[j[0]]||[]).flatMap(function(n){return e[n]||[]}),l=u(f)?f:"string"===o(f)?function(n){return n[f]}:function(n){return n},d=c.reduce(function(n,r){var t=l(r);return n.find(function(n){return l(n)===t})?n:[].concat(n,[r])},[])):d=e[r[j]]||[];var a=h?d[0]:d,s=u(b)?b(a,r):a;return n({},r,((i={})[v]=s,i))})})})})},e),function(n){return s(h.map(function(n){return U({Coll:t,join:n,fields:T[n._key],subSelector:n.on,options:j,parentFields:y})}),function(r){return s(n.map(function(n){var e=r.reduce(function(n,r){return r(n)},n);return s(w.reduce(function(r,e){var o=e.on;return s([r,U({Coll:t,join:e,fields:T[e._key],subSelector:u(o)?o(n):o,options:j,parentFields:y})],function(n){return(0,n[1])(n[0])})},e),function(n){return _(n)})}),function(n){return n})})})})}function R(r,t,e){return void 0===e&&(e={}),s(J(r,t,n({},e,{limit:1})),function(n){return n[0]})}function U(t){var e=t.Coll,o=t.join,i=o._key,f=o.Coll,c=o.single,l=o.postFetch,d=o.limit,a=r(o,S),v=t.fields,p=t.subSelector,m=t.options,h=t.parentFields,y=b(),w=f===e;return s(w&&(0,y.count)(e,p),function(r){var t=w&&(!v||!r),e=w?F(i,h):v,o=n({},m,a,{fields:x(e),limit:c?1:d||void 0});return s(t?[]:J(f,p,o),function(r){return function(t){var e,o=c?r[0]:r,f=u(l)?l(o,t):o;return n({},t,((e={})[i]=f,e))}})})}var $=["beforeInsert","beforeUpdate","beforeRemove","onInserted","onUpdated","onRemoved"],D=["onInserted","onUpdated","onRemoved"],q=new Map;function z(n,r){var t=q.get(n)||{};return r?t[r]:t}function W(n,r){var t=z(n,r);if(t)return function(n){if(void 0===n&&(n=[]),n.length){var r=n.reduce(function(n,r){return{fields:T(n.fields,r.fields),before:n.before||r.before}},{fields:null,before:void 0});return{before:r.before,fields:r.fields,fn:function(){var r=arguments;return s(n.map(function(n){return B.apply(void 0,[n].concat([].slice.call(r)))}))}}}}(t)}function B(n){void 0===n&&(n={});var r=[].slice.call(arguments,1),t=n.fn,e=n.onError,o=n.unless,i=n.when;if(u(t))try{if(null==o?void 0:o.apply(void 0,r))return;if(i&&!i.apply(void 0,r))return;return t.apply(void 0,r)}catch(r){if(!u(e))throw r;e(r,n)}}function G(n,r){var t;null==(t=console)||t.error("Error in '"+r.hookType+"' hook of '"+r.collName+"' collection:",n)}var H=["multi"],K=["multi"],Q=["multi"],V={__proto__:null,meteorAsync:{count:function(n,r,t){var e=n.rawCollection();return e.countDocuments?e.countDocuments(r):n.find(r,t).countAsync()},cursor:function(n,r,t){return n.find(r,t)},findList:function(n,r,t){return n.find(r,t).fetchAsync()},getName:function(n){return n._name||""},getTransform:function(n){return n._transform},insert:function(n,r){return n.insertAsync(r)},remove:function(n,r){return n.removeAsync(r)},update:function(r,t,e,o){return r.updateAsync(t,e,n({multi:!0},o))}},meteorSync:{count:function(n,r,t){return n.find(r,t).count()},cursor:function(n,r,t){return n.find(r,t)},findList:function(n,r,t){return n.find(r,t).fetch()},getName:function(n){return n._name||""},getTransform:function(n){return n._transform},insert:function(n,r){return n.insert(r)},remove:function(n,r){return n.remove(r)},update:function(r,t,e,o){return r.update(t,e,n({multi:!0},o))}},node:{count:function(n,r,t){return void 0===r&&(r={}),void 0===t&&(t={}),n.countDocuments(r||{},t)},cursor:function(n,r,t){void 0===r&&(r={}),void 0===t&&(t={});var e=l({fields:"projection"},t||{});return n.find(r||{},e)},findList:function(n,r,t){void 0===r&&(r={}),void 0===t&&(t={});var e=l({fields:"projection"},t||{});return n.find(r||{},e).toArray()},getName:function(n){return n.collectionName||""},getTransform:function(n){return"function"==typeof(null==n?void 0:n.transform)?n.transform:void 0},insert:function(n,r,t){return n.insertOne(r,t).then(function(n){return null==n?void 0:n.insertedId})},remove:function(n,t,e){void 0===t&&(t={}),void 0===e&&(e={});var o=e||{},i=o.multi,u=void 0===i||i,f=r(o,K);return(u?n.deleteMany(t||{},f):n.deleteOne(t||{},f)).then(function(n){var r;return null!=(r=null==n?void 0:n.deletedCount)?r:0})},update:function(n,t,e,o){void 0===t&&(t={}),void 0===e&&(e={}),void 0===o&&(o={});var i=o||{},u=i.multi,f=void 0===u||u,c=r(i,Q);return(f?n.updateMany(t||{},e||{},c):n.updateOne(t||{},e||{},c)).then(function(n){var r,t;return null!=(r=null!=(t=null==n?void 0:n.modifiedCount)?t:null==n?void 0:n.upsertedCount)?r:0})}}};exports.count=function(n,r){return s((0,b().count)(n,r),function(n){return n})},exports.exists=function(n,r){return s(R(n,r,{fields:{_id:1}}),function(n){return!!n})},exports.fetchIds=function(r,t,e){return s(J(r,t,n({},e,{fields:{_id:1}})),function(n){return n.map(function(n){return n._id})})},exports.fetchList=J,exports.fetchOne=R,exports.flattenFields=P,exports.getJoinPrefix=k,exports.getJoins=O,exports.getProtocol=b,exports.hook=function(r,t){Object.entries(t).forEach(function(t){var e=t[0],o=t[1];if(!i(o))throw new TypeError("'"+e+"' hooks must be an array");o.forEach(function(t){return function(r,t,e){var o;if(!$.includes(t))throw new TypeError("'"+t+"' is not a valid hook type");if(!u(null==e?void 0:e.fn))throw new TypeError("'hook' must be a function or contain a 'fn' key");var i=b().getName,f=z(r),c=f[t]||[],l=n({onError:D.includes(t)?G:void 0},e,{Coll:r,collName:i(r),hookType:t}),d=[].concat(c,[l]);q.set(r,n({},f,((o={})[t]=d,o)))}(r,e,t)})})},exports.insert=function(n,r){var t=b(),e=W(n,"beforeInsert");return s(u(null==e?void 0:e.fn)&&e.fn(r),function(){var e=W(n,"onInserted");return s(t.insert(n,r),function(r){if(!e)return r;var t=e.fields,o=e.fn,i=t?Object.keys(t):[];return s(1===i.length&&"_id"===i[0]?{_id:r}:R(n,{_id:r},{fields:t}),function(n){return m(function(){return o(n)},function(n){var r;return null==(r=console)?void 0:r.error("'onInserted' error:",n)}),r})})})},exports.join=function(r,t){t?(Object.entries(t).forEach(function(n){var r=n[0],t=n[1],e=t.on,i=t.fields;if(!t.Coll)throw new Error("Collection 'Coll' for '"+r+"' join is required.");if(!e)throw new Error("Join '"+r+"' has no 'on' condition specified.");var f=o(e);if(!w.includes(f))throw new Error("Join '"+r+"' has an unrecognized 'on' condition type of '"+f+"'. Should be one of '"+g+"'.");u(e)&&!i&&d("Join '"+r+"' is defined with a function 'on', but no 'fields' are explicitely specified. This could lead to failed joins if the keys necessary for the join are not specified at query time.")}),j.set(r,n({},j.get(r),t))):j.set(r,void 0)},exports.protocols=V,exports.remove=function(n,r){var t=b(),e=W(n,"beforeRemove"),o=W(n,"onRemoved"),i=function(){var n=[].slice.call(arguments).filter(function(n){return n});return n.length?n.reduce(function(n,r){return T(n,r.fields)},null):null}(e,o);return s(null===i?[]:J(n,r,{fields:i}),function(i){return s(u(null==e?void 0:e.fn)&&e.fn(i),function(){var e=t.remove(n,r);return e&&u(null==o?void 0:o.fn)?(m(function(){return i.forEach(function(n){return o.fn(n)})},function(n){var r;return null==(r=console)?void 0:r.error("'onRemoved' error:",n)}),e):e})})},exports.setJoinPrefix=function(n){_=n},exports.setProtocol=function(r){void 0===r&&(r={}),y=n({},h,r)},exports.update=function(t,e,o,i){var f=void 0===i?{}:i,c=f.multi,l=void 0===c||c,d=r(f,H),a=b(),v=W(t,"beforeUpdate"),p=W(t,"onUpdated"),h=n({multi:l},d),y=function(n,r){if(!n&&!r)return null;if(!r)return null==n?void 0:n.fields;var t=r.before?r.fields:{_id:1};return n?T(n.fields,t):t}(v,p);return s(null===y?[]:J(t,e,{fields:y,limit:l?void 0:1}),function(n){return s(u(null==v?void 0:v.fn)&&v.fn(n,o),function(){return s(a.update(t,e,o,h),function(r){if(!r||!u(null==p?void 0:p.fn))return r;var e=function(n){return void 0===n&&(n=[]),Object.fromEntries(n.map(function(n){return[n._id,n]}))}(n);return s(J(t,{_id:{$in:Object.keys(e)}},{fields:p.fields}),function(n){return m(function(){return n.forEach(function(n){p.fn(n,e[n._id])})},function(n){var r;return null==(r=console)?void 0:r.error("'onUpdated' error:",n)}),r})})})})},exports.updateProtocol=function(r){y="function"==typeof r?r(y):n({},y,r)};
|
|
2
2
|
//# sourceMappingURL=coll-fns.cjs.map
|