@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.
- package/dist/cli.js +16 -553
- package/dist/database/adapters/sqlite.d.ts.map +1 -1
- package/dist/database/adapters/sqlite.js +2 -1
- package/dist/database/db.d.ts +23 -0
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +81 -4
- package/dist/labels.d.ts +2 -0
- package/dist/labels.d.ts.map +1 -1
- package/dist/labels.js +5 -0
- package/dist/lexicon-resolve.d.ts.map +1 -1
- package/dist/lexicon-resolve.js +27 -112
- package/dist/lexicons/com/atproto/label/defs.json +75 -0
- package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
- package/dist/lexicons/com/atproto/repo/strongRef.json +24 -0
- package/dist/lexicons/dev/hatk/createRecord.json +40 -0
- package/dist/lexicons/dev/hatk/createReport.json +48 -0
- package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
- package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
- package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
- package/dist/lexicons/dev/hatk/describeLabels.json +31 -0
- package/dist/lexicons/dev/hatk/getFeed.json +30 -0
- package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
- package/dist/lexicons/dev/hatk/getRecord.json +26 -0
- package/dist/lexicons/dev/hatk/getRecords.json +32 -0
- package/dist/lexicons/dev/hatk/putPreference.json +28 -0
- package/dist/lexicons/dev/hatk/putRecord.json +41 -0
- package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
- package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
- package/dist/oauth/server.d.ts.map +1 -1
- package/dist/oauth/server.js +2 -1
- package/dist/pds-proxy.d.ts.map +1 -1
- package/dist/pds-proxy.js +15 -0
- package/dist/server-init.d.ts.map +1 -1
- package/dist/server-init.js +3 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +91 -13
- package/dist/templates/feed.tpl +14 -0
- package/dist/templates/hook.tpl +5 -0
- package/dist/templates/label.tpl +15 -0
- package/dist/templates/og.tpl +17 -0
- package/dist/templates/seed.tpl +11 -0
- package/dist/templates/setup.tpl +5 -0
- package/dist/templates/test-feed.tpl +19 -0
- package/dist/templates/test-xrpc.tpl +19 -0
- package/dist/templates/xrpc.tpl +41 -0
- package/package.json +3 -2
- package/public/admin.html +133 -0
- package/dist/cloudflare/container.d.ts +0 -73
- package/dist/cloudflare/container.d.ts.map +0 -1
- package/dist/cloudflare/container.js +0 -232
- package/dist/cloudflare/hooks.d.ts +0 -33
- package/dist/cloudflare/hooks.d.ts.map +0 -1
- package/dist/cloudflare/hooks.js +0 -40
- package/dist/cloudflare/init.d.ts +0 -27
- package/dist/cloudflare/init.d.ts.map +0 -1
- package/dist/cloudflare/init.js +0 -103
- package/dist/cloudflare/worker.d.ts +0 -27
- package/dist/cloudflare/worker.d.ts.map +0 -1
- package/dist/cloudflare/worker.js +0 -54
- package/dist/database/adapters/d1.d.ts +0 -56
- package/dist/database/adapters/d1.d.ts.map +0 -1
- package/dist/database/adapters/d1.js +0 -108
- package/dist/db.d.ts +0 -134
- package/dist/db.d.ts.map +0 -1
- package/dist/db.js +0 -1327
- package/dist/fts.d.ts +0 -20
- package/dist/fts.d.ts.map +0 -1
- package/dist/fts.js +0 -767
- package/dist/oauth/hooks.d.ts +0 -10
- package/dist/oauth/hooks.d.ts.map +0 -1
- package/dist/oauth/hooks.js +0 -40
- package/dist/schema.d.ts +0 -59
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js +0 -387
- package/dist/test-browser.d.ts +0 -14
- package/dist/test-browser.d.ts.map +0 -1
- package/dist/test-browser.js +0 -26
|
@@ -0,0 +1,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;
|
|
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"}
|
package/dist/oauth/server.js
CHANGED
|
@@ -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();
|
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;
|
|
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,
|
|
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"}
|
package/dist/server-init.js
CHANGED
|
@@ -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
|
}
|
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":"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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,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!')
|