diff --git a/packages/background-only/README.md b/packages/background-only/README.md new file mode 100644 index 0000000000..960dd8190f --- /dev/null +++ b/packages/background-only/README.md @@ -0,0 +1,60 @@ +# background-only + +This package serves as a mark package to enforce and mark modules that should only be used in the Background Thread context. It provides type definitions and runtime checks to ensure proper usage. + +## Example Usages + +Say we have a `Logger` module that has side effects calling into Native Modules or other APIs that are only available in the "Background" environment: + +```tsx +// Logger.js +import "background-only"; + +export function log(msg) { + // Notice how we are calling into NativeModules here. + NativeModules.hybridMonitor.reportJSError(...); +} +``` + +By adding `import "background-only"` to poison this module, we are now declaring that this module is only safe to be bundled in a "Background" environment, protecting this module from being accidentally bundled into a "Main thread" environment by throwing an error at runtime. + +For example, if we use `log` in a desirable position from a React component, such as in `useEffect` or an event handler, the `log` will work as expected: + +```tsx +// App.jsx +import { log } from "./Logger"; + +function App() { + useEffect() { + log(); + } + return +} +``` + +However, if we use `log` in a undesirable position from a React component, such as in the body of the rendering function, it will throw an error at runtime time: + +```tsx +// App.jsx +import { log } from './Logger'; + +function App() { + // throw! + log(); + return ; +} +``` + +## Development Note + +This package is already in its final form and does not require build or test steps. The files are simple enough to be used as-is. + +The package consists of three files in their final form: + +- `error.js` - Throws an error when imported in the wrong context +- `empty.js` - An empty module for the default export +- `index.d.ts` - TypeScript type definitions (empty) + +## Credits + +This is inspired by the [`server-only`](https://www.npmjs.com/package/server-only?activeTab=readme) package of React. diff --git a/packages/background-only/empty.js b/packages/background-only/empty.js new file mode 100644 index 0000000000..fce7161576 --- /dev/null +++ b/packages/background-only/empty.js @@ -0,0 +1,3 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. diff --git a/packages/background-only/error.js b/packages/background-only/error.js new file mode 100644 index 0000000000..e5aab846f0 --- /dev/null +++ b/packages/background-only/error.js @@ -0,0 +1,7 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. +throw new Error( + 'This module cannot be imported from a Main Thread module. ' + + 'It should only be used from a Background Thread.', +); diff --git a/packages/background-only/index.d.ts b/packages/background-only/index.d.ts new file mode 100644 index 0000000000..b8b9548e32 --- /dev/null +++ b/packages/background-only/index.d.ts @@ -0,0 +1,4 @@ +// Copyright 2024 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. +export {}; diff --git a/packages/background-only/package.json b/packages/background-only/package.json new file mode 100644 index 0000000000..a4d2d7fc9b --- /dev/null +++ b/packages/background-only/package.json @@ -0,0 +1,35 @@ +{ + "name": "background-only", + "version": "0.0.1", + "description": "This is a marker package to indicate that a module can only be used in the Background Thread.", + "keywords": [ + "react", + "lynx" + ], + "repository": { + "type": "git", + "url": "https://github.com/lynx-family/lynx-stack.git", + "directory": "packages/background-only" + }, + "license": "MIT", + "type": "module", + "exports": { + ".": { + "lepus": { + "types": "./index.d.ts", + "default": "./error.js" + }, + "default": { + "types": "./index.d.ts", + "default": "./empty.js" + } + } + }, + "main": "empty.js", + "types": "index.d.ts", + "files": [ + "error.js", + "empty.js", + "index.d.ts" + ] +} diff --git a/packages/background-only/tsconfig.json b/packages/background-only/tsconfig.json new file mode 100644 index 0000000000..513e2b12f8 --- /dev/null +++ b/packages/background-only/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": ".", + "composite": true, + }, + "include": [ + "*.ts", + "*.d.ts", + ], +} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c48861104d..edc3dad9fb 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -14,6 +14,7 @@ packages: - packages/third-party/* - packages/testing-library/* - packages/testing-library/examples/* + - packages/background-only - "!packages/testing-library/examples" - website diff --git a/tsconfig.json b/tsconfig.json index b1ed85ed15..02fbf24466 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -124,7 +124,7 @@ }, { "path": "./packages/third-party" - }, + } ], "include": [] }