@kubun/plugin-p2p 0.9.0 → 0.10.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/lib/context/delegation.d.ts +4 -0
- package/lib/context/delegation.js +1 -0
- package/lib/context/group.js +1 -1
- package/lib/context/join.js +1 -1
- package/lib/context/types.d.ts +16 -2
- package/lib/groups/broadcast-service.d.ts +60 -1
- package/lib/groups/broadcast-service.js +1 -1
- package/lib/groups/broadcast.d.ts +50 -0
- package/lib/groups/broadcast.js +1 -1
- package/lib/groups/events.d.ts +15 -5
- package/lib/groups/events.js +1 -1
- package/lib/groups/group-handle-registry.js +1 -1
- package/lib/groups/invite-payload.d.ts +16 -0
- package/lib/groups/join-utils.d.ts +68 -2
- package/lib/groups/join-utils.js +1 -1
- package/lib/groups/manager.d.ts +6 -4
- package/lib/groups/manager.js +1 -1
- package/lib/groups/store-received-grant.d.ts +47 -0
- package/lib/groups/store-received-grant.js +1 -0
- package/lib/groups/store-received-revocation.d.ts +46 -0
- package/lib/groups/store-received-revocation.js +1 -0
- package/lib/groups/wire-frame.d.ts +32 -0
- package/lib/groups/wire-frame.js +1 -0
- package/lib/hub/forward-remote-broadcast.d.ts +3 -3
- package/lib/hub/forward-remote-broadcast.js +1 -1
- package/lib/hub/group-channel.d.ts +8 -0
- package/lib/hub/group-channel.js +1 -1
- package/lib/hub/hub-connection.js +1 -1
- package/lib/hub/receive-handler.js +1 -1
- package/lib/hub/relay-manager.d.ts +7 -0
- package/lib/hub/relay-manager.js +1 -1
- package/lib/hub/send-handler.d.ts +16 -0
- package/lib/hub/send-handler.js +1 -1
- package/lib/hub/wiring.d.ts +14 -2
- package/lib/hub/wiring.js +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -1
- package/lib/schema.d.ts +2 -2
- package/lib/schema.js +47 -3
- package/lib/sync/broadcast-sender.js +1 -1
- package/lib/sync/forwarder.d.ts +1 -0
- package/lib/sync/forwarder.js +1 -1
- package/lib/sync/handlers.d.ts +5 -1
- package/lib/sync/handlers.js +1 -1
- package/lib/sync/merkle-apply.js +1 -1
- package/lib/types.d.ts +92 -1
- package/package.json +40 -40
- package/lib/sync/catalog-match.d.ts +0 -13
- package/lib/sync/catalog-match.js +0 -1
package/lib/sync/handlers.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type VerifyTokenHook } from '@enkaku/capability';
|
|
1
2
|
import type { KubunDB } from '@kubun/db';
|
|
2
3
|
import type { DefaultAccessLevel, GraphInternals } from '@kubun/engine';
|
|
3
4
|
import type { Logger } from '@kubun/logger';
|
|
@@ -10,9 +11,12 @@ import type { PeerRegistry } from './peer-registry.js';
|
|
|
10
11
|
* @param viewerDID - The DID of the requesting viewer
|
|
11
12
|
* @param ownerDID - The DID of the document owner
|
|
12
13
|
* @param delegationTokens - Array of delegation JWT tokens
|
|
14
|
+
* @param revocationChecker - Optional per-leaf-capability verification hook.
|
|
15
|
+
* When set, capabilities whose `jti` has been revoked cause the check to
|
|
16
|
+
* fail closed.
|
|
13
17
|
* @returns true if any token grants read access
|
|
14
18
|
*/
|
|
15
|
-
export declare function checkSyncDelegation(viewerDID: string, ownerDID: string, delegationTokens: Array<string
|
|
19
|
+
export declare function checkSyncDelegation(viewerDID: string, ownerDID: string, delegationTokens: Array<string>, revocationChecker?: VerifyTokenHook): Promise<boolean>;
|
|
16
20
|
export type CreateSyncHandlersParams = {
|
|
17
21
|
db: KubunDB;
|
|
18
22
|
graph: GraphInternals;
|
package/lib/sync/handlers.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{checkCapability as e}from"@enkaku/capability";import{getGraphStore as
|
|
1
|
+
import{checkCapability as e,createRevocationChecker as t}from"@enkaku/capability";import{getGraphStore as n}from"@kubun/store-graph";import{createP2PRevocationBackend as r,getP2PStore as o}from"@kubun/store-p2p";import{resolveCatalogSyncScopes as l}from"./catalog-scope.js";import{createMerkleSyncChannelHandler as a}from"./merkle-channel.js";export async function checkSyncDelegation(t,n,r,o){if(!r||0===r.length)return!1;let l=["*","urn:kubun:user:*",`urn:kubun:user:${n}`],a="document/read";for(let s of l)try{return await e({act:a,res:s},{iss:t,sub:n,cap:r},{verifyToken:o}),!0}catch{}for(let s of r)for(let r of l)try{return await e({act:a,res:r},{iss:t,sub:n,cap:s},{verifyToken:o}),!0}catch{}return!1}export function negotiateDirection(e,t){return"both"===t?e:"both"===e?t:e===t?e:t}export function createSyncHandlers(e){let{db:s,graph:i,logger:c,peerRegistry:u}=e,f=e.storeUnreadable??"persist",d=null;async function g(){return null==d&&(d=t(r(await o(s)))),d}return{"sync/negotiate":async e=>{let t,{scopes:r,delegationTokens:o,catalogIDs:a,knownModelIDs:i,direction:f}=e.param,d=e.message.payload,p=d.sub||d.iss;c.debug("sync/negotiate requested",{scopes:r,catalogIDs:a,viewerDID:p});let D=[],m=await n(s);if(null!=a&&a.length>0){let e=await l(s,a,i);if(e.modelIDs.length>0)if(null!=e.owners)for(let t of e.modelIDs)for(let n of e.owners){let e=p===n,r=!e&&await checkSyncDelegation(p,n,o,await g());(e||r)&&D.push({modelID:t,ownerDID:n})}else for(let t of e.modelIDs)for(let e of(await m.getDistinctOwnersForModel(t))){let n=p===e,r=!n&&await checkSyncDelegation(p,e,o,await g());(n||r)&&D.push({modelID:t,ownerDID:e})}e.missingClusterIDs.length>0&&(t=await m.getClusters(e.missingClusterIDs))}if(null!=r)for(let e of r){let t=p===e.ownerDID,n=!t&&await checkSyncDelegation(p,e.ownerDID,o,await g());t||n?D.push(e):c.debug("sync/negotiate: scope rejected",{scope:e,viewerDID:p})}let w=new Set,h=D.filter(e=>{let t=`${e.modelID}:${e.ownerDID}`;return!w.has(t)&&(w.add(t),!0)});c.info("sync/negotiate completed",{requested:(r?.length??0)+(a?.length??0),accepted:h.length,missingClusters:null!=t?Object.keys(t).length:0});let y=f??"pull",b=await u.getPeer({peerDID:p,stores:s}),k=b?.allowedDirection??"both",I=negotiateDirection(y,k);return I!==y&&c.info("sync/negotiate: direction downgraded",{requested:y,allowed:k,agreed:I}),{direction:I,acceptedScopes:h,excludedDocumentIDs:[],...null!=t&&{missingClusters:t}}},"sync/merkle-sync":a({db:s,graph:i,logger:c,selfDID:e.selfDID,storeUnreadable:f,defaultAccessLevel:e.defaultAccessLevel})}}
|
package/lib/sync/merkle-apply.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{asType as t,createValidator as e}from"@enkaku/schema";import{verifyToken as a}from"@enkaku/token";import{computeMutationHash as i}from"@kubun/engine";import{DocumentID as o}from"@kubun/id";import{documentMutation as n}from"@kubun/protocol";import{getGraphStore as r}from"@kubun/store-graph";import{getP2PStore as u}from"@kubun/store-p2p";import{createReceiveAccessGate as s}from"./receive-access-gate.js";let l=e(n);export async function applySyncMutations(e){let n,{db:c,graph:
|
|
1
|
+
import{asType as t,createValidator as e}from"@enkaku/schema";import{verifyToken as a}from"@enkaku/token";import{computeMutationHash as i}from"@kubun/engine";import{DocumentID as o}from"@kubun/id";import{documentMutation as n}from"@kubun/protocol";import{getGraphStore as r}from"@kubun/store-graph";import{getP2PStore as u}from"@kubun/store-p2p";import{createReceiveAccessGate as s}from"./receive-access-gate.js";let l=e(n);export async function applySyncMutations(e){let n,{db:c,graph:d,mutationJWTs:p}=e,f=await r(c);if("drop"===(e.storeUnreadable??"persist")){if(null==e.selfDID)throw Error("applySyncMutations: 'storeUnreadable: drop' requires selfDID");let t=await u(c);n=s({selfDID:e.selfDID,db:{getUserModelAccessDefault:(t,e,a)=>f.getUserModelAccessDefault(t,e,a),isMemberOfAnyCircle:(e,a)=>t.isMemberOfAnyCircle(e,a),isMemberOfAnyGroup:(e,a)=>t.isMemberOfAnyGroup(e,a),getModelInterfaces:t=>f.getModelInterfaces(t)},defaultAccessLevel:e.defaultAccessLevel??{read:"only_owner",write:"only_owner"}})}let m=0,h=0,y=0,w=0,g=0;for(let e of p){let r,u=i(e);if(await f.hasMutationHash(u)){w++;continue}try{let i=await a(e);r=t(l,i.payload)}catch{h++;continue}let s=r.sub,c=o.fromString(s).model.toString(),p=o.fromString(s);if(null==await f.getDocument(p)&&"change"===r.typ){await f.insertMutationLogEntry({mutation_hash:u,model_id:c,document_id:s,author_did:r.iss,hlc:r.hlc,mutation_jwt:e,status:"pending"}),y++;continue}try{if((await d.applyVerifiedMutation({token:e,origin:"peer",...null!=n?{accessGate:n}:{}})).dropped){g++;continue}if(m++,"set"===r.typ)for(let t of(await f.getPendingMutations(s)))try{if((await d.applyVerifiedMutation({token:t.mutation_jwt,origin:"peer",...null!=n?{accessGate:n}:{}})).dropped){await f.updateMutationStatus(t.mutation_hash,"rejected"),g++;continue}await f.updateMutationStatus(t.mutation_hash,"applied"),m++}catch{await f.updateMutationStatus(t.mutation_hash,"rejected"),h++}}catch{await f.insertMutationLogEntry({mutation_hash:u,model_id:c,document_id:s,author_did:r.iss,hlc:r.hlc,mutation_jwt:e,status:"rejected"}),h++}}return{applied:m,rejected:h,pending:y,skipped:w,dropped:g}}
|
package/lib/types.d.ts
CHANGED
|
@@ -115,7 +115,15 @@ export type GroupRequestContext = {
|
|
|
115
115
|
filterCriteria: string;
|
|
116
116
|
}) => Promise<CatalogData>;
|
|
117
117
|
listCatalogs: (ownerDID?: string) => Promise<Array<CatalogData>>;
|
|
118
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Build an invite payload for a join request.
|
|
120
|
+
*
|
|
121
|
+
* `grants` are stringified write-capability JWTs the caller wants the joiner
|
|
122
|
+
* to hold immediately on join. `revocations` are signed revocation JWTs the
|
|
123
|
+
* caller wants the joiner to apply immediately — only verified ones travel;
|
|
124
|
+
* pending revocations (cap not yet known by the inviter) do not.
|
|
125
|
+
*/
|
|
126
|
+
invite: (groupID: string, joinRequest: string, grants?: Array<string>, revocations?: Array<string>) => Promise<InviteToGroupData>;
|
|
119
127
|
join: (invitePayload: string, joinRequestPayload: string) => Promise<JoinGroupData>;
|
|
120
128
|
leave: (groupID: string) => Promise<LeaveGroupData>;
|
|
121
129
|
removeMember: (groupID: string, memberDID: string) => Promise<RemoveGroupMemberData>;
|
|
@@ -129,6 +137,53 @@ export type GroupRequestContext = {
|
|
|
129
137
|
deleteCatalog: (catalogID: string) => Promise<DeleteCatalogData>;
|
|
130
138
|
deleteCircle: (circleID: string) => Promise<DeleteCircleData>;
|
|
131
139
|
removeCircleMember: (circleID: string, memberDID: string) => Promise<RemoveCircleMemberData>;
|
|
140
|
+
/**
|
|
141
|
+
* Mint a `document/write` capability granting `to` write access on resources
|
|
142
|
+
* matching `res`. Token is stored grantor-side, broadcast to the group, and
|
|
143
|
+
* returned for direct delivery.
|
|
144
|
+
*
|
|
145
|
+
* `res` is a URN. Most-specific wins; broader URNs grant strictly more:
|
|
146
|
+
* - `urn:kubun:document:<docID>` — single doc
|
|
147
|
+
* - `urn:kubun:model:<modelID>` — every doc of that model owned by the grantor
|
|
148
|
+
* - `urn:kubun:model:<interfaceID>` — every doc of every model implementing
|
|
149
|
+
* the interface (footgun: a grant on a widely-implemented interface like
|
|
150
|
+
* `Owned` or `Timestamped` becomes a near-wildcard)
|
|
151
|
+
* - `urn:kubun:user:<DID>` — every doc owned by that DID (the grantor)
|
|
152
|
+
* - `*` — every doc the grantor owns, present and future
|
|
153
|
+
*
|
|
154
|
+
* Prefer the narrowest URN that satisfies the use case. Broad grants combine
|
|
155
|
+
* with the long default `exp` (30 days) to expand the blast radius of a
|
|
156
|
+
* leaked or misdirected token.
|
|
157
|
+
*/
|
|
158
|
+
grantWriteCapability: (params: {
|
|
159
|
+
to: string;
|
|
160
|
+
res: string;
|
|
161
|
+
groupID: string;
|
|
162
|
+
expiresIn?: number;
|
|
163
|
+
}) => Promise<string>;
|
|
164
|
+
/**
|
|
165
|
+
* Revoke a previously-granted `document/write` capability by its `jti`.
|
|
166
|
+
*
|
|
167
|
+
* Revocation is binary: once a peer learns of the revocation, every
|
|
168
|
+
* mutation that authenticates via this `jti` is denied. The check is
|
|
169
|
+
* reactive, not retroactive — mutations already applied locally stay
|
|
170
|
+
* applied; only future writes carrying the revoked `jti` are gated.
|
|
171
|
+
*
|
|
172
|
+
* Only the original capability issuer may revoke it. The resolver looks up
|
|
173
|
+
* the capability locally and rejects:
|
|
174
|
+
* - `REVOCATION_CAP_UNKNOWN` when no row matches the `jti` on this peer
|
|
175
|
+
* (multi-device-grantor case, where the issuing device is not the one
|
|
176
|
+
* calling `revokeCapability`, is not yet supported).
|
|
177
|
+
* - `REVOCATION_UNAUTHORIZED` when the viewer is not the capability's
|
|
178
|
+
* issuer.
|
|
179
|
+
*
|
|
180
|
+
* Returns the boolean reported by the store: `true` when the revocation
|
|
181
|
+
* row was newly written (or materially changed), `false` on an idempotent
|
|
182
|
+
* no-op (already revoked at an equal or newer HLC).
|
|
183
|
+
*/
|
|
184
|
+
revokeCapability: (params: {
|
|
185
|
+
jti: string;
|
|
186
|
+
}) => Promise<boolean>;
|
|
132
187
|
};
|
|
133
188
|
export type SyncRequestContext = {
|
|
134
189
|
addPeer: (config: PeerConfig) => Promise<void>;
|
|
@@ -176,11 +231,47 @@ export type HubRequestContext = {
|
|
|
176
231
|
listByGroup: (groupID: string) => Promise<Array<HubData>>;
|
|
177
232
|
listGroups: (hubID: string) => Promise<Array<GroupData>>;
|
|
178
233
|
};
|
|
234
|
+
export type DelegationData = {
|
|
235
|
+
jwt: string;
|
|
236
|
+
jti: string;
|
|
237
|
+
grantor: string;
|
|
238
|
+
audience: string;
|
|
239
|
+
resource: string;
|
|
240
|
+
exp: number;
|
|
241
|
+
};
|
|
242
|
+
export type DelegationTokenCovers = {
|
|
243
|
+
modelID?: string | null;
|
|
244
|
+
docID?: string | null;
|
|
245
|
+
};
|
|
246
|
+
export type ListOwnDelegationTokensParams = {
|
|
247
|
+
viewerDID: string;
|
|
248
|
+
grantor?: string | null;
|
|
249
|
+
covers?: DelegationTokenCovers | null;
|
|
250
|
+
};
|
|
251
|
+
export type RevokedDelegationData = {
|
|
252
|
+
jti: string;
|
|
253
|
+
grantor: string;
|
|
254
|
+
audience: string;
|
|
255
|
+
revokerDID: string;
|
|
256
|
+
revokedAt: number;
|
|
257
|
+
verifiedAt: number;
|
|
258
|
+
capExp: number | null;
|
|
259
|
+
groupID: string;
|
|
260
|
+
};
|
|
261
|
+
export type ListOwnRevokedTokensParams = {
|
|
262
|
+
viewerDID: string;
|
|
263
|
+
grantor?: string | null;
|
|
264
|
+
};
|
|
265
|
+
export type DelegationRequestContext = {
|
|
266
|
+
listOwnTokens: (params: ListOwnDelegationTokensParams) => Promise<Array<DelegationData>>;
|
|
267
|
+
listOwnRevokedTokens: (params: ListOwnRevokedTokensParams) => Promise<Array<RevokedDelegationData>>;
|
|
268
|
+
};
|
|
179
269
|
export type P2PContext = {
|
|
180
270
|
group: GroupRequestContext;
|
|
181
271
|
sync: SyncRequestContext;
|
|
182
272
|
join: P2PJoinRequestContext;
|
|
183
273
|
hub: HubRequestContext;
|
|
274
|
+
delegation: DelegationRequestContext;
|
|
184
275
|
};
|
|
185
276
|
declare module '@kubun/graphql' {
|
|
186
277
|
interface PluginContextMap {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/plugin-p2p",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -14,50 +14,50 @@
|
|
|
14
14
|
],
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@enkaku/async": "^0.
|
|
18
|
-
"@enkaku/capability": "^0.
|
|
19
|
-
"@enkaku/client": "^0.
|
|
20
|
-
"@enkaku/codec": "^0.
|
|
21
|
-
"@enkaku/event": "^0.
|
|
22
|
-
"@enkaku/generator": "^0.
|
|
23
|
-
"@enkaku/group": "^0.
|
|
24
|
-
"@enkaku/http-client-transport": "^0.
|
|
25
|
-
"@enkaku/http-server-transport": "^0.
|
|
26
|
-
"@enkaku/hub-protocol": "^0.
|
|
27
|
-
"@enkaku/hub-tunnel": "^0.
|
|
28
|
-
"@enkaku/protocol": "^0.
|
|
29
|
-
"@enkaku/runtime": "^0.
|
|
30
|
-
"@enkaku/schema": "^0.
|
|
31
|
-
"@enkaku/server": "^0.
|
|
32
|
-
"@enkaku/stream": "^0.
|
|
33
|
-
"@enkaku/token": "^0.
|
|
34
|
-
"@enkaku/transport": "^0.
|
|
17
|
+
"@enkaku/async": "^0.16.0",
|
|
18
|
+
"@enkaku/capability": "^0.16.0",
|
|
19
|
+
"@enkaku/client": "^0.16.0",
|
|
20
|
+
"@enkaku/codec": "^0.16.0",
|
|
21
|
+
"@enkaku/event": "^0.16.0",
|
|
22
|
+
"@enkaku/generator": "^0.16.0",
|
|
23
|
+
"@enkaku/group": "^0.16.1",
|
|
24
|
+
"@enkaku/http-client-transport": "^0.16.0",
|
|
25
|
+
"@enkaku/http-server-transport": "^0.16.0",
|
|
26
|
+
"@enkaku/hub-protocol": "^0.16.0",
|
|
27
|
+
"@enkaku/hub-tunnel": "^0.16.0",
|
|
28
|
+
"@enkaku/protocol": "^0.16.0",
|
|
29
|
+
"@enkaku/runtime": "^0.16.0",
|
|
30
|
+
"@enkaku/schema": "^0.16.0",
|
|
31
|
+
"@enkaku/server": "^0.16.0",
|
|
32
|
+
"@enkaku/stream": "^0.16.0",
|
|
33
|
+
"@enkaku/token": "^0.16.0",
|
|
34
|
+
"@enkaku/transport": "^0.16.0",
|
|
35
35
|
"@noble/hashes": "^2.2.0",
|
|
36
36
|
"graphql": "^16.13.2",
|
|
37
|
-
"kysely": "^0.
|
|
38
|
-
"@kubun/client": "^0.
|
|
39
|
-
"@kubun/db": "^0.
|
|
40
|
-
"@kubun/
|
|
41
|
-
"@kubun/
|
|
42
|
-
"@kubun/
|
|
43
|
-
"@kubun/
|
|
44
|
-
"@kubun/
|
|
45
|
-
"@kubun/
|
|
46
|
-
"@kubun/
|
|
47
|
-
"@kubun/
|
|
48
|
-
"@kubun/
|
|
49
|
-
"@kubun/protocol": "^0.
|
|
37
|
+
"kysely": "^0.29.2",
|
|
38
|
+
"@kubun/client": "^0.10.0",
|
|
39
|
+
"@kubun/db": "^0.10.0",
|
|
40
|
+
"@kubun/store-graph": "^0.10.0",
|
|
41
|
+
"@kubun/graphql": "^0.10.0",
|
|
42
|
+
"@kubun/db-adapter": "^0.10.0",
|
|
43
|
+
"@kubun/hlc": "^0.10.0",
|
|
44
|
+
"@kubun/id": "^0.10.0",
|
|
45
|
+
"@kubun/engine": "^0.10.0",
|
|
46
|
+
"@kubun/store-p2p": "^0.10.0",
|
|
47
|
+
"@kubun/mutation": "^0.10.0",
|
|
48
|
+
"@kubun/logger": "^0.10.0",
|
|
49
|
+
"@kubun/protocol": "^0.10.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@enkaku/hub-server": "^0.
|
|
52
|
+
"@enkaku/hub-server": "^0.16.0",
|
|
53
53
|
"get-port": "^7.2.0",
|
|
54
|
-
"@kubun/db-
|
|
55
|
-
"@kubun/
|
|
56
|
-
"@kubun/hub": "^0.
|
|
57
|
-
"@kubun/
|
|
58
|
-
"@kubun/plugin-http": "^0.
|
|
59
|
-
"@kubun/plugin-rpc": "^0.
|
|
60
|
-
"@kubun/test-utils": "^0.
|
|
54
|
+
"@kubun/db-better-sqlite": "^0.10.0",
|
|
55
|
+
"@kubun/plugin-connector": "^0.10.0",
|
|
56
|
+
"@kubun/hub": "^0.10.0",
|
|
57
|
+
"@kubun/db-node-sqlite": "^0.10.0",
|
|
58
|
+
"@kubun/plugin-http": "^0.10.0",
|
|
59
|
+
"@kubun/plugin-rpc": "^0.10.0",
|
|
60
|
+
"@kubun/test-utils": "^0.10.0"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build:clean": "del lib",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { CatalogFilterCriteria, DocumentNode } from '@kubun/protocol';
|
|
2
|
-
import type { P2PStoreAPI } from '@kubun/store-p2p';
|
|
3
|
-
/**
|
|
4
|
-
* Determine whether a document matches a catalog's filter criteria.
|
|
5
|
-
*
|
|
6
|
-
* Mirrors the semantics of {@link resolveCatalogSyncScopes} (which collects
|
|
7
|
-
* broadly-applicable models + owner filters for sync): each catalog field is
|
|
8
|
-
* AND'd, values within a field are OR'd, and the `circles` field expands to a
|
|
9
|
-
* union of circle members and merges with the explicit `owners` filter.
|
|
10
|
-
*
|
|
11
|
-
* Returns `true` iff the document would be included by this catalog.
|
|
12
|
-
*/
|
|
13
|
-
export declare function catalogMatchesDoc(criteria: CatalogFilterCriteria, doc: Pick<DocumentNode, 'model' | 'owner'>, p2pStore: P2PStoreAPI): Promise<boolean>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export async function catalogMatchesDoc(e,l,n){if(null!=e.models&&e.models.length>0&&!e.models.includes(l.model))return!1;let c=null!=e.owners&&e.owners.length>0,r=null!=e.circles&&e.circles.length>0;return!!(!c&&!r||c&&e.owners?.includes(l.owner)||r&&null!=e.circles&&await n.isMemberOfAnyCircle(l.owner,e.circles))}
|