{"id":48788513,"url":"https://github.com/tmtek/preact-pwa-native-bridge","last_synced_at":"2026-04-13T18:29:46.775Z","repository":{"id":57329542,"uuid":"181548144","full_name":"tmtek/preact-pwa-native-bridge","owner":"tmtek","description":"A javascript bridge for communicating with native wrapper apps.","archived":false,"fork":false,"pushed_at":"2019-04-15T20:15:25.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-28T09:26:43.466Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tmtek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-15T18:57:44.000Z","updated_at":"2019-04-15T20:14:50.000Z","dependencies_parsed_at":"2022-09-16T18:00:36.853Z","dependency_job_id":null,"html_url":"https://github.com/tmtek/preact-pwa-native-bridge","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tmtek/preact-pwa-native-bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmtek%2Fpreact-pwa-native-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmtek%2Fpreact-pwa-native-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmtek%2Fpreact-pwa-native-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmtek%2Fpreact-pwa-native-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tmtek","download_url":"https://codeload.github.com/tmtek/preact-pwa-native-bridge/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmtek%2Fpreact-pwa-native-bridge/sbom","scorecard":{"id":890226,"data":{"date":"2025-08-11","repo":{"name":"github.com/tmtek/preact-pwa-native-bridge","commit":"6099317097831b2fb9d2113c7747b681953753b5"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/3 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-24T11:31:43.808Z","repository_id":57329542,"created_at":"2025-08-24T11:31:43.808Z","updated_at":"2025-08-24T11:31:43.808Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31766113,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T15:25:13.801Z","status":"ssl_error","status_checked_at":"2026-04-13T15:25:09.162Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-13T18:29:45.924Z","updated_at":"2026-04-13T18:29:46.761Z","avatar_url":"https://github.com/tmtek.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Preact Native Bridge\n\nThe Preact Native Bridge is a simple javascript bridge implementation that allows a wrapping application to communicate with a [Preact](https://preactjs.com/) app. This bridge maintains the philosophy of \"props down, events up\" by implementing a decorator that allows the wrapping application to set props directly on components.\n\n### Installation \n\n```\nnpm i preact-pwa-native-bridge\n```\n\n## bridge(bridgeName)\n\nThe bridge function allows you to instantiate an object that allows methods of a javascript interface to be called.\n\n*bridgeName*: The function must be supplied the name of the javascript interface as an argument. This name is defined by the wrapping application.\n\n```javascript\nimport bridge from 'preact-pwa-native-bridge';\n\nconst bridgeExampleApi = bridge('exampleAPI');\nconst bridgeAnotherApi = bridge('anotherAPI');\n```\n\n\n### call(\"method\"|{method:[...args]}, {options})\n\nthe call() method of bridge() calls a method of the wrapper's javascript interface synchronously. You may submit any arguments you wish, and anything returned by the method of the javascript interface will be returned:\n\n```javascript\nconst bridgeExampleApi = bridge('exampleAPI');\nbridgeExampleApi.call('methodWithNoArguments');\nbridgeExampleApi.call({methodWithArguments:['arg 1', true]});\nlet data  = bridgeExampleApi.call('methodThatReturnsData');\n```\n\n### promise(\"method\"|{method:[...args]}, {options})\n\nThe promise() method of bridge() calls a method of the wrapper's javascript interface and facilitates an asynchronous response by returning a Promise object:\n\n```javascript\nconst bridgeExampleApi = bridge('exampleAPI');\n\nbridgeExampleApi\n\t.promise('methodWithNoArguments')\n\t.then(response =\u003e console.log(`Response:${response}`))\n\t.catch(error =\u003e console.log(`Error:${error}`));\n\t\nbridgeExampleApi\n\t.promise({methodWithArguments:['arg 1', true]})\n\t.then(response =\u003e console.log(`Response:${response}`))\n\t.catch(error =\u003e console.log(`Error:${error}`));\n```\n\n### Options\n\nBoth call() and promise() have an optional options object that can be passed as the second argument. the options object has the following properties:\n\n* noBridge: Supply a function that will be called if the bridge is not defined. The function can return a value used in place of the return value of the original call.\n\n```javascript\nconst bridgeExampleApi = bridge('exampleAPI');\nlet message = bridgeExampleApi.call(\n\t'getMessage', \n\t{ noBridge:() =\u003e `No Bridge...` }\n);\n```\n\n## @bridgeProps()\n\nThe bridgeProps decorator allows you to specify that a component's props can be set by the wrapping application.\n\nThe following example demonstrates wrapping a Component with bridgeProps() which links it to a named javascript interface that allows the wrapper to set the props of the component:\n\n```javascript\n@bridgeProps('AppProps')\nexport default class App extends Component {\n\trender({ title }) {\n\t\treturn \u003ch1\u003e{title}\u003c/h1\u003e\n\t}\n}\n```\nIn the example above, the first instance of App will be linked to the bridge named 'AppProps', but a second+ will not establish a link. A bridge can only support one component instance. \n\nIf you want to bridge props on a component that will have multiple instances, you can use the `bridgeName` prop:\n\n```javascript\n@bridgeProps()\nexport default class MultiInstanceComponent extends Component {\n\trender({ title }) {\n\t\treturn \u003ch1\u003e{title}\u003c/h1\u003e\n\t}\n}\n\n\u003cMultiInstanceComponent bridgeName=\"Inst1Props\" /\u003e\n\u003cMultiInstanceComponent bridgeName=\"Inst2Props\" /\u003e\n```\n\nOnce a component has been wrapped, and it's bridgeName has been specified, the wrapping application will be able to set any props on this component at any time.\n\n## Wrapper Compliance\n\nIf you are implementing the bridge on the native side, there is an interface that you must support to be compliant with preact-native-bridge.\n\n\n### Supporting bridge()\n\nIn order to support bridge, you must be able to inject a javascript interface into a webview. The javascript interface should be injected as a named object onto the DOM's window object:\n\n```javascript\nwindow['YourJSInterfaceName'] = {} //\u003c--Your injected interface\n``` \n'YourJSInterfaceName' will be the same name that the Preact app will refer to it by: \n\n```javascript\nlet myBridge = bridge('YourJSInterfaceName');\n```\n\n### Supporting call()\n\n There is nothing special that needs to be done to support call(). Any function you apply to your javascript interface can recieve arguments and return values in the standard way.\n \nOnly primitive data types such as strings, numbers, and booleans can be returned. Any object type data that you return should be encoded as a JSON string.\n\nHere is an example in Java:\n\n```java\n@JavascriptInterface\npublic String callExample(final String arg1) {\n\treturn \"You submitted:\" + arg1 + \" to the wrapper.\";\n}\n```\n\n\n### Supporting promise()\n\nAny javascript interface function that is intended to be used with promise() will get special arguments submitted to it:\n\n* first argument is the path to the callback functions as a string.\n* Then all arguments are supplied in order of submission.\n* No value need be returned.\n* The promise can be satisfied immediately or at any time in the future.\n\nHere is an example in Java:\n\n```java\n@JavascriptInterface\npublic void promiseExample(final String promise, final String arg1) {\n\n}\n```\n\nTo satisfy the promise, you have to use the promise string submitted to you as the first argument. When you are ready to return a value, you will have to use that string to build a javascript call into the web view that targets either the resolve() or reject() function of the promise located at the reference supplied to you.\n\nTheoretically, that would look like this in Java:\n\n```java\n@JavascriptInterface\npublic void promiseExample(final String promise, final String arg1) {\n\tfinal String jsToResolve = \".resolve(\\\"Response from Wrapper!\\\")\";\n\tfinal String jsToReject = \".reject(\\\"Error from Wrapper\\\")\";\n\twebView.evaluateJavascript(\"javascript:\" + promise + jsToResolve, null);\n}\n```\n\n### Supporting bridgeProps()\n\nThe bridgeProps decorator is supported by a javascript interface and requires at least one method to be implemented on the javascript interface to function correctly.\n\nWhen a component is wrapped by `bridgeProps('JSInterfaceName')`, it will call out to a method called `initProps(callback)` when it initializes:\n\nAn example in Java:\n\n```java\n@JavascriptInterface\npublic String initProps(final String propsSetCallback) {\n\tmPropsSetCallback = propsSetCallback;\n\tif (mProps != null) {\n\t\treturn new Gson().toJson(mProps);\n\t}\n\treturn \"{}\";\n}\n```\ninitProps takes one argument that is a path to a function you can call at any time to set the props for the wrapped component. \n\nIt also allows you to return json encoded as a string that will be combined/overwrite existing props of the component on startup.\n\nTo set the props in the future (Java example):\n\n```java\npublic void updateProps(final Props props) {\n\tfinal String jsToResolve = mPropsSetCallback + \"(\\\"\"+ new Gson().toJson(props) +\"\\\")\";\n\twebView.evaluateJavascript(\"javascript:\" + jsToResolve, null);\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmtek%2Fpreact-pwa-native-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftmtek%2Fpreact-pwa-native-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmtek%2Fpreact-pwa-native-bridge/lists"}