@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.
Files changed (49) hide show
  1. package/lib/context/delegation.d.ts +4 -0
  2. package/lib/context/delegation.js +1 -0
  3. package/lib/context/group.js +1 -1
  4. package/lib/context/join.js +1 -1
  5. package/lib/context/types.d.ts +16 -2
  6. package/lib/groups/broadcast-service.d.ts +60 -1
  7. package/lib/groups/broadcast-service.js +1 -1
  8. package/lib/groups/broadcast.d.ts +50 -0
  9. package/lib/groups/broadcast.js +1 -1
  10. package/lib/groups/events.d.ts +15 -5
  11. package/lib/groups/events.js +1 -1
  12. package/lib/groups/group-handle-registry.js +1 -1
  13. package/lib/groups/invite-payload.d.ts +16 -0
  14. package/lib/groups/join-utils.d.ts +68 -2
  15. package/lib/groups/join-utils.js +1 -1
  16. package/lib/groups/manager.d.ts +6 -4
  17. package/lib/groups/manager.js +1 -1
  18. package/lib/groups/store-received-grant.d.ts +47 -0
  19. package/lib/groups/store-received-grant.js +1 -0
  20. package/lib/groups/store-received-revocation.d.ts +46 -0
  21. package/lib/groups/store-received-revocation.js +1 -0
  22. package/lib/groups/wire-frame.d.ts +32 -0
  23. package/lib/groups/wire-frame.js +1 -0
  24. package/lib/hub/forward-remote-broadcast.d.ts +3 -3
  25. package/lib/hub/forward-remote-broadcast.js +1 -1
  26. package/lib/hub/group-channel.d.ts +8 -0
  27. package/lib/hub/group-channel.js +1 -1
  28. package/lib/hub/hub-connection.js +1 -1
  29. package/lib/hub/receive-handler.js +1 -1
  30. package/lib/hub/relay-manager.d.ts +7 -0
  31. package/lib/hub/relay-manager.js +1 -1
  32. package/lib/hub/send-handler.d.ts +16 -0
  33. package/lib/hub/send-handler.js +1 -1
  34. package/lib/hub/wiring.d.ts +14 -2
  35. package/lib/hub/wiring.js +1 -1
  36. package/lib/index.d.ts +1 -2
  37. package/lib/index.js +1 -1
  38. package/lib/schema.d.ts +2 -2
  39. package/lib/schema.js +47 -3
  40. package/lib/sync/broadcast-sender.js +1 -1
  41. package/lib/sync/forwarder.d.ts +1 -0
  42. package/lib/sync/forwarder.js +1 -1
  43. package/lib/sync/handlers.d.ts +5 -1
  44. package/lib/sync/handlers.js +1 -1
  45. package/lib/sync/merkle-apply.js +1 -1
  46. package/lib/types.d.ts +92 -1
  47. package/package.json +40 -40
  48. package/lib/sync/catalog-match.d.ts +0 -13
  49. package/lib/sync/catalog-match.js +0 -1
@@ -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>): Promise<boolean>;
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;
@@ -1 +1 @@
1
- import{checkCapability as e}from"@enkaku/capability";import{getGraphStore as t}from"@kubun/store-graph";import{resolveCatalogSyncScopes as n}from"./catalog-scope.js";import{createMerkleSyncChannelHandler as r}from"./merkle-channel.js";export async function checkSyncDelegation(t,n,r){if(!r||0===r.length)return!1;let o=["*","urn:kubun:user:*",`urn:kubun:user:${n}`],l="document/read";for(let s of o)try{return await e({act:l,res:s},{iss:t,sub:n,cap:r}),!0}catch{}for(let s of r)for(let r of o)try{return await e({act:l,res:r},{iss:t,sub:n,cap:s}),!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:o,graph:l,logger:s,peerRegistry:a}=e,c=e.storeUnreadable??"persist";return{"sync/negotiate":async e=>{let r,{scopes:l,delegationTokens:c,catalogIDs:i,knownModelIDs:u,direction:f}=e.param,d=e.message.payload,g=d.sub||d.iss;s.debug("sync/negotiate requested",{scopes:l,catalogIDs:i,viewerDID:g});let D=[],p=await t(o);if(null!=i&&i.length>0){let e=await n(o,i,u);if(e.modelIDs.length>0)if(null!=e.owners)for(let t of e.modelIDs)for(let n of e.owners){let e=g===n,r=!e&&await checkSyncDelegation(g,n,c);(e||r)&&D.push({modelID:t,ownerDID:n})}else for(let t of e.modelIDs)for(let e of(await p.getDistinctOwnersForModel(t))){let n=g===e,r=!n&&await checkSyncDelegation(g,e,c);(n||r)&&D.push({modelID:t,ownerDID:e})}e.missingClusterIDs.length>0&&(r=await p.getClusters(e.missingClusterIDs))}if(null!=l)for(let e of l){let t=g===e.ownerDID,n=!t&&await checkSyncDelegation(g,e.ownerDID,c);t||n?D.push(e):s.debug("sync/negotiate: scope rejected",{scope:e,viewerDID:g})}let h=new Set,m=D.filter(e=>{let t=`${e.modelID}:${e.ownerDID}`;return!h.has(t)&&(h.add(t),!0)});s.info("sync/negotiate completed",{requested:(l?.length??0)+(i?.length??0),accepted:m.length,missingClusters:null!=r?Object.keys(r).length:0});let w=f??"pull",y=await a.getPeer({peerDID:g,stores:o}),b=y?.allowedDirection??"both",I=negotiateDirection(w,b);return I!==w&&s.info("sync/negotiate: direction downgraded",{requested:w,allowed:b,agreed:I}),{direction:I,acceptedScopes:m,excludedDocumentIDs:[],...null!=r&&{missingClusters:r}}},"sync/merkle-sync":r({db:o,graph:l,logger:s,selfDID:e.selfDID,storeUnreadable:c,defaultAccessLevel:e.defaultAccessLevel})}}
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})}}
@@ -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:p,mutationJWTs:d}=e,m=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)=>m.getUserModelAccessDefault(t,e,a),isMemberOfAnyCircle:(e,a)=>t.isMemberOfAnyCircle(e,a),isMemberOfAnyGroup:(e,a)=>t.isMemberOfAnyGroup(e,a)},defaultAccessLevel:e.defaultAccessLevel??{read:"only_owner",write:"only_owner"}})}let f=0,h=0,y=0,w=0,g=0;for(let e of d){let r,u=i(e);if(await m.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(),d=o.fromString(s);if(null==await m.getDocument(d)&&"change"===r.typ){await m.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 p.applyVerifiedMutation({token:e,origin:"peer",...null!=n?{accessGate:n}:{}})).dropped){g++;continue}if(f++,"set"===r.typ)for(let t of(await m.getPendingMutations(s)))try{if((await p.applyVerifiedMutation({token:t.mutation_jwt,origin:"peer",...null!=n?{accessGate:n}:{}})).dropped){await m.updateMutationStatus(t.mutation_hash,"rejected"),g++;continue}await m.updateMutationStatus(t.mutation_hash,"applied"),f++}catch{await m.updateMutationStatus(t.mutation_hash,"rejected"),h++}}catch{await m.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:f,rejected:h,pending:y,skipped:w,dropped:g}}
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
- invite: (groupID: string, joinRequest: string) => Promise<InviteToGroupData>;
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.9.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.15.0",
18
- "@enkaku/capability": "^0.15.0",
19
- "@enkaku/client": "^0.15.1",
20
- "@enkaku/codec": "^0.15.0",
21
- "@enkaku/event": "^0.15.0",
22
- "@enkaku/generator": "^0.15.0",
23
- "@enkaku/group": "^0.15.0",
24
- "@enkaku/http-client-transport": "^0.15.0",
25
- "@enkaku/http-server-transport": "^0.15.0",
26
- "@enkaku/hub-protocol": "^0.15.0",
27
- "@enkaku/hub-tunnel": "^0.15.0",
28
- "@enkaku/protocol": "^0.15.0",
29
- "@enkaku/runtime": "^0.15.0",
30
- "@enkaku/schema": "^0.15.0",
31
- "@enkaku/server": "^0.15.0",
32
- "@enkaku/stream": "^0.15.0",
33
- "@enkaku/token": "^0.15.0",
34
- "@enkaku/transport": "^0.15.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.28.17",
38
- "@kubun/client": "^0.9.0",
39
- "@kubun/db": "^0.9.0",
40
- "@kubun/db-adapter": "^0.9.0",
41
- "@kubun/engine": "^0.9.0",
42
- "@kubun/store-p2p": "^0.9.0",
43
- "@kubun/store-graph": "^0.9.0",
44
- "@kubun/graphql": "^0.9.0",
45
- "@kubun/hlc": "^0.9.0",
46
- "@kubun/id": "^0.9.0",
47
- "@kubun/logger": "^0.9.0",
48
- "@kubun/mutation": "^0.9.0",
49
- "@kubun/protocol": "^0.9.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.15.0",
52
+ "@enkaku/hub-server": "^0.16.0",
53
53
  "get-port": "^7.2.0",
54
- "@kubun/db-node-sqlite": "^0.9.0",
55
- "@kubun/db-better-sqlite": "^0.9.0",
56
- "@kubun/hub": "^0.9.0",
57
- "@kubun/plugin-connector": "^0.9.0",
58
- "@kubun/plugin-http": "^0.9.0",
59
- "@kubun/plugin-rpc": "^0.9.0",
60
- "@kubun/test-utils": "^0.9.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))}