@atproto/dev-env 0.3.9 → 0.3.11

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/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
  }