From 2a2d11db0a579ce89b844dbbf2267380debc9c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 23 May 2014 10:31:19 +0200 Subject: [PATCH 1/4] Initial commit. --- .gitignore | 15 +++ .jshintignore | 2 + .jshintrc | 23 ++++ CONTRIBUTING.md | 194 +++++++++++++++++++++++++++++ LICENSE | 316 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 17 +++ package.json | 22 ++++ 7 files changed, 589 insertions(+) create mode 100644 .gitignore create mode 100644 .jshintignore create mode 100644 .jshintrc create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2db30da --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.idea +.project +.DS_Store +*.sublime* +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.swp +*.swo +node_modules +checkstyle.xml +loopback-connector-*.tgz diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000..25fbf5a --- /dev/null +++ b/.jshintignore @@ -0,0 +1,2 @@ +node_modules/ +coverage/ diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..66670a0 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,23 @@ +{ +"node": true, +"browser": true, +"camelcase" : true, +"eqnull" : true, +"indent": 2, +"undef": true, +"unused": true, +"quotmark": "single", +"maxlen": 90, +"trailing": true, +"newcap": true, +"nonew": true, +"sub": true, +"globals": { + "describe": true, + "it": true, + "before": true, + "beforeEach": true, + "after": true, + "afterEach": true +} +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a43e851 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,194 @@ + +### Contributing ### + +Thank you for your interest in `loopback`, an open source project +administered by StrongLoop. + +Contributing to loopback is easy. In a few simple steps: + + * Ensure that your effort is aligned with the project’s roadmap by + talking to the maintainers, especially if you are going to spend a + lot of time on it. This project is currently maintained by + [@ritch](https://github.com/ritch), [@raymondfeng](https://github.com/raymondfeng), + and [@bajtos](https://github.com/bajtos). The preferred channel of communication + is [LoopBack Forum](https://groups.google.com/forum/#!forum/loopbackjs) or + [Github Issues](https://github.com/strongloop/loopback/issues). + + * Make something better or fix a bug. + + * Adhere to code style outlined in the + [Google Javascript Style Guide][]. + + * [Sign your patches](#signing-patches) to indicate that your are + making your contribution available under the terms of the + [Contributor License Agreement](#contributor-license-agreement). + + * Submit a pull request through Github. + + +### Signing patches ### + +Like many open source projects, we need a contributor license agreement +from you before we can merge in your changes. + +In summary, by submitting your code, you are granting us a right to use +that code under the terms of this Agreement, including providing it to +others. You are also certifying that you wrote it, and that you are +allowed to license it to us. You are not giving up your copyright in +your work. The license does not change your rights to use your own +contributions for any other purpose. + +Contributor License Agreements are important because they define the +chain of ownership of a piece of software. Some companies won't allow +the use of free software without clear agreements around code ownership. +That's why many open source projects collect similar agreements from +contributors. The CLA here is based on the Apache CLA. + +To signify your agreement to these terms, add the following line to the +bottom of your commit message. Use your real name and an actual e-mail +address. + +``` +Signed-off-by: Random J Developer +``` + +Alternatively you can use the git command line to automatically add this +line, as follows: + +``` +$ git commit -sm "Replace rainbows by unicorns" +``` + + +### Contributor License Agreement ### + +``` + Individual Contributor License Agreement + + By signing this Individual Contributor License Agreement + ("Agreement"), and making a Contribution (as defined below) to + StrongLoop, Inc. ("StrongLoop"), You (as defined below) accept and + agree to the following terms and conditions for Your present and + future Contributions submitted to StrongLoop. Except for the license + granted in this Agreement to StrongLoop and recipients of software + distributed by StrongLoop, You reserve all right, title, and interest + in and to Your Contributions. + + 1. Definitions + + "You" or "Your" shall mean the copyright owner or the individual + authorized by the copyright owner that is entering into this + Agreement with StrongLoop. + + "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, that + is intentionally submitted by You to StrongLoop for inclusion in, + or documentation of, any of the products owned or managed by + StrongLoop ("Work"). For purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication + sent to StrongLoop or its representatives, including but not + limited to communication or electronic mailing lists, source code + control systems, and issue tracking systems that are managed by, + or on behalf of, StrongLoop for the purpose of discussing and + improving the Work, but excluding communication that is + conspicuously marked or otherwise designated in writing by You as + "Not a Contribution." + + 2. You Grant a Copyright License to StrongLoop + + Subject to the terms and conditions of this Agreement, You hereby + grant to StrongLoop and recipients of software distributed by + StrongLoop, a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable copyright license to reproduce, prepare + derivative works of, publicly display, publicly perform, + sublicense, and distribute Your Contributions and such derivative + works under any license and without any restrictions. + + 3. You Grant a Patent License to StrongLoop + + Subject to the terms and conditions of this Agreement, You hereby + grant to StrongLoop and to recipients of software distributed by + StrongLoop a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable (except as stated in this Section) + patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work under any license and + without any restrictions. The patent license You grant to + StrongLoop under this Section applies only to those patent claims + licensable by You that are necessarily infringed by Your + Contributions(s) alone or by combination of Your Contributions(s) + with the Work to which such Contribution(s) was submitted. If any + entity institutes a patent litigation against You or any other + entity (including a cross-claim or counterclaim in a lawsuit) + alleging that Your Contribution, or the Work to which You have + contributed, constitutes direct or contributory patent + infringement, any patent licenses granted to that entity under + this Agreement for that Contribution or Work shall terminate as + of the date such litigation is filed. + + 4. You Have the Right to Grant Licenses to StrongLoop + + You represent that You are legally entitled to grant the licenses + in this Agreement. + + If Your employer(s) has rights to intellectual property that You + create, You represent that You have received permission to make + the Contributions on behalf of that employer, that Your employer + has waived such rights for Your Contributions, or that Your + employer has executed a separate Corporate Contributor License + Agreement with StrongLoop. + + 5. The Contributions Are Your Original Work + + You represent that each of Your Contributions are Your original + works of authorship (see Section 8 (Submissions on Behalf of + Others) for submission on behalf of others). You represent that to + Your knowledge, no other person claims, or has the right to claim, + any right in any intellectual property right related to Your + Contributions. + + You also represent that You are not legally obligated, whether by + entering into an agreement or otherwise, in any way that conflicts + with the terms of this Agreement. + + You represent that Your Contribution submissions include complete + details of any third-party license or other restriction (including, + but not limited to, related patents and trademarks) of which You + are personally aware and which are associated with any part of + Your Contributions. + + 6. You Don't Have an Obligation to Provide Support for Your Contributions + + You are not expected to provide support for Your Contributions, + except to the extent You desire to provide support. You may provide + support for free, for a fee, or not at all. + + 6. No Warranties or Conditions + + StrongLoop acknowledges that unless required by applicable law or + agreed to in writing, You provide Your Contributions on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER + EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES + OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR + FITNESS FOR A PARTICULAR PURPOSE. + + 7. Submission on Behalf of Others + + If You wish to submit work that is not Your original creation, You + may submit it to StrongLoop separately from any Contribution, + identifying the complete details of its source and of any license + or other restriction (including, but not limited to, related + patents, trademarks, and license agreements) of which You are + personally aware, and conspicuously marking the work as + "Submitted on Behalf of a Third-Party: [named here]". + + 8. Agree to Notify of Change of Circumstances + + You agree to notify StrongLoop of any facts or circumstances of + which You become aware that would make these representations + inaccurate in any respect. Email us at callback@strongloop.com. +``` + + +[Google Javascript Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml +[license]: LICENSE + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..16bb096 --- /dev/null +++ b/LICENSE @@ -0,0 +1,316 @@ +Copyright (c) 2013-2014 StrongLoop, Inc and other contributors. + +loopback uses a 'dual license' model. Users may use loopback under the terms of +the MIT license, or under the StrongLoop License. The text of both is included +below. + +MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +StrongLoop License + +You may obtain a copy of the License at + + http://www.strongloop.com/license/ + +STRONGLOOP SUBSCRIPTION AGREEMENT + +PLEASE READ THIS AGREEMENT CAREFULLY BEFORE YOU AGREE TO THESE TERMS. IF YOU +ARE ACTING ON BEHALF OF AN ENTITY, THEN YOU REPRESENT THAT YOU HAVE THE +AUTHORITY TO ENTER INTO THIS AGREEMENT ON BEHALF OF THAT ENTITY. IF YOU DO NOT +AGREE TO THESE TERMS, YOU SHOULD NOT AGREE TO THE TERMS OF THIS AGREEMENT OR +INSTALL OR USE THE SOFTWARE. +This StrongLoop Subscription Agreement ("Agreement") is made by and between +StrongLoop, Inc. ("StrongLoop") with its principal place of business at 107 S. +B St, Suite 220, San Mateo, CA 94401 and the person or entity entering into this +Agreement ("Customer"). The effective date ("Effective Date") of this Agreement +is the date Customer agrees to these terms or installs or uses the Software (as +defined below). This Agreement applies to Customer's use of the Software but it +shall be superseded by any signed agreement between you and StrongLoop +concerning the Software. +1. Subscriptions and Licenses. +1.1 Subscriptions. StrongLoop offers five different subscription levels to its +customers, each as more particularly described on StrongLoop's website located +at www.strongloop.com (the "StrongLoop Site"): (1) Free; (2) Developer; (3) +Professional; (4) Gold; and (5) Platinum. The actual subscription level +applicable to Customer (the "Subscription") will be specified in the purchase +order that Customer issues to StrongLoop. This Agreement applies to Customer +regardless of the level of the Subscription selected by Customer and whether or +not Customer upgrades or downgrades its Subscription. StrongLoop hereby agrees +to provide the services as described on the StrongLoop Site for each +Subscription level during the term for which Customer has purchased the +applicable Subscription, subject to Customer paying the fees applicable to the +Subscription level purchased, if any (the "Subscription Fees"). StrongLoop may +modify the services to be provided under any Subscription upon notice to +Customer. +1.2 License Grant. Subject to the terms and conditions of this Agreement, +StrongLoop grants to Customer, during the Subscription Term (as defined in +Section 7.1 (Term and Termination) of this Agreement, a limited, non-exclusive, +non-transferable right and license, to install and use the StrongLoop Suite +software (the "Software") and the documentation made available electronically as +part of the Software (the "Documentation"), either of which may be modified +during the Term (as defined in Section 7.1 below), solely for development, +production and commercial purposes so long as Customer is using the Software to +run only one process on a given operating system at a time. This Agreement, +including but not limited to the license and restrictions contained herein, +apply to Customer regardless of whether Customer accesses the Software via +download from the StrongLoop Site or through a third-party website or service, +even if Customer acquired the Software prior to agreeing to this Agreement. +1.3 License Restrictions. Customer shall not itself, or through any parent, +subsidiary, affiliate, agent or other third party: + 1.3.1 sell, lease, license, distribute, sublicense or otherwise transfer + in whole or in part, any Software or the Documentation to a third party; + or + 1.3.2 decompile, disassemble, translate, reverse engineer or otherwise + attempt to derive source code from the Software, in whole or in part, nor + shall Customer use any mechanical, electronic or other method to trace, + decompile, disassemble, or identify the source code of the Software or + encourage others to do so, except to the limited extent, if any, that + applicable law permits such acts notwithstanding any contractual + prohibitions, provided, however, before Customer exercises any rights that + Customer believes to be entitled to based on mandatory law, Customer shall + provide StrongLoop with thirty (30) days prior written notice and provide + all reasonably requested information to allow StrongLoop to assess + Customer's claim and, at StrongLoop's sole discretion, to provide + alternatives that reduce any adverse impact on StrongLoop's intellectual + property or other rights; or + 1.3.3 allow access or permit use of the Software by any users other than + Customer's employees or authorized third-party contractors who are + providing services to Customer and agree in writing to abide by the terms + of this Agreement, provided further that Customer shall be liable for any + failure by such employees and third-party contractors to comply with the + terms of this Agreement and no usage restrictions, if any, shall be + exceeded; or + 1.3.4 create, develop, license, install, use, or deploy any third party + software or services to circumvent or provide access, permissions or + rights which violate the license keys embedded within the Software; or + 1.3.5 modify or create derivative works based upon the Software or + Documentation; or disclose the results of any benchmark test of the + Software to any third party without StrongLoop's prior written approval; + or + 1.3.6 change any proprietary rights notices which appear in the Software + or Documentation; or + 1.3.7 use the Software as part of a time sharing or service bureau + purposes or in any other resale capacity. +1.4 Third-Party Software. The Software may include individual certain software +that is owned by third parties, including individual open source software +components (the "Third-Party Software"), each of which has its own copyright and +its own applicable license conditions. Such third-party software is licensed to +Customer under the terms of the applicable third-party licenses and/or copyright +notices that can be found in the LICENSES file, the Documentation or other +materials accompanying the Software, except that Sections 5 (Warranty +Disclaimer) and 6 (Limitation of Liability) also govern Customer's use of the +third-party software. Customer agrees to comply with the terms and conditions +of the relevant third-party software licenses. +2. Support Services. StrongLoop has no obligation to provide any support for +the Software other than the support services specifically described on the +StrongLoop Site for the Subscription level procured by Customer. However, +StrongLoop has endeavored to establish a community of users of the Software who +have provided their own feedback, hints and advice regarding their experiences +in using the Software. You can find that community and user feedback on the +StrongLoop Site. The use of any information, content or other materials from, +contained in or on the StrongLoop Site are subject to the StrongLoop website +terms of use located here http://www.strongloop.com/terms-of-service. +3. Confidentiality. For purposes of this Agreement, "Confidential Information" +means any and all information or proprietary materials (in every form and media) +not generally known in the relevant trade or industry and which has been or is +hereafter disclosed or made available by StrongLoop to Customer in connection +with the transactions contemplated under this Agreement, including (i) all trade +secrets, (ii) existing or contemplated Software, services, designs, technology, +processes, technical data, engineering, techniques, methodologies and concepts +and any related information, and (iii) information relating to business plans, +sales or marketing methods and customer lists or requirements. For a period of +five (5) years from the date of disclosure of the applicable Confidential +Information, Customer shall (i) hold the Confidential Information in trust and +confidence and avoid the disclosure or release thereof to any other person or +entity by using the same degree of care as it uses to avoid unauthorized use, +disclosure, or dissemination of its own Confidential Information of a similar +nature, but not less than reasonable care, and (ii) not use the Confidential +Information for any purpose whatsoever except as expressly contemplated under +this Agreement; provided that, to the extent the Confidential Information +constitutes a trade secret under law, Customer agrees to protect such +information for so long as it qualifies as a trade secret under applicable law. +Customer shall disclose the Confidential Information only to those of its +employees and contractors having a need to know such Confidential Information +and shall take all reasonable precautions to ensure that such employees and +contractors comply with the provisions of this Section. The obligations of +Customer under this Section shall not apply to information that Customer can +demonstrate (i) was in its possession at the time of disclosure and without +restriction as to confidentiality, (ii) at the time of disclosure is generally +available to the public or after disclosure becomes generally available to the +public through no breach of agreement or other wrongful act by Customer, (iii) +has been received from a third party without restriction on disclosure and +without breach of agreement by Customer, or (iv) is independently developed by +Customer without regard to the Confidential Information. In addition, Customer +may disclose Confidential Information as required to comply with binding orders +of governmental entities that have jurisdiction over it; provided that Customer +gives StrongLoop reasonable written notice to allow StrongLoop to seek a +protective order or other appropriate remedy, discloses only such Confidential +Information as is required by the governmental entity, and uses commercially +reasonable efforts to obtain confidential treatment for any Confidential +Information disclosed. Notwithstanding the above, Customer agrees that +StrongLoop, its employees and agents shall be free to use and employ their +general skills, know-how, and expertise, and to use, disclose, and employ any +generalized ideas, concepts, know-how, methods, techniques or skills gained or +learned during the Term or thereafter. +4. Ownership. StrongLoop shall retain all intellectual property and proprietary +rights in the Software, Documentation, and related works, including but not +limited to any derivative work of the foregoing and StrongLoop's licensors shall +retain all intellectual property and proprietary rights in any Third-Party +Software that may be provided with or as a part of the Software. Customer shall +do nothing inconsistent with StrongLoop's or its licensors' title to the +Software and the intellectual property rights embodied therein, including, but +not limited to, transferring, loaning, selling, assigning, pledging, or +otherwise disposing, encumbering, or suffering a lien or encumbrance upon or +against any interest in the Software. The Software (including any Third-Party +Software) contain copyrighted material, trade secrets and other proprietary +material of StrongLoop and/or its licensors. +5. Warranty Disclaimer. THE SOFTWARE (INCLUDING ANY THIRD-PARTY SOFTWARE) AND +DOCUMENTATION MADE AVAILABLE TO CUSTOMER ARE PROVIDED "AS-IS" AND STRONGLOOP, +ON BEHALF OF ITSELF AND ITS LICENSORS, EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, TITLE, +PERFORMANCE, AND ACCURACY AND ANY IMPLIED WARRANTIES ARISING FROM STATUTE, +COURSE OF DEALING, COURSE OF PERFORMANCE, OR USAGE OF TRADE. STRONGLOOP DOES +NOT WARRANT THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR +ERROR-FREE, THAT DEFECTS IN THE SOFTWARE WILL BE CORRECTED OR THAT THE SOFTWARE +WILL PROVIDE OR ENSURE ANY PARTICULAR RESULTS OR OUTCOME. NO ORAL OR WRITTEN +INFORMATION OR ADVICE GIVEN BY STRONGLOOP OR ITS AUTHORIZED REPRESENTATIVES +SHALL CREATE A WARRANTY OR IN ANY WAY INCREASE THE SCOPE OF THIS WARRANTY. +STRONGLOOP IS NOT OBLIGATED TO PROVIDE CUSTOMER WITH UPGRADES TO THE SOFTWARE, +BUT MAY ELECT TO DO SO IN ITS SOLE DISCRETION. SOME JURISDICTIONS DO NOT ALLOW +THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO +CUSTOMER.WITHOUT LIMITING THE GENERALITY OF THE FOREGOING DISCLAIMER, THE +SOFTWARE AND DOCUMENTATION ARE NOT DESIGNED, MANUFACTURED OR INTENDED FOR USE IN +THE PLANNING, CONSTRUCTION, MAINTENANCE, CONTROL, OR DIRECT OPERATION OF NUCLEAR +FACILITIES, AIRCRAFT NAVIGATION, CONTROL OR COMMUNICATION SYSTEMS, WEAPONS +SYSTEMS, OR DIRECT LIFE SUPPORT SYSTEMS. +6. Limitation of Liability. + 6.1 Exclusion of Liability. IN NO EVENT WILL STRONGLOOP OR ITS LICENSORS + BE LIABLE UNDER THIS AGREEMENT FOR ANY INDIRECT, RELIANCE, PUNITIVE, + CONSEQUENTIAL, SPECIAL, EXEMPLARY, OR INCIDENTAL DAMAGES OF ANY KIND AND + HOWEVER CAUSED (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF + BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION AND + THE LIKE), EVEN IF STRONGLOOP HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. CUSTOMER BEARS FULL RESPONSIBILITY FOR USE OF THE SOFTWARE AND + THE SUBSCRIPTION AND STRONGLOOP DOES NOT GUARANTEE THAT THE USE OF THE + SOFTWARE AND SUBSCRIPTION WILL ENSURE THAT CUSTOMER'S NETWORK WILL BE + AVAILABLE, SECURE, MONITORED OR PROTECTED AGAINST ANY DOWNTIME, DENIAL OF + SERVICE ATTACKS, SECUITY BREACHES, HACKERS AND THE LIKE. IN NO EVENT WILL + STRONGLOOP'S CUMULATIVE LIABILITY FOR ANY DAMAGES, LOSSES AND CAUSES OF + ACTION (WHETHER IN CONTRACT, TORT, INCLUDING NEGLIGENCE, OR OTHERWISE) + ARISING OUT OF OR RELATED TO THIS AGREEMENT EXCEED THE GREATER OF ONE + HUNDRED DOLLARS (US$100) OR THE TOTAL SUBSCRIPTION FEES PAID BY CUSTOMER + TO STRONGLOOP IN THE TWELVE (12) MONTHS PRECEDING THE DATE THE CLAIM + ARISES. + 6.2 Limitation of Damages. IN NO EVENT WILL STRONGLOOP'S LICENSORS HAVE + ANY LIABILITY FOR ANY CLAIM ARISING IN CONNECTION WITH THIS AGREEMENT. + THE PROVISIONS OF THIS SECTION 6 ALLOCATE RISKS UNDER THIS AGREEMENT + BETWEEN CUSTOMER, STRONGLOOP AND STRONGLOOP'S SUPPLIERS. THE FOREGOING + LIMITATIONS, EXCLUSIONS AND DISCLAIMERS APPLY TO THE MAXIMUM EXTENT + PERMITTED BY APPLICABLE LAW, EVEN IF ANY REMEDY FAILS IN ITS ESSENTIAL + PURPOSE. + 6.3 Failure of Essential Purpose. THE PARTIES AGREE THAT THESE + LIMITATIONS SHALL APPLY EVEN IF THIS AGREEMENT OR ANY LIMITED REMEDY + SPECIFIED HEREIN IS FOUND TO HAVE FAILED OF ITS ESSENTIAL PURPOSE. + 6.4 Allocation of Risk. The sections on limitation of liability and + disclaimer of warranties allocate the risks in the Agreement between the + parties. This allocation is an essential element of the basis of the + bargain between the parties. +7. Term and Termination. +7.1 This Agreement shall commence on the Effective Date and continue for so long +as Customer has a valid Subscription and is current on the payment of any +Subscription Fees required to be paid for that Subscription (the "Subscription +Term"). Either party may terminate this Agreement immediately upon written +notice to the other party, and the Subscription and licenses granted hereunder +automatically terminate upon the termination of this Agreement. This Agreement +will terminate immediately without notice from StrongLoop if Customer fails to +comply with or otherwise breaches any provision of this Agreement. +7.2 All Sections other than Section 1.1 (Subscriptions) and 1.2 (Licenses) shall +survive the expiration or termination of this Agreement. +8. Subscription Fees and Payments. StrongLoop, Customer agrees to pay +StrongLoop the Subscription Fees as described on the StrongLoop Site for the +Subscription purchased unless a different amount has been agreed to in a +separate agreement between Customer and StrongLoop. In addition, Customer shall +pay all sales, use, value added, withholding, excise taxes and other tax, duty, +custom and similar fees levied upon the delivery or use of the Software and the +Subscriptions described in this Agreement. Fees shall be invoiced in full upon +StrongLoop's acceptance of Customer's purchase order for the Subscription. All +invoices shall be paid in US dollars and are due upon receipt and shall be paid +within thirty (30) days. Payments shall be made without right of set-off or +chargeback. If Customer does not pay the invoices when due, StrongLoop may +charge interest at one percent (1%) per month or the highest rate permitted by +law, whichever is lower, on the unpaid balance from the original due date. If +Customer fails to pay fees in accordance with this Section, StrongLoop may +suspend fulfilling its obligations under this Agreement (including but not +limited to suspending the services under the Subscription) until payment is +received by StrongLoop. If any applicable law requires Customer to withhold +amounts from any payments to StrongLoop under this Agreement, (a) Customer shall +effect such withholding, remit such amounts to the appropriate taxing +authorities and promptly furnish StrongLoop with tax receipts evidencing the +payments of such amounts and (b) the sum payable by Customer upon which the +deduction or withholding is based shall be increased to the extent necessary to +ensure that, after such deduction or withholding, StrongLoop receives and +retains, free from liability for such deduction or withholding, a net amount +equal to the amount StrongLoop would have received and retained absent the +required deduction or withholding. +9. General. +9.1 Compliance with Laws. Customer shall abide by all local, state, federal and +international laws, rules, regulations and orders applying to Customer's use of +the Software, including, without limitation, the laws and regulations of the +United States that may restrict the export and re-export of certain commodities +and technical data of United States origin, including the Software. Customer +agrees that it will not export or re-export the Software without the appropriate +United States or foreign government licenses. +9.2 Entire Agreement. This Agreement constitutes the entire agreement between +the parties concerning the subject matter hereof. This Agreement supersedes all +prior or contemporaneous discussions, proposals and agreements between the +parties relating to the subject matter hereof. No amendment, modification or +waiver of any provision of this Agreement shall be effective unless in writing +and signed by both parties. Any additional or different terms on any purchase +orders issued by Customer to StrongLoop shall not be binding on either party, +are hereby rejected by StrongLoop and void. +9.3 Severability. If any provision of this Agreement is held to be invalid or +unenforceable, the remaining portions shall remain in full force and effect and +such provision shall be enforced to the maximum extent possible so as to effect +the intent of the parties and shall be reformed to the extent necessary to make +such provision valid and enforceable. +9.4 Waiver. No waiver of rights by either party may be implied from any actions +or failures to enforce rights under this Agreement. +9.5 Force Majeure. Neither party shall be liable to the other for any delay or +failure to perform due to causes beyond its reasonable control (excluding +payment of monies due). +9.6 No Third Party Beneficiaries. Unless otherwise specifically stated, the +terms of this Agreement are intended to be and are solely for the benefit of +StrongLoop and Customer and do not create any right in favor of any third party. +9.7 Governing Law and Jurisdiction. This Agreement shall be governed by the +laws of the State of California, without reference to the principles of +conflicts of law. The provisions of the Uniform Computerized Information +Transaction Act and United Nations Convention on Contracts for the International +Sale of Goods shall not apply to this Agreement. The parties shall attempt to +resolve any dispute related to this Agreement informally, initially through +their respective management, and then by non-binding mediation in San Francisco +County, California. Any litigation related to this Agreement shall be brought +in the state or federal courts located in San Francisco County, California, and +only in those courts and each party irrevocably waives any objections to such +venue. +9.8 Notices. All notices must be in writing and shall be effective three (3) +days after the date sent to the other party's headquarters, Attention Chief +Financial Officer. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cbec962 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# LoopBack Connector + +LoopBack Connector is a set of building blocks simplifying implementation +of datasource-specific connectors like Oracle, MongoDB, REST. + +**For full documentation, see the official StrongLoop documentation**: + * [Data sources and connectors](http://docs.strongloop.com/display/DOC/Data+sources+and+connectors) + +## Installation + + npm install loopback-connector + +## Usage + +See [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql) +for an example of connector using this module. + diff --git a/package.json b/package.json new file mode 100644 index 0000000..4964419 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "loopback-connector", + "version": "1.0.0", + "description": "LoopBack connector building blocks", + "keywords": [ + "StrongLoop", + "LoopBack", + "Connector" + ], + "repository": { + "type": "git", + "url": "https://github.com/strongloop/loopback-connector" + }, + "main": "index.js", + "scripts": { + "pretest": "jshint ." + }, + "license": { + "name": "Dual MIT/StrongLoop", + "url": "https://github.com/strongloop/loopback-connector/blob/master/LICENSE" + } +} From 48884f7b7980b6bb0362a790667ac4b6ebec6f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 23 May 2014 10:50:23 +0200 Subject: [PATCH 2/4] Initial implementation. Add `lib/connector.js` and `lib/sql.js` from strongloop/loopback-datasource-juggler@5937f0c. Export both classes from `index.js` Rename `BaseSQL` to `SqlConnector`. Fix jshint errors. --- index.js | 2 + lib/connector.js | 172 ++++++++++++++++++++ lib/sql.js | 402 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 + 4 files changed, 579 insertions(+) create mode 100644 index.js create mode 100644 lib/connector.js create mode 100644 lib/sql.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..5c3f74d --- /dev/null +++ b/index.js @@ -0,0 +1,2 @@ +exports.Connector = require('./lib/connector'); +exports.SqlConnector = require('./lib/sql'); diff --git a/lib/connector.js b/lib/connector.js new file mode 100644 index 0000000..54d4227 --- /dev/null +++ b/lib/connector.js @@ -0,0 +1,172 @@ +module.exports = Connector; + +/** + * Base class for LooopBack connector. This is more a collection of useful + * methods for connectors than a super class + * @constructor + */ +function Connector(name, settings) { + this._models = {}; + this.name = name; + this.settings = settings || {}; +} + +/** + * Set the relational property to indicate the backend is a relational DB + * @type {boolean} + */ +Connector.prototype.relational = false; + +/** + * Get types associated with the connector + * @returns {String[]} The types for the connector + */ +Connector.prototype.getTypes = function() { + return ['db', 'nosql']; +}; + +/** + * Get the default data type for ID + * @returns {Function} The default type for ID + */ +Connector.prototype.getDefaultIdType = function() { + return String; +}; + +/** + * Get the metadata for the connector + * @returns {Object} The metadata object + * @property {String} type The type for the backend + * @property {Function} defaultIdType The default id type + * @property {Boolean} [isRelational] If the connector represents a relational database + * @property {Object} schemaForSettings The schema for settings object + */ +Connector.prototype.getMedadata = function () { + if (!this._metadata) { + this._metadata = { + types: this.getTypes(), + defaultIdType: this.getDefaultIdType(), + isRelational: this.isRelational || (this.getTypes().indexOf('rdbms') !== -1), + schemaForSettings: {} + }; + } + return this._metadata; +}; + +/** + * Execute a command with given parameters + * @param {String} command The command such as SQL + * @param {Object[]} [params] An array of parameters + * @param {Function} [callback] The callback function + */ +Connector.prototype.execute = function (command, params, callback) { + /*jshint unused:false */ + throw new Error('query method should be declared in connector'); +}; + +/** + * Look up the data source by model name + * @param {String} model The model name + * @returns {DataSource} The data source + */ +Connector.prototype.getDataSource = function (model) { + var m = this._models[model]; + if (!m) { + console.trace('Model not found: ' + model); + } + return m && m.model.dataSource; +}; + +/** + * Get the id property name + * @param {String} model The model name + * @returns {String} The id property name + */ +Connector.prototype.idName = function (model) { + return this.getDataSource(model).idName(model); +}; + +/** + * Get the id property names + * @param {String} model The model name + * @returns {[String]} The id property names + */ +Connector.prototype.idNames = function (model) { + return this.getDataSource(model).idNames(model); +}; + +/** + * Get the id index (sequence number, starting from 1) + * @param {String} model The model name + * @param {String} prop The property name + * @returns {Number} The id index, undefined if the property is not part + * of the primary key + */ +Connector.prototype.id = function (model, prop) { + var p = this._models[model].properties[prop]; + if (!p) { + console.trace('Property not found: ' + model + '.' + prop); + } + return p.id; +}; + +/** + * Hook to be called by DataSource for defining a model + * @param {Object} modelDefinition The model definition + */ +Connector.prototype.define = function (modelDefinition) { + if (!modelDefinition.settings) { + modelDefinition.settings = {}; + } + this._models[modelDefinition.model.modelName] = modelDefinition; +}; + +/** + * Hook to be called by DataSource for defining a model property + * @param {String} model The model name + * @param {String} propertyName The property name + * @param {Object} propertyDefinition The object for property metadata + */ +Connector.prototype.defineProperty = function (model, propertyName, propertyDefinition) { + this._models[model].properties[propertyName] = propertyDefinition; +}; + +/** + * Disconnect from the connector + */ +Connector.prototype.disconnect = function disconnect(cb) { + // NO-OP + if (cb) process.nextTick(cb); +}; + +/** + * Get the id value for the given model + * @param {String} model The model name + * @param {Object} data The model instance data + * @returns {*} The id value + * + */ +Connector.prototype.getIdValue = function (model, data) { + return data && data[this.idName(model)]; +}; + +/** + * Set the id value for the given model + * @param {String} model The model name + * @param {Object} data The model instance data + * @param {*} value The id value + * + */ +Connector.prototype.setIdValue = function (model, data, value) { + if (data) { + data[this.idName(model)] = value; + } +}; + +Connector.prototype.getType = function () { + return this.type; +}; + + + + diff --git a/lib/sql.js b/lib/sql.js new file mode 100644 index 0000000..dcad57a --- /dev/null +++ b/lib/sql.js @@ -0,0 +1,402 @@ +var util = require('util'); +var async = require('async'); +var assert = require('assert'); +var Connector = require('./connector'); + +module.exports = SqlConnector; + +/** + * Base class for connectors that are backed by relational databases/SQL + * @class + */ +function SqlConnector() { + Connector.apply(this, [].slice.call(arguments)); +} + +util.inherits(SqlConnector, Connector); + +/** + * Set the relational property to indicate the backend is a relational DB + * @type {boolean} + */ +SqlConnector.prototype.relational = true; + +/** + * Get types associated with the connector + * Returns {String[]} The types for the connector + */ +SqlConnector.prototype.getTypes = function() { + return ['db', 'rdbms', 'sql']; +}; + +/*! + * Get the default data type for ID + * Returns {Function} + */ +SqlConnector.prototype.getDefaultIdType = function() { + return Number; +}; + +SqlConnector.prototype.query = function () { + throw new Error('query method should be declared in connector'); +}; + +SqlConnector.prototype.command = function (sql, params, callback) { + return this.query(sql, params, callback); +}; + +SqlConnector.prototype.queryOne = function (sql, callback) { + return this.query(sql, function (err, data) { + if (err) { + return callback(err); + } + callback(err, data && data[0]); + }); +}; + +/** + * Get the table name for a given model. + * Returns the table name (String). + * @param {String} model The model name + */ +SqlConnector.prototype.table = function (model) { + var name = this.getDataSource(model).tableName(model); + var dbName = this.dbName; + if (typeof dbName === 'function') { + name = dbName(name); + } + return name; +}; + +/** + * Get the column name for given model property + * @param {String} model The model name + * @param {String} property The property name + * @returns {String} The column name + */ +SqlConnector.prototype.column = function (model, property) { + var name = this.getDataSource(model).columnName(model, property); + var dbName = this.dbName; + if (typeof dbName === 'function') { + name = dbName(name); + } + return name; +}; + +/** + * Get the column name for given model property + * @param {String} model The model name + * @param {String} property The property name + * @returns {Object} The column metadata + */ +SqlConnector.prototype.columnMetadata = function (model, property) { + return this.getDataSource(model).columnMetadata(model, property); +}; + +/** + * Get the corresponding property name for a given column name + * @param {String} model The model name + * @param {String} column The column name + * @returns {String} The property name for a given column + */ +SqlConnector.prototype.propertyName = function (model, column) { + var props = this._models[model].properties; + for (var p in props) { + if (this.column(model, p) === column) { + return p; + } + } + return null; +}; + +/** + * Get the id column name + * @param {String} model The model name + * @returns {String} The column name + */ +SqlConnector.prototype.idColumn = function (model) { + var name = this.getDataSource(model).idColumnName(model); + var dbName = this.dbName; + if (typeof dbName === 'function') { + name = dbName(name); + } + return name; +}; + +/** + * Get the escaped id column name + * @param {String} model The model name + * @returns {String} the escaped id column name + */ +SqlConnector.prototype.idColumnEscaped = function (model) { + return this.escapeName(this.getDataSource(model).idColumnName(model)); +}; + +/** + * Escape the name for the underlying database + * @param {String} name The name + */ +SqlConnector.prototype.escapeName = function (name) { + /*jshint unused:false */ + throw new Error('escapeName method should be declared in connector'); +}; + +/** + * Get the escaped table name + * @param {String} model The model name + * @returns {String} the escaped table name + */ +SqlConnector.prototype.tableEscaped = function (model) { + return this.escapeName(this.table(model)); +}; + +/** + * Get the escaped column name for a given model property + * @param {String} model The model name + * @param {String} property The property name + * @returns {String} The escaped column name + */ +SqlConnector.prototype.columnEscaped = function (model, property) { + return this.escapeName(this.column(model, property)); +}; + +function isIdValuePresent(idValue, callback, returningNull) { + try { + assert(idValue !== null && idValue !== undefined, 'id value is required'); + return true; + } catch (err) { + process.nextTick(function () { + if(callback) callback(returningNull ? null: err); + }); + return false; + } +} +/** + * Save the model instance into the backend store + * @param {String} model The model name + * @param {Object} data The model instance data + * @param {Function} callback The callback function + */ +SqlConnector.prototype.save = function (model, data, callback) { + var idName = this.getDataSource(model).idName(model); + var idValue = data[idName]; + + if (!isIdValuePresent(idValue, callback)) { + return; + } + + idValue = this._escapeIdValue(model, idValue); + var sql = 'UPDATE ' + this.tableEscaped(model) + ' SET ' + + this.toFields(model, data) + + ' WHERE ' + this.idColumnEscaped(model) + ' = ' + idValue; + + this.query(sql, function (err, result) { + if (callback) callback(err, result); + }); +}; + +/** + * Check if a model instance exists for the given id value + * @param {String} model The model name + * @param {*} id The id value + * @param {Function} callback The callback function + */ +SqlConnector.prototype.exists = function (model, id, callback) { + if (!isIdValuePresent(id, callback, true)) { + return; + } + var sql = 'SELECT 1 FROM ' + + this.tableEscaped(model) + ' WHERE ' + + this.idColumnEscaped(model) + ' = ' + this._escapeIdValue(model, id) + + ' LIMIT 1'; + + this.query(sql, function (err, data) { + if (!callback) return; + if (err) { + callback(err); + } else { + callback(null, data.length >= 1); + } + }); +}; + +/** + * Find a model instance by id + * @param {String} model The model name + * @param {*} id The id value + * @param {Function} callback The callback function + */ +SqlConnector.prototype.find = function find(model, id, callback) { + if (!isIdValuePresent(id, callback, true)) { + return; + } + var self = this; + var idQuery = this.idColumnEscaped(model) + ' = ' + this._escapeIdValue(model, id); + var sql = 'SELECT * FROM ' + + this.tableEscaped(model) + ' WHERE ' + idQuery + ' LIMIT 1'; + + this.query(sql, function (err, data) { + var result = (data && data.length >= 1) ? data[0] : null; + if (callback) callback(err, self.fromDatabase(model, result)); + }); +}; + +/** + * Delete a model instance by id value + * @param {String} model The model name + * @param {*} id The id value + * @param {Function} callback The callback function + */ +SqlConnector.prototype.delete = +SqlConnector.prototype.destroy = function destroy(model, id, callback) { + if (!isIdValuePresent(id, callback, true)) { + return; + } + var sql = 'DELETE FROM ' + this.tableEscaped(model) + ' WHERE ' + + this.idColumnEscaped(model) + ' = ' + this._escapeIdValue(model, id); + + this.command(sql, function (err, result) { + if (callback) callback(err, result); + }); +}; + +SqlConnector.prototype._escapeIdValue = function(model, idValue) { + var idProp = this.getDataSource(model).idProperty(model); + if(typeof this.toDatabase === 'function') { + return this.toDatabase(idProp, idValue); + } else { + if(idProp.type === Number) { + return idValue; + } else { + return '\'' + idValue + '\''; + } + } +}; + +/** + * Delete all model instances + * + * @param {String} model The model name + * @param {Function} callback The callback function + */ +SqlConnector.prototype.deleteAll = +SqlConnector.prototype.destroyAll = function destroyAll(model, callback) { + this.command('DELETE FROM ' + this.tableEscaped(model), function (err, result) { + if (callback) callback(err, result); + }); +}; + +/** + * Count all model instances by the where filter + * + * @param {String} model The model name + * @param {Function} callback The callback function + * @param {Object} where The where clause + */ +SqlConnector.prototype.count = function count(model, callback, where) { + var self = this; + var props = this._models[model].properties; + + this.queryOne('SELECT count(*) as cnt FROM ' + + this.tableEscaped(model) + ' ' + buildWhere(where), function (err, res) { + if (err) { + return callback(err); + } + callback(err, res && res.cnt); + }); + + function buildWhere(conds) { + var cs = []; + Object.keys(conds || {}).forEach(function (key) { + var keyEscaped = self.columnEscaped(model, key); + if (conds[key] === null) { + cs.push(keyEscaped + ' IS NULL'); + } else { + cs.push(keyEscaped + ' = ' + self.toDatabase(props[key], conds[key])); + } + }); + return cs.length ? ' WHERE ' + cs.join(' AND ') : ''; + } +}; + +/** + * Update attributes for a given model instance + * @param {String} model The model name + * @param {*} id The id value + * @param {Object} data The model data instance containing all properties to be updated + * @param {Function} cb The callback function + */ +SqlConnector.prototype.updateAttributes = function updateAttrs(model, id, data, cb) { + if (!isIdValuePresent(id, cb)) { + return; + } + var idName = this.getDataSource(model).idName(model); + data[idName] = id; + this.save(model, data, cb); +}; + +/** + * Disconnect from the connector + */ +SqlConnector.prototype.disconnect = function disconnect() { + // No operation +}; + +/** + * Recreate the tables for the given models + * @param {[String]|String} [models] A model name or an array of model names, + * if not present, apply to all models defined in the connector + * @param {Function} [cb] The callback function + */ +SqlConnector.prototype.automigrate = function (models, cb) { + var self = this; + + if ((!cb) && ('function' === typeof models)) { + cb = models; + models = undefined; + } + // First argument is a model name + if ('string' === typeof models) { + models = [models]; + } + + models = models || Object.keys(self._models); + async.each(models, function (model, callback) { + if (model in self._models) { + self.dropTable(model, function (err) { + if (err) { + // TODO(bajtos) should we abort here and call cb(err)? + // The original code in juggler ignored the error completely + console.error(err); + } + self.createTable(model, function (err, result) { + if (err) { + console.error(err); + } + callback(err, result); + }); + }); + } + }, cb); +}; + +/** + * Drop the table for the given model from the database + * @param {String} model The model name + * @param {Function} [cb] The callback function + */ +SqlConnector.prototype.dropTable = function (model, cb) { + this.command('DROP TABLE IF EXISTS ' + this.tableEscaped(model), cb); +}; + +/** + * Create the table for the given model + * @param {String} model The model name + * @param {Function} [cb] The callback function + */ + +SqlConnector.prototype.createTable = function (model, cb) { + this.command('CREATE TABLE ' + this.tableEscaped(model) + + ' (\n ' + this.propertiesSQL(model) + '\n)', cb); +}; + diff --git a/package.json b/package.json index 4964419..19be599 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,8 @@ "license": { "name": "Dual MIT/StrongLoop", "url": "https://github.com/strongloop/loopback-connector/blob/master/LICENSE" + }, + "dependencies": { + "async": "^0.9.0" } } From 96d3332165b444564caca2af21ca544d6d8d236f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 23 May 2014 19:18:11 +0200 Subject: [PATCH 3/4] fixup: add a stub test --- package.json | 6 +++++- test/smoke.test.js | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/smoke.test.js diff --git a/package.json b/package.json index 19be599..cf2e570 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ }, "main": "index.js", "scripts": { - "pretest": "jshint ." + "pretest": "jshint .", + "test": "mocha" }, "license": { "name": "Dual MIT/StrongLoop", @@ -21,5 +22,8 @@ }, "dependencies": { "async": "^0.9.0" + }, + "devDependencies": { + "mocha": "^1.19.0" } } diff --git a/test/smoke.test.js b/test/smoke.test.js new file mode 100644 index 0000000..70f742b --- /dev/null +++ b/test/smoke.test.js @@ -0,0 +1,12 @@ +var assert = require('assert'); +var connector = require('../'); + +describe('loopback-connector', function() { + it('exports Connector', function() { + assert(connector.Connector); + }); + + it('exports SqlConnector', function() { + assert(connector.SqlConnector); + }); +}); From 2efe31d76310bf61d2c98247beeceddedaa5e4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 3 Jun 2014 08:40:17 +0200 Subject: [PATCH 4/4] 1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cf2e570..d4c0ab3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "loopback-connector", "version": "1.0.0", - "description": "LoopBack connector building blocks", + "description": "Building blocks for LoopBack connectors", "keywords": [ "StrongLoop", "LoopBack",