@kubun/db 0.6.1 → 0.8.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/connector/credential-store.d.ts +23 -0
- package/lib/connector/credential-store.js +1 -0
- package/lib/connector/sync-state-store.d.ts +29 -0
- package/lib/connector/sync-state-store.js +1 -0
- package/lib/db.d.ts +64 -3
- package/lib/db.js +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/migrations/0-init.js +1 -1
- package/lib/types.d.ts +147 -3
- package/package.json +13 -14
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../types.js';
|
|
3
|
+
type Credential = {
|
|
4
|
+
accessToken: string;
|
|
5
|
+
refreshToken?: string;
|
|
6
|
+
expiresAt?: Date;
|
|
7
|
+
scopes: Array<string>;
|
|
8
|
+
accountLabel?: string;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
export type CredentialStore = {
|
|
12
|
+
get(providerName: string, ownerDID: string): Promise<Credential | null>;
|
|
13
|
+
set(providerName: string, ownerDID: string, credential: Credential): Promise<void>;
|
|
14
|
+
delete(providerName: string, ownerDID: string): Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
export declare class DBCredentialStore implements CredentialStore {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(getDB: () => Promise<Kysely<Database>>);
|
|
19
|
+
get(providerName: string, ownerDID: string): Promise<Credential | null>;
|
|
20
|
+
set(providerName: string, ownerDID: string, credential: Credential): Promise<void>;
|
|
21
|
+
delete(providerName: string, ownerDID: string): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class DBCredentialStore{#e;constructor(e){this.#e=e}async get(e,t){let a=await this.#e(),n=await a.selectFrom("kubun_connector_credentials").select("credential").where("provider_name","=",e).where("owner_did","=",t).executeTakeFirst();return null==n?null:this.#t(n.credential)}async set(e,t,a){let n=await this.#e(),r=this.#a(a);await n.insertInto("kubun_connector_credentials").values({provider_name:e,owner_did:t,credential:r}).onConflict(e=>e.columns(["provider_name","owner_did"]).doUpdateSet({credential:r})).execute()}async delete(e,t){let a=await this.#e();await a.deleteFrom("kubun_connector_credentials").where("provider_name","=",e).where("owner_did","=",t).execute()}#a(e){let t={accessToken:e.accessToken,scopes:e.scopes};return null!=e.refreshToken&&(t.refreshToken=e.refreshToken),null!=e.expiresAt&&(t.expiresAt=e.expiresAt.toISOString()),null!=e.accountLabel&&(t.accountLabel=e.accountLabel),null!=e.metadata&&(t.metadata=e.metadata),JSON.stringify(t)}#t(e){let t="string"==typeof e?JSON.parse(e):e,a={accessToken:t.accessToken,scopes:t.scopes};return null!=t.refreshToken&&(a.refreshToken=t.refreshToken),null!=t.expiresAt&&(a.expiresAt=new Date(t.expiresAt)),null!=t.accountLabel&&(a.accountLabel=t.accountLabel),null!=t.metadata&&(a.metadata=t.metadata),a}}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../types.js';
|
|
3
|
+
type SyncStatus = 'idle' | 'syncing' | 'error';
|
|
4
|
+
type SyncState = {
|
|
5
|
+
checkpoint: unknown;
|
|
6
|
+
lastSyncedAt: string;
|
|
7
|
+
entityCount: number;
|
|
8
|
+
status: SyncStatus;
|
|
9
|
+
error?: string;
|
|
10
|
+
};
|
|
11
|
+
type SyncStateEntry = SyncState & {
|
|
12
|
+
connectorName: string;
|
|
13
|
+
ownerDID: string;
|
|
14
|
+
};
|
|
15
|
+
export type SyncStateStore = {
|
|
16
|
+
get(connectorName: string, ownerDID: string): Promise<SyncState | null>;
|
|
17
|
+
set(connectorName: string, ownerDID: string, state: SyncState): Promise<void>;
|
|
18
|
+
delete(connectorName: string, ownerDID: string): Promise<void>;
|
|
19
|
+
listForConnector(connectorName: string): Promise<Array<SyncStateEntry>>;
|
|
20
|
+
};
|
|
21
|
+
export declare class DBSyncStateStore implements SyncStateStore {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(getDB: () => Promise<Kysely<Database>>);
|
|
24
|
+
get(connectorName: string, ownerDID: string): Promise<SyncState | null>;
|
|
25
|
+
set(connectorName: string, ownerDID: string, state: SyncState): Promise<void>;
|
|
26
|
+
delete(connectorName: string, ownerDID: string): Promise<void>;
|
|
27
|
+
listForConnector(connectorName: string): Promise<Array<SyncStateEntry>>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class DBSyncStateStore{#t;constructor(t){this.#t=t}async get(t,e){let n=await this.#t(),c=await n.selectFrom("kubun_connector_sync_state").selectAll().where("connector_name","=",t).where("owner_did","=",e).executeTakeFirst();return null==c?null:this.#e(c)}async set(t,e,n){let c=await this.#t();await c.insertInto("kubun_connector_sync_state").values({connector_name:t,owner_did:e,checkpoint:null!=n.checkpoint?JSON.stringify(n.checkpoint):null,last_synced_at:n.lastSyncedAt,entity_count:n.entityCount,status:n.status,error:n.error??null}).onConflict(t=>t.columns(["connector_name","owner_did"]).doUpdateSet({checkpoint:null!=n.checkpoint?JSON.stringify(n.checkpoint):null,last_synced_at:n.lastSyncedAt,entity_count:n.entityCount,status:n.status,error:n.error??null})).execute()}async delete(t,e){let n=await this.#t();await n.deleteFrom("kubun_connector_sync_state").where("connector_name","=",t).where("owner_did","=",e).execute()}async listForConnector(t){let e=await this.#t();return(await e.selectFrom("kubun_connector_sync_state").selectAll().where("connector_name","=",t).execute()).map(t=>({...this.#e(t),connectorName:t.connector_name,ownerDID:t.owner_did}))}#e(t){let e=null;null!=t.checkpoint&&(e="string"==typeof t.checkpoint?JSON.parse(t.checkpoint):t.checkpoint);let n={checkpoint:e,lastSyncedAt:t.last_synced_at,entityCount:t.entity_count,status:t.status};return null!=t.error&&(n.error=t.error),n}}
|
package/lib/db.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ import { DocumentID, DocumentModelID } from '@kubun/id';
|
|
|
4
4
|
import { type Logger } from '@kubun/logger';
|
|
5
5
|
import type { DocumentModel, DocumentModelsRecord, DocumentNode } from '@kubun/protocol';
|
|
6
6
|
import { Kysely, type Migration } from 'kysely';
|
|
7
|
-
import
|
|
7
|
+
import { type CredentialStore } from './connector/credential-store.js';
|
|
8
|
+
import { type SyncStateStore } from './connector/sync-state-store.js';
|
|
9
|
+
import type { Catalog, Circle, CircleMember, ClusterDefinitionRow, ClusterModel, CountDocumentsParams, Database, DocumentData, GraphModel, InsertCatalog, InsertCircle, InsertCircleMember, InsertClusterModel, InsertDocumentAttachment, InsertMutationLogEntry, InsertSpace, InsertSpaceMember, InsertSpaceMLSState, ListDocumentsParams, MutationLogEntry, QueryDocumentsParams, QueryDocumentsResult, SearchConfig, SearchDocumentResult, SearchDocumentsParams, Space, SpaceMember, SpaceMLSState } from './types.js';
|
|
8
10
|
export type Migrations = Record<string, Migration>;
|
|
9
11
|
export type DocumentCreatedEvent = {
|
|
10
12
|
type: 'create';
|
|
@@ -28,6 +30,14 @@ export type DBParams<T extends AdapterTypes = AdapterTypes> = {
|
|
|
28
30
|
export type GraphModelWithRecord = GraphModel & {
|
|
29
31
|
record: DocumentModelsRecord;
|
|
30
32
|
};
|
|
33
|
+
export type PaginationParams = {
|
|
34
|
+
limit?: number;
|
|
35
|
+
offset?: number;
|
|
36
|
+
};
|
|
37
|
+
export type PaginatedResult<T> = {
|
|
38
|
+
entries: Array<T>;
|
|
39
|
+
hasMore: boolean;
|
|
40
|
+
};
|
|
31
41
|
export type DocumentParams = {
|
|
32
42
|
id: DocumentID;
|
|
33
43
|
data: DocumentData | null;
|
|
@@ -41,8 +51,10 @@ export type SaveDocumentParams = DocumentParams & {
|
|
|
41
51
|
};
|
|
42
52
|
export type CreateGraphParams = {
|
|
43
53
|
aliases?: Record<string, string>;
|
|
44
|
-
|
|
54
|
+
extensionSDL?: string;
|
|
55
|
+
id: string;
|
|
45
56
|
name?: string;
|
|
57
|
+
pluginConfig?: Record<string, Record<string, unknown>>;
|
|
46
58
|
record: DocumentModelsRecord;
|
|
47
59
|
search?: SearchConfig;
|
|
48
60
|
};
|
|
@@ -66,8 +78,9 @@ export type WritableDB = {
|
|
|
66
78
|
export declare class KubunDB<T extends AdapterTypes = AdapterTypes> {
|
|
67
79
|
#private;
|
|
68
80
|
constructor(params: DBParams<T>);
|
|
69
|
-
/** @internal */
|
|
70
81
|
get adapter(): Adapter;
|
|
82
|
+
get connectorCredentialStore(): CredentialStore;
|
|
83
|
+
get connectorSyncStateStore(): SyncStateStore;
|
|
71
84
|
get events(): EventEmitter<DBEvents>;
|
|
72
85
|
getDB<T extends Database>(): Promise<Kysely<T>>;
|
|
73
86
|
withTransaction<R>(fn: (db: WritableDB) => Promise<R>): Promise<R>;
|
|
@@ -112,6 +125,54 @@ export declare class KubunDB<T extends AdapterTypes = AdapterTypes> {
|
|
|
112
125
|
allowedDIDs: Array<string> | null;
|
|
113
126
|
}): Promise<void>;
|
|
114
127
|
removeUserModelAccessDefaults(ownerDID: string, modelID: string, permissionTypes: Array<string>): Promise<void>;
|
|
128
|
+
createCatalog(catalog: InsertCatalog): Promise<void>;
|
|
129
|
+
getCatalog(id: string): Promise<Catalog | undefined>;
|
|
130
|
+
updateCatalog(id: string, update: Partial<Pick<InsertCatalog, 'name' | 'description' | 'filter_criteria' | 'hlc'>>): Promise<void>;
|
|
131
|
+
deleteCatalog(id: string): Promise<void>;
|
|
132
|
+
listCatalogs(ownerDID: string): Promise<Array<Catalog>>;
|
|
133
|
+
registerClusterModels(_clusterID: string, entries: Array<InsertClusterModel>): Promise<void>;
|
|
134
|
+
getClusterForModel(modelID: string): Promise<string | undefined>;
|
|
135
|
+
getClusterModels(clusterID: string): Promise<Array<ClusterModel>>;
|
|
136
|
+
saveCluster(id: string, definition: unknown): Promise<void>;
|
|
137
|
+
getCluster(id: string): Promise<ClusterDefinitionRow | undefined>;
|
|
138
|
+
getClusters(ids: Array<string>): Promise<Record<string, unknown>>;
|
|
139
|
+
createSpace(space: InsertSpace): Promise<void>;
|
|
140
|
+
getSpace(id: string): Promise<Space | undefined>;
|
|
141
|
+
updateSpace(id: string, update: Partial<Pick<InsertSpace, 'name' | 'description' | 'hub_urls' | 'hlc'>>): Promise<void>;
|
|
142
|
+
deleteSpace(id: string): Promise<void>;
|
|
143
|
+
listSpaces(): Promise<Array<Space>>;
|
|
144
|
+
createCircle(circle: InsertCircle): Promise<void>;
|
|
145
|
+
getCircle(id: string): Promise<Circle | undefined>;
|
|
146
|
+
updateCircle(id: string, update: Partial<Pick<InsertCircle, 'name' | 'description' | 'catalog_ids' | 'hlc'>>): Promise<void>;
|
|
147
|
+
deleteCircle(id: string): Promise<void>;
|
|
148
|
+
listCirclesBySpace(spaceID: string): Promise<Array<Circle>>;
|
|
149
|
+
addCircleMember(member: InsertCircleMember): Promise<void>;
|
|
150
|
+
removeCircleMember(circleID: string, memberDID: string): Promise<void>;
|
|
151
|
+
listCircleMembers(circleID: string): Promise<Array<CircleMember>>;
|
|
152
|
+
getCirclesForMember(memberDID: string): Promise<Array<Circle>>;
|
|
153
|
+
isMemberOfAnyCircle(memberDID: string, circleIDs: Array<string>): Promise<boolean>;
|
|
154
|
+
addSpaceMember(member: InsertSpaceMember): Promise<void>;
|
|
155
|
+
removeSpaceMember(spaceID: string, memberDID: string): Promise<void>;
|
|
156
|
+
getSpaceMember(spaceID: string, memberDID: string): Promise<SpaceMember | undefined>;
|
|
157
|
+
isSpaceMember(spaceID: string, memberDID: string): Promise<boolean>;
|
|
158
|
+
listSpaceMembers(spaceID: string): Promise<Array<SpaceMember>>;
|
|
159
|
+
getSpacesForMember(memberDID: string): Promise<Array<Space>>;
|
|
160
|
+
resolveCatalogScope(catalogID: string): Promise<{
|
|
161
|
+
models: Array<string> | undefined;
|
|
162
|
+
owners: Array<string> | undefined;
|
|
163
|
+
}>;
|
|
164
|
+
getDistinctOwnersForModel(modelID: string): Promise<Array<string>>;
|
|
165
|
+
listSpaceMembersPaginated(spaceID: string, params: PaginationParams): Promise<PaginatedResult<SpaceMember>>;
|
|
166
|
+
listCircleMembersPaginated(circleID: string, params: PaginationParams): Promise<PaginatedResult<CircleMember>>;
|
|
167
|
+
listSpacesPaginated(params: PaginationParams): Promise<PaginatedResult<Space>>;
|
|
168
|
+
listCirclesBySpacePaginated(spaceID: string, params: PaginationParams & {
|
|
169
|
+
memberDID?: string;
|
|
170
|
+
}): Promise<PaginatedResult<Circle>>;
|
|
171
|
+
saveMLSState(state: InsertSpaceMLSState): Promise<void>;
|
|
172
|
+
getMLSState(spaceID: string, deviceID: string): Promise<SpaceMLSState | undefined>;
|
|
173
|
+
deleteMLSState(spaceID: string, deviceID: string): Promise<void>;
|
|
174
|
+
listMLSStates(spaceID: string): Promise<Array<SpaceMLSState>>;
|
|
175
|
+
deleteSpaceMLSStates(spaceID: string): Promise<void>;
|
|
115
176
|
listDocumentModelIDs(): Promise<Array<string>>;
|
|
116
177
|
queryDocumentsByOwner(modelID: string, ownerDID: string): Promise<Array<DocumentNode>>;
|
|
117
178
|
createSearchIndex(modelID: string, fields: Array<string>): Promise<void>;
|
package/lib/db.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter as e}from"@enkaku/event";import{DocumentID as t,DocumentModelID as a}from"@kubun/id";import{getKubunLogger as i}from"@kubun/logger";import{Kysely as r,Migrator as s,ParseJSONResultsPlugin as n}from"kysely";import{serializeCursor as d}from"./cursor.js";import{getMigrations as o}from"./migrations/migrations.js";import{applyDocumentFilter as l,applyDocumentOrderBy as u,applyPagination as c}from"./query-builder.js";function h(e){let t={version:e.version,name:e.name,behavior:e.behavior,interfaces:e.interfaces,schema:e.schema,fieldsMeta:e.fields_meta};return"unique"===t.behavior&&(t.uniqueFields=e.unique_fields),t}function m(e,t){return{id:t.id,model:t.model,owner:t.owner,data:t.data,createdAt:e.decodeTimestamp(t.created_at),updatedAt:t.updated_at?e.decodeTimestamp(t.updated_at):null}}function w(e,t){let i=a.fromString(t);return i.isLocal?i.toGlobal(a.fromString(e)).toString():t}export class KubunDB{#e;#t;#a;#i;#r;constructor(t){this.#e=t.adapter,this.#t=new r({dialect:this.#e.dialect,plugins:[new n]}),this.#a=new e,this.#i=t.logger??i("db"),this.#r=this.#s()}get adapter(){return this.#e}get events(){return this.#a}getDB(){return this.#r.then(()=>this.#t)}async withTransaction(e){await this.#r;let a=this.#e,i=this.#a,r=[],s=await this.#t.transaction().setIsolationLevel("read committed").execute(async s=>await e({events:i,getDocumentModel:async e=>h(await s.selectFrom("kubun_document_models").selectAll().where("id","=",e.toString()).executeTakeFirstOrThrow()),async getDocument(e){let t=await s.selectFrom(`k_${e.model.toString()}`).selectAll().where("id","=",e.toString()).executeTakeFirst();return t?m(a,t):null},async createDocument(e){let t=e.id.toString(),i=e.id.model.toString(),n=await s.insertInto(`k_${i}`).values({id:t,owner:e.owner,model:i,data:a.encodeJSON(e.data),unique:a.encodeBinary(e.unique)}).returningAll().executeTakeFirst(),o=m(a,n);return r.push({type:"create",document:o,getCursor:()=>d({id:n.id,ts:+n.created_at})}),o},async saveDocument(e){let t=e.id.toString(),i=await s.updateTable(`k_${e.id.model.toString()}`).set({data:e.data?a.encodeJSON(e.data):null,updated_at:a.encodeTimestamp(new Date)}).where("id","=",t).returningAll().executeTakeFirst(),n=m(a,i);return r.push({type:"update",document:n,previous:e.existing,getCursor:()=>d({id:i.id,ts:+i.created_at})}),n},async insertMutationLogEntry(e){await s.insertInto("kubun_mutation_log").values(e).onConflict(e=>e.doNothing()).execute()},hasMutationHash:async e=>null!=await s.selectFrom("kubun_mutation_log").select("mutation_hash").where("mutation_hash","=",e).executeTakeFirst(),async updateMutationStatus(e,t){await s.updateTable("kubun_mutation_log").set({status:t}).where("mutation_hash","=",e).execute()},async getFieldHLCs(e){let a=t.fromString(e).model.toString(),i=await s.selectFrom(`k_${a}`).select("field_hlcs").where("id","=",e).executeTakeFirst();if(i?.field_hlcs==null)return null;let r=i.field_hlcs;return"string"==typeof r?JSON.parse(r):r},async updateFieldHLCs(e,t){let i=e.model.toString();await s.updateTable(`k_${i}`).set({field_hlcs:a.encodeJSON(t)}).where("id","=",e.toString()).execute()}}));for(let e of r)i.emit("document:saved",e);return s}async #s(){let e=new s({db:this.#t,provider:{getMigrations:()=>Promise.resolve(this.getMigrations())}}),t=await e.migrateToLatest();if(null!=t.error)throw t.error;this.#i.info("ready")}getMigrations(){return o(this.#e)}async close(){await this.#r,await this.#t.destroy(),this.#i.info("closed")}async listGraphs(){return await this.#r,await this.#t.selectFrom("kubun_graph_models").selectAll().execute()}async createGraph(e){await this.#r;let t=e.id??globalThis.crypto.randomUUID(),a=e.name??t;return await this.#t.transaction().setIsolationLevel("read committed").execute(async i=>{await i.insertInto("kubun_graph_models").values({aliases:JSON.stringify(e.aliases??{}),id:t,name:a,search:e.search?JSON.stringify(e.search):null}).onConflict(e=>e.doNothing()).execute();let r=Object.entries(e.record),s=new Set;for(;s.size<r.length;){let e=r.filter(([e,t])=>!s.has(e)&&t.interfaces.every(t=>s.has(w(e,t))));if(0===e.length)throw Error("Could not create graph: no valid model to add");await Promise.all(e.map(async([e,a])=>{await this.#n(i,{id:e,graphModelID:t,model:a}),s.add(e)}))}}),this.#i.debug("created graph {id}",{id:t}),t}async #n(e,t){let{id:a,graphModelID:i,model:r}=t,s=this.#e.types;for(let t of(await this.#r,await e.schema.createTable(`k_${a}`).ifNotExists().addColumn("id",s.text,e=>e.notNull().primaryKey()).addColumn("owner",s.text,e=>e.notNull()).addColumn("model",s.text,e=>e.notNull()).addColumn("data",s.json).addColumn("field_hlcs",s.json).addColumn("unique",s.binary,e=>e.notNull()).addColumn("created_at",s.timestamp,e=>e.defaultTo(this.#e.functions.now).notNull()).addColumn("updated_at",s.timestamp).execute(),await e.insertInto("kubun_document_models").values({id:a,version:r.version,name:r.name,behavior:r.behavior,unique_fields:"unique"===r.behavior?JSON.stringify(r.uniqueFields):null,interfaces:JSON.stringify(r.interfaces),schema:JSON.stringify(r.schema),fields_meta:JSON.stringify(r.fieldsMeta)}).onConflict(e=>e.doNothing()).execute(),r.interfaces))await e.insertInto("kubun_document_model_interfaces").values({interface_id:w(a,t),implementation_id:a}).onConflict(e=>e.doNothing()).execute();await e.insertInto("kubun_graph_document_models").values({graph_model_id:i,document_model_id:a}).onConflict(e=>e.doNothing()).execute()}async getGraph(e){await this.#r;let t=await this.#t.selectFrom("kubun_graph_models").selectAll().where("id","=",e).executeTakeFirst();if(null==t)return null;let a={};for(let t of(await this.#t.selectFrom("kubun_graph_document_models").innerJoin("kubun_document_models","kubun_graph_document_models.document_model_id","kubun_document_models.id").selectAll("kubun_document_models").where("kubun_graph_document_models.graph_model_id","=",e).execute()))a[t.id]=h(t);return{...t,record:a}}async getDocumentModel(e){return await this.#r,h(await this.#t.selectFrom("kubun_document_models").selectAll().where("id","=",e.toString()).executeTakeFirstOrThrow())}async getDocument(e){await this.#r;let t=await this.#t.selectFrom(`k_${e.model.toString()}`).selectAll().where("id","=",e.toString()).executeTakeFirst();return t?m(this.#e,t):null}async listDocuments(e){await this.#r;let[t,...a]=e.modelIDs,i=this.#t.selectFrom(`k_${t}`).selectAll().where("id","in",e.docIDs);for(let t of a)i=i.unionAll(a=>a.selectFrom(`k_${t}`).selectAll().where("id","in",e.docIDs));return(await i.execute()).map(e=>m(this.#e,e))}async countDocuments(e){let{filter:t,modelIDs:a,owner:i}=e;await this.#r;let r=this.#e.coerceFilterValue.bind(this.#e);return(await Promise.all(a.map(async e=>{let a=this.#t.selectFrom(`k_${e}`).select(e=>e.fn.countAll().as("count"));return null!=i&&(a=a.where("owner","=",i)),null!=t&&(a=a.where(e=>l(e,t,[],r))),Number((await a.executeTakeFirstOrThrow()).count)}))).reduce((e,t)=>e+t,0)}async queryDocuments(e){let{filter:t,modelIDs:a,orderBy:i,owner:r,...s}=e,n=null!=e.last;await this.#r;let o=this.#e.coerceFilterValue.bind(this.#e),[h,...w]=a,_=this.#t.selectFrom(`k_${h}`).selectAll();for(let e of(null!=r&&(_=_.where("owner","=",r)),null!=t&&(_=_.where(e=>l(e,t,[],o))),w))_=_.unionAll(a=>{let i=a.selectFrom(`k_${e}`).selectAll();return null!=r&&(i=i.where("owner","=",r)),null!=t&&(i=i.where(e=>l(e,t,[],o))),i});let[p,y]=u(_,i,n),[g,f]=c(p,s,i),b=await g.execute(),k=n?b.slice(0,f).reverse():b.slice(0,f);return{entries:y?k.map(e=>{let t={};for(let a of y){let i=e.data;for(let e of a)null!=i&&(i=i[e]);null!=i&&(t[a.join(".")]=i)}return{cursor:d({id:e.id,values:t}),document:m(this.#e,e)}}):k.map(e=>({cursor:d({id:e.id,ts:+e.created_at}),document:m(this.#e,e)})),hasMore:k.length>f}}async createDocument(e){await this.#r;let t=e.id.toString(),a=e.id.model.toString(),i={id:t,owner:e.owner,model:a,data:this.#e.encodeJSON(e.data),unique:this.#e.encodeBinary(e.unique)},r=await this.#t.transaction().setIsolationLevel("read committed").execute(async e=>await e.insertInto(`k_${a}`).values(i).returningAll().executeTakeFirst()),s=m(this.#e,r);return this.#a.emit("document:saved",{type:"create",document:s,getCursor:()=>d({id:r.id,ts:+r.created_at})}),this.#i.debug("created document {id} with model {model}",{id:t,model:a}),s}async saveDocument(e){await this.#r;let t=e.id.toString(),a={data:e.data?this.#e.encodeJSON(e.data):null,updated_at:this.#e.encodeTimestamp(new Date)},i=await this.#t.transaction().setIsolationLevel("read committed").execute(async i=>await i.updateTable(`k_${e.id.model.toString()}`).set(a).where("id","=",t).returningAll().executeTakeFirst()),r=m(this.#e,i);return this.#a.emit("document:saved",{type:"update",document:r,previous:e.existing,getCursor:()=>d({id:i.id,ts:+i.created_at})}),this.#i.debug("updated document {id}",{id:t}),r}async insertMutationLogEntry(e){await this.#r,await this.#t.insertInto("kubun_mutation_log").values(e).onConflict(e=>e.doNothing()).execute()}async hasMutationHash(e){return await this.#r,null!=await this.#t.selectFrom("kubun_mutation_log").select("mutation_hash").where("mutation_hash","=",e).executeTakeFirst()}async getMutationLogForDocuments(e){return 0===e.length?[]:(await this.#r,await this.#t.selectFrom("kubun_mutation_log").selectAll().where("document_id","in",e).orderBy("hlc","asc").execute())}async getPendingMutations(e){return await this.#r,await this.#t.selectFrom("kubun_mutation_log").selectAll().where("document_id","=",e).where("status","=","pending").orderBy("hlc","asc").execute()}async updateMutationStatus(e,t){await this.#r,await this.#t.updateTable("kubun_mutation_log").set({status:t}).where("mutation_hash","=",e).execute()}async getFieldHLCs(e){await this.#r;let a=t.fromString(e).model.toString(),i=await this.#t.selectFrom(`k_${a}`).select("field_hlcs").where("id","=",e).executeTakeFirst();if(i?.field_hlcs==null)return null;let r=i.field_hlcs;return"string"==typeof r?JSON.parse(r):r}async updateFieldHLCs(e,t){await this.#r;let a=e.model.toString();await this.#t.updateTable(`k_${a}`).set({field_hlcs:this.#e.encodeJSON(t)}).where("id","=",e.toString()).execute()}async getDocumentIDsForScope(e,t=[]){await this.#r;let a=[];for(let t of e)try{let e=await this.#t.selectFrom(`k_${t.modelID}`).select("id").where("owner","=",t.ownerDID).execute();a.push(...e.map(e=>e.id))}catch{}if(t.length>0){let e=new Set(t);return a.filter(t=>!e.has(t))}return a}async getDocumentMetadataForSync(e,t){return 0===t.length?[]:(await this.#r,(await this.#t.selectFrom(`k_${e}`).select(["id","model","owner"]).where("id","in",t).execute()).map(e=>({id:e.id,model:e.model,owner:e.owner})))}async addAttachments(e){await this.#r,await this.#t.insertInto("kubun_document_attachments").values(e).onConflict(e=>e.doNothing()).execute()}async getUserModelAccessDefault(e,t,a){await this.#r;let i=await this.#t.selectFrom("kubun_user_model_access_defaults").select(["access_level","allowed_dids"]).where("owner_did","=",e).where("model_id","=",t).where("permission_type","=",a).executeTakeFirst();return i?{level:i.access_level,allowedDIDs:i.allowed_dids}:null}async setUserModelAccessDefault(e){await this.#r,await this.#t.insertInto("kubun_user_model_access_defaults").values({owner_did:e.ownerDID,model_id:e.modelID,permission_type:e.permissionType,access_level:e.accessLevel,allowed_dids:e.allowedDIDs?this.#e.encodeJSON(e.allowedDIDs):null}).onConflict(t=>t.columns(["owner_did","model_id","permission_type"]).doUpdateSet({access_level:e.accessLevel,allowed_dids:e.allowedDIDs?this.#e.encodeJSON(e.allowedDIDs):null,updated_at:this.#e.encodeTimestamp(new Date)})).execute()}async removeUserModelAccessDefaults(e,t,a){await this.#r,await this.#t.deleteFrom("kubun_user_model_access_defaults").where("owner_did","=",e).where("model_id","=",t).where("permission_type","in",a).execute()}async listDocumentModelIDs(){return await this.#r,(await this.#t.selectFrom("kubun_document_models").select("id").execute()).map(e=>e.id)}async queryDocumentsByOwner(e,t){return await this.#r,(await this.#t.selectFrom(`k_${e}`).selectAll().where("owner","=",t).execute()).map(e=>m(this.#e,e))}async createSearchIndex(e,t){await this.#r,await this.#e.createSearchIndex(this.#t,{modelID:e,fields:t})}async dropSearchIndex(e){await this.#r,await this.#e.dropSearchIndex(this.#t,e)}async updateSearchEntry(e,t,a,i){await this.#r;let r={};for(let e of i){let t=this.#d(a,e);null!=t&&(r[e]=String(t))}await this.#e.updateSearchEntry(this.#t,e,t,r,i)}async removeSearchEntry(e,t){await this.#r,await this.#e.removeSearchEntry(this.#t,e,t)}async searchDocuments(e){await this.#r;let t=[];for(let a of e.modelIDs)for(let i of(await this.#e.searchIndex(this.#t,{query:e.query,modelID:a,limit:e.first??50})))t.push({documentID:i.documentID,modelID:a,rank:i.rank});return(t.sort((e,t)=>Math.abs(t.rank)-Math.abs(e.rank)),e.first)?t.slice(0,e.first):t}#d(e,t){let a=t.split("."),i=e;for(let e of a){if(null==i||"object"!=typeof i)return null;i=i[e]}return i}}
|
|
1
|
+
import{EventEmitter as e}from"@enkaku/event";import{DocumentID as t,DocumentModelID as a}from"@kubun/id";import{getKubunLogger as i}from"@kubun/logger";import{Kysely as r,Migrator as s,ParseJSONResultsPlugin as l}from"kysely";import{DBCredentialStore as n}from"./connector/credential-store.js";import{DBSyncStateStore as d}from"./connector/sync-state-store.js";import{serializeCursor as c}from"./cursor.js";import{getMigrations as o}from"./migrations/migrations.js";import{applyDocumentFilter as u,applyDocumentOrderBy as h,applyPagination as m}from"./query-builder.js";function _(e){let t={version:e.version,name:e.name,behavior:e.behavior,interfaces:e.interfaces,schema:e.schema,fieldsMeta:e.fields_meta};return"unique"===t.behavior&&(t.uniqueFields=e.unique_fields),t}function w(e,t){return{id:t.id,model:t.model,owner:t.owner,data:t.data,createdAt:e.decodeTimestamp(t.created_at),updatedAt:t.updated_at?e.decodeTimestamp(t.updated_at):null}}function b(e,t){let i=a.fromString(t);return i.isLocal?i.toGlobal(a.fromString(e)).toString():t}export class KubunDB{#e;#t=null;#a=null;#i;#r;#s;#l;constructor(t){this.#e=t.adapter,this.#i=new r({dialect:this.#e.dialect,plugins:[new l]}),this.#r=new e,this.#s=t.logger??i("db"),this.#l=this.#n()}get adapter(){return this.#e}get connectorCredentialStore(){return null==this.#t&&(this.#t=new n(()=>this.getDB())),this.#t}get connectorSyncStateStore(){return null==this.#a&&(this.#a=new d(()=>this.getDB())),this.#a}get events(){return this.#r}getDB(){return this.#l.then(()=>this.#i)}async withTransaction(e){await this.#l;let a=this.#e,i=this.#r,r=[],s=await this.#i.transaction().setIsolationLevel("read committed").execute(async s=>await e({events:i,getDocumentModel:async e=>_(await s.selectFrom("kubun_document_models").selectAll().where("id","=",e.toString()).executeTakeFirstOrThrow()),async getDocument(e){let t=await s.selectFrom(`k_${e.model.toString()}`).selectAll().where("id","=",e.toString()).executeTakeFirst();return t?w(a,t):null},async createDocument(e){let t=e.id.toString(),i=e.id.model.toString(),l=await s.insertInto(`k_${i}`).values({id:t,owner:e.owner,model:i,data:a.encodeJSON(e.data),unique:a.encodeBinary(e.unique)}).returningAll().executeTakeFirst(),n=w(a,l);return r.push({type:"create",document:n,getCursor:()=>c({id:l.id,ts:+l.created_at})}),n},async saveDocument(e){let t=e.id.toString(),i=await s.updateTable(`k_${e.id.model.toString()}`).set({data:e.data?a.encodeJSON(e.data):null,updated_at:a.encodeTimestamp(new Date)}).where("id","=",t).returningAll().executeTakeFirst(),l=w(a,i);return r.push({type:"update",document:l,previous:e.existing,getCursor:()=>c({id:i.id,ts:+i.created_at})}),l},async insertMutationLogEntry(e){await s.insertInto("kubun_mutation_log").values(e).onConflict(e=>e.doNothing()).execute()},hasMutationHash:async e=>null!=await s.selectFrom("kubun_mutation_log").select("mutation_hash").where("mutation_hash","=",e).executeTakeFirst(),async updateMutationStatus(e,t){await s.updateTable("kubun_mutation_log").set({status:t}).where("mutation_hash","=",e).execute()},async getFieldHLCs(e){let a=t.fromString(e).model.toString(),i=await s.selectFrom(`k_${a}`).select("field_hlcs").where("id","=",e).executeTakeFirst();if(i?.field_hlcs==null)return null;let r=i.field_hlcs;return"string"==typeof r?JSON.parse(r):r},async updateFieldHLCs(e,t){let i=e.model.toString();await s.updateTable(`k_${i}`).set({field_hlcs:a.encodeJSON(t)}).where("id","=",e.toString()).execute()}}));for(let e of r)i.emit("document:saved",e);return s}async #n(){let e=new s({db:this.#i,provider:{getMigrations:()=>Promise.resolve(this.getMigrations())}}),t=await e.migrateToLatest();if(null!=t.error)throw t.error;this.#s.info("ready")}getMigrations(){return o(this.#e)}async close(){await this.#l,await this.#i.destroy(),this.#s.info("closed")}async listGraphs(){return await this.#l,await this.#i.selectFrom("kubun_graph_models").selectAll().execute()}async createGraph(e){await this.#l;let t=e.id,a=e.name??t;return await this.#i.transaction().setIsolationLevel("read committed").execute(async i=>{await i.insertInto("kubun_graph_models").values({aliases:JSON.stringify(e.aliases??{}),extension_sdl:e.extensionSDL??null,id:t,name:a,plugin_config:e.pluginConfig?JSON.stringify(e.pluginConfig):null,search:e.search?JSON.stringify(e.search):null}).onConflict(e=>e.doNothing()).execute();let r=Object.entries(e.record),s=new Set;for(;s.size<r.length;){let e=r.filter(([e,t])=>!s.has(e)&&t.interfaces.every(t=>s.has(b(e,t))));if(0===e.length)throw Error("Could not create graph: no valid model to add");await Promise.all(e.map(async([e,a])=>{await this.#d(i,{id:e,graphModelID:t,model:a}),s.add(e)}))}}),this.#s.debug("created graph {id}",{id:t}),t}async #d(e,t){let{id:a,graphModelID:i,model:r}=t,s=this.#e.types;for(let t of(await this.#l,await e.schema.createTable(`k_${a}`).ifNotExists().addColumn("id",s.text,e=>e.notNull().primaryKey()).addColumn("owner",s.text,e=>e.notNull()).addColumn("model",s.text,e=>e.notNull()).addColumn("data",s.json).addColumn("field_hlcs",s.json).addColumn("unique",s.binary,e=>e.notNull()).addColumn("created_at",s.timestamp,e=>e.defaultTo(this.#e.functions.now).notNull()).addColumn("updated_at",s.timestamp).execute(),await e.insertInto("kubun_document_models").values({id:a,version:r.version,name:r.name,behavior:r.behavior,unique_fields:"unique"===r.behavior?JSON.stringify(r.uniqueFields):null,interfaces:JSON.stringify(r.interfaces),schema:JSON.stringify(r.schema),fields_meta:JSON.stringify(r.fieldsMeta)}).onConflict(e=>e.doNothing()).execute(),r.interfaces))await e.insertInto("kubun_document_model_interfaces").values({interface_id:b(a,t),implementation_id:a}).onConflict(e=>e.doNothing()).execute();await e.insertInto("kubun_graph_document_models").values({graph_model_id:i,document_model_id:a}).onConflict(e=>e.doNothing()).execute()}async getGraph(e){await this.#l;let t=await this.#i.selectFrom("kubun_graph_models").selectAll().where("id","=",e).executeTakeFirst();if(null==t)return null;let a={};for(let t of(await this.#i.selectFrom("kubun_graph_document_models").innerJoin("kubun_document_models","kubun_graph_document_models.document_model_id","kubun_document_models.id").selectAll("kubun_document_models").where("kubun_graph_document_models.graph_model_id","=",e).execute()))a[t.id]=_(t);return{...t,record:a}}async getDocumentModel(e){return await this.#l,_(await this.#i.selectFrom("kubun_document_models").selectAll().where("id","=",e.toString()).executeTakeFirstOrThrow())}async getDocument(e){await this.#l;let t=await this.#i.selectFrom(`k_${e.model.toString()}`).selectAll().where("id","=",e.toString()).executeTakeFirst();return t?w(this.#e,t):null}async listDocuments(e){await this.#l;let[t,...a]=e.modelIDs,i=this.#i.selectFrom(`k_${t}`).selectAll().where("id","in",e.docIDs);for(let t of a)i=i.unionAll(a=>a.selectFrom(`k_${t}`).selectAll().where("id","in",e.docIDs));return(await i.execute()).map(e=>w(this.#e,e))}async #c(e,t){if(null==t)return{effectiveModelIDs:e,effectiveOwners:void 0};let{models:a,owners:i}=await this.resolveCatalogScope(t),r=e;if(null!=a){let e=new Set(a);r=r.filter(t=>e.has(t))}return{effectiveModelIDs:r,effectiveOwners:i}}async countDocuments(e){let{catalogID:t,filter:a,modelIDs:i,owner:r}=e;await this.#l;let s=this.#e.coerceFilterValue.bind(this.#e),{effectiveModelIDs:l,effectiveOwners:n}=await this.#c(i,t);return 0===l.length?0:(await Promise.all(l.map(async e=>{let t=this.#i.selectFrom(`k_${e}`).select(e=>e.fn.countAll().as("count"));return null!=r&&(t=t.where("owner","=",r)),null!=n&&(t=t.where("owner","in",n)),null!=a&&(t=t.where(e=>u(e,a,[],s))),Number((await t.executeTakeFirstOrThrow()).count)}))).reduce((e,t)=>e+t,0)}async queryDocuments(e){let{catalogID:t,filter:a,modelIDs:i,orderBy:r,owner:s,...l}=e,n=null!=e.last;await this.#l;let d=this.#e.coerceFilterValue.bind(this.#e),{effectiveModelIDs:o,effectiveOwners:_}=await this.#c(i,t);if(0===o.length)return{entries:[],hasMore:!1};let[b,...p]=o,y=this.#i.selectFrom(`k_${b}`).selectAll();for(let e of(null!=s&&(y=y.where("owner","=",s)),null!=_&&(y=y.where("owner","in",_)),null!=a&&(y=y.where(e=>u(e,a,[],d))),p))y=y.unionAll(t=>{let i=t.selectFrom(`k_${e}`).selectAll();return null!=s&&(i=i.where("owner","=",s)),null!=_&&(i=i.where("owner","in",_)),null!=a&&(i=i.where(e=>u(e,a,[],d))),i});let[g,f]=h(y,r,n),[k,S]=m(g,l,r),x=await k.execute(),F=n?x.slice(0,S).reverse():x.slice(0,S);return{entries:f?F.map(e=>{let t={};for(let a of f){let i=e.data;for(let e of a)null!=i&&(i=i[e]);null!=i&&(t[a.join(".")]=i)}return{cursor:c({id:e.id,values:t}),document:w(this.#e,e)}}):F.map(e=>({cursor:c({id:e.id,ts:+e.created_at}),document:w(this.#e,e)})),hasMore:F.length>S}}async createDocument(e){await this.#l;let t=e.id.toString(),a=e.id.model.toString(),i={id:t,owner:e.owner,model:a,data:this.#e.encodeJSON(e.data),unique:this.#e.encodeBinary(e.unique)},r=await this.#i.transaction().setIsolationLevel("read committed").execute(async e=>await e.insertInto(`k_${a}`).values(i).returningAll().executeTakeFirst()),s=w(this.#e,r);return this.#r.emit("document:saved",{type:"create",document:s,getCursor:()=>c({id:r.id,ts:+r.created_at})}),this.#s.debug("created document {id} with model {model}",{id:t,model:a}),s}async saveDocument(e){await this.#l;let t=e.id.toString(),a={data:e.data?this.#e.encodeJSON(e.data):null,updated_at:this.#e.encodeTimestamp(new Date)},i=await this.#i.transaction().setIsolationLevel("read committed").execute(async i=>await i.updateTable(`k_${e.id.model.toString()}`).set(a).where("id","=",t).returningAll().executeTakeFirst()),r=w(this.#e,i);return this.#r.emit("document:saved",{type:"update",document:r,previous:e.existing,getCursor:()=>c({id:i.id,ts:+i.created_at})}),this.#s.debug("updated document {id}",{id:t}),r}async insertMutationLogEntry(e){await this.#l,await this.#i.insertInto("kubun_mutation_log").values(e).onConflict(e=>e.doNothing()).execute()}async hasMutationHash(e){return await this.#l,null!=await this.#i.selectFrom("kubun_mutation_log").select("mutation_hash").where("mutation_hash","=",e).executeTakeFirst()}async getMutationLogForDocuments(e){return 0===e.length?[]:(await this.#l,await this.#i.selectFrom("kubun_mutation_log").selectAll().where("document_id","in",e).orderBy("hlc","asc").execute())}async getPendingMutations(e){return await this.#l,await this.#i.selectFrom("kubun_mutation_log").selectAll().where("document_id","=",e).where("status","=","pending").orderBy("hlc","asc").execute()}async updateMutationStatus(e,t){await this.#l,await this.#i.updateTable("kubun_mutation_log").set({status:t}).where("mutation_hash","=",e).execute()}async getFieldHLCs(e){await this.#l;let a=t.fromString(e).model.toString(),i=await this.#i.selectFrom(`k_${a}`).select("field_hlcs").where("id","=",e).executeTakeFirst();if(i?.field_hlcs==null)return null;let r=i.field_hlcs;return"string"==typeof r?JSON.parse(r):r}async updateFieldHLCs(e,t){await this.#l;let a=e.model.toString();await this.#i.updateTable(`k_${a}`).set({field_hlcs:this.#e.encodeJSON(t)}).where("id","=",e.toString()).execute()}async getDocumentIDsForScope(e,t=[]){await this.#l;let a=[];for(let t of e)try{let e=await this.#i.selectFrom(`k_${t.modelID}`).select("id").where("owner","=",t.ownerDID).execute();a.push(...e.map(e=>e.id))}catch{}if(t.length>0){let e=new Set(t);return a.filter(t=>!e.has(t))}return a}async getDocumentMetadataForSync(e,t){return 0===t.length?[]:(await this.#l,(await this.#i.selectFrom(`k_${e}`).select(["id","model","owner"]).where("id","in",t).execute()).map(e=>({id:e.id,model:e.model,owner:e.owner})))}async addAttachments(e){await this.#l,await this.#i.insertInto("kubun_document_attachments").values(e).onConflict(e=>e.doNothing()).execute()}async getUserModelAccessDefault(e,t,a){await this.#l;let i=await this.#i.selectFrom("kubun_user_model_access_defaults").select(["access_level","allowed_dids"]).where("owner_did","=",e).where("model_id","=",t).where("permission_type","=",a).executeTakeFirst();return i?{level:i.access_level,allowedDIDs:i.allowed_dids}:null}async setUserModelAccessDefault(e){await this.#l,await this.#i.insertInto("kubun_user_model_access_defaults").values({owner_did:e.ownerDID,model_id:e.modelID,permission_type:e.permissionType,access_level:e.accessLevel,allowed_dids:e.allowedDIDs?this.#e.encodeJSON(e.allowedDIDs):null}).onConflict(t=>t.columns(["owner_did","model_id","permission_type"]).doUpdateSet({access_level:e.accessLevel,allowed_dids:e.allowedDIDs?this.#e.encodeJSON(e.allowedDIDs):null,updated_at:this.#e.encodeTimestamp(new Date)})).execute()}async removeUserModelAccessDefaults(e,t,a){await this.#l,await this.#i.deleteFrom("kubun_user_model_access_defaults").where("owner_did","=",e).where("model_id","=",t).where("permission_type","in",a).execute()}async createCatalog(e){await this.#l,await this.#i.insertInto("kubun_catalogs").values({id:e.id,owner_did:e.owner_did,name:e.name,description:e.description,filter_criteria:this.#e.encodeJSON(e.filter_criteria),hlc:e.hlc}).execute()}async getCatalog(e){return await this.#l,await this.#i.selectFrom("kubun_catalogs").selectAll().where("id","=",e).executeTakeFirst()}async updateCatalog(e,t){await this.#l;let a={};null!=t.name&&(a.name=t.name),null!=t.description&&(a.description=t.description),null!=t.filter_criteria&&(a.filter_criteria=this.#e.encodeJSON(t.filter_criteria)),null!=t.hlc&&(a.hlc=t.hlc),a.updated_at=this.#e.encodeTimestamp(new Date),await this.#i.updateTable("kubun_catalogs").set(a).where("id","=",e).execute()}async deleteCatalog(e){await this.#l,await this.#i.deleteFrom("kubun_catalogs").where("id","=",e).execute()}async listCatalogs(e){return await this.#l,await this.#i.selectFrom("kubun_catalogs").selectAll().where("owner_did","=",e).execute()}async registerClusterModels(e,t){0!==t.length&&(await this.#l,await this.#i.insertInto("kubun_cluster_models").values(t).onConflict(e=>e.column("model_id").doUpdateSet(e=>({cluster_id:e.ref("excluded.cluster_id"),cluster_index:e.ref("excluded.cluster_index")}))).execute())}async getClusterForModel(e){await this.#l;let t=await this.#i.selectFrom("kubun_cluster_models").select("cluster_id").where("model_id","=",e).executeTakeFirst();return t?.cluster_id}async getClusterModels(e){return await this.#l,await this.#i.selectFrom("kubun_cluster_models").selectAll().where("cluster_id","=",e).orderBy("cluster_index").execute()}async saveCluster(e,t){await this.#l,await this.#i.insertInto("kubun_clusters").values({id:e,definition:this.#e.encodeJSON(t)}).onConflict(e=>e.column("id").doUpdateSet(e=>({definition:e.ref("excluded.definition")}))).execute()}async getCluster(e){return await this.#l,await this.#i.selectFrom("kubun_clusters").selectAll().where("id","=",e).executeTakeFirst()}async getClusters(e){if(await this.#l,0===e.length)return{};let t=await this.#i.selectFrom("kubun_clusters").selectAll().where("id","in",e).execute(),a={};for(let e of t)a[e.id]=e.definition;return a}async createSpace(e){await this.#l,await this.#i.insertInto("kubun_spaces").values({id:e.id,name:e.name,description:e.description,created_by:e.created_by,hub_urls:this.#e.encodeJSON(e.hub_urls??[]),hlc:e.hlc}).execute()}async getSpace(e){return await this.#l,await this.#i.selectFrom("kubun_spaces").selectAll().where("id","=",e).executeTakeFirst()}async updateSpace(e,t){await this.#l;let a={};null!=t.name&&(a.name=t.name),null!=t.description&&(a.description=t.description),null!=t.hub_urls&&(a.hub_urls=this.#e.encodeJSON(t.hub_urls)),null!=t.hlc&&(a.hlc=t.hlc),a.updated_at=this.#e.encodeTimestamp(new Date),await this.#i.updateTable("kubun_spaces").set(a).where("id","=",e).execute()}async deleteSpace(e){await this.#l,await this.#i.deleteFrom("kubun_spaces").where("id","=",e).execute()}async listSpaces(){return await this.#l,await this.#i.selectFrom("kubun_spaces").selectAll().execute()}async createCircle(e){await this.#l,await this.#i.insertInto("kubun_circles").values({id:e.id,space_id:e.space_id,name:e.name,description:e.description,catalog_ids:this.#e.encodeJSON(e.catalog_ids),hlc:e.hlc}).execute()}async getCircle(e){return await this.#l,await this.#i.selectFrom("kubun_circles").selectAll().where("id","=",e).executeTakeFirst()}async updateCircle(e,t){await this.#l;let a={};null!=t.name&&(a.name=t.name),null!=t.description&&(a.description=t.description),null!=t.catalog_ids&&(a.catalog_ids=this.#e.encodeJSON(t.catalog_ids)),null!=t.hlc&&(a.hlc=t.hlc),a.updated_at=this.#e.encodeTimestamp(new Date),await this.#i.updateTable("kubun_circles").set(a).where("id","=",e).execute()}async deleteCircle(e){await this.#l,await this.#i.deleteFrom("kubun_circles").where("id","=",e).execute()}async listCirclesBySpace(e){return await this.#l,await this.#i.selectFrom("kubun_circles").selectAll().where("space_id","=",e).execute()}async addCircleMember(e){await this.#l,await this.#i.insertInto("kubun_circle_members").values({circle_id:e.circle_id,member_did:e.member_did,role:e.role,hlc:e.hlc}).onConflict(e=>e.columns(["circle_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),hlc:e.ref("excluded.hlc")}))).execute()}async removeCircleMember(e,t){await this.#l,await this.#i.deleteFrom("kubun_circle_members").where("circle_id","=",e).where("member_did","=",t).execute()}async listCircleMembers(e){return await this.#l,await this.#i.selectFrom("kubun_circle_members").selectAll().where("circle_id","=",e).execute()}async getCirclesForMember(e){return await this.#l,await this.#i.selectFrom("kubun_circle_members").innerJoin("kubun_circles","kubun_circles.id","kubun_circle_members.circle_id").selectAll("kubun_circles").where("kubun_circle_members.member_did","=",e).execute()}async isMemberOfAnyCircle(e,t){return await this.#l,0!==t.length&&null!=await this.#i.selectFrom("kubun_circle_members").select("circle_id").where("member_did","=",e).where("circle_id","in",t).limit(1).executeTakeFirst()}async addSpaceMember(e){await this.#l,await this.#i.insertInto("kubun_space_members").values({space_id:e.space_id,member_did:e.member_did,role:e.role}).onConflict(e=>e.columns(["space_id","member_did"]).doUpdateSet(e=>({role:e.ref("excluded.role"),updated_at:this.#e.encodeTimestamp(new Date)}))).execute()}async removeSpaceMember(e,t){await this.#l,await this.#i.deleteFrom("kubun_space_members").where("space_id","=",e).where("member_did","=",t).execute()}async getSpaceMember(e,t){return await this.#l,await this.#i.selectFrom("kubun_space_members").selectAll().where("space_id","=",e).where("member_did","=",t).executeTakeFirst()}async isSpaceMember(e,t){return await this.#l,null!=await this.#i.selectFrom("kubun_space_members").select("member_did").where("space_id","=",e).where("member_did","=",t).executeTakeFirst()}async listSpaceMembers(e){return await this.#l,await this.#i.selectFrom("kubun_space_members").selectAll().where("space_id","=",e).execute()}async getSpacesForMember(e){return await this.#l,await this.#i.selectFrom("kubun_space_members").innerJoin("kubun_spaces","kubun_spaces.id","kubun_space_members.space_id").selectAll("kubun_spaces").where("kubun_space_members.member_did","=",e).execute()}async resolveCatalogScope(e){let t;await this.#l;let a=await this.getCatalog(e);if(null==a)return{models:void 0,owners:void 0};let i=a.filter_criteria,r=null!=i.models&&i.models.length>0?i.models:void 0;if(null!=i.owners&&i.owners.length>0&&(t=[...i.owners]),null!=i.circles&&i.circles.length>0){let e=new Set(t??[]);for(let t of i.circles)for(let a of(await this.listCircleMembers(t)))e.add(a.member_did);t=Array.from(e)}return{models:r,owners:t}}async getDistinctOwnersForModel(e){await this.#l;try{return(await this.#i.selectFrom(`k_${e}`).select("owner").distinct().execute()).map(e=>e.owner)}catch{return[]}}async listSpaceMembersPaginated(e,t){await this.#l;let{limit:a,offset:i}=t,r=this.#i.selectFrom("kubun_space_members").selectAll().where("space_id","=",e).orderBy("member_did");if(null!=i&&(r=r.offset(i)),null!=a){r=r.limit(a+1);let e=await r.execute(),t=e.length>a;return{entries:t?e.slice(0,a):e,hasMore:t}}return{entries:await r.execute(),hasMore:!1}}async listCircleMembersPaginated(e,t){await this.#l;let{limit:a,offset:i}=t,r=this.#i.selectFrom("kubun_circle_members").selectAll().where("circle_id","=",e).orderBy("member_did");if(null!=i&&(r=r.offset(i)),null!=a){r=r.limit(a+1);let e=await r.execute(),t=e.length>a;return{entries:t?e.slice(0,a):e,hasMore:t}}return{entries:await r.execute(),hasMore:!1}}async listSpacesPaginated(e){await this.#l;let{limit:t,offset:a}=e,i=this.#i.selectFrom("kubun_spaces").selectAll().orderBy("name");if(null!=a&&(i=i.offset(a)),null!=t){i=i.limit(t+1);let e=await i.execute(),a=e.length>t;return{entries:a?e.slice(0,t):e,hasMore:a}}return{entries:await i.execute(),hasMore:!1}}async listCirclesBySpacePaginated(e,t){await this.#l;let{limit:a,offset:i,memberDID:r}=t,s=this.#i.selectFrom("kubun_circles").selectAll("kubun_circles").where("kubun_circles.space_id","=",e).orderBy("kubun_circles.name");if(null!=r&&(s=s.innerJoin("kubun_circle_members","kubun_circle_members.circle_id","kubun_circles.id").where("kubun_circle_members.member_did","=",r)),null!=i&&(s=s.offset(i)),null!=a){s=s.limit(a+1);let e=await s.execute(),t=e.length>a;return{entries:t?e.slice(0,a):e,hasMore:t}}return{entries:await s.execute(),hasMore:!1}}async saveMLSState(e){await this.#l,await this.#i.insertInto("kubun_space_mls_state").values({space_id:e.space_id,device_id:e.device_id,mls_state:this.#e.encodeBinary(e.mls_state),credential:e.credential,epoch:e.epoch,root_capability:e.root_capability}).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.#e.encodeTimestamp(new Date)}))).execute()}async getMLSState(e,t){return await this.#l,await this.#i.selectFrom("kubun_space_mls_state").selectAll().where("space_id","=",e).where("device_id","=",t).executeTakeFirst()}async deleteMLSState(e,t){await this.#l,await this.#i.deleteFrom("kubun_space_mls_state").where("space_id","=",e).where("device_id","=",t).execute()}async listMLSStates(e){return await this.#l,await this.#i.selectFrom("kubun_space_mls_state").selectAll().where("space_id","=",e).execute()}async deleteSpaceMLSStates(e){await this.#l,await this.#i.deleteFrom("kubun_space_mls_state").where("space_id","=",e).execute()}async listDocumentModelIDs(){return await this.#l,(await this.#i.selectFrom("kubun_document_models").select("id").execute()).map(e=>e.id)}async queryDocumentsByOwner(e,t){return await this.#l,(await this.#i.selectFrom(`k_${e}`).selectAll().where("owner","=",t).execute()).map(e=>w(this.#e,e))}async createSearchIndex(e,t){await this.#l,await this.#e.createSearchIndex(this.#i,{modelID:e,fields:t})}async dropSearchIndex(e){await this.#l,await this.#e.dropSearchIndex(this.#i,e)}async updateSearchEntry(e,t,a,i){await this.#l;let r={};for(let e of i){let t=this.#o(a,e);null!=t&&(r[e]=String(t))}await this.#e.updateSearchEntry(this.#i,e,t,r,i)}async removeSearchEntry(e,t){await this.#l,await this.#e.removeSearchEntry(this.#i,e,t)}async searchDocuments(e){await this.#l;let t=[];for(let a of e.modelIDs)for(let i of(await this.#e.searchIndex(this.#i,{query:e.query,modelID:a,limit:e.first??50})))t.push({documentID:i.documentID,modelID:a,rank:i.rank});return(t.sort((e,t)=>Math.abs(t.rank)-Math.abs(e.rank)),e.first)?t.slice(0,e.first):t}#o(e,t){let a=t.split("."),i=e;for(let e of a){if(null==i||"object"!=typeof i)return null;i=i[e]}return i}}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { CredentialStore } from './connector/credential-store.js';
|
|
2
|
+
export type { SyncStateStore } from './connector/sync-state-store.js';
|
|
1
3
|
export type { CreateGraphParams, DBEvents, DBParams, DocumentCreatedEvent, DocumentSavedEvent, GraphModelWithRecord, Migrations, WritableDB, } from './db.js';
|
|
2
4
|
export { KubunDB } from './db.js';
|
|
3
5
|
export type * from './types.js';
|
package/lib/migrations/0-init.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function getMigration(e){let t=e.types;return{up:async function(a){await a.schema.createTable("kubun_document_attachments").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("data",t.binary,e=>e.notNull()).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).execute(),await a.schema.createTable("kubun_document_models").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("version",t.text,e=>e.notNull()).addColumn("name",t.text,e=>e.notNull()).addColumn("behavior",t.text,e=>e.notNull()).addColumn("unique_fields",t.json).addColumn("interfaces",t.json,e=>e.notNull()).addColumn("schema",t.json,e=>e.notNull()).addColumn("fields_meta",t.json,e=>e.notNull()).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).execute(),await a.schema.createTable("kubun_document_model_interfaces").ifNotExists().addColumn("interface_id",t.text,e=>e.notNull().references("kubun_document_models.id")).addColumn("implementation_id",t.text,e=>e.notNull().references("kubun_document_models.id")).addUniqueConstraint("kubun_document_model_interfaces_pkey",["interface_id","implementation_id"]).execute(),await a.schema.createTable("kubun_graph_models").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("name",t.text,e=>e.notNull()).addColumn("aliases",t.json,e=>e.defaultTo("{}").notNull()).addColumn("search",t.json).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).execute(),await a.schema.createTable("kubun_graph_document_models").ifNotExists().addColumn("graph_model_id",t.text,e=>e.notNull().references("kubun_graph_models.id")).addColumn("document_model_id",t.text,e=>e.notNull().references("kubun_document_models.id")).addUniqueConstraint("kubun_graph_document_models_pkey",["graph_model_id","document_model_id"]).execute(),await a.schema.createTable("kubun_user_model_access_defaults").ifNotExists().addColumn("owner_did",t.text,e=>e.notNull()).addColumn("model_id",t.text,e=>e.notNull()).addColumn("permission_type",t.text,e=>e.notNull()).addColumn("access_level",t.text,e=>e.notNull()).addColumn("allowed_dids",t.json).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).addPrimaryKeyConstraint("kubun_user_model_access_defaults_pkey",["owner_did","model_id","permission_type"]).execute(),await a.schema.createIndex("idx_user_model_access_owner_model").on("kubun_user_model_access_defaults").columns(["owner_did","model_id"]).execute(),await a.schema.createTable("kubun_sync_checkpoints").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("peer_server_id",t.text,e=>e.notNull()).addColumn("user_id",t.text,e=>e.notNull()).addColumn("last_sync_timestamp",t.timestamp,e=>e.notNull()).addColumn("document_checkpoints",t.json,e=>e.notNull()).addColumn("vector_clock",t.json,e=>e.notNull()).execute(),await a.schema.createIndex("idx_sync_checkpoints_peer_user").on("kubun_sync_checkpoints").columns(["peer_server_id","user_id"]).execute(),await a.schema.createTable("kubun_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,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).execute(),await a.schema.createTable("kubun_mutation_log").ifNotExists().addColumn("mutation_hash",t.text,e=>e.primaryKey()).addColumn("model_id",t.text,e=>e.notNull()).addColumn("document_id",t.text,e=>e.notNull()).addColumn("author_did",t.text,e=>e.notNull()).addColumn("hlc",t.text,e=>e.notNull()).addColumn("mutation_jwt",t.text,e=>e.notNull()).addColumn("status",t.text,e=>e.notNull().defaultTo("applied")).execute(),await a.schema.createIndex("idx_mutation_log_hlc").on("kubun_mutation_log").column("hlc").execute(),await a.schema.createIndex("idx_mutation_log_document").on("kubun_mutation_log").column("document_id").execute(),await a.schema.createIndex("idx_mutation_log_status").on("kubun_mutation_log").column("status").execute()},down:async function(e){await e.schema.dropTable("kubun_mutation_log").ifExists().execute(),await e.schema.dropTable("kubun_sync_peers").ifExists().execute(),await e.schema.dropTable("kubun_sync_checkpoints").ifExists().execute(),await e.schema.dropTable("kubun_user_model_access_defaults").ifExists().execute(),await e.schema.dropTable("kubun_graph_document_models").ifExists().execute(),await e.schema.dropTable("kubun_graph_models").ifExists().execute(),await e.schema.dropTable("kubun_document_model_interfaces").ifExists().execute(),await e.schema.dropTable("kubun_document_models").ifExists().execute(),await e.schema.dropTable("kubun_document_attachments").ifExists().execute()}}}
|
|
1
|
+
export function getMigration(e){let t=e.types;return{up:async function(a){await a.schema.createTable("kubun_document_attachments").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("data",t.binary,e=>e.notNull()).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).execute(),await a.schema.createTable("kubun_document_models").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("version",t.text,e=>e.notNull()).addColumn("name",t.text,e=>e.notNull()).addColumn("behavior",t.text,e=>e.notNull()).addColumn("unique_fields",t.json).addColumn("interfaces",t.json,e=>e.notNull()).addColumn("schema",t.json,e=>e.notNull()).addColumn("fields_meta",t.json,e=>e.notNull()).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).execute(),await a.schema.createTable("kubun_document_model_interfaces").ifNotExists().addColumn("interface_id",t.text,e=>e.notNull().references("kubun_document_models.id")).addColumn("implementation_id",t.text,e=>e.notNull().references("kubun_document_models.id")).addUniqueConstraint("kubun_document_model_interfaces_pkey",["interface_id","implementation_id"]).execute(),await a.schema.createTable("kubun_graph_models").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("name",t.text,e=>e.notNull()).addColumn("aliases",t.json,e=>e.defaultTo("{}").notNull()).addColumn("search",t.json).addColumn("extension_sdl",t.text).addColumn("plugin_config",t.json).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).execute(),await a.schema.createTable("kubun_graph_document_models").ifNotExists().addColumn("graph_model_id",t.text,e=>e.notNull().references("kubun_graph_models.id")).addColumn("document_model_id",t.text,e=>e.notNull().references("kubun_document_models.id")).addUniqueConstraint("kubun_graph_document_models_pkey",["graph_model_id","document_model_id"]).execute(),await a.schema.createTable("kubun_user_model_access_defaults").ifNotExists().addColumn("owner_did",t.text,e=>e.notNull()).addColumn("model_id",t.text,e=>e.notNull()).addColumn("permission_type",t.text,e=>e.notNull()).addColumn("access_level",t.text,e=>e.notNull()).addColumn("allowed_dids",t.json).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).addPrimaryKeyConstraint("kubun_user_model_access_defaults_pkey",["owner_did","model_id","permission_type"]).execute(),await a.schema.createIndex("idx_user_model_access_owner_model").on("kubun_user_model_access_defaults").columns(["owner_did","model_id"]).execute(),await a.schema.createTable("kubun_sync_checkpoints").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("peer_server_id",t.text,e=>e.notNull()).addColumn("user_id",t.text,e=>e.notNull()).addColumn("last_sync_timestamp",t.timestamp,e=>e.notNull()).addColumn("document_checkpoints",t.json,e=>e.notNull()).addColumn("vector_clock",t.json,e=>e.notNull()).execute(),await a.schema.createIndex("idx_sync_checkpoints_peer_user").on("kubun_sync_checkpoints").columns(["peer_server_id","user_id"]).execute(),await a.schema.createTable("kubun_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,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).execute(),await a.schema.createTable("kubun_mutation_log").ifNotExists().addColumn("mutation_hash",t.text,e=>e.primaryKey()).addColumn("model_id",t.text,e=>e.notNull()).addColumn("document_id",t.text,e=>e.notNull()).addColumn("author_did",t.text,e=>e.notNull()).addColumn("hlc",t.text,e=>e.notNull()).addColumn("mutation_jwt",t.text,e=>e.notNull()).addColumn("status",t.text,e=>e.notNull().defaultTo("applied")).execute(),await a.schema.createIndex("idx_mutation_log_hlc").on("kubun_mutation_log").column("hlc").execute(),await a.schema.createIndex("idx_mutation_log_document").on("kubun_mutation_log").column("document_id").execute(),await a.schema.createIndex("idx_mutation_log_status").on("kubun_mutation_log").column("status").execute(),await a.schema.createTable("kubun_connector_sync_state").ifNotExists().addColumn("connector_name",t.text,e=>e.notNull()).addColumn("owner_did",t.text,e=>e.notNull()).addColumn("checkpoint",t.text).addColumn("last_synced_at",t.text,e=>e.notNull()).addColumn("entity_count","integer",e=>e.notNull().defaultTo(0)).addColumn("status",t.text,e=>e.notNull()).addColumn("error",t.text).addPrimaryKeyConstraint("kubun_connector_sync_state_pkey",["connector_name","owner_did"]).execute(),await a.schema.createTable("kubun_connector_credentials").ifNotExists().addColumn("provider_name",t.text,e=>e.notNull()).addColumn("owner_did",t.text,e=>e.notNull()).addColumn("credential",t.text,e=>e.notNull()).addPrimaryKeyConstraint("kubun_connector_credentials_pkey",["provider_name","owner_did"]).execute(),await a.schema.createTable("kubun_catalogs").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("owner_did",t.text,e=>e.notNull()).addColumn("name",t.text,e=>e.notNull()).addColumn("description",t.text,e=>e.notNull().defaultTo("")).addColumn("filter_criteria",t.json,e=>e.notNull()).addColumn("hlc",t.text,e=>e.notNull()).addColumn("created_at",t.timestamp,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).execute(),await a.schema.createIndex("idx_catalogs_owner").on("kubun_catalogs").column("owner_did").execute(),await a.schema.createTable("kubun_cluster_models").ifNotExists().addColumn("model_id",t.text,e=>e.notNull().primaryKey()).addColumn("cluster_id",t.text,e=>e.notNull()).addColumn("cluster_index","integer",e=>e.notNull()).execute(),await a.schema.createIndex("idx_cluster_models_cluster").on("kubun_cluster_models").column("cluster_id").execute(),await a.schema.createTable("kubun_clusters").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("definition",t.json,e=>e.notNull()).execute(),await a.schema.createTable("kubun_spaces").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,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).execute(),await a.schema.createTable("kubun_space_members").ifNotExists().addColumn("space_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,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).addPrimaryKeyConstraint("pk_space_members",["space_id","member_did"]).execute(),await a.schema.createIndex("idx_space_members_did").on("kubun_space_members").column("member_did").execute(),await a.schema.createTable("kubun_circles").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("space_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,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).execute(),await a.schema.createIndex("idx_circles_space").on("kubun_circles").column("space_id").execute(),await a.schema.createTable("kubun_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,t=>t.defaultTo(e.functions.now).notNull()).addColumn("updated_at",t.timestamp).addPrimaryKeyConstraint("pk_circle_members",["circle_id","member_did"]).execute(),await a.schema.createIndex("idx_circle_members_did").on("kubun_circle_members").column("member_did").execute(),await a.schema.createTable("kubun_hub_messages").ifNotExists().addColumn("sequence_id",t.text,e=>e.notNull().primaryKey()).addColumn("sender_did",t.text,e=>e.notNull()).addColumn("group_id",t.text).addColumn("payload",t.binary,e=>e.notNull()).addColumn("stored_at","integer",e=>e.notNull()).execute(),await a.schema.createTable("kubun_hub_deliveries").ifNotExists().addColumn("sequence_id",t.text,e=>e.notNull()).addColumn("recipient_did",t.text,e=>e.notNull()).addPrimaryKeyConstraint("pk_hub_deliveries",["sequence_id","recipient_did"]).execute(),await a.schema.createIndex("idx_hub_deliveries_recipient").on("kubun_hub_deliveries").column("recipient_did").execute(),await a.schema.createTable("kubun_hub_key_packages").ifNotExists().addColumn("id",t.serial,e=>e.primaryKey()).addColumn("owner_did",t.text,e=>e.notNull()).addColumn("key_package",t.text,e=>e.notNull()).execute(),await a.schema.createIndex("idx_hub_key_packages_owner").on("kubun_hub_key_packages").column("owner_did").execute(),await a.schema.createTable("kubun_hub_group_members").ifNotExists().addColumn("group_id",t.text,e=>e.notNull()).addColumn("member_did",t.text,e=>e.notNull()).addPrimaryKeyConstraint("pk_hub_group_members",["group_id","member_did"]).execute(),await a.schema.createTable("kubun_space_mls_state").ifNotExists().addColumn("space_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,t=>t.defaultTo(e.functions.now).notNull()).addPrimaryKeyConstraint("pk_space_mls_state",["space_id","device_id"]).execute()},down:async function(e){await e.schema.dropTable("kubun_space_mls_state").ifExists().execute(),await e.schema.dropTable("kubun_hub_group_members").ifExists().execute(),await e.schema.dropTable("kubun_hub_key_packages").ifExists().execute(),await e.schema.dropTable("kubun_hub_deliveries").ifExists().execute(),await e.schema.dropTable("kubun_hub_messages").ifExists().execute(),await e.schema.dropTable("kubun_circle_members").ifExists().execute(),await e.schema.dropTable("kubun_circles").ifExists().execute(),await e.schema.dropTable("kubun_space_members").ifExists().execute(),await e.schema.dropTable("kubun_spaces").ifExists().execute(),await e.schema.dropTable("kubun_clusters").ifExists().execute(),await e.schema.dropTable("kubun_cluster_models").ifExists().execute(),await e.schema.dropTable("kubun_catalogs").ifExists().execute(),await e.schema.dropTable("kubun_connector_credentials").ifExists().execute(),await e.schema.dropTable("kubun_connector_sync_state").ifExists().execute(),await e.schema.dropTable("kubun_mutation_log").ifExists().execute(),await e.schema.dropTable("kubun_sync_peers").ifExists().execute(),await e.schema.dropTable("kubun_sync_checkpoints").ifExists().execute(),await e.schema.dropTable("kubun_user_model_access_defaults").ifExists().execute(),await e.schema.dropTable("kubun_graph_document_models").ifExists().execute(),await e.schema.dropTable("kubun_graph_models").ifExists().execute(),await e.schema.dropTable("kubun_document_model_interfaces").ifExists().execute(),await e.schema.dropTable("kubun_document_models").ifExists().execute(),await e.schema.dropTable("kubun_document_attachments").ifExists().execute()}}}
|
package/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DocumentFieldsMeta, DocumentFilter, DocumentModelSchema, DocumentNode, DocumentOrderBy } from '@kubun/protocol';
|
|
1
|
+
import type { CatalogFilterCriteria, DocumentFieldsMeta, DocumentFilter, DocumentModelSchema, DocumentNode, DocumentOrderBy } from '@kubun/protocol';
|
|
2
2
|
import type { ColumnType, Insertable, JSONColumnType, Selectable, Updateable } from 'kysely';
|
|
3
3
|
type CreatedAtColumn = ColumnType<number, number | undefined, never>;
|
|
4
4
|
type UpdatedAtColumn = ColumnType<number, number | undefined, number | undefined>;
|
|
@@ -80,6 +80,8 @@ export type GraphModelTable = {
|
|
|
80
80
|
name: string;
|
|
81
81
|
aliases: JSONColumnType<Record<string, string>>;
|
|
82
82
|
search: JSONColumnType<SearchConfig> | null;
|
|
83
|
+
extension_sdl: string | null;
|
|
84
|
+
plugin_config: JSONColumnType<Record<string, Record<string, unknown>>> | null;
|
|
83
85
|
created_at: CreatedAtColumn;
|
|
84
86
|
updated_at: UpdatedAtColumn;
|
|
85
87
|
};
|
|
@@ -143,19 +145,159 @@ export type AccessPermissions = {
|
|
|
143
145
|
allowedDIDs?: Array<string>;
|
|
144
146
|
};
|
|
145
147
|
};
|
|
148
|
+
export type ConnectorSyncStateTable = {
|
|
149
|
+
connector_name: string;
|
|
150
|
+
owner_did: string;
|
|
151
|
+
checkpoint: string | null;
|
|
152
|
+
last_synced_at: string;
|
|
153
|
+
entity_count: number;
|
|
154
|
+
status: string;
|
|
155
|
+
error: string | null;
|
|
156
|
+
};
|
|
157
|
+
export type ConnectorSyncState = Selectable<ConnectorSyncStateTable>;
|
|
158
|
+
export type InsertConnectorSyncState = Insertable<ConnectorSyncStateTable>;
|
|
159
|
+
export type ConnectorCredentialTable = {
|
|
160
|
+
provider_name: string;
|
|
161
|
+
owner_did: string;
|
|
162
|
+
credential: string;
|
|
163
|
+
};
|
|
164
|
+
export type ConnectorCredential = Selectable<ConnectorCredentialTable>;
|
|
165
|
+
export type InsertConnectorCredential = Insertable<ConnectorCredentialTable>;
|
|
166
|
+
export type CatalogTable = {
|
|
167
|
+
id: string;
|
|
168
|
+
owner_did: string;
|
|
169
|
+
name: string;
|
|
170
|
+
description: string;
|
|
171
|
+
filter_criteria: JSONColumnType<CatalogFilterCriteria>;
|
|
172
|
+
hlc: string;
|
|
173
|
+
created_at: CreatedAtColumn;
|
|
174
|
+
updated_at: UpdatedAtColumn;
|
|
175
|
+
};
|
|
176
|
+
export type Catalog = Selectable<CatalogTable>;
|
|
177
|
+
export type InsertCatalog = Insertable<CatalogTable>;
|
|
178
|
+
export type UpdateCatalog = Updateable<CatalogTable>;
|
|
179
|
+
export type ClusterModelTable = {
|
|
180
|
+
model_id: string;
|
|
181
|
+
cluster_id: string;
|
|
182
|
+
cluster_index: number;
|
|
183
|
+
};
|
|
184
|
+
export type ClusterModel = Selectable<ClusterModelTable>;
|
|
185
|
+
export type InsertClusterModel = Insertable<ClusterModelTable>;
|
|
186
|
+
export type ClusterDefinitionTable = {
|
|
187
|
+
id: string;
|
|
188
|
+
definition: JSONColumnType<Record<string, unknown>>;
|
|
189
|
+
};
|
|
190
|
+
export type ClusterDefinitionRow = Selectable<ClusterDefinitionTable>;
|
|
191
|
+
export type SpaceTable = {
|
|
192
|
+
id: string;
|
|
193
|
+
name: string;
|
|
194
|
+
description: string;
|
|
195
|
+
created_by: string;
|
|
196
|
+
hub_urls: JSONColumnType<Array<string>>;
|
|
197
|
+
hlc: string;
|
|
198
|
+
created_at: CreatedAtColumn;
|
|
199
|
+
updated_at: UpdatedAtColumn;
|
|
200
|
+
};
|
|
201
|
+
export type Space = Selectable<SpaceTable>;
|
|
202
|
+
export type InsertSpace = Insertable<SpaceTable>;
|
|
203
|
+
export type SpaceMemberTable = {
|
|
204
|
+
space_id: string;
|
|
205
|
+
member_did: string;
|
|
206
|
+
role: string;
|
|
207
|
+
created_at: CreatedAtColumn;
|
|
208
|
+
updated_at: UpdatedAtColumn;
|
|
209
|
+
};
|
|
210
|
+
export type SpaceMember = Selectable<SpaceMemberTable>;
|
|
211
|
+
export type InsertSpaceMember = Insertable<SpaceMemberTable>;
|
|
212
|
+
export type CircleTable = {
|
|
213
|
+
id: string;
|
|
214
|
+
space_id: string;
|
|
215
|
+
name: string;
|
|
216
|
+
description: string;
|
|
217
|
+
catalog_ids: JSONColumnType<Array<string>>;
|
|
218
|
+
hlc: string;
|
|
219
|
+
created_at: CreatedAtColumn;
|
|
220
|
+
updated_at: UpdatedAtColumn;
|
|
221
|
+
};
|
|
222
|
+
export type Circle = Selectable<CircleTable>;
|
|
223
|
+
export type InsertCircle = Insertable<CircleTable>;
|
|
224
|
+
export type CircleMemberTable = {
|
|
225
|
+
circle_id: string;
|
|
226
|
+
member_did: string;
|
|
227
|
+
role: string;
|
|
228
|
+
hlc: string;
|
|
229
|
+
created_at: CreatedAtColumn;
|
|
230
|
+
updated_at: UpdatedAtColumn;
|
|
231
|
+
};
|
|
232
|
+
export type CircleMember = Selectable<CircleMemberTable>;
|
|
233
|
+
export type InsertCircleMember = Insertable<CircleMemberTable>;
|
|
234
|
+
export type HubMessageTable = {
|
|
235
|
+
sequence_id: string;
|
|
236
|
+
sender_did: string;
|
|
237
|
+
group_id: string | null;
|
|
238
|
+
payload: Uint8Array;
|
|
239
|
+
stored_at: ColumnType<number, number, never>;
|
|
240
|
+
};
|
|
241
|
+
export type HubMessage = Selectable<HubMessageTable>;
|
|
242
|
+
export type InsertHubMessage = Insertable<HubMessageTable>;
|
|
243
|
+
export type HubDeliveryTable = {
|
|
244
|
+
sequence_id: string;
|
|
245
|
+
recipient_did: string;
|
|
246
|
+
};
|
|
247
|
+
export type HubDelivery = Selectable<HubDeliveryTable>;
|
|
248
|
+
export type InsertHubDelivery = Insertable<HubDeliveryTable>;
|
|
249
|
+
export type HubKeyPackageTable = {
|
|
250
|
+
id: ColumnType<number, number | undefined, never>;
|
|
251
|
+
owner_did: string;
|
|
252
|
+
key_package: string;
|
|
253
|
+
};
|
|
254
|
+
export type HubKeyPackage = Selectable<HubKeyPackageTable>;
|
|
255
|
+
export type InsertHubKeyPackage = Insertable<HubKeyPackageTable>;
|
|
256
|
+
export type HubGroupMemberTable = {
|
|
257
|
+
group_id: string;
|
|
258
|
+
member_did: string;
|
|
259
|
+
};
|
|
260
|
+
export type HubGroupMember = Selectable<HubGroupMemberTable>;
|
|
261
|
+
export type InsertHubGroupMember = Insertable<HubGroupMemberTable>;
|
|
262
|
+
export type SpaceMLSStateTable = {
|
|
263
|
+
space_id: string;
|
|
264
|
+
device_id: string;
|
|
265
|
+
mls_state: Uint8Array;
|
|
266
|
+
credential: string;
|
|
267
|
+
epoch: number;
|
|
268
|
+
root_capability: string;
|
|
269
|
+
updated_at: UpdatedAtColumn;
|
|
270
|
+
};
|
|
271
|
+
export type SpaceMLSState = Selectable<SpaceMLSStateTable>;
|
|
272
|
+
export type InsertSpaceMLSState = Insertable<SpaceMLSStateTable>;
|
|
273
|
+
export type UpdateSpaceMLSState = Updateable<SpaceMLSStateTable>;
|
|
146
274
|
export type DocumentTables<Models extends Record<string, DocumentData> = Record<string, DocumentData>, Keys = keyof Models> = {
|
|
147
275
|
[K in string & Keys]: DocumentTable<Models[K]>;
|
|
148
276
|
};
|
|
149
277
|
export type Database = {
|
|
278
|
+
kubun_catalogs: CatalogTable;
|
|
279
|
+
kubun_circles: CircleTable;
|
|
280
|
+
kubun_circle_members: CircleMemberTable;
|
|
281
|
+
kubun_cluster_models: ClusterModelTable;
|
|
282
|
+
kubun_clusters: ClusterDefinitionTable;
|
|
283
|
+
kubun_connector_credentials: ConnectorCredentialTable;
|
|
284
|
+
kubun_connector_sync_state: ConnectorSyncStateTable;
|
|
150
285
|
kubun_document_attachments: DocumentAttachmentTable;
|
|
151
286
|
kubun_document_models: DocumentModelTable;
|
|
152
287
|
kubun_document_model_interfaces: DocumentModelInterfaceTable;
|
|
153
|
-
kubun_mutation_log: MutationLogTable;
|
|
154
288
|
kubun_graph_document_models: GraphDocumentModelTable;
|
|
155
289
|
kubun_graph_models: GraphModelTable;
|
|
156
|
-
|
|
290
|
+
kubun_hub_deliveries: HubDeliveryTable;
|
|
291
|
+
kubun_hub_group_members: HubGroupMemberTable;
|
|
292
|
+
kubun_hub_key_packages: HubKeyPackageTable;
|
|
293
|
+
kubun_hub_messages: HubMessageTable;
|
|
294
|
+
kubun_mutation_log: MutationLogTable;
|
|
295
|
+
kubun_space_members: SpaceMemberTable;
|
|
296
|
+
kubun_space_mls_state: SpaceMLSStateTable;
|
|
297
|
+
kubun_spaces: SpaceTable;
|
|
157
298
|
kubun_sync_checkpoints: SyncCheckpointTable;
|
|
158
299
|
kubun_sync_peers: SyncPeerTable;
|
|
300
|
+
kubun_user_model_access_defaults: UserModelAccessDefaultTable;
|
|
159
301
|
[key: `k_${string}`]: DocumentTable;
|
|
160
302
|
};
|
|
161
303
|
export type CursorDocument = {
|
|
@@ -171,11 +313,13 @@ export type QueryDocumentsParams = ConnectionArguments & {
|
|
|
171
313
|
filter?: DocumentFilter;
|
|
172
314
|
orderBy?: DocumentOrderBy;
|
|
173
315
|
owner?: string;
|
|
316
|
+
catalogID?: string;
|
|
174
317
|
};
|
|
175
318
|
export type CountDocumentsParams = {
|
|
176
319
|
modelIDs: Array<string>;
|
|
177
320
|
filter?: DocumentFilter;
|
|
178
321
|
owner?: string;
|
|
322
|
+
catalogID?: string;
|
|
179
323
|
};
|
|
180
324
|
export type QueryDocumentsResult = {
|
|
181
325
|
entries: Array<CursorDocument>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"type": "module",
|
|
@@ -15,18 +15,18 @@
|
|
|
15
15
|
],
|
|
16
16
|
"sideEffects": false,
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@enkaku/codec": "^0.
|
|
19
|
-
"@enkaku/event": "^0.
|
|
20
|
-
"kysely": "^0.28.
|
|
21
|
-
"@kubun/logger": "^0.
|
|
18
|
+
"@enkaku/codec": "^0.14.0",
|
|
19
|
+
"@enkaku/event": "^0.14.1",
|
|
20
|
+
"kysely": "^0.28.16",
|
|
21
|
+
"@kubun/logger": "^0.8.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@testcontainers/postgresql": "^11.
|
|
25
|
-
"@kubun/
|
|
26
|
-
"@kubun/db-
|
|
27
|
-
"@kubun/db-better-sqlite": "^0.
|
|
28
|
-
"@kubun/
|
|
29
|
-
"@kubun/
|
|
24
|
+
"@testcontainers/postgresql": "^11.14.0",
|
|
25
|
+
"@kubun/db-adapter": "^0.8.0",
|
|
26
|
+
"@kubun/db-postgres": "^0.8.0",
|
|
27
|
+
"@kubun/db-better-sqlite": "^0.8.0",
|
|
28
|
+
"@kubun/id": "^0.8.0",
|
|
29
|
+
"@kubun/protocol": "^0.8.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build:clean": "del lib",
|
|
@@ -34,9 +34,8 @@
|
|
|
34
34
|
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
|
|
35
35
|
"build:types:ci": "tsc --emitDeclarationOnly --declarationMap false",
|
|
36
36
|
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
|
|
37
|
-
"test:types": "tsc --noEmit
|
|
38
|
-
"test:
|
|
39
|
-
"test:unit": "pnpm rebuild && pnpm run test:vitest",
|
|
37
|
+
"test:types": "tsc --noEmit -p tsconfig.test.json",
|
|
38
|
+
"test:unit": "vitest run",
|
|
40
39
|
"test": "pnpm run test:types && pnpm run test:unit"
|
|
41
40
|
}
|
|
42
41
|
}
|