{"id":18369831,"url":"https://github.com/cawfree/pyongyang","last_synced_at":"2025-04-06T18:32:33.802Z","repository":{"id":65481467,"uuid":"304883816","full_name":"cawfree/pyongyang","owner":"cawfree","description":"⚛️ 📱 The quickest way to utilize web dependencies inside React Native.","archived":false,"fork":false,"pushed_at":"2020-10-22T16:32:55.000Z","size":1226,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-18T12:35:22.840Z","etag":null,"topics":["arweave","graphql","ipfs","react-native","web","webview"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cawfree.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-17T13:27:41.000Z","updated_at":"2024-05-30T11:26:56.000Z","dependencies_parsed_at":"2023-01-25T16:31:06.710Z","dependency_job_id":null,"html_url":"https://github.com/cawfree/pyongyang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cawfree%2Fpyongyang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cawfree%2Fpyongyang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cawfree%2Fpyongyang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cawfree%2Fpyongyang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cawfree","download_url":"https://codeload.github.com/cawfree/pyongyang/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247531331,"owners_count":20953936,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["arweave","graphql","ipfs","react-native","web","webview"],"created_at":"2024-11-05T23:32:28.559Z","updated_at":"2025-04-06T18:32:32.200Z","avatar_url":"https://github.com/cawfree.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pyongyang\nThe simplest way to integrate with JS dependencies designed for the Web within [**React Native**](https://reactnative.dev).\n\n\u003e ⚠️ **Warning:** Pyongyang is super experimental. Don't do anything sensitive or important with it, just have fun. 🙏\n\n### 🔥 Features\n  - Execute **any** standard web dependency within React Native!\n    - [`Web3`](https://github.com/ethereum/web3.js/), [`Arweave`](https://www.arweave.org/), [`IPFS`](https://ipfs.io/) etc.\n  - Back-and forth encryption.\n    - Data is passed back and forth using an encrypted dynamic secret persisted in obfuscated source.\n    - Every time your hook is amounted, the secret is recycled.\n  - XSS Resistant\n    - All input variables are passed through stringification first, turning executable code into safe strings.\n  - Supports ES6.\n  - Supports Android, iOS and the Web!\n\n## 🚀 Getting Started\n\nUsing [**Yarn**]():\n\n```bash\nyarn add react-native-webview pyongyang\n```\n\n## 📚 Guide\n\n### 1. Hello, world!\n\nIn the following example, we show how simple it is to invoke a JavaScript runtime running in a hidden managed [`WebView`](). First, we declare a [`Pyongyang`](./) [**Provider**](https://reactjs.org/docs/context.html) at the root of the application; this component manages the instantiation of `WebView`s to execute your scripts.\n\nInside the `Hello` component, we make a call to the `pyongyang` [**hook**](https://reactjs.org/docs/hooks-intro.html):\n\n```javascript\nimport * as React from \"react\";\nimport Pyongyang, { pyongyang } from \"pyongyang\";\n\nfunction Hello() {\n  pyongyang`alert('hello, world')`;\n  return null;\n}\n\nexport default function () {\n  return \u003cPyongyang\u003e\u003cHello /\u003e\u003c/Pyongyang\u003e;\n}\n```\n\nUpon load, the defined script is executed by an anonymous WebView, which cannot be seen or interacted with. This is because `pyongyang` is designed for pure computation.\n\n### 2. Variables\n\nLet's make things a little more complicated. This time, using the `variables` parameter, we can pass data from the React Native runtime into the target JavaScript engine. These variables can be referenced in supplied code by prefixing the variable name with a `$`.\n\nIn this instance, the variable `name` is referenced using `$name`.\n\n```javascript\nimport * as React from \"react\";\nimport Pyongyang, { pyongyang } from \"pyongyang\";\n\nfunction Variables() {\n  pyongyang(`await alert('hello, $name')`, { variables: { name: \"world\" } });\n  return null;\n}\n\nexport default function () {\n  return \u003cPyongyang\u003e\u003cVariables /\u003e\u003c/Pyongyang\u003e;\n}\n```\n\n\u003e **Note:** Notice that your code is executed within an `async` block.\n\n### 3. Callbacks\n\nIt's also simple to accept callbacks from [`pyongyang`](./). Here, the `onMessage` callback is referenced via `$onMessage`.\n\n```javascript\nimport * as React from \"react\";\nimport { Alert } from \"react-native\";\nimport Pyongyang, { pyongyang } from \"pyongyang\";\n\nfunction Callbacks() {\n  const onMessage = React.useCallback(message =\u003e console.log(message), []);\n  pyongyang(`$onMessage('hello, world!')`, { callbacks: { onMessage } });\n  return null;\n}\n\nexport default function () {\n  return \u003cPyongyang\u003e\u003cCallbacks /\u003e\u003c/Pyongyang\u003e;\n}\n```\n\n### 4. Dependencies\n\nHere's where things get interesting. It's possible to pass [**CDN**](https://www.jsdelivr.com/) script references into `pyongyang`, which become available in the window object. These external JavaScript resources can be specified using the `resources` prop.\n\nIn the example below, it's trivial to utilize the [**Interplanetary File System (IPFS)**](https://ipfs.io/) directly inline, without making any native changes.\n\n```javascript\nimport * as React from \"react\";\n\nimport Pyongyang, { pyongyang } from \"pyongyang\";\n\nfunction Ipfs() {\n  const {} = pyongyang(`\n  const node = await Ipfs.create();\n  $onNodeCreated(await node.id());\n`, {\n      resources: [\"https://unpkg.com/ipfs/dist/index.min.js\"],\n      callbacks: { onNodeCreated: console.warn },\n    },\n  );\n  return null;\n}\n\nexport default function () {\n  return \u003cPyongyang\u003e\u003cIpfs /\u003e\u003c/Pyongyang\u003e;\n};\n```\n\n### 5. Futures\n\nIt's also possible to execute in `pyongyang` after the initial script has been executed. Your script is allowed to return an object of functions which you'd like to expose back to the native runtime. These can be executed asynchronously, and retain the scope of the original function call.\n\n```javascript\nimport * as React from \"react\";\n\nimport Pyongyang, { pyongyang } from \"pyongyang\";\n\nfunction Futures() {\n  const { loading, error, futures: { myFunction } } = pyongyang`\n  const myFunction = i =\u003e i + 1;\n  return { myFunction };\n`;\n  React.useEffect(() =\u003e {\n    !!myFunction \u0026\u0026 (async () =\u003e {\n      const result = await myFunction(4);\n      console.warn(result === 5); // true\n    })();\n  }, [loading, myFunction]);\n  return null;\n}\n\nexport default function () {\n  return \u003cPyongyang\u003e\u003cFutures /\u003e\u003c/Pyongyang\u003e;\n}\n```\n\n### 6. Refs\n\nSince the JavaScript code you execute happens inside of a `WebView`, rich objects cannot be passed back into React Native; they can only be transported in a way that can be represented using JSON. Therefore, if you wish to hold onto the runtime representation of an object for use later, you need to use a **ref**, which is basically a reference to an object which can be retained and used later.\n\nTo highlight a method as a ref, prefix the method name using a `$`.\n\n```javascript\nimport * as React from \"react\";\n\nimport Pyongyang, { pyongyang } from \"pyongyang\";\n\nfunction Refs() {\n  const { loading, error, futures } = pyongyang`\n  return {\n    $get: msg =\u003e {\n      someValue: 5,\n      doSomething: () =\u003e alert(msg),\n    },\n    doSomethingWith: e =\u003e e.doSomething(),\n  };\n`;\n  React.useEffect(() =\u003e {\n    !!Object.keys(futures.length) \u0026\u0026 (async () =\u003e {\n      const { doSomethingWith, $get } = futures;\n      const x = await $get(\"Hello!\");\n      console.log(x); // e.g. \"2Zr_daUmdBwjxfMQIT0er\"\n      await doSomethingWith(x); // alert('Hello!')\n    })();\n  }, [futures]);\n  return null;\n}\n\nexport default function () {\n  return \u003cPyongyang\u003e\u003cRefs /\u003e\u003c/Pyongyang\u003e;\n}\n```\n\n## ✌️ License\n[**MIT**](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcawfree%2Fpyongyang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcawfree%2Fpyongyang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcawfree%2Fpyongyang/lists"}