├── .gitignore ├── img └── demo.png ├── dfx.json ├── NOTICE ├── run.sh ├── package.json ├── .github └── workflows │ └── ci.yml ├── src ├── www │ ├── utilities │ │ └── idl.js │ ├── index.jsx │ └── components │ │ ├── delete.jsx │ │ ├── read.jsx │ │ ├── create.jsx │ │ └── update.jsx └── superheroes │ └── Main.mo ├── README.md ├── webpack.config.js └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dfx/ 3 | build/ 4 | node_modules/ 5 | -------------------------------------------------------------------------------- /img/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enzoh/superheroes/HEAD/img/demo.png -------------------------------------------------------------------------------- /dfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "canisters": { 3 | "superheroes": { 4 | "main": "src/superheroes/Main.mo" 5 | }, 6 | "www": { 7 | "dependencies": [ 8 | "superheroes" 9 | ], 10 | "frontend": { 11 | "entrypoint": "src/www/index.jsx" 12 | }, 13 | "type": "assets" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Enzo Haussecker 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | this file except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | echo PATH = $PATH 2 | echo vessel @ `which vessel` 3 | 4 | echo 5 | echo == Build. 6 | echo 7 | 8 | dfx start --background 9 | dfx canister create --all 10 | dfx build 11 | 12 | echo 13 | echo == Test. 14 | echo 15 | 16 | dfx canister install --all 17 | dfx canister call superheroes create '(record {name = "Superman"; superpowers = opt record { 0 = "invulnerability"; 1 = opt record { 0 = "superhuman strength"; 1 = null; }; }; })' 18 | dfx canister call superheroes read '(0)' 19 | dfx canister call superheroes update '(0, record {name = "Superman"; superpowers = opt record { 0 = "invulnerability"; 1 = opt record { 0 = "superhuman strength"; 1 = opt record { 0 = "flight"; 1 = opt record { 0 = "x-ray vision"; 1 = null; }; }; }; }; })' 20 | dfx canister call superheroes delete '(0)' 21 | dfx canister call www retrieve '("index.js")' 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "email": "enzo@dfinity.org", 4 | "name": "Enzo Haussecker" 5 | }, 6 | "contributors": [ 7 | { 8 | "email": "andrew.wylde@dfinity.org", 9 | "name": "Andrew Wylde" 10 | } 11 | ], 12 | "dependencies": { 13 | "@babel/core": "7.9.0", 14 | "@babel/preset-react": "7.9.0", 15 | "@dfinity/agent": "0.6.4", 16 | "babel-loader": "8.1.0", 17 | "react": "16.13.1", 18 | "react-dom": "16.13.1", 19 | "webpack": "4.43.0", 20 | "webpack-cli": "3.3.12" 21 | }, 22 | "description": [ 23 | "A simple example that demonstrates how to build a CRUD application on", 24 | "the Internet Computer using Motoko and React." 25 | ], 26 | "license": "SEE LICENSE IN LICENSE", 27 | "name": "superheroes", 28 | "scripts": { 29 | "build": "webpack" 30 | }, 31 | "version": "0.0.0" 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "build" 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | jobs: 8 | main: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: "install dfx" 13 | run: | 14 | wget -O install-dfx.sh https://sdk.dfinity.org/install.sh 15 | yes Y | DFX_VERSION=0.6.4 bash install-dfx.sh 16 | echo "::add-path::/home/runner/bin" 17 | - name: "install dfx cache" 18 | run: dfx cache install 19 | - name: "install node" 20 | run: | 21 | wget -O install-node.sh https://deb.nodesource.com/setup_12.x 22 | sudo bash install-node.sh 23 | sudo apt-get install -y nodejs 24 | npm install 25 | - name: "install vessel" 26 | run: | 27 | wget -O /home/runner/bin/vessel https://github.com/kritzcreek/vessel/releases/download/v0.4.1/vessel-linux64 28 | chmod +x /home/runner/bin/vessel 29 | - name: "run" 30 | run: ./run.sh 31 | -------------------------------------------------------------------------------- /src/www/utilities/idl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : idl.js 3 | * Copyright : Enzo Haussecker 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Enzo Haussecker 6 | * Stability : Stable 7 | */ 8 | 9 | // Convert a Motoko list to a JavaScript array. 10 | export function fromList(list) { 11 | if (list.length == 0) { 12 | return []; 13 | } else { 14 | const tuple = list[0]; 15 | const array = fromList(tuple[1]); 16 | array.unshift(tuple[0]); 17 | return array; 18 | } 19 | } 20 | 21 | // Convert a JavaScript array to a Motoko list. 22 | export function toList(array) { 23 | return array.reduceRight((accum, x) => { 24 | return [[x, accum]]; 25 | }, []); 26 | } 27 | 28 | // Convert a Motoko optional to a JavaScript object. 29 | export function fromOptional(optional) { 30 | return optional.length > 0 ? optional[0] : null; 31 | } 32 | 33 | // Convert a JavaScript object to a Motoko optional. 34 | export function toOptional(object) { 35 | return object ? [object] : []; 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Superheroes 2 | 3 | [![Build Status](https://github.com/enzoh/superheroes/workflows/build/badge.svg)](https://github.com/enzoh/superheroes/actions?query=workflow%3Abuild) 4 | 5 | A simple example that demonstrates how to build a [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) application on the [Internet Computer](https://dfinity.org) using [Motoko](https://sdk.dfinity.org/docs/language-guide/motoko.html) and [React](https://reactjs.org). 6 | 7 | ### Prerequisites 8 | 9 | - [DFINITY SDK](https://sdk.dfinity.org/docs/download.html) v0.6.4 10 | - [Node.js](https://nodejs.org/download/release/latest-v12.x) v12.x 11 | - [Vessel](https://github.com/kritzcreek/vessel/releases/tag/v0.4.1) v0.4.1 (Optional) 12 | 13 | ### Demo 14 | 15 | Start a local internet computer. 16 | 17 | ``` 18 | dfx start 19 | ``` 20 | 21 | Execute the following commands in another tab. 22 | 23 | ``` 24 | dfx canister create --all 25 | dfx build 26 | dfx canister install --all 27 | open "http://127.0.0.1:8000/?canisterId=$(dfx canister id www)" 28 | ``` 29 | 30 | Observe the CRUD application running in your web browser. 31 | 32 | [![Result](img/demo.png)](http://www.youtube.com/watch?v=ioCW-9C8feE) 33 | -------------------------------------------------------------------------------- /src/www/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : index.jsx 3 | * Copyright : Enzo Haussecker 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Enzo Haussecker 6 | * Stability : Stable 7 | */ 8 | 9 | import React from 'react'; 10 | import ReactDOM from 'react-dom'; 11 | 12 | import Create from './components/create.jsx'; 13 | import Read from './components/read.jsx'; 14 | import Update from './components/update.jsx'; 15 | import Delete from './components/delete.jsx'; 16 | 17 | class App extends React.Component { 18 | 19 | render() { 20 | return ( 21 |
22 |

Superheroes

23 |

A simple example that demonstrates how to build a CRUD application on the Internet Computer using Motoko and React.

24 |
25 | 26 |
27 | 28 |
29 | 30 |
31 | 32 |
33 | ); 34 | } 35 | } 36 | 37 | export default App; 38 | 39 | ReactDOM.render(, document.getElementById('app')); 40 | -------------------------------------------------------------------------------- /src/www/components/delete.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : delete.jsx 3 | * Copyright : Andrew Wylde 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Andrew Wylde 6 | * Stability : Stable 7 | */ 8 | 9 | import React from 'react'; 10 | import Superheroes from 'ic:canisters/superheroes'; 11 | 12 | const $ = document.getElementById.bind(document); 13 | const idl = require('../utilities/idl'); 14 | 15 | class Delete extends React.Component { 16 | 17 | constructor() { 18 | super(); 19 | this.state = { success: null }; 20 | } 21 | 22 | delete(event) { 23 | event.preventDefault(); 24 | const superheroId = parseInt($('delete-superhero-id').value, 10); 25 | Superheroes.delete(superheroId).then((success) => { 26 | this.setState({ success }); 27 | }); 28 | } 29 | 30 | render() { 31 | return ( 32 |
33 |

Delete a Superhero

34 |
35 | 36 | 37 |
38 | 39 |
40 |
41 |
42 |             { JSON.stringify(this.state, null, 2) }
43 |           
44 |
45 |
46 | ); 47 | } 48 | } 49 | 50 | export default Delete; 51 | -------------------------------------------------------------------------------- /src/www/components/read.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : read.jsx 3 | * Copyright : Andrew Wylde 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Andrew Wylde 6 | * Stability : Stable 7 | */ 8 | 9 | import React from 'react'; 10 | import Superheroes from 'ic:canisters/superheroes'; 11 | 12 | const $ = document.getElementById.bind(document); 13 | const idl = require('../utilities/idl'); 14 | 15 | class Read extends React.Component { 16 | 17 | constructor() { 18 | super(); 19 | this.state = { superhero: null }; 20 | } 21 | 22 | read(event) { 23 | event.preventDefault(); 24 | const superheroId = parseInt($('read-superhero-id').value, 10); 25 | Superheroes.read(superheroId).then((result) => { 26 | const superhero = idl.fromOptional(result); 27 | if (superhero) { 28 | superhero.superpowers = idl.fromList(superhero.superpowers); 29 | }; 30 | this.setState({ superhero }); 31 | }); 32 | } 33 | 34 | render() { 35 | return ( 36 |
37 |

Read a Superhero

38 |
39 | 40 | 41 |
42 | 43 |
44 |
45 |
46 |             { JSON.stringify(this.state, null, 2) }
47 |           
48 |
49 |
50 | ); 51 | } 52 | } 53 | 54 | export default Read; 55 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : webpack.config.js 3 | * Copyright : Enzo Haussecker 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Enzo Haussecker 6 | * Stability : Stable 7 | */ 8 | 9 | const Config = require("./dfx.json"); 10 | const Path = require("path"); 11 | 12 | // Identify build output directory. 13 | const output = ["defaults", "build", "output"].reduce((accum, x) => { 14 | return accum && accum[x] ? accum[x] : null; 15 | }, Config) || Path.join(".dfx", "local", "canisters"); 16 | 17 | // Identify canisters aliases. 18 | const aliases = Object.entries(Config.canisters).reduce((accum, [name,]) => { 19 | const outputRoot = Path.join(__dirname, output, name); 20 | return { 21 | ...accum, 22 | ["ic:canisters/" + name]: Path.join(outputRoot, name + ".js"), 23 | ["ic:idl/" + name]: Path.join(outputRoot, name + ".did.js"), 24 | }; 25 | }, {}); 26 | 27 | // Generate webpack configuration. 28 | const generate = (name, info) => { 29 | if (typeof info.frontend !== 'object') { 30 | return; 31 | }; 32 | const inputRoot = __dirname; 33 | const outputRoot = Path.join(__dirname, output, name); 34 | return { 35 | entry: Path.join(inputRoot, info.frontend.entrypoint), 36 | mode: "production", 37 | module: { 38 | rules: [ 39 | { 40 | exclude: /node_modules/, 41 | loader: "babel-loader", 42 | options: { 43 | presets: [ 44 | "@babel/preset-react", 45 | ], 46 | }, 47 | test: /\.(js|jsx)$/, 48 | }, 49 | ], 50 | }, 51 | output: { 52 | filename: "index.js", 53 | path: Path.join(outputRoot, "assets"), 54 | }, 55 | resolve: { 56 | alias: aliases, 57 | }, 58 | }; 59 | }; 60 | 61 | module.exports = [ 62 | ...Object.entries(Config.canisters).map(([name, info]) => { 63 | return generate(name, info); 64 | }).filter(x => !!x), 65 | ]; 66 | -------------------------------------------------------------------------------- /src/superheroes/Main.mo: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Main.mo 3 | * Copyright : Enzo Haussecker 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Enzo Haussecker 6 | * Stability : Stable 7 | */ 8 | 9 | import List "mo:base/List"; 10 | import Option "mo:base/Option"; 11 | import Trie "mo:base/Trie"; 12 | 13 | actor Superheroes { 14 | 15 | /** 16 | * Types 17 | */ 18 | 19 | // The type of a superhero identifier. 20 | public type SuperheroId = Word32; 21 | 22 | // The type of a superhero. 23 | public type Superhero = { 24 | name : Text; 25 | superpowers : List.List; 26 | }; 27 | 28 | /** 29 | * Application State 30 | */ 31 | 32 | // The next available superhero identifier. 33 | private stable var next : SuperheroId = 0; 34 | 35 | // The superhero data store. 36 | private stable var superheroes : Trie.Trie = Trie.empty(); 37 | 38 | /** 39 | * High-Level API 40 | */ 41 | 42 | // Create a superhero. 43 | public func create(superhero : Superhero) : async SuperheroId { 44 | let superheroId = next; 45 | next += 1; 46 | superheroes := Trie.replace( 47 | superheroes, 48 | key(superheroId), 49 | eq, 50 | ?superhero, 51 | ).0; 52 | return superheroId; 53 | }; 54 | 55 | // Read a superhero. 56 | public query func read(superheroId : SuperheroId) : async ?Superhero { 57 | let result = Trie.find(superheroes, key(superheroId), eq); 58 | return result; 59 | }; 60 | 61 | // Update a superhero. 62 | public func update(superheroId : SuperheroId, superhero : Superhero) : async Bool { 63 | let result = Trie.find(superheroes, key(superheroId), eq); 64 | let exists = Option.isSome(result); 65 | if (exists) { 66 | superheroes := Trie.replace( 67 | superheroes, 68 | key(superheroId), 69 | eq, 70 | ?superhero, 71 | ).0; 72 | }; 73 | return exists; 74 | }; 75 | 76 | // Delete a superhero. 77 | public func delete(superheroId : SuperheroId) : async Bool { 78 | let result = Trie.find(superheroes, key(superheroId), eq); 79 | let exists = Option.isSome(result); 80 | if (exists) { 81 | superheroes := Trie.replace( 82 | superheroes, 83 | key(superheroId), 84 | eq, 85 | null, 86 | ).0; 87 | }; 88 | return exists; 89 | }; 90 | 91 | /** 92 | * Utilities 93 | */ 94 | 95 | // Test two superhero identifiers for equality. 96 | private func eq(x : SuperheroId, y : SuperheroId) : Bool { 97 | return x == y; 98 | }; 99 | 100 | // Create a trie key from a superhero identifier. 101 | private func key(x : SuperheroId) : Trie.Key { 102 | return { hash = x; key = x }; 103 | }; 104 | }; 105 | -------------------------------------------------------------------------------- /src/www/components/create.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : create.jsx 3 | * Copyright : Andrew Wylde 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Andrew Wylde 6 | * Stability : Stable 7 | */ 8 | 9 | import React from 'react'; 10 | import Superheroes from 'ic:canisters/superheroes'; 11 | 12 | const $ = document.getElementById.bind(document); 13 | const idl = require('../utilities/idl'); 14 | 15 | class Create extends React.Component { 16 | 17 | constructor() { 18 | super(); 19 | this.state = { superheroId: null }; 20 | } 21 | 22 | create(event) { 23 | event.preventDefault(); 24 | const name = $('create-name').value; 25 | const n = parseInt($('create-superpowers-count').value, 10); 26 | const superpowers = []; 27 | for (var i = 0; i < n; i++) { 28 | const superpower = $('create-superpower-' + i).value; 29 | superpowers.push(superpower); 30 | }; 31 | const superhero = { name, superpowers }; 32 | superhero.superpowers = idl.toList(superhero.superpowers); 33 | Superheroes.create(superhero).then((superheroId) => { 34 | this.setState({ superheroId }); 35 | }); 36 | } 37 | 38 | toggle() { 39 | const n = parseInt($('create-superpowers-count').value, 10); 40 | const container = $('create-superpowers-container'); 41 | while (container.hasChildNodes()) { 42 | container.removeChild(container.lastChild); 43 | }; 44 | for (var i = 0; i < n; i++) { 45 | const label = document.createElement('label'); 46 | label.setAttribute('for', 'create-superpower-' + i); 47 | label.innerHTML = 'Superpower #' + (i + 1) + ': '; 48 | container.appendChild(label); 49 | const input = document.createElement('input'); 50 | input.id = 'create-superpower-' + i; 51 | input.type = 'text'; 52 | container.appendChild(input); 53 | const br = document.createElement('br'); 54 | container.appendChild(br); 55 | }; 56 | } 57 | 58 | render() { 59 | return ( 60 |
61 |

Create a Superhero

62 |
63 | 64 | 65 |
66 | 67 | 75 |
76 |
77 | 78 | 79 |
80 |
81 |             { JSON.stringify(this.state, null, 2) }
82 |           
83 |
84 |
85 | ); 86 | } 87 | } 88 | 89 | export default Create; 90 | -------------------------------------------------------------------------------- /src/www/components/update.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : update.jsx 3 | * Copyright : Andrew Wylde 4 | * License : Apache 2.0 with LLVM Exception 5 | * Maintainer : Andrew Wylde 6 | * Stability : Stable 7 | */ 8 | 9 | import React from 'react'; 10 | import Superheroes from 'ic:canisters/superheroes'; 11 | 12 | const $ = document.getElementById.bind(document); 13 | const idl = require('../utilities/idl'); 14 | 15 | class Update extends React.Component { 16 | 17 | constructor() { 18 | super(); 19 | this.state = { success: null }; 20 | } 21 | 22 | update(event) { 23 | event.preventDefault(); 24 | const superheroId = parseInt($('update-superhero-id').value, 10); 25 | const name = $('update-name').value; 26 | const n = parseInt($('update-superpowers-count').value, 10); 27 | const superpowers = []; 28 | for (var i = 0; i < n; i++) { 29 | const superpower = $('update-superpower-' + i).value; 30 | superpowers.push(superpower); 31 | }; 32 | const superhero = { name, superpowers }; 33 | superhero.superpowers = idl.toList(superhero.superpowers); 34 | Superheroes.update(superheroId, superhero).then((success) => { 35 | this.setState({ success }); 36 | }); 37 | } 38 | 39 | toggle() { 40 | const n = parseInt($('update-superpowers-count').value, 10); 41 | const container = $('update-superpowers-container'); 42 | while (container.hasChildNodes()) { 43 | container.removeChild(container.lastChild); 44 | }; 45 | for (var i = 0; i < n; i++) { 46 | const label = document.createElement('label'); 47 | label.setAttribute('for', 'update-superpower-' + i); 48 | label.innerHTML = 'Superpower #' + (i + 1) + ': '; 49 | container.appendChild(label); 50 | const input = document.createElement('input'); 51 | input.id = 'update-superpower-' + i; 52 | input.type = 'text'; 53 | container.appendChild(input); 54 | const br = document.createElement('br'); 55 | container.appendChild(br); 56 | }; 57 | } 58 | 59 | render() { 60 | return ( 61 |
62 |

Update a Superhero

63 |
64 | 65 | 66 |
67 | 68 | 69 |
70 | 71 | 79 |
80 |
81 | 82 | 83 |
84 |
85 |             { JSON.stringify(this.state, null, 2) }
86 |           
87 |
88 |
89 | ); 90 | } 91 | } 92 | 93 | export default Update; 94 | -------------------------------------------------------------------------------- /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, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the 13 | copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other 16 | entities that control, are controlled by, or are under common control with 17 | that entity. For the purposes of this definition, "control" means (i) the 18 | power, direct or indirect, to cause the direction or management of such 19 | entity, whether by contract or otherwise, or (ii) ownership of fifty percent 20 | (50%) or more of the outstanding shares, or (iii) beneficial ownership of 21 | such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity exercising 24 | 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 source, and 28 | configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical transformation 31 | or translation of a Source form, including but not limited to compiled 32 | object code, generated documentation, and conversions to other media types. 33 | 34 | "Work" shall mean the work of authorship, whether in Source or Object form, 35 | made available under the License, as indicated by a copyright notice that is 36 | included in or attached to the work (an example is provided in the Appendix 37 | below). 38 | 39 | "Derivative Works" shall mean any work, whether in Source or Object form, 40 | that is based on (or derived from) the Work and for which the editorial 41 | revisions, annotations, elaborations, or other modifications represent, as a 42 | whole, an original work of authorship. For the purposes of this License, 43 | Derivative Works shall not include works that remain separable from, or 44 | merely link (or bind by name) to the interfaces of, the Work and Derivative 45 | Works thereof. 46 | 47 | "Contribution" shall mean any work of authorship, including the original 48 | version of the Work and any modifications or additions to that Work or 49 | Derivative Works thereof, that is intentionally submitted to Licensor for 50 | inclusion in the Work by the copyright owner or by an individual or Legal 51 | Entity authorized to submit on behalf of the copyright owner. For the 52 | purposes of this definition, "submitted" means any form of electronic, 53 | verbal, or written communication sent to the Licensor or its 54 | representatives, including but not limited to communication on electronic 55 | mailing lists, source code control systems, and issue tracking systems that 56 | are managed by, or on behalf of, the Licensor for the purpose of discussing 57 | and improving the Work, but excluding communication that is conspicuously 58 | marked or otherwise designated in writing by the copyright owner as "Not a 59 | Contribution." 60 | 61 | "Contributor" shall mean Licensor and any individual or Legal Entity on 62 | behalf of whom a Contribution has been received by Licensor and subsequently 63 | incorporated within the Work. 64 | 65 | 2. Grant of Copyright License. Subject to the terms and conditions of this 66 | License, each Contributor hereby grants to You a perpetual, worldwide, 67 | non-exclusive, no-charge, royalty-free, irrevocable copyright license to 68 | reproduce, prepare Derivative Works of, publicly display, publicly perform, 69 | sublicense, and distribute the Work and such Derivative Works in Source or 70 | Object form. 71 | 72 | 3. Grant of Patent License. Subject to the terms and conditions of this 73 | License, each Contributor hereby grants to You a perpetual, worldwide, 74 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in 75 | this section) patent license to make, have made, use, offer to sell, sell, 76 | import, and otherwise transfer the Work, where such license applies only to 77 | those patent claims licensable by such Contributor that are necessarily 78 | infringed by their Contribution(s) alone or by combination of their 79 | Contribution(s) with the Work to which such Contribution(s) was submitted. 80 | If You institute patent litigation against any entity (including a 81 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 82 | Contribution incorporated within the Work constitutes direct or contributory 83 | patent infringement, then any patent licenses granted to You under this 84 | License for that Work shall terminate as of the date such litigation is 85 | filed. 86 | 87 | 4. Redistribution. You may reproduce and distribute copies of the Work or 88 | Derivative Works thereof in any medium, with or without modifications, and 89 | in Source or Object form, provided that You meet the following conditions: 90 | 91 | a. You must give any other recipients of the Work or Derivative Works a 92 | copy of this License; and 93 | 94 | b. You must cause any modified files to carry prominent notices stating 95 | that You changed the files; and 96 | 97 | c. You must retain, in the Source form of any Derivative Works that You 98 | distribute, all copyright, patent, trademark, and attribution notices 99 | from the Source form of the Work, excluding those notices that do not 100 | pertain to any part of the Derivative Works; and 101 | 102 | d. If the Work includes a "NOTICE" text file as part of its distribution, 103 | then any Derivative Works that You distribute must include a readable 104 | copy of the attribution notices contained within such NOTICE file, 105 | excluding those notices that do not pertain to any part of the Derivative 106 | Works, in at least one of the following places: within a NOTICE text file 107 | distributed as part of the Derivative Works; within the Source form or 108 | documentation, if provided along with the Derivative Works; or, within a 109 | display generated by the Derivative Works, if and wherever such 110 | third-party notices normally appear. The contents of the NOTICE file are 111 | for informational purposes only and do not modify the License. You may 112 | add Your own attribution notices within Derivative Works that You 113 | distribute, alongside or as an addendum to the NOTICE text from the Work, 114 | provided that such additional attribution notices cannot be construed as 115 | modifying the License. 116 | 117 | You may add Your own copyright statement to Your modifications and may 118 | provide additional or different license terms and conditions for use, 119 | reproduction, or distribution of Your modifications, or for any such 120 | Derivative Works as a whole, provided Your use, reproduction, and 121 | distribution of the Work otherwise complies with the conditions stated in 122 | this License. 123 | 124 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 125 | Contribution intentionally submitted for inclusion in the Work by You to the 126 | Licensor shall be under the terms and conditions of this License, without 127 | any additional terms or conditions. Notwithstanding the above, nothing 128 | herein shall supersede or modify the terms of any separate license agreement 129 | you may have executed with Licensor regarding such Contributions. 130 | 131 | 6. Trademarks. This License does not grant permission to use the trade names, 132 | trademarks, service marks, or product names of the Licensor, except as 133 | required for reasonable and customary use in describing the origin of the 134 | Work and reproducing the content of the NOTICE file. 135 | 136 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in 137 | writing, Licensor provides the Work (and each Contributor provides its 138 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 139 | KIND, either express or implied, including, without limitation, any 140 | warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or 141 | FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining 142 | the appropriateness of using or redistributing the Work and assume any risks 143 | associated with Your exercise of permissions under this License. 144 | 145 | 8. Limitation of Liability. In no event and under no legal theory, whether in 146 | tort (including negligence), contract, or otherwise, unless required by 147 | applicable law (such as deliberate and grossly negligent acts) or agreed to 148 | in writing, shall any Contributor be liable to You for damages, including 149 | any direct, indirect, special, incidental, or consequential damages of any 150 | character arising as a result of this License or out of the use or inability 151 | to use the Work (including but not limited to damages for loss of goodwill, 152 | work stoppage, computer failure or malfunction, or any and all other 153 | commercial damages or losses), even if such Contributor has been advised of 154 | the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or 157 | Derivative Works thereof, You may choose to offer, and charge a fee for, 158 | acceptance of support, warranty, indemnity, or other liability obligations 159 | and/or rights consistent with this License. However, in accepting such 160 | obligations, You may act only on Your own behalf and on Your sole 161 | responsibility, not on behalf of any other Contributor, and only if You 162 | agree to indemnify, defend, and hold each Contributor harmless for any 163 | liability incurred by, or claims asserted against, such Contributor by 164 | reason of your accepting any such warranty or additional liability. 165 | 166 | END OF TERMS AND CONDITIONS 167 | 168 | LLVM EXCEPTION TO THE APACHE 2.0 LICENSE 169 | 170 | As an exception, if, as a result of your compiling your source code, portions 171 | of this Software are embedded into an Object form of such source code, you may 172 | redistribute such embedded portions in such Object form without complying with 173 | the conditions of Sections 4(a), 4(b) and 4(d) of the License. 174 | 175 | In addition, if you combine or link compiled forms of this Software with 176 | software that is licensed under the GPLv2 ("Combined Software") and if a court 177 | of competent jurisdiction determines that the patent provision (Section 3), the 178 | indemnity provision (Section 9) or other Section of the License conflicts with 179 | the conditions of the GPLv2, you may retroactively and prospectively choose to 180 | deem waived or otherwise exclude such Section(s) of the License, but only in 181 | their entirety and only with respect to the Combined Software. 182 | 183 | END OF LLVM EXCEPTION 184 | 185 | APPENDIX: How to apply the Apache License to your work. 186 | 187 | To apply the Apache License to your work, attach the following boilerplate 188 | notice, with the fields enclosed by brackets "[]" replaced with your own 189 | identifying information. (Don't include the brackets!) The text should be 190 | enclosed in the appropriate comment syntax for the file format. We also 191 | recommend that a file or class name and description of purpose be included on 192 | the same "printed page" as the copyright notice for easier identification 193 | within third-party archives. 194 | 195 | Copyright [yyyy] [name of copyright owner] 196 | 197 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 198 | this file except in compliance with the License. You may obtain a copy of the 199 | License at 200 | 201 | http://www.apache.org/licenses/LICENSE-2.0 202 | 203 | Unless required by applicable law or agreed to in writing, software distributed 204 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 205 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 206 | specific language governing permissions and limitations under the License. 207 | 208 | END OF APPENDIX 209 | --------------------------------------------------------------------------------