-
Notifications
You must be signed in to change notification settings - Fork 559
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
937 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# TS-generated output files. | ||
dist/ | ||
|
||
# Dependencies. | ||
node_modules/ | ||
|
||
# Local MongoDB Realm database. | ||
mongodb-realm/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# Reference App Using RealmJS in Node.js | ||
|
||
A skeleton app to be used as a reference for how to use the [Realm Node.js SDK](https://www.mongodb.com/docs/realm/sdk/node/) specifically around detecting various changes in e.g. connection state, user state, and sync errors, in order to better guide developers. | ||
|
||
## Relevant Files | ||
|
||
``` | ||
├── src | ||
│ ├── atlas-app-services (Configure Atlas App) | ||
│ │ ├── config.ts | ||
│ │ └── getAtlasApp.ts | ||
│ ├── models (Simplified data model) | ||
│ │ ├── Kiosk.ts | ||
│ │ ├── Product.ts | ||
│ │ └── Store.ts | ||
│ ├── index.ts (Entry point) | ||
│ ├── logger.ts (Replaceable logger) | ||
│ ├── realm-auth.ts (Main Realm auth usage examples) | ||
│ └── realm-query.ts (Data access/manipulation helper) | ||
└── other.. | ||
``` | ||
|
||
Main file for showcasing Realm usage pertaining to connection and error handling: | ||
* [src/realm-auth.ts](./src/realm-auth.ts) | ||
|
||
## Scope | ||
|
||
The app addresses the following points: | ||
|
||
* Listening when a user is logged out or removed. | ||
* Listening when a user's tokens are refreshed. | ||
* Listening when the underlying sync session is connecting, gets connected, gets disconnected, and fails to reconnect. | ||
* Listening for sync errors. | ||
* Listening for pre and post client resets. | ||
* Explains that the refresh of access tokens is handled automatically by the SDK. | ||
* [Refresh token expiration time](https://www.mongodb.com/docs/atlas/app-services/users/sessions/#configure-refresh-token-expiration) can be altered in the Atlas UI, whereafter you can observe the relevant client listeners being fired. | ||
* Login is shown using email/password. With the above bullet point, testing refresh token expiration is still possible in this case despite not using JWT as the login method. | ||
* Generally providing best practices for the surrounding Realm usage such as opening and closing of realms, configurations, adding subscriptions, etc. | ||
* Includes useful comments around the use of Realm. | ||
* Note that an over-simplified data model is used. This app also writes data to confirm the functionality. | ||
|
||
### Summary | ||
|
||
This reference app thus focuses on showing where and when you can (a) perform logging and (b) handle specific scenarios based on observed changes. | ||
|
||
### Realm Details | ||
|
||
* RealmJS version: ^12.0.0 | ||
* Device Sync type: Flexible | ||
|
||
## Getting Started | ||
|
||
### Prerequisites | ||
|
||
* [Node.js](https://nodejs.org/) | ||
|
||
### Set up an Atlas App Services App | ||
|
||
To sync Realm data you must first: | ||
|
||
1. [Create an App Services App](https://www.mongodb.com/docs/atlas/app-services/manage-apps/create/create-with-ui/) | ||
2. Enable [Email/Password Authentication](https://www.mongodb.com/docs/atlas/app-services/authentication/email-password/#std-label-email-password-authentication) | ||
3. [Enable Flexible Sync](https://www.mongodb.com/docs/atlas/app-services/sync/configure/enable-sync/) with **Development Mode** on. | ||
* When Development Mode is enabled, queryable fields will be added automatically. | ||
* Queryable fields used in this app: `_id`, `storeId` | ||
|
||
After running the client and seeing the available collections in Atlas, [set read/write permissions](https://www.mongodb.com/docs/atlas/app-services/rules/roles/#with-device-sync) for all collections. | ||
|
||
### Install Node.js dependencies | ||
|
||
```sh | ||
npm install | ||
``` | ||
|
||
### Run the app | ||
|
||
1. Copy your [Atlas App ID](https://www.mongodb.com/docs/atlas/app-services/reference/find-your-project-or-app-id/#std-label-find-your-app-id) from the App Services UI. | ||
2. Paste the copied ID as the value of the existing variable `ATLAS_APP_ID` in [src/atlas-app-services/config.ts](./src/atlas-app-services/config.ts): | ||
```js | ||
export const ATLAS_APP_ID = "YOUR_APP_ID"; | ||
``` | ||
|
||
3. Start the script. | ||
|
||
```sh | ||
npm start | ||
``` | ||
|
||
|
||
### Troubleshooting | ||
|
||
* If permission is denied: | ||
* Whitelist your IP address via the Atlas UI. | ||
* Make sure you have [read/write permissions](https://www.mongodb.com/docs/atlas/app-services/rules/roles/#with-device-sync) for all collections. | ||
* Removing the local database can be useful for certain errors. | ||
* When running the app, the local database will exist in the directory `mongodb-realm/`. | ||
* To remove it, run: `npm run rm-local-db` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "@realm/example-node-connection-and-error", | ||
"version": "1.0.0", | ||
"description": "A skeleton app to be used as a reference for how to use the Realm Node.js SDK specifically around detecting various changes in e.g. connection state, user state, and sync errors", | ||
"main": "src/index.ts", | ||
"scripts": { | ||
"build": "tsc", | ||
"start": "npm run build && node dist/src/index.js", | ||
"rm-local-db": "rm -rf mongodb-realm/", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"dependencies": { | ||
"realm": "^12.0.0" | ||
}, | ||
"devDependencies": { | ||
"typescript": "^5.1.6" | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
examples/example-node-connection-and-error/src/atlas-app-services/config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
//////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Copyright 2023 Realm Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
//////////////////////////////////////////////////////////////////////////// | ||
|
||
import { BSON } from "realm"; | ||
|
||
// For this example app, the constant below is type annotated as `string` rather | ||
// than inferred due to the equality check in `src/atlas-app-services/getAtlasApp.ts` | ||
// verifying that this constant has been set. | ||
export const ATLAS_APP_ID: string = "YOUR_APP_ID"; | ||
export const SYNC_STORE_ID = new BSON.ObjectId("6426106cb0ad9713140883ed"); |
47 changes: 47 additions & 0 deletions
47
examples/example-node-connection-and-error/src/atlas-app-services/getAtlasApp.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
//////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Copyright 2023 Realm Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
//////////////////////////////////////////////////////////////////////////// | ||
|
||
import Realm from "realm"; | ||
|
||
import { ATLAS_APP_ID } from "./config"; | ||
import { logger } from "../logger"; | ||
|
||
let app: Realm.App | null = null; | ||
|
||
export const getAtlasApp = function getAtlasApp() { | ||
if (!app) { | ||
if (ATLAS_APP_ID === "YOUR_APP_ID") { | ||
throw new Error( | ||
"Please add your Atlas App ID to `src/atlas-app-services/config.ts`. Refer to `README.md` on how to find your ID.", | ||
); | ||
} | ||
|
||
app = new Realm.App({ id: ATLAS_APP_ID }); | ||
|
||
// Using log level "all", "trace", or "debug" is good for debugging during developing. | ||
// Lower log levels are recommended in production for performance improvement. | ||
// logLevels = ["all", "trace", "debug", "detail", "info", "warn", "error", "fatal", "off"]; | ||
// You may import `NumericLogLevel` to get them as numbers starting from 0 (`all`). | ||
Realm.setLogLevel("error"); | ||
Realm.setLogger((logLevel, message) => { | ||
logger.info(`Log level: ${logLevel} - Log message: ${message}`); | ||
}); | ||
} | ||
|
||
return app; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Copyright 2023 Realm Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
//////////////////////////////////////////////////////////////////////////// | ||
|
||
import { register, logIn, logOut, openRealm } from "./realm-auth"; | ||
import { addDummyData, updateDummyData, deleteDummyData, getStore } from "./realm-query"; | ||
|
||
const exampleEmail = "john@doe.com"; | ||
const examplePassword = "123456"; | ||
|
||
/** | ||
* Illustrates the flow of using a synced Realm. | ||
*/ | ||
async function main(): Promise<void> { | ||
let success = await register(exampleEmail, examplePassword); | ||
if (!success) { | ||
return; | ||
} | ||
|
||
success = await logIn(exampleEmail, examplePassword); | ||
if (!success) { | ||
return; | ||
} | ||
|
||
await openRealm(); | ||
|
||
// Cleaning the DB for this example before continuing. | ||
deleteDummyData(); | ||
addDummyData(); | ||
updateDummyData(); | ||
|
||
// Print a kiosk and its products. | ||
const store = getStore(); | ||
const firstKiosk = store?.kiosks[0]; | ||
if (firstKiosk) { | ||
console.log(JSON.stringify(firstKiosk, null, 2)); | ||
} | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
//////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Copyright 2023 Realm Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
//////////////////////////////////////////////////////////////////////////// | ||
|
||
/** | ||
* Logger - This is meant to be replaced with a preferred logging implementation. | ||
*/ | ||
export const logger = { | ||
info(message: string) { | ||
console.info(new Date().toLocaleString(), '|', message); | ||
}, | ||
error(message: string) { | ||
console.error(new Date().toLocaleString(), '|', message); | ||
}, | ||
}; |
37 changes: 37 additions & 0 deletions
37
examples/example-node-connection-and-error/src/models/Kiosk.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
//////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Copyright 2023 Realm Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
//////////////////////////////////////////////////////////////////////////// | ||
|
||
import Realm, { BSON, ObjectSchema } from "realm"; | ||
|
||
import { Product } from "./Product"; | ||
|
||
export class Kiosk extends Realm.Object { | ||
_id!: BSON.ObjectId; | ||
storeId!: BSON.ObjectId; | ||
products!: Realm.List<Product>; | ||
|
||
static schema: ObjectSchema = { | ||
name: "Kiosk", | ||
primaryKey: "_id", | ||
properties: { | ||
_id: "objectId", | ||
storeId: { type: "objectId", indexed: true }, | ||
products: "Product[]", | ||
}, | ||
}; | ||
} |
44 changes: 44 additions & 0 deletions
44
examples/example-node-connection-and-error/src/models/Product.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
//////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Copyright 2023 Realm Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
//////////////////////////////////////////////////////////////////////////// | ||
|
||
import Realm, { BSON, ObjectSchema } from "realm"; | ||
|
||
/** | ||
* Current information and inventory about a type of product in a particular store. | ||
* (This is simplified to refer to a complete product (e.g. a sandwich, rather than | ||
* e.g. bread, cheese, lettuce, etc.) | ||
*/ | ||
export class Product extends Realm.Object { | ||
_id!: BSON.ObjectId; | ||
storeId!: BSON.ObjectId; | ||
name!: string; | ||
price!: number; | ||
numInStock!: number; | ||
|
||
static schema: ObjectSchema = { | ||
name: "Product", | ||
primaryKey: "_id", | ||
properties: { | ||
_id: "objectId", | ||
storeId: { type: "objectId", indexed: true }, | ||
name: "string", | ||
price: "double", | ||
numInStock: "int", | ||
}, | ||
}; | ||
} |
Oops, something went wrong.