@kubun/db 0.3.7 → 0.5.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/cursor.d.ts +0 -1
- package/lib/cursor.js +1 -7
- package/lib/db.d.ts +54 -2
- package/lib/db.js +1 -341
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -1
- package/lib/migrations/0-init.d.ts +0 -1
- package/lib/migrations/0-init.js +1 -29
- package/lib/migrations/1-add-access-control.d.ts +3 -0
- package/lib/migrations/1-add-access-control.js +1 -0
- package/lib/migrations/2-add-sync.d.ts +3 -0
- package/lib/migrations/2-add-sync.js +1 -0
- package/lib/migrations/3-add-search.d.ts +3 -0
- package/lib/migrations/3-add-search.js +1 -0
- package/lib/migrations/migrations.d.ts +0 -1
- package/lib/migrations/migrations.js +1 -6
- package/lib/query-builder.d.ts +0 -1
- package/lib/query-builder.js +1 -227
- package/lib/types.d.ts +80 -1
- package/lib/types.js +1 -1
- package/package.json +11 -8
- package/lib/cursor.d.ts.map +0 -1
- package/lib/db.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/migrations/0-init.d.ts.map +0 -1
- package/lib/migrations/migrations.d.ts.map +0 -1
- package/lib/query-builder.d.ts.map +0 -1
- package/lib/types.d.ts.map +0 -1
package/lib/cursor.d.ts
CHANGED
package/lib/cursor.js
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export function parseCursor(cursor) {
|
|
3
|
-
return b64uToJSON(cursor);
|
|
4
|
-
}
|
|
5
|
-
export function serializeCursor(data) {
|
|
6
|
-
return b64uFromJSON(data);
|
|
7
|
-
}
|
|
1
|
+
import{b64uFromJSON as r,b64uToJSON as e}from"@enkaku/codec";export function parseCursor(r){return e(r)}export function serializeCursor(e){return r(e)}
|
package/lib/db.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { type 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, type Transaction } from 'kysely';
|
|
7
|
-
import type { Database, DocumentData, GraphModel, InsertDocumentAttachment, ListDocumentsParams, QueryDocumentsParams, QueryDocumentsResult } from './types.js';
|
|
7
|
+
import type { Database, DocumentData, DocumentMutationLog, GraphModel, InsertDocumentAttachment, ListDocumentsParams, QueryDocumentsParams, QueryDocumentsResult, SearchConfig, SearchDocumentResult, SearchDocumentsParams } from './types.js';
|
|
8
8
|
export type Migrations = Record<string, Migration>;
|
|
9
9
|
export type DocumentCreatedEvent = {
|
|
10
10
|
type: 'create';
|
|
@@ -45,6 +45,7 @@ export type CreateGraphParams = {
|
|
|
45
45
|
id?: string;
|
|
46
46
|
name?: string;
|
|
47
47
|
record: DocumentModelsRecord;
|
|
48
|
+
search?: SearchConfig;
|
|
48
49
|
};
|
|
49
50
|
export type AddDocumentModelParams = {
|
|
50
51
|
transaction: Transaction<Database>;
|
|
@@ -73,5 +74,56 @@ export declare class KubunDB<T extends AdapterTypes = AdapterTypes> {
|
|
|
73
74
|
createDocument(params: CreateDocumentParams): Promise<DocumentNode>;
|
|
74
75
|
saveDocument(params: SaveDocumentParams): Promise<DocumentNode>;
|
|
75
76
|
addAttachments(attachments: Array<InsertDocumentAttachment>): Promise<void>;
|
|
77
|
+
getUserModelAccessDefault(ownerDID: string, modelID: string, permissionType: 'read' | 'write'): Promise<{
|
|
78
|
+
level: string;
|
|
79
|
+
allowedDIDs: Array<string> | null;
|
|
80
|
+
} | null>;
|
|
81
|
+
setUserModelAccessDefault(params: {
|
|
82
|
+
ownerDID: string;
|
|
83
|
+
modelID: string;
|
|
84
|
+
permissionType: 'read' | 'write';
|
|
85
|
+
accessLevel: string;
|
|
86
|
+
allowedDIDs: Array<string> | null;
|
|
87
|
+
}): Promise<void>;
|
|
88
|
+
removeUserModelAccessDefaults(ownerDID: string, modelID: string, permissionTypes: Array<string>): Promise<void>;
|
|
89
|
+
storeMutationLog(entry: {
|
|
90
|
+
documentID: string;
|
|
91
|
+
sequenceNumber: string;
|
|
92
|
+
mutationJWT: string;
|
|
93
|
+
authorDID: string;
|
|
94
|
+
}): Promise<void>;
|
|
95
|
+
getMutationLog(documentID: string, fromSequence: number): Promise<Array<DocumentMutationLog>>;
|
|
96
|
+
listDocumentModelIDs(): Promise<Array<string>>;
|
|
97
|
+
queryDocumentsByOwner(modelID: string, ownerDID: string): Promise<Array<DocumentNode>>;
|
|
98
|
+
storeSyncCheckpoint(peerServerID: string, checkpointData: {
|
|
99
|
+
userID: string;
|
|
100
|
+
lastSyncTimestamp: number;
|
|
101
|
+
documentCheckpoints: Record<string, {
|
|
102
|
+
lastKnownHash: string;
|
|
103
|
+
lastSyncedSequence: number;
|
|
104
|
+
}>;
|
|
105
|
+
vectorClock: Record<string, number>;
|
|
106
|
+
}): Promise<boolean>;
|
|
107
|
+
getSyncCheckpoint(peerServerID: string, userID: string): Promise<{
|
|
108
|
+
lastSyncTimestamp: number;
|
|
109
|
+
documentCheckpoints: Record<string, {
|
|
110
|
+
lastKnownHash: string;
|
|
111
|
+
lastSyncedSequence: number;
|
|
112
|
+
}>;
|
|
113
|
+
vectorClock: Record<string, number>;
|
|
114
|
+
} | null>;
|
|
115
|
+
listSyncCheckpoints(peerServerID: string): Promise<Array<{
|
|
116
|
+
userID: string;
|
|
117
|
+
lastSyncTimestamp: number;
|
|
118
|
+
documentCheckpoints: Record<string, {
|
|
119
|
+
lastKnownHash: string;
|
|
120
|
+
lastSyncedSequence: number;
|
|
121
|
+
}>;
|
|
122
|
+
vectorClock: Record<string, number>;
|
|
123
|
+
}>>;
|
|
124
|
+
createSearchIndex(modelID: string, fields: Array<string>): Promise<void>;
|
|
125
|
+
dropSearchIndex(modelID: string): Promise<void>;
|
|
126
|
+
updateSearchEntry(modelID: string, documentID: string, data: Record<string, unknown>, fields: Array<string>): Promise<void>;
|
|
127
|
+
removeSearchEntry(modelID: string, documentID: string): Promise<void>;
|
|
128
|
+
searchDocuments(params: SearchDocumentsParams): Promise<Array<SearchDocumentResult>>;
|
|
76
129
|
}
|
|
77
|
-
//# sourceMappingURL=db.d.ts.map
|
package/lib/db.js
CHANGED
|
@@ -1,341 +1 @@
|
|
|
1
|
-
import { EventEmitter } from '@enkaku/event';
|
|
2
|
-
import { DocumentModelID } from '@kubun/id';
|
|
3
|
-
import { getKubunLogger } from '@kubun/logger';
|
|
4
|
-
import { Kysely, Migrator, ParseJSONResultsPlugin } from 'kysely';
|
|
5
|
-
import { serializeCursor } from './cursor.js';
|
|
6
|
-
import { getMigrations } from './migrations/migrations.js';
|
|
7
|
-
import { applyDocumentFilter, applyDocumentOrderBy, applyPagination } from './query-builder.js';
|
|
8
|
-
function documentModelFromTable(row) {
|
|
9
|
-
const model = {
|
|
10
|
-
version: row.version,
|
|
11
|
-
name: row.name,
|
|
12
|
-
behavior: row.behavior,
|
|
13
|
-
interfaces: row.interfaces,
|
|
14
|
-
schema: row.schema,
|
|
15
|
-
fieldsMeta: row.fields_meta
|
|
16
|
-
};
|
|
17
|
-
if (model.behavior === 'unique') {
|
|
18
|
-
model.uniqueFields = row.unique_fields;
|
|
19
|
-
}
|
|
20
|
-
return model;
|
|
21
|
-
}
|
|
22
|
-
function documentModelToTable(id, model) {
|
|
23
|
-
return {
|
|
24
|
-
id,
|
|
25
|
-
version: model.version,
|
|
26
|
-
name: model.name,
|
|
27
|
-
behavior: model.behavior,
|
|
28
|
-
unique_fields: model.behavior === 'unique' ? JSON.stringify(model.uniqueFields) : null,
|
|
29
|
-
interfaces: JSON.stringify(model.interfaces),
|
|
30
|
-
schema: JSON.stringify(model.schema),
|
|
31
|
-
fields_meta: JSON.stringify(model.fieldsMeta)
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function documentNodeFromTable(adapter, doc) {
|
|
35
|
-
return {
|
|
36
|
-
id: doc.id,
|
|
37
|
-
model: doc.model,
|
|
38
|
-
owner: doc.owner,
|
|
39
|
-
data: doc.data,
|
|
40
|
-
createdAt: adapter.decodeTimestamp(doc.created_at),
|
|
41
|
-
updatedAt: doc.updated_at ? adapter.decodeTimestamp(doc.updated_at) : null
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function toGlobalInterfaceID(modelID, interfaceID) {
|
|
45
|
-
const id = DocumentModelID.fromString(interfaceID);
|
|
46
|
-
return id.isLocal ? id.toGlobal(DocumentModelID.fromString(modelID)).toString() : interfaceID;
|
|
47
|
-
}
|
|
48
|
-
export class KubunDB {
|
|
49
|
-
#adapter;
|
|
50
|
-
#db;
|
|
51
|
-
#events = new EventEmitter();
|
|
52
|
-
#logger;
|
|
53
|
-
#ready;
|
|
54
|
-
constructor(params){
|
|
55
|
-
this.#adapter = params.adapter;
|
|
56
|
-
this.#db = new Kysely({
|
|
57
|
-
dialect: this.#adapter.dialect,
|
|
58
|
-
plugins: [
|
|
59
|
-
new ParseJSONResultsPlugin()
|
|
60
|
-
]
|
|
61
|
-
});
|
|
62
|
-
this.#logger = params.logger ?? getKubunLogger('db');
|
|
63
|
-
this.#ready = this.#runMigrations();
|
|
64
|
-
}
|
|
65
|
-
/** @internal */ get adapter() {
|
|
66
|
-
return this.#adapter;
|
|
67
|
-
}
|
|
68
|
-
get events() {
|
|
69
|
-
return this.#events;
|
|
70
|
-
}
|
|
71
|
-
getDB() {
|
|
72
|
-
return this.#ready.then(()=>this.#db);
|
|
73
|
-
}
|
|
74
|
-
async #runMigrations() {
|
|
75
|
-
const migrator = new Migrator({
|
|
76
|
-
db: this.#db,
|
|
77
|
-
provider: {
|
|
78
|
-
getMigrations: ()=>Promise.resolve(this.getMigrations())
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
const result = await migrator.migrateToLatest();
|
|
82
|
-
if (result.error != null) {
|
|
83
|
-
throw result.error;
|
|
84
|
-
}
|
|
85
|
-
this.#logger.info('ready');
|
|
86
|
-
}
|
|
87
|
-
getMigrations() {
|
|
88
|
-
return getMigrations(this.#adapter);
|
|
89
|
-
}
|
|
90
|
-
async close() {
|
|
91
|
-
await this.#db.destroy();
|
|
92
|
-
this.#logger.info('closed');
|
|
93
|
-
}
|
|
94
|
-
async listGraphs() {
|
|
95
|
-
await this.#ready;
|
|
96
|
-
return await this.#db.selectFrom('kubun_graph_models').selectAll().execute();
|
|
97
|
-
}
|
|
98
|
-
async createGraph(params) {
|
|
99
|
-
await this.#ready;
|
|
100
|
-
const graphModelID = params.id ?? globalThis.crypto.randomUUID();
|
|
101
|
-
const name = params.name ?? graphModelID;
|
|
102
|
-
await this.#db.transaction().setIsolationLevel('read committed').execute(async (trx)=>{
|
|
103
|
-
await trx.insertInto('kubun_graph_models').values({
|
|
104
|
-
aliases: JSON.stringify(params.aliases ?? {}),
|
|
105
|
-
id: graphModelID,
|
|
106
|
-
name
|
|
107
|
-
}).onConflict((oc)=>oc.doNothing()).execute();
|
|
108
|
-
const entries = Object.entries(params.record);
|
|
109
|
-
const added = new Set();
|
|
110
|
-
while(added.size < entries.length){
|
|
111
|
-
// Get models that have not been added yet and have all their interfaces already added
|
|
112
|
-
const toAdd = entries.filter(([id, model])=>{
|
|
113
|
-
return !added.has(id) && model.interfaces.every((iid)=>added.has(toGlobalInterfaceID(id, iid)));
|
|
114
|
-
});
|
|
115
|
-
if (toAdd.length === 0) {
|
|
116
|
-
throw new Error('Could not create graph: no valid model to add');
|
|
117
|
-
}
|
|
118
|
-
await Promise.all(toAdd.map(async ([id, model])=>{
|
|
119
|
-
await this.#addDocumentModel({
|
|
120
|
-
id,
|
|
121
|
-
graphModelID,
|
|
122
|
-
model,
|
|
123
|
-
transaction: trx
|
|
124
|
-
});
|
|
125
|
-
added.add(id);
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
this.#logger.debug('created graph {id}', {
|
|
130
|
-
id: graphModelID
|
|
131
|
-
});
|
|
132
|
-
return graphModelID;
|
|
133
|
-
}
|
|
134
|
-
async #addDocumentModel(params) {
|
|
135
|
-
const { id, graphModelID, model, transaction } = params;
|
|
136
|
-
const t = this.#adapter.types;
|
|
137
|
-
await this.#ready;
|
|
138
|
-
await transaction.schema.createTable(`k_${id}`).ifNotExists().addColumn('id', t.text, (col)=>col.notNull().primaryKey()).addColumn('owner', t.text, (col)=>col.notNull()).addColumn('model', t.text, (col)=>col.notNull()).addColumn('data', t.json).addColumn('unique', t.binary, (col)=>col.notNull()).addColumn('created_at', t.timestamp, (col)=>{
|
|
139
|
-
return col.defaultTo(this.#adapter.functions.now).notNull();
|
|
140
|
-
}).addColumn('updated_at', t.timestamp).execute();
|
|
141
|
-
await transaction.insertInto('kubun_document_models').values(documentModelToTable(id, model)).onConflict((oc)=>oc.doNothing()).execute();
|
|
142
|
-
for (const interfaceID of model.interfaces){
|
|
143
|
-
await transaction.insertInto('kubun_document_model_interfaces').values({
|
|
144
|
-
interface_id: toGlobalInterfaceID(id, interfaceID),
|
|
145
|
-
implementation_id: id
|
|
146
|
-
}).onConflict((oc)=>oc.doNothing()).execute();
|
|
147
|
-
}
|
|
148
|
-
await transaction.insertInto('kubun_graph_document_models').values({
|
|
149
|
-
graph_model_id: graphModelID,
|
|
150
|
-
document_model_id: id
|
|
151
|
-
}).onConflict((oc)=>oc.doNothing()).execute();
|
|
152
|
-
}
|
|
153
|
-
async getGraph(id) {
|
|
154
|
-
await this.#ready;
|
|
155
|
-
const graph = await this.#db.selectFrom('kubun_graph_models').selectAll().where('id', '=', id).executeTakeFirst();
|
|
156
|
-
if (graph == null) {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
const record = {};
|
|
160
|
-
const rows = await this.#db.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', '=', id).execute();
|
|
161
|
-
for (const row of rows){
|
|
162
|
-
record[row.id] = documentModelFromTable(row);
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
...graph,
|
|
166
|
-
record
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
async getDocumentModel(id) {
|
|
170
|
-
await this.#ready;
|
|
171
|
-
const row = await this.#db.selectFrom('kubun_document_models').selectAll().where('id', '=', id.toString()).executeTakeFirstOrThrow();
|
|
172
|
-
return documentModelFromTable(row);
|
|
173
|
-
}
|
|
174
|
-
async getDocument(id) {
|
|
175
|
-
await this.#ready;
|
|
176
|
-
const doc = await this.#db.selectFrom(`k_${id.model.toString()}`).selectAll().where('id', '=', id.toString()).executeTakeFirst();
|
|
177
|
-
return doc ? documentNodeFromTable(this.#adapter, doc) : null;
|
|
178
|
-
}
|
|
179
|
-
async getDocumentState(id) {
|
|
180
|
-
await this.#ready;
|
|
181
|
-
const docState = await this.#db.selectFrom('kubun_document_states').selectAll().where('id', '=', id).executeTakeFirst();
|
|
182
|
-
return docState?.data ?? null;
|
|
183
|
-
}
|
|
184
|
-
async getDocumentStates(ids) {
|
|
185
|
-
await this.#ready;
|
|
186
|
-
const docStates = await this.#db.selectFrom('kubun_document_states').selectAll().where('id', 'in', ids).execute();
|
|
187
|
-
const loaded = {};
|
|
188
|
-
for (const docState of docStates){
|
|
189
|
-
loaded[docState.id] = docState.data;
|
|
190
|
-
}
|
|
191
|
-
return ids.reduce((acc, id)=>{
|
|
192
|
-
acc[id] = loaded[id] ?? null;
|
|
193
|
-
return acc;
|
|
194
|
-
}, {});
|
|
195
|
-
}
|
|
196
|
-
async listDocuments(params) {
|
|
197
|
-
await this.#ready;
|
|
198
|
-
const [first, ...rest] = params.modelIDs;
|
|
199
|
-
let query = this.#db.selectFrom(`k_${first}`).selectAll().where('id', 'in', params.docIDs);
|
|
200
|
-
for (const model of rest){
|
|
201
|
-
query = query.unionAll((eb)=>{
|
|
202
|
-
return eb.selectFrom(`k_${model}`).selectAll().where('id', 'in', params.docIDs);
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
const rows = await query.execute();
|
|
206
|
-
return rows.map((row)=>documentNodeFromTable(this.#adapter, row));
|
|
207
|
-
}
|
|
208
|
-
// TODO: countDocuments() - how to handle it with unionAll?
|
|
209
|
-
async queryDocuments(params) {
|
|
210
|
-
const { filter, modelIDs, orderBy, owner, ...pagination } = params;
|
|
211
|
-
const isReverse = params.last != null;
|
|
212
|
-
await this.#ready;
|
|
213
|
-
const [first, ...rest] = modelIDs;
|
|
214
|
-
let query = this.#db.selectFrom(`k_${first}`).selectAll();
|
|
215
|
-
if (owner != null) {
|
|
216
|
-
query = query.where('owner', '=', owner);
|
|
217
|
-
}
|
|
218
|
-
if (filter != null) {
|
|
219
|
-
query = query.where((eb)=>applyDocumentFilter(eb, filter));
|
|
220
|
-
}
|
|
221
|
-
for (const model of rest){
|
|
222
|
-
query = query.unionAll((eb)=>{
|
|
223
|
-
let q = eb.selectFrom(`k_${model}`).selectAll();
|
|
224
|
-
if (owner != null) {
|
|
225
|
-
q = q.where('owner', '=', owner);
|
|
226
|
-
}
|
|
227
|
-
if (filter != null) {
|
|
228
|
-
q = q.where((eb)=>applyDocumentFilter(eb, filter));
|
|
229
|
-
}
|
|
230
|
-
return q;
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
const [orderedQuery, orderedFieldsPaths] = applyDocumentOrderBy(query, orderBy, isReverse);
|
|
234
|
-
const [paginatedQuery, limit] = applyPagination(orderedQuery, pagination, orderBy);
|
|
235
|
-
const results = await paginatedQuery.execute();
|
|
236
|
-
const docs = isReverse ? results.slice(0, limit).reverse() : results.slice(0, limit);
|
|
237
|
-
const entries = orderedFieldsPaths ? docs.map((document)=>{
|
|
238
|
-
const values = {};
|
|
239
|
-
// Iterate through all the fields that we order by
|
|
240
|
-
for (const path of orderedFieldsPaths){
|
|
241
|
-
let value = document.data;
|
|
242
|
-
// Iterate through all the keys in the path
|
|
243
|
-
for (const key of path){
|
|
244
|
-
if (value != null) {
|
|
245
|
-
value = value[key];
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
// Add the value if set
|
|
249
|
-
if (value != null) {
|
|
250
|
-
values[path.join('.')] = value;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
const cursor = serializeCursor({
|
|
254
|
-
id: document.id,
|
|
255
|
-
values
|
|
256
|
-
});
|
|
257
|
-
return {
|
|
258
|
-
cursor,
|
|
259
|
-
document: documentNodeFromTable(this.#adapter, document)
|
|
260
|
-
};
|
|
261
|
-
}) : docs.map((document)=>{
|
|
262
|
-
const cursor = serializeCursor({
|
|
263
|
-
id: document.id,
|
|
264
|
-
ts: +document.created_at
|
|
265
|
-
});
|
|
266
|
-
return {
|
|
267
|
-
cursor,
|
|
268
|
-
document: documentNodeFromTable(this.#adapter, document)
|
|
269
|
-
};
|
|
270
|
-
});
|
|
271
|
-
return {
|
|
272
|
-
entries,
|
|
273
|
-
hasMore: docs.length > limit
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
async createDocument(params) {
|
|
277
|
-
await this.#ready;
|
|
278
|
-
const id = params.id.toString();
|
|
279
|
-
const model = params.id.model.toString();
|
|
280
|
-
const doc = await this.#db.transaction().setIsolationLevel('read committed').execute(async (trx)=>{
|
|
281
|
-
const doc = await trx.insertInto(`k_${model}`).values({
|
|
282
|
-
id,
|
|
283
|
-
owner: params.owner,
|
|
284
|
-
model,
|
|
285
|
-
data: this.#adapter.encodeJSON(params.data),
|
|
286
|
-
unique: this.#adapter.encodeBinary(params.unique)
|
|
287
|
-
}).returningAll().executeTakeFirst();
|
|
288
|
-
await trx.insertInto('kubun_document_states').values({
|
|
289
|
-
id,
|
|
290
|
-
data: params.state ? this.#adapter.encodeBinary(params.state) : null
|
|
291
|
-
}).execute();
|
|
292
|
-
return doc;
|
|
293
|
-
});
|
|
294
|
-
const document = documentNodeFromTable(this.#adapter, doc);
|
|
295
|
-
this.#events.emit('document:saved', {
|
|
296
|
-
type: 'create',
|
|
297
|
-
document,
|
|
298
|
-
getCursor: ()=>serializeCursor({
|
|
299
|
-
id: doc.id,
|
|
300
|
-
ts: +doc.created_at
|
|
301
|
-
})
|
|
302
|
-
});
|
|
303
|
-
this.#logger.debug('created document {id} with model {model}', {
|
|
304
|
-
id,
|
|
305
|
-
model
|
|
306
|
-
});
|
|
307
|
-
return document;
|
|
308
|
-
}
|
|
309
|
-
async saveDocument(params) {
|
|
310
|
-
await this.#ready;
|
|
311
|
-
const id = params.id.toString();
|
|
312
|
-
const doc = await this.#db.transaction().setIsolationLevel('read committed').execute(async (trx)=>{
|
|
313
|
-
const doc = await trx.updateTable(`k_${params.id.model.toString()}`).set({
|
|
314
|
-
data: params.data ? this.#adapter.encodeJSON(params.data) : null,
|
|
315
|
-
updated_at: this.#adapter.encodeTimestamp(new Date())
|
|
316
|
-
}).where('id', '=', id).returningAll().executeTakeFirst();
|
|
317
|
-
await trx.updateTable('kubun_document_states').set({
|
|
318
|
-
data: params.state ? this.#adapter.encodeBinary(params.state) : null
|
|
319
|
-
}).where('id', '=', id).execute();
|
|
320
|
-
return doc;
|
|
321
|
-
});
|
|
322
|
-
const document = documentNodeFromTable(this.#adapter, doc);
|
|
323
|
-
this.#events.emit('document:saved', {
|
|
324
|
-
type: 'update',
|
|
325
|
-
document,
|
|
326
|
-
previous: params.existing,
|
|
327
|
-
getCursor: ()=>serializeCursor({
|
|
328
|
-
id: doc.id,
|
|
329
|
-
ts: +doc.created_at
|
|
330
|
-
})
|
|
331
|
-
});
|
|
332
|
-
this.#logger.debug('updated document {id}', {
|
|
333
|
-
id
|
|
334
|
-
});
|
|
335
|
-
return document;
|
|
336
|
-
}
|
|
337
|
-
async addAttachments(attachments) {
|
|
338
|
-
await this.#ready;
|
|
339
|
-
await this.#db.insertInto('kubun_document_attachments').values(attachments).onConflict((oc)=>oc.doNothing()).execute();
|
|
340
|
-
}
|
|
341
|
-
}
|
|
1
|
+
import{EventEmitter as e}from"@enkaku/event";import{DocumentModelID as t}from"@kubun/id";import{getKubunLogger as a}from"@kubun/logger";import{Kysely as i,Migrator as s,ParseJSONResultsPlugin as r,sql 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 c,applyPagination as u}from"./query-builder.js";function m(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 h(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 _(e,a){let i=t.fromString(a);return i.isLocal?i.toGlobal(t.fromString(e)).toString():a}export class KubunDB{#e;#t;#a=new e;#i;#s;constructor(e){this.#e=e.adapter,this.#t=new i({dialect:this.#e.dialect,plugins:[new r]}),this.#i=e.logger??a("db"),this.#s=this.#r()}get adapter(){return this.#e}get events(){return this.#a}getDB(){return this.#s.then(()=>this.#t)}async #r(){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.#t.destroy(),this.#i.info("closed")}async listGraphs(){return await this.#s,await this.#t.selectFrom("kubun_graph_models").selectAll().execute()}async createGraph(e){await this.#s;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 s=Object.entries(e.record),r=new Set;for(;r.size<s.length;){let e=s.filter(([e,t])=>!r.has(e)&&t.interfaces.every(t=>r.has(_(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({id:e,graphModelID:t,model:a,transaction:i}),r.add(e)}))}}),this.#i.debug("created graph {id}",{id:t}),t}async #n(e){let{id:t,graphModelID:a,model:i,transaction:s}=e,r=this.#e.types;for(let e of(await this.#s,await s.schema.createTable(`k_${t}`).ifNotExists().addColumn("id",r.text,e=>e.notNull().primaryKey()).addColumn("owner",r.text,e=>e.notNull()).addColumn("model",r.text,e=>e.notNull()).addColumn("data",r.json).addColumn("unique",r.binary,e=>e.notNull()).addColumn("created_at",r.timestamp,e=>e.defaultTo(this.#e.functions.now).notNull()).addColumn("updated_at",r.timestamp).execute(),await s.insertInto("kubun_document_models").values({id:t,version:i.version,name:i.name,behavior:i.behavior,unique_fields:"unique"===i.behavior?JSON.stringify(i.uniqueFields):null,interfaces:JSON.stringify(i.interfaces),schema:JSON.stringify(i.schema),fields_meta:JSON.stringify(i.fieldsMeta)}).onConflict(e=>e.doNothing()).execute(),i.interfaces))await s.insertInto("kubun_document_model_interfaces").values({interface_id:_(t,e),implementation_id:t}).onConflict(e=>e.doNothing()).execute();await s.insertInto("kubun_graph_document_models").values({graph_model_id:a,document_model_id:t}).onConflict(e=>e.doNothing()).execute()}async getGraph(e){await this.#s;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]=m(t);return{...t,record:a}}async getDocumentModel(e){return await this.#s,m(await this.#t.selectFrom("kubun_document_models").selectAll().where("id","=",e.toString()).executeTakeFirstOrThrow())}async getDocument(e){await this.#s;let t=await this.#t.selectFrom(`k_${e.model.toString()}`).selectAll().where("id","=",e.toString()).executeTakeFirst();return t?h(this.#e,t):null}async getDocumentState(e){await this.#s;let t=await this.#t.selectFrom("kubun_document_states").selectAll().where("id","=",e).executeTakeFirst();return t?.data??null}async getDocumentStates(e){await this.#s;let t=await this.#t.selectFrom("kubun_document_states").selectAll().where("id","in",e).execute(),a={};for(let e of t)a[e.id]=e.data;return e.reduce((e,t)=>(e[t]=a[t]??null,e),{})}async listDocuments(e){await this.#s;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=>h(this.#e,e))}async queryDocuments(e){let{filter:t,modelIDs:a,orderBy:i,owner:s,...r}=e,n=null!=e.last;await this.#s;let[o,...m]=a,_=this.#t.selectFrom(`k_${o}`).selectAll();for(let e of(null!=s&&(_=_.where("owner","=",s)),null!=t&&(_=_.where(e=>l(e,t))),m))_=_.unionAll(a=>{let i=a.selectFrom(`k_${e}`).selectAll();return null!=s&&(i=i.where("owner","=",s)),null!=t&&(i=i.where(e=>l(e,t))),i});let[w,p]=c(_,i,n),[y,b]=u(w,r,i),g=await y.execute(),f=n?g.slice(0,b).reverse():g.slice(0,b);return{entries:p?f.map(e=>{let t={};for(let a of p){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:h(this.#e,e)}}):f.map(e=>({cursor:d({id:e.id,ts:+e.created_at}),document:h(this.#e,e)})),hasMore:f.length>b}}async createDocument(e){await this.#s;let t=e.id.toString(),a=e.id.model.toString(),i=await this.#t.transaction().setIsolationLevel("read committed").execute(async i=>{let s=await i.insertInto(`k_${a}`).values({id:t,owner:e.owner,model:a,data:this.#e.encodeJSON(e.data),unique:this.#e.encodeBinary(e.unique)}).returningAll().executeTakeFirst();return await i.insertInto("kubun_document_states").values({id:t,data:e.state?this.#e.encodeBinary(e.state):null}).execute(),s}),s=h(this.#e,i);return this.#a.emit("document:saved",{type:"create",document:s,getCursor:()=>d({id:i.id,ts:+i.created_at})}),this.#i.debug("created document {id} with model {model}",{id:t,model:a}),s}async saveDocument(e){await this.#s;let t=e.id.toString(),a=await this.#t.transaction().setIsolationLevel("read committed").execute(async a=>{let i=await a.updateTable(`k_${e.id.model.toString()}`).set({data:e.data?this.#e.encodeJSON(e.data):null,updated_at:this.#e.encodeTimestamp(new Date)}).where("id","=",t).returningAll().executeTakeFirst();return await a.updateTable("kubun_document_states").set({data:e.state?this.#e.encodeBinary(e.state):null}).where("id","=",t).execute(),i}),i=h(this.#e,a);return this.#a.emit("document:saved",{type:"update",document:i,previous:e.existing,getCursor:()=>d({id:a.id,ts:+a.created_at})}),this.#i.debug("updated document {id}",{id:t}),i}async addAttachments(e){await this.#s,await this.#t.insertInto("kubun_document_attachments").values(e).onConflict(e=>e.doNothing()).execute()}async getUserModelAccessDefault(e,t,a){await this.#s;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.#s,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.#s,await this.#t.deleteFrom("kubun_user_model_access_defaults").where("owner_did","=",e).where("model_id","=",t).where("permission_type","in",a).execute()}async storeMutationLog(e){await this.#s;let t=globalThis.crypto.randomUUID();await this.#t.insertInto("kubun_document_mutation_log").values({id:t,document_id:e.documentID,sequence_number:e.sequenceNumber,mutation_jwt:e.mutationJWT,author_did:e.authorDID,timestamp:Date.now()}).execute(),await this.#t.deleteFrom("kubun_document_mutation_log").where("document_id","=",e.documentID).where("id","not in",this.#t.selectFrom("kubun_document_mutation_log").select("id").where("document_id","=",e.documentID).orderBy(n`CAST(sequence_number AS INTEGER)`,"desc").limit(10)).execute()}async getMutationLog(e,t){return await this.#s,await this.#t.selectFrom("kubun_document_mutation_log").selectAll().where("document_id","=",e).where(n`CAST(sequence_number AS INTEGER)`,">=",t).orderBy(n`CAST(sequence_number AS INTEGER)`,"asc").execute()}async listDocumentModelIDs(){return await this.#s,(await this.#t.selectFrom("kubun_document_models").select("id").execute()).map(e=>e.id)}async queryDocumentsByOwner(e,t){return await this.#s,(await this.#t.selectFrom(`k_${e}`).selectAll().where("owner","=",t).execute()).map(e=>h(this.#e,e))}async storeSyncCheckpoint(e,t){await this.#s;let a=`${e}:${t.userID}`,i=JSON.stringify(t.documentCheckpoints),s=JSON.stringify(t.vectorClock);try{return await this.#t.insertInto("kubun_sync_checkpoints").values({id:a,peer_server_id:e,user_id:t.userID,last_sync_timestamp:t.lastSyncTimestamp,document_checkpoints:i,vector_clock:s}).onConflict(e=>e.column("id").doUpdateSet({last_sync_timestamp:t.lastSyncTimestamp,document_checkpoints:i,vector_clock:s})).execute(),!0}catch{return!1}}async getSyncCheckpoint(e,t){await this.#s;let a=`${e}:${t}`,i=await this.#t.selectFrom("kubun_sync_checkpoints").selectAll().where("id","=",a).executeTakeFirst();return i?{lastSyncTimestamp:i.last_sync_timestamp,documentCheckpoints:i.document_checkpoints,vectorClock:i.vector_clock}:null}async listSyncCheckpoints(e){return await this.#s,(await this.#t.selectFrom("kubun_sync_checkpoints").selectAll().where("peer_server_id","=",e).execute()).map(e=>({userID:e.user_id,lastSyncTimestamp:e.last_sync_timestamp,documentCheckpoints:e.document_checkpoints,vectorClock:e.vector_clock}))}async createSearchIndex(e,t){await this.#s,await this.#e.createSearchIndex(this.#t,{modelID:e,fields:t})}async dropSearchIndex(e){await this.#s,await this.#e.dropSearchIndex(this.#t,e)}async updateSearchEntry(e,t,a,i){await this.#s;let s={};for(let e of i){let t=this.#d(a,e);null!=t&&(s[e]=String(t))}await this.#e.updateSearchEntry(this.#t,e,t,s,i)}async removeSearchEntry(e,t){await this.#s,await this.#e.removeSearchEntry(this.#t,e,t)}async searchDocuments(e){await this.#s;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}}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{KubunDB}from"./db.js";
|
package/lib/migrations/0-init.js
CHANGED
|
@@ -1,29 +1 @@
|
|
|
1
|
-
export function getMigration(
|
|
2
|
-
const t = adapter.types;
|
|
3
|
-
async function up(db) {
|
|
4
|
-
await db.schema.createTable('kubun_document_attachments').ifNotExists().addColumn('id', t.text, (col)=>col.notNull().primaryKey()).addColumn('data', t.binary, (col)=>col.notNull()).addColumn('created_at', t.timestamp, (col)=>col.defaultTo(adapter.functions.now).notNull()).execute();
|
|
5
|
-
await db.schema.createTable('kubun_document_models').ifNotExists().addColumn('id', t.text, (col)=>col.notNull().primaryKey()).addColumn('version', t.text, (col)=>col.notNull()).addColumn('name', t.text, (col)=>col.notNull()).addColumn('behavior', t.text, (col)=>col.notNull()).addColumn('unique_fields', t.json).addColumn('interfaces', t.json, (col)=>col.notNull()).addColumn('schema', t.json, (col)=>col.notNull()).addColumn('fields_meta', t.json, (col)=>col.notNull()).addColumn('created_at', t.timestamp, (col)=>col.defaultTo(adapter.functions.now).notNull()).execute();
|
|
6
|
-
await db.schema.createTable('kubun_document_model_interfaces').ifNotExists().addColumn('interface_id', t.text, (col)=>col.notNull().references('kubun_document_models.id')).addColumn('implementation_id', t.text, (col)=>col.notNull().references('kubun_document_models.id')).addUniqueConstraint('kubun_document_model_interfaces_pkey', [
|
|
7
|
-
'interface_id',
|
|
8
|
-
'implementation_id'
|
|
9
|
-
]).execute();
|
|
10
|
-
await db.schema.createTable('kubun_document_states').ifNotExists().addColumn('id', t.text, (col)=>col.notNull().primaryKey()).addColumn('data', t.binary).execute();
|
|
11
|
-
await db.schema.createTable('kubun_graph_models').ifNotExists().addColumn('id', t.text, (col)=>col.notNull().primaryKey()).addColumn('name', t.text, (col)=>col.notNull()).addColumn('aliases', t.json, (col)=>col.defaultTo('{}').notNull()).addColumn('created_at', t.timestamp, (col)=>col.defaultTo(adapter.functions.now).notNull()).addColumn('updated_at', t.timestamp).execute();
|
|
12
|
-
await db.schema.createTable('kubun_graph_document_models').ifNotExists().addColumn('graph_model_id', t.text, (col)=>col.notNull().references('kubun_graph_models.id')).addColumn('document_model_id', t.text, (col)=>col.notNull().references('kubun_document_models.id')).addUniqueConstraint('kubun_graph_document_models_pkey', [
|
|
13
|
-
'graph_model_id',
|
|
14
|
-
'document_model_id'
|
|
15
|
-
]).execute();
|
|
16
|
-
}
|
|
17
|
-
async function down(db) {
|
|
18
|
-
await db.schema.dropTable('kubun_graph_document_models').execute();
|
|
19
|
-
await db.schema.dropTable('kubun_graph_models').execute();
|
|
20
|
-
await db.schema.dropTable('kubun_document_states').execute();
|
|
21
|
-
await db.schema.dropTable('kubun_document_model_interfaces').execute();
|
|
22
|
-
await db.schema.dropTable('kubun_document_models').execute();
|
|
23
|
-
await db.schema.dropTable('kubun_document_attachments').execute();
|
|
24
|
-
}
|
|
25
|
-
return {
|
|
26
|
-
up,
|
|
27
|
-
down
|
|
28
|
-
};
|
|
29
|
-
}
|
|
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_document_states").ifNotExists().addColumn("id",t.text,e=>e.notNull().primaryKey()).addColumn("data",t.binary).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("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()},down:async function(e){await e.schema.dropTable("kubun_graph_document_models").execute(),await e.schema.dropTable("kubun_graph_models").execute(),await e.schema.dropTable("kubun_document_states").execute(),await e.schema.dropTable("kubun_document_model_interfaces").execute(),await e.schema.dropTable("kubun_document_models").execute(),await e.schema.dropTable("kubun_document_attachments").execute()}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getMigration(e){let d=e.types;return{up:async function(t){await t.schema.createTable("kubun_user_model_access_defaults").ifNotExists().addColumn("owner_did",d.text,e=>e.notNull()).addColumn("model_id",d.text,e=>e.notNull()).addColumn("permission_type",d.text,e=>e.notNull()).addColumn("access_level",d.text,e=>e.notNull()).addColumn("allowed_dids",d.json).addColumn("created_at",d.timestamp,d=>d.defaultTo(e.functions.now).notNull()).addColumn("updated_at",d.timestamp).addPrimaryKeyConstraint("kubun_user_model_access_defaults_pkey",["owner_did","model_id","permission_type"]).execute(),await t.schema.createIndex("idx_user_model_access_owner_model").on("kubun_user_model_access_defaults").columns(["owner_did","model_id"]).execute()},down:async function(e){await e.schema.dropIndex("idx_user_model_access_owner_model").execute(),await e.schema.dropTable("kubun_user_model_access_defaults").execute()}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getMigration(t){let e=t.types;return{up:async function(n){await n.schema.createTable("kubun_document_mutation_log").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("document_id",e.text,t=>t.notNull()).addColumn("sequence_number",e.text,t=>t.notNull()).addColumn("mutation_jwt",e.text,t=>t.notNull()).addColumn("timestamp",e.timestamp,e=>e.defaultTo(t.functions.now).notNull()).addColumn("author_did",e.text,t=>t.notNull()).execute(),await n.schema.createIndex("idx_mutation_log_doc_seq").on("kubun_document_mutation_log").columns(["document_id","sequence_number"]).execute(),await n.schema.createTable("kubun_sync_checkpoints").ifNotExists().addColumn("id",e.text,t=>t.notNull().primaryKey()).addColumn("peer_server_id",e.text,t=>t.notNull()).addColumn("user_id",e.text,t=>t.notNull()).addColumn("last_sync_timestamp",e.timestamp,t=>t.notNull()).addColumn("document_checkpoints",e.json,t=>t.notNull()).addColumn("vector_clock",e.json,t=>t.notNull()).execute(),await n.schema.createIndex("idx_sync_checkpoints_peer_user").on("kubun_sync_checkpoints").columns(["peer_server_id","user_id"]).execute(),await n.schema.createTable("kubun_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,e=>e.defaultTo(t.functions.now).notNull()).addColumn("updated_at",e.timestamp,e=>e.defaultTo(t.functions.now).notNull()).execute()},down:async function(t){await t.schema.dropTable("kubun_sync_peers").ifExists().execute(),await t.schema.dropTable("kubun_sync_checkpoints").ifExists().execute(),await t.schema.dropIndex("idx_sync_checkpoints_peer_user").ifExists().execute(),await t.schema.dropIndex("idx_mutation_log_doc_seq").ifExists().execute(),await t.schema.dropTable("kubun_document_mutation_log").ifExists().execute()}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getMigration(e){return{up:async function(a){await a.schema.alterTable("kubun_graph_models").addColumn("search",e.types.json).execute()},down:async function(e){await e.schema.alterTable("kubun_graph_models").dropColumn("search").execute()}}}
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
import { getMigration as
|
|
2
|
-
export function getMigrations(adapter) {
|
|
3
|
-
return {
|
|
4
|
-
kubunMigration0: migration0(adapter)
|
|
5
|
-
};
|
|
6
|
-
}
|
|
1
|
+
import{getMigration as i}from"./0-init.js";import{getMigration as t}from"./1-add-access-control.js";import{getMigration as r}from"./2-add-sync.js";import{getMigration as o}from"./3-add-search.js";export function getMigrations(n){return{kubunMigration0:i(n),kubunMigration1:t(n),kubunMigration2:r(n),kubunMigration3:o(n)}}
|
package/lib/query-builder.d.ts
CHANGED
|
@@ -9,4 +9,3 @@ export declare function applyDocumentFilter(eb: DocumentExpressionBuilder, filte
|
|
|
9
9
|
export declare function applyValueFilter(eb: DocumentExpressionBuilder, keys: Array<string>, filter: AnyValueFilter): DocumentExpressionWrapper;
|
|
10
10
|
export declare function applyDocumentOrderBy(queryBuilder: DocumentQueryBuilder, orderBy?: DocumentOrderBy, isReverse?: boolean): [DocumentQueryBuilder, Array<Array<string>> | null];
|
|
11
11
|
export {};
|
|
12
|
-
//# sourceMappingURL=query-builder.d.ts.map
|
package/lib/query-builder.js
CHANGED
|
@@ -1,227 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
const DEFAULT_LIMIT = 50;
|
|
3
|
-
const MAX_LIMIT = 100;
|
|
4
|
-
function getLimit(value = DEFAULT_LIMIT) {
|
|
5
|
-
return Math.min(value, MAX_LIMIT);
|
|
6
|
-
}
|
|
7
|
-
function getKeyPath(eb, keys) {
|
|
8
|
-
let keyPath = eb.ref('data', '->>');
|
|
9
|
-
for (const key of keys){
|
|
10
|
-
keyPath = keyPath.key(key);
|
|
11
|
-
}
|
|
12
|
-
return keyPath;
|
|
13
|
-
}
|
|
14
|
-
function getOrderByFieldEntry(field) {
|
|
15
|
-
const keys = [];
|
|
16
|
-
let current = field;
|
|
17
|
-
do {
|
|
18
|
-
const [key, value] = Object.entries(current)[0];
|
|
19
|
-
keys.push(key);
|
|
20
|
-
if (typeof value === 'string') {
|
|
21
|
-
return {
|
|
22
|
-
keys,
|
|
23
|
-
direction: value
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
current = value;
|
|
27
|
-
}while (current != null)
|
|
28
|
-
throw new Error('Could not extract field entry');
|
|
29
|
-
}
|
|
30
|
-
function orderByDirection(direction, isReversed = false) {
|
|
31
|
-
return isReversed ? direction === 'asc' ? 'desc' : 'asc' : direction;
|
|
32
|
-
}
|
|
33
|
-
export function applyPagination(query, args, orderBy = []) {
|
|
34
|
-
const { first, last, before, after } = args;
|
|
35
|
-
if (first != null) {
|
|
36
|
-
const limit = getLimit(first);
|
|
37
|
-
return [
|
|
38
|
-
applyForwardPagination(query, limit + 1, after, orderBy),
|
|
39
|
-
limit
|
|
40
|
-
];
|
|
41
|
-
}
|
|
42
|
-
if (last != null) {
|
|
43
|
-
const limit = getLimit(last);
|
|
44
|
-
return [
|
|
45
|
-
applyBackwardPagination(query, limit + 1, before, orderBy),
|
|
46
|
-
limit
|
|
47
|
-
];
|
|
48
|
-
}
|
|
49
|
-
const limit = getLimit();
|
|
50
|
-
return [
|
|
51
|
-
query.orderBy('created_at', 'asc').limit(limit + 1),
|
|
52
|
-
limit
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
|
-
function applyForwardPagination(queryBuilder, limit, after, orderBy) {
|
|
56
|
-
let query = queryBuilder;
|
|
57
|
-
if (after != null) {
|
|
58
|
-
const { id, ts, values } = parseCursor(after);
|
|
59
|
-
if (ts != null) {
|
|
60
|
-
query = query.where((eb)=>{
|
|
61
|
-
return eb.or([
|
|
62
|
-
eb('created_at', '>', ts),
|
|
63
|
-
eb('created_at', '=', ts).and('id', '>', id)
|
|
64
|
-
]);
|
|
65
|
-
});
|
|
66
|
-
} else if (values != null) {
|
|
67
|
-
query = query.where((eb)=>{
|
|
68
|
-
const entries = [];
|
|
69
|
-
for (const orderByField of orderBy){
|
|
70
|
-
const entry = getOrderByFieldEntry(orderByField);
|
|
71
|
-
const value = values[entry.keys.join('.')];
|
|
72
|
-
if (value == null) {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
const keyPath = getKeyPath(eb, entry.keys);
|
|
76
|
-
entries.push(eb.or([
|
|
77
|
-
eb(keyPath, entry.direction === 'asc' ? '>' : '<', value),
|
|
78
|
-
eb(keyPath, '=', value).and('id', '>', id)
|
|
79
|
-
]));
|
|
80
|
-
}
|
|
81
|
-
return eb.and(entries);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return query.orderBy('created_at', 'asc').limit(limit);
|
|
86
|
-
}
|
|
87
|
-
function applyBackwardPagination(queryBuilder, limit, before, orderBy) {
|
|
88
|
-
let query = queryBuilder;
|
|
89
|
-
if (before != null) {
|
|
90
|
-
const { id, ts, values } = parseCursor(before);
|
|
91
|
-
if (ts != null) {
|
|
92
|
-
query = query.where((eb)=>{
|
|
93
|
-
return eb.or([
|
|
94
|
-
eb('created_at', '<', ts),
|
|
95
|
-
eb('created_at', '=', ts).and('id', '<', id)
|
|
96
|
-
]);
|
|
97
|
-
});
|
|
98
|
-
} else if (values != null) {
|
|
99
|
-
query = query.where((eb)=>{
|
|
100
|
-
const entries = [];
|
|
101
|
-
for (const orderByField of orderBy){
|
|
102
|
-
const entry = getOrderByFieldEntry(orderByField);
|
|
103
|
-
const value = values[entry.keys.join('.')];
|
|
104
|
-
if (value == null) {
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
const keyPath = getKeyPath(eb, entry.keys);
|
|
108
|
-
entries.push(eb.or([
|
|
109
|
-
eb(keyPath, entry.direction === 'asc' ? '<' : '>', value),
|
|
110
|
-
eb(keyPath, '=', value).and('id', '>', id)
|
|
111
|
-
]));
|
|
112
|
-
}
|
|
113
|
-
return eb.and(entries);
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return query.orderBy('created_at', 'desc').limit(limit);
|
|
118
|
-
}
|
|
119
|
-
export function applyDocumentFilter(eb, filter, path = []) {
|
|
120
|
-
const entries = Object.entries(filter);
|
|
121
|
-
if (entries.length !== 1) {
|
|
122
|
-
throw new Error('Invalid document filter');
|
|
123
|
-
}
|
|
124
|
-
const [type, value] = entries[0];
|
|
125
|
-
switch(type){
|
|
126
|
-
case 'where':
|
|
127
|
-
return applyObjectFilter(eb, value, path);
|
|
128
|
-
case 'and':
|
|
129
|
-
return eb.and(value.map((filter)=>{
|
|
130
|
-
return applyDocumentFilter(eb, filter, path);
|
|
131
|
-
}));
|
|
132
|
-
case 'or':
|
|
133
|
-
return eb.or(value.map((filter)=>{
|
|
134
|
-
return applyDocumentFilter(eb, filter, path);
|
|
135
|
-
}));
|
|
136
|
-
case 'not':
|
|
137
|
-
return eb.not(applyDocumentFilter(eb, value, path));
|
|
138
|
-
default:
|
|
139
|
-
throw new Error(`Invalid document filter type: ${type}`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function applyObjectFilter(eb, filter, path) {
|
|
143
|
-
const criteria = Object.entries(filter).map(([fieldName, valueFilter])=>{
|
|
144
|
-
// TODO: check if value filter or nested object filter should be applied
|
|
145
|
-
// for nested object, check if embedded or related object
|
|
146
|
-
return applyValueFilter(eb, [
|
|
147
|
-
...path,
|
|
148
|
-
fieldName
|
|
149
|
-
], valueFilter);
|
|
150
|
-
});
|
|
151
|
-
return eb.and(criteria);
|
|
152
|
-
}
|
|
153
|
-
export function applyValueFilter(eb, keys, filter) {
|
|
154
|
-
const entries = Object.entries(filter);
|
|
155
|
-
if (entries.length !== 1) {
|
|
156
|
-
throw new Error('Invalid value filter');
|
|
157
|
-
}
|
|
158
|
-
const fieldName = getKeyPath(eb, keys);
|
|
159
|
-
const [type, value] = entries[0];
|
|
160
|
-
switch(type){
|
|
161
|
-
case 'isNull':
|
|
162
|
-
return eb(fieldName, value === true ? 'is' : 'is not', null);
|
|
163
|
-
case 'equalTo':
|
|
164
|
-
return eb(fieldName, '=', value);
|
|
165
|
-
case 'notEqualTo':
|
|
166
|
-
return eb(fieldName, '!=', value);
|
|
167
|
-
case 'in':
|
|
168
|
-
return eb(fieldName, 'in', value);
|
|
169
|
-
case 'notIn':
|
|
170
|
-
return eb(fieldName, 'not in', value);
|
|
171
|
-
case 'lessThan':
|
|
172
|
-
return eb(fieldName, '<', value);
|
|
173
|
-
case 'lessThanOrEqualTo':
|
|
174
|
-
return eb(fieldName, '<=', value);
|
|
175
|
-
case 'greaterThan':
|
|
176
|
-
return eb(fieldName, '>', value);
|
|
177
|
-
case 'greaterThanOrEqualTo':
|
|
178
|
-
return eb(fieldName, '>=', value);
|
|
179
|
-
default:
|
|
180
|
-
throw new Error(`Invalid value filter type: ${type}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
export function applyDocumentOrderBy(queryBuilder, orderBy = [], isReverse = false) {
|
|
184
|
-
if (orderBy.length === 0) {
|
|
185
|
-
return [
|
|
186
|
-
queryBuilder.orderBy('created_at', orderByDirection('asc', isReverse)),
|
|
187
|
-
null
|
|
188
|
-
];
|
|
189
|
-
}
|
|
190
|
-
let query = queryBuilder;
|
|
191
|
-
const paths = [];
|
|
192
|
-
for (const entry of orderBy){
|
|
193
|
-
const [newQuery, path] = applyOrderByField(query, entry, isReverse);
|
|
194
|
-
query = newQuery;
|
|
195
|
-
paths.push(path);
|
|
196
|
-
}
|
|
197
|
-
return [
|
|
198
|
-
query,
|
|
199
|
-
paths
|
|
200
|
-
];
|
|
201
|
-
}
|
|
202
|
-
const KNOWN_FIELDS = {
|
|
203
|
-
_createdAt: 'created_at',
|
|
204
|
-
_owner: 'owner'
|
|
205
|
-
};
|
|
206
|
-
function applyOrderByField(query, orderBy, isReverse, path = []) {
|
|
207
|
-
const entries = Object.entries(orderBy);
|
|
208
|
-
if (entries.length !== 1) {
|
|
209
|
-
throw new Error('Invalid order by field');
|
|
210
|
-
}
|
|
211
|
-
const [key, value] = entries[0];
|
|
212
|
-
const keys = [
|
|
213
|
-
...path,
|
|
214
|
-
key
|
|
215
|
-
];
|
|
216
|
-
const knowField = KNOWN_FIELDS[key];
|
|
217
|
-
if (knowField != null) {
|
|
218
|
-
return [
|
|
219
|
-
query.orderBy(knowField, orderByDirection(value, isReverse)),
|
|
220
|
-
keys
|
|
221
|
-
];
|
|
222
|
-
}
|
|
223
|
-
return typeof value === 'string' ? [
|
|
224
|
-
query.orderBy((eb)=>getKeyPath(eb, keys), orderByDirection(value, isReverse)),
|
|
225
|
-
keys
|
|
226
|
-
] : applyOrderByField(query, value, isReverse, keys);
|
|
227
|
-
}
|
|
1
|
+
import{parseCursor as e}from"./cursor.js";function t(e=50){return Math.min(e,100)}function r(e,t){let r=e.ref("data","->>");for(let e of t)r=r.key(e);return r}function n(e){let t=[],r=e;do{let[e,n]=Object.entries(r)[0];if(t.push(e),"string"==typeof n)return{keys:t,direction:n};r=n}while(null!=r)throw Error("Could not extract field entry")}function l(e,t=!1){return t?"asc"===e?"desc":"asc":e}export function applyPagination(l,a,o=[]){let{first:i,last:u,before:c,after:d}=a;if(null!=i){let a=t(i);return[function(t,l,a,o){let i=t;if(null!=a){let{id:t,ts:l,values:u}=e(a);null!=l?i=i.where(e=>e.or([e("created_at",">",l),e("created_at","=",l).and("id",">",t)])):null!=u&&(i=i.where(e=>{let l=[];for(let a of o){let o=n(a),i=u[o.keys.join(".")];if(null==i)continue;let c=r(e,o.keys);l.push(e.or([e(c,"asc"===o.direction?">":"<",i),e(c,"=",i).and("id",">",t)]))}return e.and(l)}))}return i.orderBy("created_at","asc").limit(l)}(l,a+1,d,o),a]}if(null!=u){let a=t(u);return[function(t,l,a,o){let i=t;if(null!=a){let{id:t,ts:l,values:u}=e(a);null!=l?i=i.where(e=>e.or([e("created_at","<",l),e("created_at","=",l).and("id","<",t)])):null!=u&&(i=i.where(e=>{let l=[];for(let a of o){let o=n(a),i=u[o.keys.join(".")];if(null==i)continue;let c=r(e,o.keys);l.push(e.or([e(c,"asc"===o.direction?"<":">",i),e(c,"=",i).and("id",">",t)]))}return e.and(l)}))}return i.orderBy("created_at","desc").limit(l)}(l,a+1,c,o),a]}let s=t();return[l.orderBy("created_at","asc").limit(s+1),s]}export function applyDocumentFilter(e,t,r=[]){let n=Object.entries(t);if(1!==n.length)throw Error("Invalid document filter");let[l,a]=n[0];switch(l){case"where":var o,i,u;let c;return o=e,i=a,u=r,c=Object.entries(i).map(([e,t])=>applyValueFilter(o,[...u,e],t)),o.and(c);case"and":return e.and(a.map(t=>applyDocumentFilter(e,t,r)));case"or":return e.or(a.map(t=>applyDocumentFilter(e,t,r)));case"not":return e.not(applyDocumentFilter(e,a,r));default:throw Error(`Invalid document filter type: ${l}`)}}export function applyValueFilter(e,t,n){let l=Object.entries(n);if(1!==l.length)throw Error("Invalid value filter");let a=r(e,t),[o,i]=l[0];switch(o){case"isNull":return e(a,!0===i?"is":"is not",null);case"equalTo":return e(a,"=",i);case"notEqualTo":return e(a,"!=",i);case"in":return e(a,"in",i);case"notIn":return e(a,"not in",i);case"lessThan":return e(a,"<",i);case"lessThanOrEqualTo":return e(a,"<=",i);case"greaterThan":return e(a,">",i);case"greaterThanOrEqualTo":return e(a,">=",i);default:throw Error(`Invalid value filter type: ${o}`)}}export function applyDocumentOrderBy(e,t=[],n=!1){if(0===t.length)return[e.orderBy("created_at",l("asc",n)),null];let o=e,i=[];for(let e of t){let[t,u]=function e(t,n,o,i=[]){let u=Object.entries(n);if(1!==u.length)throw Error("Invalid order by field");let[c,d]=u[0],s=[...i,c],f=a[c];return null!=f?[t.orderBy(f,l(d,o)),s]:"string"==typeof d?[t.orderBy(e=>r(e,s),l(d,o)),s]:e(t,d,o,s)}(o,e,n);o=t,i.push(u)}return[o,i]}let a={_createdAt:"created_at",_owner:"owner"};
|
package/lib/types.d.ts
CHANGED
|
@@ -55,10 +55,25 @@ export type DocumentStateTable = {
|
|
|
55
55
|
};
|
|
56
56
|
export type DocumentState = Selectable<DocumentStateTable>;
|
|
57
57
|
export type InsertDocumentState = Insertable<DocumentStateTable>;
|
|
58
|
+
export type SearchConfig = Record<string, {
|
|
59
|
+
fields?: Array<string>;
|
|
60
|
+
}>;
|
|
61
|
+
export type SearchDocumentsParams = {
|
|
62
|
+
query: string;
|
|
63
|
+
modelIDs: Array<string>;
|
|
64
|
+
first?: number;
|
|
65
|
+
after?: string;
|
|
66
|
+
};
|
|
67
|
+
export type SearchDocumentResult = {
|
|
68
|
+
documentID: string;
|
|
69
|
+
modelID: string;
|
|
70
|
+
rank: number;
|
|
71
|
+
};
|
|
58
72
|
export type GraphModelTable = {
|
|
59
73
|
id: string;
|
|
60
74
|
name: string;
|
|
61
75
|
aliases: JSONColumnType<Record<string, string>>;
|
|
76
|
+
search: JSONColumnType<SearchConfig> | null;
|
|
62
77
|
created_at: CreatedAtColumn;
|
|
63
78
|
updated_at: UpdatedAtColumn;
|
|
64
79
|
};
|
|
@@ -71,6 +86,67 @@ export type GraphDocumentModelTable = {
|
|
|
71
86
|
};
|
|
72
87
|
export type GraphDocumentModel = Selectable<GraphDocumentModelTable>;
|
|
73
88
|
export type InsertGraphDocumentModel = Insertable<GraphDocumentModelTable>;
|
|
89
|
+
export type UserModelAccessDefaultTable = {
|
|
90
|
+
owner_did: string;
|
|
91
|
+
model_id: string;
|
|
92
|
+
permission_type: string;
|
|
93
|
+
access_level: string;
|
|
94
|
+
allowed_dids: JSONColumnType<Array<string>> | null;
|
|
95
|
+
created_at: CreatedAtColumn;
|
|
96
|
+
updated_at: UpdatedAtColumn;
|
|
97
|
+
};
|
|
98
|
+
export type UserModelAccessDefault = Selectable<UserModelAccessDefaultTable>;
|
|
99
|
+
export type InsertUserModelAccessDefault = Insertable<UserModelAccessDefaultTable>;
|
|
100
|
+
export type UpdateUserModelAccessDefault = Updateable<UserModelAccessDefaultTable>;
|
|
101
|
+
export type DocumentMutationLogTable = {
|
|
102
|
+
id: string;
|
|
103
|
+
document_id: string;
|
|
104
|
+
sequence_number: string;
|
|
105
|
+
mutation_jwt: string;
|
|
106
|
+
timestamp: CreatedAtColumn;
|
|
107
|
+
author_did: string;
|
|
108
|
+
};
|
|
109
|
+
export type DocumentMutationLog = Selectable<DocumentMutationLogTable>;
|
|
110
|
+
export type InsertDocumentMutationLog = Insertable<DocumentMutationLogTable>;
|
|
111
|
+
export type SyncCheckpointTable = {
|
|
112
|
+
id: string;
|
|
113
|
+
peer_server_id: string;
|
|
114
|
+
user_id: string;
|
|
115
|
+
last_sync_timestamp: ColumnType<number, number, number>;
|
|
116
|
+
document_checkpoints: JSONColumnType<Record<string, {
|
|
117
|
+
lastKnownHash: string;
|
|
118
|
+
lastSyncedSequence: number;
|
|
119
|
+
}>>;
|
|
120
|
+
vector_clock: JSONColumnType<Record<string, number>>;
|
|
121
|
+
};
|
|
122
|
+
export type SyncCheckpoint = Selectable<SyncCheckpointTable>;
|
|
123
|
+
export type InsertSyncCheckpoint = Insertable<SyncCheckpointTable>;
|
|
124
|
+
export type SyncPeerTable = {
|
|
125
|
+
id: string;
|
|
126
|
+
peer_did: string;
|
|
127
|
+
endpoint: string;
|
|
128
|
+
mode: string;
|
|
129
|
+
allowed_users: JSONColumnType<Array<string> | {
|
|
130
|
+
all: boolean;
|
|
131
|
+
}>;
|
|
132
|
+
priority: string;
|
|
133
|
+
trust_level: string;
|
|
134
|
+
config: JSONColumnType<Record<string, unknown>>;
|
|
135
|
+
created_at: CreatedAtColumn;
|
|
136
|
+
updated_at: UpdatedAtColumn;
|
|
137
|
+
};
|
|
138
|
+
export type SyncPeer = Selectable<SyncPeerTable>;
|
|
139
|
+
export type InsertSyncPeer = Insertable<SyncPeerTable>;
|
|
140
|
+
export type AccessPermissions = {
|
|
141
|
+
read?: {
|
|
142
|
+
level: 'only_owner' | 'anyone' | 'allowed_dids';
|
|
143
|
+
allowedDIDs?: Array<string>;
|
|
144
|
+
};
|
|
145
|
+
write?: {
|
|
146
|
+
level: 'only_owner' | 'allowed_dids';
|
|
147
|
+
allowedDIDs?: Array<string>;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
74
150
|
export type DocumentTables<Models extends Record<string, DocumentData> = Record<string, DocumentData>, Keys = keyof Models> = {
|
|
75
151
|
[K in string & Keys]: DocumentTable<Models[K]>;
|
|
76
152
|
};
|
|
@@ -81,6 +157,10 @@ export type Database = {
|
|
|
81
157
|
kubun_document_states: DocumentStateTable;
|
|
82
158
|
kubun_graph_document_models: GraphDocumentModelTable;
|
|
83
159
|
kubun_graph_models: GraphModelTable;
|
|
160
|
+
kubun_user_model_access_defaults: UserModelAccessDefaultTable;
|
|
161
|
+
kubun_document_mutation_log: DocumentMutationLogTable;
|
|
162
|
+
kubun_sync_checkpoints: SyncCheckpointTable;
|
|
163
|
+
kubun_sync_peers: SyncPeerTable;
|
|
84
164
|
[key: `k_${string}`]: DocumentTable;
|
|
85
165
|
};
|
|
86
166
|
export type CursorDocument = {
|
|
@@ -102,4 +182,3 @@ export type QueryDocumentsResult = {
|
|
|
102
182
|
hasMore: boolean;
|
|
103
183
|
};
|
|
104
184
|
export {};
|
|
105
|
-
//# sourceMappingURL=types.d.ts.map
|
package/lib/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"type": "module",
|
|
@@ -15,15 +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.13.0",
|
|
19
|
+
"@enkaku/event": "^0.13.0",
|
|
20
|
+
"kysely": "^0.28.11",
|
|
21
|
+
"@kubun/logger": "^0.5.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@
|
|
25
|
-
"@kubun/id": "^0.
|
|
26
|
-
"@kubun/protocol": "^0.
|
|
24
|
+
"@databases/pg-test": "^3.1.2",
|
|
25
|
+
"@kubun/id": "^0.5.0",
|
|
26
|
+
"@kubun/protocol": "^0.5.0",
|
|
27
|
+
"@kubun/db-adapter": "^0.5.0",
|
|
28
|
+
"@kubun/db-sqlite": "^0.5.0",
|
|
29
|
+
"@kubun/db-postgres": "^0.5.0"
|
|
27
30
|
},
|
|
28
31
|
"scripts": {
|
|
29
32
|
"build:clean": "del lib",
|
package/lib/cursor.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../src/cursor.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAEtD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAExD"}
|
package/lib/db.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,mBAAmB,YAAY,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"0-init.d.ts","sourceRoot":"","sources":["../../src/migrations/0-init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,QAAQ,CAAA;AAI/C,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAoFxD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/migrations/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAIvC,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAEzE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,eAAe,EAIhB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAGtF,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEzE,KAAK,yBAAyB,GAAG,iBAAiB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;AAE1E,KAAK,yBAAyB,GAAG,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,CAAC,CAAA;AAE/E,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAA;AAwCvF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,mBAAmB,EACzB,OAAO,GAAE,eAAoB,GAC5B,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAYhC;AA6ED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,yBAAyB,EAC7B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE,KAAK,CAAC,MAAM,CAAM,GACvB,yBAAyB,CA0B3B;AAeD,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,yBAAyB,EAC7B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,MAAM,EAAE,cAAc,GACrB,yBAAyB,CA+B3B;AAED,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,oBAAoB,EAClC,OAAO,GAAE,eAAoB,EAC7B,SAAS,UAAQ,GAChB,CAAC,oBAAoB,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAarD"}
|
package/lib/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|