@kubun/plugin-p2p 0.8.0 → 0.8.2

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 (73) hide show
  1. package/lib/context/group.d.ts +4 -0
  2. package/lib/context/group.js +1 -0
  3. package/lib/context/join.js +1 -1
  4. package/lib/context/sync.js +1 -1
  5. package/lib/context/types.d.ts +7 -8
  6. package/lib/groups/broadcast-codec.d.ts +3 -0
  7. package/lib/groups/broadcast-service.d.ts +76 -0
  8. package/lib/groups/broadcast-service.js +1 -0
  9. package/lib/{spaces → groups}/broadcast.d.ts +9 -10
  10. package/lib/groups/broadcast.js +1 -0
  11. package/lib/groups/events.d.ts +38 -0
  12. package/lib/{spaces → groups}/events.js +1 -1
  13. package/lib/{spaces → groups}/invite-payload.d.ts +2 -2
  14. package/lib/groups/join-utils.d.ts +19 -0
  15. package/lib/groups/join-utils.js +1 -0
  16. package/lib/{spaces → groups}/manager.d.ts +56 -46
  17. package/lib/groups/manager.js +1 -0
  18. package/lib/groups/mls-group-handle.d.ts +4 -0
  19. package/lib/groups/mls-group-handle.js +1 -0
  20. package/lib/groups/mls-state.d.ts +42 -0
  21. package/lib/groups/mls-state.js +1 -0
  22. package/lib/hub/connection-pool.d.ts +19 -0
  23. package/lib/hub/connection-pool.js +1 -0
  24. package/lib/hub/group-channel.d.ts +51 -0
  25. package/lib/hub/group-channel.js +1 -0
  26. package/lib/hub/receive-handler.d.ts +36 -0
  27. package/lib/hub/receive-handler.js +1 -0
  28. package/lib/hub/relay-manager.d.ts +37 -0
  29. package/lib/hub/relay-manager.js +1 -0
  30. package/lib/hub/send-handler.d.ts +28 -0
  31. package/lib/hub/send-handler.js +1 -0
  32. package/lib/index.d.ts +14 -13
  33. package/lib/index.js +1 -1
  34. package/lib/protocol.d.ts +44 -10
  35. package/lib/protocol.js +1 -1
  36. package/lib/schema.d.ts +2 -2
  37. package/lib/schema.js +42 -42
  38. package/lib/sync/catalog-scope.js +1 -1
  39. package/lib/sync/handlers.d.ts +10 -0
  40. package/lib/sync/handlers.js +1 -1
  41. package/lib/sync/merkle-apply.js +1 -1
  42. package/lib/sync/merkle-channel.d.ts +18 -0
  43. package/lib/sync/merkle-channel.js +1 -0
  44. package/lib/sync/merkle-tree.d.ts +3 -1
  45. package/lib/sync/merkle-tree.js +1 -1
  46. package/lib/sync/peer-registry.d.ts +27 -8
  47. package/lib/sync/peer-registry.js +1 -1
  48. package/lib/sync/sync-client.d.ts +15 -13
  49. package/lib/sync/sync-client.js +1 -1
  50. package/lib/sync/sync-manager.d.ts +36 -11
  51. package/lib/sync/sync-manager.js +1 -1
  52. package/lib/types.d.ts +42 -40
  53. package/package.json +20 -16
  54. package/lib/context/space.d.ts +0 -4
  55. package/lib/context/space.js +0 -1
  56. package/lib/migrations.d.ts +0 -8
  57. package/lib/migrations.js +0 -1
  58. package/lib/spaces/broadcast-codec.d.ts +0 -3
  59. package/lib/spaces/broadcast-service.d.ts +0 -59
  60. package/lib/spaces/broadcast-service.js +0 -1
  61. package/lib/spaces/broadcast.js +0 -1
  62. package/lib/spaces/events.d.ts +0 -38
  63. package/lib/spaces/group-handle.d.ts +0 -3
  64. package/lib/spaces/group-handle.js +0 -1
  65. package/lib/spaces/join-utils.d.ts +0 -22
  66. package/lib/spaces/join-utils.js +0 -1
  67. package/lib/spaces/manager.js +0 -1
  68. package/lib/spaces/mls-state.d.ts +0 -27
  69. package/lib/spaces/mls-state.js +0 -1
  70. /package/lib/{spaces → groups}/broadcast-codec.js +0 -0
  71. /package/lib/{spaces → groups}/invite-payload.js +0 -0
  72. /package/lib/{spaces → groups}/mls-json.d.ts +0 -0
  73. /package/lib/{spaces → groups}/mls-json.js +0 -0
@@ -1 +0,0 @@
1
- import{EventEmitter as e}from"@enkaku/event";import{processBroadcast as a}from"./broadcast.js";import{deserializeBroadcast as r,serializeBroadcast as t}from"./broadcast-codec.js";import{restoreGroupHandle as s}from"./group-handle.js";import{replacer as o,reviver as c}from"./mls-json.js";import{serializeGroupState as d}from"./mls-state.js";export class BroadcastService extends e{#e;constructor(e){super(),this.#e={kysely:e.kysely,adapter:e.adapter}}async prepareSend(e){let{message:a,groupState:r}=e,c=t(a),i=await s(r),{message:m}=await i.encrypt(c),n=d(i);return{encrypted:new TextEncoder().encode(JSON.stringify(m,o)),updatedGroupState:n}}async processReceived(e){let{spaceID:t,encrypted:o,groupState:i}=e,m=await s(i),n=JSON.parse(new TextDecoder().decode(o),c),p=r(await m.decrypt(n)),y=await a(this.#e,p),l=d(m);return await this.emit("broadcast",{spaceID:t,message:p,applied:y}),{message:p,applied:y,updatedGroupState:l}}}
@@ -1 +0,0 @@
1
- import{HLC as e}from"@kubun/hlc";function t(t,c){return e.compare(e.parse(t),e.parse(c))>0}export async function processBroadcast(e,c){let{kysely:a,adapter:l}=e;switch(c.type){case"circle:create":{let e=await a.selectFrom("kubun_circles").selectAll().where("id","=",c.circle.id).executeTakeFirst();if(null!=e){if(!t(c.circle.hlc,e.hlc))return!1;let r={name:c.circle.name,description:c.circle.description,catalog_ids:l.encodeJSON(c.circle.catalogIDs),hlc:c.circle.hlc,updated_at:l.encodeTimestamp(new Date)};return await a.updateTable("kubun_circles").set(r).where("id","=",c.circle.id).execute(),!0}return await a.insertInto("kubun_circles").values({id:c.circle.id,space_id:c.circle.spaceID,name:c.circle.name,description:c.circle.description,catalog_ids:l.encodeJSON(c.circle.catalogIDs),hlc:c.circle.hlc}).execute(),!0}case"circle:update":{let e=await a.selectFrom("kubun_circles").selectAll().where("id","=",c.circleID).executeTakeFirst();if(null==e||!t(c.update.hlc,e.hlc))return!1;let r={};return null!=c.update.name&&(r.name=c.update.name),null!=c.update.description&&(r.description=c.update.description),null!=c.update.catalogIDs&&(r.catalog_ids=l.encodeJSON(c.update.catalogIDs)),r.hlc=c.update.hlc,r.updated_at=l.encodeTimestamp(new Date),await a.updateTable("kubun_circles").set(r).where("id","=",c.circleID).execute(),!0}case"circle:delete":{let e=await a.selectFrom("kubun_circles").selectAll().where("id","=",c.circleID).executeTakeFirst();if(null==e||!t(c.hlc,e.hlc))return!1;return await a.deleteFrom("kubun_circles").where("id","=",c.circleID).execute(),!0}case"member:add":return await a.insertInto("kubun_circle_members").values({circle_id:c.member.circleID,member_did:c.member.memberDID,role:c.member.role,hlc:c.member.hlc}).onConflict(e=>e.columns(["circle_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),hlc:e.ref("excluded.hlc")}))).execute(),!0;case"member:remove":return await a.deleteFrom("kubun_circle_members").where("circle_id","=",c.circleID).where("member_did","=",c.memberDID).execute(),!0;case"catalog:create":{let e=await a.selectFrom("kubun_catalogs").selectAll().where("id","=",c.catalog.id).executeTakeFirst();if(null!=e){if(!t(c.catalog.hlc,e.hlc))return!1;let r={name:c.catalog.name,description:c.catalog.description,filter_criteria:l.encodeJSON(c.catalog.filterCriteria),hlc:c.catalog.hlc,updated_at:l.encodeTimestamp(new Date)};return await a.updateTable("kubun_catalogs").set(r).where("id","=",c.catalog.id).execute(),!0}return await a.insertInto("kubun_catalogs").values({id:c.catalog.id,owner_did:c.catalog.ownerDID,name:c.catalog.name,description:c.catalog.description,filter_criteria:l.encodeJSON(c.catalog.filterCriteria),hlc:c.catalog.hlc}).execute(),!0}case"catalog:update":{let e=await a.selectFrom("kubun_catalogs").selectAll().where("id","=",c.catalogID).executeTakeFirst();if(null==e||!t(c.update.hlc,e.hlc))return!1;let r={};return null!=c.update.name&&(r.name=c.update.name),null!=c.update.description&&(r.description=c.update.description),null!=c.update.filterCriteria&&(r.filter_criteria=l.encodeJSON(c.update.filterCriteria)),r.hlc=c.update.hlc,r.updated_at=l.encodeTimestamp(new Date),await a.updateTable("kubun_catalogs").set(r).where("id","=",c.catalogID).execute(),!0}case"catalog:delete":{let e=await a.selectFrom("kubun_catalogs").selectAll().where("id","=",c.catalogID).executeTakeFirst();if(null==e||!t(c.hlc,e.hlc))return!1;return await a.deleteFrom("kubun_catalogs").where("id","=",c.catalogID).execute(),!0}case"space:update":{let e=await a.selectFrom("kubun_spaces").selectAll().where("id","=",c.spaceID).executeTakeFirst();if(null==e||!t(c.update.hlc,e.hlc))return!1;let r={};return null!=c.update.name&&(r.name=c.update.name),null!=c.update.description&&(r.description=c.update.description),null!=c.update.hubURLs&&(r.hub_urls=l.encodeJSON(c.update.hubURLs)),r.hlc=c.update.hlc,r.updated_at=l.encodeTimestamp(new Date),await a.updateTable("kubun_spaces").set(r).where("id","=",c.spaceID).execute(),!0}}}
@@ -1,38 +0,0 @@
1
- import { EventEmitter } from '@enkaku/event';
2
- import type { CircleData, CircleMemberData, SpaceData, SpaceMemberData } from '../index.js';
3
- export type SpaceEventMap = {
4
- spaceJoined: SpaceData;
5
- spaceLeft: SpaceData & {
6
- spaceID: string;
7
- };
8
- spaceDataChanged: SpaceData & {
9
- spaceID: string;
10
- };
11
- spaceMemberJoined: SpaceMemberData & {
12
- spaceID: string;
13
- };
14
- spaceMemberLeft: SpaceMemberData & {
15
- spaceID: string;
16
- };
17
- circleCreated: CircleData & {
18
- spaceID: string;
19
- };
20
- circleDeleted: CircleData & {
21
- spaceID: string;
22
- };
23
- circleDataChanged: CircleData & {
24
- circleID: string;
25
- };
26
- circleMemberAdded: CircleMemberData & {
27
- circleID: string;
28
- };
29
- circleMemberRemoved: CircleMemberData & {
30
- circleID: string;
31
- };
32
- circleCatalogsChanged: CircleData & {
33
- circleID: string;
34
- };
35
- };
36
- export type SpaceEventEmitter = EventEmitter<SpaceEventMap>;
37
- export declare function createSpaceEventEmitter(): SpaceEventEmitter;
38
- export declare function createFilteredGenerator<K extends keyof SpaceEventMap>(emitter: SpaceEventEmitter, eventName: K, filter?: (data: SpaceEventMap[K]) => boolean): AsyncGenerator<SpaceEventMap[K], void, void>;
@@ -1,3 +0,0 @@
1
- import { type GroupHandle } from '@enkaku/group';
2
- import { type SerializedGroupState } from './mls-state.js';
3
- export declare function restoreGroupHandle(serialized: SerializedGroupState): Promise<GroupHandle>;
@@ -1 +0,0 @@
1
- import{restoreGroup as r}from"@enkaku/group";import{deserializeGroupState as o}from"./mls-state.js";export async function restoreGroupHandle(t){let{state:e,credential:n,rootCapability:m}=o(t);return r({state:e,credential:n,rootCapability:m})}
@@ -1,22 +0,0 @@
1
- import type { OwnIdentity } from '@enkaku/token';
2
- import type { Database } from '@kubun/db';
3
- import type { Adapter } from '@kubun/db-adapter';
4
- import { HLC } from '@kubun/hlc';
5
- import type { Kysely } from 'kysely';
6
- import type { SpaceData } from '../types.js';
7
- import type { SpaceEventEmitter } from './events.js';
8
- export type CreateSpaceFromJoinParams = {
9
- db: Kysely<Database>;
10
- adapter: Adapter;
11
- hlc: HLC;
12
- emitter: SpaceEventEmitter;
13
- identity: OwnIdentity;
14
- invite: {
15
- spaceID: string;
16
- spaceName: string;
17
- hubURLs: Array<string>;
18
- };
19
- };
20
- export declare function createSpaceFromJoin(params: CreateSpaceFromJoinParams): Promise<{
21
- space: SpaceData | null;
22
- }>;
@@ -1 +0,0 @@
1
- import{HLC as e}from"@kubun/hlc";import{toISO as t}from"../context/types.js";export async function createSpaceFromJoin(a){let{db:c,adapter:s,hlc:i,emitter:r,identity:n,invite:l}=a;null==await c.selectFrom("kubun_spaces").selectAll().where("id","=",l.spaceID).executeTakeFirst()&&await c.insertInto("kubun_spaces").values({id:l.spaceID,name:l.spaceName,description:"",created_by:n.id,hub_urls:s.encodeJSON(l.hubURLs),hlc:e.serialize(i.now())}).execute();let u=await c.selectFrom("kubun_spaces").selectAll().where("id","=",l.spaceID).executeTakeFirst(),o=null!=u?{id:u.id,name:u.name,description:u.description,createdBy:u.created_by,createdAt:t(u.created_at)}:null;return null!=o&&await r.emit("spaceJoined",o),{space:o}}
@@ -1 +0,0 @@
1
- import{commitInvite as e,createGroup as t,createInvite as a,processWelcome as i,removeMember as r}from"@enkaku/group";import{HLC as c}from"@kubun/hlc";import{serializeGroupState as d}from"./mls-state.js";export class SpaceManager{#e;#t;#a;#i;#r;constructor(e){this.#e=e.kysely,this.#t=e.adapter,this.#a=e.identity.id,this.#i=e.getRandomID,this.#r=new c({nodeID:e.identity.id})}async #c(){return await this.#e}async #d(e,t,a){let i=d(t),r=a??await this.#c();await r.insertInto("kubun_space_mls_state").values({space_id:e,device_id:this.#a,mls_state:this.#t.encodeBinary(i.mlsState),credential:i.credential,epoch:i.epoch,root_capability:i.rootCapability}).onConflict(e=>e.columns(["space_id","device_id"]).doUpdateSet(e=>({mls_state:e.ref("excluded.mls_state"),credential:e.ref("excluded.credential"),epoch:e.ref("excluded.epoch"),root_capability:e.ref("excluded.root_capability"),updated_at:this.#t.encodeTimestamp(new Date)}))).execute()}async createSpace(e,a){let i=this.#i(),{group:r}=await t(e.identity,i),d=a??await this.#c();return await d.insertInto("kubun_spaces").values({id:i,name:e.name,description:e.description??"",created_by:e.identity.id,hub_urls:this.#t.encodeJSON(e.hubURLs??[]),hlc:c.serialize(this.#r.now())}).execute(),await this.#d(i,r,d),await d.insertInto("kubun_space_members").values({space_id:i,member_did:e.identity.id,role:"admin"}).onConflict(e=>e.columns(["space_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),updated_at:this.#t.encodeTimestamp(new Date)}))).execute(),{spaceID:i,groupHandle:r}}async updateSpace(e){let t=c.serialize(this.#r.now()),a={};null!=e.update.name&&(a.name=e.update.name),null!=e.update.description&&(a.description=e.update.description),null!=e.update.hubURLs&&(a.hub_urls=this.#t.encodeJSON(e.update.hubURLs)),a.hlc=t,a.updated_at=this.#t.encodeTimestamp(new Date);let i=await this.#c();return await i.updateTable("kubun_spaces").set(a).where("id","=",e.spaceID).execute(),{broadcast:{type:"space:update",spaceID:e.spaceID,update:{...e.update,hlc:t}}}}async inviteToSpace(t,i){let{invite:r}=await a({group:t.groupHandle,identity:t.identity,recipientDID:t.recipientDID,permission:t.permission}),{commitMessage:c,welcomeMessage:d,newGroup:s}=await e(t.groupHandle,t.recipientKeyPackage),l=i??await this.#c();return await this.#d(t.spaceID,s,l),await l.insertInto("kubun_space_members").values({space_id:t.spaceID,member_did:t.recipientDID,role:"admin"===t.permission?"admin":"member"}).onConflict(e=>e.columns(["space_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),updated_at:this.#t.encodeTimestamp(new Date)}))).execute(),{invite:r,welcomeMessage:d,commitMessage:c,updatedGroupHandle:s}}async joinSpace(e,t){let{group:a}=await i({identity:e.identity,invite:e.invite,welcome:e.welcomeMessage,keyPackageBundle:e.keyPackageBundle,ratchetTree:e.ratchetTree}),r=t??await this.#c();return await this.#d(e.spaceID,a,r),await r.insertInto("kubun_space_members").values({space_id:e.spaceID,member_did:e.identity.id,role:"member"}).onConflict(e=>e.columns(["space_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),updated_at:this.#t.encodeTimestamp(new Date)}))).execute(),{groupHandle:a}}async removeMember(e,t){let{commitMessage:a,newGroup:i}=await r(e.groupHandle,e.leafIndex),c=t??await this.#c();return await this.#d(e.spaceID,i,c),await c.deleteFrom("kubun_space_members").where("space_id","=",e.spaceID).where("member_did","=",e.memberDID).execute(),{commitMessage:a,updatedGroupHandle:i}}async removeSpaceMember(e,t){let a=e.groupHandle.findMemberLeafIndex(e.memberDID);if(null==a)throw Error(`Member ${e.memberDID} not found in MLS group`);let{commitMessage:i,newGroup:c}=await r(e.groupHandle,a),d=t??await this.#c();return await this.#d(e.spaceID,c,d),await d.deleteFrom("kubun_space_members").where("space_id","=",e.spaceID).where("member_did","=",e.memberDID).execute(),{commitMessage:i,updatedGroupHandle:c}}async leaveSpace(e,t){let a=async t=>{await t.deleteFrom("kubun_space_mls_state").where("space_id","=",e.spaceID).where("device_id","=",this.#a).execute(),await t.deleteFrom("kubun_space_members").where("space_id","=",e.spaceID).where("member_did","=",e.identity.id).execute()};if(null!=t)await a(t);else{let e=await this.#c();await e.transaction().execute(a)}}async loadSpace(e){let t=await this.#c(),a=await t.selectFrom("kubun_space_mls_state").selectAll().where("space_id","=",e).where("device_id","=",this.#a).executeTakeFirst();if(null!=a)return{epoch:a.epoch,credential:a.credential}}async createCircle(e){let t=this.#i(),a=c.serialize(this.#r.now()),i=e.catalogIDs??[],r=await this.#c();return await r.insertInto("kubun_circles").values({id:t,space_id:e.spaceID,name:e.name,description:e.description??"",catalog_ids:this.#t.encodeJSON(i),hlc:a}).execute(),{circleID:t,broadcast:{type:"circle:create",circle:{id:t,spaceID:e.spaceID,name:e.name,description:e.description??"",catalogIDs:i,hlc:a}}}}async updateCircle(e){let t=c.serialize(this.#r.now()),a=[],i=await this.#c();if(null!=e.update.catalogIDs){let t=await i.selectFrom("kubun_circles").selectAll().where("id","=",e.circleID).executeTakeFirst(),r=new Set(null!=t?t.catalog_ids:[]),c=e.update.catalogIDs.filter(e=>!r.has(e));for(let e of(await Promise.all(c.map(e=>i.selectFrom("kubun_catalogs").selectAll().where("id","=",e).executeTakeFirst()))))null!=e&&a.push({type:"catalog:create",catalog:{id:e.id,ownerDID:e.owner_did,name:e.name,description:e.description,filterCriteria:e.filter_criteria,hlc:e.hlc}})}let r={};null!=e.update.name&&(r.name=e.update.name),null!=e.update.description&&(r.description=e.update.description),null!=e.update.catalogIDs&&(r.catalog_ids=this.#t.encodeJSON(e.update.catalogIDs)),r.hlc=t,r.updated_at=this.#t.encodeTimestamp(new Date),await i.updateTable("kubun_circles").set(r).where("id","=",e.circleID).execute();let d={type:"circle:update",circleID:e.circleID,update:{...e.update,hlc:t}};return{broadcast:d,broadcasts:[d,...a]}}async deleteCircle(e){let t=c.serialize(this.#r.now()),a=await this.#c();return await a.deleteFrom("kubun_circles").where("id","=",e.circleID).execute(),{broadcast:{type:"circle:delete",circleID:e.circleID,hlc:t}}}async addCircleMember(e){let t=await this.#c();if(null==await t.selectFrom("kubun_space_members").select("member_did").where("space_id","=",e.spaceID).where("member_did","=",e.memberDID).executeTakeFirst())throw Error(`${e.memberDID} is not a member of space ${e.spaceID}`);let a=c.serialize(this.#r.now());return await t.insertInto("kubun_circle_members").values({circle_id:e.circleID,member_did:e.memberDID,role:e.role,hlc:a}).onConflict(e=>e.columns(["circle_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),hlc:e.ref("excluded.hlc")}))).execute(),{broadcast:{type:"member:add",member:{circleID:e.circleID,memberDID:e.memberDID,role:e.role,hlc:a}}}}async removeCircleMember(e){let t=c.serialize(this.#r.now()),a=await this.#c();return await a.deleteFrom("kubun_circle_members").where("circle_id","=",e.circleID).where("member_did","=",e.memberDID).execute(),{broadcast:{type:"member:remove",circleID:e.circleID,memberDID:e.memberDID,hlc:t}}}}
@@ -1,27 +0,0 @@
1
- import { type ClientState, type GroupHandle, type MemberCredential } from '@enkaku/group';
2
- /**
3
- * Serialized form of a GroupHandle for DB persistence.
4
- * The MLS ClientState is opaque binary; the credential is JSON.
5
- */
6
- export type SerializedGroupState = {
7
- mlsState: Uint8Array;
8
- credential: string;
9
- epoch: number;
10
- rootCapability: string;
11
- };
12
- /**
13
- * Serialize a GroupHandle's state for persistence.
14
- * The implementer must verify the serialization approach works
15
- * with the installed version of ts-mls.
16
- */
17
- export declare function serializeGroupState(group: GroupHandle): SerializedGroupState;
18
- export type GroupState = {
19
- state: ClientState;
20
- credential: MemberCredential;
21
- rootCapability: string;
22
- };
23
- /**
24
- * Deserialize persisted state back into GroupHandle constructor params.
25
- * Returns the params needed to reconstruct a GroupHandle.
26
- */
27
- export declare function deserializeGroupState(serialized: SerializedGroupState): GroupState;
@@ -1 +0,0 @@
1
- import{decodeClientState as t,encodeClientState as e}from"@enkaku/group";export function serializeGroupState(t){return{mlsState:e(t.state),credential:JSON.stringify(t.credential),epoch:Number(t.epoch),rootCapability:t.rootCapability}}export function deserializeGroupState(e){let r=t(e.mlsState);if(null==r)throw Error("Could not decode ClientState");return{state:r,credential:JSON.parse(e.credential),rootCapability:e.rootCapability}}
File without changes
File without changes
File without changes
File without changes