coll-fns 1.4.3 → 1.5.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 +416 -7
- 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 +17 -10
- package/src/index.d.ts +71 -0
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ Stop repeating business logic all over your code base. Define hooks on collectio
|
|
|
13
13
|
- [Rationale](#rationale)
|
|
14
14
|
- [Installation and configuration](#installation-and-configuration)
|
|
15
15
|
- [`setProtocol(protocol)`](#setprotocolprotocol)
|
|
16
|
+
- [Execution context (`bindEnvironment`)](#execution-context-bindenvironment)
|
|
16
17
|
- [Bypassing `coll-fns`](#bypassing-coll-fns)
|
|
17
18
|
- [Joins and fetch](#joins-and-fetch)
|
|
18
19
|
- [Quick start examples](#quick-start-examples)
|
|
@@ -53,6 +54,17 @@ Stop repeating business logic all over your code base. Define hooks on collectio
|
|
|
53
54
|
- [Default behavior](#default-behavior)
|
|
54
55
|
- [Options](#options)
|
|
55
56
|
- [Hook best practices](#hook-best-practices)
|
|
57
|
+
- [Nested reactive publications](#nested-reactive-publications)
|
|
58
|
+
- [When to use `publish`](#when-to-use-publish)
|
|
59
|
+
- [`publish(publication, Coll, selector, options)`](#publishpublication-coll-selector-options)
|
|
60
|
+
- [Publication context (`this` in Meteor)](#publication-context-this-in-meteor)
|
|
61
|
+
- [How child declarations work](#how-child-declarations-work)
|
|
62
|
+
- [Ancestors chain](#ancestors-chain)
|
|
63
|
+
- [How `deps` works](#how-deps-works)
|
|
64
|
+
- [Debugging](#debugging)
|
|
65
|
+
- [Built-in optimizations](#built-in-optimizations)
|
|
66
|
+
- [Using `publish` outside Meteor](#using-publish-outside-meteor)
|
|
67
|
+
- [Current limitations](#current-limitations)
|
|
56
68
|
- [License](#license)
|
|
57
69
|
|
|
58
70
|
# Rationale
|
|
@@ -122,7 +134,7 @@ And since it uses a protocol, it can be used with the **native MongoDB driver**
|
|
|
122
134
|
|
|
123
135
|
</details>
|
|
124
136
|
|
|
125
|
-
<details
|
|
137
|
+
<details>
|
|
126
138
|
<summary><strong>Functional API</strong></summary>
|
|
127
139
|
|
|
128
140
|
A lot of libraries that add functionalities to the database layer mutate the collection instances themselves or, when more respectful, offer ways to extend the collection constructor somehow.
|
|
@@ -139,6 +151,26 @@ For Meteor developers, it also means being able to enhance the `Meteor.users` co
|
|
|
139
151
|
|
|
140
152
|
</details>
|
|
141
153
|
|
|
154
|
+
<details style="margin-bottom: 1rem">
|
|
155
|
+
<summary><strong>Nested reactive publications</strong></summary>
|
|
156
|
+
|
|
157
|
+
In Meteor in particular, publication of data over DDP that gets synced on the client in Minimongo is very convenient. It makes for really reactive applications where data doesn't get stale. Optimistic UI optimizations is built-in and doesn't require additional complex logic.
|
|
158
|
+
|
|
159
|
+
However, it can get **difficult to publish exactly the right documents**, especially when using a very useful library that allows joining collections together and keeping data much more normalized!
|
|
160
|
+
|
|
161
|
+
Although returning Meteor cursors from a publish function is still the most optimized path, it sometimes makes sense to **publish children documents based on their relationship with their parent**. But doing so is usually very difficult to implement.
|
|
162
|
+
|
|
163
|
+
Some existing community libraries that promise to do so either:
|
|
164
|
+
|
|
165
|
+
- don't actually work (might understand `added` and `removed` callbacks, but won't react to updates)
|
|
166
|
+
- are too simplistic (cause a lot of duplicated observers)
|
|
167
|
+
- come with a much more complex data layer
|
|
168
|
+
- add somewhat unpredictable reactivity on the server.
|
|
169
|
+
|
|
170
|
+
Since `coll-fns` is already very good at understanding relationships, a `publish` helper was introduced to allow such fine-tuned reactivity out of the box. 💪
|
|
171
|
+
|
|
172
|
+
</details>
|
|
173
|
+
|
|
142
174
|
# Installation and configuration
|
|
143
175
|
|
|
144
176
|
**IMPORTANT**: For concision, the **examples will use the synchronous Meteor protocol** to avoid `async/await` boilerplate. Of course, your code will have to be adapted when used with an asynchronous protocol.
|
|
@@ -220,10 +252,19 @@ const customProtocol = {
|
|
|
220
252
|
* and return the inserted _id. */
|
|
221
253
|
insert(/* Coll, doc, options */) {},
|
|
222
254
|
|
|
255
|
+
/* Observe document changes.
|
|
256
|
+
* Must return a handle with a `stop()` method. */
|
|
257
|
+
observe(/* Coll, selector = {}, callbacks = {}, options = {} */) {},
|
|
258
|
+
|
|
223
259
|
/* Remove documents in a collection
|
|
224
260
|
* and return the number of removed documents. */
|
|
225
261
|
remove(/* Coll, selector, options */) {},
|
|
226
262
|
|
|
263
|
+
/* Stable stringify function used for internal query keys.
|
|
264
|
+
* EJSON canonical stringify is used as a good default,
|
|
265
|
+
* but can be overridden. */
|
|
266
|
+
stringify(/* value */) {},
|
|
267
|
+
|
|
227
268
|
/* Update documents in a collection
|
|
228
269
|
* and return the number of modified documents. */
|
|
229
270
|
update(/* Coll, selector, modifier, options */) {},
|
|
@@ -232,6 +273,33 @@ const customProtocol = {
|
|
|
232
273
|
setProtocol(customProtocol);
|
|
233
274
|
```
|
|
234
275
|
|
|
276
|
+
`observe` expected shape:
|
|
277
|
+
|
|
278
|
+
```js
|
|
279
|
+
observe(Coll, selector = {}, callbacks = {}, options = {}) {
|
|
280
|
+
const { added, changed, removed } = callbacks;
|
|
281
|
+
|
|
282
|
+
// Your implementation subscribes reactively to selector/options changes.
|
|
283
|
+
// Callbacks should be invoked with:
|
|
284
|
+
// - added(id, fields)
|
|
285
|
+
// - changed(id, fields)
|
|
286
|
+
// - removed(id)
|
|
287
|
+
//
|
|
288
|
+
// Then return an object exposing a stop() method.
|
|
289
|
+
return {
|
|
290
|
+
stop() {
|
|
291
|
+
// Tear down underlying observer/resources.
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Notes:
|
|
298
|
+
|
|
299
|
+
- `observe` can be sync or async (returning a Promise of the stop-handle).
|
|
300
|
+
- `fields` should contain changed/added fields payload expected by your transport.
|
|
301
|
+
- `publish()` relies on this contract to keep nested observers in sync.
|
|
302
|
+
|
|
235
303
|
If your runtime has special callback context requirements, implement `bindEnvironment`.
|
|
236
304
|
|
|
237
305
|
```js
|
|
@@ -248,6 +316,11 @@ const customProtocol = {
|
|
|
248
316
|
|
|
249
317
|
If your runtime has no such requirement, simply omit `bindEnvironment`.
|
|
250
318
|
|
|
319
|
+
If you want to use the [`publish()`](#publishpublication-args-options) composite publication helper:
|
|
320
|
+
|
|
321
|
+
- `observe` must be defined on the protocol.
|
|
322
|
+
- `stringify` can be defined if the default EJSON implementation is not sufficient.
|
|
323
|
+
|
|
251
324
|
</details>
|
|
252
325
|
|
|
253
326
|
## Bypassing `coll-fns`
|
|
@@ -449,7 +522,7 @@ join(Workers, {
|
|
|
449
522
|
|
|
450
523
|
When joins are too complex to be defined with an array or object (although rare), a function can be used as the `on` property. Each parent document will be passed to this function, which should return a selector to use on the child collection.
|
|
451
524
|
|
|
452
|
-
When using function-based joins, **a `
|
|
525
|
+
When using function-based joins, **a `deps` property should be added** to the join definition to declare which parent fields are required for the join to work:
|
|
453
526
|
|
|
454
527
|
```js
|
|
455
528
|
import { join } from "coll-fns";
|
|
@@ -472,7 +545,7 @@ join(Posts, {
|
|
|
472
545
|
};
|
|
473
546
|
},
|
|
474
547
|
/* Parent fields needed in the join function */
|
|
475
|
-
|
|
548
|
+
deps: {
|
|
476
549
|
_id: 1, // Optional. _id is implicit in any fetch.
|
|
477
550
|
postedAt: 1,
|
|
478
551
|
},
|
|
@@ -480,6 +553,8 @@ join(Posts, {
|
|
|
480
553
|
});
|
|
481
554
|
```
|
|
482
555
|
|
|
556
|
+
`fields` remains accepted as a backward-compatible alias for `deps`.
|
|
557
|
+
|
|
483
558
|
### Recursive joins
|
|
484
559
|
|
|
485
560
|
A collection can define joins on itself.
|
|
@@ -499,7 +574,7 @@ join(Users, {
|
|
|
499
574
|
|
|
500
575
|
### Join additional options
|
|
501
576
|
|
|
502
|
-
Any additional properties defined on the join (other than `Coll`, `on`, `single`, `postFetch`) will be treated as options to pass to the nested documents `fetchList`. It usually includes:
|
|
577
|
+
Any additional properties defined on the join (other than `Coll`, `on`, `single`, `postFetch`, `deps` and legacy `fields`) will be treated as options to pass to the nested documents `fetchList`. It usually includes:
|
|
503
578
|
|
|
504
579
|
- `limit`: Maximum joined documents count
|
|
505
580
|
- `skip`: Documents to skip in the fetch
|
|
@@ -509,7 +584,7 @@ Any additional properties defined on the join (other than `Coll`, `on`, `single`
|
|
|
509
584
|
|
|
510
585
|
Children documents might need to be modified (transformed, ordered, filtered...) after being fetched. The `postFetch: (childrenDocs, parentDoc) => childrenDocs` join definition property can be used to do so.
|
|
511
586
|
|
|
512
|
-
The second argument of the function is the parent document. If some of its properties are needed, they should be declared in the `
|
|
587
|
+
The second argument of the function is the parent document. If some of its properties are needed, they should be declared in the join `deps` property so they are guaranteed to be fetched on the parent.
|
|
513
588
|
|
|
514
589
|
```js
|
|
515
590
|
import { join } from "coll-fns";
|
|
@@ -521,8 +596,8 @@ join(Resources, {
|
|
|
521
596
|
Coll: Tasks,
|
|
522
597
|
on: ["_id", "resourceId"],
|
|
523
598
|
|
|
524
|
-
/* Ensure `tasksOrder` will be fetched */
|
|
525
|
-
|
|
599
|
+
/* Ensure `tasksOrder` will be fetched on parent docs */
|
|
600
|
+
deps: { tasksOrder: 1 },
|
|
526
601
|
|
|
527
602
|
/* Transform the joined tasks documents based on parent resource. */
|
|
528
603
|
postFetch(tasks, resource) {
|
|
@@ -1521,6 +1596,340 @@ hook(Users, {
|
|
|
1521
1596
|
|
|
1522
1597
|
</details>
|
|
1523
1598
|
|
|
1599
|
+
# Nested reactive publications
|
|
1600
|
+
|
|
1601
|
+
If `coll-fns` is used in a Meteor project, using publications is a way to create fully reactive applications. `publish` function helps to publish complex hierarchical data.
|
|
1602
|
+
|
|
1603
|
+
## When to use `publish`
|
|
1604
|
+
|
|
1605
|
+
Use `publish()` when the publication tree is dynamic and cannot be represented as a simple static list of cursors.
|
|
1606
|
+
|
|
1607
|
+
**Important caveat (Meteor):** if a publication can return plain cursor(s) directly from `Meteor.publish`, prefer that approach. Native cursor-return publications are simpler and usually more optimized by Meteor internals than any userland helper.
|
|
1608
|
+
|
|
1609
|
+
`publish()` is intended for cases where you need one or more of:
|
|
1610
|
+
|
|
1611
|
+
- nested reactive children depending on parent documents
|
|
1612
|
+
- selector recomputation based on changed parent fields
|
|
1613
|
+
- observer reuse and invalidation logic you do not want to hand-roll repeatedly
|
|
1614
|
+
|
|
1615
|
+
## `publish(publication, Coll, selector, options)`
|
|
1616
|
+
|
|
1617
|
+
Create a reactive publication tree (Meteor-style) with support for:
|
|
1618
|
+
|
|
1619
|
+
- explicit child observers (`{ Coll, on, ... }`)
|
|
1620
|
+
- join shorthand children (`{ join: "joinKey", ... }`)
|
|
1621
|
+
- implicit join children derived from parent requested join fields
|
|
1622
|
+
|
|
1623
|
+
`publish` internally uses protocol methods:
|
|
1624
|
+
|
|
1625
|
+
- `observe` to track cursor changes
|
|
1626
|
+
- `getName` to emit DDP collection names
|
|
1627
|
+
- `stringify` to build stable query reuse keys
|
|
1628
|
+
|
|
1629
|
+
As with normal joins, child `on` values can be:
|
|
1630
|
+
|
|
1631
|
+
- static selector objects
|
|
1632
|
+
- functions `(parent, ...ancestors) => selector`
|
|
1633
|
+
- join-array selectors: `[from, to, toSelector?]`
|
|
1634
|
+
|
|
1635
|
+
Refer to the [`join()`](#joincoll-joindefinitions) section for more details.
|
|
1636
|
+
|
|
1637
|
+
```js
|
|
1638
|
+
import { Meteor } from "meteor/meteor";
|
|
1639
|
+
import { join, publish, setJoinPrefix } from "coll-fns";
|
|
1640
|
+
import {
|
|
1641
|
+
Posts,
|
|
1642
|
+
Users,
|
|
1643
|
+
Comments,
|
|
1644
|
+
Tags,
|
|
1645
|
+
FeatureFlags,
|
|
1646
|
+
PostStats,
|
|
1647
|
+
} from "/imports/api/collections";
|
|
1648
|
+
|
|
1649
|
+
setJoinPrefix("+");
|
|
1650
|
+
|
|
1651
|
+
join(Posts, {
|
|
1652
|
+
author: { Coll: Users, on: ["authorId", "_id"], single: true },
|
|
1653
|
+
comments: { Coll: Comments, on: ["_id", "postId"], sort: { createdAt: -1 } },
|
|
1654
|
+
stats: { Coll: PostStats, on: ["_id", "postId"], single: true },
|
|
1655
|
+
});
|
|
1656
|
+
|
|
1657
|
+
join(Comments, {
|
|
1658
|
+
author: { Coll: Users, on: ["authorId", "_id"], single: true },
|
|
1659
|
+
});
|
|
1660
|
+
|
|
1661
|
+
Meteor.publish("posts.tree", function postsTree() {
|
|
1662
|
+
return publish(
|
|
1663
|
+
this,
|
|
1664
|
+
Posts,
|
|
1665
|
+
{ status: "published" },
|
|
1666
|
+
{
|
|
1667
|
+
fields: {
|
|
1668
|
+
title: 1,
|
|
1669
|
+
authorId: 1,
|
|
1670
|
+
tagIds: 1,
|
|
1671
|
+
editorId: 1,
|
|
1672
|
+
"+": {
|
|
1673
|
+
stats: 1,
|
|
1674
|
+
comments: {
|
|
1675
|
+
body: 1,
|
|
1676
|
+
createdAt: 1,
|
|
1677
|
+
"+": {
|
|
1678
|
+
author: { displayName: 1 },
|
|
1679
|
+
},
|
|
1680
|
+
},
|
|
1681
|
+
},
|
|
1682
|
+
},
|
|
1683
|
+
children: [
|
|
1684
|
+
/* Predefined join on Posts collection */
|
|
1685
|
+
{
|
|
1686
|
+
join: "author",
|
|
1687
|
+
fields: { displayName: 1, avatarUrl: 1 },
|
|
1688
|
+
},
|
|
1689
|
+
|
|
1690
|
+
/* Array selector */
|
|
1691
|
+
{
|
|
1692
|
+
Coll: Tags,
|
|
1693
|
+
on: [["tagIds"], "_id"],
|
|
1694
|
+
fields: { label: 1, color: 1 },
|
|
1695
|
+
deps: undefined, // Array selector children implicitely derive deps
|
|
1696
|
+
},
|
|
1697
|
+
|
|
1698
|
+
/* Function selector */
|
|
1699
|
+
{
|
|
1700
|
+
Coll: Users,
|
|
1701
|
+
on: (post) => ({ _id: post.editorId }),
|
|
1702
|
+
fields: { displayName: 1 },
|
|
1703
|
+
deps: ["editorId"],
|
|
1704
|
+
},
|
|
1705
|
+
|
|
1706
|
+
/* Object selector. Always returns the same data irrespective of parent. */
|
|
1707
|
+
{
|
|
1708
|
+
Coll: FeatureFlags,
|
|
1709
|
+
on: { scope: "posts_publication" },
|
|
1710
|
+
fields: { key: 1, enabled: 1 },
|
|
1711
|
+
deps: false,
|
|
1712
|
+
},
|
|
1713
|
+
],
|
|
1714
|
+
}
|
|
1715
|
+
);
|
|
1716
|
+
});
|
|
1717
|
+
```
|
|
1718
|
+
|
|
1719
|
+
`options.maxConcurrent` controls how many child observer creations can run at
|
|
1720
|
+
the same time (`10` by default).
|
|
1721
|
+
|
|
1722
|
+
Why it matters:
|
|
1723
|
+
|
|
1724
|
+
- each parent `added`/`changed` can trigger many child observer creations
|
|
1725
|
+
- unbounded concurrency can create CPU spikes and DB pressure
|
|
1726
|
+
- too little concurrency can slow initial publication warm-up
|
|
1727
|
+
|
|
1728
|
+
What it controls exactly:
|
|
1729
|
+
|
|
1730
|
+
- only child observer creation tasks are throttled
|
|
1731
|
+
- observer reuse still applies (duplicate query keys are collapsed)
|
|
1732
|
+
- invalidation logic still runs; the option just smooths creation bursts
|
|
1733
|
+
|
|
1734
|
+
Practical guidance:
|
|
1735
|
+
|
|
1736
|
+
- decrease it if your publication causes heavy DB load or event-loop stalls
|
|
1737
|
+
- increase it if your DB/runtime handles parallelism well and warm-up is slow
|
|
1738
|
+
- keep in mind this is per `publish()` call, not a single global cap
|
|
1739
|
+
|
|
1740
|
+
Example:
|
|
1741
|
+
|
|
1742
|
+
```js
|
|
1743
|
+
Meteor.publish("posts.tree", function postsTree() {
|
|
1744
|
+
return publish(
|
|
1745
|
+
this,
|
|
1746
|
+
Posts,
|
|
1747
|
+
{ status: "published" },
|
|
1748
|
+
{
|
|
1749
|
+
...args,
|
|
1750
|
+
maxConcurrent: 5,
|
|
1751
|
+
}
|
|
1752
|
+
);
|
|
1753
|
+
});
|
|
1754
|
+
```
|
|
1755
|
+
|
|
1756
|
+
## Publication context (`this` in Meteor)
|
|
1757
|
+
|
|
1758
|
+
`publish()` is designed first for Meteor publications. In Meteor usage, the first
|
|
1759
|
+
argument should be the publication session/context (`this`) received in
|
|
1760
|
+
`Meteor.publish(name, function () { ... })`.
|
|
1761
|
+
|
|
1762
|
+
Minimal expected shape of `publication`:
|
|
1763
|
+
|
|
1764
|
+
- `ready()` (required)
|
|
1765
|
+
- `added(collectionName, id, fields)` (optional but normally provided by Meteor)
|
|
1766
|
+
- `changed(collectionName, id, fields)` (optional but normally provided by Meteor)
|
|
1767
|
+
- `removed(collectionName, id)` (optional but normally provided by Meteor)
|
|
1768
|
+
- `onStop(fn)` (optional, used for cleanup registration)
|
|
1769
|
+
- `error(err)` (optional, used as error sink)
|
|
1770
|
+
|
|
1771
|
+
Example:
|
|
1772
|
+
|
|
1773
|
+
```js
|
|
1774
|
+
Meteor.publish("posts.tree", function () {
|
|
1775
|
+
// `this` is the publication context/session.
|
|
1776
|
+
return publish(this, Posts, { status: "published" });
|
|
1777
|
+
});
|
|
1778
|
+
```
|
|
1779
|
+
|
|
1780
|
+
If `ready` is missing, `publish()` throws.
|
|
1781
|
+
|
|
1782
|
+
## How child declarations work
|
|
1783
|
+
|
|
1784
|
+
`children` entries can be objects or falsy values (`false`, `null`, `undefined`).
|
|
1785
|
+
Falsy entries are ignored, which allows short-circuit declarations like
|
|
1786
|
+
`isEnabled && { ...childArgs }`.
|
|
1787
|
+
|
|
1788
|
+
Object entries can be defined with either:
|
|
1789
|
+
|
|
1790
|
+
- explicit child args:
|
|
1791
|
+
- `{ Coll, on, fields?, deps?, children?, ...cursorOptions }`
|
|
1792
|
+
- join shorthand:
|
|
1793
|
+
- `{ join: "joinKey", ...overrides }`
|
|
1794
|
+
|
|
1795
|
+
Additionally, join children can be derived implicitly from requested parent join fields.
|
|
1796
|
+
|
|
1797
|
+
Conflict rule:
|
|
1798
|
+
|
|
1799
|
+
- If the same join key is declared both as explicit child (`{ join: "..." }`) and in parent join fields (`fields["+"][joinKey]` or root join key without prefix), `publish()` throws and asks you to choose one style.
|
|
1800
|
+
|
|
1801
|
+
## Ancestors chain
|
|
1802
|
+
|
|
1803
|
+
For function selectors and function deps, the helper passes:
|
|
1804
|
+
|
|
1805
|
+
- first argument: direct parent document
|
|
1806
|
+
- remaining arguments: full ancestors chain (grandparent, great-grandparent, ...)
|
|
1807
|
+
|
|
1808
|
+
This is useful when deep children must depend on context from higher levels.
|
|
1809
|
+
|
|
1810
|
+
```js
|
|
1811
|
+
Meteor.publish("resources.tasks.actions", function () {
|
|
1812
|
+
return publish(
|
|
1813
|
+
this,
|
|
1814
|
+
Resources,
|
|
1815
|
+
{ archived: false },
|
|
1816
|
+
{
|
|
1817
|
+
children: [
|
|
1818
|
+
{
|
|
1819
|
+
Coll: Tasks,
|
|
1820
|
+
on: (resource) => ({ resourceId: resource._id }),
|
|
1821
|
+
deps: ["_id"],
|
|
1822
|
+
children: [
|
|
1823
|
+
{
|
|
1824
|
+
Coll: Actions,
|
|
1825
|
+
on: (task, resource) => ({
|
|
1826
|
+
taskId: task._id,
|
|
1827
|
+
tenantId: resource.tenantId,
|
|
1828
|
+
}),
|
|
1829
|
+
deps(changedFields, task, resource) {
|
|
1830
|
+
// Re-run when task link changes or resource tenancy changes.
|
|
1831
|
+
if ("tenantId" in changedFields) return true;
|
|
1832
|
+
return ["_id", "tenantId"];
|
|
1833
|
+
},
|
|
1834
|
+
},
|
|
1835
|
+
],
|
|
1836
|
+
},
|
|
1837
|
+
],
|
|
1838
|
+
}
|
|
1839
|
+
);
|
|
1840
|
+
});
|
|
1841
|
+
```
|
|
1842
|
+
|
|
1843
|
+
## How `deps` works
|
|
1844
|
+
|
|
1845
|
+
`deps` controls when child observers are invalidated and recomputed after parent `changed` events.
|
|
1846
|
+
|
|
1847
|
+
Supported values:
|
|
1848
|
+
|
|
1849
|
+
- `true`: always invalidate
|
|
1850
|
+
- `false`: never invalidate
|
|
1851
|
+
- `"field"` or `["fieldA", "fieldB"]`: invalidate only when those keys are present in changed fields
|
|
1852
|
+
- `{ fieldA: 1, fieldB: true }`: object shorthand converted to watched keys (truthy top-level keys only)
|
|
1853
|
+
- function `(changedFields, parent, ...ancestors) => depsLike`: dynamic rule
|
|
1854
|
+
- `undefined`: special behavior
|
|
1855
|
+
|
|
1856
|
+
Special behavior when `deps` is `undefined`:
|
|
1857
|
+
|
|
1858
|
+
- static selector object child: treated as no invalidation (`[]`)
|
|
1859
|
+
- array/function selector child: treated as potentially dependent and will always invalidate conservatively
|
|
1860
|
+
|
|
1861
|
+
For array selectors, implicit deps are auto-derived from the `from` key.
|
|
1862
|
+
|
|
1863
|
+
`deps` matching is flat:
|
|
1864
|
+
|
|
1865
|
+
- matching is done against exact keys present in `changedFields`
|
|
1866
|
+
- no deep path traversal is performed by `publish()`
|
|
1867
|
+
- nested object deps only contribute top-level keys
|
|
1868
|
+
|
|
1869
|
+
## Debugging
|
|
1870
|
+
|
|
1871
|
+
`publish()` supports lightweight lifecycle debugging with:
|
|
1872
|
+
|
|
1873
|
+
- `debug: true` to log all internal debug events
|
|
1874
|
+
- `debug: { EVENT_NAME: true, ... }` to log selected events only
|
|
1875
|
+
|
|
1876
|
+
Examples of event names include:
|
|
1877
|
+
|
|
1878
|
+
- `CREATED`, `REUSED`
|
|
1879
|
+
- `INVALIDATED`
|
|
1880
|
+
- `DOC_ADDED`, `DOC_CHANGED`, `DOC_REMOVED`
|
|
1881
|
+
- `CANCELLED`, `UNFOLLOWED`, `STOPPED`, `READY`
|
|
1882
|
+
|
|
1883
|
+
Debug scope:
|
|
1884
|
+
|
|
1885
|
+
- Root `debug` applies to the root observer.
|
|
1886
|
+
- Explicit children can override with their own `debug`.
|
|
1887
|
+
- Join-shorthand children (`{ join: "x", ... }`) can also provide `debug`.
|
|
1888
|
+
- Implicit join-derived children (from parent `fields`) inherit parent `debug`.
|
|
1889
|
+
|
|
1890
|
+
## Built-in optimizations
|
|
1891
|
+
|
|
1892
|
+
`publish()` is designed to stay controlled even with nested reactive trees.
|
|
1893
|
+
|
|
1894
|
+
In practical terms, it aims to protect you from:
|
|
1895
|
+
|
|
1896
|
+
- creating the same observer repeatedly for equivalent child queries
|
|
1897
|
+
- runaway bursts of child observer creation
|
|
1898
|
+
- stale async creations being attached after data already changed
|
|
1899
|
+
- leaked child observers when parent links disappear
|
|
1900
|
+
- duplicate add/remove churn for documents shared by multiple branches
|
|
1901
|
+
|
|
1902
|
+
Why this matters:
|
|
1903
|
+
|
|
1904
|
+
- lower risk of memory growth from forgotten/stale observers
|
|
1905
|
+
- fewer unnecessary observers and DB watches
|
|
1906
|
+
- more predictable behavior during frequent parent changes
|
|
1907
|
+
- safer use of nested publications in real apps, not only toy examples
|
|
1908
|
+
|
|
1909
|
+
`maxConcurrent` is part of this safety model: it prevents uncontrolled parallel
|
|
1910
|
+
creation bursts and lets you tune throughput vs load.
|
|
1911
|
+
|
|
1912
|
+
## Using `publish` outside Meteor
|
|
1913
|
+
|
|
1914
|
+
The helper can be used outside Meteor only if both layers are provided:
|
|
1915
|
+
|
|
1916
|
+
- protocol layer (`setProtocol`) supporting at least:
|
|
1917
|
+
- `observe`
|
|
1918
|
+
- `getName` (optional, default implementation provided)
|
|
1919
|
+
- `stringify` (optional, default implementation provided)
|
|
1920
|
+
- publication transport/context object implementing the callbacks [listed above](#publication-context-this-in-meteor)
|
|
1921
|
+
(`added/changed/removed/ready/onStop/error`)
|
|
1922
|
+
|
|
1923
|
+
Protocol methods handle database reactivity.
|
|
1924
|
+
`publication` handles how data changes are emitted to clients.
|
|
1925
|
+
|
|
1926
|
+
## Current limitations
|
|
1927
|
+
|
|
1928
|
+
- `publish()` is a helper, not a replacement for simple cursor-return publications.
|
|
1929
|
+
- Deep/dynamic trees can still be expensive if selectors are broad and highly volatile.
|
|
1930
|
+
- If `deps` are too broad (or omitted for dynamic selectors), invalidations may be frequent.
|
|
1931
|
+
- For best results, keep parent selectors selective and declare precise `deps`.
|
|
1932
|
+
|
|
1524
1933
|
# License
|
|
1525
1934
|
|
|
1526
1935
|
MIT
|
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 e=arguments[r];for(var t in e)({}).hasOwnProperty.call(e,t)&&(n[t]=e[t])}return n},n.apply(null,arguments)}function r(n,r){if(null==n)return{};var e={};for(var t in n)if({}.hasOwnProperty.call(n,t)){if(-1!==r.indexOf(t))continue;e[t]=n[t]}return e}function e(n){var r=function(n){if("object"!=typeof n||!n)return n;var r=n[Symbol.toPrimitive];if(void 0!==r){var e=r.call(n,"string");if("object"!=typeof e)return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)}(n);return"symbol"==typeof r?r:r+""}var t={count:function(){throw new Error("'count' method must be defined with 'setProtocol'.")},findList:function(){throw new Error("'findList' method must be defined with 'setProtocol'.")},getName:function(){return""},getTransform:function(){},bindEnvironment:function(n){return n},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=t;function i(n){return n?"function"==typeof n?n(o):"object"==typeof n?n:o:o}var u=function(){},f=function(n){return{}.toString.call(n).split(" ")[1].slice(0,-1).toLowerCase()},c=function(n){return Array.isArray(n)},l=function(n){return"function"==typeof n},a=function(n){return n&&!c(n)&&"object"===f(n)};function d(n){return l(null==n?void 0:n.then)}function s(n,r){return p(function(r){var e=r[0];return[n[e]||e,r[1]]},r)}function v(n,r){var e=n.split("."),t=e[0],o=function(n,r){(null==r||r>n.length)&&(r=n.length);for(var e=0,t=Array(r);e<r;e++)t[e]=n[e];return t}(e).slice(1),i=r[t];if(o.length<1)return i;var u=o.join(".");return a(i)?v(u,i):c(i)?i.flatMap(function(n){var r=v(u,n);return c(r)?r:[r]}):i}function m(n,r){if(void 0===r&&(r=u),c(n)){var e=n;return e.some(d)?Promise.all(e).then(function(n){return r(n,!0)}):r(e,!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(c(r))return r.map(n);if(!a(r))throw new TypeError("'map' only works on array or plain object");return Object.fromEntries(Object.entries(r).map(n))}function h(n,r){if(void 0===r)return function(r){return h(n,r)};if(c(r))return r.filter(n);if(!a(r))throw new TypeError("'filter' only works on array or plain object");return Object.fromEntries(Object.entries(r).filter(n))}function y(n,r){try{var e=n();d(e)&&e.catch(function(n){l(r)&&r(n)})}catch(n){l(r)&&r(n)}}var w=["array","function","object"],b=w.join("', '"),g=new Map,E=null;function _(n){return g.get(n)||{}}function j(){return E}var x=["+"];function O(n,r){return void 0===r&&(r=!1),a(n)?r?k(n):n:n?void 0:{}}function k(r,e){var t;if(!r)return r;var o=Object.keys(r);return o.some(function(n){return n.startsWith("$")})?e?((t={})[e]=r,t):r:o.reduce(function(t,o){var i=o.indexOf(".");if(i>=0){var u=o.slice(0,i),f=r[u];if(f&&!a(f))return t}var c,l=r[o],d=e?[e,o].join("."):o;return a(l)?n({},t,k(l,d)):n({},t,((c={})[d]=!!l,c))},void 0)}function P(t,o){var i;if(void 0===o&&(o={}),!a(t))return{_:O(t)};var u=function(t,o){void 0===o&&(o={});var i=Object.keys(o),u=j();if(u){var f=t[u],c=r(t,[u].map(e));return n(f?{"+":h(function(n){return i.includes(n[0])},f)}:{"+":void 0},c)}return Object.entries(t).reduce(function(r,e){var t,o,u=e[0],f=e[1];return i.includes(u)?n({},r,{"+":n({},r["+"]||{},(o={},o[u]=f,o))}):n({},r,((t={})[u]=f,t))},{})}(t,o),f=u["+"],c=r(u,x);if(!f)return{_:O(c,!0),"+":void 0};if(!c||null==(i=Object.keys(c))||!i.length)return{_:O(c,!0),"+":f};var l=Object.keys(f).reduce(function(r,e){var t,i=o[e],u=i.on,f=i.fields,c=Array.isArray(u)?((t={})[u[0]]=1,t):void 0;return c||f?n({},r,c,f):r},c);return{_:O(l,!0),"+":f}}function T(n,r){if(!A(n)&&!A(r))return n||r?C(M(n),M(r)):{}}function C(r,e){void 0===r&&(r={}),void 0===e&&(e={});for(var t=n({},r),o=0,i=Object.entries(e||{});o<i.length;o++){var u=i[o],f=u[0],c=u[1],l=t[f];t[f]=a(l)&&a(c)?C(l,c):c}return t}function A(n){return void 0===n||!!n&&!a(n)}function M(n){return a(n)?h(function(n){return n[1]},n):{}}function S(r,e){var t,o,i,u;if(!a(e))return e;var f=j(),c=f?null==(t=e[f])?void 0:t[r]:e[r];if("number"!=typeof c)return e;if(Infinity===c)return e;var l=c-1;return n({},e,f?((u={})[f]=n({},e[f],((i={})[r]=l,i)),u):((o={})[r]=l,o))}var I=["fields","transform"],N=["_key","Coll","on","single","postFetch","limit"],R=["_key","Coll","on","single","postFetch","limit"];function F(e,t,o){void 0===t&&(t={}),void 0===o&&(o={});var u=i(),d=u.count,s=u.findList,p=u.getTransform,h=_(e),y=p(e),w=o.fields,b=o.transform,g=void 0===b?y:b,E=r(o,I),j=function(n){return l(g)?g(n):n},x=P(w,h),k=x._,T=x["+"],C=void 0===T?{}:T,A=Object.keys(C);return!h||null==A||!A.length||w&&!a(w)?m(s(e,t,n({},E,{fields:k,transform:null})),function(n){return n.map(j)}):m(s(e,t,n({},E,{fields:k,transform:null})),function(t){var i=A.reduce(function(r,e){var t,o=h[e];if(!o)return r;var i=f(o.on),u=n({},o,{_key:e});return n({},r,((t={})[i]=[].concat(r[i]||[],[u]),t))},{}),u=i.array,s=i.object,p=void 0===s?[]:s,y=i.function,b=void 0===y?[]:y;return m((void 0===u?[]:u).reduce(function(t,i){var u=i._key,s=i.Coll,p=i.on,h=i.single,y=i.postFetch,b=r(i,N);return m(t,function(r){var t,i,E=p[0],j=p[1],x=p[2],k=void 0===x?{}:x,T=c(E),A=T?r.flatMap(function(n){return n[E[0]]}):r.map(function(n){return n[E]}),M=c(j),I=n({},k,M?((t={})[j[0]]={$elemMatch:{$in:A}},t):((i={})[j]={$in:A},i)),N=s===e&&C[u]>1;return m(N&&d(e,I),function(e){var t,i=N&&!e,d=N?S(u,w):C[u],p=P(d,_(s)||{})._,x=!p||Object.keys(p).length<=0,k=a(d)&&!x&&"_id"!==j?n({},d,((t={})[j]=1,t)):d,A=n({},o,b,{fields:O(k),limit:void 0,transform:N?g:void 0});return m(i?[]:F(s,I,A),function(e){var t=M?{}:e.reduce(function(r,e){var t,o=v(j,e);return c(o)?o.reduce(function(r,t){var o;return n({},r,((o={})[t]=[].concat(r[t]||[],[e]),o))},r):n({},r,((t={})[o]=[].concat(r[o]||[],[e]),t))},{});return r.map(function(r){var o,i,c,a,d=[];M?d=e.filter(function(n){var e,t=n[j[0]]||[];return T?(e=t,(r[E[0]]||[]).some(function(n){return e.indexOf(n)>=0})):t.includes(r[E])}):T?(i="_id",c=(r[E[0]]||[]).flatMap(function(n){return t[n]||[]}),a=l(i)?i:"string"===f(i)?function(n){return n[i]}:function(n){return n},d=c.reduce(function(n,r){var e=a(r);return n.find(function(n){return a(n)===e})?n:[].concat(n,[r])},[])):d=t[r[E]]||[];var s=h?d[0]:d,v=l(y)?y(s,r):s;return n({},r,((o={})[u]=v,o))})})})})},t),function(n){return m(p.map(function(n){return J({Coll:e,join:n,fields:C[n._key],subSelector:n.on,options:E,parentFields:w})}),function(r){return m(n.map(function(n){var t=r.reduce(function(n,r){return r(n)},n);return m(b.reduce(function(r,t){var o=t.on;return m([r,J({Coll:e,join:t,fields:C[t._key],subSelector:l(o)?o(n):o,options:E,parentFields:w})],function(n){return(0,n[1])(n[0])})},t),function(n){return j(n)})}),function(n){return n})})})})}function L(r,e,t){return void 0===t&&(t={}),m(F(r,e,n({},t,{limit:1})),function(n){return n[0]})}function $(n,r){return m(L(n,r,{fields:{_id:1}}),function(n){return!!n})}function J(e){var t=e.Coll,o=e.join,u=o._key,f=o.Coll,c=o.single,a=o.postFetch,d=o.limit,s=r(o,R),v=e.fields,p=e.subSelector,h=e.options,y=e.parentFields,w=i(),b=f===t;return m(b&&(0,w.count)(t,p),function(r){var e=b&&(!v||!r),t=b?S(u,y):v,o=n({},h,s,{fields:O(t),limit:c?1:d||void 0});return m(e?[]:F(f,p,o),function(r){return function(e){var t,o=c?r[0]:r,i=l(a)?a(o,e):o;return n({},e,((t={})[u]=i,t))}})})}var U="drop",D="shift",z=!1,K=W({maxConcurrent:10,maxPending:250});function q(){return z=!0,K}function W(n){var r=function(n){try{if(d.size>=t)throw new Error("Max concurrent calls reached");var e=function(r,e){try{var t=function(r,e){try{var t=function(){d.add(n);var r=n.args;return Promise.resolve(n.fn.apply(void 0,void 0===r?[]:r)).then(function(){})}()}catch(n){return e(n)}return t&&t.then?t.then(void 0,e):t}(0,function(r){!function(n,r){var e=l(u)?u:console.error;Promise.resolve().then(function(){return e(n,r)}).catch(function(n){return console.error(n)})}(r,n)})}catch(n){return e(!0,n)}return t&&t.then?t.then(e.bind(null,!1),e.bind(null,!0)):e(!1,t)}(0,function(e,o){if(d.delete(n),function(){if(!(d.size>=t)){var n=a.shift();n&&r(n)}}(),e)throw o;return o});return Promise.resolve(e&&e.then?e.then(function(){}):void 0)}catch(n){return Promise.reject(n)}},e=n.maxConcurrent,t=void 0===e?10:e,o=n.maxPending,i=void 0===o?250:o,u=n.onError,f=n.onOverflow,c=void 0===f?B:f;!function(n){void 0===n&&(n={});var r=n.maxConcurrent,e=n.maxPending,t=n.onOverflow;if(!(Number.isFinite(r)&&Number.isInteger(r)&&r>=1))throw new TypeError("'maxConcurrent' must be a finite positive integer.");if(!(Infinity===e||Number.isInteger(e)&&e>=0))throw new TypeError("'maxPending' must be a positive integer or `Infinity`");if(!l(t)&&![U,D].includes(t))throw new TypeError("'onOverflow' must be either a function or one of '"+U+"' or '"+D+"'")}({maxConcurrent:t,maxPending:i,onError:u,onOverflow:c});var a=[],d=new Set;function s(n){d.size<t?r(n):a.length<i?a.push(n):function(n){c!==U&&(c===D?(a.shift(),a.length<i&&s(n)):l(c)?function(n){var r=[].concat(a,[n]),e=c([].concat(a),n);if(void 0!==e){if(!Array.isArray(e))throw new TypeError("'onOverflow' must return an array");var t=e.reduce(function(n,e){var t=e._id,o=r.find(function(n){return n._id===t});return o?n.includes(o)?n:[].concat(n,[o]):n},[]);a=t}}(n):console.error("Invalid 'onOverflow'"))}(n)}return{add:function(n){s({_id:Symbol(),fn:n,args:Array.from([].slice.call(arguments,1))})},clear:function(){a=[]}}}function B(){console.warn("'maxPending' limit reached. Call is dropped")}var G,H=["beforeInsert","beforeUpdate","beforeRemove","onInserted","onUpdated","onRemoved"],Q=["onInserted","onUpdated","onRemoved"],V=new Map;function X(n,r){var e=V.get(n)||{};return r?e[r]:e}function Y(r,e){var t=X(r,e);if(t)return function(r,e){if(void 0===r&&(r=[]),void 0===e&&(e=!1),r.length){var t=function(n){return void 0===n&&(n=[]),n.reduce(function(n,r){return{fields:T(n.fields,r.fields),before:n.before||r.before}},{fields:null,before:void 0})}(r);return{before:t.before,fields:t.fields,fn:function(){var t=[].slice.call(arguments);if(!e)return m(r.map(function(n){return nn.apply(void 0,[n].concat(t))}));r.forEach(function(r){return Z.apply(void 0,[n({},r,{fireAndForget:e})].concat(t))})}}}}(t,Q.includes(e))}function Z(n){void 0===n&&(n={});var r=null!=G?G:G||(G=q());r.add.apply(r,[nn,n].concat([].slice.call(arguments,1)))}function nn(n){void 0===n&&(n={});var r=[].slice.call(arguments,1),e=n.fireAndForget,t=n.fn,o=n.onError,u=n.unless,f=n.when,c=i().bindEnvironment;function a(n){var r=[].slice.call(arguments,1);if(l(n))return e&&l(c)?c(n).apply(void 0,r):n.apply(void 0,r)}if(l(t)){var s=function(r){if(!l(o))throw r;a(o,r,n)};try{var v=m(a.apply(void 0,[u].concat(r)),function(n){if(!n)return m(!f||a.apply(void 0,[f].concat(r)),function(n){if(n)return a.apply(void 0,[t].concat(r))})});return d(v)?v.catch(s):v}catch(n){return s(n)}}}function rn(n,r){var e;null==(e=console)||e.error("Error in '"+r.hookType+"' hook of '"+r.collName+"' collection:",n)}function en(n,r){var e=i(),t=Y(n,"beforeRemove"),o=Y(n,"onRemoved"),u=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}(t,o);return m(null===u?[]:F(n,r,{fields:u}),function(i){return m(l(null==t?void 0:t.fn)&&t.fn(i),function(){return m(e.remove(n,r),function(n){return n&&l(null==o?void 0:o.fn)?(y(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)}),n):n})})})}var tn=["multi"];function on(e,t,o,u){var f=void 0===u?{}:u,c=f.multi,a=void 0===c||c,d=r(f,tn),s=i(),v=Y(e,"beforeUpdate"),p=Y(e,"onUpdated"),h=n({multi:a},d),w=function(n,r){if(!n&&!r)return null;if(!r)return null==n?void 0:n.fields;var e=r.before?r.fields:{_id:1};return n?T(n.fields,e):e}(v,p);return m(null===w?[]:F(e,t,{fields:w,limit:a?void 0:1}),function(n){return m(l(null==v?void 0:v.fn)&&v.fn(n,o),function(){return m(s.update(e,t,o,h),function(r){if(!r||!l(null==p?void 0:p.fn))return r;var t=function(n){return void 0===n&&(n=[]),Object.fromEntries(n.map(function(n){return[n._id,n]}))}(n);return m(F(e,{_id:{$in:Object.keys(t)}},{fields:p.fields}),function(n){return y(function(){return n.forEach(function(n){p.fn(n,t[n._id])})},function(n){var r;return null==(r=console)?void 0:r.error("'onUpdated' error:",n)}),r})})})})}var un=new Map;function fn(n){return!n||a(n)}function cn(n){return Array.isArray(n)&&2===n.length&&a(n[0])&&(a(r=n[1])||"string"==typeof r);var r}var ln=["multi"],an=["multi"],dn={__proto__:null,meteorAsync:{count:function(n,r,e){var t=n.rawCollection();return t.countDocuments?t.countDocuments(r):n.find(r,e).countAsync()},findList:function(n,r,e){return n.find(r,e).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,e,t,o){return r.updateAsync(e,t,n({multi:!0},o))}},meteorSync:{count:function(n,r,e){return n.find(r,e).count()},findList:function(n,r,e){return n.find(r,e).fetch()},getName:function(n){return n._name||""},getTransform:function(n){return n._transform},bindEnvironment:function(n){var r=null==globalThis?void 0:globalThis.Meteor,e=null==r?void 0:r.bindEnvironment;return"function"!=typeof e?n:e(n)},insert:function(n,r){return n.insert(r)},remove:function(n,r){return n.remove(r)},update:function(r,e,t,o){return r.update(e,t,n({multi:!0},o))}},node:{count:function(n,r,e){return void 0===r&&(r={}),void 0===e&&(e={}),n.countDocuments(r||{},e)},findList:function(n,r,e){void 0===r&&(r={}),void 0===e&&(e={});var t=s({fields:"projection"},e||{});return n.find(r||{},t).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,e){return n.insertOne(r,e).then(function(n){return null==n?void 0:n.insertedId})},remove:function(n,e,t){void 0===e&&(e={}),void 0===t&&(t={});var o=t||{},i=o.multi,u=void 0===i||i,f=r(o,ln);return(u?n.deleteMany(e||{},f):n.deleteOne(e||{},f)).then(function(n){var r;return null!=(r=null==n?void 0:n.deletedCount)?r:0})},update:function(n,e,t,o){void 0===e&&(e={}),void 0===t&&(t={}),void 0===o&&(o={});var i=o||{},u=i.multi,f=void 0===u||u,c=r(i,an);return(f?n.updateMany(e||{},t||{},c):n.updateOne(e||{},t||{},c)).then(function(n){var r,e;return null!=(r=null!=(e=null==n?void 0:n.modifiedCount)?e:null==n?void 0:n.upsertedCount)?r:0})}}};exports.configurePool=function(n){if(void 0===n&&(n={}),z)throw new Error("'configurePool' must be called at startup before processing hooks");K=W(n)},exports.count=function(n,r,e){return m((0,i().count)(n,r,e),function(n){return n})},exports.exists=$,exports.fetchIds=function(r,e,t){return m(F(r,e,n({},t,{fields:{_id:1}})),function(n){return n.map(function(n){return n._id})})},exports.fetchList=F,exports.fetchOne=L,exports.flattenFields=k,exports.getJoinPrefix=j,exports.getJoins=_,exports.hook=function(r,e){Object.entries(e).forEach(function(e){var t=e[0],o=e[1];if(!c(o))throw new TypeError("'"+t+"' hooks must be an array");o.forEach(function(e){return function(r,e,t){var o;if(!H.includes(e))throw new TypeError("'"+e+"' is not a valid hook type");if(!l(null==t?void 0:t.fn))throw new TypeError("'hook' must be a function or contain a 'fn' key");var u=i().getName,f=X(r),c=f[e]||[],a=n({onError:Q.includes(e)?rn:void 0},t,{Coll:r,collName:u(r),hookType:e}),d=[].concat(c,[a]);V.set(r,n({},f,((o={})[e]=d,o)))}(r,t,e)})})},exports.insert=function(n,r){var e=i(),t=Y(n,"beforeInsert");return m(l(null==t?void 0:t.fn)&&t.fn(r),function(){var t=Y(n,"onInserted");return m(e.insert(n,r),function(r){if(!t)return r;var e=t.fields,o=t.fn,i=e?Object.keys(e):[];return m(1===i.length&&"_id"===i[0]?{_id:r}:L(n,{_id:r},{fields:e}),function(n){return y(function(){return o(n)},function(n){var r;return null==(r=console)?void 0:r.error("'onInserted' error:",n)}),r})})})},exports.join=function(r,e){e?(Object.entries(e).forEach(function(n){var r=n[0],e=n[1],t=e.on,o=e.fields;if(!e.Coll)throw new Error("Collection 'Coll' for '"+r+"' join is required.");if(!t)throw new Error("Join '"+r+"' has no 'on' condition specified.");var i=f(t);if(!w.includes(i))throw new Error("Join '"+r+"' has an unrecognized 'on' condition type of '"+i+"'. Should be one of '"+b+"'.");l(t)&&!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 explicitly specified. This could lead to failed joins if the keys necessary for the join are not specified at query time.")}),g.set(r,n({},g.get(r),e))):g.set(r,void 0)},exports.protocols=dn,exports.registerSoftRemove=function(n,r){var e=void 0===r?{}:r,t=e.docToCollSelectorPairs,o=e.fields,u=void 0===o?{_id:1}:o,f=e.keepModifier,c=e.when;if(!a(n))throw new TypeError("Collection must be an object");var d=i().getName(n);if(un.has(n))throw new Error("'registerSoftRemove' already exists for collection '"+d+"'");if(![t,c].some(l))throw new TypeError("'"+d+"' 'registerSoftRemove' must provide at least one predicate.");un.set(n,{fields:u,defaultKeepModifier:f,shouldKeepDoc:function(n){return m(l(c)&&c(n),function(r){return!!r||!!l(t)&&m(function(n,r){return m(n(r),function(n){if(!Array.isArray(n)||!n.every(cn))throw new TypeError("'docToCollSelectorPairs' should return an array of '[Coll, selector]' tuples");return n})}(t,n),function(n){return m(function(n){return void 0===n&&(n=[]),m(n.map(function(n){return $(n[0],n[1])}),function(n){return n.some(function(n){return n})})}(n),function(n){return!!n})})})}})},exports.remove=en,exports.setJoinPrefix=function(n){E=n},exports.setProtocol=function(r){void 0===r&&(r={}),o=n({},t,r)},exports.softRemove=function(r,e,t,o){void 0===e&&(e={});var u=(void 0===o?{}:o).detailed,f=void 0!==u&&u,c=function(n){var r=un.get(n);if(!r){var e=i().getName(n);throw new Error("'softRemove' must be registered with 'registerSoftRemove' before using it with collection '"+e+"'")}return r}(r),d=c.fields,s=c.shouldKeepDoc,v=c.defaultKeepModifier;function p(n){var r=n.removed,e=void 0===r?0:r,t=n.updated,o=void 0===t?null:t;return f?{removed:e,updated:o}:(null!=e?e:0)+(null!=o?o:0)}return m(F(r,e,{fields:n({},null!=d?d:{},{_id:1}),transform:null}),function(n){return m(n.map(function(n){return m(s(n),function(r){return r?n._id:null})}),function(n){var o=n.filter(function(n){return null!==n});return o.length?m(function(n){if(fn(n))return n||null;if(l(n))return m(n(),function(n){if(fn(n))return n||null;throw new TypeError("'keepModifier' must be a valid modifier, a falsy value or a function that returns one of those.")});throw new TypeError("'keepModifier' must be a valid modifier, a falsy value or a function that returns one of those.")}(null!=t?t:v),function(n){return m([en(r,{$and:[a(e)?e:{_id:e},{_id:{$nin:o}}]}),n?on(r,{_id:{$in:o}},n):null],function(n){return p({removed:n[0],updated:n[1]})})}):m(en(r,e),function(n){return p({removed:n})})})})},exports.update=on;
|
|
1
|
+
var n=require("ejson"),r=require("nanoid/non-secure");function e(n){return n&&"object"==typeof n&&"default"in n?n:{default:n}}var t=/*#__PURE__*/e(n);function o(){return o=Object.assign?Object.assign.bind():function(n){for(var r=1;r<arguments.length;r++){var e=arguments[r];for(var t in e)({}).hasOwnProperty.call(e,t)&&(n[t]=e[t])}return n},o.apply(null,arguments)}function i(n,r){if(null==n)return{};var e={};for(var t in n)if({}.hasOwnProperty.call(n,t)){if(-1!==r.indexOf(t))continue;e[t]=n[t]}return e}function u(n){var r=function(n){if("object"!=typeof n||!n)return n;var r=n[Symbol.toPrimitive];if(void 0!==r){var e=r.call(n,"string");if("object"!=typeof e)return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)}(n);return"symbol"==typeof r?r:r+""}var c={count:function(){throw new Error("'count' method must be defined with 'setProtocol'.")},findList:function(){throw new Error("'findList' method must be defined with 'setProtocol'.")},getName:function(){return""},getTransform:function(){},bindEnvironment:function(n){return n},insert:function(){throw new Error("'insert' method must be defined with 'setProtocol'.")},observe:function(){throw new Error("'observe' method must be defined with 'setProtocol'.")},remove:function(){throw new Error("'remove' method must be defined with 'setProtocol'.")},stringify:function(n){return t.default.stringify(n,{canonical:!0})},update:function(){throw new Error("'update' method must be defined with 'setProtocol'.")}},f=c;function l(n){return n?"function"==typeof n?n(f):"object"==typeof n?n:f:f}var a=function(){},s=function(n){return{}.toString.call(n).split(" ")[1].slice(0,-1).toLowerCase()},d=function(n){return Array.isArray(n)},v=function(n){return"function"==typeof n},h=function(n){return n&&!d(n)&&"object"===s(n)};function m(n){return v(null==n?void 0:n.then)}function p(n,r){return b(function(r){var e=r[0];return[n[e]||e,r[1]]},r)}function y(n,r){var e=n.split("."),t=e[0],o=function(n,r){(null==r||r>n.length)&&(r=n.length);for(var e=0,t=Array(r);e<r;e++)t[e]=n[e];return t}(e).slice(1),i=r[t];if(o.length<1)return i;var u=o.join(".");return h(i)?y(u,i):d(i)?i.flatMap(function(n){var r=y(u,n);return d(r)?r:[r]}):i}function w(n,r){if(void 0===r&&(r=a),d(n)){var e=n;return e.some(m)?Promise.all(e).then(function(n){return r(n,!0)}):r(e,!1)}return m(n)?n.then(function(n){return r(n,!0)}):r(n,!1)}function b(n,r){if(void 0===r)return function(r){return b(n,r)};if(d(r))return r.map(n);if(!h(r))throw new TypeError("'map' only works on array or plain object");return Object.fromEntries(Object.entries(r).map(n))}function g(n,r){if(void 0===r)return function(r){return g(n,r)};if(d(r))return r.filter(n);if(!h(r))throw new TypeError("'filter' only works on array or plain object");return Object.fromEntries(Object.entries(r).filter(n))}function P(n,r){try{var e=n();m(e)&&e.catch(function(n){v(r)&&r(n)})}catch(n){v(r)&&r(n)}}function E(n,r){return Object.hasOwn?Object.hasOwn(n,r):Object.prototype.hasOwnProperty.call(n,r)}var j=["array","function","object"],C=j.join("', '"),O=new Map,x=null;function _(n){return O.get(n)||{}}function A(){return x}var S=["+"];function k(n,r){return void 0===r&&(r=!1),h(n)?r?M(n):n:n?void 0:{}}function M(n,r){var e;if(!n)return n;var t=Object.keys(n);return t.some(function(n){return n.startsWith("$")})?r?((e={})[r]=n,e):n:t.reduce(function(e,t){var i=t.indexOf(".");if(i>=0){var u=t.slice(0,i),c=n[u];if(c&&!h(c))return e}var f,l=n[t],a=r?[r,t].join("."):t;return h(l)?o({},e,M(l,a)):o({},e,((f={})[a]=!!l,f))},void 0)}function T(n,r){var e;if(void 0===r&&(r={}),!h(n))return{_:k(n)};var t=function(n,r){void 0===r&&(r={});var e=Object.keys(r),t=A();if(t){var c=n[t],f=i(n,[t].map(u));return o(c?{"+":g(function(n){return e.includes(n[0])},c)}:{"+":void 0},f)}return Object.entries(n).reduce(function(n,r){var t,i,u=r[0],c=r[1];return e.includes(u)?o({},n,{"+":o({},n["+"]||{},(i={},i[u]=c,i))}):o({},n,((t={})[u]=c,t))},{})}(n,r),c=t["+"],f=i(t,S);return c?f&&null!=(e=Object.keys(f))&&e.length?{_:k(Object.keys(c).reduce(function(n,e){var t,i=r[e],u=i.on,c=i.deps,f=void 0===c?i.fields:c,l=Array.isArray(u)?((t={})[u[0]]=1,t):void 0;return l||f?o({},n,l,f):n},f),!0),"+":c}:{_:k(f,!0),"+":c}:{_:k(f,!0),"+":void 0}}function D(n,r){if(!I(n)&&!I(r))return n||r?N(R(n),R(r)):{}}function N(n,r){void 0===n&&(n={}),void 0===r&&(r={});for(var e=o({},n),t=0,i=Object.entries(r||{});t<i.length;t++){var u=i[t],c=u[0],f=u[1],l=e[c];e[c]=h(l)&&h(f)?N(l,f):f}return e}function I(n){return void 0===n||!!n&&!h(n)}function R(n){return h(n)?g(function(n){return n[1]},n):{}}function L(n,r){var e,t,i,u;if(!h(r))return r;var c=A(),f=c?null==(e=r[c])?void 0:e[n]:r[n];if("number"!=typeof f)return r;if(Infinity===f)return r;var l=f-1;return o({},r,c?((u={})[c]=o({},r[c],((i={})[n]=l,i)),u):((t={})[n]=l,t))}var $=["fields","transform"],F=["_key","Coll","on","single","postFetch","limit"],J=["_key","Coll","on","single","postFetch","limit"];function U(n,r,e){void 0===r&&(r={}),void 0===e&&(e={});var t=l(),u=t.count,c=t.findList,f=t.getTransform,a=_(n),m=f(n),p=e.fields,b=e.transform,g=void 0===b?m:b,P=i(e,$),E=function(n){return v(g)?g(n):n},j=T(p,a),C=j._,O=j["+"],x=void 0===O?{}:O,A=Object.keys(x);return!a||null==A||!A.length||p&&!h(p)?w(c(n,r,o({},P,{fields:C,transform:null})),function(n){return n.map(E)}):w(c(n,r,o({},P,{fields:C,transform:null})),function(r){var t=function(n,r){return void 0===n&&(n=[]),void 0===r&&(r={}),n.reduce(function(n,e){var t,i=r[e];if(!i)return n;var u=s(i.on),c=o({},i,{_key:e});return o({},n,((t={})[u]=[].concat(n[u]||[],[c]),t))},{})}(A,a),c=t.array,f=t.object,l=void 0===f?[]:f,m=t.function,b=void 0===m?[]:m;return w((void 0===c?[]:c).reduce(function(r,t){var c=t._key,f=t.Coll,l=t.on,a=t.single,m=t.postFetch,b=i(t,F);return w(r,function(r){var t,i,P=l[0],E=l[1],j=l[2],C=void 0===j?{}:j,O=d(P),A=O?r.flatMap(function(n){return n[P[0]]}):r.map(function(n){return n[P]}),S=d(E),M=o({},C,S?((t={})[E[0]]={$elemMatch:{$in:A}},t):((i={})[E]={$in:A},i)),D=f===n&&x[c]>1;return w(D&&u(n,M),function(n){var t,i=D&&!n,u=D?L(c,p):x[c],l=T(u,_(f)||{})._,j=!l||Object.keys(l).length<=0,C=h(u)&&!j&&"_id"!==E?o({},u,((t={})[E]=1,t)):u,A=o({},e,b,{fields:k(C),limit:void 0,transform:D?g:void 0});return w(i?[]:U(f,M,A),function(n){var e=S?{}:n.reduce(function(n,r){var e,t=y(E,r);return d(t)?t.reduce(function(n,e){var t;return o({},n,((t={})[e]=[].concat(n[e]||[],[r]),t))},n):o({},n,((e={})[t]=[].concat(n[t]||[],[r]),e))},{});return r.map(function(r){var t,i,u,f,l=[];S?l=n.filter(function(n){var e,t=n[E[0]]||[];return O?(e=t,(r[P[0]]||[]).some(function(n){return e.indexOf(n)>=0})):t.includes(r[P])}):O?(i="_id",u=(r[P[0]]||[]).flatMap(function(n){return e[n]||[]}),f=v(i)?i:"string"===s(i)?function(n){return n[i]}:function(n){return n},l=u.reduce(function(n,r){var e=f(r);return n.find(function(n){return f(n)===e})?n:[].concat(n,[r])},[])):l=e[r[P]]||[];var d=a?l[0]:l,h=v(m)?m(d,r):d;return o({},r,((t={})[c]=h,t))})})})})},r),function(r){return w(l.map(function(r){return K({Coll:n,join:r,fields:x[r._key],subSelector:r.on,options:P,parentFields:p})}),function(e){return w(r.map(function(r){var t=e.reduce(function(n,r){return r(n)},r);return w(b.reduce(function(e,t){var o=t.on;return w([e,K({Coll:n,join:t,fields:x[t._key],subSelector:v(o)?o(r):o,options:P,parentFields:p})],function(n){return(0,n[1])(n[0])})},t),function(n){return E(n)})}),function(n){return n})})})})}function q(n,r,e){return void 0===e&&(e={}),w(U(n,r,o({},e,{limit:1})),function(n){return n[0]})}function z(n,r){return w(q(n,r,{fields:{_id:1}}),function(n){return!!n})}function K(n){var r=n.Coll,e=n.join,t=e._key,u=e.Coll,c=e.single,f=e.postFetch,a=e.limit,s=i(e,J),d=n.fields,h=n.subSelector,m=n.options,p=n.parentFields,y=l(),b=u===r;return w(b&&(0,y.count)(r,h),function(n){var r=b&&(!d||!n),e=b?L(t,p):d,i=o({},m,s,{fields:k(e),limit:c?1:a||void 0});return w(r?[]:U(u,h,i),function(n){return function(r){var e,i=c?n[0]:n,u=v(f)?f(i,r):i;return o({},r,((e={})[t]=u,e))}})})}var V="drop",W="shift",Y=!1,B=H({maxConcurrent:10,maxPending:250});function G(){return Y=!0,B}function H(n){var r=function(n){try{if(a.size>=t)throw new Error("Max concurrent calls reached");var e=function(r,e){try{var t=function(r,e){try{var t=function(){a.add(n);var r=n.args;return Promise.resolve(n.fn.apply(void 0,void 0===r?[]:r)).then(function(){})}()}catch(n){return e(n)}return t&&t.then?t.then(void 0,e):t}(0,function(r){!function(n,r){var e=v(u)?u:console.error;Promise.resolve().then(function(){return e(n,r)}).catch(function(n){return console.error(n)})}(r,n)})}catch(n){return e(!0,n)}return t&&t.then?t.then(e.bind(null,!1),e.bind(null,!0)):e(!1,t)}(0,function(e,o){if(a.delete(n),function(){if(!(a.size>=t)){var n=l.shift();n&&r(n)}}(),e)throw o;return o});return Promise.resolve(e&&e.then?e.then(function(){}):void 0)}catch(n){return Promise.reject(n)}},e=n.maxConcurrent,t=void 0===e?10:e,o=n.maxPending,i=void 0===o?250:o,u=n.onError,c=n.onOverflow,f=void 0===c?Q:c;!function(n){void 0===n&&(n={});var r=n.maxConcurrent,e=n.maxPending,t=n.onOverflow;if(!(Number.isFinite(r)&&Number.isInteger(r)&&r>=1))throw new TypeError("'maxConcurrent' must be a finite positive integer.");if(!(Infinity===e||Number.isInteger(e)&&e>=0))throw new TypeError("'maxPending' must be a positive integer or `Infinity`");if(!v(t)&&![V,W].includes(t))throw new TypeError("'onOverflow' must be either a function or one of '"+V+"' or '"+W+"'")}({maxConcurrent:t,maxPending:i,onError:u,onOverflow:f});var l=[],a=new Set;function s(n){a.size<t?r(n):l.length<i?l.push(n):function(n){f!==V&&(f===W?(l.shift(),l.length<i&&s(n)):v(f)?function(n){var r=[].concat(l,[n]),e=f([].concat(l),n);if(void 0!==e){if(!Array.isArray(e))throw new TypeError("'onOverflow' must return an array");var t=e.reduce(function(n,e){var t=e._id,o=r.find(function(n){return n._id===t});return o?n.includes(o)?n:[].concat(n,[o]):n},[]);l=t}}(n):console.error("Invalid 'onOverflow'"))}(n)}return{add:function(n){s({_id:Symbol(),fn:n,args:Array.from([].slice.call(arguments,1))})},clear:function(){l=[]}}}function Q(){console.warn("'maxPending' limit reached. Call is dropped")}var X,Z=["beforeInsert","beforeUpdate","beforeRemove","onInserted","onUpdated","onRemoved"],nn=["onInserted","onUpdated","onRemoved"],rn=new Map;function en(n,r){var e=rn.get(n)||{};return r?e[r]:e}function tn(n,r){var e=en(n,r);if(e)return function(n,r){if(void 0===n&&(n=[]),void 0===r&&(r=!1),n.length){var e=function(n){return void 0===n&&(n=[]),n.reduce(function(n,r){return{fields:D(n.fields,r.fields),before:n.before||r.before}},{fields:null,before:void 0})}(n);return{before:e.before,fields:e.fields,fn:function(){var e=[].slice.call(arguments);if(!r)return w(n.map(function(n){return un.apply(void 0,[n].concat(e))}));n.forEach(function(n){return on.apply(void 0,[o({},n,{fireAndForget:r})].concat(e))})}}}}(e,nn.includes(r))}function on(n){void 0===n&&(n={});var r=null!=X?X:X||(X=G());r.add.apply(r,[un,n].concat([].slice.call(arguments,1)))}function un(n){void 0===n&&(n={});var r=[].slice.call(arguments,1),e=n.fireAndForget,t=n.fn,o=n.onError,i=n.unless,u=n.when,c=l().bindEnvironment;function f(n){var r=[].slice.call(arguments,1);if(v(n))return e&&v(c)?c(n).apply(void 0,r):n.apply(void 0,r)}if(v(t)){var a=function(r){if(!v(o))throw r;f(o,r,n)};try{var s=w(f.apply(void 0,[i].concat(r)),function(n){if(!n)return w(!u||f.apply(void 0,[u].concat(r)),function(n){if(n)return f.apply(void 0,[t].concat(r))})});return m(s)?s.catch(a):s}catch(n){return a(n)}}}function cn(n,r){var e;null==(e=console)||e.error("Error in '"+r.hookType+"' hook of '"+r.collName+"' collection:",n)}function fn(n,r){var e=l(),t=tn(n,"beforeRemove"),o=tn(n,"onRemoved"),i=function(){var n=[].slice.call(arguments).filter(function(n){return n});return n.length?n.reduce(function(n,r){return D(n,r.fields)},null):null}(t,o);return w(null===i?[]:U(n,r,{fields:i}),function(i){return w(v(null==t?void 0:t.fn)&&t.fn(i),function(){return w(e.remove(n,r),function(n){return n&&v(null==o?void 0:o.fn)?(P(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)}),n):n})})})}var ln=["Coll","children","deps","debug","fields","selector","on"],an=["join"],sn=["maxConcurrent","on"],dn=["Coll","selector","children","deps","debug","on"],vn=["Coll","selector","children","on"];function hn(n,r){try{var e=n()}catch(n){return r(n)}return e&&e.then?e.then(void 0,r):e}var mn="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function pn(n,r,e){if(!n.s){if(e instanceof yn){if(!e.s)return void(e.o=pn.bind(null,n,r));1&r&&(r=e.s),e=e.v}if(e&&e.then)return void e.then(pn.bind(null,n,r),pn.bind(null,n,2));n.s=r,n.v=e;var t=n.o;t&&t(n)}}var yn=/*#__PURE__*/function(){function n(){}return n.prototype.then=function(r,e){var t=new n,o=this.s;if(o){var i=1&o?r:e;if(i){try{pn(t,1,i(this.v))}catch(n){pn(t,2,n)}return t}return this}return this.o=function(n){try{var o=n.v;1&n.s?pn(t,1,r?r(o):o):e?pn(t,1,e(o)):pn(t,2,o)}catch(n){pn(t,2,n)}},t},n}();function wn(n){return n instanceof yn&&1&n.s}var bn=function(n,r){void 0===r&&(r=[]);try{var e,t=function(t){if(e)return t;if(d(n)){var i=(r||[])[0];if(!i)return console.warn("[`publish`]: A parent is necessary to use a join selector."),Cn;var u,c=n[0],f=n[1],l=n[2],a=d(c),s=d(f);if(!a&&!s){var v,h=i[c];if(void 0===h)return Cn;(v={})[f]=h,u=v}if(a&&!s){var m,p=i[c[0]];if(void 0===p)return Cn;(m={})[f]={$in:p||[]},u=m}if(!a&&s){var y,w=i[c];if(void 0===w)return Cn;(y={})[f[0]]={$elemMatch:{$eq:w}},u=y}if(a&&s){var b,g=i[c[0]];if(void 0===g)return Cn;(b={})[f[0]]={$elemMatch:{$in:g||[]}},u=b}return u?l?o({},l,u):u:Cn}return"object"==typeof n?n:Cn};if(!n)return Promise.resolve(Cn);var i=function(){if(v(n))return Promise.resolve(n.apply(void 0,r)).then(function(n){return n?(e=1,n):(console.warn("[`publish`]: `selector` function should produce a valid selector object"),e=1,Cn)})}();return Promise.resolve(i&&i.then?i.then(t):t(i))}catch(n){return Promise.reject(n)}},gn="|";function Pn(){var n=new Map;return n.find=function(r,e){var t=n.get(r);if(t)return Array.from(t.values()).find(e)},n.push=function(r,e){var t=n.get(r);return t?t.add(e):n.set(r,new Set([e])),n},n.pull=function(r,e){if(!n.has(r))return n;var t=n.get(r);return t&&(t.delete(e),t.size||n.delete(r)),n},n}function En(n,r){void 0===r&&(r={});var e=l();return[e.getName(n),e.stringify(r)].join(gn)}function jn(n,r,e){void 0===r&&(r={}),void 0===e&&(e={});var t=l(),o=e.fields,i=e.limit,u=e.skip,c=e.sort;return En(n,r)+[o,c,i,u].filter(function(n){return void 0!==n}).map(function(n){return h(n)?t.stringify(n):n.toString()}).join(gn)}var Cn={_id:{$exists:!1}};function On(n){if(void 0!==n)return"boolean"==typeof n?n:v(n)?function(){try{return Promise.resolve(n.apply(void 0,[].slice.call(arguments))).then(On)}catch(n){return Promise.reject(n)}}:d(n)?n:h(n)?Object.entries(n).filter(function(n){return n[1]}).map(function(n){return n[0]}):n instanceof Set?[].concat(n):"string"==typeof n&&[n]}function xn(n){return function(r){var e;n&&(!0===n||null!=n&&n[r])&&(e=console).log.apply(e,[r].concat([].slice.call(arguments,1)))}}function _n(n,r,e){var t,i=null==(t=_(n))?void 0:t[r];if(!i){var u=l();throw new Error("Join '"+r+"' is not defined on collection '"+u.getName(n)+"'.")}var c=i.deps;return o({Coll:i.Coll,on:i.on,deps:void 0===c?i.fields:c,limit:i.single?1:i.limit},e)}var An=["multi"];function Sn(n,r,e,t){var u=void 0===t?{}:t,c=u.multi,f=void 0===c||c,a=i(u,An),s=l(),d=tn(n,"beforeUpdate"),h=tn(n,"onUpdated"),m=o({multi:f},a),p=function(n,r){if(!n&&!r)return null;if(!r)return null==n?void 0:n.fields;var e=r.before?r.fields:{_id:1};return n?D(n.fields,e):e}(d,h);return w(null===p?[]:U(n,r,{fields:p,limit:f?void 0:1}),function(t){return w(v(null==d?void 0:d.fn)&&d.fn(t,e),function(){return w(s.update(n,r,e,m),function(r){if(!r||!v(null==h?void 0:h.fn))return r;var e=function(n){return void 0===n&&(n=[]),Object.fromEntries(n.map(function(n){return[n._id,n]}))}(t);return w(U(n,{_id:{$in:Object.keys(e)}},{fields:h.fields}),function(n){return P(function(){return n.forEach(function(n){h.fn(n,e[n._id])})},function(n){var r;return null==(r=console)?void 0:r.error("'onUpdated' error:",n)}),r})})})})}var kn=new Map;function Mn(n){return!n||h(n)}function Tn(n){return Array.isArray(n)&&2===n.length&&h(n[0])&&(h(r=n[1])||"string"==typeof r);var r}var Dn=["multi"],Nn=["multi"],In={__proto__:null,meteorAsync:{count:function(n,r,e){var t=n.rawCollection();return t.countDocuments?t.countDocuments(r):n.find(r,e).countAsync()},findList:function(n,r,e){return n.find(r,e).fetchAsync()},getName:function(n){return n._name||""},getTransform:function(n){return n._transform},insert:function(n,r){return n.insertAsync(r)},observe:function(n,r,e,t){return n.find(r,t).observeChangesAsync(e)},remove:function(n,r){return n.removeAsync(r)},update:function(n,r,e,t){return n.updateAsync(r,e,o({multi:!0},t))}},meteorSync:{count:function(n,r,e){return n.find(r,e).count()},findList:function(n,r,e){return n.find(r,e).fetch()},getName:function(n){return n._name||""},getTransform:function(n){return n._transform},bindEnvironment:function(n){var r=null==globalThis?void 0:globalThis.Meteor,e=null==r?void 0:r.bindEnvironment;return"function"!=typeof e?n:e(n)},insert:function(n,r){return n.insert(r)},observe:function(n,r,e,t){return n.find(r,t).observeChanges(e)},remove:function(n,r){return n.remove(r)},update:function(n,r,e,t){return n.update(r,e,o({multi:!0},t))}},node:{count:function(n,r,e){return void 0===r&&(r={}),void 0===e&&(e={}),n.countDocuments(r||{},e)},findList:function(n,r,e){void 0===r&&(r={}),void 0===e&&(e={});var t=p({fields:"projection"},e||{});return n.find(r||{},t).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,e){return n.insertOne(r,e).then(function(n){return null==n?void 0:n.insertedId})},remove:function(n,r,e){void 0===r&&(r={}),void 0===e&&(e={});var t=e||{},o=t.multi,u=void 0===o||o,c=i(t,Dn);return(u?n.deleteMany(r||{},c):n.deleteOne(r||{},c)).then(function(n){var r;return null!=(r=null==n?void 0:n.deletedCount)?r:0})},update:function(n,r,e,t){void 0===r&&(r={}),void 0===e&&(e={}),void 0===t&&(t={});var o=t||{},u=o.multi,c=void 0===u||u,f=i(o,Nn);return(c?n.updateMany(r||{},e||{},f):n.updateOne(r||{},e||{},f)).then(function(n){var r,e;return null!=(r=null!=(e=null==n?void 0:n.modifiedCount)?e:null==n?void 0:n.upsertedCount)?r:0})}}};exports.configurePool=function(n){if(void 0===n&&(n={}),Y)throw new Error("'configurePool' must be called at startup before processing hooks");B=H(n)},exports.count=function(n,r,e){return w((0,l().count)(n,r,e),function(n){return n})},exports.exists=z,exports.fetchIds=function(n,r,e){return w(U(n,r,o({},e,{fields:{_id:1}})),function(n){return n.map(function(n){return n._id})})},exports.fetchList=U,exports.fetchOne=q,exports.flattenFields=M,exports.getJoinPrefix=A,exports.getJoins=_,exports.hook=function(n,r){Object.entries(r).forEach(function(r){var e=r[0],t=r[1];if(!d(t))throw new TypeError("'"+e+"' hooks must be an array");t.forEach(function(r){return function(n,r,e){var t;if(!Z.includes(r))throw new TypeError("'"+r+"' is not a valid hook type");if(!v(null==e?void 0:e.fn))throw new TypeError("'hook' must be a function or contain a 'fn' key");var i=l().getName,u=en(n),c=u[r]||[],f=o({onError:nn.includes(r)?cn:void 0},e,{Coll:n,collName:i(n),hookType:r}),a=[].concat(c,[f]);rn.set(n,o({},u,((t={})[r]=a,t)))}(n,e,r)})})},exports.insert=function(n,r){var e=l(),t=tn(n,"beforeInsert");return w(v(null==t?void 0:t.fn)&&t.fn(r),function(){var t=tn(n,"onInserted");return w(e.insert(n,r),function(r){if(!t)return r;var e=t.fields,o=t.fn,i=e?Object.keys(e):[];return w(1===i.length&&"_id"===i[0]?{_id:r}:q(n,{_id:r},{fields:e}),function(n){return P(function(){return o(n)},function(n){var r;return null==(r=console)?void 0:r.error("'onInserted' error:",n)}),r})})})},exports.join=function(n,r){r?(Object.entries(r).forEach(function(n){var r=n[0],e=n[1],t=e.on,o=e.deps,i=void 0===o?e.fields:o;if(!e.Coll)throw new Error("Collection 'Coll' for '"+r+"' join is required.");if(!t)throw new Error("Join '"+r+"' has no 'on' condition specified.");var u=s(t);if(!j.includes(u))throw new Error("Join '"+r+"' has an unrecognized 'on' condition type of '"+u+"'. Should be one of '"+C+"'.");v(t)&&!i&&function(){var n;console&&console.warn&&(n=console).warn.apply(n,[].slice.call(arguments))}("Join '"+r+"' is defined with a function 'on', but no 'deps' are explicitly specified. This could lead to failed joins if the keys necessary for the join are not specified at query time.")}),O.set(n,o({},O.get(n),r))):O.set(n,void 0)},exports.protocols=In,exports.publish=function(n,e,t,u){void 0===u&&(u={});try{if(!v(n.ready))throw new Error("'publication' context with a 'ready' method must be passed to 'publish'");var c=o({},u,{Coll:e,selector:t});return Promise.resolve(hn(function(){return Promise.resolve(function(n,e){void 0===e&&(e={});try{var t=function(e,c){void 0===e&&(e={});var f=(void 0===c?{}:c).ancestors,a=void 0===f?[]:f;try{if(s)return Promise.resolve(null);var b=function(n){var r=n.Coll,e=n.children,t=void 0===e?[]:e,u=n.deps,c=n.debug,f=n.fields,a=n.selector,s=n.on,d=void 0===s?a:s,v=i(n,ln),m=T(f,_(r)),p=m._,y=m["+"],w=void 0===y?{}:y,b=Object.keys(w),g=t.reduce(function(n,e){if(!e)return n;if(!h(e)){var t=l();throw new Error("Each child of '"+t.getName(r)+"' collection must be an object or a falsy value to ignore.")}if(!e.join)return[].concat(n,[e]);var o=e.join,u=i(e,an);if(b.includes(o))throw new Error("Join '"+o+"' is defined both in parent fields and as an explicit child. Choose one or the other.");return[].concat(n,[_n(r,o,u)])},[]),P=b.map(function(n){return _n(r,n,{debug:c,fields:w[n]})});return o({Coll:r,selector:a,fields:p,children:[].concat(g,P),deps:u,debug:c,on:d},v)}(e),g=b.Coll,P=b.selector,j=b.children,C=void 0===j?[]:j,O=b.debug,x=b.on,A=void 0===x?P:x,S=i(b,dn);if(!P&&!A)throw new Error("'selector' or 'on' is necessary to create an observer.");var k=xn(O),M=C.filter(h),D=r.nanoid(),N=function(n){return[D,R,n].join(gn)},I=l(),R=I.getName(g),L=!1,$=new Set;return Promise.resolve(bn(A,a)).then(function(e){var c=function(n,r,e,o){try{return L||s?Promise.resolve():_.check(r,e)?Promise.resolve(t(n,{ancestors:o})).then(function(n){n&&(L||s||!_.check(r,e)?n.unfollowMaybeCancel(r):(u(r,n),$.add(n)))}):Promise.resolve()}catch(n){return Promise.reject(n)}},f=En(g,e),l=jn(g,e,S),b=function(n){if(null==n||!n.length)return function(){return!1};var r=n.reduce(function(n,r){if(n){var e=function(n){var r=n.on,e=void 0===r?n.selector:r,t=On(n.deps);if("boolean"==typeof t)return t;if(h(e)&&void 0===t)return[];if(!d(e))return t;var o=e[0],i=d(o)?o[0]:o;return d(t)?[i].concat(t):v(t)?[i,t]:[i]}(r);return!0===e||void 0===e||(d(e)?e.forEach(function(r){return n.add(r)}):n.add(e),n)}},new Set);if(!0===r)return function(){return!0};var e=Array.from(r).map(function(n){return function(r){try{var e,t=function(t){return e?t:"string"!=typeof n||E(r,n)},o=arguments;if("boolean"==typeof n)return Promise.resolve(n);var i=function(){if(v(n))return Promise.resolve(n.apply(void 0,[r].concat([].slice.call(o,1)))).then(function(n){if(d(n)){var t=n.some(function(n){return E(r,n)});return e=1,t}return e=1,!n})}();return Promise.resolve(i&&i.then?i.then(t):t(i))}catch(n){return Promise.reject(n)}}});return function(){try{var n,r=arguments,t=function(n,r,e){if("function"==typeof n[mn]){var t,o,i,u=function(n){try{for(;!((t=c.next()).done||e&&e());)if((n=r(t.value))&&n.then){if(!wn(n))return void n.then(u,i||(i=pn.bind(null,o=new yn,2)));n=n.v}o?pn(o,1,n):o=n}catch(n){pn(o||(o=new yn),2,n)}},c=n[mn]();if(u(),c.return){var f=function(n){try{t.done||c.return()}catch(n){}return n};if(o&&o.then)return o.then(f,function(n){throw f(n)});f()}return o}if(!("length"in n))throw new TypeError("Object is not iterable");for(var l=[],a=0;a<n.length;a++)l.push(n[a]);return function(n,r,e){var t,o,i=-1;return function u(c){try{for(;++i<n.length&&(!e||!e());)if((c=r(i))&&c.then){if(!wn(c))return void c.then(u,o||(o=pn.bind(null,t=new yn,2)));c=c.v}t?pn(t,1,c):t=c}catch(n){pn(t||(t=new yn),2,n)}}(),t}(l,function(n){return r(l[n])},e)}(e,function(e){return Promise.resolve(e.apply(void 0,[].slice.call(r))).then(function(r){if(r)return n=!0})},function(){return n});return Promise.resolve(t&&t.then?t.then(function(r){return!!n&&r}):!!n&&t)}catch(n){return Promise.reject(n)}}}(M),P=p.get(l);if(P)return k("REUSED",f),P;var j,C,O,x=new Set,_=(j=new Map,{check:function(n,r){return j.get(n)===r},register:function(n){var e=r.nanoid();return j.set(n,e),e},remove:function(n){j.delete(n)}}),A=new Promise(function(n,r){C=n,O=r});function T(n,r){r.unfollowMaybeCancel(n),$.delete(r),m.pull(n,r)}function F(r,e){var t,o=[r,e].join("|");x.delete(o);var i=null!=(t=y.get(o))?t:0,u=Math.max(0,i-1);u<=0?(y.delete(o),k("DOC_REMOVED",r,e),null==n.removed||n.removed(r,e)):y.set(o,u)}return p.set(l,A),hn(function(){if(e===Cn)return k("BYPASSED",f),p.delete(l),C(null),null;var r={added:function(r,e){try{if(L)return Promise.resolve();if(function(r,e,t){var o,i=[r,e].join("|");x.add(i);var u=null!=(o=y.get(i))?o:0;y.set(i,u+1),k("DOC_ADDED",r,e),null==n.added||n.added(r,e,t)}(R,r,e),null==M||!M.length)return Promise.resolve();var t=N(r),i=_.register(t),u=[o({},e,{_id:r})].concat(a);return M.forEach(function(n){return w.add(c,n,t,i,u)}),Promise.resolve()}catch(n){return Promise.reject(n)}},changed:function(r,e){try{return L?Promise.resolve():(k("DOC_CHANGED",R,r,e),null==n.changed||n.changed(R,r,e),null!=M&&M.length?Promise.resolve(q(g,{_id:r},{fields:S.fields,transform:null})).then(function(n){var t=[n].concat(a);return Promise.resolve(b.apply(void 0,[e].concat(t))).then(function(n){if(n){k("INVALIDATED",f);var e=N(r);return Promise.resolve(function(n){try{var r=m.get(n);return r?Promise.resolve(Promise.all(r.values())).then(function(n){return new Map(n.map(function(n){return[n.queryKey,n]}))}):Promise.resolve(new Map)}catch(n){return Promise.reject(n)}}(e)).then(function(n){return Promise.resolve(function(n,r){try{return null!=r&&r.length?Promise.resolve(Promise.all(r.map(function(r){var e=r.Coll,t=r.on,o=void 0===t?r.selector:t,u=i(r,vn);return Promise.resolve(bn(o,n)).then(function(n){return[jn(e,n,u),r]})}))).then(function(n){return new Map(n)}):Promise.resolve(new Map)}catch(n){return Promise.reject(n)}}(t,M)).then(function(r){var o=Array.from(r.entries()).reduce(function(r,e){var t=e[1];return n.has(e[0])?r:[].concat(r,[t])},[]);if(o.length){var i=_.register(e);o.forEach(function(n){w.add(c,n,e,i,t)})}n.forEach(function(n,t){r.has(t)||w.add(T,e,n)})})})}})}):Promise.resolve())}catch(n){return Promise.reject(n)}},removed:function(n){if(!L){F(R,n);var r=N(n);_.remove(r),(m.get(r)||new Set).forEach(function(n){return w.add(T,r,n)})}}};return Promise.resolve(I.observe(g,e,r,S)).then(function(n){return k("CREATED",f),s?(n.stop(),p.delete(l),C(null),null):(n.id=D,n.queryKey=l,n.docsList=x,n.cancel=function(){L||(n.stop(),$.forEach(function(n){return n.unfollowMaybeCancel()}),$.clear(),Array.from(m.entries()).forEach(function(n){var r=n[0],e=n[1],t=void 0===e?new Set:e;(function(n){return n.split(gn)[0]===D})(r)&&(t.forEach(function(n){return n.unfollowMaybeCancel(r)}),m.delete(r))}),Array.from(x).forEach(function(n){var r=n.split("|");F(r[0],r[1])}),x.clear(),p.delete(l),L=!0,k("CANCELLED",f))},n.unfollowMaybeCancel=function(r){n.followers&&(n.followers.delete(r),k("UNFOLLOWED","from",f,"by",r)),m.pull(r,n),(!n.followers||n.followers.size<1)&&n.cancel()},p.set(l,n),C(n),n)})},function(n){throw p.delete(l),O(n),n})})}catch(n){return Promise.reject(n)}},u=function(n,r){var e=r.followers;e?e.add(n):r.followers=new Set([n]),m.push(n,r)},c=xn(e.debug),f=e.maxConcurrent,a=i(e,sn),s=!1,m=Pn(),p=Pn(),y=Pn(),w=H({maxConcurrent:null!=f?f:10,maxPending:Infinity});return Promise.resolve(t(a)).then(function(r){if(!r)throw new Error("`publish` failed to create root observer");var e={stop:function(){s=!0,r.cancel(),p.forEach(function(n){return null==n||null==n.cancel?void 0:n.cancel()}),p.clear(),m.clear(),c("STOPPED")}};return null==n.onStop||n.onStop(e.stop),n.ready(),c("READY"),e})}catch(n){return Promise.reject(n)}}(n,c))},function(r){if(!v(n.error))throw r;n.error(r)}))}catch(n){return Promise.reject(n)}},exports.registerSoftRemove=function(n,r){var e=void 0===r?{}:r,t=e.docToCollSelectorPairs,o=e.fields,i=void 0===o?{_id:1}:o,u=e.keepModifier,c=e.when;if(!h(n))throw new TypeError("Collection must be an object");var f=l().getName(n);if(kn.has(n))throw new Error("'registerSoftRemove' already exists for collection '"+f+"'");if(![t,c].some(v))throw new TypeError("'"+f+"' 'registerSoftRemove' must provide at least one predicate.");kn.set(n,{fields:i,defaultKeepModifier:u,shouldKeepDoc:function(n){return w(v(c)&&c(n),function(r){return!!r||!!v(t)&&w(function(n,r){return w(n(r),function(n){if(!Array.isArray(n)||!n.every(Tn))throw new TypeError("'docToCollSelectorPairs' should return an array of '[Coll, selector]' tuples");return n})}(t,n),function(n){return w(function(n){return void 0===n&&(n=[]),w(n.map(function(n){return z(n[0],n[1])}),function(n){return n.some(function(n){return n})})}(n),function(n){return!!n})})})}})},exports.remove=fn,exports.setJoinPrefix=function(n){x=n},exports.setProtocol=function(n){void 0===n&&(n={}),f=o({},c,n)},exports.softRemove=function(n,r,e,t){void 0===r&&(r={});var i=(void 0===t?{}:t).detailed,u=void 0!==i&&i,c=function(n){var r=kn.get(n);if(!r){var e=l().getName(n);throw new Error("'softRemove' must be registered with 'registerSoftRemove' before using it with collection '"+e+"'")}return r}(n),f=c.fields,a=c.shouldKeepDoc,s=c.defaultKeepModifier;function d(n){var r=n.removed,e=void 0===r?0:r,t=n.updated,o=void 0===t?null:t;return u?{removed:e,updated:o}:(null!=e?e:0)+(null!=o?o:0)}return w(U(n,r,{fields:o({},null!=f?f:{},{_id:1}),transform:null}),function(t){return w(t.map(function(n){return w(a(n),function(r){return r?n._id:null})}),function(t){var o=t.filter(function(n){return null!==n});return o.length?w(function(n){if(Mn(n))return n||null;if(v(n))return w(n(),function(n){if(Mn(n))return n||null;throw new TypeError("'keepModifier' must be a valid modifier, a falsy value or a function that returns one of those.")});throw new TypeError("'keepModifier' must be a valid modifier, a falsy value or a function that returns one of those.")}(null!=e?e:s),function(e){return w([fn(n,{$and:[h(r)?r:{_id:r},{_id:{$nin:o}}]}),e?Sn(n,{_id:{$in:o}},e):null],function(n){return d({removed:n[0],updated:n[1]})})}):w(fn(n,r),function(n){return d({removed:n})})})})},exports.update=Sn;
|
|
2
2
|
//# sourceMappingURL=coll-fns.cjs.map
|