@atproto/bsync
Advanced tools
Comparing version 0.0.1 to 0.0.2-next.0
# @atproto/bsync | ||
## 0.0.2-next.0 | ||
### Patch Changes | ||
- Updated dependencies []: | ||
- @atproto/common@0.3.4-next.0 | ||
- @atproto/syntax@0.2.1-next.0 | ||
## 0.0.1 | ||
@@ -4,0 +12,0 @@ |
@@ -7,1 +7,2 @@ import { Interceptor, PromiseClient } from '@connectrpc/connect'; | ||
export declare const authWithApiKey: (apiKey: string) => Interceptor; | ||
//# sourceMappingURL=client.d.ts.map |
@@ -37,1 +37,2 @@ export declare const envToCfg: (env: ServerEnvironment) => ServerConfig; | ||
export {}; | ||
//# sourceMappingURL=config.d.ts.map |
@@ -0,1 +1,2 @@ | ||
/// <reference types="node" /> | ||
import TypedEventEmitter from 'typed-emitter'; | ||
@@ -8,2 +9,3 @@ import { ServerConfig } from './config'; | ||
cfg: ServerConfig; | ||
shutdown: AbortSignal; | ||
}; | ||
@@ -13,5 +15,6 @@ export declare class AppContext { | ||
cfg: ServerConfig; | ||
shutdown: AbortSignal; | ||
events: TypedEventEmitter<AppEvents>; | ||
constructor(opts: AppContextOptions); | ||
static fromConfig(cfg: ServerConfig, overrides?: Partial<AppContextOptions>): Promise<AppContext>; | ||
static fromConfig(cfg: ServerConfig, shutdown: AbortSignal, overrides?: Partial<AppContextOptions>): Promise<AppContext>; | ||
} | ||
@@ -22,1 +25,2 @@ export default AppContext; | ||
}; | ||
//# sourceMappingURL=context.d.ts.map |
@@ -32,1 +32,2 @@ import { Migrator } from 'kysely'; | ||
}; | ||
//# sourceMappingURL=index.d.ts.map |
import { Kysely } from 'kysely'; | ||
export declare function up(db: Kysely<unknown>): Promise<void>; | ||
export declare function down(db: Kysely<unknown>): Promise<void>; | ||
//# sourceMappingURL=20240108T220751294Z-init.d.ts.map |
export * as _20240108T220751294Z from './20240108T220751294Z-init'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -7,1 +7,2 @@ import { Migration, MigrationProvider } from 'kysely'; | ||
} | ||
//# sourceMappingURL=provider.d.ts.map |
@@ -7,1 +7,2 @@ import { Kysely } from 'kysely'; | ||
export default DatabaseSchema; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -12,1 +12,2 @@ import { Selectable } from 'kysely'; | ||
}; | ||
//# sourceMappingURL=mute_item.d.ts.map |
@@ -16,1 +16,2 @@ import { GeneratedAlways, Selectable } from 'kysely'; | ||
export declare const createMuteOpChannel = "mute_op_create"; | ||
//# sourceMappingURL=mute_op.d.ts.map |
@@ -13,1 +13,2 @@ import { Pool as PgPool } from 'pg'; | ||
}; | ||
//# sourceMappingURL=types.d.ts.map |
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import http from 'node:http'; | ||
@@ -15,3 +16,3 @@ import AppContext, { AppContextOptions } from './context'; | ||
private terminator; | ||
private dbStatsInterval; | ||
private dbStatsInterval?; | ||
constructor(opts: { | ||
@@ -28,1 +29,2 @@ ctx: AppContext; | ||
export default BsyncService; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -5,1 +5,2 @@ import { subsystemLogger } from '@atproto/common'; | ||
export declare const loggerMiddleware: import("pino-http").HttpLogger; | ||
//# sourceMappingURL=logger.d.ts.map |
@@ -1,6 +0,14 @@ | ||
import { AddMuteOperationRequest, AddMuteOperationResponse, PingRequest, PingResponse, ScanMuteOperationsRequest, ScanMuteOperationsResponse } from './bsync_pb.ts'; | ||
import { AddMuteOperationRequest, AddMuteOperationResponse, PingRequest, PingResponse, ScanMuteOperationsRequest, ScanMuteOperationsResponse } from './bsync_pb'; | ||
import { MethodKind } from '@bufbuild/protobuf'; | ||
/** | ||
* @generated from service bsync.Service | ||
*/ | ||
export declare const Service: { | ||
readonly typeName: "bsync.Service"; | ||
readonly methods: { | ||
/** | ||
* Sync | ||
* | ||
* @generated from rpc bsync.Service.AddMuteOperation | ||
*/ | ||
readonly addMuteOperation: { | ||
@@ -12,2 +20,5 @@ readonly name: "AddMuteOperation"; | ||
}; | ||
/** | ||
* @generated from rpc bsync.Service.ScanMuteOperations | ||
*/ | ||
readonly scanMuteOperations: { | ||
@@ -19,2 +30,7 @@ readonly name: "ScanMuteOperations"; | ||
}; | ||
/** | ||
* Ping | ||
* | ||
* @generated from rpc bsync.Service.Ping | ||
*/ | ||
readonly ping: { | ||
@@ -28,1 +44,2 @@ readonly name: "Ping"; | ||
}; | ||
//# sourceMappingURL=bsync_connect.d.ts.map |
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from '@bufbuild/protobuf'; | ||
import { Message, proto3 } from '@bufbuild/protobuf'; | ||
/** | ||
* @generated from message bsync.MuteOperation | ||
*/ | ||
export declare class MuteOperation extends Message<MuteOperation> { | ||
/** | ||
* @generated from field: string id = 1; | ||
*/ | ||
id: string; | ||
/** | ||
* @generated from field: bsync.MuteOperation.Type type = 2; | ||
*/ | ||
type: MuteOperation_Type; | ||
/** | ||
* @generated from field: string actor_did = 3; | ||
*/ | ||
actorDid: string; | ||
/** | ||
* @generated from field: string subject = 4; | ||
*/ | ||
subject: string; | ||
@@ -17,11 +32,38 @@ constructor(data?: PartialMessage<MuteOperation>); | ||
} | ||
/** | ||
* @generated from enum bsync.MuteOperation.Type | ||
*/ | ||
export declare enum MuteOperation_Type { | ||
/** | ||
* @generated from enum value: TYPE_UNSPECIFIED = 0; | ||
*/ | ||
UNSPECIFIED = 0, | ||
/** | ||
* @generated from enum value: TYPE_ADD = 1; | ||
*/ | ||
ADD = 1, | ||
/** | ||
* @generated from enum value: TYPE_REMOVE = 2; | ||
*/ | ||
REMOVE = 2, | ||
/** | ||
* @generated from enum value: TYPE_CLEAR = 3; | ||
*/ | ||
CLEAR = 3 | ||
} | ||
/** | ||
* @generated from message bsync.AddMuteOperationRequest | ||
*/ | ||
export declare class AddMuteOperationRequest extends Message<AddMuteOperationRequest> { | ||
/** | ||
* @generated from field: bsync.MuteOperation.Type type = 1; | ||
*/ | ||
type: MuteOperation_Type; | ||
/** | ||
* @generated from field: string actor_did = 2; | ||
*/ | ||
actorDid: string; | ||
/** | ||
* @generated from field: string subject = 3; | ||
*/ | ||
subject: string; | ||
@@ -37,3 +79,9 @@ constructor(data?: PartialMessage<AddMuteOperationRequest>); | ||
} | ||
/** | ||
* @generated from message bsync.AddMuteOperationResponse | ||
*/ | ||
export declare class AddMuteOperationResponse extends Message<AddMuteOperationResponse> { | ||
/** | ||
* @generated from field: bsync.MuteOperation operation = 1; | ||
*/ | ||
operation?: MuteOperation; | ||
@@ -49,4 +97,13 @@ constructor(data?: PartialMessage<AddMuteOperationResponse>); | ||
} | ||
/** | ||
* @generated from message bsync.ScanMuteOperationsRequest | ||
*/ | ||
export declare class ScanMuteOperationsRequest extends Message<ScanMuteOperationsRequest> { | ||
/** | ||
* @generated from field: string cursor = 1; | ||
*/ | ||
cursor: string; | ||
/** | ||
* @generated from field: int32 limit = 2; | ||
*/ | ||
limit: number; | ||
@@ -62,4 +119,13 @@ constructor(data?: PartialMessage<ScanMuteOperationsRequest>); | ||
} | ||
/** | ||
* @generated from message bsync.ScanMuteOperationsResponse | ||
*/ | ||
export declare class ScanMuteOperationsResponse extends Message<ScanMuteOperationsResponse> { | ||
/** | ||
* @generated from field: repeated bsync.MuteOperation operations = 1; | ||
*/ | ||
operations: MuteOperation[]; | ||
/** | ||
* @generated from field: string cursor = 2; | ||
*/ | ||
cursor: string; | ||
@@ -75,2 +141,7 @@ constructor(data?: PartialMessage<ScanMuteOperationsResponse>); | ||
} | ||
/** | ||
* Ping | ||
* | ||
* @generated from message bsync.PingRequest | ||
*/ | ||
export declare class PingRequest extends Message<PingRequest> { | ||
@@ -86,2 +157,5 @@ constructor(data?: PartialMessage<PingRequest>); | ||
} | ||
/** | ||
* @generated from message bsync.PingResponse | ||
*/ | ||
export declare class PingResponse extends Message<PingResponse> { | ||
@@ -97,1 +171,2 @@ constructor(data?: PartialMessage<PingResponse>); | ||
} | ||
//# sourceMappingURL=bsync_pb.d.ts.map |
@@ -6,1 +6,2 @@ import { ServiceImpl } from '@connectrpc/connect'; | ||
export default _default; | ||
//# sourceMappingURL=add-mute-operation.d.ts.map |
import { HandlerContext } from '@connectrpc/connect'; | ||
import AppContext from '../context'; | ||
export declare const authWithApiKey: (ctx: AppContext, handlerCtx: HandlerContext) => void; | ||
//# sourceMappingURL=auth.d.ts.map |
@@ -5,1 +5,2 @@ import { ConnectRouter } from '@connectrpc/connect'; | ||
export default _default; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -6,1 +6,2 @@ import { ServiceImpl } from '@connectrpc/connect'; | ||
export default _default; | ||
//# sourceMappingURL=scan-mute-operations.d.ts.map |
@@ -1,6 +0,6 @@ | ||
const base = require('../../jest.config.base.js') | ||
/** @type {import('jest').Config} */ | ||
module.exports = { | ||
...base, | ||
displayName: 'Bsync', | ||
transform: { '^.+\\.(t|j)s$': '@swc/jest' }, | ||
setupFiles: ['<rootDir>/../../jest.setup.ts'], | ||
} |
{ | ||
"name": "@atproto/bsync", | ||
"version": "0.0.1", | ||
"version": "0.0.2-next.0", | ||
"license": "MIT", | ||
@@ -17,2 +17,3 @@ "description": "Sychronizing service for app.bsky App View (Bluesky API)", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
@@ -29,4 +30,4 @@ "@bufbuild/protobuf": "^1.5.0", | ||
"typed-emitter": "^2.1.0", | ||
"@atproto/common": "^0.3.3", | ||
"@atproto/syntax": "^0.2.0" | ||
"@atproto/common": "^0.3.4-next.0", | ||
"@atproto/syntax": "^0.2.1-next.0" | ||
}, | ||
@@ -37,8 +38,8 @@ "devDependencies": { | ||
"@connectrpc/protoc-gen-connect-es": "^1.1.4", | ||
"@types/pg": "^8.6.6" | ||
"@types/pg": "^8.6.6", | ||
"jest": "^28.1.2", | ||
"ts-node": "^10.8.2" | ||
}, | ||
"scripts": { | ||
"build": "node ./build.js", | ||
"postbuild": "tsc --build tsconfig.build.json", | ||
"update-main-to-dist": "node ../../update-main-to-dist.js packages/bsync", | ||
"build": "tsc --build tsconfig.build.json", | ||
"start": "node --enable-source-maps dist/bin.js", | ||
@@ -50,4 +51,3 @@ "test": "../dev-infra/with-test-db.sh jest", | ||
"buf:gen": "buf generate proto" | ||
}, | ||
"types": "dist/index.d.ts" | ||
} | ||
} |
@@ -10,2 +10,3 @@ import TypedEventEmitter from 'typed-emitter' | ||
cfg: ServerConfig | ||
shutdown: AbortSignal | ||
} | ||
@@ -16,2 +17,3 @@ | ||
cfg: ServerConfig | ||
shutdown: AbortSignal | ||
events: TypedEventEmitter<AppEvents> | ||
@@ -22,2 +24,3 @@ | ||
this.cfg = opts.cfg | ||
this.shutdown = opts.shutdown | ||
this.events = new EventEmitter() as TypedEventEmitter<AppEvents> | ||
@@ -28,2 +31,3 @@ } | ||
cfg: ServerConfig, | ||
shutdown: AbortSignal, | ||
overrides?: Partial<AppContextOptions>, | ||
@@ -38,3 +42,3 @@ ): Promise<AppContext> { | ||
}) | ||
return new AppContext({ db, cfg, ...overrides }) | ||
return new AppContext({ db, cfg, shutdown, ...overrides }) | ||
} | ||
@@ -41,0 +45,0 @@ } |
@@ -37,37 +37,39 @@ import assert from 'assert' | ||
this.pool = instances.pool | ||
return | ||
} | ||
} else { | ||
// else create a pool & connect | ||
const { schema, url } = opts | ||
const pool = | ||
opts.pool ?? | ||
new PgPool({ | ||
connectionString: url, | ||
max: opts.poolSize, | ||
maxUses: opts.poolMaxUses, | ||
idleTimeoutMillis: opts.poolIdleTimeoutMs, | ||
}) | ||
// else create a pool & connect | ||
const { schema, url } = opts | ||
const pool = | ||
opts.pool ?? | ||
new PgPool({ | ||
connectionString: url, | ||
max: opts.poolSize, | ||
maxUses: opts.poolMaxUses, | ||
idleTimeoutMillis: opts.poolIdleTimeoutMs, | ||
// Select count(*) and other pg bigints as js integer | ||
pgTypes.setTypeParser(pgTypes.builtins.INT8, (n) => parseInt(n, 10)) | ||
// Setup schema usage, primarily for test parallelism (each test suite runs in its own pg schema) | ||
if (schema && !/^[a-z_]+$/i.test(schema)) { | ||
throw new Error( | ||
`Postgres schema must only contain [A-Za-z_]: ${schema}`, | ||
) | ||
} | ||
pool.on('error', onPoolError) | ||
pool.on('connect', (client) => { | ||
client.on('error', onClientError) | ||
if (schema) { | ||
// Shared objects such as extensions will go in the public schema | ||
client.query(`SET search_path TO "${schema}",public;`) | ||
} | ||
}) | ||
// Select count(*) and other pg bigints as js integer | ||
pgTypes.setTypeParser(pgTypes.builtins.INT8, (n) => parseInt(n, 10)) | ||
// Setup schema usage, primarily for test parallelism (each test suite runs in its own pg schema) | ||
if (schema && !/^[a-z_]+$/i.test(schema)) { | ||
throw new Error(`Postgres schema must only contain [A-Za-z_]: ${schema}`) | ||
this.pool = pool | ||
this.db = new Kysely<DatabaseSchemaType>({ | ||
dialect: new PostgresDialect({ pool }), | ||
}) | ||
} | ||
pool.on('error', onPoolError) | ||
pool.on('connect', (client) => { | ||
client.on('error', onClientError) | ||
if (schema) { | ||
// Shared objects such as extensions will go in the public schema | ||
client.query(`SET search_path TO "${schema}",public;`) | ||
} | ||
}) | ||
this.pool = pool | ||
this.db = new Kysely<DatabaseSchemaType>({ | ||
dialect: new PostgresDialect({ pool }), | ||
}) | ||
this.migrator = new Migrator({ | ||
@@ -169,3 +171,3 @@ db: this.db, | ||
class LeakyTxPlugin implements KyselyPlugin { | ||
private txOver: boolean | ||
private txOver = false | ||
@@ -172,0 +174,0 @@ endTx() { |
@@ -22,3 +22,3 @@ import http from 'node:http' | ||
private terminator: HttpTerminator | ||
private dbStatsInterval: NodeJS.Timer | ||
private dbStatsInterval?: NodeJS.Timeout | ||
@@ -40,4 +40,4 @@ constructor(opts: { | ||
): Promise<BsyncService> { | ||
const ctx = await AppContext.fromConfig(cfg, overrides) | ||
const ac = new AbortController() | ||
const ctx = await AppContext.fromConfig(cfg, ac.signal, overrides) | ||
const handler = connectNodeAdapter({ | ||
@@ -60,2 +60,5 @@ routes: routes(ctx), | ||
async start(): Promise<http.Server> { | ||
if (this.dbStatsInterval) { | ||
throw new Error(`${this.constructor.name} already started`) | ||
} | ||
this.dbStatsInterval = setInterval(() => { | ||
@@ -83,2 +86,3 @@ dbLogger.info( | ||
clearInterval(this.dbStatsInterval) | ||
this.dbStatsInterval = undefined | ||
} | ||
@@ -85,0 +89,0 @@ |
@@ -13,3 +13,3 @@ // @generated by protoc-gen-connect-es v1.3.0 with parameter "target=ts,import_extension=.ts" | ||
ScanMuteOperationsResponse, | ||
} from './bsync_pb.ts' | ||
} from './bsync_pb' | ||
import { MethodKind } from '@bufbuild/protobuf' | ||
@@ -16,0 +16,0 @@ |
@@ -16,3 +16,6 @@ import { once } from 'node:events' | ||
const nextMuteOpPromise = once(events, createMuteOpChannel, { | ||
signal: AbortSignal.timeout(ctx.cfg.service.longPollTimeoutMs), | ||
signal: combineSignals( | ||
ctx.shutdown, | ||
AbortSignal.timeout(ctx.cfg.service.longPollTimeoutMs), | ||
), | ||
}) | ||
@@ -35,2 +38,3 @@ nextMuteOpPromise.catch(() => null) // ensure timeout is always handled | ||
} catch (err) { | ||
ctx.shutdown.throwIfAborted() | ||
return new ScanMuteOperationsResponse({ | ||
@@ -72,1 +76,16 @@ operations: [], | ||
} | ||
const combineSignals = (a: AbortSignal, b: AbortSignal) => { | ||
const controller = new AbortController() | ||
for (const signal of [a, b]) { | ||
if (signal.aborted) { | ||
controller.abort() | ||
return signal | ||
} | ||
signal.addEventListener('abort', () => controller.abort(signal.reason), { | ||
// @ts-ignore https://github.com/DefinitelyTyped/DefinitelyTyped/pull/68625 | ||
signal: controller.signal, | ||
}) | ||
} | ||
return controller.signal | ||
} |
{ | ||
"extends": "./tsconfig.json", | ||
"exclude": ["**/*.spec.ts", "**/*.test.ts"] | ||
"extends": "../../tsconfig/node.json", | ||
"compilerOptions": { | ||
"rootDir": "./src", | ||
"outDir": "./dist" | ||
}, | ||
"include": ["./src"] | ||
} |
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "./src", | ||
"outDir": "./dist", | ||
"emitDeclarationOnly": true | ||
}, | ||
"module": "nodenext", | ||
"include": ["./src", "__tests__/**/**.ts"], | ||
"include": [], | ||
"references": [ | ||
{ "path": "../common/tsconfig.build.json" }, | ||
{ "path": "../common-web/tsconfig.build.json" } | ||
{ "path": "./tsconfig.build.json" }, | ||
{ "path": "./tsconfig.tests.json" } | ||
] | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Unpopular package
QualityThis package is not very popular.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
107
0
163707
6
756
3364
1
3