Compare commits

..
Author SHA1 Message Date
Marc KassayandDaniel Sogl 34ecd29d9f feat(audio-management): add plugin for audio streams (#2877)
* feat(audio-management): add plugin for audio streams

* Update index.ts
2019-01-19 09:25:51 +01:00
Ibby Hadeed 651a40f784 chore(): update changelog 2019-01-08 07:06:18 -05:00
Ibby Hadeed f420d2b830 5.0.0-beta.23 2019-01-08 07:06:12 -05:00
Ibby Hadeed e374b52c59 feat: add analytics-firebase plugin 2019-01-08 07:06:05 -05:00
Andrew CritesandDaniel Sogl 8e405cc3d3 feat(blinkid): add plugin (#2833)
* feat(blinkid): add plugin

* fix(blinkid): type name corrections
2019-01-04 22:06:25 +01:00
Daniel 7483c3554c chore(): bump deps 2018-12-07 13:41:16 +01:00
Daniel 06634dc5f4 chore(): update changelog 2018-12-01 17:07:08 +01:00
Daniel 8879ffb789 5.0.0-beta.22 2018-12-01 17:06:42 +01:00
Daniel 649dca1ef4 chore: update deps
BREAKING CHANGE: Requires Angular 7.1 and TypeScript 3.1
2018-12-01 17:04:03 +01:00
Daniel 165c3cc211 Merge branch 'master' into v5 2018-12-01 16:55:01 +01:00
Simon Bang TerkildsenandDaniel Sogl 31e4058257 fix(local-notifications): update type of the every property (#2825) 2018-12-01 16:06:27 +01:00
Luka313andDaniel Sogl b9e9aa184e feat(downloader): add plugin (#2820)
* feat(downloader): add plugin

* Update index.ts
2018-12-01 15:48:11 +01:00
mhartington 220e22b659 docs(): add ngx import path 2018-10-10 16:13:45 -05:00
Perry GovierandDaniel Sogl ac78a1540c chore(tidy up): getting rid of redundant code to make TSDoc happy (#2747) 2018-09-27 08:05:08 +02:00
Daniel bdd1755f8b chore(): update changelog 2018-09-25 20:37:32 +02:00
Daniel 3ed39c06ed 5.0.0-beta.21 2018-09-25 20:37:24 +02:00
Daniel 89a5ca7ec5 merge master into v5 2018-09-25 20:29:32 +02:00
Daniel 0422521db6 chore(package): bump deps 2018-09-25 20:12:57 +02:00
Ken SodemannandGitHub 8d57df3e64 fix(keyboard): include the mode parameter in setResizeMode() 2018-09-25 10:12:24 -05:00
Ken SodemannandDaniel Sogl fbf7463724 fix(keyboard): use cordova-plugin-ionic-keyboard (#2743)
Previous was using the deprecated keyboard plugin.

Fixes #2306
2018-09-25 16:45:43 +02:00
somqandDaniel Sogl cbeb4139d9 fix(bluetooth-le): Removed a wrong cordova decorator param (#2733)
* fix(bluetooth-le): Removed a wrong cordova decorator param (v5)

* fix(bluetooth-le): Fixed wrong return encapsulation - removed 'result' prop - for methods read and subscribe
2018-09-25 16:44:42 +02:00
Tom SeldonandDaniel Sogl 457d47cc16 fix(secure-storage): add missing "getPromise" import (#2727) 2018-09-25 16:42:31 +02:00
Daniel 358474dcfd fix(build): fix macos mojave build errors 2018-09-25 11:06:10 +02:00
Daniel d6d9b54991 chore(package): cleanup deps 2018-09-25 11:04:22 +02:00
Daniel 93ff513bd8 chore(package): bump deps 2018-09-24 19:16:55 +02:00
Daniel d3af51915e Revert "chore(pacakge): bump deps"
This reverts commit 276c88dea1.
2018-09-24 19:14:04 +02:00
Daniel 276c88dea1 chore(pacakge): bump deps 2018-09-24 19:08:57 +02:00
Daniel 653f5a2969 fix(secure-storage): import getPromise 2018-09-24 19:07:06 +02:00
Daniel e661f2ece9 fix(screenshot): import getPromise 2018-09-24 19:06:55 +02:00
Daniel 15cd285ec6 fix(printer): import getPromise 2018-09-24 19:06:40 +02:00
Daniel SoglandGitHub 95b92623a6 fix(admob-free): fix duplicated class 2018-09-24 18:59:51 +02:00
Daniel 7aa5e00453 chore(): update changelog 2018-09-18 19:23:27 +02:00
Daniel 59fd0cc50d 5.0.0-beta.20 2018-09-18 19:23:22 +02:00
Max LynchandDaniel c433317051 fix(build): Fix TypeScript bug, wrong type exported for wrap fn 2018-09-18 19:23:00 +02:00
Daniel f223ed4fa1 chore(): update changelog 2018-09-18 16:25:35 +02:00
Daniel 7160953683 5.0.0-beta.19 2018-09-18 16:25:26 +02:00
Daniel 4c55212b8d chore(pacakge): bump deps 2018-09-18 16:24:57 +02:00
Daniel 38a1dd1187 Merge branch 'master' into v5 2018-09-18 16:24:05 +02:00
Daniel 7cff234c26 chore(): update changelog 2018-09-17 18:27:54 +02:00
Daniel 039c6d40af Merge branch 'master' into v5 2018-09-17 18:23:18 +02:00
Daniel 46b1a7385c docs: add @beta tag to docs until v5 release 2018-09-17 17:24:17 +02:00
Daniel SoglandGitHub 737ad518c8 Update tslint.json 2018-09-17 16:36:18 +02:00
Daniel 89ed51cc49 refactor: follow callable-types lint rule 2018-09-17 16:18:31 +02:00
Daniel 26a8df9b7c refactor: follow no-angle-bracket-type-assertion lint rule 2018-09-17 16:14:23 +02:00
Daniel 84db491ead refactor(code-push): follow member-access lint rule 2018-09-17 16:09:15 +02:00
Daniel d5011fb105 refactor: follow space-before-function-paren lint rule 2018-09-17 16:07:44 +02:00
Daniel c9d41ebd8a refactor: follow array-type lint rule 2018-09-17 16:05:37 +02:00
Daniel 60a7190eda refactor(in-app-review): ignore no-irregular-whitespace rule 2018-09-17 15:52:39 +02:00
Daniel 261106131e fix(index-app-content): fix lint 2018-09-17 15:48:57 +02:00
Daniel 4803912350 fix(ms-adal): remove duplicate imports 2018-09-17 15:48:37 +02:00
Daniel 9feefe8454 fix(web-intent): fix lint 2018-09-17 15:43:27 +02:00
Daniel 81df665189 chore(package): bump jest and ts-node 2018-09-17 15:41:59 +02:00
Daniel f2c8edecc4 chore(package): update ionic-lint-rules 2018-09-17 15:37:05 +02:00
Daniel 6c18a8bc4f chore(package): remove more unused packages 2018-09-17 15:25:40 +02:00
Daniel ca7f872a3c chore(package): remove babelify 2018-09-17 15:22:15 +02:00
Daniel 2c04ae5985 chore(scripts): remove fs-extra-promise 2018-09-17 15:18:29 +02:00
Daniel 2e47de2ee3 chore(): update changelog 2018-09-15 11:53:31 +02:00
Daniel 384d1ea71e 5.0.0-beta.18 2018-09-15 11:53:21 +02:00
Daniel f7e76c5f83 chore(package): bump deps 2018-09-15 11:48:44 +02:00
Daniel d2d1f4889e Merge branch 'master' into v5 2018-09-15 11:46:46 +02:00
Daniel 8f8aeb6e6a 5.0.0-beta.17 2018-08-31 20:31:56 +02:00
Daniel f75243e10b chore(): update changelog 2018-08-31 19:34:07 +02:00
Daniel 0f5ae4726d 5.0.0-beta.16 2018-08-31 19:34:01 +02:00
Daniel 5462a2358c chore(package): bump deps 2018-08-31 19:30:57 +02:00
Daniel 9c75e53702 Merge branch 'master' into v5 2018-08-31 19:29:20 +02:00
Max LynchandGitHub 2213673055 Merge pull request #2679 from perrygovier/v5
fix(contacts): fixing builds
2018-08-30 14:41:13 -05:00
perry c8d25a1fc5 fix(camera): fixing builds 2018-08-30 14:16:38 -05:00
Nicolas HENRYandIbby Hadeed bd345818f8 fix(core): wrapEventObservable (#2660)
* fix wrapEventObservable

* fix lint
2018-08-26 19:38:22 -04:00
Daniel 110fb7e8e1 chore(): update changelog 2018-08-25 12:11:37 +02:00
Daniel c0d776cdd2 5.0.0-beta.15 2018-08-25 12:11:21 +02:00
Daniel 89140c1502 docs(bluetooth-le): fix jsdoc 2018-08-25 12:08:48 +02:00
Daniel 8f19719d2a chore(package): bump deps 2018-08-25 12:06:40 +02:00
Daniel 999aca1b8d Merge branch 'master' into v5 2018-08-25 12:05:57 +02:00
Paxton HareandDaniel Sogl 1ad4cc1375 fix(contacts): remove double import of checkAvailability (#2659) 2018-08-25 11:59:19 +02:00
Ibby Hadeed 38b6501612 chore(): handle identifiers in v5 build process
Closes #2652
2018-08-23 10:15:28 -04:00
Paxton HareandIbby Hadeed fe87b68ccc chore(): fix CordovaInstanceProperty decorator (#2655)
This manifests in many plugins just not quite working right.
2018-08-23 09:40:00 -04:00
Paxton HareandIbby Hadeed 9e923fa8da chore(): fix path related issues with v5 build (#2654) 2018-08-23 09:37:10 -04:00
Daniel 5e9c92a773 fix(extended-device-information): fix wrong decorator 2018-08-21 21:12:43 +02:00
Daniel 5ac940d2bf chore(package): bump deps 2018-08-21 20:51:02 +02:00
Daniel e47a3e1522 fix(clevertap): fix jsdoc 2018-08-16 22:46:34 +02:00
Daniel 1a1c665b18 chore(package): bump deps 2018-08-16 22:46:19 +02:00
Daniel f2728f26fe merge master into v5 2018-08-16 22:43:50 +02:00
Daniel SoglandGitHub 2f560d619a docs(contacts): mark as deprecated 2018-07-27 21:39:22 +02:00
Daniel 342b9dace5 chore(): update changelog 2018-07-18 22:21:56 +02:00
Daniel 07557e95ec chore(): update changelog 2018-07-18 22:20:12 +02:00
Daniel b7be1bf9dd 5.0.0-beta.14 2018-07-18 22:19:46 +02:00
Daniel b01c2ee1fb docs(build): fix lint 2018-07-18 22:17:37 +02:00
Daniel bea5eaea1a Merge branch 'master' into v5 2018-07-18 22:12:44 +02:00
Daniel 97b80b533b chore(package): bump deps 2018-07-18 21:46:58 +02:00
Daniel 6ea43ef5e4 refactor(scripts): fix typo 2018-07-01 13:12:27 +02:00
Daniel f9c49dcd3f chore(package): bump deps 2018-07-01 12:55:00 +02:00
Daniel SoglandGitHub db70bbd765 Update CHANGELOG.md 2018-06-28 14:37:43 +02:00
Daniel 81287c9edf chore(): update changelog 2018-06-28 14:37:02 +02:00
Daniel 6398dcf479 set version 2018-06-28 14:22:47 +02:00
Daniel 0a758f85e6 Merge branch 'master' into v5 2018-06-28 14:20:20 +02:00
Daniel 23e0977954 Merge remote-tracking branch 'origin/master' into v5 2018-06-28 13:37:10 +02:00
Daniel 95c8566d76 chore(package): bump deps 2018-06-28 13:25:37 +02:00
Perry GovierandMike Hartington 7d5e7aaa7d fix(appodeal): removed bad imports 2018-06-25 15:57:26 -04:00
Nicolas HENRYandDaniel Sogl 406ad12232 fix(file-tramsfer): fix v5 imports for file-transfer plugin (#2537) 2018-06-23 17:20:00 +02:00
Daniel aff44e9fde chore(): update changelog 2018-06-23 13:28:13 +02:00
Daniel ed515f7017 chore(package): bump deps 2018-06-22 18:24:09 +02:00
Daniel f3ef2a877d Merge branch 'master' into v5 2018-06-22 18:13:47 +02:00
mhartington f7afd1f066 bump 2018-06-14 19:15:34 -04:00
mhartington 74a65b039f bump() 2018-06-14 15:29:05 -04:00
Max LynchandGitHub 37f16ba5da Merge pull request #2549 from ionic-team/ionic-webview
feat(ionic-webview): plugin for cordova-plugin-ionic-webview 2.0
2018-06-12 16:59:00 -05:00
Daniel Imhoff 8beb1774b8 feat(ionic-webview): plugin for cordova-plugin-ionic-webview 2.0 2018-06-12 16:53:35 -05:00
Nicolas HENRYandIbby Hadeed 6662234894 fix(v5-builder): stop transforming "declare" classes (#2503) 2018-05-10 00:44:53 -04:00
mhartington db32d2d520 chore(): bump 2018-05-09 12:55:19 -04:00
Daniel aa90626116 chore(package): bump webpack 2018-05-05 10:33:19 +02:00
Daniel 5516165fb6 chore(lint): add rxjs 6 lint rules 2018-05-05 10:29:51 +02:00
Daniel SoglandGitHub 48714d72d6 fix(str-prnt): rxjs 6 import 2018-05-05 10:26:23 +02:00
Daniel e0b0687004 fix(): fix rxjs 6 imports 2018-05-04 10:38:35 +02:00
Daniel 885d09d0ab chore(package): Angular 6 stable 2018-05-04 10:32:58 +02:00
Daniel 0b3d299a96 fix(): fix more lint errors 2018-05-04 10:31:06 +02:00
Daniel f34b6e6664 fix(): fix tealium jsdoc 2018-05-04 10:28:43 +02:00
Daniel 3fbd475ed2 Merge remote-tracking branch 'origin/master' into v5 2018-05-04 10:22:32 +02:00
Daniel 3b43bd76fd chore(package): bump deps 2018-04-25 10:14:13 +02:00
Perry GovierandDaniel Sogl d3c2859d38 fix(linting): Fixing misc linting errors that typedoc complains about (#2476)
* fix(linting): Fixing misc linting errors that typedoc complains about

* angularJS safe promises

* fix(clibpoard): minor linting error
2018-04-24 22:12:21 +02:00
Daniel fbaacfb572 refactor(iab): fix rxjs 6 import 2018-04-21 15:49:43 +02:00
Daniel f348f95e56 WIP 2018-04-21 15:34:12 +02:00
Daniel f13b31f074 chore(build): fix windows errors and bump deps 2018-04-21 10:34:54 +02:00
Nicolas HENRYandIbby Hadeed 88fda657f4 chore(build): fix v5 imports (#2465) 2018-04-19 13:52:26 -04:00
Daniel SoglandGitHub 0dfbb386ff docs(iab): fix jsdoc 2018-04-16 21:32:03 +02:00
Daniel 213d77ffda Merge branch 'master' into v5 2018-04-15 12:15:08 +02:00
Daniel d55fd2a109 chore(package): bump deps 2018-04-13 16:05:31 +02:00
Daniel b36a1f9df6 fix(): fix lint 2018-04-13 12:41:45 +02:00
Daniel fa08b99bbc chore(package): bump deps 2018-04-13 12:39:08 +02:00
Daniel f414e0e081 Merge remote-tracking branch 'origin/master' into v5 2018-04-13 12:34:16 +02:00
Daniel 86b637e85a refactor(core): remove lodash
closes: #2452
2018-04-13 12:33:45 +02:00
Ibby Hadeed 3b440c6df8 Must return promise to asyncify! 2018-04-11 12:59:41 -04:00
Ibby Hadeed ad1848899d chore(): update changelog 2018-04-11 12:51:38 -04:00
Ibby Hadeed 242cd4b124 5.0.0-beta.9 2018-04-11 12:51:32 -04:00
Ibby Hadeed abee240df5 Add cordova typings to dependencies 2018-04-11 12:51:18 -04:00
Ibby Hadeed 6d8b406471 Fix logging 2018-04-11 12:47:13 -04:00
Ibby Hadeed 29646d8da0 update changelog 2018-04-11 12:34:47 -04:00
Ibby Hadeed 9f70bf5727 5.0.0-beta.8 2018-04-11 12:34:31 -04:00
Ibby Hadeed f21b63be47 Merge branch 'v5' of github.com:ionic-team/ionic-native into v5 2018-04-11 12:34:20 -04:00
Ibby Hadeed 7a1ff64bf2 Do not set rxjs version for now 2018-04-11 12:34:02 -04:00
Ibby Hadeed c13a53ad45 Set explicit types 2018-04-11 12:32:16 -04:00
Ibby Hadeed 9e3f1cc0c6 fix publish command 2018-04-09 16:03:09 -04:00
Ibby Hadeed 4ce15c6cd7 5.0.0-beta.7 2018-04-09 16:01:47 -04:00
Daniel c63895db19 refactor(scripts): use rxjs 6 syntax for plugin templates 2018-04-09 21:59:34 +02:00
Daniel 3aea3900bc chore(package): bump deps 2018-04-09 21:53:54 +02:00
Ibby Hadeed d96c230b2e Update deps 2018-04-09 15:18:38 -04:00
Ibby Hadeed bb6342b72a Fix NGC build with Angular 6 2018-04-09 15:18:30 -04:00
Ibby Hadeed d56826f12d Fix decorators + remove duplicate implementations 2018-04-09 14:49:08 -04:00
Ibby Hadeed b09eb06cb0 Update code style 2018-04-09 14:32:20 -04:00
Ibby Hadeed fd87e968f0 Restore interfaces.ts file 2018-04-09 14:31:22 -04:00
Daniel e12c90f890 chore(package): bump deps 2018-04-09 20:14:01 +02:00
Daniel f70eaea71e fix(): build errors 2018-04-09 20:10:36 +02:00
Daniel 29d668ca2f Merge branch 'master' into v5 2018-04-09 20:06:25 +02:00
Daniel c0737feb41 Merge branch 'master' into v5 2018-04-08 18:51:08 +02:00
Daniel c4e8c2efbc Merge branch 'master' into v5 2018-04-08 18:29:41 +02:00
Daniel 83680aad96 Merge branch 'master' into v5 2018-04-06 23:06:59 +02:00
Daniel cc9a980dc3 fix(build): fix ngx build errors 2018-04-06 09:43:57 +02:00
Daniel 3750cad793 chore(pacakge): fix deps 2018-04-06 09:33:10 +02:00
Daniel 4aca04a62e Merge remote-tracking branch 'origin/master' into v5 2018-04-05 22:05:19 +02:00
Daniel 3ced31ed2a fix(plugins): fix rxjs 6 build errors
#2439
2018-04-05 21:44:19 +02:00
Daniel 48b0f16ed9 fix(core): fix rxjs 6 build errors
#2439
2018-04-05 21:34:04 +02:00
Daniel 97a73ca369 chore(package): bump deps 2018-04-05 16:34:33 +02:00
Daniel bf0eaf75b9 Merge branch 'master' into v5 2018-04-05 16:31:11 +02:00
Daniel 0b08ce4395 Merge remote-tracking branch 'origin/master' into v5 2018-04-04 11:02:38 +02:00
Daniel 70f01fe528 Merge branch 'master' into v5 2018-03-24 21:14:09 +01:00
Daniel SoglandGitHub b5e04cca20 refactor(device-feedback): rename interface 2018-03-23 15:38:45 +01:00
Daniel c15b78bab2 refactor(build): lint build scripts 2018-03-23 10:57:54 +01:00
Daniel d7829e4012 refactor(): applied new lint rules 2018-03-23 10:42:10 +01:00
Daniel 28e95ea66e chore(package): bump deps 2018-03-23 10:41:27 +01:00
Daniel 9711061889 chore(package): bump deps 2018-03-23 10:07:47 +01:00
Daniel a7c1dea6a1 BREAKING CHANGE: remove google-maps plugin 2018-03-23 10:05:08 +01:00
Daniel 12235cef2e chore(package): set correct version 2018-03-23 10:03:50 +01:00
Daniel 3a84aeec21 Merge remote-tracking branch 'origin/master' into v5 2018-03-23 10:01:37 +01:00
Daniel acfaeac64b chhore(package): bump ts-node 2018-03-19 13:42:06 +01:00
Daniel d35e790b1e chore(package): bump deps 2018-03-19 13:33:14 +01:00
Daniel 1e401682f6 Merge remote-tracking branch 'origin/v5' into v5 2018-03-19 13:14:19 +01:00
Daniel 1d7ee313a0 chore(package): bump webpack 2018-03-19 13:14:10 +01:00
Daniel a1c4d48f54 chore(pacakge): bump webpack 2018-03-19 13:13:55 +01:00
Daniel 9e2e902b18 chore(package): bump lodash 2018-03-19 13:09:19 +01:00
Daniel c99340d504 chore(package): bump fs-extra and fix angular versions 2018-03-19 13:07:12 +01:00
Daniel 9f19e2ba07 chore(package): bump jest 2018-03-19 13:03:38 +01:00
Daniel b9d9f0bd54 fix sqlite property 2018-03-19 12:59:55 +01:00
Daniel a6d5d51489 Merge remote-tracking branch 'origin/master' into v5 2018-03-19 08:44:12 +01:00
Daniel 1c95039c02 Merge remote-tracking branch 'origin/master' into v5 2018-03-17 01:29:14 +01:00
Daniel 92aff84e54 Merge remote-tracking branch 'upstream/master' into v5 2018-03-16 17:30:10 +01:00
Ibby Hadeed 821d8222fa Merge w/ master 2018-01-25 12:31:38 -05:00
Ibby Hadeed 85d685b38f Fix logging in publish task 2017-12-29 10:56:20 -05:00
Ibby Hadeed 13308403cb 5.0.0-beta.4 2017-12-29 10:54:16 -05:00
Ibby Hadeed b60df6cf7e Update readme 2017-12-29 10:47:34 -05:00
Ibby Hadeed dcf5102c57 Update readme 2017-12-29 10:40:46 -05:00
Ibby Hadeed 0cc1a2b2ff Use AngularJS promise if available 2017-12-29 10:15:44 -05:00
Ibby Hadeed fc9dcc8e64 Merge remote-tracking branch 'origin' into v5.0-new2 2017-12-28 23:43:49 -05:00
Ibby Hadeed 228c0bb9f3 Update winstonjs 2017-12-28 23:43:29 -05:00
Ibby Hadeed 1c35991548 Use winston 2017-12-28 23:15:34 -05:00
Ibby Hadeed a26457b30a 5.0.0-beta.3 2017-12-28 22:13:34 -05:00
Ibby Hadeed 542e7d24f0 Extend IonicNativePlugin 2017-12-28 22:12:48 -05:00
Ibby Hadeed 2f5f34c2c5 5.0.0-beta.2 2017-12-28 08:58:04 -05:00
Ibby Hadeed 2a3f015f07 Update publish function 2017-12-28 08:57:50 -05:00
Ibby Hadeed 11a1cc2ff5 Fix InstanceCheck/CordovaCheck transformers 2017-12-28 08:54:28 -05:00
Ibby Hadeed 6416395727 Add ignore list for decorators 2017-12-28 08:40:52 -05:00
Ibby Hadeed 75675ea19f Update paths 2017-12-28 07:40:57 -05:00
Ibby Hadeed c22ac6d681 Merge master in 2017-12-28 07:31:14 -05:00
Ibby Hadeed 0f9c21ab42 Merge in v5 code 2017-12-28 07:28:44 -05:00
308 changed files with 20279 additions and 11258 deletions
+14 -14
View File
@@ -1,15 +1,15 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
+3
View File
@@ -5,4 +5,7 @@ node_modules/
aot/
scripts/ionic-native-bower
dist/
src/@ionic-native/plugins/**/ngx
*.d.ts
injectable-classes.json
+101 -181
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -194,7 +194,7 @@ Checks if the plugin and property exist before getting/setting the property's va
Example:
```ts
@CordovaProperty
@CordovaProperty()
someProperty: string;
```
+23 -23
View File
@@ -1,23 +1,23 @@
Copyright 2015-present Drifty Co.
http://drifty.com/
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.
Copyright 2015-present Drifty Co.
http://drifty.com/
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.
+71 -12
View File
@@ -11,22 +11,26 @@ Ionic Native wraps plugin callbacks in a Promise or Observable, providing a comm
Run following command to install Ionic Native in your project.
```bash
npm install @ionic-native/core
npm install @ionic-native/core@beta --save
```
You also need to install the Ionic Native package for each plugin you want to add. Please see the [Ionic Native documentation](https://ionicframework.com/docs/native/) for complete instructions on how to add and use the plugins.
**NOTE: to use Ionic Native v5, you must use the `@beta` tag when installing any NPM package.**
## Documentation
For the full Ionic Native documentation, please visit [https://ionicframework.com/docs/native/](https://ionicframework.com/docs/native/).
### Basic Usage
To use a plugin, import and add the plugin provider to your `@NgModule`, and then inject it where you wish to use it.
#### Ionic/Angular apps
To use a plugin, import and add the plugin provider to your `@NgModule`, and then inject it where you wish to use it.
Make sure to import the injectable class from the `/ngx` directory as shown in the following examples:
```typescript
// app.module.ts
import { Camera } from '@ionic-native/camera';
import { Camera } from '@ionic-native/camera/ngx';
...
@@ -44,7 +48,7 @@ export class AppModule { }
```
```typescript
import { Geolocation } from '@ionic-native/geolocation';
import { Geolocation } from '@ionic-native/geolocation/ngx';
import { Platform } from 'ionic-angular';
@Component({ ... })
@@ -74,16 +78,71 @@ export class MyComponent {
}
```
### Mocking and Browser Development
#### ES2015+/TypeScript
These modules can work in any ES2015+/TypeScript app (including Angular/Ionic apps). To use any plugin, import the class from the appropriate package, and use it's static methods.
```js
import { Camera } from '@ionic-native/camera';
Ionic Native 3.x makes it possible to mock plugins and develop nearly the entirety of your app in the browser or in `ionic serve`.
document.addEventListener('deviceready', () => {
Camera.getPicture()
.then((data) => console.log('Took a picture!', data))
.catch((e) => console.log('Error occurred while taking a picture', e));
});
```
#### AngularJS
Ionic Native generates an AngularJS module in runtime and prepares a service for each plugin. To use the plugins in your AngularJS app:
1. Download the latest bundle from the [Github releases](https://github.com/ionic-team/ionic-native/releases) page.
2. Include it in `index.html` before your app's code.
3. Inject `ionic.native` module in your app.
4. Inject any plugin you would like to use with a `$cordova` prefix.
```js
angular.module('myApp', ['ionic.native'])
.controller('MyPageController', function($cordovaCamera) {
$cordovaCamera.getPicture()
.then(
function(data) {
console.log('Took a picture!', data);
},
function(err) {
console.log('Error occurred while taking a picture', err);
}
);
});
```
#### Vanilla JS
To use Ionic Native in any other setup:
1. Download the latest bundle from the [Github releases](https://github.com/ionic-team/ionic-native/releases) page.
2. Include it in `index.html` before your app's code.
3. Access any plugin using the global `IonicNative` variable.
```js
document.addEventListener('deviceready', function() {
IonicNative.Camera.getPicture()
.then(
function(data) {
console.log('Took a picture!', data);
},
function(err) {
console.log('Error occurred while taking a picture', err);
}
);
});
```
### Mocking and Browser Development (Ionic/Angular apps only)
Ionic Native makes it possible to mock plugins and develop nearly the entirety of your app in the browser or in `ionic serve`.
To do this, you need to provide a mock implementation of the plugins you wish to use. Here's an example of mocking the `Camera` plugin to return a stock image while in development:
First import the `Camera` class in your `src/app/app.module.ts` file:
```typescript
import { Camera } from '@ionic-native/camera';
import { Camera } from '@ionic-native/camera/ngx';
```
Then create a new class that extends the `Camera` class with a mock implementation:
@@ -109,8 +168,11 @@ Here's the full example:
```typescript
import { ErrorHandler, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Camera } from '@ionic-native/camera';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { Camera } from '@ionic-native/camera/ngx';
import { HomePage } from '../pages/home/home';
import { MyApp } from './app.component';
@@ -146,9 +208,6 @@ Spent way too long diagnosing an issue only to realize a plugin wasn't firing or
Let us know or submit a PR! Take a look at [the Developer Guide](https://github.com/ionic-team/ionic-native/blob/master/DEVELOPER.md) for more on how to contribute. :heart:
## Ionic v1 (AngularJS, Angular 1.x) support
For Ionic v1 (AngularJS, Angular 1.x) support, please use version 2 of Ionic Native. See the [2.x README](https://github.com/ionic-team/ionic-native/blob/v2.x/README.md) for usage information.
# Credits
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
- run: bash ./scripts/git/config.sh
- run:
name: Build Ionic Native
command: npm run build:core && ./node_modules/.bin/tsc
command: npm run build
- run:
name: Generate README files to ensure docs are valid
command: npm run readmes
-40
View File
@@ -1,40 +0,0 @@
'use strict';
module.exports = config => {
const conf = {
frameworks: ['jasmine', 'karma-typescript'],
plugins: ['karma-typescript', 'karma-jasmine', 'karma-phantomjs-launcher'],
preprocessors: {
'src/**/*.ts': ['karma-typescript']
},
karmaTypescriptConfig: {
bundlerOptions: {
entrypoints: /\.spec\.ts$/,
transforms: [require('karma-typescript-es6-transform')()]
},
compilerOptions: {
lib: ['es2015', 'dom'],
paths: {
'@ionic-native/core': ['./src/@ionic-native/core']
},
baseUrl: '.'
}
},
files: [{ pattern: 'src/**/*.ts', included: true, watched: true }],
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: false
};
config.set(conf);
};
+8667 -6756
View File
File diff suppressed because it is too large Load Diff
+58 -43
View File
@@ -1,63 +1,78 @@
{
"name": "ionic-native",
"version": "4.12.2",
"version": "5.0.0-beta.23",
"description": "Native plugin wrappers for Cordova and Ionic with TypeScript, ES6+, Promise and Observable support",
"homepage": "https://ionicframework.com/",
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
"license": "MIT",
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"build:core": "tsc -p tsconfig.core.json",
"build:esm": "ts-node -P scripts/tsconfig.json scripts/tasks/build-esm",
"build:es5": "ts-node -P scripts/tsconfig.json scripts/tasks/build-es5",
"build:ngx": "ts-node -P scripts/tsconfig.json scripts/tasks/build-ngx",
"build": "npm run build:core && npm run build:esm && npm run build:ngx && npm run build:es5",
"prebuild": "rimraf -rf dist",
"npmpub": "ts-node -P scripts/tsconfig.json scripts/tasks/publish",
"lint": "gulp lint",
"readmes": "gulp readmes",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"postchangelog": "git commit -am \"chore(): update changelog\"",
"shipit": "npm run build && npm run readmes && npm run npmpub"
},
"devDependencies": {
"@angular/compiler": "^5.2.11",
"@angular/compiler-cli": "^5.2.11",
"@angular/core": "^5.2.11",
"@angular/common": "^7.1.2",
"@angular/compiler": "^7.1.2",
"@angular/compiler-cli": "^7.1.2",
"@angular/core": "^7.1.2",
"@types/cordova": "0.0.34",
"@types/jasmine": "^2.8.8",
"@types/node": "8.10.20",
"canonical-path": "0.0.2",
"child-process-promise": "2.2.1",
"conventional-changelog-cli": "^2.0.5",
"@types/fs-extra": "^5.0.4",
"@types/jest": "^23.3.10",
"@types/lodash": "^4.14.118",
"@types/node": "^10.12.12",
"@types/rimraf": "^2.0.2",
"@types/webpack": "^4.4.20",
"ajv": "^6.6.1",
"async-promise-queue": "^1.0.4",
"conventional-changelog-cli": "^2.0.11",
"cz-conventional-changelog": "^2.1.0",
"dgeni": "0.4.7",
"dgeni": "^0.4.10",
"dgeni-packages": "0.16.10",
"fs-extra": "2.0.0",
"fs-extra-promise": "0.4.1",
"fs-extra": "^7.0.1",
"gulp": "3.9.1",
"gulp-rename": "^1.4.0",
"gulp-replace": "^1.0.0",
"gulp-tslint": "6.1.2",
"jasmine-core": "^3.2.1",
"karma": "^2.0.5",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.1.2",
"karma-phantomjs-launcher": "^1.0.4",
"karma-typescript": "^3.0.13",
"karma-typescript-es6-transform": "^1.0.4",
"lodash": "^4.17.10",
"gulp-tslint": "^8.1.3",
"jest": "^23.6.0",
"lodash": "^4.17.11",
"minimist": "1.2.0",
"node-html-encoder": "0.0.2",
"q": "^1.5.1",
"queue": "^4.5.0",
"natives": "^1.1.6",
"rimraf": "^2.6.2",
"rxjs": "^5.5.12",
"semver": "^5.5.1",
"tslint": "3.15.1",
"tslint-ionic-rules": "0.0.8",
"typescript": "~2.4.2",
"rxjs": "^6.3.3",
"ts-jest": "^23.10.5",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"tslint-ionic-rules": "0.0.21",
"typescript": "3.1.6",
"uglifyjs-webpack-plugin": "^2.0.1",
"unminified-webpack-plugin": "^2.0.0",
"webpack": "^4.27.1",
"winston": "^3.1.0",
"zone.js": "^0.8.26"
},
"scripts": {
"start": "npm run test:watch",
"lint": "gulp lint",
"build": "npm run clean && npm run lint && npm run build:core && npm run build:modules",
"build:core": "ngc -p scripts/build/tsconfig-core.json",
"build:modules": "node scripts/build/build.js",
"clean": "rimraf dist .tmp",
"shipit": "npm run build && gulp readmes && npm run npmpub",
"npmpub": "node scripts/build/publish.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"postchangelog": "git commit -am \"chore(): update changelog\"",
"test": "karma start karma.conf.js --single-run",
"test:watch": "karma start karma.conf.js",
"readmes": "gulp readmes"
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(js?|ts?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json"
]
},
"repository": {
"type": "git",
-154
View File
@@ -1,154 +0,0 @@
'use strict';
// Node module dependencies
const fs = require('fs-extra-promise').useFs(require('fs-extra')),
queue = require('queue'),
path = require('path'),
exec = require('child_process').exec;
// Constants for the build process. Paths and JSON files templates
const ROOT = path.resolve(path.join(__dirname, '../../')), // root ionic-native directory
PLUGINS_PATH = path.resolve(ROOT, 'src/@ionic-native/plugins'), // path to plugins source files
CORE_PACKAGE_JSON = require(path.resolve(__dirname, 'core-package.json')), // core package.json
PLUGIN_PACKAGE_JSON = require(path.resolve(__dirname, 'plugin-package.json')), // plugin package.json template
PLUGIN_TS_CONFIG = require(path.resolve(__dirname, 'tsconfig-plugin.json')), // plugin tsconfig template
BUILD_TMP = path.resolve(ROOT, '.tmp'), // tmp directory path
BUILD_DIST_ROOT = path.resolve(ROOT, 'dist/@ionic-native'), // dist directory root path
BUILD_CORE_DIST = path.resolve(BUILD_DIST_ROOT, 'core'); // core dist directory path
// dependency versions
const ANGULAR_VERSION = '*',
RXJS_VERSION = '^5.5.11',
MIN_CORE_VERSION = '^4.11.0',
IONIC_NATIVE_VERSION = require(path.resolve(ROOT, 'package.json')).version;
// package dependencies
const CORE_PEER_DEPS = {
rxjs: RXJS_VERSION
};
const PLUGIN_PEER_DEPS = {
'@ionic-native/core': MIN_CORE_VERSION,
'@angular/core': ANGULAR_VERSION,
rxjs: RXJS_VERSION
};
// set peer dependencies for all plugins
PLUGIN_PACKAGE_JSON.peerDependencies = PLUGIN_PEER_DEPS;
// Create tmp/dist directories
console.log('Making new TMP directory');
fs.mkdirpSync(BUILD_TMP);
// Prepare and copy the core module's package.json
console.log('Preparing core module package.json');
CORE_PACKAGE_JSON.version = IONIC_NATIVE_VERSION;
CORE_PACKAGE_JSON.peerDependencies = CORE_PEER_DEPS;
fs.writeJsonSync(
path.resolve(BUILD_CORE_DIST, 'package.json'),
CORE_PACKAGE_JSON
);
// Fetch a list of the plugins
const PLUGINS = fs.readdirSync(PLUGINS_PATH);
// Build specific list of plugins to build from arguments, if any
let pluginsToBuild = process.argv.slice(2);
let ignoreErrors = false;
let errors = [];
const index = pluginsToBuild.indexOf('ignore-errors');
if (index > -1) {
ignoreErrors = true;
pluginsToBuild.splice(index, 1);
console.log(
'Build will continue even if errors were thrown. Errors will be printed when build finishes.'
);
}
if (!pluginsToBuild.length) {
pluginsToBuild = PLUGINS;
}
// Create a queue to process tasks
const QUEUE = queue({
concurrency: require('os').cpus().length
});
// Function to process a single plugin
const addPluginToQueue = pluginName => {
QUEUE.push(callback => {
console.log(`Building plugin: ${pluginName}`);
const PLUGIN_BUILD_DIR = path.resolve(BUILD_TMP, 'plugins', pluginName),
PLUGIN_SRC_PATH = path.resolve(PLUGINS_PATH, pluginName, 'index.ts');
let tsConfigPath;
fs.mkdirpAsync(PLUGIN_BUILD_DIR) // create tmp build dir
.then(() => fs.mkdirpAsync(path.resolve(BUILD_DIST_ROOT, pluginName))) // create dist dir
.then(() => {
// Write tsconfig.json
const tsConfig = JSON.parse(JSON.stringify(PLUGIN_TS_CONFIG));
tsConfig.files = [PLUGIN_SRC_PATH];
// tsConfig.compilerOptions.paths['@ionic-native/core'] = [BUILD_CORE_DIST];
tsConfigPath = path.resolve(PLUGIN_BUILD_DIR, 'tsconfig.json');
return fs.writeJsonAsync(tsConfigPath, tsConfig);
})
.then(() => {
// clone package.json
const packageJson = JSON.parse(JSON.stringify(PLUGIN_PACKAGE_JSON));
packageJson.name = `@ionic-native/${pluginName}`;
packageJson.version = IONIC_NATIVE_VERSION;
return fs.writeJsonAsync(
path.resolve(BUILD_DIST_ROOT, pluginName, 'package.json'),
packageJson
);
})
.then(() => {
// compile the plugin
exec(
`${ROOT}/node_modules/.bin/ngc -p ${tsConfigPath}`,
(err, stdout, stderr) => {
if (err) {
if (!ignoreErrors) {
// oops! something went wrong.
console.log(err);
callback(`\n\nBuilding ${pluginName} failed.`);
return;
} else {
errors.push(err);
}
}
// we're done with this plugin!
callback();
}
);
})
.catch(callback);
}); // QUEUE.push end
};
pluginsToBuild.forEach(addPluginToQueue);
QUEUE.start(err => {
if (err) {
console.log('Error building plugins.');
console.log(err);
process.stderr.write(err);
process.exit(1);
} else if (errors.length) {
errors.forEach(e => {
console.log(e.message) && console.log('\n');
process.stderr.write(err);
});
console.log('Build complete with errors');
process.exit(1);
} else {
console.log('Done processing plugins!');
}
});
-14
View File
@@ -1,14 +0,0 @@
{
"name": "@ionic-native/core",
"version": "{{VERSION}}",
"description": "Ionic Native - Native plugins for ionic apps",
"module": "index.js",
"typings": "index.d.ts",
"author": "ionic",
"license": "MIT",
"peerDependencies": {},
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic-native.git"
}
}
+126
View File
@@ -0,0 +1,126 @@
import * as ts from 'typescript';
import * as fs from 'fs-extra';
import * as path from 'path';
import { camelCase, clone } from 'lodash';
import { Logger } from '../logger';
export const ROOT = path.resolve(__dirname, '../../');
// tslint:disable-next-line:no-var-requires
export const TS_CONFIG = clone(require(path.resolve(ROOT, 'tsconfig.json')));
export const COMPILER_OPTIONS = TS_CONFIG.compilerOptions;
export const PLUGINS_ROOT = path.join(ROOT, 'src/@ionic-native/plugins/');
export const PLUGIN_PATHS = fs.readdirSync(PLUGINS_ROOT).map(d => path.join(PLUGINS_ROOT, d, 'index.ts'));
export function getDecorator(node: ts.Node, index = 0): ts.Decorator {
if (node.decorators && node.decorators[index]) {
return node.decorators[index];
}
}
export function hasDecorator(decoratorName: string, node: ts.Node): boolean {
return node.decorators && node.decorators.length && node.decorators.findIndex(d => getDecoratorName(d) === decoratorName) > -1;
}
export function getDecoratorName(decorator: any) {
return decorator.expression.expression.text;
}
export function getRawDecoratorArgs(decorator: any): any[] {
if (decorator.expression.arguments.length === 0) return [];
return decorator.expression.arguments[0].properties;
}
export function getDecoratorArgs(decorator: any) {
const properties: any[] = getRawDecoratorArgs(decorator);
const args = {};
properties.forEach(prop => {
let val;
switch (prop.initializer.kind) {
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.Identifier:
val = prop.initializer.text;
break;
case ts.SyntaxKind.ArrayLiteralExpression:
val = prop.initializer.elements.map((e: any) => e.text);
break;
case ts.SyntaxKind.TrueKeyword:
val = true;
break;
case ts.SyntaxKind.FalseKeyword:
val = false;
break;
case ts.SyntaxKind.NumericLiteral:
val = Number(prop.initializer.text);
break;
default:
Logger.debug('Unexpected property value type: ' + prop.initializer.kind);
throw new Error('Unexpected property value type << helpers.ts >>');
}
args[prop.name.text] = val;
});
return args;
}
/**
* FROM STENCIL
* Convert a js value into typescript AST
* @param val array, object, string, boolean, or number
* @returns Typescript Object Literal, Array Literal, String Literal, Boolean Literal, Numeric Literal
*/
export function convertValueToLiteral(val: any) {
if (Array.isArray(val)) {
return arrayToArrayLiteral(val);
}
if (typeof val === 'object') {
return objectToObjectLiteral(val);
}
if (typeof val === 'number') {
return ts.createNumericLiteral(String(val));
}
return ts.createLiteral(val);
}
/**
* FROM STENCIL
* Convert a js object into typescript AST
* @param obj key value object
* @returns Typescript Object Literal Expression
*/
function objectToObjectLiteral(obj: { [key: string]: any }): ts.ObjectLiteralExpression {
const newProperties: ts.ObjectLiteralElementLike[] = Object.keys(obj).map((key: string): ts.ObjectLiteralElementLike => {
return ts.createPropertyAssignment(ts.createLiteral(key), convertValueToLiteral(obj[key]) as ts.Expression);
});
return ts.createObjectLiteral(newProperties);
}
/**
* FROM STENCIL
* Convert a js array into typescript AST
* @param list array
* @returns Typescript Array Literal Expression
*/
function arrayToArrayLiteral(list: any[]): ts.ArrayLiteralExpression {
const newList: any[] = list.map(convertValueToLiteral);
return ts.createArrayLiteral(newList);
}
export function getMethodsForDecorator(decoratorName: string) {
switch (decoratorName) {
case 'CordovaProperty': return ['cordovaPropertyGet', 'cordovaPropertySet'];
case 'InstanceProperty': return ['instancePropertyGet', 'instancePropertySet'];
case 'CordovaCheck': return ['checkAvailability'];
case 'InstanceCheck': return ['instanceAvailability'];
}
return [camelCase(decoratorName)];
}
+105
View File
@@ -0,0 +1,105 @@
import * as ts from 'typescript';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as ngc from '@angular/compiler-cli';
import * as rimraf from 'rimraf';
import { generateDeclarations } from './transpile';
import { clone } from 'lodash';
import { EmitFlags } from '@angular/compiler-cli';
import { importsTransformer } from './transformers/imports';
import { pluginClassTransformer } from './transformers/plugin-class';
import { COMPILER_OPTIONS, PLUGIN_PATHS, ROOT } from './helpers';
export function getProgram(rootNames: string[] = createSourceFiles()) {
const options: ngc.CompilerOptions = clone(COMPILER_OPTIONS);
options.basePath = ROOT;
options.moduleResolution = ts.ModuleResolutionKind.NodeJs;
options.module = ts.ModuleKind.ES2015;
options.target = ts.ScriptTarget.ES5;
options.lib = ['dom', 'es2017'];
options.inlineSourceMap = true;
options.inlineSources = true;
delete options.baseUrl;
const host: ngc.CompilerHost = ngc.createCompilerHost({ options });
return ngc.createProgram({
rootNames,
options,
host
});
}
// hacky way to export metadata only for core package
export function transpileNgxCore() {
getProgram([path.resolve(ROOT, 'src/@ionic-native/core/index.ts')]).emit({
emitFlags: EmitFlags.Metadata,
emitCallback: ({ program, writeFile, customTransformers, cancellationToken, targetSourceFile }) =>
program.emit(targetSourceFile, writeFile, cancellationToken, true, customTransformers)
});
}
export function transpileNgx() {
getProgram().emit({
emitFlags: EmitFlags.Metadata,
customTransformers: {
beforeTs: [
importsTransformer(true),
pluginClassTransformer(true)
]
}
});
}
export function generateDeclarationFiles() {
generateDeclarations(PLUGIN_PATHS.map(p => p.replace('index.ts', 'ngx/index.ts')));
}
// remove reference to @ionic-native/core decorators
export function modifyMetadata() {
PLUGIN_PATHS.map(p => p.replace(path.join(ROOT, 'src'), path.join(ROOT, 'dist')).replace('index.ts', 'ngx/index.metadata.json'))
.forEach(p => {
const content = fs.readJSONSync(p);
let _prop;
for (const prop in content[0].metadata) {
_prop = content[0].metadata[prop];
removeIonicNativeDecorators(_prop);
if (_prop.members) {
for (const memberProp in _prop.members) {
removeIonicNativeDecorators(_prop.members[memberProp][0]);
}
}
}
fs.writeJSONSync(p, content);
});
}
function removeIonicNativeDecorators(node: any) {
if (node.decorators && node.decorators.length) {
node.decorators = node.decorators.filter((d, i) => d.expression.module !== '@ionic-native/core');
}
if (node.decorators && !node.decorators.length) delete node.decorators;
}
function createSourceFiles(): string[] {
return PLUGIN_PATHS.map((indexPath: string) => {
const ngxPath = path.resolve(indexPath.replace('index.ts', ''), 'ngx'),
newPath = path.resolve(ngxPath, 'index.ts');
// delete directory
rimraf.sync(ngxPath);
fs.mkdirpSync(ngxPath);
fs.copyFileSync(indexPath, newPath);
return newPath;
});
}
export function cleanupNgx() {
PLUGIN_PATHS.forEach((indexPath: string) =>
rimraf.sync(indexPath.replace('index.ts', 'ngx'))
);
}
-14
View File
@@ -1,14 +0,0 @@
{
"name": "@ionic-native/{{PLUGIN}}",
"version": "{{VERSION}}",
"description": "Ionic Native - Native plugins for ionic apps",
"module": "index.js",
"typings": "index.d.ts",
"author": "ionic",
"license": "MIT",
"peerDependencies": {},
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic-native.git"
}
}
-51
View File
@@ -1,51 +0,0 @@
'use strict';
// Node module dependencies
const fs = require('fs-extra-promise').useFs(require('fs-extra')),
queue = require('queue'),
path = require('path'),
exec = require('child-process-promise').exec;
const ROOT = path.resolve(path.join(__dirname, '../../')),
DIST = path.resolve(ROOT, 'dist', '@ionic-native');
const FLAGS = '--access public'; // add any flags here if you want... (example: --tag alpha)
const PACKAGES = fs.readdirSync(DIST);
const failedPackages = [];
const QUEUE = queue({
concurrency: 10
});
PACKAGES.forEach(packageName => {
QUEUE.push(done => {
console.log(`Publishing @ionic-native/${packageName}`);
const packagePath = path.resolve(DIST, packageName);
exec(`npm publish ${packagePath} ${FLAGS}`)
.then(() => done())
.catch(e => {
if (
e.stderr &&
e.stderr.indexOf('previously published version') === -1
) {
failedPackages.push({
cmd: e.cmd,
stderr: e.stderr
});
}
done();
});
});
});
QUEUE.start(err => {
if (err) {
console.log('Error publishing ionic-native. ', err);
} else if (failedPackages.length > 0) {
console.log(`${failedPackages.length} packages failed to publish.`);
console.log(failedPackages);
} else {
console.log('Done publishing ionic-native!');
}
});
+2
View File
@@ -0,0 +1,2 @@
// removes the __extends method that is added automatically by typescript
module.exports = source => source.replace(/var\s__extends\s=\s\(this\s&&[\sa-z\._\(\)\|{}=:\[\]&,;?]+}\)\(\);/i, '');
@@ -0,0 +1,59 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import * as ts from 'typescript';
import { hasDecorator, ROOT } from '../helpers';
export interface InjectableClassEntry {
file: string;
className: string;
dirName: string;
}
const injectableClasses: InjectableClassEntry[] = [];
export const EMIT_PATH = path.resolve(ROOT, 'injectable-classes.json');
/**
* This transformer extracts all the injectable classes
* so we can use all the names later on when we compile
* an es5 bundle.
*
* Every injectable class will end up in the
* window['IonicNative'] object.
*/
export function extractInjectables() {
return (ctx: ts.TransformationContext) => {
return tsSourceFile => {
if (tsSourceFile.fileName.indexOf('src/@ionic-native/plugins') > -1) {
ts.visitEachChild(
tsSourceFile,
node => {
if (node.kind !== ts.SyntaxKind.ClassDeclaration) {
return node;
}
const isInjectable: boolean = hasDecorator('Injectable', node);
if (isInjectable) {
injectableClasses.push({
file: tsSourceFile.path,
className: (node as ts.ClassDeclaration).name.text,
dirName: tsSourceFile.path.split(/[\\\/]+/).reverse()[1]
});
}
},
ctx
);
}
return tsSourceFile;
};
};
}
export function emitInjectableClasses() {
fs.writeJSONSync(EMIT_PATH, injectableClasses);
}
export function cleanEmittedData() {
fs.unlinkSync(EMIT_PATH);
}
+69
View File
@@ -0,0 +1,69 @@
import * as ts from 'typescript';
import { getMethodsForDecorator } from '../helpers';
function transformImports(file: ts.SourceFile, ctx: ts.TransformationContext, ngcBuild?: boolean) {
// remove angular imports
if (!ngcBuild) {
file.statements = (file.statements as any).filter((s: any) => !(s.kind === ts.SyntaxKind.ImportDeclaration && s.moduleSpecifier.text === '@angular/core'));
}
// find the @ionic-native/core import statement
const importStatement = (file.statements as any).find((s: any) => {
return s.kind === ts.SyntaxKind.ImportDeclaration && s.moduleSpecifier.text === '@ionic-native/core';
});
// we're only interested in files containing @ionic-native/core import statement
if (!importStatement) return file;
const decorators: string[] = [];
const decoratorRegex: RegExp = /@([a-zA-Z]+)\(/g;
const ignored: string [] = ['Plugin', 'Component', 'Injectable'];
const keep: string [] = ['getPromise', 'checkAvailability'];
let m;
while ((m = decoratorRegex.exec(file.text)) !== null) {
if (m.index === decoratorRegex.lastIndex) {
decoratorRegex.lastIndex++;
}
if (m && m[1] && decorators.indexOf(m[1]) === -1 && ignored.indexOf(m[1]) === -1) decorators.push(m[1]);
}
if (decorators.length) {
let methods = [];
decorators.forEach(d => methods = getMethodsForDecorator(d).concat(methods));
importStatement.importClause.namedBindings.elements = [
ts.createIdentifier('IonicNativePlugin'),
...methods.map(m => ts.createIdentifier(m)),
...importStatement.importClause.namedBindings.elements.filter(el => keep.indexOf(el.name.text) !== -1)
];
if (ngcBuild) {
importStatement.importClause.namedBindings.elements = importStatement.importClause.namedBindings.elements.map(
binding => {
if (binding.escapedText) {
binding.name = {
text: binding.escapedText
};
}
return binding;
}
);
}
}
return file;
}
export function importsTransformer(ngcBuild?: boolean) {
return (ctx: ts.TransformationContext) => {
return tsSourceFile => {
return transformImports(tsSourceFile, ctx, ngcBuild);
};
};
}
+37
View File
@@ -0,0 +1,37 @@
import * as ts from 'typescript';
import { transformMethod } from './methods';
import { transformProperty } from './properties';
export function transformMembers(cls: ts.ClassDeclaration) {
const propertyIndices: number[] = [];
const members = cls.members.map((member: any, index: number) => {
// only process decorated members
if (!member.decorators || !member.decorators.length) return member;
switch (member.kind) {
case ts.SyntaxKind.MethodDeclaration:
return transformMethod(member);
case ts.SyntaxKind.PropertyDeclaration:
propertyIndices.push(index);
return member;
case ts.SyntaxKind.Constructor:
return ts.createConstructor(undefined, undefined, member.parameters, member.body);
default:
return member; // in case anything gets here by accident...
}
});
propertyIndices.forEach((i: number) => {
const [getter, setter] = transformProperty(members, i) as any;
members.push(getter, setter);
});
propertyIndices.reverse().forEach(i => members.splice(i, 1));
return members;
}
+49
View File
@@ -0,0 +1,49 @@
import * as ts from 'typescript';
import { Logger } from '../../logger';
import { convertValueToLiteral, getDecorator, getDecoratorArgs, getDecoratorName, getMethodsForDecorator } from '../helpers';
export function transformMethod(method: ts.MethodDeclaration) {
if (!method) return;
const decorator = getDecorator(method),
decoratorName = getDecoratorName(decorator),
decoratorArgs = getDecoratorArgs(decorator);
try {
return ts.createMethod(undefined, undefined, undefined, method.name, undefined, method.typeParameters, method.parameters, method.type, ts.createBlock([
ts.createReturn(
getMethodBlock(method, decoratorName, decoratorArgs)
)
]));
} catch (e) {
Logger.error('Error transforming method: ' + (method.name as any).text);
Logger.error(e.message);
}
}
function getMethodBlock(method: ts.MethodDeclaration, decoratorName: string, decoratorArgs: any): ts.Expression {
const decoratorMethod = getMethodsForDecorator(decoratorName)[0];
switch (decoratorName) {
case 'CordovaCheck':
case 'InstanceCheck':
// TODO remove function wrapper
return ts.createImmediatelyInvokedArrowFunction([ts.createIf(
ts.createBinary(
ts.createCall(ts.createIdentifier(decoratorMethod), undefined, [ts.createThis()]),
ts.SyntaxKind.EqualsEqualsEqualsToken,
ts.createTrue()
),
method.body
)]);
default:
return ts.createCall(ts.createIdentifier(decoratorMethod), undefined, [
ts.createThis(),
ts.createLiteral((method.name as any).text),
convertValueToLiteral(decoratorArgs),
ts.createIdentifier('arguments')
]);
}
}
@@ -0,0 +1,80 @@
import * as ts from 'typescript';
import { Logger } from '../../logger';
import {
convertValueToLiteral,
getDecorator,
getDecoratorArgs,
getDecoratorName
} from '../helpers';
import { transformMembers } from './members';
function transformClass(cls: any, ngcBuild?: boolean) {
Logger.profile('transformClass: ' + cls.name.text);
const pluginStatics = [];
const dec: any = getDecorator(cls);
if (dec) {
const pluginDecoratorArgs = getDecoratorArgs(dec);
// add plugin decorator args as static properties of the plugin's class
for (const prop in pluginDecoratorArgs) {
pluginStatics.push(
ts.createProperty(
undefined,
[ts.createToken(ts.SyntaxKind.StaticKeyword)],
ts.createIdentifier(prop),
undefined,
undefined,
convertValueToLiteral(pluginDecoratorArgs[prop])
)
);
}
}
cls = ts.createClassDeclaration(
ngcBuild && cls.decorators && cls.decorators.length
? cls.decorators.filter(d => getDecoratorName(d) === 'Injectable')
: undefined, // remove Plugin and Injectable decorators
[ts.createToken(ts.SyntaxKind.ExportKeyword)],
cls.name,
cls.typeParameters,
cls.heritageClauses,
[...transformMembers(cls), ...pluginStatics]
);
Logger.profile('transformClass: ' + cls.name.text);
return cls;
}
function transformClasses(
file: ts.SourceFile,
ctx: ts.TransformationContext,
ngcBuild?: boolean
) {
Logger.silly('Transforming file: ' + file.fileName);
return ts.visitEachChild(
file,
node => {
if (node.kind !== ts.SyntaxKind.ClassDeclaration
|| (node.modifiers && node.modifiers.find(v => v.kind === ts.SyntaxKind.DeclareKeyword))) {
return node;
}
return transformClass(node, ngcBuild);
},
ctx
);
}
export function pluginClassTransformer(
ngcBuild?: boolean
): ts.TransformerFactory<ts.SourceFile> {
return (ctx: ts.TransformationContext) => {
return tsSourceFile => {
if (tsSourceFile.fileName.indexOf('src/@ionic-native/plugins') > -1)
return transformClasses(tsSourceFile, ctx, ngcBuild);
return tsSourceFile;
};
};
}
+67
View File
@@ -0,0 +1,67 @@
import * as ts from 'typescript';
import { getDecorator, getDecoratorName } from '../helpers';
export function transformProperty(members: any[], index: number) {
const property = members[index] as ts.PropertyDeclaration,
decorator = getDecorator(property),
decoratorName = getDecoratorName(decorator);
let type: 'cordova' | 'instance';
switch (decoratorName) {
case 'CordovaProperty':
type = 'cordova';
break;
case 'InstanceProperty':
type = 'instance';
break;
default:
return property;
}
const getter = ts.createGetAccessor(
undefined,
undefined,
property.name,
undefined,
property.type,
ts.createBlock([
ts.createReturn(
ts.createCall(ts.createIdentifier(type + 'PropertyGet'), undefined, [
ts.createThis(),
ts.createLiteral((property.name as any).text)
])
)
])
);
const setter = ts.createSetAccessor(
undefined,
undefined,
property.name,
[
ts.createParameter(
undefined,
undefined,
undefined,
'value',
undefined,
property.type
)
],
ts.createBlock([
ts.createStatement(
ts.createCall(ts.createIdentifier(type + 'PropertySet'), undefined, [
ts.createThis(),
ts.createLiteral((property.name as any).text),
ts.createIdentifier('value')
])
)
])
);
return [getter, setter];
}
+51
View File
@@ -0,0 +1,51 @@
import * as ts from 'typescript';
import { pluginClassTransformer } from './transformers/plugin-class';
import { importsTransformer } from './transformers/imports';
import { clone } from 'lodash';
import { emitInjectableClasses, extractInjectables } from './transformers/extract-injectables';
import { COMPILER_OPTIONS, PLUGIN_PATHS, TS_CONFIG } from './helpers';
let host: ts.CompilerHost;
export function getCompilerHost() {
if (!host) host = ts.createCompilerHost(TS_CONFIG);
return host;
}
export function getProgram(declaration = false, pluginPaths: string[] = PLUGIN_PATHS) {
const compilerOptions: ts.CompilerOptions = clone(COMPILER_OPTIONS);
compilerOptions.declaration = declaration;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
compilerOptions.target = ts.ScriptTarget.ES5;
compilerOptions.module = ts.ModuleKind.ES2015;
compilerOptions.inlineSourceMap = true;
compilerOptions.inlineSources = true;
compilerOptions.lib = [
'lib.dom.d.ts',
'lib.es5.d.ts',
'lib.es2015.d.ts',
'lib.es2016.d.ts',
'lib.es2017.d.ts'
];
return ts.createProgram(pluginPaths, compilerOptions, getCompilerHost());
}
export function generateDeclarations(sourceFiles?: string[]) {
return getProgram(true, sourceFiles).emit(undefined, getCompilerHost().writeFile, undefined, true);
}
export function transpile() {
const emitResult = getProgram().emit(undefined, getCompilerHost().writeFile, undefined, false, {
before: [
extractInjectables(),
importsTransformer(),
pluginClassTransformer(),
]
});
emitInjectableClasses();
return emitResult;
}
-23
View File
@@ -1,23 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"declaration": true,
"stripInternal": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "es2015",
"moduleResolution": "node",
"outDir": "../../../dist/@ionic-native/",
"paths": {
"@ionic-native/core": ["../../../dist/@ionic-native/core"]
},
"rootDir": "../../../src/@ionic-native/plugins/",
"target": "es5",
"skipLibCheck": true,
"lib": ["es2015", "dom"],
"sourceMap": true,
"inlineSources": true,
"noImplicitAny": true
},
"files": []
}
-71
View File
@@ -1,71 +0,0 @@
const exec = require('child-process-promise').exec;
let diff;
exec(`git branch | grep \\* | cut -d ' ' -f2`)
.then(output => {
if (output.stderr) {
return Promise.reject(output.stderr);
}
const branch = output.stdout.trim();
if (branch !== 'master') {
console.log('Merging master branch in ...');
// not on master branch
// let's test the changes that were made
return exec(`git merge origin master`);
}
})
.then(output => {
if (output && output.stderr) {
return Promise.reject(output.stderr);
}
console.log('Checking for differences ...');
return exec(`git diff --name-status origin master`);
})
.then(output => {
if (output && output.stderr) {
return Promise.reject(output.stderr);
}
diff = output.stdout;
diff = diff.replace(/A\s+/g, '');
diff = diff.match(
/src\/@ionic-native\/plugins\/([a-zA-Z0-9\-]+)\/index\.ts/g
);
if (!diff) process.exit();
console.log(
`${
diff.length
} plugins were modified. We will now build them to verify they still work.`
);
return exec('npm run build:core --silent');
})
.then(output => {
if (output && output.stderr) {
return Promise.reject(output.stderr);
}
console.log('Built core library successfully ...');
console.log('Building plugins ...');
diff = diff.map(text =>
text.replace('src/@ionic-native/plugins/', '').replace('/index.ts', '')
);
return exec(`npm run build:modules ${diff.join(' ')} --silent`);
})
.then(output => {
if (output && output.stderr) {
console.log(output.stderr);
process.exit(1);
}
console.log(output.stdout);
process.exit();
})
.catch(e => {
console.log(e.message || e);
process.exit(1);
});
@@ -2,5 +2,5 @@
"sitePath": "../ionic-site",
"v2DocsDir": "docs/native",
"docsDest": "../ionic-site/content/docs/native",
"pluginDir": "dist/@ionic-native"
"pluginDir": "dist/@ionic-native/plugins"
}
@@ -50,9 +50,9 @@ module.exports = currentVersion => {
// Don't run unwanted processors since we are not using the normal file reading processor
readFilesProcessor.$enabled = false;
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
readFilesProcessor.basePath = path.resolve(__dirname, '../../..');
readTypeScriptModules.basePath = path.resolve(__dirname, '../..');
readTypeScriptModules.basePath = path.resolve(__dirname, '../../..');
readTypeScriptModules.sourceFiles = [
'./src/@ionic-native/plugins/**/*.ts'
];
@@ -40,7 +40,6 @@ module.exports = currentVersion => {
computePathsProcessor.pathTemplates = [{
docTypes: ['class'],
getOutputPath: doc => doc.originalModule.replace(config.pluginDir + '/', '')
.replace('/plugins', '')
.replace(/\/index$/, '/README.md')
}];
@@ -50,15 +49,15 @@ module.exports = currentVersion => {
.config(function(readFilesProcessor, readTypeScriptModules) {
// Don't run unwanted processors since we are not using the normal file reading processor
readFilesProcessor.$enabled = false;
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
readFilesProcessor.basePath = path.resolve(__dirname, '../../..');
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../..'));
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../../..'));
readTypeScriptModules.sourceFiles = ['./src/@ionic-native/plugins/**/*.ts'];
})
// Configure file writing
.config(function(writeFilesProcessor) {
writeFilesProcessor.outputFolder = './dist/';
writeFilesProcessor.outputFolder = './dist/@ionic-native/';
})
// Configure rendering
@@ -10,7 +10,7 @@ module.exports = function readmes(renderDocsProcessor) {
docs = docs.filter(doc => (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page');
docs.forEach(doc => {
doc.outputPath = doc.outputPath.replace('src/', '');
doc.outputPath = doc.outputPath.replace('src/@ionic-native/', '');
});
return docs;
@@ -187,7 +187,7 @@ docType: "<$ doc.docType $>"
<ol class="installation">
<li>Install the Cordova and Ionic Native plugins:<br>
<pre><code class="nohighlight">$ <@ if prop.install @><$ prop.install | replace('<', '&lt;').replace('>', '&gt;') $><@ else @>ionic cordova plugin add <$ prop.plugin $><@ endif @>
$ npm install --save @ionic-native/<$ doc.npmId $>
$ npm install @ionic-native/<$ doc.npmId $>@beta
</code></pre>
</li>
<li><a href="https://ionicframework.com/docs/native/#Add_Plugins_to_Your_App_Module">Add this plugin to your app's module</a></li>
@@ -17,7 +17,7 @@
```
$ <@ if prop.install @><$ prop.install $><@ else @>ionic cordova plugin add <$ prop.plugin $><@ endif @>
$ npm install --save @ionic-native/<$ doc.npmId $>
$ npm install @ionic-native/<$ doc.npmId $>@beta
```
## [Usage Documentation](https://ionicframework.com/docs/native/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/')|replace('index.ts','')|replace('src/@ionic-native/plugins/','') $>)
+19 -16
View File
@@ -1,39 +1,42 @@
"use strict";
const config = require('../config.json'),
'use strict';
const config = require('./config.json'),
projectPackage = require('../../package.json'),
path = require('path'),
fs = require('fs-extra-promise').useFs(require('fs-extra')),
fs = require('fs-extra'),
Dgeni = require('dgeni');
module.exports = gulp => {
gulp.task('docs', [], () => {
try {
const ionicPackage = require('./dgeni-config')(projectPackage.version),
const ionicPackage = require('./dgeni/dgeni-config')(
projectPackage.version
),
dgeni = new Dgeni([ionicPackage]);
return dgeni.generate().then(docs => console.log(docs.length + ' docs generated'));
return dgeni
.generate()
.then(docs => console.log(docs.length + ' docs generated'));
} catch (err) {
console.log(err.stack);
}
});
gulp.task('readmes', [], function() {
fs.copySync(path.resolve(__dirname, '..', '..', 'README.md'), path.resolve(__dirname, '..', '..', config.pluginDir, 'core', 'README.md'));
fs.copySync(
path.resolve(__dirname, '..', '..', 'README.md'),
path.resolve(__dirname, '..', '..', config.pluginDir, 'core', 'README.md')
);
try {
const ionicPackage = require('./dgeni-readmes-config')(projectPackage.version),
const ionicPackage = require('./dgeni/dgeni-readmes-config')(
projectPackage.version
),
dgeni = new Dgeni([ionicPackage]);
return dgeni.generate().then(docs => console.log(docs.length + ' README files generated'));
return dgeni
.generate()
.then(docs => console.log(docs.length + ' README files generated'));
} catch (err) {
console.log(err.stack);
}
});
};
+1 -1
View File
@@ -31,7 +31,7 @@ function run {
# git push origin master || :
echo "-- Updated docs for $VERSION_NAME succesfully!"
echo "-- Updated docs for $VERSION_NAME successfully!"
fi
}
+244 -244
View File
@@ -1,244 +1,244 @@
# bash utils from angularjs
# This file provides:
# - a default control flow
# * initializes the environment
# * call a function in your script based on the arguments
# - named argument parsing and automatic generation of the "usage" for your script
# - utility functions
#
# Usage:
# - define the variable ARGS_DEF (see below) with the arguments for your script
# - include this file using `source utils.inc` at the end of your script.
#
# Default control flow:
# 0. Set the current directory to the directory of the script. By this
# the script can be called from anywhere.
# 1. Parse the named arguments
# 2. [Redacted]
# 3. If the parameter "verbose" is set, the `-x` flag will be set in bash.
# 4. The function "init" will be called if it exists
# 5. If the parameter "action" is set, it will call the function with the name of that parameter.
# Otherwise the function "run" will be called.
#
# Named Argument Parsing:
# - The variable ARGS_DEF defines the valid command arguments
# * Required args syntax: --paramName=paramRegex
# * Optional args syntax: [--paramName=paramRegex]
# * e.g. ARG_DEFS=("--required_param=(.+)" "[--optional_param=(.+)]")
# - Checks that:
# * all arguments match to an entry in ARGS_DEF
# * all required arguments are present
# * all arguments match their regex
# - Afterwards, every paramter value will be stored in a variable
# with the name of the parameter in upper case (with dash converted to underscore).
#
# Special arguments that are always available:
# - "--action=.*": This parameter will be used to dispatch to a function with that name when the
# script is started
# - "--verbose=true": This will set the `-x` flag in bash so that all calls will be logged
#
# Utility functions:
# - readJsonProp
# - replaceJsonProp
# - resolveDir
# - getVar
# - serVar
# - isFunction
# always stop on errors
set -e
function usage {
echo "Usage: ${0} ${ARG_DEFS[@]}"
exit 1
}
function parseArgs {
local REQUIRED_ARG_NAMES=()
# -- helper functions
function varName {
# everything to upper case and dash to underscore
echo ${1//-/_} | tr '[:lower:]' '[:upper:]'
}
function readArgDefs {
local ARG_DEF
local AD_OPTIONAL
local AD_NAME
local AD_RE
# -- helper functions
function parseArgDef {
local ARG_DEF_REGEX="(\[?)--([^=]+)=(.*)"
if [[ ! $1 =~ $ARG_DEF_REGEX ]]; then
echo "Internal error: arg def has wrong format: $ARG_DEF"
exit 1
fi
AD_OPTIONAL="${BASH_REMATCH[1]}"
AD_NAME="${BASH_REMATCH[2]}"
AD_RE="${BASH_REMATCH[3]}"
if [[ $AD_OPTIONAL ]]; then
# Remove last bracket for optional args.
# Can't put this into the ARG_DEF_REGEX somehow...
AD_RE=${AD_RE%?}
fi
}
# -- run
for ARG_DEF in "${ARG_DEFS[@]}"
do
parseArgDef $ARG_DEF
local AD_NAME_UPPER=$(varName $AD_NAME)
setVar "${AD_NAME_UPPER}_OPTIONAL" "$AD_OPTIONAL"
setVar "${AD_NAME_UPPER}_RE" "$AD_RE"
if [[ ! $AD_OPTIONAL ]]; then
REQUIRED_ARG_NAMES+=($AD_NAME)
fi
done
}
function readAndValidateArgs {
local ARG_NAME
local ARG_VALUE
local ARG_NAME_UPPER
# -- helper functions
function parseArg {
local ARG_REGEX="--([^=]+)=?(.*)"
if [[ ! $1 =~ $ARG_REGEX ]]; then
echo "Can't parse argument $i"
usage
fi
ARG_NAME="${BASH_REMATCH[1]}"
ARG_VALUE="${BASH_REMATCH[2]}"
ARG_NAME_UPPER=$(varName $ARG_NAME)
}
function validateArg {
local AD_RE=$(getVar ${ARG_NAME_UPPER}_RE)
if [[ ! $AD_RE ]]; then
echo "Unknown option: $ARG_NAME"
usage
fi
if [[ ! $ARG_VALUE =~ ^${AD_RE}$ ]]; then
echo "Wrong format: $ARG_NAME"
usage;
fi
# validate that the "action" option points to a valid function
if [[ $ARG_NAME == "action" ]] && ! isFunction $ARG_VALUE; then
echo "No action $ARG_VALUE defined in this script"
usage;
fi
}
# -- run
for i in "$@"
do
parseArg $i
validateArg
setVar "${ARG_NAME_UPPER}" "$ARG_VALUE"
done
}
function checkMissingArgs {
local ARG_NAME
for ARG_NAME in "${REQUIRED_ARG_NAMES[@]}"
do
ARG_VALUE=$(getVar $(varName $ARG_NAME))
if [[ ! $ARG_VALUE ]]; then
echo "Missing: $ARG_NAME"
usage;
fi
done
}
# -- run
readArgDefs
readAndValidateArgs "$@"
checkMissingArgs
}
# getVar(varName)
function getVar {
echo ${!1}
}
# setVar(varName, varValue)
function setVar {
eval "$1=\"$2\""
}
# isFunction(name)
# - to be used in an if, so return 0 if successful and 1 if not!
function isFunction {
if [[ $(type -t $1) == "function" ]]; then
return 0
else
return 1
fi
}
# readJsonProp(jsonFile, property)
# - restriction: property needs to be on an own line!
function readJsonProp {
echo $(sed -En 's/.*"'$2'"[ ]*:[ ]*"(.*)".*/\1/p' $1)
}
# replaceJsonProp(jsonFile, property, newValue)
# - note: propertyRegex will be automatically placed into a
# capturing group! -> all other groups start at index 2!
function replaceJsonProp {
replaceInFile $1 "\"$2\": \".*?\"" "\"$2\": \"$3\""
}
# replaceInFile(file, findPattern, replacePattern)
function replaceInFile {
perl -pi -e "s/$2/$3/g;" $1
}
# resolveDir(relativeDir)
# - resolves a directory relative to the current script
function resolveDir {
echo $(cd $SCRIPT_DIR; cd $1; pwd)
}
function main {
# normalize the working dir to the directory of the script
cd $(dirname $0);SCRIPT_DIR=$(pwd)
ARG_DEFS+=("[--verbose=(true|false)]")
parseArgs "$@"
# --verbose argument
if [[ $VERBOSE == "true" ]]; then
set -x
fi
if isFunction init; then
init "$@"
fi
# jump to the function denoted by the --action argument,
# otherwise call the "run" function
if [[ $ACTION ]]; then
$ACTION "$@"
else
run "$@"
fi
}
main "$@"
# bash utils from angularjs
# This file provides:
# - a default control flow
# * initializes the environment
# * call a function in your script based on the arguments
# - named argument parsing and automatic generation of the "usage" for your script
# - utility functions
#
# Usage:
# - define the variable ARGS_DEF (see below) with the arguments for your script
# - include this file using `source utils.inc` at the end of your script.
#
# Default control flow:
# 0. Set the current directory to the directory of the script. By this
# the script can be called from anywhere.
# 1. Parse the named arguments
# 2. [Redacted]
# 3. If the parameter "verbose" is set, the `-x` flag will be set in bash.
# 4. The function "init" will be called if it exists
# 5. If the parameter "action" is set, it will call the function with the name of that parameter.
# Otherwise the function "run" will be called.
#
# Named Argument Parsing:
# - The variable ARGS_DEF defines the valid command arguments
# * Required args syntax: --paramName=paramRegex
# * Optional args syntax: [--paramName=paramRegex]
# * e.g. ARG_DEFS=("--required_param=(.+)" "[--optional_param=(.+)]")
# - Checks that:
# * all arguments match to an entry in ARGS_DEF
# * all required arguments are present
# * all arguments match their regex
# - Afterwards, every paramter value will be stored in a variable
# with the name of the parameter in upper case (with dash converted to underscore).
#
# Special arguments that are always available:
# - "--action=.*": This parameter will be used to dispatch to a function with that name when the
# script is started
# - "--verbose=true": This will set the `-x` flag in bash so that all calls will be logged
#
# Utility functions:
# - readJsonProp
# - replaceJsonProp
# - resolveDir
# - getVar
# - serVar
# - isFunction
# always stop on errors
set -e
function usage {
echo "Usage: ${0} ${ARG_DEFS[@]}"
exit 1
}
function parseArgs {
local REQUIRED_ARG_NAMES=()
# -- helper functions
function varName {
# everything to upper case and dash to underscore
echo ${1//-/_} | tr '[:lower:]' '[:upper:]'
}
function readArgDefs {
local ARG_DEF
local AD_OPTIONAL
local AD_NAME
local AD_RE
# -- helper functions
function parseArgDef {
local ARG_DEF_REGEX="(\[?)--([^=]+)=(.*)"
if [[ ! $1 =~ $ARG_DEF_REGEX ]]; then
echo "Internal error: arg def has wrong format: $ARG_DEF"
exit 1
fi
AD_OPTIONAL="${BASH_REMATCH[1]}"
AD_NAME="${BASH_REMATCH[2]}"
AD_RE="${BASH_REMATCH[3]}"
if [[ $AD_OPTIONAL ]]; then
# Remove last bracket for optional args.
# Can't put this into the ARG_DEF_REGEX somehow...
AD_RE=${AD_RE%?}
fi
}
# -- run
for ARG_DEF in "${ARG_DEFS[@]}"
do
parseArgDef $ARG_DEF
local AD_NAME_UPPER=$(varName $AD_NAME)
setVar "${AD_NAME_UPPER}_OPTIONAL" "$AD_OPTIONAL"
setVar "${AD_NAME_UPPER}_RE" "$AD_RE"
if [[ ! $AD_OPTIONAL ]]; then
REQUIRED_ARG_NAMES+=($AD_NAME)
fi
done
}
function readAndValidateArgs {
local ARG_NAME
local ARG_VALUE
local ARG_NAME_UPPER
# -- helper functions
function parseArg {
local ARG_REGEX="--([^=]+)=?(.*)"
if [[ ! $1 =~ $ARG_REGEX ]]; then
echo "Can't parse argument $i"
usage
fi
ARG_NAME="${BASH_REMATCH[1]}"
ARG_VALUE="${BASH_REMATCH[2]}"
ARG_NAME_UPPER=$(varName $ARG_NAME)
}
function validateArg {
local AD_RE=$(getVar ${ARG_NAME_UPPER}_RE)
if [[ ! $AD_RE ]]; then
echo "Unknown option: $ARG_NAME"
usage
fi
if [[ ! $ARG_VALUE =~ ^${AD_RE}$ ]]; then
echo "Wrong format: $ARG_NAME"
usage;
fi
# validate that the "action" option points to a valid function
if [[ $ARG_NAME == "action" ]] && ! isFunction $ARG_VALUE; then
echo "No action $ARG_VALUE defined in this script"
usage;
fi
}
# -- run
for i in "$@"
do
parseArg $i
validateArg
setVar "${ARG_NAME_UPPER}" "$ARG_VALUE"
done
}
function checkMissingArgs {
local ARG_NAME
for ARG_NAME in "${REQUIRED_ARG_NAMES[@]}"
do
ARG_VALUE=$(getVar $(varName $ARG_NAME))
if [[ ! $ARG_VALUE ]]; then
echo "Missing: $ARG_NAME"
usage;
fi
done
}
# -- run
readArgDefs
readAndValidateArgs "$@"
checkMissingArgs
}
# getVar(varName)
function getVar {
echo ${!1}
}
# setVar(varName, varValue)
function setVar {
eval "$1=\"$2\""
}
# isFunction(name)
# - to be used in an if, so return 0 if successful and 1 if not!
function isFunction {
if [[ $(type -t $1) == "function" ]]; then
return 0
else
return 1
fi
}
# readJsonProp(jsonFile, property)
# - restriction: property needs to be on an own line!
function readJsonProp {
echo $(sed -En 's/.*"'$2'"[ ]*:[ ]*"(.*)".*/\1/p' $1)
}
# replaceJsonProp(jsonFile, property, newValue)
# - note: propertyRegex will be automatically placed into a
# capturing group! -> all other groups start at index 2!
function replaceJsonProp {
replaceInFile $1 "\"$2\": \".*?\"" "\"$2\": \"$3\""
}
# replaceInFile(file, findPattern, replacePattern)
function replaceInFile {
perl -pi -e "s/$2/$3/g;" $1
}
# resolveDir(relativeDir)
# - resolves a directory relative to the current script
function resolveDir {
echo $(cd $SCRIPT_DIR; cd $1; pwd)
}
function main {
# normalize the working dir to the directory of the script
cd $(dirname $0);SCRIPT_DIR=$(pwd)
ARG_DEFS+=("[--verbose=(true|false)]")
parseArgs "$@"
# --verbose argument
if [[ $VERBOSE == "true" ]]; then
set -x
fi
if isFunction init; then
init "$@"
fi
# jump to the function denoted by the --action argument,
# otherwise call the "run" function
if [[ $ACTION ]]; then
$ACTION "$@"
else
run "$@"
fi
}
main "$@"
+11
View File
@@ -0,0 +1,11 @@
import { createLogger, format, transports } from 'winston';
const { combine, colorize, simple } = format;
const LOG_LEVEL = 'verbose';
export const Logger = createLogger({
level: LOG_LEVEL,
format: combine(colorize(), simple()),
transports: [new transports.Console({ level: LOG_LEVEL })]
});
+97
View File
@@ -0,0 +1,97 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import * as uglifyJsPlugin from 'uglifyjs-webpack-plugin';
import * as unminifiedPlugin from 'unminified-webpack-plugin';
import * as webpack from 'webpack';
import { ROOT } from '../build/helpers';
import {
cleanEmittedData,
EMIT_PATH,
InjectableClassEntry
} from '../build/transformers/extract-injectables';
import { Logger } from '../logger';
const DIST = path.resolve(ROOT, 'dist');
const INDEX_PATH = path.resolve(DIST, 'index.js');
const INJECTABLE_CLASSES = fs
.readJSONSync(EMIT_PATH)
.map((item: InjectableClassEntry) => {
item.file =
'./' +
item.file
.split(/[\/\\]+/)
.slice(-4, -1)
.join('/');
return item;
});
const webpackConfig: webpack.Configuration = {
mode: 'production',
entry: INDEX_PATH,
devtool: 'source-map',
target: 'web',
output: {
path: DIST,
filename: 'ionic-native.min.js'
},
resolve: {
modules: ['node_modules'],
extensions: ['.js'],
alias: {
'@ionic-native/core': path.resolve(DIST, '@ionic-native/core/index.js')
}
},
module: {
rules: [
{
test: /\.js$/,
use: path.resolve(ROOT, 'scripts/build/remove-tslib-helpers.js')
}
]
},
plugins: [
new webpack.ProvidePlugin({
__extends: ['tslib', '__extends']
}),
new webpack.optimize.OccurrenceOrderPlugin(true),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new uglifyJsPlugin({
sourceMap: true
}),
new unminifiedPlugin()
]
};
function getPluginImport(entry: InjectableClassEntry) {
return `import { ${entry.className} } from '${entry.file}';`;
}
function createIndexFile() {
let fileContent = '';
fileContent += INJECTABLE_CLASSES.map(getPluginImport).join('\n');
fileContent += `\nwindow.IonicNative = {\n`;
fileContent += INJECTABLE_CLASSES.map(e => e.className).join(',\n');
fileContent += '\n};\n';
fileContent += `require('./@ionic-native/core/bootstrap').checkReady();\n`;
fileContent += `require('./@ionic-native/core/ng1').initAngular1(window.IonicNative);`;
fs.writeFileSync(INDEX_PATH, fileContent, { encoding: 'utf-8' });
}
function compile() {
Logger.profile('build-es5');
webpack(webpackConfig, (err, stats) => {
Logger.profile('build-es5');
if (err) Logger.error('Error occurred while compiling with Webpack', err);
else {
Logger.info('Compiled ES5 file with Webpack successfully.');
}
cleanEmittedData();
});
}
createIndexFile();
compile();
+46
View File
@@ -0,0 +1,46 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import { PLUGIN_PATHS, ROOT } from '../build/helpers';
import { EMIT_PATH } from '../build/transformers/extract-injectables';
import { generateDeclarations, transpile } from '../build/transpile';
generateDeclarations();
transpile();
const outDirs = PLUGIN_PATHS.map(p =>
p.replace(path.join(ROOT, 'src'), path.join(ROOT, 'dist')).replace(/[\\/]index.ts/, '')
);
const injectableClasses = fs.readJSONSync(EMIT_PATH);
outDirs.forEach(dir => {
const classes = injectableClasses.filter(
entry => entry.dirName === dir.split(/[\\/]+/).pop()
);
let jsFile: string = fs.readFileSync(path.join(dir, 'index.js'), 'utf-8'),
dtsFile: string = fs.readFileSync(path.join(dir, 'index.d.ts'), 'utf-8');
classes.forEach(entry => {
dtsFile = dtsFile.replace(
`class ${entry.className} `,
'class ' + entry.className + 'Original '
);
dtsFile += `\nexport declare const ${entry.className}: ${
entry.className
}Original;`;
jsFile = jsFile.replace(
new RegExp(`([\\s\\(])${entry.className}([\\s\\.;\\(,])`, 'g'),
'$1' + entry.className + 'Original$2'
);
jsFile = jsFile.replace(
`export { ${entry.className}Original }`,
`var ${entry.className} = new ${entry.className}Original();\nexport { ${
entry.className
} }`
);
});
fs.writeFileSync(path.join(dir, 'index.js'), jsFile, 'utf-8');
fs.writeFileSync(path.join(dir, 'index.d.ts'), dtsFile, 'utf-8');
});
+13
View File
@@ -0,0 +1,13 @@
import {
cleanupNgx,
generateDeclarationFiles,
modifyMetadata,
transpileNgx,
transpileNgxCore
} from '../build/ngx';
transpileNgxCore();
transpileNgx();
generateDeclarationFiles();
modifyMetadata();
cleanupNgx();
+112
View File
@@ -0,0 +1,112 @@
import * as Queue from 'async-promise-queue';
import { exec } from 'child_process';
import * as fs from 'fs-extra';
import { merge } from 'lodash';
import { cpus } from 'os';
import * as path from 'path';
import { PLUGIN_PATHS, ROOT } from '../build/helpers';
import { Logger } from '../logger';
// tslint:disable-next-line:no-var-requires
const MAIN_PACKAGE_JSON = require('../../package.json');
const VERSION = MAIN_PACKAGE_JSON.version;
const FLAGS = '--access public --tag beta';
const PACKAGE_JSON_BASE = {
description: 'Ionic Native - Native plugins for ionic apps',
module: 'index.js',
typings: 'index.d.ts',
author: 'ionic',
license: 'MIT',
repository: {
type: 'git',
url: 'https://github.com/ionic-team/ionic-native.git'
}
};
const DIST = path.resolve(ROOT, 'dist/@ionic-native');
const PACKAGES = [];
const RXJS_VERSION = '*';
const PLUGIN_PEER_DEPENDENCIES = {
'@ionic-native/core': VERSION, // TODO change this in production
rxjs: RXJS_VERSION
};
function getPackageJsonContent(name, peerDependencies = {}, dependencies = {}) {
return merge(PACKAGE_JSON_BASE, {
name: '@ionic-native/' + name,
dependencies,
peerDependencies,
version: VERSION
});
}
function writePackageJson(data: any, dir: string) {
const filePath = path.resolve(dir, 'package.json');
fs.writeJSONSync(filePath, data);
PACKAGES.push(dir);
}
function prepare() {
// write @ionic-native/core package.json
writePackageJson(
getPackageJsonContent('core', { rxjs: RXJS_VERSION }, { '@types/cordova': 'latest' }),
path.resolve(DIST, 'core')
);
// write plugin package.json files
PLUGIN_PATHS.forEach((pluginPath: string) => {
const pluginName = pluginPath.split(/[\/\\]+/).slice(-2)[0];
const packageJsonContents = getPackageJsonContent(
pluginName,
PLUGIN_PEER_DEPENDENCIES
);
const dir = path.resolve(DIST, 'plugins', pluginName);
writePackageJson(packageJsonContents, dir);
});
}
async function publish(ignoreErrors = false) {
Logger.profile('Publishing');
// upload 1 package per CPU thread at a time
const worker = Queue.async.asyncify((pkg: any) =>
new Promise<any>((resolve, reject) => {
exec(`npm publish ${pkg} ${FLAGS}`, (err, stdout) => {
if (stdout) {
Logger.verbose(stdout.trim());
resolve(stdout);
}
if (err) {
if (!ignoreErrors) {
if (
err.message.includes(
'You cannot publish over the previously published version'
)
) {
Logger.verbose('Ignoring duplicate version error.');
return resolve();
}
reject(err);
}
}
});
})
);
try {
await Queue(worker, PACKAGES, cpus().length);
Logger.info('Done publishing!');
} catch (e) {
Logger.error('Error publishing!');
Logger.error(e);
}
Logger.profile('Publishing');
}
prepare();
publish();
+1 -1
View File
@@ -11,7 +11,7 @@
*/
import { Injectable } from '@angular/core';
import { Plugin, Cordova, CordovaProperty, CordovaInstance, InstanceProperty, IonicNativePlugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { Observable } from 'rxjs';
/**
* @name {{ Plugin_Name }}
+1 -1
View File
@@ -11,7 +11,7 @@
*/
import { Injectable } from '@angular/core';
import { Plugin, Cordova, CordovaProperty, CordovaInstance, InstanceProperty, IonicNativePlugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { Observable } from 'rxjs';
/**
* @name {{ Plugin_Name }}
+12
View File
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"moduleResolution": "node",
"noImplicitAny": false,
"lib": ["es6"]
},
"exclude": [
"node_modules"
]
}
+1 -1
View File
@@ -16,7 +16,7 @@ export function checkReady() {
});
setTimeout(() => {
if (!didFireReady && !!window.cordova) {
if (!didFireReady && window.cordova) {
console.warn(
`Ionic Native: deviceready did not fire within ${DEVICE_READY_TIMEOUT}ms. This can happen when plugins are in an inconsistent state. Try removing plugins from plugins/ and reinstalling them.`
);
-251
View File
@@ -1,251 +0,0 @@
import 'core-js';
import { Observable } from 'rxjs/Observable';
import { Cordova, CordovaCheck, CordovaInstance, CordovaProperty, InstanceProperty, Plugin } from './decorators';
import { IonicNativePlugin } from './ionic-native-plugin';
import { ERR_CORDOVA_NOT_AVAILABLE, ERR_PLUGIN_NOT_INSTALLED } from './plugin';
declare const window: any;
class TestObject {
constructor(public _objectInstance: any) {}
@InstanceProperty name: string;
@CordovaInstance({ sync: true })
pingSync(): string {
return;
}
@CordovaInstance()
ping(): Promise<any> {
return;
}
}
@Plugin({
pluginName: 'TestPlugin',
pluginRef: 'testPlugin',
repo: '',
plugin: 'cordova-plugin-my-plugin',
platforms: ['Android', 'iOS']
})
class TestPlugin extends IonicNativePlugin {
@CordovaProperty name: string;
@Cordova({ sync: true })
pingSync(): string {
return;
}
@Cordova()
ping(): Promise<string> {
return;
}
@CordovaCheck()
customPing(): Promise<string> {
return Promise.resolve('pong');
}
create(): TestObject {
return new TestObject(TestPlugin.getPlugin().create());
}
@Cordova({
destruct: true
})
destructPromise(): Promise<any> {
return;
}
@Cordova({
destruct: true,
observable: true
})
destructObservable(): Observable<any> {
return;
}
}
function definePlugin() {
(window as any).testPlugin = {
name: 'John Smith',
ping: (success: Function, error: Function) => success('pong'),
pingSync: () => 'pong',
create: function TestObject() {
this.pingSync = () => 'pong';
this.ping = (success: Function, error: Function) => success('pong');
this.name = 'John Smith';
return this;
},
destructPromise: (success: Function) => success('hello', 'world'),
destructObservable: (success: Function) => success('hello', 'world')
};
}
describe('Regular Decorators', () => {
let plugin: TestPlugin;
beforeEach(() => {
plugin = new TestPlugin();
definePlugin();
});
describe('Plugin', () => {
it('should set pluginName', () => {
expect(TestPlugin.getPluginName()).toEqual('TestPlugin');
});
it('should set pluginRef', () => {
expect(TestPlugin.getPluginRef()).toEqual('testPlugin');
});
it('should return original plugin object', () => {
expect(TestPlugin.getPlugin()).toEqual(window.testPlugin);
});
it('should return supported platforms', () => {
expect(TestPlugin.getSupportedPlatforms()).toEqual(['Android', 'iOS']);
});
});
describe('Cordova', () => {
it('should do a sync function', () => {
expect(plugin.pingSync()).toEqual('pong');
});
it('should do an async function', (done: Function) => {
plugin
.ping()
.then(res => {
expect(res).toEqual('pong');
done();
})
.catch(e => {
expect(e).toBeUndefined();
done('Method should have resolved');
});
});
it('should throw plugin_not_installed error', (done: Function) => {
delete window.testPlugin;
window.cordova = true;
expect(<any>plugin.pingSync()).toEqual(ERR_PLUGIN_NOT_INSTALLED);
plugin.ping().catch(e => {
expect(e).toEqual(ERR_PLUGIN_NOT_INSTALLED.error);
delete window.cordova;
done();
});
});
it('should throw cordova_not_available error', (done: Function) => {
delete window.testPlugin;
expect(<any>plugin.pingSync()).toEqual(ERR_CORDOVA_NOT_AVAILABLE);
plugin.ping().catch(e => {
expect(e).toEqual(ERR_CORDOVA_NOT_AVAILABLE.error);
done();
});
});
});
describe('CordovaProperty', () => {
it('should return property value', () => {
expect(plugin.name).toEqual('John Smith');
});
it('should set property value', () => {
plugin.name = 'value2';
expect(plugin.name).toEqual('value2');
});
});
describe('CordovaCheck', () => {
it('should run the method when plugin exists', done => {
plugin.customPing().then(res => {
expect(res).toEqual('pong');
done();
});
});
it('shouldnt run the method when plugin doesnt exist', done => {
delete window.testPlugin;
window.cordova = true;
plugin.customPing().catch(e => {
expect(e).toEqual(ERR_PLUGIN_NOT_INSTALLED.error);
done();
});
});
});
describe('CordovaOptions', () => {
describe('destruct', () => {
it('should destruct values returned by a Promise', done => {
plugin.destructPromise().then((args: any[]) => {
expect(args).toEqual(['hello', 'world']);
done();
});
});
it('should destruct values returned by an Observable', done => {
plugin.destructObservable().subscribe((args: any[]) => {
expect(args).toEqual(['hello', 'world']);
done();
});
});
});
});
});
describe('Instance Decorators', () => {
let instance: TestObject, plugin: TestPlugin;
beforeEach(() => {
definePlugin();
plugin = new TestPlugin();
instance = plugin.create();
});
describe('Instance plugin', () => {});
describe('CordovaInstance', () => {
it('should call instance async method', done => {
instance.ping().then(r => {
expect(r).toEqual('pong');
done();
});
});
it('should call instance sync method', () => {
expect(instance.pingSync()).toEqual('pong');
});
it('shouldnt call instance method when _objectInstance is undefined', () => {
delete instance._objectInstance;
instance
.ping()
.then(r => {
expect(r).toBeUndefined();
})
.catch(e => {
expect(e).toBeUndefined();
});
});
});
describe('InstanceProperty', () => {
it('should return property value', () => {
expect(instance.name).toEqual('John Smith');
});
it('should set property value', () => {
instance.name = 'John Cena';
expect(instance.name).toEqual('John Cena');
});
});
});
-326
View File
@@ -1,326 +0,0 @@
import { Observable } from 'rxjs/Observable';
import { _throw } from 'rxjs/observable/throw';
import { checkAvailability, instanceAvailability, overrideFunction, wrap, wrapInstance } from './plugin';
import { getPlugin, getPromise } from './util';
export interface PluginConfig {
/**
* Plugin name, this should match the class name
*/
pluginName: string;
/**
* Plugin NPM package name
*/
plugin: string;
/**
* Plugin object reference
*/
pluginRef?: string;
/**
* Github repository URL
*/
repo?: string;
/**
* Custom install command
*/
install?: string;
/**
* Available installation variables
*/
installVariables?: string[];
/**
* Supported platforms
*/
platforms?: string[];
[key: string]: any;
}
export interface CordovaOptions {
destruct?: boolean;
/**
* Set to true if the wrapped method is a sync function
*/
sync?: boolean;
/**
* Callback order. Set to reverse if the success/error callbacks are the first 2 arguments that the wrapped method takes.
*/
callbackOrder?: 'reverse';
/**
* Callback style
*/
callbackStyle?: 'node' | 'object';
/**
* Set a custom index for the success callback function. This doesn't work if callbackOrder or callbackStyle are set.
*/
successIndex?: number;
/**
* Set a custom index for the error callback function. This doesn't work if callbackOrder or callbackStyle are set.
*/
errorIndex?: number;
/**
* Success function property name. This must be set if callbackStyle is set to object.
*/
successName?: string;
/**
* Error function property name. This must be set if callbackStyle is set to object.
*/
errorName?: string;
/**
* Set to true to return an observable
*/
observable?: boolean;
/**
* If observable is set to true, this can be set to a different function name that will cancel the observable.
*/
clearFunction?: string;
/**
* This can be used if clearFunction is set. Set this to true to call the clearFunction with the same arguments used in the initial function.
*/
clearWithArgs?: boolean;
/**
* Creates an observable that wraps a global event. Replaces document.addEventListener
*/
eventObservable?: boolean;
/**
* Event name, this must be set if eventObservable is set to true
*/
event?: string;
/**
* Element to attach the event listener to, this is optional, defaults to `window`
*/
element?: any;
/**
* Set to true if the wrapped method returns a promise
*/
otherPromise?: boolean;
/**
* Supported platforms
*/
platforms?: string[];
}
export interface CordovaCheckOptions {
sync?: boolean;
observable?: boolean;
}
/**
* @private
*/
export function InstanceCheck(opts: CordovaCheckOptions = {}) {
return (
pluginObj: Object,
methodName: string,
descriptor: TypedPropertyDescriptor<any>
): TypedPropertyDescriptor<any> => {
return {
value: function(...args: any[]): any {
if (instanceAvailability(this)) {
return descriptor.value.apply(this, args);
} else {
if (opts.sync) {
return;
} else if (opts.observable) {
return new Observable<any>(() => {});
}
return getPromise(() => {});
}
},
enumerable: true
};
};
}
/**
* Executes function only if plugin is available
* @private
*/
export function CordovaCheck(opts: CordovaCheckOptions = {}) {
return (
pluginObj: Object,
methodName: string,
descriptor: TypedPropertyDescriptor<any>
): TypedPropertyDescriptor<any> => {
return {
value: function(...args: any[]): any {
const check = checkAvailability(pluginObj);
if (check === true) {
return descriptor.value.apply(this, args);
} else {
if (opts.sync) {
return null;
} else if (opts.observable) {
return _throw(new Error(check && check.error));
}
return Promise.reject(check && check.error);
}
},
enumerable: true
};
};
}
/**
* @private
*
* Class decorator specifying Plugin metadata. Required for all plugins.
*
* @usage
* ```typescript
* @Plugin({
* pluginName: 'MyPlugin',
* plugin: 'cordova-plugin-myplugin',
* pluginRef: 'window.myplugin'
* })
* export class MyPlugin {
*
* // Plugin wrappers, properties, and functions go here ...
*
* }
* ```
*/
export function Plugin(config: PluginConfig): ClassDecorator {
return function(cls: any) {
// Add these fields to the class
for (let prop in config) {
cls[prop] = config[prop];
}
cls['installed'] = function(printWarning?: boolean) {
return !!getPlugin(config.pluginRef);
};
cls['getPlugin'] = function() {
return getPlugin(config.pluginRef);
};
cls['checkInstall'] = function() {
return checkAvailability(cls) === true;
};
cls['getPluginName'] = function() {
return config.pluginName;
};
cls['getPluginRef'] = function() {
return config.pluginRef;
};
cls['getPluginInstallName'] = function() {
return config.plugin;
};
cls['getPluginRepo'] = function() {
return config.repo;
};
cls['getSupportedPlatforms'] = function() {
return config.platforms;
};
return cls;
};
}
/**
* @private
*
* Wrap a stub function in a call to a Cordova plugin, checking if both Cordova
* and the required plugin are installed.
*/
export function Cordova(opts: CordovaOptions = {}) {
return (
target: Object,
methodName: string,
descriptor: TypedPropertyDescriptor<any>
) => {
return {
value: function(...args: any[]) {
return wrap(this, methodName, opts).apply(this, args);
},
enumerable: true
};
};
}
/**
* @private
*
* Wrap an instance method
*/
export function CordovaInstance(opts: CordovaOptions = {}) {
return (target: Object, methodName: string) => {
return {
value: function(...args: any[]) {
return wrapInstance(this, methodName, opts).apply(this, args);
},
enumerable: true
};
};
}
/**
* @private
*
*
* Before calling the original method, ensure Cordova and the plugin are installed.
*/
export function CordovaProperty(target: any, key: string) {
Object.defineProperty(target, key, {
enumerable: true,
get: () => {
if (checkAvailability(target, key) === true) {
return getPlugin(target.constructor.getPluginRef())[key];
} else {
return null;
}
},
set: value => {
if (checkAvailability(target, key) === true) {
getPlugin(target.constructor.getPluginRef())[key] = value;
}
}
});
}
/**
* @private
* @param target
* @param key
* @constructor
*/
export function InstanceProperty(target: any, key: string) {
Object.defineProperty(target, key, {
enumerable: true,
get: function() {
return this._objectInstance[key];
},
set: function(value) {
this._objectInstance[key] = value;
}
});
}
/**
* @private
*
* Wrap a stub function in a call to a Cordova plugin, checking if both Cordova
* and the required plugin are installed.
*/
export function CordovaFunctionOverride(opts: any = {}) {
return (
target: Object,
methodName: string,
descriptor: TypedPropertyDescriptor<any>
) => {
return {
value: function(...args: any[]) {
return overrideFunction(this, methodName, opts);
},
enumerable: true
};
};
}
@@ -0,0 +1,108 @@
import { callCordovaPlugin, wrapPromise } from './common';
declare const window: any;
class MockPlugin {
static getPluginRef(): string {
return 'mockPlugin';
}
static getPluginName(): string {
return 'MockPlugin';
}
static getPluginInstallName(): string {
return '';
}
create(): MockInstancePluginObject {
return new MockInstancePluginObject();
}
}
class MockInstancePluginObject {
_pluginInstance: MockCordovaPlugin;
constructor() {
this._pluginInstance = new MockCordovaPlugin();
}
}
class MockCordovaPlugin {
static ping = jest.fn((arg: string) => 'pong');
static pingAsync = jest.fn(
(arg: string, success: Function, error: Function) => success('pong')
);
ping = jest.fn((arg: string) => 'pong');
pingAsync = jest.fn((arg: string, success: Function, error: Function) =>
success('pong')
);
}
describe('Common decorator functions', () => {
let plugin: MockPlugin, instancePluginObject: MockInstancePluginObject;
beforeAll(() => {
window.mockPlugin = MockCordovaPlugin;
plugin = new MockPlugin();
instancePluginObject = plugin.create();
});
describe('callCordovaPlugin', () => {
test('should return value from cordova plugin', () => {
expect(callCordovaPlugin(plugin, 'ping', ['pingpong'])).toBe('pong');
});
test('original method should have been called', () => {
expect(MockCordovaPlugin.ping.mock.calls.length).toBe(1);
});
test('original method should have received args', () => {
expect(MockCordovaPlugin.ping.mock.calls[0][0]).toBe('pingpong');
});
});
describe('wrapPromise', () => {
test('should return a promise that resolves with a value', async () => {
expect(await wrapPromise(plugin, 'pingAsync', ['pingpong'])).toBe('pong');
});
test('original method should have been called', () => {
expect(MockCordovaPlugin.pingAsync.mock.calls.length).toBe(1);
});
test('original method should have received args', () => {
expect(MockCordovaPlugin.pingAsync.mock.calls[0][0]).toBe('pingpong');
expect(typeof MockCordovaPlugin.pingAsync.mock.calls[0][1]).toBe(
'function'
);
expect(typeof MockCordovaPlugin.pingAsync.mock.calls[0][2]).toBe(
'function'
);
});
});
describe('wrapObservable', () => {
test('should return an observable that emits a value', async () => {});
test('original method should have been called', () => {});
test('original method should have received args', () => {});
});
describe('wrapEventObservable', () => {
test('should return an observable that wraps an event listener', async () => {});
});
describe('callInstance', () => {
test('should call an instance method', async () => {});
test('original method should have been called', () => {
// expect(instancePluginObject._pluginInstance.ping.mock.calls.length).toBe(1);
});
test('original method should have received args', () => {
// expect(instancePluginObject._pluginInstance.ping.mock.calls[0][0]).toBe('pingpong');
});
});
});
@@ -1,179 +1,50 @@
import { Observable } from 'rxjs/Observable';
import { fromEvent } from 'rxjs/observable/fromEvent';
import { Observable, fromEvent } from 'rxjs';
import { checkReady } from './bootstrap';
import { CordovaOptions } from './decorators';
import { cordovaWarn, getPlugin, getPromise, pluginWarn } from './util';
import { CordovaOptions } from './interfaces';
checkReady();
// declare const window;
// declare var Promise;
declare const window: any;
export const ERR_CORDOVA_NOT_AVAILABLE = { error: 'cordova_not_available' };
export const ERR_PLUGIN_NOT_INSTALLED = { error: 'plugin_not_installed' };
/**
* Checks if plugin/cordova is available
* @return {boolean | { error: string } }
* @private
*/
export function checkAvailability(
pluginRef: string,
methodName?: string,
pluginName?: string
): boolean | { error: string };
export function checkAvailability(
pluginObj: any,
methodName?: string,
pluginName?: string
): boolean | { error: string };
export function checkAvailability(
plugin: any,
methodName?: string,
pluginName?: string
): boolean | { error: string } {
let pluginRef, pluginInstance, pluginPackage;
if (typeof plugin === 'string') {
pluginRef = plugin;
} else {
pluginRef = plugin.constructor.getPluginRef();
pluginName = plugin.constructor.getPluginName();
pluginPackage = plugin.constructor.getPluginInstallName();
}
pluginInstance = getPlugin(pluginRef);
if (
!pluginInstance ||
(!!methodName && typeof pluginInstance[methodName] === 'undefined')
) {
if (!window.cordova) {
cordovaWarn(pluginName, methodName);
return ERR_CORDOVA_NOT_AVAILABLE;
}
pluginWarn(pluginName, pluginPackage, methodName);
return ERR_PLUGIN_NOT_INSTALLED;
}
return true;
}
/**
* Checks if _objectInstance exists and has the method/property
* @private
*/
export function instanceAvailability(
pluginObj: any,
methodName?: string
): boolean {
return (
pluginObj._objectInstance &&
(!methodName ||
typeof pluginObj._objectInstance[methodName] !== 'undefined')
);
}
function setIndex(
args: any[],
opts: any = {},
resolve?: Function,
reject?: Function
): any {
// ignore resolve and reject in case sync
if (opts.sync) {
return args;
}
// If the plugin method expects myMethod(success, err, options)
if (opts.callbackOrder === 'reverse') {
// Get those arguments in the order [resolve, reject, ...restOfArgs]
args.unshift(reject);
args.unshift(resolve);
} else if (opts.callbackStyle === 'node') {
args.push((err: any, result: any) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
} else if (
opts.callbackStyle === 'object' &&
opts.successName &&
opts.errorName
) {
let obj: any = {};
obj[opts.successName] = resolve;
obj[opts.errorName] = reject;
args.push(obj);
} else if (
typeof opts.successIndex !== 'undefined' ||
typeof opts.errorIndex !== 'undefined'
) {
const setSuccessIndex = () => {
// If we've specified a success/error index
if (opts.successIndex > args.length) {
args[opts.successIndex] = resolve;
} else {
args.splice(opts.successIndex, 0, resolve);
}
};
const setErrorIndex = () => {
// We don't want that the reject cb gets spliced into the position of an optional argument that has not been defined and thus causing non expected behaviour.
if (opts.errorIndex > args.length) {
args[opts.errorIndex] = reject; // insert the reject fn at the correct specific index
} else {
args.splice(opts.errorIndex, 0, reject); // otherwise just splice it into the array
}
};
if (opts.successIndex > opts.errorIndex) {
setErrorIndex();
setSuccessIndex();
export function getPromise<T>(
callback: (resolve: Function, reject?: Function) => any
): Promise<T> {
const tryNativePromise = () => {
if (Promise) {
return new Promise<T>((resolve, reject) => {
callback(resolve, reject);
});
} else {
setSuccessIndex();
setErrorIndex();
console.error(
'No Promise support or polyfill found. To enable Ionic Native support, please add the es6-promise polyfill before this script, or run with a library like Angular or on a recent browser.'
);
}
} else {
// Otherwise, let's tack them on to the end of the argument list
// which is 90% of cases
args.push(resolve);
args.push(reject);
};
if (window.angular) {
const injector = window.angular
.element(document.querySelector('[ng-app]') || document.body)
.injector();
if (injector) {
const $q = injector.get('$q');
return $q((resolve: Function, reject: Function) => {
callback(resolve, reject);
});
}
console.warn(
`Angular 1 was detected but $q couldn't be retrieved. This is usually when the app is not bootstrapped on the html or body tag. Falling back to native promises which won't trigger an automatic digest when promises resolve.`
);
}
return args;
return tryNativePromise();
}
function callCordovaPlugin(
export function wrapPromise(
pluginObj: any,
methodName: string,
args: any[],
opts: any = {},
resolve?: Function,
reject?: Function
) {
// Try to figure out where the success/error callbacks need to be bound
// to our promise resolve/reject handlers.
args = setIndex(args, opts, resolve, reject);
const availabilityCheck = checkAvailability(pluginObj, methodName);
if (availabilityCheck === true) {
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
return pluginInstance[methodName].apply(pluginInstance, args);
} else {
return availabilityCheck;
}
}
function wrapPromise(
pluginObj: any,
methodName: string,
args: any[],
opts: any = {}
opts: CordovaOptions = {}
) {
let pluginResult: any, rej: Function;
const p = getPromise((resolve: Function, reject: Function) => {
@@ -288,7 +159,176 @@ function wrapObservable(
});
}
function callInstance(
/**
* Wrap the event with an observable
* @private
* @param event even name
* @param element The element to attach the event listener to
* @returns {Observable}
*/
function wrapEventObservable(event: string, element: any): Observable<any> {
element = element ? get(window, element) : window;
return fromEvent(element, event);
}
/**
* Checks if plugin/cordova is available
* @return {boolean | { error: string } }
* @private
*/
export function checkAvailability(
pluginRef: string,
methodName?: string,
pluginName?: string
): boolean | { error: string };
export function checkAvailability(
pluginObj: any,
methodName?: string,
pluginName?: string
): boolean | { error: string };
export function checkAvailability(
plugin: any,
methodName?: string,
pluginName?: string
): boolean | { error: string } {
let pluginRef, pluginInstance, pluginPackage;
if (typeof plugin === 'string') {
pluginRef = plugin;
} else {
pluginRef = plugin.constructor.getPluginRef();
pluginName = plugin.constructor.getPluginName();
pluginPackage = plugin.constructor.getPluginInstallName();
}
pluginInstance = getPlugin(pluginRef);
if (
!pluginInstance ||
(!!methodName && typeof pluginInstance[methodName] === 'undefined')
) {
if (!window.cordova) {
cordovaWarn(pluginName, methodName);
return ERR_CORDOVA_NOT_AVAILABLE;
}
pluginWarn(pluginName, pluginPackage, methodName);
return ERR_PLUGIN_NOT_INSTALLED;
}
return true;
}
/**
* Checks if _objectInstance exists and has the method/property
* @private
*/
export function instanceAvailability(
pluginObj: any,
methodName?: string
): boolean {
return (
pluginObj._objectInstance &&
(!methodName ||
typeof pluginObj._objectInstance[methodName] !== 'undefined')
);
}
export function setIndex(
args: any[],
opts: any = {},
resolve?: Function,
reject?: Function
): any {
// ignore resolve and reject in case sync
if (opts.sync) {
return args;
}
// If the plugin method expects myMethod(success, err, options)
if (opts.callbackOrder === 'reverse') {
// Get those arguments in the order [resolve, reject, ...restOfArgs]
args.unshift(reject);
args.unshift(resolve);
} else if (opts.callbackStyle === 'node') {
args.push((err: any, result: any) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
} else if (
opts.callbackStyle === 'object' &&
opts.successName &&
opts.errorName
) {
const obj: any = {};
obj[opts.successName] = resolve;
obj[opts.errorName] = reject;
args.push(obj);
} else if (
typeof opts.successIndex !== 'undefined' ||
typeof opts.errorIndex !== 'undefined'
) {
const setSuccessIndex = () => {
// If we've specified a success/error index
if (opts.successIndex > args.length) {
args[opts.successIndex] = resolve;
} else {
args.splice(opts.successIndex, 0, resolve);
}
};
const setErrorIndex = () => {
// We don't want that the reject cb gets spliced into the position of an optional argument that has not been
// defined and thus causing non expected behavior.
if (opts.errorIndex > args.length) {
args[opts.errorIndex] = reject; // insert the reject fn at the correct specific index
} else {
args.splice(opts.errorIndex, 0, reject); // otherwise just splice it into the array
}
};
if (opts.successIndex > opts.errorIndex) {
setErrorIndex();
setSuccessIndex();
} else {
setSuccessIndex();
setErrorIndex();
}
} else {
// Otherwise, let's tack them on to the end of the argument list
// which is 90% of cases
args.push(resolve);
args.push(reject);
}
return args;
}
export function callCordovaPlugin(
pluginObj: any,
methodName: string,
args: any[],
opts: any = {},
resolve?: Function,
reject?: Function
) {
// Try to figure out where the success/error callbacks need to be bound
// to our promise resolve/reject handlers.
args = setIndex(args, opts, resolve, reject);
const availabilityCheck = checkAvailability(pluginObj, methodName);
if (availabilityCheck === true) {
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
return pluginInstance[methodName].apply(pluginInstance, args);
} else {
return availabilityCheck;
}
}
export function callInstance(
pluginObj: any,
methodName: string,
args: any[],
@@ -306,60 +346,84 @@ function callInstance(
}
}
/**
* Wrap the event with an observable
* @private
* @param event even name
* @param element The element to attach the event listener to
* @returns {Observable}
*/
export function wrapEventObservable(
event: string,
element: any = window
): Observable<any> {
return fromEvent(element, event);
export function getPlugin(pluginRef: string): any {
return get(window, pluginRef);
}
/**
* Certain plugins expect the user to override methods in the plugin. For example,
* window.cordova.plugins.backgroundMode.onactivate = function() { ... }.
*
* Unfortunately, this is brittle and would be better wrapped as an Observable. overrideFunction
* does just this.
* @private
*/
export function overrideFunction(
pluginObj: any,
methodName: string,
args: any[],
opts: any = {}
): Observable<any> {
return new Observable(observer => {
const availabilityCheck = checkAvailability(
pluginObj,
null,
pluginObj.constructor.getPluginName()
);
if (availabilityCheck === true) {
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
pluginInstance[methodName] = observer.next.bind(observer);
return () => (pluginInstance[methodName] = () => {});
} else {
observer.error(availabilityCheck);
observer.complete();
export function get(element: Element | Window, path: string) {
const paths: string[] = path.split('.');
let obj: any = element;
for (let i = 0; i < paths.length; i++) {
if (!obj) {
return null;
}
});
obj = obj[paths[i]];
}
return obj;
}
export function pluginWarn(
pluginName: string,
plugin?: string,
method?: string
): void {
if (method) {
console.warn(
'Native: tried calling ' +
pluginName +
'.' +
method +
', but the ' +
pluginName +
' plugin is not installed.'
);
} else {
console.warn(
`Native: tried accessing the ${pluginName} plugin but it's not installed.`
);
}
if (plugin) {
console.warn(
`Install the ${pluginName} plugin: 'ionic cordova plugin add ${plugin}'`
);
}
}
/**
* @private
* @param pluginName
* @param method
*/
export const wrap = function(
export function cordovaWarn(pluginName: string, method?: string): void {
if (method) {
console.warn(
'Native: tried calling ' +
pluginName +
'.' +
method +
', but Cordova is not available. Make sure to include cordova.js or run in a device/simulator'
);
} else {
console.warn(
'Native: tried accessing the ' +
pluginName +
' plugin but Cordova is not available. Make sure to include cordova.js or run in a device/simulator'
);
}
}
// Fixes a bug in TypeScript 2.9.2 where the ...args is being converted into args: {} and
// causing compilation issues
export type WrapFn = (...args: any[]) => any;
/**
* @private
*/
export const wrap = (
pluginObj: any,
methodName: string,
opts: CordovaOptions = {}
) {
): WrapFn => {
return (...args: any[]) => {
if (opts.sync) {
// Sync doesn't wrap the plugin with a promise or observable, it returns the result as-is
@@ -383,7 +447,7 @@ export function wrapInstance(
pluginObj: any,
methodName: string,
opts: any = {}
) {
): Function {
return (...args: any[]) => {
if (opts.sync) {
return callInstance(pluginObj, methodName, args, opts);
@@ -413,7 +477,6 @@ export function wrapInstance(
if (pluginResult && pluginResult.error) {
observer.error(pluginResult.error);
observer.complete();
}
return () => {
@@ -461,7 +524,7 @@ export function wrapInstance(
reject
);
}
if (result && !!result.then) {
if (result && result.then) {
result.then(resolve, reject);
} else {
reject();
@@ -0,0 +1,25 @@
import { Observable, Observer } from 'rxjs';
import { checkAvailability, getPlugin } from './common';
function overrideFunction(pluginObj: any, methodName: string): Observable<any> {
return new Observable((observer: Observer<any>) => {
const availabilityCheck = checkAvailability(pluginObj, methodName);
if (availabilityCheck === true) {
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
pluginInstance[methodName] = observer.next.bind(observer);
return () => (pluginInstance[methodName] = () => {});
} else {
observer.error(availabilityCheck);
observer.complete();
}
});
}
export function cordovaFunctionOverride(
pluginObj: any,
methodName: string,
args: IArguments | any[] = []
) {
return overrideFunction(pluginObj, methodName);
}
@@ -0,0 +1,7 @@
import { wrapInstance } from './common';
import { CordovaOptions } from './interfaces';
export function cordovaInstance(pluginObj: any, methodName: string, config: CordovaOptions, args: IArguments | any[]) {
args = Array.from(args);
return wrapInstance(pluginObj, methodName, config).apply(this, args);
}
@@ -0,0 +1,14 @@
import { checkAvailability, getPlugin } from './common';
export function cordovaPropertyGet(pluginObj: any, key: string) {
if (checkAvailability(pluginObj, key) === true) {
return getPlugin(pluginObj.constructor.getPluginRef())[key];
}
return null;
}
export function cordovaPropertySet(pluginObj: any, key: string, value: any) {
if (checkAvailability(pluginObj, key) === true) {
getPlugin(pluginObj.constructor.getPluginRef())[key] = value;
}
}
@@ -0,0 +1,6 @@
import { wrap } from './common';
import { CordovaOptions } from './interfaces';
export function cordova(pluginObj: any, methodName: string, config: CordovaOptions, args: IArguments | any[]) {
return wrap(pluginObj, methodName, config).apply(this, args);
}
@@ -0,0 +1,12 @@
export function instancePropertyGet(pluginObj: any, key: string) {
if (pluginObj._objectInstance && pluginObj._objectInstance[key]) {
return pluginObj._objectInstance[key];
}
return null;
}
export function instancePropertySet(pluginObj: any, key: string, value: any) {
if (pluginObj._objectInstance) {
pluginObj._objectInstance[key] = value;
}
}
@@ -0,0 +1,107 @@
export interface PluginConfig {
/**
* Plugin name, this should match the class name
*/
pluginName: string;
/**
* Plugin NPM package name
*/
plugin: string;
/**
* Plugin object reference
*/
pluginRef?: string;
/**
* Github repository URL
*/
repo?: string;
/**
* Custom install command
*/
install?: string;
/**
* Available installation variables
*/
installVariables?: string[];
/**
* Supported platforms
*/
platforms?: string[];
[key: string]: any;
}
export interface CordovaOptions {
destruct?: boolean;
/**
* Set to true if the wrapped method is a sync function
*/
sync?: boolean;
/**
* Callback order. Set to reverse if the success/error callbacks are the first 2 arguments that the wrapped method
* takes.
*/
callbackOrder?: 'reverse';
/**
* Callback style
*/
callbackStyle?: 'node' | 'object';
/**
* Set a custom index for the success callback function. This doesn't work if callbackOrder or callbackStyle are set.
*/
successIndex?: number;
/**
* Set a custom index for the error callback function. This doesn't work if callbackOrder or callbackStyle are set.
*/
errorIndex?: number;
/**
* Success function property name. This must be set if callbackStyle is set to object.
*/
successName?: string;
/**
* Error function property name. This must be set if callbackStyle is set to object.
*/
errorName?: string;
/**
* Set to true to return an observable
*/
observable?: boolean;
/**
* If observable is set to true, this can be set to a different function name that will cancel the observable.
*/
clearFunction?: string;
/**
* This can be used if clearFunction is set. Set this to true to call the clearFunction with the same arguments used
* in the initial function.
*/
clearWithArgs?: boolean;
/**
* Creates an observable that wraps a global event. Replaces document.addEventListener
*/
eventObservable?: boolean;
/**
* Event name, this must be set if eventObservable is set to true
*/
event?: string;
/**
* Element to attach the event listener to, this is optional, defaults to `window`
*/
element?: any;
/**
* Set to true if the wrapped method returns a promise
*/
otherPromise?: boolean;
/**
* Supported platforms
*/
platforms?: string[];
}
export declare const Plugin: (config: PluginConfig) => ClassDecorator;
export declare const Cordova: (config?: CordovaOptions) => MethodDecorator;
export declare const CordovaProperty: () => PropertyDecorator;
export declare const CordovaInstance: (config?: CordovaOptions) => MethodDecorator;
export declare const InstanceProperty: () => PropertyDecorator;
export declare const CordovaCheck: (config?: CordovaOptions) => MethodDecorator;
export declare const InstanceCheck: (config?: CordovaOptions) => MethodDecorator;
export declare const CordovaFunctionOverride: () => MethodDecorator;
+14 -4
View File
@@ -1,4 +1,14 @@
export * from './plugin';
export * from './decorators';
export * from './util';
export * from './ionic-native-plugin';
import { checkReady } from './bootstrap';
export { IonicNativePlugin } from './ionic-native-plugin';
// Decorators
export { checkAvailability, instanceAvailability, wrap, getPromise } from './decorators/common';
export * from './decorators/cordova';
export * from './decorators/cordova-function-override';
export * from './decorators/cordova-instance';
export * from './decorators/cordova-property';
export * from './decorators/instance-property';
export * from './decorators/interfaces';
checkReady();
@@ -1,74 +0,0 @@
// This is to verify that new (FileTransfer.getPlugin)() works
import { CordovaInstance, Plugin } from './decorators';
import { IonicNativePlugin } from './ionic-native-plugin';
import { checkAvailability } from './plugin';
class FT {
hello(): string {
return 'world';
}
}
(window as any).FileTransfer = () => new FT();
@Plugin({
plugin: 'cordova-plugin-file-transfer',
pluginRef: 'FileTransfer',
repo: '',
pluginName: 'FileTransfer'
})
export class FileTransfer extends IonicNativePlugin {
create(): FileTransferObject {
let instance: any;
if (
checkAvailability(
FileTransfer.getPluginRef(),
null,
FileTransfer.getPluginName()
) === true
) {
instance = new (FileTransfer.getPlugin())();
}
return new FileTransferObject(instance);
}
}
export class FileTransferObject {
constructor(public _objectInstance: any) {
console.info(
'Creating a new FileTransferObject with instance: ',
_objectInstance
);
}
@CordovaInstance({ sync: true })
hello(): string {
return;
}
}
describe('Mock FileTransfer Plugin', () => {
let plugin: FileTransfer, instance: FileTransferObject;
beforeAll(() => {
plugin = new FileTransfer();
instance = plugin.create();
});
it('should create a new FileTransfer plugin instance', () => {
expect(plugin instanceof FileTransfer).toBeTruthy();
});
it('should create new FileTransferObject instance', () => {
expect(instance instanceof FileTransferObject).toBeTruthy();
});
it('FileTransferObject instance should have _objectInstance property', () => {
expect(instance._objectInstance).toBeDefined();
});
it('FileTransferObject.hello should return world', () => {
console.info('instance hello is', instance.hello());
expect(instance.hello()).toEqual('world');
});
});
+10 -16
View File
@@ -1,3 +1,6 @@
import { checkAvailability } from './decorators/common';
import { get } from './util';
export class IonicNativePlugin {
static pluginName: string;
@@ -15,40 +18,31 @@ export class IonicNativePlugin {
* Returns a boolean that indicates whether the plugin is installed
* @return {boolean}
*/
static installed(): boolean {
return false;
}
static installed(): boolean { return checkAvailability(this.pluginRef) === true; }
/**
* Returns the original plugin object
*/
static getPlugin(): any {}
static getPlugin(): any { return get(window, this.pluginRef); }
/**
* Returns the plugin's name
*/
static getPluginName(): string {
return;
}
static getPluginName(): string { return this.pluginName; }
/**
* Returns the plugin's reference
*/
static getPluginRef(): string {
return;
}
static getPluginRef(): string { return this.pluginRef; }
/**
* Returns the plugin's install name
*/
static getPluginInstallName(): string {
return;
}
static getPluginInstallName(): string { return this.plugin; }
/**
* Returns the plugin's supported platforms
*/
static getSupportedPlatforms(): string[] {
return;
}
static getSupportedPlatforms(): string[] { return this.platforms || []; }
}
+27
View File
@@ -0,0 +1,27 @@
declare const window: any;
/**
* Initialize the ionic.native Angular module if we're running in ng1.
* This iterates through the list of registered plugins and dynamically
* creates Angular 1 services of the form $cordovaSERVICE, ex: $cordovaStatusBar.
*/
export function initAngular1(plugins: any) {
if (window.angular) {
const ngModule = window.angular.module('ionic.native', []);
for (const name in plugins) {
const serviceName = '$cordova' + name;
const cls = plugins[name];
((serviceName, cls, name) => {
ngModule.service(serviceName, [
() => {
const funcs = window.angular.copy(cls);
funcs.__proto__['name'] = name;
return funcs;
}
]);
})(serviceName, cls, name);
}
}
}
+8 -71
View File
@@ -3,25 +3,24 @@ declare const window: any;
/**
* @private
*/
export const get = (element: Element | Window, path: string): any => {
export function get(element: Element | Window, path: string) {
const paths: string[] = path.split('.');
let obj: any = element;
for (let i: number = 0; i < paths.length; i++) {
if (!obj) {
return null;
}
for (let i = 0; i < paths.length; i++) {
if (!obj) { return null; }
obj = obj[paths[i]];
}
return obj;
};
}
/**
* @private
*/
export const getPromise = (callback: Function): Promise<any> => {
export function getPromise(callback: Function = () => {}): Promise<any> {
const tryNativePromise = () => {
if (window.Promise) {
return new Promise((resolve, reject) => {
return new Promise<any>((resolve, reject) => {
callback(resolve, reject);
});
} else {
@@ -32,66 +31,4 @@ export const getPromise = (callback: Function): Promise<any> => {
};
return tryNativePromise();
};
/**
* @private
* @param pluginRef
* @returns {null|*}
*/
export const getPlugin = (pluginRef: string): any => {
return get(window, pluginRef);
};
/**
* @private
*/
export const pluginWarn = (
pluginName: string,
plugin?: string,
method?: string
): void => {
if (method) {
console.warn(
'Ionic Native: tried calling ' +
pluginName +
'.' +
method +
', but the ' +
pluginName +
' plugin is not installed.'
);
} else {
console.warn(
`'Ionic Native: tried accessing the ${pluginName} plugin but it's not installed.`
);
}
if (plugin) {
console.warn(
`Install the ${pluginName} plugin: 'ionic cordova plugin add ${plugin}'`
);
}
};
/**
* @private
* @param pluginName
* @param method
*/
export const cordovaWarn = (pluginName: string, method?: string): void => {
if (method) {
console.warn(
'Ionic Native: tried calling ' +
pluginName +
'.' +
method +
', but Cordova is not available. Make sure to a) run in a real device or simulator and b) include cordova.js in your index.html'
);
} else {
console.warn(
'Native: tried accessing the ' +
pluginName +
' plugin but Cordova is not available. Make sure to a) run in a real device or simulator and b) include cordova.js in your index.html'
);
}
};
}
+7 -7
View File
@@ -21,12 +21,12 @@ export interface TextCaptureOptions {
* for example: ["English", "French", "German"]. Empty array
* disables language selection.
*/
selectableRecognitionLanguages?: Array<string>;
selectableRecognitionLanguages?: string[];
/**
* Recognition language selected by default.
*/
recognitionLanguages?: Array<string>;
recognitionLanguages?: string[];
/**
* Width and height of the recognition area, separated by a
@@ -75,7 +75,7 @@ export interface TextCaptureResult {
* · rect (string): position and size of the bounding rectangle,
* a string of 4 integers separated with whitespaces ("x y width height").
*/
textLines: Array<{ text: string, quadrangle: string, rect?: string }>;
textLines: { text: string, quadrangle: string, rect?: string }[];
/**
* Additional information. This object has the following keys:
@@ -94,7 +94,7 @@ export interface TextCaptureResult {
stabilityStatus: string,
userAction: string,
frameSize: string,
recognitionLanguages: Array<string>
recognitionLanguages: string[]
};
/**
@@ -136,8 +136,8 @@ export interface DataCaptureOptions {
customDataCaptureScenario?: {
name: string,
description: string,
recognitionLanguages: Array<string>,
fields: Array<{ regEx: string }>
recognitionLanguages: string[],
fields: { regEx: string }[]
};
/**
@@ -268,7 +268,7 @@ export interface DataCaptureResult {
*
* @usage
* ```typescript
* import { AbbyyRTR } from '@ionic-native/abbyy-rtr';
* import { AbbyyRTR } from '@ionic-native/abbyy-rtr/ngx';
*
*
* constructor(private abbyyRTR: AbbyyRTR) { }
@@ -62,7 +62,7 @@ export interface ActionSheetOptions {
*
* @usage
* ```typescript
* import { ActionSheet, ActionSheetOptions } from '@ionic-native/action-sheet';
* import { ActionSheet, ActionSheetOptions } from '@ionic-native/action-sheet/ngx';
*
* constructor(private actionSheet: ActionSheet) { }
*
@@ -79,7 +79,7 @@ export interface ActionSheetOptions {
* addDestructiveButtonWithLabel: 'Delete',
* androidTheme: this.actionSheet.ANDROID_THEMES.THEME_HOLO_DARK,
* destructiveButtonLast: true
* };
* }
*
* this.actionSheet.show(options).then((buttonIndex: number) => {
* console.log('Button pressed: ' + buttonIndex);
@@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { fromEvent } from 'rxjs/observable/fromEvent';
import { Observable, fromEvent } from 'rxjs';
export interface AdMobFreeBannerConfig {
/**
@@ -68,12 +67,12 @@ export interface AdMobFreeRewardVideoConfig {
* @name AdMob Free
* @description
* A free, no ad-sharing version of Google AdMob plugin for Cordova.
*
*
* Requires Cordova plugin: `cordova-plugin-admob-free`. For more info, please see the [AdMob Free plugin docs](https://github.com/ratson/cordova-plugin-admob-free).
*
* @usage
* ```typescript
* import { AdMobFree, AdMobFreeBannerConfig } from '@ionic-native/admob-free';
* import { AdMobFree, AdMobFreeBannerConfig } from '@ionic-native/admob-free/ngx';
*
*
* constructor(private admobFree: AdMobFree) { }
@@ -179,7 +178,7 @@ export class AdMobFree extends IonicNativePlugin {
plugin: 'cordova-plugin-admob-free',
pluginRef: 'admob.banner'
})
export class AdMobFreeBanner {
export class AdMobFreeBanner extends IonicNativePlugin {
/**
* Update config
* @param options
@@ -235,7 +234,7 @@ export class AdMobFreeBanner {
plugin: 'cordova-plugin-admob-free',
pluginRef: 'admob.interstitial'
})
export class AdMobFreeInterstitial {
export class AdMobFreeInterstitial extends IonicNativePlugin {
/**
* Update config
* @param options
@@ -282,7 +281,7 @@ export class AdMobFreeInterstitial {
plugin: 'cordova-plugin-admob-free',
pluginRef: 'admob.rewardvideo'
})
export class AdMobFreeRewardVideo {
export class AdMobFreeRewardVideo extends IonicNativePlugin {
/**
* Update config
* @param {AdMobFreeRewardVideoConfig} options Admob reward config
@@ -0,0 +1,94 @@
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable, fromEvent } from 'rxjs';
export type AdUnitIDOption = string | {
android: string;
ios: string;
};
/**
* @name AdMob Plus
* @description
* AdMob Plus is the successor of cordova-plugin-admob-free, which provides a cleaner API and build with modern tools.
*/
@Plugin({
plugin: 'cordova-admob-plus',
pluginName: 'AdMob',
pluginRef: 'admob.banner',
repo: 'https://github.com/admob-plus/admob-plus',
platforms: ['Android', 'iOS']
})
export class Banner {
@Cordova({ otherPromise: true })
hide(): Promise<any> {
return Promise.resolve();
}
@Cordova({ otherPromise: true })
show(opts: { id?: AdUnitIDOption }): Promise<any> {
return Promise.resolve();
}
}
@Plugin({
plugin: 'cordova-admob-plus',
pluginName: 'AdMob',
pluginRef: 'admob.interstitial',
})
export class Interstitial {
@Cordova({ otherPromise: true })
load(opts: { id?: AdUnitIDOption }): Promise<any> {
return Promise.resolve();
}
@Cordova({ otherPromise: true })
show(): Promise<any> {
return Promise.resolve();
}
}
@Plugin({
plugin: 'cordova-admob-plus',
pluginName: 'AdMob',
pluginRef: 'admob.rewardVideo',
})
export class RewardVideo {
@Cordova({ otherPromise: true })
load(opts: { id?: AdUnitIDOption }): Promise<any> {
return Promise.resolve();
}
@Cordova({ otherPromise: true })
show(): Promise<any> {
return Promise.resolve();
}
}
@Plugin({
platforms: ['Android', 'iOS'],
plugin: 'cordova-admob-plus',
pluginName: 'AdMob',
pluginRef: 'admob',
repo: 'https://github.com/admob-plus/admob-plus',
})
@Injectable()
export class AdMob extends IonicNativePlugin {
banner = new Banner();
interstitial = new Interstitial();
rewardVideo = new RewardVideo();
@Cordova({ otherPromise: true })
setAppMuted(value: boolean): Promise<any> {
return Promise.resolve();
}
@Cordova({ otherPromise: true })
setAppVolume(value: number): Promise<any> {
return Promise.resolve();
}
on(event: string): Observable<any> {
return fromEvent(document, event);
}
}
+8 -8
View File
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { Observable } from 'rxjs';
export type AdSize =
| 'SMART_BANNER'
@@ -106,8 +106,8 @@ export interface AdExtras {
* IMPORTANT NOTICE: this plugin takes a percentage out of your earnings if you profit more than $1,000. Read more about this on the plugin's repo. For a completely free alternative, see [AdMobPro Free](../admob-free).
* @usage
* ```typescript
* import { AdMobPro } from '@ionic-native/admob-pro';
* import { Platform } from 'ionic-angular';
* import { AdMobPro } from '@ionic-native/admob-pro/ngx';
* import { Platform } from '@ionic/angular';
*
* constructor(private admob: AdMobPro, private platform: Platform ) { }
*
@@ -275,7 +275,7 @@ export class AdMobPro extends IonicNativePlugin {
@Cordova({
eventObservable: true,
event: 'onAdFailLoad',
element: document
element: 'document'
})
onAdFailLoad(): Observable<any> {
return;
@@ -288,7 +288,7 @@ export class AdMobPro extends IonicNativePlugin {
@Cordova({
eventObservable: true,
event: 'onAdLoaded',
element: document
element: 'document'
})
onAdLoaded(): Observable<any> {
return;
@@ -301,7 +301,7 @@ export class AdMobPro extends IonicNativePlugin {
@Cordova({
eventObservable: true,
event: 'onAdPresent',
element: document
element: 'document'
})
onAdPresent(): Observable<any> {
return;
@@ -314,7 +314,7 @@ export class AdMobPro extends IonicNativePlugin {
@Cordova({
eventObservable: true,
event: 'onAdLeaveApp',
element: document
element: 'document'
})
onAdLeaveApp(): Observable<any> {
return;
@@ -327,7 +327,7 @@ export class AdMobPro extends IonicNativePlugin {
@Cordova({
eventObservable: true,
event: 'onAdDismiss',
element: document
element: 'document'
})
onAdDismiss(): Observable<any> {
return;
+7 -8
View File
@@ -10,12 +10,12 @@ import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
*
* @usage
* ```typescript
* import { AES256 } from '@ionic-native/aes-256';
* import { AES256 } from '@ionic-native/aes-256/ngx';
*
* private secureKey: string;
* private secureIV: string;
*
* constructor(private aes256: AES256) {
*
* constructor(private aes256: AES256) {
* this.generateSecureKeyAndIV(); // To generate the random secureKey and secureIV
* }
*
@@ -34,16 +34,16 @@ import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
* .then(res => console.log('Decrypted Data : ',res))
* .catch((error: any) => console.error(error));
*
*
*
* * this.aes256.generateSecureKey('random password 12345')
* .then(res => console.log('Secure Key : ',res))
* .catch((error: any) => console.error(error));
*
*
*
*
* * this.aes256.generateSecureIV('random password 12345')
* .then(res => console.log('Secure IV : ',res))
* .catch((error: any) => console.error(error));
*
*
* ```
*/
@Plugin({
@@ -56,7 +56,6 @@ import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
})
@Injectable()
export class AES256 extends IonicNativePlugin {
/**
* This function used to perform the aes256 encryption
* @param {string} secureKey A 32 bytes string, which will used as input key for AES256 encryption.
+1 -1
View File
@@ -10,7 +10,7 @@ import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
*
* @usage
* ```typescript
* import { Alipay } from '@ionic-native/alipay';
* import { Alipay } from '@ionic-native/alipay/ngx';
*
* constructor(private alipay: Alipay) {
*
@@ -0,0 +1,248 @@
import { Injectable } from '@angular/core';
import { Cordova, CordovaProperty, IonicNativePlugin, Plugin } from '@ionic-native/core';
/**
* @name Analytics Firebase
* @description
* Google Analytics Firebase plugin for Ionic Native apps.
*
* @usage
* ```typescript
* import { AnalyticsFirebase } from '@ionic-native/analytics-firebase';
*
*
* constructor(private analyticsFirebase: AnalyticsFirebase) { }
*
* // Track an event with default events and params
* const eventParams = {};
* eventParams[this.analyticsFirebase.DEFAULT_PARAMS.LEVEL] = 29;
* this.analyticsFirebase.logEvent(this.analyticsFirebase.DEFAULT_EVENTS.LEVEL_UP, eventParams)
* .then(() => console.log('Event successfully tracked'))
* .catch(err => console.log('Error tracking event:', err));
*
* // Track an event with custom events and params
* const eventParams = {};
* eventParams['my-prop'] = 29;
* this.analyticsFirebase.logEvent('my-event', eventParams)
* .then(() => console.log('Event successfully tracked'))
* .catch(err => console.log('Error tracking event:', err));
*
*
* // Reset analytics data
* this.analyticsFirebase.resetAnalyticsData()
* .then(() => console.log('Analytics data have been reset'))
* .catch(err => console.log('Error resetting analytics data:', err));
*
*
* // Track a screen view
* this.analyticsFirebase.setCurrentScreen('Home')
* .then(() => console.log('View successfully tracked'))
* .catch(err => console.log('Error tracking view:', err));
*
*
* // Set user id
* this.analyticsFirebase.setUserId('USER-ID')
* .then(() => console.log('User id successfully set'))
* .catch(err => console.log('Error setting user id:', err));
*
*
* // Set user property from default properties
* this.analyticsFirebase.setUserProperty('KEY', 'VALUE')
* .then(() => console.log('User property successfully set'))
* .catch(err => console.log('Error setting user property:', err));
*
* ```
*/
@Plugin({
pluginName: 'AnalyticsFirebase',
plugin: 'cordova-plugin-analytics',
pluginRef: 'analytics',
repo: 'https://github.com/appfeel/analytics-google',
platforms: ['Android', 'iOS']
})
@Injectable()
export class AnalyticsFirebase extends IonicNativePlugin {
/**
* This enum represents AnalyticsFirebase default events.
* Use one of these default events or a custom event
* @readonly
*/
@CordovaProperty()
readonly DEFAULT_EVENTS: {
ADD_PAYMENT_INFO: string;
ADD_TO_CART: string;
ADD_TO_WISHLIST: string;
APP_OPEN: string;
BEGIN_CHECKOUT: string;
CAMPAIGN_DETAILS: string;
CHECKOUT_PROGRESS: string;
EARN_VIRTUAL_CURRENCY: string;
ECOMMERCE_PURCHASE: string;
GENERATE_LEAD: string;
JOIN_GROUP: string;
LEVEL_END: string;
LEVEL_START: string;
LEVEL_UP: string;
LOGIN: string;
POST_SCORE: string;
PRESENT_OFFER: string;
PURCHASE_REFUND: string;
REMOVE_FROM_CART: string;
SEARCH: string;
SELECT_CONTENT: string;
SET_CHECKOUT_OPTION: string;
SHARE: string;
SIGN_UP: string;
SPEND_VIRTUAL_CURRENCY: string;
TUTORIAL_BEGIN: string;
TUTORIAL_COMPLETE: string;
UNLOCK_ACHIEVEMENT: string;
VIEW_ITEM: string;
VIEW_ITEM_LIST: string;
VIEW_SEARCH_RESULTS: string;
};
/**
* This enum represents AnalyticsFirebase default params.
* Use one of these default params or a custom param
* @readonly
*/
@CordovaProperty()
readonly DEFAULT_PARAMS: {
ACHIEVEMENT_ID: string;
ACLID: string;
AFFILIATION: string;
CAMPAIGN: string;
CHARACTER: string;
CHECKOUT_OPTION: string;
CHECKOUT_STEP: string;
CONTENT: string;
CONTENT_TYPE: string;
COUPON: string;
CP1: string;
CREATIVE_NAME: string;
CREATIVE_SLOT: string;
CURRENCY: string;
DESTINATION: string;
END_DATE: string;
FLIGHT_NUMBER: string;
GROUP_ID: string;
INDEX: string;
ITEM_BRAND: string;
ITEM_CATEGORY: string;
ITEM_ID: string;
ITEM_LIST: string;
ITEM_LOCATION_ID: string;
ITEM_NAME: string;
ITEM_VARIANT: string;
LEVEL: string;
LEVEL_NAME: string;
LOCATION: string;
MEDIUM: string;
METHOD: string;
NUMBER_OF_NIGHTS: string;
NUMBER_OF_PASSENGERS: string;
NUMBER_OF_ROOMS: string;
ORIGIN: string;
PRICE: string;
QUANTITY: string;
SCORE: string;
SEARCH_TERM: string;
SHIPPING: string;
SOURCE: string;
START_DATE: string;
SUCCESS: string;
TAX: string;
TERM: string;
TRANSACTION_ID: string;
TRAVEL_CLASS: string;
VALUE: string;
VIRTUAL_CURRENCY_NAME: string;
};
/**
* Logs an app event. The event can have up to 25 parameters.
* Events with the same name must have the same parameters.
* Up to 500 event names are supported.
* Using predefined [FirebaseAnalytics.Event](https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html) and/or [FirebaseAnalytics.Param](https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Param.html) is recommended for optimal reporting.
*
* @param eventName {string} The event name
* @param eventParams {object} (Optional) The event params
* @return {Promise<any>} Returns a promise that resolves when the event is logged
*/
@Cordova()
logEvent(eventName: string, eventParams?: object): Promise<any> {
return;
}
/**
* Clears all analytics data for this app from the device and resets the app instance id
* @return {Promise<any>} Returns a promise that resolves when the analytics data is cleared
*/
@Cordova()
resetAnalyticsData(): Promise<any> {
return;
}
/**
* Sets whether analytics collection is enabled for this app on this device. This setting is persisted across app sessions. By default it is enabled
* @param screenName {boolean} The value of the collection
* @return {Promise<any>} Returns a promise that resolves when the collection is enabled/disabled
*/
@Cordova()
setAnalyticsCollectionEnabled(enabled: boolean): Promise<any> {
return;
}
/**
* Sets the current screen name, which specifies the current visual context in your app.
* This helps identify the areas in your app where users spend their time and how they interact with your app
* @param screenName {string} The screen name
* @return {Promise<any>} Returns a promise that resolves when the current screen is setted
*/
@Cordova()
setCurrentScreen(screenName: string): Promise<any> {
return;
}
/**
* Sets the minimum engagement time required before starting a session. The default value is 10000 (10 seconds)
* @param screenName {number} The duration in milliseconds
* @return {Promise<any>} Returns a promise that resolves when the minimum session duration is set
*/
@Cordova()
setMinimumSessionDuration(milliseconds: number): Promise<any> {
return;
}
/**
* Sets the duration of inactivity that terminates the current session. The default value is 1800000 (30 minutes)
* @param screenName {number} The duration in milliseconds
* @return {Promise<any>} Returns a promise that resolves when the session timeout duration is set
*/
@Cordova()
setSessionTimeoutDuration(milliseconds: number): Promise<any> {
return;
}
/**
* Sets the user ID property. This feature must be used in accordance with Google's Privacy Policy
* @param userId {string} The user id
* @return {Promise<any>} Returns a promise that resolves when the user id is setted
*/
@Cordova()
setUserId(userId: string): Promise<any> {
return;
}
/**
* Sets a user property to a given value. Up to 25 user property names are supported. Once set, user property values persist throughout the app lifecycle and across sessions
* @param userPropertyName {string} The user property name
* @param userPropertyValue {string} The user property value
* @return {Promise<any>} Returns a promise that resolves when the user property setted
*/
@Cordova()
setUserProperty(userPropertyName: string, userPropertyValue: string): Promise<any> {
return;
}
}
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { Observable } from 'rxjs';
export type AndroidExoPlayerAspectRatio = 'FILL_SCREEN' | 'FIT_SCREEN';
@@ -158,7 +158,7 @@ export interface AndroidExoPlayerControllerConfig {
*
* @usage
* ```typescript
* import { AndroidExoPlayer } from '@ionic-native/android-exoplayer';
* import { AndroidExoPlayer } from '@ionic-native/android-exoplayer/ngx';
*
* constructor(private androidExoPlayer: AndroidExoPlayer) { }
*
@@ -110,7 +110,7 @@ export interface AFADeleteOptions {
* This plugin will open a native dialog fragment prompting the user to authenticate using their fingerprint. If the device has a secure lockscreen (pattern, PIN, or password), the user may opt to authenticate using that method as a backup.
* @usage
* ```typescript
* import { AndroidFingerprintAuth } from '@ionic-native/android-fingerprint-auth';
* import { AndroidFingerprintAuth } from '@ionic-native/android-fingerprint-auth/ngx';
*
* constructor(private androidFingerprintAuth: AndroidFingerprintAuth) { }
*
@@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { Cordova, Plugin, IonicNativePlugin } from '@ionic-native/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
/**
* Bit flag values for setSystemUiVisibility()
* @see https://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int)
* @see https://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int)
*/
export enum AndroidSystemUiFlags {
/** View has requested the system UI (status bar) to be visible (the default). SYSTEM_UI_FLAG_VISIBLE */
@@ -36,7 +36,7 @@ export enum AndroidSystemUiFlags {
* In Android 4.4+, however, you can now enter true full screen, fully interactive immersive mode. In this mode, your app will remain in true full screen until you choose otherwise; users can swipe down from the top of the screen to temporarily display the system UI.
* @usage
* ```typescript
* import { AndroidFullScreen } from '@ionic-native/android-full-screen';
* import { AndroidFullScreen } from '@ionic-native/android-full-screen/ngx';
*
* constructor(private androidFullScreen: AndroidFullScreen) { }
*
@@ -62,63 +62,81 @@ export class AndroidFullScreen extends IonicNativePlugin {
* @return {Promise<void>}
*/
@Cordova()
isSupported(): Promise<void> { return; }
isSupported(): Promise<void> {
return;
}
/**
* Is immersive mode supported?
* @return {Promise<void>}
*/
@Cordova()
isImmersiveModeSupported(): Promise<void> { return; }
isImmersiveModeSupported(): Promise<void> {
return;
}
/**
* The width of the screen in immersive mode.
* @return {Promise<number>}
*/
@Cordova()
immersiveWidth(): Promise<number> { return; }
immersiveWidth(): Promise<number> {
return;
}
/**
* The height of the screen in immersive mode.
* @return {Promise<number>}
*/
@Cordova()
immersiveHeight(): Promise<number> { return; }
immersiveHeight(): Promise<number> {
return;
}
/**
* Hide system UI until user interacts.
* @return {Promise<void>}
*/
@Cordova()
leanMode(): Promise<void> { return; }
leanMode(): Promise<void> {
return;
}
/**
* Show system UI.
* @return {Promise<void>}
*/
@Cordova()
showSystemUI(): Promise<void> { return; }
showSystemUI(): Promise<void> {
return;
}
/**
* Extend your app underneath the status bar (Android 4.4+ only).
* @return {Promise<void>}
*/
@Cordova()
showUnderStatusBar(): Promise<void> { return; }
showUnderStatusBar(): Promise<void> {
return;
}
/**
* Extend your app underneath the system UI (Android 4.4+ only).
* @return {Promise<void>}
*/
@Cordova()
showUnderSystemUI(): Promise<void> { return; }
showUnderSystemUI(): Promise<void> {
return;
}
/**
* Hide system UI and keep it hidden (Android 4.4+ only).
* @return {Promise<void>}
*/
@Cordova()
immersiveMode(): Promise<void> { return; }
immersiveMode(): Promise<void> {
return;
}
/**
* Manually set the the system UI to a custom mode. This mirrors the Android method of the same name. (Android 4.4+ only).
@@ -127,5 +145,7 @@ export class AndroidFullScreen extends IonicNativePlugin {
* @return {Promise<void>}
*/
@Cordova()
setSystemUiVisibility(visibility: AndroidSystemUiFlags): Promise<void> { return; }
setSystemUiVisibility(visibility: AndroidSystemUiFlags): Promise<void> {
return;
}
}
@@ -10,7 +10,7 @@ import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
*
* @usage
* ```
* import { AndroidPermissions } from '@ionic-native/android-permissions';
* import { AndroidPermissions } from '@ionic-native/android-permissions/ngx';
*
*
* constructor(private androidPermissions: AndroidPermissions) { }
@@ -223,7 +223,7 @@ export class AndroidPermissions extends IonicNativePlugin {
/**
* Request permissions
* @param {Array<string>} permissions An array with permissions
* @param {string[]} permissions An array with permissions
* @return {Promise<any>} Returns a promise
*/
@Cordova()
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { Cordova, Plugin, IonicNativePlugin } from '@ionic-native/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
/**
* @name App Availability
@@ -10,7 +10,7 @@ import { Cordova, Plugin, IonicNativePlugin } from '@ionic-native/core';
*
* @usage
* ```typescript
* import { AppAvailability } from '@ionic-native/app-availability';
* import { AppAvailability } from '@ionic-native/app-availability/ngx';
* import { Platform } from 'ionic-angular';
*
* constructor(private appAvailability: AppAvailability, private platform: Platform) { }
@@ -48,6 +48,8 @@ export class AppAvailability extends IonicNativePlugin {
* @returns {Promise<boolean>}
*/
@Cordova()
check(app: string): Promise<boolean> { return; }
check(app: string): Promise<boolean> {
return;
}
}
@@ -17,7 +17,7 @@ export interface StringMap {
*
* @usage
* ```typescript
* import { AppCenterAnalytics } from '@ionic-native/app-center-analytics';
* import { AppCenterAnalytics } from '@ionic-native/app-center-analytics/ngx';
*
*
* constructor(private appCenterAnalytics: AppCenterAnalytics) { }
@@ -40,7 +40,7 @@ export interface AppCenterCrashReportDevice {
*
* @usage
* ```typescript
* import { AppCenterCrashes } from '@ionic-native/app-center-crashes';
* import { AppCenterCrashes } from '@ionic-native/app-center-crashes/ngx';
*
*
* constructor(private AppCenterCrashes: AppCenterCrashes) { }
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { Observable } from 'rxjs';
/**
* @name App Center Push
@@ -10,7 +10,7 @@ import { Observable } from 'rxjs/Observable';
*
* @usage
* ```typescript
* import { AppCenterPush } from '@ionic-native/app-center-push';
* import { AppCenterPush } from '@ionic-native/app-center-push/ngx';
*
*
* constructor(private appCenterPush: AppCenterPush) { }
@@ -1,4 +1,4 @@
import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Injectable } from '@angular/core';
/**
@@ -8,8 +8,8 @@ import { Injectable } from '@angular/core';
*
* @usage
* ```typescript
* import { Platfrom } from 'ionic-angular';
* import { AppMinimize } from '@ionic-native/app-minimize';
* import { Platfrom } from '@ionic/angular';
* import { AppMinimize } from '@ionic-native/app-minimize/ngx';
*
*
* constructor(private platform: Platform, private appMinimize: AppMinimize) { }
@@ -37,6 +37,8 @@ export class AppMinimize extends IonicNativePlugin {
* @return {Promise<any>}
*/
@Cordova()
minimize(): Promise<any> { return; }
minimize(): Promise<any> {
return;
}
}
@@ -1,5 +1,5 @@
import { Cordova, Plugin, IonicNativePlugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';
/**
@@ -9,7 +9,7 @@ import { Injectable } from '@angular/core';
*
* @usage
* ```typescript
* import { AppPreferences } from '@ionic-native/app-preferences';
* import { AppPreferences } from '@ionic-native/app-preferences/ngx';
*
* constructor(private appPreferences: AppPreferences) { }
*
@@ -25,11 +25,18 @@ import { Injectable } from '@angular/core';
plugin: 'cordova-plugin-app-preferences',
pluginRef: 'plugins.appPreferences',
repo: 'https://github.com/apla/me.apla.cordova.app-preferences',
platforms: ['Android', 'BlackBerry 10', 'Browser', 'iOS', 'macOS', 'Windows 8', 'Windows Phone']
platforms: [
'Android',
'BlackBerry 10',
'Browser',
'iOS',
'macOS',
'Windows 8',
'Windows Phone'
]
})
@Injectable()
export class AppPreferences extends IonicNativePlugin {
/**
* Get a preference value
*
@@ -40,7 +47,9 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
callbackOrder: 'reverse'
})
fetch(dict: string, key?: string): Promise<any> { return; }
fetch(dict: string, key?: string): Promise<any> {
return;
}
/**
* Set a preference value
@@ -67,7 +76,9 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
callbackOrder: 'reverse'
})
remove(dict: string, key?: string): Promise<any> { return; }
remove(dict: string, key?: string): Promise<any> {
return;
}
/**
* Clear preferences
@@ -77,7 +88,9 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
callbackOrder: 'reverse'
})
clearAll(): Promise<any> { return; }
clearAll(): Promise<any> {
return;
}
/**
* Show native preferences interface
@@ -87,7 +100,9 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
callbackOrder: 'reverse'
})
show(): Promise<any> { return; }
show(): Promise<any> {
return;
}
/**
* Show native preferences interface
@@ -98,7 +113,9 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
observable: true
})
watch(subscribe: boolean): Observable<any> { return; }
watch(subscribe: boolean): Observable<any> {
return;
}
/**
* Return named configuration context
@@ -111,13 +128,17 @@ export class AppPreferences extends IonicNativePlugin {
platforms: ['Android'],
sync: true
})
suite(suiteName: string): any { return; }
suite(suiteName: string): any {
return;
}
@Cordova({
platforms: ['iOS'],
sync: true
})
iosSuite(suiteName: string): any { return; }
iosSuite(suiteName: string): any {
return;
}
/**
* Return cloud synchronized configuration context
@@ -127,7 +148,9 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
platforms: ['iOS', 'Windows', 'Windows Phone 8']
})
cloudSync(): Object { return; }
cloudSync(): Object {
return;
}
/**
* Return default configuration context
@@ -137,6 +160,7 @@ export class AppPreferences extends IonicNativePlugin {
@Cordova({
platforms: ['iOS', 'Windows', 'Windows Phone 8']
})
defaults(): Object { return; }
defaults(): Object {
return;
}
}
+6 -5
View File
@@ -75,7 +75,7 @@ export interface AppRateCustomLocale {
/** No button label */
noButtonLabel?: string;
/** App rate promt title */
/** App rate prompt title */
appRatePromptTitle?: string;
/** Feedback prompt title */
@@ -134,7 +134,7 @@ export interface AppUrls {
*
* @usage
* ```typescript
* import { AppRate } from '@ionic-native/app-rate';
* import { AppRate } from '@ionic-native/app-rate/ngx';
*
* constructor(private appRate: AppRate) { }
*
@@ -144,7 +144,7 @@ export interface AppUrls {
* ios: '<app_id>',
* android: 'market://details?id=<package_name>',
* windows: 'ms-windows-store://review/?ProductId=<store_id>'
* };
* }
*
* this.appRate.promptForRating(true);
*
@@ -156,7 +156,7 @@ export interface AppUrls {
* android: 'market://details?id=<package_name>',
* windows: 'ms-windows-store://review/?ProductId=<store_id>'
* }
* };
* }
*
* this.appRate.promptForRating(false);
* ```
@@ -181,7 +181,8 @@ export class AppRate extends IonicNativePlugin {
* Configure various settings for the Rating View.
* See table below for options
*/
@CordovaProperty preferences: AppRatePreferences;
@CordovaProperty()
preferences: AppRatePreferences;
/**
* Prompts the user for rating
@@ -26,7 +26,7 @@ export interface AppUpdateOptions {
* Then use the following code:
*
* ```typescript
* import { AppUpdate } from '@ionic-native/app-update';
* import { AppUpdate } from '@ionic-native/app-update/ngx';
*
* constructor(private appUpdate: AppUpdate) {
*
@@ -1,6 +1,5 @@
import { Injectable } from '@angular/core';
import { Cordova, Plugin, IonicNativePlugin } from '@ionic-native/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
/**
@@ -12,7 +11,7 @@ import { Cordova, Plugin, IonicNativePlugin } from '@ionic-native/core';
*
* @usage
* ```typescript
* import { AppVersion } from '@ionic-native/app-version';
* import { AppVersion } from '@ionic-native/app-version/ngx';
*
* constructor(private appVersion: AppVersion) { }
*
+5 -4
View File
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
import { Observable } from 'rxjs';
export type IMakePayments =
| 'This device can make payments and has a supported card'
@@ -71,6 +71,7 @@ export interface IShippingMethod {
detail: string;
amount: number;
}
export interface IOrderItemsAndShippingMethods {
items: IOrderItem[];
shippingMethods?: IShippingMethod[];
@@ -99,7 +100,7 @@ export interface ISelectedShippingContact {
*
* @usage
* ```typescript
* import { ApplePay } from '@ionic-native/apple-pay';
* import { ApplePay } from '@ionic-native/apple-pay/ngx';
*
*
* constructor(private applePay: ApplePay) { }
@@ -237,7 +238,7 @@ export class ApplePay extends IonicNativePlugin {
* this.paySheetItems.shippingCost = {
* label: 'Shipping Cost',
* amount: shippingMethod[0].amount
* };
* }
* this.applePay.updateItemsAndShippingMethods(this.paySheetItems, shippingMethods);
* });
*/
@@ -0,0 +1,116 @@
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
export interface EncryptedCardData {
activationData: string;
encryptedPassData: string;
wrappedKey: string;
}
export interface CardData {
cardholderName: string;
primaryAccountNumberSuffix: string;
localizedDescription?: string;
paymentNetwork: string;
}
/**
* @name Apple Wallet
* @description
* A Cordova plugin that enables users from Add Payment Cards to their Apple Wallet.
*
* @usage
* ```typescript
* import { AppleWallet } from '@ionic-native/apple-wallet/ngx';
*
*
* constructor(private appleWallet: AppleWallet) { }
*
* ...
*
*
* this.appleWallet.available()
* .then((res) => {
* // res is a boolean value, either true or false
* console.log("Is Apple Wallet available? ", res);
* })
* .catch((message) => {
* console.error("ERROR AVAILBLE>> ", message);
* });
*
* ...
*
* let data: cardData = {
* cardholderName: 'Test User',
* primaryAccountNumberSuffix: '1234',
* localizedDescription: 'Description of payment card',
* paymentNetwork: 'VISA'
* }
*
* this.appleWallet.startAddPaymentPass(data: cardData)
* .then((res) => {
* console.log("startAddPaymentPass success response ", res);
* })
* .catch((err) => {
* console.error("startAddPaymentPass ERROR response", err);
* });
*
* ...
*
* let data: encryptedCardData = {
* activationData: 'encoded Base64 activationData from your server',
* encryptedPassData: 'encoded Base64 encryptedPassData from your server',
* wrappedKey: 'encoded Base64 wrappedKey from your server',
* }
*
* this.appleWallet.encryptedCardData(data: encryptedCardData)
* .then((res) => {
* console.log("completeAddCardToAppleWallet success response ", res);
* })
* .catch((err) => {
* console.error("completeAddCardToAppleWallet ERROR response", err);
* });
*
* ```
* @Interfaces
* EncryptedCardData
* CardData
*/
@Plugin({
pluginName: 'AppleWallet',
plugin: 'cordova-apple-wallet',
pluginRef: 'AppleWallet',
repo: 'https://github.com/tomavic/cordova-apple-wallet',
platforms: ['iOS']
})
@Injectable()
export class AppleWallet extends IonicNativePlugin {
/**
* Detects if the current device supports Apple Wallet
* @return {Promise<boolean>} Returns a promise
*/
@Cordova()
available(): Promise<boolean> {
return;
}
/**
* Simple call with the configuration data needed to instantiate a new PKAddPaymentPassViewController object.
* @param {cardData} data
* @return {Promise<any>} Returns a promise
*/
@Cordova()
startAddPaymentPass(data: CardData): Promise<any> {
return;
}
/**
* Simple call contains the card data needed to add a card to Apple Pay.
* @param {encryptedCardData} data
* @return {Promise<any>} Returns a promise
*/
@Cordova()
completeAddPaymentPass(data: EncryptedCardData): Promise<any> {
return;
}
}

Some files were not shown because too many files have changed in this diff Show More