@hatk/hatk 0.0.1-alpha.9 → 0.0.1-alpha.90

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 (218) hide show
  1. package/dist/adapter.d.ts +19 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/adapter.js +113 -0
  4. package/dist/backfill.d.ts +29 -2
  5. package/dist/backfill.d.ts.map +1 -1
  6. package/dist/backfill.js +137 -51
  7. package/dist/car.d.ts +20 -0
  8. package/dist/car.d.ts.map +1 -1
  9. package/dist/car.js +108 -0
  10. package/dist/cli.js +247 -1043
  11. package/dist/config.d.ts +145 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +61 -8
  14. package/dist/database/adapter-factory.d.ts +6 -0
  15. package/dist/database/adapter-factory.d.ts.map +1 -0
  16. package/dist/database/adapter-factory.js +20 -0
  17. package/dist/database/adapters/duckdb-search.d.ts +12 -0
  18. package/dist/database/adapters/duckdb-search.d.ts.map +1 -0
  19. package/dist/database/adapters/duckdb-search.js +27 -0
  20. package/dist/database/adapters/duckdb.d.ts +25 -0
  21. package/dist/database/adapters/duckdb.d.ts.map +1 -0
  22. package/dist/database/adapters/duckdb.js +161 -0
  23. package/dist/database/adapters/sqlite-search.d.ts +16 -0
  24. package/dist/database/adapters/sqlite-search.d.ts.map +1 -0
  25. package/dist/database/adapters/sqlite-search.js +76 -0
  26. package/dist/database/adapters/sqlite.d.ts +18 -0
  27. package/dist/database/adapters/sqlite.d.ts.map +1 -0
  28. package/dist/database/adapters/sqlite.js +88 -0
  29. package/dist/{db.d.ts → database/db.d.ts} +68 -6
  30. package/dist/database/db.d.ts.map +1 -0
  31. package/dist/database/db.js +1775 -0
  32. package/dist/database/dialect.d.ts +45 -0
  33. package/dist/database/dialect.d.ts.map +1 -0
  34. package/dist/database/dialect.js +72 -0
  35. package/dist/{fts.d.ts → database/fts.d.ts} +7 -0
  36. package/dist/database/fts.d.ts.map +1 -0
  37. package/dist/{fts.js → database/fts.js} +122 -34
  38. package/dist/database/index.d.ts +7 -0
  39. package/dist/database/index.d.ts.map +1 -0
  40. package/dist/database/index.js +6 -0
  41. package/dist/database/ports.d.ts +50 -0
  42. package/dist/database/ports.d.ts.map +1 -0
  43. package/dist/database/ports.js +1 -0
  44. package/dist/{schema.d.ts → database/schema.d.ts} +16 -3
  45. package/dist/database/schema.d.ts.map +1 -0
  46. package/dist/{schema.js → database/schema.js} +126 -44
  47. package/dist/dev-entry.d.ts +8 -0
  48. package/dist/dev-entry.d.ts.map +1 -0
  49. package/dist/dev-entry.js +127 -0
  50. package/dist/feeds.d.ts +26 -8
  51. package/dist/feeds.d.ts.map +1 -1
  52. package/dist/feeds.js +72 -16
  53. package/dist/hooks.d.ts +102 -0
  54. package/dist/hooks.d.ts.map +1 -0
  55. package/dist/hooks.js +186 -0
  56. package/dist/hydrate.d.ts +49 -6
  57. package/dist/hydrate.d.ts.map +1 -1
  58. package/dist/hydrate.js +21 -20
  59. package/dist/indexer.d.ts +156 -3
  60. package/dist/indexer.d.ts.map +1 -1
  61. package/dist/indexer.js +539 -94
  62. package/dist/jetstream.d.ts +118 -0
  63. package/dist/jetstream.d.ts.map +1 -0
  64. package/dist/jetstream.js +225 -0
  65. package/dist/labels.d.ts +36 -0
  66. package/dist/labels.d.ts.map +1 -1
  67. package/dist/labels.js +71 -6
  68. package/dist/lex-types.d.ts +2 -0
  69. package/dist/lex-types.d.ts.map +1 -1
  70. package/dist/lexicon-resolve.d.ts.map +1 -1
  71. package/dist/lexicon-resolve.js +27 -112
  72. package/dist/lexicons/com/atproto/label/defs.json +75 -0
  73. package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
  74. package/dist/lexicons/com/atproto/repo/strongRef.json +21 -0
  75. package/dist/lexicons/dev/hatk/applyWrites.json +87 -0
  76. package/dist/lexicons/dev/hatk/createRecord.json +40 -0
  77. package/dist/lexicons/dev/hatk/createReport.json +48 -0
  78. package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
  79. package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
  80. package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
  81. package/dist/lexicons/dev/hatk/describeLabels.json +45 -0
  82. package/dist/lexicons/dev/hatk/getFeed.json +30 -0
  83. package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
  84. package/dist/lexicons/dev/hatk/getRecord.json +26 -0
  85. package/dist/lexicons/dev/hatk/getRecords.json +32 -0
  86. package/dist/lexicons/dev/hatk/putPreference.json +28 -0
  87. package/dist/lexicons/dev/hatk/putRecord.json +41 -0
  88. package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
  89. package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
  90. package/dist/logger.d.ts +29 -0
  91. package/dist/logger.d.ts.map +1 -1
  92. package/dist/logger.js +29 -0
  93. package/dist/main.js +198 -75
  94. package/dist/mst.d.ts +15 -0
  95. package/dist/mst.d.ts.map +1 -1
  96. package/dist/mst.js +13 -0
  97. package/dist/oauth/db.d.ts +16 -1
  98. package/dist/oauth/db.d.ts.map +1 -1
  99. package/dist/oauth/db.js +74 -19
  100. package/dist/oauth/discovery.d.ts +10 -0
  101. package/dist/oauth/discovery.d.ts.map +1 -1
  102. package/dist/oauth/discovery.js +54 -2
  103. package/dist/oauth/server.d.ts +93 -1
  104. package/dist/oauth/server.d.ts.map +1 -1
  105. package/dist/oauth/server.js +416 -39
  106. package/dist/oauth/service-describe.d.ts +42 -0
  107. package/dist/oauth/service-describe.d.ts.map +1 -0
  108. package/dist/oauth/service-describe.js +108 -0
  109. package/dist/oauth/session.d.ts +32 -0
  110. package/dist/oauth/session.d.ts.map +1 -0
  111. package/dist/oauth/session.js +131 -0
  112. package/dist/opengraph.d.ts +10 -0
  113. package/dist/opengraph.d.ts.map +1 -1
  114. package/dist/opengraph.js +94 -42
  115. package/dist/pds-proxy.d.ts +82 -0
  116. package/dist/pds-proxy.d.ts.map +1 -0
  117. package/dist/pds-proxy.js +356 -0
  118. package/dist/private-collections.d.ts +13 -0
  119. package/dist/private-collections.d.ts.map +1 -0
  120. package/dist/private-collections.js +27 -0
  121. package/dist/push.d.ts +54 -0
  122. package/dist/push.d.ts.map +1 -0
  123. package/dist/push.js +367 -0
  124. package/dist/renderer.d.ts +27 -0
  125. package/dist/renderer.d.ts.map +1 -0
  126. package/dist/renderer.js +46 -0
  127. package/dist/resolve-hatk.d.ts +6 -0
  128. package/dist/resolve-hatk.d.ts.map +1 -0
  129. package/dist/resolve-hatk.js +20 -0
  130. package/dist/response.d.ts +16 -0
  131. package/dist/response.d.ts.map +1 -0
  132. package/dist/response.js +69 -0
  133. package/dist/scanner.d.ts +21 -0
  134. package/dist/scanner.d.ts.map +1 -0
  135. package/dist/scanner.js +88 -0
  136. package/dist/seed.d.ts +19 -0
  137. package/dist/seed.d.ts.map +1 -1
  138. package/dist/seed.js +43 -4
  139. package/dist/server-init.d.ts +8 -0
  140. package/dist/server-init.d.ts.map +1 -0
  141. package/dist/server-init.js +62 -0
  142. package/dist/server.d.ts +34 -3
  143. package/dist/server.d.ts.map +1 -1
  144. package/dist/server.js +1021 -649
  145. package/dist/setup.d.ts +28 -1
  146. package/dist/setup.d.ts.map +1 -1
  147. package/dist/setup.js +50 -3
  148. package/dist/spaces/blob.d.ts +51 -0
  149. package/dist/spaces/blob.d.ts.map +1 -0
  150. package/dist/spaces/blob.js +111 -0
  151. package/dist/spaces/credential.d.ts +62 -0
  152. package/dist/spaces/credential.d.ts.map +1 -0
  153. package/dist/spaces/credential.js +184 -0
  154. package/dist/spaces/engine.d.ts +97 -0
  155. package/dist/spaces/engine.d.ts.map +1 -0
  156. package/dist/spaces/engine.js +559 -0
  157. package/dist/spaces/guard.d.ts +41 -0
  158. package/dist/spaces/guard.d.ts.map +1 -0
  159. package/dist/spaces/guard.js +79 -0
  160. package/dist/spaces/identity.d.ts +37 -0
  161. package/dist/spaces/identity.d.ts.map +1 -0
  162. package/dist/spaces/identity.js +88 -0
  163. package/dist/spaces/index.d.ts +55 -0
  164. package/dist/spaces/index.d.ts.map +1 -0
  165. package/dist/spaces/index.js +133 -0
  166. package/dist/spaces/notify.d.ts +51 -0
  167. package/dist/spaces/notify.d.ts.map +1 -0
  168. package/dist/spaces/notify.js +121 -0
  169. package/dist/spaces/records.d.ts +37 -0
  170. package/dist/spaces/records.d.ts.map +1 -0
  171. package/dist/spaces/records.js +63 -0
  172. package/dist/spaces/store.d.ts +51 -0
  173. package/dist/spaces/store.d.ts.map +1 -0
  174. package/dist/spaces/store.js +99 -0
  175. package/dist/spaces/uri.d.ts +60 -0
  176. package/dist/spaces/uri.d.ts.map +1 -0
  177. package/dist/spaces/uri.js +97 -0
  178. package/dist/spaces/verify.d.ts +39 -0
  179. package/dist/spaces/verify.d.ts.map +1 -0
  180. package/dist/spaces/verify.js +87 -0
  181. package/dist/spaces/viewer.d.ts +51 -0
  182. package/dist/spaces/viewer.d.ts.map +1 -0
  183. package/dist/spaces/viewer.js +167 -0
  184. package/dist/spaces/visibility.d.ts +57 -0
  185. package/dist/spaces/visibility.d.ts.map +1 -0
  186. package/dist/spaces/visibility.js +81 -0
  187. package/dist/templates/feed.tpl +18 -0
  188. package/dist/templates/hook.tpl +5 -0
  189. package/dist/templates/label.tpl +15 -0
  190. package/dist/templates/og.tpl +17 -0
  191. package/dist/templates/seed.tpl +11 -0
  192. package/dist/templates/setup.tpl +5 -0
  193. package/dist/templates/test-feed.tpl +19 -0
  194. package/dist/templates/test-xrpc.tpl +19 -0
  195. package/dist/templates/xrpc.tpl +53 -0
  196. package/dist/test.d.ts +3 -1
  197. package/dist/test.d.ts.map +1 -1
  198. package/dist/test.js +60 -36
  199. package/dist/views.js +1 -1
  200. package/dist/vite-plugin.d.ts +1 -1
  201. package/dist/vite-plugin.d.ts.map +1 -1
  202. package/dist/vite-plugin.js +254 -66
  203. package/dist/xrpc.d.ts +101 -12
  204. package/dist/xrpc.d.ts.map +1 -1
  205. package/dist/xrpc.js +255 -55
  206. package/package.json +21 -9
  207. package/public/admin-auth.js +271 -306
  208. package/public/admin.html +177 -61
  209. package/dist/db.d.ts.map +0 -1
  210. package/dist/db.js +0 -1361
  211. package/dist/fts.d.ts.map +0 -1
  212. package/dist/oauth/hooks.d.ts +0 -10
  213. package/dist/oauth/hooks.d.ts.map +0 -1
  214. package/dist/oauth/hooks.js +0 -40
  215. package/dist/schema.d.ts.map +0 -1
  216. package/dist/test-browser.d.ts +0 -14
  217. package/dist/test-browser.d.ts.map +0 -1
  218. package/dist/test-browser.js +0 -26
@@ -1,42 +1,59 @@
1
1
  import { readFileSync, readdirSync, statSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
+ import { DUCKDB_DIALECT } from "./dialect.js";
3
4
  // Convert camelCase to snake_case
4
5
  export function toSnakeCase(str) {
5
6
  return str.replace(/([A-Z])/g, '_$1').toLowerCase();
6
7
  }
7
- function mapType(prop) {
8
+ /**
9
+ * The columns every generated table carries before any lexicon field. A record
10
+ * property with one of these names — `fyi.opensocial.space` has a `uri` — would
11
+ * otherwise produce a CREATE TABLE with a duplicate column and fail at boot.
12
+ * It is stored under `record_<name>` instead; `originalName` still carries the
13
+ * lexicon's spelling, which is what every reshaped row is keyed by.
14
+ */
15
+ const ENVELOPE_COLUMNS = new Set(['uri', 'cid', 'did', 'space', 'indexed_at', 'handle']);
16
+ export function columnName(fieldName) {
17
+ const snake = toSnakeCase(fieldName);
18
+ return ENVELOPE_COLUMNS.has(snake) ? `record_${snake}` : snake;
19
+ }
20
+ // Quote a column name to avoid conflicts with SQL reserved words
21
+ export function q(name) {
22
+ return `"${name}"`;
23
+ }
24
+ function mapType(prop, dialect) {
8
25
  if (prop.type === 'string') {
9
26
  if (prop.format === 'datetime')
10
- return { duckdbType: 'TIMESTAMP', isRef: false };
27
+ return { sqlType: dialect.typeMap.timestamp, isRef: false, isJson: false };
11
28
  if (prop.format === 'at-uri')
12
- return { duckdbType: 'TEXT', isRef: true };
13
- return { duckdbType: 'TEXT', isRef: false };
29
+ return { sqlType: dialect.typeMap.text, isRef: true, isJson: false };
30
+ return { sqlType: dialect.typeMap.text, isRef: false, isJson: false };
14
31
  }
15
32
  if (prop.type === 'integer')
16
- return { duckdbType: 'INTEGER', isRef: false };
33
+ return { sqlType: dialect.typeMap.integer, isRef: false, isJson: false };
17
34
  if (prop.type === 'boolean')
18
- return { duckdbType: 'BOOLEAN', isRef: false };
35
+ return { sqlType: dialect.typeMap.boolean, isRef: false, isJson: false };
19
36
  if (prop.type === 'bytes')
20
- return { duckdbType: 'BLOB', isRef: false };
37
+ return { sqlType: dialect.typeMap.blob, isRef: false, isJson: false };
21
38
  if (prop.type === 'cid-link')
22
- return { duckdbType: 'TEXT', isRef: false };
39
+ return { sqlType: dialect.typeMap.text, isRef: false, isJson: false };
23
40
  if (prop.type === 'array')
24
- return { duckdbType: 'JSON', isRef: false };
41
+ return { sqlType: dialect.jsonType, isRef: false, isJson: true };
25
42
  if (prop.type === 'blob')
26
- return { duckdbType: 'JSON', isRef: false };
43
+ return { sqlType: dialect.jsonType, isRef: false, isJson: true };
27
44
  if (prop.type === 'union')
28
- return { duckdbType: 'JSON', isRef: false };
45
+ return { sqlType: dialect.jsonType, isRef: false, isJson: true };
29
46
  if (prop.type === 'unknown')
30
- return { duckdbType: 'JSON', isRef: false };
47
+ return { sqlType: dialect.jsonType, isRef: false, isJson: true };
31
48
  if (prop.type === 'object')
32
- return { duckdbType: 'JSON', isRef: false };
49
+ return { sqlType: dialect.jsonType, isRef: false, isJson: true };
33
50
  if (prop.type === 'ref') {
34
51
  // strongRef contains { uri, cid } — handled specially in generateTableSchema
35
52
  if (prop.ref === 'com.atproto.repo.strongRef')
36
- return { duckdbType: 'STRONG_REF', isRef: true };
37
- return { duckdbType: 'JSON', isRef: false };
53
+ return { sqlType: 'STRONG_REF', isRef: true, isJson: false };
54
+ return { sqlType: dialect.jsonType, isRef: false, isJson: true };
38
55
  }
39
- return { duckdbType: 'TEXT', isRef: false };
56
+ return { sqlType: dialect.typeMap.text, isRef: false, isJson: false };
40
57
  }
41
58
  // Recursively find all .json files in a directory
42
59
  function findJsonFiles(dir) {
@@ -63,6 +80,20 @@ export function loadLexicons(lexiconsDir) {
63
80
  }
64
81
  return lexicons;
65
82
  }
83
+ /**
84
+ * Lexicons the validator cannot model but hatk legitimately keeps.
85
+ *
86
+ * A space type is how the indexer learns which collections a space holds, and
87
+ * a permission set is what an OAuth scope resolves through; both are real
88
+ * lexicons an app vendors on purpose. `validateLexicons` reports each as an
89
+ * unknown definition type, which would read as a fatal schema error at boot.
90
+ * Only these two are set aside — anything else unknown is still a mistake the
91
+ * validator should refuse.
92
+ */
93
+ const UNMODELLED_DEF_TYPES = new Set(['space', 'permission-set']);
94
+ export function validatableLexicons(lexicons) {
95
+ return [...lexicons.values()].filter((lex) => !UNMODELLED_DEF_TYPES.has(lex.defs?.main?.type));
96
+ }
66
97
  /**
67
98
  * Discover collections by scanning lexicons for record-type definitions.
68
99
  */
@@ -121,7 +152,7 @@ function resolveRefDef(ref, defs, lexicons) {
121
152
  return lexicons?.get(ref)?.defs?.main || null;
122
153
  }
123
154
  /** Resolve a single union ref to a branch schema */
124
- function resolveUnionBranch(ref, collection, fieldName, defs, lexicons) {
155
+ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons, dialect) {
125
156
  let branchDef = null;
126
157
  let branchName;
127
158
  let fullType;
@@ -153,7 +184,10 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons) {
153
184
  let arrayField;
154
185
  let wrapperField;
155
186
  let propSource = branchDef.properties;
156
- const branchRequired = new Set(branchDef.required || []);
187
+ // `required` has to travel with propSource: once the columns come from the
188
+ // item (or wrapper target) def, the outer branch's `required` describes the
189
+ // wrapper property, not these columns.
190
+ let branchRequired = new Set(branchDef.required || []);
157
191
  // Check for single-property wrapper patterns
158
192
  const propEntries = Object.entries(branchDef.properties);
159
193
  if (propEntries.length === 1) {
@@ -166,6 +200,7 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons) {
166
200
  isArray = true;
167
201
  arrayField = onlyField;
168
202
  propSource = itemDef.properties;
203
+ branchRequired = new Set(itemDef.required || []);
169
204
  }
170
205
  }
171
206
  else if (onlyProp.type === 'ref' && onlyProp.ref) {
@@ -174,6 +209,7 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons) {
174
209
  if (refDef?.type === 'object' && refDef.properties) {
175
210
  wrapperField = onlyField;
176
211
  propSource = refDef.properties;
212
+ branchRequired = new Set(refDef.required || []);
177
213
  }
178
214
  }
179
215
  }
@@ -181,21 +217,22 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons) {
181
217
  const tableName = `"${collection}__${snakeField}_${branchName}"`;
182
218
  const columns = [];
183
219
  for (const [propName, prop] of Object.entries(propSource)) {
184
- const { duckdbType, isRef } = mapType(prop);
220
+ const { sqlType, isRef, isJson } = mapType(prop, dialect);
185
221
  // Skip STRONG_REF expansion in branch tables — treat as JSON
186
- const finalType = duckdbType === 'STRONG_REF' ? 'JSON' : duckdbType;
222
+ const finalType = sqlType === 'STRONG_REF' ? dialect.jsonType : sqlType;
187
223
  columns.push({
188
224
  name: toSnakeCase(propName),
189
225
  originalName: propName,
190
- duckdbType: finalType,
226
+ sqlType: finalType,
191
227
  notNull: branchRequired.has(propName),
192
- isRef: finalType !== 'JSON' && isRef,
228
+ isRef: finalType !== dialect.jsonType && isRef,
229
+ isJson: isJson || sqlType === 'STRONG_REF',
193
230
  });
194
231
  }
195
232
  return { type: fullType, branchName, tableName, columns, isArray, arrayField, wrapperField };
196
233
  }
197
234
  // Generate a TableSchema from a lexicon record definition
198
- export function generateTableSchema(nsid, lexicon, lexicons) {
235
+ export function generateTableSchema(nsid, lexicon, lexicons, dialect = DUCKDB_DIALECT) {
199
236
  const mainDef = lexicon.defs?.main;
200
237
  if (!mainDef || mainDef.type !== 'record') {
201
238
  throw new Error(`Lexicon ${nsid} does not define a record type`);
@@ -214,7 +251,7 @@ export function generateTableSchema(nsid, lexicon, lexicons) {
214
251
  if (p.type === 'union' && p.refs) {
215
252
  const branches = [];
216
253
  for (const ref of p.refs) {
217
- const branch = resolveUnionBranch(ref, nsid, fieldName, lexicon.defs, lexicons);
254
+ const branch = resolveUnionBranch(ref, nsid, fieldName, lexicon.defs, lexicons, dialect);
218
255
  if (branch)
219
256
  branches.push(branch);
220
257
  }
@@ -223,11 +260,12 @@ export function generateTableSchema(nsid, lexicon, lexicons) {
223
260
  }
224
261
  // Still add the JSON column for the raw union value
225
262
  columns.push({
226
- name: toSnakeCase(fieldName),
263
+ name: columnName(fieldName),
227
264
  originalName: fieldName,
228
- duckdbType: 'JSON',
265
+ sqlType: dialect.jsonType,
229
266
  notNull: required.has(fieldName),
230
267
  isRef: false,
268
+ isJson: true,
231
269
  });
232
270
  continue;
233
271
  }
@@ -238,13 +276,14 @@ export function generateTableSchema(nsid, lexicon, lexicons) {
238
276
  const childColumns = [];
239
277
  const itemRequired = new Set(p.items?.required || lexicon.defs?.[p.items?.ref?.slice(1)]?.required || []);
240
278
  for (const [itemField, itemProp] of Object.entries(itemProps)) {
241
- const { duckdbType, isRef } = mapType(itemProp);
279
+ const { sqlType, isRef, isJson } = mapType(itemProp, dialect);
242
280
  childColumns.push({
243
281
  name: toSnakeCase(itemField),
244
282
  originalName: itemField,
245
- duckdbType,
283
+ sqlType,
246
284
  notNull: itemRequired.has(itemField),
247
285
  isRef,
286
+ isJson,
248
287
  });
249
288
  }
250
289
  const snakeField = toSnakeCase(fieldName);
@@ -257,31 +296,34 @@ export function generateTableSchema(nsid, lexicon, lexicons) {
257
296
  continue;
258
297
  }
259
298
  }
260
- const { duckdbType, isRef } = mapType(p);
261
- if (duckdbType === 'STRONG_REF') {
299
+ const { sqlType, isRef, isJson } = mapType(p, dialect);
300
+ if (sqlType === 'STRONG_REF') {
262
301
  // Expand strongRef into two columns: {name}_uri and {name}_cid
263
302
  columns.push({
264
303
  name: toSnakeCase(fieldName) + '_uri',
265
304
  originalName: fieldName,
266
- duckdbType: 'TEXT',
305
+ sqlType: dialect.typeMap.text,
267
306
  notNull: required.has(fieldName),
268
307
  isRef: true,
308
+ isJson: false,
269
309
  });
270
310
  columns.push({
271
311
  name: toSnakeCase(fieldName) + '_cid',
272
312
  originalName: fieldName + '__cid',
273
- duckdbType: 'TEXT',
313
+ sqlType: dialect.typeMap.text,
274
314
  notNull: required.has(fieldName),
275
315
  isRef: false,
316
+ isJson: false,
276
317
  });
277
318
  }
278
319
  else {
279
320
  columns.push({
280
- name: toSnakeCase(fieldName),
321
+ name: columnName(fieldName),
281
322
  originalName: fieldName,
282
- duckdbType,
323
+ sqlType,
283
324
  notNull: required.has(fieldName),
284
325
  isRef,
326
+ isJson,
285
327
  });
286
328
  }
287
329
  }
@@ -296,26 +338,35 @@ export function generateTableSchema(nsid, lexicon, lexicons) {
296
338
  };
297
339
  }
298
340
  // Generate CREATE TABLE SQL from a TableSchema
299
- export function generateCreateTableSQL(schema) {
341
+ export function generateCreateTableSQL(schema, dialect = DUCKDB_DIALECT) {
342
+ // `space` is the permissioned space a row came from, and NULL for everything
343
+ // off the firehose. It is the only per-row visibility marker in the schema:
344
+ // a space record is readable by whoever the space's authority admits, so no
345
+ // read may serve one without knowing who is asking. NULL means "public repo
346
+ // data", which is what every existing row is.
300
347
  const lines = [
301
348
  ' uri TEXT PRIMARY KEY',
302
349
  ' cid TEXT',
303
350
  ' did TEXT NOT NULL',
304
- ' indexed_at TIMESTAMP NOT NULL',
351
+ ' space TEXT',
352
+ ` indexed_at ${dialect.timestampType} NOT NULL`,
305
353
  ];
306
354
  for (const col of schema.columns) {
307
355
  const nullable = col.notNull ? ' NOT NULL' : '';
308
- lines.push(` ${col.name} ${col.duckdbType}${nullable}`);
356
+ lines.push(` ${q(col.name)} ${col.sqlType}${nullable}`);
309
357
  }
310
358
  const createTable = `CREATE TABLE IF NOT EXISTS ${schema.tableName} (\n${lines.join(',\n')}\n);`;
311
359
  const prefix = schema.collection.replace(/\./g, '_');
312
360
  const indexes = [
313
361
  `CREATE INDEX IF NOT EXISTS idx_${prefix}_indexed ON ${schema.tableName}(indexed_at DESC);`,
314
362
  `CREATE INDEX IF NOT EXISTS idx_${prefix}_author ON ${schema.tableName}(did);`,
363
+ // Every read that serves space rows filters on this column, and every read
364
+ // that does not still tests it for NULL.
365
+ `CREATE INDEX IF NOT EXISTS idx_${prefix}_space ON ${schema.tableName}(space);`,
315
366
  ];
316
367
  // Index ref columns for hydration lookups
317
368
  for (const refCol of schema.refColumns) {
318
- indexes.push(`CREATE INDEX IF NOT EXISTS idx_${prefix}_${refCol} ON ${schema.tableName}(${refCol});`);
369
+ indexes.push(`CREATE INDEX IF NOT EXISTS idx_${prefix}_${refCol} ON ${schema.tableName}(${q(refCol)});`);
319
370
  }
320
371
  // Child table DDL
321
372
  const childDDL = [];
@@ -323,16 +374,16 @@ export function generateCreateTableSQL(schema) {
323
374
  const childLines = [' parent_uri TEXT NOT NULL', ' parent_did TEXT NOT NULL'];
324
375
  for (const col of child.columns) {
325
376
  const nullable = col.notNull ? ' NOT NULL' : '';
326
- childLines.push(` ${col.name} ${col.duckdbType}${nullable}`);
377
+ childLines.push(` ${q(col.name)} ${col.sqlType}${nullable}`);
327
378
  }
328
379
  childDDL.push(`CREATE TABLE IF NOT EXISTS ${child.tableName} (\n${childLines.join(',\n')}\n);`);
329
380
  const childPrefix = `${prefix}__${toSnakeCase(child.fieldName)}`;
330
381
  childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${childPrefix}_parent ON ${child.tableName}(parent_uri);`);
331
382
  childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${childPrefix}_did ON ${child.tableName}(parent_did);`);
332
383
  for (const col of child.columns) {
333
- if (col.duckdbType === 'JSON' || col.duckdbType === 'BLOB')
384
+ if (col.isJson || col.sqlType === 'BLOB')
334
385
  continue;
335
- childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${childPrefix}_${col.name} ON ${child.tableName}(${col.name});`);
386
+ childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${childPrefix}_${col.name} ON ${child.tableName}(${q(col.name)});`);
336
387
  }
337
388
  }
338
389
  // Union branch table DDL
@@ -341,18 +392,49 @@ export function generateCreateTableSQL(schema) {
341
392
  const branchLines = [' parent_uri TEXT NOT NULL', ' parent_did TEXT NOT NULL'];
342
393
  for (const col of branch.columns) {
343
394
  const nullable = col.notNull ? ' NOT NULL' : '';
344
- branchLines.push(` ${col.name} ${col.duckdbType}${nullable}`);
395
+ branchLines.push(` ${q(col.name)} ${col.sqlType}${nullable}`);
345
396
  }
346
397
  childDDL.push(`CREATE TABLE IF NOT EXISTS ${branch.tableName} (\n${branchLines.join(',\n')}\n);`);
347
398
  const branchPrefix = branch.tableName.replace(/"/g, '').replace(/\./g, '_');
348
399
  childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${branchPrefix}_parent ON ${branch.tableName}(parent_uri);`);
349
400
  childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${branchPrefix}_did ON ${branch.tableName}(parent_did);`);
350
401
  for (const col of branch.columns) {
351
- if (col.duckdbType === 'JSON' || col.duckdbType === 'BLOB')
402
+ if (col.isJson || col.sqlType === 'BLOB')
352
403
  continue;
353
- childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${branchPrefix}_${col.name} ON ${branch.tableName}(${col.name});`);
404
+ childDDL.push(`CREATE INDEX IF NOT EXISTS idx_${branchPrefix}_${col.name} ON ${branch.tableName}(${q(col.name)});`);
354
405
  }
355
406
  }
356
407
  }
357
408
  return [createTable, ...indexes, ...childDDL].join('\n');
358
409
  }
410
+ /**
411
+ * Build table schemas and DDL from lexicons and collections.
412
+ * Shared by main.ts (server boot) and cli.ts (hatk schema command).
413
+ */
414
+ export function buildSchemas(lexicons, collections, dialect = DUCKDB_DIALECT) {
415
+ const schemas = [];
416
+ const ddlStatements = [];
417
+ for (const nsid of collections) {
418
+ const lexicon = lexicons.get(nsid);
419
+ if (!lexicon) {
420
+ const genericDDL = `CREATE TABLE IF NOT EXISTS "${nsid}" (
421
+ uri TEXT PRIMARY KEY,
422
+ cid TEXT,
423
+ did TEXT NOT NULL,
424
+ space TEXT,
425
+ indexed_at ${dialect.timestampType} NOT NULL,
426
+ data ${dialect.jsonType}
427
+ );
428
+ CREATE INDEX IF NOT EXISTS idx_${nsid.replace(/\./g, '_')}_indexed ON "${nsid}"(indexed_at DESC);
429
+ CREATE INDEX IF NOT EXISTS idx_${nsid.replace(/\./g, '_')}_author ON "${nsid}"(did);
430
+ CREATE INDEX IF NOT EXISTS idx_${nsid.replace(/\./g, '_')}_space ON "${nsid}"(space);`;
431
+ schemas.push({ collection: nsid, tableName: `"${nsid}"`, columns: [], refColumns: [], children: [], unions: [] });
432
+ ddlStatements.push(genericDDL);
433
+ continue;
434
+ }
435
+ const schema = generateTableSchema(nsid, lexicon, lexicons, dialect);
436
+ schemas.push(schema);
437
+ ddlStatements.push(generateCreateTableSQL(schema, dialect));
438
+ }
439
+ return { schemas, ddlStatements };
440
+ }
@@ -0,0 +1,8 @@
1
+ export declare const handler: (request: Request) => Promise<Response>;
2
+ /** Re-scan server/ directory to pick up changed handlers in dev mode. */
3
+ export declare function reloadServer(): Promise<void>;
4
+ export { renderPage } from './renderer.ts';
5
+ export { getRenderer } from './renderer.ts';
6
+ export { callXrpc } from './xrpc.ts';
7
+ export { parseSessionCookie, getSessionCookieName } from './oauth/session.ts';
8
+ //# sourceMappingURL=dev-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-entry.d.ts","sourceRoot":"","sources":["../src/dev-entry.ts"],"names":[],"mappings":"AAiIA,eAAO,MAAM,OAAO,yCAKlB,CAAA;AAEF,yEAAyE;AACzE,wBAAsB,YAAY,kBAEjC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Dev mode entry point — loaded through Vite's module runner.
3
+ * Boots hatk infrastructure and exports the fetch handler.
4
+ */
5
+ import { loadConfig } from "./config.js";
6
+ import { validatableLexicons, loadLexicons, storeLexicons, discoverCollections, buildSchemas, } from "./database/schema.js";
7
+ import { discoverViews } from "./views.js";
8
+ import { initDatabase, migrateSchema, getSchemaDump } from "./database/db.js";
9
+ import { createAdapter } from "./database/adapter-factory.js";
10
+ import { getDialect } from "./database/dialect.js";
11
+ import { setSearchPort } from "./database/fts.js";
12
+ import { configureRelay, configureCdn, configureOAuth } from "./xrpc.js";
13
+ import { initOAuth } from "./oauth/server.js";
14
+ import { initServer } from "./server-init.js";
15
+ import { createHandler, registerCoreHandlers } from "./server.js";
16
+ import { setPrivateCollections } from "./private-collections.js";
17
+ import { auxCursorKey, startAuxIndexer, startIndexer, sweepReferences } from "./indexer.js";
18
+ import { getCursor } from "./database/db.js";
19
+ import { runBackfill, configurePlc } from "./backfill.js";
20
+ import { rebuildAllIndexes } from "./database/fts.js";
21
+ import { relayHttpUrl } from "./config.js";
22
+ import { validateLexicons } from '@bigmoves/lexicon';
23
+ import { log } from "./logger.js";
24
+ import { mkdirSync } from 'node:fs';
25
+ import { dirname, resolve } from 'node:path';
26
+ process.env.DEV_MODE = '1';
27
+ // Boot sequence (mirrors main.ts but exports handler instead of starting server)
28
+ const configPath = 'hatk.config.ts';
29
+ const configDir = dirname(resolve(configPath));
30
+ const config = await loadConfig(configPath);
31
+ configureRelay(config.relay);
32
+ configurePlc(config.plc);
33
+ configureCdn(config.cdn);
34
+ const lexicons = loadLexicons(resolve(configDir, 'lexicons'));
35
+ const lexiconErrors = validateLexicons(validatableLexicons(lexicons));
36
+ if (lexiconErrors) {
37
+ for (const [nsid, errors] of Object.entries(lexiconErrors)) {
38
+ for (const err of errors)
39
+ console.error(`Invalid lexicon ${nsid}: ${err}`);
40
+ }
41
+ throw new Error('Invalid lexicons');
42
+ }
43
+ storeLexicons(lexicons);
44
+ const collections = config.collections.length > 0 ? config.collections : discoverCollections(lexicons);
45
+ discoverViews();
46
+ const engineDialect = getDialect(config.databaseEngine);
47
+ const { schemas, ddlStatements } = buildSchemas(lexicons, collections, engineDialect);
48
+ if (config.database !== ':memory:') {
49
+ mkdirSync(dirname(config.database), { recursive: true });
50
+ }
51
+ const { adapter, searchPort } = await createAdapter(config.databaseEngine);
52
+ setSearchPort(searchPort);
53
+ await initDatabase(adapter, config.database, schemas, ddlStatements);
54
+ await migrateSchema(schemas);
55
+ // Write db/schema.sql
56
+ try {
57
+ const { mkdirSync, writeFileSync } = await import('node:fs');
58
+ const schemaDir = resolve(configDir, 'db');
59
+ mkdirSync(schemaDir, { recursive: true });
60
+ const schemaDump = await getSchemaDump();
61
+ writeFileSync(resolve(schemaDir, 'schema.sql'), `-- This file is auto-generated by hatk on startup. Do not edit.\n-- Database engine: ${config.databaseEngine}\n\n${schemaDump}\n`);
62
+ log(`[hatk] Schema written to db/schema.sql`);
63
+ }
64
+ catch { }
65
+ // Initialize handlers from server/ directory
66
+ await initServer(resolve(configDir, 'server'));
67
+ // Register built-in dev.hatk.* handlers so callXrpc() can find them
68
+ setPrivateCollections(config.privateCollections);
69
+ registerCoreHandlers(collections, config.oauth);
70
+ configureOAuth(config.oauth);
71
+ if (config.oauth) {
72
+ await initOAuth(config.oauth, config.plc, config.relay);
73
+ }
74
+ // Start indexer
75
+ const collectionSet = new Set(collections);
76
+ // Same escape hatch as main.ts: boot from live instead of the saved cursor.
77
+ const ignoreSavedCursor = Boolean(process.env.HATK_IGNORE_SAVED_CURSOR);
78
+ if (ignoreSavedCursor)
79
+ log('[dev] HATK_IGNORE_SAVED_CURSOR set — starting indexer from live');
80
+ const cursor = ignoreSavedCursor ? null : await getCursor('relay');
81
+ startIndexer({
82
+ relayUrl: config.relay,
83
+ plcUrl: config.plc,
84
+ collections: collectionSet,
85
+ signalCollections: config.backfill.signalCollections ? new Set(config.backfill.signalCollections) : undefined,
86
+ references: config.backfill.references,
87
+ pinnedRepos: config.backfill.repos ? new Set(config.backfill.repos) : undefined,
88
+ cursor,
89
+ fetchTimeout: config.backfill.fetchTimeout,
90
+ maxRetries: config.backfill.maxRetries,
91
+ parallelism: config.backfill.parallelism,
92
+ ftsRebuildInterval: config.ftsRebuildInterval,
93
+ });
94
+ void sweepReferences();
95
+ for (const relayUrl of config.relays) {
96
+ const auxCursor = ignoreSavedCursor ? null : await getCursor(auxCursorKey(relayUrl));
97
+ startAuxIndexer({ relayUrl, collections: collectionSet, cursor: auxCursor });
98
+ }
99
+ // Run backfill in background (no restart in dev mode)
100
+ runBackfill({
101
+ pdsUrl: relayHttpUrl(config.relay),
102
+ extraPdsUrls: config.relays.map(relayHttpUrl),
103
+ plcUrl: config.plc,
104
+ collections: collectionSet,
105
+ config: config.backfill,
106
+ })
107
+ .then(() => rebuildAllIndexes(Array.from(collectionSet)))
108
+ .catch((err) => console.error('[backfill]', err.message));
109
+ // Export the handler for Vite middleware
110
+ export const handler = createHandler({
111
+ collections: Array.from(collectionSet),
112
+ publicDir: null, // Vite serves static assets in dev
113
+ oauth: config.oauth,
114
+ admins: config.admins,
115
+ });
116
+ /** Re-scan server/ directory to pick up changed handlers in dev mode. */
117
+ export async function reloadServer() {
118
+ await initServer(resolve(configDir, 'server'));
119
+ }
120
+ export { renderPage } from "./renderer.js";
121
+ export { getRenderer } from "./renderer.js";
122
+ export { callXrpc } from "./xrpc.js";
123
+ export { parseSessionCookie, getSessionCookieName } from "./oauth/session.js";
124
+ log(`[hatk] Dev server ready`);
125
+ log(` Relay: ${config.relay}${config.relays.length ? ` (+ ${config.relays.join(', ')})` : ''}`);
126
+ log(` Database: ${config.database}`);
127
+ log(` Collections: ${collections.join(', ')}`);
package/dist/feeds.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { HydrateContext, Row } from './hydrate.ts';
1
+ import type { BaseContext, Row } from './hydrate.ts';
2
2
  import type { Checked } from './lex-types.ts';
3
- export type { HydrateContext, Row };
3
+ export type { BaseContext, Row };
4
4
  export interface FeedResult {
5
5
  uris: string[];
6
6
  cursor?: string;
@@ -16,7 +16,9 @@ export interface PaginateResult<T> {
16
16
  }
17
17
  export interface FeedContext {
18
18
  db: {
19
- query: (sql: string, params?: any[]) => Promise<any[]>;
19
+ query: (sql: string, params?: unknown[]) => Promise<unknown[]>;
20
+ /** Raw SQL with the permissioned-space guard off. See `spaces/guard.ts`. */
21
+ unfiltered: (sql: string, params?: unknown[]) => Promise<unknown[]>;
20
22
  };
21
23
  params: Record<string, string>;
22
24
  cursor?: string;
@@ -34,6 +36,18 @@ export interface FeedContext {
34
36
  paginate: <T extends {
35
37
  uri: string;
36
38
  }>(sql: string, opts?: PaginateOpts) => Promise<PaginateResult<T>>;
39
+ /**
40
+ * The permissioned-space gate, for SQL this feed builds without `paginate`.
41
+ *
42
+ * `paginate` applies it already. This is for a feed that runs its own query
43
+ * — a raw `ctx.db.query` over a record table has to carry it, or it serves
44
+ * space rows to whoever asks. See `spaceFilterSql`.
45
+ */
46
+ spaceFilter: (alias: string, startIdx: number) => {
47
+ sql: string;
48
+ params: string[];
49
+ nextIdx: number;
50
+ };
37
51
  }
38
52
  type FeedGenerate = (ctx: FeedContext & {
39
53
  ok: (value: FeedResult) => Checked<FeedResult>;
@@ -43,17 +57,17 @@ type FeedOpts = {
43
57
  view?: string;
44
58
  label: string;
45
59
  generate: FeedGenerate;
46
- hydrate?: (ctx: HydrateContext<any>) => Promise<unknown[]>;
60
+ hydrate?: (ctx: BaseContext, items: Row<any>[]) => Promise<unknown[]>;
47
61
  } | {
48
62
  collection?: never;
49
63
  view?: never;
50
64
  label: string;
51
65
  generate: FeedGenerate;
52
- hydrate: (ctx: HydrateContext<any>) => Promise<unknown[]>;
66
+ hydrate: (ctx: BaseContext, items: Row<any>[]) => Promise<unknown[]>;
53
67
  };
54
68
  export declare function createPaginate(deps: {
55
69
  db: {
56
- query: (sql: string, params?: any[]) => Promise<any[]>;
70
+ query: (sql: string, params?: unknown[]) => Promise<unknown[]>;
57
71
  };
58
72
  cursor?: string;
59
73
  limit: number;
@@ -70,14 +84,18 @@ export declare function defineFeed(opts: FeedOpts): {
70
84
  collection: string;
71
85
  view?: string;
72
86
  label: string;
73
- hydrate?: (ctx: HydrateContext<any>) => Promise<unknown[]>;
87
+ hydrate?: (ctx: BaseContext, items: Row<any>[]) => Promise<unknown[]>;
88
+ __type: "feed";
74
89
  } | {
75
90
  generate: (ctx: any) => Promise<Checked<FeedResult>>;
76
91
  collection?: never;
77
92
  view?: never;
78
93
  label: string;
79
- hydrate: (ctx: HydrateContext<any>) => Promise<unknown[]>;
94
+ hydrate: (ctx: BaseContext, items: Row<any>[]) => Promise<unknown[]>;
95
+ __type: "feed";
80
96
  };
97
+ /** Register a single feed from a scanned server/ module. */
98
+ export declare function registerFeed(name: string, generator: ReturnType<typeof defineFeed>): void;
81
99
  export declare function initFeeds(feedsDir: string): Promise<void>;
82
100
  /** Execute a feed and run its hydrate pipeline if present. */
83
101
  export declare function executeFeed(name: string, params: Record<string, string>, cursor: string | undefined, limit: number, viewer?: {
@@ -1 +1 @@
1
- {"version":3,"file":"feeds.d.ts","sourceRoot":"","sources":["../src/feeds.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,YAAY,EAAE,cAAc,EAAE,GAAG,EAAE,CAAA;AAEnC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;KAAE,CAAA;IAC9D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC9B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACzE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC9C,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IAC7D,QAAQ,EAAE,CAAC,CAAC,SAAS;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;CACtG;AAkBD,KAAK,YAAY,GAAG,CAClB,GAAG,EAAE,WAAW,GAAG;IAAE,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;CAAE,KAClE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;AAEjC,KAAK,QAAQ,GACT;IACE,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,YAAY,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CAC3D,GACD;IACE,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,YAAY,CAAA;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CAC1D,CAAA;AAEL,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,EAAE,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;KAAE,CAAA;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAC1E,IACe,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,MAAM,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAmDvG;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ;oBACL,GAAG;gBA3ErB,MAAM;WACX,MAAM;WACN,MAAM;cAEH,CAAC,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;;oBAuE5B,GAAG;iBApEpB,KAAK;WACX,KAAK;WACL,MAAM;aAEJ,CAAC,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;EAiE9D;AAID,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8D/D;AAED,8DAA8D;AAC9D,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAC9B,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAczE;AAED,wBAAgB,SAAS,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAE7D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD"}
1
+ {"version":3,"file":"feeds.d.ts","sourceRoot":"","sources":["../src/feeds.ts"],"names":[],"mappings":"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"}