@hatk/hatk 0.0.1-alpha.55 → 0.0.1-alpha.57
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/dist/indexer.js +27 -24
- package/dist/lexicons/dev/hatk/applyWrites.json +87 -0
- package/dist/pds-proxy.d.ts +18 -0
- package/dist/pds-proxy.d.ts.map +1 -1
- package/dist/pds-proxy.js +70 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +6 -1
- package/dist/xrpc.d.ts +12 -0
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +8 -1
- package/package.json +1 -1
package/dist/indexer.js
CHANGED
|
@@ -373,32 +373,35 @@ function processMessage(bytes, collections) {
|
|
|
373
373
|
}]);
|
|
374
374
|
continue;
|
|
375
375
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
376
|
+
const opCid = typeof op.cid === 'string' ? op.cid : op.cid?.$link;
|
|
377
|
+
if (!opCid)
|
|
378
|
+
continue;
|
|
379
|
+
const data = blocks.get(opCid);
|
|
380
|
+
if (!data)
|
|
381
|
+
continue;
|
|
382
|
+
try {
|
|
383
|
+
const { value: record } = cborDecode(data);
|
|
384
|
+
if (record?.$type === collection) {
|
|
385
|
+
const validationError = validateRecord(getLexiconArray(), collection, record);
|
|
386
|
+
if (validationError) {
|
|
387
|
+
emit('indexer', 'validation_skip', {
|
|
388
|
+
uri,
|
|
389
|
+
collection,
|
|
390
|
+
path: validationError.path,
|
|
391
|
+
error: validationError.message,
|
|
392
|
+
});
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const item = { collection, uri, cid: opCid, authorDid: did, record };
|
|
396
|
+
// If DID is mid-backfill, buffer instead of writing directly
|
|
397
|
+
if (pendingBuffers.has(did)) {
|
|
398
|
+
pendingBuffers.get(did).push(item);
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
bufferWrite(item);
|
|
399
402
|
}
|
|
400
403
|
}
|
|
401
|
-
catch { }
|
|
402
404
|
}
|
|
405
|
+
catch { }
|
|
403
406
|
}
|
|
404
407
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lexicon": 1,
|
|
3
|
+
"id": "dev.hatk.applyWrites",
|
|
4
|
+
"defs": {
|
|
5
|
+
"main": {
|
|
6
|
+
"type": "procedure",
|
|
7
|
+
"description": "Apply multiple record writes in a single atomic PDS transaction.",
|
|
8
|
+
"input": {
|
|
9
|
+
"encoding": "application/json",
|
|
10
|
+
"schema": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"required": ["writes"],
|
|
13
|
+
"properties": {
|
|
14
|
+
"writes": {
|
|
15
|
+
"type": "array",
|
|
16
|
+
"items": {
|
|
17
|
+
"type": "union",
|
|
18
|
+
"refs": ["#create", "#update", "#delete"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"output": {
|
|
25
|
+
"encoding": "application/json",
|
|
26
|
+
"schema": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"properties": {
|
|
29
|
+
"results": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "union",
|
|
33
|
+
"refs": ["#createResult", "#updateResult", "#deleteResult"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"create": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"required": ["collection", "value"],
|
|
43
|
+
"properties": {
|
|
44
|
+
"collection": { "type": "string" },
|
|
45
|
+
"rkey": { "type": "string" },
|
|
46
|
+
"value": { "type": "unknown" }
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"update": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"required": ["collection", "rkey", "value"],
|
|
52
|
+
"properties": {
|
|
53
|
+
"collection": { "type": "string" },
|
|
54
|
+
"rkey": { "type": "string" },
|
|
55
|
+
"value": { "type": "unknown" }
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"delete": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"required": ["collection", "rkey"],
|
|
61
|
+
"properties": {
|
|
62
|
+
"collection": { "type": "string" },
|
|
63
|
+
"rkey": { "type": "string" }
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"createResult": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"required": ["uri", "cid"],
|
|
69
|
+
"properties": {
|
|
70
|
+
"uri": { "type": "string", "format": "at-uri" },
|
|
71
|
+
"cid": { "type": "string", "format": "cid" }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"updateResult": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"required": ["uri", "cid"],
|
|
77
|
+
"properties": {
|
|
78
|
+
"uri": { "type": "string", "format": "at-uri" },
|
|
79
|
+
"cid": { "type": "string", "format": "cid" }
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"deleteResult": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"properties": {}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
package/dist/pds-proxy.d.ts
CHANGED
|
@@ -34,6 +34,24 @@ export declare function pdsPutRecord(oauthConfig: OAuthConfig, viewer: {
|
|
|
34
34
|
uri?: string;
|
|
35
35
|
cid?: string;
|
|
36
36
|
}>;
|
|
37
|
+
export interface ApplyWritesOp {
|
|
38
|
+
$type: string;
|
|
39
|
+
collection: string;
|
|
40
|
+
rkey?: string;
|
|
41
|
+
value?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
export interface ApplyWritesResult {
|
|
44
|
+
$type: string;
|
|
45
|
+
uri?: string;
|
|
46
|
+
cid?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function pdsApplyWrites(oauthConfig: OAuthConfig, viewer: {
|
|
49
|
+
did: string;
|
|
50
|
+
}, input: {
|
|
51
|
+
writes: ApplyWritesOp[];
|
|
52
|
+
}): Promise<{
|
|
53
|
+
results?: ApplyWritesResult[];
|
|
54
|
+
}>;
|
|
37
55
|
export declare function pdsUploadBlob(oauthConfig: OAuthConfig, viewer: {
|
|
38
56
|
did: string;
|
|
39
57
|
}, body: Uint8Array, contentType: string): Promise<{
|
package/dist/pds-proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pds-proxy.d.ts","sourceRoot":"","sources":["../src/pds-proxy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAU9C,qBAAa,UAAW,SAAQ,KAAK;IAE1B,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAIlB;AAED,qBAAa,sBAAuB,SAAQ,UAAU;;CAIrD;AAuHD,wBAAsB,eAAe,CACnC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC3F,OAAO,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwCzC;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAyBlC;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1F,OAAO,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCzC;AAED,wBAAsB,aAAa,CACjC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAS5B"}
|
|
1
|
+
{"version":3,"file":"pds-proxy.d.ts","sourceRoot":"","sources":["../src/pds-proxy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAU9C,qBAAa,UAAW,SAAQ,KAAK;IAE1B,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAIlB;AAED,qBAAa,sBAAuB,SAAQ,UAAU;;CAIrD;AAuHD,wBAAsB,eAAe,CACnC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC3F,OAAO,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwCzC;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAyBlC;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1F,OAAO,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCzC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAYD,wBAAsB,cAAc,CAClC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,KAAK,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,GACjC,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC,CAgE5C;AAED,wBAAsB,aAAa,CACjC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACvB,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAS5B"}
|
package/dist/pds-proxy.js
CHANGED
|
@@ -195,6 +195,76 @@ export async function pdsPutRecord(oauthConfig, viewer, input) {
|
|
|
195
195
|
}
|
|
196
196
|
return pdsRes.body;
|
|
197
197
|
}
|
|
198
|
+
/** Map dev.hatk.applyWrites#* types to com.atproto.repo.applyWrites#* for PDS. */
|
|
199
|
+
function toPdsWriteType($type) {
|
|
200
|
+
return $type.replace('dev.hatk.applyWrites#', 'com.atproto.repo.applyWrites#');
|
|
201
|
+
}
|
|
202
|
+
function isCreateOrUpdate($type) {
|
|
203
|
+
const mapped = toPdsWriteType($type);
|
|
204
|
+
return mapped === 'com.atproto.repo.applyWrites#create' || mapped === 'com.atproto.repo.applyWrites#update';
|
|
205
|
+
}
|
|
206
|
+
export async function pdsApplyWrites(oauthConfig, viewer, input) {
|
|
207
|
+
// Validate all create/update records before sending
|
|
208
|
+
for (const write of input.writes) {
|
|
209
|
+
if (isCreateOrUpdate(write.$type) && write.value) {
|
|
210
|
+
const validationError = validateRecord(getLexiconArray(), write.collection, write.value);
|
|
211
|
+
if (validationError) {
|
|
212
|
+
throw new ProxyError(400, `InvalidRecord: ${validationError.path ? validationError.path + ': ' : ''}${validationError.message}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const session = await getSession(viewer.did);
|
|
217
|
+
if (!session)
|
|
218
|
+
throw new ProxyError(401, 'No PDS session for user');
|
|
219
|
+
const pdsUrl = `${session.pds_endpoint}/xrpc/com.atproto.repo.applyWrites`;
|
|
220
|
+
const pdsBody = {
|
|
221
|
+
repo: viewer.did,
|
|
222
|
+
writes: input.writes.map((w) => ({ ...w, $type: toPdsWriteType(w.$type) })),
|
|
223
|
+
};
|
|
224
|
+
const pdsRes = await proxyToPds(oauthConfig, session, 'POST', pdsUrl, pdsBody);
|
|
225
|
+
if (!pdsRes.ok)
|
|
226
|
+
throw new ProxyError(pdsRes.status, String(pdsRes.body.error || 'PDS applyWrites failed'));
|
|
227
|
+
// Index results locally
|
|
228
|
+
const results = pdsRes.body.results ?? [];
|
|
229
|
+
for (let i = 0; i < input.writes.length; i++) {
|
|
230
|
+
const write = input.writes[i];
|
|
231
|
+
const result = results[i];
|
|
232
|
+
try {
|
|
233
|
+
const mapped = toPdsWriteType(write.$type);
|
|
234
|
+
if (mapped === 'com.atproto.repo.applyWrites#create' && result?.uri && result?.cid && write.value) {
|
|
235
|
+
await insertRecord(write.collection, result.uri, result.cid, viewer.did, write.value);
|
|
236
|
+
await runLabelRules({
|
|
237
|
+
uri: result.uri,
|
|
238
|
+
cid: result.cid,
|
|
239
|
+
did: viewer.did,
|
|
240
|
+
collection: write.collection,
|
|
241
|
+
value: write.value,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
else if (mapped === 'com.atproto.repo.applyWrites#update' && result?.uri && result?.cid && write.value) {
|
|
245
|
+
await insertRecord(write.collection, result.uri, result.cid, viewer.did, write.value);
|
|
246
|
+
await runLabelRules({
|
|
247
|
+
uri: result.uri,
|
|
248
|
+
cid: result.cid,
|
|
249
|
+
did: viewer.did,
|
|
250
|
+
collection: write.collection,
|
|
251
|
+
value: write.value,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
else if (mapped === 'com.atproto.repo.applyWrites#delete' && write.rkey) {
|
|
255
|
+
const uri = `at://${viewer.did}/${write.collection}/${write.rkey}`;
|
|
256
|
+
await dbDeleteRecord(write.collection, uri);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
emit('pds-proxy', 'local_index_error', {
|
|
261
|
+
op: 'applyWrites',
|
|
262
|
+
error: err instanceof Error ? err.message : String(err),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return pdsRes.body;
|
|
267
|
+
}
|
|
198
268
|
export async function pdsUploadBlob(oauthConfig, viewer, body, contentType) {
|
|
199
269
|
const session = await getSession(viewer.did);
|
|
200
270
|
if (!session)
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA2B9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAgM3F;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxF,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA+zB5F;AAGD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,MAAM,GAAE,MAAM,EAAO,EACrB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,OAAO,WAAW,EAAE,MAAM,CAG5B"}
|
package/dist/server.js
CHANGED
|
@@ -12,7 +12,7 @@ import { emit, timer } from "./logger.js";
|
|
|
12
12
|
import { getAuthServerMetadata, getProtectedResourceMetadata, getJwks, getClientMetadata, handlePar, buildAuthorizeRedirect, handleCallback, serverLogin, handleToken, authenticate, } from "./oauth/server.js";
|
|
13
13
|
import { createSessionCookie, sessionCookieHeader, clearSessionCookieHeader, parseSessionCookie, } from "./oauth/session.js";
|
|
14
14
|
import { getOAuthRequest } from "./oauth/db.js";
|
|
15
|
-
import { pdsCreateRecord, pdsDeleteRecord, pdsPutRecord, pdsUploadBlob, ProxyError, ScopeMissingProxyError, } from "./pds-proxy.js";
|
|
15
|
+
import { pdsCreateRecord, pdsDeleteRecord, pdsPutRecord, pdsApplyWrites, pdsUploadBlob, ProxyError, ScopeMissingProxyError, } from "./pds-proxy.js";
|
|
16
16
|
import { json, jsonError, cors, withCors, file, notFound } from "./response.js";
|
|
17
17
|
import { serve } from "./adapter.js";
|
|
18
18
|
import { renderPage } from "./renderer.js";
|
|
@@ -154,6 +154,11 @@ export function registerCoreHandlers(collections, oauth) {
|
|
|
154
154
|
throw new InvalidRequestError('Authentication required');
|
|
155
155
|
return pdsUploadBlob(oauth, viewer, input, 'application/octet-stream');
|
|
156
156
|
});
|
|
157
|
+
registerCoreXrpcHandler('dev.hatk.applyWrites', async (_params, _cursor, _limit, viewer, input) => {
|
|
158
|
+
if (!viewer)
|
|
159
|
+
throw new InvalidRequestError('Authentication required');
|
|
160
|
+
return pdsApplyWrites(oauth, viewer, input);
|
|
161
|
+
});
|
|
157
162
|
registerCoreXrpcHandler('dev.hatk.push.registerToken', async (_params, _cursor, _limit, viewer, input) => {
|
|
158
163
|
if (!viewer)
|
|
159
164
|
throw new InvalidRequestError('Authentication required');
|
package/dist/xrpc.d.ts
CHANGED
|
@@ -61,6 +61,18 @@ export interface XrpcContext<P = Record<string, string>, Records extends Record<
|
|
|
61
61
|
cid?: string;
|
|
62
62
|
}>;
|
|
63
63
|
deleteRecord: (collection: string, rkey: string) => Promise<void>;
|
|
64
|
+
applyWrites: (writes: Array<{
|
|
65
|
+
$type: string;
|
|
66
|
+
collection: string;
|
|
67
|
+
rkey?: string;
|
|
68
|
+
value?: Record<string, unknown>;
|
|
69
|
+
}>) => Promise<{
|
|
70
|
+
results?: Array<{
|
|
71
|
+
$type: string;
|
|
72
|
+
uri?: string;
|
|
73
|
+
cid?: string;
|
|
74
|
+
}>;
|
|
75
|
+
}>;
|
|
64
76
|
}
|
|
65
77
|
/** Set the relay URL used for blob URL generation. Called once during boot. */
|
|
66
78
|
export declare function configureRelay(relay: string): void;
|
package/dist/xrpc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xrpc.d.ts","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"xrpc.d.ts","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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"}
|
package/dist/xrpc.js
CHANGED
|
@@ -32,7 +32,7 @@ import { log, emit, timer } from "./logger.js";
|
|
|
32
32
|
import { querySQL, runSQL, packCursor, unpackCursor, isTakendownDid, filterTakendownDids, searchRecords, findUriByFields, } from "./database/db.js";
|
|
33
33
|
import { resolveRecords, buildBaseContext } from "./hydrate.js";
|
|
34
34
|
import { getLexicon } from "./database/schema.js";
|
|
35
|
-
import { pdsCreateRecord, pdsPutRecord, pdsDeleteRecord } from "./pds-proxy.js";
|
|
35
|
+
import { pdsCreateRecord, pdsPutRecord, pdsDeleteRecord, pdsApplyWrites } from "./pds-proxy.js";
|
|
36
36
|
let _oauthConfig = null;
|
|
37
37
|
/** Set the OAuth config used for record write helpers. Called once during boot. */
|
|
38
38
|
export function configureOAuth(config) {
|
|
@@ -116,6 +116,13 @@ export function buildXrpcContext(params, cursor, limit, viewer, input) {
|
|
|
116
116
|
throw new Error('Authentication required to write records');
|
|
117
117
|
await pdsDeleteRecord(_oauthConfig, viewer, { collection, rkey });
|
|
118
118
|
},
|
|
119
|
+
applyWrites: async (writes) => {
|
|
120
|
+
if (!_oauthConfig)
|
|
121
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
122
|
+
if (!viewer)
|
|
123
|
+
throw new Error('Authentication required to write records');
|
|
124
|
+
return pdsApplyWrites(_oauthConfig, viewer, { writes });
|
|
125
|
+
},
|
|
119
126
|
};
|
|
120
127
|
}
|
|
121
128
|
const handlers = new Map();
|