@kubun/store-p2p 0.8.0 → 0.9.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/api.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import type { Adapter } from '@kubun/db-adapter';
2
2
  import type { Kysely } from 'kysely';
3
- import type { Circle, CircleMember, Group, GroupMember, GroupMLSState, InsertCircle, InsertCircleMember, InsertGroup, InsertGroupMember, InsertGroupMLSState, InsertSyncPeer, P2PStoreTables, PaginatedResult, PaginationParams, SyncPeer } from './tables.js';
3
+ import type { Circle, CircleMember, Group, GroupMember, GroupMLSState, Hub, InsertCircle, InsertCircleMember, InsertGroup, InsertGroupHub, InsertGroupMember, InsertGroupMLSState, InsertHub, InsertSyncPeer, P2PStoreTables, PaginatedResult, PaginationParams, SyncPeer } from './tables.js';
4
4
  export type P2PStoreAPI = {
5
5
  createGroup(group: InsertGroup): Promise<void>;
6
6
  getGroup(id: string): Promise<Group | undefined>;
7
- updateGroup(id: string, update: Partial<Pick<InsertGroup, 'name' | 'description' | 'hub_urls' | 'hlc'>>): Promise<void>;
7
+ updateGroup(id: string, update: Partial<Pick<InsertGroup, 'name' | 'description' | 'hlc'>>): Promise<void>;
8
8
  deleteGroup(id: string): Promise<void>;
9
9
  listGroups(): Promise<Array<Group>>;
10
10
  listGroupsOffsetPaged(params: PaginationParams): Promise<PaginatedResult<Group>>;
@@ -12,15 +12,35 @@ export type P2PStoreAPI = {
12
12
  removeGroupMember(groupID: string, memberDID: string): Promise<void>;
13
13
  getGroupMember(groupID: string, memberDID: string): Promise<GroupMember | undefined>;
14
14
  isGroupMember(groupID: string, memberDID: string): Promise<boolean>;
15
+ isMemberOfAnyGroup(viewerDID: string, groupIDs: Array<string>): Promise<boolean>;
15
16
  listGroupMembers(groupID: string): Promise<Array<GroupMember>>;
16
17
  getGroupsForMember(memberDID: string): Promise<Array<Group>>;
18
+ /**
19
+ * Batch fetch groups for multiple members. Returns a Map keyed by
20
+ * `memberDID`; values are arrays of groups for that member. Members with
21
+ * no groups are absent from the map. Single SQL query joining
22
+ * `group_members` to `groups`. Empty input short-circuits with an empty
23
+ * Map (no SQL).
24
+ *
25
+ * Caller is responsible for deduplicating DIDs.
26
+ */
27
+ getGroupsForMembers(memberDIDs: Array<string>): Promise<Map<string, Array<Group>>>;
17
28
  createCircle(circle: InsertCircle): Promise<void>;
18
29
  getCircle(id: string): Promise<Circle | undefined>;
30
+ /**
31
+ * Batch fetch circles by ID. Returns a Map keyed by ID; missing IDs are
32
+ * absent from the map. Single SQL query with `WHERE id IN (...)`. Empty
33
+ * input short-circuits with an empty Map (no SQL).
34
+ *
35
+ * Caller is responsible for deduplicating IDs.
36
+ */
37
+ getCircles(ids: Array<string>): Promise<Map<string, Circle>>;
19
38
  updateCircle(id: string, update: Partial<Pick<InsertCircle, 'name' | 'description' | 'catalog_ids' | 'hlc'>>): Promise<void>;
20
39
  deleteCircle(id: string): Promise<void>;
21
40
  listCirclesByGroup(groupID: string): Promise<Array<Circle>>;
22
41
  addCircleMember(member: InsertCircleMember): Promise<void>;
23
42
  removeCircleMember(circleID: string, memberDID: string): Promise<void>;
43
+ getCircleMember(circleID: string, memberDID: string): Promise<CircleMember | undefined>;
24
44
  listCircleMembers(circleID: string): Promise<Array<CircleMember>>;
25
45
  getCirclesForMember(memberDID: string): Promise<Array<Circle>>;
26
46
  isMemberOfAnyCircle(memberDID: string, circleIDs: Array<string>): Promise<boolean>;
@@ -34,5 +54,30 @@ export type P2PStoreAPI = {
34
54
  listSyncPeers(): Promise<Array<SyncPeer>>;
35
55
  updateSyncPeer(peerDID: string, update: Partial<InsertSyncPeer>): Promise<void>;
36
56
  removeSyncPeer(peerDID: string): Promise<void>;
57
+ recordBroadcast(entry: {
58
+ docID: string;
59
+ version: string;
60
+ mlsGroupID: string;
61
+ }): Promise<boolean>;
62
+ hasBroadcast(entry: {
63
+ docID: string;
64
+ version: string;
65
+ mlsGroupID: string;
66
+ }): Promise<boolean>;
67
+ insertHub(hub: InsertHub): Promise<void>;
68
+ getHub(id: string): Promise<Hub | undefined>;
69
+ getHubByURL(url: string): Promise<Hub | undefined>;
70
+ updateHub(id: string, update: Partial<Pick<InsertHub, 'label' | 'url' | 'server_did'>>): Promise<void>;
71
+ deleteHub(id: string): Promise<void>;
72
+ listHubs(): Promise<Array<Hub>>;
73
+ insertGroupHub(binding: InsertGroupHub): Promise<boolean>;
74
+ deleteGroupHub(params: {
75
+ groupID: string;
76
+ hubID: string;
77
+ }): Promise<boolean>;
78
+ listGroupIDsByHubID(hubID: string): Promise<Array<string>>;
79
+ listHubsByGroupID(groupID: string): Promise<Array<Hub>>;
80
+ listGroupsByHubID(hubID: string): Promise<Array<Group>>;
81
+ deleteGroupHubsByHubID(hubID: string): Promise<void>;
37
82
  };
38
83
  export declare function createP2PStore(db: Kysely<P2PStoreTables>, adapter: Adapter): P2PStoreAPI;
package/lib/api.js CHANGED
@@ -1 +1 @@
1
- export function createP2PStore(e,r){return{async createGroup(t){await e.insertInto("kubun_p2p_groups").values({id:t.id,name:t.name,description:t.description,created_by:t.created_by,hub_urls:r.encodeJSON(t.hub_urls??[]),hlc:t.hlc}).execute()},getGroup:async r=>await e.selectFrom("kubun_p2p_groups").selectAll().where("id","=",r).executeTakeFirst(),async updateGroup(t,l){let c={};null!=l.name&&(c.name=l.name),null!=l.description&&(c.description=l.description),null!=l.hub_urls&&(c.hub_urls=r.encodeJSON(l.hub_urls)),null!=l.hlc&&(c.hlc=l.hlc),c.updated_at=r.encodeTimestamp(new Date),await e.updateTable("kubun_p2p_groups").set(c).where("id","=",t).execute()},async deleteGroup(r){await e.deleteFrom("kubun_p2p_groups").where("id","=",r).execute()},listGroups:async()=>await e.selectFrom("kubun_p2p_groups").selectAll().execute(),async listGroupsOffsetPaged(r){let{limit:t,offset:l}=r,c=e.selectFrom("kubun_p2p_groups").selectAll().orderBy("name");if(null!=l&&(c=c.offset(l)),null!=t){c=c.limit(t+1);let e=await c.execute(),r=e.length>t;return{entries:r?e.slice(0,t):e,hasMore:r}}return{entries:await c.execute(),hasMore:!1}},async addGroupMember(t){await e.insertInto("kubun_p2p_group_members").values({group_id:t.group_id,member_did:t.member_did,role:t.role}).onConflict(e=>e.columns(["group_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),updated_at:r.encodeTimestamp(new Date)}))).execute()},async removeGroupMember(r,t){await e.deleteFrom("kubun_p2p_group_members").where("group_id","=",r).where("member_did","=",t).execute()},getGroupMember:async(r,t)=>await e.selectFrom("kubun_p2p_group_members").selectAll().where("group_id","=",r).where("member_did","=",t).executeTakeFirst(),isGroupMember:async(r,t)=>null!=await e.selectFrom("kubun_p2p_group_members").select("member_did").where("group_id","=",r).where("member_did","=",t).executeTakeFirst(),listGroupMembers:async r=>await e.selectFrom("kubun_p2p_group_members").selectAll().where("group_id","=",r).execute(),getGroupsForMember:async r=>await e.selectFrom("kubun_p2p_group_members").innerJoin("kubun_p2p_groups","kubun_p2p_groups.id","kubun_p2p_group_members.group_id").selectAll("kubun_p2p_groups").where("kubun_p2p_group_members.member_did","=",r).execute(),async createCircle(t){await e.insertInto("kubun_p2p_circles").values({id:t.id,group_id:t.group_id,name:t.name,description:t.description,catalog_ids:r.encodeJSON(t.catalog_ids),hlc:t.hlc}).execute()},getCircle:async r=>await e.selectFrom("kubun_p2p_circles").selectAll().where("id","=",r).executeTakeFirst(),async updateCircle(t,l){let c={};null!=l.name&&(c.name=l.name),null!=l.description&&(c.description=l.description),null!=l.catalog_ids&&(c.catalog_ids=r.encodeJSON(l.catalog_ids)),null!=l.hlc&&(c.hlc=l.hlc),c.updated_at=r.encodeTimestamp(new Date),await e.updateTable("kubun_p2p_circles").set(c).where("id","=",t).execute()},async deleteCircle(r){await e.deleteFrom("kubun_p2p_circles").where("id","=",r).execute()},listCirclesByGroup:async r=>await e.selectFrom("kubun_p2p_circles").selectAll().where("group_id","=",r).execute(),async addCircleMember(r){await e.insertInto("kubun_p2p_circle_members").values({circle_id:r.circle_id,member_did:r.member_did,role:r.role,hlc:r.hlc}).onConflict(e=>e.columns(["circle_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),hlc:e.ref("excluded.hlc")}))).execute()},async removeCircleMember(r,t){await e.deleteFrom("kubun_p2p_circle_members").where("circle_id","=",r).where("member_did","=",t).execute()},listCircleMembers:async r=>await e.selectFrom("kubun_p2p_circle_members").selectAll().where("circle_id","=",r).execute(),getCirclesForMember:async r=>await e.selectFrom("kubun_p2p_circle_members").innerJoin("kubun_p2p_circles","kubun_p2p_circles.id","kubun_p2p_circle_members.circle_id").selectAll("kubun_p2p_circles").where("kubun_p2p_circle_members.member_did","=",r).execute(),isMemberOfAnyCircle:async(r,t)=>0!==t.length&&null!=await e.selectFrom("kubun_p2p_circle_members").select("circle_id").where("member_did","=",r).where("circle_id","in",t).limit(1).executeTakeFirst(),async saveMLSState(t){await e.insertInto("kubun_p2p_group_mls_state").values({group_id:t.group_id,device_id:t.device_id,mls_state:r.encodeBinary(t.mls_state),credential:t.credential,epoch:t.epoch,root_capability:t.root_capability}).onConflict(e=>e.columns(["group_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:r.encodeTimestamp(new Date)}))).execute()},getMLSState:async(r,t)=>await e.selectFrom("kubun_p2p_group_mls_state").selectAll().where("group_id","=",r).where("device_id","=",t).executeTakeFirst(),async deleteMLSState(r,t){await e.deleteFrom("kubun_p2p_group_mls_state").where("group_id","=",r).where("device_id","=",t).execute()},listMLSStates:async r=>await e.selectFrom("kubun_p2p_group_mls_state").selectAll().where("group_id","=",r).execute(),async deleteGroupMLSStates(r){await e.deleteFrom("kubun_p2p_group_mls_state").where("group_id","=",r).execute()},async addSyncPeer(t){let l=r.encodeJSON(t.allowed_users),c=r.encodeJSON(t.config);await e.insertInto("kubun_p2p_sync_peers").values({...t,allowed_users:l,config:c}).onConflict(e=>e.column("peer_did").doUpdateSet({endpoint:t.endpoint,mode:t.mode,allowed_users:l,priority:t.priority,trust_level:t.trust_level,config:c,updated_at:t.updated_at})).execute()},getSyncPeer:async r=>await e.selectFrom("kubun_p2p_sync_peers").selectAll().where("peer_did","=",r).executeTakeFirst(),listSyncPeers:async()=>await e.selectFrom("kubun_p2p_sync_peers").selectAll().execute(),async updateSyncPeer(t,l){let c={};null!=l.endpoint&&(c.endpoint=l.endpoint),null!=l.mode&&(c.mode=l.mode),null!=l.allowed_users&&(c.allowed_users=r.encodeJSON(l.allowed_users)),null!=l.priority&&(c.priority=l.priority),null!=l.trust_level&&(c.trust_level=l.trust_level),null!=l.config&&(c.config=r.encodeJSON(l.config)),c.updated_at=Date.now(),await e.updateTable("kubun_p2p_sync_peers").set(c).where("peer_did","=",t).execute()},async removeSyncPeer(r){await e.deleteFrom("kubun_p2p_sync_peers").where("peer_did","=",r).execute()}}}
1
+ export function createP2PStore(e,u){return{async createGroup(u){await e.insertInto("kubun_p2p_groups").values({id:u.id,name:u.name,description:u.description,created_by:u.created_by,hlc:u.hlc}).execute()},getGroup:async u=>await e.selectFrom("kubun_p2p_groups").selectAll().where("id","=",u).executeTakeFirst(),async updateGroup(r,t){let s={};null!=t.name&&(s.name=t.name),null!=t.description&&(s.description=t.description),null!=t.hlc&&(s.hlc=t.hlc),s.updated_at=u.encodeTimestamp(new Date),await e.updateTable("kubun_p2p_groups").set(s).where("id","=",r).execute()},async deleteGroup(u){await e.deleteFrom("kubun_p2p_groups").where("id","=",u).execute()},listGroups:async()=>await e.selectFrom("kubun_p2p_groups").selectAll().execute(),async listGroupsOffsetPaged(u){let{limit:r,offset:t}=u,s=e.selectFrom("kubun_p2p_groups").selectAll().orderBy("name");if(null!=t&&(s=s.offset(t)),null!=r){s=s.limit(r+1);let e=await s.execute(),u=e.length>r;return{entries:u?e.slice(0,r):e,hasMore:u}}return{entries:await s.execute(),hasMore:!1}},async addGroupMember(r){await e.insertInto("kubun_p2p_group_members").values({group_id:r.group_id,member_did:r.member_did,role:r.role}).onConflict(e=>e.columns(["group_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),updated_at:u.encodeTimestamp(new Date)}))).execute()},async removeGroupMember(u,r){await e.deleteFrom("kubun_p2p_group_members").where("group_id","=",u).where("member_did","=",r).execute()},getGroupMember:async(u,r)=>await e.selectFrom("kubun_p2p_group_members").selectAll().where("group_id","=",u).where("member_did","=",r).executeTakeFirst(),isGroupMember:async(u,r)=>null!=await e.selectFrom("kubun_p2p_group_members").select("member_did").where("group_id","=",u).where("member_did","=",r).executeTakeFirst(),isMemberOfAnyGroup:async(u,r)=>0!==r.length&&null!=await e.selectFrom("kubun_p2p_group_members").select("group_id").where("member_did","=",u).where("group_id","in",r).limit(1).executeTakeFirst(),listGroupMembers:async u=>await e.selectFrom("kubun_p2p_group_members").selectAll().where("group_id","=",u).execute(),getGroupsForMember:async u=>await e.selectFrom("kubun_p2p_group_members").innerJoin("kubun_p2p_groups","kubun_p2p_groups.id","kubun_p2p_group_members.group_id").selectAll("kubun_p2p_groups").where("kubun_p2p_group_members.member_did","=",u).execute(),async getGroupsForMembers(u){let r=new Map;if(0===u.length)return r;for(let t of(await e.selectFrom("kubun_p2p_group_members").innerJoin("kubun_p2p_groups","kubun_p2p_groups.id","kubun_p2p_group_members.group_id").select(["kubun_p2p_group_members.member_did as member_did","kubun_p2p_groups.id as id","kubun_p2p_groups.name as name","kubun_p2p_groups.description as description","kubun_p2p_groups.created_by as created_by","kubun_p2p_groups.hlc as hlc","kubun_p2p_groups.created_at as created_at","kubun_p2p_groups.updated_at as updated_at"]).where("kubun_p2p_group_members.member_did","in",u).execute())){let{member_did:e,...u}=t,s=r.get(e);null!=s?s.push(u):r.set(e,[u])}return r},async createCircle(r){await e.insertInto("kubun_p2p_circles").values({id:r.id,group_id:r.group_id,name:r.name,description:r.description,catalog_ids:u.encodeJSON(r.catalog_ids),hlc:r.hlc}).execute()},getCircle:async u=>await e.selectFrom("kubun_p2p_circles").selectAll().where("id","=",u).executeTakeFirst(),async getCircles(u){let r=new Map;if(0===u.length)return r;for(let t of(await e.selectFrom("kubun_p2p_circles").selectAll().where("id","in",u).execute()))r.set(t.id,t);return r},async updateCircle(r,t){let s={};null!=t.name&&(s.name=t.name),null!=t.description&&(s.description=t.description),null!=t.catalog_ids&&(s.catalog_ids=u.encodeJSON(t.catalog_ids)),null!=t.hlc&&(s.hlc=t.hlc),s.updated_at=u.encodeTimestamp(new Date),await e.updateTable("kubun_p2p_circles").set(s).where("id","=",r).execute()},async deleteCircle(u){await e.deleteFrom("kubun_p2p_circles").where("id","=",u).execute()},listCirclesByGroup:async u=>await e.selectFrom("kubun_p2p_circles").selectAll().where("group_id","=",u).execute(),async addCircleMember(u){await e.insertInto("kubun_p2p_circle_members").values({circle_id:u.circle_id,member_did:u.member_did,role:u.role,hlc:u.hlc}).onConflict(e=>e.columns(["circle_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),hlc:e.ref("excluded.hlc")}))).execute()},async removeCircleMember(u,r){await e.deleteFrom("kubun_p2p_circle_members").where("circle_id","=",u).where("member_did","=",r).execute()},getCircleMember:async(u,r)=>await e.selectFrom("kubun_p2p_circle_members").selectAll().where("circle_id","=",u).where("member_did","=",r).executeTakeFirst(),listCircleMembers:async u=>await e.selectFrom("kubun_p2p_circle_members").selectAll().where("circle_id","=",u).execute(),getCirclesForMember:async u=>await e.selectFrom("kubun_p2p_circle_members").innerJoin("kubun_p2p_circles","kubun_p2p_circles.id","kubun_p2p_circle_members.circle_id").selectAll("kubun_p2p_circles").where("kubun_p2p_circle_members.member_did","=",u).execute(),isMemberOfAnyCircle:async(u,r)=>0!==r.length&&null!=await e.selectFrom("kubun_p2p_circle_members").select("circle_id").where("member_did","=",u).where("circle_id","in",r).limit(1).executeTakeFirst(),async saveMLSState(r){await e.insertInto("kubun_p2p_group_mls_state").values({group_id:r.group_id,device_id:r.device_id,mls_state:u.encodeBinary(r.mls_state),credential:r.credential,epoch:r.epoch,root_capability:r.root_capability}).onConflict(e=>e.columns(["group_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:u.encodeTimestamp(new Date)}))).execute()},getMLSState:async(u,r)=>await e.selectFrom("kubun_p2p_group_mls_state").selectAll().where("group_id","=",u).where("device_id","=",r).executeTakeFirst(),async deleteMLSState(u,r){await e.deleteFrom("kubun_p2p_group_mls_state").where("group_id","=",u).where("device_id","=",r).execute()},listMLSStates:async u=>await e.selectFrom("kubun_p2p_group_mls_state").selectAll().where("group_id","=",u).execute(),async deleteGroupMLSStates(u){await e.deleteFrom("kubun_p2p_group_mls_state").where("group_id","=",u).execute()},async addSyncPeer(r){let t=u.encodeJSON(r.allowed_users),s=u.encodeJSON(r.config);await e.insertInto("kubun_p2p_sync_peers").values({...r,allowed_users:t,config:s}).onConflict(e=>e.column("peer_did").doUpdateSet({endpoint:r.endpoint,mode:r.mode,allowed_users:t,priority:r.priority,trust_level:r.trust_level,config:s,updated_at:r.updated_at})).execute()},getSyncPeer:async u=>await e.selectFrom("kubun_p2p_sync_peers").selectAll().where("peer_did","=",u).executeTakeFirst(),listSyncPeers:async()=>await e.selectFrom("kubun_p2p_sync_peers").selectAll().execute(),async updateSyncPeer(r,t){let s={};null!=t.endpoint&&(s.endpoint=t.endpoint),null!=t.mode&&(s.mode=t.mode),null!=t.allowed_users&&(s.allowed_users=u.encodeJSON(t.allowed_users)),null!=t.priority&&(s.priority=t.priority),null!=t.trust_level&&(s.trust_level=t.trust_level),null!=t.config&&(s.config=u.encodeJSON(t.config)),s.updated_at=Date.now(),await e.updateTable("kubun_p2p_sync_peers").set(s).where("peer_did","=",r).execute()},async removeSyncPeer(u){await e.deleteFrom("kubun_p2p_sync_peers").where("peer_did","=",u).execute()},recordBroadcast:async u=>((await e.insertInto("kubun_p2p_broadcast_log").values({doc_id:u.docID,version:u.version,mls_group_id:u.mlsGroupID}).onConflict(e=>e.columns(["doc_id","version","mls_group_id"]).doNothing()).executeTakeFirst()).numInsertedOrUpdatedRows??0n)>0n,hasBroadcast:async u=>null!=await e.selectFrom("kubun_p2p_broadcast_log").select("doc_id").where("doc_id","=",u.docID).where("version","=",u.version).where("mls_group_id","=",u.mlsGroupID).limit(1).executeTakeFirst(),async insertHub(u){await e.insertInto("kubun_p2p_hubs").values({id:u.id,label:u.label,url:u.url,server_did:u.server_did}).execute()},getHub:async u=>await e.selectFrom("kubun_p2p_hubs").selectAll().where("id","=",u).executeTakeFirst(),getHubByURL:async u=>await e.selectFrom("kubun_p2p_hubs").selectAll().where("url","=",u).executeTakeFirst(),async updateHub(r,t){let s={};void 0!==t.label&&(s.label=t.label),void 0!==t.url&&(s.url=t.url),void 0!==t.server_did&&(s.server_did=t.server_did),s.updated_at=u.encodeTimestamp(new Date),await e.updateTable("kubun_p2p_hubs").set(s).where("id","=",r).execute()},async deleteHub(u){await e.deleteFrom("kubun_p2p_hubs").where("id","=",u).execute()},listHubs:async()=>await e.selectFrom("kubun_p2p_hubs").selectAll().execute(),insertGroupHub:async u=>((await e.insertInto("kubun_p2p_group_hubs").values({group_id:u.group_id,hub_id:u.hub_id}).onConflict(e=>e.columns(["group_id","hub_id"]).doNothing()).executeTakeFirst()).numInsertedOrUpdatedRows??0n)>0n,deleteGroupHub:async u=>((await e.deleteFrom("kubun_p2p_group_hubs").where("group_id","=",u.groupID).where("hub_id","=",u.hubID).executeTakeFirst()).numDeletedRows??0n)>0n,listGroupIDsByHubID:async u=>(await e.selectFrom("kubun_p2p_group_hubs").select("group_id").where("hub_id","=",u).execute()).map(e=>e.group_id),listHubsByGroupID:async u=>await e.selectFrom("kubun_p2p_group_hubs").innerJoin("kubun_p2p_hubs","kubun_p2p_hubs.id","kubun_p2p_group_hubs.hub_id").selectAll("kubun_p2p_hubs").where("kubun_p2p_group_hubs.group_id","=",u).execute(),listGroupsByHubID:async u=>await e.selectFrom("kubun_p2p_group_hubs").innerJoin("kubun_p2p_groups","kubun_p2p_groups.id","kubun_p2p_group_hubs.group_id").select(["kubun_p2p_groups.id as id","kubun_p2p_groups.name as name","kubun_p2p_groups.description as description","kubun_p2p_groups.created_by as created_by","kubun_p2p_groups.hlc as hlc","kubun_p2p_groups.created_at as created_at","kubun_p2p_groups.updated_at as updated_at"]).where("kubun_p2p_group_hubs.hub_id","=",u).execute(),async deleteGroupHubsByHubID(u){await e.deleteFrom("kubun_p2p_group_hubs").where("hub_id","=",u).execute()}}}
package/lib/index.d.ts CHANGED
@@ -5,4 +5,4 @@ export { createP2PStore } from './api.js';
5
5
  export { p2pStoreDefinition } from './definition.js';
6
6
  export declare const P2P_STORE: "p2p";
7
7
  export declare function getP2PStore(provider: StoreProvider): Promise<P2PStoreAPI>;
8
- export type { Circle, CircleMember, CircleMemberTable, CircleTable, Group, GroupMember, GroupMemberTable, GroupMLSState, GroupMLSStateTable, GroupTable, InsertCircle, InsertCircleMember, InsertGroup, InsertGroupMember, InsertGroupMLSState, InsertSyncCheckpoint, InsertSyncPeer, P2PStoreTables, PaginatedResult, PaginationParams, SyncCheckpoint, SyncCheckpointTable, SyncPeer, SyncPeerTable, UpdateGroupMLSState, } from './tables.js';
8
+ export type { Circle, CircleMember, CircleMemberTable, CircleTable, Group, GroupHub, GroupHubTable, GroupMember, GroupMemberTable, GroupMLSState, GroupMLSStateTable, GroupTable, Hub, HubTable, InsertCircle, InsertCircleMember, InsertGroup, InsertGroupHub, InsertGroupMember, InsertGroupMLSState, InsertHub, InsertSyncCheckpoint, InsertSyncPeer, P2PStoreTables, PaginatedResult, PaginationParams, SyncCheckpoint, SyncCheckpointTable, SyncPeer, SyncPeerTable, UpdateGroupMLSState, } from './tables.js';
package/lib/migrations.js CHANGED
@@ -1 +1 @@
1
- export function getP2PMigrations(e){let t=e.types,a=e.functions.now;return{"0-init":{async up(e){await e.schema.createTable("kubun_p2p_groups").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("name",t.text,e=>e.notNull()).addColumn("description",t.text,e=>e.notNull().defaultTo("")).addColumn("created_by",t.text,e=>e.notNull()).addColumn("hub_urls",t.json,e=>e.defaultTo("[]").notNull()).addColumn("hlc",t.text,e=>e.notNull()).addColumn("created_at",t.timestamp,e=>e.defaultTo(a).notNull()).addColumn("updated_at",t.timestamp).execute(),await e.schema.createTable("kubun_p2p_group_members").ifNotExists().addColumn("group_id",t.text,e=>e.notNull()).addColumn("member_did",t.text,e=>e.notNull()).addColumn("role",t.text,e=>e.notNull().defaultTo("member")).addColumn("created_at",t.timestamp,e=>e.defaultTo(a).notNull()).addColumn("updated_at",t.timestamp).addPrimaryKeyConstraint("pk_p2p_group_members",["group_id","member_did"]).execute(),await e.schema.createIndex("idx_p2p_group_members_did").ifNotExists().on("kubun_p2p_group_members").column("member_did").execute(),await e.schema.createTable("kubun_p2p_circles").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("group_id",t.text,e=>e.notNull()).addColumn("name",t.text,e=>e.notNull()).addColumn("description",t.text,e=>e.notNull().defaultTo("")).addColumn("catalog_ids",t.json,e=>e.notNull().defaultTo("[]")).addColumn("hlc",t.text,e=>e.notNull()).addColumn("created_at",t.timestamp,e=>e.defaultTo(a).notNull()).addColumn("updated_at",t.timestamp).execute(),await e.schema.createIndex("idx_p2p_circles_group").ifNotExists().on("kubun_p2p_circles").column("group_id").execute(),await e.schema.createTable("kubun_p2p_circle_members").ifNotExists().addColumn("circle_id",t.text,e=>e.notNull()).addColumn("member_did",t.text,e=>e.notNull()).addColumn("role",t.text,e=>e.notNull().defaultTo("member")).addColumn("hlc",t.text,e=>e.notNull()).addColumn("created_at",t.timestamp,e=>e.defaultTo(a).notNull()).addColumn("updated_at",t.timestamp).addPrimaryKeyConstraint("pk_p2p_circle_members",["circle_id","member_did"]).execute(),await e.schema.createIndex("idx_p2p_circle_members_did").ifNotExists().on("kubun_p2p_circle_members").column("member_did").execute(),await e.schema.createTable("kubun_p2p_group_mls_state").ifNotExists().addColumn("group_id",t.text,e=>e.notNull()).addColumn("device_id",t.text,e=>e.notNull()).addColumn("mls_state",t.binary,e=>e.notNull()).addColumn("credential",t.text,e=>e.notNull()).addColumn("epoch","integer",e=>e.notNull()).addColumn("root_capability",t.text,e=>e.notNull().defaultTo("")).addColumn("updated_at",t.timestamp,e=>e.defaultTo(a).notNull()).addPrimaryKeyConstraint("pk_p2p_group_mls_state",["group_id","device_id"]).execute(),await e.schema.createTable("kubun_p2p_sync_peers").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("peer_did",t.text,e=>e.notNull().unique()).addColumn("endpoint",t.text,e=>e.notNull()).addColumn("mode",t.text,e=>e.notNull()).addColumn("allowed_users",t.json,e=>e.notNull()).addColumn("priority",t.text,e=>e.notNull().defaultTo("0")).addColumn("trust_level",t.text,e=>e.notNull()).addColumn("config",t.json,e=>e.notNull()).addColumn("created_at",t.timestamp,e=>e.defaultTo(a).notNull()).addColumn("updated_at",t.timestamp,e=>e.defaultTo(a).notNull()).execute(),await e.schema.createTable("kubun_p2p_sync_checkpoints").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("peer_did",t.text,e=>e.notNull()).addColumn("scope",t.text,e=>e.notNull()).addColumn("checkpoint_hlc",t.text,e=>e.notNull()).addColumn("updated_at",t.timestamp,e=>e.defaultTo(a).notNull()).execute()},async down(e){await e.schema.dropTable("kubun_p2p_sync_checkpoints").ifExists().execute(),await e.schema.dropTable("kubun_p2p_sync_peers").ifExists().execute(),await e.schema.dropTable("kubun_p2p_group_mls_state").ifExists().execute(),await e.schema.dropTable("kubun_p2p_circle_members").ifExists().execute(),await e.schema.dropTable("kubun_p2p_circles").ifExists().execute(),await e.schema.dropTable("kubun_p2p_group_members").ifExists().execute(),await e.schema.dropTable("kubun_p2p_groups").ifExists().execute()}}}}
1
+ export function getP2PMigrations(t){let e=t.types,a=t.functions.now;return{"0-init":{async up(t){await t.schema.createTable("kubun_p2p_groups").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("name",e.text,t=>t.notNull()).addColumn("description",e.text,t=>t.notNull().defaultTo("")).addColumn("created_by",e.text,t=>t.notNull()).addColumn("hlc",e.text,t=>t.notNull()).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addColumn("updated_at",e.timestamp).execute(),await t.schema.createTable("kubun_p2p_group_members").ifNotExists().addColumn("group_id",e.text,t=>t.notNull()).addColumn("member_did",e.text,t=>t.notNull()).addColumn("role",e.text,t=>t.notNull().defaultTo("member")).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addColumn("updated_at",e.timestamp).addPrimaryKeyConstraint("pk_p2p_group_members",["group_id","member_did"]).execute(),await t.schema.createIndex("idx_p2p_group_members_did").ifNotExists().on("kubun_p2p_group_members").column("member_did").execute(),await t.schema.createTable("kubun_p2p_circles").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("group_id",e.text,t=>t.notNull()).addColumn("name",e.text,t=>t.notNull()).addColumn("description",e.text,t=>t.notNull().defaultTo("")).addColumn("catalog_ids",e.json,t=>t.notNull().defaultTo("[]")).addColumn("hlc",e.text,t=>t.notNull()).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addColumn("updated_at",e.timestamp).execute(),await t.schema.createIndex("idx_p2p_circles_group").ifNotExists().on("kubun_p2p_circles").column("group_id").execute(),await t.schema.createTable("kubun_p2p_circle_members").ifNotExists().addColumn("circle_id",e.text,t=>t.notNull()).addColumn("member_did",e.text,t=>t.notNull()).addColumn("role",e.text,t=>t.notNull().defaultTo("member")).addColumn("hlc",e.text,t=>t.notNull()).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addColumn("updated_at",e.timestamp).addPrimaryKeyConstraint("pk_p2p_circle_members",["circle_id","member_did"]).execute(),await t.schema.createIndex("idx_p2p_circle_members_did").ifNotExists().on("kubun_p2p_circle_members").column("member_did").execute(),await t.schema.createTable("kubun_p2p_group_mls_state").ifNotExists().addColumn("group_id",e.text,t=>t.notNull()).addColumn("device_id",e.text,t=>t.notNull()).addColumn("mls_state",e.binary,t=>t.notNull()).addColumn("credential",e.text,t=>t.notNull()).addColumn("epoch","integer",t=>t.notNull()).addColumn("root_capability",e.text,t=>t.notNull().defaultTo("")).addColumn("updated_at",e.timestamp,t=>t.defaultTo(a).notNull()).addPrimaryKeyConstraint("pk_p2p_group_mls_state",["group_id","device_id"]).execute(),await t.schema.createTable("kubun_p2p_sync_peers").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("peer_did",e.text,t=>t.notNull().unique()).addColumn("endpoint",e.text,t=>t.notNull()).addColumn("mode",e.text,t=>t.notNull()).addColumn("allowed_users",e.json,t=>t.notNull()).addColumn("priority",e.text,t=>t.notNull().defaultTo("0")).addColumn("trust_level",e.text,t=>t.notNull()).addColumn("config",e.json,t=>t.notNull()).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addColumn("updated_at",e.timestamp,t=>t.defaultTo(a).notNull()).execute(),await t.schema.createTable("kubun_p2p_sync_checkpoints").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("peer_did",e.text,t=>t.notNull()).addColumn("scope",e.text,t=>t.notNull()).addColumn("checkpoint_hlc",e.text,t=>t.notNull()).addColumn("updated_at",e.timestamp,t=>t.defaultTo(a).notNull()).execute(),await t.schema.createTable("kubun_p2p_broadcast_log").ifNotExists().addColumn("doc_id",e.text,t=>t.notNull()).addColumn("version",e.text,t=>t.notNull()).addColumn("mls_group_id",e.text,t=>t.notNull()).addColumn("broadcast_at",e.timestamp,t=>t.defaultTo(a).notNull()).addPrimaryKeyConstraint("pk_p2p_broadcast_log",["doc_id","version","mls_group_id"]).execute(),await t.schema.createIndex("idx_p2p_broadcast_log_doc").ifNotExists().on("kubun_p2p_broadcast_log").column("doc_id").execute(),await t.schema.createTable("kubun_p2p_hubs").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("label",e.text).addColumn("url",e.text,t=>t.notNull().unique()).addColumn("server_did",e.text).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addColumn("updated_at",e.timestamp).execute(),await t.schema.createTable("kubun_p2p_group_hubs").ifNotExists().addColumn("group_id",e.text,t=>t.notNull()).addColumn("hub_id",e.text,t=>t.notNull()).addColumn("created_at",e.timestamp,t=>t.defaultTo(a).notNull()).addPrimaryKeyConstraint("pk_p2p_group_hubs",["group_id","hub_id"]).execute(),await t.schema.createIndex("idx_p2p_group_hubs_hub").ifNotExists().on("kubun_p2p_group_hubs").column("hub_id").execute()},async down(t){await t.schema.dropTable("kubun_p2p_group_hubs").ifExists().execute(),await t.schema.dropTable("kubun_p2p_hubs").ifExists().execute(),await t.schema.dropTable("kubun_p2p_broadcast_log").ifExists().execute(),await t.schema.dropTable("kubun_p2p_sync_checkpoints").ifExists().execute(),await t.schema.dropTable("kubun_p2p_sync_peers").ifExists().execute(),await t.schema.dropTable("kubun_p2p_group_mls_state").ifExists().execute(),await t.schema.dropTable("kubun_p2p_circle_members").ifExists().execute(),await t.schema.dropTable("kubun_p2p_circles").ifExists().execute(),await t.schema.dropTable("kubun_p2p_group_members").ifExists().execute(),await t.schema.dropTable("kubun_p2p_groups").ifExists().execute()}}}}
package/lib/tables.d.ts CHANGED
@@ -8,7 +8,6 @@ export type GroupTable = {
8
8
  name: string;
9
9
  description: DefaultedStringColumn;
10
10
  created_by: string;
11
- hub_urls: JSONArrayColumn<string>;
12
11
  hlc: string;
13
12
  created_at: CreatedAtColumn;
14
13
  updated_at: UpdatedAtColumn;
@@ -83,6 +82,31 @@ export type SyncCheckpointTable = {
83
82
  };
84
83
  export type SyncCheckpoint = Selectable<SyncCheckpointTable>;
85
84
  export type InsertSyncCheckpoint = Insertable<SyncCheckpointTable>;
85
+ export type BroadcastLogTable = {
86
+ doc_id: string;
87
+ version: string;
88
+ mls_group_id: string;
89
+ broadcast_at: CreatedAtColumn;
90
+ };
91
+ export type BroadcastLogEntry = Selectable<BroadcastLogTable>;
92
+ export type InsertBroadcastLogEntry = Insertable<BroadcastLogTable>;
93
+ export type HubTable = {
94
+ id: string;
95
+ label: string | null;
96
+ url: string;
97
+ server_did: string | null;
98
+ created_at: CreatedAtColumn;
99
+ updated_at: UpdatedAtColumn;
100
+ };
101
+ export type Hub = Selectable<HubTable>;
102
+ export type InsertHub = Insertable<HubTable>;
103
+ export type GroupHubTable = {
104
+ group_id: string;
105
+ hub_id: string;
106
+ created_at: CreatedAtColumn;
107
+ };
108
+ export type GroupHub = Selectable<GroupHubTable>;
109
+ export type InsertGroupHub = Insertable<GroupHubTable>;
86
110
  export type PaginationParams = {
87
111
  limit?: number;
88
112
  offset?: number;
@@ -99,5 +123,8 @@ export type P2PStoreTables = {
99
123
  kubun_p2p_group_mls_state: GroupMLSStateTable;
100
124
  kubun_p2p_sync_peers: SyncPeerTable;
101
125
  kubun_p2p_sync_checkpoints: SyncCheckpointTable;
126
+ kubun_p2p_broadcast_log: BroadcastLogTable;
127
+ kubun_p2p_hubs: HubTable;
128
+ kubun_p2p_group_hubs: GroupHubTable;
102
129
  };
103
130
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/store-p2p",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "license": "see LICENSE.md",
5
5
  "keywords": [],
6
6
  "type": "module",
@@ -15,14 +15,14 @@
15
15
  ],
16
16
  "sideEffects": false,
17
17
  "dependencies": {
18
- "kysely": "^0.28.16",
19
- "@kubun/db": "^0.8.1",
20
- "@kubun/db-adapter": "^0.8.1"
18
+ "kysely": "^0.28.17",
19
+ "@kubun/db": "^0.9.0",
20
+ "@kubun/db-adapter": "^0.9.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@testcontainers/postgresql": "^11.14.0",
24
- "@kubun/db-better-sqlite": "^0.8.1",
25
- "@kubun/db-postgres": "^0.8.1"
24
+ "@kubun/db-better-sqlite": "^0.9.0",
25
+ "@kubun/db-postgres": "^0.9.0"
26
26
  },
27
27
  "scripts": {
28
28
  "build:clean": "del lib",