@hatk/hatk 0.0.1-alpha.41 → 0.0.1-alpha.42

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.
Files changed (77) hide show
  1. package/dist/cli.js +16 -553
  2. package/dist/database/adapters/sqlite.d.ts.map +1 -1
  3. package/dist/database/adapters/sqlite.js +2 -1
  4. package/dist/database/db.d.ts +23 -0
  5. package/dist/database/db.d.ts.map +1 -1
  6. package/dist/database/db.js +81 -4
  7. package/dist/labels.d.ts +2 -0
  8. package/dist/labels.d.ts.map +1 -1
  9. package/dist/labels.js +5 -0
  10. package/dist/lexicon-resolve.d.ts.map +1 -1
  11. package/dist/lexicon-resolve.js +27 -112
  12. package/dist/lexicons/com/atproto/label/defs.json +75 -0
  13. package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
  14. package/dist/lexicons/com/atproto/repo/strongRef.json +24 -0
  15. package/dist/lexicons/dev/hatk/createRecord.json +40 -0
  16. package/dist/lexicons/dev/hatk/createReport.json +48 -0
  17. package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
  18. package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
  19. package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
  20. package/dist/lexicons/dev/hatk/describeLabels.json +31 -0
  21. package/dist/lexicons/dev/hatk/getFeed.json +30 -0
  22. package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
  23. package/dist/lexicons/dev/hatk/getRecord.json +26 -0
  24. package/dist/lexicons/dev/hatk/getRecords.json +32 -0
  25. package/dist/lexicons/dev/hatk/putPreference.json +28 -0
  26. package/dist/lexicons/dev/hatk/putRecord.json +41 -0
  27. package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
  28. package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
  29. package/dist/oauth/server.d.ts.map +1 -1
  30. package/dist/oauth/server.js +2 -1
  31. package/dist/pds-proxy.d.ts.map +1 -1
  32. package/dist/pds-proxy.js +15 -0
  33. package/dist/server-init.d.ts.map +1 -1
  34. package/dist/server-init.js +3 -2
  35. package/dist/server.d.ts.map +1 -1
  36. package/dist/server.js +91 -13
  37. package/dist/templates/feed.tpl +14 -0
  38. package/dist/templates/hook.tpl +5 -0
  39. package/dist/templates/label.tpl +15 -0
  40. package/dist/templates/og.tpl +17 -0
  41. package/dist/templates/seed.tpl +11 -0
  42. package/dist/templates/setup.tpl +5 -0
  43. package/dist/templates/test-feed.tpl +19 -0
  44. package/dist/templates/test-xrpc.tpl +19 -0
  45. package/dist/templates/xrpc.tpl +41 -0
  46. package/package.json +3 -2
  47. package/public/admin.html +133 -0
  48. package/dist/cloudflare/container.d.ts +0 -73
  49. package/dist/cloudflare/container.d.ts.map +0 -1
  50. package/dist/cloudflare/container.js +0 -232
  51. package/dist/cloudflare/hooks.d.ts +0 -33
  52. package/dist/cloudflare/hooks.d.ts.map +0 -1
  53. package/dist/cloudflare/hooks.js +0 -40
  54. package/dist/cloudflare/init.d.ts +0 -27
  55. package/dist/cloudflare/init.d.ts.map +0 -1
  56. package/dist/cloudflare/init.js +0 -103
  57. package/dist/cloudflare/worker.d.ts +0 -27
  58. package/dist/cloudflare/worker.d.ts.map +0 -1
  59. package/dist/cloudflare/worker.js +0 -54
  60. package/dist/database/adapters/d1.d.ts +0 -56
  61. package/dist/database/adapters/d1.d.ts.map +0 -1
  62. package/dist/database/adapters/d1.js +0 -108
  63. package/dist/db.d.ts +0 -134
  64. package/dist/db.d.ts.map +0 -1
  65. package/dist/db.js +0 -1327
  66. package/dist/fts.d.ts +0 -20
  67. package/dist/fts.d.ts.map +0 -1
  68. package/dist/fts.js +0 -767
  69. package/dist/oauth/hooks.d.ts +0 -10
  70. package/dist/oauth/hooks.d.ts.map +0 -1
  71. package/dist/oauth/hooks.js +0 -40
  72. package/dist/schema.d.ts +0 -59
  73. package/dist/schema.d.ts.map +0 -1
  74. package/dist/schema.js +0 -387
  75. package/dist/test-browser.d.ts +0 -14
  76. package/dist/test-browser.d.ts.map +0 -1
  77. package/dist/test-browser.js +0 -26
@@ -0,0 +1,29 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.describeFeeds",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "List available feeds.",
8
+ "output": {
9
+ "encoding": "application/json",
10
+ "schema": {
11
+ "type": "object",
12
+ "properties": {
13
+ "feeds": {
14
+ "type": "array",
15
+ "items": {
16
+ "type": "object",
17
+ "required": ["name", "label"],
18
+ "properties": {
19
+ "name": { "type": "string" },
20
+ "label": { "type": "string" }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.describeLabels",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "List available label definitions.",
8
+ "output": {
9
+ "encoding": "application/json",
10
+ "schema": {
11
+ "type": "object",
12
+ "properties": {
13
+ "definitions": {
14
+ "type": "array",
15
+ "items": {
16
+ "type": "object",
17
+ "required": ["identifier", "severity", "blurs", "defaultSetting"],
18
+ "properties": {
19
+ "identifier": { "type": "string" },
20
+ "severity": { "type": "string" },
21
+ "blurs": { "type": "string" },
22
+ "defaultSetting": { "type": "string" }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.getFeed",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "Retrieve a named feed of items.",
8
+ "parameters": {
9
+ "type": "params",
10
+ "required": ["feed"],
11
+ "properties": {
12
+ "feed": { "type": "string", "description": "Feed name" },
13
+ "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 30 },
14
+ "cursor": { "type": "string" }
15
+ }
16
+ },
17
+ "output": {
18
+ "encoding": "application/json",
19
+ "schema": {
20
+ "type": "object",
21
+ "required": ["items"],
22
+ "properties": {
23
+ "items": { "type": "array", "items": { "type": "unknown" } },
24
+ "cursor": { "type": "string" }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.getPreferences",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "Get all preferences for the authenticated user.",
8
+ "output": {
9
+ "encoding": "application/json",
10
+ "schema": {
11
+ "type": "object",
12
+ "properties": {
13
+ "preferences": { "type": "unknown" }
14
+ }
15
+ }
16
+ }
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.getRecord",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "Fetch a single record by AT URI.",
8
+ "parameters": {
9
+ "type": "params",
10
+ "required": ["uri"],
11
+ "properties": {
12
+ "uri": { "type": "string", "format": "at-uri" }
13
+ }
14
+ },
15
+ "output": {
16
+ "encoding": "application/json",
17
+ "schema": {
18
+ "type": "object",
19
+ "properties": {
20
+ "record": { "type": "unknown" }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.getRecords",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "List records from a collection with optional filters.",
8
+ "parameters": {
9
+ "type": "params",
10
+ "required": ["collection"],
11
+ "properties": {
12
+ "collection": { "type": "string" },
13
+ "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 },
14
+ "cursor": { "type": "string" },
15
+ "sort": { "type": "string" },
16
+ "order": { "type": "string" }
17
+ }
18
+ },
19
+ "output": {
20
+ "encoding": "application/json",
21
+ "schema": {
22
+ "type": "object",
23
+ "required": ["items"],
24
+ "properties": {
25
+ "items": { "type": "array", "items": { "type": "unknown" } },
26
+ "cursor": { "type": "string" }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.putPreference",
4
+ "defs": {
5
+ "main": {
6
+ "type": "procedure",
7
+ "description": "Set a single preference by key.",
8
+ "input": {
9
+ "encoding": "application/json",
10
+ "schema": {
11
+ "type": "object",
12
+ "required": ["key", "value"],
13
+ "properties": {
14
+ "key": { "type": "string" },
15
+ "value": { "type": "unknown" }
16
+ }
17
+ }
18
+ },
19
+ "output": {
20
+ "encoding": "application/json",
21
+ "schema": {
22
+ "type": "object",
23
+ "properties": {}
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.putRecord",
4
+ "defs": {
5
+ "main": {
6
+ "type": "procedure",
7
+ "description": "Create or update a record via the user's PDS.",
8
+ "input": {
9
+ "encoding": "application/json",
10
+ "schema": {
11
+ "type": "object",
12
+ "required": ["collection", "rkey", "record"],
13
+ "properties": {
14
+ "collection": { "type": "string" },
15
+ "rkey": { "type": "string" },
16
+ "record": { "type": "unknown" },
17
+ "repo": { "type": "string", "format": "did" }
18
+ }
19
+ }
20
+ },
21
+ "output": {
22
+ "encoding": "application/json",
23
+ "schema": {
24
+ "type": "object",
25
+ "properties": {
26
+ "uri": { "type": "string", "format": "at-uri" },
27
+ "cid": { "type": "string", "format": "cid" },
28
+ "commit": {
29
+ "type": "object",
30
+ "properties": {
31
+ "cid": { "type": "string", "format": "cid" },
32
+ "rev": { "type": "string" }
33
+ }
34
+ },
35
+ "validationStatus": { "type": "string" }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.searchRecords",
4
+ "defs": {
5
+ "main": {
6
+ "type": "query",
7
+ "description": "Full-text search across a collection.",
8
+ "parameters": {
9
+ "type": "params",
10
+ "required": ["collection", "q"],
11
+ "properties": {
12
+ "collection": { "type": "string" },
13
+ "q": { "type": "string", "description": "Search query" },
14
+ "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 },
15
+ "cursor": { "type": "string" },
16
+ "fuzzy": { "type": "boolean", "default": true }
17
+ }
18
+ },
19
+ "output": {
20
+ "encoding": "application/json",
21
+ "schema": {
22
+ "type": "object",
23
+ "required": ["items"],
24
+ "properties": {
25
+ "items": { "type": "array", "items": { "type": "unknown" } },
26
+ "cursor": { "type": "string" }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "lexicon": 1,
3
+ "id": "dev.hatk.uploadBlob",
4
+ "defs": {
5
+ "main": {
6
+ "type": "procedure",
7
+ "description": "Upload a blob via the user's PDS.",
8
+ "input": {
9
+ "encoding": "*/*"
10
+ },
11
+ "output": {
12
+ "encoding": "application/json",
13
+ "schema": {
14
+ "type": "object",
15
+ "required": ["blob"],
16
+ "properties": {
17
+ "blob": { "type": "blob" }
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
@@ -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;AA2E/C,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrG;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;;;;;;;;;;;EAqBxE;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;EAO/E;AAED,wBAAgB,OAAO;;;;;;;;;;;;;;;;;;;;;;EAWtB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;EAcpE;AAID,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CA2ItD;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,CAShF;AAID,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoGtF;AAID,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAyHrG;AAID,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,GAAG,CAAC,CAUd;AA0JD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtF,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmEpF;AAID,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA0BjC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AA4E/C,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrG;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;;;;;;;;;;;EAqBxE;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;EAO/E;AAED,wBAAgB,OAAO;;;;;;;;;;;;;;;;;;;;;;EAWtB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;EAcpE;AAID,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CA2ItD;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,CAShF;AAID,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoGtF;AAID,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAyHrG;AAID,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,GAAG,CAAC,CAUd;AA0JD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtF,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAoEpF;AAID,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA0BjC"}
@@ -4,7 +4,7 @@ import { parseDpopProof, createDpopProof } from "./dpop.js";
4
4
  import { initSession } from "./session.js";
5
5
  import { resolveClient, validateRedirectUri, isLoopbackClient } from "./client.js";
6
6
  import { discoverAuthServer, resolveHandle } from "./discovery.js";
7
- import { getServerKey, storeServerKey, storeOAuthRequest, getOAuthRequest, deleteOAuthRequest, storeAuthCode, consumeAuthCode, storeSession, checkAndStoreDpopJti, cleanupExpiredOAuth, storeRefreshToken, getRefreshToken, revokeRefreshToken, } from "./db.js";
7
+ import { getServerKey, storeServerKey, storeOAuthRequest, getOAuthRequest, deleteOAuthRequest, storeAuthCode, consumeAuthCode, storeSession, deleteSession, checkAndStoreDpopJti, cleanupExpiredOAuth, storeRefreshToken, getRefreshToken, revokeRefreshToken, } from "./db.js";
8
8
  import { emit } from "../logger.js";
9
9
  import { querySQL } from "../database/db.js";
10
10
  import { fireOnLoginHook } from "../hooks.js";
@@ -621,6 +621,7 @@ export async function refreshPdsSession(config, session) {
621
621
  did: session.did,
622
622
  pds_endpoint: session.pds_endpoint,
623
623
  });
624
+ await deleteSession(session.did);
624
625
  return null;
625
626
  }
626
627
  const tokenData = await tokenRes.json();
@@ -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;AAS9C,qBAAa,UAAW,SAAQ,KAAK;IAE1B,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAIlB;AAED,qBAAa,sBAAuB,SAAQ,UAAU;;CAIrD;AAoHD,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,CAiCzC;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,CA8BzC;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"}
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;gBAAd,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAIlB;AAED,qBAAa,sBAAuB,SAAQ,UAAU;;CAIrD;AAoHD,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,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
@@ -6,6 +6,7 @@ import { validateRecord } from '@bigmoves/lexicon';
6
6
  import { getLexiconArray } from "./database/schema.js";
7
7
  import { insertRecord, deleteRecord as dbDeleteRecord } from "./database/db.js";
8
8
  import { emit } from "./logger.js";
9
+ import { runLabelRules } from "./labels.js";
9
10
  export class ProxyError extends Error {
10
11
  status;
11
12
  constructor(status, message) {
@@ -117,6 +118,13 @@ export async function pdsCreateRecord(oauthConfig, viewer, input) {
117
118
  throw new ProxyError(pdsRes.status, String(pdsRes.body.error || 'PDS write failed'));
118
119
  try {
119
120
  await insertRecord(input.collection, String(pdsRes.body.uri), String(pdsRes.body.cid), viewer.did, input.record);
121
+ await runLabelRules({
122
+ uri: String(pdsRes.body.uri),
123
+ cid: String(pdsRes.body.cid),
124
+ did: viewer.did,
125
+ collection: input.collection,
126
+ value: input.record,
127
+ });
120
128
  }
121
129
  catch (err) {
122
130
  emit('pds-proxy', 'local_index_error', {
@@ -171,6 +179,13 @@ export async function pdsPutRecord(oauthConfig, viewer, input) {
171
179
  throw new ProxyError(pdsRes.status, String(pdsRes.body.error || 'PDS write failed'));
172
180
  try {
173
181
  await insertRecord(input.collection, String(pdsRes.body.uri), String(pdsRes.body.cid), viewer.did, input.record);
182
+ await runLabelRules({
183
+ uri: String(pdsRes.body.uri),
184
+ cid: String(pdsRes.body.cid),
185
+ did: viewer.did,
186
+ collection: input.collection,
187
+ value: input.record,
188
+ });
174
189
  }
175
190
  catch (err) {
176
191
  emit('pds-proxy', 'local_index_error', { op: 'putRecord', error: err instanceof Error ? err.message : String(err) });
@@ -1 +1 @@
1
- {"version":3,"file":"server-init.d.ts","sourceRoot":"","sources":["../src/server-init.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DjG"}
1
+ {"version":3,"file":"server-init.d.ts","sourceRoot":"","sources":["../src/server-init.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DjG"}
@@ -3,7 +3,7 @@ import { log } from "./logger.js";
3
3
  import { scanServerDir } from "./scanner.js";
4
4
  import { registerFeed, listFeeds } from "./feeds.js";
5
5
  import { registerXrpcHandler, listXrpc } from "./xrpc.js";
6
- import { registerLabelModule, getLabelDefinitions } from "./labels.js";
6
+ import { registerLabelModule, getLabelDefinitions, clearLabels } from "./labels.js";
7
7
  import { registerOgHandler } from "./opengraph.js";
8
8
  import { registerHook } from "./hooks.js";
9
9
  import { runSetupHandler } from "./setup.js";
@@ -40,7 +40,8 @@ export async function initServer(serverDir, opts) {
40
40
  for (const entry of scanned.hooks) {
41
41
  registerHook(entry.mod.event, entry.mod.handler);
42
42
  }
43
- // 5. Register labels
43
+ // 5. Register labels (clear first for hot-reload)
44
+ clearLabels();
44
45
  for (const entry of scanned.labels) {
45
46
  registerLabelModule(entry.name, entry.mod);
46
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAqDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA0B9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAwH3F;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,CA8xB5F;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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA0B9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAuK3F;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,CA6zB5F;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,7 +1,7 @@
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, } from "./database/db.js";
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
5
  import { executeFeed, listFeeds } from "./feeds.js";
6
6
  import { executeXrpc, InvalidRequestError, NotFoundError, registerCoreXrpcHandler } from "./xrpc.js";
7
7
  import { resolveRecords } from "./hydrate.js";
@@ -16,8 +16,8 @@ import { pdsCreateRecord, pdsDeleteRecord, pdsPutRecord, pdsUploadBlob, ProxyErr
16
16
  import { json, jsonError, cors, withCors, file, notFound } from "./response.js";
17
17
  import { serve } from "./adapter.js";
18
18
  import { renderPage } from "./renderer.js";
19
- function scopeMissingResponse(acceptEncoding) {
20
- const res = withCors(jsonError(401, 'ScopeMissingError', acceptEncoding));
19
+ function scopeMissingResponse(acceptEncoding, handle) {
20
+ const res = withCors(json({ error: 'ScopeMissingError', ...(handle ? { handle } : {}) }, 401, acceptEncoding));
21
21
  res.headers.append('Set-Cookie', clearSessionCookieHeader());
22
22
  return res;
23
23
  }
@@ -154,6 +154,53 @@ export function registerCoreHandlers(collections, oauth) {
154
154
  throw new InvalidRequestError('Authentication required');
155
155
  return pdsUploadBlob(oauth, viewer, input, 'application/octet-stream');
156
156
  });
157
+ registerCoreXrpcHandler('dev.hatk.createReport', async (_params, _cursor, _limit, viewer, input) => {
158
+ if (!viewer)
159
+ throw new InvalidRequestError('Authentication required');
160
+ const body = input;
161
+ if (!body.subject)
162
+ throw new InvalidRequestError('Missing subject');
163
+ if (!body.label || typeof body.label !== 'string')
164
+ throw new InvalidRequestError('Missing or invalid label');
165
+ const defs = getLabelDefinitions();
166
+ if (!defs.some((d) => d.identifier === body.label)) {
167
+ throw new InvalidRequestError(`Unknown label: ${body.label}`);
168
+ }
169
+ if (body.reason && body.reason.length > 2000) {
170
+ throw new InvalidRequestError('Reason must be 2000 characters or less');
171
+ }
172
+ let subjectUri;
173
+ let subjectDid;
174
+ if (body.subject.uri) {
175
+ subjectUri = body.subject.uri;
176
+ const match = body.subject.uri.match(/^at:\/\/(did:[^/]+)/);
177
+ if (!match)
178
+ throw new InvalidRequestError('Invalid subject URI');
179
+ subjectDid = match[1];
180
+ }
181
+ else if (body.subject.did) {
182
+ subjectUri = `at://${body.subject.did}`;
183
+ subjectDid = body.subject.did;
184
+ }
185
+ else {
186
+ throw new InvalidRequestError('Subject must have uri or did');
187
+ }
188
+ const result = await insertReport({
189
+ subjectUri,
190
+ subjectDid,
191
+ label: body.label,
192
+ reason: body.reason,
193
+ reportedBy: viewer.did,
194
+ });
195
+ return {
196
+ id: result.id,
197
+ subject: body.subject,
198
+ label: body.label,
199
+ reason: body.reason || null,
200
+ reportedBy: viewer.did,
201
+ createdAt: new Date().toISOString(),
202
+ };
203
+ });
157
204
  }
158
205
  }
159
206
  /**
@@ -561,7 +608,38 @@ export function createHandler(config) {
561
608
  heapTotal: `${(mem.heapTotal / 1024 / 1024).toFixed(1)} MiB`,
562
609
  external: `${(mem.external / 1024 / 1024).toFixed(1)} MiB`,
563
610
  };
564
- return withCors(json({ repos: counts, duckdb: dbInfo, node, collections: collectionCounts }, 200, acceptEncoding));
611
+ const openReports = await getOpenReportCount();
612
+ return withCors(json({ repos: counts, duckdb: dbInfo, node, collections: collectionCounts, openReports }, 200, acceptEncoding));
613
+ }
614
+ // GET /admin/reports — list reports
615
+ if (url.pathname === '/admin/reports' && request.method === 'GET') {
616
+ const denied = requireAdmin(viewer, acceptEncoding);
617
+ if (denied)
618
+ return denied;
619
+ const status = url.searchParams.get('status') || 'open';
620
+ const label = url.searchParams.get('label') || undefined;
621
+ const limit = parseInt(url.searchParams.get('limit') || '50');
622
+ const offset = parseInt(url.searchParams.get('offset') || '0');
623
+ const result = await queryReports({ status, label, limit, offset });
624
+ return withCors(json(result, 200, acceptEncoding));
625
+ }
626
+ // POST /admin/reports/resolve — resolve or dismiss a report
627
+ if (url.pathname === '/admin/reports/resolve' && request.method === 'POST') {
628
+ const denied = requireAdmin(viewer, acceptEncoding);
629
+ if (denied)
630
+ return denied;
631
+ const { id, action } = JSON.parse(await request.text());
632
+ if (!id || !action)
633
+ return withCors(jsonError(400, 'Missing id or action', acceptEncoding));
634
+ if (action !== 'resolve' && action !== 'dismiss')
635
+ return withCors(jsonError(400, 'Action must be resolve or dismiss', acceptEncoding));
636
+ const report = await resolveReport(id, action === 'resolve' ? 'resolved' : 'dismissed', viewer.did);
637
+ if (!report)
638
+ return withCors(jsonError(404, 'Report not found or already resolved', acceptEncoding));
639
+ if (action === 'resolve') {
640
+ await insertLabels([{ src: 'admin', uri: report.subjectUri, val: report.label }]);
641
+ }
642
+ return withCors(json({ ok: true }, 200, acceptEncoding));
565
643
  }
566
644
  // GET /admin/info/:did — repo status info
567
645
  if (url.pathname.startsWith('/admin/info/did:')) {
@@ -757,9 +835,9 @@ export function createHandler(config) {
757
835
  }
758
836
  catch (err) {
759
837
  if (err instanceof ScopeMissingProxyError)
760
- return scopeMissingResponse(acceptEncoding);
838
+ return scopeMissingResponse(acceptEncoding, viewer?.handle);
761
839
  if (err instanceof ProxyError)
762
- return withCors(jsonError(err.status, err.message, acceptEncoding));
840
+ return withCors(json({ error: err.message, ...(viewer?.handle ? { handle: viewer.handle } : {}) }, err.status, acceptEncoding));
763
841
  throw err;
764
842
  }
765
843
  }
@@ -774,9 +852,9 @@ export function createHandler(config) {
774
852
  }
775
853
  catch (err) {
776
854
  if (err instanceof ScopeMissingProxyError)
777
- return scopeMissingResponse(acceptEncoding);
855
+ return scopeMissingResponse(acceptEncoding, viewer?.handle);
778
856
  if (err instanceof ProxyError)
779
- return withCors(jsonError(err.status, err.message, acceptEncoding));
857
+ return withCors(json({ error: err.message, ...(viewer?.handle ? { handle: viewer.handle } : {}) }, err.status, acceptEncoding));
780
858
  throw err;
781
859
  }
782
860
  }
@@ -791,9 +869,9 @@ export function createHandler(config) {
791
869
  }
792
870
  catch (err) {
793
871
  if (err instanceof ScopeMissingProxyError)
794
- return scopeMissingResponse(acceptEncoding);
872
+ return scopeMissingResponse(acceptEncoding, viewer?.handle);
795
873
  if (err instanceof ProxyError)
796
- return withCors(jsonError(err.status, err.message, acceptEncoding));
874
+ return withCors(json({ error: err.message, ...(viewer?.handle ? { handle: viewer.handle } : {}) }, err.status, acceptEncoding));
797
875
  throw err;
798
876
  }
799
877
  }
@@ -809,9 +887,9 @@ export function createHandler(config) {
809
887
  }
810
888
  catch (err) {
811
889
  if (err instanceof ScopeMissingProxyError)
812
- return scopeMissingResponse(acceptEncoding);
890
+ return scopeMissingResponse(acceptEncoding, viewer?.handle);
813
891
  if (err instanceof ProxyError)
814
- return withCors(jsonError(err.status, err.message, acceptEncoding));
892
+ return withCors(json({ error: err.message, ...(viewer?.handle ? { handle: viewer.handle } : {}) }, err.status, acceptEncoding));
815
893
  throw err;
816
894
  }
817
895
  }
@@ -873,7 +951,7 @@ export function createHandler(config) {
873
951
  }
874
952
  catch (err) {
875
953
  if (err instanceof ScopeMissingProxyError)
876
- return scopeMissingResponse(acceptEncoding);
954
+ return scopeMissingResponse(acceptEncoding, viewer?.handle);
877
955
  if (err instanceof InvalidRequestError) {
878
956
  return withCors(jsonError(err.status, err.errorName || err.message, acceptEncoding));
879
957
  }
@@ -0,0 +1,14 @@
1
+ import { defineFeed } from '$hatk'
2
+
3
+ export default defineFeed({
4
+ collection: 'your.collection.here',
5
+ label: '{{Name}}',
6
+
7
+ async generate(ctx) {
8
+ const { rows, cursor } = await ctx.paginate<{ uri: string }>(
9
+ `SELECT uri, cid, indexed_at FROM "your.collection.here"`,
10
+ )
11
+
12
+ return ctx.ok({ uris: rows.map((r) => r.uri), cursor })
13
+ },
14
+ })
@@ -0,0 +1,5 @@
1
+ import { defineHook } from '$hatk'
2
+
3
+ export default defineHook('{{name}}', async (ctx) => {
4
+ // Hook logic here
5
+ })
@@ -0,0 +1,15 @@
1
+ import { defineLabel } from '$hatk'
2
+
3
+ export default defineLabel({
4
+ definition: {
5
+ identifier: '{{name}}',
6
+ severity: 'inform',
7
+ blurs: 'none',
8
+ defaultSetting: 'warn',
9
+ locales: [{ lang: 'en', name: '{{Name}}', description: 'Description here' }],
10
+ },
11
+ async evaluate(ctx) {
12
+ // Return array of label identifiers to apply, or empty array
13
+ return []
14
+ },
15
+ })
@@ -0,0 +1,17 @@
1
+ import type { OpengraphContext, OpengraphResult } from '@hatk/hatk/opengraph'
2
+
3
+ export default {
4
+ path: '/og/{{name}}/:id',
5
+ async generate(ctx: OpengraphContext): Promise<OpengraphResult> {
6
+ const { db, params } = ctx
7
+ return {
8
+ element: {
9
+ type: 'div',
10
+ props: {
11
+ style: { display: 'flex', width: '100%', height: '100%', background: '#080b12', color: 'white', alignItems: 'center', justifyContent: 'center' },
12
+ children: params.id,
13
+ },
14
+ },
15
+ }
16
+ },
17
+ }
@@ -0,0 +1,11 @@
1
+ import { seed } from '$hatk'
2
+
3
+ const { createAccount, createRecord } = seed()
4
+
5
+ const alice = await createAccount('alice.test')
6
+
7
+ // await createRecord(alice, 'your.collection.here', {
8
+ // field: 'value',
9
+ // }, { rkey: 'my-record' })
10
+
11
+ console.log('\n[seed] Done!')