@atproto/bsync 0.0.24 → 0.0.26-next.0

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 (137) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/bin/migration-create.ts +1 -1
  3. package/dist/client.d.ts +1 -1
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +7 -12
  6. package/dist/client.js.map +1 -1
  7. package/dist/config.js +16 -24
  8. package/dist/config.js.map +1 -1
  9. package/dist/context.d.ts +6 -6
  10. package/dist/context.d.ts.map +1 -1
  11. package/dist/context.js +8 -36
  12. package/dist/context.js.map +1 -1
  13. package/dist/db/index.d.ts +6 -4
  14. package/dist/db/index.d.ts.map +1 -1
  15. package/dist/db/index.js +26 -101
  16. package/dist/db/index.js.map +1 -1
  17. package/dist/db/migrations/20240108T220751294Z-init.js +4 -8
  18. package/dist/db/migrations/20240108T220751294Z-init.js.map +1 -1
  19. package/dist/db/migrations/20240717T224303472Z-notif-ops.js +4 -8
  20. package/dist/db/migrations/20240717T224303472Z-notif-ops.js.map +1 -1
  21. package/dist/db/migrations/20250527T022203400Z-add-operation.js +5 -9
  22. package/dist/db/migrations/20250527T022203400Z-add-operation.js.map +1 -1
  23. package/dist/db/migrations/20250603T163446567Z-alter-operation.js +2 -6
  24. package/dist/db/migrations/20250603T163446567Z-alter-operation.js.map +1 -1
  25. package/dist/db/migrations/index.d.ts +4 -4
  26. package/dist/db/migrations/index.d.ts.map +1 -1
  27. package/dist/db/migrations/index.js +4 -40
  28. package/dist/db/migrations/index.js.map +1 -1
  29. package/dist/db/migrations/provider.js +2 -11
  30. package/dist/db/migrations/provider.js.map +1 -1
  31. package/dist/db/schema/index.d.ts +5 -5
  32. package/dist/db/schema/index.d.ts.map +1 -1
  33. package/dist/db/schema/index.js +1 -2
  34. package/dist/db/schema/index.js.map +1 -1
  35. package/dist/db/schema/mute_item.js +1 -4
  36. package/dist/db/schema/mute_item.js.map +1 -1
  37. package/dist/db/schema/mute_op.d.ts +1 -1
  38. package/dist/db/schema/mute_op.d.ts.map +1 -1
  39. package/dist/db/schema/mute_op.js +2 -5
  40. package/dist/db/schema/mute_op.js.map +1 -1
  41. package/dist/db/schema/notif_item.js +1 -4
  42. package/dist/db/schema/notif_item.js.map +1 -1
  43. package/dist/db/schema/notif_op.js +2 -5
  44. package/dist/db/schema/notif_op.js.map +1 -1
  45. package/dist/db/schema/operation.d.ts +2 -2
  46. package/dist/db/schema/operation.d.ts.map +1 -1
  47. package/dist/db/schema/operation.js +2 -5
  48. package/dist/db/schema/operation.js.map +1 -1
  49. package/dist/db/types.d.ts +3 -1
  50. package/dist/db/types.d.ts.map +1 -1
  51. package/dist/db/types.js +1 -2
  52. package/dist/db/types.js.map +1 -1
  53. package/dist/index.d.ts +7 -7
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +37 -88
  56. package/dist/index.js.map +1 -1
  57. package/dist/logger.js +8 -11
  58. package/dist/logger.js.map +1 -1
  59. package/dist/proto/bsync_connect.d.ts +10 -1
  60. package/dist/proto/bsync_connect.d.ts.map +1 -1
  61. package/dist/proto/bsync_connect.js +33 -27
  62. package/dist/proto/bsync_connect.js.map +1 -1
  63. package/dist/proto/bsync_pb.d.ts +38 -0
  64. package/dist/proto/bsync_pb.d.ts.map +1 -1
  65. package/dist/proto/bsync_pb.js +260 -680
  66. package/dist/proto/bsync_pb.js.map +1 -1
  67. package/dist/routes/add-mute-operation.d.ts +2 -2
  68. package/dist/routes/add-mute-operation.d.ts.map +1 -1
  69. package/dist/routes/add-mute-operation.js +28 -30
  70. package/dist/routes/add-mute-operation.js.map +1 -1
  71. package/dist/routes/add-notif-operation.d.ts +2 -2
  72. package/dist/routes/add-notif-operation.d.ts.map +1 -1
  73. package/dist/routes/add-notif-operation.js +14 -16
  74. package/dist/routes/add-notif-operation.js.map +1 -1
  75. package/dist/routes/auth.d.ts +1 -1
  76. package/dist/routes/auth.d.ts.map +1 -1
  77. package/dist/routes/auth.js +4 -8
  78. package/dist/routes/auth.js.map +1 -1
  79. package/dist/routes/delete-operations.d.ts +6 -0
  80. package/dist/routes/delete-operations.d.ts.map +1 -0
  81. package/dist/routes/delete-operations.js +36 -0
  82. package/dist/routes/delete-operations.js.map +1 -0
  83. package/dist/routes/index.d.ts +1 -1
  84. package/dist/routes/index.d.ts.map +1 -1
  85. package/dist/routes/index.js +19 -22
  86. package/dist/routes/index.js.map +1 -1
  87. package/dist/routes/put-operation.d.ts +2 -2
  88. package/dist/routes/put-operation.d.ts.map +1 -1
  89. package/dist/routes/put-operation.js +24 -37
  90. package/dist/routes/put-operation.js.map +1 -1
  91. package/dist/routes/scan-mute-operations.d.ts +2 -2
  92. package/dist/routes/scan-mute-operations.d.ts.map +1 -1
  93. package/dist/routes/scan-mute-operations.js +13 -15
  94. package/dist/routes/scan-mute-operations.js.map +1 -1
  95. package/dist/routes/scan-notif-operations.d.ts +2 -2
  96. package/dist/routes/scan-notif-operations.d.ts.map +1 -1
  97. package/dist/routes/scan-notif-operations.js +13 -15
  98. package/dist/routes/scan-notif-operations.js.map +1 -1
  99. package/dist/routes/scan-operations.d.ts +2 -2
  100. package/dist/routes/scan-operations.d.ts.map +1 -1
  101. package/dist/routes/scan-operations.js +13 -15
  102. package/dist/routes/scan-operations.js.map +1 -1
  103. package/dist/routes/util.d.ts +1 -0
  104. package/dist/routes/util.d.ts.map +1 -1
  105. package/dist/routes/util.js +21 -17
  106. package/dist/routes/util.js.map +1 -1
  107. package/{jest.config.js → jest.config.cjs} +8 -1
  108. package/package.json +14 -9
  109. package/proto/bsync.proto +10 -0
  110. package/src/client.ts +1 -1
  111. package/src/context.ts +7 -7
  112. package/src/db/index.ts +12 -8
  113. package/src/db/migrations/index.ts +4 -4
  114. package/src/db/schema/index.ts +5 -5
  115. package/src/db/schema/mute_op.ts +1 -1
  116. package/src/db/schema/operation.ts +2 -2
  117. package/src/db/types.ts +3 -1
  118. package/src/index.ts +17 -13
  119. package/src/proto/bsync_connect.ts +10 -1
  120. package/src/proto/bsync_pb.ts +80 -0
  121. package/src/routes/add-mute-operation.ts +10 -7
  122. package/src/routes/add-notif-operation.ts +7 -7
  123. package/src/routes/auth.ts +1 -1
  124. package/src/routes/delete-operations.ts +45 -0
  125. package/src/routes/index.ts +10 -8
  126. package/src/routes/put-operation.ts +12 -24
  127. package/src/routes/scan-mute-operations.ts +6 -6
  128. package/src/routes/scan-notif-operations.ts +6 -6
  129. package/src/routes/scan-operations.ts +6 -6
  130. package/src/routes/util.ts +16 -0
  131. package/tests/delete-operations.test.ts +108 -0
  132. package/tests/mutes.test.ts +2 -2
  133. package/tests/notifications.test.ts +2 -2
  134. package/tests/operations.test.ts +2 -2
  135. package/tsconfig.build.json +1 -1
  136. package/tsconfig.build.tsbuildinfo +1 -1
  137. package/tsconfig.tests.json +1 -1
@@ -1,17 +1,20 @@
1
1
  import { Code, ConnectError, ServiceImpl } from '@connectrpc/connect'
2
2
  import { sql } from 'kysely'
3
- import { ensureValidNsid, ensureValidRecordKey } from '@atproto/syntax'
4
- import { AppContext } from '../context'
5
- import { Database } from '../db'
6
- import { OperationMethod, createOperationChannel } from '../db/schema/operation'
7
- import { Service } from '../proto/bsync_connect'
3
+ import { ensureValidRecordKey } from '@atproto/syntax'
4
+ import { AppContext } from '../context.js'
5
+ import { Database } from '../db/index.js'
6
+ import {
7
+ OperationMethod,
8
+ createOperationChannel,
9
+ } from '../db/schema/operation.js'
10
+ import { Service } from '../proto/bsync_connect.js'
8
11
  import {
9
12
  Method,
10
13
  PutOperationRequest,
11
14
  PutOperationResponse,
12
- } from '../proto/bsync_pb'
13
- import { authWithApiKey } from './auth'
14
- import { isValidDid } from './util'
15
+ } from '../proto/bsync_pb.js'
16
+ import { authWithApiKey } from './auth.js'
17
+ import { isValidDid, validateNamespace } from './util.js'
15
18
 
16
19
  export default (ctx: AppContext): Partial<ServiceImpl<typeof Service>> => ({
17
20
  async putOperation(req, handlerCtx) {
@@ -103,25 +106,10 @@ const validateOp = (req: PutOperationRequest): Operation => {
103
106
  return req as Operation
104
107
  }
105
108
 
106
- const validateNamespace = (namespace: string): void => {
107
- const parts = namespace.split('#')
108
-
109
- if (parts.length !== 1 && parts.length !== 2) {
110
- throw new Error('namespace must be in the format "nsid[#fragment]"')
111
- }
112
-
113
- const [nsid, fragment] = parts
114
-
115
- ensureValidNsid(nsid)
116
- if (fragment && !/^[a-zA-Z][a-zA-Z0-9]*$/.test(fragment)) {
117
- throw new Error('namespace fragment must be a valid identifier')
118
- }
119
- }
120
-
121
109
  type Operation = {
122
110
  actorDid: string
123
111
  namespace: string
124
112
  key: string
125
- payload: Uint8Array
113
+ payload: Uint8Array<ArrayBuffer>
126
114
  method: OperationMethod
127
115
  }
@@ -1,11 +1,11 @@
1
1
  import { once } from 'node:events'
2
2
  import { ServiceImpl } from '@connectrpc/connect'
3
- import { AppContext } from '../context'
4
- import { createMuteOpChannel } from '../db/schema/mute_op'
5
- import { Service } from '../proto/bsync_connect'
6
- import { ScanMuteOperationsResponse } from '../proto/bsync_pb'
7
- import { authWithApiKey } from './auth'
8
- import { combineSignals, validCursor } from './util'
3
+ import { AppContext } from '../context.js'
4
+ import { createMuteOpChannel } from '../db/schema/mute_op.js'
5
+ import { Service } from '../proto/bsync_connect.js'
6
+ import { ScanMuteOperationsResponse } from '../proto/bsync_pb.js'
7
+ import { authWithApiKey } from './auth.js'
8
+ import { combineSignals, validCursor } from './util.js'
9
9
 
10
10
  export default (ctx: AppContext): Partial<ServiceImpl<typeof Service>> => ({
11
11
  async scanMuteOperations(req, handlerCtx) {
@@ -1,11 +1,11 @@
1
1
  import { once } from 'node:events'
2
2
  import { ServiceImpl } from '@connectrpc/connect'
3
- import { AppContext } from '../context'
4
- import { createNotifOpChannel } from '../db/schema/notif_op'
5
- import { Service } from '../proto/bsync_connect'
6
- import { ScanNotifOperationsResponse } from '../proto/bsync_pb'
7
- import { authWithApiKey } from './auth'
8
- import { combineSignals, validCursor } from './util'
3
+ import { AppContext } from '../context.js'
4
+ import { createNotifOpChannel } from '../db/schema/notif_op.js'
5
+ import { Service } from '../proto/bsync_connect.js'
6
+ import { ScanNotifOperationsResponse } from '../proto/bsync_pb.js'
7
+ import { authWithApiKey } from './auth.js'
8
+ import { combineSignals, validCursor } from './util.js'
9
9
 
10
10
  export default (ctx: AppContext): Partial<ServiceImpl<typeof Service>> => ({
11
11
  async scanNotifOperations(req, handlerCtx) {
@@ -1,11 +1,11 @@
1
1
  import { once } from 'node:events'
2
2
  import { ServiceImpl } from '@connectrpc/connect'
3
- import { AppContext } from '../context'
4
- import { createOperationChannel } from '../db/schema/operation'
5
- import { Service } from '../proto/bsync_connect'
6
- import { ScanOperationsResponse } from '../proto/bsync_pb'
7
- import { authWithApiKey } from './auth'
8
- import { combineSignals, validCursor } from './util'
3
+ import { AppContext } from '../context.js'
4
+ import { createOperationChannel } from '../db/schema/operation.js'
5
+ import { Service } from '../proto/bsync_connect.js'
6
+ import { ScanOperationsResponse } from '../proto/bsync_pb.js'
7
+ import { authWithApiKey } from './auth.js'
8
+ import { combineSignals, validCursor } from './util.js'
9
9
 
10
10
  export default (ctx: AppContext): Partial<ServiceImpl<typeof Service>> => ({
11
11
  async scanOperations(req, handlerCtx) {
@@ -3,6 +3,7 @@ import {
3
3
  InvalidDidError,
4
4
  ensureValidAtUri,
5
5
  ensureValidDid,
6
+ ensureValidNsid,
6
7
  } from '@atproto/syntax'
7
8
 
8
9
  export const validCursor = (cursor: string): number | null => {
@@ -49,3 +50,18 @@ export const isValidAtUri = (uri: string) => {
49
50
  return false
50
51
  }
51
52
  }
53
+
54
+ export const validateNamespace = (namespace: string): void => {
55
+ const parts = namespace.split('#')
56
+
57
+ if (parts.length !== 1 && parts.length !== 2) {
58
+ throw new Error('namespace must be in the format "nsid[#fragment]"')
59
+ }
60
+
61
+ const [nsid, fragment] = parts
62
+
63
+ ensureValidNsid(nsid)
64
+ if (fragment && !/^[a-zA-Z][a-zA-Z0-9]*$/.test(fragment)) {
65
+ throw new Error('namespace fragment must be a valid identifier')
66
+ }
67
+ }
@@ -0,0 +1,108 @@
1
+ import getPort from 'get-port'
2
+ import {
3
+ BsyncClient,
4
+ BsyncService,
5
+ Database,
6
+ authWithApiKey,
7
+ createClient,
8
+ envToCfg,
9
+ } from '../src/index.js'
10
+ import { Method } from '../src/proto/bsync_pb.js'
11
+
12
+ describe('operations', () => {
13
+ let bsync: BsyncService
14
+ let client: BsyncClient
15
+
16
+ const validPayload0 = Buffer.from(JSON.stringify({ value: 0 }))
17
+ const validPayload1 = Buffer.from(JSON.stringify({ value: 1 }))
18
+
19
+ beforeAll(async () => {
20
+ bsync = await BsyncService.create(
21
+ envToCfg({
22
+ port: await getPort(),
23
+ dbUrl: process.env.DB_POSTGRES_URL,
24
+ dbSchema: 'bsync_delete_operations',
25
+ apiKeys: ['key-1'],
26
+ longPollTimeoutMs: 500,
27
+ }),
28
+ )
29
+ await bsync.ctx.db.migrateToLatestOrThrow()
30
+ await bsync.start()
31
+ client = createClient({
32
+ httpVersion: '1.1',
33
+ baseUrl: `http://localhost:${bsync.ctx.cfg.service.port}`,
34
+ interceptors: [authWithApiKey('key-1')],
35
+ })
36
+ })
37
+
38
+ afterAll(async () => {
39
+ await bsync.destroy()
40
+ })
41
+
42
+ beforeEach(async () => {
43
+ await clearOps(bsync.ctx.db)
44
+ })
45
+
46
+ it('deletes', async () => {
47
+ const res1 = await client.putOperation({
48
+ actorDid: 'did:example:a',
49
+ namespace: 'app.bsky.some.col',
50
+ key: 'key1',
51
+ method: Method.CREATE,
52
+ payload: validPayload0,
53
+ })
54
+ const res2 = await client.putOperation({
55
+ actorDid: 'did:example:a',
56
+ namespace: 'app.bsky.other.col#id',
57
+ key: 'key1',
58
+ method: Method.UPDATE,
59
+ payload: validPayload1,
60
+ })
61
+
62
+ expect(res1.operation?.id).toBe('1')
63
+ expect(res2.operation?.id).toBe('2')
64
+ expect(await dumpOps(bsync.ctx.db)).toStrictEqual([
65
+ {
66
+ id: 1,
67
+ actorDid: 'did:example:a',
68
+ namespace: 'app.bsky.some.col',
69
+ key: 'key1',
70
+ method: Method.CREATE,
71
+ payload: validPayload0,
72
+ createdAt: expect.any(Date),
73
+ },
74
+ {
75
+ id: 2,
76
+ actorDid: 'did:example:a',
77
+ namespace: 'app.bsky.other.col#id',
78
+ key: 'key1',
79
+ method: Method.UPDATE,
80
+ payload: validPayload1,
81
+ createdAt: expect.any(Date),
82
+ },
83
+ ])
84
+
85
+ await client.deleteOperationsByActorAndNamespace({
86
+ actorDid: 'did:example:a',
87
+ namespace: 'app.bsky.some.col',
88
+ })
89
+ await client.deleteOperationsByActorAndNamespace({
90
+ actorDid: 'did:example:a',
91
+ namespace: 'app.bsky.other.col#id',
92
+ })
93
+
94
+ expect(await dumpOps(bsync.ctx.db)).toStrictEqual([])
95
+ })
96
+ })
97
+
98
+ const dumpOps = async (db: Database) => {
99
+ return db.db
100
+ .selectFrom('operation')
101
+ .selectAll()
102
+ .orderBy('id', 'asc')
103
+ .execute()
104
+ }
105
+
106
+ const clearOps = async (db: Database) => {
107
+ await db.db.deleteFrom('operation').execute()
108
+ }
@@ -8,8 +8,8 @@ import {
8
8
  authWithApiKey,
9
9
  createClient,
10
10
  envToCfg,
11
- } from '../src'
12
- import { MuteOperation, MuteOperation_Type } from '../src/proto/bsync_pb'
11
+ } from '../src/index.js'
12
+ import { MuteOperation, MuteOperation_Type } from '../src/proto/bsync_pb.js'
13
13
 
14
14
  describe('mutes', () => {
15
15
  let bsync: BsyncService
@@ -8,8 +8,8 @@ import {
8
8
  authWithApiKey,
9
9
  createClient,
10
10
  envToCfg,
11
- } from '../src'
12
- import { NotifOperation } from '../src/proto/bsync_pb'
11
+ } from '../src/index.js'
12
+ import { NotifOperation } from '../src/proto/bsync_pb.js'
13
13
 
14
14
  describe('notifications', () => {
15
15
  let bsync: BsyncService
@@ -9,8 +9,8 @@ import {
9
9
  authWithApiKey,
10
10
  createClient,
11
11
  envToCfg,
12
- } from '../src'
13
- import { Method, Operation } from '../src/proto/bsync_pb'
12
+ } from '../src/index.js'
13
+ import { Method, Operation } from '../src/proto/bsync_pb.js'
14
14
 
15
15
  describe('operations', () => {
16
16
  let bsync: BsyncService
@@ -4,5 +4,5 @@
4
4
  "rootDir": "./src",
5
5
  "outDir": "./dist"
6
6
  },
7
- "include": ["./src"]
7
+ "include": ["./src", "../../tsconfig/cjs-default-exports.d.ts"]
8
8
  }
@@ -1 +1 @@
1
- {"root":["./src/client.ts","./src/config.ts","./src/context.ts","./src/index.ts","./src/logger.ts","./src/db/index.ts","./src/db/types.ts","./src/db/migrations/20240108T220751294Z-init.ts","./src/db/migrations/20240717T224303472Z-notif-ops.ts","./src/db/migrations/20250527T022203400Z-add-operation.ts","./src/db/migrations/20250603T163446567Z-alter-operation.ts","./src/db/migrations/index.ts","./src/db/migrations/provider.ts","./src/db/schema/index.ts","./src/db/schema/mute_item.ts","./src/db/schema/mute_op.ts","./src/db/schema/notif_item.ts","./src/db/schema/notif_op.ts","./src/db/schema/operation.ts","./src/proto/bsync_connect.ts","./src/proto/bsync_pb.ts","./src/routes/add-mute-operation.ts","./src/routes/add-notif-operation.ts","./src/routes/auth.ts","./src/routes/index.ts","./src/routes/put-operation.ts","./src/routes/scan-mute-operations.ts","./src/routes/scan-notif-operations.ts","./src/routes/scan-operations.ts","./src/routes/util.ts"],"version":"5.8.2"}
1
+ {"root":["./src/client.ts","./src/config.ts","./src/context.ts","./src/index.ts","./src/logger.ts","./src/db/index.ts","./src/db/types.ts","./src/db/migrations/20240108t220751294z-init.ts","./src/db/migrations/20240717t224303472z-notif-ops.ts","./src/db/migrations/20250527t022203400z-add-operation.ts","./src/db/migrations/20250603t163446567z-alter-operation.ts","./src/db/migrations/index.ts","./src/db/migrations/provider.ts","./src/db/schema/index.ts","./src/db/schema/mute_item.ts","./src/db/schema/mute_op.ts","./src/db/schema/notif_item.ts","./src/db/schema/notif_op.ts","./src/db/schema/operation.ts","./src/proto/bsync_connect.ts","./src/proto/bsync_pb.ts","./src/routes/add-mute-operation.ts","./src/routes/add-notif-operation.ts","./src/routes/auth.ts","./src/routes/delete-operations.ts","./src/routes/index.ts","./src/routes/put-operation.ts","./src/routes/scan-mute-operations.ts","./src/routes/scan-notif-operations.ts","./src/routes/scan-operations.ts","./src/routes/util.ts","../../tsconfig/cjs-default-exports.d.ts"],"version":"6.0.3"}
@@ -3,5 +3,5 @@
3
3
  "compilerOptions": {
4
4
  "rootDir": "."
5
5
  },
6
- "include": ["./tests"]
6
+ "include": ["./tests", "../../tsconfig/cjs-default-exports.d.ts"]
7
7
  }