@powersync/service-core 0.5.1 → 0.6.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.
- package/CHANGELOG.md +6 -0
- package/dist/routes/configure-fastify.d.ts +883 -0
- package/dist/routes/configure-fastify.js +58 -0
- package/dist/routes/configure-fastify.js.map +1 -0
- package/dist/routes/configure-rsocket.d.ts +13 -0
- package/dist/routes/configure-rsocket.js +46 -0
- package/dist/routes/configure-rsocket.js.map +1 -0
- package/dist/routes/endpoints/socket-route.js +3 -10
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/route-register.d.ts +1 -1
- package/dist/routes/route-register.js +1 -1
- package/dist/routes/route-register.js.map +1 -1
- package/dist/routes/router-socket.d.ts +4 -4
- package/dist/routes/router-socket.js.map +1 -1
- package/dist/routes/router.d.ts +1 -0
- package/dist/routes/router.js.map +1 -1
- package/dist/routes/routes-index.d.ts +2 -0
- package/dist/routes/routes-index.js +2 -0
- package/dist/routes/routes-index.js.map +1 -1
- package/dist/sync/sync-index.d.ts +1 -0
- package/dist/sync/sync-index.js +1 -0
- package/dist/sync/sync-index.js.map +1 -1
- package/package.json +3 -3
- package/src/routes/configure-fastify.ts +102 -0
- package/src/routes/configure-rsocket.ts +59 -0
- package/src/routes/endpoints/socket-route.ts +3 -10
- package/src/routes/route-register.ts +2 -2
- package/src/routes/router-socket.ts +5 -5
- package/src/routes/router.ts +2 -0
- package/src/routes/routes-index.ts +2 -0
- package/src/sync/sync-index.ts +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { registerFastifyRoutes } from './route-register.js';
|
|
2
|
+
import { ADMIN_ROUTES } from './endpoints/admin.js';
|
|
3
|
+
import { CHECKPOINT_ROUTES } from './endpoints/checkpointing.js';
|
|
4
|
+
import { DEV_ROUTES } from './endpoints/dev.js';
|
|
5
|
+
import { SYNC_RULES_ROUTES } from './endpoints/sync-rules.js';
|
|
6
|
+
import { SYNC_STREAM_ROUTES } from './endpoints/sync-stream.js';
|
|
7
|
+
import { createRequestQueueHook } from './hooks.js';
|
|
8
|
+
export const DEFAULT_ROUTE_OPTIONS = {
|
|
9
|
+
api: {
|
|
10
|
+
routes: [...ADMIN_ROUTES, ...CHECKPOINT_ROUTES, ...DEV_ROUTES, ...SYNC_RULES_ROUTES],
|
|
11
|
+
queueOptions: {
|
|
12
|
+
concurrency: 10,
|
|
13
|
+
max_queue_depth: 20
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
syncStream: {
|
|
17
|
+
routes: [...SYNC_STREAM_ROUTES],
|
|
18
|
+
queueOptions: {
|
|
19
|
+
concurrency: 200,
|
|
20
|
+
max_queue_depth: 0
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Registers default routes on a Fastify server. Consumers can optionally configure
|
|
26
|
+
* concurrency queue limits or override routes.
|
|
27
|
+
*/
|
|
28
|
+
export function configureFastifyServer(server, options) {
|
|
29
|
+
const { system, routes = DEFAULT_ROUTE_OPTIONS } = options;
|
|
30
|
+
/**
|
|
31
|
+
* Fastify creates an encapsulated context for each `.register` call.
|
|
32
|
+
* Creating a separate context here to separate the concurrency limits for Admin APIs
|
|
33
|
+
* and Sync Streaming routes.
|
|
34
|
+
* https://github.com/fastify/fastify/blob/main/docs/Reference/Encapsulation.md
|
|
35
|
+
*/
|
|
36
|
+
server.register(async function (childContext) {
|
|
37
|
+
registerFastifyRoutes(childContext, async () => {
|
|
38
|
+
return {
|
|
39
|
+
user_id: undefined,
|
|
40
|
+
system: system
|
|
41
|
+
};
|
|
42
|
+
}, routes.api?.routes ?? DEFAULT_ROUTE_OPTIONS.api.routes);
|
|
43
|
+
// Limit the active concurrent requests
|
|
44
|
+
childContext.addHook('onRequest', createRequestQueueHook(routes.api?.queueOptions ?? DEFAULT_ROUTE_OPTIONS.api.queueOptions));
|
|
45
|
+
});
|
|
46
|
+
// Create a separate context for concurrency queueing
|
|
47
|
+
server.register(async function (childContext) {
|
|
48
|
+
registerFastifyRoutes(childContext, async () => {
|
|
49
|
+
return {
|
|
50
|
+
user_id: undefined,
|
|
51
|
+
system: system
|
|
52
|
+
};
|
|
53
|
+
}, routes.syncStream?.routes ?? DEFAULT_ROUTE_OPTIONS.syncStream.routes);
|
|
54
|
+
// Limit the active concurrent requests
|
|
55
|
+
childContext.addHook('onRequest', createRequestQueueHook(routes.syncStream?.queueOptions ?? DEFAULT_ROUTE_OPTIONS.syncStream.queueOptions));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=configure-fastify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure-fastify.js","sourceRoot":"","sources":["../../src/routes/configure-fastify.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAI5D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAA4B,MAAM,YAAY,CAAC;AA0B9E,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,EAAE;QACH,MAAM,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,iBAAiB,EAAE,GAAG,UAAU,EAAE,GAAG,iBAAiB,CAAC;QACpF,YAAY,EAAE;YACZ,WAAW,EAAE,EAAE;YACf,eAAe,EAAE,EAAE;SACpB;KACF;IACD,UAAU,EAAE;QACV,MAAM,EAAE,CAAC,GAAG,kBAAkB,CAAC;QAC/B,YAAY,EAAE;YACZ,WAAW,EAAE,GAAG;YAChB,eAAe,EAAE,CAAC;SACnB;KACF;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA+B,EAAE,OAA4B;IAClG,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,OAAO,CAAC;IAC3D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW,YAAY;QAC1C,qBAAqB,CACnB,YAAY,EACZ,KAAK,IAAI,EAAE;YACT,OAAO;gBACL,OAAO,EAAE,SAAS;gBAClB,MAAM,EAAE,MAAM;aACf,CAAC;QACJ,CAAC,EACD,MAAM,CAAC,GAAG,EAAE,MAAM,IAAI,qBAAqB,CAAC,GAAG,CAAC,MAAM,CACvD,CAAC;QACF,uCAAuC;QACvC,YAAY,CAAC,OAAO,CAClB,WAAW,EACX,sBAAsB,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,IAAI,qBAAqB,CAAC,GAAG,CAAC,YAAY,CAAC,CAC3F,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,qDAAqD;IACrD,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW,YAAY;QAC1C,qBAAqB,CACnB,YAAY,EACZ,KAAK,IAAI,EAAE;YACT,OAAO;gBACL,OAAO,EAAE,SAAS;gBAClB,MAAM,EAAE,MAAM;aACf,CAAC;QACJ,CAAC,EACD,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,qBAAqB,CAAC,UAAU,CAAC,MAAM,CACrE,CAAC;QACF,uCAAuC;QACvC,YAAY,CAAC,OAAO,CAClB,WAAW,EACX,sBAAsB,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,IAAI,qBAAqB,CAAC,UAAU,CAAC,YAAY,CAAC,CACzG,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import * as http from 'http';
|
|
3
|
+
import { ReactiveSocketRouter } from '@powersync/service-rsocket-router';
|
|
4
|
+
import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
|
|
5
|
+
import { SocketRouteGenerator } from './router-socket.js';
|
|
6
|
+
import { Context } from './router.js';
|
|
7
|
+
export type RSockerRouterConfig = {
|
|
8
|
+
system: CorePowerSyncSystem;
|
|
9
|
+
server: http.Server;
|
|
10
|
+
routeGenerators?: SocketRouteGenerator[];
|
|
11
|
+
};
|
|
12
|
+
export declare const DEFAULT_SOCKET_ROUTES: SocketRouteGenerator[];
|
|
13
|
+
export declare function configureRSocket(router: ReactiveSocketRouter<Context>, options: RSockerRouterConfig): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { deserialize } from 'bson';
|
|
2
|
+
import { errors, logger } from '@powersync/lib-services-framework';
|
|
3
|
+
import { RSocketRequestMeta } from '@powersync/service-rsocket-router';
|
|
4
|
+
import { generateContext, getTokenFromHeader } from './auth.js';
|
|
5
|
+
import { syncStreamReactive } from './endpoints/socket-route.js';
|
|
6
|
+
import { RSocketContextMeta } from './router-socket.js';
|
|
7
|
+
export const DEFAULT_SOCKET_ROUTES = [syncStreamReactive];
|
|
8
|
+
export function configureRSocket(router, options) {
|
|
9
|
+
const { routeGenerators = DEFAULT_SOCKET_ROUTES, server, system } = options;
|
|
10
|
+
router.applyWebSocketEndpoints(server, {
|
|
11
|
+
contextProvider: async (data) => {
|
|
12
|
+
const { token } = RSocketContextMeta.decode(deserialize(data));
|
|
13
|
+
if (!token) {
|
|
14
|
+
throw new errors.AuthorizationError('No token provided');
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const extracted_token = getTokenFromHeader(token);
|
|
18
|
+
if (extracted_token != null) {
|
|
19
|
+
const { context, errors: token_errors } = await generateContext(system, extracted_token);
|
|
20
|
+
if (context?.token_payload == null) {
|
|
21
|
+
throw new errors.AuthorizationError(token_errors ?? 'Authentication required');
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
token,
|
|
25
|
+
...context,
|
|
26
|
+
token_errors: token_errors,
|
|
27
|
+
system
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new errors.AuthorizationError('No token provided');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (ex) {
|
|
35
|
+
logger.error(ex);
|
|
36
|
+
throw ex;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
endpoints: routeGenerators.map((generator) => generator(router)),
|
|
40
|
+
metaDecoder: async (meta) => {
|
|
41
|
+
return RSocketRequestMeta.decode(deserialize(meta));
|
|
42
|
+
},
|
|
43
|
+
payloadDecoder: async (rawData) => rawData && deserialize(rawData)
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=configure-rsocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure-rsocket.js","sourceRoot":"","sources":["../../src/routes/configure-rsocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAwB,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAG7F,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAwB,MAAM,oBAAoB,CAAC;AAS9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAE1D,MAAM,UAAU,gBAAgB,CAAC,MAAqC,EAAE,OAA4B;IAClG,MAAM,EAAE,eAAe,GAAG,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE5E,MAAM,CAAC,uBAAuB,CAAC,MAAM,EAAE;QACrC,eAAe,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE;YACtC,MAAM,EAAE,KAAK,EAAE,GAAG,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAQ,CAAC,CAAC;YAEtE,IAAI,CAAC,KAAK,EAAE;gBACV,MAAM,IAAI,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;aAC1D;YAED,IAAI;gBACF,MAAM,eAAe,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;gBAClD,IAAI,eAAe,IAAI,IAAI,EAAE;oBAC3B,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;oBACzF,IAAI,OAAO,EAAE,aAAa,IAAI,IAAI,EAAE;wBAClC,MAAM,IAAI,MAAM,CAAC,kBAAkB,CAAC,YAAY,IAAI,yBAAyB,CAAC,CAAC;qBAChF;oBACD,OAAO;wBACL,KAAK;wBACL,GAAG,OAAO;wBACV,YAAY,EAAE,YAAY;wBAC1B,MAAM;qBACP,CAAC;iBACH;qBAAM;oBACL,MAAM,IAAI,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;iBAC1D;aACF;YAAC,OAAO,EAAE,EAAE;gBACX,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACjB,MAAM,EAAE,CAAC;aACV;QACH,CAAC;QACD,SAAS,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAChE,WAAW,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE;YAClC,OAAO,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAQ,CAAC,CAAC;QAC7D,CAAC;QACD,cAAc,EAAE,KAAK,EAAE,OAAgB,EAAE,EAAE,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC;KAC5E,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -2,17 +2,10 @@ import { errors, logger, schema } from '@powersync/lib-services-framework';
|
|
|
2
2
|
import { RequestParameters } from '@powersync/service-sync-rules';
|
|
3
3
|
import { serialize } from 'bson';
|
|
4
4
|
import { Metrics } from '../../metrics/Metrics.js';
|
|
5
|
-
import
|
|
5
|
+
import * as sync from '../../sync/sync-index.js';
|
|
6
6
|
import * as util from '../../util/util-index.js';
|
|
7
7
|
import { SyncRoutes } from './sync-stream.js';
|
|
8
|
-
import { RequestTracker } from '../../sync/RequestTracker.js';
|
|
9
8
|
export const syncStreamReactive = (router) => router.reactiveStream(SyncRoutes.STREAM, {
|
|
10
|
-
authorize: ({ context }) => {
|
|
11
|
-
return {
|
|
12
|
-
authorized: !!context.token_payload,
|
|
13
|
-
errors: ['Authentication required'].concat(context.token_errors ?? [])
|
|
14
|
-
};
|
|
15
|
-
},
|
|
16
9
|
validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
|
|
17
10
|
handler: async ({ context, params, responder, observer, initialN }) => {
|
|
18
11
|
const { system } = context;
|
|
@@ -52,9 +45,9 @@ export const syncStreamReactive = (router) => router.reactiveStream(SyncRoutes.S
|
|
|
52
45
|
observer.triggerCancel();
|
|
53
46
|
});
|
|
54
47
|
Metrics.getInstance().concurrent_connections.add(1);
|
|
55
|
-
const tracker = new RequestTracker();
|
|
48
|
+
const tracker = new sync.RequestTracker();
|
|
56
49
|
try {
|
|
57
|
-
for await (const data of streamResponse({
|
|
50
|
+
for await (const data of sync.streamResponse({
|
|
58
51
|
storage,
|
|
59
52
|
params: {
|
|
60
53
|
...params,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-route.js","sourceRoot":"","sources":["../../../src/routes/endpoints/socket-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"socket-route.js","sourceRoot":"","sources":["../../../src/routes/endpoints/socket-route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,IAAI,MAAM,0BAA0B,CAAC;AACjD,OAAO,KAAK,IAAI,MAAM,0BAA0B,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,CAAC,MAAM,kBAAkB,GAAyB,CAAC,MAAM,EAAE,EAAE,CACjE,MAAM,CAAC,cAAc,CAAiC,UAAU,CAAC,MAAM,EAAE;IACvE,SAAS,EAAE,MAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IAC9F,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;QACpE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAE3B,IAAI,MAAM,CAAC,MAAM,EAAE;YACjB,SAAS,CAAC,OAAO,CACf,IAAI,MAAM,CAAC,YAAY,CAAC;gBACtB,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EAAE,iCAAiC;aAC/C,CAAC,CACH,CAAC;YACF,SAAS,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO;SACR;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QAEzC,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,OAAO,CAAC,aAAc,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAE1F,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,0CAA0C;QAC1C,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAC/C,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE;YACtB,SAAS,CAAC,OAAO,CACf,IAAI,MAAM,CAAC,YAAY,CAAC;gBACtB,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,yBAAyB;aACvC,CAAC,CACH,CAAC;YACF,SAAS,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO;SACR;QAED,IAAI,UAAU,GAAG,QAAQ,CAAC;QAC1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,gBAAgB,CAAC;YACzC,OAAO,CAAC,CAAC;gBACP,UAAU,IAAI,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,EAAE,GAAG,EAAE;gBACX,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,iBAAiB,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE;YACnD,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,WAAW,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,IAAI;YACF,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,cAAc,CAAC;gBAC3C,OAAO;gBACP,MAAM,EAAE;oBACN,GAAG,MAAM;oBACT,WAAW,EAAE,IAAI,CAAC,8BAA8B;iBACjD;gBACD,UAAU;gBACV,KAAK,EAAE,OAAQ,CAAC,aAAc;gBAC9B,kBAAkB,EAAE;oBAClB,8CAA8C;oBAC9C,UAAU,EAAE,KAAK;iBAClB;gBACD,OAAO;gBACP,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,EAAE;gBACF,IAAI,IAAI,IAAI,IAAI,EAAE;oBAChB,4CAA4C;oBAC5C,SAAS;iBACV;qBAAM,IAAI,OAAO,IAAI,IAAI,QAAQ,EAAE;oBAClC,2CAA2C;oBAC3C,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;iBACpD;gBAED;oBACE,+CAA+C;oBAC/C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAW,CAAC;oBAC7C,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,CAAC,CAAC;oBAC9C,UAAU,EAAE,CAAC;oBACb,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;iBAC1C;gBAED,IAAI,UAAU,IAAI,CAAC,EAAE;oBACnB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;wBAClC,MAAM,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC;4BAClC,OAAO;gCACL,IAAI,UAAU,GAAG,CAAC,EAAE;oCAClB,iEAAiE;oCACjE,OAAO,EAAE,CAAC;oCACV,CAAC,EAAE,CAAC;iCACL;4BACH,CAAC;4BACD,MAAM,EAAE,GAAG,EAAE;gCACX,8CAA8C;gCAC9C,OAAO,EAAE,CAAC;gCACV,CAAC,EAAE,CAAC;4BACN,CAAC;yBACF,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;iBACJ;aACF;SACF;QAAC,OAAO,EAAE,EAAE;YACX,kDAAkD;YAClD,4CAA4C;YAC5C,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;YACjD,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YACzC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SAC1B;gBAAS;YACR,SAAS,CAAC,UAAU,EAAE,CAAC;YACvB,iBAAiB,EAAE,CAAC;YACpB,QAAQ,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE;gBAClC,OAAO,EAAE,UAAU,CAAC,OAAO;gBAC3B,iBAAiB,EAAE,OAAO,CAAC,gBAAgB;gBAC3C,iBAAiB,EAAE,OAAO,CAAC,eAAe;aAC3C,CAAC,CAAC;YACH,OAAO,CAAC,WAAW,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SACtD;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-register.js","sourceRoot":"","sources":["../../src/routes/route-register.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"route-register.js","sourceRoot":"","sources":["../../src/routes/route-register.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { IReactiveStream, ReactiveSocketRouter } from '@powersync/service-rsocket-router';
|
|
1
2
|
import * as t from 'ts-codec';
|
|
2
|
-
import { ReactiveSocketRouter, IReactiveStream } from '@powersync/service-rsocket-router';
|
|
3
3
|
import { Context } from './router.js';
|
|
4
|
-
export declare const RSocketContextMeta: t.ObjectCodec<{
|
|
5
|
-
token: t.IdentityCodec<t.CodecType.String>;
|
|
6
|
-
}>;
|
|
7
4
|
/**
|
|
8
5
|
* Creates a socket route handler given a router instance
|
|
9
6
|
*/
|
|
10
7
|
export type SocketRouteGenerator = (router: ReactiveSocketRouter<Context>) => IReactiveStream;
|
|
8
|
+
export declare const RSocketContextMeta: t.ObjectCodec<{
|
|
9
|
+
token: t.IdentityCodec<t.CodecType.String>;
|
|
10
|
+
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-socket.js","sourceRoot":"","sources":["../../src/routes/router-socket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router-socket.js","sourceRoot":"","sources":["../../src/routes/router-socket.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAS9B,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM;CAChB,CAAC,CAAC"}
|
package/dist/routes/router.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export type RequestEndpoint<I, O, C = Context, Payload = RequestEndpointHandlerP
|
|
|
20
20
|
export type RequestEndpointHandlerPayload<I = any, C = Context, Request = BasicRouterRequest> = router.EndpointHandlerPayload<I, C> & {
|
|
21
21
|
request: Request;
|
|
22
22
|
};
|
|
23
|
+
export type RouteDefinition<I = any, O = any> = RequestEndpoint<I, O>;
|
|
23
24
|
/**
|
|
24
25
|
* Helper function for making generics work well when defining routes
|
|
25
26
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/routes/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/routes/router.ts"],"names":[],"mappings":"AAwCA;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA4C;IAE5C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-index.js","sourceRoot":"","sources":["../../src/routes/routes-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,SAAS,MAAM,sCAAsC,CAAC;AAClE,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"routes-index.js","sourceRoot":"","sources":["../../src/routes/routes-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,OAAO,KAAK,SAAS,MAAM,sCAAsC,CAAC;AAClE,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
|
package/dist/sync/sync-index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-index.js","sourceRoot":"","sources":["../../src/sync/sync-index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"sync-index.js","sourceRoot":"","sources":["../../src/sync/sync-index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.6.0",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"license": "FSL-1.1-Apache-2.0",
|
|
11
11
|
"type": "module",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"winston": "^3.13.0",
|
|
35
35
|
"yaml": "^2.3.2",
|
|
36
36
|
"@powersync/lib-services-framework": "0.1.1",
|
|
37
|
-
"@powersync/service-jpgwire": "0.17.13",
|
|
38
37
|
"@powersync/service-jsonbig": "0.17.10",
|
|
39
|
-
"@powersync/service-
|
|
38
|
+
"@powersync/service-jpgwire": "0.17.13",
|
|
40
39
|
"@powersync/service-sync-rules": "0.18.1",
|
|
40
|
+
"@powersync/service-rsocket-router": "0.0.10",
|
|
41
41
|
"@powersync/service-types": "0.1.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type fastify from 'fastify';
|
|
2
|
+
import { registerFastifyRoutes } from './route-register.js';
|
|
3
|
+
|
|
4
|
+
import * as system from '../system/system-index.js';
|
|
5
|
+
|
|
6
|
+
import { ADMIN_ROUTES } from './endpoints/admin.js';
|
|
7
|
+
import { CHECKPOINT_ROUTES } from './endpoints/checkpointing.js';
|
|
8
|
+
import { DEV_ROUTES } from './endpoints/dev.js';
|
|
9
|
+
import { SYNC_RULES_ROUTES } from './endpoints/sync-rules.js';
|
|
10
|
+
import { SYNC_STREAM_ROUTES } from './endpoints/sync-stream.js';
|
|
11
|
+
import { createRequestQueueHook, CreateRequestQueueParams } from './hooks.js';
|
|
12
|
+
import { RouteDefinition } from './router.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A list of route definitions to be registered as endpoints.
|
|
16
|
+
* Supplied concurrency limits will be applied to the grouped routes.
|
|
17
|
+
*/
|
|
18
|
+
export type RouteRegistrationOptions = {
|
|
19
|
+
routes: RouteDefinition[];
|
|
20
|
+
queueOptions: CreateRequestQueueParams;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* HTTP routes separated by API and Sync stream categories.
|
|
25
|
+
* This allows for separate concurrency limits.
|
|
26
|
+
*/
|
|
27
|
+
export type RouteDefinitions = {
|
|
28
|
+
api?: Partial<RouteRegistrationOptions>;
|
|
29
|
+
syncStream?: Partial<RouteRegistrationOptions>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type FastifyServerConfig = {
|
|
33
|
+
system: system.CorePowerSyncSystem;
|
|
34
|
+
routes?: RouteDefinitions;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const DEFAULT_ROUTE_OPTIONS = {
|
|
38
|
+
api: {
|
|
39
|
+
routes: [...ADMIN_ROUTES, ...CHECKPOINT_ROUTES, ...DEV_ROUTES, ...SYNC_RULES_ROUTES],
|
|
40
|
+
queueOptions: {
|
|
41
|
+
concurrency: 10,
|
|
42
|
+
max_queue_depth: 20
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
syncStream: {
|
|
46
|
+
routes: [...SYNC_STREAM_ROUTES],
|
|
47
|
+
queueOptions: {
|
|
48
|
+
concurrency: 200,
|
|
49
|
+
max_queue_depth: 0
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Registers default routes on a Fastify server. Consumers can optionally configure
|
|
56
|
+
* concurrency queue limits or override routes.
|
|
57
|
+
*/
|
|
58
|
+
export function configureFastifyServer(server: fastify.FastifyInstance, options: FastifyServerConfig) {
|
|
59
|
+
const { system, routes = DEFAULT_ROUTE_OPTIONS } = options;
|
|
60
|
+
/**
|
|
61
|
+
* Fastify creates an encapsulated context for each `.register` call.
|
|
62
|
+
* Creating a separate context here to separate the concurrency limits for Admin APIs
|
|
63
|
+
* and Sync Streaming routes.
|
|
64
|
+
* https://github.com/fastify/fastify/blob/main/docs/Reference/Encapsulation.md
|
|
65
|
+
*/
|
|
66
|
+
server.register(async function (childContext) {
|
|
67
|
+
registerFastifyRoutes(
|
|
68
|
+
childContext,
|
|
69
|
+
async () => {
|
|
70
|
+
return {
|
|
71
|
+
user_id: undefined,
|
|
72
|
+
system: system
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
routes.api?.routes ?? DEFAULT_ROUTE_OPTIONS.api.routes
|
|
76
|
+
);
|
|
77
|
+
// Limit the active concurrent requests
|
|
78
|
+
childContext.addHook(
|
|
79
|
+
'onRequest',
|
|
80
|
+
createRequestQueueHook(routes.api?.queueOptions ?? DEFAULT_ROUTE_OPTIONS.api.queueOptions)
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Create a separate context for concurrency queueing
|
|
85
|
+
server.register(async function (childContext) {
|
|
86
|
+
registerFastifyRoutes(
|
|
87
|
+
childContext,
|
|
88
|
+
async () => {
|
|
89
|
+
return {
|
|
90
|
+
user_id: undefined,
|
|
91
|
+
system: system
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
routes.syncStream?.routes ?? DEFAULT_ROUTE_OPTIONS.syncStream.routes
|
|
95
|
+
);
|
|
96
|
+
// Limit the active concurrent requests
|
|
97
|
+
childContext.addHook(
|
|
98
|
+
'onRequest',
|
|
99
|
+
createRequestQueueHook(routes.syncStream?.queueOptions ?? DEFAULT_ROUTE_OPTIONS.syncStream.queueOptions)
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { deserialize } from 'bson';
|
|
2
|
+
import * as http from 'http';
|
|
3
|
+
|
|
4
|
+
import { errors, logger } from '@powersync/lib-services-framework';
|
|
5
|
+
import { ReactiveSocketRouter, RSocketRequestMeta } from '@powersync/service-rsocket-router';
|
|
6
|
+
|
|
7
|
+
import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
|
|
8
|
+
import { generateContext, getTokenFromHeader } from './auth.js';
|
|
9
|
+
import { syncStreamReactive } from './endpoints/socket-route.js';
|
|
10
|
+
import { RSocketContextMeta, SocketRouteGenerator } from './router-socket.js';
|
|
11
|
+
import { Context } from './router.js';
|
|
12
|
+
|
|
13
|
+
export type RSockerRouterConfig = {
|
|
14
|
+
system: CorePowerSyncSystem;
|
|
15
|
+
server: http.Server;
|
|
16
|
+
routeGenerators?: SocketRouteGenerator[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const DEFAULT_SOCKET_ROUTES = [syncStreamReactive];
|
|
20
|
+
|
|
21
|
+
export function configureRSocket(router: ReactiveSocketRouter<Context>, options: RSockerRouterConfig) {
|
|
22
|
+
const { routeGenerators = DEFAULT_SOCKET_ROUTES, server, system } = options;
|
|
23
|
+
|
|
24
|
+
router.applyWebSocketEndpoints(server, {
|
|
25
|
+
contextProvider: async (data: Buffer) => {
|
|
26
|
+
const { token } = RSocketContextMeta.decode(deserialize(data) as any);
|
|
27
|
+
|
|
28
|
+
if (!token) {
|
|
29
|
+
throw new errors.AuthorizationError('No token provided');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const extracted_token = getTokenFromHeader(token);
|
|
34
|
+
if (extracted_token != null) {
|
|
35
|
+
const { context, errors: token_errors } = await generateContext(system, extracted_token);
|
|
36
|
+
if (context?.token_payload == null) {
|
|
37
|
+
throw new errors.AuthorizationError(token_errors ?? 'Authentication required');
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
token,
|
|
41
|
+
...context,
|
|
42
|
+
token_errors: token_errors,
|
|
43
|
+
system
|
|
44
|
+
};
|
|
45
|
+
} else {
|
|
46
|
+
throw new errors.AuthorizationError('No token provided');
|
|
47
|
+
}
|
|
48
|
+
} catch (ex) {
|
|
49
|
+
logger.error(ex);
|
|
50
|
+
throw ex;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
endpoints: routeGenerators.map((generator) => generator(router)),
|
|
54
|
+
metaDecoder: async (meta: Buffer) => {
|
|
55
|
+
return RSocketRequestMeta.decode(deserialize(meta) as any);
|
|
56
|
+
},
|
|
57
|
+
payloadDecoder: async (rawData?: Buffer) => rawData && deserialize(rawData)
|
|
58
|
+
});
|
|
59
|
+
}
|
|
@@ -3,20 +3,13 @@ import { RequestParameters } from '@powersync/service-sync-rules';
|
|
|
3
3
|
import { serialize } from 'bson';
|
|
4
4
|
|
|
5
5
|
import { Metrics } from '../../metrics/Metrics.js';
|
|
6
|
-
import
|
|
6
|
+
import * as sync from '../../sync/sync-index.js';
|
|
7
7
|
import * as util from '../../util/util-index.js';
|
|
8
8
|
import { SocketRouteGenerator } from '../router-socket.js';
|
|
9
9
|
import { SyncRoutes } from './sync-stream.js';
|
|
10
|
-
import { RequestTracker } from '../../sync/RequestTracker.js';
|
|
11
10
|
|
|
12
11
|
export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
13
12
|
router.reactiveStream<util.StreamingSyncRequest, any>(SyncRoutes.STREAM, {
|
|
14
|
-
authorize: ({ context }) => {
|
|
15
|
-
return {
|
|
16
|
-
authorized: !!context.token_payload,
|
|
17
|
-
errors: ['Authentication required'].concat(context.token_errors ?? [])
|
|
18
|
-
};
|
|
19
|
-
},
|
|
20
13
|
validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
|
|
21
14
|
handler: async ({ context, params, responder, observer, initialN }) => {
|
|
22
15
|
const { system } = context;
|
|
@@ -67,9 +60,9 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
|
67
60
|
});
|
|
68
61
|
|
|
69
62
|
Metrics.getInstance().concurrent_connections.add(1);
|
|
70
|
-
const tracker = new RequestTracker();
|
|
63
|
+
const tracker = new sync.RequestTracker();
|
|
71
64
|
try {
|
|
72
|
-
for await (const data of streamResponse({
|
|
65
|
+
for await (const data of sync.streamResponse({
|
|
73
66
|
storage,
|
|
74
67
|
params: {
|
|
75
68
|
...params,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import fastify from 'fastify';
|
|
1
|
+
import type fastify from 'fastify';
|
|
2
2
|
|
|
3
|
-
import { errors,
|
|
3
|
+
import { errors, HTTPMethod, logger, router } from '@powersync/lib-services-framework';
|
|
4
4
|
import { Context, ContextProvider, RequestEndpoint, RequestEndpointHandlerPayload } from './router.js';
|
|
5
5
|
|
|
6
6
|
export type FastifyEndpoint<I, O, C> = RequestEndpoint<I, O, C> & {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { IReactiveStream, ReactiveSocketRouter } from '@powersync/service-rsocket-router';
|
|
1
2
|
import * as t from 'ts-codec';
|
|
2
|
-
import { ReactiveSocketRouter, IReactiveStream } from '@powersync/service-rsocket-router';
|
|
3
3
|
|
|
4
4
|
import { Context } from './router.js';
|
|
5
5
|
|
|
6
|
-
export const RSocketContextMeta = t.object({
|
|
7
|
-
token: t.string
|
|
8
|
-
});
|
|
9
|
-
|
|
10
6
|
/**
|
|
11
7
|
* Creates a socket route handler given a router instance
|
|
12
8
|
*/
|
|
13
9
|
export type SocketRouteGenerator = (router: ReactiveSocketRouter<Context>) => IReactiveStream;
|
|
10
|
+
|
|
11
|
+
export const RSocketContextMeta = t.object({
|
|
12
|
+
token: t.string
|
|
13
|
+
});
|
package/src/routes/router.ts
CHANGED
package/src/sync/sync-index.ts
CHANGED