@hatk/hatk 0.0.1-alpha.40 → 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 (89) 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/dev-entry.d.ts.map +1 -1
  8. package/dist/dev-entry.js +2 -1
  9. package/dist/hooks.d.ts +24 -3
  10. package/dist/hooks.d.ts.map +1 -1
  11. package/dist/hooks.js +34 -7
  12. package/dist/indexer.d.ts +2 -0
  13. package/dist/indexer.d.ts.map +1 -1
  14. package/dist/indexer.js +17 -0
  15. package/dist/labels.d.ts +2 -0
  16. package/dist/labels.d.ts.map +1 -1
  17. package/dist/labels.js +5 -0
  18. package/dist/lexicon-resolve.d.ts.map +1 -1
  19. package/dist/lexicon-resolve.js +27 -112
  20. package/dist/lexicons/com/atproto/label/defs.json +75 -0
  21. package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
  22. package/dist/lexicons/com/atproto/repo/strongRef.json +24 -0
  23. package/dist/lexicons/dev/hatk/createRecord.json +40 -0
  24. package/dist/lexicons/dev/hatk/createReport.json +48 -0
  25. package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
  26. package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
  27. package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
  28. package/dist/lexicons/dev/hatk/describeLabels.json +31 -0
  29. package/dist/lexicons/dev/hatk/getFeed.json +30 -0
  30. package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
  31. package/dist/lexicons/dev/hatk/getRecord.json +26 -0
  32. package/dist/lexicons/dev/hatk/getRecords.json +32 -0
  33. package/dist/lexicons/dev/hatk/putPreference.json +28 -0
  34. package/dist/lexicons/dev/hatk/putRecord.json +41 -0
  35. package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
  36. package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
  37. package/dist/main.js +2 -1
  38. package/dist/oauth/server.d.ts.map +1 -1
  39. package/dist/oauth/server.js +3 -2
  40. package/dist/pds-proxy.d.ts.map +1 -1
  41. package/dist/pds-proxy.js +15 -0
  42. package/dist/server-init.d.ts.map +1 -1
  43. package/dist/server-init.js +3 -2
  44. package/dist/server.d.ts.map +1 -1
  45. package/dist/server.js +91 -13
  46. package/dist/templates/feed.tpl +14 -0
  47. package/dist/templates/hook.tpl +5 -0
  48. package/dist/templates/label.tpl +15 -0
  49. package/dist/templates/og.tpl +17 -0
  50. package/dist/templates/seed.tpl +11 -0
  51. package/dist/templates/setup.tpl +5 -0
  52. package/dist/templates/test-feed.tpl +19 -0
  53. package/dist/templates/test-xrpc.tpl +19 -0
  54. package/dist/templates/xrpc.tpl +41 -0
  55. package/dist/xrpc.d.ts +14 -0
  56. package/dist/xrpc.d.ts.map +1 -1
  57. package/dist/xrpc.js +27 -0
  58. package/package.json +3 -2
  59. package/public/admin.html +133 -0
  60. package/dist/cloudflare/container.d.ts +0 -73
  61. package/dist/cloudflare/container.d.ts.map +0 -1
  62. package/dist/cloudflare/container.js +0 -232
  63. package/dist/cloudflare/hooks.d.ts +0 -33
  64. package/dist/cloudflare/hooks.d.ts.map +0 -1
  65. package/dist/cloudflare/hooks.js +0 -40
  66. package/dist/cloudflare/init.d.ts +0 -27
  67. package/dist/cloudflare/init.d.ts.map +0 -1
  68. package/dist/cloudflare/init.js +0 -103
  69. package/dist/cloudflare/worker.d.ts +0 -27
  70. package/dist/cloudflare/worker.d.ts.map +0 -1
  71. package/dist/cloudflare/worker.js +0 -54
  72. package/dist/database/adapters/d1.d.ts +0 -56
  73. package/dist/database/adapters/d1.d.ts.map +0 -1
  74. package/dist/database/adapters/d1.js +0 -108
  75. package/dist/db.d.ts +0 -134
  76. package/dist/db.d.ts.map +0 -1
  77. package/dist/db.js +0 -1327
  78. package/dist/fts.d.ts +0 -20
  79. package/dist/fts.d.ts.map +0 -1
  80. package/dist/fts.js +0 -767
  81. package/dist/oauth/hooks.d.ts +0 -10
  82. package/dist/oauth/hooks.d.ts.map +0 -1
  83. package/dist/oauth/hooks.js +0 -40
  84. package/dist/schema.d.ts +0 -59
  85. package/dist/schema.d.ts.map +0 -1
  86. package/dist/schema.js +0 -387
  87. package/dist/test-browser.d.ts +0 -14
  88. package/dist/test-browser.d.ts.map +0 -1
  89. package/dist/test-browser.js +0 -26
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { mkdirSync, writeFileSync, existsSync, unlinkSync, readdirSync, readFileSync } from 'node:fs';
2
+ import { mkdirSync, writeFileSync, existsSync, unlinkSync, readdirSync, readFileSync, cpSync } from 'node:fs';
3
3
  import { resolve, join, dirname } from 'node:path';
4
4
  import { execSync, spawn } from 'node:child_process';
5
5
  import { loadLexicons, discoverCollections, buildSchemas } from "./database/schema.js";
@@ -108,148 +108,16 @@ function usage() {
108
108
  if (!command)
109
109
  usage();
110
110
  // --- Templates ---
111
- const templates = {
112
- feed: (name) => `import { defineFeed } from '../hatk.generated.ts'
113
-
114
- export default defineFeed({
115
- collection: 'your.collection.here',
116
- label: '${name.charAt(0).toUpperCase() + name.slice(1)}',
117
-
118
- async generate(ctx) {
119
- const { rows, cursor } = await ctx.paginate<{ uri: string }>(
120
- \`SELECT uri, cid, indexed_at FROM "your.collection.here"\`,
121
- )
122
-
123
- return ctx.ok({ uris: rows.map((r) => r.uri), cursor })
124
- },
125
- })
126
- `,
127
- xrpc: (name) => `import { defineQuery } from '../hatk.generated.ts'
128
-
129
- export default defineQuery('${name}', async (ctx) => {
130
- const { ok, db, params, packCursor, unpackCursor } = ctx
131
- const limit = params.limit ?? 30
132
- const cursor = params.cursor
133
-
134
- const conditions: string[] = []
135
- const sqlParams: (string | number)[] = []
136
- let paramIdx = 1
137
-
138
- if (cursor) {
139
- const parsed = unpackCursor(cursor)
140
- if (parsed) {
141
- conditions.push(\`(s.indexed_at < $\${paramIdx} OR (s.indexed_at = $\${paramIdx + 1} AND s.cid < $\${paramIdx + 2}))\`)
142
- sqlParams.push(parsed.primary, parsed.primary, parsed.cid)
143
- paramIdx += 3
144
- }
145
- }
146
-
147
- const where = conditions.length ? 'WHERE ' + conditions.join(' AND ') : ''
148
-
149
- const rows = await db.query(
150
- \`SELECT s.* FROM "your.collection.here" s \${where} ORDER BY s.indexed_at DESC, s.cid DESC LIMIT $\${paramIdx}\`,
151
- sqlParams.concat([limit + 1]),
152
- )
153
-
154
- const hasMore = rows.length > limit
155
- if (hasMore) rows.pop()
156
- const lastRow = rows[rows.length - 1]
157
-
158
- return ok({
159
- items: rows,
160
- cursor: hasMore && lastRow ? packCursor(lastRow.indexed_at, lastRow.cid) : undefined,
161
- })
162
- })
163
- `,
164
- label: (name) => `import type { LabelRuleContext } from '@hatk/hatk/labels'
165
-
166
- export default {
167
- definition: {
168
- identifier: '${name}',
169
- severity: 'inform',
170
- blurs: 'none',
171
- defaultSetting: 'warn',
172
- locales: [{ lang: 'en', name: '${name.charAt(0).toUpperCase() + name.slice(1)}', description: 'Description here' }],
173
- },
174
- async evaluate(ctx: LabelRuleContext) {
175
- // Return array of label identifiers to apply, or empty array
176
- return []
177
- },
178
- }
179
- `,
180
- og: (name) => `import type { OpengraphContext, OpengraphResult } from '@hatk/hatk/opengraph'
181
-
182
- export default {
183
- path: '/og/${name}/:id',
184
- async generate(ctx: OpengraphContext): Promise<OpengraphResult> {
185
- const { db, params } = ctx
186
- return {
187
- element: {
188
- type: 'div',
189
- props: {
190
- style: { display: 'flex', width: '100%', height: '100%', background: '#080b12', color: 'white', alignItems: 'center', justifyContent: 'center' },
191
- children: params.id,
192
- },
193
- },
194
- }
195
- },
111
+ const templateDir = join(import.meta.dirname, 'templates');
112
+ function loadTemplate(file, name) {
113
+ const raw = readFileSync(join(templateDir, file), 'utf-8');
114
+ const capitalized = name.charAt(0).toUpperCase() + name.slice(1);
115
+ return raw.replaceAll('{{name}}', name).replaceAll('{{Name}}', capitalized);
196
116
  }
197
- `,
198
- hook: (name) => `import { defineHook } from '../hatk.generated.ts'
199
-
200
- export default defineHook('${name}', async (ctx) => {
201
- // Hook logic here
202
- })
203
- `,
204
- setup: (_name) => `import { defineSetup } from '../hatk.generated.ts'
205
-
206
- export default defineSetup(async (ctx) => {
207
- // Setup logic here — runs before the server starts
208
- })
209
- `,
210
- };
211
- const testTemplates = {
212
- feed: (name) => `import { describe, test, expect, beforeAll, afterAll } from 'vitest'
213
- import { createTestContext } from '@hatk/hatk/test'
214
-
215
- let ctx: Awaited<ReturnType<typeof createTestContext>>
216
-
217
- beforeAll(async () => {
218
- ctx = await createTestContext()
219
- await ctx.loadFixtures()
220
- })
221
-
222
- afterAll(async () => ctx?.close())
223
-
224
- describe('${name} feed', () => {
225
- test('returns results', async () => {
226
- const feed = ctx.loadFeed('${name}')
227
- const result = await feed.generate(ctx.feedContext({ limit: 10 }))
228
- expect(result).toBeDefined()
229
- })
230
- })
231
- `,
232
- xrpc: (name) => `import { describe, test, expect, beforeAll, afterAll } from 'vitest'
233
- import { createTestContext } from '@hatk/hatk/test'
234
-
235
- let ctx: Awaited<ReturnType<typeof createTestContext>>
236
-
237
- beforeAll(async () => {
238
- ctx = await createTestContext()
239
- await ctx.loadFixtures()
240
- })
241
-
242
- afterAll(async () => ctx?.close())
243
-
244
- describe('${name}', () => {
245
- test('returns response', async () => {
246
- const handler = ctx.loadXrpc('${name}')
247
- const result = await handler.handler({ params: {} })
248
- expect(result).toBeDefined()
249
- })
250
- })
251
- `,
252
- };
117
+ const templateTypes = ['feed', 'xrpc', 'label', 'og', 'hook', 'setup'];
118
+ const testTemplateTypes = ['feed', 'xrpc'];
119
+ const templates = Object.fromEntries(templateTypes.map((t) => [t, (name) => loadTemplate(`${t}.tpl`, name)]));
120
+ const testTemplates = Object.fromEntries(testTemplateTypes.map((t) => [t, (name) => loadTemplate(`test-${t}.tpl`, name)]));
253
121
  const lexiconTemplates = {
254
122
  record: (nsid) => ({
255
123
  lexicon: 1,
@@ -402,415 +270,10 @@ export default defineConfig({
402
270
  <html><head><title>${name}</title></head>
403
271
  <body><h1>${name}</h1></body></html>
404
272
  `);
405
- // Scaffold core framework lexicons under dev.hatk namespace
406
- const coreLexDir = join(dir, 'lexicons', 'dev', 'hatk');
407
- mkdirSync(coreLexDir, { recursive: true });
408
- writeFileSync(join(coreLexDir, 'describeCollections.json'), JSON.stringify({
409
- lexicon: 1,
410
- id: 'dev.hatk.describeCollections',
411
- defs: {
412
- main: {
413
- type: 'query',
414
- description: 'List indexed collections and their schemas.',
415
- output: {
416
- encoding: 'application/json',
417
- schema: {
418
- type: 'object',
419
- properties: {
420
- collections: {
421
- type: 'array',
422
- items: {
423
- type: 'object',
424
- required: ['collection'],
425
- properties: {
426
- collection: { type: 'string' },
427
- columns: {
428
- type: 'array',
429
- items: {
430
- type: 'object',
431
- required: ['name', 'originalName', 'type', 'required'],
432
- properties: {
433
- name: { type: 'string' },
434
- originalName: { type: 'string' },
435
- type: { type: 'string' },
436
- required: { type: 'boolean' },
437
- },
438
- },
439
- },
440
- },
441
- },
442
- },
443
- },
444
- },
445
- },
446
- },
447
- },
448
- }, null, 2) + '\n');
449
- writeFileSync(join(coreLexDir, 'describeFeeds.json'), JSON.stringify({
450
- lexicon: 1,
451
- id: 'dev.hatk.describeFeeds',
452
- defs: {
453
- main: {
454
- type: 'query',
455
- description: 'List available feeds.',
456
- output: {
457
- encoding: 'application/json',
458
- schema: {
459
- type: 'object',
460
- properties: {
461
- feeds: {
462
- type: 'array',
463
- items: {
464
- type: 'object',
465
- required: ['name', 'label'],
466
- properties: {
467
- name: { type: 'string' },
468
- label: { type: 'string' },
469
- },
470
- },
471
- },
472
- },
473
- },
474
- },
475
- },
476
- },
477
- }, null, 2) + '\n');
478
- writeFileSync(join(coreLexDir, 'describeLabels.json'), JSON.stringify({
479
- lexicon: 1,
480
- id: 'dev.hatk.describeLabels',
481
- defs: {
482
- main: {
483
- type: 'query',
484
- description: 'List available label definitions.',
485
- output: {
486
- encoding: 'application/json',
487
- schema: {
488
- type: 'object',
489
- properties: {
490
- definitions: {
491
- type: 'array',
492
- items: {
493
- type: 'object',
494
- required: ['identifier', 'severity', 'blurs', 'defaultSetting'],
495
- properties: {
496
- identifier: { type: 'string' },
497
- severity: { type: 'string' },
498
- blurs: { type: 'string' },
499
- defaultSetting: { type: 'string' },
500
- },
501
- },
502
- },
503
- },
504
- },
505
- },
506
- },
507
- },
508
- }, null, 2) + '\n');
509
- writeFileSync(join(coreLexDir, 'createRecord.json'), JSON.stringify({
510
- lexicon: 1,
511
- id: 'dev.hatk.createRecord',
512
- defs: {
513
- main: {
514
- type: 'procedure',
515
- description: "Create a record via the user's PDS.",
516
- input: {
517
- encoding: 'application/json',
518
- schema: {
519
- type: 'object',
520
- required: ['collection', 'repo', 'record'],
521
- properties: {
522
- collection: { type: 'string' },
523
- repo: { type: 'string', format: 'did' },
524
- record: { type: 'unknown' },
525
- },
526
- },
527
- },
528
- output: {
529
- encoding: 'application/json',
530
- schema: {
531
- type: 'object',
532
- properties: {
533
- uri: { type: 'string', format: 'at-uri' },
534
- cid: { type: 'string', format: 'cid' },
535
- commit: {
536
- type: 'object',
537
- properties: {
538
- cid: { type: 'string', format: 'cid' },
539
- rev: { type: 'string' },
540
- },
541
- },
542
- validationStatus: { type: 'string' },
543
- },
544
- },
545
- },
546
- },
547
- },
548
- }, null, 2) + '\n');
549
- writeFileSync(join(coreLexDir, 'deleteRecord.json'), JSON.stringify({
550
- lexicon: 1,
551
- id: 'dev.hatk.deleteRecord',
552
- defs: {
553
- main: {
554
- type: 'procedure',
555
- description: "Delete a record via the user's PDS.",
556
- input: {
557
- encoding: 'application/json',
558
- schema: {
559
- type: 'object',
560
- required: ['collection', 'rkey'],
561
- properties: {
562
- collection: { type: 'string' },
563
- rkey: { type: 'string' },
564
- },
565
- },
566
- },
567
- output: { encoding: 'application/json', schema: { type: 'object', properties: {} } },
568
- },
569
- },
570
- }, null, 2) + '\n');
571
- writeFileSync(join(coreLexDir, 'putRecord.json'), JSON.stringify({
572
- lexicon: 1,
573
- id: 'dev.hatk.putRecord',
574
- defs: {
575
- main: {
576
- type: 'procedure',
577
- description: "Create or update a record via the user's PDS.",
578
- input: {
579
- encoding: 'application/json',
580
- schema: {
581
- type: 'object',
582
- required: ['collection', 'rkey', 'record'],
583
- properties: {
584
- collection: { type: 'string' },
585
- rkey: { type: 'string' },
586
- record: { type: 'unknown' },
587
- repo: { type: 'string', format: 'did' },
588
- },
589
- },
590
- },
591
- output: {
592
- encoding: 'application/json',
593
- schema: {
594
- type: 'object',
595
- properties: {
596
- uri: { type: 'string', format: 'at-uri' },
597
- cid: { type: 'string', format: 'cid' },
598
- commit: {
599
- type: 'object',
600
- properties: {
601
- cid: { type: 'string', format: 'cid' },
602
- rev: { type: 'string' },
603
- },
604
- },
605
- validationStatus: { type: 'string' },
606
- },
607
- },
608
- },
609
- },
610
- },
611
- }, null, 2) + '\n');
612
- writeFileSync(join(coreLexDir, 'uploadBlob.json'), JSON.stringify({
613
- lexicon: 1,
614
- id: 'dev.hatk.uploadBlob',
615
- defs: {
616
- main: {
617
- type: 'procedure',
618
- description: "Upload a blob via the user's PDS.",
619
- input: {
620
- encoding: '*/*',
621
- },
622
- output: {
623
- encoding: 'application/json',
624
- schema: {
625
- type: 'object',
626
- required: ['blob'],
627
- properties: {
628
- blob: { type: 'blob' },
629
- },
630
- },
631
- },
632
- },
633
- },
634
- }, null, 2) + '\n');
635
- writeFileSync(join(coreLexDir, 'getPreferences.json'), JSON.stringify({
636
- lexicon: 1,
637
- id: 'dev.hatk.getPreferences',
638
- defs: {
639
- main: {
640
- type: 'query',
641
- description: 'Get all preferences for the authenticated user.',
642
- output: {
643
- encoding: 'application/json',
644
- schema: {
645
- type: 'object',
646
- properties: {
647
- preferences: { type: 'unknown' },
648
- },
649
- },
650
- },
651
- },
652
- },
653
- }, null, 2) + '\n');
654
- writeFileSync(join(coreLexDir, 'putPreference.json'), JSON.stringify({
655
- lexicon: 1,
656
- id: 'dev.hatk.putPreference',
657
- defs: {
658
- main: {
659
- type: 'procedure',
660
- description: 'Set a single preference by key.',
661
- input: {
662
- encoding: 'application/json',
663
- schema: {
664
- type: 'object',
665
- required: ['key', 'value'],
666
- properties: {
667
- key: { type: 'string' },
668
- value: { type: 'unknown' },
669
- },
670
- },
671
- },
672
- output: {
673
- encoding: 'application/json',
674
- schema: {
675
- type: 'object',
676
- properties: {},
677
- },
678
- },
679
- },
680
- },
681
- }, null, 2) + '\n');
682
- writeFileSync(join(coreLexDir, 'getFeed.json'), JSON.stringify({
683
- lexicon: 1,
684
- id: 'dev.hatk.getFeed',
685
- defs: {
686
- main: {
687
- type: 'query',
688
- description: 'Retrieve a named feed of items.',
689
- parameters: {
690
- type: 'params',
691
- required: ['feed'],
692
- properties: {
693
- feed: { type: 'string', description: 'Feed name' },
694
- limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 },
695
- cursor: { type: 'string' },
696
- },
697
- },
698
- output: {
699
- encoding: 'application/json',
700
- schema: {
701
- type: 'object',
702
- required: ['items'],
703
- properties: {
704
- items: { type: 'array', items: { type: 'unknown' } },
705
- cursor: { type: 'string' },
706
- },
707
- },
708
- },
709
- },
710
- },
711
- }, null, 2) + '\n');
712
- writeFileSync(join(coreLexDir, 'getRecord.json'), JSON.stringify({
713
- lexicon: 1,
714
- id: 'dev.hatk.getRecord',
715
- defs: {
716
- main: {
717
- type: 'query',
718
- description: 'Fetch a single record by AT URI.',
719
- parameters: {
720
- type: 'params',
721
- required: ['uri'],
722
- properties: {
723
- uri: { type: 'string', format: 'at-uri' },
724
- },
725
- },
726
- output: {
727
- encoding: 'application/json',
728
- schema: {
729
- type: 'object',
730
- properties: {
731
- record: { type: 'unknown' },
732
- },
733
- },
734
- },
735
- },
736
- },
737
- }, null, 2) + '\n');
738
- writeFileSync(join(coreLexDir, 'getRecords.json'), JSON.stringify({
739
- lexicon: 1,
740
- id: 'dev.hatk.getRecords',
741
- defs: {
742
- main: {
743
- type: 'query',
744
- description: 'List records from a collection with optional filters.',
745
- parameters: {
746
- type: 'params',
747
- required: ['collection'],
748
- properties: {
749
- collection: { type: 'string' },
750
- limit: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
751
- cursor: { type: 'string' },
752
- sort: { type: 'string' },
753
- order: { type: 'string' },
754
- },
755
- },
756
- output: {
757
- encoding: 'application/json',
758
- schema: {
759
- type: 'object',
760
- required: ['items'],
761
- properties: {
762
- items: { type: 'array', items: { type: 'unknown' } },
763
- cursor: { type: 'string' },
764
- },
765
- },
766
- },
767
- },
768
- },
769
- }, null, 2) + '\n');
770
- writeFileSync(join(coreLexDir, 'searchRecords.json'), JSON.stringify({
771
- lexicon: 1,
772
- id: 'dev.hatk.searchRecords',
773
- defs: {
774
- main: {
775
- type: 'query',
776
- description: 'Full-text search across a collection.',
777
- parameters: {
778
- type: 'params',
779
- required: ['collection', 'q'],
780
- properties: {
781
- collection: { type: 'string' },
782
- q: { type: 'string', description: 'Search query' },
783
- limit: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
784
- cursor: { type: 'string' },
785
- fuzzy: { type: 'boolean', default: true },
786
- },
787
- },
788
- output: {
789
- encoding: 'application/json',
790
- schema: {
791
- type: 'object',
792
- required: ['items'],
793
- properties: {
794
- items: { type: 'array', items: { type: 'unknown' } },
795
- cursor: { type: 'string' },
796
- },
797
- },
798
- },
799
- },
800
- },
801
- }, null, 2) + '\n');
802
- writeFileSync(join(dir, 'seeds', 'seed.ts'), `import { seed } from '../hatk.generated.ts'
803
-
804
- const { createAccount, createRecord } = seed()
805
-
806
- const alice = await createAccount('alice.test')
807
-
808
- // await createRecord(alice, 'your.collection.here', {
809
- // field: 'value',
810
- // }, { rkey: 'my-record' })
811
-
812
- console.log('\\n[seed] Done!')
813
- `);
273
+ // Copy core framework lexicons (dev.hatk.* and dependencies like com.atproto.repo.strongRef)
274
+ const builtinLexDir = join(import.meta.dirname, 'lexicons');
275
+ cpSync(builtinLexDir, join(dir, 'lexicons'), { recursive: true });
276
+ writeFileSync(join(dir, 'seeds', 'seed.ts'), loadTemplate('seed.tpl', ''));
814
277
  writeFileSync(join(dir, 'docker-compose.yml'), `services:
815
278
  plc:
816
279
  build:
@@ -1603,7 +1066,7 @@ else if (command === 'generate') {
1603
1066
  if (procedureNsids.length > 0) {
1604
1067
  clientOut += ` if (_procedures.has(nsid)) {\n`;
1605
1068
  clientOut += ` const res = await _fetch(path, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(arg) })\n`;
1606
- clientOut += ` if (typeof window !== 'undefined' && res.status === 401) { const _h = getViewer()?.handle; window.location.href = _h ? \`/oauth/login?handle=\${encodeURIComponent(_h)}\` : '/oauth/login'; return new Promise(() => {}) as any }\n`;
1069
+ clientOut += ` if (typeof window !== 'undefined' && res.status === 401) { const _b = await res.json().catch(() => ({})); const _h = _b.handle ?? getViewer()?.handle; window.location.href = _h ? \`/oauth/login?handle=\${encodeURIComponent(_h)}\` : '/oauth/login'; return new Promise(() => {}) as any }\n`;
1607
1070
  clientOut += ` if (!res.ok) throw new Error(\`XRPC \${nsid} failed: \${res.status}\`)\n`;
1608
1071
  clientOut += ` return res.json() as Promise<OutputOf<K>>\n`;
1609
1072
  clientOut += ` }\n`;
@@ -1615,7 +1078,7 @@ else if (command === 'generate') {
1615
1078
  clientOut += ` const qs = params.toString()\n`;
1616
1079
  clientOut += ` if (qs) path += \`?\${qs}\`\n`;
1617
1080
  clientOut += ` const res = await _fetch(path)\n`;
1618
- clientOut += ` if (typeof window !== 'undefined' && res.status === 401) { window.location.href = '/oauth/login'; return new Promise(() => {}) as any }\n`;
1081
+ clientOut += ` if (typeof window !== 'undefined' && res.status === 401) { const _b = await res.json().catch(() => ({})); const _h = _b.handle ?? getViewer()?.handle; window.location.href = _h ? \`/oauth/login?handle=\${encodeURIComponent(_h)}\` : '/oauth/login'; return new Promise(() => {}) as any }\n`;
1619
1082
  clientOut += ` if (!res.ok) throw new Error(\`XRPC \${nsid} failed: \${res.status}\`)\n`;
1620
1083
  clientOut += ` return res.json() as Promise<OutputOf<K>>\n`;
1621
1084
  clientOut += `}\n`;
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/database/adapters/sqlite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAoBtE,qBAAa,aAAc,YAAW,YAAY;IAChD,OAAO,EAAE,OAAO,CAAW;IAE3B,OAAO,CAAC,EAAE,CAAoB;IAExB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC,KAAK,IAAI,IAAI;IAMP,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAMrF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,kBAAkB,CACtB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,YAAY,CAAC;CAmCzB"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/database/adapters/sqlite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAqBtE,qBAAa,aAAc,YAAW,YAAY;IAChD,OAAO,EAAE,OAAO,CAAW;IAE3B,OAAO,CAAC,EAAE,CAAoB;IAExB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC,KAAK,IAAI,IAAI;IAMP,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAMrF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,kBAAkB,CACtB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,YAAY,CAAC;CAmCzB"}
@@ -10,7 +10,8 @@ function translateParams(sql, params) {
10
10
  const expandedParams = [];
11
11
  const translated = sql.replace(/\$(\d+)/g, (_match, numStr) => {
12
12
  const idx = parseInt(numStr) - 1; // $1 → index 0
13
- expandedParams.push(params[idx]);
13
+ const val = params[idx];
14
+ expandedParams.push(typeof val === 'boolean' ? (val ? 1 : 0) : val);
14
15
  return '?';
15
16
  });
16
17
  return { sql: translated, params: expandedParams };
@@ -155,5 +155,28 @@ export declare function isTakendownDid(did: string): Promise<boolean>;
155
155
  export declare function getPreferences(did: string): Promise<Record<string, any>>;
156
156
  export declare function putPreference(did: string, key: string, value: any): Promise<void>;
157
157
  export declare function filterTakendownDids(dids: string[]): Promise<Set<string>>;
158
+ export declare function insertReport(report: {
159
+ subjectUri: string;
160
+ subjectDid: string;
161
+ label: string;
162
+ reason?: string;
163
+ reportedBy: string;
164
+ }): Promise<{
165
+ id: number;
166
+ }>;
167
+ export declare function queryReports(opts: {
168
+ status?: string;
169
+ label?: string;
170
+ limit?: number;
171
+ offset?: number;
172
+ }): Promise<{
173
+ reports: any[];
174
+ total: number;
175
+ }>;
176
+ export declare function resolveReport(id: number, action: 'resolved' | 'dismissed', resolvedBy: string): Promise<{
177
+ subjectUri: string;
178
+ label: string;
179
+ } | null>;
180
+ export declare function getOpenReportCount(): Promise<number>;
158
181
  export {};
159
182
  //# sourceMappingURL=db.d.ts.map