@hatk/hatk 0.0.1-alpha.2 → 0.0.1-alpha.3

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/cli.js CHANGED
@@ -797,7 +797,7 @@ RUN npm ci --omit=dev
797
797
  COPY . .
798
798
  RUN node_modules/.bin/hatk build
799
799
  EXPOSE 3000
800
- CMD ["node", "--no-warnings", "node_modules/@hatk/hatk/dist/main.js", "config.yaml"]
800
+ CMD ["node", "node_modules/@hatk/hatk/dist/main.js", "config.yaml"]
801
801
  `);
802
802
  const pkgDeps = { '@hatk/oauth-client': '*', hatk: '*' };
803
803
  const pkgDevDeps = {
@@ -926,6 +926,7 @@ export default defineConfig({
926
926
  <head>
927
927
  <meta charset="utf-8" />
928
928
  <meta name="viewport" content="width=device-width, initial-scale=1" />
929
+ <meta name="description" content="${name}" />
929
930
  <title>${name}</title>
930
931
  %sveltekit.head%
931
932
  </head>
@@ -1437,7 +1438,11 @@ else if (command === 'dev') {
1437
1438
  else {
1438
1439
  // No frontend — just run the hatk server directly
1439
1440
  const mainPath = resolve(import.meta.dirname, 'main.js');
1440
- execSync(`npx tsx ${mainPath} config.yaml`, { stdio: 'inherit', cwd: process.cwd() });
1441
+ execSync(`npx tsx ${mainPath} config.yaml`, {
1442
+ stdio: 'inherit',
1443
+ cwd: process.cwd(),
1444
+ env: { ...process.env, DEV_MODE: '1' },
1445
+ });
1441
1446
  }
1442
1447
  }
1443
1448
  catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAiD3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA2B9C,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,GAAG,EAAE,eAAe,KAAK;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAC/D,MAAM,CAm7BR"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAmD3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA2B9C,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,GAAG,EAAE,eAAe,KAAK;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAC/D,MAAM,CAo8BR"}
package/dist/server.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { createServer } from 'node:http';
2
+ import { gzipSync } from 'node:zlib';
3
+ import { existsSync } from 'node:fs';
2
4
  import { readFile } from 'node:fs/promises';
3
5
  import { join, extname } from 'node:path';
4
6
  import { queryRecords, getRecordByUri, searchRecords, getSchema, reshapeRow, setRepoStatus, getRepoStatus, getRepoRetryInfo, querySQL, insertRecord, deleteRecord, queryLabelsForUris, insertLabels, searchAccounts, listReposPaginated, getCollectionCounts, normalizeValue, getSchemaDump, getPreferences, putPreference, } from "./db.js";
@@ -39,12 +41,13 @@ function readBodyRaw(req) {
39
41
  }
40
42
  export function startServer(port, collections, publicDir, oauth, admins = [], resolveViewer) {
41
43
  const coreXrpc = (method) => `/xrpc/dev.hatk.${method}`;
44
+ const devMode = process.env.DEV_MODE === '1';
42
45
  function requireAdmin(viewer, res) {
43
46
  if (!viewer) {
44
47
  jsonError(res, 401, 'Authentication required');
45
48
  return false;
46
49
  }
47
- if (!admins.includes(viewer.did)) {
50
+ if (!devMode && !admins.includes(viewer.did)) {
48
51
  jsonError(res, 403, 'Admin access required');
49
52
  return false;
50
53
  }
@@ -864,6 +867,21 @@ export function startServer(port, collections, publicDir, oauth, admins = [], re
864
867
  throw err;
865
868
  }
866
869
  }
870
+ // GET /robots.txt — serve from user's public dir or fall back to hatk default
871
+ if (url.pathname === '/robots.txt') {
872
+ const userRobots = publicDir ? join(publicDir, 'robots.txt') : null;
873
+ const defaultRobots = join(import.meta.dirname, '../public/robots.txt');
874
+ const robotsPath = userRobots && existsSync(userRobots) ? userRobots : defaultRobots;
875
+ try {
876
+ const content = await readFile(robotsPath);
877
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
878
+ res.end(content);
879
+ return;
880
+ }
881
+ catch {
882
+ // fall through
883
+ }
884
+ }
867
885
  // Static file serving
868
886
  if (publicDir) {
869
887
  try {
@@ -912,15 +930,33 @@ export function startServer(port, collections, publicDir, oauth, admins = [], re
912
930
  server.listen(port, () => log(`[server] ${oauth?.issuer || `http://localhost:${port}`}`));
913
931
  return server;
914
932
  }
933
+ function sendJson(res, status, body) {
934
+ const acceptEncoding = res.req?.headers['accept-encoding'] || '';
935
+ if (body.length > 1024 && /\bgzip\b/.test(acceptEncoding)) {
936
+ const compressed = gzipSync(body);
937
+ res.writeHead(status, {
938
+ 'Content-Type': 'application/json',
939
+ 'Content-Encoding': 'gzip',
940
+ Vary: 'Accept-Encoding',
941
+ ...(status === 200 ? { 'Cache-Control': 'no-store' } : {}),
942
+ });
943
+ res.end(compressed);
944
+ }
945
+ else {
946
+ res.writeHead(status, {
947
+ 'Content-Type': 'application/json',
948
+ ...(status === 200 ? { 'Cache-Control': 'no-store' } : {}),
949
+ });
950
+ res.end(body);
951
+ }
952
+ }
915
953
  function jsonResponse(res, data) {
916
- res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
917
- res.end(JSON.stringify(data, (_, v) => normalizeValue(v)));
954
+ sendJson(res, 200, Buffer.from(JSON.stringify(data, (_, v) => normalizeValue(v))));
918
955
  }
919
956
  function jsonError(res, status, message) {
920
957
  if (res.headersSent)
921
958
  return;
922
- res.writeHead(status, { 'Content-Type': 'application/json' });
923
- res.end(JSON.stringify({ error: message }));
959
+ sendJson(res, status, Buffer.from(JSON.stringify({ error: message })));
924
960
  }
925
961
  /** Proxy a request to the user's PDS with DPoP + automatic nonce retry + token refresh. */
926
962
  async function proxyToPds(oauthConfig, session, method, pdsUrl, body) {
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAKlC,wBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAsFrD"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAKlC,wBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAuFrD"}
@@ -71,6 +71,7 @@ export function hatk(opts) {
71
71
  ...process.env,
72
72
  PORT: String(backendPort),
73
73
  OAUTH_ISSUER: process.env.OAUTH_ISSUER || issuer,
74
+ DEV_MODE: '1',
74
75
  },
75
76
  });
76
77
  server.httpServer?.on('close', () => {
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@hatk/hatk",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.3",
4
4
  "bin": {
5
5
  "hatk": "dist/cli.js"
6
6
  },
7
+ "files": [
8
+ "dist",
9
+ "fonts",
10
+ "public"
11
+ ],
7
12
  "type": "module",
8
13
  "exports": {
9
14
  "./feeds": "./dist/feeds.js",
@@ -19,7 +24,6 @@
19
24
  "./test/browser": "./dist/test-browser.js",
20
25
  "./vite-plugin": "./dist/vite-plugin.js"
21
26
  },
22
- "files": ["dist", "fonts", "public"],
23
27
  "scripts": {
24
28
  "build": "tsc -p tsconfig.build.json",
25
29
  "prepublishOnly": "npm run build"
@@ -0,0 +1,2 @@
1
+ User-agent: *
2
+ Allow: /