@hatk/hatk 0.0.1-alpha.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/dist/backfill.d.ts +11 -0
- package/dist/backfill.d.ts.map +1 -0
- package/dist/backfill.js +328 -0
- package/dist/car.d.ts +5 -0
- package/dist/car.d.ts.map +1 -0
- package/dist/car.js +52 -0
- package/dist/cbor.d.ts +7 -0
- package/dist/cbor.d.ts.map +1 -0
- package/dist/cbor.js +89 -0
- package/dist/cid.d.ts +4 -0
- package/dist/cid.d.ts.map +1 -0
- package/dist/cid.js +39 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1663 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +43 -0
- package/dist/db.d.ts +134 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +1361 -0
- package/dist/feeds.d.ts +95 -0
- package/dist/feeds.d.ts.map +1 -0
- package/dist/feeds.js +144 -0
- package/dist/fts.d.ts +20 -0
- package/dist/fts.d.ts.map +1 -0
- package/dist/fts.js +762 -0
- package/dist/hydrate.d.ts +23 -0
- package/dist/hydrate.d.ts.map +1 -0
- package/dist/hydrate.js +75 -0
- package/dist/indexer.d.ts +14 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +316 -0
- package/dist/labels.d.ts +29 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +111 -0
- package/dist/lex-types.d.ts +401 -0
- package/dist/lex-types.d.ts.map +1 -0
- package/dist/lex-types.js +4 -0
- package/dist/lexicon-resolve.d.ts +14 -0
- package/dist/lexicon-resolve.d.ts.map +1 -0
- package/dist/lexicon-resolve.js +280 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +23 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +148 -0
- package/dist/mst.d.ts +6 -0
- package/dist/mst.d.ts.map +1 -0
- package/dist/mst.js +30 -0
- package/dist/oauth/client.d.ts +16 -0
- package/dist/oauth/client.d.ts.map +1 -0
- package/dist/oauth/client.js +54 -0
- package/dist/oauth/crypto.d.ts +28 -0
- package/dist/oauth/crypto.d.ts.map +1 -0
- package/dist/oauth/crypto.js +101 -0
- package/dist/oauth/db.d.ts +47 -0
- package/dist/oauth/db.d.ts.map +1 -0
- package/dist/oauth/db.js +139 -0
- package/dist/oauth/discovery.d.ts +22 -0
- package/dist/oauth/discovery.d.ts.map +1 -0
- package/dist/oauth/discovery.js +50 -0
- package/dist/oauth/dpop.d.ts +11 -0
- package/dist/oauth/dpop.d.ts.map +1 -0
- package/dist/oauth/dpop.js +56 -0
- package/dist/oauth/hooks.d.ts +10 -0
- package/dist/oauth/hooks.d.ts.map +1 -0
- package/dist/oauth/hooks.js +40 -0
- package/dist/oauth/server.d.ts +86 -0
- package/dist/oauth/server.d.ts.map +1 -0
- package/dist/oauth/server.js +572 -0
- package/dist/opengraph.d.ts +34 -0
- package/dist/opengraph.d.ts.map +1 -0
- package/dist/opengraph.js +198 -0
- package/dist/schema.d.ts +51 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +358 -0
- package/dist/seed.d.ts +29 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +86 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1024 -0
- package/dist/setup.d.ts +8 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +48 -0
- package/dist/test-browser.d.ts +14 -0
- package/dist/test-browser.d.ts.map +1 -0
- package/dist/test-browser.js +26 -0
- package/dist/test.d.ts +47 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +256 -0
- package/dist/views.d.ts +40 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/views.js +178 -0
- package/dist/vite-plugin.d.ts +5 -0
- package/dist/vite-plugin.d.ts.map +1 -0
- package/dist/vite-plugin.js +86 -0
- package/dist/xrpc-client.d.ts +18 -0
- package/dist/xrpc-client.d.ts.map +1 -0
- package/dist/xrpc-client.js +54 -0
- package/dist/xrpc.d.ts +53 -0
- package/dist/xrpc.d.ts.map +1 -0
- package/dist/xrpc.js +139 -0
- package/fonts/Inter-Regular.woff +0 -0
- package/package.json +41 -0
- package/public/admin-auth.js +320 -0
- package/public/admin.html +2166 -0
package/dist/feeds.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { HydrateContext, Row } from './hydrate.ts';
|
|
2
|
+
import type { Checked } from './lex-types.ts';
|
|
3
|
+
export type { HydrateContext, Row };
|
|
4
|
+
export interface FeedResult {
|
|
5
|
+
uris: string[];
|
|
6
|
+
cursor?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PaginateOpts {
|
|
9
|
+
params?: (string | number)[];
|
|
10
|
+
orderBy?: string;
|
|
11
|
+
order?: 'ASC' | 'DESC';
|
|
12
|
+
}
|
|
13
|
+
export interface PaginateResult<T> {
|
|
14
|
+
rows: T[];
|
|
15
|
+
cursor: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface FeedContext {
|
|
18
|
+
db: {
|
|
19
|
+
query: (sql: string, params?: any[]) => Promise<any[]>;
|
|
20
|
+
};
|
|
21
|
+
params: Record<string, string>;
|
|
22
|
+
cursor?: string;
|
|
23
|
+
limit: number;
|
|
24
|
+
viewer: {
|
|
25
|
+
did: string;
|
|
26
|
+
} | null;
|
|
27
|
+
packCursor: (primary: string | number, cid: string) => string;
|
|
28
|
+
unpackCursor: (cursor: string) => {
|
|
29
|
+
primary: string;
|
|
30
|
+
cid: string;
|
|
31
|
+
} | null;
|
|
32
|
+
isTakendown: (did: string) => Promise<boolean>;
|
|
33
|
+
filterTakendownDids: (dids: string[]) => Promise<Set<string>>;
|
|
34
|
+
paginate: <T extends {
|
|
35
|
+
uri: string;
|
|
36
|
+
}>(sql: string, opts?: PaginateOpts) => Promise<PaginateResult<T>>;
|
|
37
|
+
}
|
|
38
|
+
type FeedGenerate = (ctx: FeedContext & {
|
|
39
|
+
ok: (value: FeedResult) => Checked<FeedResult>;
|
|
40
|
+
}) => Promise<Checked<FeedResult>>;
|
|
41
|
+
type FeedOpts = {
|
|
42
|
+
collection: string;
|
|
43
|
+
view?: string;
|
|
44
|
+
label: string;
|
|
45
|
+
generate: FeedGenerate;
|
|
46
|
+
hydrate?: (ctx: HydrateContext<any>) => Promise<unknown[]>;
|
|
47
|
+
} | {
|
|
48
|
+
collection?: never;
|
|
49
|
+
view?: never;
|
|
50
|
+
label: string;
|
|
51
|
+
generate: FeedGenerate;
|
|
52
|
+
hydrate: (ctx: HydrateContext<any>) => Promise<unknown[]>;
|
|
53
|
+
};
|
|
54
|
+
export declare function createPaginate(deps: {
|
|
55
|
+
db: {
|
|
56
|
+
query: (sql: string, params?: any[]) => Promise<any[]>;
|
|
57
|
+
};
|
|
58
|
+
cursor?: string;
|
|
59
|
+
limit: number;
|
|
60
|
+
packCursor: (primary: string | number, cid: string) => string;
|
|
61
|
+
unpackCursor: (cursor: string) => {
|
|
62
|
+
primary: string;
|
|
63
|
+
cid: string;
|
|
64
|
+
} | null;
|
|
65
|
+
}): <T extends {
|
|
66
|
+
uri: string;
|
|
67
|
+
}>(sql: string, opts?: PaginateOpts) => Promise<PaginateResult<T>>;
|
|
68
|
+
export declare function defineFeed(opts: FeedOpts): {
|
|
69
|
+
generate: (ctx: any) => Promise<Checked<FeedResult>>;
|
|
70
|
+
collection: string;
|
|
71
|
+
view?: string;
|
|
72
|
+
label: string;
|
|
73
|
+
hydrate?: (ctx: HydrateContext<any>) => Promise<unknown[]>;
|
|
74
|
+
} | {
|
|
75
|
+
generate: (ctx: any) => Promise<Checked<FeedResult>>;
|
|
76
|
+
collection?: never;
|
|
77
|
+
view?: never;
|
|
78
|
+
label: string;
|
|
79
|
+
hydrate: (ctx: HydrateContext<any>) => Promise<unknown[]>;
|
|
80
|
+
};
|
|
81
|
+
export declare function initFeeds(feedsDir: string): Promise<void>;
|
|
82
|
+
/** Execute a feed and run its hydrate pipeline if present. */
|
|
83
|
+
export declare function executeFeed(name: string, params: Record<string, string>, cursor: string | undefined, limit: number, viewer?: {
|
|
84
|
+
did: string;
|
|
85
|
+
} | null): Promise<{
|
|
86
|
+
items?: unknown[];
|
|
87
|
+
uris?: string[];
|
|
88
|
+
cursor?: string;
|
|
89
|
+
} | null>;
|
|
90
|
+
export declare function listFeeds(): {
|
|
91
|
+
name: string;
|
|
92
|
+
label: string;
|
|
93
|
+
}[];
|
|
94
|
+
export declare function feedHasHydrate(name: string): boolean;
|
|
95
|
+
//# sourceMappingURL=feeds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feeds.d.ts","sourceRoot":"","sources":["../src/feeds.ts"],"names":[],"mappings":"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"}
|
package/dist/feeds.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
import { resolve } from 'node:path';
|
|
10
|
+
import { readdirSync } from 'node:fs';
|
|
11
|
+
import { log } from "./logger.js";
|
|
12
|
+
import { querySQL, packCursor, unpackCursor, isTakendownDid, filterTakendownDids } from "./db.js";
|
|
13
|
+
import { resolveRecords, buildHydrateContext } from "./hydrate.js";
|
|
14
|
+
export function createPaginate(deps) {
|
|
15
|
+
return async (sql, opts) => {
|
|
16
|
+
const { db, cursor, limit, packCursor: pack, unpackCursor: unpack } = deps;
|
|
17
|
+
const userParams = opts?.params ?? [];
|
|
18
|
+
const orderBy = opts?.orderBy ?? 'indexed_at';
|
|
19
|
+
const order = opts?.order ?? 'DESC';
|
|
20
|
+
// Derive table prefix and bare column names from qualified orderBy (e.g. "p.played_time" → "p.")
|
|
21
|
+
const dotIdx = orderBy.lastIndexOf('.');
|
|
22
|
+
const prefix = dotIdx >= 0 ? orderBy.substring(0, dotIdx + 1) : '';
|
|
23
|
+
const cidCol = prefix + 'cid';
|
|
24
|
+
const orderByCol = dotIdx >= 0 ? orderBy.substring(dotIdx + 1) : orderBy;
|
|
25
|
+
const op = order === 'ASC' ? '>' : '<';
|
|
26
|
+
let paramIdx = userParams.length + 1;
|
|
27
|
+
const sqlParams = [...userParams];
|
|
28
|
+
// Build cursor condition
|
|
29
|
+
let cursorCondition = '';
|
|
30
|
+
if (cursor) {
|
|
31
|
+
const parsed = unpack(cursor);
|
|
32
|
+
if (parsed) {
|
|
33
|
+
cursorCondition = `(${orderBy} ${op} $${paramIdx} OR (${orderBy} = $${paramIdx + 1} AND ${cidCol} ${op} $${paramIdx + 2}))`;
|
|
34
|
+
sqlParams.push(parsed.primary, parsed.primary, parsed.cid);
|
|
35
|
+
paramIdx += 3;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Detect existing WHERE and append cursor condition
|
|
39
|
+
let fullSql = sql;
|
|
40
|
+
if (cursorCondition) {
|
|
41
|
+
if (/\bWHERE\b/i.test(sql)) {
|
|
42
|
+
fullSql += ` AND ${cursorCondition}`;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
fullSql += ` WHERE ${cursorCondition}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
fullSql += ` ORDER BY ${orderBy} ${order}, ${cidCol} ${order} LIMIT $${paramIdx}`;
|
|
49
|
+
sqlParams.push(limit + 1);
|
|
50
|
+
const rows = (await db.query(fullSql, sqlParams));
|
|
51
|
+
const hasMore = rows.length > limit;
|
|
52
|
+
if (hasMore)
|
|
53
|
+
rows.pop();
|
|
54
|
+
const last = rows[rows.length - 1];
|
|
55
|
+
return {
|
|
56
|
+
rows,
|
|
57
|
+
cursor: hasMore && last ? pack(last[orderByCol], last.cid) : undefined,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function defineFeed(opts) {
|
|
62
|
+
return { ...opts, generate: (ctx) => opts.generate({ ...ctx, ok: (v) => v }) };
|
|
63
|
+
}
|
|
64
|
+
const feeds = new Map();
|
|
65
|
+
export async function initFeeds(feedsDir) {
|
|
66
|
+
let files;
|
|
67
|
+
try {
|
|
68
|
+
files = readdirSync(feedsDir)
|
|
69
|
+
.filter((f) => (f.endsWith('.ts') || f.endsWith('.js')) && !f.startsWith('_'))
|
|
70
|
+
.sort();
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
const name = file.replace(/\.(ts|js)$/, '');
|
|
77
|
+
const scriptPath = resolve(feedsDir, file);
|
|
78
|
+
const mod = await import(__rewriteRelativeImportExtension(scriptPath));
|
|
79
|
+
const generator = mod.default;
|
|
80
|
+
const handler = {
|
|
81
|
+
name,
|
|
82
|
+
label: generator.label || name,
|
|
83
|
+
collection: generator.collection,
|
|
84
|
+
view: generator.view,
|
|
85
|
+
generate: async (params, cursor, limit, viewer) => {
|
|
86
|
+
const paginateDeps = {
|
|
87
|
+
db: { query: querySQL },
|
|
88
|
+
cursor,
|
|
89
|
+
limit,
|
|
90
|
+
packCursor,
|
|
91
|
+
unpackCursor,
|
|
92
|
+
};
|
|
93
|
+
const ctx = {
|
|
94
|
+
db: { query: querySQL },
|
|
95
|
+
params,
|
|
96
|
+
cursor,
|
|
97
|
+
limit,
|
|
98
|
+
viewer,
|
|
99
|
+
packCursor,
|
|
100
|
+
unpackCursor,
|
|
101
|
+
isTakendown: isTakendownDid,
|
|
102
|
+
filterTakendownDids,
|
|
103
|
+
paginate: createPaginate(paginateDeps),
|
|
104
|
+
};
|
|
105
|
+
const result = await generator.generate(ctx);
|
|
106
|
+
if (Array.isArray(result)) {
|
|
107
|
+
return { uris: result.map((r) => r.uri || r) };
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
uris: result.uris,
|
|
111
|
+
cursor: result.cursor,
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
if (typeof generator.hydrate === 'function') {
|
|
116
|
+
handler.hydrate = generator.hydrate;
|
|
117
|
+
log(`[feeds] discovered: ${name} (with hydrate)`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
log(`[feeds] discovered: ${name}`);
|
|
121
|
+
}
|
|
122
|
+
feeds.set(name, handler);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Execute a feed and run its hydrate pipeline if present. */
|
|
126
|
+
export async function executeFeed(name, params, cursor, limit, viewer) {
|
|
127
|
+
const handler = feeds.get(name);
|
|
128
|
+
if (!handler)
|
|
129
|
+
return null;
|
|
130
|
+
const result = await handler.generate(params, cursor, limit, viewer || null);
|
|
131
|
+
if (handler.hydrate) {
|
|
132
|
+
const items = await resolveRecords(result.uris);
|
|
133
|
+
const ctx = buildHydrateContext(items, viewer || null);
|
|
134
|
+
const hydrated = await handler.hydrate(ctx);
|
|
135
|
+
return { items: hydrated, cursor: result.cursor };
|
|
136
|
+
}
|
|
137
|
+
return { uris: result.uris, cursor: result.cursor };
|
|
138
|
+
}
|
|
139
|
+
export function listFeeds() {
|
|
140
|
+
return Array.from(feeds.values()).map((f) => ({ name: f.name, label: f.label }));
|
|
141
|
+
}
|
|
142
|
+
export function feedHasHydrate(name) {
|
|
143
|
+
return feeds.get(name)?.hydrate != null;
|
|
144
|
+
}
|
package/dist/fts.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function getSearchColumns(collection: string): string[];
|
|
2
|
+
export declare function getLastRebuiltAt(collection: string): string | null;
|
|
3
|
+
/**
|
|
4
|
+
* DuckDB FTS can't handle dots in table names (interprets them as catalog.schema.table).
|
|
5
|
+
* We create a shadow table with underscored names for FTS indexing.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ftsTableName(collection: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Build FTS index for a collection.
|
|
10
|
+
* Creates a shadow table copy and indexes all TEXT NOT NULL columns
|
|
11
|
+
* using Porter stemmer with English stopwords.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildFtsIndex(collection: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Strip English stop words from a search query, preserving non-stop-word terms.
|
|
16
|
+
* Returns the cleaned query string. If all words are stop words, returns the original query.
|
|
17
|
+
*/
|
|
18
|
+
export declare function stripStopWords(query: string): string;
|
|
19
|
+
export declare function rebuildAllIndexes(collections: string[]): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=fts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fts.d.ts","sourceRoot":"","sources":["../src/fts.ts"],"names":[],"mappings":"AAwEA,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0FrE;AAokBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB5E"}
|