@hatk/hatk 0.0.1-alpha.7 → 0.0.1-alpha.70
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/adapter.d.ts +19 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +108 -0
- package/dist/backfill.d.ts +21 -2
- package/dist/backfill.d.ts.map +1 -1
- package/dist/backfill.js +116 -43
- package/dist/car.d.ts +42 -10
- package/dist/car.d.ts.map +1 -1
- package/dist/car.js +154 -14
- package/dist/cli.js +243 -1043
- package/dist/config.d.ts +32 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -9
- package/dist/database/adapter-factory.d.ts +6 -0
- package/dist/database/adapter-factory.d.ts.map +1 -0
- package/dist/database/adapter-factory.js +20 -0
- package/dist/database/adapters/duckdb-search.d.ts +12 -0
- package/dist/database/adapters/duckdb-search.d.ts.map +1 -0
- package/dist/database/adapters/duckdb-search.js +27 -0
- package/dist/database/adapters/duckdb.d.ts +25 -0
- package/dist/database/adapters/duckdb.d.ts.map +1 -0
- package/dist/database/adapters/duckdb.js +161 -0
- package/dist/database/adapters/sqlite-search.d.ts +23 -0
- package/dist/database/adapters/sqlite-search.d.ts.map +1 -0
- package/dist/database/adapters/sqlite-search.js +74 -0
- package/dist/database/adapters/sqlite.d.ts +18 -0
- package/dist/database/adapters/sqlite.d.ts.map +1 -0
- package/dist/database/adapters/sqlite.js +88 -0
- package/dist/{db.d.ts → database/db.d.ts} +57 -6
- package/dist/database/db.d.ts.map +1 -0
- package/dist/{db.js → database/db.js} +755 -552
- package/dist/database/dialect.d.ts +45 -0
- package/dist/database/dialect.d.ts.map +1 -0
- package/dist/database/dialect.js +72 -0
- package/dist/{fts.d.ts → database/fts.d.ts} +7 -0
- package/dist/database/fts.d.ts.map +1 -0
- package/dist/{fts.js → database/fts.js} +116 -32
- package/dist/database/index.d.ts +7 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +6 -0
- package/dist/database/ports.d.ts +50 -0
- package/dist/database/ports.d.ts.map +1 -0
- package/dist/database/ports.js +1 -0
- package/dist/{schema.d.ts → database/schema.d.ts} +14 -3
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/{schema.js → database/schema.js} +81 -41
- package/dist/dev-entry.d.ts +8 -0
- package/dist/dev-entry.d.ts.map +1 -0
- package/dist/dev-entry.js +119 -0
- package/dist/feeds.d.ts +12 -8
- package/dist/feeds.d.ts.map +1 -1
- package/dist/feeds.js +51 -6
- package/dist/hooks.d.ts +85 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +163 -0
- package/dist/hydrate.d.ts +7 -6
- package/dist/hydrate.d.ts.map +1 -1
- package/dist/hydrate.js +4 -16
- package/dist/indexer.d.ts +43 -0
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +246 -38
- package/dist/labels.d.ts +36 -0
- package/dist/labels.d.ts.map +1 -1
- package/dist/labels.js +71 -6
- package/dist/lexicon-resolve.d.ts.map +1 -1
- package/dist/lexicon-resolve.js +27 -112
- package/dist/lexicons/com/atproto/label/defs.json +75 -0
- package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
- package/dist/lexicons/com/atproto/repo/strongRef.json +21 -0
- package/dist/lexicons/dev/hatk/applyWrites.json +87 -0
- package/dist/lexicons/dev/hatk/createRecord.json +40 -0
- package/dist/lexicons/dev/hatk/createReport.json +48 -0
- package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
- package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
- package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
- package/dist/lexicons/dev/hatk/describeLabels.json +45 -0
- package/dist/lexicons/dev/hatk/getFeed.json +30 -0
- package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
- package/dist/lexicons/dev/hatk/getRecord.json +26 -0
- package/dist/lexicons/dev/hatk/getRecords.json +32 -0
- package/dist/lexicons/dev/hatk/putPreference.json +28 -0
- package/dist/lexicons/dev/hatk/putRecord.json +41 -0
- package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
- package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
- package/dist/logger.d.ts +29 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +29 -0
- package/dist/main.js +148 -68
- package/dist/mst.d.ts +18 -1
- package/dist/mst.d.ts.map +1 -1
- package/dist/mst.js +19 -8
- package/dist/oauth/db.d.ts +3 -1
- package/dist/oauth/db.d.ts.map +1 -1
- package/dist/oauth/db.js +56 -19
- package/dist/oauth/discovery.d.ts.map +1 -1
- package/dist/oauth/discovery.js +13 -1
- package/dist/oauth/server.d.ts +38 -0
- package/dist/oauth/server.d.ts.map +1 -1
- package/dist/oauth/server.js +228 -31
- package/dist/oauth/session.d.ts +11 -0
- package/dist/oauth/session.d.ts.map +1 -0
- package/dist/oauth/session.js +65 -0
- package/dist/opengraph.d.ts +10 -0
- package/dist/opengraph.d.ts.map +1 -1
- package/dist/opengraph.js +80 -40
- package/dist/pds-proxy.d.ts +60 -0
- package/dist/pds-proxy.d.ts.map +1 -0
- package/dist/pds-proxy.js +277 -0
- package/dist/private-collections.d.ts +8 -0
- package/dist/private-collections.d.ts.map +1 -0
- package/dist/private-collections.js +22 -0
- package/dist/push.d.ts +34 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +186 -0
- package/dist/renderer.d.ts +27 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +46 -0
- package/dist/resolve-hatk.d.ts +6 -0
- package/dist/resolve-hatk.d.ts.map +1 -0
- package/dist/resolve-hatk.js +20 -0
- package/dist/response.d.ts +16 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +69 -0
- package/dist/scanner.d.ts +21 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +88 -0
- package/dist/seed.d.ts +19 -0
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +43 -4
- package/dist/server-init.d.ts +8 -0
- package/dist/server-init.d.ts.map +1 -0
- package/dist/server-init.js +62 -0
- package/dist/server.d.ts +26 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +729 -638
- package/dist/setup.d.ts +28 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +50 -3
- package/dist/templates/feed.tpl +14 -0
- package/dist/templates/hook.tpl +5 -0
- package/dist/templates/label.tpl +15 -0
- package/dist/templates/og.tpl +17 -0
- package/dist/templates/seed.tpl +11 -0
- package/dist/templates/setup.tpl +5 -0
- package/dist/templates/test-feed.tpl +19 -0
- package/dist/templates/test-xrpc.tpl +19 -0
- package/dist/templates/xrpc.tpl +41 -0
- package/dist/test.d.ts +1 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +41 -32
- package/dist/views.js +1 -1
- package/dist/vite-plugin.d.ts +1 -1
- package/dist/vite-plugin.d.ts.map +1 -1
- package/dist/vite-plugin.js +254 -66
- package/dist/xrpc.d.ts +75 -11
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +189 -39
- package/package.json +17 -9
- package/public/admin-auth.js +271 -306
- package/public/admin.html +177 -61
- package/dist/db.d.ts.map +0 -1
- package/dist/fts.d.ts.map +0 -1
- package/dist/oauth/hooks.d.ts +0 -10
- package/dist/oauth/hooks.d.ts.map +0 -1
- package/dist/oauth/hooks.js +0 -40
- package/dist/schema.d.ts.map +0 -1
- package/dist/test-browser.d.ts +0 -14
- package/dist/test-browser.d.ts.map +0 -1
- package/dist/test-browser.js +0 -26
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Lifecycle hooks that run in response to server events.
|
|
11
|
+
*
|
|
12
|
+
* Place hook modules in the `hooks/` directory. Currently supported hooks:
|
|
13
|
+
*
|
|
14
|
+
* - `on-login.ts` — called after each successful OAuth login
|
|
15
|
+
* - `on-commit-*.ts` — called after records are indexed from the firehose
|
|
16
|
+
*
|
|
17
|
+
* Each hook default-exports the result of `defineHook()`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* // hooks/on-login.ts
|
|
22
|
+
* import { defineHook } from '$hatk'
|
|
23
|
+
*
|
|
24
|
+
* export default defineHook("on-login", async (ctx) => {
|
|
25
|
+
* await ctx.ensureRepo(ctx.did)
|
|
26
|
+
* })
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* // hooks/on-commit-favorite.ts
|
|
32
|
+
* import { defineHook } from '$hatk'
|
|
33
|
+
*
|
|
34
|
+
* export default defineHook("on-commit", { collections: ["social.grain.favorite"] },
|
|
35
|
+
* async ({ action, collection, record, repo, uri, db, lookup, push }) => {
|
|
36
|
+
* if (action !== "create") return
|
|
37
|
+
* // send push notification, etc.
|
|
38
|
+
* }
|
|
39
|
+
* )
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
import { existsSync } from 'node:fs';
|
|
43
|
+
import { resolve } from 'node:path';
|
|
44
|
+
import { pdsCreateRecord, pdsPutRecord, pdsDeleteRecord } from "./pds-proxy.js";
|
|
45
|
+
import { log, emit } from "./logger.js";
|
|
46
|
+
import { setRepoStatus, runSQL } from "./database/db.js";
|
|
47
|
+
import { triggerAutoBackfill, awaitBackfill } from "./indexer.js";
|
|
48
|
+
import { buildBaseContext } from "./hydrate.js";
|
|
49
|
+
import { buildPushInterface, isPushEnabled } from "./push.js";
|
|
50
|
+
export function defineHook(event, ...args) {
|
|
51
|
+
if (event === 'on-login') {
|
|
52
|
+
return { __type: 'hook', event, handler: args[0] };
|
|
53
|
+
}
|
|
54
|
+
if (event === 'on-commit') {
|
|
55
|
+
const options = args[0];
|
|
56
|
+
const handler = args[1];
|
|
57
|
+
return { __type: 'hook', event, collections: options.collections, handler };
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Unknown hook event: ${event}`);
|
|
60
|
+
}
|
|
61
|
+
let onLoginHook = null;
|
|
62
|
+
const onCommitHooks = [];
|
|
63
|
+
/**
|
|
64
|
+
* Discover and load the on-login hook from the project's `hooks/` directory.
|
|
65
|
+
* Looks for `on-login.ts` or `on-login.js`. Safe to call if no hook exists.
|
|
66
|
+
*/
|
|
67
|
+
export async function loadOnLoginHook(hooksDir) {
|
|
68
|
+
const tsPath = resolve(hooksDir, 'on-login.ts');
|
|
69
|
+
const jsPath = resolve(hooksDir, 'on-login.js');
|
|
70
|
+
const path = existsSync(tsPath) ? tsPath : existsSync(jsPath) ? jsPath : null;
|
|
71
|
+
if (!path)
|
|
72
|
+
return;
|
|
73
|
+
const mod = await import(__rewriteRelativeImportExtension(/* @vite-ignore */ `${path}?t=${Date.now()}`));
|
|
74
|
+
onLoginHook = mod.default;
|
|
75
|
+
log('[hooks] on-login hook loaded');
|
|
76
|
+
}
|
|
77
|
+
/** Mark a DID as pending, trigger auto-backfill, and wait for completion. */
|
|
78
|
+
async function ensureRepo(did) {
|
|
79
|
+
await setRepoStatus(did, 'pending');
|
|
80
|
+
triggerAutoBackfill(did);
|
|
81
|
+
await awaitBackfill(did);
|
|
82
|
+
}
|
|
83
|
+
/** Register a hook from a scanned server/ module. */
|
|
84
|
+
export function registerHook(event, handler, options) {
|
|
85
|
+
if (event === 'on-login') {
|
|
86
|
+
onLoginHook = handler;
|
|
87
|
+
log('[hooks] on-login hook registered');
|
|
88
|
+
}
|
|
89
|
+
else if (event === 'on-commit') {
|
|
90
|
+
const collections = new Set(options?.collections || []);
|
|
91
|
+
onCommitHooks.push({ collections, handler: handler });
|
|
92
|
+
log(`[hooks] on-commit hook registered (collections: ${[...collections].join(', ')})`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Fire the on-login hook if loaded. Errors are logged but never block login. */
|
|
96
|
+
export async function fireOnLoginHook(did, oauthConfig) {
|
|
97
|
+
if (!onLoginHook)
|
|
98
|
+
return;
|
|
99
|
+
try {
|
|
100
|
+
const base = buildBaseContext({ did });
|
|
101
|
+
const viewer = { did };
|
|
102
|
+
const hookPromise = onLoginHook({
|
|
103
|
+
...base,
|
|
104
|
+
did,
|
|
105
|
+
db: { query: base.db.query, run: runSQL },
|
|
106
|
+
ensureRepo,
|
|
107
|
+
createRecord: async (collection, record, opts) => {
|
|
108
|
+
if (!oauthConfig)
|
|
109
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
110
|
+
return pdsCreateRecord(oauthConfig, viewer, { collection, record, rkey: opts?.rkey });
|
|
111
|
+
},
|
|
112
|
+
putRecord: async (collection, rkey, record) => {
|
|
113
|
+
if (!oauthConfig)
|
|
114
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
115
|
+
return pdsPutRecord(oauthConfig, viewer, { collection, rkey, record });
|
|
116
|
+
},
|
|
117
|
+
deleteRecord: async (collection, rkey) => {
|
|
118
|
+
if (!oauthConfig)
|
|
119
|
+
throw new Error('No OAuth config — cannot write to PDS');
|
|
120
|
+
await pdsDeleteRecord(oauthConfig, viewer, { collection, rkey });
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('on-login hook timed out after 30s')), 30_000));
|
|
124
|
+
await Promise.race([hookPromise, timeout]);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
emit('hooks', 'on_login_error', { did, error: err.message });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Fire on-commit hooks for a batch of indexed records.
|
|
132
|
+
* Runs async and non-blocking — errors are logged but never throw.
|
|
133
|
+
*/
|
|
134
|
+
export function fireOnCommitHooks(items) {
|
|
135
|
+
if (onCommitHooks.length === 0)
|
|
136
|
+
return;
|
|
137
|
+
const base = buildBaseContext(null);
|
|
138
|
+
const push = isPushEnabled() ? buildPushInterface() : { send: async () => { } };
|
|
139
|
+
for (const item of items) {
|
|
140
|
+
for (const hook of onCommitHooks) {
|
|
141
|
+
if (hook.collections.size > 0 && !hook.collections.has(item.collection))
|
|
142
|
+
continue;
|
|
143
|
+
hook
|
|
144
|
+
.handler({
|
|
145
|
+
action: item.action,
|
|
146
|
+
collection: item.collection,
|
|
147
|
+
record: item.record,
|
|
148
|
+
repo: item.authorDid,
|
|
149
|
+
uri: item.uri,
|
|
150
|
+
db: { query: base.db.query, run: runSQL },
|
|
151
|
+
lookup: base.lookup,
|
|
152
|
+
push,
|
|
153
|
+
})
|
|
154
|
+
.catch((err) => {
|
|
155
|
+
emit('hooks', 'on_commit_error', {
|
|
156
|
+
collection: item.collection,
|
|
157
|
+
uri: item.uri,
|
|
158
|
+
error: err.message,
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
package/dist/hydrate.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Row } from './lex-types.ts';
|
|
2
2
|
export type { Row };
|
|
3
|
-
export interface
|
|
4
|
-
items: Row<T>[];
|
|
3
|
+
export interface BaseContext {
|
|
5
4
|
viewer: {
|
|
6
5
|
did: string;
|
|
6
|
+
handle?: string;
|
|
7
7
|
} | null;
|
|
8
8
|
db: {
|
|
9
9
|
query: (sql: string, params?: unknown[]) => Promise<unknown[]>;
|
|
@@ -12,12 +12,13 @@ export interface HydrateContext<T = unknown> {
|
|
|
12
12
|
lookup: <R = unknown>(collection: string, field: string, values: string[]) => Promise<Map<string, Row<R>>>;
|
|
13
13
|
count: (collection: string, field: string, values: string[]) => Promise<Map<string, number>>;
|
|
14
14
|
labels: (uris: string[]) => Promise<Map<string, unknown[]>>;
|
|
15
|
-
blobUrl: (did: string, ref: unknown, preset?:
|
|
15
|
+
blobUrl: (did: string, ref: unknown, preset?: string) => string | undefined;
|
|
16
16
|
}
|
|
17
17
|
/** Fetch records for URIs, reshape them, and filter out taken-down DIDs. */
|
|
18
18
|
export declare function resolveRecords(uris: string[]): Promise<Row<unknown>[]>;
|
|
19
|
-
/** Build a
|
|
20
|
-
export declare function
|
|
19
|
+
/** Build a BaseContext for hydration. */
|
|
20
|
+
export declare function buildBaseContext(viewer: {
|
|
21
21
|
did: string;
|
|
22
|
-
|
|
22
|
+
handle?: string;
|
|
23
|
+
} | null): BaseContext;
|
|
23
24
|
//# sourceMappingURL=hydrate.d.ts.map
|
package/dist/hydrate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../src/hydrate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../src/hydrate.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AAEzC,YAAY,EAAE,GAAG,EAAE,CAAA;AAInB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC/C,EAAE,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;KAAE,CAAA;IACtE,UAAU,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7F,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1G,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;IAC3D,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;CAC5E;AAID,4EAA4E;AAC5E,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAoC5E;AAID,yCAAyC;AACzC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,WAAW,CAkB7F"}
|
package/dist/hydrate.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getRecordsMap, countByFieldBatch, lookupByFieldBatch, querySQL, queryLabelsForUris, filterTakendownDids, getRecordsByUris, reshapeRow, } from "./database/db.js";
|
|
2
2
|
import { blobUrl } from "./xrpc.js";
|
|
3
3
|
// --- Record Resolution ---
|
|
4
4
|
/** Fetch records for URIs, reshape them, and filter out taken-down DIDs. */
|
|
@@ -39,24 +39,12 @@ export async function resolveRecords(uris) {
|
|
|
39
39
|
.filter((r) => r != null);
|
|
40
40
|
}
|
|
41
41
|
// --- Context Builder ---
|
|
42
|
-
/** Build a
|
|
43
|
-
export function
|
|
42
|
+
/** Build a BaseContext for hydration. */
|
|
43
|
+
export function buildBaseContext(viewer) {
|
|
44
44
|
return {
|
|
45
|
-
items,
|
|
46
45
|
viewer,
|
|
47
46
|
db: { query: querySQL },
|
|
48
|
-
getRecords:
|
|
49
|
-
if (uris.length === 0)
|
|
50
|
-
return new Map();
|
|
51
|
-
const records = await getRecordsByUris(collection, uris);
|
|
52
|
-
const map = new Map();
|
|
53
|
-
for (const r of records) {
|
|
54
|
-
const shaped = reshapeRow(r, r?.__childData, r?.__unionData);
|
|
55
|
-
if (shaped)
|
|
56
|
-
map.set(shaped.uri, shaped);
|
|
57
|
-
}
|
|
58
|
-
return map;
|
|
59
|
-
},
|
|
47
|
+
getRecords: getRecordsMap,
|
|
60
48
|
lookup: async (collection, field, values) => {
|
|
61
49
|
if (values.length === 0)
|
|
62
50
|
return new Map();
|
package/dist/indexer.d.ts
CHANGED
|
@@ -1,14 +1,57 @@
|
|
|
1
|
+
/** Record the latest firehose sequence seen. Source of truth for cursor persistence and reconnect resume. */
|
|
2
|
+
export declare function noteSeq(seq: number): void;
|
|
3
|
+
/**
|
|
4
|
+
* Persist the latest firehose sequence when it has advanced past the stored
|
|
5
|
+
* cursor. Runs on a timer independent of the write path: an app whose
|
|
6
|
+
* collections rarely appear on the firehose never flushes a batch, so the
|
|
7
|
+
* flush-path cursor write alone leaves the stored cursor frozen — and a frozen
|
|
8
|
+
* cursor makes the relay replay its whole retention window at line rate
|
|
9
|
+
* (~135 GB/hour observed against bsky.network) on every boot and reconnect.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkpointCursor(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* The cursor a reconnect should resume from: the latest seq this process has
|
|
14
|
+
* seen, falling back to the boot-time cursor before any message has arrived.
|
|
15
|
+
* Reusing the boot-time cursor on every reconnect would replay everything
|
|
16
|
+
* received since the process started.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resumeCursor(liveSeq: number | null, bootCursor: string | null | undefined): string | null | undefined;
|
|
19
|
+
/** Reset module cursor state between tests. */
|
|
20
|
+
export declare function _resetCursorStateForTests(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Auto-backfill a DID's repo when first seen on the firehose.
|
|
23
|
+
*
|
|
24
|
+
* Fetches the full repo via CAR export, inserts all records, then replays any
|
|
25
|
+
* firehose events that arrived during the backfill. Concurrency is capped at
|
|
26
|
+
* `maxConcurrentBackfills`. Failed backfills retry with exponential delay up
|
|
27
|
+
* to `maxRetries`.
|
|
28
|
+
*/
|
|
29
|
+
/** Wait for a DID's backfill to complete if one is in flight. */
|
|
30
|
+
export declare function awaitBackfill(did: string): Promise<void>;
|
|
1
31
|
export declare function triggerAutoBackfill(did: string, attempt?: number): Promise<void>;
|
|
32
|
+
/** Configuration for the firehose indexer. */
|
|
2
33
|
interface IndexerOpts {
|
|
3
34
|
relayUrl: string;
|
|
35
|
+
plcUrl: string;
|
|
4
36
|
collections: Set<string>;
|
|
5
37
|
signalCollections?: Set<string>;
|
|
6
38
|
pinnedRepos?: Set<string>;
|
|
7
39
|
cursor?: string | null;
|
|
8
40
|
fetchTimeout: number;
|
|
9
41
|
maxRetries: number;
|
|
42
|
+
parallelism?: number;
|
|
10
43
|
ftsRebuildInterval?: number;
|
|
11
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Connect to the AT Protocol relay firehose and begin indexing.
|
|
47
|
+
*
|
|
48
|
+
* Opens a WebSocket to `subscribeRepos`, processes commit messages synchronously
|
|
49
|
+
* on the event loop to minimize backpressure, and batches writes through
|
|
50
|
+
* {@link flushBuffer}. New DIDs trigger auto-backfill via {@link triggerAutoBackfill}.
|
|
51
|
+
* Reconnects automatically on disconnect after a 3s delay.
|
|
52
|
+
*
|
|
53
|
+
* @returns The WebSocket connection (for shutdown coordination)
|
|
54
|
+
*/
|
|
12
55
|
export declare function startIndexer(opts: IndexerOpts): Promise<WebSocket>;
|
|
13
56
|
export {};
|
|
14
57
|
//# sourceMappingURL=indexer.d.ts.map
|
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":"AA4KA,6GAA6G;AAC7G,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAStD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC,MAAM,GAAG,IAAI,GAAG,SAAS,CAE3B;AAED,+CAA+C;AAC/C,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AAED;;;;;;;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,CA8EjF;AAED,8CAA8C;AAC9C,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,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,CA4DxE"}
|