@hatk/hatk 0.0.1-alpha.40 → 0.0.1-alpha.41
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/dev-entry.d.ts.map +1 -1
- package/dist/dev-entry.js +2 -1
- package/dist/hooks.d.ts +24 -3
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +34 -7
- package/dist/indexer.d.ts +2 -0
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +17 -0
- package/dist/main.js +2 -1
- package/dist/oauth/server.js +1 -1
- package/dist/xrpc.d.ts +14 -0
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +27 -0
- package/package.json +1 -1
package/dist/dev-entry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-entry.d.ts","sourceRoot":"","sources":["../src/dev-entry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dev-entry.d.ts","sourceRoot":"","sources":["../src/dev-entry.ts"],"names":[],"mappings":"AA4GA,eAAO,MAAM,OAAO,yCAKlB,CAAA;AAEF,yEAAyE;AACzE,wBAAsB,YAAY,kBAEjC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/dev-entry.js
CHANGED
|
@@ -9,7 +9,7 @@ import { initDatabase, migrateSchema, getSchemaDump } from "./database/db.js";
|
|
|
9
9
|
import { createAdapter } from "./database/adapter-factory.js";
|
|
10
10
|
import { getDialect } from "./database/dialect.js";
|
|
11
11
|
import { setSearchPort } from "./database/fts.js";
|
|
12
|
-
import { configureRelay } from "./xrpc.js";
|
|
12
|
+
import { configureRelay, configureOAuth } from "./xrpc.js";
|
|
13
13
|
import { initOAuth } from "./oauth/server.js";
|
|
14
14
|
import { initServer } from "./server-init.js";
|
|
15
15
|
import { createHandler, registerCoreHandlers } from "./server.js";
|
|
@@ -63,6 +63,7 @@ catch { }
|
|
|
63
63
|
await initServer(resolve(configDir, 'server'));
|
|
64
64
|
// Register built-in dev.hatk.* handlers so callXrpc() can find them
|
|
65
65
|
registerCoreHandlers(collections, config.oauth);
|
|
66
|
+
configureOAuth(config.oauth);
|
|
66
67
|
if (config.oauth) {
|
|
67
68
|
await initOAuth(config.oauth, config.plc, config.relay);
|
|
68
69
|
}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
|
+
import type { OAuthConfig } from './config.ts';
|
|
2
|
+
import { type BaseContext } from './hydrate.ts';
|
|
1
3
|
/** Context passed to the on-login hook after a successful OAuth login. */
|
|
2
|
-
export type OnLoginCtx = {
|
|
4
|
+
export type OnLoginCtx = Omit<BaseContext, 'db'> & {
|
|
3
5
|
/** DID of the user who just logged in. */
|
|
4
6
|
did: string;
|
|
5
|
-
/**
|
|
7
|
+
/** Database access with both read and write. */
|
|
8
|
+
db: {
|
|
9
|
+
query: (sql: string, params?: unknown[]) => Promise<unknown[]>;
|
|
10
|
+
run: (sql: string, params?: unknown[]) => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
/** Trigger a backfill for a DID and wait for it to complete. */
|
|
6
13
|
ensureRepo: (did: string) => Promise<void>;
|
|
14
|
+
/** Write a record to the user's PDS and index locally. */
|
|
15
|
+
createRecord: (collection: string, record: Record<string, unknown>, opts?: {
|
|
16
|
+
rkey?: string;
|
|
17
|
+
}) => Promise<{
|
|
18
|
+
uri?: string;
|
|
19
|
+
cid?: string;
|
|
20
|
+
}>;
|
|
21
|
+
/** Create or update a record on the user's PDS and index locally. */
|
|
22
|
+
putRecord: (collection: string, rkey: string, record: Record<string, unknown>) => Promise<{
|
|
23
|
+
uri?: string;
|
|
24
|
+
cid?: string;
|
|
25
|
+
}>;
|
|
26
|
+
/** Delete a record from the user's PDS and local index. */
|
|
27
|
+
deleteRecord: (collection: string, rkey: string) => Promise<void>;
|
|
7
28
|
};
|
|
8
29
|
export declare function defineHook(event: 'on-login', handler: (ctx: OnLoginCtx) => Promise<void>): {
|
|
9
30
|
__type: "hook";
|
|
@@ -18,5 +39,5 @@ export declare function loadOnLoginHook(hooksDir: string): Promise<void>;
|
|
|
18
39
|
/** Register a hook from a scanned server/ module. */
|
|
19
40
|
export declare function registerHook(event: string, handler: Function): void;
|
|
20
41
|
/** Fire the on-login hook if loaded. Errors are logged but never block login. */
|
|
21
|
-
export declare function fireOnLoginHook(did: string): Promise<void>;
|
|
42
|
+
export declare function fireOnLoginHook(did: string, oauthConfig: OAuthConfig | null): Promise<void>;
|
|
22
43
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAK9C,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAEjE,0EAA0E;AAC1E,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG;IACjD,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,gDAAgD;IAChD,EAAE,EAAE;QACF,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;QAC9D,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KACxD,CAAA;IACD,gEAAgE;IAChE,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C,0DAA0D;IAC1D,YAAY,EAAE,CACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KACrB,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5C,qEAAqE;IACrE,SAAS,EAAE,CACT,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5C,2DAA2D;IAC3D,YAAY,EAAE,CACZ,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC;;;mBAA5B,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC;EAExF;AAMD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQrE;AASD,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAKnE;AAED,iFAAiF;AACjF,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BjG"}
|
package/dist/hooks.js
CHANGED
|
@@ -29,9 +29,11 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
29
29
|
*/
|
|
30
30
|
import { existsSync } from 'node:fs';
|
|
31
31
|
import { resolve } from 'node:path';
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
32
|
+
import { pdsCreateRecord, pdsPutRecord, pdsDeleteRecord } from "./pds-proxy.js";
|
|
33
|
+
import { log, emit } from "./logger.js";
|
|
34
|
+
import { setRepoStatus, runSQL } from "./database/db.js";
|
|
35
|
+
import { triggerAutoBackfill, awaitBackfill } from "./indexer.js";
|
|
36
|
+
import { buildBaseContext } from "./hydrate.js";
|
|
35
37
|
export function defineHook(event, handler) {
|
|
36
38
|
return { __type: 'hook', event, handler };
|
|
37
39
|
}
|
|
@@ -50,10 +52,11 @@ export async function loadOnLoginHook(hooksDir) {
|
|
|
50
52
|
onLoginHook = mod.default;
|
|
51
53
|
log('[hooks] on-login hook loaded');
|
|
52
54
|
}
|
|
53
|
-
/** Mark a DID as pending
|
|
55
|
+
/** Mark a DID as pending, trigger auto-backfill, and wait for completion. */
|
|
54
56
|
async function ensureRepo(did) {
|
|
55
57
|
await setRepoStatus(did, 'pending');
|
|
56
58
|
triggerAutoBackfill(did);
|
|
59
|
+
await awaitBackfill(did);
|
|
57
60
|
}
|
|
58
61
|
/** Register a hook from a scanned server/ module. */
|
|
59
62
|
export function registerHook(event, handler) {
|
|
@@ -63,13 +66,37 @@ export function registerHook(event, handler) {
|
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
/** Fire the on-login hook if loaded. Errors are logged but never block login. */
|
|
66
|
-
export async function fireOnLoginHook(did) {
|
|
69
|
+
export async function fireOnLoginHook(did, oauthConfig) {
|
|
67
70
|
if (!onLoginHook)
|
|
68
71
|
return;
|
|
69
72
|
try {
|
|
70
|
-
|
|
73
|
+
const base = buildBaseContext({ did });
|
|
74
|
+
const viewer = { did };
|
|
75
|
+
const hookPromise = onLoginHook({
|
|
76
|
+
...base,
|
|
77
|
+
did,
|
|
78
|
+
db: { query: base.db.query, run: runSQL },
|
|
79
|
+
ensureRepo,
|
|
80
|
+
createRecord: async (collection, record, opts) => {
|
|
81
|
+
if (!oauthConfig)
|
|
82
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
83
|
+
return pdsCreateRecord(oauthConfig, viewer, { collection, record, rkey: opts?.rkey });
|
|
84
|
+
},
|
|
85
|
+
putRecord: async (collection, rkey, record) => {
|
|
86
|
+
if (!oauthConfig)
|
|
87
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
88
|
+
return pdsPutRecord(oauthConfig, viewer, { collection, rkey, record });
|
|
89
|
+
},
|
|
90
|
+
deleteRecord: async (collection, rkey) => {
|
|
91
|
+
if (!oauthConfig)
|
|
92
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
93
|
+
await pdsDeleteRecord(oauthConfig, viewer, { collection, rkey });
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('on-login hook timed out after 30s')), 30_000));
|
|
97
|
+
await Promise.race([hookPromise, timeout]);
|
|
71
98
|
}
|
|
72
99
|
catch (err) {
|
|
73
|
-
|
|
100
|
+
emit('hooks', 'on_login_error', { did, error: err.message });
|
|
74
101
|
}
|
|
75
102
|
}
|
package/dist/indexer.d.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* `maxConcurrentBackfills`. Failed backfills retry with exponential delay up
|
|
7
7
|
* to `maxRetries`.
|
|
8
8
|
*/
|
|
9
|
+
/** Wait for a DID's backfill to complete if one is in flight. */
|
|
10
|
+
export declare function awaitBackfill(did: string): Promise<void>;
|
|
9
11
|
export declare function triggerAutoBackfill(did: string, attempt?: number): Promise<void>;
|
|
10
12
|
/** Configuration for the firehose indexer. */
|
|
11
13
|
interface IndexerOpts {
|
package/dist/indexer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAwJA;;;;;;;GAOG;AACH,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxD;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EjF;AAED,8CAA8C;AAC9C,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAyBD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAmDxE"}
|
package/dist/indexer.js
CHANGED
|
@@ -18,6 +18,7 @@ let ftsRebuildInterval = 500;
|
|
|
18
18
|
const pendingBuffers = new Map();
|
|
19
19
|
// Track in-flight backfills to avoid duplicates
|
|
20
20
|
const backfillInFlight = new Set();
|
|
21
|
+
const backfillPromises = new Map();
|
|
21
22
|
const pendingReschedule = new Set();
|
|
22
23
|
// In-memory cache of repo status to avoid flooding the DB read queue
|
|
23
24
|
const repoStatusCache = new Map();
|
|
@@ -130,6 +131,11 @@ function bufferWrite(item) {
|
|
|
130
131
|
* `maxConcurrentBackfills`. Failed backfills retry with exponential delay up
|
|
131
132
|
* to `maxRetries`.
|
|
132
133
|
*/
|
|
134
|
+
/** Wait for a DID's backfill to complete if one is in flight. */
|
|
135
|
+
export function awaitBackfill(did) {
|
|
136
|
+
const entry = backfillPromises.get(did);
|
|
137
|
+
return entry ? entry.promise : Promise.resolve();
|
|
138
|
+
}
|
|
133
139
|
export async function triggerAutoBackfill(did, attempt = 0) {
|
|
134
140
|
if (backfillInFlight.has(did))
|
|
135
141
|
return;
|
|
@@ -145,6 +151,11 @@ export async function triggerAutoBackfill(did, attempt = 0) {
|
|
|
145
151
|
}
|
|
146
152
|
backfillInFlight.add(did);
|
|
147
153
|
pendingBuffers.set(did, []);
|
|
154
|
+
if (!backfillPromises.has(did)) {
|
|
155
|
+
let resolveBackfill;
|
|
156
|
+
const promise = new Promise((r) => { resolveBackfill = r; });
|
|
157
|
+
backfillPromises.set(did, { promise, resolve: resolveBackfill });
|
|
158
|
+
}
|
|
148
159
|
if (attempt === 0)
|
|
149
160
|
await setRepoStatus(did, 'pending');
|
|
150
161
|
const elapsed = timer();
|
|
@@ -184,6 +195,12 @@ export async function triggerAutoBackfill(did, attempt = 0) {
|
|
|
184
195
|
error,
|
|
185
196
|
retry_count: currentRetryCount,
|
|
186
197
|
});
|
|
198
|
+
// Resolve awaiting callers (e.g. on-login hooks)
|
|
199
|
+
const entry = backfillPromises.get(did);
|
|
200
|
+
if (entry) {
|
|
201
|
+
entry.resolve();
|
|
202
|
+
backfillPromises.delete(did);
|
|
203
|
+
}
|
|
187
204
|
if (status === 'error' && currentRetryCount < indexerMaxRetries) {
|
|
188
205
|
const delaySecs = Math.min(currentRetryCount * 60, 3600);
|
|
189
206
|
const delayMs = Math.max(delaySecs, 60) * 1000;
|
package/dist/main.js
CHANGED
|
@@ -19,7 +19,7 @@ import { createAdapter } from "./database/adapter-factory.js";
|
|
|
19
19
|
import { getDialect } from "./database/dialect.js";
|
|
20
20
|
import { setSearchPort } from "./database/fts.js";
|
|
21
21
|
import { initFeeds, listFeeds } from "./feeds.js";
|
|
22
|
-
import { initXrpc, listXrpc, configureRelay, callXrpc } from "./xrpc.js";
|
|
22
|
+
import { initXrpc, listXrpc, configureRelay, configureOAuth, callXrpc } from "./xrpc.js";
|
|
23
23
|
import { initOpengraph } from "./opengraph.js";
|
|
24
24
|
import { initLabels, getLabelDefinitions } from "./labels.js";
|
|
25
25
|
import { startIndexer } from "./indexer.js";
|
|
@@ -112,6 +112,7 @@ else {
|
|
|
112
112
|
}
|
|
113
113
|
// Register built-in dev.hatk.* handlers so callXrpc() can find them
|
|
114
114
|
registerCoreHandlers(collections, config.oauth);
|
|
115
|
+
configureOAuth(config.oauth);
|
|
115
116
|
// Write db/schema.sql (after setup, so setup-created tables are included)
|
|
116
117
|
try {
|
|
117
118
|
const schemaDir = resolve(configDir, 'db');
|
package/dist/oauth/server.js
CHANGED
|
@@ -432,7 +432,7 @@ export async function handleCallback(config, code, state, iss) {
|
|
|
432
432
|
dpopJkt: serverJkt,
|
|
433
433
|
tokenExpiresAt: tokenData.expires_in ? Math.floor(Date.now() / 1000) + tokenData.expires_in : undefined,
|
|
434
434
|
});
|
|
435
|
-
await fireOnLoginHook(did);
|
|
435
|
+
await fireOnLoginHook(did, config);
|
|
436
436
|
// Generate authorization code for the client
|
|
437
437
|
const clientCode = randomToken();
|
|
438
438
|
await storeAuthCode(clientCode, request.request_uri);
|
package/dist/xrpc.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { BaseContext } from './hydrate.ts';
|
|
2
2
|
import type { Row, FlatRow } from './lex-types.ts';
|
|
3
|
+
import type { OAuthConfig } from './config.ts';
|
|
3
4
|
export type { Row, FlatRow };
|
|
5
|
+
/** Set the OAuth config used for record write helpers. Called once during boot. */
|
|
6
|
+
export declare function configureOAuth(config: OAuthConfig | null): void;
|
|
4
7
|
/** Thrown from XRPC handlers to return a 400 response with an error message. */
|
|
5
8
|
export declare class InvalidRequestError extends Error {
|
|
6
9
|
status: number;
|
|
@@ -47,6 +50,17 @@ export interface XrpcContext<P = Record<string, string>, Records extends Record<
|
|
|
47
50
|
}>;
|
|
48
51
|
resolve: <R = unknown>(uris: string[]) => Promise<Row<R>[]>;
|
|
49
52
|
exists: (collection: string, filters: Record<string, string>) => Promise<boolean>;
|
|
53
|
+
createRecord: (collection: string, record: Record<string, unknown>, opts?: {
|
|
54
|
+
rkey?: string;
|
|
55
|
+
}) => Promise<{
|
|
56
|
+
uri?: string;
|
|
57
|
+
cid?: string;
|
|
58
|
+
}>;
|
|
59
|
+
putRecord: (collection: string, rkey: string, record: Record<string, unknown>) => Promise<{
|
|
60
|
+
uri?: string;
|
|
61
|
+
cid?: string;
|
|
62
|
+
}>;
|
|
63
|
+
deleteRecord: (collection: string, rkey: string) => Promise<void>;
|
|
50
64
|
}
|
|
51
65
|
/** Set the relay URL used for blob URL generation. Called once during boot. */
|
|
52
66
|
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":"AAsCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"xrpc.d.ts","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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"}
|
package/dist/xrpc.js
CHANGED
|
@@ -32,6 +32,12 @@ 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";
|
|
36
|
+
let _oauthConfig = null;
|
|
37
|
+
/** Set the OAuth config used for record write helpers. Called once during boot. */
|
|
38
|
+
export function configureOAuth(config) {
|
|
39
|
+
_oauthConfig = config;
|
|
40
|
+
}
|
|
35
41
|
/** Thrown from XRPC handlers to return a 400 response with an error message. */
|
|
36
42
|
export class InvalidRequestError extends Error {
|
|
37
43
|
status = 400;
|
|
@@ -89,6 +95,27 @@ export function buildXrpcContext(params, cursor, limit, viewer, input) {
|
|
|
89
95
|
const uri = await findUriByFields(collection, conditions);
|
|
90
96
|
return uri !== null;
|
|
91
97
|
},
|
|
98
|
+
createRecord: async (collection, record, opts) => {
|
|
99
|
+
if (!_oauthConfig)
|
|
100
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
101
|
+
if (!viewer)
|
|
102
|
+
throw new Error('Authentication required to write records');
|
|
103
|
+
return pdsCreateRecord(_oauthConfig, viewer, { collection, record, rkey: opts?.rkey });
|
|
104
|
+
},
|
|
105
|
+
putRecord: async (collection, rkey, record) => {
|
|
106
|
+
if (!_oauthConfig)
|
|
107
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
108
|
+
if (!viewer)
|
|
109
|
+
throw new Error('Authentication required to write records');
|
|
110
|
+
return pdsPutRecord(_oauthConfig, viewer, { collection, rkey, record });
|
|
111
|
+
},
|
|
112
|
+
deleteRecord: async (collection, rkey) => {
|
|
113
|
+
if (!_oauthConfig)
|
|
114
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
115
|
+
if (!viewer)
|
|
116
|
+
throw new Error('Authentication required to write records');
|
|
117
|
+
await pdsDeleteRecord(_oauthConfig, viewer, { collection, rkey });
|
|
118
|
+
},
|
|
92
119
|
};
|
|
93
120
|
}
|
|
94
121
|
const handlers = new Map();
|