@atproto/bsync 0.0.31 → 0.0.33

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 (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/logger.js +2 -2
  6. package/dist/logger.js.map +1 -1
  7. package/package.json +17 -13
  8. package/bin/migration-create.ts +0 -38
  9. package/buf.gen.yaml +0 -12
  10. package/jest.config.cjs +0 -21
  11. package/proto/bsync.proto +0 -134
  12. package/src/client.ts +0 -25
  13. package/src/config.ts +0 -90
  14. package/src/context.ts +0 -48
  15. package/src/db/index.ts +0 -200
  16. package/src/db/migrations/20240108T220751294Z-init.ts +0 -26
  17. package/src/db/migrations/20240717T224303472Z-notif-ops.ts +0 -24
  18. package/src/db/migrations/20250527T022203400Z-add-operation.ts +0 -20
  19. package/src/db/migrations/20250603T163446567Z-alter-operation.ts +0 -19
  20. package/src/db/migrations/index.ts +0 -8
  21. package/src/db/migrations/provider.ts +0 -8
  22. package/src/db/schema/index.ts +0 -16
  23. package/src/db/schema/mute_item.ts +0 -13
  24. package/src/db/schema/mute_op.ts +0 -18
  25. package/src/db/schema/notif_item.ts +0 -13
  26. package/src/db/schema/notif_op.ts +0 -16
  27. package/src/db/schema/operation.ts +0 -20
  28. package/src/db/types.ts +0 -19
  29. package/src/index.ts +0 -130
  30. package/src/logger.ts +0 -26
  31. package/src/routes/add-mute-operation.ts +0 -154
  32. package/src/routes/add-notif-operation.ts +0 -80
  33. package/src/routes/auth.ts +0 -15
  34. package/src/routes/delete-operations.ts +0 -45
  35. package/src/routes/index.ts +0 -28
  36. package/src/routes/put-operation.ts +0 -115
  37. package/src/routes/scan-mute-operations.ts +0 -65
  38. package/src/routes/scan-notif-operations.ts +0 -64
  39. package/src/routes/scan-operations.ts +0 -67
  40. package/src/routes/util.ts +0 -67
  41. package/tests/delete-operations.test.ts +0 -108
  42. package/tests/mutes.test.ts +0 -352
  43. package/tests/notifications.test.ts +0 -209
  44. package/tests/operations.test.ts +0 -327
  45. package/tsconfig.build.json +0 -8
  46. package/tsconfig.build.tsbuildinfo +0 -1
  47. package/tsconfig.json +0 -7
  48. package/tsconfig.tests.json +0 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atproto/bsync
2
2
 
3
+ ## 0.0.33
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update TypeScript build to rely on references to composite internal projects
8
+
9
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Bundle only necessary files in the NPM tarball, including the `CHANGELOG.md` and `README.md` files (if present).
10
+
11
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Build with `noImplicitAny` enabled
12
+
13
+ - Updated dependencies [[`28a0b58`](https://github.com/bluesky-social/atproto/commit/28a0b588147863eaef948cd2bb8fc0f19d08cda9), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07)]:
14
+ - @atproto/syntax@0.6.4
15
+ - @atproto/common@0.6.5
16
+
17
+ ## 0.0.32
18
+
19
+ ### Patch Changes
20
+
21
+ - [#4179](https://github.com/bluesky-social/atproto/pull/4179) [`85c25ef`](https://github.com/bluesky-social/atproto/commit/85c25efde14c1d0383f32bba21b21bdad2ae2619) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - Subscribe to the real bsync service in dev-env instead of using a mock, with a `BsyncSubscription` on the bsky dataplane that consumes the mute, notif, and operation streams. Supports immediate shutdown (aborting in-flight long-polls) and cursor-based draining so tests stay fast.
22
+
3
23
  ## 0.0.31
4
24
 
5
25
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAA;AAI5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAO5D,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,qBAAa,YAAY;IAChB,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;IAC1B,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAmC;IAEhD,YAAY,IAAI,EAAE;QAChB,GAAG,EAAE,UAAU,CAAA;QACf,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;QACnB,EAAE,EAAE,eAAe,CAAA;KACpB,EAKA;IAED,OAAa,MAAM,CACjB,GAAG,EAAE,YAAY,EACjB,SAAS,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACrC,OAAO,CAAC,YAAY,CAAC,CAiBvB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CA0BlC;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAS7B;IAEK,cAAc,kBAoBnB;CACF;eAEc,YAAY"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAA;AAI5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAO5D,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,qBAAa,YAAY;IAChB,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;IAC1B,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAmC;IAEhD,YAAY,IAAI,EAAE;QAChB,GAAG,EAAE,UAAU,CAAA;QACf,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;QACnB,EAAE,EAAE,eAAe,CAAA;KACpB,EAKA;IAED,OAAa,MAAM,CACjB,GAAG,EAAE,YAAY,EACjB,SAAS,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACrC,OAAO,CAAC,YAAY,CAAC,CAmBvB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CA0BlC;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAS7B;IAEK,cAAc,kBAoBnB;CACF;eAEc,YAAY"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import events from 'node:events';
1
+ import events, { setMaxListeners } from 'node:events';
2
2
  import http from 'node:http';
3
3
  import { connectNodeAdapter } from '@connectrpc/connect-node';
4
4
  // eslint-disable-next-line import/default
@@ -24,6 +24,8 @@ export class BsyncService {
24
24
  }
25
25
  static async create(cfg, overrides) {
26
26
  const ac = new AbortController();
27
+ // Prevents unhelpful warnings.
28
+ setMaxListeners(100, ac.signal);
27
29
  const ctx = await AppContext.fromConfig(cfg, ac.signal, overrides);
28
30
  const handler = connectNodeAdapter({
29
31
  routes: routes(ctx),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import events from 'node:events'\nimport http from 'node:http'\nimport { connectNodeAdapter } from '@connectrpc/connect-node'\n// eslint-disable-next-line import/default\nimport httpTerminator from 'http-terminator'\nimport { ServerConfig } from './config.js'\nimport { AppContext, AppContextOptions } from './context.js'\nimport { createMuteOpChannel } from './db/schema/mute_op.js'\nimport { createNotifOpChannel } from './db/schema/notif_op.js'\nimport { createOperationChannel } from './db/schema/operation.js'\nimport { dbLogger, loggerMiddleware } from './logger.js'\nimport routes from './routes/index.js'\n\nexport * from './config.js'\nexport * from './client.js'\nexport { Database } from './db/index.js'\nexport { AppContext } from './context.js'\nexport { httpLogger } from './logger.js'\n\ntype BsyncServiceState = 'initialized' | 'started' | 'destroyed'\n\nexport class BsyncService {\n public ctx: AppContext\n public server: http.Server\n private terminator: httpTerminator.HttpTerminator\n private ac: AbortController\n private state: BsyncServiceState = 'initialized'\n\n constructor(opts: {\n ctx: AppContext\n server: http.Server\n ac: AbortController\n }) {\n this.ctx = opts.ctx\n this.server = opts.server\n this.ac = opts.ac\n this.terminator = httpTerminator.createHttpTerminator(opts)\n }\n\n static async create(\n cfg: ServerConfig,\n overrides?: Partial<AppContextOptions>,\n ): Promise<BsyncService> {\n const ac = new AbortController()\n const ctx = await AppContext.fromConfig(cfg, ac.signal, overrides)\n const handler = connectNodeAdapter({\n routes: routes(ctx),\n shutdownSignal: ac.signal,\n })\n const server = http.createServer((req, res) => {\n loggerMiddleware(req, res)\n if (isHealth(req.url)) {\n res.statusCode = 200\n res.setHeader('content-type', 'application/json')\n return res.end(JSON.stringify({ version: cfg.service.version }))\n }\n handler(req, res)\n })\n return new BsyncService({ ctx, server, ac })\n }\n\n async start(): Promise<http.Server> {\n if (this.state !== 'initialized') {\n throw new Error(`${this.constructor.name} already started`)\n }\n this.state = 'started'\n\n const dbStatsInterval = setInterval(() => {\n dbLogger.info(\n {\n idleCount: this.ctx.db.pool.idleCount,\n totalCount: this.ctx.db.pool.totalCount,\n waitingCount: this.ctx.db.pool.waitingCount,\n },\n 'db pool stats',\n )\n }, 10000)\n\n this.ac.signal.addEventListener('abort', () => {\n clearInterval(dbStatsInterval)\n })\n\n await this.setupAppEvents()\n this.server.listen(this.ctx.cfg.service.port)\n this.server.keepAliveTimeout = 90000\n await events.once(this.server, 'listening')\n return this.server\n }\n\n async destroy(): Promise<void> {\n if (this.state === 'destroyed') return\n this.state = 'destroyed'\n this.ac.abort()\n try {\n await this.terminator.terminate()\n } finally {\n await this.ctx.db.close()\n }\n }\n\n async setupAppEvents() {\n const conn = await this.ctx.db.pool.connect()\n this.ac.signal.addEventListener('abort', () => conn.release(), {\n once: true,\n })\n // if these error, unhandled rejection should cause process to exit\n conn.query(`listen ${createMuteOpChannel}`)\n conn.query(`listen ${createNotifOpChannel}`)\n conn.query(`listen ${createOperationChannel}`)\n conn.on('notification', (notif) => {\n if (notif.channel === createMuteOpChannel) {\n this.ctx.events.emit(createMuteOpChannel)\n }\n if (notif.channel === createNotifOpChannel) {\n this.ctx.events.emit(createNotifOpChannel)\n }\n if (notif.channel === createOperationChannel) {\n this.ctx.events.emit(createOperationChannel)\n }\n })\n }\n}\n\nexport default BsyncService\n\nconst isHealth = (urlStr: string | undefined) => {\n if (!urlStr) return false\n const url = new URL(urlStr, 'http://host')\n return url.pathname === '/_health'\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import events, { setMaxListeners } from 'node:events'\nimport http from 'node:http'\nimport { connectNodeAdapter } from '@connectrpc/connect-node'\n// eslint-disable-next-line import/default\nimport httpTerminator from 'http-terminator'\nimport { ServerConfig } from './config.js'\nimport { AppContext, AppContextOptions } from './context.js'\nimport { createMuteOpChannel } from './db/schema/mute_op.js'\nimport { createNotifOpChannel } from './db/schema/notif_op.js'\nimport { createOperationChannel } from './db/schema/operation.js'\nimport { dbLogger, loggerMiddleware } from './logger.js'\nimport routes from './routes/index.js'\n\nexport * from './config.js'\nexport * from './client.js'\nexport { Database } from './db/index.js'\nexport { AppContext } from './context.js'\nexport { httpLogger } from './logger.js'\n\ntype BsyncServiceState = 'initialized' | 'started' | 'destroyed'\n\nexport class BsyncService {\n public ctx: AppContext\n public server: http.Server\n private terminator: httpTerminator.HttpTerminator\n private ac: AbortController\n private state: BsyncServiceState = 'initialized'\n\n constructor(opts: {\n ctx: AppContext\n server: http.Server\n ac: AbortController\n }) {\n this.ctx = opts.ctx\n this.server = opts.server\n this.ac = opts.ac\n this.terminator = httpTerminator.createHttpTerminator(opts)\n }\n\n static async create(\n cfg: ServerConfig,\n overrides?: Partial<AppContextOptions>,\n ): Promise<BsyncService> {\n const ac = new AbortController()\n // Prevents unhelpful warnings.\n setMaxListeners(100, ac.signal)\n const ctx = await AppContext.fromConfig(cfg, ac.signal, overrides)\n const handler = connectNodeAdapter({\n routes: routes(ctx),\n shutdownSignal: ac.signal,\n })\n const server = http.createServer((req, res) => {\n loggerMiddleware(req, res)\n if (isHealth(req.url)) {\n res.statusCode = 200\n res.setHeader('content-type', 'application/json')\n return res.end(JSON.stringify({ version: cfg.service.version }))\n }\n handler(req, res)\n })\n return new BsyncService({ ctx, server, ac })\n }\n\n async start(): Promise<http.Server> {\n if (this.state !== 'initialized') {\n throw new Error(`${this.constructor.name} already started`)\n }\n this.state = 'started'\n\n const dbStatsInterval = setInterval(() => {\n dbLogger.info(\n {\n idleCount: this.ctx.db.pool.idleCount,\n totalCount: this.ctx.db.pool.totalCount,\n waitingCount: this.ctx.db.pool.waitingCount,\n },\n 'db pool stats',\n )\n }, 10000)\n\n this.ac.signal.addEventListener('abort', () => {\n clearInterval(dbStatsInterval)\n })\n\n await this.setupAppEvents()\n this.server.listen(this.ctx.cfg.service.port)\n this.server.keepAliveTimeout = 90000\n await events.once(this.server, 'listening')\n return this.server\n }\n\n async destroy(): Promise<void> {\n if (this.state === 'destroyed') return\n this.state = 'destroyed'\n this.ac.abort()\n try {\n await this.terminator.terminate()\n } finally {\n await this.ctx.db.close()\n }\n }\n\n async setupAppEvents() {\n const conn = await this.ctx.db.pool.connect()\n this.ac.signal.addEventListener('abort', () => conn.release(), {\n once: true,\n })\n // if these error, unhandled rejection should cause process to exit\n conn.query(`listen ${createMuteOpChannel}`)\n conn.query(`listen ${createNotifOpChannel}`)\n conn.query(`listen ${createOperationChannel}`)\n conn.on('notification', (notif) => {\n if (notif.channel === createMuteOpChannel) {\n this.ctx.events.emit(createMuteOpChannel)\n }\n if (notif.channel === createNotifOpChannel) {\n this.ctx.events.emit(createNotifOpChannel)\n }\n if (notif.channel === createOperationChannel) {\n this.ctx.events.emit(createOperationChannel)\n }\n })\n }\n}\n\nexport default BsyncService\n\nconst isHealth = (urlStr: string | undefined) => {\n if (!urlStr) return false\n const url = new URL(urlStr, 'http://host')\n return url.pathname === '/_health'\n}\n"]}
package/dist/logger.js CHANGED
@@ -9,8 +9,8 @@ export const loggerMiddleware = pinoHttp({
9
9
  },
10
10
  serializers: {
11
11
  err: (err) => ({
12
- code: err?.['code'],
13
- message: err?.['message'],
12
+ code: err?.code,
13
+ message: err?.message,
14
14
  }),
15
15
  req: (req) => {
16
16
  const serialized = stdSerializers.req(req);
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEnE,MAAM,CAAC,MAAM,QAAQ,GACnB,eAAe,CAAC,UAAU,CAAC,CAAA;AAC7B,MAAM,CAAC,MAAM,UAAU,GACrB,eAAe,CAAC,OAAO,CAAC,CAAA;AAE1B,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE;QACN,KAAK,EAAE,CAAC,2BAA2B,CAAC;KACrC;IACD,WAAW,EAAE;QACX,GAAG,EAAE,CAAC,GAAY,EAAE,EAAE,CAAC,CAAC;YACtB,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC;YACnB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC;SAC1B,CAAC;QACF,GAAG,EAAE,CAAC,GAAoB,EAAE,EAAE;YAC5B,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YACpD,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,CAAA;QACnC,CAAC;KACF;CACF,CAAC,CAAA","sourcesContent":["import { type IncomingMessage } from 'node:http'\nimport { pinoHttp, stdSerializers } from 'pino-http'\nimport { obfuscateHeaders, subsystemLogger } from '@atproto/common'\n\nexport const dbLogger: ReturnType<typeof subsystemLogger> =\n subsystemLogger('bsync:db')\nexport const httpLogger: ReturnType<typeof subsystemLogger> =\n subsystemLogger('bsync')\n\nexport const loggerMiddleware = pinoHttp({\n logger: httpLogger,\n redact: {\n paths: ['req.headers.authorization'],\n },\n serializers: {\n err: (err: unknown) => ({\n code: err?.['code'],\n message: err?.['message'],\n }),\n req: (req: IncomingMessage) => {\n const serialized = stdSerializers.req(req)\n const headers = obfuscateHeaders(serialized.headers)\n return { ...serialized, headers }\n },\n },\n})\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEnE,MAAM,CAAC,MAAM,QAAQ,GACnB,eAAe,CAAC,UAAU,CAAC,CAAA;AAC7B,MAAM,CAAC,MAAM,UAAU,GACrB,eAAe,CAAC,OAAO,CAAC,CAAA;AAE1B,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE;QACN,KAAK,EAAE,CAAC,2BAA2B,CAAC;KACrC;IACD,WAAW,EAAE;QACX,GAAG,EAAE,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;YAClB,IAAI,EAAE,GAAG,EAAE,IAAI;YACf,OAAO,EAAE,GAAG,EAAE,OAAO;SACtB,CAAC;QACF,GAAG,EAAE,CAAC,GAAoB,EAAE,EAAE;YAC5B,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YACpD,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,CAAA;QACnC,CAAC;KACF;CACF,CAAC,CAAA","sourcesContent":["import { type IncomingMessage } from 'node:http'\nimport { pinoHttp, stdSerializers } from 'pino-http'\nimport { obfuscateHeaders, subsystemLogger } from '@atproto/common'\n\nexport const dbLogger: ReturnType<typeof subsystemLogger> =\n subsystemLogger('bsync:db')\nexport const httpLogger: ReturnType<typeof subsystemLogger> =\n subsystemLogger('bsync')\n\nexport const loggerMiddleware = pinoHttp({\n logger: httpLogger,\n redact: {\n paths: ['req.headers.authorization'],\n },\n serializers: {\n err: (err: any) => ({\n code: err?.code,\n message: err?.message,\n }),\n req: (req: IncomingMessage) => {\n const serialized = stdSerializers.req(req)\n const headers = obfuscateHeaders(serialized.headers)\n return { ...serialized, headers }\n },\n },\n})\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/bsync",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "license": "MIT",
5
5
  "description": "Sychronizing service for app.bsky App View (Bluesky API)",
6
6
  "keywords": [
@@ -13,6 +13,18 @@
13
13
  "url": "https://github.com/bluesky-social/atproto",
14
14
  "directory": "packages/bsync"
15
15
  },
16
+ "files": [
17
+ "./dist",
18
+ "./README.md",
19
+ "./CHANGELOG.md"
20
+ ],
21
+ "type": "module",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ }
27
+ },
16
28
  "engines": {
17
29
  "node": ">=22"
18
30
  },
@@ -25,8 +37,8 @@
25
37
  "pg": "^8.10.0",
26
38
  "pino-http": "^11.0.0",
27
39
  "typed-emitter": "^2.1.0",
28
- "@atproto/common": "^0.6.4",
29
- "@atproto/syntax": "^0.6.3"
40
+ "@atproto/common": "^0.6.5",
41
+ "@atproto/syntax": "^0.6.4"
30
42
  },
31
43
  "devDependencies": {
32
44
  "@bufbuild/buf": "^1.28.1",
@@ -34,15 +46,7 @@
34
46
  "@connectrpc/protoc-gen-connect-es": "^1.1.4",
35
47
  "@types/pg": "^8.15.5",
36
48
  "get-port": "^5.1.1",
37
- "jest": "^30.0.0",
38
- "ts-node": "^10.8.2"
39
- },
40
- "type": "module",
41
- "exports": {
42
- ".": {
43
- "types": "./dist/index.d.ts",
44
- "default": "./dist/index.js"
45
- }
49
+ "jest": "^30.0.0"
46
50
  },
47
51
  "scripts": {
48
52
  "codegen:buf": "buf generate proto",
@@ -52,7 +56,7 @@
52
56
  "test": "NODE_OPTIONS=--experimental-vm-modules ../dev-infra/with-test-db.sh jest",
53
57
  "test:log": "tail -50 test.log | pino-pretty",
54
58
  "test:updateSnapshot": "jest --updateSnapshot",
55
- "migration:create": "ts-node ./bin/migration-create.ts",
59
+ "migration:create": "node ./bin/migration-create.ts",
56
60
  "buf:gen": ">&2 echo 'DEPRECATED: run `pnpm run codegen:buf` instead ' && pnpm run codegen:buf"
57
61
  }
58
62
  }
@@ -1,38 +0,0 @@
1
- #!/usr/bin/env ts-node
2
-
3
- import * as fs from 'node:fs/promises'
4
- import * as path from 'node:path'
5
-
6
- export async function main() {
7
- const now = new Date()
8
- const prefix = now.toISOString().replace(/[^a-z0-9]/gi, '') // Order of migrations matches alphabetical order of their names
9
- const name = process.argv[2]
10
- if (!name || !name.match(/^[a-z0-9-]+$/)) {
11
- process.exitCode = 1
12
- return console.error(
13
- 'Must pass a migration name consisting of lowercase digits, numbers, and dashes.',
14
- )
15
- }
16
- const filename = `${prefix}-${name}`
17
- const dir = path.join(__dirname, '..', 'src', 'db', 'migrations')
18
-
19
- await fs.writeFile(path.join(dir, `${filename}.ts`), template, { flag: 'wx' })
20
- await fs.writeFile(
21
- path.join(dir, 'index.ts'),
22
- `export * as _${prefix} from './${filename}.js'\n`,
23
- { flag: 'a' },
24
- )
25
- }
26
-
27
- const template = `import { Kysely } from 'kysely'
28
-
29
- export async function up(db: Kysely<unknown>): Promise<void> {
30
- // Migration code
31
- }
32
-
33
- export async function down(db: Kysely<unknown>): Promise<void> {
34
- // Migration code
35
- }
36
- `
37
-
38
- main()
package/buf.gen.yaml DELETED
@@ -1,12 +0,0 @@
1
- version: v1
2
- plugins:
3
- - plugin: es
4
- opt:
5
- - target=ts
6
- - import_extension=
7
- out: src/proto
8
- - plugin: connect-es
9
- opt:
10
- - target=ts
11
- - import_extension=.js
12
- out: src/proto
package/jest.config.cjs DELETED
@@ -1,21 +0,0 @@
1
- /** @type {import('jest').Config} */
2
- module.exports = {
3
- displayName: 'Bsync',
4
- transform: {
5
- '^.+\\.(t|j)s$': [
6
- '@swc/jest',
7
- {
8
- jsc: {
9
- parser: { syntax: 'typescript', importAttributes: true },
10
- experimental: { keepImportAttributes: true },
11
- transform: {},
12
- },
13
- module: { type: 'es6' },
14
- },
15
- ],
16
- },
17
- extensionsToTreatAsEsm: ['.ts'],
18
- transformIgnorePatterns: [],
19
- setupFiles: ['<rootDir>/../../test.setup.ts'],
20
- moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] },
21
- }
package/proto/bsync.proto DELETED
@@ -1,134 +0,0 @@
1
- syntax = "proto3";
2
-
3
- package bsync;
4
- option go_package = "./;bsync";
5
-
6
- //
7
- // Sync
8
- //
9
-
10
-
11
- message MuteOperation {
12
- enum Type {
13
- TYPE_UNSPECIFIED = 0;
14
- TYPE_ADD = 1;
15
- TYPE_REMOVE = 2;
16
- TYPE_CLEAR = 3;
17
- }
18
- string id = 1;
19
- Type type = 2;
20
- string actor_did = 3;
21
- string subject = 4;
22
- }
23
-
24
- message AddMuteOperationRequest {
25
- MuteOperation.Type type = 1;
26
- string actor_did = 2;
27
- string subject = 3;
28
- }
29
-
30
- message AddMuteOperationResponse {
31
- MuteOperation operation = 1;
32
- }
33
-
34
- message ScanMuteOperationsRequest {
35
- string cursor = 1;
36
- int32 limit = 2;
37
- }
38
-
39
- message ScanMuteOperationsResponse {
40
- repeated MuteOperation operations = 1;
41
- string cursor = 2;
42
- }
43
-
44
- message NotifOperation {
45
- string id = 1;
46
- string actor_did = 2;
47
- optional bool priority = 3;
48
- }
49
-
50
- message AddNotifOperationRequest {
51
- string actor_did = 1;
52
- optional bool priority = 2;
53
- }
54
-
55
- message AddNotifOperationResponse {
56
- NotifOperation operation = 1;
57
- }
58
-
59
- message ScanNotifOperationsRequest {
60
- string cursor = 1;
61
- int32 limit = 2;
62
- }
63
-
64
- message ScanNotifOperationsResponse {
65
- repeated NotifOperation operations = 1;
66
- string cursor = 2;
67
- }
68
-
69
-
70
- enum Method {
71
- METHOD_UNSPECIFIED = 0;
72
- METHOD_CREATE = 1;
73
- METHOD_UPDATE = 2;
74
- METHOD_DELETE = 3;
75
- }
76
-
77
- message Operation {
78
- string id = 1;
79
- string actor_did = 2;
80
- string namespace = 3;
81
- string key = 4;
82
- Method method = 5;
83
- bytes payload = 6;
84
- }
85
-
86
- message PutOperationRequest {
87
- string actor_did = 1;
88
- string namespace = 2;
89
- string key = 3;
90
- Method method = 4;
91
- bytes payload = 5;
92
- }
93
-
94
- message PutOperationResponse {
95
- Operation operation = 1;
96
- }
97
-
98
- message ScanOperationsRequest {
99
- string cursor = 1;
100
- int32 limit = 2;
101
- }
102
-
103
- message ScanOperationsResponse {
104
- repeated Operation operations = 1;
105
- string cursor = 2;
106
- }
107
-
108
- message DeleteOperationsByActorAndNamespaceRequest {
109
- string actor_did = 1;
110
- string namespace = 2;
111
- }
112
-
113
- message DeleteOperationsByActorAndNamespaceResponse {
114
- int32 deleted_count = 1;
115
- }
116
-
117
-
118
- // Ping
119
- message PingRequest {}
120
- message PingResponse {}
121
-
122
-
123
- service Service {
124
- // Sync
125
- rpc AddMuteOperation(AddMuteOperationRequest) returns (AddMuteOperationResponse);
126
- rpc ScanMuteOperations(ScanMuteOperationsRequest) returns (ScanMuteOperationsResponse);
127
- rpc AddNotifOperation(AddNotifOperationRequest) returns (AddNotifOperationResponse);
128
- rpc ScanNotifOperations(ScanNotifOperationsRequest) returns (ScanNotifOperationsResponse);
129
- rpc PutOperation(PutOperationRequest) returns (PutOperationResponse);
130
- rpc ScanOperations(ScanOperationsRequest) returns (ScanOperationsResponse);
131
- rpc DeleteOperationsByActorAndNamespace(DeleteOperationsByActorAndNamespaceRequest) returns (DeleteOperationsByActorAndNamespaceResponse);
132
- // Ping
133
- rpc Ping(PingRequest) returns (PingResponse);
134
- }
package/src/client.ts DELETED
@@ -1,25 +0,0 @@
1
- import {
2
- Interceptor,
3
- PromiseClient,
4
- createPromiseClient,
5
- } from '@connectrpc/connect'
6
- import {
7
- ConnectTransportOptions,
8
- createConnectTransport,
9
- } from '@connectrpc/connect-node'
10
- import { Service } from './proto/bsync_connect.js'
11
-
12
- export type BsyncClient = PromiseClient<typeof Service>
13
-
14
- export const createClient = (opts: ConnectTransportOptions): BsyncClient => {
15
- const transport = createConnectTransport(opts)
16
- return createPromiseClient(Service, transport)
17
- }
18
-
19
- export const authWithApiKey =
20
- (apiKey: string): Interceptor =>
21
- (next) =>
22
- (req) => {
23
- req.header.set('authorization', `Bearer ${apiKey}`)
24
- return next(req)
25
- }
package/src/config.ts DELETED
@@ -1,90 +0,0 @@
1
- import assert from 'node:assert'
2
- import { envBool, envInt, envList, envStr } from '@atproto/common'
3
-
4
- export const envToCfg = (env: ServerEnvironment): ServerConfig => {
5
- const serviceCfg: ServerConfig['service'] = {
6
- port: env.port ?? 2585,
7
- version: env.version ?? 'unknown',
8
- longPollTimeoutMs: env.longPollTimeoutMs ?? 10000,
9
- }
10
-
11
- assert(env.dbUrl, 'missing postgres url')
12
- const dbCfg: ServerConfig['db'] = {
13
- url: env.dbUrl,
14
- schema: env.dbSchema,
15
- poolSize: env.dbPoolSize,
16
- poolMaxUses: env.dbPoolMaxUses,
17
- poolIdleTimeoutMs: env.dbPoolIdleTimeoutMs,
18
- migrate: env.dbMigrate,
19
- }
20
-
21
- assert(env.apiKeys.length > 0, 'missing api keys')
22
- const authCfg: ServerConfig['auth'] = {
23
- apiKeys: new Set(env.apiKeys),
24
- }
25
-
26
- return {
27
- service: serviceCfg,
28
- db: dbCfg,
29
- auth: authCfg,
30
- }
31
- }
32
-
33
- export type ServerConfig = {
34
- service: ServiceConfig
35
- db: DatabaseConfig
36
- auth: AuthConfig
37
- }
38
-
39
- type ServiceConfig = {
40
- port: number
41
- version?: string
42
- longPollTimeoutMs: number
43
- }
44
-
45
- type DatabaseConfig = {
46
- url: string
47
- schema?: string
48
- poolSize?: number
49
- poolMaxUses?: number
50
- poolIdleTimeoutMs?: number
51
- migrate?: boolean
52
- }
53
-
54
- type AuthConfig = {
55
- apiKeys: Set<string>
56
- }
57
-
58
- export const readEnv = (): ServerEnvironment => {
59
- return {
60
- // service
61
- port: envInt('BSYNC_PORT'),
62
- version: envStr('BSYNC_VERSION'),
63
- longPollTimeoutMs: envInt('BSYNC_LONG_POLL_TIMEOUT_MS'),
64
- // database
65
- dbUrl: envStr('BSYNC_DB_POSTGRES_URL'),
66
- dbSchema: envStr('BSYNC_DB_POSTGRES_SCHEMA'),
67
- dbPoolSize: envInt('BSYNC_DB_POOL_SIZE'),
68
- dbPoolMaxUses: envInt('BSYNC_DB_POOL_MAX_USES'),
69
- dbPoolIdleTimeoutMs: envInt('BSYNC_DB_POOL_IDLE_TIMEOUT_MS'),
70
- dbMigrate: envBool('BSYNC_DB_MIGRATE'),
71
- // secrets
72
- apiKeys: envList('BSYNC_API_KEYS'),
73
- }
74
- }
75
-
76
- export type ServerEnvironment = {
77
- // service
78
- port?: number
79
- version?: string
80
- longPollTimeoutMs?: number
81
- // database
82
- dbUrl?: string
83
- dbSchema?: string
84
- dbPoolSize?: number
85
- dbPoolMaxUses?: number
86
- dbPoolIdleTimeoutMs?: number
87
- dbMigrate?: boolean
88
- // secrets
89
- apiKeys: string[]
90
- }
package/src/context.ts DELETED
@@ -1,48 +0,0 @@
1
- import { EventEmitter } from 'node:events'
2
- import type TypedEmitter from 'typed-emitter'
3
- import { ServerConfig } from './config.js'
4
- import { Database } from './db/index.js'
5
- import { createMuteOpChannel } from './db/schema/mute_op.js'
6
- import { createNotifOpChannel } from './db/schema/notif_op.js'
7
- import { createOperationChannel } from './db/schema/operation.js'
8
-
9
- export type AppContextOptions = {
10
- db: Database
11
- cfg: ServerConfig
12
- shutdown: AbortSignal
13
- }
14
-
15
- export class AppContext {
16
- db: Database
17
- cfg: ServerConfig
18
- shutdown: AbortSignal
19
- events: TypedEmitter.default<AppEvents>
20
-
21
- constructor(opts: AppContextOptions) {
22
- this.db = opts.db
23
- this.cfg = opts.cfg
24
- this.shutdown = opts.shutdown
25
- this.events = new EventEmitter() as TypedEmitter.default<AppEvents>
26
- }
27
-
28
- static async fromConfig(
29
- cfg: ServerConfig,
30
- shutdown: AbortSignal,
31
- overrides?: Partial<AppContextOptions>,
32
- ): Promise<AppContext> {
33
- const db = new Database({
34
- url: cfg.db.url,
35
- schema: cfg.db.schema,
36
- poolSize: cfg.db.poolSize,
37
- poolMaxUses: cfg.db.poolMaxUses,
38
- poolIdleTimeoutMs: cfg.db.poolIdleTimeoutMs,
39
- })
40
- return new AppContext({ db, cfg, shutdown, ...overrides })
41
- }
42
- }
43
-
44
- export type AppEvents = {
45
- [createMuteOpChannel]: () => void
46
- [createNotifOpChannel]: () => void
47
- [createOperationChannel]: () => void
48
- }