@atproto/dev-env 0.3.9 → 0.3.11

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/dev-env",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "license": "MIT",
5
5
  "description": "Local development environment helper for atproto development",
6
6
  "keywords": [
@@ -24,18 +24,21 @@
24
24
  "get-port": "^5.1.1",
25
25
  "multiformats": "^9.9.0",
26
26
  "uint8arrays": "3.0.0",
27
- "@atproto/api": "^0.12.7",
28
- "@atproto/bsky": "^0.0.49",
27
+ "@atproto/api": "^0.12.9",
28
+ "@atproto/bsky": "^0.0.51",
29
29
  "@atproto/bsync": "^0.0.3",
30
30
  "@atproto/common-web": "^0.3.0",
31
31
  "@atproto/crypto": "^0.4.0",
32
32
  "@atproto/identity": "^0.4.0",
33
33
  "@atproto/lexicon": "^0.4.0",
34
- "@atproto/ozone": "^0.1.11",
35
- "@atproto/pds": "^0.4.18",
34
+ "@atproto/ozone": "^0.1.13",
35
+ "@atproto/pds": "^0.4.20",
36
36
  "@atproto/syntax": "^0.3.0",
37
37
  "@atproto/xrpc-server": "^0.5.1"
38
38
  },
39
+ "devDependencies": {
40
+ "@types/express": "^4.17.13"
41
+ },
39
42
  "scripts": {
40
43
  "build": "tsc --build tsconfig.build.json",
41
44
  "start": "../dev-infra/with-test-redis-and-db.sh node dist/bin.js"
package/src/bin.ts CHANGED
@@ -26,10 +26,16 @@ const run = async () => {
26
26
  publicUrl: 'http://localhost:2584',
27
27
  },
28
28
  plc: { port: 2582 },
29
+ introspect: { port: 2581 },
29
30
  })
30
31
  mockMailer(network.pds)
31
32
  await generateMockSetup(network)
32
33
 
34
+ if (network.introspect) {
35
+ console.log(
36
+ `🔍 Dev-env introspection server started http://localhost:${network.introspect.port}`,
37
+ )
38
+ }
33
39
  console.log(
34
40
  `👤 DID Placeholder server started http://localhost:${network.plc.port}`,
35
41
  )
@@ -37,6 +43,7 @@ const run = async () => {
37
43
  `🌞 Personal Data server started http://localhost:${network.pds.port}`,
38
44
  )
39
45
  console.log(`🗼 Ozone server started http://localhost:${network.ozone.port}`)
46
+ console.log(`🗼 Ozone service DID ${network.ozone.ctx.cfg.service.did}`)
40
47
  console.log(`🌅 Bsky Appview started http://localhost:${network.bsky.port}`)
41
48
  for (const fg of network.feedGens) {
42
49
  console.log(`🤖 Feed Generator started http://localhost:${fg.port}`)
package/src/bsky.ts CHANGED
@@ -58,6 +58,7 @@ export class TestBsky {
58
58
  didPlcUrl: cfg.plcUrl,
59
59
  publicUrl: 'https://bsky.public.url',
60
60
  serverDid,
61
+ alternateAudienceDids: [],
61
62
  dataplaneUrls: [`http://localhost:${dataplanePort}`],
62
63
  dataplaneHttpVersion: '1.1',
63
64
  bsyncUrl: `http://localhost:${bsyncPort}`,
@@ -0,0 +1,54 @@
1
+ import http from 'node:http'
2
+ import events from 'node:events'
3
+ import express from 'express'
4
+ import { TestPlc } from './plc'
5
+ import { TestPds } from './pds'
6
+ import { TestBsky } from './bsky'
7
+ import { TestOzone } from './ozone'
8
+
9
+ export class IntrospectServer {
10
+ constructor(
11
+ public port: number,
12
+ public server: http.Server,
13
+ ) {}
14
+
15
+ static async start(
16
+ port: number,
17
+ plc: TestPlc,
18
+ pds: TestPds,
19
+ bsky: TestBsky,
20
+ ozone: TestOzone,
21
+ ) {
22
+ const app = express()
23
+ app.get('/', (_req, res) => {
24
+ res.status(200).send({
25
+ plc: {
26
+ url: plc.url,
27
+ },
28
+ pds: {
29
+ url: pds.url,
30
+ did: pds.ctx.cfg.service.did,
31
+ },
32
+ bsky: {
33
+ url: bsky.url,
34
+ did: bsky.ctx.cfg.serverDid,
35
+ },
36
+ ozone: {
37
+ url: ozone.url,
38
+ did: ozone.ctx.cfg.service.did,
39
+ },
40
+ db: {
41
+ url: ozone.ctx.cfg.db.postgresUrl,
42
+ },
43
+ })
44
+ })
45
+ const server = app.listen(port)
46
+ await events.once(server, 'listening')
47
+ return new IntrospectServer(port, server)
48
+ }
49
+
50
+ async close() {
51
+ this.server.close()
52
+ await events.once(this.server, 'close')
53
+ }
54
+ }
package/src/mock/index.ts CHANGED
@@ -350,328 +350,6 @@ export async function generateMockSetup(env: TestNetwork) {
350
350
  },
351
351
  )
352
352
 
353
- // create the dev-env moderator
354
- {
355
- const res = await clients.loggedout.api.com.atproto.server.createAccount({
356
- email: 'mod-authority@test.com',
357
- handle: 'mod-authority.test',
358
- password: 'hunter2',
359
- })
360
- const agent = env.pds.getClient()
361
- agent.api.setHeader('Authorization', `Bearer ${res.data.accessJwt}`)
362
- await agent.api.app.bsky.actor.profile.create(
363
- { repo: res.data.did },
364
- {
365
- displayName: 'Dev-env Moderation',
366
- description: `The pretend version of mod.bsky.app`,
367
- },
368
- )
369
-
370
- await agent.api.app.bsky.labeler.service.create(
371
- { repo: res.data.did, rkey: 'self' },
372
- {
373
- policies: {
374
- labelValues: [
375
- '!hide',
376
- '!warn',
377
- 'porn',
378
- 'sexual',
379
- 'nudity',
380
- 'sexual-figurative',
381
- 'graphic-media',
382
- 'self-harm',
383
- 'sensitive',
384
- 'extremist',
385
- 'intolerant',
386
- 'threat',
387
- 'rude',
388
- 'illicit',
389
- 'security',
390
- 'unsafe-link',
391
- 'impersonation',
392
- 'misinformation',
393
- 'scam',
394
- 'engagement-farming',
395
- 'spam',
396
- 'rumor',
397
- 'misleading',
398
- 'inauthentic',
399
- ],
400
- labelValueDefinitions: [
401
- {
402
- identifier: 'spam',
403
- blurs: 'content',
404
- severity: 'inform',
405
- defaultSetting: 'hide',
406
- adultOnly: false,
407
- locales: [
408
- {
409
- lang: 'en',
410
- name: 'Spam',
411
- description:
412
- 'Unwanted, repeated, or unrelated actions that bother users.',
413
- },
414
- ],
415
- },
416
- {
417
- identifier: 'impersonation',
418
- blurs: 'none',
419
- severity: 'inform',
420
- defaultSetting: 'hide',
421
- adultOnly: false,
422
- locales: [
423
- {
424
- lang: 'en',
425
- name: 'Impersonation',
426
- description:
427
- 'Pretending to be someone else without permission.',
428
- },
429
- ],
430
- },
431
- {
432
- identifier: 'scam',
433
- blurs: 'content',
434
- severity: 'alert',
435
- defaultSetting: 'hide',
436
- adultOnly: false,
437
- locales: [
438
- {
439
- lang: 'en',
440
- name: 'Scam',
441
- description: 'Scams, phishing & fraud.',
442
- },
443
- ],
444
- },
445
- {
446
- identifier: 'intolerant',
447
- blurs: 'content',
448
- severity: 'alert',
449
- defaultSetting: 'warn',
450
- adultOnly: false,
451
- locales: [
452
- {
453
- lang: 'en',
454
- name: 'Intolerance',
455
- description: 'Discrimination against protected groups.',
456
- },
457
- ],
458
- },
459
- {
460
- identifier: 'self-harm',
461
- blurs: 'content',
462
- severity: 'alert',
463
- defaultSetting: 'warn',
464
- adultOnly: false,
465
- locales: [
466
- {
467
- lang: 'en',
468
- name: 'Self-Harm',
469
- description:
470
- 'Promotes self-harm, including graphic images, glorifying discussions, or triggering stories.',
471
- },
472
- ],
473
- },
474
- {
475
- identifier: 'security',
476
- blurs: 'content',
477
- severity: 'alert',
478
- defaultSetting: 'hide',
479
- adultOnly: false,
480
- locales: [
481
- {
482
- lang: 'en',
483
- name: 'Security Concerns',
484
- description:
485
- 'May be unsafe and could harm your device, steal your info, or get your account hacked.',
486
- },
487
- ],
488
- },
489
- {
490
- identifier: 'misleading',
491
- blurs: 'content',
492
- severity: 'alert',
493
- defaultSetting: 'warn',
494
- adultOnly: false,
495
- locales: [
496
- {
497
- lang: 'en',
498
- name: 'Misleading',
499
- description:
500
- 'Altered images/videos, deceptive links, or false statements.',
501
- },
502
- ],
503
- },
504
- {
505
- identifier: 'threat',
506
- blurs: 'content',
507
- severity: 'inform',
508
- defaultSetting: 'hide',
509
- adultOnly: false,
510
- locales: [
511
- {
512
- lang: 'en',
513
- name: 'Threats',
514
- description:
515
- 'Promotes violence or harm towards others, including threats, incitement, or advocacy of harm.',
516
- },
517
- ],
518
- },
519
- {
520
- identifier: 'unsafe-link',
521
- blurs: 'content',
522
- severity: 'alert',
523
- defaultSetting: 'hide',
524
- adultOnly: false,
525
- locales: [
526
- {
527
- lang: 'en',
528
- name: 'Unsafe link',
529
- description:
530
- 'Links to harmful sites with malware, phishing, or violating content that risk security and privacy.',
531
- },
532
- ],
533
- },
534
- {
535
- identifier: 'illicit',
536
- blurs: 'content',
537
- severity: 'alert',
538
- defaultSetting: 'hide',
539
- adultOnly: false,
540
- locales: [
541
- {
542
- lang: 'en',
543
- name: 'Illicit',
544
- description:
545
- 'Promoting or selling potentially illicit goods, services, or activities.',
546
- },
547
- ],
548
- },
549
- {
550
- identifier: 'misinformation',
551
- blurs: 'content',
552
- severity: 'inform',
553
- defaultSetting: 'warn',
554
- adultOnly: false,
555
- locales: [
556
- {
557
- lang: 'en',
558
- name: 'Misinformation',
559
- description:
560
- 'Spreading false or misleading info, including unverified claims and harmful conspiracy theories.',
561
- },
562
- ],
563
- },
564
- {
565
- identifier: 'rumor',
566
- blurs: 'content',
567
- severity: 'inform',
568
- defaultSetting: 'warn',
569
- adultOnly: false,
570
- locales: [
571
- {
572
- lang: 'en',
573
- name: 'Rumor',
574
- description:
575
- 'Approach with caution, as these claims lack evidence from credible sources.',
576
- },
577
- ],
578
- },
579
- {
580
- identifier: 'rude',
581
- blurs: 'content',
582
- severity: 'inform',
583
- defaultSetting: 'hide',
584
- adultOnly: false,
585
- locales: [
586
- {
587
- lang: 'en',
588
- name: 'Rude',
589
- description:
590
- 'Rude or impolite, including crude language and disrespectful comments, without constructive purpose.',
591
- },
592
- ],
593
- },
594
- {
595
- identifier: 'extremist',
596
- blurs: 'content',
597
- severity: 'alert',
598
- defaultSetting: 'hide',
599
- adultOnly: false,
600
- locales: [
601
- {
602
- lang: 'en',
603
- name: 'Extremist',
604
- description:
605
- 'Radical views advocating violence, hate, or discrimination against individuals or groups.',
606
- },
607
- ],
608
- },
609
- {
610
- identifier: 'sensitive',
611
- blurs: 'content',
612
- severity: 'alert',
613
- defaultSetting: 'warn',
614
- adultOnly: false,
615
- locales: [
616
- {
617
- lang: 'en',
618
- name: 'Sensitive',
619
- description:
620
- 'May be upsetting, covering topics like substance abuse or mental health issues, cautioning sensitive viewers.',
621
- },
622
- ],
623
- },
624
- {
625
- identifier: 'engagement-farming',
626
- blurs: 'content',
627
- severity: 'alert',
628
- defaultSetting: 'hide',
629
- adultOnly: false,
630
- locales: [
631
- {
632
- lang: 'en',
633
- name: 'Engagement Farming',
634
- description:
635
- 'Insincere content or bulk actions aimed at gaining followers, including frequent follows, posts, and likes.',
636
- },
637
- ],
638
- },
639
- {
640
- identifier: 'inauthentic',
641
- blurs: 'content',
642
- severity: 'alert',
643
- defaultSetting: 'hide',
644
- adultOnly: false,
645
- locales: [
646
- {
647
- lang: 'en',
648
- name: 'Inauthentic Account',
649
- description: 'Bot or a person pretending to be someone else.',
650
- },
651
- ],
652
- },
653
- {
654
- identifier: 'sexual-figurative',
655
- blurs: 'media',
656
- severity: 'none',
657
- defaultSetting: 'show',
658
- adultOnly: true,
659
- locales: [
660
- {
661
- lang: 'en',
662
- name: 'Sexually Suggestive (Cartoon)',
663
- description:
664
- 'Art with explicit or suggestive sexual themes, including provocative imagery or partial nudity.',
665
- },
666
- ],
667
- },
668
- ],
669
- },
670
- createdAt: date.next().value,
671
- },
672
- )
673
- }
674
-
675
353
  // create a labeler account
676
354
  {
677
355
  const res = await clients.loggedout.api.com.atproto.server.createAccount({
package/src/network.ts CHANGED
@@ -7,11 +7,12 @@ import { TestServerParams } from './types'
7
7
  import { TestPlc } from './plc'
8
8
  import { TestPds } from './pds'
9
9
  import { TestBsky } from './bsky'
10
- import { TestOzone, createOzoneDid } from './ozone'
10
+ import { TestOzone } from './ozone'
11
+ import { OzoneServiceProfile } from './ozone-service-profile'
11
12
  import { mockNetworkUtilities } from './util'
12
13
  import { TestNetworkNoAppView } from './network-no-appview'
13
- import { Secp256k1Keypair } from '@atproto/crypto'
14
14
  import { EXAMPLE_LABELER } from './const'
15
+ import { IntrospectServer } from './introspect'
15
16
 
16
17
  const ADMIN_USERNAME = 'admin'
17
18
  const ADMIN_PASSWORD = 'admin-pass'
@@ -22,6 +23,7 @@ export class TestNetwork extends TestNetworkNoAppView {
22
23
  public pds: TestPds,
23
24
  public bsky: TestBsky,
24
25
  public ozone: TestOzone,
26
+ public introspect?: IntrospectServer,
25
27
  ) {
26
28
  super(plc, pds)
27
29
  }
@@ -42,8 +44,16 @@ export class TestNetwork extends TestNetworkNoAppView {
42
44
  const pdsPort = params.pds?.port ?? (await getPort())
43
45
  const ozonePort = params.ozone?.port ?? (await getPort())
44
46
 
45
- const ozoneKey = await Secp256k1Keypair.create({ exportable: true })
46
- const ozoneDid = await createOzoneDid(plc.url, ozoneKey)
47
+ const thirdPartyPdsProps = {
48
+ didPlcUrl: plc.url,
49
+ ...params.pds,
50
+ inviteRequired: false,
51
+ port: await getPort(),
52
+ }
53
+ const thirdPartyPds = await TestPds.create(thirdPartyPdsProps)
54
+ const ozoneServiceProfile = new OzoneServiceProfile(thirdPartyPds)
55
+ const { did: ozoneDid, key: ozoneKey } =
56
+ await ozoneServiceProfile.createDidAndKey()
47
57
 
48
58
  const bsky = await TestBsky.create({
49
59
  port: bskyPort,
@@ -58,22 +68,25 @@ export class TestNetwork extends TestNetworkNoAppView {
58
68
  ...params.bsky,
59
69
  })
60
70
 
61
- const pds = await TestPds.create({
71
+ const modServiceUrl = `http://localhost:${ozonePort}`
72
+ const pdsProps = {
62
73
  port: pdsPort,
63
74
  didPlcUrl: plc.url,
64
75
  bskyAppViewUrl: bsky.url,
65
76
  bskyAppViewDid: bsky.ctx.cfg.serverDid,
66
- modServiceUrl: `http://localhost:${ozonePort}`,
77
+ modServiceUrl,
67
78
  modServiceDid: ozoneDid,
68
79
  ...params.pds,
69
- })
80
+ }
81
+
82
+ const pds = await TestPds.create(pdsProps)
70
83
 
71
84
  const ozone = await TestOzone.create({
72
85
  port: ozonePort,
73
86
  plcUrl: plc.url,
74
87
  signingKey: ozoneKey,
75
88
  serverDid: ozoneDid,
76
- dbPostgresSchema: `ozone_${dbPostgresSchema}`,
89
+ dbPostgresSchema: `ozone_${dbPostgresSchema || 'db'}`,
77
90
  dbPostgresUrl,
78
91
  appviewUrl: bsky.url,
79
92
  appviewDid: bsky.ctx.cfg.serverDid,
@@ -83,9 +96,42 @@ export class TestNetwork extends TestNetworkNoAppView {
83
96
  ...params.ozone,
84
97
  })
85
98
 
99
+ let inviteCode: string | undefined
100
+ if (pdsProps.inviteRequired) {
101
+ const { data: invite } = await pds
102
+ .getClient()
103
+ .api.com.atproto.server.createInviteCode(
104
+ { useCount: 1 },
105
+ {
106
+ encoding: 'application/json',
107
+ headers: pds.adminAuthHeaders(),
108
+ },
109
+ )
110
+ inviteCode = invite.code
111
+ }
112
+ await ozoneServiceProfile.createServiceDetails(pds, modServiceUrl, {
113
+ inviteCode,
114
+ })
115
+
116
+ ozone.addAdminDid(ozoneDid)
117
+
86
118
  mockNetworkUtilities(pds, bsky)
119
+ await pds.processAll()
120
+ await bsky.sub.background.processAll()
121
+ await thirdPartyPds.close()
122
+
123
+ let introspect: IntrospectServer | undefined = undefined
124
+ if (params.introspect?.port) {
125
+ introspect = await IntrospectServer.start(
126
+ params.introspect.port,
127
+ plc,
128
+ pds,
129
+ bsky,
130
+ ozone,
131
+ )
132
+ }
87
133
 
88
- return new TestNetwork(plc, pds, bsky, ozone)
134
+ return new TestNetwork(plc, pds, bsky, ozone, introspect)
89
135
  }
90
136
 
91
137
  async processFullSubscription(timeout = 5000) {
@@ -144,5 +190,6 @@ export class TestNetwork extends TestNetworkNoAppView {
144
190
  await this.bsky.close()
145
191
  await this.pds.close()
146
192
  await this.plc.close()
193
+ await this.introspect?.close()
147
194
  }
148
195
  }