├── .github ├── assets │ ├── reactables-diagram.png │ └── reactables-wasm.png └── workflows │ ├── core-reactable.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── esbuild.js ├── examples ├── render.cs ├── render.ex ├── render.go ├── render.java ├── render.js ├── render.py └── render.rb ├── package-lock.json ├── package.json ├── shrinkwrap.sh ├── src ├── index.d.ts ├── index.jsx └── prelude.js └── test2.json /.github/assets/reactables-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylibso/reactables/bf6c64cd043fb9083f880267961105baa4a251a4/.github/assets/reactables-diagram.png -------------------------------------------------------------------------------- /.github/assets/reactables-wasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylibso/reactables/bf6c64cd043fb9083f880267961105baa4a251a4/.github/assets/reactables-wasm.png -------------------------------------------------------------------------------- /.github/workflows/core-reactable.yml: -------------------------------------------------------------------------------- 1 | name: build-reactables-core 2 | run-name: ${{ github.actor }} is building the core reactable 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | get-extism: 8 | runs-on: ubuntu-latest 9 | env: 10 | TAG: v1.0.0-rc3 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Setup wasm-merge and wasm-opt 15 | run: | 16 | curl -L https://github.com/WebAssembly/binaryen/releases/download/version_116/binaryen-version_116-x86_64-linux.tar.gz > binaryen.tar.gz 17 | tar xvzf binaryen.tar.gz 18 | sudo cp binaryen-version_116/bin/wasm-merge /usr/local/bin 19 | sudo cp binaryen-version_116/bin/wasm-opt /usr/local/bin 20 | # test it out 21 | wasm-merge 22 | 23 | - name: Setup Extism JS-PDK 24 | run: | 25 | curl -L -O "https://github.com/extism/js-pdk/releases/download/$TAG/extism-js-x86_64-linux-$TAG.gz" 26 | gunzip extism-js*.gz 27 | sudo mv extism-js-* /usr/local/bin/extism-js 28 | chmod +x /usr/local/bin/extism-js 29 | extism-js 30 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | release: 4 | types: [created] 5 | 6 | jobs: 7 | release: 8 | env: 9 | EXTISM_JS_TAG: v1.0.0-rc3 10 | name: Build and Release Reactables 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | 16 | - name: Setup wasm-merge 17 | run: | 18 | curl -L https://github.com/WebAssembly/binaryen/releases/download/version_116/binaryen-version_116-x86_64-linux.tar.gz > binaryen.tar.gz 19 | tar xvzf binaryen.tar.gz 20 | sudo cp binaryen-version_116/bin/wasm-merge /usr/local/bin 21 | sudo cp binaryen-version_116/bin/wasm-opt /usr/local/bin 22 | wasm-merge --version 23 | 24 | - name: Setup Extism JS-PDK 25 | run: | 26 | curl -L -O "https://github.com/extism/js-pdk/releases/download/$EXTISM_JS_TAG/extism-js-x86_64-linux-$EXTISM_JS_TAG.gz" 27 | gunzip extism-js*.gz 28 | sudo mv extism-js-* /usr/local/bin/extism-js 29 | chmod +x /usr/local/bin/extism-js 30 | extism-js --version 31 | 32 | - name: Build 33 | run: | 34 | npm i 35 | npm run build 36 | cp dist/plugin.wasm ./reactable.core.wasm 37 | 38 | - name: Upload Artifact to Release 39 | uses: softprops/action-gh-release@v1 40 | with: 41 | if-no-files-found: error 42 | files: | 43 | *.wasm 44 | if: startsWith(github.ref, 'refs/tags/') 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023-present Dylibso, Inc. 190 | Licensed under the Apache License, Version 2.0 (the "License"); 191 | you may not use this file except in compliance with the License. 192 | You may obtain a copy of the License at 193 | 194 | http://www.apache.org/licenses/LICENSE-2.0 195 | 196 | Unless required by applicable law or agreed to in writing, software 197 | distributed under the License is distributed on an "AS IS" BASIS, 198 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 199 | See the License for the specific language governing permissions and 200 | limitations under the License. 201 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 | 5 | Reactables by Dylibso 6 | 7 |

8 |

Shrinkwrapped, Portable, & Secure React Components

9 | 10 | [Why](#why-reactables) · [Use Cases](#use-cases) · [Usage](#usage) · [Request Feature](https://github.com/dylibso/reactables/issues/new) 11 | 12 |
13 | 14 | Reactables bring the power of React and JSX to everyone's programming language of choice. 15 | Compile and render JSX templates securely from over 15 different programming languages including Python, Go, Java, Ruby, .NET, PHP, and more! 16 | 17 |

18 | 19 | 20 | Reactables by Dylibso 21 | 22 |

23 | 24 | ## Why Reactables? 25 | 26 | There are many embeddable templating languages (e.g., Handlebars.js, Mustache, Liquid, etc.) in the world today, but all suffer from a few shortcomings: 27 | 28 | - They lack expressivity and complexity turns messy (ie. non Turing-complete languages) 29 | - They can be unfamiliar to many users and come with a non-zero learning curve 30 | - They require users to leave all of their pre-built components behind and start from scratch 31 | - They are incompatible with popular web development tools (e.g. Webpack, ESBuild, etc.) 32 | 33 | In an ideal world, React/JSX could be used as a general purpose template engine and all of the above limitations would fade 34 | away, but alas: 35 | 36 | - You can only embed in JavaScript. What if your code base is written in something else or you have multiple languages? 37 | - What if your JSX templates are provided by a third party? That's not very secure... 38 | 39 | Enter Reactables! These happen to be the two primary problems that [Extism](https://extism.org) aims to solve. 40 | Reactables is distributed as an [Extism Plug-in](https://extism.org/docs/concepts/plug-in), so you can now compile and render React/JSX **safely** from within your programming language of choice. 41 | 42 | ## Use Cases 43 | 44 | 1. Your entire codebase is written in `` but you really want/need to render templates with JSX 45 | 2. You're a SaaS platform and you want to give your customers the ability to customize various artifacts and touch points such as hosted pages, emails, and PDFs. 46 | 47 | ## Features 48 | 49 | - Run arbritrary JavaScript / JSX in your code **securely**! 50 | - Suport for over 15 different host programming languages 51 | - Incorporate your favorite tooling, styling, and NPM packages (experimental) 52 | - Package up a full blown JSX app using ESBuild or Webpack 53 | - Build and distribute new Reactables from your component library. They're customizable and portable! 54 | 55 | ## Ready to Consume 56 | 57 | **Choose from pre-built Reactables that are ready to go out-of-the-box for your immediate enjoyment.** Each Reactable is implemented as 58 | a WebAssembly Module in the form of an [Extism Plugin](https://extism.org/docs/concepts/plug-in) that embeds React and other dependencies along with an interface to compile JSX templates and render them with supplied props. 59 | 60 | - **Reactable Core** provides a foundational plugin with React securely embedded to provide the core JSX compilation and rendering capabilities. Get it [here](https://github.com/dylibso/reactables/releases) 61 | 62 | ### Coming Soon 63 | - **Reactable Email** extends Reactable Core with components from [react-email](https://github.com/resendlabs/react-email) 64 | - **Reactable PDF** extends Reactable Core with components from [react-pdf](https://github.com/diegomura/react-pdf) 65 | 66 | ## Usage 67 | 68 | 1. Include the appropriate [Extism SDK](https://extism.org/docs/quickstart/host-quickstart) into your application 69 | 2. Instantiate your Reactable of choice as a new Extism Plugin 70 | 3. Call the `compileTemplate` function with your JSX template 71 | 4. Call the `render` function with your props 72 | 5. Voila! 73 | 74 | ### Example (Python) 75 | 76 | The following example embeds Reactable Core in a Python program to render a simple a JSX template with a customer name property. 77 | See the [examples directory](examples/) for examples in more languages. 78 | 79 | ```python 80 | import extism 81 | import json 82 | 83 | plugin_url = "https://github.com/dylibso/reactables/releases/latest/download/reactable.core.wasm" 84 | manifest = { "wasm": [ { "url": plugin_url } ] } 85 | reactable = extism.Plugin(manifest, wasi=True) 86 | 87 | # Take our JSX code as a string 88 | jsx_code = """ 89 | function App(props) { 90 | return

Hello, {props.customerName}!

91 | } 92 | """ 93 | 94 | # Compile the template and register it by name 95 | reactable.call('compileTemplate', json.dumps({ 96 | "name": "greeting-template", 97 | "code": jsx_code, 98 | })) 99 | 100 | # Render template by name, passing in some props 101 | props = { "customerName": "Benjamin" } 102 | html = reactable.call('render', json.dumps({ 103 | "name": "greeting-template", 104 | "props": props, 105 | })) 106 | 107 | print(html) 108 | #

Hello, Benjamin!

109 | ``` 110 | 111 | ## Build your own 112 | 113 | Reactable Core can be extended to create new and novel Reactables that incorporate other components, styles, packages, etc. 114 | 115 | -------------------------------------------------------------------------------- /esbuild.js: -------------------------------------------------------------------------------- 1 | const esbuild = require('esbuild'); 2 | const { NodeModulesPolyfillPlugin } = require('@esbuild-plugins/node-modules-polyfill') 3 | 4 | esbuild 5 | .build({ 6 | entryPoints: ['src/index.jsx'], 7 | outdir: 'dist', 8 | bundle: true, 9 | sourcemap: true, 10 | minify: false, // might want to use true for production build 11 | format: 'cjs', // needs to be CJS for now 12 | target: ['es2020'], // don't go over es2020 because quickjs doesn't support it 13 | plugins: [NodeModulesPolyfillPlugin()] 14 | }) 15 | 16 | -------------------------------------------------------------------------------- /examples/render.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Extism.Sdk; 3 | using System.Text.Json; 4 | 5 | namespace SerializeBasic 6 | { 7 | public class Template 8 | { 9 | public string Name { get; set; } 10 | public string Code { get; set; } 11 | } 12 | 13 | public class Invocation 14 | { 15 | public string Name { get; set; } 16 | public Dictionary Props { get; set; } 17 | } 18 | 19 | public class Program 20 | { 21 | public static void Main() 22 | { 23 | var manifest = new Manifest(new UrlWasmSource("https://github.com/dylibso/reactables/releases/latest/download/reactable.core.wasm")); 24 | using var reactable = new Plugin(manifest, new HostFunction[] { }, withWasi: true); 25 | 26 | var template = new Template 27 | { 28 | Name = "greeting-template", 29 | Code = @" 30 | function App(props) { 31 | return

Hello, {props.customerName}!

32 | } 33 | " 34 | }; 35 | 36 | string templString = JsonSerializer.Serialize(template); 37 | reactable.Call("compileTemplate", templString); 38 | 39 | var invocation = new Invocation 40 | { 41 | Name = "greeting-template", 42 | Props = new Dictionary() { 43 | { "customerName", "Benjamin" } 44 | } 45 | }; 46 | 47 | 48 | string invocationString = JsonSerializer.Serialize(invocation); 49 | var result = reactable.Call("render", invocationString); 50 | Console.WriteLine(result); 51 | } 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /examples/render.ex: -------------------------------------------------------------------------------- 1 | url = "https://github.com/dylibso/reactables/releases/latest/download/reactble.core.wasm" 2 | manifest = %{wasm: [%{url: url}]} 3 | {:ok, reactable} = Extism.Plugin.new(manifest, true) 4 | 5 | # Define the JSX template 6 | templ = %{ 7 | "name" => "greeting-template", 8 | "code" => """ 9 | function App(props) { 10 | return

Hello, {props.customerName}!

11 | } 12 | """ 13 | } 14 | 15 | # Compile the template and register it by name 16 | reactable.call("compileTemplate", Jason.encode!(templ)) 17 | 18 | # Define props and render the template 19 | props = %{ "customerName" => "Benjamin" } 20 | html = reactable.call("render", Jason.encode!(%{ "props" => props, "name" => "greeting-template" })) 21 | 22 | IO.puts(html) 23 | 24 | -------------------------------------------------------------------------------- /examples/render.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "github.com/extism/go-sdk" 8 | "os" 9 | ) 10 | 11 | type Template struct { 12 | Name string `json:"name"` 13 | Code string `json:"code"` 14 | } 15 | 16 | type Invocation struct { 17 | Name string `json:"name"` 18 | Props map[string]interface{} `json:"props"` 19 | } 20 | 21 | func main() { 22 | manifest := extism.Manifest{ 23 | Wasm: []extism.Wasm{ 24 | extism.WasmUrl{ 25 | Url: "https://github.com/dylibso/reactables/releases/latest/download/reactable.core.wasm", 26 | }, 27 | }, 28 | } 29 | 30 | ctx := context.Background() 31 | config := extism.PluginConfig{ 32 | EnableWasi: true, 33 | } 34 | reactable, err := extism.NewPlugin(ctx, manifest, config, []extism.HostFunction{}) 35 | 36 | if err != nil { 37 | fmt.Printf("Failed to initialize plugin: %v\n", err) 38 | os.Exit(1) 39 | } 40 | 41 | jsx_code := ` 42 | function App(props) { 43 | return

Hello, {props.customerName}!

44 | } 45 | ` 46 | 47 | templ := Template{ 48 | Name: "greeting-template", 49 | Code: jsx_code, 50 | } 51 | 52 | templJson, err := json.Marshal(templ) 53 | if err != nil { 54 | fmt.Printf("Failed to initialize plugin: %v\n", err) 55 | os.Exit(1) 56 | } 57 | 58 | exit, _, err := reactable.Call("compileTemplate", templJson) 59 | if err != nil { 60 | fmt.Println(err) 61 | os.Exit(int(exit)) 62 | } 63 | 64 | var props map[string]interface{} 65 | props["customerName"] = "Benjamin" 66 | 67 | inv := Invocation{ 68 | Name: "greeting-template", 69 | Props: props, 70 | } 71 | 72 | invJson, err := json.Marshal(inv) 73 | if err != nil { 74 | fmt.Printf("Failed to marshal invocation: %v\n", err) 75 | os.Exit(1) 76 | } 77 | 78 | exit, out, err := reactable.Call("render", invJson) 79 | if err != nil { 80 | fmt.Println(err) 81 | os.Exit(int(exit)) 82 | } 83 | 84 | fmt.Println(string(out)) 85 | } 86 | -------------------------------------------------------------------------------- /examples/render.java: -------------------------------------------------------------------------------- 1 | import com.google.gson.Gson; 2 | import org.extism.sdk.manifest.Manifest; 3 | import org.extism.sdk.wasm.UrlWasmSource; 4 | import org.extism.sdk.Plugin; 5 | 6 | public class ReactableJava { 7 | static class Template { 8 | private String name; 9 | private String code; 10 | } 11 | 12 | static class Invocation { 13 | private String name; 14 | private Map props; 15 | } 16 | 17 | public static void main(String[] args) { 18 | var url = "https://github.com/dylibso/reactables/releases/latest/download/reactable.core.wasm"; 19 | var manifest = new Manifest(List.of(UrlWasmSource.fromUrl(url))); 20 | var reactable = new Plugin(manifest, true, null); 21 | 22 | Template template = new Template(); 23 | template.setName("greeting-template"); 24 | template.setCode( 25 | "function App(props) {\n" + 26 | " return

Hello, {props.customerName}!

\n" + 27 | "}"); 28 | 29 | Gson gson = new Gson(); 30 | String templString = gson.toJson(template); 31 | reactable.call("compileTemplate", templString); 32 | 33 | Invocation invocation = new Invocation(); 34 | invocation.setName("greeting-template"); 35 | Map props = new HashMap<>(); 36 | props.put("customerName", "Benjamin"); 37 | invocation.setProps(props); 38 | 39 | String invocationString = gson.toJson(invocation); 40 | String result = reactable.call("render", invocationString); 41 | System.out.println(result); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/render.js: -------------------------------------------------------------------------------- 1 | import createPlugin from '@extism/extism'; 2 | 3 | async function main() { 4 | const plugin = await createPlugin( 5 | 'https://github.com/dylibso/reactables/releases/latest/download/reactable.core.wasm', 6 | { useWasi: true } 7 | ); 8 | 9 | const templ = { 10 | name: "greeting-template", 11 | code: ` 12 | function App(props) { 13 | return

Hello, {props.customerName}!

14 | } 15 | ` 16 | } 17 | 18 | await plugin.call("compileTemplate", JSON.stringify(templ)); 19 | 20 | const invocation = { 21 | name: "greeting-template", 22 | props: { customerName: "Benjamin" }, 23 | } 24 | 25 | let out = await plugin.call("render", JSON.stringify(invocation)); 26 | console.log(out.text()) 27 | } 28 | 29 | main() 30 | -------------------------------------------------------------------------------- /examples/render.py: -------------------------------------------------------------------------------- 1 | import extism 2 | import json 3 | 4 | manifest = { 5 | "wasm": [ 6 | { "url": "https://github.com/dylibso/reactables/releases/latest/download/reactable.core.wasm" } 7 | ] 8 | } 9 | reactable = extism.Plugin(manifest, wasi=True) 10 | 11 | # Take our JSX code as a string 12 | templ = { 13 | "name": "greeting-template", 14 | "code": """ 15 | function App(props) { 16 | return

Hello, {props.customerName}!

17 | } 18 | """ 19 | } 20 | 21 | # Compile the template and register it by name 22 | reactable.call('compileTemplate', json.dumps(templ)) 23 | 24 | # Render template by name passing in some props 25 | props = { "customerName": "Benjamin" } 26 | html = reactable.call('render', json.dumps({ "props": props, "name": "greeting-template" })) 27 | 28 | print(html) 29 | -------------------------------------------------------------------------------- /examples/render.rb: -------------------------------------------------------------------------------- 1 | require 'extism' 2 | 3 | url = 'https://github.com/extism/reactables/releases/latest/download/reactable.core.wasm' 4 | manifest = Extism::Manifest.from_url url 5 | reactable = Extism::Plugin.new(manifest) 6 | 7 | jsx_code = <<~JSX 8 | export function App(props) { 9 | return

Hello {props.customerName}!

10 | } 11 | JSX 12 | 13 | # Compile our JSX template and register by name 14 | reactable.call('compileTemplate', 15 | JSON.generate( 16 | name: 'greeting-template', 17 | code: jsx_code 18 | )) 19 | 20 | # Render with customer specific props 21 | props = { customerName: 'Benjamin' } 22 | html = reactable.call('render', 23 | JSON.generate( 24 | templateName: 'greeting-template', 25 | props: props 26 | )) 27 | 28 | puts html 29 | # =>

Hello Benjamin!

30 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-sandbox", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "react-sandbox", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@babel/core": "^7.23.3", 13 | "@babel/preset-react": "^7.23.3", 14 | "@esbuild-plugins/node-modules-polyfill": "^0.2.2", 15 | "react-dom": "^18.2.0", 16 | "react-tools": "^0.13.3" 17 | }, 18 | "devDependencies": { 19 | "esbuild": "^0.25.0" 20 | } 21 | }, 22 | "node_modules/@ampproject/remapping": { 23 | "version": "2.2.1", 24 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", 25 | "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", 26 | "dependencies": { 27 | "@jridgewell/gen-mapping": "^0.3.0", 28 | "@jridgewell/trace-mapping": "^0.3.9" 29 | }, 30 | "engines": { 31 | "node": ">=6.0.0" 32 | } 33 | }, 34 | "node_modules/@babel/code-frame": { 35 | "version": "7.22.13", 36 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", 37 | "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", 38 | "dependencies": { 39 | "@babel/highlight": "^7.22.13", 40 | "chalk": "^2.4.2" 41 | }, 42 | "engines": { 43 | "node": ">=6.9.0" 44 | } 45 | }, 46 | "node_modules/@babel/compat-data": { 47 | "version": "7.23.3", 48 | "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", 49 | "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", 50 | "engines": { 51 | "node": ">=6.9.0" 52 | } 53 | }, 54 | "node_modules/@babel/core": { 55 | "version": "7.23.3", 56 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", 57 | "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", 58 | "dependencies": { 59 | "@ampproject/remapping": "^2.2.0", 60 | "@babel/code-frame": "^7.22.13", 61 | "@babel/generator": "^7.23.3", 62 | "@babel/helper-compilation-targets": "^7.22.15", 63 | "@babel/helper-module-transforms": "^7.23.3", 64 | "@babel/helpers": "^7.23.2", 65 | "@babel/parser": "^7.23.3", 66 | "@babel/template": "^7.22.15", 67 | "@babel/traverse": "^7.23.3", 68 | "@babel/types": "^7.23.3", 69 | "convert-source-map": "^2.0.0", 70 | "debug": "^4.1.0", 71 | "gensync": "^1.0.0-beta.2", 72 | "json5": "^2.2.3", 73 | "semver": "^6.3.1" 74 | }, 75 | "engines": { 76 | "node": ">=6.9.0" 77 | }, 78 | "funding": { 79 | "type": "opencollective", 80 | "url": "https://opencollective.com/babel" 81 | } 82 | }, 83 | "node_modules/@babel/generator": { 84 | "version": "7.23.3", 85 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", 86 | "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", 87 | "dependencies": { 88 | "@babel/types": "^7.23.3", 89 | "@jridgewell/gen-mapping": "^0.3.2", 90 | "@jridgewell/trace-mapping": "^0.3.17", 91 | "jsesc": "^2.5.1" 92 | }, 93 | "engines": { 94 | "node": ">=6.9.0" 95 | } 96 | }, 97 | "node_modules/@babel/helper-annotate-as-pure": { 98 | "version": "7.22.5", 99 | "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", 100 | "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", 101 | "dependencies": { 102 | "@babel/types": "^7.22.5" 103 | }, 104 | "engines": { 105 | "node": ">=6.9.0" 106 | } 107 | }, 108 | "node_modules/@babel/helper-compilation-targets": { 109 | "version": "7.22.15", 110 | "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", 111 | "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", 112 | "dependencies": { 113 | "@babel/compat-data": "^7.22.9", 114 | "@babel/helper-validator-option": "^7.22.15", 115 | "browserslist": "^4.21.9", 116 | "lru-cache": "^5.1.1", 117 | "semver": "^6.3.1" 118 | }, 119 | "engines": { 120 | "node": ">=6.9.0" 121 | } 122 | }, 123 | "node_modules/@babel/helper-environment-visitor": { 124 | "version": "7.22.20", 125 | "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", 126 | "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", 127 | "engines": { 128 | "node": ">=6.9.0" 129 | } 130 | }, 131 | "node_modules/@babel/helper-function-name": { 132 | "version": "7.23.0", 133 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", 134 | "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", 135 | "dependencies": { 136 | "@babel/template": "^7.22.15", 137 | "@babel/types": "^7.23.0" 138 | }, 139 | "engines": { 140 | "node": ">=6.9.0" 141 | } 142 | }, 143 | "node_modules/@babel/helper-hoist-variables": { 144 | "version": "7.22.5", 145 | "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", 146 | "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", 147 | "dependencies": { 148 | "@babel/types": "^7.22.5" 149 | }, 150 | "engines": { 151 | "node": ">=6.9.0" 152 | } 153 | }, 154 | "node_modules/@babel/helper-module-imports": { 155 | "version": "7.22.15", 156 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", 157 | "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", 158 | "dependencies": { 159 | "@babel/types": "^7.22.15" 160 | }, 161 | "engines": { 162 | "node": ">=6.9.0" 163 | } 164 | }, 165 | "node_modules/@babel/helper-module-transforms": { 166 | "version": "7.23.3", 167 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", 168 | "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", 169 | "dependencies": { 170 | "@babel/helper-environment-visitor": "^7.22.20", 171 | "@babel/helper-module-imports": "^7.22.15", 172 | "@babel/helper-simple-access": "^7.22.5", 173 | "@babel/helper-split-export-declaration": "^7.22.6", 174 | "@babel/helper-validator-identifier": "^7.22.20" 175 | }, 176 | "engines": { 177 | "node": ">=6.9.0" 178 | }, 179 | "peerDependencies": { 180 | "@babel/core": "^7.0.0" 181 | } 182 | }, 183 | "node_modules/@babel/helper-plugin-utils": { 184 | "version": "7.22.5", 185 | "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", 186 | "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", 187 | "engines": { 188 | "node": ">=6.9.0" 189 | } 190 | }, 191 | "node_modules/@babel/helper-simple-access": { 192 | "version": "7.22.5", 193 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", 194 | "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", 195 | "dependencies": { 196 | "@babel/types": "^7.22.5" 197 | }, 198 | "engines": { 199 | "node": ">=6.9.0" 200 | } 201 | }, 202 | "node_modules/@babel/helper-split-export-declaration": { 203 | "version": "7.22.6", 204 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", 205 | "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", 206 | "dependencies": { 207 | "@babel/types": "^7.22.5" 208 | }, 209 | "engines": { 210 | "node": ">=6.9.0" 211 | } 212 | }, 213 | "node_modules/@babel/helper-string-parser": { 214 | "version": "7.22.5", 215 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", 216 | "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", 217 | "engines": { 218 | "node": ">=6.9.0" 219 | } 220 | }, 221 | "node_modules/@babel/helper-validator-identifier": { 222 | "version": "7.22.20", 223 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", 224 | "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", 225 | "engines": { 226 | "node": ">=6.9.0" 227 | } 228 | }, 229 | "node_modules/@babel/helper-validator-option": { 230 | "version": "7.22.15", 231 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", 232 | "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", 233 | "engines": { 234 | "node": ">=6.9.0" 235 | } 236 | }, 237 | "node_modules/@babel/helpers": { 238 | "version": "7.23.2", 239 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", 240 | "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", 241 | "dependencies": { 242 | "@babel/template": "^7.22.15", 243 | "@babel/traverse": "^7.23.2", 244 | "@babel/types": "^7.23.0" 245 | }, 246 | "engines": { 247 | "node": ">=6.9.0" 248 | } 249 | }, 250 | "node_modules/@babel/highlight": { 251 | "version": "7.22.20", 252 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", 253 | "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", 254 | "dependencies": { 255 | "@babel/helper-validator-identifier": "^7.22.20", 256 | "chalk": "^2.4.2", 257 | "js-tokens": "^4.0.0" 258 | }, 259 | "engines": { 260 | "node": ">=6.9.0" 261 | } 262 | }, 263 | "node_modules/@babel/parser": { 264 | "version": "7.23.3", 265 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", 266 | "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", 267 | "bin": { 268 | "parser": "bin/babel-parser.js" 269 | }, 270 | "engines": { 271 | "node": ">=6.0.0" 272 | } 273 | }, 274 | "node_modules/@babel/plugin-syntax-jsx": { 275 | "version": "7.23.3", 276 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", 277 | "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", 278 | "dependencies": { 279 | "@babel/helper-plugin-utils": "^7.22.5" 280 | }, 281 | "engines": { 282 | "node": ">=6.9.0" 283 | }, 284 | "peerDependencies": { 285 | "@babel/core": "^7.0.0-0" 286 | } 287 | }, 288 | "node_modules/@babel/plugin-transform-react-display-name": { 289 | "version": "7.23.3", 290 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz", 291 | "integrity": "sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==", 292 | "dependencies": { 293 | "@babel/helper-plugin-utils": "^7.22.5" 294 | }, 295 | "engines": { 296 | "node": ">=6.9.0" 297 | }, 298 | "peerDependencies": { 299 | "@babel/core": "^7.0.0-0" 300 | } 301 | }, 302 | "node_modules/@babel/plugin-transform-react-jsx": { 303 | "version": "7.22.15", 304 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", 305 | "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", 306 | "dependencies": { 307 | "@babel/helper-annotate-as-pure": "^7.22.5", 308 | "@babel/helper-module-imports": "^7.22.15", 309 | "@babel/helper-plugin-utils": "^7.22.5", 310 | "@babel/plugin-syntax-jsx": "^7.22.5", 311 | "@babel/types": "^7.22.15" 312 | }, 313 | "engines": { 314 | "node": ">=6.9.0" 315 | }, 316 | "peerDependencies": { 317 | "@babel/core": "^7.0.0-0" 318 | } 319 | }, 320 | "node_modules/@babel/plugin-transform-react-jsx-development": { 321 | "version": "7.22.5", 322 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", 323 | "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", 324 | "dependencies": { 325 | "@babel/plugin-transform-react-jsx": "^7.22.5" 326 | }, 327 | "engines": { 328 | "node": ">=6.9.0" 329 | }, 330 | "peerDependencies": { 331 | "@babel/core": "^7.0.0-0" 332 | } 333 | }, 334 | "node_modules/@babel/plugin-transform-react-pure-annotations": { 335 | "version": "7.23.3", 336 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", 337 | "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", 338 | "dependencies": { 339 | "@babel/helper-annotate-as-pure": "^7.22.5", 340 | "@babel/helper-plugin-utils": "^7.22.5" 341 | }, 342 | "engines": { 343 | "node": ">=6.9.0" 344 | }, 345 | "peerDependencies": { 346 | "@babel/core": "^7.0.0-0" 347 | } 348 | }, 349 | "node_modules/@babel/preset-react": { 350 | "version": "7.23.3", 351 | "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", 352 | "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", 353 | "dependencies": { 354 | "@babel/helper-plugin-utils": "^7.22.5", 355 | "@babel/helper-validator-option": "^7.22.15", 356 | "@babel/plugin-transform-react-display-name": "^7.23.3", 357 | "@babel/plugin-transform-react-jsx": "^7.22.15", 358 | "@babel/plugin-transform-react-jsx-development": "^7.22.5", 359 | "@babel/plugin-transform-react-pure-annotations": "^7.23.3" 360 | }, 361 | "engines": { 362 | "node": ">=6.9.0" 363 | }, 364 | "peerDependencies": { 365 | "@babel/core": "^7.0.0-0" 366 | } 367 | }, 368 | "node_modules/@babel/template": { 369 | "version": "7.22.15", 370 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", 371 | "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", 372 | "dependencies": { 373 | "@babel/code-frame": "^7.22.13", 374 | "@babel/parser": "^7.22.15", 375 | "@babel/types": "^7.22.15" 376 | }, 377 | "engines": { 378 | "node": ">=6.9.0" 379 | } 380 | }, 381 | "node_modules/@babel/traverse": { 382 | "version": "7.23.3", 383 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", 384 | "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", 385 | "dependencies": { 386 | "@babel/code-frame": "^7.22.13", 387 | "@babel/generator": "^7.23.3", 388 | "@babel/helper-environment-visitor": "^7.22.20", 389 | "@babel/helper-function-name": "^7.23.0", 390 | "@babel/helper-hoist-variables": "^7.22.5", 391 | "@babel/helper-split-export-declaration": "^7.22.6", 392 | "@babel/parser": "^7.23.3", 393 | "@babel/types": "^7.23.3", 394 | "debug": "^4.1.0", 395 | "globals": "^11.1.0" 396 | }, 397 | "engines": { 398 | "node": ">=6.9.0" 399 | } 400 | }, 401 | "node_modules/@babel/types": { 402 | "version": "7.23.3", 403 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", 404 | "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", 405 | "dependencies": { 406 | "@babel/helper-string-parser": "^7.22.5", 407 | "@babel/helper-validator-identifier": "^7.22.20", 408 | "to-fast-properties": "^2.0.0" 409 | }, 410 | "engines": { 411 | "node": ">=6.9.0" 412 | } 413 | }, 414 | "node_modules/@esbuild-plugins/node-modules-polyfill": { 415 | "version": "0.2.2", 416 | "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", 417 | "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", 418 | "dependencies": { 419 | "escape-string-regexp": "^4.0.0", 420 | "rollup-plugin-node-polyfills": "^0.2.1" 421 | }, 422 | "peerDependencies": { 423 | "esbuild": "*" 424 | } 425 | }, 426 | "node_modules/@esbuild-plugins/node-modules-polyfill/node_modules/escape-string-regexp": { 427 | "version": "4.0.0", 428 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 429 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 430 | "engines": { 431 | "node": ">=10" 432 | }, 433 | "funding": { 434 | "url": "https://github.com/sponsors/sindresorhus" 435 | } 436 | }, 437 | "node_modules/@esbuild/aix-ppc64": { 438 | "version": "0.25.0", 439 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", 440 | "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", 441 | "cpu": [ 442 | "ppc64" 443 | ], 444 | "license": "MIT", 445 | "optional": true, 446 | "os": [ 447 | "aix" 448 | ], 449 | "engines": { 450 | "node": ">=18" 451 | } 452 | }, 453 | "node_modules/@esbuild/android-arm": { 454 | "version": "0.25.0", 455 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", 456 | "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", 457 | "cpu": [ 458 | "arm" 459 | ], 460 | "license": "MIT", 461 | "optional": true, 462 | "os": [ 463 | "android" 464 | ], 465 | "engines": { 466 | "node": ">=18" 467 | } 468 | }, 469 | "node_modules/@esbuild/android-arm64": { 470 | "version": "0.25.0", 471 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", 472 | "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", 473 | "cpu": [ 474 | "arm64" 475 | ], 476 | "license": "MIT", 477 | "optional": true, 478 | "os": [ 479 | "android" 480 | ], 481 | "engines": { 482 | "node": ">=18" 483 | } 484 | }, 485 | "node_modules/@esbuild/android-x64": { 486 | "version": "0.25.0", 487 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", 488 | "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", 489 | "cpu": [ 490 | "x64" 491 | ], 492 | "license": "MIT", 493 | "optional": true, 494 | "os": [ 495 | "android" 496 | ], 497 | "engines": { 498 | "node": ">=18" 499 | } 500 | }, 501 | "node_modules/@esbuild/darwin-arm64": { 502 | "version": "0.25.0", 503 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", 504 | "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", 505 | "cpu": [ 506 | "arm64" 507 | ], 508 | "license": "MIT", 509 | "optional": true, 510 | "os": [ 511 | "darwin" 512 | ], 513 | "engines": { 514 | "node": ">=18" 515 | } 516 | }, 517 | "node_modules/@esbuild/darwin-x64": { 518 | "version": "0.25.0", 519 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", 520 | "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", 521 | "cpu": [ 522 | "x64" 523 | ], 524 | "license": "MIT", 525 | "optional": true, 526 | "os": [ 527 | "darwin" 528 | ], 529 | "engines": { 530 | "node": ">=18" 531 | } 532 | }, 533 | "node_modules/@esbuild/freebsd-arm64": { 534 | "version": "0.25.0", 535 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", 536 | "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", 537 | "cpu": [ 538 | "arm64" 539 | ], 540 | "license": "MIT", 541 | "optional": true, 542 | "os": [ 543 | "freebsd" 544 | ], 545 | "engines": { 546 | "node": ">=18" 547 | } 548 | }, 549 | "node_modules/@esbuild/freebsd-x64": { 550 | "version": "0.25.0", 551 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", 552 | "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", 553 | "cpu": [ 554 | "x64" 555 | ], 556 | "license": "MIT", 557 | "optional": true, 558 | "os": [ 559 | "freebsd" 560 | ], 561 | "engines": { 562 | "node": ">=18" 563 | } 564 | }, 565 | "node_modules/@esbuild/linux-arm": { 566 | "version": "0.25.0", 567 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", 568 | "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", 569 | "cpu": [ 570 | "arm" 571 | ], 572 | "license": "MIT", 573 | "optional": true, 574 | "os": [ 575 | "linux" 576 | ], 577 | "engines": { 578 | "node": ">=18" 579 | } 580 | }, 581 | "node_modules/@esbuild/linux-arm64": { 582 | "version": "0.25.0", 583 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", 584 | "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", 585 | "cpu": [ 586 | "arm64" 587 | ], 588 | "license": "MIT", 589 | "optional": true, 590 | "os": [ 591 | "linux" 592 | ], 593 | "engines": { 594 | "node": ">=18" 595 | } 596 | }, 597 | "node_modules/@esbuild/linux-ia32": { 598 | "version": "0.25.0", 599 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", 600 | "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", 601 | "cpu": [ 602 | "ia32" 603 | ], 604 | "license": "MIT", 605 | "optional": true, 606 | "os": [ 607 | "linux" 608 | ], 609 | "engines": { 610 | "node": ">=18" 611 | } 612 | }, 613 | "node_modules/@esbuild/linux-loong64": { 614 | "version": "0.25.0", 615 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", 616 | "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", 617 | "cpu": [ 618 | "loong64" 619 | ], 620 | "license": "MIT", 621 | "optional": true, 622 | "os": [ 623 | "linux" 624 | ], 625 | "engines": { 626 | "node": ">=18" 627 | } 628 | }, 629 | "node_modules/@esbuild/linux-mips64el": { 630 | "version": "0.25.0", 631 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", 632 | "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", 633 | "cpu": [ 634 | "mips64el" 635 | ], 636 | "license": "MIT", 637 | "optional": true, 638 | "os": [ 639 | "linux" 640 | ], 641 | "engines": { 642 | "node": ">=18" 643 | } 644 | }, 645 | "node_modules/@esbuild/linux-ppc64": { 646 | "version": "0.25.0", 647 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", 648 | "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", 649 | "cpu": [ 650 | "ppc64" 651 | ], 652 | "license": "MIT", 653 | "optional": true, 654 | "os": [ 655 | "linux" 656 | ], 657 | "engines": { 658 | "node": ">=18" 659 | } 660 | }, 661 | "node_modules/@esbuild/linux-riscv64": { 662 | "version": "0.25.0", 663 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", 664 | "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", 665 | "cpu": [ 666 | "riscv64" 667 | ], 668 | "license": "MIT", 669 | "optional": true, 670 | "os": [ 671 | "linux" 672 | ], 673 | "engines": { 674 | "node": ">=18" 675 | } 676 | }, 677 | "node_modules/@esbuild/linux-s390x": { 678 | "version": "0.25.0", 679 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", 680 | "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", 681 | "cpu": [ 682 | "s390x" 683 | ], 684 | "license": "MIT", 685 | "optional": true, 686 | "os": [ 687 | "linux" 688 | ], 689 | "engines": { 690 | "node": ">=18" 691 | } 692 | }, 693 | "node_modules/@esbuild/linux-x64": { 694 | "version": "0.25.0", 695 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", 696 | "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", 697 | "cpu": [ 698 | "x64" 699 | ], 700 | "license": "MIT", 701 | "optional": true, 702 | "os": [ 703 | "linux" 704 | ], 705 | "engines": { 706 | "node": ">=18" 707 | } 708 | }, 709 | "node_modules/@esbuild/netbsd-arm64": { 710 | "version": "0.25.0", 711 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", 712 | "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", 713 | "cpu": [ 714 | "arm64" 715 | ], 716 | "license": "MIT", 717 | "optional": true, 718 | "os": [ 719 | "netbsd" 720 | ], 721 | "engines": { 722 | "node": ">=18" 723 | } 724 | }, 725 | "node_modules/@esbuild/netbsd-x64": { 726 | "version": "0.25.0", 727 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", 728 | "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", 729 | "cpu": [ 730 | "x64" 731 | ], 732 | "license": "MIT", 733 | "optional": true, 734 | "os": [ 735 | "netbsd" 736 | ], 737 | "engines": { 738 | "node": ">=18" 739 | } 740 | }, 741 | "node_modules/@esbuild/openbsd-arm64": { 742 | "version": "0.25.0", 743 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", 744 | "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", 745 | "cpu": [ 746 | "arm64" 747 | ], 748 | "license": "MIT", 749 | "optional": true, 750 | "os": [ 751 | "openbsd" 752 | ], 753 | "engines": { 754 | "node": ">=18" 755 | } 756 | }, 757 | "node_modules/@esbuild/openbsd-x64": { 758 | "version": "0.25.0", 759 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", 760 | "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", 761 | "cpu": [ 762 | "x64" 763 | ], 764 | "license": "MIT", 765 | "optional": true, 766 | "os": [ 767 | "openbsd" 768 | ], 769 | "engines": { 770 | "node": ">=18" 771 | } 772 | }, 773 | "node_modules/@esbuild/sunos-x64": { 774 | "version": "0.25.0", 775 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", 776 | "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", 777 | "cpu": [ 778 | "x64" 779 | ], 780 | "license": "MIT", 781 | "optional": true, 782 | "os": [ 783 | "sunos" 784 | ], 785 | "engines": { 786 | "node": ">=18" 787 | } 788 | }, 789 | "node_modules/@esbuild/win32-arm64": { 790 | "version": "0.25.0", 791 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", 792 | "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", 793 | "cpu": [ 794 | "arm64" 795 | ], 796 | "license": "MIT", 797 | "optional": true, 798 | "os": [ 799 | "win32" 800 | ], 801 | "engines": { 802 | "node": ">=18" 803 | } 804 | }, 805 | "node_modules/@esbuild/win32-ia32": { 806 | "version": "0.25.0", 807 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", 808 | "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", 809 | "cpu": [ 810 | "ia32" 811 | ], 812 | "license": "MIT", 813 | "optional": true, 814 | "os": [ 815 | "win32" 816 | ], 817 | "engines": { 818 | "node": ">=18" 819 | } 820 | }, 821 | "node_modules/@esbuild/win32-x64": { 822 | "version": "0.25.0", 823 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", 824 | "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", 825 | "cpu": [ 826 | "x64" 827 | ], 828 | "license": "MIT", 829 | "optional": true, 830 | "os": [ 831 | "win32" 832 | ], 833 | "engines": { 834 | "node": ">=18" 835 | } 836 | }, 837 | "node_modules/@jridgewell/gen-mapping": { 838 | "version": "0.3.3", 839 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 840 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 841 | "dependencies": { 842 | "@jridgewell/set-array": "^1.0.1", 843 | "@jridgewell/sourcemap-codec": "^1.4.10", 844 | "@jridgewell/trace-mapping": "^0.3.9" 845 | }, 846 | "engines": { 847 | "node": ">=6.0.0" 848 | } 849 | }, 850 | "node_modules/@jridgewell/resolve-uri": { 851 | "version": "3.1.1", 852 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", 853 | "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", 854 | "engines": { 855 | "node": ">=6.0.0" 856 | } 857 | }, 858 | "node_modules/@jridgewell/set-array": { 859 | "version": "1.1.2", 860 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 861 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 862 | "engines": { 863 | "node": ">=6.0.0" 864 | } 865 | }, 866 | "node_modules/@jridgewell/sourcemap-codec": { 867 | "version": "1.4.15", 868 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 869 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" 870 | }, 871 | "node_modules/@jridgewell/trace-mapping": { 872 | "version": "0.3.20", 873 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", 874 | "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", 875 | "dependencies": { 876 | "@jridgewell/resolve-uri": "^3.1.0", 877 | "@jridgewell/sourcemap-codec": "^1.4.14" 878 | } 879 | }, 880 | "node_modules/acorn": { 881 | "version": "5.7.4", 882 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", 883 | "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", 884 | "bin": { 885 | "acorn": "bin/acorn" 886 | }, 887 | "engines": { 888 | "node": ">=0.4.0" 889 | } 890 | }, 891 | "node_modules/amdefine": { 892 | "version": "1.0.1", 893 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 894 | "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", 895 | "engines": { 896 | "node": ">=0.4.2" 897 | } 898 | }, 899 | "node_modules/ansi-styles": { 900 | "version": "3.2.1", 901 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 902 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 903 | "dependencies": { 904 | "color-convert": "^1.9.0" 905 | }, 906 | "engines": { 907 | "node": ">=4" 908 | } 909 | }, 910 | "node_modules/ast-types": { 911 | "version": "0.9.6", 912 | "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", 913 | "integrity": "sha512-qEdtR2UH78yyHX/AUNfXmJTlM48XoFZKBdwi1nzkI1mJL21cmbu0cvjxjpkXJ5NENMq42H+hNs8VLJcqXLerBQ==", 914 | "engines": { 915 | "node": ">= 0.8" 916 | } 917 | }, 918 | "node_modules/balanced-match": { 919 | "version": "1.0.2", 920 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 921 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 922 | }, 923 | "node_modules/base62": { 924 | "version": "0.1.1", 925 | "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz", 926 | "integrity": "sha512-QtExujIOq/F672OkHmDi3CdkphOA1kSQ38gv03Ro3cplYQk831dq9GM3Q1oXAxpR5HNJjGjjjT2pHtBGAJu1jw==", 927 | "engines": { 928 | "node": "*" 929 | } 930 | }, 931 | "node_modules/brace-expansion": { 932 | "version": "1.1.11", 933 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 934 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 935 | "dependencies": { 936 | "balanced-match": "^1.0.0", 937 | "concat-map": "0.0.1" 938 | } 939 | }, 940 | "node_modules/browserslist": { 941 | "version": "4.22.1", 942 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", 943 | "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", 944 | "funding": [ 945 | { 946 | "type": "opencollective", 947 | "url": "https://opencollective.com/browserslist" 948 | }, 949 | { 950 | "type": "tidelift", 951 | "url": "https://tidelift.com/funding/github/npm/browserslist" 952 | }, 953 | { 954 | "type": "github", 955 | "url": "https://github.com/sponsors/ai" 956 | } 957 | ], 958 | "dependencies": { 959 | "caniuse-lite": "^1.0.30001541", 960 | "electron-to-chromium": "^1.4.535", 961 | "node-releases": "^2.0.13", 962 | "update-browserslist-db": "^1.0.13" 963 | }, 964 | "bin": { 965 | "browserslist": "cli.js" 966 | }, 967 | "engines": { 968 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 969 | } 970 | }, 971 | "node_modules/caniuse-lite": { 972 | "version": "1.0.30001563", 973 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", 974 | "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", 975 | "funding": [ 976 | { 977 | "type": "opencollective", 978 | "url": "https://opencollective.com/browserslist" 979 | }, 980 | { 981 | "type": "tidelift", 982 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 983 | }, 984 | { 985 | "type": "github", 986 | "url": "https://github.com/sponsors/ai" 987 | } 988 | ] 989 | }, 990 | "node_modules/chalk": { 991 | "version": "2.4.2", 992 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 993 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 994 | "dependencies": { 995 | "ansi-styles": "^3.2.1", 996 | "escape-string-regexp": "^1.0.5", 997 | "supports-color": "^5.3.0" 998 | }, 999 | "engines": { 1000 | "node": ">=4" 1001 | } 1002 | }, 1003 | "node_modules/color-convert": { 1004 | "version": "1.9.3", 1005 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 1006 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 1007 | "dependencies": { 1008 | "color-name": "1.1.3" 1009 | } 1010 | }, 1011 | "node_modules/color-convert/node_modules/color-name": { 1012 | "version": "1.1.3", 1013 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 1014 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" 1015 | }, 1016 | "node_modules/commander": { 1017 | "version": "2.20.3", 1018 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 1019 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 1020 | }, 1021 | "node_modules/commoner": { 1022 | "version": "0.10.8", 1023 | "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", 1024 | "integrity": "sha512-3/qHkNMM6o/KGXHITA14y78PcfmXh4+AOCJpSoF73h4VY1JpdGv3CHMS5+JW6SwLhfJt4RhNmLAa7+RRX/62EQ==", 1025 | "dependencies": { 1026 | "commander": "^2.5.0", 1027 | "detective": "^4.3.1", 1028 | "glob": "^5.0.15", 1029 | "graceful-fs": "^4.1.2", 1030 | "iconv-lite": "^0.4.5", 1031 | "mkdirp": "^0.5.0", 1032 | "private": "^0.1.6", 1033 | "q": "^1.1.2", 1034 | "recast": "^0.11.17" 1035 | }, 1036 | "bin": { 1037 | "commonize": "bin/commonize" 1038 | }, 1039 | "engines": { 1040 | "node": ">= 0.8" 1041 | } 1042 | }, 1043 | "node_modules/concat-map": { 1044 | "version": "0.0.1", 1045 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1046 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 1047 | }, 1048 | "node_modules/convert-source-map": { 1049 | "version": "2.0.0", 1050 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", 1051 | "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" 1052 | }, 1053 | "node_modules/debug": { 1054 | "version": "4.3.4", 1055 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1056 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1057 | "dependencies": { 1058 | "ms": "2.1.2" 1059 | }, 1060 | "engines": { 1061 | "node": ">=6.0" 1062 | }, 1063 | "peerDependenciesMeta": { 1064 | "supports-color": { 1065 | "optional": true 1066 | } 1067 | } 1068 | }, 1069 | "node_modules/defined": { 1070 | "version": "1.0.1", 1071 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", 1072 | "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", 1073 | "funding": { 1074 | "url": "https://github.com/sponsors/ljharb" 1075 | } 1076 | }, 1077 | "node_modules/detective": { 1078 | "version": "4.7.1", 1079 | "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", 1080 | "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", 1081 | "dependencies": { 1082 | "acorn": "^5.2.1", 1083 | "defined": "^1.0.0" 1084 | } 1085 | }, 1086 | "node_modules/electron-to-chromium": { 1087 | "version": "1.4.588", 1088 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", 1089 | "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==" 1090 | }, 1091 | "node_modules/esbuild": { 1092 | "version": "0.25.0", 1093 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", 1094 | "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", 1095 | "hasInstallScript": true, 1096 | "license": "MIT", 1097 | "bin": { 1098 | "esbuild": "bin/esbuild" 1099 | }, 1100 | "engines": { 1101 | "node": ">=18" 1102 | }, 1103 | "optionalDependencies": { 1104 | "@esbuild/aix-ppc64": "0.25.0", 1105 | "@esbuild/android-arm": "0.25.0", 1106 | "@esbuild/android-arm64": "0.25.0", 1107 | "@esbuild/android-x64": "0.25.0", 1108 | "@esbuild/darwin-arm64": "0.25.0", 1109 | "@esbuild/darwin-x64": "0.25.0", 1110 | "@esbuild/freebsd-arm64": "0.25.0", 1111 | "@esbuild/freebsd-x64": "0.25.0", 1112 | "@esbuild/linux-arm": "0.25.0", 1113 | "@esbuild/linux-arm64": "0.25.0", 1114 | "@esbuild/linux-ia32": "0.25.0", 1115 | "@esbuild/linux-loong64": "0.25.0", 1116 | "@esbuild/linux-mips64el": "0.25.0", 1117 | "@esbuild/linux-ppc64": "0.25.0", 1118 | "@esbuild/linux-riscv64": "0.25.0", 1119 | "@esbuild/linux-s390x": "0.25.0", 1120 | "@esbuild/linux-x64": "0.25.0", 1121 | "@esbuild/netbsd-arm64": "0.25.0", 1122 | "@esbuild/netbsd-x64": "0.25.0", 1123 | "@esbuild/openbsd-arm64": "0.25.0", 1124 | "@esbuild/openbsd-x64": "0.25.0", 1125 | "@esbuild/sunos-x64": "0.25.0", 1126 | "@esbuild/win32-arm64": "0.25.0", 1127 | "@esbuild/win32-ia32": "0.25.0", 1128 | "@esbuild/win32-x64": "0.25.0" 1129 | } 1130 | }, 1131 | "node_modules/escalade": { 1132 | "version": "3.1.1", 1133 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 1134 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 1135 | "engines": { 1136 | "node": ">=6" 1137 | } 1138 | }, 1139 | "node_modules/escape-string-regexp": { 1140 | "version": "1.0.5", 1141 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 1142 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 1143 | "engines": { 1144 | "node": ">=0.8.0" 1145 | } 1146 | }, 1147 | "node_modules/esprima": { 1148 | "version": "3.1.3", 1149 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", 1150 | "integrity": "sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==", 1151 | "bin": { 1152 | "esparse": "bin/esparse.js", 1153 | "esvalidate": "bin/esvalidate.js" 1154 | }, 1155 | "engines": { 1156 | "node": ">=4" 1157 | } 1158 | }, 1159 | "node_modules/esprima-fb": { 1160 | "version": "13001.1001.0-dev-harmony-fb", 1161 | "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz", 1162 | "integrity": "sha512-u0PLCs9J36198vK7lFdvzfOiMT2v2K9/9d+J2M4d1ZEfTsXzvrzRHh95D+/sIziSabl4b6QKJOTn8+VaWc/B4A==", 1163 | "bin": { 1164 | "esparse": "bin/esparse.js", 1165 | "esvalidate": "bin/esvalidate.js" 1166 | }, 1167 | "engines": { 1168 | "node": ">=0.4.0" 1169 | } 1170 | }, 1171 | "node_modules/estree-walker": { 1172 | "version": "0.6.1", 1173 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 1174 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" 1175 | }, 1176 | "node_modules/gensync": { 1177 | "version": "1.0.0-beta.2", 1178 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 1179 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 1180 | "engines": { 1181 | "node": ">=6.9.0" 1182 | } 1183 | }, 1184 | "node_modules/glob": { 1185 | "version": "5.0.15", 1186 | "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", 1187 | "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", 1188 | "dependencies": { 1189 | "inflight": "^1.0.4", 1190 | "inherits": "2", 1191 | "minimatch": "2 || 3", 1192 | "once": "^1.3.0", 1193 | "path-is-absolute": "^1.0.0" 1194 | }, 1195 | "engines": { 1196 | "node": "*" 1197 | } 1198 | }, 1199 | "node_modules/globals": { 1200 | "version": "11.12.0", 1201 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 1202 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 1203 | "engines": { 1204 | "node": ">=4" 1205 | } 1206 | }, 1207 | "node_modules/graceful-fs": { 1208 | "version": "4.2.11", 1209 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1210 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" 1211 | }, 1212 | "node_modules/has-flag": { 1213 | "version": "3.0.0", 1214 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1215 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 1216 | "engines": { 1217 | "node": ">=4" 1218 | } 1219 | }, 1220 | "node_modules/iconv-lite": { 1221 | "version": "0.4.24", 1222 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1223 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1224 | "dependencies": { 1225 | "safer-buffer": ">= 2.1.2 < 3" 1226 | }, 1227 | "engines": { 1228 | "node": ">=0.10.0" 1229 | } 1230 | }, 1231 | "node_modules/inflight": { 1232 | "version": "1.0.6", 1233 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1234 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1235 | "dependencies": { 1236 | "once": "^1.3.0", 1237 | "wrappy": "1" 1238 | } 1239 | }, 1240 | "node_modules/inherits": { 1241 | "version": "2.0.4", 1242 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1243 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1244 | }, 1245 | "node_modules/js-tokens": { 1246 | "version": "4.0.0", 1247 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1248 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 1249 | }, 1250 | "node_modules/jsesc": { 1251 | "version": "2.5.2", 1252 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1253 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 1254 | "bin": { 1255 | "jsesc": "bin/jsesc" 1256 | }, 1257 | "engines": { 1258 | "node": ">=4" 1259 | } 1260 | }, 1261 | "node_modules/json5": { 1262 | "version": "2.2.3", 1263 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 1264 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 1265 | "bin": { 1266 | "json5": "lib/cli.js" 1267 | }, 1268 | "engines": { 1269 | "node": ">=6" 1270 | } 1271 | }, 1272 | "node_modules/jstransform": { 1273 | "version": "10.1.0", 1274 | "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz", 1275 | "integrity": "sha512-hzsCrPlH8ASlARV/sjsjbnvg0AXz9DxMHry44wXF3GTvletHT8UhsmqUzSGaImlney40E1gw4D6izUzifD15IQ==", 1276 | "dependencies": { 1277 | "base62": "0.1.1", 1278 | "esprima-fb": "13001.1001.0-dev-harmony-fb", 1279 | "source-map": "0.1.31" 1280 | }, 1281 | "engines": { 1282 | "node": ">=0.8.8" 1283 | } 1284 | }, 1285 | "node_modules/loose-envify": { 1286 | "version": "1.4.0", 1287 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 1288 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 1289 | "dependencies": { 1290 | "js-tokens": "^3.0.0 || ^4.0.0" 1291 | }, 1292 | "bin": { 1293 | "loose-envify": "cli.js" 1294 | } 1295 | }, 1296 | "node_modules/lru-cache": { 1297 | "version": "5.1.1", 1298 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 1299 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 1300 | "dependencies": { 1301 | "yallist": "^3.0.2" 1302 | } 1303 | }, 1304 | "node_modules/magic-string": { 1305 | "version": "0.25.9", 1306 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", 1307 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 1308 | "dependencies": { 1309 | "sourcemap-codec": "^1.4.8" 1310 | } 1311 | }, 1312 | "node_modules/minimatch": { 1313 | "version": "3.1.2", 1314 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1315 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1316 | "dependencies": { 1317 | "brace-expansion": "^1.1.7" 1318 | }, 1319 | "engines": { 1320 | "node": "*" 1321 | } 1322 | }, 1323 | "node_modules/minimist": { 1324 | "version": "1.2.8", 1325 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1326 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1327 | "funding": { 1328 | "url": "https://github.com/sponsors/ljharb" 1329 | } 1330 | }, 1331 | "node_modules/mkdirp": { 1332 | "version": "0.5.6", 1333 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 1334 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 1335 | "dependencies": { 1336 | "minimist": "^1.2.6" 1337 | }, 1338 | "bin": { 1339 | "mkdirp": "bin/cmd.js" 1340 | } 1341 | }, 1342 | "node_modules/ms": { 1343 | "version": "2.1.2", 1344 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1345 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1346 | }, 1347 | "node_modules/node-releases": { 1348 | "version": "2.0.13", 1349 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", 1350 | "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" 1351 | }, 1352 | "node_modules/once": { 1353 | "version": "1.4.0", 1354 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1355 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1356 | "dependencies": { 1357 | "wrappy": "1" 1358 | } 1359 | }, 1360 | "node_modules/path-is-absolute": { 1361 | "version": "1.0.1", 1362 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1363 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1364 | "engines": { 1365 | "node": ">=0.10.0" 1366 | } 1367 | }, 1368 | "node_modules/picocolors": { 1369 | "version": "1.0.0", 1370 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1371 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" 1372 | }, 1373 | "node_modules/private": { 1374 | "version": "0.1.8", 1375 | "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", 1376 | "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", 1377 | "engines": { 1378 | "node": ">= 0.6" 1379 | } 1380 | }, 1381 | "node_modules/q": { 1382 | "version": "1.5.1", 1383 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 1384 | "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", 1385 | "engines": { 1386 | "node": ">=0.6.0", 1387 | "teleport": ">=0.2.0" 1388 | } 1389 | }, 1390 | "node_modules/react": { 1391 | "version": "18.2.0", 1392 | "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", 1393 | "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", 1394 | "peer": true, 1395 | "dependencies": { 1396 | "loose-envify": "^1.1.0" 1397 | }, 1398 | "engines": { 1399 | "node": ">=0.10.0" 1400 | } 1401 | }, 1402 | "node_modules/react-dom": { 1403 | "version": "18.2.0", 1404 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", 1405 | "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", 1406 | "dependencies": { 1407 | "loose-envify": "^1.1.0", 1408 | "scheduler": "^0.23.0" 1409 | }, 1410 | "peerDependencies": { 1411 | "react": "^18.2.0" 1412 | } 1413 | }, 1414 | "node_modules/react-dom/node_modules/scheduler": { 1415 | "version": "0.23.0", 1416 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", 1417 | "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", 1418 | "dependencies": { 1419 | "loose-envify": "^1.1.0" 1420 | } 1421 | }, 1422 | "node_modules/react-tools": { 1423 | "version": "0.13.3", 1424 | "resolved": "https://registry.npmjs.org/react-tools/-/react-tools-0.13.3.tgz", 1425 | "integrity": "sha512-lmdjIRNk2cVUdlF/dyy6oP0nG2qrlX5qKFYRtiC5zK5Sg5QqgUEOrcS7Jz+kPNeOj9OWT7NfrR/cDvbGGSjCyg==", 1426 | "deprecated": "react-tools is deprecated. For more information, visit https://fb.me/react-tools-deprecated", 1427 | "dependencies": { 1428 | "commoner": "^0.10.0", 1429 | "jstransform": "^10.1.0" 1430 | }, 1431 | "bin": { 1432 | "jsx": "bin/jsx" 1433 | }, 1434 | "engines": { 1435 | "node": ">=0.10.0" 1436 | } 1437 | }, 1438 | "node_modules/recast": { 1439 | "version": "0.11.23", 1440 | "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", 1441 | "integrity": "sha512-+nixG+3NugceyR8O1bLU45qs84JgI3+8EauyRZafLgC9XbdAOIVgwV1Pe2da0YzGo62KzWoZwUpVEQf6qNAXWA==", 1442 | "dependencies": { 1443 | "ast-types": "0.9.6", 1444 | "esprima": "~3.1.0", 1445 | "private": "~0.1.5", 1446 | "source-map": "~0.5.0" 1447 | }, 1448 | "engines": { 1449 | "node": ">= 0.8" 1450 | } 1451 | }, 1452 | "node_modules/recast/node_modules/source-map": { 1453 | "version": "0.5.7", 1454 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1455 | "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", 1456 | "engines": { 1457 | "node": ">=0.10.0" 1458 | } 1459 | }, 1460 | "node_modules/rollup-plugin-inject": { 1461 | "version": "3.0.2", 1462 | "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", 1463 | "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", 1464 | "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", 1465 | "dependencies": { 1466 | "estree-walker": "^0.6.1", 1467 | "magic-string": "^0.25.3", 1468 | "rollup-pluginutils": "^2.8.1" 1469 | } 1470 | }, 1471 | "node_modules/rollup-plugin-node-polyfills": { 1472 | "version": "0.2.1", 1473 | "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", 1474 | "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", 1475 | "dependencies": { 1476 | "rollup-plugin-inject": "^3.0.0" 1477 | } 1478 | }, 1479 | "node_modules/rollup-pluginutils": { 1480 | "version": "2.8.2", 1481 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 1482 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 1483 | "dependencies": { 1484 | "estree-walker": "^0.6.1" 1485 | } 1486 | }, 1487 | "node_modules/safer-buffer": { 1488 | "version": "2.1.2", 1489 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1490 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1491 | }, 1492 | "node_modules/semver": { 1493 | "version": "6.3.1", 1494 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 1495 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 1496 | "bin": { 1497 | "semver": "bin/semver.js" 1498 | } 1499 | }, 1500 | "node_modules/source-map": { 1501 | "version": "0.1.31", 1502 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", 1503 | "integrity": "sha512-qFALUiKHo35Duky0Ubmb5YKj9b3c6CcgGNGeI60sd6Nn3KaY7h9fclEOcCVk0hwszwYYP6+X2/jpS5hHqqVuig==", 1504 | "dependencies": { 1505 | "amdefine": ">=0.0.4" 1506 | }, 1507 | "engines": { 1508 | "node": ">=0.8.0" 1509 | } 1510 | }, 1511 | "node_modules/sourcemap-codec": { 1512 | "version": "1.4.8", 1513 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 1514 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 1515 | "deprecated": "Please use @jridgewell/sourcemap-codec instead" 1516 | }, 1517 | "node_modules/supports-color": { 1518 | "version": "5.5.0", 1519 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1520 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1521 | "dependencies": { 1522 | "has-flag": "^3.0.0" 1523 | }, 1524 | "engines": { 1525 | "node": ">=4" 1526 | } 1527 | }, 1528 | "node_modules/to-fast-properties": { 1529 | "version": "2.0.0", 1530 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 1531 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", 1532 | "engines": { 1533 | "node": ">=4" 1534 | } 1535 | }, 1536 | "node_modules/update-browserslist-db": { 1537 | "version": "1.0.13", 1538 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", 1539 | "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", 1540 | "funding": [ 1541 | { 1542 | "type": "opencollective", 1543 | "url": "https://opencollective.com/browserslist" 1544 | }, 1545 | { 1546 | "type": "tidelift", 1547 | "url": "https://tidelift.com/funding/github/npm/browserslist" 1548 | }, 1549 | { 1550 | "type": "github", 1551 | "url": "https://github.com/sponsors/ai" 1552 | } 1553 | ], 1554 | "dependencies": { 1555 | "escalade": "^3.1.1", 1556 | "picocolors": "^1.0.0" 1557 | }, 1558 | "bin": { 1559 | "update-browserslist-db": "cli.js" 1560 | }, 1561 | "peerDependencies": { 1562 | "browserslist": ">= 4.21.0" 1563 | } 1564 | }, 1565 | "node_modules/wrappy": { 1566 | "version": "1.0.2", 1567 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1568 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1569 | }, 1570 | "node_modules/yallist": { 1571 | "version": "3.1.1", 1572 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 1573 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 1574 | } 1575 | } 1576 | } 1577 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-sandbox", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "node esbuild.js && extism-js dist/index.js -i src/index.d.ts -o dist/plugin.wasm" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "esbuild": "^0.25.0" 14 | }, 15 | "dependencies": { 16 | "@babel/core": "^7.23.3", 17 | "@babel/preset-react": "^7.23.3", 18 | "@esbuild-plugins/node-modules-polyfill": "^0.2.2", 19 | "react-dom": "^18.2.0", 20 | "react-tools": "^0.13.3" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /shrinkwrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This is a pretty hacky script to automatically wrap up 4 | # a third party component library into a reactable 5 | 6 | if [ "$#" -ne 3 ]; then 7 | echo "Usage: $0 " 8 | exit 1 9 | fi 10 | 11 | npm_package=$1 12 | prelude_file=$2 13 | output_file=$3 14 | 15 | cd /tmp 16 | 17 | git clone git@github.com:dylibso/reactables.git my-reactable 18 | cd my-reactable/ 19 | 20 | # do any npm installs you need for your library (might be a better way to assume this in something like a gh action) 21 | npm install $npm_package -E 22 | 23 | cp $prelude_file src/prelude.js 24 | 25 | # build it like normal 26 | npm run build 27 | 28 | cp dist/plugin.wasm $output_file 29 | cd .. 30 | rm -rf my-reactable 31 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'main' { 2 | export function run(): I32; 3 | export function compileTemplate(): I32; 4 | export function render(): I32; 5 | } 6 | -------------------------------------------------------------------------------- /src/index.jsx: -------------------------------------------------------------------------------- 1 | import { renderToString } from 'react-dom/server'; 2 | import React from 'react' 3 | import * as reactTools from 'react-tools' 4 | import * as Prelude from './prelude' 5 | 6 | function getGlobals() { 7 | const keys = Object 8 | .getOwnPropertyNames(Prelude) 9 | .filter(k => k !== "default") 10 | .sort(); 11 | const refs = keys.map(k => Prelude[k]) 12 | return [keys, refs] 13 | } 14 | 15 | export function compileTemplate() { 16 | const inputStr = Host.inputString() 17 | const { name, code } = JSON.parse(inputStr) 18 | Var.set(`template-${name}`, code) 19 | } 20 | 21 | export function render() { 22 | const { name, props } = JSON.parse(Host.inputString()) 23 | const code = Var.getString(`template-${name}`) 24 | let view = reactTools.transform(code, {}) + '; return App' 25 | let [globalKeys, globalRefs] = getGlobals() 26 | globalKeys.push('React') 27 | globalRefs.push(React) 28 | globalKeys.push(view) 29 | view = (new Function(...globalKeys))(...globalRefs) 30 | Host.outputString(renderToString(React.createElement(view, props, null))) 31 | } 32 | 33 | export function run() { 34 | let { view, props } = JSON.parse(Host.inputString()) 35 | view = reactTools.transform(view, {}) + '; return App;' 36 | let [globalKeys, globalRefs] = getGlobals() 37 | globalKeys.push('React') 38 | globalRefs.push(React) 39 | globalKeys.push(view) 40 | view = (new Function(...globalKeys))(...globalRefs) 41 | Host.outputString(renderToString(React.createElement(view, props, null))) 42 | } 43 | -------------------------------------------------------------------------------- /src/prelude.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dylibso/reactables/bf6c64cd043fb9083f880267961105baa4a251a4/src/prelude.js -------------------------------------------------------------------------------- /test2.json: -------------------------------------------------------------------------------- 1 | { 2 | "view": "function App(props) { return

Hello, {props.toWhat}

; }", 3 | "props": { 4 | "toWhat": "World!" 5 | } 6 | } 7 | --------------------------------------------------------------------------------