@hatk/hatk 0.0.1-alpha.61 → 0.0.1-alpha.63
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.js +6 -6
- package/dist/car.d.ts.map +1 -1
- package/dist/car.js +2 -2
- package/dist/cbor.js +1 -1
- package/dist/cli.js +3 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/database/adapter-factory.js +4 -4
- package/dist/database/adapters/duckdb-search.d.ts.map +1 -1
- package/dist/database/adapters/duckdb.d.ts.map +1 -1
- package/dist/database/adapters/sqlite-search.d.ts.map +1 -1
- package/dist/database/adapters/sqlite.d.ts.map +1 -1
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +12 -11
- package/dist/database/fts.js +4 -4
- package/dist/database/index.js +4 -4
- package/dist/database/schema.d.ts.map +1 -1
- package/dist/database/schema.js +1 -1
- package/dist/dev-entry.js +21 -21
- package/dist/feeds.d.ts +4 -4
- package/dist/feeds.d.ts.map +1 -1
- package/dist/feeds.js +3 -3
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +10 -8
- package/dist/hydrate.d.ts.map +1 -1
- package/dist/hydrate.js +2 -2
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +16 -12
- package/dist/labels.d.ts +1 -1
- package/dist/labels.d.ts.map +1 -1
- package/dist/labels.js +2 -2
- package/dist/lexicon-resolve.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/strongRef.json +1 -4
- package/dist/main.js +25 -25
- package/dist/mst.js +1 -1
- package/dist/oauth/db.d.ts.map +1 -1
- package/dist/oauth/db.js +10 -2
- package/dist/oauth/dpop.js +1 -1
- package/dist/oauth/server.d.ts +17 -3
- package/dist/oauth/server.d.ts.map +1 -1
- package/dist/oauth/server.js +41 -20
- package/dist/oauth/session.js +1 -1
- package/dist/opengraph.d.ts +1 -1
- package/dist/opengraph.d.ts.map +1 -1
- package/dist/opengraph.js +2 -2
- package/dist/pds-proxy.d.ts.map +1 -1
- package/dist/pds-proxy.js +7 -7
- package/dist/push.d.ts.map +1 -1
- package/dist/push.js +11 -9
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +1 -1
- package/dist/response.js +1 -1
- package/dist/scanner.js +1 -1
- package/dist/seed.js +1 -1
- package/dist/server-init.js +9 -9
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +32 -23
- package/dist/setup.d.ts +1 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +2 -2
- package/dist/test.js +14 -14
- package/dist/views.js +2 -2
- package/dist/vite-plugin.js +1 -1
- package/dist/xrpc-client.d.ts.map +1 -1
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +5 -5
- package/package.json +2 -2
- package/public/admin.html +37 -20
package/dist/main.js
CHANGED
|
@@ -9,32 +9,32 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
9
9
|
};
|
|
10
10
|
import { mkdirSync, writeFileSync, existsSync } from 'node:fs';
|
|
11
11
|
import { dirname, resolve } from 'node:path';
|
|
12
|
-
import { registerHatkResolveHook } from
|
|
13
|
-
import { log } from
|
|
14
|
-
import { loadConfig } from
|
|
15
|
-
import { loadLexicons, storeLexicons, discoverCollections, buildSchemas } from
|
|
16
|
-
import { discoverViews } from
|
|
17
|
-
import { initDatabase, getCursor, querySQL, getSqlDialect, getSchemaDump, migrateSchema } from
|
|
18
|
-
import { createAdapter } from
|
|
19
|
-
import { getDialect } from
|
|
20
|
-
import { setSearchPort } from
|
|
21
|
-
import { initFeeds, listFeeds } from
|
|
22
|
-
import { initXrpc, listXrpc, configureRelay, configureCdn, configureOAuth, callXrpc } from
|
|
23
|
-
import { initOpengraph } from
|
|
24
|
-
import { initLabels, getLabelDefinitions } from
|
|
25
|
-
import { startIndexer } from
|
|
26
|
-
import { rebuildAllIndexes } from
|
|
27
|
-
import { createHandler, registerCoreHandlers } from
|
|
28
|
-
import { serve } from
|
|
12
|
+
import { registerHatkResolveHook } from './resolve-hatk.js';
|
|
13
|
+
import { log } from './logger.js';
|
|
14
|
+
import { loadConfig } from './config.js';
|
|
15
|
+
import { loadLexicons, storeLexicons, discoverCollections, buildSchemas } from './database/schema.js';
|
|
16
|
+
import { discoverViews } from './views.js';
|
|
17
|
+
import { initDatabase, getCursor, querySQL, getSqlDialect, getSchemaDump, migrateSchema } from './database/db.js';
|
|
18
|
+
import { createAdapter } from './database/adapter-factory.js';
|
|
19
|
+
import { getDialect } from './database/dialect.js';
|
|
20
|
+
import { setSearchPort } from './database/fts.js';
|
|
21
|
+
import { initFeeds, listFeeds } from './feeds.js';
|
|
22
|
+
import { initXrpc, listXrpc, configureRelay, configureCdn, configureOAuth, callXrpc } from './xrpc.js';
|
|
23
|
+
import { initOpengraph } from './opengraph.js';
|
|
24
|
+
import { initLabels, getLabelDefinitions } from './labels.js';
|
|
25
|
+
import { startIndexer } from './indexer.js';
|
|
26
|
+
import { rebuildAllIndexes } from './database/fts.js';
|
|
27
|
+
import { createHandler, registerCoreHandlers } from './server.js';
|
|
28
|
+
import { serve } from './adapter.js';
|
|
29
29
|
import { validateLexicons } from '@bigmoves/lexicon';
|
|
30
|
-
import { relayHttpUrl } from
|
|
31
|
-
import { runBackfill } from
|
|
32
|
-
import { initOAuth } from
|
|
33
|
-
import { parseSessionCookie, getSessionCookieName } from
|
|
34
|
-
import { loadOnLoginHook } from
|
|
35
|
-
import { initPush, isPushEnabled } from
|
|
36
|
-
import { initSetup } from
|
|
37
|
-
import { initServer } from
|
|
30
|
+
import { relayHttpUrl } from './config.js';
|
|
31
|
+
import { runBackfill } from './backfill.js';
|
|
32
|
+
import { initOAuth } from './oauth/server.js';
|
|
33
|
+
import { parseSessionCookie, getSessionCookieName } from './oauth/session.js';
|
|
34
|
+
import { loadOnLoginHook } from './hooks.js';
|
|
35
|
+
import { initPush, isPushEnabled } from './push.js';
|
|
36
|
+
import { initSetup } from './setup.js';
|
|
37
|
+
import { initServer } from './server-init.js';
|
|
38
38
|
const configPath = process.argv[2] || 'hatk.config.ts';
|
|
39
39
|
const configDir = dirname(resolve(configPath));
|
|
40
40
|
registerHatkResolveHook();
|
package/dist/mst.js
CHANGED
package/dist/oauth/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/oauth/db.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,6+CA4DrB,CAAA;AAID,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/oauth/db.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/db.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// packages/hatk/src/oauth/db.ts
|
|
2
|
-
import { querySQL, runSQL } from
|
|
2
|
+
import { querySQL, runSQL } from '../database/db.js';
|
|
3
3
|
// --- DDL ---
|
|
4
4
|
export const OAUTH_DDL = `
|
|
5
5
|
CREATE TABLE IF NOT EXISTS _oauth_keys (
|
|
@@ -126,7 +126,15 @@ export async function consumeAuthCode(code) {
|
|
|
126
126
|
// --- Sessions ---
|
|
127
127
|
export async function storeSession(did, data) {
|
|
128
128
|
await runSQL(`INSERT OR REPLACE INTO _oauth_sessions (did, pds_endpoint, pds_auth_server, access_token, refresh_token, dpop_jkt, token_expires_at, updated_at)
|
|
129
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,CURRENT_TIMESTAMP)`, [
|
|
129
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,CURRENT_TIMESTAMP)`, [
|
|
130
|
+
did,
|
|
131
|
+
data.pdsEndpoint,
|
|
132
|
+
data.pdsAuthServer || null,
|
|
133
|
+
data.accessToken,
|
|
134
|
+
data.refreshToken || null,
|
|
135
|
+
data.dpopJkt,
|
|
136
|
+
data.tokenExpiresAt || null,
|
|
137
|
+
]);
|
|
130
138
|
}
|
|
131
139
|
export async function getSession(did) {
|
|
132
140
|
const rows = await querySQL('SELECT * FROM _oauth_sessions WHERE did = $1', [did]);
|
package/dist/oauth/dpop.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// packages/hatk/src/oauth/dpop.ts
|
|
2
|
-
import { parseJwt, importPublicKey, verifyEs256, computeJwkThumbprint, sha256, base64UrlEncode, signJwt, importPrivateKey, } from
|
|
2
|
+
import { parseJwt, importPublicKey, verifyEs256, computeJwkThumbprint, sha256, base64UrlEncode, signJwt, importPrivateKey, } from './crypto.js';
|
|
3
3
|
/** Validate a DPoP proof JWT from a client request. */
|
|
4
4
|
export async function parseDpopProof(proof, method, url, expectedJkt, accessToken) {
|
|
5
5
|
const { header, payload, signatureInput, signature } = parseJwt(proof);
|
package/dist/oauth/server.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import type { OAuthConfig } from '../config.ts';
|
|
2
|
+
/**
|
|
3
|
+
* RFC 6749 §5.2 OAuth token-endpoint error.
|
|
4
|
+
*
|
|
5
|
+
* Surfaces as HTTP `status` (default 400) with body
|
|
6
|
+
* `{ error: code, error_description: description }` so OAuth clients can
|
|
7
|
+
* distinguish a permanently-rejected refresh token (`invalid_grant`) from
|
|
8
|
+
* a transient server failure and decide whether to log the user out.
|
|
9
|
+
*/
|
|
10
|
+
export declare class OAuthError extends Error {
|
|
11
|
+
readonly code: 'invalid_request' | 'invalid_client' | 'invalid_grant' | 'unauthorized_client' | 'unsupported_grant_type' | 'invalid_scope';
|
|
12
|
+
readonly description: string;
|
|
13
|
+
readonly status: number;
|
|
14
|
+
constructor(code: 'invalid_request' | 'invalid_client' | 'invalid_grant' | 'unauthorized_client' | 'unsupported_grant_type' | 'invalid_scope', description: string, status?: number);
|
|
15
|
+
}
|
|
2
16
|
export declare function initOAuth(_config: OAuthConfig, plcUrl: string, relayUrl: string): Promise<void>;
|
|
3
17
|
export declare function getAuthServerMetadata(issuer: string, config: OAuthConfig): {
|
|
4
18
|
issuer: string;
|
|
@@ -28,9 +42,6 @@ export declare function getProtectedResourceMetadata(issuer: string, config: OAu
|
|
|
28
42
|
};
|
|
29
43
|
export declare function getJwks(): {
|
|
30
44
|
keys: {
|
|
31
|
-
kid: string;
|
|
32
|
-
use: string;
|
|
33
|
-
alg: string;
|
|
34
45
|
crv?: string;
|
|
35
46
|
d?: string;
|
|
36
47
|
dp?: string;
|
|
@@ -47,6 +58,9 @@ export declare function getJwks(): {
|
|
|
47
58
|
qi?: string;
|
|
48
59
|
x?: string;
|
|
49
60
|
y?: string;
|
|
61
|
+
kid: string;
|
|
62
|
+
use: string;
|
|
63
|
+
alg: string;
|
|
50
64
|
}[];
|
|
51
65
|
};
|
|
52
66
|
export declare function getClientMetadata(issuer: string, config: OAuthConfig): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/server.js
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
// packages/hatk/src/oauth/server.ts
|
|
2
|
-
import { generateKeyPair, importPrivateKey, computeJwkThumbprint, signJwt, parseJwt, verifyEs256, importPublicKey, randomToken, sha256, base64UrlEncode, } from
|
|
3
|
-
import { parseDpopProof, createDpopProof } from
|
|
4
|
-
import { initSession } from
|
|
5
|
-
import { resolveClient, validateRedirectUri, isLoopbackClient } from
|
|
6
|
-
import { discoverAuthServer, resolveHandle, fetchProtectedResourceMetadata, fetchAuthServerMetadata } from
|
|
7
|
-
import { getServerKey, storeServerKey, storeOAuthRequest, getOAuthRequest, deleteOAuthRequest, storeAuthCode, consumeAuthCode, storeSession, deleteSession, checkAndStoreDpopJti, cleanupExpiredOAuth, storeRefreshToken, getRefreshToken, revokeRefreshToken, } from
|
|
8
|
-
import { emit } from
|
|
9
|
-
import { querySQL } from
|
|
10
|
-
import { fireOnLoginHook } from
|
|
2
|
+
import { generateKeyPair, importPrivateKey, computeJwkThumbprint, signJwt, parseJwt, verifyEs256, importPublicKey, randomToken, sha256, base64UrlEncode, } from './crypto.js';
|
|
3
|
+
import { parseDpopProof, createDpopProof } from './dpop.js';
|
|
4
|
+
import { initSession } from './session.js';
|
|
5
|
+
import { resolveClient, validateRedirectUri, isLoopbackClient } from './client.js';
|
|
6
|
+
import { discoverAuthServer, resolveHandle, fetchProtectedResourceMetadata, fetchAuthServerMetadata, } from './discovery.js';
|
|
7
|
+
import { getServerKey, storeServerKey, storeOAuthRequest, getOAuthRequest, deleteOAuthRequest, storeAuthCode, consumeAuthCode, storeSession, deleteSession, checkAndStoreDpopJti, cleanupExpiredOAuth, storeRefreshToken, getRefreshToken, revokeRefreshToken, } from './db.js';
|
|
8
|
+
import { emit } from '../logger.js';
|
|
9
|
+
import { querySQL } from '../database/db.js';
|
|
10
|
+
import { fireOnLoginHook } from '../hooks.js';
|
|
11
11
|
const SERVER_KEY_KID = 'appview-oauth-key';
|
|
12
|
+
/**
|
|
13
|
+
* RFC 6749 §5.2 OAuth token-endpoint error.
|
|
14
|
+
*
|
|
15
|
+
* Surfaces as HTTP `status` (default 400) with body
|
|
16
|
+
* `{ error: code, error_description: description }` so OAuth clients can
|
|
17
|
+
* distinguish a permanently-rejected refresh token (`invalid_grant`) from
|
|
18
|
+
* a transient server failure and decide whether to log the user out.
|
|
19
|
+
*/
|
|
20
|
+
export class OAuthError extends Error {
|
|
21
|
+
code;
|
|
22
|
+
description;
|
|
23
|
+
status;
|
|
24
|
+
constructor(code, description, status = 400) {
|
|
25
|
+
super(description);
|
|
26
|
+
this.code = code;
|
|
27
|
+
this.description = description;
|
|
28
|
+
this.status = status;
|
|
29
|
+
this.name = 'OAuthError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
12
32
|
async function resolveHandleForDid(did) {
|
|
13
33
|
const rows = (await querySQL('SELECT handle FROM _repos WHERE did = $1', [did]));
|
|
14
34
|
return rows[0]?.handle || undefined;
|
|
@@ -427,7 +447,7 @@ export async function serverLogin(config, handle, options) {
|
|
|
427
447
|
// --- OAuth Callback (PDS redirects here) ---
|
|
428
448
|
export async function handleCallback(config, code, state, iss) {
|
|
429
449
|
// Find the matching OAuth request by pds_state (unique per PAR)
|
|
430
|
-
const { querySQL } = await import(
|
|
450
|
+
const { querySQL } = await import('../database/db.js');
|
|
431
451
|
let request = null;
|
|
432
452
|
if (state) {
|
|
433
453
|
const rows = await querySQL(`SELECT * FROM _oauth_requests WHERE pds_state = $1 AND expires_at > $2`, [
|
|
@@ -516,7 +536,7 @@ export async function handleCallback(config, code, state, iss) {
|
|
|
516
536
|
await storeAuthCode(clientCode, request.request_uri);
|
|
517
537
|
// Update the request with the DID (in case it wasn't set during PAR)
|
|
518
538
|
if (!request.did && did) {
|
|
519
|
-
const { runSQL } = await import(
|
|
539
|
+
const { runSQL } = await import('../database/db.js');
|
|
520
540
|
await runSQL('UPDATE _oauth_requests SET did = $1 WHERE request_uri = $2', [did, request.request_uri]);
|
|
521
541
|
}
|
|
522
542
|
// Build redirect back to client
|
|
@@ -530,14 +550,14 @@ export async function handleCallback(config, code, state, iss) {
|
|
|
530
550
|
export async function handleToken(config, body, dpopHeader, requestUrl) {
|
|
531
551
|
const grantType = body.grant_type;
|
|
532
552
|
if (!grantType)
|
|
533
|
-
throw new
|
|
553
|
+
throw new OAuthError('invalid_request', 'grant_type is required');
|
|
534
554
|
if (grantType === 'authorization_code') {
|
|
535
555
|
return handleAuthorizationCodeGrant(config, body, dpopHeader, requestUrl);
|
|
536
556
|
}
|
|
537
557
|
else if (grantType === 'refresh_token') {
|
|
538
558
|
return handleRefreshTokenGrant(config, body, dpopHeader, requestUrl);
|
|
539
559
|
}
|
|
540
|
-
throw new
|
|
560
|
+
throw new OAuthError('unsupported_grant_type', `Unsupported grant_type: ${grantType}`);
|
|
541
561
|
}
|
|
542
562
|
async function handleAuthorizationCodeGrant(config, body, dpopHeader, requestUrl) {
|
|
543
563
|
const dpop = await parseDpopProof(dpopHeader, 'POST', requestUrl);
|
|
@@ -610,20 +630,21 @@ async function handleRefreshTokenGrant(config, body, dpopHeader, requestUrl) {
|
|
|
610
630
|
const dpop = await parseDpopProof(dpopHeader, 'POST', requestUrl);
|
|
611
631
|
const fresh = await checkAndStoreDpopJti(dpop.jti, dpop.iat + 300);
|
|
612
632
|
if (!fresh)
|
|
613
|
-
throw new
|
|
633
|
+
throw new OAuthError('invalid_request', 'DPoP jti replay detected');
|
|
614
634
|
const { refresh_token, client_id } = body;
|
|
615
635
|
if (!refresh_token || !client_id)
|
|
616
|
-
throw new
|
|
617
|
-
// Look up and validate refresh token
|
|
636
|
+
throw new OAuthError('invalid_request', 'Missing required parameters');
|
|
637
|
+
// Look up and validate refresh token. Per RFC 6749 §5.2, all of these are
|
|
638
|
+
// `invalid_grant` — the client must treat them as terminal and re-authenticate.
|
|
618
639
|
const stored = await getRefreshToken(refresh_token);
|
|
619
640
|
if (!stored)
|
|
620
|
-
throw new
|
|
641
|
+
throw new OAuthError('invalid_grant', 'Invalid refresh token');
|
|
621
642
|
if (stored.revoked)
|
|
622
|
-
throw new
|
|
643
|
+
throw new OAuthError('invalid_grant', 'Refresh token revoked');
|
|
623
644
|
if (stored.expires_at && stored.expires_at < Math.floor(Date.now() / 1000))
|
|
624
|
-
throw new
|
|
645
|
+
throw new OAuthError('invalid_grant', 'Refresh token expired');
|
|
625
646
|
if (stored.client_id !== client_id)
|
|
626
|
-
throw new
|
|
647
|
+
throw new OAuthError('invalid_grant', 'client_id mismatch');
|
|
627
648
|
// Revoke old refresh token (rotation)
|
|
628
649
|
await revokeRefreshToken(refresh_token);
|
|
629
650
|
const did = stored.did;
|
package/dist/oauth/session.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SSR session cookie — AES-GCM encrypted HttpOnly cookie for server-side viewer resolution.
|
|
2
2
|
// Separate from OAuth protocol flows but uses the same server keypair for key derivation.
|
|
3
|
-
import { base64UrlEncode, base64UrlDecode } from
|
|
3
|
+
import { base64UrlEncode, base64UrlDecode } from './crypto.js';
|
|
4
4
|
let _privateJwk;
|
|
5
5
|
let _cookieName = '__hatk_session';
|
|
6
6
|
const MAX_AGE = 30 * 24 * 60 * 60; // 30 days in seconds
|
package/dist/opengraph.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface OpengraphResult {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
export declare function defineOG(path: string, generate: (ctx: OpengraphContext) => Promise<OpengraphResult>): {
|
|
32
|
-
__type:
|
|
32
|
+
__type: 'og';
|
|
33
33
|
path: string;
|
|
34
34
|
generate: (ctx: OpengraphContext) => Promise<OpengraphResult>;
|
|
35
35
|
};
|
package/dist/opengraph.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opengraph.d.ts","sourceRoot":"","sources":["../src/opengraph.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC3B,QAAQ,CAAC,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAA;QAC3C,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;CACF;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACpD;AAED,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAA;IAC5D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAChD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"opengraph.d.ts","sourceRoot":"","sources":["../src/opengraph.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC3B,QAAQ,CAAC,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAA;QAC3C,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;CACF;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACpD;AAED,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAA;IAC5D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAChD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC;YACjF,IAAI;;oBADgC,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC;EAEnG;AAkCD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0EhE;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAC9D,GAAG,IAAI,CAsDP;AAED,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+BrF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyC3E"}
|
package/dist/opengraph.js
CHANGED
|
@@ -8,7 +8,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
8
8
|
};
|
|
9
9
|
import { resolve } from 'node:path';
|
|
10
10
|
import { readFileSync, readdirSync } from 'node:fs';
|
|
11
|
-
import { log } from
|
|
11
|
+
import { log } from './logger.js';
|
|
12
12
|
// Lazy-imported to avoid CJS require() issues in Vite's module runner
|
|
13
13
|
let _satori = null;
|
|
14
14
|
let _Resvg = null;
|
|
@@ -22,7 +22,7 @@ async function getResvg() {
|
|
|
22
22
|
_Resvg = (await import('@resvg/resvg-js')).Resvg;
|
|
23
23
|
return _Resvg;
|
|
24
24
|
}
|
|
25
|
-
import { buildXrpcContext } from
|
|
25
|
+
import { buildXrpcContext } from './xrpc.js';
|
|
26
26
|
export function defineOG(path, generate) {
|
|
27
27
|
return { __type: 'og', path, generate };
|
|
28
28
|
}
|
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;
|
|
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;IADvB,YACS,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EAGhB;CACF;AAED,qBAAa,sBAAuB,SAAQ,UAAU;IACpD,cAEC;CACF;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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Shared PDS proxy functions — used by both HTTP route handlers and XRPC handlers.
|
|
2
|
-
import { getSession, getServerKey, deleteSession } from
|
|
3
|
-
import { createDpopProof } from
|
|
4
|
-
import { refreshPdsSession } from
|
|
2
|
+
import { getSession, getServerKey, deleteSession } from './oauth/db.js';
|
|
3
|
+
import { createDpopProof } from './oauth/dpop.js';
|
|
4
|
+
import { refreshPdsSession } from './oauth/server.js';
|
|
5
5
|
import { validateRecord } from '@bigmoves/lexicon';
|
|
6
|
-
import { getLexiconArray } from
|
|
7
|
-
import { insertRecord, deleteRecord as dbDeleteRecord } from
|
|
8
|
-
import { emit } from
|
|
9
|
-
import { runLabelRules } from
|
|
6
|
+
import { getLexiconArray } from './database/schema.js';
|
|
7
|
+
import { insertRecord, deleteRecord as dbDeleteRecord } from './database/db.js';
|
|
8
|
+
import { emit } from './logger.js';
|
|
9
|
+
import { runLabelRules } from './labels.js';
|
|
10
10
|
export class ProxyError extends Error {
|
|
11
11
|
status;
|
|
12
12
|
constructor(status, message) {
|
package/dist/push.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9C;AAOD,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CASpE;AAED,iDAAiD;AACjD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI,aAAa,CAElD;
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9C;AAOD,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CASpE;AAED,iDAAiD;AACjD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI,aAAa,CAElD;AAsJD,4DAA4D;AAC5D,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/F;AAED,2BAA2B;AAC3B,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,6CAA6C;AAC7C,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E"}
|
package/dist/push.js
CHANGED
|
@@ -10,8 +10,8 @@ import { connect } from 'node:http2';
|
|
|
10
10
|
import { readFileSync } from 'node:fs';
|
|
11
11
|
import { createSign } from 'node:crypto';
|
|
12
12
|
import { resolve } from 'node:path';
|
|
13
|
-
import { emit } from
|
|
14
|
-
import { runSQL, querySQL } from
|
|
13
|
+
import { emit } from './logger.js';
|
|
14
|
+
import { runSQL, querySQL } from './database/db.js';
|
|
15
15
|
let pushConfig = null;
|
|
16
16
|
let apnsKey = null;
|
|
17
17
|
let cachedJwt = null;
|
|
@@ -63,9 +63,7 @@ function getHttp2Session() {
|
|
|
63
63
|
if (http2Session && !http2Session.closed && !http2Session.destroyed) {
|
|
64
64
|
return http2Session;
|
|
65
65
|
}
|
|
66
|
-
const host = pushConfig?.apns.production !== false
|
|
67
|
-
? 'https://api.push.apple.com'
|
|
68
|
-
: 'https://api.sandbox.push.apple.com';
|
|
66
|
+
const host = pushConfig?.apns.production !== false ? 'https://api.push.apple.com' : 'https://api.sandbox.push.apple.com';
|
|
69
67
|
emit('push', 'connecting', { host });
|
|
70
68
|
http2Session = connect(host, {
|
|
71
69
|
peerMaxConcurrentStreams: 100,
|
|
@@ -86,7 +84,7 @@ function getHttp2Session() {
|
|
|
86
84
|
async function send(payload) {
|
|
87
85
|
if (!pushConfig || !apnsKey)
|
|
88
86
|
return;
|
|
89
|
-
const tokens = await querySQL(`SELECT token, platform FROM _push_tokens WHERE did = $1`, [payload.did]);
|
|
87
|
+
const tokens = (await querySQL(`SELECT token, platform FROM _push_tokens WHERE did = $1`, [payload.did]));
|
|
90
88
|
if (tokens.length === 0)
|
|
91
89
|
return;
|
|
92
90
|
const jwt = getApnsJwt();
|
|
@@ -113,7 +111,7 @@ async function sendToApns(token, payload, jwt, original) {
|
|
|
113
111
|
const headers = {
|
|
114
112
|
':method': 'POST',
|
|
115
113
|
':path': `/3/device/${token}`,
|
|
116
|
-
|
|
114
|
+
authorization: `bearer ${jwt}`,
|
|
117
115
|
'apns-topic': pushConfig.apns.bundleId,
|
|
118
116
|
'apns-push-type': 'alert',
|
|
119
117
|
};
|
|
@@ -123,8 +121,12 @@ async function sendToApns(token, payload, jwt, original) {
|
|
|
123
121
|
return new Promise((resolve) => {
|
|
124
122
|
const req = session.request(headers);
|
|
125
123
|
let settled = false;
|
|
126
|
-
const done = () => {
|
|
127
|
-
|
|
124
|
+
const done = () => {
|
|
125
|
+
if (settled)
|
|
126
|
+
return;
|
|
127
|
+
settled = true;
|
|
128
|
+
resolve();
|
|
129
|
+
};
|
|
128
130
|
req.setTimeout(15_000, () => {
|
|
129
131
|
req.close();
|
|
130
132
|
emit('push', 'send_error', { did: original.did, error: 'APNs request timed out' });
|
package/dist/renderer.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface RenderResult {
|
|
|
7
7
|
}
|
|
8
8
|
export type RendererHandler = (request: Request, manifest: SSRManifest) => Promise<RenderResult>;
|
|
9
9
|
export declare function defineRenderer(handler: RendererHandler): {
|
|
10
|
-
__type:
|
|
10
|
+
__type: 'renderer';
|
|
11
11
|
handler: RendererHandler;
|
|
12
12
|
};
|
|
13
13
|
export declare function registerRenderer(handler: RendererHandler): void;
|
package/dist/renderer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;AAKhG,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;AAKhG,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe;YACpC,UAAU;;EAC5B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAG/D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAE1D;AAED,wBAAgB,WAAW,IAAI,eAAe,GAAG,IAAI,CAEpD;AAED,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAEnD;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsBnH"}
|
package/dist/renderer.js
CHANGED
package/dist/response.js
CHANGED
package/dist/scanner.js
CHANGED
|
@@ -8,7 +8,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
8
8
|
};
|
|
9
9
|
import { resolve, relative } from 'node:path';
|
|
10
10
|
import { readdirSync, statSync, existsSync } from 'node:fs';
|
|
11
|
-
import { log } from
|
|
11
|
+
import { log } from './logger.js';
|
|
12
12
|
/** Recursively collect .ts/.js files, skipping _ prefixed and dot files */
|
|
13
13
|
function walkDir(dir) {
|
|
14
14
|
const results = [];
|
package/dist/seed.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* )
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
import { loadLexicons } from
|
|
26
|
+
import { loadLexicons } from './database/schema.js';
|
|
27
27
|
import { validateRecord } from '@bigmoves/lexicon';
|
|
28
28
|
import { resolve } from 'node:path';
|
|
29
29
|
import { readFileSync } from 'node:fs';
|
package/dist/server-init.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { log } from
|
|
3
|
-
import { scanServerDir } from
|
|
4
|
-
import { registerFeed, listFeeds } from
|
|
5
|
-
import { registerXrpcHandler, listXrpc } from
|
|
6
|
-
import { registerLabelModule, getLabelDefinitions, clearLabels } from
|
|
7
|
-
import { registerOgHandler } from
|
|
8
|
-
import { registerHook } from
|
|
9
|
-
import { runSetupHandler } from
|
|
10
|
-
import { registerRenderer } from
|
|
2
|
+
import { log } from './logger.js';
|
|
3
|
+
import { scanServerDir } from './scanner.js';
|
|
4
|
+
import { registerFeed, listFeeds } from './feeds.js';
|
|
5
|
+
import { registerXrpcHandler, listXrpc } from './xrpc.js';
|
|
6
|
+
import { registerLabelModule, getLabelDefinitions, clearLabels } from './labels.js';
|
|
7
|
+
import { registerOgHandler } from './opengraph.js';
|
|
8
|
+
import { registerHook } from './hooks.js';
|
|
9
|
+
import { runSetupHandler } from './setup.js';
|
|
10
|
+
import { registerRenderer } from './renderer.js';
|
|
11
11
|
/**
|
|
12
12
|
* Scan the server/ directory and register all discovered handlers.
|
|
13
13
|
* Setup scripts run immediately (in sorted order).
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AA0DA,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,CA02B5F;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
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { join, extname } from 'node:path';
|
|
4
|
-
import { queryRecords, getRecordByUri, searchRecords, getSchema, reshapeRow, setRepoStatus, getRepoStatus, getRepoRetryInfo, queryLabelsForUris, insertLabels, searchAccounts, listReposPaginated, getCollectionCounts, getRepoStatusCounts, getDatabaseSize, deleteLabels, getRecentRecords, listActiveRepoDids, removeRepo, getRepoHandle, getPreferences, putPreference, insertReport, queryReports, resolveReport, getOpenReportCount, } from
|
|
5
|
-
import { executeFeed, listFeeds } from
|
|
6
|
-
import { executeXrpc, InvalidRequestError, NotFoundError, registerCoreXrpcHandler } from
|
|
7
|
-
import { resolveRecords } from
|
|
8
|
-
import { handleOpengraphRequest, buildOgMeta } from
|
|
9
|
-
import { getLabelDefinitions, rescanLabels } from
|
|
10
|
-
import { triggerAutoBackfill } from
|
|
11
|
-
import { emit, timer } from
|
|
12
|
-
import { getAuthServerMetadata, getProtectedResourceMetadata, getJwks, getClientMetadata, handlePar, buildAuthorizeRedirect, handleCallback, serverLogin, handleToken, authenticate, } from
|
|
13
|
-
import { createSessionCookie, sessionCookieHeader, clearSessionCookieHeader, parseSessionCookie, } from
|
|
14
|
-
import { getOAuthRequest } from
|
|
15
|
-
import { pdsCreateRecord, pdsDeleteRecord, pdsPutRecord, pdsApplyWrites, pdsUploadBlob, ProxyError, ScopeMissingProxyError, } from
|
|
16
|
-
import { json, jsonError, cors, withCors, file, notFound } from
|
|
17
|
-
import { serve } from
|
|
18
|
-
import { renderPage } from
|
|
4
|
+
import { queryRecords, getRecordByUri, searchRecords, getSchema, reshapeRow, setRepoStatus, getRepoStatus, getRepoRetryInfo, queryLabelsForUris, insertLabels, searchAccounts, listReposPaginated, getCollectionCounts, getRepoStatusCounts, getDatabaseSize, deleteLabels, getRecentRecords, listActiveRepoDids, removeRepo, getRepoHandle, getPreferences, putPreference, insertReport, queryReports, resolveReport, getOpenReportCount, } from './database/db.js';
|
|
5
|
+
import { executeFeed, listFeeds } from './feeds.js';
|
|
6
|
+
import { executeXrpc, InvalidRequestError, NotFoundError, registerCoreXrpcHandler } from './xrpc.js';
|
|
7
|
+
import { resolveRecords } from './hydrate.js';
|
|
8
|
+
import { handleOpengraphRequest, buildOgMeta } from './opengraph.js';
|
|
9
|
+
import { getLabelDefinitions, rescanLabels } from './labels.js';
|
|
10
|
+
import { triggerAutoBackfill } from './indexer.js';
|
|
11
|
+
import { emit, timer } from './logger.js';
|
|
12
|
+
import { getAuthServerMetadata, getProtectedResourceMetadata, getJwks, getClientMetadata, handlePar, buildAuthorizeRedirect, handleCallback, serverLogin, handleToken, authenticate, OAuthError, } from './oauth/server.js';
|
|
13
|
+
import { createSessionCookie, sessionCookieHeader, clearSessionCookieHeader, parseSessionCookie, } from './oauth/session.js';
|
|
14
|
+
import { getOAuthRequest } from './oauth/db.js';
|
|
15
|
+
import { pdsCreateRecord, pdsDeleteRecord, pdsPutRecord, pdsApplyWrites, pdsUploadBlob, ProxyError, ScopeMissingProxyError, } from './pds-proxy.js';
|
|
16
|
+
import { json, jsonError, cors, withCors, file, notFound } from './response.js';
|
|
17
|
+
import { serve } from './adapter.js';
|
|
18
|
+
import { renderPage } from './renderer.js';
|
|
19
19
|
function scopeMissingResponse(acceptEncoding, handle) {
|
|
20
20
|
const res = withCors(json({ error: 'ScopeMissingError', ...(handle ? { handle } : {}) }, 401, acceptEncoding));
|
|
21
21
|
res.headers.append('Set-Cookie', clearSessionCookieHeader());
|
|
@@ -168,7 +168,7 @@ export function registerCoreHandlers(collections, oauth) {
|
|
|
168
168
|
const platform = body.platform || 'apns';
|
|
169
169
|
if (!['apns', 'fcm', 'web'].includes(platform))
|
|
170
170
|
throw new InvalidRequestError('Invalid platform');
|
|
171
|
-
const { registerToken } = await import(
|
|
171
|
+
const { registerToken } = await import('./push.js');
|
|
172
172
|
await registerToken(viewer.did, body.token, platform);
|
|
173
173
|
return { success: true };
|
|
174
174
|
});
|
|
@@ -178,7 +178,7 @@ export function registerCoreHandlers(collections, oauth) {
|
|
|
178
178
|
const body = input;
|
|
179
179
|
if (!body.token || typeof body.token !== 'string')
|
|
180
180
|
throw new InvalidRequestError('Missing or invalid token');
|
|
181
|
-
const { unregisterToken } = await import(
|
|
181
|
+
const { unregisterToken } = await import('./push.js');
|
|
182
182
|
await unregisterToken(viewer.did, body.token);
|
|
183
183
|
return { success: true };
|
|
184
184
|
});
|
|
@@ -743,7 +743,7 @@ export function createHandler(config) {
|
|
|
743
743
|
const did = url.searchParams.get('did');
|
|
744
744
|
if (!did)
|
|
745
745
|
return withCors(jsonError(400, 'did required', acceptEncoding));
|
|
746
|
-
const handle = await getRepoHandle(did) ?? did;
|
|
746
|
+
const handle = (await getRepoHandle(did)) ?? did;
|
|
747
747
|
const cookieValue = await createSessionCookie({ did, handle });
|
|
748
748
|
const secure = url.protocol === 'https:';
|
|
749
749
|
return new Response(JSON.stringify({ ok: true }), {
|
|
@@ -817,7 +817,7 @@ export function createHandler(config) {
|
|
|
817
817
|
return withCors(jsonError(400, 'Missing code', acceptEncoding));
|
|
818
818
|
const result = await handleCallback(oauth, code, state, iss);
|
|
819
819
|
const isSecure = requestOrigin.startsWith('https');
|
|
820
|
-
const handle = await getRepoHandle(result.did) ?? result.did;
|
|
820
|
+
const handle = (await getRepoHandle(result.did)) ?? result.did;
|
|
821
821
|
const cookie = await createSessionCookie({ did: result.did, handle });
|
|
822
822
|
// Server-initiated login stores redirectUri as '/' — redirect cleanly without code/iss params
|
|
823
823
|
const redirectTo = result.clientRedirectUri.startsWith('/?code=') ? '/' : result.clientRedirectUri;
|
|
@@ -849,10 +849,19 @@ export function createHandler(config) {
|
|
|
849
849
|
body = JSON.parse(rawBody);
|
|
850
850
|
}
|
|
851
851
|
const dpopHeader = request.headers.get('dpop');
|
|
852
|
-
if (!dpopHeader)
|
|
853
|
-
return withCors(
|
|
854
|
-
|
|
855
|
-
|
|
852
|
+
if (!dpopHeader) {
|
|
853
|
+
return withCors(json({ error: 'invalid_request', error_description: 'DPoP header required' }, 400, acceptEncoding));
|
|
854
|
+
}
|
|
855
|
+
try {
|
|
856
|
+
const result = await handleToken(oauth, body, dpopHeader, `${requestOrigin}/oauth/token`);
|
|
857
|
+
return withCors(json(result, 200, acceptEncoding));
|
|
858
|
+
}
|
|
859
|
+
catch (err) {
|
|
860
|
+
if (err instanceof OAuthError) {
|
|
861
|
+
return withCors(json({ error: err.code, error_description: err.description }, err.status, acceptEncoding));
|
|
862
|
+
}
|
|
863
|
+
throw err;
|
|
864
|
+
}
|
|
856
865
|
}
|
|
857
866
|
// POST /xrpc/dev.hatk.createRecord — proxy write to user's PDS
|
|
858
867
|
if (url.pathname === coreXrpc('createRecord') && request.method === 'POST' && oauth) {
|
package/dist/setup.d.ts
CHANGED