Skip to content

Commit

Permalink
[Fix] Improve bson usage (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevensJourney authored May 17, 2024
1 parent 6b01811 commit 62e43aa
Show file tree
Hide file tree
Showing 22 changed files with 339 additions and 742 deletions.
7 changes: 7 additions & 0 deletions .changeset/many-chefs-hug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@powersync/react-native': minor
'@powersync/common': minor
'@powersync/web': minor
---

Improved import and usage of BSON library.
1 change: 0 additions & 1 deletion demos/example-electron/vite.renderer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export default defineConfig((env) => {
'@powersync/web > js-logger',
'@powersync/web > lodash/throttle',
'@powersync/web > can-ndjson-stream',
'@powersync/web > bson',
'@powersync/web > buffer',
'@powersync/web > rsocket-core',
'@powersync/web > rsocket-websocket-client',
Expand Down
4 changes: 2 additions & 2 deletions demos/example-nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"lowlight": "^2.9.0",
"next": "14.1.0",
"next-images": "1.8.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"remixicon": "^2.5.0",
"shiki": "^0.10.1",
"simplify-js": "^1.2.4"
Expand Down
3 changes: 3 additions & 0 deletions demos/example-vite/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Column, ColumnType, WASQLitePowerSyncDatabaseOpenFactory, Schema, Table } from '@powersync/web';
import Logger from 'js-logger';

Logger.useDefaults();

/**
* A placeholder connector which doesn't do anything.
Expand Down
8 changes: 0 additions & 8 deletions demos/example-vite/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import wasm from 'vite-plugin-wasm';
import topLevelAwait from 'vite-plugin-top-level-await';

import { defineConfig } from 'vite';

// https://vitejs.dev/config/
Expand All @@ -13,12 +12,6 @@ export default defineConfig({
},
emptyOutDir: true
},
resolve: {
alias: [
// https://jira.mongodb.org/browse/NODE-5773
{ find: 'bson', replacement: require.resolve('bson') }
]
},
envDir: '..', // Use this dir for env vars, not 'src'.
optimizeDeps: {
// Don't optimize these packages as they contain web workers and WASM files.
Expand All @@ -29,7 +22,6 @@ export default defineConfig({
'@powersync/web > js-logger',
'@powersync/web > lodash/throttle',
'@powersync/web > can-ndjson-stream',
'@powersync/web > bson',
'@powersync/web > buffer',
'@powersync/web > rsocket-core',
'@powersync/web > rsocket-websocket-client',
Expand Down
6 changes: 3 additions & 3 deletions demos/example-webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
"@powersync/web": "workspace:*"
},
"devDependencies": {
"webpack-cli": "^5.1.4",
"webpack": "^5.90.1",
"@types/webpack": "^5.28.5",
"html-webpack-plugin": "^5.6.0",
"serve": "^14.2.1",
"html-webpack-plugin": "^5.6.0"
"webpack": "^5.90.1",
"webpack-cli": "^5.1.4"
}
}
3 changes: 3 additions & 0 deletions demos/example-webpack/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Column, ColumnType, WASQLitePowerSyncDatabaseOpenFactory, Schema, Table } from '@powersync/web';
import Logger from 'js-logger';

Logger.useDefaults();

/**
* A placeholder connector which doesn't do anything.
Expand Down
6 changes: 6 additions & 0 deletions demos/example-webpack/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ module.exports = {
filename: 'index.js',
path: path.join(__dirname, 'dist')
},
externals: {
// BSON includes imports to these, but does not have a hard requirement for them to be present.
crypto: 'Crypto',
stream: 'Stream',
vm: 'VM'
},
devtool: 'source-map',
mode: 'development',
resolve: {
Expand Down
3 changes: 3 additions & 0 deletions demos/react-supabase-todolist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
"dependencies": {
"@powersync/react": "workspace:*",
"@powersync/web": "workspace:*",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@journeyapps/wa-sqlite": "~0.2.0",
"@mui/icons-material": "^5.15.12",
"@mui/material": "^5.15.12",
"@mui/x-data-grid": "^6.19.6",
"@supabase/supabase-js": "^2.39.7",
"buffer": "^6.0.3",
"formik": "^2.4.6",
"js-logger": "^1.6.1",
"lodash": "^4.17.21",
"react": "^18.2.0",
Expand Down
9 changes: 1 addition & 8 deletions demos/react-supabase-todolist/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { fileURLToPath, URL } from 'url';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url); // Needed since the config file is also an ES module

// https://vitejs.dev/config/
export default defineConfig({
Expand All @@ -19,11 +17,7 @@ export default defineConfig({
emptyOutDir: true
},
resolve: {
alias: [
{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
// https://jira.mongodb.org/browse/NODE-5773
{ find: 'bson', replacement: require.resolve('bson') }
]
alias: [{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) }]
},
publicDir: '../public',
envDir: '..', // Use this dir for env vars, not 'src'.
Expand All @@ -36,7 +30,6 @@ export default defineConfig({
'@powersync/web > js-logger',
'@powersync/web > lodash/throttle',
'@powersync/web > can-ndjson-stream',
'@powersync/web > bson',
'@powersync/web > buffer',
'@powersync/web > rsocket-core',
'@powersync/web > rsocket-websocket-client',
Expand Down
7 changes: 1 addition & 6 deletions demos/vue-supabase-todolist/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,7 @@ export default defineConfig({
],
define: { 'process.env': {} },
resolve: {
alias: [
{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
// https://jira.mongodb.org/browse/NODE-5773
{ find: 'bson', replacement: require.resolve('bson') }
],
alias: [{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) }],
extensions: ['.js', '.json', '.jsx', '.mjs', '.ts', '.tsx', '.vue']
},
optimizeDeps: {
Expand All @@ -86,7 +82,6 @@ export default defineConfig({
'@powersync/web > js-logger',
'@powersync/web > lodash/throttle',
'@powersync/web > can-ndjson-stream',
'@powersync/web > bson',
'@powersync/web > buffer',
'@powersync/web > rsocket-core',
'@powersync/web > rsocket-websocket-client',
Expand Down
1 change: 0 additions & 1 deletion demos/yjs-react-supabase-text-collab/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export default defineConfig({
'@powersync/web > js-logger',
'@powersync/web > lodash/throttle',
'@powersync/web > can-ndjson-stream',
'@powersync/web > bson',
'@powersync/web > buffer',
'@powersync/web > rsocket-core',
'@powersync/web > rsocket-websocket-client',
Expand Down
4 changes: 2 additions & 2 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
},
"dependencies": {
"async-mutex": "^0.4.0",
"bson": "^6.6.0",
"buffer": "^6.0.3",
"can-ndjson-stream": "^1.0.2",
"cross-fetch": "^4.0.0",
Expand All @@ -43,6 +42,7 @@
"@types/node": "^20.5.9",
"@types/uuid": "^9.0.1",
"typescript": "^5.1.3",
"vitest": "^1.5.2"
"vitest": "^1.5.2",
"bson": "^6.6.0"
}
}
21 changes: 15 additions & 6 deletions packages/common/src/client/sync/stream/AbstractRemote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import { DataStream } from '../../../utils/DataStream';
import ndjsonStream from 'can-ndjson-stream';
import { RSocket, RSocketConnector, Requestable } from 'rsocket-core';
import { WebsocketClientTransport } from 'rsocket-websocket-client';
import { serialize, deserialize } from 'bson';
import type { BSON } from 'bson';
import { AbortOperation } from '../../../utils/AbortOperation';
import { Buffer } from 'buffer';

export type BSONImplementation = typeof BSON;

export type RemoteConnector = {
fetchCredentials: () => Promise<PowerSyncCredentials | null>;
};
Expand Down Expand Up @@ -171,13 +173,20 @@ export abstract class AbstractRemote {
return res;
}

/**
* Provides a BSON implementation. The import nature of this varies depending on the platform
*/
abstract getBSON(): Promise<BSONImplementation>;

/**
* Connects to the sync/stream websocket endpoint
*/
async socketStream(options: SyncStreamOptions): Promise<DataStream<StreamingSyncLine>> {
const { path } = options;
const request = await this.buildRequest(path);

const bson = await this.getBSON();

const connector = new RSocketConnector({
transport: new WebsocketClientTransport({
url: this.options.socketUrlTransformer(request.url)
Expand All @@ -190,7 +199,7 @@ export abstract class AbstractRemote {
payload: {
data: null,
metadata: Buffer.from(
serialize({
bson.serialize({
token: request.headers.Authorization
})
)
Expand Down Expand Up @@ -223,7 +232,7 @@ export abstract class AbstractRemote {
}
socketIsClosed = true;
rsocket.close();
}
};
// We initially request this amount and expect these to arrive eventually
let pendingEventsCount = SYNC_QUEUE_REQUEST_N;

Expand All @@ -232,9 +241,9 @@ export abstract class AbstractRemote {

const res = rsocket.requestStream(
{
data: Buffer.from(serialize(options.data)),
data: Buffer.from(bson.serialize(options.data)),
metadata: Buffer.from(
serialize({
bson.serialize({
path
})
)
Expand Down Expand Up @@ -268,7 +277,7 @@ export abstract class AbstractRemote {
return;
}

const deserializedData = deserialize(data);
const deserializedData = bson.deserialize(data);
stream.enqueueData(deserializedData);
},
onComplete: () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
},
"dependencies": {
"@powersync/react": "workspace:*",
"async-lock": "^1.4.0"
"async-lock": "^1.4.0",
"bson": "^6.6.0"
},
"devDependencies": {
"@journeyapps/react-native-quick-sqlite": "^1.1.6",
Expand Down
15 changes: 13 additions & 2 deletions packages/react-native/src/sync/stream/ReactNativeRemote.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { AbstractRemote, DataStream, StreamingSyncLine, SyncStreamOptions } from '@powersync/common';
import {
AbstractRemote,
BSONImplementation,
DataStream,
StreamingSyncLine,
SyncStreamOptions
} from '@powersync/common';
import { Platform } from 'react-native';

// Note docs for React Native https://github.com/mongodb/js-bson?tab=readme-ov-file#react-native
import { BSON } from 'bson';
export const STREAMING_POST_TIMEOUT_MS = 30_000;

type PolyfillTest = {
Expand Down Expand Up @@ -53,6 +60,10 @@ ${missingPolyfills.join('\n')}`
};

export class ReactNativeRemote extends AbstractRemote {
async getBSON(): Promise<BSONImplementation> {
return BSON;
}

async socketStream(options: SyncStreamOptions): Promise<DataStream<StreamingSyncLine>> {
validatePolyfills(SocketPolyfillTests);
return super.socketStream(options);
Expand Down
8 changes: 8 additions & 0 deletions packages/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ if (typeof self.Buffer == 'undefined') {
}
```

## Webpack

See the [example Webpack config](https://github.com/powersync-ja/powersync-js/blob/main/demos/example-webpack/webpack.config.js) for details on polyfills and requirements.

## Vite

See the [example Vite config](https://github.com/powersync-ja/powersync-js/blob/main/demos/example-vite/vite.config.ts) for details on polyfills and requirements.

# Getting Started

Our [full SDK reference](https://docs.powersync.com/client-sdk-references/js-web) contains everything you need to know to get started implementing PowerSync in your project.
Expand Down
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"dependencies": {
"async-mutex": "^0.4.0",
"buffer": "^6.0.3",
"bson": "^6.6.0",
"comlink": "^4.4.1",
"js-logger": "^1.6.1",
"lodash": "^4.17.21"
Expand Down
19 changes: 17 additions & 2 deletions packages/web/src/db/sync/WebRemote.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
import { AbstractRemote } from '@powersync/common';
import { AbstractRemote, BSONImplementation } from '@powersync/common';

export class WebRemote extends AbstractRemote {}
export class WebRemote extends AbstractRemote {
private _bson: BSONImplementation | undefined;

async getBSON(): Promise<BSONImplementation> {
if (this._bson) {
return this._bson;
}

/**
* Dynamic import to be used only when needed.
*/
const { BSON } = await import('bson');
this._bson = BSON;
return this._bson;
}
}
7 changes: 6 additions & 1 deletion packages/web/tests/utils/MockStreamOpenFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
PowerSyncDatabaseOptions,
SyncStreamOptions,
DataStream,
StreamingSyncLine
StreamingSyncLine,
BSONImplementation
} from '@powersync/common';
import {
PowerSyncDatabase,
Expand Down Expand Up @@ -41,6 +42,10 @@ export class MockRemote extends AbstractRemote {
this.streamController = null;
}

async getBSON(): Promise<BSONImplementation> {
return import('bson');
}

post(path: string, data: any, headers?: Record<string, string> | undefined): Promise<any> {
throw new Error('Method not implemented.');
}
Expand Down
Loading

0 comments on commit 62e43aa

Please sign in to comment.