├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── demo
├── .editorconfig
├── .gitignore
├── App_Resources
│ ├── Android
│ │ ├── app.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── background.png
│ │ │ ├── icon.png
│ │ │ └── logo.png
│ │ │ ├── drawable-ldpi
│ │ │ ├── background.png
│ │ │ ├── icon.png
│ │ │ └── logo.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── background.png
│ │ │ ├── icon.png
│ │ │ └── logo.png
│ │ │ ├── drawable-nodpi
│ │ │ └── splash_screen.xml
│ │ │ ├── drawable-xhdpi
│ │ │ ├── background.png
│ │ │ ├── icon.png
│ │ │ └── logo.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── background.png
│ │ │ ├── icon.png
│ │ │ └── logo.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── background.png
│ │ │ ├── icon.png
│ │ │ └── logo.png
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ │ ├── values-v29
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── styles.xml
│ └── iOS
│ │ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── icon-1024.png
│ │ │ ├── icon-20.png
│ │ │ ├── icon-20@2x.png
│ │ │ ├── icon-20@3x.png
│ │ │ ├── icon-29.png
│ │ │ ├── icon-29@2x.png
│ │ │ ├── icon-29@3x.png
│ │ │ ├── icon-40.png
│ │ │ ├── icon-40@2x.png
│ │ │ ├── icon-40@3x.png
│ │ │ ├── icon-60@2x.png
│ │ │ ├── icon-60@3x.png
│ │ │ ├── icon-76.png
│ │ │ ├── icon-76@2x.png
│ │ │ └── icon-83.5@2x.png
│ │ ├── Contents.json
│ │ ├── LaunchImage.launchimage
│ │ │ ├── Contents.json
│ │ │ ├── Default-1125h.png
│ │ │ ├── Default-568h@2x.png
│ │ │ ├── Default-667h@2x.png
│ │ │ ├── Default-736h@3x.png
│ │ │ ├── Default-Landscape-X.png
│ │ │ ├── Default-Landscape-XR.png
│ │ │ ├── Default-Landscape-XS-Max.png
│ │ │ ├── Default-Landscape.png
│ │ │ ├── Default-Landscape@2x.png
│ │ │ ├── Default-Landscape@3x.png
│ │ │ ├── Default-Portrait-XR.png
│ │ │ ├── Default-Portrait-XS-Max.png
│ │ │ ├── Default-Portrait.png
│ │ │ ├── Default-Portrait@2x.png
│ │ │ ├── Default.png
│ │ │ └── Default@2x.png
│ │ ├── LaunchScreen.AspectFill.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchScreen-AspectFill.png
│ │ │ ├── LaunchScreen-AspectFill@2x.png
│ │ │ └── LaunchScreen-AspectFill@3x.png
│ │ └── LaunchScreen.Center.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchScreen-Center.png
│ │ │ ├── LaunchScreen-Center@2x.png
│ │ │ └── LaunchScreen-Center@3x.png
│ │ ├── Info.plist
│ │ ├── LaunchScreen.storyboard
│ │ └── build.xcconfig
├── app
│ ├── app-root.xml
│ ├── app.css
│ ├── app.js
│ ├── encrypted.sqlite
│ ├── icon.sqlite
│ ├── main-page.js
│ ├── main-page.xml
│ ├── name_db.sqlite
│ └── sqlite_syncer.js
├── jsconfig.json
├── nativescript.config.ts
├── package.json
└── webpack.config.js
├── src
├── .npmignore
├── LICENSE
├── README.md
├── changelog
├── contributors.md
├── nativescript.webpack.js
├── package.json
├── platforms
│ └── ios
│ │ ├── build.xcconfig
│ │ └── module.modulemap
├── sqlite-internal.android.js
├── sqlite-internal.ios.js
└── sqlite.js
└── tsconfig.json
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: NathanaelA
2 | patreon: NathanaelA
3 | custom: https://www.paypal.me/MasterTechnology
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.tgz
3 | *.tar
4 | node_modules/
5 | demoos/
6 | *.zip
7 | package-lock.json
8 |
9 | demo/hooks/
10 | demo/platforms/
11 |
12 | demo-sync/
13 | old/
14 | graphics/
15 | encrypted/
16 | commercial/
17 | sync/
18 |
19 | # Commercial Only
20 | sqlite.d.ts
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2019 Nathanael Anderson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Archived Public Repo
2 | See: https://fluentreports.com/blog/?p=1434
3 | - If you want any support, you can purchase it here: https://nativescript.tools/product/10
4 | - If you are already a paid customer please post any issues here: https://git.master-technology.com/nativescript-sqlite/nativescript-sqlite
5 |
6 |
7 |
8 | ## NativeScript-sqlite
9 |
10 |

11 |
12 | ## Developed & Sponsored by
13 | [](https://master.technology)
14 |
15 | ## Documentation
16 | The [documentation](src/README.md) for the plugin is located in the [src folder](src).
17 |
18 |
19 | ## Commercial Options
20 | The [commercial version](https://nativescript.tools/product/10) comes with the following enhancements:
21 | - TypeScript definitions
22 | - Totally backwards compatible with the free version
23 | - Prepared statements
24 | - Multilevel transaction support
25 | - Encryption
26 | - Run multiple queries per call (i.e. get(["select 1", "select 2", "select 3"]))
27 | - **Multi-threading**
28 |
29 | ## Installation
30 | - tns plugin add nativescript-sqlite@latest
31 |
32 | ### Installation of Encrypted Plugin (Provides encryption support)
33 | - tns plugin add nativescript-sqlite-encrypted-1.5.0.tgz
34 |
35 | ### Installation of Commercial Plugin (Provides Transactions, Prepared statements, multiple queries)
36 | - tns plugin add nativescript-sqlite-commercial-1.4.2.tgz
37 |
--------------------------------------------------------------------------------
/demo/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | trim_trailing_whitespace = true
7 | charset = utf-8
8 |
9 | [*.json]
10 | indent_style = space
11 | indent_size = 2
12 |
13 | [*.js]
14 | indent_style = space
15 | indent_size = 2
16 |
17 | [*.ts]
18 | indent_style = space
19 | indent_size = 2
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | # NativeScript
2 | hooks/
3 | node_modules/
4 | platforms/
5 |
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 |
13 | # General
14 | .DS_Store
15 | .AppleDouble
16 | .LSOverride
17 | .idea
18 | .cloud
19 | .project
20 | tmp/
21 | typings/
22 |
23 | app/test.sqlite
24 | app/test2.sqlite
25 | beta-250/
26 |
27 | # Visual Studio Code
28 | .vscode/*
29 | !.vscode/settings.json
30 | !.vscode/tasks.json
31 | !.vscode/launch.json
32 | !.vscode/extensions.json
33 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/app.gradle:
--------------------------------------------------------------------------------
1 | // Add your native dependencies here:
2 |
3 | // Uncomment to add recyclerview-v7 dependency
4 | //dependencies {
5 | // implementation 'com.android.support:recyclerview-v7:+'
6 | //}
7 |
8 | // If you want to add something to be applied before applying plugins' include.gradle files
9 | // e.g. project.ext.googlePlayServicesVersion = "15.0.1"
10 | // create a file named before-plugins.gradle in the current directory and place it there
11 |
12 | android {
13 | defaultConfig {
14 | minSdkVersion 17
15 | generatedDensities = []
16 | }
17 | aaptOptions {
18 | additionalParameters "--no-version-vectors"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-hdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-hdpi/background.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-hdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-hdpi/logo.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-ldpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-ldpi/background.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-ldpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-ldpi/logo.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-mdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-mdpi/background.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-mdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-mdpi/logo.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 |
5 | -
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xhdpi/background.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/values-v21/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3d5afe
4 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
13 |
14 |
15 |
18 |
19 |
20 |
23 |
24 |
28 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/values-v29/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #F5F5F5
4 | #757575
5 | #33B5E5
6 | #272734
7 | #36b115
8 | #960b0b
9 |
10 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/demo/App_Resources/Android/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
21 |
22 |
23 |
31 |
32 |
34 |
35 |
36 |
42 |
43 |
45 |
46 |
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "icon-20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "icon-20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "icon-29.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "icon-29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "icon-29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "icon-40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "icon-40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "icon-60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "icon-60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "icon-20.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "icon-20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "icon-29.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "icon-29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "icon-40.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "icon-40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "icon-76.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "icon-76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "icon-83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "icon-1024.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "2688h",
7 | "filename" : "Default-Portrait-XS-Max.png",
8 | "minimum-system-version" : "12.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "2688h",
16 | "filename" : "Default-Landscape-XS-Max.png",
17 | "minimum-system-version" : "12.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "1792h",
25 | "filename" : "Default-Portrait-XR.png",
26 | "minimum-system-version" : "12.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "extent" : "full-screen",
32 | "idiom" : "iphone",
33 | "subtype" : "1792h",
34 | "filename" : "Default-Landscape-XR.png",
35 | "minimum-system-version" : "12.0",
36 | "orientation" : "landscape",
37 | "scale" : "2x"
38 | },
39 | {
40 | "extent" : "full-screen",
41 | "idiom" : "iphone",
42 | "subtype" : "2436h",
43 | "filename" : "Default-1125h.png",
44 | "minimum-system-version" : "11.0",
45 | "orientation" : "portrait",
46 | "scale" : "3x"
47 | },
48 | {
49 | "extent" : "full-screen",
50 | "idiom" : "iphone",
51 | "subtype" : "2436h",
52 | "filename" : "Default-Landscape-X.png",
53 | "minimum-system-version" : "11.0",
54 | "orientation" : "landscape",
55 | "scale" : "3x"
56 | },
57 | {
58 | "extent" : "full-screen",
59 | "idiom" : "iphone",
60 | "subtype" : "736h",
61 | "filename" : "Default-736h@3x.png",
62 | "minimum-system-version" : "8.0",
63 | "orientation" : "portrait",
64 | "scale" : "3x"
65 | },
66 | {
67 | "extent" : "full-screen",
68 | "idiom" : "iphone",
69 | "subtype" : "736h",
70 | "filename" : "Default-Landscape@3x.png",
71 | "minimum-system-version" : "8.0",
72 | "orientation" : "landscape",
73 | "scale" : "3x"
74 | },
75 | {
76 | "extent" : "full-screen",
77 | "idiom" : "iphone",
78 | "subtype" : "667h",
79 | "filename" : "Default-667h@2x.png",
80 | "minimum-system-version" : "8.0",
81 | "orientation" : "portrait",
82 | "scale" : "2x"
83 | },
84 | {
85 | "orientation" : "portrait",
86 | "idiom" : "iphone",
87 | "filename" : "Default@2x.png",
88 | "extent" : "full-screen",
89 | "minimum-system-version" : "7.0",
90 | "scale" : "2x"
91 | },
92 | {
93 | "extent" : "full-screen",
94 | "idiom" : "iphone",
95 | "subtype" : "retina4",
96 | "filename" : "Default-568h@2x.png",
97 | "minimum-system-version" : "7.0",
98 | "orientation" : "portrait",
99 | "scale" : "2x"
100 | },
101 | {
102 | "orientation" : "portrait",
103 | "idiom" : "ipad",
104 | "filename" : "Default-Portrait.png",
105 | "extent" : "full-screen",
106 | "minimum-system-version" : "7.0",
107 | "scale" : "1x"
108 | },
109 | {
110 | "orientation" : "landscape",
111 | "idiom" : "ipad",
112 | "filename" : "Default-Landscape.png",
113 | "extent" : "full-screen",
114 | "minimum-system-version" : "7.0",
115 | "scale" : "1x"
116 | },
117 | {
118 | "orientation" : "portrait",
119 | "idiom" : "ipad",
120 | "filename" : "Default-Portrait@2x.png",
121 | "extent" : "full-screen",
122 | "minimum-system-version" : "7.0",
123 | "scale" : "2x"
124 | },
125 | {
126 | "orientation" : "landscape",
127 | "idiom" : "ipad",
128 | "filename" : "Default-Landscape@2x.png",
129 | "extent" : "full-screen",
130 | "minimum-system-version" : "7.0",
131 | "scale" : "2x"
132 | },
133 | {
134 | "orientation" : "portrait",
135 | "idiom" : "iphone",
136 | "filename" : "Default.png",
137 | "extent" : "full-screen",
138 | "scale" : "1x"
139 | },
140 | {
141 | "orientation" : "portrait",
142 | "idiom" : "iphone",
143 | "filename" : "Default@2x.png",
144 | "extent" : "full-screen",
145 | "scale" : "2x"
146 | },
147 | {
148 | "orientation" : "portrait",
149 | "idiom" : "iphone",
150 | "filename" : "Default-568h@2x.png",
151 | "extent" : "full-screen",
152 | "subtype" : "retina4",
153 | "scale" : "2x"
154 | },
155 | {
156 | "orientation" : "portrait",
157 | "idiom" : "ipad",
158 | "extent" : "to-status-bar",
159 | "scale" : "1x"
160 | },
161 | {
162 | "orientation" : "portrait",
163 | "idiom" : "ipad",
164 | "filename" : "Default-Portrait.png",
165 | "extent" : "full-screen",
166 | "scale" : "1x"
167 | },
168 | {
169 | "orientation" : "landscape",
170 | "idiom" : "ipad",
171 | "extent" : "to-status-bar",
172 | "scale" : "1x"
173 | },
174 | {
175 | "orientation" : "landscape",
176 | "idiom" : "ipad",
177 | "filename" : "Default-Landscape.png",
178 | "extent" : "full-screen",
179 | "scale" : "1x"
180 | },
181 | {
182 | "orientation" : "portrait",
183 | "idiom" : "ipad",
184 | "extent" : "to-status-bar",
185 | "scale" : "2x"
186 | },
187 | {
188 | "orientation" : "portrait",
189 | "idiom" : "ipad",
190 | "filename" : "Default-Portrait@2x.png",
191 | "extent" : "full-screen",
192 | "scale" : "2x"
193 | },
194 | {
195 | "orientation" : "landscape",
196 | "idiom" : "ipad",
197 | "extent" : "to-status-bar",
198 | "scale" : "2x"
199 | },
200 | {
201 | "orientation" : "landscape",
202 | "idiom" : "ipad",
203 | "filename" : "Default-Landscape@2x.png",
204 | "extent" : "full-screen",
205 | "scale" : "2x"
206 | }
207 | ],
208 | "info" : {
209 | "version" : 1,
210 | "author" : "xcode"
211 | }
212 | }
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XR.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XS-Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XS-Max.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XR.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XS-Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XS-Max.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-AspectFill.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-AspectFill@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchScreen-AspectFill@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchScreen-Center.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchScreen-Center@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchScreen-Center@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiresFullScreen
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/demo/App_Resources/iOS/build.xcconfig:
--------------------------------------------------------------------------------
1 | // You can add custom settings here
2 | // for example you can uncomment the following line to force distribution code signing
3 | // CODE_SIGN_IDENTITY = iPhone Distribution
4 | // To build for device with XCode you need to specify your development team.
5 | // DEVELOPMENT_TEAM = YOUR_TEAM_ID;
6 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
7 |
--------------------------------------------------------------------------------
/demo/app/app-root.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/demo/app/app.css:
--------------------------------------------------------------------------------
1 | /*
2 | In NativeScript, the app.css file is where you place CSS rules that
3 | you would like to apply to your entire application. Check out
4 | http://docs.nativescript.org/ui/styling for a full list of the CSS
5 | selectors and properties you can use to style UI components.
6 |
7 | /*
8 | In many cases you may want to use the NativeScript core theme instead
9 | of writing your own CSS rules. You can learn more about the
10 | NativeScript core theme at https://github.com/nativescript/theme
11 | The imported CSS rules must precede all other types of rules.
12 | */
13 |
14 | /* @import '@nativescript/theme/css/core.css';
15 | @import '@nativescript/theme/css/default.css'; */
16 |
17 | /* Place any CSS rules you want to apply on both iOS and Android here.
18 | This is where the vast majority of your CSS code goes. */
19 |
20 | /*
21 | The following CSS rule changes the font size of all Buttons that have the
22 | "-primary" class modifier.
23 | */
24 |
25 | Page {
26 | background-color: lightgrey;
27 | color: black;
28 | }
29 | button {
30 | font-size: 20;
31 | horizontal-align: center;
32 | }
33 |
34 | .one {
35 | background-color: black;
36 | color: white;
37 | }
38 |
39 | .two {
40 | background-color: lightgrey;
41 | color: black;
42 | }
43 |
44 | .entry {
45 | background-color: lightgrey;
46 | color: black;
47 | }
48 |
49 | .copyright {
50 | background-color: black;
51 | color: white;
52 | font-size: 16;
53 | width: 100%;
54 | horizontal-align: center;
55 | }
56 |
--------------------------------------------------------------------------------
/demo/app/app.js:
--------------------------------------------------------------------------------
1 | /*
2 | In NativeScript, the app.js file is the entry point to your application.
3 | You can use this file to perform app-level initialization, but the primary
4 | purpose of the file is to pass control to the app’s first module.
5 | */
6 |
7 | import { Application } from '@nativescript/core';
8 |
9 | Application.run({ moduleName: 'app-root' })
10 |
11 | /*
12 | Do not place any code after the application has been started as it will not
13 | be executed on iOS.
14 | */
15 |
--------------------------------------------------------------------------------
/demo/app/encrypted.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/app/encrypted.sqlite
--------------------------------------------------------------------------------
/demo/app/icon.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/app/icon.sqlite
--------------------------------------------------------------------------------
/demo/app/main-page.js:
--------------------------------------------------------------------------------
1 | /**************************************************************************************
2 | * (c) 2015-2021, Master Technology
3 | * Licensed under the MIT license or contact me for a support, changes, enhancements,
4 | * and/or if you require a commercial licensing
5 | *
6 | * Any questions please feel free to put a issue up on github
7 | * Nathan@master-technology.com http://nativescript.tools
8 | *************************************************************************************/
9 |
10 | const sqlite = require('nativescript-sqlite');
11 | const ObservableArray = require("@nativescript/core/data/observable-array").ObservableArray;
12 | const FileSystemAccess = require("@nativescript/core/file-system/file-system-access").FileSystemAccess;
13 |
14 |
15 | //var Tracing = require('./tracing.js');
16 | //Tracing(sqlite, {ignore: ["close", "resultType", "valueType", "_toStringArray", "_getResultEngine"], disableAddedFunction: true});
17 |
18 | let dbname = 'name_db.sqlite';
19 | let db = null;
20 | let page = null;
21 |
22 | const data = new ObservableArray();
23 |
24 | console.log("NativeScript Runtime Version", global.__runtimeVersion);
25 |
26 | if (sqlite.HAS_COMMERCIAL) {
27 | console.log("Using Commercial");
28 | data.push({name:'Commercial Support', css:'one'});
29 | } else {
30 | console.log("No Commercial Support");
31 | }
32 |
33 | if (sqlite.HAS_ENCRYPTION) {
34 | console.log("Using Encryption");
35 | dbname = 'encrypted.sqlite';
36 | data.push({name:'Encryption Support', css:'one'});
37 | } else {
38 | console.log("No Encryption");
39 | }
40 | data.push({name: 'Loading...', css: 'one'});
41 |
42 |
43 | if (sqlite.HAS_SYNC) {
44 | console.log("Using Sync");
45 | data.push({name: 'Sync Support',css: 'one'});
46 | } else {
47 | console.log("No Sync");
48 | }
49 |
50 |
51 | exports.pageLoaded = async function (args) {
52 | page = args.object;
53 | page.bindingContext = {names: data};
54 | console.log("Using Database:", dbname);
55 |
56 | if (!sqlite.exists(dbname)) {
57 | sqlite.copyDatabase(dbname);
58 | }
59 | try {
60 | let myDb = await sqlite(dbname, {key: 'testing', multithreading: false, /*!!sqlite.HAS_COMMERCIAL ,*/ migrate: true},
61 | );
62 |
63 | let b = function (err, dbConnection) {
64 | if (err) {
65 | console.log(err, err.stack);
66 | }
67 | db = dbConnection;
68 | db.resultType(sqlite.RESULTSASOBJECT);
69 |
70 | db.version().then(function (results) {
71 | console.log("User Version: ", results, typeof results, Number.isNumber(results)); //, String.isString(results));
72 | });
73 |
74 | if (sqlite.HAS_ENCRYPTION) {
75 | db.get("PRAGMA cipher_version;").then(function (results) {
76 | console.log("Cipher version", results['cipher_version']);
77 | });
78 | }
79 |
80 | reloadData();
81 | };
82 | b(null, myDb);
83 | } catch(err) {
84 | console.log("sqlite error", err, err.stack);
85 | }
86 | };
87 |
88 | exports.addNewName = function() {
89 | const entry = page.getViewById('entry');
90 | const name = entry.text;
91 | if (name.length > 0) {
92 | if (name.toLowerCase() === "test" || name.toLowerCase() === "runtest" || name.toLowerCase() === "tests" || name.toLowerCase() === "runtests" || name.indexOf("Test") === 0) {
93 | runTests();
94 | return;
95 | }
96 |
97 | if (name.toLowerCase() === "sync") {
98 | db.enableTracking("names", {'syncTime': 10}).then((res) => {
99 | console.log("Result", res);
100 | }).catch((err) => {
101 | console.log("Error",err, err.stack);
102 | });
103 | return;
104 | }
105 |
106 | if (name.toLowerCase() === "fsync") {
107 | db.enableTracking("names", {force: true, syncTime: 10}).then((res) => {
108 | console.log("Result", res);
109 | }).catch((err) => {
110 | console.log("Error",err, err.stack);
111 | });
112 | return;
113 | }
114 |
115 | if (name.toLowerCase() === "csync") {
116 | db.execSQL("update __mt_sync_tracking set completed=1");
117 | return;
118 | }
119 |
120 |
121 | if (name.toLowerCase() === "dsync") {
122 | db.execSQL("delete from __mt_sync_tracking");
123 | return;
124 | }
125 |
126 | if (name.toLowerCase() === 'tsync') {
127 | db.all("select * from __mt_sync_tracking").then((res) => {
128 | console.log("Results:", res);
129 | });
130 | return;
131 | }
132 |
133 |
134 | db.execSQL("insert into names (name) values (?)", name);
135 | reloadData();
136 | }
137 | entry.text = '';
138 | };
139 |
140 | exports.openMT = function() {
141 | const utils = require('@nativescript/core/utils/utils');
142 | utils.openUrl("https://www.master-technology.com");
143 | };
144 |
145 | function reloadData() {
146 | db.resultType(sqlite.RESULTSASOBJECT);
147 | db.valueType(sqlite.VALUESARENATIVE);
148 |
149 | db.all('select name from names', function (err, loadedData) {
150 | data.length = 0;
151 | if (err) {
152 | console.log(err);
153 | } else {
154 | for (let i=0;i {
172 | console.error("Error", err);
173 | });
174 | }
175 |
176 |
177 | async function setupTests() {
178 | loadBlob();
179 | data.push({name: 'Creating tables and data...', css: 'one'});
180 | try {
181 | await db.execSQL('drop table if exists tests;');
182 | await db.execSQL('create table tests (`int_field` integer, `num_field` numeric, `real_field` real, `text_field` text, `blob_field` blob)');
183 | await db.execSQL('insert into tests (int_field, num_field, real_field, text_field, blob_field) values (1,1.2,2.4,"Text1",?)',[blob]);
184 | await db.execSQL('insert into tests (int_field, num_field, real_field, text_field, blob_field) values (2,4.8,5.6,"Text2",?)',[blob]);
185 | await db.execSQL('insert into tests (int_field, num_field, real_field, text_field, blob_field) values (3,null,null,null,null)');
186 | } catch (err) {
187 | console.log("Error", err);
188 | data.push({name: 'Error setting up tests...'+err.toString(), css: 'two'});
189 | throw err;
190 | }
191 | }
192 |
193 | function checkRowOfData(inData, validData) {
194 | if (Array.isArray(inData)) {
195 | for (let i = 0; i < inData.length; i++) {
196 | if (typeof inData[i] === "number") {
197 | if (inData[i] !== validData[i]) {
198 | if ((inData[i] - 0.1) > validData[i] || (inData[i] + 0.1) < validData[i]) {
199 | console.log("Failed", inData[i], validData[i])
200 | return ({status: false, field: i});
201 | }
202 | }
203 | } else {
204 | if (inData[i] !== validData[i]) {
205 | // console.log("Check:", inData[i], validData[i], typeof inData[i], typeof validData[i]);
206 | if (inData[i] === null || validData[i] === null) {
207 | return ({status: false, field: i});
208 | }
209 | // Do we have a ".count" property, if so check it
210 | if (inData[i].count > 0 && inData[i].count === validData[i].count) {
211 | for (let j = 0; j < inData[i].count; j++) {
212 | if (inData[i][j] !== validData[i][j]) {
213 | return ({status: false, field: i});
214 | }
215 | }
216 | return ({status: true});
217 | }
218 | // Do we have a ".length" property, if so check it
219 | else if (inData[i].length > 0 && inData[i].length === validData[i].length) {
220 | for (let j = 0; j < inData[i].length; j++) {
221 | if (inData[i][j] !== validData[i][j]) {
222 | return ({status: false, field: i});
223 | }
224 | }
225 | return ({status: true});
226 | } else {
227 | console.log("Failed:", inData[i].length, validData[i].length, typeof inData[i], typeof validData[i]);
228 | return ({status: false, field: i});
229 | }
230 | }
231 | }
232 | }
233 | } else if (typeof inData === 'number') {
234 | if (inData !== validData) {
235 | if ((inData - 0.1) > validData || (inData + 0.1) < validData) {
236 | return ({status: false, field: 0});
237 | }
238 | }
239 | } else {
240 | for (let key in inData) {
241 | if (inData.hasOwnProperty(key)) {
242 | if (typeof inData[key] === "number") {
243 | if (inData[key] !== validData[key]) {
244 | if ((inData[key]-0.1) > validData[key] || (inData[key]+0.1) < validData[key]) {
245 | return ({status: false, field: key});
246 | }
247 | }
248 | } else {
249 | if (inData[key] !== validData[key]) {
250 | if (inData[key] === null || validData[key] === null) {
251 | return ({status: false, field: key});
252 | }
253 | // Do we have a ".count" property, if so check it
254 | if (inData[key].count > 0 && inData[key].count === validData[key].count) {
255 | for (let j = 0; j < inData[key].count; j++) {
256 | if (inData[key][j] !== validData[key][j]) {
257 | return ({status: false, field: key});
258 | }
259 | }
260 | return ({status: true});
261 | }
262 | // Do we have a ".length" property, if so check it
263 | else if (inData[key].length > 0 && inData[key].length === validData[key].length) {
264 | for (let j = 0; j < inData[key].length; j++) {
265 | if (inData[key][j] !== validData[key][j]) {
266 | return ({status: false, field: key});
267 | }
268 | }
269 | return ({status: true});
270 | } else {
271 | return ({status: false, field: key});
272 | }
273 | }
274 | }
275 | }
276 | }
277 | }
278 | return {status: true};
279 | }
280 |
281 | function runATest(options, callback) {
282 |
283 | //console.log("!-------------- Starting Test", options.name);
284 |
285 | //data.push({name: "Starting test"+options.name});
286 | const checkResults = function(err, inData) {
287 | //console.log("!-------------- Checking Results", options.name, "Error: ", err, "Data:", inData);
288 | let passed = true;
289 | if (err) {
290 | console.log("!------------ Error", err.toString());
291 | data.push({name: options.name + " test failed with: ", css: 'one'});
292 | data.push({name: " " + err.toString(), css:'one'});
293 | return callback(false);
294 | }
295 | if (!inData || inData.length !== options.results.length) {
296 | console.dir(inData);
297 | console.log("!----------- No Data");
298 | data.push({name: options.name + " test failed with different results length", css: 'one'});
299 | return callback(false);
300 | }
301 | if (inData.length === 0) {
302 | console.log("!-------- No Data Returned");
303 | return callback(passed);
304 | }
305 | // console.log("!------------ Data Returned", inData.length, inData);
306 | for (let i=0;i {
427 | let runningTest = -1;
428 | const runTest = function (status) {
429 | if (!status) {
430 | return reject("Failed: " + tests[runningTest].name);
431 | } else if (runningTest > -1) {
432 | data.push({name: "Passed: " + tests[runningTest].name, 'css': 'two'});
433 | }
434 | runningTest++;
435 | if (runningTest >= tests.length) {
436 | return resolve(status);
437 | }
438 | try {
439 | runATest(tests[runningTest], runTest);
440 | } catch(err) {
441 | console.error("Failed Test", tests[runningTest].name)
442 | return reject(err);
443 | }
444 | };
445 |
446 | data.push({name: "-----------------------------", css: 'two'});
447 | runTest(true);
448 | });
449 | }
450 |
451 | async function runNativeArrayTest() {
452 | console.log("!-------------- Starting RNA Test");
453 | db.resultType(sqlite.RESULTSASARRAY);
454 | db.valueType(sqlite.VALUESARENATIVE);
455 |
456 | const tests = [
457 | // Callback
458 | {name: 'NativeArray Check', sql: 'select count(*) from tests', results: [3], use: 0},
459 | {name: 'NativeArray Get', sql: 'select * from tests where int_field=?', values: [2], results: [2,4.8,5.6,'Text2', blob], use: 0},
460 | {name: 'NativeArray All', sql: 'select * from tests order by int_field', results: [[1,1.2,2.4,"Text1",blob],[2,4.8,5.6,'Text2',blob],[3,null,null,null,null]], use: 1},
461 | {name: 'NativeArray Each', sql: 'select * from tests order by int_field', results: [[1,1.2,2.4,"Text1",blob],[2,4.8,5.6,'Text2',blob],[3,null,null,null,null]], use: 2},
462 |
463 | // Promise
464 | {name: 'NativeArray Promise Check', sql: 'select count(*) from tests', results: [3], use: 3},
465 | {name: 'NativeArray Promise Get', sql: 'select * from tests where int_field=?', values: [2], results: [2,4.8,5.6,'Text2',blob], use: 3},
466 | {name: 'NativeArray Promise All', sql: 'select * from tests order by int_field', results: [[1,1.2,2.4,"Text1",blob],[2,4.8,5.6,'Text2',blob],[3,null,null,null,null]], use: 4},
467 | {name: 'NativeArray Promise Each', sql: 'select * from tests order by int_field', results: [[1,1.2,2.4,"Text1",blob],[2,4.8,5.6,'Text2',blob],[3,null,null,null,null]], use: 5}
468 |
469 | ];
470 | await runTestGroup(tests);
471 | }
472 |
473 | async function runStringArrayTest() {
474 | console.log("!-------------- Starting RSA Test");
475 | db.resultType(sqlite.RESULTSASARRAY);
476 | db.valueType(sqlite.VALUESARESTRINGS);
477 | const tests = [
478 | // Callback Version
479 | {name: 'StringArray Get', sql: 'select * from tests where int_field=?', values: [2], results: ["2","4.8","5.6",'Text2',blob], use: 0},
480 | {name: 'StringArray All', sql: 'select * from tests order by int_field', results: [["1","1.2","2.4","Text1",blob],["2","4.8","5.6",'Text2',blob], ["3",null,null,null,null]], use: 1},
481 | {name: 'StringArray Each', sql: 'select * from tests order by int_field', results: [["1","1.2","2.4","Text1",blob],["2","4.8","5.6",'Text2',blob], ["3",null,null,null,null]], use: 2},
482 |
483 | // Promise Version
484 | {name: 'StringArray Promise Get', sql: 'select * from tests where int_field=?', values: [2], results: ["2","4.8","5.6",'Text2',blob], use: 3},
485 | {name: 'StringArray Promise All', sql: 'select * from tests order by int_field', results: [["1","1.2","2.4","Text1",blob],["2","4.8","5.6",'Text2',blob],["3",null,null,null,null]], use: 4},
486 | {name: 'StringArray Promise Each', sql: 'select * from tests order by int_field', results: [["1","1.2","2.4","Text1",blob],["2","4.8","5.6",'Text2',blob],["3",null,null,null,null]], use: 5}
487 | ];
488 | await runTestGroup(tests);
489 | }
490 |
491 | async function runNativeObjectTest() {
492 | console.log("!-------------- Starting RNO Test");
493 | db.resultType(sqlite.RESULTSASOBJECT);
494 | db.valueType(sqlite.VALUESARENATIVE);
495 |
496 | const tests = [
497 | // Callback
498 | {name: 'NativeObject Get', sql: 'select * from tests where int_field=?', values: [2], results: {int_field: 2, num_field: 4.8, real_field: 5.6, text_field: 'Text2', blob_field: blob}, use: 0},
499 | {name: 'NativeObject All', sql: 'select * from tests order by int_field', results: [{int_field: 1, num_field: 1.2, real_field: 2.4, text_field: 'Text1', blob_field: blob},{int_field: 2, num_field: 4.8, real_field: 5.6, text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 1},
500 | {name: 'NativeObject Each', sql: 'select * from tests order by int_field', results: [{int_field: 1, num_field: 1.2, real_field: 2.4, text_field: 'Text1', blob_field: blob},{int_field: 2, num_field: 4.8, real_field: 5.6, text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 2},
501 |
502 | // Promise
503 | {name: 'NativeObject Promise Get', sql: 'select * from tests where int_field=?', values: [2], results: {int_field: 2, num_field: 4.8, real_field: 5.6, text_field: 'Text2', blob_field: blob}, use: 3},
504 | {name: 'NativeObject Promise All', sql: 'select * from tests order by int_field', results: [{int_field: 1, num_field: 1.2, real_field: 2.4, text_field: 'Text1', blob_field: blob},{int_field: 2, num_field: 4.8, real_field: 5.6, text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 4},
505 | {name: 'NativeObject Promise Each', sql: 'select * from tests order by int_field', results: [{int_field: 1, num_field: 1.2, real_field: 2.4, text_field: 'Text1', blob_field: blob},{int_field: 2, num_field: 4.8, real_field: 5.6, text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 5}
506 |
507 | ];
508 | await runTestGroup(tests);
509 | }
510 |
511 | async function runStringObjectTest() {
512 | console.log("!-------------- Starting RSO Test");
513 | db.resultType(sqlite.RESULTSASOBJECT);
514 | db.valueType(sqlite.VALUESARENATIVE);
515 |
516 | const tests = [
517 | // Callback
518 | {name: 'StringObject Get', sql: 'select * from tests where int_field=?', values: [2], results: {int_field: "2", num_field: "4.8", real_field: "5.6", text_field: 'Text2', blob_field: blob}, use: 0},
519 | {name: 'StringObject All', sql: 'select * from tests order by int_field', results: [{int_field: "1", num_field: "1.2", real_field: "2.4", text_field: 'Text1', blob_field: blob},{int_field: "2", num_field: "4.8", real_field: "5.6", text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 1},
520 | {name: 'StringObject Each', sql: 'select * from tests order by int_field', results: [{int_field: "1", num_field: "1.2", real_field: "2.4", text_field: 'Text1', blob_field: blob},{int_field: "2", num_field: "4.8", real_field: "5.6", text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 2},
521 |
522 | // Promise
523 | {name: 'StringObject Promise Get', sql: 'select * from tests where int_field=?', values: [2], results: {int_field: "2", num_field: "4.8", real_field: "5.6", text_field: 'Text2', blob_field: blob}, use: 3},
524 | {name: 'StringObject Promise All', sql: 'select * from tests order by int_field', results: [{int_field: "1", num_field: "1.2", real_field: "2.4", text_field: 'Text1', blob_field: blob},{int_field: "2", num_field: "4.8", real_field: "5.6", text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 4},
525 | {name: 'StringObject Promise Each', sql: 'select * from tests order by int_field', results: [{int_field: "1", num_field: "1.2", real_field: "2.4", text_field: 'Text1', blob_field: blob},{int_field: "2", num_field: "4.8", real_field: "5.6", text_field: 'Text2', blob_field: blob},{int_field: 3, num_field: null, real_field: null, text_field: null, blob_field: null}], use: 5}
526 |
527 | ];
528 | await runTestGroup(tests);
529 | }
530 |
531 | async function setupPreparedTests() {
532 | if (!sqlite.HAS_COMMERCIAL) {
533 | return;
534 | }
535 |
536 | console.log("!-------------- Creating Prepared Tests Data");
537 | try {
538 | await db.execSQL('drop table if exists preparetests;');
539 | await db.execSQL('create table preparetests (`int_field` integer, `num_field` numeric, `real_field` real, `text_field` text, `blob_field` blob)');
540 | } catch (err) {
541 | data.push({name: 'Failed to create tables and data...', css: 'one'});
542 | console.log("!---- Create Table err", err);
543 | throw err;
544 | }
545 | }
546 |
547 | async function runExtraTests() {
548 | console.log("!-------------- Extra Tests");
549 | data.push({name: "-----------------------------", css: 'two'});
550 | db.resultType(sqlite.RESULTSASOBJECT);
551 | db.valueType(sqlite.VALUESARENATIVE);
552 |
553 | try {
554 | await db.execSQL('drop table if exists extratests;');
555 | await db.execSQL('create table extratests (`int_field` integer, `num_field` numeric, `real_field` real, `text_field` text, `blob_field` blob, `int2field` integer)');
556 | await db.execSQL('insert into extratests values (1, 2, 3, "4", "5", 6)');
557 | let val = await db.get('select * from extratests');
558 | if (!(val.int_field === 1 && val.num_field === 2 && val.int2field === 6)) {
559 | throw new Error("ExtraTest data does not match");
560 | }
561 |
562 | await db.execSQL("update extratests set num_field=null where int_field=1");
563 | val = await db.get('select * from extratests');
564 | if (val.int_field !== 1 || val.num_field !== null) {
565 | throw new Error("Failed ExtraTest direct null");
566 | }
567 |
568 | await db.execSQL("update extratests set int2field=null where int_field=1");
569 | val = await db.get('select * from extratests');
570 | if (val.int_field !== 1 || val.int2field !== null) {
571 | throw new Error("Failed ExtraTest int is null");
572 | }
573 |
574 | await db.execSQL("update extratests set real_field=? where int_field=1", [null]);
575 | val = await db.get('select * from extratests');
576 | if (val.int_field !== 1 || val.real_field !== null) {
577 | throw new Error("Failed ExtraTest param as null")
578 | }
579 | } catch (err) {
580 | console.log("Failed: Extra Tests", err)
581 | data.push({name: 'Failed: Extra Tests...'+err, 'css': 'one'});
582 | throw err;
583 | }
584 | data.push({name: 'Passed: Extra Tests...', 'css': 'two'});
585 | }
586 |
587 | async function runPreparedTests(callback) {
588 | if (!sqlite.HAS_COMMERCIAL) {
589 | return;
590 | }
591 | db.resultType(sqlite.RESULTSASARRAY);
592 | db.valueType(sqlite.VALUESARENATIVE);
593 |
594 | try {
595 | // Test to make sure Rollbacks work
596 | await setupPreparedTests();
597 | await createPreparedData(true);
598 | let tests = [{
599 | name: 'Verify Rollback Check',
600 | sql: 'select count(*) from preparetests',
601 | results: [0],
602 | use: 0
603 | }];
604 | await runTestGroup(tests);
605 |
606 |
607 | // Test to make sure Commits work
608 | await createPreparedData(false);
609 | tests = [{
610 | name: 'Verify Commit Check',
611 | sql: 'select count(*) from preparetests',
612 | results: [3],
613 | use: 0
614 | },
615 | {
616 | name: 'Commit/Prepare All', sql: 'select * from preparetests order by int_field', results: [
617 | [1, 1.2, 2.4, 'Text1', blob],
618 | [2, 2.4, 3.6, 'Text2', blob],
619 | [3, 3.6, 4.8, 'Text3', blob]
620 | ], use: 1
621 | }];
622 | await runTestGroup(tests);
623 | } catch (err) {
624 | data.push({name: 'Failed: Prepared Tests...', 'css': 'one'});
625 | throw err;
626 | }
627 | data.push({name: 'Passed: Prepared Tests...', 'css': 'two'});
628 |
629 | }
630 |
631 | async function createPreparedData(rollback) {
632 | if (!sqlite.HAS_COMMERCIAL) {
633 | return;
634 | }
635 |
636 | let prepared;
637 | try {
638 | console.log("!------------------ Create Prepared Tests");
639 | prepared = db.prepare("insert into preparetests (int_field, num_field, real_field, text_field, blob_field) values (?,?,?,?,?);");
640 | } catch(err) {
641 | console.log("Error creating prepare data", err);
642 | throw err;
643 | }
644 |
645 | try {
646 | await db.begin();
647 | await prepared.execute([1, 1.2, 2.4, "Text1", blob]);
648 | await prepared.execute([[2, 2.4, 3.6, "Text2", blob], [3, 3.6, 4.8, "Text3", blob]]);
649 | if (rollback) {
650 | await db.rollback();
651 | } else {
652 | await db.commit();
653 | }
654 | prepared.finished();
655 | } catch (err) {
656 | data.push({name: 'Failed Prepared Tests...', css: 'one'});
657 | console.log(err);
658 | throw err;
659 | }
660 | }
661 |
662 | async function delay(time) {
663 | return new Promise((resolve) => {
664 | setTimeout(() => { resolve(); }, time);
665 | });
666 | }
667 |
668 | async function runTests() {
669 | data.length = 0;
670 | data.push({name: 'Running SQLite tests...', css: 'one'});
671 |
672 | try {
673 | await setupTests();
674 | await delay(10);
675 | data.push({name: 'Created tables & data...', css: 'one'});
676 | // for (let i=0;i<20;i++) {
677 | // data.length = 0;
678 | await runNativeArrayTest();
679 | await delay(10);
680 | await runNativeObjectTest();
681 | await delay(10);
682 | await runStringArrayTest();
683 | await delay(10);
684 | await runStringObjectTest();
685 | await delay(10);
686 | // }
687 | await runPreparedTests();
688 | await delay(10);
689 | await runExtraTests();
690 | data.push({name: "-----------------------------", css: 'two'});
691 | data.push({name: 'Tests completed...', css: 'two'});
692 | } catch (err) {
693 | data.push({name: "-----------------------------", css: 'two'});
694 | data.push({name: 'Tests failed...', css: 'one'});
695 | data.push({name: err, css: 'one'});
696 | }
697 | console.log("-----------------------------");
698 | console.log("Tests completed!");
699 | }
700 |
701 |
--------------------------------------------------------------------------------
/demo/app/main-page.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/demo/app/name_db.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NathanaelA/nativescript-sqlite/0cf65148fc786bc56edf2396c12b4ec52670d164/demo/app/name_db.sqlite
--------------------------------------------------------------------------------
/demo/app/sqlite_syncer.js:
--------------------------------------------------------------------------------
1 | /************************************************************************************
2 | * (c) 2019-21 Master Technology
3 | * Licensed under the MIT license or contact me for a support, changes, enhancements,
4 | * and/or if you require a commercial licensing
5 | *
6 | * Any questions please feel free to email me or put a issue up on github
7 | * Nathan@master-technology.com http://nativescript.tools
8 | ***********************************************************************************
9 | * Version 1.1.0 - Sync
10 | ***********************************************************************************
11 | * NOTE: This code will run inside the worker if you are using multithreading!
12 | *
13 | * You can use to send a message back to the main thread (or from the main thread)
14 | * sqlite.notify("customName", message)
15 | *
16 | * from this code (or the main thread) to receive message:
17 | * sqlite.addMessageHandler("customName", callback);
18 | *
19 | ***********************************************************************************/
20 |
21 | module.exports = {
22 | setup: function(db) {
23 | console.log("Syncer Setup");
24 | },
25 | handleSync: function(res, callback, db) {
26 | console.log("Handle Sync", res);
27 | // TODO: Send records to remote server, upon getting notified that records are good; run the "Callback()"
28 |
29 | // currently during testing, lets just Sending a False back will say the records are NOT done...
30 | callback(false);
31 | },
32 | startSync: function(options, db) {
33 | console.log("Starting sync with these options", options);
34 | },
35 | stopSync: function(db) {
36 | console.log("Stopping Syncing");
37 | },
38 | };
39 |
--------------------------------------------------------------------------------
/demo/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./",
4 | "paths": {
5 | "~/*": ["app/*"],
6 | "@/*": ["app/*"]
7 | }
8 | },
9 | "include": ["app/**/*"]
10 | }
11 |
--------------------------------------------------------------------------------
/demo/nativescript.config.ts:
--------------------------------------------------------------------------------
1 | import { NativeScriptConfig } from '@nativescript/core';
2 |
3 | export default {
4 | id: 'technology.master.sqlitedemo',
5 | appPath: 'app',
6 | appResourcesPath: 'App_Resources',
7 | android: {
8 | v8Flags: '--expose_gc',
9 | markingMode: 'none'
10 | }
11 | } as NativeScriptConfig;
12 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-sqlite-demo",
3 | "main": "app/app.js",
4 | "version": "8.0.0",
5 | "author": "Nathan Anderson {
4 | webpack.init(env);
5 |
6 | // Learn how to customize:
7 | // https://docs.nativescript.org/webpack
8 |
9 | return webpack.resolveConfig();
10 | };
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/.npmignore:
--------------------------------------------------------------------------------
1 | demo/
2 | changelog.
3 | contributors.md
4 | sqlite.android.queue.js
5 | sqlite.d.ts
6 | tsconfig.json
7 | tslint.json
8 | .idea/
9 | .git/
10 | graphics/
11 | *.tgz
12 | *.tar
13 | *.stackdump
14 |
--------------------------------------------------------------------------------
/src/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2021, Nathanael Anderson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 |     [](https://twitter.com/congocart)
2 |
3 | # NativeScript sqlite
4 |
5 | A NativeScript module providing sqlite actions for Android and iOS. (with multi-threading)
6 |
7 |
8 | ## License
9 |
10 | There are two possible licenses this is released under;
11 |
12 | [](https://www.npmjs.com/package/nativescript-sqlite)
13 | 
14 |
15 |
16 | ### NativeScript-Sqlite Free version
17 |
18 | This part of the library is released under the MIT License, meaning you are free to include this code any type of program -- However for entities that need a support contract, changes, enhancements and/or a commercial license please see [http://nativescript.tools](http://nativescript.tools/product/10)
19 |
20 |
21 | ### NativeScript-SQLite Commercial/Encrypted Version
22 | This also has a commercial license version, allowing you to use the commercial version of the plugin in your projects.
23 |
24 | The [commercial version](http://nativescript.tools/product/10) comes with the following enhancements:
25 | - TypeScript definitions
26 | - Totally backwards compatible with the free version
27 | - Prepared statements
28 | - Multilevel transaction support
29 | - Encryption
30 | - multiple sql statements per query
31 | - Full source code
32 | - **Multi-threading**
33 |
34 | Note: On iOS when installing the encryption, you **might** have to delete the following file:
35 | `node_modules/nativescript-sqlite/platforms/ios/module.modulemap`. And then run a `tns platform clean ios`
36 | This file is REQUIRED for normal un-encrypted sqlite; but it can conflict with encryption on some versions of XCode. When you run the app; if you get a console line about encryption not being linked in; then this is the cause.
37 |
38 | ## Example Application
39 |
40 | An example application can be downloaded or cloned from https://github.com/NathanaelA/nativescript-sqlite
41 | To use you need to do:
42 | * `npm i`
43 | * `tns run`
44 |
45 | ***optional***
46 | * `tns plugin add nativescript-sqlite-commercial-???.tgz`
47 | * `tns plugin add nativescript-sqlite-encrypted-???.tgz`
48 | * `tns plugin add nativescript-sqlite-sync-???.tgz`
49 |
50 | Then run the app the normal way you would.
51 |
52 |
53 | ## Installation
54 |
55 | Run `tns plugin add nativescript-sqlite` in your ROOT directory of your project.
56 |
57 | ***optional***
58 | * `tns plugin add ./plugins/nativescript-sqlite-commercial-???.tgz`
59 | * `tns plugin add ./plugins/nativescript-sqlite-encrypted-???.tgz`
60 | * `tns plugin add ./plugins/nativescript-sqlite-sync-???.tgz`
61 |
62 | ## Webpacking (NativeScript 8 / Webpack 5)
63 |
64 | You don't have to do anything! It will automatically add all *.sqlite files in your project.
65 |
66 |
67 | ## Webpacking (NativeScript 5, 6 & 7 / Webpack 4)
68 |
69 | If you are including your own sqlite database embedded in your app; and you are webpacking then around line 100 of the `webpack.config.js` is
70 | a section that looks like so:
71 |
72 | ```js
73 | // Copy assets to out dir. Add your own globs as needed.
74 | new CopyWebpackPlugin([
75 | { from: { glob: "fonts/**" } },
76 | { from: { glob: "**/*.jpg" } },
77 | { from: { glob: "**/*.png" } },
78 | { from: { glob: "**/*.sqlite" }},
79 | ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] })
80 | ```
81 |
82 | Add a new line `{ from: { glob: "**/*.sqlite" } },` so that it will pick up your sqlite file while bundling the application.
83 |
84 | In addition, if you are not using the Sync, Commercial or Encrypted plugin; you would need to add to the webpack.config.js file any you are not using:
85 |
86 | ```
87 | externals.push('nativescript-sqlite-commercial');
88 | externals.push('nativescript-sqlite-encrypted');
89 | externals.push('nativescript-sqlite-sync');
90 | ```
91 | so that it ignores those during webpacking, right below the line that says
92 | 'const externals = nsWebpack.getConvertedExternals(env.externals)'
93 |
94 | ## Usage
95 |
96 | To use the sqlite module you must first `require()` it:
97 |
98 | ```js
99 | const Sqlite = require( "nativescript-sqlite" );
100 | ```
101 |
102 | (or with TypeScript, if using the commercial version)
103 | ```ts
104 | import Sqlite from "nativescript-sqlite";
105 | ```
106 |
107 | After you have a reference to the module you can then call the available methods.
108 | The database defaults to returning result sets in arrays; i.e. [[field1, field2, ...], [field1, field2], [field1, field2] ...] you can change this to returning them in objects if you desire.
109 |
110 | ## Shipping a Database with the application
111 |
112 | If you are planning on shipping a database with the application; drop the file in your projects /app folder (`src` if using Angular). The Sqlite.copyDatabase("database_name") will copy the database from that folder to the proper database folder on your platform.
113 |
114 |
115 | ### Callbacks
116 | * All callbacks have the standard (Error, result) prototype
117 | * USE CALLBACKS or PROMISES; it is not recommended to use both
118 |
119 | ### Promises
120 | * Will either call your *reject* with the error or the *resolve* with the answer
121 | * USE CALLBACKS or PROMISES; it is not recommended to use both
122 |
123 | ### Constants
124 | * Sqlite.RESULTSASARRAY - Returns results as Arrays (ex: select name, phone --- results [[name,phone]])
125 | * Sqlite.RESULTSASOBJECT - Returns results as Objects (ex: select name, phone --- results [{name: name, phone: phone}]
126 | * Sqlite.VALUESARENATIVE - Returns the values as the native values; i.e. Integer = Integer, Float = Number
127 | * Sqlite.VALUESARESTRINGS - Returns all the values as a string; so the Integer 1 would be returned as "1"
128 |
129 |
130 | * Sqlite.HAS_COMMERCIAL - will be true if commercial library is loaded.
131 | * Sqlite.HAS_ENCRYPTION - will be true if encryption library is loaded.
132 | * Sqlite.HAS_SYNC - will be true if sync library is loaded.
133 |
134 | ### Methods
135 | #### new Sqlite(dbname, options, callback)
136 | #### promise = Sqlite(dbname, options, callback)
137 | ##### Parameters
138 | * dbname: your database name. This can be ":memory:" for a memory Database. This can be "" for a Temporary Database.
139 | * options
140 | * "readOnly", which if set to true will make the db read only when it opens it
141 | * "key", used for using/opening encrypted databases (See Encryption at bottom of document, require Commercial version)
142 | * "multithreading", enable background multitasking. All SQL is ran on a background worker thread. (Requires Commercial version)
143 | * "migrate", migrates a Encrypted Sql database from v3 to the new v4. If you are a new user you do not need to set this flag as new created databases will already be in v4. If you are upgrading a app that used v1.3.0 or earlier of NS-Sqlite-Encrypted; then you will probably want to set this flag to true.
144 | * (optional) callback (error, db): db is the fully OPEN database object that allows interacting with the db.
145 | * RETURNS: promise of the DB object
146 |
147 | You should choose either to use a promise or a callback; you can use whichever you are most comfortable with -- however, as with this example, you CAN use both if you want; but side effects WILL occur with some functions.
148 |
149 | ```js
150 | // Promise based example
151 | const Sqlite = require( "nativescript-sqlite" );
152 |
153 | const db = await Sqlite("MyTable");
154 | console.log("Are we open yet (Promise based)? ", db.isOpen() ? "Yes" : "No"); // Yes
155 | ```
156 |
157 | or
158 |
159 | ```js
160 | // Callback based example
161 | const Sqlite = require( "nativescript-sqlite" );
162 | new Sqlite("MyTable", function(err, db) {
163 | if (err) {
164 | console.error("We failed to open database", err);
165 | } else {
166 | // This should ALWAYS be true, db object is open in the "Callback" if no errors occurred
167 | console.log("Are we open yet (Callback based)? ", db.isOpen() ? "Yes" : "No"); // Yes
168 | }
169 | });
170 | ```
171 |
172 |
173 | #### Sqlite.isSqlite()
174 | ##### Parameters
175 | * object to check
176 | * RETURNS: Boolean, True or False if the object passed to this function is a sqlite database
177 |
178 | ```js
179 | // my-page.js
180 | new Sqlite("test.db", function(err, db) {
181 | console.log("Is a Sqlite Database:", Sqlite.isSqlite(db) ? "Yes" : "No"); // Should print "Yes"
182 | });
183 | ```
184 |
185 | #### Sqlite.exists(dbName)
186 | ##### Parameters
187 | * dbName - database name
188 | * RETURNS: Boolean, True if the database exists in the App/OS Database folder
189 |
190 |
191 | #### Sqlite.deleteDatabase(dbName)
192 | * dbName - database name to delete in the App/OS Database folder
193 | * RETURNS: Nothing
194 |
195 |
196 | #### Sqlite.copyDatabase(dbName, destName)
197 | * dbName - database name to copy from your app folder to the proper database folder on the OS
198 | * destName - (OPTIONAL) - if you want the database destination name to be something different than the source
199 | * RETURNS: True if copy was successful
200 | * NOTES: This will only copy the file if it does not already exist at the destination.
201 |
202 | ```js
203 | // If we are in Debug Code, we always delete the database first so that the latest copy of the database is used...
204 | if (DEBUGMODE && Sqlite.exists("mydatabase.sqlite")) {
205 | Sqlite.deleteDatabase("mydatabase.sqlite");
206 | }
207 | if (!Sqlite.exists("mydatabase.sqlite")) {
208 | // Example: Copying a different name to mydatabase.sqlite
209 | // Sqlite.copyDatabase("original.sqlite", "mydatabase.sqlite");
210 | // OR copy mydatabase to where it belongs...
211 | Sqlite.copyDatabase("mydatabase.sqlite");
212 | }
213 | ```
214 |
215 | ### DB Methods = Returned Database Object from Constructor
216 | #### DB.version()
217 | ##### Parameters
218 | * Value to set it to, or a Callback for retrieving the value.
219 | If Callback Value will have the version. On a new Database it will be Zero
220 | If Version number, then the database will be changed to the version you passed to this function
221 | * RETURNS: Promise.
222 |
223 | ```js
224 | new Sqlite("test.db", function(err, db) {
225 | db.version(function(err, ver) {
226 | if (ver === 0) {
227 | db.execSQL("Create table....");
228 | db.version(1); // Sets the version to 1
229 | }
230 | });
231 | });
232 | ```
233 |
234 | #### DB.isOpen()
235 | * RETURNS: Boolean, Is the current database open true/false
236 | Please note; it is possible that this value could be wrong initially in multithreading as the db might still be in the process of opening. For compatibility we set this to true automatically in multithreading after you do an open.
237 |
238 |
239 | #### DB.resultType(Sqlite.YYY)
240 | ##### Parameters
241 | * Pass in Sqlite.RESULTSASOBJECT or Sqlite.RESULTSASARRAY to change the result sets configuration
242 | This will set the database to return the results in which ever choice you make. (Default is RESULTSASARRAY)
243 |
244 |
245 | #### DB.valueType(Sqlite.YYY)
246 | ##### Parameters
247 | * Pass in Sqlite.VALUESARENATIVE or Sqlite.VALUESARESTRING to change the result sets configuration
248 | This will set the database to return the results to which ever choice you make. (Default is VALUESARENATIVE)
249 |
250 |
251 | #### DB.close()
252 | * Closes the database
253 | * RETURNS: Promise
254 | NOTE: Any DB calls after this will throw errors.
255 |
256 |
257 | #### DB.execSQL(SQL statement, params, callback)
258 | #### DB.execSQL([multiple statements], [params], callback) - Commercial Version Feature
259 | ##### Parameters
260 | * SQL statements to run, can use ? for Parameters
261 | * Params (Optional) - an array of Parameters
262 | * Callback will either return null or the last id inserted or the record count of update/delete
263 | This routine you can use for "update", "insert", "delete" and any other sqlite command where you are not expecting a result set back.
264 | If this is a Insert it will return the last row id of the new inserted record. If it is a update/insert it will return the number of rows affected.
265 | If you send multiple queries, then you will get an array of results.
266 | * RETURNS: Promise; resolved results are the same as the callback values.
267 |
268 | ```js
269 | // new SQLite(....
270 | db.execSQL("insert into Hello (word) values (?)", ["Hi"], function(err, id) {
271 | console.log("The new record id is:", id);
272 | });
273 | ```
274 |
275 | ```js
276 | // NOTE: Sending Arrays of queries is only available in Commercial version...
277 | // new SQLite(....
278 | const promise = db.execSQL(["insert into Hello (word) values (?)", "insert into Hello (word) values (?)"], [["Hi"], ["Hello"]]);
279 | promise.then(function(ids) {
280 | console.log("The new record ids are:", ids[0], ids[1]);
281 | });
282 | ```
283 |
284 |
285 | #### DB.get(statement, params, callbacks)
286 | #### DB.get([multiple statements], [params], callback) - Commercial Version Feature
287 | ##### Parameters
288 | * SQL SELECT statement, can use ? for parameters
289 | * Params (Optional)
290 | * Callback will have the first row of the result set.
291 | * RETURNS: Promise, will has have first row.
292 |
293 | ```js
294 | // new SQLite(...
295 | db.get('select * from Hello where id=?', [1], function(err, row) {
296 | console.log("Row of data was: ", row); // Prints [["Field1", "Field2",...]]
297 | });
298 | ```
299 |
300 | ```js
301 | // new SQLite(...
302 | const promise = db.get('select * from Hello where id=?', [1]);
303 | promise.then(function(row) {
304 | console.log("Row of data was: ", row); // Prints [["Field1", "Field2",...]]
305 | });
306 | ```
307 |
308 |
309 |
310 | #### DB.all(query, params, callback)
311 | #### DB.all([multiple queries], [params], callback) - Commercial Version Feature
312 | ##### Parameters
313 | * SQL SELECT statement, can use ? for parameters
314 | * Params (Optional)
315 | * Callback will have the all the rows of the result set.
316 | * RETURNS: Promise, will have all the rows of the result set.
317 |
318 | ```js
319 | // new SQLite(...
320 | db.all('select * from Hello where id > ? and id < ?', [1,100], function(err, resultSet) {
321 | console.log("Result set is:", resultSet); // Prints [["Row_1 Field_1" "Row_1 Field_2",...], ["Row 2"...], ...]
322 | });
323 | ```
324 |
325 | ```js
326 | // new SQLite(...
327 | const promise = db.all('select * from Hello where id > ? and id < ?', [1,100]);
328 | promise.then(function(resultSet) {
329 | console.log("Result set is:", resultSet); // Prints [["Row_1 Field_1" "Row_1 Field_2",...], ["Row 2"...], ...]
330 | });
331 | ```
332 |
333 |
334 |
335 | #### DB.each()
336 | ##### Parameters
337 | * SQL Select statement, can use ? for parameters
338 | * Params (Optional)
339 | * Callback (REQUIRED) will be called for EACH row of the result set with the current row value
340 | * Finished_Callback (Optional) will be called when it is complete with the number of rows handled.
341 | * RETURNS: Promise; please note the per row CALLBACK is still required; otherwise you won't have any results...
342 |
343 |
344 | ```js
345 | // new SQLite(...
346 | db.each('select * from Hello where id >= ? and id <= ?', [1, 100],
347 | function (err, row) {
348 | console.log("Row results it:", row); // Prints ["Row x Field_1", "Row x Field 2"...] for each row passed to it
349 | },
350 | function (err, count) {
351 | console.log("Rows displayed:", count); // Prints 100 (Assuming their are a 100 rows found)
352 | });
353 | ```
354 |
355 | ```js
356 | // new SQLite(...
357 | const promise = db.each('select * from Hello where id >= ? and id <= ?', [1, 100],
358 | function (err, row) {
359 | console.log("Row results it:", row); // Prints ["Row x Field_1", "Row x Field 2"...] for each row passed to it
360 | });
361 | promise.then(function (count) {
362 | console.log("Rows displayed:", count); // Prints 100 (Assuming their are a 100 rows found)
363 | });
364 | ```
365 |
366 |
367 |
368 | ## Commercial Only Features
369 |
370 | #### To enable the optional features
371 |
372 | To enable encryption: `tns plugin add nativescript-sqlite-encrypted-1.2.1.tgz`
373 |
374 | To enable commercial: `tns plugin add nativescript-sqlite-commercial-1.2.0.tgz`
375 |
376 |
377 | ### Encryption Support
378 | Pass the encryption key into database open function using the `options.key` and it will be applied. Please note the database itself MUST be created with encryption to use encryption. So if you create a plain database, you can not retroactively add encryption to it.
379 | If you pass a blank (**""**) empty key, then it will treat it as no key. But, it will still use the encrypted driver in case you need certain features from the more modern sqlite driver; but don't need encryption.
380 |
381 | Note: Enabling/Compiling in the encryption driver adds about 3 megs to the size to the application APK on android and about 2 megs to a iOS application.
382 |
383 | #### Encryption Upgrade
384 | There is a NEW upgrade option you can pass to the database constructor. if you were using an older version (1.3.0 or earlier) of this NS-Sqlite-Encryption.
385 | * "migrate", migrates a Encrypted Sql database from v3 to the new v4. If you are a new user you do not need to set this flag as new created databases will already be in v4. If you are upgrading a app that used v1.3.0 or earlier of NS-Sqlite-Encrypted; then you will probably want to set this flag to true.
386 |
387 | #### iOS Encryption Notes
388 |
389 | If you see `SQLCipher does not seem to be linked into the application`
390 |
391 | Sometimes iOS decides it really wants to bring in the native SQLite over the encrypted version.
392 | A couple things you can try:
393 | - Delete some files that aren't needed when using encryption that might bring in the standard sqlite plugin.
394 | - `rm node_modules/nativescript-sqlite/platforms/ios/build.xcconfig`
395 | - `rm node_modules/nativescript-sqlite/platforms/ios/module.modulemap`
396 | - Then `tns platform clean ios`
397 |
398 |
399 |
400 | ### Multitasking / Multithreading
401 | The commercial version supports putting all SQL access into a background thread, so your UI doesn't freeze while doing data access. To enable; just pass in {multithreading: true} as an option when creating a new Sqlite connection.
402 |
403 |
404 | ### Prepared Queries
405 | #### DB.prepare(SQL)
406 | ##### Parameter:
407 | * SQL Statement
408 | * Returns Prepared Statement
409 |
410 | #### PREPAREDSTATEMENT.execute(param1, param2, param3, optional_callback)
411 | #### PREPAREDSTATEMENT.execute([param1, param2, param3], optional_callback)
412 | #### PREPAREDSTATEMENT.execute([ [ p1, p2, p3], [p1, p2, p3], ...], optional_callback)
413 | ###### Parameters:
414 | * Pass in values, Array of values, or Array of Arrays
415 | * Pass in an optional callback last for when finished.
416 | * Returns a Promise
417 |
418 | #### PREPAREDSATEMENT.finished()
419 | * Cleans up and destroys this prepared statement. Use when you are all done with the prepared statement.
420 |
421 | ```js
422 | const prep = db.prepare('insert into names (first, last) values (?,?)');
423 | for (let i=0;i<10;i++) {
424 | prep.execute(["Name", i]);
425 | }
426 | prep.finished();
427 | ```
428 |
429 |
430 | ### Transactions
431 | #### DB.begin()
432 | ##### Parameters
433 | * callback (Optional)
434 | * RETURNS promise
435 | This starts a new transactions, if you start a nested transaction, until you commit the first transaction nothing is written.
436 |
437 | #### DB.commit()
438 | ##### Parameters
439 | * callback (Optional)
440 | * RETURNS promise
441 | This commits a single transaction, if this is a nested transaction; the changes are not written until the first/final transaction is committed.
442 |
443 | #### DB.commitAll()
444 | ##### Parameters
445 | * callback (Optional)
446 | * RETURNS promise
447 | This commits the entire transaction group, everything is written and any open transactions are committed.
448 |
449 | #### DB.rollback()
450 | ##### Parameters
451 | * callback (Optional)
452 | * RETURNS promise
453 | This rolls back a single transaction, if this is a nested transaction; only the outermost nested transaction is rolled back.
454 |
455 | #### DB.rollbackAll()
456 | ##### Parameters
457 | * callback (Optional)
458 | * RETURNS promise
459 | This rolls back the entire transaction group; everything is cancelled.
460 |
461 |
462 | ## Tutorials
463 |
464 | Need a little more to get started? Check out these tutorials for using SQLite in a NativeScript Android and iOS application.
465 |
466 | * [SQLite in a NativeScript Angular Application](https://www.thepolyglotdeveloper.com/2016/10/using-sqlite-in-a-nativescript-angular-2-mobile-app/)
467 | * [SQLite in a NativeScript Vanilla Application](https://www.thepolyglotdeveloper.com/2016/04/use-sqlite-save-data-telerik-nativescript-app/)
468 | * [SQLite in a NativeScript Vue Application](https://www.nativescript.org/blog/data-management-with-sqlite-and-vuex-in-a-nativescript-vue-app)
469 |
470 | ## Error Notes
471 | - If you get an error about opening a SQL table `android.database.sqlite.SQLiteException: Failed to change locale for db to 'en_US'.`
472 | You need to create the table and insert the locale it is failing on:
473 | ```
474 | CREATE TABLE android_metadata ( locale TEXT );
475 | insert into android_metadata values ('en_us');
476 | ```
477 | Or pass the `.androidFlags` value of `16` to the open statement.
478 |
--------------------------------------------------------------------------------
/src/changelog:
--------------------------------------------------------------------------------
1 | Changelog
2 |
3 | v1.0.8 - Fix for iOS Column names, Android allow copy from sub-directory
4 | v1.0.9 - Adding Transaction support
5 | v1.0.10 - Fixed docs
6 | v1.1.2 - Fixed ios xCode 8 issues
7 | v1.1.3 - Updated iOS demo and fixes for Webpack
8 | v1.1.4 - Adding iosFlags & androidFlags ability to be passed in as the options.
9 | v1.1.6 - Added blog support in iOS version
10 | v1.1.7 - Missed one of the iOS blob support
11 | v1.1.8 - Commercial Only changes
12 | v1.1.9 - Fix for Promise and version() function
13 | v1.1.10 - Fix for iOS int truncation
14 | v1.1.11 - Fix for Documentation and Package.json (no plugin changes)
15 |
16 | v2.0.0 - Allowed sqlite plugin to have plugins. New version now supports a fairly extensible interface to allow the optional
17 | - commercial, encryption, multitasking support to be loaded at the time you load the sqlite library. Everything is now totally
18 | - automatic; and has full support for Transactions, Prepared statements, and Encryption.
19 | v2.0.1 - Fix for opening database issue, now supports flags properly.
20 | v2.1.0 - make plugin system more webpackable.
21 | v2.2.0 - Fix an iOS insert/update corruption issue. Several commercial diagnostic enhancements.
22 | v2.2.1 - Fix an iOS issue; 32 bit library wasn't built into new framework. Upgrade to NS 4.x for demo
23 | v2.2.2 - Fix an iOS issue; dbname could be deallocatd by runtime/objc marshalling - Thanks Martin Bektchiev!
24 | v2.2.3 - Fix SQLite ReadOnly bitmask flag on iOS - Thanks Eduardo Speroni!
25 | v2.2.4 - Fix CopyDatabase on Android to respect the app version (for livesync) - Thanks Webleaf
26 | v2.2.5 - Fix CopyDatabase indexOf to lastIndexOf - Thanks Webleaf
27 | v2.2.6 - Forgot to include the ios sqlite helper in v2.2.4/v2.2.5
28 | v2.3.0 - Several minor issues fixed, Multi-threading added to Sqlite
29 | v2.3.1 - iOS SQLExec bind returns the wrong error value
30 | v2.3.2 - Added Promise tests, started ES6 updated.
31 | v2.3.3 - In some worker situations, the context cannot be retrieved, added additional method to get context.
32 | v2.4.0 - Adding Sync Support
33 | v2.5.0 - NS 6 Support, Webpack fixes, iOS Fix
34 | v2.6.0 - Blog fixes, Updated typings, context fix, copyDatabase fix & can have options destination name
35 | v2.6.1 - Fixed creating :memory: table on Android. - Thanks Lars Hollenbach
36 | v2.6.2 - Doc fixes, version not returning a number when on promise based path, sqlexec eating errors on ios - Thanks Eugine Mirotin & jscti
37 | v2.6.3 - Issue with using w/o constructor fixed
38 | v2.6.4 - Fixes in Blob handling on android, now directly supports byte[] arrays on android.
39 | v2.6.5 - Issue with using w/o "new" on iOS fixed
40 | v2.6.6 - Missed a tns-core-modules reference in
41 | v2.7.0 - Add NS 8 Webpack support
42 | v2.8.0 - Fixes for Webpack / Webworkers
43 | v2.8.1 - More fixes for WebWorker/Webpacking issues
44 | v2.8.2 - Fixes for iOS 14.5+ issues on opening database
45 | v2.8.3 - Add missing Commercial feature exclusion to Webpack 5
46 | v2.8.4 - Webpack 4 (Older NS support)
47 | v2.8.5 - Found issue with iOS not supporting Blob properly as a parameter not in an array of params.
48 |
--------------------------------------------------------------------------------
/src/contributors.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributing to any Master Technology projects
3 |
4 | ## Contributor License Agreement
5 | This Contributor License Agreement (the “Agreement”) represents the terms under which You may contribute to any code in this repo. In order to clarify the intellectual property license granted with Contributions from any person or entity, Master Technology must have an Agreement on file that has been signed by each person or entity contributing to our code, indicating agreement to the license terms below. This license is for your protection as a contributor as well as the protection of Master Technology and its users; it does not change your rights to use your own Contributions for any other purpose.
6 | We appreciate your contributions to our repo and ask that to show that you have accepted this agreement:
7 | You please email us your name, address, github name and github email address for us to file account complete the following information and agree to this Agreement below. If you have any questions about this Agreement, please contact us at clientservice@nativescript.org.
8 |
9 |
10 | ### I. DEFINITIONS
11 |
12 | “You” or “Your” shall mean the copyright owner or legal entity authorized by the copyright owner submitting the Contribution to Master Technology.
13 | “Contribution” shall mean any original work of authorship, including any modifications or additions to an existing work, bug fixes, configuration changes, documentation or other material that is submitted by You to Master Technology for inclusion in, or documentation of, any of the software products owned by Master Technology (the “Software”). For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to Master Technology or its representatives unless such Contribution is conspicuously marked or otherwise designated in writing by You as “Not a Contribution.”
14 |
15 | ### II. TERMS
16 |
17 | 1. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to Master Technology and its licensees a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable, fully transferable license to use, copy, reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute Your Contributions and any such derivative works on any licensing terms, including, but not limited to (a) the Apache 2.0 license or (b) any binary, proprietary or commercial license.
18 |
19 | 2. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to Master Technology and to recipients of software distributed by Master Technology a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Software, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Software to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Software to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Software shall terminate as of the date such litigation is filed.
20 |
21 | 3. Warranty of Title. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer or that your employer has waived such rights for your Contributions to Master Technology.
22 |
23 | 4. Original Work. You represent that the Contributions are Your original works of authorship, and to Your knowledge, no other person claims, or has the right to claim, any intellectual property rights in or to the Contributions. You also represent that You are not legally obligated, whether by entering into an agreement or otherwise, in any way that conflicts with the terms of this license. For avoidance of doubt, Your Contribution is not subject to any agreement requiring You to assign the intellectual property rights to Your Contributions to an employer or customer.
24 |
25 | 5. Third Party Licenses. You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
26 |
27 | 6. We determine the code that is in our project. You understand that the decision to include the Contribution in any project or source repository is entirely that of Master Technology, and this agreement does not guarantee that the Contributions will be included in any product.
28 |
29 | 7. Support. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all.
30 |
31 | 8. No Implied Warranties. Master Technology acknowledges that, except as explicitly described in this Agreement, the Contribution is provided on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
32 |
33 | 9. Change in Circumstances. You agree to notify Master Technology of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
34 |
35 |
--------------------------------------------------------------------------------
/src/nativescript.webpack.js:
--------------------------------------------------------------------------------
1 | /**************************************************************************************
2 | * (c) 2021, Master Technology
3 | * Licensed under the MIT license or contact me for a support, changes, enhancements,
4 | * and/or if you require a commercial licensing
5 | *
6 | * Any questions please feel free to put a issue up on github
7 | * Nathan@master.technology http://nativescript.tools
8 | *************************************************************************************/
9 |
10 | /* global require, module */
11 | const fs = require('fs');
12 | const path = require('path');
13 |
14 | module.exports = webpack => {
15 |
16 | // Add all sqlite files
17 | webpack.Utils.addCopyRule('**/*.sqlite');
18 | webpack.Utils.addCopyRule('**/*.db');
19 |
20 | webpack.chainWebpack((config, env) => {
21 | // Update Externals to eliminate any warnings/errors during building
22 | const externals = config.get('externals');
23 | let hasSync = false, hasCom = false, hasEnc = false, hasKey = false;
24 |
25 | let dirname = path.resolve(__dirname, "../");
26 | if (!fs.existsSync(dirname+"/nativescript-sqlite-sync")) {
27 | console.warn("NativeScript-SQLite Sync not detected, disabling support!");
28 | externals.push('nativescript-sqlite-sync');
29 | } else {
30 | hasSync = true;
31 | }
32 | if (!fs.existsSync(dirname+"/nativescript-sqlite-commercial")) {
33 | console.warn("NativeScript-SQLite Commercial not detected, disabling support!");
34 | externals.push('nativescript-sqlite-commercial');
35 | externals.push('nativescript-sqlite-commercial/commercial-multi');
36 | } else {
37 | hasCom = true;
38 | }
39 | if (!fs.existsSync(dirname+"/nativescript-sqlite-encrypted")) {
40 | console.warn("NativeScript-SQLite Encrypted not detected, disabling support!");
41 | externals.push('nativescript-sqlite-encrypted');
42 | } else {
43 | hasEnc = true;
44 | }
45 | if (!fs.existsSync(dirname+"/nativescript-sqlite-nosql")) {
46 | console.warn("NativeScript-SQLite NoSQL/Keystore not detected, disabling support!");
47 | externals.push('nativescript-sqlite-keystore');
48 | } else {
49 | hasKey = true;
50 | }
51 |
52 | if (!hasCom && !hasSync && !hasEnc) {
53 | // Are you really that self centered to delete this code
54 | // after using our hard work for free in your project?
55 | advertise();
56 | }
57 |
58 | config.set('externals', externals);
59 |
60 | config.module
61 | .rule('workers')
62 | .exclude.clear();
63 |
64 | // Add TNS_WEBPACK to the defines...
65 | config.plugin('DefinePlugin').tap(args => {
66 | args[0]['global.TNS_WEBPACK'] = 5;
67 | args[0]['global._MT_HAS_SQLITE'] = (hasCom ? 1 : 0) + (hasEnc ? 2 : 0) + (hasSync ? 4 : 0) + (hasKey ? 8 : 0);
68 | return args;
69 | });
70 | });
71 | }
72 |
73 | // Time is money, We have spent a huge amount of time developing and testing this plugin.
74 | // This time is time you did not have to spend.
75 | // If you can't support us, financially at this point.
76 | // At least let our advertisements live so that maybe in the future when you get rich,
77 | // you will remember upon what foundations you built your empire. ;-)
78 | function advertise() {
79 | console.log("\r\n\r\n");
80 | console.log("***********************************************************************************");
81 | console.log("* Please support the developer of this open source plugins you are using. *");
82 | console.log("* *");
83 | console.log("* NativeScript-Sqlite *");
84 | console.log("* *");
85 | console.log("* You can purchase a commercial version (which also removes this message) at: *")
86 | console.log("* https://nativescript.tools *");
87 | console.log("***********************************************************************************");
88 | console.log("\r\n\r\n");
89 |
90 | // Are you really going to be so selfish, to delete any of our ad code now?
91 | for (let time = Date.now() + 5000; Date.now() < time; );
92 | }
93 |
--------------------------------------------------------------------------------
/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-sqlite",
3 | "version": "2.8.5",
4 | "description": "A sqlite NativeScript module for Android and iOS",
5 | "main": "sqlite",
6 | "nativescript": {
7 | "platforms": {
8 | "android": "1.4.0",
9 | "ios": "1.4.0"
10 | },
11 | "plugin": {
12 | "nan": "true",
13 | "pan": "true",
14 | "core3": "true",
15 | "core4": "true",
16 | "core5": "true",
17 | "core6": "true",
18 | "core7": "true",
19 | "core8": "true",
20 | "vue": "true",
21 | "category": "Database"
22 | }
23 | },
24 | "typings": "sqlite.d.ts",
25 | "repository": {
26 | "type": "git",
27 | "url": "https://github.com/nathanaela/nativescript-sqlite.git"
28 | },
29 | "keywords": [
30 | "NativeScript",
31 | "SQL",
32 | "SQLite",
33 | "SQLCipher",
34 | "Encrypted",
35 | "Database",
36 | "DB",
37 | "iOS",
38 | "Android",
39 | "JavaScript",
40 | "encryption",
41 | "multithreaded"
42 | ],
43 | "author": {
44 | "name": "Nathanael Anderson",
45 | "email": "nathan@master-technology.com"
46 | },
47 | "license": "MIT",
48 | "bugs": {
49 | "url": "https://github.com/nathanaela/nativescript-sqlite/issues"
50 | },
51 | "homepage": "https://github.com/nathanaela/nativescript-sqlite",
52 | "readmeFilename": "README.md"
53 | }
54 |
--------------------------------------------------------------------------------
/src/platforms/ios/build.xcconfig:
--------------------------------------------------------------------------------
1 | HEADER_SEARCH_PATHS = $(inherited) ${PROJECT_DIR}/../../node_modules/nativescript-sqlite/platforms/ios
2 |
--------------------------------------------------------------------------------
/src/platforms/ios/module.modulemap:
--------------------------------------------------------------------------------
1 | module sqlite3 [system] {
2 | header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
3 | link "sqlite3"
4 | link "libsqlite3"
5 | export *
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/src/sqlite-internal.android.js:
--------------------------------------------------------------------------------
1 | /**************************************************************************************
2 | * (c) 2015-2021, Master Technology
3 | * Licensed under the MIT license or contact me for a support, changes, enhancements,
4 | * and/or if you require a commercial licensing
5 | *
6 | * Any questions please feel free to put a issue up on github
7 | * Nathan@master-technology.com http://nativescript.tools
8 | * Version 2.7.0 - Android
9 | *************************************************************************************/
10 | /* global global, require, module */
11 |
12 | "use strict";
13 |
14 | const appModule = require("@nativescript/core/application");
15 | const fsModule = require("@nativescript/core/file-system");
16 |
17 |
18 | //import * as appModule from '@nativescript/core/application';
19 | //import * as fsModule from '@nativescript/core/file-system';
20 |
21 | /*jshint undef: true */
22 | /*global java, android, Promise */
23 |
24 | // Needed for Creating Database - Android Specific flag
25 | //var CREATEIFNEEDED = 0x10000000;
26 |
27 | // Used to track any plugin Init
28 | let _DatabasePluginInits = [];
29 |
30 |
31 | /***
32 | * Parses a Row of data into a JS Array (as Native)
33 | * @param cursor {Object}
34 | * @returns {Array}
35 | */
36 | function DBGetRowArrayNative(cursor) {
37 | //noinspection JSUnresolvedFunction
38 | let count = cursor.getColumnCount();
39 | let results = [];
40 | for (let i=0;i {
371 | if (typeof valueOrCallback === 'function') {
372 | this.get('PRAGMA user_version', function (err, data) {
373 | const value = data && parseInt(data[0], 10);
374 | valueOrCallback(err, value);
375 | if (err) { reject(err); }
376 | else resolve(value);
377 | }, Database.RESULTSASARRAY);
378 | } else if (!isNaN(valueOrCallback + 0)) {
379 | this.execSQL('PRAGMA user_version=' + (valueOrCallback + 0).toString()).then(resolve, reject);
380 | } else {
381 | this.get('PRAGMA user_version', undefined, undefined, Database.RESULTSASARRAY).then((data) => {
382 | resolve(data && parseInt(data[0], 10))
383 | }).catch(reject);
384 | }
385 | });
386 | };
387 |
388 | /***
389 | * Is the database currently open
390 | * @returns {boolean} - true if the db is open
391 | */
392 | Database.prototype.isOpen = function() {
393 | return this._isOpen;
394 | };
395 |
396 | /***
397 | * Gets/Sets whether you get Arrays or Objects for the row values
398 | * @param value - Database.RESULTSASARRAY or Database.RESULTSASOBJECT
399 | * @returns {number} - Database.RESULTSASARRAY or Database.RESULTSASOBJECT
400 | */
401 | Database.prototype.resultType = function(value) {
402 | if (value === Database.RESULTSASARRAY) {
403 | this._resultType = Database.RESULTSASARRAY;
404 | setResultValueTypeEngine(this._resultType, this._valuesType);
405 |
406 | } else if (value === Database.RESULTSASOBJECT) {
407 | this._resultType = Database.RESULTSASOBJECT;
408 | setResultValueTypeEngine(this._resultType, this._valuesType);
409 | }
410 | return this._resultType;
411 | };
412 |
413 | /***
414 | * Gets/Sets whether you get Native or Strings for the row values
415 | * @param value - Database.VALUESARENATIVE or Database.VALUESARESTRINGS
416 | * @returns {number} - Database.VALUESARENATIVE or Database.VALUESARESTRINGS
417 | */
418 | Database.prototype.valueType = function(value) {
419 | if (value === Database.VALUESARENATIVE) {
420 | this._valuesType = Database.VALUESARENATIVE;
421 | setResultValueTypeEngine(this._resultType, this._valuesType);
422 |
423 | } else if (value === Database.VALUESARESTRINGS) {
424 | this._valuesType = Database.VALUESARESTRINGS;
425 | setResultValueTypeEngine(this._resultType, this._valuesType);
426 | }
427 | return this._valuesType;
428 | };
429 |
430 | // noinspection JSUnusedLocalSymbols
431 | /**
432 | * Dummy transaction function for public version
433 | * @param callback
434 | * @returns {Promise}
435 | */
436 | Database.prototype.begin = function(callback) {
437 | throw new Error("Transactions are a Commercial version feature.");
438 | };
439 |
440 | // noinspection JSUnusedLocalSymbols
441 | /**
442 | * Dummy prepare function for public version
443 | * @param sql
444 | * @returns {*}
445 | */
446 | Database.prototype.prepare = function(sql) {
447 | throw new Error("Prepared statements are a Commercial version feature.");
448 | };
449 |
450 |
451 | // noinspection JSUnusedLocalSymbols
452 | /**
453 | * Dummy sync enable tracking function for public version
454 | * @returns {*}
455 | */
456 | Database.prototype.enableTracking = function(tables, options, callback) {
457 | throw new Error("Table sync is a Commercial version feature.");
458 | };
459 |
460 |
461 | /***
462 | * Closes this database, any queries after this will fail with an error
463 | * @param callback
464 | */
465 | Database.prototype.close = function(callback) {
466 |
467 | const self = this;
468 | return new Promise(function(resolve, reject) {
469 | if (!self._isOpen) {
470 | if (callback) {
471 | callback('SQLITE.CLOSE - Database is already closed');
472 | }
473 | reject('SQLITE.CLOSE - Database is already closed');
474 | return;
475 | }
476 |
477 | self._db.close();
478 | self._isOpen = false;
479 | if (callback) {
480 | callback(null, null);
481 | }
482 | resolve();
483 | });
484 | };
485 |
486 | /***
487 | * Exec SQL
488 | * @param sql - sql to use
489 | * @param params - optional array of parameters
490 | * @param callback - (err, result) - can be last_row_id for insert, and rows affected for update/delete
491 | * @returns Promise
492 | */
493 | Database.prototype.execSQL = function(sql, params, callback) {
494 | if (typeof params === 'function') {
495 | callback = params;
496 | params = undefined;
497 | }
498 |
499 | const self = this;
500 | return new Promise(function(resolve, reject) {
501 | let hasCallback = true;
502 | if (typeof callback !== 'function') {
503 | callback = reject;
504 | hasCallback = false;
505 | }
506 |
507 | if (!self._isOpen) {
508 | callback("SQLITE.EXECSQL - Database is not open");
509 | return;
510 | }
511 |
512 | // Need to see if we have to run any status queries afterwords
513 | let flags = 0;
514 | let test = sql.trim().substr(0, 7).toLowerCase();
515 | if (test === 'insert ') {
516 | flags = 1;
517 | } else if (test === 'update ' || test === 'delete ') {
518 | flags = 2;
519 | }
520 |
521 | try {
522 | if (params !== undefined) {
523 | self._db.execSQL(sql, self._toStringArray(params));
524 | } else {
525 | self._db.execSQL(sql);
526 | }
527 | } catch (Err) {
528 | callback(Err, null);
529 | return;
530 | }
531 |
532 | switch (flags) {
533 | case 0:
534 | if (hasCallback) {
535 | callback(null, null);
536 | }
537 | resolve(null);
538 | break;
539 | case 1:
540 | // noinspection JSIgnoredPromiseFromCall
541 | self.get('select last_insert_rowid()', function (err, data) {
542 | if (hasCallback) {
543 | callback(err, data && data[0]);
544 | }
545 | if (err) {
546 | reject(err);
547 | } else {
548 | resolve(data && data[0]);
549 | }
550 | }, Database.RESULTSASARRAY | Database.VALUESARENATIVE);
551 | break;
552 | case 2:
553 | // noinspection JSIgnoredPromiseFromCall
554 | self.get('select changes()', function (err, data) {
555 | if (hasCallback) {
556 | callback(err, data && data[0]);
557 | }
558 | if (err) {
559 | reject(err);
560 | } else {
561 | resolve(data && data[0]);
562 | }
563 | }, Database.RESULTSASARRAY | Database.VALUESARENATIVE);
564 | break;
565 | default:
566 | resolve();
567 | }
568 |
569 | });
570 | };
571 |
572 | /***
573 | * Get the first record result set
574 | * @param sql - sql to run
575 | * @param params - optional
576 | * @param callback - callback (error, results)
577 | * @param mode - allows you to manually override the results set to be a array or object
578 | * @returns Promise
579 | */
580 | Database.prototype.get = function(sql, params, callback, mode) {
581 | if (typeof params === 'function') {
582 | mode = callback;
583 | callback = params;
584 | params = undefined;
585 | }
586 |
587 | const self = this;
588 | return new Promise(function(resolve, reject) {
589 | let hasCallback = true;
590 | if (typeof callback !== 'function') {
591 | callback = reject;
592 | hasCallback = false;
593 | }
594 |
595 | if (!self._isOpen) {
596 | callback("SQLITE.GET - Database is not open", null);
597 | return;
598 | }
599 |
600 | let cursor;
601 | try {
602 | if (params !== undefined) {
603 | //noinspection JSUnresolvedFunction
604 | cursor = self._db.rawQuery(sql, self._toStringArray(params));
605 | } else {
606 | //noinspection JSUnresolvedFunction
607 | cursor = self._db.rawQuery(sql, null);
608 | }
609 | } catch (err) {
610 | callback(err, null);
611 | return;
612 | }
613 |
614 | // No Records
615 | // noinspection JSUnresolvedFunction
616 | if (cursor.getCount() === 0) {
617 | cursor.close();
618 | if (hasCallback) {
619 | callback(null, null);
620 | }
621 | resolve(null);
622 | return;
623 | }
624 |
625 | let results;
626 | const resultEngine = self._getResultEngine(mode);
627 | try {
628 | //noinspection JSUnresolvedFunction
629 | cursor.moveToFirst();
630 | results = resultEngine(cursor);
631 | cursor.close();
632 | } catch (err) {
633 | callback(err, null);
634 | return;
635 | }
636 | if (hasCallback) {
637 | callback(null, results);
638 | }
639 | resolve(results);
640 | });
641 | };
642 |
643 | Database.prototype._getResultEngine = function(mode) {
644 | if (mode == null || mode === 0) {
645 | mode = this._resultType | this._valuesType;
646 | }
647 |
648 | let resultType = (mode & (Database.RESULTSASARRAY|Database.RESULTSASOBJECT));
649 | if (resultType === 0) {
650 | resultType = this._resultType;
651 | }
652 | let valueType = (mode & (Database.VALUESARENATIVE|Database.VALUESARESTRINGS));
653 | if (valueType === 0) {
654 | valueType = this._valuesType;
655 | }
656 |
657 | if (resultType === Database.RESULTSASOBJECT) {
658 | if (valueType === Database.VALUESARESTRINGS) {
659 | return DBGetRowObjectString;
660 | } else {
661 | return DBGetRowObjectNative;
662 | }
663 | } else {
664 | if (valueType === Database.VALUESARESTRINGS) {
665 | return DBGetRowArrayString;
666 | } else {
667 | return DBGetRowArrayNative;
668 | }
669 | }
670 |
671 | };
672 |
673 | /***
674 | * This returns the entire result set in a array of rows
675 | * @param sql - Sql to run
676 | * @param params - optional
677 | * @param callback - (err, results)
678 | * @param mode - Allow you to force a specific mode
679 | * @returns Promise
680 | */
681 | Database.prototype.all = function(sql, params, callback, mode) {
682 | if (typeof params === 'function') {
683 | mode = callback;
684 | callback = params;
685 | params = undefined;
686 | }
687 |
688 | const self = this;
689 | return new Promise(function(resolve, reject) {
690 | let hasCallback = true;
691 | if (typeof callback !== 'function') {
692 | callback = reject;
693 | hasCallback = false;
694 | }
695 |
696 | if (!self._isOpen) {
697 | callback("SQLITE.ALL - Database is not open");
698 | return;
699 | }
700 |
701 | let cursor, count;
702 | try {
703 | if (params !== undefined) {
704 | //noinspection JSUnresolvedFunction
705 | cursor = self._db.rawQuery(sql, self._toStringArray(params));
706 | } else {
707 | //noinspection JSUnresolvedFunction
708 | cursor = self._db.rawQuery(sql, null);
709 | }
710 | // noinspection JSUnresolvedFunction
711 | count = cursor.getCount();
712 | } catch (err) {
713 | callback(err);
714 | return;
715 | }
716 |
717 |
718 | // No Records
719 | if (count === 0) {
720 | cursor.close();
721 | if (hasCallback) {
722 | callback(null, []);
723 | }
724 | resolve([]);
725 | return;
726 | }
727 | //noinspection JSUnresolvedFunction
728 | cursor.moveToFirst();
729 |
730 | const resultEngine = self._getResultEngine(mode);
731 |
732 |
733 |
734 | let results = [];
735 | try {
736 | for (let i = 0; i < count; i++) {
737 | const data = resultEngine(cursor); // jshint ignore:line
738 | results.push(data);
739 | //noinspection JSUnresolvedFunction
740 | cursor.moveToNext();
741 | }
742 | cursor.close();
743 | } catch (err) {
744 | callback(err);
745 | return;
746 | }
747 | if (hasCallback) {
748 | callback(null, results);
749 | }
750 | resolve(results);
751 | });
752 | };
753 |
754 | /***
755 | * This sends each row of the result set to the "Callback" and at the end calls the complete callback upon completion
756 | * @param sql - sql to run
757 | * @param params - optional
758 | * @param callback - callback (err, rowsResult)
759 | * @param complete - callback (err, recordCount)
760 | * @returns Promise
761 | */
762 | Database.prototype.each = function(sql, params, callback, complete) {
763 | if (typeof params === 'function') {
764 | complete = callback;
765 | callback = params;
766 | params = undefined;
767 | }
768 |
769 | // Callback is required
770 | if (typeof callback !== 'function') {
771 | throw new Error("SQLITE.EACH - requires a callback");
772 | }
773 |
774 | const self = this;
775 | return new Promise(function (resolve, reject) {
776 |
777 | // Set the error Callback
778 | let errorCB = complete || callback;
779 |
780 | let cursor, count;
781 | try {
782 | if (params !== undefined) {
783 | //noinspection JSUnresolvedFunction
784 | cursor = self._db.rawQuery(sql, self._toStringArray(params));
785 | } else {
786 | //noinspection JSUnresolvedFunction
787 | cursor = self._db.rawQuery(sql, null);
788 | }
789 | // noinspection JSUnresolvedFunction
790 | count = cursor.getCount();
791 | } catch (err) {
792 | errorCB(err, null);
793 | reject(err);
794 | return;
795 | }
796 |
797 | // No Records
798 | if (count === 0) {
799 | cursor.close();
800 | if (complete) {
801 | complete(null, 0);
802 | }
803 | resolve(0);
804 | return;
805 | }
806 | //noinspection JSUnresolvedFunction
807 | cursor.moveToFirst();
808 |
809 | try {
810 | for (let i = 0; i < count; i++) {
811 | const data = DBGetRowResults(cursor); // jshint ignore:line
812 | callback(null, data);
813 | //noinspection JSUnresolvedFunction
814 | cursor.moveToNext();
815 | }
816 | cursor.close();
817 | } catch (err) {
818 | errorCB(err, null);
819 | reject(err);
820 | return;
821 | }
822 | if (complete) {
823 | complete(null, count);
824 | }
825 | resolve(count);
826 | });
827 | };
828 |
829 | /***
830 | * Converts a Mixed Array to a String Array
831 | * @param paramsIn
832 | * @returns {Array}
833 | * @private
834 | */
835 | Database.prototype._toStringArray = function(paramsIn) {
836 | let stringParams = [], params;
837 | if (Object.prototype.toString.apply(paramsIn) !== '[object Array]') {
838 | params = [paramsIn];
839 | } else {
840 | params = paramsIn;
841 | }
842 |
843 | const count = params.length;
844 | for (let i = 0; i < count; ++i) {
845 | if (params[i] == null) { // jshint ignore:line
846 | stringParams.push(null);
847 | } else if (params[i].getClass) {
848 | switch (params[i].getClass().getSimpleName()) {
849 | case "ByteArrayOutputStream":
850 | stringParams.push(params[i].toByteArray());
851 | break;
852 | case "byte[]":
853 | stringParams.push(params[i]);
854 | break;
855 | default:
856 | console.warn("Unknown Java class:", params[i].getClass().getSimpleName(), "Converting to string");
857 | stringParams.push(params[i].toString());
858 | }
859 | } else {
860 | stringParams.push(params[i].toString());
861 | }
862 | }
863 |
864 | return stringParams;
865 | };
866 |
867 | Database.prototype.notify = function(type, message) {
868 | if (typeof global.postMessage === 'function') {
869 | postMessage({id: -2, type: type, message: message});
870 | } else {
871 | console.error("SQLite: Not in a thread");
872 |
873 | // Local Notify
874 | this._notify(type, message);
875 | }
876 | };
877 |
878 | Database.prototype._notify = function(type, message) {
879 | if (type == null || typeof this._messageHandlers[type] === "undefined") {
880 | return;
881 | }
882 | let handlers = this._messageHandlers[type];
883 | try {
884 | for (let i = 0; i < handlers; i++) {
885 | handlers[i](message, type, this);
886 | }
887 | } catch (err) {
888 | console.error("SQLite: Error in user code ", err, err.stack);
889 | }
890 | }
891 |
892 | Database.prototype.addMessageHandler = function(type, callback) {
893 | if (typeof this._messageHandlers[type] === 'undefined') {
894 | this._messageHandlers[type] = [];
895 | }
896 | this._messageHandlers[type].push(callback);
897 | };
898 |
899 | Database.prototype.removeMessageHandler = function(type, callback) {
900 | if (type != null && typeof this._messageHandlers[type] === "undefined") {
901 | console.error("SQLite: This message handler " + type + " does not exist.");
902 | return;
903 | }
904 |
905 | if (callback) {
906 | // Remove all message handles that match this callback & this db...
907 | for (let i = 0; i < this._messageHandlers[type].length; i++) {
908 | if (this._messageHandlers[type][i].callback === callback) {
909 | this._messageHandlers[type].splice(i, 1);
910 | i--;
911 | }
912 | }
913 | } else if (type != null) {
914 | // Remove all message handlers for this type
915 | this._messageHandlers[type] = [];
916 | } else {
917 | // Remove all message handlers for this database
918 | this._messageHandlers = [];
919 | }
920 | };
921 |
922 | /***
923 | * Is this a SQLite object
924 | * @param obj - possible sqlite object to check
925 | * @returns {boolean}
926 | */
927 | Database.isSqlite = function(obj) {
928 | return obj && obj._isSqlite;
929 | };
930 |
931 | /**
932 | * Does this database exist on disk
933 | * @param name
934 | * @returns {*}
935 | */
936 | Database.exists = function(name) {
937 | //noinspection JSUnresolvedFunction
938 | const dbName = _getContext().getDatabasePath(name).getAbsolutePath();
939 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
940 | const dbFile = new java.io.File(dbName);
941 | // noinspection JSUnresolvedFunction
942 | return dbFile.exists();
943 | };
944 |
945 | /**
946 | * Delete the database file if it exists
947 | * @param name
948 | */
949 | Database.deleteDatabase = function(name) {
950 | //noinspection JSUnresolvedFunction
951 | const dbName = _getContext().getDatabasePath(name).getAbsolutePath();
952 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
953 | let dbFile = new java.io.File(dbName);
954 | if (dbFile.exists()) {
955 | dbFile.delete();
956 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
957 | dbFile = new java.io.File(dbName + '-journal');
958 | if (dbFile.exists()) {
959 | dbFile.delete();
960 | }
961 | }
962 | };
963 |
964 | Database.manualBackup = function(name) {
965 | const dbName = _getContext().getDatabasePath(name).getAbsolutePath();
966 | let dbFile = new java.io.File(dbName);
967 | let myInput = new java.io.FileInputStream(dbName);
968 | if (dbFile.exists()) {
969 |
970 | // Attempt to use the local app directory version
971 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
972 | const outPath = android.os.Environment.getExternalStoragePublicDirectory (android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/" + name;
973 | let myOutput = new java.io.FileOutputStream( outPath );
974 | let success = true;
975 | try {
976 | //transfer bytes from the input file to the output file
977 | //noinspection JSUnresolvedFunction,JSUnresolvedVariable
978 | let buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.class.getField("TYPE").get(null), 1024);
979 | let length;
980 | while ((length = myInput.read(buffer)) > 0) {
981 | // noinspection JSUnresolvedFunction
982 | myOutput.write(buffer, 0, length);
983 | }
984 | }
985 | catch (err) {
986 | success = false;
987 | }
988 |
989 | //Close the streams
990 | // noinspection JSUnresolvedFunction
991 | myOutput.flush();
992 | // noinspection JSUnresolvedFunction
993 | myOutput.close();
994 | myInput.close();
995 | return success;
996 | }
997 |
998 | };
999 |
1000 | /**
1001 | * Copy the database from the install location
1002 | * @param name
1003 | * @param destName - Optional DB Destination Name
1004 | */
1005 | Database.copyDatabase = function (name, destName) {
1006 |
1007 | //Open your local db as the input stream
1008 | let myInput;
1009 | try {
1010 |
1011 | let sourcePath, tempName;
1012 | if (name.indexOf('/') === -1) {
1013 | sourcePath = fsModule.knownFolders.currentApp().path + '/';
1014 | tempName = name;
1015 | } else {
1016 | sourcePath = name.substr(0, name.lastIndexOf('/') + 1);
1017 | tempName = name.substr(sourcePath.length);
1018 | }
1019 |
1020 | // Attempt to use the local app directory version
1021 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
1022 | myInput = new java.io.FileInputStream(sourcePath + tempName);
1023 | } catch (err) {
1024 | // Use the Assets version
1025 | // noinspection JSUnresolvedFunction
1026 | myInput = _getContext().getAssets().open("app/" + name);
1027 | }
1028 |
1029 | if (name.indexOf('/') >= 0) {
1030 | name = name.substring(name.lastIndexOf('/') + 1);
1031 | }
1032 |
1033 | // If we don't have a destName set; use Name
1034 | if (!destName) { destName = name; }
1035 | else if (destName.indexOf("/") >= 0) {
1036 | destName = destName.substring(destName.lastIndexOf('/') + 1);
1037 | }
1038 |
1039 | //noinspection JSUnresolvedFunction
1040 | const dbName = _getContext().getDatabasePath(destName).getAbsolutePath();
1041 | const path = dbName.substr(0, dbName.lastIndexOf('/') + 1);
1042 |
1043 | // Create "databases" folder if it is missing. This causes issues on Emulators if it is missing
1044 | // So we create it if it is missing
1045 |
1046 | try {
1047 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
1048 | const javaFile = new java.io.File(path);
1049 | //noinspection JSUnresolvedFunction
1050 | if (!javaFile.exists()) {
1051 | //noinspection JSUnresolvedFunction
1052 | javaFile.mkdirs();
1053 | //noinspection JSUnresolvedFunction
1054 | javaFile.setReadable(true);
1055 | //noinspection JSUnresolvedFunction
1056 | javaFile.setWritable(true);
1057 | }
1058 | } catch (err) {
1059 | console.info("SQLITE - COPYDATABASE - Creating DB Folder Error", err);
1060 | }
1061 |
1062 | //Open the empty db as the output stream
1063 | // noinspection JSUnresolvedFunction,JSUnresolvedVariable
1064 | const myOutput = new java.io.FileOutputStream(dbName);
1065 |
1066 |
1067 | let success = true;
1068 | try {
1069 | //transfer bytes from the input file to the output file
1070 | //noinspection JSUnresolvedFunction,JSUnresolvedVariable
1071 | let buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.class.getField("TYPE").get(null), 1024);
1072 | let length;
1073 | while ((length = myInput.read(buffer)) > 0) {
1074 | // noinspection JSUnresolvedFunction
1075 | myOutput.write(buffer, 0, length);
1076 | }
1077 | } catch (err) {
1078 | success = false;
1079 | }
1080 |
1081 |
1082 | //Close the streams
1083 | // noinspection JSUnresolvedFunction
1084 | myOutput.flush();
1085 | // noinspection JSUnresolvedFunction
1086 | myOutput.close();
1087 | myInput.close();
1088 | return success;
1089 | };
1090 |
1091 | // Literal Defines
1092 | Database.prototype.RESULTSASARRAY = Database.RESULTSASARRAY = 1;
1093 | Database.prototype.RESULTSASOBJECT = Database.RESULTSASOBJECT = 2;
1094 | Database.prototype.VALUESARENATIVE = Database.VALUESARENATIVE = 4;
1095 | Database.prototype.VALUESARESTRINGS = Database.VALUESARESTRINGS = 8;
1096 |
1097 | TryLoadingCommercialPlugin();
1098 | TryLoadingEncryptionPlugin();
1099 | TryLoadingSyncPlugin();
1100 |
1101 | module.exports = Database;
1102 |
1103 | /**
1104 | * gets the current application context
1105 | * @returns {*}
1106 | * @private
1107 | */
1108 | function _getContext() {
1109 | try {
1110 | if (appModule.android.context) {
1111 | return (appModule.android.context);
1112 | }
1113 | if (typeof appModule.getNativeApplication === 'function') {
1114 | let ctx = appModule.getNativeApplication();
1115 | if (ctx) {
1116 | return ctx;
1117 | }
1118 | }
1119 | } catch (err) {
1120 | console.log("SQLITE: Using Fallback");
1121 | // In some cases Multidex has been the report
1122 | // the getNativeApplication calls .getInstance which fails
1123 | }
1124 |
1125 | //noinspection JSUnresolvedFunction,JSUnresolvedVariable
1126 | let ctx = java.lang.Class.forName("android.app.AppGlobals").getMethod("getInitialApplication", null).invoke(null, null);
1127 | if (ctx) return ctx;
1128 |
1129 | //noinspection JSUnresolvedFunction,JSUnresolvedVariable
1130 | ctx = java.lang.Class.forName("android.app.ActivityThread").getMethod("currentApplication", null).invoke(null, null);
1131 |
1132 | return ctx;
1133 | }
1134 |
1135 | /** Uses a SQLite Plugin **/
1136 | function UsePlugin(loadedSrc, DBModule) {
1137 | if (loadedSrc.prototypes) {
1138 | for (let key in loadedSrc.prototypes) {
1139 | if (!loadedSrc.prototypes.hasOwnProperty(key)) { continue; }
1140 | if (DBModule.prototype[key]) {
1141 | DBModule.prototype["_"+key] = DBModule.prototype[key];
1142 | }
1143 | DBModule.prototype[key] = loadedSrc.prototypes[key];
1144 | }
1145 | }
1146 | if (loadedSrc.statics) {
1147 | for (let key in loadedSrc.statics) {
1148 | if (!loadedSrc.statics.hasOwnProperty(key)) { continue; }
1149 | DBModule[key] = loadedSrc.statics[key];
1150 | }
1151 | }
1152 | if (typeof loadedSrc.init === 'function') {
1153 | _DatabasePluginInits.push(loadedSrc.init);
1154 | }
1155 | }
1156 |
1157 | function TryLoadingCommercialPlugin() {
1158 | try {
1159 | const sqlCom = require('nativescript-sqlite-commercial');
1160 | UsePlugin(sqlCom, Database);
1161 | }
1162 | catch (e) {
1163 | /* Do Nothing if it doesn't exist as it is an optional plugin */
1164 | }
1165 | }
1166 |
1167 | function TryLoadingEncryptionPlugin() {
1168 | try {
1169 | const sqlEnc = require('nativescript-sqlite-encrypted');
1170 | UsePlugin(sqlEnc, Database);
1171 | }
1172 | catch (e) {
1173 | /* Do Nothing if it doesn't exist as it is an optional plugin */
1174 | }
1175 | }
1176 |
1177 | function TryLoadingSyncPlugin() {
1178 | try {
1179 | const sqlSync = require('nativescript-sqlite-sync');
1180 | UsePlugin(sqlSync, Database);
1181 | }
1182 | catch (e) {
1183 | /* Do Nothing if it doesn't exist as it is an optional plugin */
1184 | }
1185 | }
1186 |
1187 |
--------------------------------------------------------------------------------
/src/sqlite-internal.ios.js:
--------------------------------------------------------------------------------
1 | /************************************************************************************
2 | * (c) 2015-2021 Master Technology
3 | * Licensed under the MIT license or contact me for a support, changes, enhancements,
4 | * and/or if you require a commercial licensing
5 | *
6 | * Any questions please feel free to email me or put a issue up on github
7 | * Nathan@master-technology.com http://nativescript.tools
8 | * Version 2.7.0 - iOS
9 | ***********************************************************************************/
10 | /* global global, require, module */
11 |
12 | "use strict";
13 | const fs = require('@nativescript/core/file-system');
14 |
15 | /* jshint undef: true, camelcase: false */
16 | /* global Promise, NSFileManager, NSBundle, NSString, interop, sqlite3_open_v2, sqlite3_close, sqlite3_prepare_v2, sqlite3_step,
17 | sqlite3_finalize, sqlite3_bind_null, sqlite3_bind_text, sqlite3_column_type, sqlite3_column_int64,
18 | sqlite3_column_double, sqlite3_column_text, sqlite3_column_count, sqlite3_column_name, sqlite3_bind_blob */
19 |
20 | let _DatabasePluginInits = [];
21 | const TRANSIENT = new interop.Pointer(-1);
22 |
23 |
24 | /***
25 | * Converts a string to a UTF-8 char array and wraps it in an adopted pointer
26 | * (which is GC managed and kept alive until it's referenced by a variable).
27 | * The reason for doing it is that iOS runtime marshals JS string arguments via
28 | * temporary buffers which are deallocated immediately after the call returns. In
29 | * some cases however, we need them to stay alive for subsequent native calls
30 | * because otherwise attempts to read the freed memory may lead to unpredictable
31 | * app crashes.
32 | * E.g. `sqlite3_step` function happens to use the stored `char *` passed as
33 | * `dbname` to `sqlite3_open_v2`.
34 | * @param str
35 | * @returns {AdoptedPointer} object
36 | */
37 | function toCharPtr(str) {
38 | const objcStr = NSString.stringWithString(str);
39 | // UTF8 strings can be encoded in 4 byte representing each character
40 | // We are wasting a few bytes of memory, just to make sure we have enough room to copy it...
41 | const bufferSize = ((str.length) * 4) + 1;
42 | const buffer = interop.alloc(bufferSize);
43 |
44 | objcStr.getCStringMaxLengthEncoding(buffer, bufferSize, NSUTF8StringEncoding);
45 |
46 | return buffer;
47 | }
48 |
49 | /***
50 | * Creates a Cursor Tracking Statement for reading result sets
51 | * @param statement
52 | * @param resultType
53 | * @param valuesType
54 | * @constructor
55 | */
56 | function CursorStatement(statement, resultType, valuesType) {
57 | this.statement = statement;
58 | this.resultType = resultType;
59 | this.valuesType = valuesType;
60 | this.built = false;
61 | this.columns = [];
62 | }
63 |
64 | //noinspection JSValidateJSDoc
65 | /***
66 | * Database Constructor
67 | * @param dbname - Database Name
68 | * @param options - options
69 | * @param callback - Callback when Done
70 | * @returns {Promise} object
71 | * @constructor
72 | */
73 | function Database(dbname, options, callback) {
74 | if (!(this instanceof Database)) { // jshint ignore:line
75 | //noinspection JSValidateTypes
76 | return new Database(dbname, options, callback);
77 | }
78 | this._messageHandlers = [];
79 | this._isOpen = false;
80 | this._resultType = Database.RESULTSASARRAY;
81 | this._valuesType = Database.VALUESARENATIVE;
82 |
83 | if (typeof options === 'function') {
84 | callback = options;
85 | options = {};
86 | } else {
87 | options = options || {};
88 | }
89 |
90 | this._options = options;
91 |
92 | // Check to see if it has a path, or if it is a relative dbname
93 | // DBNAME = "" - is a Temporary Database
94 | // DBNAME = ":memory:" - is a Memory only database
95 | if (dbname !== "" && dbname !== ":memory:") {
96 | let path;
97 | if (dbname.indexOf('/') === -1) {
98 | // noinspection JSUnresolvedVariable, JSUnresolvedFunction
99 | path = fs.knownFolders.documents().path;
100 | dbname = path + '/' + dbname;
101 | } else {
102 | path = dbname.substr(0, dbname.lastIndexOf('/') + 1);
103 | }
104 |
105 | // Create "databases" folder if it is missing. This causes issues on Emulators if it is missing
106 | // So we create it if it is missing
107 |
108 | try {
109 | // noinspection JSUnresolvedVariable
110 | if (!fs.File.exists(path)) {
111 | //noinspection JSUnresolvedFunction
112 | const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
113 | //noinspection JSUnresolvedFunction
114 | if (!fileManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(path, true, null, null)) {
115 | console.warn("SQLITE.CONSTRUCTOR - Creating DB Folder Error");
116 | }
117 | }
118 | }
119 | catch (err) {
120 | console.warn("SQLITE.CONSTRUCTOR - Creating DB Folder Error", err);
121 | }
122 | }
123 | this._dbnamePtr = toCharPtr(dbname);
124 | const self = this;
125 | //noinspection JSUnresolvedFunction
126 | return new Promise(function (resolve, reject) {
127 | let error;
128 | try {
129 | let flags = 0;
130 | if (typeof options.iosFlags !== 'undefined') {
131 | flags = options.iosFlags;
132 | }
133 |
134 | self._db = new interop.Reference();
135 | if (options && options.readOnly) {
136 | // SQLITE_OPEN_FULLMUTEX = 65536, SQLITE_OPEN_READONLY = 1 ---- 1 | 65536 = 65537
137 | error = sqlite3_open_v2(self._dbnamePtr, self._db, 65537 | flags, null);
138 | } else {
139 | // SQLITE_OPEN_FULLMUTEX = 65536, SQLITE_OPEN_CREATE = 4, SQLITE_OPEN_READWRITE = 2 --- 4 | 2 | 65536 = 65542
140 | error = sqlite3_open_v2(self._dbnamePtr, self._db, 65542 | flags, null);
141 | }
142 | self._db = self._db.value;
143 | } catch (err) {
144 | if (callback) { callback(err, null); }
145 | reject(err);
146 | return;
147 | }
148 | if (error) {
149 | if (callback) { callback(error, null); }
150 | reject(error);
151 | return;
152 | }
153 |
154 | self._isOpen = true;
155 |
156 | let doneCnt = _DatabasePluginInits.length, doneHandled = 0;
157 | const done = function(err) {
158 | if (err) {
159 | doneHandled = doneCnt; // We don't want any more triggers after this
160 | if (callback) { callback(err, null); }
161 | reject(err);
162 | return;
163 | }
164 | doneHandled++;
165 | if (doneHandled === doneCnt) {
166 | if (callback) { callback(null, self); }
167 | resolve(self);
168 | }
169 | };
170 |
171 | if (doneCnt) {
172 | try {
173 | for (let i = 0; i < doneCnt; i++) {
174 | _DatabasePluginInits[i].call(self, options, done);
175 | }
176 | } catch (err) {
177 | done(err);
178 | }
179 | } else {
180 | if (callback) { callback(null, self); }
181 | resolve(self);
182 | }
183 |
184 | });
185 | }
186 |
187 | /***
188 | * Constant that this structure is a sqlite structure
189 | * @type {boolean}
190 | */
191 | Database.prototype._isSqlite = true;
192 |
193 | /***
194 | * This gets or sets the database version
195 | * @param valueOrCallback to set or callback(err, version)
196 | * @returns Promise
197 | */
198 | Database.prototype.version = function(valueOrCallback) {
199 | return new Promise((resolve, reject) => {
200 | if (typeof valueOrCallback === 'function') {
201 | this.get('PRAGMA user_version', function (err, data) {
202 | const value = data && parseInt(data[0], 10);
203 | valueOrCallback(err, value);
204 | if (err) { reject(err); }
205 | else resolve(value);
206 | }, Database.RESULTSASARRAY);
207 | } else if (!isNaN(valueOrCallback + 0)) {
208 | this.execSQL('PRAGMA user_version=' + (valueOrCallback + 0).toString()).then(resolve, reject);
209 | } else {
210 | this.get('PRAGMA user_version', undefined, undefined, Database.RESULTSASARRAY).then((data) => {
211 | resolve(data && parseInt(data[0], 10))
212 | }).catch(reject);
213 | }
214 | });
215 | };
216 |
217 | /***
218 | * Is the database currently open
219 | * @returns {boolean} - true if the db is open
220 | */
221 | Database.prototype.isOpen = function() {
222 | return this._isOpen;
223 | };
224 |
225 | /***
226 | * Gets/Sets whether you get Arrays or Objects for the row values
227 | * @param value - Database.RESULTSASARRAY or Database.RESULTSASOBJECT
228 | * @returns {number} - Database.RESULTSASARRAY or Database.RESULTSASOBJECT
229 | */
230 | Database.prototype.resultType = function(value) {
231 | if (value === Database.RESULTSASARRAY) {
232 | this._resultType = Database.RESULTSASARRAY;
233 | } else if (value === Database.RESULTSASOBJECT) {
234 | this._resultType = Database.RESULTSASOBJECT;
235 | }
236 | return this._resultType;
237 | };
238 |
239 | /***
240 | * Gets/Sets whether you get Native or Strings for the row values
241 | * @param value - Database.VALUESARENATIVE or Database.VALUESARESTRINGS
242 | * @returns {number} - Database.VALUESARENATIVE or Database.VALUESARESTRINGS
243 | */
244 | Database.prototype.valueType = function(value) {
245 | if (value === Database.VALUESARENATIVE) {
246 | this._valuesType = Database.VALUESARENATIVE;
247 | } else if (value === Database.VALUESARESTRINGS) {
248 | this._valuesType = Database.VALUESARESTRINGS;
249 | }
250 | return this._valuesType;
251 | };
252 |
253 | /**
254 | * Dummy transaction function for public version
255 | * @param callback
256 | * @returns {Promise}
257 | */
258 | Database.prototype.begin = function(callback) {
259 | throw new Error("Transactions are a Commercial version feature.");
260 | };
261 |
262 | /**
263 | * Dummy prepare function for public version
264 | * @param sql
265 | * @returns {*}
266 | */
267 | Database.prototype.prepare = function(sql) {
268 | throw new Error("Prepared statements are a Commercial version feature.");
269 | };
270 |
271 | // noinspection JSUnusedLocalSymbols
272 | /**
273 | * Dummy sync enable tracking function for public version
274 | * @returns {*}
275 | */
276 | Database.prototype.enableTracking = function(tables, options, callback) {
277 | throw new Error("Table sync is a Commercial version feature.");
278 | };
279 |
280 |
281 |
282 | /***
283 | * Closes this database, any queries after this will fail with an error
284 | * @param callback
285 | * @returns Promise
286 | */
287 | Database.prototype.close = function(callback) {
288 |
289 | const self = this;
290 | return new Promise( function (resolve, reject) {
291 | if (!self._isOpen) {
292 | if (callback) {
293 | callback('SQLITE.CLOSE - Database is already closed');
294 | }
295 | reject('SQLITE.CLOSE - Database is already closed');
296 | return;
297 |
298 | }
299 |
300 | sqlite3_close(self._db);
301 | self._db = null;
302 | self._isOpen = false;
303 | if (self._dbnamePtr != null) {
304 | interop.free(self._dbnamePtr);
305 | self._dbnamePtr = null;
306 | }
307 | if (callback) {
308 | callback(null, null);
309 | }
310 | resolve();
311 | });
312 | };
313 |
314 | /***
315 | * Exec SQL
316 | * @param sql - sql to use
317 | * @param params - optional array of parameters
318 | * @param callback - (err, result) - can be last_row_id for insert, and rows affected for update/delete
319 | * @returns Promise
320 | */
321 | Database.prototype.execSQL = function(sql, params, callback) {
322 | if (typeof params === 'function') {
323 | callback = params;
324 | params = undefined;
325 | }
326 |
327 | const self = this;
328 | return new Promise( function(resolve, reject) {
329 |
330 | let hasCallback = true;
331 | if (typeof callback !== 'function') {
332 | callback = reject;
333 | hasCallback = false;
334 | }
335 |
336 | if (!self._isOpen) {
337 | callback("SQLITE.EXECSQL - Database is not open");
338 | return;
339 | }
340 |
341 | // Need to see if we have to run any status queries afterwords
342 | let flags = 0;
343 | let test = sql.trim().substr(0, 7).toLowerCase();
344 | if (test === 'insert ') {
345 | flags = 1;
346 | } else if (test === 'update ' || test === 'delete ') {
347 | flags = 2;
348 | }
349 |
350 |
351 | let res;
352 | try {
353 | let statement = new interop.Reference();
354 | res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
355 | statement = statement.value;
356 | if (res) {
357 | callback("SQLITE.ExecSQL Failed Prepare: " + res);
358 | return;
359 | }
360 | if (params !== undefined) {
361 | if (!self._bind(statement, params)) {
362 | sqlite3_finalize(statement);
363 | callback("SQLITE.ExecSQL Bind Error");
364 | return;
365 | }
366 | }
367 | let result = sqlite3_step(statement);
368 | sqlite3_finalize(statement);
369 | if (result && result !== 100 && result !== 101) {
370 | callback("SQLITE.ExecSQL Failed " + result);
371 | return;
372 | }
373 |
374 | } catch (Err) {
375 | callback(Err, null);
376 | return;
377 | }
378 |
379 |
380 | switch (flags) {
381 | case 0:
382 | if (hasCallback) {
383 | callback();
384 | }
385 | resolve();
386 | break;
387 |
388 | case 1:
389 | self.get('select last_insert_rowid()', function (err, data) {
390 | if (hasCallback) {
391 | callback(err, data && data[0]);
392 | }
393 | if (err) {
394 | reject(err);
395 | } else {
396 | resolve(data && data[0]);
397 | }
398 | }, Database.RESULTSASARRAY | Database.VALUESARENATIVE);
399 | break;
400 |
401 | case 2:
402 | self.get('select changes()', function (err, data) {
403 | if (hasCallback) {
404 | callback(err, data && data[0]);
405 | }
406 | if (err) {
407 | reject(err);
408 | } else {
409 | resolve(data && data[0]);
410 | }
411 | }, Database.RESULTSASARRAY | Database.VALUESARENATIVE);
412 | break;
413 |
414 | default:
415 | if (hasCallback) {
416 | callback();
417 | }
418 | resolve();
419 | }
420 | });
421 | };
422 |
423 | /***
424 | * Get the first record result set
425 | * @param sql - sql to run
426 | * @param params - optional
427 | * @param callback - callback (error, results)
428 | * @param mode - allows you to manually override the results set to be a array or object
429 | * @returns Promise
430 | */
431 | Database.prototype.get = function(sql, params, callback, mode) {
432 | if (typeof params === 'function') {
433 | mode = callback;
434 | callback = params;
435 | params = undefined;
436 | }
437 |
438 |
439 | const self = this;
440 | return new Promise( function (resolve, reject) {
441 | let hasCallback = true;
442 |
443 | if (typeof callback !== 'function') {
444 | callback = reject;
445 | hasCallback = false;
446 | }
447 |
448 | if (!self._isOpen) {
449 | callback("SQLITE.GET - Database is not open");
450 | return;
451 | }
452 |
453 | let cursor;
454 | try {
455 | let statement = new interop.Reference();
456 | let res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
457 | if (res) {
458 | callback("SQLITE.GET Failed Prepare: " + res);
459 | return;
460 | }
461 | statement = statement.value;
462 | let cursorStatement = new CursorStatement(statement, self._resultType, self._valuesType);
463 |
464 | if (params !== undefined) {
465 | if (!self._bind(statement, params)) {
466 | sqlite3_finalize(statement);
467 | callback("SQLITE.GET Bind Error");
468 | return;
469 | }
470 | }
471 |
472 | let result = sqlite3_step(statement);
473 | if (result === 100) {
474 | cursor = self._getResults(cursorStatement, mode);
475 | }
476 | sqlite3_finalize(statement);
477 | if (result && result !== 100 && result !== 101) {
478 | callback("SQLITE.GET - Step Error" + result);
479 | return;
480 | }
481 | } catch (err) {
482 | callback(err);
483 | return;
484 | }
485 |
486 | // No Records
487 | if (!cursor) {
488 | if (hasCallback) {
489 | callback(null, null);
490 | }
491 | resolve(null);
492 | return;
493 | }
494 |
495 | if (hasCallback) {
496 | callback(null, cursor);
497 | }
498 | resolve(cursor);
499 | });
500 | };
501 |
502 | /***
503 | * This returns the entire result set in a array of rows
504 | * @param sql - Sql to run
505 | * @param params - optional
506 | * @param callback - (err, results)
507 | * @param mode - set a specific return mode
508 | * @returns Promise
509 | */
510 | Database.prototype.all = function(sql, params, callback, mode) {
511 | if (typeof params === 'function') {
512 | callback = params;
513 | params = undefined;
514 | }
515 |
516 | const self = this;
517 | return new Promise(function(resolve, reject) {
518 |
519 | let hasCallback = true;
520 | if (typeof callback !== 'function') {
521 | callback = reject;
522 | hasCallback = false;
523 | }
524 |
525 | if (!self._isOpen) {
526 | callback("SQLITE.ALL - Database is not open");
527 | return;
528 | }
529 |
530 | let rows = [], res;
531 | try {
532 | let statement = new interop.Reference();
533 | res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
534 | if (res) {
535 | callback("SQLITE.ALL - Prepare Error " + res);
536 | return;
537 | }
538 |
539 | statement = statement.value;
540 | let cursorStatement = new CursorStatement(statement, self._resultType, self._valuesType);
541 |
542 | if (params !== undefined) {
543 | if (!self._bind(statement, params)) {
544 | sqlite3_finalize(statement);
545 | callback("SQLITE.ALL Bind Error");
546 | return;
547 | }
548 | }
549 |
550 | let result;
551 | do {
552 | result = sqlite3_step(statement);
553 | if (result === 100) {
554 | let cursor = self._getResults(cursorStatement, mode);
555 | if (cursor) {
556 | rows.push(cursor);
557 | }
558 | } else if (result && result !== 101) {
559 | sqlite3_finalize(statement);
560 | callback("SQLITE.ALL - Database Error" + result);
561 | return;
562 | }
563 | } while (result === 100);
564 | sqlite3_finalize(statement);
565 | } catch (err) {
566 | callback(err, null);
567 | return;
568 | }
569 |
570 | // No Records
571 | if (rows.length === 0) {
572 | if (hasCallback) {
573 | callback(null, []);
574 | }
575 | resolve([]);
576 | return;
577 | }
578 |
579 | if (hasCallback) {
580 | callback(null, rows);
581 | }
582 | resolve(rows);
583 | });
584 | };
585 |
586 | /***
587 | * This sends each row of the result set to the "Callback" and at the end calls the complete callback upon completion
588 | * @param sql - sql to run
589 | * @param params - optional
590 | * @param callback - callback (err, rowsResult)
591 | * @param complete - callback (err, recordCount)
592 | * @returns {Promise}
593 | */
594 | Database.prototype.each = function(sql, params, callback, complete) {
595 | if (typeof params === 'function') {
596 | complete = callback;
597 | callback = params;
598 | params = undefined;
599 | }
600 |
601 | // Callback is required
602 | if (typeof callback !== 'function') {
603 | throw new Error("SQLITE.EACH - requires a callback");
604 | }
605 |
606 | const self = this;
607 | return new Promise (function(resolve, reject) {
608 |
609 | // Set the error Callback
610 | let errorCB = complete || callback;
611 |
612 | let count = 0, res;
613 | try {
614 |
615 | let statement = new interop.Reference();
616 | res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
617 | if (res) {
618 | errorCB("SQLITE.EACH Error in Prepare" + res);
619 | reject("SQLITE.EACH Error in Prepare" + res);
620 | return;
621 | }
622 | statement = statement.value;
623 | let cursorStatement = new CursorStatement(statement, self._resultType, self._valuesType);
624 |
625 | if (params !== undefined) {
626 | if (!self._bind(statement, params)) {
627 | sqlite3_finalize(statement);
628 | errorCB("SQLITE.EACH Bind Error");
629 | reject("SQLITE.EACH Bind Error");
630 | return;
631 | }
632 | }
633 | let result;
634 | do {
635 | result = sqlite3_step(statement);
636 | if (result === 100) {
637 | let cursor = self._getResults(cursorStatement);
638 | if (cursor) {
639 | count++;
640 | callback(null, cursor);
641 | }
642 | } else if (result && result !== 101) {
643 | sqlite3_finalize(statement);
644 | errorCB("SQLITE.EACH - Database Error " + result);
645 | reject("SQLITE.EACH - Database Error " + result);
646 | return;
647 | }
648 | } while (result === 100);
649 | sqlite3_finalize(statement);
650 | } catch (err) {
651 | errorCB(err, null);
652 | reject(err);
653 | return;
654 | }
655 |
656 | if (complete) {
657 | complete(null, count);
658 | }
659 | resolve(count);
660 | });
661 | };
662 |
663 | /**
664 | * Binds the Parameters in a Statement
665 | * @param statement
666 | * @param params
667 | * @private
668 | */
669 | Database.prototype._bind = function(statement, params) {
670 | let param, res;
671 |
672 | if (Array.isArray(params)) {
673 | const count = params.length;
674 | for (let i=0; i= 0) {
776 | cn = "column"+i;
777 | }
778 | cursorStatement.columns.push(cn);
779 | }
780 | }
781 | cursorStatement.built=true;
782 | }
783 |
784 | let cnt = cursorStatement.count, data;
785 | if (cnt === 0) { return null; }
786 | if (resultType === Database.RESULTSASARRAY) {
787 | data = [];
788 | if (valueType === Database.VALUESARESTRINGS) {
789 | for (i = 0; i < cnt; i++) {
790 | data.push(this._getStringResult(statement, i));
791 | }
792 | } else {
793 | for (i = 0; i < cnt; i++) {
794 | data.push(this._getNativeResult(statement, i));
795 | }
796 | }
797 | return data;
798 | } else {
799 | let colName = cursorStatement.columns;
800 | data = {};
801 | if (valueType === Database.VALUESARESTRINGS) {
802 | for (i = 0; i < cnt; i++) {
803 | data[colName[i]] = this._getStringResult(statement, i);
804 | }
805 | } else {
806 | for (i = 0; i < cnt; i++) {
807 | data[colName[i]] = this._getNativeResult(statement, i);
808 | }
809 | }
810 | return data;
811 | }
812 | };
813 |
814 | Database.prototype.notify = function(type, message) {
815 | if (typeof global.postMessage === 'function') {
816 | postMessage({id: -2, type: type, message: message});
817 | } else {
818 | console.error("SQLite: Not in a thread");
819 |
820 | // Local Notify
821 | this._notify(type, message);
822 | }
823 | };
824 |
825 | Database.prototype._notify = function(type, message) {
826 | if (type == null || typeof this._messageHandlers[type] === "undefined") {
827 | return;
828 | }
829 | let handlers = this._messageHandlers[type];
830 | try {
831 | for (let i = 0; i < handlers; i++) {
832 | handlers[i](message, type, this);
833 | }
834 | } catch (err) {
835 | console.error("SQLite: Error in user code ", err, err.stack);
836 | }
837 | }
838 |
839 | Database.prototype.addMessageHandler = function(type, callback) {
840 | if (typeof this._messageHandlers[type] === 'undefined') {
841 | this._messageHandlers[type] = [];
842 | }
843 | this._messageHandlers[type].push(callback);
844 | };
845 |
846 | Database.prototype.removeMessageHandler = function(type, callback) {
847 | if (type != null && typeof this._messageHandlers[type] === "undefined") {
848 | console.error("SQLite: This message handler " + type + " does not exist.");
849 | return;
850 | }
851 |
852 | if (callback) {
853 | // Remove all message handles that match this callback & this db...
854 | for (let i = 0; i < this._messageHandlers[type].length; i++) {
855 | if (this._messageHandlers[type][i].callback === callback) {
856 | this._messageHandlers[type].splice(i, 1);
857 | i--;
858 | }
859 | }
860 | } else if (type != null) {
861 | // Remove all message handlers for this type
862 | this._messageHandlers[type] = [];
863 | } else {
864 | // Remove all message handlers for this database
865 | this._messageHandlers = [];
866 | }
867 | };
868 |
869 | /***
870 | * Is this a SQLite object
871 | * @param obj - possible sqlite object to check
872 | * @returns {boolean}
873 | */
874 | Database.isSqlite = function(obj) {
875 | return obj && obj._isSqlite;
876 | };
877 |
878 | Database.exists = function(name) {
879 | if (name.indexOf('/') === -1) {
880 | name = fs.knownFolders.documents().path + '/' + name;
881 | }
882 |
883 | //noinspection JSUnresolvedFunction
884 | const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
885 |
886 | return fileManager.fileExistsAtPath(name);
887 | };
888 |
889 | Database.deleteDatabase = function(name) {
890 | //noinspection JSUnresolvedFunction
891 | const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
892 |
893 | let path;
894 | if (name.indexOf('/') === -1) {
895 | path = fs.knownFolders.documents().path + '/';
896 | } else {
897 | path = name.substr(0, name.lastIndexOf('/') + 1);
898 | name = name.substr(path.length);
899 | }
900 |
901 | if (!fileManager.fileExistsAtPath(path + name)) { return; }
902 |
903 | // Need to remove the trailing .sqlite
904 | let idx = name.lastIndexOf('.');
905 | if (idx) {
906 | name = name.substr(0,idx);
907 | }
908 |
909 | let files = fileManager.contentsOfDirectoryAtPathError(path, null);
910 | if (!files) {
911 | return;
912 | }
913 |
914 | for (let i = 0; i < files.count; i++) {
915 | const fileName = files.objectAtIndex(i);
916 | if (fileName.indexOf(name) !== -1) {
917 | fileManager.removeItemAtPathError(path + fileName, null);
918 | }
919 | }
920 | };
921 |
922 | Database.copyDatabase = function (name, destName) {
923 | //noinspection JSUnresolvedFunction
924 |
925 | const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
926 |
927 | let path;
928 | if (name.indexOf('/') === -1) {
929 | path = fs.knownFolders.documents().path + '/';
930 | } else {
931 | path = name.substr(0, name.lastIndexOf('/') + 1);
932 | name = name.substr(path.length);
933 | }
934 |
935 | let source = fs.knownFolders.currentApp().path + '/' + name;
936 |
937 | if (!destName) { destName = name; }
938 | else if (destName.indexOf("/") >= 0) {
939 | destName = destName.substring(destName.lastIndexOf('/') + 1);
940 | }
941 |
942 | let destination = path + destName;
943 | fileManager.copyItemAtPathToPathError(source, destination, null);
944 | };
945 |
946 | function UsePlugin(loadedSrc, DBModule) {
947 | if (loadedSrc.prototypes) {
948 | for (let key in loadedSrc.prototypes) {
949 | if (!loadedSrc.prototypes.hasOwnProperty(key)) { continue; }
950 | if (DBModule.prototype[key]) {
951 | DBModule.prototype["_"+key] = DBModule.prototype[key];
952 | }
953 | DBModule.prototype[key] = loadedSrc.prototypes[key];
954 | }
955 | }
956 | if (loadedSrc.statics) {
957 | for (let key in loadedSrc.statics) {
958 | if (!loadedSrc.statics.hasOwnProperty(key)) { continue; }
959 | DBModule[key] = loadedSrc.statics[key];
960 | }
961 | }
962 | if (typeof loadedSrc.init === 'function') {
963 | _DatabasePluginInits.push(loadedSrc.init);
964 | }
965 | }
966 |
967 | function iosProperty(_this, property) {
968 | if (typeof property === "function") {
969 | // xCode < 8
970 | return property.call(_this);
971 | } else {
972 | // xCode >= 8
973 | return property;
974 | }
975 | }
976 |
977 | // Literal Defines
978 | Database.prototype.RESULTSASARRAY = Database.RESULTSASARRAY = 1;
979 | Database.prototype.RESULTSASOBJECT = Database.RESULTSASOBJECT = 2;
980 | Database.prototype.VALUESARENATIVE = Database.VALUESARENATIVE = 4;
981 | Database.prototype.VALUESARESTRINGS = Database.VALUESARESTRINGS = 8;
982 |
983 |
984 |
985 | /** These are optional plugins, must have a static require statement for webpack **/
986 | TryLoadingCommercialPlugin();
987 | TryLoadingEncryptionPlugin();
988 | TryLoadingSyncPlugin();
989 |
990 | function TryLoadingCommercialPlugin() {
991 | try {
992 | const sqlCom = require('nativescript-sqlite-commercial');
993 | UsePlugin(sqlCom, Database);
994 | }
995 | catch (e) { /* Do Nothing if it doesn't exist as it is an optional plugin */
996 | }
997 | }
998 |
999 | function TryLoadingEncryptionPlugin() {
1000 | try {
1001 | const sqlEnc = require('nativescript-sqlite-encrypted');
1002 | UsePlugin(sqlEnc, Database);
1003 | }
1004 | catch (e) { /* Do Nothing if it doesn't exist as it is an optional plugin */
1005 | }
1006 | }
1007 |
1008 | function TryLoadingSyncPlugin() {
1009 | try {
1010 | const sqlSync = require('nativescript-sqlite-sync');
1011 | UsePlugin(sqlSync, Database);
1012 | }
1013 | catch (e) { /* Do Nothing if it doesn't exist as it is an optional plugin */
1014 | }
1015 | }
1016 |
1017 |
1018 | module.exports = Database;
1019 |
1020 |
--------------------------------------------------------------------------------
/src/sqlite.js:
--------------------------------------------------------------------------------
1 | /**************************************************************************************
2 | * (c) 2015-2021, Master Technology
3 | * Licensed under the MIT license or contact me for a support, changes, enhancements,
4 | * and/or if you require a commercial licensing
5 | *
6 | * Any questions please feel free to put a issue up on github
7 | * Nathan@master-technology.com http://nativescript.tools
8 | * Version 2.7.0 - Android
9 | *************************************************************************************/
10 | /* global global, require, module */
11 |
12 | "use strict";
13 | const DBInternal = require("nativescript-sqlite/sqlite-internal");
14 |
15 | function Database(dbname, options, callback) {
16 | if (typeof options === 'function') {
17 | callback = options;
18 | //noinspection JSUnusedAssignment
19 | options = {};
20 | } else {
21 | //noinspection JSUnusedAssignment
22 | options = options || {};
23 | }
24 |
25 | if (options && options.multithreading && typeof global.Worker === 'function') {
26 | // We don't want this value passed into the worker; to try and start another worker (which would fail).
27 | delete options.multithreading;
28 | if (!DBInternal.HAS_COMMERCIAL) {
29 | throw new Error("Multithreading is a commercial only feature; see https://nativescript.tools/product/10");
30 | }
31 | // We have to wrap this in a try/catch because of Webpack 4
32 | try {
33 | const multiSQL = require("nativescript-sqlite-commercial/commercial-multi");
34 | return new multiSQL(dbname, options, callback);
35 | } catch (err) {
36 | console.warn("Multithreading is a commercial only feature; see https://nativescript.tools/product/10");
37 | }
38 | }
39 | return new DBInternal(dbname, options, callback);
40 | }
41 |
42 | // Copy static Properties & Static functions over so that they still work
43 | for (let item in DBInternal) {
44 | if (DBInternal.hasOwnProperty(item)) {
45 | Database[item] = DBInternal[item];
46 | }
47 | }
48 |
49 | if (global.TNS_WEBPACK && global.TNS_WEBPACK >= 5) {
50 | if (global._MT_HAS_SQLITE) {
51 | Database.HAS_COMMERCIAL = (global._MT_HAS_SQLITE & 1) === 1;
52 | Database.HAS_ENCRYPTION = (global._MT_HAS_SQLITE & 2) === 2;
53 | Database.HAS_SYNC = (global._MT_HAS_SQLITE & 4) === 4;
54 | Database.HAS_KEYSTORE = (global._MT_HAS_SQLITE & 8) === 8;
55 | }
56 | }
57 |
58 | module.exports = Database;
59 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "removeComments": true,
6 | "experimentalDecorators": true,
7 | "sourceMap": true
8 | },
9 | "compileOnSave": false,
10 | "exclude": [
11 | "node_modules",
12 | "platforms"
13 | ]
14 | }
--------------------------------------------------------------------------------