@kubun/graphql 0.4.3 → 0.4.4
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/context.d.ts +2 -0
- package/lib/context.d.ts.map +1 -1
- package/lib/context.js +111 -13
- package/lib/schema.d.ts.map +1 -1
- package/lib/schema.js +12 -14
- package/package.json +1 -1
package/lib/context.d.ts
CHANGED
|
@@ -26,9 +26,11 @@ export type SubscriptionContext = {
|
|
|
26
26
|
* Query and subscription functions requiring server implementation
|
|
27
27
|
*/
|
|
28
28
|
export type ReadOnlyContext = QueryContext & SubscriptionContext;
|
|
29
|
+
export type AccessChecker = (doc: DocumentNode, permissionType: 'read' | 'write') => Promise<boolean>;
|
|
29
30
|
export type ReadContextParams = {
|
|
30
31
|
db: KubunDB;
|
|
31
32
|
viewerDID: string;
|
|
33
|
+
accessChecker?: AccessChecker;
|
|
32
34
|
};
|
|
33
35
|
export declare function createReadContext(params: ReadContextParams): ReadOnlyContext;
|
|
34
36
|
/**
|
package/lib/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,OAAO,EAAE,MAAM,WAAW,CAAA;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,EAAE,UAAU,EAAuB,IAAI,EAAE,MAAM,eAAe,CAAA;AAE1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAE7E;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,IAAI,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IACtD,iBAAiB,CACf,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EACvB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAA;IACpC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAA;CACvF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,0BAA0B,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,CAAA;IACjF,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,CAAA;IACpE,0BAA0B,IAAI,cAAc,CAAC,MAAM,CAAC,CAAA;IACpD,4BAA4B,CAC1B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GAC3C,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAA;IACrC,8BAA8B,CAC5B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GAC3C,cAAc,CAAC,MAAM,CAAC,CAAA;CAC1B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,mBAAmB,CAAA;AAEhE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,OAAO,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/lib/context.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defer } from '@enkaku/async';
|
|
2
2
|
import { DocumentID } from '@kubun/id';
|
|
3
3
|
export function createReadContext(params) {
|
|
4
|
-
const { db, viewerDID } = params;
|
|
4
|
+
const { db, viewerDID, accessChecker } = params;
|
|
5
5
|
function createEventGenerator(filter, transform) {
|
|
6
6
|
let isDone = false;
|
|
7
7
|
let pending = null;
|
|
@@ -63,32 +63,130 @@ export function createReadContext(params) {
|
|
|
63
63
|
return viewerDID;
|
|
64
64
|
},
|
|
65
65
|
async loadDocument (id) {
|
|
66
|
-
|
|
66
|
+
const doc = await db.getDocument(DocumentID.fromString(id));
|
|
67
|
+
if (!doc) return null;
|
|
68
|
+
// Check access if access checker is provided
|
|
69
|
+
if (accessChecker) {
|
|
70
|
+
const hasAccess = await accessChecker(doc, 'read');
|
|
71
|
+
if (!hasAccess) {
|
|
72
|
+
// Access denied - return null (error will be added by GraphQL layer)
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return doc;
|
|
67
77
|
},
|
|
68
78
|
async resolveConnection (modelIDs, args) {
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
// If no access checker, return all documents
|
|
80
|
+
if (accessChecker == null) {
|
|
81
|
+
const { entries, hasMore } = await db.queryDocuments({
|
|
82
|
+
...args,
|
|
83
|
+
modelIDs
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
edges: entries.map((e)=>({
|
|
87
|
+
cursor: e.cursor,
|
|
88
|
+
node: e.document
|
|
89
|
+
})),
|
|
90
|
+
pageInfo: {
|
|
91
|
+
hasNextPage: args.first ? hasMore : false,
|
|
92
|
+
hasPreviousPage: args.first ? false : hasMore,
|
|
93
|
+
endCursor: entries.at(-1)?.cursor ?? null,
|
|
94
|
+
startCursor: entries.at(0)?.cursor ?? null
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// With access control: post-fetch filtering with over-fetching
|
|
99
|
+
const allEntries = [];
|
|
100
|
+
let requestedCount = 0;
|
|
101
|
+
let attempts = 0;
|
|
102
|
+
const maxAttempts = 10 // Prevent infinite loops
|
|
103
|
+
;
|
|
104
|
+
if (args.first != null) {
|
|
105
|
+
requestedCount = args.first;
|
|
106
|
+
const fetchSize = requestedCount * 2 // Over-fetch to reduce round trips
|
|
107
|
+
;
|
|
108
|
+
let cursor = args.after;
|
|
109
|
+
while(allEntries.length < requestedCount && attempts < maxAttempts){
|
|
110
|
+
// Fetch unfiltered batch from DB
|
|
111
|
+
const { entries, hasMore } = await db.queryDocuments({
|
|
112
|
+
...args,
|
|
113
|
+
modelIDs,
|
|
114
|
+
first: fetchSize,
|
|
115
|
+
after: cursor
|
|
116
|
+
});
|
|
117
|
+
if (entries.length === 0 && !hasMore) break;
|
|
118
|
+
// Filter based on access rules
|
|
119
|
+
for (const entry of entries){
|
|
120
|
+
if (await accessChecker(entry.document, 'read')) {
|
|
121
|
+
allEntries.push(entry);
|
|
122
|
+
if (allEntries.length >= requestedCount) break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!hasMore) break;
|
|
126
|
+
cursor = entries.at(-1)?.cursor ?? null;
|
|
127
|
+
attempts++;
|
|
128
|
+
}
|
|
129
|
+
} else if (args.last != null) {
|
|
130
|
+
requestedCount = args.last;
|
|
131
|
+
const fetchSize = requestedCount * 2 // Over-fetch to reduce round trips
|
|
132
|
+
;
|
|
133
|
+
let cursor = args.before;
|
|
134
|
+
while(allEntries.length < requestedCount && attempts < maxAttempts){
|
|
135
|
+
// Fetch unfiltered batch from DB
|
|
136
|
+
const { entries, hasMore } = await db.queryDocuments({
|
|
137
|
+
...args,
|
|
138
|
+
modelIDs,
|
|
139
|
+
last: fetchSize,
|
|
140
|
+
before: cursor
|
|
141
|
+
});
|
|
142
|
+
if (entries.length === 0 && !hasMore) break;
|
|
143
|
+
// Filter based on access rules - note we reverse the entries array for backward pagination
|
|
144
|
+
for (const entry of [
|
|
145
|
+
...entries
|
|
146
|
+
].reverse()){
|
|
147
|
+
if (await accessChecker(entry.document, 'read')) {
|
|
148
|
+
allEntries.unshift(entry);
|
|
149
|
+
if (allEntries.length >= requestedCount) break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (!hasMore) break;
|
|
153
|
+
cursor = entries.at(0)?.cursor ?? null;
|
|
154
|
+
attempts++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Return only requested count
|
|
158
|
+
const resultEntries = allEntries.slice(0, requestedCount);
|
|
159
|
+
const hasMoreResults = allEntries.length > requestedCount;
|
|
74
160
|
return {
|
|
75
|
-
edges:
|
|
161
|
+
edges: resultEntries.map((e)=>({
|
|
76
162
|
cursor: e.cursor,
|
|
77
163
|
node: e.document
|
|
78
164
|
})),
|
|
79
165
|
pageInfo: {
|
|
80
|
-
hasNextPage: args.first ?
|
|
81
|
-
hasPreviousPage: args.first ? false :
|
|
82
|
-
endCursor:
|
|
83
|
-
startCursor:
|
|
166
|
+
hasNextPage: args.first ? hasMoreResults : false,
|
|
167
|
+
hasPreviousPage: args.first ? false : hasMoreResults,
|
|
168
|
+
endCursor: resultEntries.at(-1)?.cursor ?? null,
|
|
169
|
+
startCursor: resultEntries.at(0)?.cursor ?? null
|
|
84
170
|
}
|
|
85
171
|
};
|
|
86
172
|
},
|
|
87
173
|
async resolveList (modelIDs, docIDs) {
|
|
88
|
-
|
|
174
|
+
const documents = await db.listDocuments({
|
|
89
175
|
modelIDs,
|
|
90
176
|
docIDs
|
|
91
177
|
});
|
|
178
|
+
// If no access checker, return all documents
|
|
179
|
+
if (!accessChecker) {
|
|
180
|
+
return documents;
|
|
181
|
+
}
|
|
182
|
+
// Filter based on access control
|
|
183
|
+
const accessible = [];
|
|
184
|
+
for (const doc of documents){
|
|
185
|
+
if (await accessChecker(doc, 'read')) {
|
|
186
|
+
accessible.push(doc);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return accessible;
|
|
92
190
|
},
|
|
93
191
|
subscribeToDocumentCreated (modelIDs) {
|
|
94
192
|
return createEventGenerator((event)=>event.type === 'create' && modelIDs.includes(event.document.model), (event)=>event.document);
|
package/lib/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,eAAe,EAAY,MAAM,WAAW,CAAA;AAC/E,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EAEZ,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,WAAW,EAEX,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,WAAW,EAEX,SAAS,EACV,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EAGL,eAAe,EAEf,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAI1B,sBAAsB,EACtB,KAAK,gBAAgB,EAErB,oBAAoB,EACpB,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,aAAa,EAKd,MAAM,SAAS,CAAA;AAkBhB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/lib/schema.js
CHANGED
|
@@ -26,14 +26,17 @@ function isList(type) {
|
|
|
26
26
|
return isListType(type) || isNonNullType(type) && isListType(type.ofType);
|
|
27
27
|
}
|
|
28
28
|
function collectAllModelIDs(collected, record, interfaceID) {
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
29
|
+
const implementedBy = record[interfaceID];
|
|
30
|
+
if (implementedBy == null) {
|
|
31
31
|
throw new Error(`Interface ${interfaceID} not found in record`);
|
|
32
32
|
}
|
|
33
|
-
for (const id of
|
|
34
|
-
if (
|
|
33
|
+
for (const id of implementedBy){
|
|
34
|
+
// Check if this id is itself an interface (exists in record with implementers)
|
|
35
|
+
if (record[id] != null) {
|
|
36
|
+
// The id is an interface that has implementers, resolve recursively
|
|
35
37
|
collectAllModelIDs(collected, record, id);
|
|
36
38
|
} else {
|
|
39
|
+
// The id is a concrete model
|
|
37
40
|
collected.add(id);
|
|
38
41
|
}
|
|
39
42
|
}
|
|
@@ -241,18 +244,11 @@ export class SchemaBuilder {
|
|
|
241
244
|
for (const [modelIDstring, model] of Object.entries(params.record)){
|
|
242
245
|
const modelID = DocumentModelID.fromString(modelIDstring);
|
|
243
246
|
Object.assign(this._references, model.schema.$defs ?? {});
|
|
244
|
-
referencedInterfaces[modelIDstring] ??= {
|
|
245
|
-
isInterface: model.behavior === 'interface',
|
|
246
|
-
implementedBy: new Set()
|
|
247
|
-
};
|
|
248
247
|
// Extract interfaces
|
|
249
248
|
for (const iid of model.interfaces){
|
|
250
249
|
const interfaceID = getGlobalID(iid, modelID).toString();
|
|
251
|
-
referencedInterfaces[interfaceID] ??=
|
|
252
|
-
|
|
253
|
-
implementedBy: new Set()
|
|
254
|
-
};
|
|
255
|
-
referencedInterfaces[interfaceID].implementedBy.add(modelIDstring);
|
|
250
|
+
referencedInterfaces[interfaceID] ??= new Set();
|
|
251
|
+
referencedInterfaces[interfaceID].add(modelIDstring);
|
|
256
252
|
}
|
|
257
253
|
// Extract inverse relations
|
|
258
254
|
for (const [fieldName, meta] of Object.entries(model.fieldsMeta)){
|
|
@@ -274,7 +270,9 @@ export class SchemaBuilder {
|
|
|
274
270
|
for (const id of Object.keys(referencedInterfaces)){
|
|
275
271
|
const implementedBy = new Set();
|
|
276
272
|
collectAllModelIDs(implementedBy, referencedInterfaces, id);
|
|
277
|
-
|
|
273
|
+
if (implementedBy.size !== 0) {
|
|
274
|
+
this._implemented[id] = Array.from(implementedBy);
|
|
275
|
+
}
|
|
278
276
|
for (const modelID of implementedBy){
|
|
279
277
|
nodeModelIDs.add(modelID);
|
|
280
278
|
}
|