From 05b4dea4b7e19856cee2b87e1f63dbb7a7fe06a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 26 Feb 2024 09:48:39 +0100 Subject: [PATCH] Replace "rollup" bundling with TypeScript project references (#6492) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adding a "build" script to SDK using TS project references * Removed "realm:bundle" in favour of "realm:build" * Downgrading "module" of shared code to es2015 * Fixing up unit tests * Exporting "bare" types from @realm/fetch * Building only commonjs for now * WIP * No named exports only cjs * Moving public types into dist * Marking toFetchArgs as @internal * Minor changes to platforms * Stop generating TS via Cmake * Seperating "node-wrapper" bindgen into two separate templates reusing a base * Injecting binding instead of importing "realm/binding" * Adding a script to clean the SDK package * No need to emit the native.d.ts in the platform directories anymore * Moved patching of binding to a function called after injection * Fixed relative paths in tsconfig.json * Adding documentation on applyPatch * Emitting source-maps * Renaming "build" script to "build:typescript" * Moved deprecated global Realm into its own file * Refactored namespace API * Renamed "build" to "build:typescript" across depending packages * Expose Auth on the namespace * Renamed "realm:build:typescript" to "realm:build:ts" * Waypoint * Adding a "check-types" script * Adding @internal tags * Exposing Realm on the Realm namespace to help ease ESM transition * Adding a comment * Removed the tsconfig.base.json * Removed an extraneous internal tag * Adding transpilation as a dep of "test" * Fixed running tests and building from scratch * Fixed tests (again) * Fixed missing import inĀ @realm/react * Exporting the namespace deprecated-global.ts * Fixed test coverage * Removed the build:ts:instrumented script again * Adding binding sourcecode to the dist artifact upload * Fixing namespace errors * Fixed lint error * Adding a Jest wrapper for the RN entrypoint * Attempt at fixing coverage * Incorporating feedback * Fixed tsconfigs * Adding binding files to package files * Fixed output of bindgen:generate:typescript --- .github/workflows/pr-realm-js.yml | 2 + .gitignore | 3 + .../environments/electron/package.json | 4 +- .../environments/node/package.json | 4 +- .../environments/react-native/package.json | 12 +- integration-tests/tests/.mocharc.json | 5 +- integration-tests/tests/.nycrc.json | 3 +- integration-tests/tests/package.json | 9 +- .../tests/src/tests/migrations.ts | 1 - package-lock.json | 16 +- package.json | 5 +- packages/babel-plugin/package.json | 3 +- packages/fetch/package.json | 4 +- packages/fetch/tsconfig.node.base.json | 3 +- packages/fetch/tsconfig.node.cjs.json | 3 +- packages/fetch/tsconfig.node.esm.json | 3 +- packages/realm-react/package.json | 4 +- packages/realm-react/src/UserProvider.tsx | 1 + packages/realm-tools/package.json | 2 +- packages/realm/.eslintignore | 3 + packages/realm/bindgen/CMakeLists.txt | 30 +- packages/realm/bindgen/node.cmake | 4 +- packages/realm/bindgen/package.json | 7 +- .../bindgen/src/templates/base-wrapper.ts | 161 ++++ .../bindgen/src/templates/node-wrapper.ts | 198 +--- .../src/templates/react-native-wrapper.ts | 67 ++ .../realm/bindgen/src/templates/typescript.ts | 11 +- .../realm/{types.d.cts => binding/index.d.ts} | 7 +- packages/realm/binding/index.js | 45 + packages/realm/index.react-native.js | 13 +- packages/realm/package.json | 130 ++- packages/realm/rollup.config.mjs | 122 --- packages/realm/src/ClassHelpers.ts | 2 + packages/realm/src/Listeners.ts | 1 + packages/realm/src/PropertyHelpers.ts | 3 + packages/realm/src/Realm.ts | 875 +++--------------- packages/realm/src/TypeHelpers.ts | 3 + packages/realm/src/Types.ts | 39 +- packages/realm/src/app-services/App.ts | 22 +- packages/realm/src/app-services/Auth.ts | 26 + packages/realm/src/app-services/MongoDB.ts | 53 ++ .../src/app-services/MongoDBCollection.ts | 2 +- .../src/app-services/NetworkTransport.ts | 3 +- packages/realm/src/app-services/Services.ts | 27 + packages/realm/src/app-services/Sync.ts | 35 +- .../src/app-services/SyncConfiguration.ts | 2 +- packages/realm/src/app-services/User.ts | 4 +- packages/realm/src/app-services/utils.ts | 6 +- packages/realm/src/assert.ts | 1 + packages/realm/src/binding.ts | 159 ---- packages/realm/src/debug.ts | 2 + packages/realm/src/deprecated-global.ts | 182 ++++ packages/realm/src/index.ts | 185 +--- packages/realm/src/internal.ts | 7 +- packages/realm/src/platform.ts | 7 + packages/realm/src/platform/binding-patch.ts | 163 ++++ packages/realm/src/platform/binding.ts | 30 + packages/realm/src/platform/device-info.ts | 10 +- packages/realm/src/platform/file-system.ts | 4 +- packages/realm/src/platform/network.ts | 4 +- .../platform/node/binding.ts} | 8 +- packages/realm/src/platform/node/fs.ts | 6 +- packages/realm/src/platform/node/index.ts | 4 +- .../src/platform/node/sync-proxy-config.ts | 4 +- .../realm/src/platform/node/tsconfig.json | 19 - .../src/platform/react-native/binding.ts | 22 + .../src/platform/react-native/device-info.ts | 4 +- .../realm/src/platform/react-native/fs.ts | 5 +- .../realm/src/platform/react-native/index.ts | 5 +- .../src/platform/react-native/tsconfig.json | 22 - .../realm/src/platform/sync-proxy-config.ts | 10 +- packages/realm/src/schema/from-binding.ts | 13 +- packages/realm/src/schema/to-binding.ts | 13 +- packages/realm/src/schema/types.ts | 2 + packages/realm/src/tests/list.test.ts | 2 +- .../realm/src/tests/schema-transform.test.ts | 3 +- packages/realm/src/tests/schema-utils.test.ts | 17 +- .../realm/src/tests/schema-validation.test.ts | 8 +- packages/realm/src/tests/tsconfig.json | 12 - packages/realm/src/tests/utils.ts | 5 +- packages/realm/tsconfig.binding.json | 25 + packages/realm/tsconfig.json | 43 +- packages/realm/tsconfig.node.json | 23 + .../realm/tsconfig.public-types-check.json | 16 + packages/realm/tsconfig.public-types.json | 12 + packages/realm/tsconfig.react-native.json | 25 + packages/realm/tsconfig.shared.json | 38 + packages/realm/tsconfig.tests.json | 21 + 88 files changed, 1401 insertions(+), 1728 deletions(-) create mode 100644 packages/realm/bindgen/src/templates/base-wrapper.ts create mode 100644 packages/realm/bindgen/src/templates/react-native-wrapper.ts rename packages/realm/{types.d.cts => binding/index.d.ts} (82%) create mode 100644 packages/realm/binding/index.js delete mode 100644 packages/realm/rollup.config.mjs create mode 100644 packages/realm/src/app-services/Auth.ts create mode 100644 packages/realm/src/app-services/MongoDB.ts create mode 100644 packages/realm/src/app-services/Services.ts delete mode 100644 packages/realm/src/binding.ts create mode 100644 packages/realm/src/deprecated-global.ts create mode 100644 packages/realm/src/platform/binding-patch.ts create mode 100644 packages/realm/src/platform/binding.ts rename packages/realm/{index.node.js => src/platform/node/binding.ts} (77%) delete mode 100644 packages/realm/src/platform/node/tsconfig.json create mode 100644 packages/realm/src/platform/react-native/binding.ts delete mode 100644 packages/realm/src/platform/react-native/tsconfig.json delete mode 100644 packages/realm/src/tests/tsconfig.json create mode 100644 packages/realm/tsconfig.binding.json create mode 100644 packages/realm/tsconfig.node.json create mode 100644 packages/realm/tsconfig.public-types-check.json create mode 100644 packages/realm/tsconfig.public-types.json create mode 100644 packages/realm/tsconfig.react-native.json create mode 100644 packages/realm/tsconfig.shared.json create mode 100644 packages/realm/tsconfig.tests.json diff --git a/.github/workflows/pr-realm-js.yml b/.github/workflows/pr-realm-js.yml index 44a34a6e5a9..3c4ea279539 100644 --- a/.github/workflows/pr-realm-js.yml +++ b/.github/workflows/pr-realm-js.yml @@ -48,6 +48,8 @@ jobs: path: | README.md packages/*/dist + packages/realm/binding/dist + packages/realm/binding/generated build: name: Build for ${{ matrix.variant.os }} ${{ matrix.variant.arch }} diff --git a/.gitignore b/.gitignore index 5b91ac900c1..5556dbafa80 100644 --- a/.gitignore +++ b/.gitignore @@ -113,9 +113,12 @@ coverage/ # Generated artifacts /packages/realm/bindgen/vendor/bindgen-lib/generated/ /packages/realm/generated/ +/packages/realm/binding/generated # Build artifacts /packages/realm/dist/ +/packages/realm/binding/dist/ +/packages/realm/binding/build/ /packages/realm/prebuilds/ /packages/realm/react-native/android/src/main/java/io/realm/react/Version.java /packages/realm/react-native/android/src/main/jniLibs/ diff --git a/integration-tests/environments/electron/package.json b/integration-tests/environments/electron/package.json index 07a0c3cae9d..7f0bbdb7a0b 100644 --- a/integration-tests/environments/electron/package.json +++ b/integration-tests/environments/electron/package.json @@ -25,7 +25,7 @@ "test:main": { "command": "mocha-remote --reporter @realm/mocha-reporter --id main tsx runner.ts main", "dependencies": [ - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/realm:build:node", "../../../packages/mocha-reporter:bundle" ] @@ -33,7 +33,7 @@ "test:renderer": { "command": "mocha-remote --reporter @realm/mocha-reporter --id renderer tsx runner.ts renderer", "dependencies": [ - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/realm:build:node", "../../../packages/mocha-reporter:bundle" ] diff --git a/integration-tests/environments/node/package.json b/integration-tests/environments/node/package.json index 25d980f8f7e..4898d10f50b 100644 --- a/integration-tests/environments/node/package.json +++ b/integration-tests/environments/node/package.json @@ -13,7 +13,7 @@ "test": { "command": "mocha-remote --reporter @realm/mocha-reporter tsx index.mjs", "dependencies": [ - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/realm:build:node", "../../../packages/mocha-reporter:bundle" ] @@ -21,7 +21,7 @@ "test:commonjs": { "command": "mocha-remote --reporter @realm/mocha-reporter tsx index.cjs", "dependencies": [ - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/realm:build:node", "../../../packages/mocha-reporter:bundle" ] diff --git a/integration-tests/environments/react-native/package.json b/integration-tests/environments/react-native/package.json index bc540b15786..3b1df70b75c 100644 --- a/integration-tests/environments/react-native/package.json +++ b/integration-tests/environments/react-native/package.json @@ -98,7 +98,7 @@ "command": "npm run common", "dependencies": [ "../../../packages/realm:build:android", - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/mocha-reporter:bundle" ], "env": { @@ -116,7 +116,7 @@ "command": "npm run common", "dependencies": [ "pod-install:simulator", - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/mocha-reporter:bundle" ], "env": { @@ -128,7 +128,7 @@ "command": "npm run common", "dependencies": [ "pod-install:catalyst", - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/mocha-reporter:bundle" ], "env": { @@ -155,7 +155,7 @@ "command": "npm run common", "dependencies": [ "../../../packages/realm:build:android", - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/mocha-reporter:bundle" ], "env": { @@ -168,7 +168,7 @@ "dependencies": [ "pod-install:simulator", "../../../packages/realm:build:ios:debug:simulator", - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/mocha-reporter:bundle" ], "env": { @@ -181,7 +181,7 @@ "dependencies": [ "pod-install:catalyst", "../../../packages/realm:build:ios:debug:catalyst", - "../../../packages/realm:bundle", + "../../../packages/realm:build:ts", "../../../packages/mocha-reporter:bundle" ], "env": { diff --git a/integration-tests/tests/.mocharc.json b/integration-tests/tests/.mocharc.json index fe1943f504f..d24db138079 100644 --- a/integration-tests/tests/.mocharc.json +++ b/integration-tests/tests/.mocharc.json @@ -6,6 +6,9 @@ "no-warnings" ], "reporter": "@realm/mocha-reporter", - "require": "src/node/inject-globals.ts", + "require": [ + "source-map-support/register", + "src/node/inject-globals.ts" + ], "spec": "src/index.ts" } \ No newline at end of file diff --git a/integration-tests/tests/.nycrc.json b/integration-tests/tests/.nycrc.json index 29783b819f9..8f4c0fae43f 100644 --- a/integration-tests/tests/.nycrc.json +++ b/integration-tests/tests/.nycrc.json @@ -1,8 +1,7 @@ { - "extends": "@istanbuljs/nyc-config-typescript", - "all": true, "cwd": "../..", "include": [ + "packages/realm/dist/**", "packages/realm/src/**" ] } \ No newline at end of file diff --git a/integration-tests/tests/package.json b/integration-tests/tests/package.json index 4820da67007..040d54656a7 100644 --- a/integration-tests/tests/package.json +++ b/integration-tests/tests/package.json @@ -20,46 +20,42 @@ "lint": { "command": "eslint --ext .js,.ts . && tsc --noEmit", "dependencies": [ - "../../packages/realm:bundle" + "build-dependencies" ] }, "build": { "command": "tsc", "dependencies": [ - "../../packages/realm:bundle", "build-dependencies" ] }, "start": { "command": "mocha --watch", "dependencies": [ - "../../packages/realm:bundle", "build-dependencies" ] }, "test": { "command": "mocha --exit", "dependencies": [ - "../../packages/realm:bundle", "build-dependencies" ] }, "coverage": { "command": "nyc mocha --exit", "dependencies": [ - "../../packages/realm:bundle:coverage", "build-dependencies" ] }, "ci:coverage": { "command": "nyc --reporter=lcov -- mocha --exit", "dependencies": [ - "../../packages/realm:bundle:coverage", "build-dependencies" ] }, "build-dependencies": { "dependencies": [ + "../../packages/realm:build:ts", "../../packages/realm:build:node", "../../packages/mocha-reporter:bundle" ] @@ -69,7 +65,6 @@ "realm": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", "@realm/app-importer": "*", "@realm/mocha-reporter": "*", "@thi.ng/bench": "^3.1.16", diff --git a/integration-tests/tests/src/tests/migrations.ts b/integration-tests/tests/src/tests/migrations.ts index 2ef1774db5c..f4cf6cc1b5c 100644 --- a/integration-tests/tests/src/tests/migrations.ts +++ b/integration-tests/tests/src/tests/migrations.ts @@ -18,7 +18,6 @@ import Realm from "realm"; import { expect } from "chai"; import { DogSchema, IDog, IPerson, PersonSchema } from "../schemas/person-and-dogs"; -import { BSON } from "realm/dist/bundle"; const TestSchema = { name: "Test", diff --git a/package-lock.json b/package-lock.json index d873b76a2b5..3c838798325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", "@rollup/plugin-typescript": "^11.1.6", + "@tsconfig/node-lts": "^20.1.1", "@typescript-eslint/eslint-plugin": "^5.60.0", "@typescript-eslint/parser": "^5.60.0", "clang-format": "^1.8.0", @@ -5269,7 +5270,7 @@ "resolved": "integration-tests/tests", "link": true }, - "node_modules/@realm/js-binding": { + "node_modules/@realm/js-bindgen": { "resolved": "packages/realm/bindgen", "link": true }, @@ -5698,6 +5699,11 @@ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, + "node_modules/@tsconfig/node-lts": { + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node-lts/-/node-lts-20.1.1.tgz", + "integrity": "sha512-V7wHydi1dv8I8xiOX3pJ0lhC+MlOakznvLks94J6y/TqQK6DBcbdD1G4jEq8yU+s6lBASPn4e1Ci636fDqeyvQ==" + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -25148,6 +25154,9 @@ "prebuild-install": "^7.1.1" }, "devDependencies": { + "@babel/cli": "^7.23.9", + "@babel/core": "^7.23.9", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", "@realm/bindgen": "^0.1.0", "@realm/fetch": "^0.1.0", "@types/chai": "^4.3.3", @@ -25719,10 +25728,7 @@ } }, "packages/realm/bindgen": { - "name": "@realm/js-binding", - "workspaces": [ - "packages/realm/bindgen/vendor/realm-core/" - ] + "name": "@realm/js-bindgen" }, "packages/realm/bindgen/vendor/realm-core": { "name": "@realm/bindgen", diff --git a/package.json b/package.json index 2d685abbfdb..c807725273d 100644 --- a/package.json +++ b/package.json @@ -17,12 +17,12 @@ "build": { "dependencies": [ "bundle", - "./packages/realm:build" + "./packages/realm:build:ts" ] }, "bundle": { "dependencies": [ - "./packages/realm:bundle", + "./packages/realm:build:ts", "./packages/babel-plugin:bundle", "./packages/mocha-reporter:bundle", "./packages/realm-react:bundle", @@ -78,6 +78,7 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", "@rollup/plugin-typescript": "^11.1.6", + "@tsconfig/node-lts": "^20.1.1", "@typescript-eslint/eslint-plugin": "^5.60.0", "@typescript-eslint/parser": "^5.60.0", "clang-format": "^1.8.0", diff --git a/packages/babel-plugin/package.json b/packages/babel-plugin/package.json index b179ef8fac7..7deabe9f109 100644 --- a/packages/babel-plugin/package.json +++ b/packages/babel-plugin/package.json @@ -23,7 +23,8 @@ "test": { "command": "jest", "dependencies": [ - "../realm:bundle" + "../realm:build:ts", + "../realm:bindgen:build:typescript" ] } }, diff --git a/packages/fetch/package.json b/packages/fetch/package.json index 9472a8dcd1b..260d12e9337 100644 --- a/packages/fetch/package.json +++ b/packages/fetch/package.json @@ -21,13 +21,13 @@ } }, "exports": { + "types": "./dist/types/types.d.ts", "node": { "import": "./dist/node-esm/node.js", "require": "./dist/node-cjs/node.js" }, "react-native": "./dist/react-native/react-native.js", - "browser": "./dist/browser/browser.js", - "types": "./dist/types/types.d.ts" + "browser": "./dist/browser/browser.js" }, "react-native": "./dist/react-native/react-native.js", "types": "./dist/types/types.d.ts", diff --git a/packages/fetch/tsconfig.node.base.json b/packages/fetch/tsconfig.node.base.json index 97a15ad5c16..c4f130afebb 100644 --- a/packages/fetch/tsconfig.node.base.json +++ b/packages/fetch/tsconfig.node.base.json @@ -4,6 +4,7 @@ "@tsconfig/node18/tsconfig.json", ], "files": [ - "src/node.ts" + "src/node.ts", + "src/types.ts" ] } \ No newline at end of file diff --git a/packages/fetch/tsconfig.node.cjs.json b/packages/fetch/tsconfig.node.cjs.json index 37941373997..86e1871265d 100644 --- a/packages/fetch/tsconfig.node.cjs.json +++ b/packages/fetch/tsconfig.node.cjs.json @@ -2,7 +2,8 @@ "extends": "./tsconfig.node.base.json", "compilerOptions": { "outDir": "./dist/node-cjs", - "module": "CommonJS" + "module": "Node16", + "moduleResolution": "Node16" }, "references": [ { "path": "tsconfig.types.json" } diff --git a/packages/fetch/tsconfig.node.esm.json b/packages/fetch/tsconfig.node.esm.json index 6d83d110054..3f96c2f4f7e 100644 --- a/packages/fetch/tsconfig.node.esm.json +++ b/packages/fetch/tsconfig.node.esm.json @@ -2,7 +2,8 @@ "extends": "./tsconfig.node.base.json", "compilerOptions": { "outDir": "./dist/node-esm", - "module": "ES2022" + "module": "es2022", + "moduleResolution": "Bundler" }, "references": [ { "path": "tsconfig.types.json" } diff --git a/packages/realm-react/package.json b/packages/realm-react/package.json index e687982cb20..c37a2605951 100644 --- a/packages/realm-react/package.json +++ b/packages/realm-react/package.json @@ -18,7 +18,7 @@ "bundle": { "command": "rollup --config && tsc -p tsconfig.types.json", "dependencies": [ - "../realm:bundle", + "../realm:build:ts", "../realm-common:bundle" ], "files": [ @@ -33,7 +33,7 @@ "test": { "command": "jest --forceExit", "dependencies": [ - "../realm:bundle", + "../realm:build:ts", "../realm:build:node", "../realm-common:bundle", "../realm-app-importer:type-check" diff --git a/packages/realm-react/src/UserProvider.tsx b/packages/realm-react/src/UserProvider.tsx index fa0cb8c458f..90da85ee204 100644 --- a/packages/realm-react/src/UserProvider.tsx +++ b/packages/realm-react/src/UserProvider.tsx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////////////// import React, { createContext, useContext, useEffect, useState } from "react"; +import type Realm from "realm"; import { useApp } from "./AppProvider"; diff --git a/packages/realm-tools/package.json b/packages/realm-tools/package.json index 77f173f2c1c..a5a084c1c63 100644 --- a/packages/realm-tools/package.json +++ b/packages/realm-tools/package.json @@ -17,7 +17,7 @@ "build": { "command": "tsc -p tsconfig.build.json", "dependencies": [ - "../realm:bundle" + "../realm:build:ts" ], "files": [ "tsconfig.build.json", diff --git a/packages/realm/.eslintignore b/packages/realm/.eslintignore index add41ffd433..608b3230b93 100644 --- a/packages/realm/.eslintignore +++ b/packages/realm/.eslintignore @@ -2,3 +2,6 @@ dist/ docs/ bindgen/vendor/realm-core/ src/tests/realms/ + +# Files transpiled by babel from generated files +binding/generated/*.cjs diff --git a/packages/realm/bindgen/CMakeLists.txt b/packages/realm/bindgen/CMakeLists.txt index b4c14d541e5..26fa9ad0edf 100644 --- a/packages/realm/bindgen/CMakeLists.txt +++ b/packages/realm/bindgen/CMakeLists.txt @@ -137,35 +137,7 @@ list(FILTER SDK_TS_FILES EXCLUDE REGEX "templates/[^/]*\.ts$") set(JS_SPEC_FILE ${SDK_DIR}/bindgen/js_spec.yml) set(JS_OPT_IN_FILE ${SDK_DIR}/bindgen/js_opt_in_spec.yml) -set(TYPESCRIPT_OUTPUT_DIR ${SDK_DIR}/generated/ts) - -set(GENERATED_TS_FILES - ${TYPESCRIPT_OUTPUT_DIR}/native.d.mts - ${TYPESCRIPT_OUTPUT_DIR}/core.ts -) -bindgen( - TEMPLATE ${SDK_DIR}/bindgen/src/templates/typescript.ts - OUTPUTS ${GENERATED_TS_FILES} - OUTDIR ${TYPESCRIPT_OUTPUT_DIR} - SPECS ${JS_SPEC_FILE} - OPTIN ${JS_OPT_IN_FILE} - SOURCES ${SDK_TS_FILES} -) - -set(GENERATED_JS_FILES - ${TYPESCRIPT_OUTPUT_DIR}/native-node.mjs - ${TYPESCRIPT_OUTPUT_DIR}/native-react-native.mjs -) -bindgen( - TEMPLATE ${SDK_DIR}/bindgen/src/templates/node-wrapper.ts - OUTPUTS ${GENERATED_JS_FILES} - OUTDIR ${TYPESCRIPT_OUTPUT_DIR} - SPECS ${JS_SPEC_FILE} - OPTIN ${JS_OPT_IN_FILE} - SOURCES ${SDK_TS_FILES} -) - -add_custom_target(TypeScript ALL DEPENDS ${GENERATED_TS_FILES} ${GENERATED_JS_FILES}) +set(NODE_OUTPUT_DIR ${SDK_DIR}/binding/build) if(DEFINED CMAKE_JS_VERSION) include(node.cmake) diff --git a/packages/realm/bindgen/node.cmake b/packages/realm/bindgen/node.cmake index 644ab617262..41653fa44ac 100644 --- a/packages/realm/bindgen/node.cmake +++ b/packages/realm/bindgen/node.cmake @@ -10,8 +10,8 @@ set_target_properties(realm-js-node PROPERTIES set_target_properties(realm-js-node PROPERTIES # Need a dummy generator expression to avoid adding in the config name - LIBRARY_OUTPUT_DIRECTORY "${TYPESCRIPT_OUTPUT_DIR}/$<0:dummy_genex>" - RUNTIME_OUTPUT_DIRECTORY "${TYPESCRIPT_OUTPUT_DIR}/$<0:dummy_genex>" + LIBRARY_OUTPUT_DIRECTORY "${NODE_OUTPUT_DIR}/$<0:dummy_genex>" + RUNTIME_OUTPUT_DIRECTORY "${NODE_OUTPUT_DIR}/$<0:dummy_genex>" ) if(WIN32) diff --git a/packages/realm/bindgen/package.json b/packages/realm/bindgen/package.json index 17a27368f37..d513fab7a99 100644 --- a/packages/realm/bindgen/package.json +++ b/packages/realm/bindgen/package.json @@ -1,8 +1,5 @@ { - "name": "@realm/js-binding", + "name": "@realm/js-bindgen", "private": true, - "type": "module", - "workspaces": [ - "packages/realm/bindgen/vendor/realm-core/" - ] + "type": "module" } diff --git a/packages/realm/bindgen/src/templates/base-wrapper.ts b/packages/realm/bindgen/src/templates/base-wrapper.ts new file mode 100644 index 00000000000..607d0a48130 --- /dev/null +++ b/packages/realm/bindgen/src/templates/base-wrapper.ts @@ -0,0 +1,161 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2022 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 { strict as assert } from "assert"; +import { Property } from "@realm/bindgen/bound-model"; +import { TemplateContext } from "@realm/bindgen/context"; +import { Outputter } from "@realm/bindgen/outputter"; + +import { doJsPasses } from "../js-passes"; + +export function generateNativeBigIntSupport(out: Outputter) { + out(` + const NativeBigIntSupport = Object.freeze({ + add(a, b) { return a + b; }, + equals(a, b) { return a == b; }, // using == rather than === to support number and string RHS! + isInt(a) { return typeof(a) === "bigint"; }, + numToInt(a) { return BigInt(a); }, + strToInt(a) { return BigInt(a); }, + intToNum(a) { return Number(a); }, + }); + `); +} + +export function generate({ spec: boundSpec }: TemplateContext, out: Outputter): void { + const spec = doJsPasses(boundSpec); + + out(` + import { Long, ObjectId, UUID, Decimal128, EJSON } from "bson"; + import { Float, Status } from "../dist/core"; + + export * from "../dist/core"; + + // Copied from lib/utils.js. + // TODO consider importing instead. + // Might be slightly faster to make dedicated wrapper for 1 and 2 argument forms, but unlikely to be worth it. + function _promisify(nullAllowed, func) { + return new Promise((resolve, reject) => { + func((...cbargs) => { + // Any errors in this function should flow into the Promise chain, rather than out to the caller, + // since callers of async callbacks aren't expecting exceptions. + try { + if (cbargs.length < 1 || cbargs.length > 2) throw Error("invalid cbargs length " + cbargs.length); + let error = cbargs[cbargs.length - 1]; + if (error) { + reject(error); + } else if (cbargs.length == 2) { + const result = cbargs[0]; + if (!nullAllowed && (result === null || result === undefined)) { + throw new Error("Unexpected null or undefined successful result"); + } + resolve(result); + } else { + resolve(); + } + } catch (err) { + reject(err); + } + }); + }); + } + `); + + const injectables = [ + "Long", + "ArrayBuffer", + "Float", + "Status", + "ObjectId", + "UUID", + "Decimal128", + "EJSON_parse: EJSON.parse", + "EJSON_stringify: EJSON.stringify", + ]; + + for (const cls of spec.classes) { + injectables.push(cls.jsName); + + let body = ""; + + // It will always be accessed via this name rather than a static to enable optimizations + // that depend on the symbol not changing. + const symb = `_${cls.rootBase().jsName}_Symbol`; + + if (!cls.base) { + // Only root classes get symbols and constructors + out(`const ${symb} = Symbol("Realm.${cls.jsName}.external_pointer");`); + + body += `constructor(ptr) { this[${symb}] = ptr};`; + } + + // This will override the extractor from the base class to do a more specific type check. + body += ` + static _extract(self) { + if (!(self instanceof ${cls.jsName})) + throw new TypeError("Expected a ${cls.jsName}"); + const out = self[${symb}]; + if (!out) + throw new TypeError("received an improperly constructed ${cls.jsName}"); + return out; + }; + `; + + for (const method of cls.methods) { + if (!method.isOptedInTo) continue; + + // Eagerly bind the name once from the native module. + const native = `_native_${method.id}`; + out(`const ${native} = nativeModule.${method.id};`); + // TODO consider pre-extracting class-typed arguments while still in JIT VM. + const asyncSig = method.sig.asyncTransform(); + const params = (asyncSig ?? method.sig).args.map((a) => a.name); + const args = [ + method.isStatic ? [] : `this[${symb}]`, // + ...params, + asyncSig ? "_cb" : [], + ].flat(); + let call = `${native}(${args})`; + if (asyncSig) { + // JS can't distinguish between a `const EJson*` that is nullptr (which can't happen), and + // one that points to the string "null" because both become null by the time they reach JS. + // In order to allow the latter (which does happen! E.g. the promise from `response.text()` + // can resolve to `"null"`) we need a special case here. + // TODO see if there is a better approach. + assert(asyncSig.ret.isTemplate("AsyncResult")); + const ret = asyncSig.ret.args[0]; + const nullAllowed = !!(ret.is("Pointer") && ret.type.kind == "Const" && ret.type.type.isPrimitive("EJson")); + call = `_promisify(${nullAllowed}, _cb => ${call})`; + } + body += ` + ${method.isStatic ? "static" : ""} + ${method instanceof Property ? "get" : ""} + ${method.jsName}(${params}) { + return ${call}; + }`; + } + + if (cls.iterable) { + const native = `_native_${cls.iteratorMethodId()}`; + out(`const ${native} = nativeModule.${cls.iteratorMethodId()};`); + body += `\n[Symbol.iterator]() { return ${native}(this[${symb}]); }`; + } + + out(`export class ${cls.jsName} ${cls.base ? `extends ${cls.base.jsName}` : ""} { ${body} }`); + } + + out(`nativeModule.injectInjectables({ ${injectables} });`); +} diff --git a/packages/realm/bindgen/src/templates/node-wrapper.ts b/packages/realm/bindgen/src/templates/node-wrapper.ts index ca05ae287e1..f99066c3b0c 100644 --- a/packages/realm/bindgen/src/templates/node-wrapper.ts +++ b/packages/realm/bindgen/src/templates/node-wrapper.ts @@ -15,52 +15,20 @@ // limitations under the License. // //////////////////////////////////////////////////////////////////////////// -import { strict as assert } from "assert"; -import { Property } from "@realm/bindgen/bound-model"; import { TemplateContext } from "@realm/bindgen/context"; -import { doJsPasses } from "../js-passes"; import { eslint } from "../eslint-formatter"; +import { generate as generateBase, generateNativeBigIntSupport } from "./base-wrapper"; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export function generate({ rawSpec, spec: boundSpec, file }: TemplateContext): void { - const spec = doJsPasses(boundSpec); - const reactLines = []; - const nodeLines = []; - function both(...content: string[]) { - reactLines.push(...content); - nodeLines.push(...content); - } +export function generate(context: TemplateContext): void { + const out = context.file("native.node.mjs", eslint); - both("// This file is generated: Update the spec instead of editing this file directly"); + out("// This file is generated: Update the spec instead of editing this file directly"); - // TODO RN vs Node will probably diverge further in the future and will likely need different templates. - // But for now, this should work to let us load the native module for both platforms. - reactLines.push(` - /*global global*/ - import { Platform, NativeModules } from "react-native"; - if (Platform.OS === "android") { - // Getting the native module on Android will inject the Realm global - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const RealmNativeModule = NativeModules.Realm; - } - // TODO: Remove the need to store Realm as a global - // @see https://github.com/realm/realm-js/issues/2126 - const nativeModule = global.__RealmFuncs; - if(!nativeModule) { - throw new Error("Could not find the Realm binary. Please consult our troubleshooting guide: https://www.mongodb.com/docs/realm-sdks/js/latest/#md:troubleshooting-missing-binary"); - } - - export const WeakRef = global.WeakRef ?? class WeakRef { - constructor(obj) { this.native = nativeModule.createWeakRef(obj) } - deref() { return nativeModule.lockWeakRef(this.native) } - }; - `); - nodeLines.push(` - /*global global, require */ - import { createRequire } from 'node:module'; - const nodeRequire = typeof require === 'function' ? require : createRequire(import.meta.url); - const nativeModule = nodeRequire("./realm.node"); + out(` + /* eslint-disable @typescript-eslint/no-var-requires */ + /* global global, require */ + const nativeModule = require("#realm.node"); if(!nativeModule) { throw new Error("Could not find the Realm binary. Please consult our troubleshooting guide: https://www.mongodb.com/docs/realm-sdks/js/latest/#md:troubleshooting-missing-binary"); @@ -70,152 +38,14 @@ export function generate({ rawSpec, spec: boundSpec, file }: TemplateContext): v export const WeakRef = global.WeakRef; `); - both(` - const NativeBigIntSupport = Object.freeze({ - add(a, b) { return a + b; }, - equals(a, b) { return a == b; }, // using == rather than === to support number and string RHS! - isInt(a) { return typeof(a) === "bigint"; }, - numToInt(a) { return BigInt(a); }, - strToInt(a) { return BigInt(a); }, - intToNum(a) { return Number(a); }, - }); - `); - nodeLines.push(` - export const Int64 = NativeBigIntSupport; // Node always supports BigInt - `); - reactLines.push(` - // Hermes supports BigInt, but JSC doesn't. - export const Int64 = global.HermesInternal ? NativeBigIntSupport : { - add(a, b) { return a.add(b); }, - equals(a, b) { return a.equals(b); }, - isInt(a) { return a instanceof Long; }, - numToInt(a) { return Long.fromNumber(a); }, - strToInt(a) { return Long.fromString(a); }, - intToNum(a) { return a.toNumber(); }, - } - `); - - both(` - import { Long, ObjectId, UUID, Decimal128, EJSON } from "bson"; - import { Float, Status } from "./core"; + generateNativeBigIntSupport(out); - export * from "./core"; - - // Copied from lib/utils.js. - // TODO consider importing instead. - // Might be slightly faster to make dedicated wrapper for 1 and 2 argument forms, but unlikely to be worth it. - function _promisify(nullAllowed, func) { - return new Promise((resolve, reject) => { - func((...cbargs) => { - // Any errors in this function should flow into the Promise chain, rather than out to the caller, - // since callers of async callbacks aren't expecting exceptions. - try { - if (cbargs.length < 1 || cbargs.length > 2) throw Error("invalid cbargs length " + cbargs.length); - let error = cbargs[cbargs.length - 1]; - if (error) { - reject(error); - } else if (cbargs.length == 2) { - const result = cbargs[0]; - if (!nullAllowed && (result === null || result === undefined)) { - throw new Error("Unexpected null or undefined successful result"); - } - resolve(result); - } else { - resolve(); - } - } catch (err) { - reject(err); - } - }); - }); - } + out(` + export const Int64 = NativeBigIntSupport; // Node always supports BigInt `); - const injectables = [ - "Long", - "ArrayBuffer", - "Float", - "Status", - "ObjectId", - "UUID", - "Decimal128", - "EJSON_parse: EJSON.parse", - "EJSON_stringify: EJSON.stringify", - ]; - - for (const cls of spec.classes) { - injectables.push(cls.jsName); - - let body = ""; - - // It will always be accessed via this name rather than a static to enable optimizations - // that depend on the symbol not changing. - const symb = `_${cls.rootBase().jsName}_Symbol`; - - if (!cls.base) { - // Only root classes get symbols and constructors - both(`const ${symb} = Symbol("Realm.${cls.jsName}.external_pointer");`); - - body += `constructor(ptr) { this[${symb}] = ptr};`; - } - - // This will override the extractor from the base class to do a more specific type check. - body += ` - static _extract(self) { - if (!(self instanceof ${cls.jsName})) - throw new TypeError("Expected a ${cls.jsName}"); - const out = self[${symb}]; - if (!out) - throw new TypeError("received an improperly constructed ${cls.jsName}"); - return out; - }; - `; - - for (const method of cls.methods) { - if (!method.isOptedInTo) continue; - - // Eagerly bind the name once from the native module. - const native = `_native_${method.id}`; - both(`const ${native} = nativeModule.${method.id};`); - // TODO consider pre-extracting class-typed arguments while still in JIT VM. - const asyncSig = method.sig.asyncTransform(); - const params = (asyncSig ?? method.sig).args.map((a) => a.name); - const args = [ - method.isStatic ? [] : `this[${symb}]`, // - ...params, - asyncSig ? "_cb" : [], - ].flat(); - let call = `${native}(${args})`; - if (asyncSig) { - // JS can't distinguish between a `const EJson*` that is nullptr (which can't happen), and - // one that points to the string "null" because both become null by the time they reach JS. - // In order to allow the latter (which does happen! E.g. the promise from `response.text()` - // can resolve to `"null"`) we need a special case here. - // TODO see if there is a better approach. - assert(asyncSig.ret.isTemplate("AsyncResult")); - const ret = asyncSig.ret.args[0]; - const nullAllowed = !!(ret.is("Pointer") && ret.type.kind == "Const" && ret.type.type.isPrimitive("EJson")); - call = `_promisify(${nullAllowed}, _cb => ${call})`; - } - body += ` - ${method.isStatic ? "static" : ""} - ${method instanceof Property ? "get" : ""} - ${method.jsName}(${params}) { - return ${call}; - }`; - } - - if (cls.iterable) { - const native = `_native_${cls.iteratorMethodId()}`; - both(`const ${native} = nativeModule.${cls.iteratorMethodId()};`); - body += `\n[Symbol.iterator]() { return ${native}(this[${symb}]); }`; - } - - both(`export class ${cls.jsName} ${cls.base ? `extends ${cls.base.jsName}` : ""} { ${body} }`); - } - - both(`nativeModule.injectInjectables({ ${injectables} });`); + generateBase(context, out); - file("native-node.mjs", eslint)(nodeLines.join("\n")); - file("native-react-native.mjs", eslint)(reactLines.join("\n")); + context.file("native.node.d.mts", eslint)("export * from './native'"); + context.file("native.node.d.cts", eslint)("import * as binding from './native'; export = binding;"); } diff --git a/packages/realm/bindgen/src/templates/react-native-wrapper.ts b/packages/realm/bindgen/src/templates/react-native-wrapper.ts new file mode 100644 index 00000000000..153a11b4d32 --- /dev/null +++ b/packages/realm/bindgen/src/templates/react-native-wrapper.ts @@ -0,0 +1,67 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2022 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 { TemplateContext } from "@realm/bindgen/context"; + +import { eslint } from "../eslint-formatter"; +import { generate as generateBase, generateNativeBigIntSupport } from "./base-wrapper"; + +export function generate(context: TemplateContext): void { + const out = context.file("native.react-native.mjs", eslint); + + out("// This file is generated: Update the spec instead of editing this file directly"); + + out(` + /*global global*/ + import { Platform, NativeModules } from "react-native"; + if (Platform.OS === "android") { + // Getting the native module on Android will inject the Realm global + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const RealmNativeModule = NativeModules.Realm; + } + // TODO: Remove the need to store Realm as a global + // @see https://github.com/realm/realm-js/issues/2126 + const nativeModule = global.__RealmFuncs; + if(!nativeModule) { + throw new Error("Could not find the Realm binary. Please consult our troubleshooting guide: https://www.mongodb.com/docs/realm-sdks/js/latest/#md:troubleshooting-missing-binary"); + } + + export const WeakRef = global.WeakRef ?? class WeakRef { + constructor(obj) { this.native = nativeModule.createWeakRef(obj) } + deref() { return nativeModule.lockWeakRef(this.native) } + }; + `); + + generateNativeBigIntSupport(out); + + out(` + // Hermes supports BigInt, but JSC doesn't. + export const Int64 = global.HermesInternal ? NativeBigIntSupport : { + add(a, b) { return a.add(b); }, + equals(a, b) { return a.equals(b); }, + isInt(a) { return a instanceof Long; }, + numToInt(a) { return Long.fromNumber(a); }, + strToInt(a) { return Long.fromString(a); }, + intToNum(a) { return a.toNumber(); }, + } + `); + + generateBase(context, out); + + context.file("native.react-native.d.mts", eslint)("export * from './native'"); + context.file("native.react-native.d.cts", eslint)("import * as binding from './native'; export = binding;"); +} diff --git a/packages/realm/bindgen/src/templates/typescript.ts b/packages/realm/bindgen/src/templates/typescript.ts index 6cbadcb8f69..0bd78ecea88 100644 --- a/packages/realm/bindgen/src/templates/typescript.ts +++ b/packages/realm/bindgen/src/templates/typescript.ts @@ -174,14 +174,11 @@ export function generate({ rawSpec, spec: boundSpec, file }: TemplateContext): v } `); - const out = file("native.d.mts", eslint); + const out = file("native.d.ts", eslint); out("// This file is generated: Update the spec instead of editing this file directly"); - - out("declare module 'realm/binding' {"); - out('import { ObjectId, UUID, Decimal128 } from "bson";'); - out("import { Float, Status, ", spec.enums.map((e) => e.name).join(", "), '} from "realm/binding/core";'); - out('export * from "realm/binding/core";'); + out("import { Float, Status, ", spec.enums.map((e) => e.name).join(", "), '} from "../dist/core";'); + out('export * from "../dist/core";'); out("// Utilities"); out("export type AppError = Error & {code: number};"); @@ -290,6 +287,4 @@ export function generate({ rawSpec, spec: boundSpec, file }: TemplateContext): v } out(`}`); } - - out("} // end of module declaration"); } diff --git a/packages/realm/types.d.cts b/packages/realm/binding/index.d.ts similarity index 82% rename from packages/realm/types.d.cts rename to packages/realm/binding/index.d.ts index 388b6d93ba8..a2882a4b24d 100644 --- a/packages/realm/types.d.cts +++ b/packages/realm/binding/index.d.ts @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////// // -// Copyright 2023 Realm Inc. +// Copyright 2024 Realm Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ // limitations under the License. // //////////////////////////////////////////////////////////////////////////// +import * as binding from "./generated/native"; +export { binding }; -import { Realm } from "./dist/bundle"; -export = Realm; +export function inject(value: typeof binding): void; diff --git a/packages/realm/binding/index.js b/packages/realm/binding/index.js new file mode 100644 index 00000000000..c33718f1394 --- /dev/null +++ b/packages/realm/binding/index.js @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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. +// +//////////////////////////////////////////////////////////////////////////// + +/* eslint-env commonjs */ + +let injected = null; + +module.exports.binding = new Proxy( + {}, + { + get(_, prop, receiver) { + if (injected) { + return Reflect.get(injected, prop, receiver); + } else { + throw new Error(`Getting '${prop.toString()}' from binding before it was injected`); + } + }, + set(_, prop, value) { + if (injected) { + return Reflect.set(injected, prop, value, injected); + } else { + throw new Error(`Setting '${prop.toString()}' on binding before it was injected`); + } + }, + }, +); + +exports.inject = (value) => { + injected = value; +}; diff --git a/packages/realm/index.react-native.js b/packages/realm/index.react-native.js index 2a1b1b35d81..05208820113 100644 --- a/packages/realm/index.react-native.js +++ b/packages/realm/index.react-native.js @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////// // -// Copyright 2023 Realm Inc. +// Copyright 2024 Realm Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,14 @@ // //////////////////////////////////////////////////////////////////////////// -/* eslint-disable @typescript-eslint/no-var-requires -- We're exporting using CJS assignment */ /* eslint-env commonjs */ +/* global process */ -module.exports = require("./dist/bundle.react-native").Realm; +// Runtime check to provide our Node.js entrypoint instead of requiring end-users to apply a mock +if (typeof process !== "undefined" && typeof process.env?.JEST_WORKER_ID !== "undefined") { + // Re-naming "require" to obfuscate the call from Metro + const nodeRequire = require; + module.exports = nodeRequire("./dist/platform/node/index.js"); +} else { + module.exports = require("./dist/platform/react-native/index.js"); +} diff --git a/packages/realm/package.json b/packages/realm/package.json index 581bc731ef6..e95693d3357 100644 --- a/packages/realm/package.json +++ b/packages/realm/package.json @@ -33,23 +33,30 @@ "config": { "anonymizedBundleId": "tkgif/+3l1e9wStGJp2TOngAK3UcQ2u7OM8ZYJU5JYo=" }, - "types": "./types.d.cts", - "main": "./index.node.js", + "types": "./dist/public-types/index.d.ts", + "main": "./dist/platform/node/index.js", "react-native": "./index.react-native.js", "exports": { ".": { - "types": "./types.d.cts", - "node": "./index.node.js", - "require": "./index.node.js", + "types": "./dist/public-types/index.d.ts", + "node": "./dist/platform/node/index.js", "react-native": "./index.react-native.js" }, "./scripts/submit-analytics": "./scripts/submit-analytics.mjs", "./react-native.config.js": "./react-native.config.js", "./package.json": "./package.json" }, + "imports": { + "#realm.node": "./binding/build/realm.node" + }, "files": [ "dependencies.list", "dist", + "binding/dist", + "binding/generated/*.cjs", + "binding/generated/*.d.cts", + "binding/generated/*.d.ts", + "public-types", "index.node.js", "index.react-native.js", "types.d.cts", @@ -67,14 +74,7 @@ "test": "wireit", "test:types": "tsc --project type-tests/tsconfig.json", "lint": "eslint --ext .js,.mjs,.ts .", - "build": "echo 'Run bundle, build:node, build:ios or build:android or other scripts depending on these instead' && exit 1", - "bundle": "wireit", - "bundle:coverage": "ENABLE_TEST_COVERAGE_INSTRUMENTATION=true npm run bundle", - "bindgen:configure": "wireit", - "bindgen:build:node": "wireit", - "bindgen:generate:typescript": "wireit", - "bindgen:generate:wrappers": "wireit", - "bindgen:generate:spec-schema": "wireit", + "build:ts": "wireit", "build:node": "wireit", "build:node:prebuild": "wireit", "build:node:prebuild:arm": "wireit", @@ -86,6 +86,7 @@ "build:ios:debug:simulator": "wireit", "build:ios:debug:ios": "wireit", "build:ios:debug:catalyst": "wireit", + "check-types": "wireit", "install": "prebuild-install --runtime napi || echo 'Failed to download prebuild for Realm'", "docs": "wireit", "postinstall": "node ./scripts/submit-analytics.mjs" @@ -94,32 +95,38 @@ "test": { "command": "mocha --exit", "dependencies": [ + "../fetch:build", "build:node", + "bindgen:build:typescript", + "bindgen:generate:node-wrapper", + "bindgen:generate:react-native-wrapper", + "bindgen:transpile" + ], + "env": { + "TSX_TSCONFIG_PATH": "tsconfig.tests.json" + } + }, + "build:ts": { + "command": "tsc --build", + "dependencies": [ + "../fetch:build", "bindgen:generate:typescript", - "bindgen:generate:wrappers", - "../fetch:build" + "bindgen:generate:node-wrapper", + "bindgen:generate:react-native-wrapper", + "bindgen:transpile" ] }, - "bundle": { - "command": "rollup --config", - "env": { - "ENABLE_TEST_COVERAGE_INSTRUMENTATION": { - "external": true - } - }, + "bindgen:transpile": { + "command": "babel binding/generated --out-dir binding/generated --extensions .mjs --out-file-extension .cjs --plugins @babel/plugin-transform-modules-commonjs", "dependencies": [ - "bindgen:generate:typescript", - "bindgen:generate:wrappers", - "../fetch:build" + "bindgen:generate:node-wrapper", + "bindgen:generate:react-native-wrapper" ], "files": [ - "rollup.config.mjs", - "src/**/*.ts", - "tsconfig.json", - "src/**/tsconfig.json" + "binding/generated/*.mjs" ], "output": [ - "dist" + "binding/generated/*.cjs" ] }, "bindgen:configure": { @@ -131,8 +138,21 @@ "bindgen:configure" ] }, + "bindgen:build:typescript": { + "command": "tsc --project tsconfig.binding.json", + "dependencies": [ + "bindgen:generate:typescript" + ], + "files": [ + "binding/generated/core.ts" + ], + "output": [ + "binding/dist/core.js", + "binding/dist/core.d.ts" + ] + }, "bindgen:generate:typescript": { - "command": "realm-bindgen --template bindgen/src/templates/typescript.ts --spec bindgen/vendor/realm-core/bindgen/spec.yml --spec bindgen/js_spec.yml --opt-in bindgen/js_opt_in_spec.yml --output ./generated/ts", + "command": "realm-bindgen --template bindgen/src/templates/typescript.ts --spec bindgen/vendor/realm-core/bindgen/spec.yml --spec bindgen/js_spec.yml --opt-in bindgen/js_opt_in_spec.yml --output binding/generated", "dependencies": [ "bindgen:generate:spec-schema" ], @@ -146,12 +166,12 @@ "bindgen/src/templates/typescript.ts" ], "output": [ - "generated/ts/core.ts", - "generated/ts/native.d.mts" + "binding/generated/core.ts", + "binding/generated/native.d.ts" ] }, - "bindgen:generate:wrappers": { - "command": "realm-bindgen --template bindgen/src/templates/node-wrapper.ts --spec bindgen/vendor/realm-core/bindgen/spec.yml --spec bindgen/js_spec.yml --opt-in bindgen/js_opt_in_spec.yml --output ./generated/ts", + "bindgen:generate:node-wrapper": { + "command": "realm-bindgen --template bindgen/src/templates/node-wrapper.ts --spec bindgen/vendor/realm-core/bindgen/spec.yml --spec bindgen/js_spec.yml --opt-in bindgen/js_opt_in_spec.yml --output binding/generated", "dependencies": [ "bindgen:generate:spec-schema" ], @@ -162,11 +182,34 @@ "bindgen/js_opt_in_spec.yml", "bindgen/src", "!bindgen/src/templates", + "bindgen/src/templates/base-wrapper.ts", "bindgen/src/templates/node-wrapper.ts" ], "output": [ - "generated/ts/native-node.mjs", - "generated/ts/native-react-native.mjs" + "binding/generated/native.node.mjs", + "binding/generated/native.node.d.mts", + "binding/generated/native.node.d.cts" + ] + }, + "bindgen:generate:react-native-wrapper": { + "command": "realm-bindgen --template bindgen/src/templates/react-native-wrapper.ts --spec bindgen/vendor/realm-core/bindgen/spec.yml --spec bindgen/js_spec.yml --opt-in bindgen/js_opt_in_spec.yml --output binding/generated", + "dependencies": [ + "bindgen:generate:spec-schema" + ], + "files": [ + "bindgen/vendor/realm-core/bindgen/spec.yml", + "bindgen/vendor/realm-core/bindgen/src", + "bindgen/js_spec.yml", + "bindgen/js_opt_in_spec.yml", + "bindgen/src", + "!bindgen/src/templates", + "bindgen/src/templates/base-wrapper.ts", + "bindgen/src/templates/react-native-wrapper.ts" + ], + "output": [ + "binding/generated/native.react-native.mjs", + "binding/generated/native.react-native.d.mts", + "binding/generated/native.react-native.d.cts" ] }, "bindgen:generate:spec-schema": { @@ -268,10 +311,16 @@ "CONFIGURATION": "Debug" } }, + "check-types": { + "command": "tsc --project tsconfig.public-types-check.json", + "dependencies": [ + "build:ts" + ] + }, "docs": { "command": "typedoc", "dependencies": [ - "bundle" + "build:ts" ] } }, @@ -290,6 +339,9 @@ } }, "devDependencies": { + "@babel/cli": "^7.23.9", + "@babel/core": "^7.23.9", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", "@realm/bindgen": "^0.1.0", "@realm/fetch": "^0.1.0", "@types/chai": "^4.3.3", @@ -316,7 +368,7 @@ }, "binary": { "module_name": "realm", - "module_path": "generated/ts", + "module_path": "binding/build", "host": "https://static.realm.io", "remote_path": "realm-js-prebuilds/{version}", "napi_versions": [ diff --git a/packages/realm/rollup.config.mjs b/packages/realm/rollup.config.mjs deleted file mode 100644 index 8085daa3bfe..00000000000 --- a/packages/realm/rollup.config.mjs +++ /dev/null @@ -1,122 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2022 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. -// -//////////////////////////////////////////////////////////////////////////// - -/* eslint-env node */ - -import { nodeResolve } from "@rollup/plugin-node-resolve"; -import commonjs from "@rollup/plugin-commonjs"; -import json from "@rollup/plugin-json"; -import typescript from "@rollup/plugin-typescript"; -import replace from "@rollup/plugin-replace"; -import dts from "rollup-plugin-dts"; -import istanbul from "rollup-plugin-istanbul"; - -import pkg from "./package.json" assert { type: "json" }; - -const mainExport = pkg.exports["."]; -// Default is '{,**/}*.(cts|mts|ts|tsx)', we add js, mjs and json to include "realm/binding" in the binding -// This is actually a workaround for https://github.com/rollup/plugins/issues/1663 -const typescriptInclude = "{,**/}*.(cts|mts|ts|tsx|js|mjs|json)"; - -const { ENABLE_TEST_COVERAGE_INSTRUMENTATION } = process.env; -if (ENABLE_TEST_COVERAGE_INSTRUMENTATION) { - // eslint-disable-next-line no-console - console.warn(`\n\n!!! WARNING: Instrumenting ${mainExport.node} for test coverage !!!\n`); -} - -export default [ - { - input: "src/platform/node/index.ts", - output: [ - { - file: "./dist/bundle.node.js", - format: "cjs", - sourcemap: true, - }, - ], - plugins: [ - ENABLE_TEST_COVERAGE_INSTRUMENTATION === "true" - ? istanbul({ - include: ["src/**"], - }) - : undefined, - nodeResolve({ - modulesOnly: true, - preferBuiltins: true, - exportConditions: ["node", "module", "main"], - }), - replace({ - preventAssignment: true, - delimiters: ["", ""], - values: { - '"./realm.node"': '"../generated/ts/realm.node"', - }, - }), - json(), - typescript({ - tsconfig: "src/platform/node/tsconfig.json", - noEmitOnError: true, - outputToFilesystem: true, - include: typescriptInclude, - }), - ], - external: ["bson", "debug", "node:module", "node:fs", "node:path"], - }, - { - input: "src/platform/react-native/index.ts", - output: { - file: "./dist/bundle.react-native.js", - format: "cjs", - sourcemap: true, - }, - plugins: [ - nodeResolve({ - mainFields: ["react-native", "browser", "module", "main"], - exportConditions: ["react-native", "browser", "module", "main"], - resolveOnly: ["@realm/fetch", "path-browserify"], - }), - // We need to use `commonjs` because of "path-browserify" - commonjs(), - json(), - typescript({ - tsconfig: "src/platform/react-native/tsconfig.json", - noEmitOnError: true, - outputToFilesystem: true, - include: typescriptInclude, - }), - ], - external: ["bson", "debug", "react-native"], - }, - { - input: "src/index.ts", - output: { - file: "dist/bundle.d.ts", - format: "es", - }, - plugins: [ - dts({ - respectExternal: true, - compilerOptions: { - stripInternal: true, - noResolve: false, - }, - }), - ], - external: ["bson"], - }, -]; diff --git a/packages/realm/src/ClassHelpers.ts b/packages/realm/src/ClassHelpers.ts index ea1fb180329..3b0880feb2e 100644 --- a/packages/realm/src/ClassHelpers.ts +++ b/packages/realm/src/ClassHelpers.ts @@ -37,6 +37,7 @@ export type ClassHelpers = { canonicalObjectSchema: CanonicalObjectSchema; }; +/** @internal */ export function setClassHelpers(constructor: RealmObjectConstructor, value: ClassHelpers): void { // Store the properties map on the object class Object.defineProperty(constructor, INTERNAL_HELPERS, { @@ -52,6 +53,7 @@ export function setClassHelpers(constructor: RealmObjectConstructor, value: Clas * NOTE: This is a free function instead of a member of RealmObject to limit conflicts with user defined properties. * @param arg The object or constructor to get a helpers for. * @returns Helpers injected onto the class by the `ClassMap`. + * @internal */ export function getClassHelpers(arg: typeof RealmObject): ClassHelpers { const helpers = arg[INTERNAL_HELPERS]; diff --git a/packages/realm/src/Listeners.ts b/packages/realm/src/Listeners.ts index e1b0330f3b4..976e83a6c21 100644 --- a/packages/realm/src/Listeners.ts +++ b/packages/realm/src/Listeners.ts @@ -24,6 +24,7 @@ export type CallbackAdder /** @internal */ export type CallbackRemover = (token: TokenType) => void; +/** @internal */ export type ListenersOptions = { add: CallbackAdder; remove: CallbackRemover; diff --git a/packages/realm/src/PropertyHelpers.ts b/packages/realm/src/PropertyHelpers.ts index 8258cf14bfd..2074910af67 100644 --- a/packages/realm/src/PropertyHelpers.ts +++ b/packages/realm/src/PropertyHelpers.ts @@ -45,6 +45,7 @@ function getAny(results: binding.Results, index: number) { return results.getAny(index); } +/** @internal */ export type HelperOptions = { realm: Realm; getClassHelpers: (name: string) => ClassHelpers; @@ -64,6 +65,7 @@ type PropertyAccessors = { collectionHelpers?: OrderedCollectionHelpers; }; +/** @internal */ export type PropertyHelpers = TypeHelpers & PropertyAccessors & { type: binding.PropertyType; @@ -336,6 +338,7 @@ function getPropertyHelpers(type: binding.PropertyType, options: PropertyOptions } } +/** @internal */ export function createPropertyHelpers(property: PropertyContext, options: HelperOptions): PropertyHelpers { const collectionType = property.type & binding.PropertyType.Collection; const typeOptions: TypeOptions = { diff --git a/packages/realm/src/Realm.ts b/packages/realm/src/Realm.ts index 347d517529a..59df4f406c3 100644 --- a/packages/realm/src/Realm.ts +++ b/packages/realm/src/Realm.ts @@ -17,165 +17,35 @@ //////////////////////////////////////////////////////////////////////////// import { - AggregatePipelineStage, AnyList, AnyRealmObject, AnyResults, - ApiKey, - ApiKeyAuth, - App, - AppChangeCallback, - AppConfiguration, - AppServicesFunction, - BSON, - BaseChangeEvent, - BaseConfiguration, - BaseObjectSchema, - BaseSubscriptionSet, - BaseSyncConfiguration, - CanonicalGeoPoint, - CanonicalGeoPolygon, CanonicalObjectSchema, - CanonicalObjectSchemaProperty, - CanonicalPropertiesTypes, - CanonicalPropertySchema, - ChangeEvent, - ChangeEventId, ClassHelpers, ClassMap, - ClientResetAfterCallback, - ClientResetBeforeCallback, - ClientResetConfig, - ClientResetDiscardUnsyncedChangesConfiguration, - ClientResetFallbackCallback, - ClientResetManualConfiguration, - ClientResetMode, - ClientResetRecoverOrDiscardUnsyncedChangesConfiguration, - ClientResetRecoverUnsyncedChangesConfiguration, - Collection, - CollectionChangeCallback, - CollectionChangeSet, - CollectionPropertyTypeName, - CompensatingWriteError, - CompensatingWriteInfo, Configuration, - ConfigurationWithSync, - ConfigurationWithoutSync, - ConnectionNotificationCallback, - ConnectionState, Constructor, - CountOptions, - Credentials, - DefaultFunctionsFactory, DefaultObject, - DefaultUserProfileData, - DeleteEvent, - DeleteResult, - Dictionary, - DictionaryChangeCallback, - DictionaryChangeSet, - Document, - DocumentKey, - DocumentNamespace, - DropDatabaseEvent, - DropEvent, - EmailPasswordAuth, - ErrorCallback, - Filter, - FindOneAndModifyOptions, - FindOneOptions, - FindOptions, - FlexibleSyncConfiguration, - GeoBox, - GeoCircle, - GeoPoint, - GeoPolygon, - GeoPosition, INTERNAL, - IndexDecorator, InitialSubscriptions, - InsertEvent, - InsertManyResult, - InsertOneResult, - InvalidateEvent, List, - LocalAppConfiguration, LogLevel, LoggerCallback, - MapToDecorator, - Metadata, - MetadataMode, MigrationCallback, - MongoDB, - MongoDBCollection, - MongoDBDatabase, - MutableSubscriptionSet, - NewDocument, - NumericLogLevel, - ObjectChangeCallback, - ObjectChangeSet, ObjectSchema, - ObjectSchemaProperty, - OpenRealmBehaviorConfiguration, - OpenRealmBehaviorType, - OpenRealmTimeOutBehavior, - OperationType, - OrderedCollection, - PartitionSyncConfiguration, - PartitionValue, - PrimaryKey, - PrimitivePropertyTypeName, - ProgressDirection, - ProgressMode, - ProgressNotificationCallback, ProgressRealmPromise, - PropertiesTypes, - PropertySchema, - PropertySchemaParseError, - PropertySchemaShorthand, - PropertySchemaStrict, - PropertyTypeName, - ProviderType, - ProxyType, - PushClient, REALM, RealmEvent, RealmListenerCallback, RealmListeners, RealmObject, RealmObjectConstructor, - RealmSet, - RelationshipPropertyTypeName, - RenameEvent, - ReplaceEvent, Results, - SSLConfiguration, - SSLVerifyCallback, - SSLVerifyObject, - SchemaParseError, - SessionState, - SessionStopPolicy, - SortDescriptor, - Subscription, - SubscriptionOptions, SubscriptionSet, - SubscriptionSetState, - SyncConfiguration, - SyncError, SyncSession, TypeAssertionError, - Types, Unmanaged, - Update, - UpdateDescription, - UpdateEvent, UpdateMode, - UpdateOptions, - UpdateResult, - User, - UserChangeCallback, - UserState, - WaitForSync, assert, binding, defaultLogger, @@ -185,13 +55,8 @@ import { fromBindingLoggerLevelToLogLevel, fromBindingRealmSchema, fs, - index, - kmToRadians, - mapTo, - miToRadians, normalizeObjectSchema, normalizeRealmSchema, - safeGlobalThis, toArrayBuffer, toBindingLoggerLevel, toBindingSchema, @@ -237,46 +102,6 @@ type InternalConfig = { * The Realm database. */ export class Realm { - public static App = App; - public static Auth = { EmailPasswordAuth, ApiKeyAuth }; - public static BSON = BSON; - public static ClientResetMode = ClientResetMode; - public static Collection = Collection; - public static CompensatingWriteError = CompensatingWriteError; - public static ConnectionState = ConnectionState; - public static Credentials = Credentials; - public static Dictionary = Dictionary; - public static flags = flags; - public static index = index; - public static List = List; - public static mapTo = mapTo; - public static MetadataMode = MetadataMode; - public static NumericLogLevel = NumericLogLevel; - public static Object = RealmObject; - public static OpenRealmBehaviorType = OpenRealmBehaviorType; - public static OpenRealmTimeOutBehavior = OpenRealmTimeOutBehavior; - public static OrderedCollection = OrderedCollection; - public static ProgressDirection = ProgressDirection; - public static ProgressMode = ProgressMode; - public static PropertySchemaParseError = PropertySchemaParseError; - public static ProviderType = ProviderType; - public static ProxyType = ProxyType; - public static Results = Results; - public static SchemaParseError = SchemaParseError; - public static SessionState = SessionState; - public static SessionStopPolicy = SessionStopPolicy; - public static Set = RealmSet; - public static SubscriptionSetState = SubscriptionSetState; - public static SyncError = SyncError; - public static Types = Types; - public static UpdateMode = UpdateMode; - public static User = User; - public static UserState = UserState; - public static WaitForSync = WaitForSync; - - public static kmToRadians = kmToRadians; - public static miToRadians = miToRadians; - public static defaultPath = Realm.normalizePath("default.realm"); private static internals = new Set>(); @@ -1316,582 +1141,136 @@ function isEmbedded(objectSchema: binding.ObjectSchema): boolean { // This declaration needs to happen in the same file which declares "Realm" // @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-namespaces-with-classes-functions-and-enums -// We need these type aliases because of https://github.com/Swatinem/rollup-plugin-dts/issues/223 -// We cannot move this to a different file and rely on module declarations because of https://github.com/Swatinem/rollup-plugin-dts/issues/168 - -type AppType< - FunctionsFactoryType extends DefaultFunctionsFactory = DefaultFunctionsFactory, - CustomDataType extends DefaultObject = DefaultObject, -> = App; -type BSONType = typeof BSON; -type ClientResetModeType = ClientResetMode; -type CollectionType< - KeyType = unknown, - ValueType = unknown, - EntryType = [KeyType, ValueType], - T = ValueType, - ChangeCallbackType = unknown, -> = Collection; -type CompensatingWriteErrorType = CompensatingWriteError; -type ConnectionStateType = ConnectionState; -type CredentialsType = Credentials; -type DictionaryType = Dictionary; -type IndexDecoratorType = IndexDecorator; -type ListType = List; -type MapToDecoratorType = MapToDecorator; -type MetadataModeType = MetadataMode; -type MetadataType = Metadata; -type Mixed = unknown; -type ObjectType = string | RealmObjectConstructor; -type OpenRealmBehaviorTypeType = OpenRealmBehaviorType; -type OpenRealmTimeOutBehaviorType = OpenRealmTimeOutBehavior; -type ProgressDirectionType = ProgressDirection; -type ProgressModeType = ProgressMode; -type PropertySchemaParseErrorType = PropertySchemaParseError; -type ProviderTypeType = ProviderType; -type ProxyTypeType = ProxyType; -type ResultsType = Results; -type SchemaParseErrorType = SchemaParseError; -type SessionStateType = SessionState; -type SessionStopPolicyType = SessionStopPolicy; -type SetType = RealmSet; -type SSLConfigurationType = SSLConfiguration; -type SSLVerifyCallbackType = SSLVerifyCallback; -type SSLVerifyObjectType = SSLVerifyObject; -type SyncErrorType = SyncError; -type SyncSessionType = SyncSession; -type TypesType = typeof Types; -type UpdateModeType = UpdateMode; -type UserStateType = UserState; -type UserType< - UserFunctionsType extends DefaultFunctionsFactory = DefaultFunctionsFactory, - UserCustomDataType extends DefaultObject = DefaultObject, - UserProfileDataType extends DefaultUserProfileData = DefaultUserProfileData, -> = User; - -type BaseSubscriptionSetType = BaseSubscriptionSet; -type LogLevelType = LogLevel; -type NumericLogLevelType = NumericLogLevel; -type MutableSubscriptionSetType = MutableSubscriptionSet; -type PartitionValueType = PartitionValue; -type SubscriptionOptionsType = SubscriptionOptions; -type SubscriptionSetType = SubscriptionSet; -type SubscriptionSetStateType = SubscriptionSetState; -type SubscriptionType = Subscription; - -type ObjectIdType = BSON.ObjectId; -type Decimal128Type = BSON.Decimal128; -type UUIDType = BSON.UUID; - -type ApiKeyType = ApiKey; -type EmailPasswordAuthType = EmailPasswordAuth; -type ApiKeyAuthType = ApiKeyAuth; - -type AggregatePipelineStageType = AggregatePipelineStage; -type BaseChangeEventType = BaseChangeEvent; -type ChangeEventType = ChangeEvent; -type ChangeEventIdType = ChangeEventId; -type CountOptionsType = CountOptions; -type DeleteEventType = DeleteEvent; -type DeleteResultType = DeleteResult; -type DocumentType = Document; -type DocumentKeyType = DocumentKey; -type DocumentNamespaceType = DocumentNamespace; -type DropDatabaseEventType = DropDatabaseEvent; -type DropEventType = DropEvent; -type FilterType = Filter; -type FindOneAndModifyOptionsType = FindOneAndModifyOptions; -type FindOneOptionsType = FindOneOptions; -type FindOptionsType = FindOptions; -type InsertEventType = InsertEvent; -type InsertManyResultType = InsertManyResult; -type InsertOneResultType = InsertOneResult; -type InvalidateEventType = InvalidateEvent; -type MongoDBType = MongoDB; -type MongoDBCollectionType = MongoDBCollection; -type MongoDBDatabaseType = MongoDBDatabase; -type NewDocumentType = NewDocument; -type OperationTypeType = OperationType; -type OrderedCollectionType = OrderedCollection; -type RenameEventType = RenameEvent; -type ReplaceEventType = ReplaceEvent; -type UpdateType = Update; -type UpdateDescriptionType = UpdateDescription; -type UpdateEventType = UpdateEvent; -type UpdateOptionsType = UpdateOptions; -type UpdateResultType = UpdateResult; -type WaitForSyncType = WaitForSync; - -type GlobalDate = Date; - -// IMPORTANT: This needs to match the namespace below! -// eslint-disable-next-line @typescript-eslint/no-namespace -export declare namespace Realm { - // TODO: Decide if we want to deprecate this as well - export type Object = RealmObject; - export { - // Pure type exports below - AppType as App, - AppChangeCallback, - AppConfiguration, - AppServicesFunction, - /** @deprecated Will be removed in v13.0.0. Please use {@link AppServicesFunction} */ - AppServicesFunction as RealmFunction, - BaseConfiguration, - BaseObjectSchema, - BaseSyncConfiguration, - BSONType as BSON, - CanonicalObjectSchema, - /** @deprecated Will be removed in v13.0.0. Please use {@link CanonicalPropertySchema} */ - CanonicalObjectSchemaProperty, - CanonicalPropertySchema, - CanonicalPropertiesTypes, - ClientResetModeType as ClientResetMode, - ClientResetFallbackCallback, - ClientResetBeforeCallback, - ClientResetAfterCallback, - ClientResetManualConfiguration, - ClientResetDiscardUnsyncedChangesConfiguration, - ClientResetRecoverUnsyncedChangesConfiguration, - /** @deprecated Will be removed in v13.0.0. Please use {@link ClientResetRecoverUnsyncedChangesConfiguration} */ - ClientResetRecoverUnsyncedChangesConfiguration as ClientResetRecoveryConfiguration, - ClientResetRecoverOrDiscardUnsyncedChangesConfiguration, - ClientResetConfig, - CollectionChangeCallback, - CollectionChangeSet, - CollectionPropertyTypeName, - CollectionType as Collection, - CompensatingWriteErrorType as CompensatingWriteError, - CompensatingWriteInfo, - ConfigurationWithoutSync, - ConfigurationWithSync, - Configuration, - ConnectionNotificationCallback, - ConnectionStateType as ConnectionState, - CredentialsType as Credentials, - DefaultFunctionsFactory, - DefaultUserProfileData, - DictionaryType as Dictionary, - DictionaryChangeCallback, - DictionaryChangeSet, - ErrorCallback, - FlexibleSyncConfiguration, - IndexDecoratorType as IndexDecorator, - ListType as List, - LocalAppConfiguration, - MapToDecoratorType as MapToDecorator, - MetadataModeType as MetadataMode, - MetadataType as Metadata, - MigrationCallback, - Mixed, - NumericLogLevelType as NumericLogLevel, - ObjectChangeCallback, - ObjectChangeSet, - ObjectSchema, - /** @deprecated Will be removed in v13.0.0. Please use {@link PropertySchema} */ - ObjectSchemaProperty, - ObjectType, - OpenRealmBehaviorConfiguration, - OpenRealmBehaviorTypeType as OpenRealmBehaviorType, - OpenRealmTimeOutBehaviorType as OpenRealmTimeOutBehavior, - OrderedCollectionType as OrderedCollection, - PartitionSyncConfiguration, - PrimaryKey, - PrimitivePropertyTypeName, - ProgressDirectionType as ProgressDirection, - ProgressModeType as ProgressMode, - ProgressNotificationCallback, - PropertiesTypes, - PropertySchema, - PropertySchemaParseErrorType as PropertySchemaParseError, - PropertySchemaShorthand, - PropertySchemaStrict, - PropertyTypeName, - ProviderTypeType as ProviderType, - ProxyTypeType as ProxyType, - RealmEventName, - RealmObjectConstructor, - /** @deprecated Will be removed in v13.0.0. Please use {@link RealmObjectConstructor} */ - RealmObjectConstructor as ObjectClass, - RelationshipPropertyTypeName, - ResultsType as Results, - SchemaParseErrorType as SchemaParseError, - SessionStateType as SessionState, - SessionStopPolicyType as SessionStopPolicy, - SetType as Set, - SortDescriptor, - SSLConfigurationType as SSLConfiguration, - SSLVerifyCallbackType as SSLVerifyCallback, - SSLVerifyObjectType as SSLVerifyObject, - SubscriptionSetStateType as SubscriptionSetState, - SyncConfiguration, - SyncErrorType as SyncError, - TypesType as Types, - UpdateModeType as UpdateMode, - UserChangeCallback, - UserStateType as UserState, - UserType as User, - WaitForSyncType as WaitForSync, - GeoBox, - GeoCircle, - GeoPoint, - GeoPolygon, - CanonicalGeoPolygon, - CanonicalGeoPoint, - GeoPosition, - }; - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace App { - export type Credentials = CredentialsType; - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Sync { - export type BaseSubscriptionSet = BaseSubscriptionSetType; - export type LogLevel = LogLevelType; - export type NumericLogLevel = NumericLogLevelType; - export type MutableSubscriptionSet = MutableSubscriptionSetType; - export type PartitionValue = PartitionValueType; - export type SubscriptionOptions = SubscriptionOptionsType; - export type SubscriptionSet = SubscriptionSetType; - export type SubscriptionSetState = SubscriptionSetStateType; - /** @deprecated Please use {@link SubscriptionSetState} */ - export type SubscriptionsState = SubscriptionSetStateType; - export type Subscription = SubscriptionType; - export type SyncSession = SyncSessionType; - /** - * @deprecated Got renamed to {@SyncSession} and please use named imports - */ - export type Session = SyncSessionType; - } - } - - /** - * Re-export of a subset of the "bson" package, enabling access to the BSON types without requiring an explicit dependency on the "bson" package. - * @see {@link https://www.npmjs.com/package/bson#documentation|the BSON documentation} for more information. - */ - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace BSON { - export type ObjectId = ObjectIdType; - export type Decimal128 = Decimal128Type; - export type UUID = UUIDType; - } - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Auth { - export type EmailPasswordAuth = EmailPasswordAuthType; - export type ApiKey = ApiKeyType; - export type ApiKeyAuth = ApiKeyAuthType; - } - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Services { - export type MongoDB = MongoDBType; - export type MongoDBDatabase = MongoDBDatabaseType; - /** @deprecated Please read {@link https://www.mongodb.com/docs/atlas/app-services/reference/push-notifications/} */ - export type Push = PushClient; - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace MongoDB { - export type AggregatePipelineStage = AggregatePipelineStageType; - export type BaseChangeEvent = BaseChangeEventType; - export type ChangeEvent = ChangeEventType; - export type ChangeEventId = ChangeEventIdType; - export type CountOptions = CountOptionsType; - export type DeleteEvent = DeleteEventType; - export type DeleteResult = DeleteResultType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - export type Document = DocumentType; - export type DocumentKey = DocumentKeyType; - export type DocumentNamespace = DocumentNamespaceType; - export type DropDatabaseEvent = DropDatabaseEventType; - export type DropEvent = DropEventType; - export type Filter = FilterType; - export type FindOneAndModifyOptions = FindOneAndModifyOptionsType; - export type FindOneOptions = FindOneOptionsType; - export type FindOptions = FindOptionsType; - export type InsertEvent = InsertEventType; - export type InsertManyResult = InsertManyResultType; - export type InsertOneResult = InsertOneResultType; - export type InvalidateEvent = InvalidateEventType; - export type MongoDBCollection = MongoDBCollectionType; - export type NewDocument = NewDocumentType; - export type OperationType = OperationTypeType; - export type RenameEvent = RenameEventType; - export type ReplaceEvent = ReplaceEventType; - export type Update = UpdateType; - export type UpdateDescription = UpdateDescriptionType; - export type UpdateEvent = UpdateEventType; - export type UpdateOptions = UpdateOptionsType; - export type UpdateResult = UpdateResultType; - } - } - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Types { - export type Bool = boolean; - export type String = string; - export type Int = number; - export type Float = number; - export type Double = number; - export type Decimal128 = Realm.BSON.Decimal128; - export type ObjectId = Realm.BSON.ObjectId; - export type UUID = Realm.BSON.UUID; - export type Date = GlobalDate; - export type Data = ArrayBuffer; - export type List = Realm.List; - export type Set = Realm.Set; - export type Dictionary = Realm.Dictionary; - export type Mixed = unknown; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - export type LinkingObjects = Realm.Results; - } -} - -// Exporting a deprecated global for backwards compatibility -const RealmConstructor = Realm; -declare global { - /** @deprecated Will be removed in v13.0.0. Please use an import statement. */ - export class Realm extends RealmConstructor {} - // IMPORTANT: This needs to match the namespace above! - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Realm { - // TODO: Decide if we want to deprecate this as well - export type Object = RealmObject; - export { - // Pure type exports below - AppType as App, - AppChangeCallback, - AppConfiguration, - AppServicesFunction, - /** @deprecated Will be removed in v13.0.0. Please use {@link AppServicesFunction} */ - AppServicesFunction as RealmFunction, - BaseConfiguration, - BaseObjectSchema, - BaseSyncConfiguration, - BSONType as BSON, - CanonicalObjectSchema, - /** @deprecated Will be removed in v13.0.0. Please use {@link CanonicalPropertySchema} */ - CanonicalObjectSchemaProperty, - CanonicalPropertySchema, - CanonicalPropertiesTypes, - ClientResetModeType as ClientResetMode, - ClientResetFallbackCallback, - ClientResetBeforeCallback, - ClientResetAfterCallback, - ClientResetManualConfiguration, - ClientResetDiscardUnsyncedChangesConfiguration, - ClientResetRecoverUnsyncedChangesConfiguration, - /** @deprecated Will be removed in v13.0.0. Please use {@link ClientResetRecoverUnsyncedChangesConfiguration} */ - ClientResetRecoverUnsyncedChangesConfiguration as ClientResetRecoveryConfiguration, - ClientResetRecoverOrDiscardUnsyncedChangesConfiguration, - ClientResetConfig, - CollectionChangeCallback, - CollectionChangeSet, - CollectionPropertyTypeName, - CollectionType as Collection, - CompensatingWriteErrorType as CompensatingWriteError, - CompensatingWriteInfo, - ConfigurationWithoutSync, - ConfigurationWithSync, - Configuration, - ConnectionNotificationCallback, - ConnectionStateType as ConnectionState, - CredentialsType as Credentials, - DefaultFunctionsFactory, - DefaultUserProfileData, - DictionaryType as Dictionary, - DictionaryChangeCallback, - DictionaryChangeSet, - ErrorCallback, - FlexibleSyncConfiguration, - IndexDecoratorType as IndexDecorator, - ListType as List, - LocalAppConfiguration, - MapToDecoratorType as MapToDecorator, - MetadataModeType as MetadataMode, - Metadata, - MigrationCallback, - Mixed, - NumericLogLevelType as NumericLogLevel, - ObjectChangeCallback, - ObjectChangeSet, - ObjectSchema, - /** @deprecated Will be removed in v13.0.0. Please use {@link PropertySchema} */ - ObjectSchemaProperty, - ObjectType, - OpenRealmBehaviorConfiguration, - OpenRealmBehaviorTypeType as OpenRealmBehaviorType, - OpenRealmTimeOutBehaviorType as OpenRealmTimeOutBehavior, - PartitionSyncConfiguration, - PrimaryKey, - PrimitivePropertyTypeName, - ProgressDirectionType as ProgressDirection, - ProgressModeType as ProgressMode, - ProgressNotificationCallback, - PropertiesTypes, - PropertySchema, - PropertySchemaParseErrorType as PropertySchemaParseError, - PropertySchemaShorthand, - PropertySchemaStrict, - PropertyTypeName, - ProviderTypeType as ProviderType, - RealmObjectConstructor, - /** @deprecated Will be removed in v13.0.0. Please use {@link RealmObjectConstructor} */ - RealmObjectConstructor as ObjectClass, - RelationshipPropertyTypeName, - ResultsType as Results, - SchemaParseErrorType as SchemaParseError, - SessionStateType as SessionState, - SessionStopPolicyType as SessionStopPolicy, - SetType as Set, - SortDescriptor, - SSLConfigurationType as SSLConfiguration, - SSLVerifyCallbackType as SSLVerifyCallback, - SSLVerifyObjectType as SSLVerifyObject, - SubscriptionSetStateType as SubscriptionSetState, - SyncConfiguration, - SyncErrorType as SyncError, - TypesType as Types, - UpdateModeType as UpdateMode, - UserChangeCallback, - UserStateType as UserState, - GeoBox, - GeoCircle, - GeoPoint, - GeoPolygon, - CanonicalGeoPolygon, - CanonicalGeoPoint, - GeoPosition, - UserType as User, - WaitForSyncType as WaitForSync, - }; - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace App { - export type Credentials = CredentialsType; - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Sync { - export type BaseSubscriptionSet = BaseSubscriptionSetType; - export type LogLevel = LogLevelType; - export type NumericLogLevel = NumericLogLevelType; - export type MutableSubscriptionSet = MutableSubscriptionSetType; - export type PartitionValue = PartitionValueType; - export type SubscriptionOptions = SubscriptionOptionsType; - export type SubscriptionSet = SubscriptionSetType; - export type SubscriptionSetState = SubscriptionSetStateType; - /** @deprecated Please use {@link SubscriptionSetState} */ - export type SubscriptionsState = SubscriptionSetStateType; - export type Subscription = SubscriptionType; - export type SyncSession = SyncSessionType; - /** - * @deprecated Got renamed to {@SyncSession} and please use named imports - */ - export type Session = SyncSessionType; - } - } - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace BSON { - export type ObjectId = ObjectIdType; - export type Decimal128 = Decimal128Type; - export type UUID = UUIDType; - } - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Auth { - export type EmailPasswordAuth = EmailPasswordAuthType; - export type ApiKey = ApiKeyType; - export type ApiKeyAuth = ApiKeyAuthType; - } - - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Services { - export type MongoDB = MongoDBType; - export type MongoDBDatabase = MongoDBDatabaseType; - /** @deprecated Please read {@link https://www.mongodb.com/docs/atlas/app-services/reference/push-notifications/} */ - export type Push = PushClient; - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace MongoDB { - export type AggregatePipelineStage = AggregatePipelineStageType; - export type BaseChangeEvent = BaseChangeEventType; - export type ChangeEvent = ChangeEventType; - export type ChangeEventId = ChangeEventIdType; - export type CountOptions = CountOptionsType; - export type DeleteEvent = DeleteEventType; - export type DeleteResult = DeleteResultType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - export type Document = DocumentType; - export type DocumentKey = DocumentKeyType; - export type DocumentNamespace = DocumentNamespaceType; - export type DropDatabaseEvent = DropDatabaseEventType; - export type DropEvent = DropEventType; - export type Filter = FilterType; - export type FindOneAndModifyOptions = FindOneAndModifyOptionsType; - export type FindOneOptions = FindOneOptionsType; - export type FindOptions = FindOptionsType; - export type InsertEvent = InsertEventType; - export type InsertManyResult = InsertManyResultType; - export type InsertOneResult = InsertOneResultType; - export type InvalidateEvent = InvalidateEventType; - export type MongoDBCollection = MongoDBCollectionType; - export type NewDocument = NewDocumentType; - export type OperationType = OperationTypeType; - export type RenameEvent = RenameEventType; - export type ReplaceEvent = ReplaceEventType; - export type Update = UpdateType; - export type UpdateDescription = UpdateDescriptionType; - export type UpdateEvent = UpdateEventType; - export type UpdateOptions = UpdateOptionsType; - export type UpdateResult = UpdateResultType; - } - } +import * as internal from "./internal"; +// Needed to avoid complaints about a self-reference +import RealmItself = Realm; - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace Types { - export type Bool = boolean; - export type String = string; - export type Int = number; - export type Float = number; - export type Double = number; - export type Decimal128 = Realm.BSON.Decimal128; - export type ObjectId = Realm.BSON.ObjectId; - export type UUID = Realm.BSON.UUID; - export type Date = GlobalDate; - export type Data = ArrayBuffer; - export type List = Realm.List; - export type Set = Realm.Set; - export type Dictionary = Realm.Dictionary; - export type Mixed = unknown; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - export type LinkingObjects = Realm.Results; - } - } +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace Realm { + export import Realm = RealmItself; + export import flags = internal.flags; + + export import Object = internal.RealmObject; + export import App = internal.App; + export import Auth = internal.Auth; + export import BSON = internal.BSON; + export import Types = internal.Types; + export import Services = internal.Services; + + export import index = internal.index; + export import mapTo = internal.mapTo; + export import kmToRadians = internal.kmToRadians; + export import miToRadians = internal.miToRadians; + + export import AppChangeCallback = internal.AppChangeCallback; + export import AppConfiguration = internal.AppConfiguration; + export import AppServicesFunction = internal.AppServicesFunction; + export import BaseConfiguration = internal.BaseConfiguration; + export import BaseObjectSchema = internal.BaseObjectSchema; + export import BaseSyncConfiguration = internal.BaseSyncConfiguration; + export import CanonicalObjectSchema = internal.CanonicalObjectSchema; + export import CanonicalPropertySchema = internal.CanonicalPropertySchema; + export import CanonicalPropertiesTypes = internal.CanonicalPropertiesTypes; + export import ClientResetMode = internal.ClientResetMode; + export import ClientResetFallbackCallback = internal.ClientResetFallbackCallback; + export import ClientResetBeforeCallback = internal.ClientResetBeforeCallback; + export import ClientResetAfterCallback = internal.ClientResetAfterCallback; + export import ClientResetManualConfiguration = internal.ClientResetManualConfiguration; + export import ClientResetDiscardUnsyncedChangesConfiguration = internal.ClientResetDiscardUnsyncedChangesConfiguration; + export import ClientResetRecoverUnsyncedChangesConfiguration = internal.ClientResetRecoverUnsyncedChangesConfiguration; + export import ClientResetRecoverOrDiscardUnsyncedChangesConfiguration = internal.ClientResetRecoverOrDiscardUnsyncedChangesConfiguration; + export import ClientResetConfig = internal.ClientResetConfig; + export import CollectionChangeCallback = internal.CollectionChangeCallback; + export import CollectionChangeSet = internal.CollectionChangeSet; + export import CollectionPropertyTypeName = internal.CollectionPropertyTypeName; + export import Collection = internal.Collection; + export import CompensatingWriteError = internal.CompensatingWriteError; + export import CompensatingWriteInfo = internal.CompensatingWriteInfo; + export import ConfigurationWithoutSync = internal.ConfigurationWithoutSync; + export import ConfigurationWithSync = internal.ConfigurationWithSync; + export import Configuration = internal.Configuration; + export import ConnectionNotificationCallback = internal.ConnectionNotificationCallback; + export import ConnectionState = internal.ConnectionState; + export import Credentials = internal.Credentials; + export import DefaultFunctionsFactory = internal.DefaultFunctionsFactory; + export import DefaultUserProfileData = internal.DefaultUserProfileData; + export import Dictionary = internal.Dictionary; + export import DictionaryChangeCallback = internal.DictionaryChangeCallback; + export import DictionaryChangeSet = internal.DictionaryChangeSet; + export import ErrorCallback = internal.ErrorCallback; + export import FlexibleSyncConfiguration = internal.FlexibleSyncConfiguration; + export import IndexDecorator = internal.IndexDecorator; + export import List = internal.List; + export import LocalAppConfiguration = internal.LocalAppConfiguration; + export import MapToDecorator = internal.MapToDecorator; + export import MetadataMode = internal.MetadataMode; + export import Metadata = internal.Metadata; + export import MigrationCallback = internal.MigrationCallback; + export import Mixed = internal.Types.Mixed; + export import NumericLogLevel = internal.NumericLogLevel; + export import ObjectChangeCallback = internal.ObjectChangeCallback; + export import ObjectChangeSet = internal.ObjectChangeSet; + export import ObjectSchema = internal.ObjectSchema; + export import ObjectType = internal.ObjectType; + export import OpenRealmBehaviorConfiguration = internal.OpenRealmBehaviorConfiguration; + export import OpenRealmBehaviorType = internal.OpenRealmBehaviorType; + export import OpenRealmTimeOutBehavior = internal.OpenRealmTimeOutBehavior; + export import OrderedCollection = internal.OrderedCollection; + export import PartitionSyncConfiguration = internal.PartitionSyncConfiguration; + export import PrimaryKey = internal.PrimaryKey; + export import PrimitivePropertyTypeName = internal.PrimitivePropertyTypeName; + export import ProgressDirection = internal.ProgressDirection; + export import ProgressMode = internal.ProgressMode; + export import ProgressNotificationCallback = internal.ProgressNotificationCallback; + export import PropertiesTypes = internal.PropertiesTypes; + export import PropertySchema = internal.PropertySchema; + export import PropertySchemaParseError = internal.PropertySchemaParseError; + export import PropertySchemaShorthand = internal.PropertySchemaShorthand; + export import PropertySchemaStrict = internal.PropertySchemaStrict; + export import PropertyTypeName = internal.PropertyTypeName; + export import ProviderType = internal.ProviderType; + export import ProxyType = internal.ProxyType; + export import RealmEventName = internal.RealmEventName; + export import RealmObjectConstructor = internal.RealmObjectConstructor; + export import RelationshipPropertyTypeName = internal.RelationshipPropertyTypeName; + export import Results = internal.Results; + export import SchemaParseError = internal.SchemaParseError; + export import SessionState = internal.SessionState; + export import SessionStopPolicy = internal.SessionStopPolicy; + export import Set = internal.RealmSet; + export import SortDescriptor = internal.SortDescriptor; + export import SSLConfiguration = internal.SSLConfiguration; + export import SSLVerifyCallback = internal.SSLVerifyCallback; + export import SSLVerifyObject = internal.SSLVerifyObject; + export import SubscriptionSetState = internal.SubscriptionSetState; + export import SyncConfiguration = internal.SyncConfiguration; + export import SyncError = internal.SyncError; + export import UpdateMode = internal.UpdateMode; + export import UserChangeCallback = internal.UserChangeCallback; + export import UserState = internal.UserState; + export import User = internal.User; + export import WaitForSync = internal.WaitForSync; + export import GeoBox = internal.GeoBox; + export import GeoCircle = internal.GeoCircle; + export import GeoPoint = internal.GeoPoint; + export import GeoPolygon = internal.GeoPolygon; + export import CanonicalGeoPolygon = internal.CanonicalGeoPolygon; + export import CanonicalGeoPoint = internal.CanonicalGeoPoint; + export import GeoPosition = internal.GeoPosition; + + // Deprecated exports below + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.AppServicesFunction} */ + export import RealmFunction = internal.AppServicesFunction; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.CanonicalPropertySchema} */ + export import CanonicalObjectSchemaProperty = internal.CanonicalPropertySchema; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.ClientResetRecoverUnsyncedChangesConfiguration} */ + export import ClientResetRecoveryConfiguration = internal.ClientResetRecoverUnsyncedChangesConfiguration; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.PropertySchema} */ + export import ObjectSchemaProperty = internal.PropertySchema; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.RealmObjectConstructor} */ + export import ObjectClass = internal.RealmObjectConstructor; } //Set default logger and log level. Realm.setLogger(defaultLogger); Realm.setLogLevel(defaultLoggerLevel); - -// Patch the global at runtime -let warnedAboutGlobalRealmUse = false; -Object.defineProperty(safeGlobalThis, "Realm", { - get() { - if (flags.THROW_ON_GLOBAL_REALM) { - throw new Error( - "Accessed global Realm, please update your code to ensure you import Realm:\nimport Realm from 'realm';", - ); - } else if (!warnedAboutGlobalRealmUse) { - // eslint-disable-next-line no-console - console.warn( - "Your app is relying on a Realm global, which will be removed in realm-js v13, please update your code to ensure you import Realm:\n\n", - 'import Realm from "realm"; // For ES Modules\n', - 'const Realm = require("realm"); // For CommonJS\n\n', - "To determine where, put this in the top of your index file:\n", - `import Realm from "realm";\n`, - `Realm.flags.THROW_ON_GLOBAL_REALM = true`, - ); - warnedAboutGlobalRealmUse = true; - } - return RealmConstructor; - }, - configurable: false, -}); diff --git a/packages/realm/src/TypeHelpers.ts b/packages/realm/src/TypeHelpers.ts index 4a92ea2c7a9..be3da30a00d 100644 --- a/packages/realm/src/TypeHelpers.ts +++ b/packages/realm/src/TypeHelpers.ts @@ -76,6 +76,7 @@ export type TypeHelpers = { fromBinding(value: unknown): T; }; +/** @internal */ export type TypeOptions = { realm: Realm; name: string; @@ -88,6 +89,7 @@ export type TypeOptions = { // TODO: Consider testing for expected object instance types and throw something similar to the legacy SDK: // "Only Realm instances are supported." (which should probably have been "RealmObject") // instead of relying on the binding to throw. +/** @internal */ export function mixedToBinding(realm: binding.Realm, value: unknown): binding.MixedArg { if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) { // Fast track pass through for the most commonly used types @@ -387,6 +389,7 @@ const TYPES_MAPPING: Record Type }, }; +/** @internal */ export function getTypeHelpers(type: binding.PropertyType, options: TypeOptions): TypeHelpers { const helpers = TYPES_MAPPING[type]; assert(helpers, `Unexpected type ${type}`); diff --git a/packages/realm/src/Types.ts b/packages/realm/src/Types.ts index aa05103d044..94141285212 100644 --- a/packages/realm/src/Types.ts +++ b/packages/realm/src/Types.ts @@ -16,18 +16,10 @@ // //////////////////////////////////////////////////////////////////////////// -import { BSON, Dictionary, List, RealmSet, Results } from "./internal"; - -const RealmDictionary = Dictionary; -type RealmDictionary = Dictionary; - -const RealmList = List; -type RealmList = List; - -const RealmResults = Results; -type RealmResults = Results; +import * as internal from "./internal"; const GlobalDate = Date; +type GlobalDate = Date; // eslint-disable-next-line @typescript-eslint/no-namespace export namespace Types { @@ -37,29 +29,22 @@ export namespace Types { export type Float = number; export type Double = number; - export type Decimal128 = BSON.Decimal128; - export const Decimal128 = BSON.Decimal128; + export import Decimal128 = internal.BSON.Decimal128; + export import ObjectId = internal.BSON.ObjectId; + export import UUID = internal.BSON.UUID; - export type ObjectId = BSON.ObjectId; - export const ObjectId = BSON.ObjectId; - - export type UUID = BSON.UUID; - export const UUID = BSON.UUID; - - export type Date = typeof GlobalDate; + export type Date = GlobalDate; export const Date = GlobalDate; export type Data = ArrayBuffer; export const Data = ArrayBuffer; - export type List = RealmList; - export const List: typeof RealmList = RealmList; - export type Set = RealmSet; - export const Set: typeof RealmSet = RealmSet; - export type Dictionary = RealmDictionary; - export const Dictionary: typeof RealmDictionary = RealmDictionary; + export import List = internal.List; + export import Set = internal.RealmSet; + export import Dictionary = internal.Dictionary; + export type Mixed = unknown; /* eslint-disable-next-line @typescript-eslint/no-unused-vars -- We don't use the `LinkingPropertyName` at runtime */ - export type LinkingObjects = RealmResults; - export const LinkingObjects: typeof RealmResults = RealmResults; + export type LinkingObjects = internal.Results; + export const LinkingObjects = internal.Results; } diff --git a/packages/realm/src/app-services/App.ts b/packages/realm/src/app-services/App.ts index 4fa8e928c98..6b3a67b5091 100644 --- a/packages/realm/src/app-services/App.ts +++ b/packages/realm/src/app-services/App.ts @@ -19,12 +19,12 @@ import type { AnyFetch } from "@realm/fetch"; import { AnyUser, + Configuration, Credentials, DefaultFunctionsFactory, DefaultObject, EmailPasswordAuth, Listeners, - Sync, User, assert, binding, @@ -211,14 +211,6 @@ export class App< return newApp; } - public static Sync = Sync; - - /** - * All credentials available for authentication. - * @see https://www.mongodb.com/docs/atlas/app-services/authentication/ - */ - public static Credentials = Credentials; - /** @internal */ public static deviceInfo = deviceInfo.create(); /** @internal */ @@ -402,3 +394,15 @@ export class App< this.listeners.removeAll(); } } + +import * as internal from "../internal"; + +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace App { + /** + * All credentials available for authentication. + * @see https://www.mongodb.com/docs/atlas/app-services/authentication/ + */ + export type Credentials = internal.Credentials; + export import Sync = internal.Sync; +} diff --git a/packages/realm/src/app-services/Auth.ts b/packages/realm/src/app-services/Auth.ts new file mode 100644 index 00000000000..c540791f5bc --- /dev/null +++ b/packages/realm/src/app-services/Auth.ts @@ -0,0 +1,26 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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 * as internal from "../internal"; + +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace Auth { + export import EmailPasswordAuth = internal.EmailPasswordAuth; + export type ApiKey = internal.ApiKey; + export import ApiKeyAuth = internal.ApiKeyAuth; +} diff --git a/packages/realm/src/app-services/MongoDB.ts b/packages/realm/src/app-services/MongoDB.ts new file mode 100644 index 00000000000..9e3916db054 --- /dev/null +++ b/packages/realm/src/app-services/MongoDB.ts @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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 * as internal from "../internal"; + +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace MongoDB { + export import AggregatePipelineStage = internal.AggregatePipelineStage; + export import BaseChangeEvent = internal.BaseChangeEvent; + export import ChangeEvent = internal.ChangeEvent; + export import ChangeEventId = internal.ChangeEventId; + export import CountOptions = internal.CountOptions; + export import DeleteEvent = internal.DeleteEvent; + export import DeleteResult = internal.DeleteResult; + export import Document = internal.Document; + export import DocumentKey = internal.DocumentKey; + export import DocumentNamespace = internal.DocumentNamespace; + export import DropDatabaseEvent = internal.DropDatabaseEvent; + export import DropEvent = internal.DropEvent; + export import Filter = internal.Filter; + export import FindOneAndModifyOptions = internal.FindOneAndModifyOptions; + export import FindOneOptions = internal.FindOneOptions; + export import FindOptions = internal.FindOptions; + export import InsertEvent = internal.InsertEvent; + export import InsertManyResult = internal.InsertManyResult; + export import InsertOneResult = internal.InsertOneResult; + export import InvalidateEvent = internal.InvalidateEvent; + export import MongoDBCollection = internal.MongoDBCollection; + export import NewDocument = internal.NewDocument; + export import OperationType = internal.OperationType; + export import RenameEvent = internal.RenameEvent; + export import ReplaceEvent = internal.ReplaceEvent; + export import Update = internal.Update; + export import UpdateDescription = internal.UpdateDescription; + export import UpdateEvent = internal.UpdateEvent; + export import UpdateOptions = internal.UpdateOptions; + export import UpdateResult = internal.UpdateResult; +} diff --git a/packages/realm/src/app-services/MongoDBCollection.ts b/packages/realm/src/app-services/MongoDBCollection.ts index 297d931cfa6..28405976f30 100644 --- a/packages/realm/src/app-services/MongoDBCollection.ts +++ b/packages/realm/src/app-services/MongoDBCollection.ts @@ -23,7 +23,7 @@ import { DefaultFunctionsFactory, User, binding, createFactory, toArrayBuffer } /** * A remote MongoDB service enabling access to an Atlas cluster. */ -export type MongoDB = { +export type MongoDBService = { /** * The name of the MongoDB service. */ diff --git a/packages/realm/src/app-services/NetworkTransport.ts b/packages/realm/src/app-services/NetworkTransport.ts index 1cb553354b3..60357f5dfb5 100644 --- a/packages/realm/src/app-services/NetworkTransport.ts +++ b/packages/realm/src/app-services/NetworkTransport.ts @@ -16,7 +16,6 @@ // //////////////////////////////////////////////////////////////////////////// -import { toFetchArgs } from "src/binding"; import { binding, extendDebug, network } from "../internal"; import type { Headers } from "@realm/fetch"; @@ -33,7 +32,7 @@ function flattenHeaders(headers: Headers) { /** @internal */ export function createNetworkTransport(fetch = network.fetch) { return binding.Helpers.makeNetworkTransport((request, callback) => { - const [url, init] = toFetchArgs(request); + const [url, init] = binding.toFetchArgs(request); debug("requesting %s %O", url, init); fetch(url, init).then( async (response) => { diff --git a/packages/realm/src/app-services/Services.ts b/packages/realm/src/app-services/Services.ts new file mode 100644 index 00000000000..9b226e603db --- /dev/null +++ b/packages/realm/src/app-services/Services.ts @@ -0,0 +1,27 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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 * as internal from "../internal"; + +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace Services { + export import MongoDB = internal.MongoDB; + export import MongoDBDatabase = internal.MongoDBDatabase; + /** @deprecated Please read {@link https://www.mongodb.com/docs/atlas/app-services/reference/push-notifications/} */ + export type Push = internal.PushClient; +} diff --git a/packages/realm/src/app-services/Sync.ts b/packages/realm/src/app-services/Sync.ts index b16d53dee13..9abb21d4e39 100644 --- a/packages/realm/src/app-services/Sync.ts +++ b/packages/realm/src/app-services/Sync.ts @@ -18,19 +18,13 @@ import { App, - ConnectionState, LogLevel, Logger, - MutableSubscriptionSet, - NumericLogLevel, OpenRealmBehaviorConfiguration, OpenRealmBehaviorType, OpenRealmTimeOutBehavior, PartitionValue, Realm, - Subscription, - SubscriptionSet, - SubscriptionSetState, SyncSession, User, assert, @@ -41,17 +35,9 @@ import { validateSyncConfiguration, } from "../internal"; -export class Sync { - static Session = SyncSession; - static ConnectionState = ConnectionState; - static Subscription = Subscription; - static SubscriptionSet = SubscriptionSet; - static MutableSubscriptionSet = MutableSubscriptionSet; - static SubscriptionSetState = SubscriptionSetState; - /** @deprecated Please use {@link SubscriptionSetState} as a named import */ - static SubscriptionsState = SubscriptionSetState; - static NumericLogLevel = NumericLogLevel; +import * as internal from "../internal"; +export class Sync { /** @deprecated Will be removed in v13.0.0. Please use {@link Realm.setLogLevel}. */ static setLogLevel(app: App, level: LogLevel) { const numericLevel = toBindingLoggerLevel(level); @@ -194,3 +180,20 @@ export class Sync { timeOutBehavior: OpenRealmTimeOutBehavior.ThrowException, }; } + +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace Sync { + export import ConnectionState = internal.ConnectionState; + export import BaseSubscriptionSet = internal.BaseSubscriptionSet; + export import LogLevel = internal.LogLevel; + export import NumericLogLevel = internal.NumericLogLevel; + export import MutableSubscriptionSet = internal.MutableSubscriptionSet; + export import PartitionValue = internal.PartitionValue; + export import SubscriptionOptions = internal.SubscriptionOptions; + export import SubscriptionSet = internal.SubscriptionSet; + export import SubscriptionSetState = internal.SubscriptionSetState; + /** @deprecated Please use {@link internal.SubscriptionSetState} */ + export import SubscriptionsState = internal.SubscriptionSetState; + export import Subscription = internal.Subscription; + export import Session = internal.SyncSession; +} diff --git a/packages/realm/src/app-services/SyncConfiguration.ts b/packages/realm/src/app-services/SyncConfiguration.ts index 37d83091d04..5476fa11995 100644 --- a/packages/realm/src/app-services/SyncConfiguration.ts +++ b/packages/realm/src/app-services/SyncConfiguration.ts @@ -17,7 +17,6 @@ //////////////////////////////////////////////////////////////////////////// import { EJSON, ObjectId, UUID } from "bson"; -import { syncProxyConfig } from "src/platform/sync-proxy-config"; import { AnyUser, @@ -32,6 +31,7 @@ import { User, assert, binding, + syncProxyConfig, toBindingClientResetMode, toBindingErrorHandler, toBindingErrorHandlerWithOnManual, diff --git a/packages/realm/src/app-services/User.ts b/packages/realm/src/app-services/User.ts index 409746fe3c3..0e01dda2b59 100644 --- a/packages/realm/src/app-services/User.ts +++ b/packages/realm/src/app-services/User.ts @@ -26,8 +26,8 @@ import { DefaultUserProfileData, Document, Listeners, - MongoDB, MongoDBCollection, + MongoDBService, ProviderType, PushClient, assert, @@ -345,7 +345,7 @@ export class User< * .collection("widgets") * .find({ color: "blue" }); */ - mongoClient(serviceName: string): MongoDB { + mongoClient(serviceName: string): MongoDBService { assert.string(serviceName, "serviceName"); assert(serviceName.length, "Please provide the name of the MongoDB service to connect to."); diff --git a/packages/realm/src/app-services/utils.ts b/packages/realm/src/app-services/utils.ts index c2dd6c85232..f21ae6b74b8 100644 --- a/packages/realm/src/app-services/utils.ts +++ b/packages/realm/src/app-services/utils.ts @@ -16,13 +16,17 @@ // //////////////////////////////////////////////////////////////////////////// -import { binding } from "src/internal"; +import { binding } from "../internal"; /** * Remove entries for undefined property values. * @internal */ export function cleanArguments(args: unknown[]): binding.EJson[]; +/** + * Remove entries for undefined property values. + * @internal + */ export function cleanArguments(args: unknown): binding.EJson; export function cleanArguments(args: unknown[] | unknown) { if (Array.isArray(args)) { diff --git a/packages/realm/src/assert.ts b/packages/realm/src/assert.ts index adda06f73b1..2e8f2c7065e 100644 --- a/packages/realm/src/assert.ts +++ b/packages/realm/src/assert.ts @@ -25,6 +25,7 @@ import { AssertionError, BSON, DefaultObject, PrimaryKey, Realm, TypeAssertionEr * @param condition The condition that must be truthy to avoid throwing. * @param err Optional message or error to throw. * Or a function producing this, which is useful to avoid computing the error message in case it's not needed. + * @internal */ export function assert( condition: unknown, diff --git a/packages/realm/src/binding.ts b/packages/realm/src/binding.ts deleted file mode 100644 index cd8202b0b01..00000000000 --- a/packages/realm/src/binding.ts +++ /dev/null @@ -1,159 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2022 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 { - HttpMethod, - IndexSet, - Int64, - Int64Type, - ObjKey, - Request, - SyncSession, - Timestamp, - WeakSyncSession, -} from "realm/binding"; -import { AbortSignal, fetch } from "@realm/fetch"; - -/** @internal */ -export * from "realm/binding"; - -/** @internal */ -declare module "realm/binding" { - interface IndexSet { - asIndexes(): Iterator; - } - interface Timestamp { - toDate(): Date; - } - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Timestamp { - export function fromDate(d: Date): Timestamp; - } - - interface SyncSession { - /** Returns a WeakSyncSession and releases the strong reference held by this SyncSession */ - weaken(): WeakSyncSession; - } - - interface WeakSyncSession { - /** - * Similar to WeakRef.deref(), but takes a callback so that the strong reference can be - * automatically released when the callback exists (either by returning or throwing). - * It is not legal to hold on to the SyncSession after this returns because its - * strong reference will have been deleted. - */ - withDeref(callback: (shared: SyncSession | null) => Ret): Ret; - } -} - -IndexSet.prototype.asIndexes = function* (this: IndexSet) { - for (const [from, to] of this) { - let i = from; - while (i < to) { - yield i; - i++; - } - } -}; - -Timestamp.fromDate = (d: Date) => - Timestamp.make(Int64.numToInt(Math.floor(d.valueOf() / 1000)), (d.valueOf() % 1000) * 1000_000); - -Timestamp.prototype.toDate = function () { - return new Date(Number(this.seconds) * 1000 + this.nanoseconds / 1000_000); -}; - -SyncSession.prototype.weaken = function () { - try { - return WeakSyncSession.weakCopyOf(this); - } finally { - this.$resetSharedPtr(); - } -}; - -WeakSyncSession.prototype.withDeref = function (callback: (shared: SyncSession | null) => Ret) { - const shared = this.rawDereference(); - try { - return callback(shared); - } finally { - shared?.$resetSharedPtr(); - } -}; - -/** @internal */ -export class InvalidObjKey extends TypeError { - constructor(input: string) { - super(`Cannot convert '${input}' to an ObjKey`); - } -} - -/** @internal */ -export function stringToObjKey(input: string): ObjKey { - try { - return Int64.strToInt(input) as unknown as ObjKey; - } catch { - throw new InvalidObjKey(input); - } -} - -/** @internal */ -export function isEmptyObjKey(objKey: ObjKey) { - // This relies on the JS representation of an ObjKey being a bigint - return Int64.equals(objKey as unknown as Int64, -1); -} - -function fromBindingFetchBody(body: string) { - if (body.length === 0) { - return undefined; - } else { - return body; - } -} - -const HTTP_METHOD: Record = { - [HttpMethod.Get]: "GET", - [HttpMethod.Post]: "POST", - [HttpMethod.Put]: "PUT", - [HttpMethod.Patch]: "PATCH", - [HttpMethod.Del]: "DELETE", -}; - -function fromBindingFetchMethod(method: HttpMethod) { - if (method in HTTP_METHOD) { - return HTTP_METHOD[method]; - } else { - throw new Error(`Unexpected method ${method}`); - } -} - -function fromBindingTimeoutSignal(timeoutMs: Int64Type): AbortSignal | undefined { - const timeout = Number(timeoutMs); - return timeout > 0 ? AbortSignal.timeout(timeout) : undefined; -} - -export function toFetchArgs({ url, method, timeoutMs, body, headers }: Request): Parameters { - return [ - url, - { - body: fromBindingFetchBody(body), - method: fromBindingFetchMethod(method), - signal: fromBindingTimeoutSignal(timeoutMs), - headers, - }, - ]; -} diff --git a/packages/realm/src/debug.ts b/packages/realm/src/debug.ts index 91cda03b5e4..9a2ab866593 100644 --- a/packages/realm/src/debug.ts +++ b/packages/realm/src/debug.ts @@ -18,8 +18,10 @@ import createDebug from "debug"; +/** @internal */ export const debug = createDebug("realm"); +/** @internal */ export function extendDebug(namespace: string) { return debug.extend(namespace); } diff --git a/packages/realm/src/deprecated-global.ts b/packages/realm/src/deprecated-global.ts new file mode 100644 index 00000000000..d850e82b22c --- /dev/null +++ b/packages/realm/src/deprecated-global.ts @@ -0,0 +1,182 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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 as RealmConstructor, flags, safeGlobalThis } from "./internal"; +import * as internal from "./internal"; + +let warnedAboutGlobalRealmUse = false; +Object.defineProperty(safeGlobalThis, "Realm", { + get() { + if (flags.THROW_ON_GLOBAL_REALM) { + throw new Error( + "Accessed global Realm, please update your code to ensure you import Realm:\nimport Realm from 'realm';", + ); + } else if (!warnedAboutGlobalRealmUse) { + // eslint-disable-next-line no-console + console.warn( + "Your app is relying on a Realm global, which will be removed in realm-js v13, please update your code to ensure you import Realm:\n\n", + 'import Realm from "realm"; // For ES Modules\n', + 'const Realm = require("realm"); // For CommonJS\n\n', + "To determine where, put this in the top of your index file:\n", + `import Realm from "realm";\n`, + `Realm.flags.THROW_ON_GLOBAL_REALM = true`, + ); + warnedAboutGlobalRealmUse = true; + } + return RealmConstructor; + }, + configurable: true, +}); + +declare global { + // No need to keep this updated with the namespace in Realm.ts, since this is marked as deprecated + // We cannot simply "export import Realm" here, because that results in ts(2667): + // "Imports are not permitted in module augmentations. Consider moving them to the enclosing external module." + + /* eslint-disable @typescript-eslint/no-namespace */ + + /** @deprecated Will be removed in v13.0.0. Please use an import statement. */ + export class Realm extends RealmConstructor {} + /** + * @deprecated Will be removed in v13.0.0. Please use an import statement. + */ + export namespace Realm { + export import Realm = RealmConstructor; + export import flags = internal.flags; + + export import Object = internal.RealmObject; + export import App = internal.App; + export import Auth = internal.Auth; + export import BSON = internal.BSON; + export import Types = internal.Types; + export import Services = internal.Services; + + export import index = internal.index; + export import mapTo = internal.mapTo; + export import kmToRadians = internal.kmToRadians; + export import miToRadians = internal.miToRadians; + + export import AppChangeCallback = internal.AppChangeCallback; + export import AppConfiguration = internal.AppConfiguration; + export import AppServicesFunction = internal.AppServicesFunction; + export import BaseConfiguration = internal.BaseConfiguration; + export import BaseObjectSchema = internal.BaseObjectSchema; + export import BaseSyncConfiguration = internal.BaseSyncConfiguration; + export import CanonicalObjectSchema = internal.CanonicalObjectSchema; + export import CanonicalPropertySchema = internal.CanonicalPropertySchema; + export import CanonicalPropertiesTypes = internal.CanonicalPropertiesTypes; + export import ClientResetMode = internal.ClientResetMode; + export import ClientResetFallbackCallback = internal.ClientResetFallbackCallback; + export import ClientResetBeforeCallback = internal.ClientResetBeforeCallback; + export import ClientResetAfterCallback = internal.ClientResetAfterCallback; + export import ClientResetManualConfiguration = internal.ClientResetManualConfiguration; + export import ClientResetDiscardUnsyncedChangesConfiguration = internal.ClientResetDiscardUnsyncedChangesConfiguration; + export import ClientResetRecoverUnsyncedChangesConfiguration = internal.ClientResetRecoverUnsyncedChangesConfiguration; + export import ClientResetRecoverOrDiscardUnsyncedChangesConfiguration = internal.ClientResetRecoverOrDiscardUnsyncedChangesConfiguration; + export import ClientResetConfig = internal.ClientResetConfig; + export import CollectionChangeCallback = internal.CollectionChangeCallback; + export import CollectionChangeSet = internal.CollectionChangeSet; + export import CollectionPropertyTypeName = internal.CollectionPropertyTypeName; + export import Collection = internal.Collection; + export import CompensatingWriteError = internal.CompensatingWriteError; + export import CompensatingWriteInfo = internal.CompensatingWriteInfo; + export import ConfigurationWithoutSync = internal.ConfigurationWithoutSync; + export import ConfigurationWithSync = internal.ConfigurationWithSync; + export import Configuration = internal.Configuration; + export import ConnectionNotificationCallback = internal.ConnectionNotificationCallback; + export import ConnectionState = internal.ConnectionState; + export import Credentials = internal.Credentials; + export import DefaultFunctionsFactory = internal.DefaultFunctionsFactory; + export import DefaultUserProfileData = internal.DefaultUserProfileData; + export import Dictionary = internal.Dictionary; + export import DictionaryChangeCallback = internal.DictionaryChangeCallback; + export import DictionaryChangeSet = internal.DictionaryChangeSet; + export import ErrorCallback = internal.ErrorCallback; + export import FlexibleSyncConfiguration = internal.FlexibleSyncConfiguration; + export import IndexDecorator = internal.IndexDecorator; + export import List = internal.List; + export import LocalAppConfiguration = internal.LocalAppConfiguration; + export import MapToDecorator = internal.MapToDecorator; + export import MetadataMode = internal.MetadataMode; + export import Metadata = internal.Metadata; + export import MigrationCallback = internal.MigrationCallback; + export import Mixed = internal.Types.Mixed; + export import NumericLogLevel = internal.NumericLogLevel; + export import ObjectChangeCallback = internal.ObjectChangeCallback; + export import ObjectChangeSet = internal.ObjectChangeSet; + export import ObjectSchema = internal.ObjectSchema; + export import ObjectType = internal.ObjectType; + export import OpenRealmBehaviorConfiguration = internal.OpenRealmBehaviorConfiguration; + export import OpenRealmBehaviorType = internal.OpenRealmBehaviorType; + export import OpenRealmTimeOutBehavior = internal.OpenRealmTimeOutBehavior; + export import OrderedCollection = internal.OrderedCollection; + export import PartitionSyncConfiguration = internal.PartitionSyncConfiguration; + export import PrimaryKey = internal.PrimaryKey; + export import PrimitivePropertyTypeName = internal.PrimitivePropertyTypeName; + export import ProgressDirection = internal.ProgressDirection; + export import ProgressMode = internal.ProgressMode; + export import ProgressNotificationCallback = internal.ProgressNotificationCallback; + export import PropertiesTypes = internal.PropertiesTypes; + export import PropertySchema = internal.PropertySchema; + export import PropertySchemaParseError = internal.PropertySchemaParseError; + export import PropertySchemaShorthand = internal.PropertySchemaShorthand; + export import PropertySchemaStrict = internal.PropertySchemaStrict; + export import PropertyTypeName = internal.PropertyTypeName; + export import ProviderType = internal.ProviderType; + export import ProxyType = internal.ProxyType; + export import RealmEventName = internal.RealmEventName; + export import RealmObjectConstructor = internal.RealmObjectConstructor; + export import RelationshipPropertyTypeName = internal.RelationshipPropertyTypeName; + export import Results = internal.Results; + export import SchemaParseError = internal.SchemaParseError; + export import SessionState = internal.SessionState; + export import SessionStopPolicy = internal.SessionStopPolicy; + export import Set = internal.RealmSet; + export import SortDescriptor = internal.SortDescriptor; + export import SSLConfiguration = internal.SSLConfiguration; + export import SSLVerifyCallback = internal.SSLVerifyCallback; + export import SSLVerifyObject = internal.SSLVerifyObject; + export import SubscriptionSetState = internal.SubscriptionSetState; + export import SyncConfiguration = internal.SyncConfiguration; + export import SyncError = internal.SyncError; + export import UpdateMode = internal.UpdateMode; + export import UserChangeCallback = internal.UserChangeCallback; + export import UserState = internal.UserState; + export import User = internal.User; + export import WaitForSync = internal.WaitForSync; + export import GeoBox = internal.GeoBox; + export import GeoCircle = internal.GeoCircle; + export import GeoPoint = internal.GeoPoint; + export import GeoPolygon = internal.GeoPolygon; + export import CanonicalGeoPolygon = internal.CanonicalGeoPolygon; + export import CanonicalGeoPoint = internal.CanonicalGeoPoint; + export import GeoPosition = internal.GeoPosition; + + // Deprecated exports below + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.AppServicesFunction} */ + export import RealmFunction = internal.AppServicesFunction; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.CanonicalPropertySchema} */ + export import CanonicalObjectSchemaProperty = internal.CanonicalPropertySchema; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.ClientResetRecoverUnsyncedChangesConfiguration} */ + export import ClientResetRecoveryConfiguration = internal.ClientResetRecoverUnsyncedChangesConfiguration; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.PropertySchema} */ + export import ObjectSchemaProperty = internal.PropertySchema; + /** @deprecated Will be removed in v13.0.0. Please use {@link internal.RealmObjectConstructor} */ + export import ObjectClass = internal.RealmObjectConstructor; + } +} diff --git a/packages/realm/src/index.ts b/packages/realm/src/index.ts index 034adf46d6d..1b50f8bff6b 100644 --- a/packages/realm/src/index.ts +++ b/packages/realm/src/index.ts @@ -16,186 +16,5 @@ // //////////////////////////////////////////////////////////////////////////// -import { - AppServicesFunction, - CanonicalPropertySchema, - ClientResetRecoverUnsyncedChangesConfiguration, - Realm, - RealmObjectConstructor, - SyncSession, -} from "./internal"; - -export { - AggregatePipelineStage, - ApiKey, - ApiKeyAuth, - App, - AppChangeCallback, - AppConfiguration, - AppServicesFunction, - /** @deprecated Will be removed in v13.0.0. Please use {@link AppServicesFunction} */ - AppServicesFunction as RealmFunction, - AssertionError, - BaseConfiguration, - BaseObjectSchema, - BaseSubscriptionSet, - BaseSyncConfiguration, - BSON, - BaseChangeEvent, - CanonicalObjectSchema, - /** @deprecated Got renamed to {@link CanonicalPropertySchema} */ - CanonicalObjectSchemaProperty, - CanonicalPropertiesTypes, - CanonicalPropertySchema, - ChangeEvent, - ChangeEventId, - ClientResetAfterCallback, - ClientResetBeforeCallback, - ClientResetConfig, - ClientResetDiscardUnsyncedChangesConfiguration, - ClientResetFallbackCallback, - ClientResetManualConfiguration, - ClientResetMode, - ClientResetRecoverOrDiscardUnsyncedChangesConfiguration, - ClientResetRecoverUnsyncedChangesConfiguration, - /** @deprecated Got renamed to {@link ClientResetRecoverUnsyncedChangesConfiguration} */ - ClientResetRecoverUnsyncedChangesConfiguration as ClientResetRecoveryConfiguration, - Collection, - CollectionChangeCallback, - CollectionChangeSet, - CollectionPropertyTypeName, - CompensatingWriteError, - CompensatingWriteInfo, - Configuration, - ConfigurationWithoutSync, - ConfigurationWithSync, - ConnectionNotificationCallback, - ConnectionState, - CountOptions, - Credentials, - DefaultFunctionsFactory, - DefaultUserProfileData, - DeleteEvent, - DeleteResult, - Dictionary, - DictionaryChangeCallback, - DictionaryChangeSet, - Document, - DocumentKey, - DocumentNamespace, - DropDatabaseEvent, - DropEvent, - EmailPasswordAuth, - ErrorCallback, - Filter, - FindOneAndModifyOptions, - FindOneOptions, - FindOptions, - flags, - FlexibleSyncConfiguration, - index, - IndexDecorator, - InsertEvent, - InsertManyResult, - InsertOneResult, - InvalidateEvent, - List, - LocalAppConfiguration, - LoggerCallback, - LogLevel, - mapTo, - MapToDecorator, - MetadataMode, - Metadata, - MigrationCallback, - MongoDB, - MongoDBCollection, - MongoDBDatabase, - MutableSubscriptionSet, - NewDocument, - NumericLogLevel, - /** @deprecated Got renamed to {@link RealmObjectConstructor} */ - RealmObjectConstructor as ObjectClass, - ObjectChangeCallback, - ObjectChangeSet, - ObjectSchema, - ObjectSchemaParseError, - ObjectSchemaProperty, - OpenRealmBehaviorConfiguration, - OpenRealmBehaviorType, - OpenRealmTimeOutBehavior, - OperationType, - OrderedCollection, - PartitionSyncConfiguration, - PartitionValue, - PrimaryKey, - PrimitivePropertyTypeName, - ProgressDirection, - ProgressMode, - ProgressNotificationCallback, - ProgressRealmPromise, - PropertiesTypes, - PropertySchema, - PropertySchemaCommon, - PropertySchemaParseError, - PropertySchemaShorthand, - PropertySchemaStrict, - PropertyTypeName, - ProviderType, - ProxyType, - Realm, - RealmEventName, - RealmObject as Object, - RealmObjectConstructor, - RealmSet as Set, - RelationshipPropertyTypeName, - RenameEvent, - ReplaceEvent, - Results, - SchemaParseError, - SessionState, - SessionStopPolicy, - SortDescriptor, - SSLConfiguration, - SSLVerifyCallback, - SSLVerifyObject, - Subscription, - SubscriptionOptions, - SubscriptionSet, - SubscriptionSetState, - SubscriptionsState, - Sync, - SyncConfiguration, - SyncError, - SyncSession, - /** @deprecated Got renamed to {@link SyncSession} */ - SyncSession as Session, - TypeAssertionError, - Types, - Update, - UpdateDescription, - UpdateEvent, - UpdateMode, - UpdateOptions, - UpdateResult, - User, - UserChangeCallback, - UserState, - UserTypeName, - GeoBox, - GeoCircle, - GeoPoint, - GeoPolygon, - CanonicalGeoPolygon, - CanonicalGeoPoint, - GeoPosition, - kmToRadians, - miToRadians, - WaitForSync, -} from "./internal"; - -export type Mixed = unknown; -export type ObjectType = string | RealmObjectConstructor; - -// Exporting default for backwards compatibility -export default Realm; +import { Realm } from "./Realm"; +export = Realm; diff --git a/packages/realm/src/internal.ts b/packages/realm/src/internal.ts index d0a565fe753..2ca1fde964c 100644 --- a/packages/realm/src/internal.ts +++ b/packages/realm/src/internal.ts @@ -28,8 +28,6 @@ export * from "./safeGlobalThis"; /** @internal */ export * from "./platform"; -/** @internal */ -export * as binding from "./binding"; export * from "./flags"; export * from "./bson"; export * from "./errors"; @@ -78,6 +76,7 @@ export * from "./app-services/utils"; export * from "./app-services/SyncConfiguration"; export * from "./app-services/Credentials"; export * from "./app-services/User"; +export * from "./app-services/MongoDB"; export * from "./app-services/NetworkTransport"; export * from "./app-services/SyncSession"; export * from "./app-services/ApiKeyAuth"; @@ -88,10 +87,12 @@ export * from "./app-services/FunctionsFactory"; export * from "./app-services/UserProfile"; export * from "./app-services/BaseSubscriptionSet"; export * from "./app-services/MutableSubscriptionSet"; +export * from "./app-services/Services"; export * from "./app-services/SubscriptionSet"; export * from "./app-services/Subscription"; export * from "./app-services/Sync"; export * from "./app-services/App"; +export * from "./app-services/Auth"; export * from "./Realm"; export * from "./RealmListeners"; @@ -100,3 +101,5 @@ export * from "./ProgressRealmPromise"; export * from "./Unmanaged"; export * from "./schema"; + +import "./deprecated-global"; diff --git a/packages/realm/src/platform.ts b/packages/realm/src/platform.ts index 9b48fb8f312..92c3f1377bd 100644 --- a/packages/realm/src/platform.ts +++ b/packages/realm/src/platform.ts @@ -16,6 +16,13 @@ // //////////////////////////////////////////////////////////////////////////// +/** @internal */ +export { binding } from "./platform/binding"; +/** @internal */ export { deviceInfo } from "./platform/device-info"; +/** @internal */ export { fs } from "./platform/file-system"; +/** @internal */ export { network } from "./platform/network"; +/** @internal */ +export { syncProxyConfig } from "./platform/sync-proxy-config"; diff --git a/packages/realm/src/platform/binding-patch.ts b/packages/realm/src/platform/binding-patch.ts new file mode 100644 index 00000000000..60b8c432db0 --- /dev/null +++ b/packages/realm/src/platform/binding-patch.ts @@ -0,0 +1,163 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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 { AbortSignal, fetch } from "@realm/fetch"; + +/** @internal */ +import type * as binding from "../../binding/generated/native"; + +type Binding = typeof binding; + +/** @internal */ +declare module "../../binding/generated/native" { + /** @internal */ + export interface IndexSet { + asIndexes(): Iterator; + } + export interface Timestamp { + toDate(): Date; + } + // eslint-disable-next-line @typescript-eslint/no-namespace + export namespace Timestamp { + function fromDate(d: Date): binding.Timestamp; + } + export interface SyncSession { + /** Returns a WeakSyncSession and releases the strong reference held by this SyncSession */ + weaken(): WeakSyncSession; + } + + export interface WeakSyncSession { + /** + * Similar to WeakRef.deref(), but takes a callback so that the strong reference can be + * automatically released when the callback exists (either by returning or throwing). + * It is not legal to hold on to the SyncSession after this returns because its + * strong reference will have been deleted. + */ + withDeref(callback: (shared: SyncSession | null) => Ret): Ret; + } + + export class InvalidObjKey extends TypeError { + constructor(input: string); + } + export function stringToObjKey(input: string): binding.ObjKey; + export function isEmptyObjKey(objKey: binding.ObjKey): boolean; + export function toFetchArgs(request: binding.Request): Parameters; +} + +/** + * Applies SDK level patches to the binding. + * This should only be called after the binding has been injected. + * @internal + */ +export function applyPatch(binding: Binding) { + binding.IndexSet.prototype.asIndexes = function* (this: binding.IndexSet) { + for (const [from, to] of this) { + let i = from; + while (i < to) { + yield i; + i++; + } + } + }; + + binding.Timestamp.fromDate = (d: Date) => + binding.Timestamp.make(binding.Int64.numToInt(Math.floor(d.valueOf() / 1000)), (d.valueOf() % 1000) * 1000_000); + + binding.Timestamp.prototype.toDate = function () { + return new Date(Number(this.seconds) * 1000 + this.nanoseconds / 1000_000); + }; + + binding.SyncSession.prototype.weaken = function () { + try { + return binding.WeakSyncSession.weakCopyOf(this); + } finally { + this.$resetSharedPtr(); + } + }; + + binding.WeakSyncSession.prototype.withDeref = function ( + callback: (shared: binding.SyncSession | null) => Ret, + ) { + const shared = this.rawDereference(); + try { + return callback(shared); + } finally { + shared?.$resetSharedPtr(); + } + }; + + binding.InvalidObjKey = class InvalidObjKey extends TypeError { + constructor(input: string) { + super(`Cannot convert '${input}' to an ObjKey`); + } + }; + + binding.stringToObjKey = (input: string) => { + try { + return binding.Int64.strToInt(input) as unknown as binding.ObjKey; + } catch { + throw new binding.InvalidObjKey(input); + } + }; + + binding.isEmptyObjKey = (objKey: binding.ObjKey) => { + // This relies on the JS representation of an ObjKey being a bigint + return binding.Int64.equals(objKey as unknown as binding.Int64, -1); + }; + + function fromBindingFetchBody(body: string) { + if (body.length === 0) { + return undefined; + } else { + return body; + } + } + + const HTTP_METHOD: Record = { + [binding.HttpMethod.Get]: "GET", + [binding.HttpMethod.Post]: "POST", + [binding.HttpMethod.Put]: "PUT", + [binding.HttpMethod.Patch]: "PATCH", + [binding.HttpMethod.Del]: "DELETE", + }; + + function fromBindingFetchMethod(method: binding.HttpMethod) { + if (method in HTTP_METHOD) { + return HTTP_METHOD[method]; + } else { + throw new Error(`Unexpected method ${method}`); + } + } + + function fromBindingTimeoutSignal(timeoutMs: binding.Int64Type): AbortSignal | undefined { + const timeout = Number(timeoutMs); + return timeout > 0 ? AbortSignal.timeout(timeout) : undefined; + } + + binding.toFetchArgs = ({ url, method, timeoutMs, body, headers }) => { + return [ + url, + { + body: fromBindingFetchBody(body), + method: fromBindingFetchMethod(method), + signal: fromBindingTimeoutSignal(timeoutMs), + headers, + }, + ]; + }; +} diff --git a/packages/realm/src/platform/binding.ts b/packages/realm/src/platform/binding.ts new file mode 100644 index 00000000000..d874ff21731 --- /dev/null +++ b/packages/realm/src/platform/binding.ts @@ -0,0 +1,30 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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. +// +//////////////////////////////////////////////////////////////////////////// + +/** @internal */ +import { binding, inject } from "../../binding"; +import { applyPatch } from "./binding-patch"; + +/** @internal */ +export { binding }; + +/** @internal */ +export function injectAndPatch(value: typeof binding) { + inject(value); + applyPatch(value); +} diff --git a/packages/realm/src/platform/device-info.ts b/packages/realm/src/platform/device-info.ts index d674a4bf2b6..55958c1154c 100644 --- a/packages/realm/src/platform/device-info.ts +++ b/packages/realm/src/platform/device-info.ts @@ -16,18 +16,20 @@ // //////////////////////////////////////////////////////////////////////////// -import { DeviceInfo } from "../binding"; +import type { binding } from "./binding"; type DeviceInfoType = { - create(): DeviceInfo; + create(): binding.DeviceInfo; }; +/** @internal */ export const deviceInfo: DeviceInfoType = { create() { throw new Error("Not supported on this platform"); }, }; -export function inject(injected: DeviceInfoType) { - Object.freeze(Object.assign(deviceInfo, injected)); +/** @internal */ +export function inject(value: DeviceInfoType) { + Object.freeze(Object.assign(deviceInfo, value)); } diff --git a/packages/realm/src/platform/file-system.ts b/packages/realm/src/platform/file-system.ts index 07aafc507b2..a845ad759d2 100644 --- a/packages/realm/src/platform/file-system.ts +++ b/packages/realm/src/platform/file-system.ts @@ -74,6 +74,6 @@ export const fs: FileSystemType = { }, }; -export function inject(injected: FileSystemType) { - Object.freeze(Object.assign(fs, injected)); +export function inject(value: FileSystemType) { + Object.freeze(Object.assign(fs, value)); } diff --git a/packages/realm/src/platform/network.ts b/packages/realm/src/platform/network.ts index 95b9d6918f9..ce920f112cd 100644 --- a/packages/realm/src/platform/network.ts +++ b/packages/realm/src/platform/network.ts @@ -22,6 +22,6 @@ type NetworkType = { fetch: typeof fetch }; export const network: NetworkType = { fetch }; -export function inject(injected: NetworkType) { - Object.freeze(Object.assign(network, injected)); +export function inject(value: NetworkType) { + Object.freeze(Object.assign(network, value)); } diff --git a/packages/realm/index.node.js b/packages/realm/src/platform/node/binding.ts similarity index 77% rename from packages/realm/index.node.js rename to packages/realm/src/platform/node/binding.ts index 72a84d18353..9bbdc6a8792 100644 --- a/packages/realm/index.node.js +++ b/packages/realm/src/platform/node/binding.ts @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////// // -// Copyright 2023 Realm Inc. +// Copyright 2024 Realm Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -/* eslint-disable @typescript-eslint/no-var-requires -- We're exporting using CJS assignment */ -/* eslint-env commonjs */ +import { injectAndPatch } from "../binding"; +import * as binding from "../../../binding/generated/native.node.cjs"; -module.exports = require("./dist/bundle.node").Realm; +injectAndPatch(binding); diff --git a/packages/realm/src/platform/node/fs.ts b/packages/realm/src/platform/node/fs.ts index b322d20ef99..0ee57b61658 100644 --- a/packages/realm/src/platform/node/fs.ts +++ b/packages/realm/src/platform/node/fs.ts @@ -21,7 +21,7 @@ import { dirname, isAbsolute, join } from "node:path"; import { inject } from "../file-system"; import { extendDebug } from "../../debug"; -import { JsPlatformHelpers } from "../../binding"; +import { binding } from "../binding"; const debug = extendDebug("fs"); @@ -48,10 +48,10 @@ inject({ }, setDefaultDirectoryPath(path) { debug("setDefaultDirectoryPath", path); - return JsPlatformHelpers.setDefaultRealmFileDirectory(path); + return binding.JsPlatformHelpers.setDefaultRealmFileDirectory(path); }, getDefaultDirectoryPath() { - return JsPlatformHelpers.defaultRealmFileDirectory(); + return binding.JsPlatformHelpers.defaultRealmFileDirectory(); }, exists(path) { debug("exists", path); diff --git a/packages/realm/src/platform/node/index.ts b/packages/realm/src/platform/node/index.ts index 9aec874b3b6..1ff57402ff0 100644 --- a/packages/realm/src/platform/node/index.ts +++ b/packages/realm/src/platform/node/index.ts @@ -16,9 +16,11 @@ // //////////////////////////////////////////////////////////////////////////// +import "./binding"; import "./fs"; import "./device-info"; import "./sync-proxy-config"; import "./custom-inspect"; -export * from "../../index"; +import { Realm } from "../../Realm"; +export = Realm; diff --git a/packages/realm/src/platform/node/sync-proxy-config.ts b/packages/realm/src/platform/node/sync-proxy-config.ts index 5ebc3c74fa1..c2bbbd71687 100644 --- a/packages/realm/src/platform/node/sync-proxy-config.ts +++ b/packages/realm/src/platform/node/sync-proxy-config.ts @@ -19,9 +19,11 @@ import process from "node:process"; import { URL } from "node:url"; -import { ProxyType } from "realm/binding"; +import { binding } from "../binding"; import { inject } from "../sync-proxy-config"; +import ProxyType = binding.ProxyType; + inject({ create() { for (const envVar of ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"]) { diff --git a/packages/realm/src/platform/node/tsconfig.json b/packages/realm/src/platform/node/tsconfig.json deleted file mode 100644 index 79601781630..00000000000 --- a/packages/realm/src/platform/node/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "compilerOptions": { - "types": ["@realm/fetch", "node"], - "noResolve": false, - "incremental": true, - "resolveJsonModule": true, - "paths": { - "realm/binding": ["./generated/ts/native-node.mjs"], - "realm/binding/core": ["./generated/ts/core.ts"] - } - }, - "exclude": [ - "../react-native/", - "../../tests/", - "../../index.cjs.ts", - "../../../type-tests/" - ], -} diff --git a/packages/realm/src/platform/react-native/binding.ts b/packages/realm/src/platform/react-native/binding.ts new file mode 100644 index 00000000000..4d02fdd9ede --- /dev/null +++ b/packages/realm/src/platform/react-native/binding.ts @@ -0,0 +1,22 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2024 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 { injectAndPatch } from "../binding"; +import * as binding from "../../../binding/generated/native.react-native.cjs"; + +injectAndPatch(binding); diff --git a/packages/realm/src/platform/react-native/device-info.ts b/packages/realm/src/platform/react-native/device-info.ts index c7ed11e03e6..014b1e3d185 100644 --- a/packages/realm/src/platform/react-native/device-info.ts +++ b/packages/realm/src/platform/react-native/device-info.ts @@ -21,7 +21,7 @@ import { Platform } from "react-native"; import { config, version } from "realm/package.json"; import { inject } from "../device-info"; -import { JsPlatformHelpers } from "../../binding"; +import { binding } from "../binding"; function getDeviceName() { if (Platform.OS === "ios") { @@ -71,7 +71,7 @@ inject({ deviceName: getDeviceName(), deviceVersion: getDeviceVersion(), - cpuArch: JsPlatformHelpers.getCpuArch(), + cpuArch: binding.JsPlatformHelpers.getCpuArch(), frameworkName: "react-native", frameworkVersion: getReactNativeVersion(), diff --git a/packages/realm/src/platform/react-native/fs.ts b/packages/realm/src/platform/react-native/fs.ts index 430ae4ff32b..65190b272a6 100644 --- a/packages/realm/src/platform/react-native/fs.ts +++ b/packages/realm/src/platform/react-native/fs.ts @@ -19,7 +19,10 @@ import { isAbsolute, join } from "path-browserify"; import { inject } from "../file-system"; import { extendDebug } from "../../debug"; -import { Helpers, JsPlatformHelpers } from "../../binding"; +import { binding } from "../binding"; + +import JsPlatformHelpers = binding.JsPlatformHelpers; +import Helpers = binding.Helpers; const debug = extendDebug("fs"); diff --git a/packages/realm/src/platform/react-native/index.ts b/packages/realm/src/platform/react-native/index.ts index 9fe4597e3dc..4c5a1e26317 100644 --- a/packages/realm/src/platform/react-native/index.ts +++ b/packages/realm/src/platform/react-native/index.ts @@ -15,8 +15,11 @@ // limitations under the License. // //////////////////////////////////////////////////////////////////////////// + +import "./binding"; import "./fs"; import "./device-info"; import "./sync-proxy-config"; -export * from "../../index"; +import { Realm } from "../../Realm"; +export = Realm; diff --git a/packages/realm/src/platform/react-native/tsconfig.json b/packages/realm/src/platform/react-native/tsconfig.json deleted file mode 100644 index 6b0853a8d81..00000000000 --- a/packages/realm/src/platform/react-native/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "compilerOptions": { - "noResolve": false, - "incremental": true, - "resolveJsonModule": true, - "types": [ - "react-native", - "path-browserify" - ], - "paths": { - "realm/binding": ["./generated/ts/native-react-native.mjs"], - "realm/binding/core": ["./generated/ts/core.ts"] - } - }, - "exclude": [ - "../node/", - "../../tests/", - "../../index.cjs.ts", - "../../../type-tests/" - ], -} diff --git a/packages/realm/src/platform/sync-proxy-config.ts b/packages/realm/src/platform/sync-proxy-config.ts index f7e8b7f4fee..2b466fd2206 100644 --- a/packages/realm/src/platform/sync-proxy-config.ts +++ b/packages/realm/src/platform/sync-proxy-config.ts @@ -16,18 +16,20 @@ // //////////////////////////////////////////////////////////////////////////// -import { SyncProxyConfig } from "../binding"; +import type { binding } from "./binding"; type SyncProxyConfigType = { - create(): SyncProxyConfig | undefined; + create(): binding.SyncProxyConfig | undefined; }; +/** @internal */ export const syncProxyConfig: SyncProxyConfigType = { create() { throw new Error("proxyConfig is not supported on this platform"); }, }; -export function inject(injected: SyncProxyConfigType) { - Object.freeze(Object.assign(syncProxyConfig, injected)); +/** @internal */ +export function inject(value: SyncProxyConfigType) { + Object.freeze(Object.assign(syncProxyConfig, value)); } diff --git a/packages/realm/src/schema/from-binding.ts b/packages/realm/src/schema/from-binding.ts index 6ae6a6d5265..020093ce90d 100644 --- a/packages/realm/src/schema/from-binding.ts +++ b/packages/realm/src/schema/from-binding.ts @@ -16,13 +16,12 @@ // //////////////////////////////////////////////////////////////////////////// -import { - ObjectSchema as BindingObjectSchema, - Property as BindingProperty, - PropertyType as BindingPropertyType, - TableType, -} from "../binding"; -import { assert } from "../internal"; +import { assert, binding } from "../internal"; + +type BindingObjectSchema = binding.ObjectSchema; +type BindingProperty = binding.Property; +import TableType = binding.TableType; +import BindingPropertyType = binding.PropertyType; import { CanonicalObjectSchema, CanonicalPropertySchema, PropertyTypeName } from "./types"; diff --git a/packages/realm/src/schema/to-binding.ts b/packages/realm/src/schema/to-binding.ts index 3755d040dff..f72ae32ff80 100644 --- a/packages/realm/src/schema/to-binding.ts +++ b/packages/realm/src/schema/to-binding.ts @@ -16,13 +16,12 @@ // //////////////////////////////////////////////////////////////////////////// -import { - ObjectSchema_Relaxed as BindingObjectSchema, - Property_Relaxed as BindingProperty, - PropertyType as BindingPropertyType, - TableType, -} from "../binding"; -import { CanonicalObjectSchema, CanonicalPropertySchema, PropertyTypeName, assert } from "../internal"; +import { CanonicalObjectSchema, CanonicalPropertySchema, PropertyTypeName, assert, binding } from "../internal"; + +type BindingObjectSchema = binding.ObjectSchema_Relaxed; +type BindingProperty = binding.Property_Relaxed; +import TableType = binding.TableType; +import BindingPropertyType = binding.PropertyType; /** @internal */ export const TYPE_MAPPINGS: Record = { diff --git a/packages/realm/src/schema/types.ts b/packages/realm/src/schema/types.ts index fdc1004902a..c4a3160d399 100644 --- a/packages/realm/src/schema/types.ts +++ b/packages/realm/src/schema/types.ts @@ -314,3 +314,5 @@ export type PropertySchemaStrict = PropertySchemaCommon & optional?: false; } ); + +export type ObjectType = string | RealmObjectConstructor; diff --git a/packages/realm/src/tests/list.test.ts b/packages/realm/src/tests/list.test.ts index 36615c8cde2..14333514eef 100644 --- a/packages/realm/src/tests/list.test.ts +++ b/packages/realm/src/tests/list.test.ts @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -import { Realm } from "../index"; +import { Realm } from "../Realm"; import { RealmContext, closeRealm, generateTempRealmPath } from "./utils"; diff --git a/packages/realm/src/tests/schema-transform.test.ts b/packages/realm/src/tests/schema-transform.test.ts index 3677bc8a95b..bcf9f358d4c 100644 --- a/packages/realm/src/tests/schema-transform.test.ts +++ b/packages/realm/src/tests/schema-transform.test.ts @@ -22,7 +22,7 @@ import { expect } from "chai"; import { fromBindingPropertySchema } from "../schema/from-binding"; import { toBindingPropertySchema } from "../schema/to-binding"; import { normalizePropertySchema } from "../schema/normalize"; -import { PropertySchema } from "../schema"; +import { PropertySchema } from "../schema/types"; const TEST_CASES: (string | PropertySchema)[] = [ "string", @@ -49,6 +49,7 @@ describe("schema transform", () => { linkOriginPropertyName: "", isPrimary: false, isIndexed: false, + isFulltextIndexed: false, // eslint-disable-next-line @typescript-eslint/no-explicit-any columnKey: { value: 0n } as any, ...bindingSchema, diff --git a/packages/realm/src/tests/schema-utils.test.ts b/packages/realm/src/tests/schema-utils.test.ts index 85f7a51b8ea..1714c5be9ae 100644 --- a/packages/realm/src/tests/schema-utils.test.ts +++ b/packages/realm/src/tests/schema-utils.test.ts @@ -19,14 +19,15 @@ import { expect } from "chai"; import { inspect } from "util"; -import { - ObjectSchema as BindingObjectSchema, - Property as BindingProperty, - PropertyType as BindingPropertyType, - ColKey, - TableKey, - TableType, -} from "../binding"; +import { binding } from "../platform/binding"; + +import BindingObjectSchema = binding.ObjectSchema; +import BindingProperty = binding.Property; +import BindingPropertyType = binding.PropertyType; +import ColKey = binding.ColKey; +import TableKey = binding.TableKey; +import TableType = binding.TableType; + import { CanonicalObjectSchema, CanonicalPropertySchema } from "../schema"; import { fromBindingObjectSchema, fromBindingPropertySchema } from "../schema/from-binding"; diff --git a/packages/realm/src/tests/schema-validation.test.ts b/packages/realm/src/tests/schema-validation.test.ts index 464dcedefad..98aeb71fcf1 100644 --- a/packages/realm/src/tests/schema-validation.test.ts +++ b/packages/realm/src/tests/schema-validation.test.ts @@ -18,12 +18,8 @@ import { expect } from "chai"; -import { - ObjectSchemaParseError, - PropertySchemaParseError, - validateObjectSchema, - validatePropertySchema, -} from "../internal"; +import { validateObjectSchema, validatePropertySchema } from "../schema/validate"; +import { ObjectSchemaParseError, PropertySchemaParseError } from "../errors"; const OBJECT_NAME = "MyObject"; const PROPERTY_NAME = "prop"; diff --git a/packages/realm/src/tests/tsconfig.json b/packages/realm/src/tests/tsconfig.json deleted file mode 100644 index 7b40aa035dc..00000000000 --- a/packages/realm/src/tests/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "noResolve": false, - "strictFunctionTypes": false, - "types": [ - "mocha", - "node" - ] - }, - "exclude": [] -} diff --git a/packages/realm/src/tests/utils.ts b/packages/realm/src/tests/utils.ts index 79c2c1ace4e..8ce19aba0ee 100644 --- a/packages/realm/src/tests/utils.ts +++ b/packages/realm/src/tests/utils.ts @@ -18,9 +18,8 @@ import path from "node:path"; import fs from "node:fs"; -import { fileURLToPath } from "node:url"; -import type { Realm } from "../index"; +import type { Realm } from "../Realm"; export type RealmContext = Mocha.Context & { realm: Realm }; @@ -28,7 +27,7 @@ export function generateRandomInteger() { return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); } -export const REALMS_DIR = fileURLToPath(new URL("realms", import.meta.url)); +export const REALMS_DIR = path.resolve(__dirname, "realms"); export const REALMS_TEMP_DIR = path.resolve(REALMS_DIR, "temp"); if (!fs.existsSync(REALMS_TEMP_DIR)) { fs.mkdirSync(REALMS_TEMP_DIR, { recursive: true }); diff --git a/packages/realm/tsconfig.binding.json b/packages/realm/tsconfig.binding.json new file mode 100644 index 00000000000..e0d59186524 --- /dev/null +++ b/packages/realm/tsconfig.binding.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "composite": true, + "outDir": "binding/dist", + "rootDir": "binding/generated", + "target": "es2022", + "module": "Node16", + "moduleResolution": "Node16", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "preserveConstEnums": true, + "lib": [ + "ES2022" + ], + "types": [ + "@realm/fetch" + ], + "noResolve": true + }, + "files": [ + "./binding/generated/core.ts" + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.json b/packages/realm/tsconfig.json index 929d56f006a..7234e33604d 100644 --- a/packages/realm/tsconfig.json +++ b/packages/realm/tsconfig.json @@ -1,35 +1,10 @@ { - "compilerOptions": { - "strict": true, - "target": "ES2022", - "module": "ES2020", - "moduleResolution": "node", - "noEmit": true, - "esModuleInterop": true, - "noResolve": true, - "lib": [ - "ES2022" - ], - "types": [ - "@realm/fetch", - "bson", - "debug", - "ms" // debug dependency - ], - "baseUrl": ".", - "paths": { - "realm/binding": ["./generated/ts/native-node.mjs"], - "realm/binding/core": ["./generated/ts/core.ts"] - } - }, - "include": [ - "src/", - "generated/ts/" - ], - "exclude": [ - "src/tests/", - "type-tests/", - "src/platform/node/", - "src/platform/react-native/" - ], -} + "files": [], + "references": [ + { "path": "./tsconfig.shared.json" }, + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.react-native.json" }, + { "path": "./tsconfig.tests.json" }, + { "path": "./tsconfig.public-types.json" } + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.node.json b/packages/realm/tsconfig.node.json new file mode 100644 index 00000000000..9de69372af8 --- /dev/null +++ b/packages/realm/tsconfig.node.json @@ -0,0 +1,23 @@ +{ + "extends": "@tsconfig/node-lts", + "compilerOptions": { + "composite": true, + "module": "Node16", + "moduleResolution": "Node16", + "outDir": "dist/platform/node", + "rootDir": "src/platform/node", + "sourceMap": true, + "resolveJsonModule": true, + "allowJs": true, + "types": [ + "@realm/fetch", + "node" + ], + }, + "include": [ + "src/platform/node/**/*" + ], + "references": [ + { "path": "./tsconfig.shared.json" } + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.public-types-check.json b/packages/realm/tsconfig.public-types-check.json new file mode 100644 index 00000000000..e6a31c2e275 --- /dev/null +++ b/packages/realm/tsconfig.public-types-check.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "noEmit": true, + "strict": true, + "lib": [ + "es2020" + ], + "types": [ + "bson", + "@realm/fetch" + ] + }, + "include": [ + "dist/public-types" + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.public-types.json b/packages/realm/tsconfig.public-types.json new file mode 100644 index 00000000000..ef0413cfa5d --- /dev/null +++ b/packages/realm/tsconfig.public-types.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.shared.json", + "compilerOptions": { + "outDir": "dist/public-types", + "emitDeclarationOnly": true, + "declarationMap": true, + "stripInternal": true + }, + "references": [ + { "path": "./tsconfig.shared.json" } + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.react-native.json b/packages/realm/tsconfig.react-native.json new file mode 100644 index 00000000000..a49361274be --- /dev/null +++ b/packages/realm/tsconfig.react-native.json @@ -0,0 +1,25 @@ +{ + "extends": "@react-native/typescript-config/tsconfig.json", + "compilerOptions": { + "composite": true, + "module": "node16", + "moduleResolution": "node16", + "outDir": "dist/platform/react-native", + "rootDir": "src/platform/react-native", + "sourceMap": true, + "resolveJsonModule": true, + "noEmit": false, + "allowImportingTsExtensions": false, + "types": [ + "@realm/fetch", + "react-native", + "path-browserify" + ], + }, + "include": [ + "src/platform/react-native/**/*" + ], + "references": [ + { "path": "./tsconfig.shared.json" } + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.shared.json b/packages/realm/tsconfig.shared.json new file mode 100644 index 00000000000..1986f4ebbe2 --- /dev/null +++ b/packages/realm/tsconfig.shared.json @@ -0,0 +1,38 @@ +{ + "compilerOptions": { + "composite": true, + "module": "Node16", + "moduleResolution": "Node16", + "outDir": "dist", + "rootDir": "src", + "sourceMap": true, + "target": "es2022", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "lib": [ + "ES2022" + ], + "noResolve": true, + "types": [ + "bson", + "debug", + "@realm/fetch", + "./binding/generated/native.d.ts", + "./binding/dist/core.d.ts", + "./binding/index.d.ts" + ] + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "src/tests", + "src/platform/node", + "src/platform/react-native" + ], + "references": [ + { "path": "./tsconfig.binding.json" } + ] +} \ No newline at end of file diff --git a/packages/realm/tsconfig.tests.json b/packages/realm/tsconfig.tests.json new file mode 100644 index 00000000000..44ec1aaebd7 --- /dev/null +++ b/packages/realm/tsconfig.tests.json @@ -0,0 +1,21 @@ +{ + "extends": "@tsconfig/node-lts", + "compilerOptions": { + "composite": true, + "esModuleInterop": true, + "noEmit": true, + "strictFunctionTypes": false, + "strictNullChecks": false, + "forceConsistentCasingInFileNames": true, + "types": [ + "mocha", + "node", + ] + }, + "include": [ + "src/tests/**/*" + ], + "references": [ + { "path": "./tsconfig.shared.json" } + ] +} \ No newline at end of file