├── .forceignore ├── .github ├── CODEOWNERS ├── FUNDING.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── config └── project-scratch-def.json ├── force-app ├── main │ ├── aura │ │ └── LC_API │ │ │ ├── LC_API.cmp │ │ │ ├── LC_API.cmp-meta.xml │ │ │ ├── LC_APIController.js │ │ │ ├── LC_APIHelper.js │ │ │ └── LC_APIRenderer.js │ ├── classes │ │ ├── LC_VisualforceDomainController.cls │ │ └── LC_VisualforceDomainController.cls-meta.xml │ ├── pages │ │ ├── LC_APIPage.page │ │ ├── LC_APIPage.page-meta.xml │ │ ├── LC_VisualforceDomainPage.page │ │ └── LC_VisualforceDomainPage.page-meta.xml │ └── staticresources │ │ ├── jsforce.resource │ │ ├── jsforce.resource-meta.xml │ │ ├── penpal.resource │ │ └── penpal.resource-meta.xml └── test │ └── classes │ ├── LC_VisualforceDomainControllerTest.cls │ └── LC_VisualforceDomainControllerTest.cls-meta.xml ├── force-demo └── main │ ├── aura │ ├── LC_FetchDemo │ │ ├── LC_FetchDemo.cmp │ │ ├── LC_FetchDemo.cmp-meta.xml │ │ ├── LC_FetchDemo.design │ │ └── LC_FetchDemoController.js │ └── LC_RequestDemo │ │ ├── LC_RequestDemo.cmp │ │ ├── LC_RequestDemo.cmp-meta.xml │ │ ├── LC_RequestDemo.design │ │ └── LC_RequestDemoController.js │ ├── flexipages │ └── LC_Demo.flexipage-meta.xml │ ├── permissionsets │ └── LC_Demo.permissionset-meta.xml │ └── tabs │ └── LC_Demo.tab-meta.xml ├── package-lock.json ├── package.json └── sfdx-project.json /.forceignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status 2 | # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm 3 | # 4 | 5 | package.xml 6 | **/profiles 7 | **/applications/standard__* 8 | 9 | # LWC configuration files 10 | **/jsconfig.json 11 | **/.eslintrc.json 12 | 13 | # LWC Jest 14 | **/__tests__/** -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # 2 | # Code Owners File Format 3 | # https://help.github.com/articles/about-code-owners/ 4 | # 5 | # A CODEOWNERS file uses a pattern that follows the same rules used in gitignore files. 6 | # The pattern is followed by one or more GitHub usernames or team names using the 7 | # standard @username or @org/team-name format. You can also refer to a user by an 8 | # email address that has been added to their GitHub account, for example user@example.com. 9 | # 10 | 11 | * @douglascayers 12 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.paypal.me/douglascayers/ # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### What does this pull request do? 2 | 3 | 4 | ### What issues does this pull request fix or reference? 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Salesforce DX configuration files. 2 | .sfdx/ 3 | 4 | # IlluminatedCloud configuration files. 5 | .idea/ 6 | IlluminatedCloud/ 7 | *.iml 8 | 9 | # Visual Studio Code configuration files. 10 | .vscode/ 11 | 12 | # A temp directory where build scripts convert 13 | # source files to metadata format. 14 | mdapi/ 15 | 16 | # NPM cache directory. 17 | node_modules/ -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Salesforce Open Source Community Code of Conduct 2 | 3 | ## About the Code of Conduct 4 | 5 | Equality is a core value at Salesforce. We believe a diverse and inclusive 6 | community fosters innovation and creativity, and are committed to building a 7 | culture where everyone feels included. 8 | 9 | Salesforce open-source projects are committed to providing a friendly, safe, and 10 | welcoming environment for all, regardless of gender identity and expression, 11 | sexual orientation, disability, physical appearance, body size, ethnicity, nationality, 12 | race, age, religion, level of experience, education, socioeconomic status, or 13 | other similar personal characteristics. 14 | 15 | The goal of this code of conduct is to specify a baseline standard of behavior so 16 | that people with different social values and communication styles can work 17 | together effectively, productively, and respectfully in our open source community. 18 | It also establishes a mechanism for reporting issues and resolving conflicts. 19 | 20 | All questions and reports of abusive, harassing, or otherwise unacceptable behavior 21 | in a Salesforce open-source project may be reported by contacting the Salesforce 22 | Open Source Conduct Committee at ossconduct@salesforce.com. 23 | 24 | ## Our Pledge 25 | 26 | In the interest of fostering an open and welcoming environment, we as 27 | contributors and maintainers pledge to making participation in our project and 28 | our community a harassment-free experience for everyone, regardless of gender 29 | identity and expression, sexual orientation, disability, physical appearance, 30 | body size, ethnicity, nationality, race, age, religion, level of experience, education, 31 | socioeconomic status, or other similar personal characteristics. 32 | 33 | ## Our Standards 34 | 35 | Examples of behavior that contributes to creating a positive environment 36 | include: 37 | 38 | * Using welcoming and inclusive language 39 | * Being respectful of differing viewpoints and experiences 40 | * Gracefully accepting constructive criticism 41 | * Focusing on what is best for the community 42 | * Showing empathy toward other community members 43 | 44 | Examples of unacceptable behavior by participants include: 45 | 46 | * The use of sexualized language or imagery and unwelcome sexual attention or 47 | advances 48 | * Personal attacks, insulting/derogatory comments, or trolling 49 | * Public or private harassment 50 | * Publishing, or threatening to publish, others' private information—such as 51 | a physical or electronic address—without explicit permission 52 | * Other conduct which could reasonably be considered inappropriate in a 53 | professional setting 54 | * Advocating for or encouraging any of the above behaviors 55 | 56 | ## Our Responsibilities 57 | 58 | Project maintainers are responsible for clarifying the standards of acceptable 59 | behavior and are expected to take appropriate and fair corrective action in 60 | response to any instances of unacceptable behavior. 61 | 62 | Project maintainers have the right and responsibility to remove, edit, or 63 | reject comments, commits, code, wiki edits, issues, and other contributions 64 | that are not aligned with this Code of Conduct, or to ban temporarily or 65 | permanently any contributor for other behaviors that they deem inappropriate, 66 | threatening, offensive, or harmful. 67 | 68 | ## Scope 69 | 70 | This Code of Conduct applies both within project spaces and in public spaces 71 | when an individual is representing the project or its community. Examples of 72 | representing a project or community include using an official project email 73 | address, posting via an official social media account, or acting as an appointed 74 | representative at an online or offline event. Representation of a project may be 75 | further defined and clarified by project maintainers. 76 | 77 | ## Enforcement 78 | 79 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 80 | reported by contacting the Salesforce Open Source Conduct Committee 81 | at ossconduct@salesforce.com. All complaints will be reviewed and investigated 82 | and will result in a response that is deemed necessary and appropriate to the 83 | circumstances. The committee is obligated to maintain confidentiality with 84 | regard to the reporter of an incident. Further details of specific enforcement 85 | policies may be posted separately. 86 | 87 | Project maintainers who do not follow or enforce the Code of Conduct in good 88 | faith may face temporary or permanent repercussions as determined by other 89 | members of the project's leadership and the Salesforce Open Source Conduct 90 | Committee. 91 | 92 | ## Attribution 93 | 94 | This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant-home], 95 | version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html. 96 | It includes adaptions and additions from [Go Community Code of Conduct][golang-coc], 97 | [CNCF Code of Conduct][cncf-coc], and [Microsoft Open Source Code of Conduct][microsoft-coc]. 98 | 99 | This Code of Conduct is licensed under the [Creative Commons Attribution 3.0 License][cc-by-3-us]. 100 | 101 | [contributor-covenant-home]: https://www.contributor-covenant.org (https://www.contributor-covenant.org/) 102 | [golang-coc]: https://golang.org/conduct 103 | [cncf-coc]: https://github.com/cncf/foundation/blob/master/code-of-conduct.md 104 | [microsoft-coc]: https://opensource.microsoft.com/codeofconduct/ 105 | [cc-by-3-us]: https://creativecommons.org/licenses/by/3.0/us/ 106 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Call REST API from Lightning Aura Components without Named Credentials 2 | 3 | A simple [promise-based](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_promises.htm) 4 | [service component](https://developer.salesforce.com/blogs/2018/08/implement-and-use-lightning-service-components.html) 5 | for working with Salesforce REST API and JavaScript Fetch API 6 | directly from your aura component's JavaScript without you needing to 7 | write Apex or configure Named Credentials. Just install and use. 8 | 9 | ## 📝 Table of Contents 10 | 11 | * [Prerequisites](#-prerequisites) 12 | * [Getting Started](#-getting-started) 13 | * [Example Usage](#-example-usage) 14 | * [Sponsoring](#-sponsoring) 15 | * [Contributing](#-contributing) 16 | * [Troubleshooting](#-troubleshooting) 17 | * [Authors](#️-authors) 18 | * [Acknowledgements](#-acknowledgements) 19 | * [Other Utilities](#-other-utilities) 20 | * [License](#-license) 21 | 22 | ## 🚨 Prerequisites 23 | 24 | 1. Enable Lightning Experience 25 | 2. Enable My Domain 26 | 3. Allow IFraming of Visualforce Pages with Clickjack Protection 27 | 28 | You can find step-by-step instructions with screen shots in the [Mass Action Scheduler](https://github.com/douglascayers-org/sfdx-mass-action-scheduler/wiki/Prerequisites) wiki, which is my primary app that uses this component. 29 | 30 | ## 👋 Getting Started 31 | 32 | 1. Deploy this project to your org (you only need what's in `force-app` folder). 33 | 34 | ``` 35 | git clone https://github.com/douglascayers/sfdx-lightning-api-component.git 36 | 37 | cd sfdx-lightning-api-component 38 | 39 | sfdx force:org:create -a lapi -s -f config/project-scratch-def.json 40 | 41 | sfdx force:source:deploy -u lapi -p force-app 42 | ``` 43 | 44 | 2. Explore the `LC_RequestDemo` and `LC_FetchDemo` components in the `force-demo` folder on usage. 45 | 46 | 3. Try out a demo 47 | 48 | ``` 49 | sfdx force:source:deploy -u lapi -p force-demo 50 | 51 | sfdx force:user:permset:assign -n LC_Demo 52 | 53 | sfdx force:org:open -u lapi -p //lightning/n/LC_Demo 54 | ``` 55 | 56 | a. Assign yourself the **LC Demo** permission set. 57 | 58 | b. Navigate to the **LC Demo** tab. 59 | 60 | c. Play with the sample components to send different [REST API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_what_is_rest_api.htm) and [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests. 61 | 62 | d. Marvel that you didn't have to write any Apex code or configure a Named Credential :) 63 | 64 | ## 📘 Example Usage 65 | 66 | Add the `` to your aura component and give it an `aura:id` for reference. 67 | 68 | ```xml 69 | 70 | 71 | 72 | ... 73 | 74 | ``` 75 | 76 | Find the `` by its `aura:id` then call one of the request methods: 77 | * The `restRequest(..)` method passing in a JSON object with the `url`, `method`, `body`, and any `headers` properties, or 78 | * The `fetchRequest(..)` method passing in a JSON object with the `url` and `options` properties 79 | 80 | ```js 81 | // YourComponentController.js 82 | ({ 83 | createAccount: function( component, event, helper ) { 84 | 85 | component.find( 'lc_api' ).restRequest({ 86 | 'url' : '/services/data/v47.0/sobjects/Account', 87 | 'method' : 'post', 88 | 'body' : JSON.stringify({ 89 | "Name" : "LC Demo Account" 90 | }) 91 | }).then( $A.getCallback( function( response ) { 92 | // handle response 93 | // { id: "001f400000YEZB8AAP", success: true, errors: [] } 94 | })).catch( $A.getCallback( function( err ) { 95 | // handle error 96 | })); 97 | 98 | }, 99 | 100 | getDataFromGist: function( component, event, helper ) { 101 | 102 | component.find( 'lc_api' ).fetchRequest({ 103 | 'url' : 'https://gist.githubusercontent.com/douglascayers/e96c53304dc78dc83e59a85753f29111/raw/sfdx-mass-action-scheduler-version.js', 104 | 'options': {} 105 | }).then( $A.getCallback( function( response ) { 106 | // handle response 107 | })).catch( $A.getCallback( function( err ) { 108 | // handle error 109 | })); 110 | 111 | } 112 | 113 | }) 114 | ``` 115 | 116 | ## 💎 Sponsoring 117 | 118 | This project is a [free-as-in-speech](https://www.howtogeek.com/howto/31717/what-do-the-phrases-free-speech-vs.-free-beer-really-mean/) and [open source](https://opensource.com/resources/what-open-source) developed passion project of [Doug Ayers](https://douglascayers.com). 119 | 120 | If you've found value in my open source projects, please consider showing your support: 121 | * ⭐️ [Star](https://github.com/douglascayers/sfdx-lightning-api-component) this project on GitHub 122 | * 📣 [Tweet](https://twitter.com/intent/tweet/?url=https%3A%2F%2Fgithub.com%2Fdouglascayers%2Fsfdx-lightning-api-component&text=%E2%9A%A1%EF%B8%8F%20Use%20Salesforce%20REST%20API%20in%20Lightning%20Components%20without%20Named%20Credentials%20or%20Apex%20by%20%40DouglasCAyers&related=douglascayers%2Csalesforcedevs&hashtags=salesforce) this project to your followers 123 | * Contribute a ☕️ or 🌮 via my [virtual tip jar on PayPal](https://www.paypal.me/douglascayers/) 124 | 125 | Thank you! ❤️ 126 | 127 | https://douglascayers.com/thanks-for-your-support/ 128 | 129 | ## 🙏 Contributing 130 | 131 | Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. 132 | 133 | For code contributions, please follow the [GitHub flow](https://help.github.com/en/articles/github-flow): 134 | 1. Fork this project and [install the source code](#-getting-started). 135 | 2. Create your feature branch (`git checkout -b feature/AmazingFeature`). 136 | 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`). 137 | 4. Push to your feature branch (`git push origin feature/AmazingFeature`). 138 | 5. Open a pull request to the `develop` branch. 139 | 140 | ## 🧐 Troubleshooting 141 | 142 | ### "Access Denied" or "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://yourinstance.visualforce.com' is therefore not allowed access." 143 | 144 | Your request was blocked due to [Cross-Origin Resource Sharing (CORS) policy](https://help.salesforce.com/articleView?id=extend_code_cors.htm&type=5). 145 | 146 | This can happen when trying to make a request to `/services/apexrest/` endpoint. 147 | For example, the Visualforce domain hosting `LC_APIPage` is on `https://yourinstance.visualforce.com` and is trying to make a web request to `https://yourinstance.my.salesforce.com/services/apexrest/`. 148 | Because the two domains do not match, then CORS policy prevents the request. 149 | 150 | 1. In **Setup**, navigate to **Security | CORS**. 151 | 152 | 2. Add the origin URL mentioned in your error message (e.g. `https://yourinstance.visualforce.com`) to the list of whitelisted domains. 153 | 154 | ## ✍️ Authors 155 | 156 | [Doug Ayers](https://douglascayers.com) develops and maintains the project. 157 | 158 | See also the list of [contributors](https://github.com/douglascayers/sfdx-lightning-api-component/graphs/contributors) who participated in this project. 159 | 160 | ## 🎉 Acknowledgements 161 | 162 | [Penpal](https://github.com/Aaronius/penpal) 163 | for a secure, promise-based library for communicating between windows and iframes. 164 | 165 | [jsforce](https://jsforce.github.io/) 166 | for an elegant, promise-based library for working with Salesforce REST API. 167 | 168 | ## 🎈 Other Utilities 169 | 170 | You should check out [sfdc-lax](https://github.com/ruslan-kurchenko/sfdc-lax) by Ruslan Kurchenko, 171 | a promise-based service component that makes calling Apex actions or using Lightning Data Service a breeze. 172 | 173 | ## 👀 License 174 | 175 | The source code is licensed under the [BSD 3-Clause License](LICENSE) 176 | -------------------------------------------------------------------------------- /config/project-scratch-def.json: -------------------------------------------------------------------------------- 1 | { 2 | "orgName" : "Lightning API", 3 | "edition" : "Developer", 4 | "features" : [], 5 | "settings" : { 6 | "mobileSettings" : { 7 | "enableS1EncryptedStoragePref2" : false 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /force-app/main/aura/LC_API/LC_API.cmp: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 11 | 12 | 16 | 17 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 65 | 66 | 70 | 71 | 72 | 96 | 97 | 101 | 102 | 103 |
104 | {!v.body} 105 |
106 | 107 |
108 | -------------------------------------------------------------------------------- /force-app/main/aura/LC_API/LC_API.cmp-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | LC_API 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/aura/LC_API/LC_APIController.js: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | ({ 8 | /** 9 | * Called once during component initialization phase. 10 | */ 11 | onInit: function( component, event, helper ) { 12 | helper._penpal = {}; 13 | helper.makeApexRequest( component, 'c.getVisualforceDomainURL' ).then( $A.getCallback( function( vfDomainURL ) { 14 | component.set( 'v.iframeSrc', `${vfDomainURL}/apex/LC_APIPage` ); 15 | })).catch( $A.getCallback( function( err ) { 16 | console.error( 'LC_API: Error determining visualforce domain', err ); 17 | })); 18 | }, 19 | 20 | /** 21 | * Called once after ltng:require has loaded scripts. 22 | */ 23 | onScriptsLoaded: function( component, event, helper ) { 24 | 25 | }, 26 | 27 | /** 28 | * Called each time the component renders itself. 29 | */ 30 | onRender: function( component, event, helper ) { 31 | 32 | const isPenpalFrameCreated = component.get( 'v.penpalFrameCreated' ); 33 | 34 | // For Penpal to operate correctly, you must ensure that `connectToChild` 35 | // is called before the iframe has called `connectToParent`. 36 | // Since the iframe source is calculated asynchronously, 37 | // we listen to the component's render events and each time 38 | // check if the iframe source is ready, and if so, then we initialize 39 | // penpal to connect this component to the iframe. 40 | // Since we only want to do this once, we also set the initialized flag. 41 | if ( !isPenpalFrameCreated ) { 42 | 43 | const container = component.find( 'penpalFrameContainer' ); 44 | const iframeSrc = component.get( 'v.iframeSrc' ); 45 | 46 | // Ensure the container element has rendered otherwise we can't 47 | // append child elements to it. And wait for the iframe source to 48 | // be available otherwise no reason to create the iframe element. 49 | if ( !$A.util.isEmpty( container ) && !$A.util.isEmpty( iframeSrc ) ) { 50 | 51 | $A.createComponent( 52 | "aura:html", 53 | { 54 | "aura:id": "penpalFrame", 55 | "tag": "iframe", 56 | "HTMLAttributes": { 57 | "src": iframeSrc 58 | } 59 | }, 60 | function ( iframeCmp, status, errorMessage ) { 61 | 62 | // This callback happened asynchronously, so make one 63 | // more check on whether the penpal frame has been initialized or not 64 | // in the off chance a separate render cycle got here before this one. 65 | const isPenpalFrameCreated = component.get( 'v.penpalFrameCreated' ); 66 | 67 | if ( isPenpalFrameCreated ) { 68 | 69 | console.log( 'LC_API: iframe is already initialized' ); 70 | 71 | } else if ( status === 'SUCCESS' ) { 72 | 73 | // At this point, the iframe component has been constructed 74 | // but not yet been rendered, so we don't have access to the 75 | // HTML iframe element yet. We need to wait for another render cycle, 76 | // that is, we need to wait for the render() method to be called again 77 | // after we append the new iframe component to the body of its container. 78 | // Once we're able to find the 'penpalFrame' on the page then 79 | // we can proceed with the rest of the penpal initialization. 80 | 81 | component.set( 'v.penpalFrameCreated', true ); 82 | 83 | container.set( 'v.body', [ iframeCmp ] ); 84 | 85 | console.info( 'LC_API: iframe initialized' ); 86 | 87 | } else if ( status === 'INCOMPLETE' ) { 88 | 89 | console.warn( 'LC_API: No response from server or client is offline' ); 90 | 91 | } else if ( status === 'ERROR' ) { 92 | 93 | console.error( 'LC_API: Error creating iframe: ' + errorMessage ); 94 | 95 | } 96 | 97 | } 98 | ); 99 | 100 | } // else, iframe source is empty, keep waiting 101 | 102 | } else { 103 | 104 | const isPenpalFrameConnected = component.get( 'v.penpalFrameConnected' ); 105 | const iframeCmp = component.find( 'penpalFrame' ); 106 | 107 | if ( !$A.util.isEmpty( iframeCmp ) && !isPenpalFrameConnected ) { 108 | 109 | const connection = Penpal.connectToChild({ 110 | // The iframe to which a connection should be made 111 | iframe: iframeCmp.getElement() 112 | }); 113 | 114 | helper._penpal.connection = connection; 115 | 116 | connection.promise.then( $A.getCallback( function( child ) { 117 | 118 | // Cache a reference to the child so that we can 119 | // use it in the restRequest/fetchRequest methods, 120 | // as well as be able to destroy it when this component unrenders. 121 | helper._penpal.child = child; 122 | console.info( 'LC_API: connected to iframe ' + iframeCmp.getGlobalId() ); 123 | component.set( 'v.penpalFrameConnected', true ); 124 | 125 | })).catch( $A.getCallback( function( err ) { 126 | 127 | console.error( 'LC_API: Error establishing connection to iframe ' + iframeCmp.getGlobalId(), err ); 128 | component.set( 'v.penpalFrameConnected', false ); 129 | 130 | })); 131 | 132 | } 133 | 134 | } 135 | 136 | }, 137 | 138 | onRestRequest: function( component, event, helper ) { 139 | const params = event.getParam( 'arguments' ); 140 | return helper.handleRestRequest( component, params.request ); 141 | }, 142 | 143 | onFetchRequest: function( component, event, helper ) { 144 | const params = event.getParam( 'arguments' ); 145 | return helper.handleFetchRequest( component, params.request ); 146 | } 147 | }) 148 | /* 149 | BSD 3-Clause License 150 | 151 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 152 | All rights reserved. 153 | 154 | Redistribution and use in source and binary forms, with or without 155 | modification, are permitted provided that the following conditions are met: 156 | 157 | * Redistributions of source code must retain the above copyright notice, this 158 | list of conditions and the following disclaimer. 159 | 160 | * Redistributions in binary form must reproduce the above copyright notice, 161 | this list of conditions and the following disclaimer in the documentation 162 | and/or other materials provided with the distribution. 163 | 164 | * Neither the name of the copyright holder nor the names of its 165 | contributors may be used to endorse or promote products derived from 166 | this software without specific prior written permission. 167 | 168 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 169 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 170 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 171 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 172 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 173 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 174 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 175 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 176 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 177 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 178 | */ -------------------------------------------------------------------------------- /force-app/main/aura/LC_API/LC_APIHelper.js: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | ({ 8 | handleRestRequest: function( component, request ) { 9 | 10 | const helper = this; 11 | 12 | const defaultRequest = { 13 | 'method' : 'get' 14 | }; 15 | 16 | const defaultHeaders = { 17 | 'Content-Type': 'application/json' 18 | }; 19 | 20 | request = Object.assign( {}, defaultRequest, request ); 21 | request.headers = Object.assign( {}, defaultHeaders, request.headers ); 22 | 23 | return helper.getPenpalChild().then( $A.getCallback( function( child ) { 24 | return helper.makePenpalRequest( 'rest', child, request ); 25 | })); 26 | 27 | }, 28 | 29 | handleFetchRequest: function( component, request ) { 30 | 31 | const helper = this; 32 | 33 | return helper.getPenpalChild().then( $A.getCallback( function( child ) { 34 | return helper.makePenpalRequest( 'fetch', child, request ); 35 | })); 36 | 37 | }, 38 | 39 | // ------------------------------------------------------------ 40 | 41 | /** 42 | * For internal use. 43 | * Returns a promise waiting for the parent-child penpal handshake to complete 44 | * then resolves with reference to the penpal child for making requests. 45 | */ 46 | getPenpalChild: function() { 47 | 48 | const helper = this; 49 | 50 | return new Promise( $A.getCallback( function( resolve, reject ) { 51 | 52 | let child = helper._penpal.child; 53 | 54 | if ( child ) { 55 | 56 | resolve( child ); 57 | 58 | } else { 59 | 60 | // all time values in milliseconds 61 | const timeout = 10000; // ten seconds 62 | const pollFrequency = 500; // half a second 63 | const startTime = new Date().getTime(); 64 | const endTime = startTime + timeout; 65 | 66 | const timerId = setInterval( $A.getCallback( function() { 67 | 68 | child = helper._penpal.child; 69 | 70 | if ( child ) { 71 | 72 | // parent-child penpal handshake now complete 73 | clearInterval( timerId ); 74 | resolve( child ); 75 | 76 | } else { 77 | 78 | // check if we have exceeded our timeout 79 | const currentTime = new Date().getTime(); 80 | if ( currentTime > endTime ) { 81 | clearInterval( timerId ); 82 | reject( 'LC_API: Timeout trying to establish connection to iframe' ); 83 | } 84 | // else, keep polling 85 | 86 | } 87 | 88 | }), pollFrequency ); 89 | 90 | } 91 | 92 | })); 93 | 94 | }, 95 | 96 | /** 97 | * For internal use. 98 | * Returns a promise waiting for the parent-child penpal request to complete 99 | * then resolves with response from the child iframe. 100 | */ 101 | makePenpalRequest: function( requestType, child, request ) { 102 | 103 | let p; 104 | 105 | if ( requestType === 'rest' ) { 106 | p = child.restRequest( request ); 107 | } else if ( requestType === 'fetch' ) { 108 | p = child.fetchRequest( request ); 109 | } else { 110 | p = Promise.resolve({ 111 | success: false, 112 | data: 'LC_API: Invalid request type: ' + requestType 113 | }); 114 | } 115 | 116 | return p.then( $A.getCallback( function( response ) { 117 | if ( response.success ) { 118 | return response.data; 119 | } else { 120 | return Promise.reject( response.data ); 121 | } 122 | })); 123 | 124 | }, 125 | 126 | /** 127 | * For internal use. 128 | * Returns a promise waiting for the Apex request to complete 129 | * then resolves with the JSON response, or rejects if any error. 130 | * 131 | * @param component 132 | * (required) Reference to the component who has access to the Aura Enabled method specified by `actionName`. 133 | * @param actionName 134 | * (required) Name of the Aura Enabled Apex method in form `c.methodName`. 135 | * @param params 136 | * (optional) JSON map of request parameters to pass to the Apex action. 137 | * @param options 138 | * (optional) JSON map of options to customize the request. 139 | * `background` set to true will execute request in background thread. 140 | * `storable` set to true will cache the response. 141 | */ 142 | makeApexRequest: function( component, actionName, params, options ) { 143 | 144 | const helper = this; 145 | 146 | return new Promise( $A.getCallback( function( resolve, reject ) { 147 | 148 | const action = component.get( actionName ); 149 | 150 | if ( params ) { 151 | action.setParams( params ); 152 | } 153 | 154 | if ( options ) { 155 | if ( options.background ) { action.setBackground(); } 156 | if ( options.storable ) { action.setStorable(); } 157 | } 158 | 159 | action.setCallback( helper, function( response ) { 160 | if ( component.isValid() && response.getState() === 'SUCCESS' ) { 161 | 162 | resolve( response.getReturnValue() ); 163 | 164 | } else { 165 | 166 | console.error( 'Error calling action "' + actionName + '" with state: ' + response.getState() ); 167 | 168 | helper.logActionErrors( response.getError() ); 169 | 170 | reject( response.getError() ); 171 | 172 | } 173 | }); 174 | 175 | $A.enqueueAction( action ); 176 | 177 | })); 178 | 179 | }, 180 | 181 | /** 182 | * For internal use. 183 | * Logs to console errors object. 184 | * Errors may be a String or Array. 185 | */ 186 | logActionErrors: function( errors ) { 187 | if ( errors ) { 188 | if ( errors.length > 0 ) { 189 | for ( var i = 0; i < errors.length; i++ ) { 190 | console.error( 'Error: ' + errors[i].message ); 191 | } 192 | } else { 193 | console.error( 'Error: ' + errors ); 194 | } 195 | } else { 196 | console.error( 'Unknown error' ); 197 | } 198 | } 199 | 200 | }) 201 | /* 202 | BSD 3-Clause License 203 | 204 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 205 | All rights reserved. 206 | 207 | Redistribution and use in source and binary forms, with or without 208 | modification, are permitted provided that the following conditions are met: 209 | 210 | * Redistributions of source code must retain the above copyright notice, this 211 | list of conditions and the following disclaimer. 212 | 213 | * Redistributions in binary form must reproduce the above copyright notice, 214 | this list of conditions and the following disclaimer in the documentation 215 | and/or other materials provided with the distribution. 216 | 217 | * Neither the name of the copyright holder nor the names of its 218 | contributors may be used to endorse or promote products derived from 219 | this software without specific prior written permission. 220 | 221 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 222 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 223 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 224 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 225 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 226 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 227 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 228 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 229 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 230 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 231 | */ 232 | -------------------------------------------------------------------------------- /force-app/main/aura/LC_API/LC_APIRenderer.js: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | ({ 8 | unrender: function( component, helper ) { 9 | this.superUnrender(); 10 | // When component unrenders then cleanup penpal 11 | // resources by destroying the connection and nulling out 12 | // the helper's cached reference to the connection and child. 13 | // This ensures that the helper.handleXyzRequest(..) methods 14 | // wait appropriately for the new parent-child handshake to complete 15 | // when this component is re-initialized and scripts are loaded. 16 | if ( helper._penpal && helper._penpal.connection ) { 17 | helper._penpal.connection.destroy(); 18 | helper._penpal = {}; 19 | } 20 | } 21 | }) 22 | /* 23 | BSD 3-Clause License 24 | 25 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 26 | All rights reserved. 27 | 28 | Redistribution and use in source and binary forms, with or without 29 | modification, are permitted provided that the following conditions are met: 30 | 31 | * Redistributions of source code must retain the above copyright notice, this 32 | list of conditions and the following disclaimer. 33 | 34 | * Redistributions in binary form must reproduce the above copyright notice, 35 | this list of conditions and the following disclaimer in the documentation 36 | and/or other materials provided with the distribution. 37 | 38 | * Neither the name of the copyright holder nor the names of its 39 | contributors may be used to endorse or promote products derived from 40 | this software without specific prior written permission. 41 | 42 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 43 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 45 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 46 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 48 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 49 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 51 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | */ -------------------------------------------------------------------------------- /force-app/main/classes/LC_VisualforceDomainController.cls: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | public with sharing class LC_VisualforceDomainController { 8 | 9 | // Aura Component 10 | 11 | @AuraEnabled( cacheable = true ) 12 | public static String getVisualforceDomainURL() { 13 | PageReference vfPage = Page.LC_VisualforceDomainPage; 14 | return ( Test.isRunningTest() ? 'https://visualforce.com' : vfPage.getContent().toString().trim() ); 15 | } 16 | 17 | // ----------------------------------------------------------------------------- 18 | 19 | // Visualforce Page 20 | 21 | public String getDomainURL() { 22 | URL requestURL = URL.getCurrentRequestUrl(); 23 | return requestURL.toExternalForm().substringBefore( requestURL.getPath() ); 24 | } 25 | 26 | } 27 | /* 28 | BSD 3-Clause License 29 | 30 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 31 | All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | * Redistributions of source code must retain the above copyright notice, this 37 | list of conditions and the following disclaimer. 38 | 39 | * Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 43 | * Neither the name of the copyright holder nor the names of its 44 | contributors may be used to endorse or promote products derived from 45 | this software without specific prior written permission. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 51 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 54 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 55 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 56 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | */ -------------------------------------------------------------------------------- /force-app/main/classes/LC_VisualforceDomainController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/pages/LC_APIPage.page: -------------------------------------------------------------------------------- 1 | 7 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /force-app/main/pages/LC_APIPage.page-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | false 5 | false 6 | 7 | 8 | -------------------------------------------------------------------------------- /force-app/main/pages/LC_VisualforceDomainPage.page: -------------------------------------------------------------------------------- 1 | 7 | {!domainURL} 14 | -------------------------------------------------------------------------------- /force-app/main/pages/LC_VisualforceDomainPage.page-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | false 5 | false 6 | 7 | 8 | -------------------------------------------------------------------------------- /force-app/main/staticresources/jsforce.resource-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Public 4 | application/javascript 5 | v1.9.3 6 | http://jsforce.github.io/ 7 | 8 | -------------------------------------------------------------------------------- /force-app/main/staticresources/penpal.resource: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Aaron Hardy 3 | * https://unpkg.com/penpal@4.1.1/dist/penpal.min.js 4 | * https://github.com/Aaronius/penpal 5 | */ 6 | var Penpal=function(){"use strict";const e="handshake";const n="handshake-reply";const t="call";const r="reply";const o="fulfilled";const i="rejected";const c="message";const s="DataCloneError";const a="ConnectionDestroyed";const d="ConnectionTimeout";const l="NotInIframe";const u="NoIframeSrc";var m=()=>{const e=[];let n=false;return{destroy(){n=true;e.forEach(e=>{e()})},onDestroy(t){n?t():e.push(t)}}};const h={"http:":"80","https:":"443"};const f=/^(https?:)?\/\/([^\/:]+)?(:(\d+))?/;const g=["file:","data:"];var p=e=>{if(e&&g.find(n=>e.startsWith(n))){return"null"}const n=document.location;const t=f.exec(e);let r;let o;let i;if(t){r=t[1]?t[1]:n.protocol;o=t[2];i=t[4]}else{r=n.protocol;o=n.hostname;i=n.port}const c=i&&i!==h[r]?`:${i}`:"";return`${r}//${o}${c}`};var v=e=>{return function(){if(e){for(var n=arguments.length,t=new Array(n),r=0;r{let n=e.name,t=e.message,r=e.stack;return{name:n,message:t,stack:r}};const w=e=>{const n=new Error;Object.keys(e).forEach(t=>n[t]=e[t]);return n};var y=(e,n,a)=>{const d=e.localName,l=e.local,u=e.remote,m=e.originForSending,h=e.originForReceiving;let f=false;a(`${d}: Connecting call receiver`);const g=e=>{if(e.source!==u||e.data.penpal!==t){return}if(e.origin!==h){a(`${d} received message from origin ${e.origin} which did not match expected origin ${h}`);return}const c=e.data,l=c.methodName,g=c.args,p=c.id;a(`${d}: Received ${l}() call`);const v=e=>{return n=>{a(`${d}: Sending ${l}() reply`);if(f){a(`${d}: Unable to send ${l}() reply due to destroyed connection`);return}const t={penpal:r,id:p,resolution:e,returnValue:n};if(e===i&&n instanceof Error){t.returnValue=E(n);t.returnValueIsError=true}try{u.postMessage(t,m)}catch(e){if(e.name===s){u.postMessage({penpal:r,id:p,resolution:i,returnValue:E(e),returnValueIsError:true},m)}throw e}}};new Promise(e=>e(n[l].apply(n,g))).then(v(o),v(i))};l.addEventListener(c,g);return()=>{f=true;l.removeEventListener(c,g)}};let $=0;var N=()=>++$;var C=(e,n,i,s,d)=>{const l=n.localName,u=n.local,m=n.remote,h=n.originForSending,f=n.originForReceiving;let g=false;d(`${l}: Connecting call sender`);const p=e=>{return function(){for(var n=arguments.length,i=new Array(n),p=0;p{const a=N();const g=t=>{if(t.source!==m||t.data.penpal!==r||t.data.id!==a){return}if(t.origin!==f){d(`${l} received message from origin ${t.origin} which did not match expected origin ${f}`);return}d(`${l}: Received ${e}() reply`);u.removeEventListener(c,g);let i=t.data.returnValue;if(t.data.returnValueIsError){i=w(i)}(t.data.resolution===o?n:s)(i)};u.addEventListener(c,g);m.postMessage({penpal:t,id:a,methodName:e,args:i},h)})}};i.reduce((e,n)=>{e[n]=p(n);return e},e);return()=>{g=true}};const I=6e4;var T=t=>{let r=t.iframe,o=t.methods,i=o===void 0?{}:o,s=t.childOrigin,l=t.timeout,h=t.debug;const f=v(h);const g=window;const E=m(),w=E.destroy,$=E.onDestroy;if(!s){if(!r.src&&!r.srcdoc){const e=new Error("Iframe must have src or srcdoc property defined.");e.code=u;throw e}s=p(r.src)}const N=s==="null"?"*":s;const T=new Promise((t,o)=>{let u;if(l!==undefined){u=setTimeout(()=>{const e=new Error(`Connection to child timed out after ${l}ms`);e.code=d;o(e);w()},l)}const m={};let h;let p;const v=o=>{const c=r.contentWindow;if(o.source!==c||o.data.penpal!==e){return}if(o.origin!==s){f(`Parent received handshake from origin ${o.origin} which did not match expected origin ${s}`);return}f("Parent: Received handshake, sending reply");o.source.postMessage({penpal:n,methodNames:Object.keys(i)},N);const a={localName:"Parent",local:g,remote:c,originForSending:N,originForReceiving:s};if(p){p()}p=y(a,i,f);$(p);if(h){h.forEach(e=>{delete m[e]})}h=o.data.methodNames;const d=C(m,a,h,w,f);$(d);clearTimeout(u);t(m)};g.addEventListener(c,v);f("Parent: Awaiting handshake");var E=setInterval(()=>{if(!document.contains(r)){clearInterval(E);w()}},I);$(()=>{g.removeEventListener(c,v);clearInterval(E);const e=new Error("Connection destroyed");e.code=a;o(e)})});return{promise:T,destroy:w}};var k=function(){let t=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{},r=t.parentOrigin,o=r===void 0?"*":r,i=t.methods,s=i===void 0?{}:i,u=t.timeout,h=t.debug;const f=v(h);if(window===window.top){const e=new Error("connectToParent() must be called within an iframe");e.code=l;throw e}const g=m(),p=g.destroy,E=g.onDestroy;const w=window;const $=w.parent;const N=new Promise((t,r)=>{let i;if(u!==undefined){i=setTimeout(()=>{const e=new Error(`Connection to parent timed out after ${u}ms`);e.code=d;r(e);p()},u)}const l=e=>{try{clearTimeout()}catch(e){return}if(e.source!==$||e.data.penpal!==n){return}if(o!=="*"&&o!==e.origin){f(`Child received handshake reply from origin ${e.origin} which did not match expected origin ${o}`);return}f("Child: Received handshake reply");w.removeEventListener(c,l);const r={localName:"Child",local:w,remote:$,originForSending:e.origin==="null"?"*":e.origin,originForReceiving:e.origin};const a={};const d=y(r,s,f);E(d);const u=C(a,r,e.data.methodNames,p,f);E(u);clearTimeout(i);t(a)};w.addEventListener(c,l);E(()=>{w.removeEventListener(c,l);const e=new Error("Connection destroyed");e.code=a;r(e)});f("Child: Sending handshake");$.postMessage({penpal:e,methodNames:Object.keys(s)},o)});return{promise:N,destroy:p}};var O={ERR_CONNECTION_DESTROYED:a,ERR_CONNECTION_TIMEOUT:d,ERR_NOT_IN_IFRAME:l,ERR_NO_IFRAME_SRC:u,connectToChild:T,connectToParent:k};return O}(); 7 | 8 | // Expose penpal to lightning components by adding it to the `window` object. 9 | // https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/security_share_code.htm 10 | window.Penpal = Penpal; 11 | 12 | /* 13 | The MIT License (MIT) 14 | 15 | Copyright (c) 2016, Aaron Hardy 16 | 17 | Permission is hereby granted, free of charge, to any person obtaining a copy 18 | of this software and associated documentation files (the "Software"), to deal 19 | in the Software without restriction, including without limitation the rights 20 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | copies of the Software, and to permit persons to whom the Software is 22 | furnished to do so, subject to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included in all 25 | copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | SOFTWARE. 34 | */ -------------------------------------------------------------------------------- /force-app/main/staticresources/penpal.resource-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Public 4 | application/javascript 5 | v4.1.1 6 | https://github.com/Aaronius/penpal 7 | 8 | -------------------------------------------------------------------------------- /force-app/test/classes/LC_VisualforceDomainControllerTest.cls: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | @IsTest 8 | private class LC_VisualforceDomainControllerTest { 9 | 10 | // Aura Component 11 | 12 | @IsTest 13 | static void test_get_visualforce_domain_url() { 14 | 15 | Test.startTest(); 16 | 17 | String vfDomainURL = LC_VisualforceDomainController.getVisualforceDomainURL(); 18 | 19 | System.assertEquals( 'https://visualforce.com', vfDomainURL ); 20 | 21 | Test.stopTest(); 22 | 23 | } 24 | 25 | // ----------------------------------------------------------------------------- 26 | 27 | // Visualforce Page 28 | 29 | @IsTest 30 | static void test_get_domain_url() { 31 | 32 | Test.setCurrentPage( Page.LC_VisualforceDomainPage ); 33 | 34 | Test.startTest(); 35 | 36 | LC_VisualforceDomainController controller = new LC_VisualforceDomainController(); 37 | 38 | String domainURL = controller.getDomainURL(); 39 | 40 | // The test is not running in Visualforce context, 41 | // so best we can get here is domain in Apex context. 42 | System.assertEquals( URL.getSalesforceBaseUrl().toExternalForm(), domainURL ); 43 | 44 | Test.stopTest(); 45 | 46 | } 47 | 48 | } 49 | /* 50 | BSD 3-Clause License 51 | 52 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 53 | All rights reserved. 54 | 55 | Redistribution and use in source and binary forms, with or without 56 | modification, are permitted provided that the following conditions are met: 57 | 58 | * Redistributions of source code must retain the above copyright notice, this 59 | list of conditions and the following disclaimer. 60 | 61 | * Redistributions in binary form must reproduce the above copyright notice, 62 | this list of conditions and the following disclaimer in the documentation 63 | and/or other materials provided with the distribution. 64 | 65 | * Neither the name of the copyright holder nor the names of its 66 | contributors may be used to endorse or promote products derived from 67 | this software without specific prior written permission. 68 | 69 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 70 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 71 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 72 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 73 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 74 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 75 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 76 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 77 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 78 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 79 | */ -------------------------------------------------------------------------------- /force-app/test/classes/LC_VisualforceDomainControllerTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_FetchDemo/LC_FetchDemo.cmp: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |

24 |

25 | 26 | 27 | 28 | 29 |

30 |

31 |

{!v.responseText}
32 |

33 |
34 | 35 |
36 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_FetchDemo/LC_FetchDemo.cmp-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | LC_FetchDemo 5 | 6 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_FetchDemo/LC_FetchDemo.design: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_FetchDemo/LC_FetchDemoController.js: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | ({ 8 | onSubmitRequestConfirmed: function( component, event, helper ) { 9 | 10 | component.set( 'v.responseText', 'please wait...' ); 11 | 12 | let url = component.get( 'v.url' ); 13 | let method = component.get( 'v.httpMethod' ); 14 | let body = component.get( 'v.requestBody' ); 15 | let headers = component.get( 'v.requestHeaders' ); 16 | 17 | component.find( 'lc_api' ).fetchRequest({ 18 | 'url' : url, 19 | 'options' : { 20 | 'method' : method, 21 | 'body' : ( method.toLowerCase() === 'get' ) ? null : body, 22 | 'headers' : headers 23 | } 24 | }).then( $A.getCallback( function( response ) { 25 | component.set( 'v.responseIsError', false ); 26 | component.set( 'v.responseText', JSON.stringify( response, null, 2 ) ); 27 | })).catch( $A.getCallback( function( err ) { 28 | component.set( 'v.responseIsError', true ); 29 | component.set( 'v.responseText', JSON.stringify( err, null, 2 ) ); 30 | })); 31 | 32 | } 33 | }) 34 | /* 35 | BSD 3-Clause License 36 | 37 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 38 | All rights reserved. 39 | 40 | Redistribution and use in source and binary forms, with or without 41 | modification, are permitted provided that the following conditions are met: 42 | 43 | * Redistributions of source code must retain the above copyright notice, this 44 | list of conditions and the following disclaimer. 45 | 46 | * Redistributions in binary form must reproduce the above copyright notice, 47 | this list of conditions and the following disclaimer in the documentation 48 | and/or other materials provided with the distribution. 49 | 50 | * Neither the name of the copyright holder nor the names of its 51 | contributors may be used to endorse or promote products derived from 52 | this software without specific prior written permission. 53 | 54 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 55 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 57 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 58 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 60 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 61 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 62 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 63 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 | */ -------------------------------------------------------------------------------- /force-demo/main/aura/LC_RequestDemo/LC_RequestDemo.cmp: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |

24 |

25 | 26 | 27 | 28 | 29 |

30 |

31 |

{!v.responseText}
32 |

33 |
34 | 35 |
36 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_RequestDemo/LC_RequestDemo.cmp-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 47.0 4 | LC_RequestDemo 5 | 6 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_RequestDemo/LC_RequestDemo.design: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /force-demo/main/aura/LC_RequestDemo/LC_RequestDemoController.js: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Doug Ayers 3 | Website: https://douglascayers.com 4 | GitHub: https://github.com/douglascayers/sfdx-lightning-api-component 5 | License: BSD 3-Clause License 6 | */ 7 | ({ 8 | onSubmitRequestConfirmed: function( component, event, helper ) { 9 | 10 | component.set( 'v.responseText', 'please wait...' ); 11 | 12 | component.find( 'lc_api' ).restRequest({ 13 | 'url' : component.get( 'v.url' ), 14 | 'method' : component.get( 'v.httpMethod' ), 15 | 'body' : component.get( 'v.requestBody' ), 16 | 'headers' : component.get( 'v.requestHeaders' ) 17 | }).then( $A.getCallback( function( response ) { 18 | component.set( 'v.responseIsError', false ); 19 | component.set( 'v.responseText', JSON.stringify( response, null, 2 ) ); 20 | })).catch( $A.getCallback( function( err ) { 21 | component.set( 'v.responseIsError', true ); 22 | component.set( 'v.responseText', JSON.stringify( err, null, 2 ) ); 23 | })); 24 | 25 | } 26 | }) 27 | /* 28 | BSD 3-Clause License 29 | 30 | Copyright (c) 2018-2019, Doug Ayers, douglascayers.com 31 | All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | * Redistributions of source code must retain the above copyright notice, this 37 | list of conditions and the following disclaimer. 38 | 39 | * Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 43 | * Neither the name of the copyright holder nor the names of its 44 | contributors may be used to endorse or promote products derived from 45 | this software without specific prior written permission. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 51 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 54 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 55 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 56 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | */ -------------------------------------------------------------------------------- /force-demo/main/flexipages/LC_Demo.flexipage-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | httpMethod 7 | post 8 | 9 | 10 | requestBody 11 | { "Name" : "LC Demo Account" } 12 | 13 | 14 | url 15 | /services/data/v47.0/sobjects/Account 16 | 17 | LC_RequestDemo 18 | 19 | 20 | 21 | httpMethod 22 | get 23 | 24 | 25 | requestBody 26 | 27 | 28 | url 29 | /services/data/v47.0/ui-api/layout/Account 30 | 31 | LC_RequestDemo 32 | 33 | column1 34 | Region 35 | 36 | 37 | 38 | 39 | httpMethod 40 | get 41 | 42 | 43 | requestBody 44 | 45 | 46 | url 47 | /services/data/v47.0/sobjects/Account 48 | 49 | LC_RequestDemo 50 | 51 | 52 | 53 | httpMethod 54 | get 55 | 56 | 57 | requestBody 58 | 59 | 60 | url 61 | https://gist.githubusercontent.com/douglascayers/e96c53304dc78dc83e59a85753f29111/raw/sfdx-mass-action-scheduler-version.js 62 | 63 | LC_FetchDemo 64 | 65 | column2 66 | Region 67 | 68 | LC Demo 69 | 72 | AppPage 73 | 74 | -------------------------------------------------------------------------------- /force-demo/main/permissionsets/LC_Demo.permissionset-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Grants access to the LC Demo lightning tab. 4 | false 5 | 6 | 7 | LC_Demo 8 | Visible 9 | 10 | 11 | -------------------------------------------------------------------------------- /force-demo/main/tabs/LC_Demo.tab-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Created by Lightning App Builder 4 | LC_Demo 5 | 6 | Custom9: Lightning 7 | 8 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sfdx-lightning-api-component", 3 | "version": "2.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ajv": { 8 | "version": "6.10.2", 9 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", 10 | "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", 11 | "requires": { 12 | "fast-deep-equal": "^2.0.1", 13 | "fast-json-stable-stringify": "^2.0.0", 14 | "json-schema-traverse": "^0.4.1", 15 | "uri-js": "^4.2.2" 16 | } 17 | }, 18 | "asap": { 19 | "version": "2.0.6", 20 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 21 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 22 | }, 23 | "asn1": { 24 | "version": "0.2.4", 25 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 26 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 27 | "requires": { 28 | "safer-buffer": "~2.1.0" 29 | } 30 | }, 31 | "assert-plus": { 32 | "version": "1.0.0", 33 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 34 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 35 | }, 36 | "asynckit": { 37 | "version": "0.4.0", 38 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 39 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 40 | }, 41 | "aws-sign2": { 42 | "version": "0.7.0", 43 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 44 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 45 | }, 46 | "aws4": { 47 | "version": "1.9.0", 48 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", 49 | "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" 50 | }, 51 | "base64-url": { 52 | "version": "2.3.2", 53 | "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-2.3.2.tgz", 54 | "integrity": "sha512-2QpXjtjndKqPn9JKBpMTCbDGpgicfLUu+N5Y1vEfbuyqb1MN1D68C9YKCth4SjTHRvJleF3tPuxhLbH79MM0iQ==" 55 | }, 56 | "bcrypt-pbkdf": { 57 | "version": "1.0.2", 58 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 59 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 60 | "requires": { 61 | "tweetnacl": "^0.14.3" 62 | } 63 | }, 64 | "caseless": { 65 | "version": "0.12.0", 66 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 67 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 68 | }, 69 | "co-prompt": { 70 | "version": "1.0.0", 71 | "resolved": "https://registry.npmjs.org/co-prompt/-/co-prompt-1.0.0.tgz", 72 | "integrity": "sha1-+zcOntrEhXayenMv5dfyHZ/G5vY=", 73 | "requires": { 74 | "keypress": "~0.2.1" 75 | } 76 | }, 77 | "coffeescript": { 78 | "version": "1.12.7", 79 | "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz", 80 | "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==" 81 | }, 82 | "combined-stream": { 83 | "version": "1.0.8", 84 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 85 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 86 | "requires": { 87 | "delayed-stream": "~1.0.0" 88 | } 89 | }, 90 | "commander": { 91 | "version": "2.20.3", 92 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 93 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 94 | }, 95 | "core-util-is": { 96 | "version": "1.0.2", 97 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 98 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 99 | }, 100 | "csprng": { 101 | "version": "0.1.2", 102 | "resolved": "https://registry.npmjs.org/csprng/-/csprng-0.1.2.tgz", 103 | "integrity": "sha1-S8aPEvo2jSUqWYQcusqXSxirReI=", 104 | "requires": { 105 | "sequin": "*" 106 | } 107 | }, 108 | "csv-parse": { 109 | "version": "4.8.2", 110 | "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.8.2.tgz", 111 | "integrity": "sha512-WfYwyJepTbjS5jWAWpVskOJ8Z10231HaFw6qJhSjGrpfMPf3yuoRohlasYsP/6/3YgTQcvZpTvoUo37eaei9Fw==" 112 | }, 113 | "csv-stringify": { 114 | "version": "1.1.2", 115 | "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-1.1.2.tgz", 116 | "integrity": "sha1-d6QVJlgbzjOA8SsA18W7rHDIK1g=", 117 | "requires": { 118 | "lodash.get": "~4.4.2" 119 | } 120 | }, 121 | "dashdash": { 122 | "version": "1.14.1", 123 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 124 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 125 | "requires": { 126 | "assert-plus": "^1.0.0" 127 | } 128 | }, 129 | "define-properties": { 130 | "version": "1.1.3", 131 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 132 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 133 | "requires": { 134 | "object-keys": "^1.0.12" 135 | } 136 | }, 137 | "delayed-stream": { 138 | "version": "1.0.0", 139 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 140 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 141 | }, 142 | "ecc-jsbn": { 143 | "version": "0.1.2", 144 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 145 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 146 | "requires": { 147 | "jsbn": "~0.1.0", 148 | "safer-buffer": "^2.1.0" 149 | } 150 | }, 151 | "es-abstract": { 152 | "version": "1.16.3", 153 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.3.tgz", 154 | "integrity": "sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw==", 155 | "requires": { 156 | "es-to-primitive": "^1.2.1", 157 | "function-bind": "^1.1.1", 158 | "has": "^1.0.3", 159 | "has-symbols": "^1.0.1", 160 | "is-callable": "^1.1.4", 161 | "is-regex": "^1.0.4", 162 | "object-inspect": "^1.7.0", 163 | "object-keys": "^1.1.1", 164 | "string.prototype.trimleft": "^2.1.0", 165 | "string.prototype.trimright": "^2.1.0" 166 | } 167 | }, 168 | "es-to-primitive": { 169 | "version": "1.2.1", 170 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 171 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 172 | "requires": { 173 | "is-callable": "^1.1.4", 174 | "is-date-object": "^1.0.1", 175 | "is-symbol": "^1.0.2" 176 | } 177 | }, 178 | "extend": { 179 | "version": "3.0.2", 180 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 181 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 182 | }, 183 | "extsprintf": { 184 | "version": "1.3.0", 185 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 186 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 187 | }, 188 | "fast-deep-equal": { 189 | "version": "2.0.1", 190 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 191 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" 192 | }, 193 | "fast-json-stable-stringify": { 194 | "version": "2.0.0", 195 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 196 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 197 | }, 198 | "faye": { 199 | "version": "1.2.4", 200 | "resolved": "https://registry.npmjs.org/faye/-/faye-1.2.4.tgz", 201 | "integrity": "sha1-l47YpY8dSB5cH5i6y4lZ3l7FxkM=", 202 | "requires": { 203 | "asap": "*", 204 | "csprng": "*", 205 | "faye-websocket": ">=0.9.1", 206 | "tough-cookie": "*", 207 | "tunnel-agent": "*" 208 | } 209 | }, 210 | "faye-websocket": { 211 | "version": "0.11.3", 212 | "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", 213 | "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", 214 | "requires": { 215 | "websocket-driver": ">=0.5.1" 216 | } 217 | }, 218 | "forever-agent": { 219 | "version": "0.6.1", 220 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 221 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 222 | }, 223 | "form-data": { 224 | "version": "2.3.3", 225 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 226 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 227 | "requires": { 228 | "asynckit": "^0.4.0", 229 | "combined-stream": "^1.0.6", 230 | "mime-types": "^2.1.12" 231 | } 232 | }, 233 | "function-bind": { 234 | "version": "1.1.1", 235 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 236 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 237 | }, 238 | "getpass": { 239 | "version": "0.1.7", 240 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 241 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 242 | "requires": { 243 | "assert-plus": "^1.0.0" 244 | } 245 | }, 246 | "har-schema": { 247 | "version": "2.0.0", 248 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 249 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 250 | }, 251 | "har-validator": { 252 | "version": "5.1.3", 253 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 254 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 255 | "requires": { 256 | "ajv": "^6.5.5", 257 | "har-schema": "^2.0.0" 258 | } 259 | }, 260 | "has": { 261 | "version": "1.0.3", 262 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 263 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 264 | "requires": { 265 | "function-bind": "^1.1.1" 266 | } 267 | }, 268 | "has-symbols": { 269 | "version": "1.0.1", 270 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 271 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" 272 | }, 273 | "http-parser-js": { 274 | "version": "0.4.10", 275 | "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", 276 | "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=" 277 | }, 278 | "http-signature": { 279 | "version": "1.2.0", 280 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 281 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 282 | "requires": { 283 | "assert-plus": "^1.0.0", 284 | "jsprim": "^1.2.2", 285 | "sshpk": "^1.7.0" 286 | } 287 | }, 288 | "inherits": { 289 | "version": "2.0.4", 290 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 291 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 292 | }, 293 | "ip-regex": { 294 | "version": "2.1.0", 295 | "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", 296 | "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" 297 | }, 298 | "is-callable": { 299 | "version": "1.1.4", 300 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 301 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" 302 | }, 303 | "is-date-object": { 304 | "version": "1.0.1", 305 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 306 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" 307 | }, 308 | "is-regex": { 309 | "version": "1.0.4", 310 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 311 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 312 | "requires": { 313 | "has": "^1.0.1" 314 | } 315 | }, 316 | "is-symbol": { 317 | "version": "1.0.3", 318 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 319 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 320 | "requires": { 321 | "has-symbols": "^1.0.1" 322 | } 323 | }, 324 | "is-typedarray": { 325 | "version": "1.0.0", 326 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 327 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 328 | }, 329 | "is-wsl": { 330 | "version": "1.1.0", 331 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", 332 | "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" 333 | }, 334 | "isarray": { 335 | "version": "1.0.0", 336 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 337 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 338 | }, 339 | "isstream": { 340 | "version": "0.1.2", 341 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 342 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 343 | }, 344 | "jsbn": { 345 | "version": "0.1.1", 346 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 347 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 348 | }, 349 | "jsforce": { 350 | "version": "1.9.3", 351 | "resolved": "https://registry.npmjs.org/jsforce/-/jsforce-1.9.3.tgz", 352 | "integrity": "sha512-NJiBoTfsSElVZnh1MO7zv8anDPdy6vBVG19SEJ5pQtE+QJKFksjy4tpXbyzVyBft5Lo6Npr1HIPUP+RkVd9weQ==", 353 | "requires": { 354 | "base64-url": "^2.2.0", 355 | "co-prompt": "^1.0.0", 356 | "coffeescript": "^1.10.0", 357 | "commander": "^2.9.0", 358 | "csv-parse": "^4.6.3", 359 | "csv-stringify": "^1.0.4", 360 | "faye": "^1.2.0", 361 | "inherits": "^2.0.1", 362 | "lodash": "^4.17.14", 363 | "multistream": "^2.0.5", 364 | "opn": "^5.3.0", 365 | "promise": "^7.1.1", 366 | "readable-stream": "^2.1.0", 367 | "request": "^2.72.0", 368 | "xml2js": "^0.4.16" 369 | } 370 | }, 371 | "json-schema": { 372 | "version": "0.2.3", 373 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 374 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 375 | }, 376 | "json-schema-traverse": { 377 | "version": "0.4.1", 378 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 379 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 380 | }, 381 | "json-stringify-safe": { 382 | "version": "5.0.1", 383 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 384 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 385 | }, 386 | "jsprim": { 387 | "version": "1.4.1", 388 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 389 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 390 | "requires": { 391 | "assert-plus": "1.0.0", 392 | "extsprintf": "1.3.0", 393 | "json-schema": "0.2.3", 394 | "verror": "1.10.0" 395 | } 396 | }, 397 | "keypress": { 398 | "version": "0.2.1", 399 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.2.1.tgz", 400 | "integrity": "sha1-HoBFQlABjbrUw/6USX1uZ7YmnHc=" 401 | }, 402 | "lodash": { 403 | "version": "4.17.15", 404 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 405 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 406 | }, 407 | "lodash.get": { 408 | "version": "4.4.2", 409 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 410 | "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" 411 | }, 412 | "mime-db": { 413 | "version": "1.42.0", 414 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", 415 | "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" 416 | }, 417 | "mime-types": { 418 | "version": "2.1.25", 419 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", 420 | "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", 421 | "requires": { 422 | "mime-db": "1.42.0" 423 | } 424 | }, 425 | "multistream": { 426 | "version": "2.1.1", 427 | "resolved": "https://registry.npmjs.org/multistream/-/multistream-2.1.1.tgz", 428 | "integrity": "sha512-xasv76hl6nr1dEy3lPvy7Ej7K/Lx3O/FCvwge8PeVJpciPPoNCbaANcNiBug3IpdvTveZUcAV0DJzdnUDMesNQ==", 429 | "requires": { 430 | "inherits": "^2.0.1", 431 | "readable-stream": "^2.0.5" 432 | } 433 | }, 434 | "oauth-sign": { 435 | "version": "0.9.0", 436 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 437 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 438 | }, 439 | "object-inspect": { 440 | "version": "1.7.0", 441 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 442 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" 443 | }, 444 | "object-keys": { 445 | "version": "1.1.1", 446 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 447 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 448 | }, 449 | "object.getownpropertydescriptors": { 450 | "version": "2.0.3", 451 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", 452 | "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", 453 | "requires": { 454 | "define-properties": "^1.1.2", 455 | "es-abstract": "^1.5.1" 456 | } 457 | }, 458 | "opn": { 459 | "version": "5.5.0", 460 | "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", 461 | "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", 462 | "requires": { 463 | "is-wsl": "^1.1.0" 464 | } 465 | }, 466 | "penpal": { 467 | "version": "4.1.1", 468 | "resolved": "https://registry.npmjs.org/penpal/-/penpal-4.1.1.tgz", 469 | "integrity": "sha512-6d1f8khVLyBz3DnhLztbfjJ7+ANxdXRM2l6awpnCdEtbrmse4AGTsELOvGuNY0SU7xZw7heGbP6IikVvaVTOWw==" 470 | }, 471 | "performance-now": { 472 | "version": "2.1.0", 473 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 474 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 475 | }, 476 | "process-nextick-args": { 477 | "version": "2.0.1", 478 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 479 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 480 | }, 481 | "promise": { 482 | "version": "7.3.1", 483 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 484 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 485 | "requires": { 486 | "asap": "~2.0.3" 487 | } 488 | }, 489 | "psl": { 490 | "version": "1.6.0", 491 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", 492 | "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==" 493 | }, 494 | "punycode": { 495 | "version": "2.1.1", 496 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 497 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 498 | }, 499 | "qs": { 500 | "version": "6.5.2", 501 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 502 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 503 | }, 504 | "readable-stream": { 505 | "version": "2.3.6", 506 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 507 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 508 | "requires": { 509 | "core-util-is": "~1.0.0", 510 | "inherits": "~2.0.3", 511 | "isarray": "~1.0.0", 512 | "process-nextick-args": "~2.0.0", 513 | "safe-buffer": "~5.1.1", 514 | "string_decoder": "~1.1.1", 515 | "util-deprecate": "~1.0.1" 516 | }, 517 | "dependencies": { 518 | "safe-buffer": { 519 | "version": "5.1.2", 520 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 521 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 522 | } 523 | } 524 | }, 525 | "request": { 526 | "version": "2.88.0", 527 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 528 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 529 | "requires": { 530 | "aws-sign2": "~0.7.0", 531 | "aws4": "^1.8.0", 532 | "caseless": "~0.12.0", 533 | "combined-stream": "~1.0.6", 534 | "extend": "~3.0.2", 535 | "forever-agent": "~0.6.1", 536 | "form-data": "~2.3.2", 537 | "har-validator": "~5.1.0", 538 | "http-signature": "~1.2.0", 539 | "is-typedarray": "~1.0.0", 540 | "isstream": "~0.1.2", 541 | "json-stringify-safe": "~5.0.1", 542 | "mime-types": "~2.1.19", 543 | "oauth-sign": "~0.9.0", 544 | "performance-now": "^2.1.0", 545 | "qs": "~6.5.2", 546 | "safe-buffer": "^5.1.2", 547 | "tough-cookie": "~2.4.3", 548 | "tunnel-agent": "^0.6.0", 549 | "uuid": "^3.3.2" 550 | }, 551 | "dependencies": { 552 | "punycode": { 553 | "version": "1.4.1", 554 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 555 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 556 | }, 557 | "tough-cookie": { 558 | "version": "2.4.3", 559 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 560 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 561 | "requires": { 562 | "psl": "^1.1.24", 563 | "punycode": "^1.4.1" 564 | } 565 | } 566 | } 567 | }, 568 | "safe-buffer": { 569 | "version": "5.2.0", 570 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 571 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 572 | }, 573 | "safer-buffer": { 574 | "version": "2.1.2", 575 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 576 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 577 | }, 578 | "sax": { 579 | "version": "1.2.4", 580 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 581 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 582 | }, 583 | "sequin": { 584 | "version": "0.1.1", 585 | "resolved": "https://registry.npmjs.org/sequin/-/sequin-0.1.1.tgz", 586 | "integrity": "sha1-XC04nWajg3NOqvvEXt6ywcsb5wE=" 587 | }, 588 | "sshpk": { 589 | "version": "1.16.1", 590 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 591 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 592 | "requires": { 593 | "asn1": "~0.2.3", 594 | "assert-plus": "^1.0.0", 595 | "bcrypt-pbkdf": "^1.0.0", 596 | "dashdash": "^1.12.0", 597 | "ecc-jsbn": "~0.1.1", 598 | "getpass": "^0.1.1", 599 | "jsbn": "~0.1.0", 600 | "safer-buffer": "^2.0.2", 601 | "tweetnacl": "~0.14.0" 602 | } 603 | }, 604 | "string.prototype.trimleft": { 605 | "version": "2.1.0", 606 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", 607 | "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", 608 | "requires": { 609 | "define-properties": "^1.1.3", 610 | "function-bind": "^1.1.1" 611 | } 612 | }, 613 | "string.prototype.trimright": { 614 | "version": "2.1.0", 615 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", 616 | "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", 617 | "requires": { 618 | "define-properties": "^1.1.3", 619 | "function-bind": "^1.1.1" 620 | } 621 | }, 622 | "string_decoder": { 623 | "version": "1.1.1", 624 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 625 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 626 | "requires": { 627 | "safe-buffer": "~5.1.0" 628 | }, 629 | "dependencies": { 630 | "safe-buffer": { 631 | "version": "5.1.2", 632 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 633 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 634 | } 635 | } 636 | }, 637 | "tough-cookie": { 638 | "version": "3.0.1", 639 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", 640 | "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", 641 | "requires": { 642 | "ip-regex": "^2.1.0", 643 | "psl": "^1.1.28", 644 | "punycode": "^2.1.1" 645 | } 646 | }, 647 | "tunnel-agent": { 648 | "version": "0.6.0", 649 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 650 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 651 | "requires": { 652 | "safe-buffer": "^5.0.1" 653 | } 654 | }, 655 | "tweetnacl": { 656 | "version": "0.14.5", 657 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 658 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 659 | }, 660 | "uri-js": { 661 | "version": "4.2.2", 662 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 663 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 664 | "requires": { 665 | "punycode": "^2.1.0" 666 | } 667 | }, 668 | "util-deprecate": { 669 | "version": "1.0.2", 670 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 671 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 672 | }, 673 | "util.promisify": { 674 | "version": "1.0.0", 675 | "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", 676 | "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", 677 | "requires": { 678 | "define-properties": "^1.1.2", 679 | "object.getownpropertydescriptors": "^2.0.3" 680 | } 681 | }, 682 | "uuid": { 683 | "version": "3.3.3", 684 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 685 | "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" 686 | }, 687 | "verror": { 688 | "version": "1.10.0", 689 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 690 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 691 | "requires": { 692 | "assert-plus": "^1.0.0", 693 | "core-util-is": "1.0.2", 694 | "extsprintf": "^1.2.0" 695 | } 696 | }, 697 | "websocket-driver": { 698 | "version": "0.7.3", 699 | "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", 700 | "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", 701 | "requires": { 702 | "http-parser-js": ">=0.4.0 <0.4.11", 703 | "safe-buffer": ">=5.1.0", 704 | "websocket-extensions": ">=0.1.1" 705 | } 706 | }, 707 | "websocket-extensions": { 708 | "version": "0.1.3", 709 | "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", 710 | "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" 711 | }, 712 | "xml2js": { 713 | "version": "0.4.22", 714 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", 715 | "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", 716 | "requires": { 717 | "sax": ">=0.6.0", 718 | "util.promisify": "~1.0.0", 719 | "xmlbuilder": "~11.0.0" 720 | } 721 | }, 722 | "xmlbuilder": { 723 | "version": "11.0.1", 724 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 725 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 726 | } 727 | } 728 | } 729 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sfdx-lightning-api-component", 3 | "version": "2.2.0", 4 | "description": "Promise-based service component for calling REST API from Lightning Aura Components without Named Credentials.", 5 | "scripts": { 6 | "org:create": "sfdx force:org:create --setalias lapi --setdefaultusername --definitionfile config/project-scratch-def.json", 7 | "org:delete": "sfdx force:org:delete --targetusername lapi", 8 | "org:open": "sfdx force:org:open --targetusername lapi --path //lightning/n/LC_Demo", 9 | "source:deploy": "sfdx force:source:deploy --sourcepath force-app,force-demo --wait 10", 10 | "permset:assign": "sfdx force:user:permset:assign --permsetname LC_Demo", 11 | "apex:test": "sfdx force:apex:test:run --targetusername lapi --codecoverage --resultformat human --wait 10" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/douglascayers/sfdx-lightning-api-component.git" 16 | }, 17 | "keywords": [ 18 | "salesforce", 19 | "aura", 20 | "promise", 21 | "lightning-components" 22 | ], 23 | "author": "Doug Ayers", 24 | "license": "BSD-3-Clause", 25 | "bugs": "https://github.com/douglascayers/sfdx-lightning-api-component/issues", 26 | "homepage": "https://github.com/douglascayers/sfdx-lightning-api-component#readme", 27 | "dependencies": { 28 | "jsforce": "1.9.3", 29 | "penpal": "4.1.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sfdx-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageDirectories" : [ 3 | { 4 | "path" : "force-app", 5 | "default" : true 6 | }, 7 | { 8 | "path" : "force-demo", 9 | "default" : false 10 | } 11 | ], 12 | "namespace" : "", 13 | "sfdcLoginUrl" : "https://login.salesforce.com", 14 | "sourceApiVersion" : "47.0" 15 | } 16 | --------------------------------------------------------------------------------