diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6e87a00 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..3856c8c --- /dev/null +++ b/.eslintrc @@ -0,0 +1,41 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module", + "project": "./tsconfig.base.json" + }, + "ignorePatterns": ["**/*"], + "plugins": ["@typescript-eslint", "@nrwl/nx"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + "prettier/@typescript-eslint" + ], + "rules": { + "@typescript-eslint/explicit-member-accessibility": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-parameter-properties": "off", + "@nrwl/nx/enforce-module-boundaries": [ + "error", + { + "enforceBuildableLibDependency": true, + "allow": [], + "depConstraints": [ + { "sourceTag": "*", "onlyDependOnLibsWithTags": ["*"] } + ] + } + ] + }, + "overrides": [ + { + "files": ["*.tsx"], + "rules": { + "@typescript-eslint/no-unused-vars": "off" + } + } + ] +} diff --git a/.gitignore b/.gitignore index 8b49c30..ea0c923 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,44 @@ -*.js -*.js.map -*.log -!scripts/*.js -demo/app/*.js -!demo/karma.conf.js -!demo/app/tests/*.js -demo/*.d.ts -!demo/references.d.ts -demo/lib -demo/platforms -demo/node_modules -node_modules \ No newline at end of file +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc + +# dependencies +node_modules +package-lock.json +yarn.lock + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db + +*.tgz +packages/**/angular/dist diff --git a/.npmignore b/.npmignore deleted file mode 100644 index d222e7e..0000000 --- a/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -demo/ -screenshots/ -*.gif -*.png -*.log -*.map -*.ts -!*.d.ts diff --git a/.npsrc b/.npsrc new file mode 100644 index 0000000..12f87dc --- /dev/null +++ b/.npsrc @@ -0,0 +1,3 @@ +{ + "config": "./tools/workspace-scripts.js" +} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..413ca14 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Add files here to ignore them from prettier formatting + +/dist +/coverage +native-src diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..4a9f8e0 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "useTabs": true, + "printWidth": 600, + "tabWidth": 2, + "singleQuote": true +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8c3d1ac --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "node" +script: +- npm run setup +- npm start @nativescript.build-all diff --git a/LICENSE b/LICENSE index 9d6ed2d..061c440 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -The MIT License (MIT) - -nativescript-yourplugin -Copyright (c) 2016, Your Name - -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. \ No newline at end of file + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You 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 the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You 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, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its 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. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2015-2019 Progress Software Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index 553eecc..fb9d57d 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,71 @@ -# Develop a NativeScript plugin +**=== IMPORTANT** -## Getting started +**Download and Configure first:** -1. `git clone https://github.com/NathanWalker/nativescript-plugin-seed.git myplugin` -2. `cd myplugin` -3. `npm run postclone` -4. `npm run setup` -5. Get to work. +1. Download a zip of this repo +2. Unzip and name the folder appropriately (perhaps the name of the npm scope you intend to manage here) +3. Setup workspace: `npm run setup` +4. Configure your npm scope: `npm run config` -This seed expands on several things [presented here](http://developer.telerik.com/featured/creating-nativescript-plugins-in-typescript/). +=== -## Usage - -The seed is prepared to allow you to test and try out your plugin via the `demo` folder. -Additionally it provides a proper `.gitignore` to keep GitHub tidy as well as `.npmignore` to ensure everyone is happy when you publish your plugin via npm. - -### Linking to CocoaPod or Android Arsenal plugins - -You will want to create these folders and files in the root: +# @nativescript/\* plugins ``` -platforms -- - ios -- - Podfile - android -- - include.gradle +npm run setup +npm start ``` -Doing so will open up those native apis to your plugin :) - -Take a look at these existing plugins for how that can be done very simply: +- @nativescript/yourplugin -* [nativescript-cardview](https://github.com/bradmartin/nativescript-cardview/tree/master/platforms) -* [nativescript-floatingactionbutton](https://github.com/bradmartin/nativescript-floatingactionbutton/tree/master/platforms) +# How to use? -### Typical development workflow: +This workspace manages the suite of plugins listed above. -1. Make changes to plugin files -2. Make changes in `demo` that would test those changes out -3. `npm run demo.ios` or `npm run demo.android` **(must be run from the root directory)** +In general, when in doubt with what to do, just `npm start`. -Those `demo` tasks are just general helpers. You may want to have more granular control on the device and/or emulator you want to run. For that, you can just run things the manual way: +## How to add a new package to workspace? ``` -cd demo - -// when developing, to ensure the latest code is built into the demo, it's a guarantee to remove the plugin and add it back -tns plugin remove nativescript-yourplugin -tns plugin add .. - -// manual platform adds -tns platform add ios -// and/or -tns platform add android +npm run add ``` -Then use any of the available options from the `tns` command line: - -* [Emulate your project](https://github.com/NativeScript/nativescript-cli#emulate-your-project) -* [Run your project](https://github.com/NativeScript/nativescript-cli#run-your-project) -* [Full list of commands](https://github.com/NativeScript/nativescript-cli#the-commands) +At the prompt, enter the name of the new package. -## Unittesting -This plugin automatically adds Jasmine-based unittest support to your plugin. -Open `demo/app/tests/tests.js` and adjust its contents. +- This adds a plugin harness in `packages` with the necessary boilerplate to just start developing +- Updates all demo app flavors to support demoing the new package +- Adds shared code in `tools/demo` where you can write demo code **once** and share across all demo flavors +- Updates build tooling to support the new package +- Updates the `npm start` interactive display +- Updates the README here to list the new package -You can read more about this topic [here](https://docs.nativescript.org/tooling/testing). - -Once you're ready to test your plugin's API execute one of these commands in the plugin root: +## How to add Angular compatibility to a package ``` -npm run test.ios -npm run test.android +npm run add-angular ``` -## Publish +At the prompt, enter the name of the package to add an `angular` folder to it with the necessary boilerplate to provide Angular support to the package. -When you have everything ready to publish: +## How to focus on just 1 package to develop in isolation -* Bump the version number in `package.json` -* `npm run build` - **very important** - ensure the latest is built **before** you publish -* `npm publish` +``` +npm start +``` -## Contributing - Want to make the seed better? +- Choose the focus commands for the package you wish to focus on and hit enter. +- All the demo app's will be updated to isolate that 1 package and for supported IDE's (currently VS Code), the source code will also become isolated in the workspace. -Or at least help keep it up to date with NativeScript releases, which would be excellent. +Note: _good to always clean the demo you plan to run after focusing. (You can clean any demo from `npm start` as well)_ -``` -npm install -g typescript // if you don't already have it -git clone https://github.com/NathanWalker/nativescript-plugin-seed -cd nativescript-plugin-seed +## How to publish packages? -// Improve! ``` +npm run publish-packages +``` + +- You will be prompted for the package names to publish. Leaving blank and hitting enter will publish them all. +- You will then be prompted for the version to use. Leaving blank will auto bump the patch version (it also handles prerelease types like alpha, beta, rc, etc. - It even auto tags the corresponding prelease type on npm). +- You will then be given a brief sanity check ๐Ÿง ๐Ÿ˜Š + +

Made with โค๏ธ

diff --git a/apps/demo-angular/.gitignore b/apps/demo-angular/.gitignore new file mode 100644 index 0000000..74ba2bc --- /dev/null +++ b/apps/demo-angular/.gitignore @@ -0,0 +1,3 @@ +hooks +platforms +!webpack.config.js \ No newline at end of file diff --git a/apps/demo-angular/nativescript.config.ts b/apps/demo-angular/nativescript.config.ts new file mode 100644 index 0000000..395e275 --- /dev/null +++ b/apps/demo-angular/nativescript.config.ts @@ -0,0 +1,11 @@ +import { NativeScriptConfig } from '@nativescript/core'; + +export default { + id: 'org.nativescript.plugindemoangular', + appResourcesPath: '../../tools/assets/App_Resources', + android: { + v8Flags: '--expose_gc', + markingMode: 'none', + }, + appPath: 'src', +} as NativeScriptConfig; diff --git a/apps/demo-angular/package.json b/apps/demo-angular/package.json new file mode 100644 index 0000000..3f2f0f2 --- /dev/null +++ b/apps/demo-angular/package.json @@ -0,0 +1,28 @@ +{ + "main": "main.js", + "dependencies": { + "@angular/animations": "file:../../node_modules/@angular/animations", + "@angular/common": "file:../../node_modules/@angular/common", + "@angular/compiler": "file:../../node_modules/@angular/compiler", + "@angular/core": "file:../../node_modules/@angular/core", + "@angular/forms": "file:../../node_modules/@angular/forms", + "@angular/platform-browser": "file:../../node_modules/@angular/platform-browser", + "@angular/platform-browser-dynamic": "file:../../node_modules/@angular/platform-browser-dynamic", + "@angular/router": "file:../../node_modules/@angular/router", + "@nativescript/angular": "file:../../node_modules/@nativescript/angular", + "@nativescript/core": "file:../../node_modules/@nativescript/core", + "nativescript-theme-core": "file:../../node_modules/nativescript-theme-core", + "reflect-metadata": "file:../../node_modules/reflect-metadata", + "rxjs": "file:../../node_modules/rxjs", + "zone.js": "file:../../node_modules/zone.js", + "@nativescript/yourplugin": "file:../../dist/packages/yourplugin" + }, + "devDependencies": { + "@angular/compiler-cli": "file:../../node_modules/@angular/compiler-cli", + "@nativescript/android": "~7.0.0", + "@nativescript/ios": "7.0.0", + "@nativescript/webpack": "~3.0.0", + "@ngtools/webpack": "file:../../node_modules/@ngtools/webpack", + "typescript": "file:../../node_modules/typescript" + } +} diff --git a/apps/demo-angular/references.d.ts b/apps/demo-angular/references.d.ts new file mode 100644 index 0000000..22bac92 --- /dev/null +++ b/apps/demo-angular/references.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/demo-angular/src/app-routing.module.ts b/apps/demo-angular/src/app-routing.module.ts new file mode 100644 index 0000000..cad2265 --- /dev/null +++ b/apps/demo-angular/src/app-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { Routes } from '@angular/router'; +import { NativeScriptRouterModule } from '@nativescript/angular'; + +import { HomeComponent } from './home.component'; + +const routes: Routes = [ + { path: '', redirectTo: '/home', pathMatch: 'full' }, + { path: 'home', component: HomeComponent }, + { path: 'yourplugin', loadChildren: () => import('./plugin-demos/yourplugin.module').then((m) => m.YourpluginModule) }, +]; + +@NgModule({ + imports: [NativeScriptRouterModule.forRoot(routes)], + exports: [NativeScriptRouterModule], +}) +export class AppRoutingModule {} diff --git a/apps/demo-angular/src/app.component.ts b/apps/demo-angular/src/app.component.ts new file mode 100644 index 0000000..e37a75f --- /dev/null +++ b/apps/demo-angular/src/app.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'demo-app', + template: ` + + `, +}) +export class AppComponent {} diff --git a/apps/demo-angular/src/app.css b/apps/demo-angular/src/app.css new file mode 100644 index 0000000..386a8ee --- /dev/null +++ b/apps/demo-angular/src/app.css @@ -0,0 +1,21 @@ +๏ปฟ@import '~nativescript-theme-core/css/core.light.css'; + +button, label, stack-layout { + horizontal-align: center; +} + +button { + font-size: 36; +} + +.title { + font-size: 30; + margin: 20; +} + +.message { + font-size: 20; + color: #284848; + text-align: center; + margin: 0 20; +} diff --git a/apps/demo-angular/src/app.module.ts b/apps/demo-angular/src/app.module.ts new file mode 100644 index 0000000..c869e4d --- /dev/null +++ b/apps/demo-angular/src/app.module.ts @@ -0,0 +1,14 @@ +import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core'; +import { NativeScriptModule } from '@nativescript/angular'; + +import { AppComponent } from './app.component'; +import { AppRoutingModule } from './app-routing.module'; +import { HomeComponent } from './home.component'; + +@NgModule({ + schemas: [NO_ERRORS_SCHEMA], + declarations: [AppComponent, HomeComponent], + bootstrap: [AppComponent], + imports: [NativeScriptModule, AppRoutingModule], +}) +export class AppModule {} diff --git a/apps/demo-angular/src/home.component.html b/apps/demo-angular/src/home.component.html new file mode 100644 index 0000000..b6ad279 --- /dev/null +++ b/apps/demo-angular/src/home.component.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/demo-angular/src/home.component.ts b/apps/demo-angular/src/home.component.ts new file mode 100644 index 0000000..0f1e46d --- /dev/null +++ b/apps/demo-angular/src/home.component.ts @@ -0,0 +1,13 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'demo-home', + templateUrl: 'home.component.html', +}) +export class HomeComponent { + demos = [ + { + name: 'yourplugin', + }, + ]; +} diff --git a/apps/demo-angular/src/main.ts b/apps/demo-angular/src/main.ts new file mode 100644 index 0000000..b6b1db3 --- /dev/null +++ b/apps/demo-angular/src/main.ts @@ -0,0 +1,4 @@ +import { platformNativeScriptDynamic } from "@nativescript/angular"; +import { AppModule } from "./app.module"; + +platformNativeScriptDynamic().bootstrapModule(AppModule); \ No newline at end of file diff --git a/apps/demo-angular/src/plugin-demos/.gitkeep b/apps/demo-angular/src/plugin-demos/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/demo-angular/src/plugin-demos/yourplugin.component.html b/apps/demo-angular/src/plugin-demos/yourplugin.component.html new file mode 100644 index 0000000..f70630f --- /dev/null +++ b/apps/demo-angular/src/plugin-demos/yourplugin.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/demo-angular/src/plugin-demos/yourplugin.component.ts b/apps/demo-angular/src/plugin-demos/yourplugin.component.ts new file mode 100644 index 0000000..bae2f60 --- /dev/null +++ b/apps/demo-angular/src/plugin-demos/yourplugin.component.ts @@ -0,0 +1,17 @@ +import { Component, NgZone } from '@angular/core'; +import { DemoSharedYourplugin } from '@demo/shared'; +import {} from '@nativescript/yourplugin'; + +@Component({ + selector: 'demo-yourplugin', + templateUrl: 'yourplugin.component.html', +}) +export class YourpluginComponent { + demoShared: DemoSharedYourplugin; + + constructor(private _ngZone: NgZone) {} + + ngOnInit() { + this.demoShared = new DemoSharedYourplugin(); + } +} diff --git a/apps/demo-angular/src/plugin-demos/yourplugin.module.ts b/apps/demo-angular/src/plugin-demos/yourplugin.module.ts new file mode 100644 index 0000000..d96de1a --- /dev/null +++ b/apps/demo-angular/src/plugin-demos/yourplugin.module.ts @@ -0,0 +1,10 @@ +import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core'; +import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular'; +import { YourpluginComponent } from './yourplugin.component'; + +@NgModule({ + imports: [NativeScriptCommonModule, NativeScriptRouterModule.forChild([{ path: '', component: YourpluginComponent }])], + declarations: [YourpluginComponent], + schemas: [NO_ERRORS_SCHEMA], +}) +export class YourpluginModule {} diff --git a/apps/demo-angular/tsconfig.json b/apps/demo-angular/tsconfig.json new file mode 100644 index 0000000..0ba046a --- /dev/null +++ b/apps/demo-angular/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDirs": [ + ".", + "../.." + ], + "baseUrl": ".", + "paths": { + "~/*": [ + "src/*" + ], + "@nativescript/*": [ + "../../dist/packages/*" + ], + "@demo/shared": [ + "../../tools/demo/index.ts" + ] + } + }, + "files": [ + "./references.d.ts", + "./src/main.ts" + ] +} \ No newline at end of file diff --git a/apps/demo-angular/webpack.config.js b/apps/demo-angular/webpack.config.js new file mode 100644 index 0000000..fe48a43 --- /dev/null +++ b/apps/demo-angular/webpack.config.js @@ -0,0 +1,436 @@ +const { join, relative, resolve, sep, dirname } = require('path'); +const fs = require('fs'); + +const webpack = require('webpack'); +const nsWebpack = require('@nativescript/webpack'); +const nativescriptTarget = require('@nativescript/webpack/nativescript-target'); +const { + nsSupportHmrNg +} = require('@nativescript/webpack/transformers/ns-support-hmr-ng'); +const { nsTransformNativeClassesNg } = require("@nativescript/webpack/transformers/ns-transform-native-classes-ng"); +const { + getMainModulePath +} = require('@nativescript/webpack/utils/ast-utils'); +const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require("@nativescript/webpack/utils/tsconfig-utils"); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const { + NativeScriptWorkerPlugin +} = require('nativescript-worker-loader/NativeScriptWorkerPlugin'); +const TerserPlugin = require('terser-webpack-plugin'); +const { + getAngularCompilerPlugin +} = require('@nativescript/webpack/plugins/NativeScriptAngularCompilerPlugin'); +const hashSalt = Date.now().toString(); + +module.exports = env => { + // Add your custom Activities, Services and other Android app components here. + const appComponents = [ + "@nativescript/core/ui/frame", "@nativescript/core/ui/frame/activity" + ]; + + const platform = env && ((env.android && 'android') || (env.ios && 'ios')); + if (!platform) { + throw new Error('You need to provide a target platform!'); + } + + const AngularCompilerPlugin = getAngularCompilerPlugin(platform); + const projectRoot = __dirname; + + // Default destination inside platforms//... + const dist = resolve( + projectRoot, + nsWebpack.getAppPath(platform, projectRoot) + ); + + const { + // The 'appPath' and 'appResourcesPath' values are fetched from + // the nsconfig.json configuration file + // when bundling with `tns run android|ios --bundle`. + appPath = 'src', + appResourcesPath = 'App_Resources', + + // You can provide the following flags when running 'tns run android|ios' + snapshot, // --env.snapshot, + production, // --env.production + uglify, // --env.uglify + report, // --env.report + sourceMap, // --env.sourceMap + hiddenSourceMap, // --env.hiddenSourceMap + hmr, // --env.hmr, + unitTesting, // --env.unitTesting + testing, // --env.testing + verbose, // --env.verbose + ci, // --env.ci + snapshotInDocker, // --env.snapshotInDocker + skipSnapshotTools, // --env.skipSnapshotTools + compileSnapshot // --env.compileSnapshot + } = env; + + const useLibs = compileSnapshot; + const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; + const externals = nsWebpack.getConvertedExternals(env.externals); + const appFullPath = resolve(projectRoot, appPath); + const appResourcesFullPath = resolve(projectRoot, appResourcesPath); + let tsConfigName = 'tsconfig.json'; + let tsConfigTnsName = 'tsconfig.tns.json'; + let tsConfigPath = resolve(projectRoot, tsConfigName); + const tsConfigTnsPath = resolve(projectRoot, tsConfigTnsName); + if (fs.existsSync(tsConfigTnsPath)) { + // still support shared angular app configurations + tsConfigName = tsConfigTnsName; + tsConfigPath = tsConfigTnsPath; + } + const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`; + const entryPath = `.${sep}${entryModule}`; + const entries = { bundle: entryPath }; + const areCoreModulesExternal = + Array.isArray(env.externals) && + env.externals.some(e => e.indexOf('@nativescript') > -1); + if (platform === 'ios' && !areCoreModulesExternal && !testing) { + entries['tns_modules/@nativescript/core/inspector_modules'] = + 'inspector_modules'; + } + + const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath); + nsWebpack.processTsPathsForScopedModules({ compilerOptions }); + nsWebpack.processTsPathsForScopedAngular({ compilerOptions }); + + const ngCompilerTransformers = [nsTransformNativeClassesNg]; + const additionalLazyModuleResources = []; + + const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }; + const copyTargets = [ + { from: 'assets/**', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } }, + { from: 'fonts/**', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } }, + ]; + + if (!production) { + // for development purposes only + // for example, include mock json folder + // copyTargets.push({ from: 'tools/mockdata', to: 'assets/mockdata' }); + + if (hmr) { + ngCompilerTransformers.push(nsSupportHmrNg); + } + } + + // when "@angular/core" is external, it's not included in the bundles. In this way, it will be used + // directly from node_modules and the Angular modules loader won't be able to resolve the lazy routes + // fixes https://github.com/NativeScript/nativescript-cli/issues/4024 + if (env.externals && env.externals.indexOf('@angular/core') > -1) { + const appModuleRelativePath = getMainModulePath( + resolve(appFullPath, entryModule), + tsConfigName + ); + if (appModuleRelativePath) { + const appModuleFolderPath = dirname( + resolve(appFullPath, appModuleRelativePath) + ); + // include the new lazy loader path in the allowed ones + additionalLazyModuleResources.push(appModuleFolderPath); + } + } + + const ngCompilerPlugin = new AngularCompilerPlugin({ + hostReplacementPaths: nsWebpack.getResolver([platform, 'tns']), + platformTransformers: ngCompilerTransformers.map(t => + t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot) + ), + mainPath: join(appFullPath, entryModule), + tsConfigPath, + skipCodeGeneration: false, + sourceMap: !!isAnySourceMapEnabled, + additionalLazyModuleResources: additionalLazyModuleResources, + compilerOptions: { paths: compilerOptions.paths } + }); + + let sourceMapFilename = nsWebpack.getSourceMapFilename( + hiddenSourceMap, + __dirname, + dist + ); + + const itemsToClean = [`${dist}/**/*`]; + if (platform === 'android') { + itemsToClean.push( + `${join( + projectRoot, + 'platforms', + 'android', + 'app', + 'src', + 'main', + 'assets', + 'snapshots' + )}` + ); + itemsToClean.push( + `${join( + projectRoot, + 'platforms', + 'android', + 'app', + 'build', + 'configurations', + 'nativescript-android-snapshot' + )}` + ); + } + + const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigName); + + nsWebpack.processAppComponents(appComponents, platform); + const config = { + mode: production ? 'production' : 'development', + context: appFullPath, + externals, + watchOptions: { + ignored: [ + appResourcesFullPath, + // Don't watch hidden files + '**/.*' + ] + }, + target: nativescriptTarget, + entry: entries, + output: { + pathinfo: false, + path: dist, + sourceMapFilename, + libraryTarget: 'commonjs2', + filename: '[name].js', + globalObject: 'global', + hashSalt + }, + resolve: { + extensions: ['.ts', '.js', '.scss', '.css'], + // Resolve {N} system modules from @nativescript/core + modules: [ + resolve(__dirname, 'node_modules/@nativescript/core'), + resolve(__dirname, 'node_modules'), + 'node_modules/@nativescript/core', + 'node_modules' + ], + alias: { + '~/package.json': resolve(projectRoot, 'package.json'), + '~': appFullPath, + "tns-core-modules": "@nativescript/core", + "nativescript-angular": "@nativescript/angular", + '@demo/shared': resolve(projectRoot, '..', '..', 'tools', 'demo') + }, + symlinks: true + }, + resolveLoader: { + symlinks: false + }, + node: { + // Disable node shims that conflict with NativeScript + http: false, + timers: false, + setImmediate: false, + fs: 'empty', + __dirname: false + }, + devtool: hiddenSourceMap + ? 'hidden-source-map' + : sourceMap + ? 'inline-source-map' + : 'none', + optimization: { + runtimeChunk: 'single', + noEmitOnErrors: noEmitOnErrorFromTSConfig, + splitChunks: { + cacheGroups: { + vendor: { + name: 'vendor', + chunks: 'all', + test: (module, chunks) => { + const moduleName = module.nameForCondition + ? module.nameForCondition() + : ''; + return ( + /[\\/]node_modules[\\/]/.test(moduleName) || + appComponents.some(comp => comp === moduleName) + ); + }, + enforce: true + } + } + }, + minimize: !!uglify, + minimizer: [ + new TerserPlugin({ + parallel: true, + cache: !ci, + sourceMap: isAnySourceMapEnabled, + terserOptions: { + output: { + comments: false, + semicolons: !isAnySourceMapEnabled + }, + compress: { + // The Android SBG has problems parsing the output + // when these options are enabled + collapse_vars: platform !== 'android', + sequences: platform !== 'android', + // custom + drop_console: true, + drop_debugger: true, + ecma: 6, + keep_infinity: platform === 'android', // for Chrome/V8 + reduce_funcs: platform !== 'android', // for Chrome/V8 + global_defs: { + __UGLIFIED__: true + } + }, + // custom + ecma: 6, + safari10: platform !== 'android' + } + }) + ] + }, + module: { + rules: [ + { + include: join(appFullPath, entryPath), + use: [ + // Require all Android app components + platform === 'android' && { + loader: '@nativescript/webpack/helpers/android-app-components-loader', + options: { modules: appComponents } + }, + + { + loader: '@nativescript/webpack/bundle-config-loader', + options: { + angular: true, + loadCss: !snapshot, // load the application css if in debug mode + unitTesting, + appFullPath, + projectRoot, + ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform) + } + } + ].filter(loader => !!loader) + }, + + { test: /\.html$|\.xml$/, use: 'raw-loader' }, + + { + test: /[\/|\\]app\.css$/, + use: [ + '@nativescript/webpack/helpers/style-hot-loader', + { + loader: "@nativescript/webpack/helpers/css2json-loader", + options: { useForImports: true } + }, + ], + }, + { + test: /[\/|\\]app\.scss$/, + use: [ + '@nativescript/webpack/helpers/style-hot-loader', + { + loader: "@nativescript/webpack/helpers/css2json-loader", + options: { useForImports: true } + }, + 'sass-loader', + ], + }, + + // Angular components reference css files and their imports using raw-loader + { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: 'raw-loader' }, + { + test: /\.scss$/, + exclude: /[\/|\\]app\.scss$/, + use: ['raw-loader', 'resolve-url-loader', 'sass-loader'] + }, + + { + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + use: [ + '@nativescript/webpack/helpers/moduleid-compat-loader', + '@nativescript/webpack/helpers/lazy-ngmodule-hot-loader', + '@ngtools/webpack' + ] + }, + + // Mark files inside `@angular/core` as using SystemJS style dynamic imports. + // Removing this will cause deprecation warnings to appear. + { + test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/, + parser: { system: true } + } + ] + }, + plugins: [ + // Define useful constants like TNS_WEBPACK + new webpack.DefinePlugin({ + 'global.TNS_WEBPACK': 'true', + 'global.isAndroid': platform === 'android', + 'global.isIOS': platform === 'ios', + process: 'global.process' + }), + // Remove all files from the out dir. + new CleanWebpackPlugin({ + cleanOnceBeforeBuildPatterns: itemsToClean, + verbose: !!verbose + }), + // Copy assets + new CopyWebpackPlugin({ + patterns: copyTargets, + }), + new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'), + // For instructions on how to set up workers with webpack + // check out https://github.com/nativescript/worker-loader + new NativeScriptWorkerPlugin(), + ngCompilerPlugin, + // Does IPC communication with the {N} CLI to notify events when running in watch mode. + new nsWebpack.WatchStateLoggerPlugin() + ] + }; + + if (report) { + // Generate report files for bundles content + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + reportFilename: resolve(projectRoot, 'report', `report.html`), + statsFilename: resolve(projectRoot, 'report', `stats.json`) + }) + ); + } + + if (snapshot) { + config.plugins.push( + new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: 'vendor', + angular: true, + requireModules: [ + 'reflect-metadata', + '@angular/platform-browser', + '@angular/core', + '@angular/common', + '@angular/router', + '@nativescript/angular' + ], + projectRoot, + webpackConfig: config, + snapshotInDocker, + skipSnapshotTools, + useLibs + }) + ); + } + + if (!production && hmr) { + config.plugins.push(new webpack.HotModuleReplacementPlugin()); + } + + return config; +}; \ No newline at end of file diff --git a/apps/demo/.gitignore b/apps/demo/.gitignore new file mode 100644 index 0000000..407ded9 --- /dev/null +++ b/apps/demo/.gitignore @@ -0,0 +1,42 @@ +# NativeScript +hooks/ +node_modules/ +platforms/ + +# NativeScript Template +*.js.map +*.js +!webpack.config.js + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# General +.DS_Store +.AppleDouble +.LSOverride +.idea +.cloud +.project +tmp/ +typings/ + +# misc +npm-debug.log + +# app +!*.d.ts +!src/assets/fontawesome.min.css +/report/ +.nsbuildinfo +/temp/ +/src/tns_modules/ + +# app uses platform specific scss which can inadvertently get renamed which will cause problems +app/app.scss + +package-lock.json diff --git a/apps/demo/nativescript.config.ts b/apps/demo/nativescript.config.ts new file mode 100644 index 0000000..411ac72 --- /dev/null +++ b/apps/demo/nativescript.config.ts @@ -0,0 +1,11 @@ +import { NativeScriptConfig } from '@nativescript/core'; + +export default { + id: 'org.nativescript.plugindemo', + appResourcesPath: '../../tools/assets/App_Resources', + android: { + v8Flags: '--expose_gc', + markingMode: 'none', + }, + appPath: 'src', +} as NativeScriptConfig; diff --git a/apps/demo/package.json b/apps/demo/package.json new file mode 100644 index 0000000..c5159d1 --- /dev/null +++ b/apps/demo/package.json @@ -0,0 +1,17 @@ +{ + "main": "app.js", + "description": "NativeScript Application", + "license": "SEE LICENSE IN ", + "repository": "", + "dependencies": { + "nativescript-theme-core": "file:../../node_modules/nativescript-theme-core", + "@nativescript/core": "file:../../node_modules/@nativescript/core", + "@nativescript/yourplugin": "file:../../packages/yourplugin" + }, + "devDependencies": { + "@nativescript/android": "~7.0.0", + "@nativescript/ios": "7.0.0", + "@nativescript/webpack": "3.0.0", + "typescript": "file:../../node_modules/typescript" + } +} diff --git a/apps/demo/references.d.ts b/apps/demo/references.d.ts new file mode 100644 index 0000000..22bac92 --- /dev/null +++ b/apps/demo/references.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/demo/src/app-root.xml b/apps/demo/src/app-root.xml new file mode 100644 index 0000000..54e70d9 --- /dev/null +++ b/apps/demo/src/app-root.xml @@ -0,0 +1,2 @@ + + diff --git a/apps/demo/src/app.css b/apps/demo/src/app.css new file mode 100644 index 0000000..50170bd --- /dev/null +++ b/apps/demo/src/app.css @@ -0,0 +1 @@ +@import '~nativescript-theme-core/css/core.light.css'; \ No newline at end of file diff --git a/apps/demo/src/app.ts b/apps/demo/src/app.ts new file mode 100644 index 0000000..a4c5c52 --- /dev/null +++ b/apps/demo/src/app.ts @@ -0,0 +1,3 @@ +import { Application } from '@nativescript/core'; + +Application.run({ moduleName: 'app-root' }); diff --git a/apps/demo/src/main-page.ts b/apps/demo/src/main-page.ts new file mode 100644 index 0000000..89e6b7a --- /dev/null +++ b/apps/demo/src/main-page.ts @@ -0,0 +1,7 @@ +import { EventData, Page } from '@nativescript/core'; +import { MainViewModel } from "./main-view-model"; + +export function navigatingTo(args: EventData) { + const page = args.object; + page.bindingContext = new MainViewModel(); +} diff --git a/apps/demo/src/main-page.xml b/apps/demo/src/main-page.xml new file mode 100644 index 0000000..b1f6cb1 --- /dev/null +++ b/apps/demo/src/main-page.xml @@ -0,0 +1,13 @@ + + + + + + + +