├── .gitignore
├── .gitmodules
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── DEVELOPMENT.md
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── plugin.xml
├── scripts
└── iosAddBridgingHeader.js
├── src
├── android
│ ├── AssetBundle.java
│ ├── AssetBundleDownloader.java
│ ├── AssetBundleManager.java
│ ├── AssetManagerCache.java
│ ├── AssetManifest.java
│ ├── DownloadFailureException.java
│ ├── IOUtils.java
│ ├── WebAppConfiguration.java
│ ├── WebAppLocalServer.java
│ ├── WebResourceHandler.java
│ └── build-extras.gradle
└── ios
│ ├── Asset.swift
│ ├── AssetBundle.swift
│ ├── AssetBundleDownloader.swift
│ ├── AssetBundleManager.swift
│ ├── AssetManifest.swift
│ ├── Errors.swift
│ ├── METNetworkReachabilityManager.h
│ ├── METNetworkReachabilityManager.m
│ ├── METPlugin.h
│ ├── METPlugin.m
│ ├── METRandomValueGenerator.h
│ ├── METRandomValueGenerator.m
│ ├── METRetryStrategy.h
│ ├── METRetryStrategy.m
│ ├── METTimer.h
│ ├── METTimer.m
│ ├── Utility.swift
│ ├── WebAppConfiguration.swift
│ ├── WebAppLocalServer.swift
│ └── cordova-plugin-meteor-webapp-Bridging-Header.h
├── tests
├── fixtures
│ ├── bundled_www
│ │ ├── application
│ │ │ ├── app
│ │ │ │ ├── mobileapp.js
│ │ │ │ ├── mobileapp.js.map
│ │ │ │ ├── some-data.json
│ │ │ │ ├── some-file
│ │ │ │ ├── some-font.woff
│ │ │ │ ├── some-image.jpg
│ │ │ │ ├── some-image.png
│ │ │ │ ├── some-javascript.js
│ │ │ │ ├── some-page.html
│ │ │ │ ├── some-stylesheet.css
│ │ │ │ ├── some-text.txt
│ │ │ │ ├── some-video.mp4
│ │ │ │ ├── template.mobileapp.js
│ │ │ │ └── template.mobileapp.js.map
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── merged-stylesheets.css.map
│ │ │ ├── not-in-manifest
│ │ │ ├── packages
│ │ │ │ ├── meteor.js
│ │ │ │ └── meteor.js.map
│ │ │ └── program.json
│ │ └── cordova_plugins.js
│ ├── downloadable_versions
│ │ ├── 127.0.0.1_root_url
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── different_cordova_compatibility_version
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── missing_app_id
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── missing_cordova_compatibility_version
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── missing_root_url
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── version1
│ │ │ ├── app
│ │ │ │ ├── 6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map
│ │ │ │ ├── 979b20f66caf126704c250fbd29ce253c6cb490e.map
│ │ │ │ ├── mobileapp.js
│ │ │ │ └── template.mobileapp.js
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── merged-stylesheets.css.map
│ │ │ ├── not-in-manifest
│ │ │ ├── packages
│ │ │ │ ├── 57d11a30155349aa5106f8150cee35eac5f4764c.map
│ │ │ │ └── meteor.js
│ │ │ ├── some-data.json
│ │ │ ├── some-file
│ │ │ ├── some-font.woff
│ │ │ ├── some-image.jpg
│ │ │ ├── some-image.png
│ │ │ ├── some-javascript.js
│ │ │ ├── some-page.html
│ │ │ ├── some-stylesheet.css
│ │ │ ├── some-text.txt
│ │ │ └── some-video.mp4
│ │ ├── version2
│ │ │ ├── 20ae2c8d51b2507244e598844414ecdec2615ce3.map
│ │ │ ├── app
│ │ │ │ ├── 3f6275657e6db3a21acb37d0f6c207cf83871e90.map
│ │ │ │ ├── 6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map
│ │ │ │ ├── mobileapp.js
│ │ │ │ └── template.mobileapp.js
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── packages
│ │ │ │ ├── 57d11a30155349aa5106f8150cee35eac5f4764c.map
│ │ │ │ └── meteor.js
│ │ │ ├── some-data.json
│ │ │ ├── some-file
│ │ │ ├── some-font.woff
│ │ │ ├── some-image.jpg
│ │ │ ├── some-image.png
│ │ │ ├── some-javascript.js
│ │ │ ├── some-other-file
│ │ │ ├── some-page.html
│ │ │ ├── some-stylesheet.css
│ │ │ ├── some-text.txt
│ │ │ └── some-video.mp4
│ │ ├── version2_with_invalid_asset
│ │ │ ├── 20ae2c8d51b2507244e598844414ecdec2615ce3.map
│ │ │ ├── app
│ │ │ │ ├── 3f6275657e6db3a21acb37d0f6c207cf83871e90.map
│ │ │ │ ├── 6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map
│ │ │ │ ├── mobileapp.js
│ │ │ │ └── template.mobileapp.js
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── packages
│ │ │ │ ├── 57d11a30155349aa5106f8150cee35eac5f4764c.map
│ │ │ │ └── meteor.js
│ │ │ ├── some-data.json
│ │ │ ├── some-file
│ │ │ ├── some-font.woff
│ │ │ ├── some-image.jpg
│ │ │ ├── some-image.png
│ │ │ ├── some-javascript.js
│ │ │ ├── some-other-file
│ │ │ ├── some-page.html
│ │ │ ├── some-stylesheet.css
│ │ │ ├── some-text.txt
│ │ │ └── some-video.mp4
│ │ ├── version2_with_missing_asset
│ │ │ ├── 20ae2c8d51b2507244e598844414ecdec2615ce3.map
│ │ │ ├── app
│ │ │ │ ├── 3f6275657e6db3a21acb37d0f6c207cf83871e90.map
│ │ │ │ ├── 6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map
│ │ │ │ └── mobileapp.js
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── packages
│ │ │ │ ├── 57d11a30155349aa5106f8150cee35eac5f4764c.map
│ │ │ │ └── meteor.js
│ │ │ ├── some-data.json
│ │ │ ├── some-file
│ │ │ ├── some-font.woff
│ │ │ ├── some-image.jpg
│ │ │ ├── some-image.png
│ │ │ ├── some-javascript.js
│ │ │ ├── some-other-file
│ │ │ ├── some-page.html
│ │ │ ├── some-stylesheet.css
│ │ │ ├── some-text.txt
│ │ │ └── some-video.mp4
│ │ ├── version2_with_version_mismatch
│ │ │ ├── 20ae2c8d51b2507244e598844414ecdec2615ce3.map
│ │ │ ├── app
│ │ │ │ ├── 3f6275657e6db3a21acb37d0f6c207cf83871e90.map
│ │ │ │ ├── 6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map
│ │ │ │ ├── mobileapp.js
│ │ │ │ └── template.mobileapp.js
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── packages
│ │ │ │ ├── 57d11a30155349aa5106f8150cee35eac5f4764c.map
│ │ │ │ └── meteor.js
│ │ │ ├── some-data.json
│ │ │ ├── some-file
│ │ │ ├── some-font.woff
│ │ │ ├── some-image.jpg
│ │ │ ├── some-image.png
│ │ │ ├── some-javascript.js
│ │ │ ├── some-other-file
│ │ │ ├── some-page.html
│ │ │ ├── some-stylesheet.css
│ │ │ ├── some-text.txt
│ │ │ └── some-video.mp4
│ │ ├── version3
│ │ │ ├── 20ae2c8d51b2507244e598844414ecdec2615ce3.map
│ │ │ ├── app
│ │ │ │ ├── 36e96c1d40459ae12164569599c9c0a203b36db7.map
│ │ │ │ ├── 6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map
│ │ │ │ ├── mobileapp.js
│ │ │ │ └── template.mobileapp.js
│ │ │ ├── head.html
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ ├── merged-stylesheets.css
│ │ │ ├── packages
│ │ │ │ ├── 57d11a30155349aa5106f8150cee35eac5f4764c.map
│ │ │ │ └── meteor.js
│ │ │ ├── some-data.json
│ │ │ ├── some-file
│ │ │ ├── some-font.woff
│ │ │ ├── some-image.jpg
│ │ │ ├── some-image.png
│ │ │ ├── some-javascript.js
│ │ │ ├── some-other-file
│ │ │ ├── some-page.html
│ │ │ ├── some-stylesheet.css
│ │ │ ├── some-text.txt
│ │ │ └── some-video.mp4
│ │ ├── wrong_app_id
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ └── wrong_root_url
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ └── partially_downloaded_versions
│ │ └── version2
│ │ ├── app
│ │ ├── some-file
│ │ └── some-other-file
│ │ ├── index.html
│ │ └── program.json
├── package.json
├── plugin.xml
├── src
│ ├── android
│ │ └── WebAppMockRemoteServer.java
│ └── ios
│ │ ├── GCDWebServer+Testing.h
│ │ ├── GCDWebServer+Testing.m
│ │ ├── WebAppLocalServer+Testing.swift
│ │ ├── WebAppMockRemoteServer.swift
│ │ └── cordova-plugin-meteor-webapp-tests-Bridging-Header.h
└── www
│ ├── fetch.js
│ ├── tests.js
│ ├── underscore.js
│ ├── webapp_local_server_testing.js
│ └── webapp_mock_remote_server.js
└── www
└── webapp_local_server.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .idea/
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/ios/GCDWebServer"]
2 | path = src/ios/GCDWebServer
3 | url = https://github.com/meteor/GCDWebServer.git
4 | branch = master
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src/ios/GCDWebServer/Tests/
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | os: osx
2 | osx_image: xcode11.2
3 | git:
4 | depth: 2
5 | node_js:
6 | - 12
7 | install:
8 | - npm install
9 | script:
10 | - npm test
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ## v2.0.0, 2020-10-02
4 | Use WebViewAssetLoader on Android with newest cordova AndroidX webview usage
5 |
6 | ## v1.9.1, 2020-03-05
7 | Removes hook to set Swift version
8 |
9 | ## v1.9.0, 2020-03-04
10 | Migrates Swift code to be compatible with Swift version 5
11 |
12 | ## v1.8.0, 2020-01-16
13 | It makes cordova-plugin-meteor-webapp ready for Cordova 9.
14 | - changes context.requireCordovaModule to require for non-Cordova modules
15 | - removes .woff content type test because it never worked
16 | - updates travis test to use recent versions
17 | - removes .paramedic.config.js and use options directly on package.json
18 | - declares xcode as npm dependency
19 | - updates dev dependencies
20 | - updates DEVELOPMENT.md
21 |
22 | This version should be used for apps running Meteor 1.10 forward.
23 |
24 | ## v1.7.4, 2020-01-16
25 | We didn't had a tag for 1.7.0 that was the last version before the updates for
26 | Cordova 9 then we published 1.7.4 from this revision d5a7377c.
27 |
28 | This version should be used for apps running Meteor 1.9 or previous versions.
29 |
--------------------------------------------------------------------------------
/DEVELOPMENT.md:
--------------------------------------------------------------------------------
1 | # `cordova-plugin-meteor-webapp` Development
2 |
3 | ## Setup
4 |
5 | 1) Start with a cloned copy of the `cordova-plugin-meteor-webapp` repo:
6 |
7 | ```
8 | cd ~
9 | git clone https://github.com/meteor/cordova-plugin-meteor-webapp.git
10 | ```
11 |
12 | 2) Make sure the `GCDWebServer` submodule is pulled in:
13 |
14 | ```
15 | cd cordova-plugin-meteor-webapp
16 | git submodule update --init --recursive
17 | ```
18 |
19 | ## Running npm Tests
20 |
21 | 1) Install dependencies
22 | ```
23 | npm install
24 | ```
25 |
26 | 2) Install devDependencies from package.json globally one by one
27 | ```
28 | npm install -g xxx
29 | ```
30 |
31 | Filipe: I'm not sure why it's only working when installed globally
32 |
33 | 3) Run the tests
34 | ```
35 | npm test
36 | ```
37 |
38 | ## Running iOS Tests
39 |
40 | 1) Create a new test Cordova app:
41 |
42 | ```
43 | cd ~
44 | cordova create test-app
45 | ```
46 |
47 | 2) Add the `cordova-plugin-meteor-webapp`, `cordova-plugin-meteor-webapp-tests`, and `cordova-plugin-test-framework` plugins:
48 |
49 | ```
50 | cd test-app
51 | cordova plugin add https://github.com/apache/cordova-plugin-test-framework.git
52 | cordova plugin add ../cordova-plugin-meteor-webapp/
53 | cordova plugin add ../cordova-plugin-meteor-webapp/tests
54 | ```
55 |
56 | 3) Add the `ios` platform:
57 |
58 | ```
59 | cordova platform add ios
60 | ```
61 |
62 | 4) Add a [`build.json`](https://cordova.apache.org/docs/en/latest/guide/platforms/ios/#using-buildjson) file to the root of your `test-app`, that includes your Apple Developer Team ID:
63 |
64 | ```json
65 | {
66 | "ios": {
67 | "debug": {
68 | "developmentTeam": "ABC123DEF456"
69 | },
70 | "release": {
71 | "developmentTeam": "ABC123DEF456",
72 | "codeSignIdentity": "iPhone Developer",
73 | "packageType": "ad-hoc"
74 | }
75 | }
76 | }
77 | ```
78 |
79 | 5) Update the `test-app`'s `config.xml` to point to the test runner:
80 |
81 | Change
82 |
83 | ```xml
84 |
85 | ```
86 |
87 | to
88 |
89 | ```xml
90 |
91 | ```
92 |
93 | 6) Run the tests on a device or using the iOS emulator:
94 |
95 | ```
96 | cordova emulate ios
97 | ```
98 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Meteor Development Group
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 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-meteor-webapp",
3 | "version": "2.0.0",
4 | "description": "Cordova plugin that serves a Meteor web app through a local server and implements hot code push",
5 | "cordova": {
6 | "id": "cordova-plugin-meteor-webapp",
7 | "platforms": [
8 | "android",
9 | "ios"
10 | ]
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/meteor/cordova-plugin-meteor-webapp"
15 | },
16 | "keywords": [
17 | "cordova",
18 | "meteor",
19 | "ecosystem:cordova",
20 | "cordova-android",
21 | "cordova-ios"
22 | ],
23 | "author": "Meteor Development Group",
24 | "license": "MIT",
25 | "scripts": {
26 | "pretest": "ios-sim start --devicetypeid=iPhone-11-Pro-Max",
27 | "test": "cordova-paramedic --plugin . --platform ios --target 'iPhone-11-Pro-Max' --args=--buildFlag='-UseModernBuildSystem=0' --verbose"
28 | },
29 | "dependencies": {
30 | "xcode": "^2.0.0"
31 | },
32 | "devDependencies": {
33 | "cordova": "^9.0.0",
34 | "cordova-paramedic": "github:meteor/cordova-paramedic#40df66c3efc2f0db4d66b8c172174a68c031c114",
35 | "ios-deploy": "^1.10.0-beta.3",
36 | "ios-sim": "^8.0.2"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | Meteor Webapp
6 | Cordova plugin that serves a Meteor web app through a local server and implements hot code push
7 | cordova,meteor
8 | Meteor Development Group
9 | MIT
10 | https://github.com/meteor/cordova-plugin-meteor-webapp.git
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 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/scripts/iosAddBridgingHeader.js:
--------------------------------------------------------------------------------
1 | module.exports = function(context) {
2 | var fs = require('fs');
3 | var path = require('path');
4 | var cordova_util = context.requireCordovaModule('cordova-lib/src/cordova/util.js');
5 | var ConfigParser = context.requireCordovaModule('cordova-common').ConfigParser;
6 |
7 | var projectRoot = context.opts.projectRoot;
8 |
9 | var configXml = cordova_util.projectConfig(projectRoot);
10 | var config = new ConfigParser(configXml);
11 | var projectName = config.name();
12 |
13 | var platformRoot = path.join(context.opts.projectRoot, 'platforms/ios');
14 | var projectBridgingHeaderPath = path.join(platformRoot, projectName,
15 | 'Bridging-Header.h');
16 |
17 | var pluginId = context.opts.plugin.id;
18 | var pluginBridgingHeaderFilename = pluginId + '-Bridging-Header.h';
19 | var importDirective = '#import "' + pluginBridgingHeaderFilename + '"';
20 |
21 | var data = fs.readFileSync(projectBridgingHeaderPath, {'encoding': 'utf8'});
22 |
23 | var regExp = new RegExp("^" + importDirective + "$", "m");
24 |
25 | if (!regExp.test(data)) {
26 | fs.appendFileSync(projectBridgingHeaderPath, importDirective + "\n");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/android/AssetManagerCache.java:
--------------------------------------------------------------------------------
1 | package com.meteor.webapp;
2 |
3 | import android.content.res.AssetManager;
4 |
5 | import java.io.IOException;
6 | import java.io.ObjectInputStream;
7 | import java.util.Map;
8 |
9 | class AssetManagerCache {
10 | private static final String LOG_TAG = "MeteorWebApp";
11 |
12 | private AssetManager assetManager;
13 | private Map listCache;
14 |
15 | public AssetManagerCache(AssetManager assetManager) throws IOException {
16 | this.assetManager = assetManager;
17 |
18 | ObjectInputStream inputStream = null;
19 | try {
20 | inputStream = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
21 | listCache = (Map) inputStream.readObject();
22 | } catch (ClassNotFoundException e) {
23 | } finally {
24 | if (inputStream != null) {
25 | try {
26 | inputStream.close();
27 | } catch (IOException e) {
28 | }
29 | }
30 | }
31 | }
32 |
33 | public final String[] list(String path) {
34 | if (path.startsWith("/")) {
35 | path = path.substring(1);
36 | }
37 |
38 | if (path.endsWith("/")) {
39 | path = path.substring(0, path.length() - 1);
40 | }
41 |
42 | String[] children = listCache.get(path);
43 | return children;
44 | }
45 |
46 | public boolean exists(String path) {
47 | String parentPath;
48 | String filename;
49 |
50 | int parentEndIndex = path.lastIndexOf("/");
51 | if (parentEndIndex == -1) {
52 | parentPath = "";
53 | filename = path;
54 | } else {
55 | parentPath = path.substring(0, parentEndIndex);
56 | filename = path.substring(parentEndIndex + 1);
57 | }
58 |
59 | String[] children = list(parentPath);
60 |
61 | if (children == null) return false;
62 |
63 | for (String child : children) {
64 | if (child.equals(filename)) {
65 | return true;
66 | }
67 | }
68 |
69 | return false;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/android/AssetManifest.java:
--------------------------------------------------------------------------------
1 | package com.meteor.webapp;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONException;
5 | import org.json.JSONObject;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | final class AssetManifest {
11 | private static final String LOG_TAG = "MeteorWebApp";
12 |
13 | static final class Entry {
14 | final String filePath;
15 | final String urlPath;
16 | final String fileType;
17 | final boolean cacheable;
18 | final String hash;
19 | final String sourceMapFilePath;
20 | final String sourceMapUrlPath;
21 |
22 | Entry(String filePath, String urlPath, String fileType, boolean cacheable, String hash, String sourceMapFilePath, String sourceMapUrlPath) {
23 | this.filePath = filePath;
24 | this.urlPath = urlPath;
25 | this.fileType = fileType;
26 | this.cacheable = cacheable;
27 | this.hash = hash;
28 | this.sourceMapFilePath = sourceMapFilePath;
29 | this.sourceMapUrlPath = sourceMapUrlPath;
30 | }
31 | }
32 |
33 | final String version;
34 | final String cordovaCompatibilityVersion;
35 | final List entries;
36 |
37 | public AssetManifest(String string) throws WebAppException {
38 | try {
39 | JSONObject json = new JSONObject(string);
40 | String format = json.optString("format", null);
41 | if (format != null && !format.equals("web-program-pre1")) {
42 | throw new WebAppException("The asset manifest format is incompatible: " + format);
43 | }
44 |
45 | try {
46 | version = json.getString("version");
47 | } catch (JSONException e) {
48 | throw new WebAppException("Asset manifest does not have a version", e);
49 | }
50 |
51 | try {
52 | JSONObject cordovaCompatibilityVersions = json.getJSONObject("cordovaCompatibilityVersions");
53 | cordovaCompatibilityVersion = cordovaCompatibilityVersions.getString("android");
54 | } catch (JSONException e) {
55 | throw new WebAppException("Asset manifest does not have a cordovaCompatibilityVersion", e);
56 | }
57 |
58 | JSONArray entriesJSON = json.getJSONArray("manifest");
59 |
60 | entries = new ArrayList(entriesJSON.length());
61 |
62 | for (int i = 0; i < entriesJSON.length(); i++) {
63 | JSONObject entryJSON = entriesJSON.getJSONObject(i);
64 |
65 | if (!entryJSON.getString("where").equals("client")) continue;
66 |
67 | String filePath = entryJSON.getString("path");
68 | String urlPath = entryJSON.getString("url");
69 |
70 | String fileType = entryJSON.getString("type");
71 | boolean cacheable = entryJSON.getBoolean("cacheable");
72 | String hash = entryJSON.optString("hash", null);
73 | String sourceMapFilePath = entryJSON.optString("sourceMap", null);
74 | String sourceMapUrlPath = entryJSON.optString("sourceMapUrl", null);
75 |
76 | Entry entry = new Entry(filePath, urlPath, fileType, cacheable, hash, sourceMapFilePath, sourceMapUrlPath);
77 | entries.add(entry);
78 | }
79 | } catch (JSONException e) {
80 | throw new WebAppException("Error parsing asset manifest", e);
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/android/DownloadFailureException.java:
--------------------------------------------------------------------------------
1 | package com.meteor.webapp;
2 |
3 | class WebAppException extends Exception {
4 | public WebAppException(String detailMessage) {
5 | super(detailMessage);
6 | }
7 |
8 | public WebAppException(String detailMessage, Throwable throwable) {
9 | super(detailMessage, throwable);
10 | }
11 |
12 | public WebAppException(Throwable throwable) {
13 | super(throwable);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/android/IOUtils.java:
--------------------------------------------------------------------------------
1 | package com.meteor.webapp;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.InputStreamReader;
8 |
9 | import okio.BufferedSink;
10 | import okio.Okio;
11 | import okio.Source;
12 |
13 | class IOUtils {
14 | private static final String LOG_TAG = IOUtils.class.getSimpleName();
15 |
16 | public static String stringFromInputStream(InputStream inputStream) throws IOException {
17 | assert (inputStream != null);
18 |
19 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
20 | StringBuilder stringBuilder = new StringBuilder();
21 | String line;
22 | while ((line = reader.readLine()) != null) {
23 | stringBuilder.append(line);
24 | stringBuilder.append("\n");
25 | }
26 | return stringBuilder.toString();
27 | }
28 |
29 | public static File writeToFile(Source source, File file) throws IOException {
30 | BufferedSink sink = null;
31 | try {
32 | sink = Okio.buffer(Okio.sink(file));
33 | sink.writeAll(source);
34 | } finally {
35 | source.close();
36 | if (sink != null) {
37 | sink.close();
38 | }
39 | }
40 | return file;
41 | }
42 |
43 | public static void writeToFile(byte[] bytes, File file) throws IOException {
44 | BufferedSink sink = null;
45 | try {
46 | sink = Okio.buffer(Okio.sink(file));
47 | sink.write(bytes);
48 | } finally {
49 | if (sink != null) {
50 | sink.close();
51 | }
52 | }
53 | }
54 |
55 | public static boolean deleteRecursively(File file) {
56 | if (file.isDirectory()) {
57 | for (File child : file.listFiles()) {
58 | if (!deleteRecursively(child)) {
59 | return false;
60 | }
61 | }
62 | }
63 | return file.delete();
64 | }
65 | }
--------------------------------------------------------------------------------
/src/android/WebAppConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.meteor.webapp;
2 |
3 | import android.content.SharedPreferences;
4 | import android.util.Log;
5 |
6 | import java.util.Collections;
7 | import java.util.HashSet;
8 | import java.util.Set;
9 |
10 | class WebAppConfiguration {
11 | private SharedPreferences preferences;
12 |
13 | public WebAppConfiguration(SharedPreferences preferences) {
14 | this.preferences = preferences;
15 | }
16 |
17 | public String getAppId() {
18 | return preferences.getString("appId", null);
19 | }
20 |
21 | public void setAppId(String appId) {
22 | preferences.edit().putString("appId", appId).commit();
23 | }
24 |
25 | public String getRootUrlString() {
26 | return preferences.getString("rootUrl", null);
27 | }
28 |
29 | public void setRootUrlString(String rootUrlString) {
30 | preferences.edit().putString("rootUrl", rootUrlString).commit();
31 | }
32 |
33 | public String getCordovaCompatibilityVersion() {
34 | return preferences.getString("cordovaCompatibilityVersion", null);
35 | }
36 |
37 | public void setCordovaCompatibilityVersion(String version) {
38 | preferences.edit().putString("cordovaCompatibilityVersion", version).commit();
39 | }
40 |
41 | public String getLastDownloadedVersion() {
42 | return preferences.getString("lastDownloadedVersion", null);
43 | }
44 |
45 | public void setLastDownloadedVersion(String version) {
46 | preferences.edit().putString("lastDownloadedVersion", version).commit();
47 | }
48 |
49 | public String getLastSeenInitialVersion() {
50 | return preferences.getString("lastSeenInitialVersion", null);
51 | }
52 |
53 | public void setLastSeenInitialVersion(String version) {
54 | preferences.edit().putString("lastSeenInitialVersion", version).commit();
55 | }
56 |
57 | public String getLastKnownGoodVersion() {
58 | return preferences.getString("lastKnownGoodVersion", null);
59 | }
60 |
61 | public void setLastKnownGoodVersion(String version) {
62 | preferences.edit().putString("lastKnownGoodVersion", version).commit();
63 | }
64 |
65 | public Set getBlacklistedVersions() {
66 | Set blacklistedVersions = preferences.getStringSet("blacklistedVersions", Collections.EMPTY_SET);
67 | Log.d("BLACKLIST", "getBlacklistedVersions: " + blacklistedVersions);
68 | return blacklistedVersions;
69 | }
70 |
71 | public void addBlacklistedVersion(String version) {
72 | Set versionsForRetry = new HashSet(preferences.getStringSet("versionsForRetry", Collections.EMPTY_SET));
73 | Set blacklistedVersions = new HashSet(getBlacklistedVersions());
74 | Log.d("BLACKLIST", "versionsForRetry: " + versionsForRetry);
75 |
76 | if (!versionsForRetry.contains(version) && !blacklistedVersions.contains(version)) {
77 | Log.d("BLACKLIST", "adding faulty version for retry: " + version);
78 | versionsForRetry.add(version);
79 | preferences.edit().putStringSet("versionsForRetry", versionsForRetry).commit();
80 | } else {
81 | versionsForRetry.remove(version);
82 | blacklistedVersions.add(version);
83 | Log.d("BLACKLIST", "blacklisting version: " + version);
84 | preferences.edit().putStringSet("versionsForRetry", versionsForRetry).commit();
85 | preferences.edit().putStringSet("blacklistedVersions", blacklistedVersions).commit();
86 | }
87 | }
88 |
89 | public void reset() {
90 | preferences.edit().clear().commit();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/android/WebResourceHandler.java:
--------------------------------------------------------------------------------
1 | package com.meteor.webapp;
2 |
3 | import android.net.Uri;
4 |
5 | interface WebResourceHandler {
6 | Uri remapUri(Uri uri);
7 | }
8 |
--------------------------------------------------------------------------------
/src/android/build-extras.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 | cdvPluginPostBuildExtras.add({
20 | def inAssetsDir = file("src/main/assets")
21 | if (!inAssetsDir.exists()) {
22 | // Backwards compatibility for cordova-android < 7.0.0:
23 | inAssetsDir = file("assets")
24 | }
25 | def outAssetsDir = inAssetsDir
26 | def outFile = new File(outAssetsDir, "cdvasset.manifest")
27 |
28 | def newTask = task("cdvCreateAssetManifest") {
29 | doLast {
30 | def contents = new HashMap()
31 | def sizes = new HashMap()
32 | contents[""] = inAssetsDir.list()
33 | def tree = fileTree(dir: inAssetsDir)
34 | tree.visit { fileDetails ->
35 | if (fileDetails.isDirectory()) {
36 | contents[fileDetails.relativePath.toString()] = fileDetails.file.list()
37 | } else {
38 | sizes[fileDetails.relativePath.toString()] = fileDetails.file.length()
39 | }
40 | }
41 |
42 | outAssetsDir.mkdirs()
43 | outFile.withObjectOutputStream { oos ->
44 | oos.writeObject(contents)
45 | oos.writeObject(sizes)
46 | }
47 | }
48 | }
49 | newTask.inputs.dir inAssetsDir
50 | newTask.outputs.file outFile
51 | def preBuildTask = tasks["preBuild"]
52 | preBuildTask.dependsOn(newTask)
53 | })
54 |
--------------------------------------------------------------------------------
/src/ios/Asset.swift:
--------------------------------------------------------------------------------
1 | struct Asset {
2 | let bundle: AssetBundle
3 | let filePath: String
4 | var fileURL: URL {
5 | return bundle.directoryURL.appendingPathComponent(filePath, isDirectory: false)
6 | }
7 | let urlPath: String
8 | let fileType: String?
9 | let cacheable: Bool
10 | let hash: String?
11 | let sourceMapURLPath: String?
12 |
13 | init(bundle: AssetBundle, filePath: String, urlPath: String, fileType: String? = nil,
14 | cacheable: Bool, hash: String? = nil, sourceMapURLPath: String? = nil) {
15 | self.bundle = bundle
16 | self.filePath = filePath
17 | self.urlPath = urlPath
18 | self.fileType = fileType
19 | self.cacheable = cacheable
20 | self.hash = hash
21 | self.sourceMapURLPath = sourceMapURLPath
22 | }
23 | }
24 |
25 | extension Asset: CustomStringConvertible {
26 | var description: String {
27 | return urlPath
28 | }
29 | }
30 |
31 | extension Asset: Hashable, Equatable {
32 | var hashValue: Int { return ObjectIdentifier(bundle).hashValue ^ urlPath.hashValue }
33 | }
34 |
35 | func ==(lhs: Asset, rhs: Asset) -> Bool {
36 | return ObjectIdentifier(lhs.bundle) == ObjectIdentifier(rhs.bundle)
37 | && lhs.urlPath == rhs.urlPath
38 | }
39 |
--------------------------------------------------------------------------------
/src/ios/AssetBundle.swift:
--------------------------------------------------------------------------------
1 | /// Regex used to extract __meteor_runtime_config__ from index.html
2 | private let configJSONRegEx = try! NSRegularExpression(
3 | pattern: "__meteor_runtime_config__ = JSON.parse\\(decodeURIComponent\\(\"([^\"]*)\"\\)\\)",
4 | options: [])
5 |
6 | /// Load the runtime config by extracting and parsing
7 | /// `__meteor_runtime_config__` from index.html
8 | func loadRuntimeConfigFromIndexFileAtURL(_ fileURL: URL) throws -> AssetBundle.RuntimeConfig {
9 | do {
10 | let indexFileString = try NSString(contentsOf: fileURL, encoding: String.Encoding.utf8.rawValue)
11 | guard
12 | let match = configJSONRegEx.firstMatchInString(indexFileString as String),
13 | let configString = (indexFileString.substring(with: match.range(at: 1)) as NSString).removingPercentEncoding,
14 | let configData = configString.data(using: String.Encoding.utf8)
15 | else { throw WebAppError.unsuitableAssetBundle(reason: "Couldn't load runtime config from index file", underlyingError: nil) }
16 | return AssetBundle.RuntimeConfig(json: try JSONSerialization.jsonObject(with: configData, options: []) as! JSONObject)
17 | } catch {
18 | throw WebAppError.unsuitableAssetBundle(reason: "Couldn't load runtime config from index file", underlyingError: error)
19 | }
20 | }
21 |
22 | final class AssetBundle {
23 | private(set) var directoryURL: URL
24 |
25 | let version: String
26 | let cordovaCompatibilityVersion: String
27 |
28 | private var parentAssetBundle: AssetBundle?
29 | private var ownAssetsByURLPath: [String: Asset] = [:]
30 | private(set) var indexFile: Asset?
31 |
32 | var ownAssets: [Asset] {
33 | return Array(ownAssetsByURLPath.values)
34 | }
35 |
36 | convenience init(directoryURL: URL, parentAssetBundle: AssetBundle? = nil) throws {
37 | let manifestURL = directoryURL.appendingPathComponent("program.json")
38 | let manifest = try AssetManifest(fileURL: manifestURL)
39 | try self.init(directoryURL: directoryURL, manifest: manifest, parentAssetBundle: parentAssetBundle)
40 | }
41 |
42 | init(directoryURL: URL, manifest: AssetManifest, parentAssetBundle: AssetBundle? = nil) throws {
43 | self.directoryURL = directoryURL
44 | self.parentAssetBundle = parentAssetBundle
45 |
46 | self.version = manifest.version
47 | self.cordovaCompatibilityVersion = manifest.cordovaCompatibilityVersion
48 |
49 | for entry in manifest.entries {
50 | let URLPath = URLPathByRemovingQueryString(entry.URLPath)
51 |
52 | if parentAssetBundle?.cachedAssetForURLPath(URLPath, hash: entry.hash) == nil {
53 | let asset = Asset(
54 | bundle: self,
55 | filePath: entry.filePath,
56 | urlPath: URLPath,
57 | fileType: entry.fileType,
58 | cacheable: entry.cacheable,
59 | hash: entry.hash,
60 | sourceMapURLPath: entry.sourceMapURLPath)
61 | addAsset(asset)
62 | }
63 |
64 | if let sourceMapPath = entry.sourceMapPath,
65 | let sourceMapURLPath = entry.sourceMapURLPath {
66 | if parentAssetBundle?.cachedAssetForURLPath(sourceMapURLPath) == nil {
67 | let sourceMap = Asset(
68 | bundle: self,
69 | filePath: sourceMapPath,
70 | urlPath: sourceMapURLPath,
71 | fileType: "json",
72 | cacheable: true)
73 | addAsset(sourceMap)
74 | }
75 | }
76 | }
77 |
78 | let indexFile = Asset(bundle: self, filePath: "index.html", urlPath: "/", fileType: "html", cacheable: false, hash: nil)
79 | addAsset(indexFile)
80 | self.indexFile = indexFile
81 | }
82 |
83 | func addAsset(_ asset: Asset) {
84 | ownAssetsByURLPath[asset.urlPath] = asset
85 | }
86 |
87 | func assetForURLPath(_ URLPath: String) -> Asset? {
88 | return ownAssetsByURLPath[URLPath] ?? parentAssetBundle?.assetForURLPath(URLPath)
89 | }
90 |
91 | func assetExistsInBundle(_ URLPath: String) -> Bool {
92 | return ownAssetsByURLPath[URLPath] != nil
93 | }
94 |
95 | func cachedAssetForURLPath(_ URLPath: String, hash: String? = nil) -> Asset? {
96 | if let asset = ownAssetsByURLPath[URLPath],
97 | // If the asset is not cacheable, we require a matching hash
98 | (asset.cacheable || asset.hash != nil) && asset.hash == hash {
99 | return asset
100 | } else {
101 | return nil
102 | }
103 | }
104 |
105 | struct RuntimeConfig {
106 | private let json: JSONObject
107 |
108 | init(json: JSONObject) {
109 | self.json = json
110 | }
111 |
112 | var appId: String? {
113 | return json["appId"] as? String
114 | }
115 |
116 | var rootURL: URL? {
117 | if let rootURLString = json["ROOT_URL"] as? String {
118 | return URL(string: rootURLString)
119 | } else {
120 | return nil
121 | }
122 | }
123 |
124 | var autoupdateVersionCordova: String? {
125 | return json["autoupdateVersionCordova"] as? String
126 | }
127 | }
128 |
129 | /// The runtime config is lazily initialized by loading it from the index.html
130 | lazy var runtimeConfig: RuntimeConfig? = {
131 | guard let indexFile = self.indexFile else { return nil }
132 |
133 | do {
134 | return try loadRuntimeConfigFromIndexFileAtURL(indexFile.fileURL as URL)
135 | } catch {
136 | NSLog("\(error)")
137 | return nil
138 | }
139 | }()
140 |
141 | var appId: String? {
142 | return runtimeConfig?.appId
143 | }
144 |
145 | var rootURL: URL? {
146 | return runtimeConfig?.rootURL
147 | }
148 |
149 | func didMoveToDirectoryAtURL(_ directoryURL: URL) {
150 | self.directoryURL = directoryURL
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/ios/AssetManifest.swift:
--------------------------------------------------------------------------------
1 | struct AssetManifest {
2 | struct Entry {
3 | let filePath: String
4 | let URLPath: String
5 | let fileType: String
6 | let cacheable: Bool
7 | let hash: String?
8 | let sourceMapPath: String?
9 | let sourceMapURLPath: String?
10 | }
11 |
12 | let version: String
13 | let cordovaCompatibilityVersion: String
14 | var entries: [Entry]
15 |
16 | init(fileURL: URL) throws {
17 | try self.init(data: try Data(contentsOf: fileURL, options: []))
18 | }
19 |
20 | init(data: Data) throws {
21 | let JSON: JSONObject
22 | do {
23 | JSON = try JSONSerialization.jsonObject(with: data, options: []) as! JSONObject
24 | } catch {
25 | throw WebAppError.invalidAssetManifest(reason: "Error parsing asset manifest", underlyingError: error)
26 | }
27 |
28 | if let format = JSON["format"] as? String, format != "web-program-pre1" {
29 | throw WebAppError.invalidAssetManifest(reason: "The asset manifest format is incompatible: \(format)", underlyingError: nil)
30 | }
31 |
32 | guard let version = JSON["version"] as? String else {
33 | throw WebAppError.invalidAssetManifest(reason: "Asset manifest does not have a version", underlyingError: nil)
34 | }
35 |
36 | self.version = version
37 |
38 | guard let cordovaCompatibilityVersions = JSON["cordovaCompatibilityVersions"] as? JSONObject,
39 | let cordovaCompatibilityVersion = cordovaCompatibilityVersions["ios"] as? String else {
40 | throw WebAppError.invalidAssetManifest(reason: "Asset manifest does not have a cordovaCompatibilityVersion", underlyingError: nil)
41 | }
42 |
43 | self.cordovaCompatibilityVersion = cordovaCompatibilityVersion
44 |
45 | let entriesJSON = JSON["manifest"] as? [JSONObject] ?? []
46 | entries = []
47 | for entryJSON in entriesJSON {
48 | if entryJSON["where"] as? String != "client" { continue }
49 |
50 | if let URLPath = entryJSON["url"] as? String,
51 | let filePath = entryJSON["path"] as? String,
52 | let fileType = entryJSON["type"] as? String,
53 | let hash = entryJSON["hash"] as? String,
54 | let cacheable = entryJSON["cacheable"] as? Bool {
55 | let sourceMapPath = entryJSON["sourceMap"] as? String
56 | let sourceMapURLPath = entryJSON["sourceMapUrl"] as? String
57 |
58 | let entry = Entry(filePath: filePath, URLPath: URLPath,
59 | fileType: fileType, cacheable: cacheable, hash: hash,
60 | sourceMapPath: sourceMapPath, sourceMapURLPath: sourceMapURLPath)
61 | entries.append(entry)
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/ios/Errors.swift:
--------------------------------------------------------------------------------
1 | enum WebAppError: Error, CustomStringConvertible {
2 | case invalidAssetManifest(reason: String, underlyingError: Error?)
3 | case fileSystemFailure(reason: String, underlyingError: Error?)
4 | case downloadFailure(reason: String, underlyingError: Error?)
5 | case unsuitableAssetBundle(reason: String, underlyingError: Error?)
6 |
7 | var description: String {
8 | switch self {
9 | case .invalidAssetManifest(let reason, let underlyingError):
10 | return errorMessageWithReason(reason, underlyingError: underlyingError)
11 | case .fileSystemFailure(let reason, let underlyingError):
12 | return errorMessageWithReason(reason, underlyingError: underlyingError)
13 | case .downloadFailure(let reason, let underlyingError):
14 | return errorMessageWithReason(reason, underlyingError: underlyingError)
15 | case .unsuitableAssetBundle(let reason, let underlyingError):
16 | return errorMessageWithReason(reason, underlyingError: underlyingError)
17 | }
18 | }
19 | }
20 |
21 | func errorMessageWithReason(_ reason: String, underlyingError: Error?) -> String {
22 | if let underlyingError = underlyingError {
23 | return "\(reason): \(underlyingError)"
24 | } else {
25 | return reason
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ios/METNetworkReachabilityManager.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import
22 |
23 | NS_ASSUME_NONNULL_BEGIN
24 |
25 | typedef NS_ENUM(NSInteger, METNetworkReachabilityStatus) {
26 | METNetworkReachabilityStatusUnknown = 0,
27 | METNetworkReachabilityStatusNotReachable,
28 | METNetworkReachabilityStatusReachable
29 | };
30 |
31 | @protocol METNetworkReachabilityManagerDelegate;
32 |
33 | @interface METNetworkReachabilityManager : NSObject
34 |
35 | - (instancetype)initWithHostName:(NSString *)hostName NS_DESIGNATED_INITIALIZER;
36 | - (instancetype)init NS_UNAVAILABLE;
37 |
38 | @property (nullable, weak, nonatomic) id delegate;
39 | @property (nullable, strong, nonatomic) dispatch_queue_t delegateQueue;
40 |
41 | @property (assign, nonatomic) METNetworkReachabilityStatus reachabilityStatus;
42 |
43 | - (BOOL)startMonitoring;
44 | - (void)stopMonitoring;
45 |
46 | @end
47 |
48 | @protocol METNetworkReachabilityManagerDelegate
49 |
50 | - (void)networkReachabilityManager:(METNetworkReachabilityManager *)reachabilityManager didDetectReachabilityStatusChange:(METNetworkReachabilityStatus)reachabilityStatus;
51 |
52 | @end
53 |
54 | NS_ASSUME_NONNULL_END
55 |
--------------------------------------------------------------------------------
/src/ios/METNetworkReachabilityManager.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import "METNetworkReachabilityManager.h"
22 |
23 | @import SystemConfiguration;
24 |
25 | @interface METNetworkReachabilityManager ()
26 |
27 | - (void)didReceiveCallbackWithFlags:(SCNetworkReachabilityFlags)flags;
28 |
29 | @end
30 |
31 | static void METNetworkReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
32 | METNetworkReachabilityManager *reachabilityManager = (__bridge METNetworkReachabilityManager *)info;
33 | [reachabilityManager didReceiveCallbackWithFlags:flags];
34 | }
35 |
36 | @implementation METNetworkReachabilityManager {
37 | SCNetworkReachabilityRef _reachabilityRef;
38 | }
39 |
40 | #pragma mark - Lifecycle
41 |
42 | - (instancetype)initWithHostName:(NSString *)hostName {
43 | self = [super init];
44 | if (self) {
45 | _reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
46 | if (_reachabilityRef == NULL) {
47 | self = nil;
48 | }
49 | }
50 | return self;
51 | }
52 |
53 | - (void)dealloc {
54 | [self stopMonitoring];
55 | if (_reachabilityRef != NULL) {
56 | CFRelease(_reachabilityRef);
57 | }
58 | }
59 |
60 | #pragma mark - Monitoring Reachability State
61 |
62 | - (BOOL)startMonitoring {
63 | NSAssert(_delegateQueue != nil, @"Delegate queue should be set before calling startMonitoring");
64 |
65 | SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
66 |
67 | if (SCNetworkReachabilitySetCallback(_reachabilityRef, METNetworkReachabilityCallback, &context)) {
68 | return SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _delegateQueue);
69 | }
70 |
71 | return NO;
72 | }
73 |
74 | - (void)stopMonitoring {
75 | if (_reachabilityRef != NULL) {
76 | SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, NULL);
77 | }
78 | }
79 |
80 | - (void)didReceiveCallbackWithFlags:(SCNetworkReachabilityFlags)flags {
81 | BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
82 | BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
83 | BOOL canConnectAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0));
84 | BOOL canConnectWithoutUserInteraction = (canConnectAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0);
85 | BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction));
86 |
87 | if (isNetworkReachable) {
88 | self.reachabilityStatus = METNetworkReachabilityStatusReachable;
89 | } else {
90 | self.reachabilityStatus = METNetworkReachabilityStatusNotReachable;
91 | }
92 |
93 | [_delegate networkReachabilityManager:self didDetectReachabilityStatusChange:_reachabilityStatus];
94 | }
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/src/ios/METPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface CDVPlugin ()
4 |
5 | - (instancetype)initWithWebViewEngine:(id )theWebViewEngine NS_DESIGNATED_INITIALIZER;
6 |
7 | @end
8 |
9 | @interface METPlugin : CDVPlugin
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/src/ios/METPlugin.m:
--------------------------------------------------------------------------------
1 | #import "METPlugin.h"
2 |
3 | @implementation METPlugin
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/src/ios/METRandomValueGenerator.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import
22 |
23 | NS_ASSUME_NONNULL_BEGIN
24 |
25 | @interface METRandomValueGenerator : NSObject
26 |
27 | + (METRandomValueGenerator *)defaultRandomValueGenerator;
28 |
29 | - (double)randomFraction;
30 |
31 | - (NSString *)randomStringWithCharactersFromString:(NSString *)characters length:(NSUInteger)length;
32 | - (NSString *)randomHexStringWithLength:(NSUInteger)length;
33 | - (NSString *)randomSeed;
34 | - (NSString *)randomIdentifier;
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/src/ios/METRandomValueGenerator.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import "METRandomValueGenerator.h"
22 |
23 | @implementation METRandomValueGenerator
24 |
25 | + (METRandomValueGenerator *)defaultRandomValueGenerator {
26 | static METRandomValueGenerator *defaultRandomValueGenerator;
27 | static dispatch_once_t onceToken;
28 |
29 | dispatch_once(&onceToken, ^{
30 | defaultRandomValueGenerator = [[self alloc] init];
31 | });
32 |
33 | return defaultRandomValueGenerator;
34 | }
35 |
36 | - (instancetype)init {
37 | self = [super init];
38 | if (self) {
39 | // rand48 functions require an initial value to be seeded
40 | srand48(time(0));
41 | }
42 | return self;
43 | }
44 |
45 | - (double)randomFraction {
46 | return drand48();
47 | }
48 |
49 | - (NSUInteger)randomUnsignedInteger {
50 | return arc4random();
51 | }
52 |
53 | - (NSUInteger)randomIntegerLessThanInteger:(NSUInteger)upperBound {
54 | return arc4random_uniform((u_int32_t)upperBound);
55 | }
56 |
57 | - (NSString *)randomStringWithCharactersFromString:(NSString *)characters length:(NSUInteger)length {
58 | NSMutableString *string = [NSMutableString stringWithCapacity:length];
59 | for (NSUInteger i = 0; i < length; i++) {
60 | NSUInteger index = [self randomIntegerLessThanInteger:[characters length]];
61 | unichar character = [characters characterAtIndex:index];
62 | [string appendFormat:@"%c", character];
63 | }
64 | return [string copy];
65 | }
66 |
67 | - (NSString *)randomHexStringWithLength:(NSUInteger)length {
68 | return [self randomStringWithCharactersFromString:@"0123456789abcdef" length:length];
69 | }
70 |
71 | - (NSString *)randomSeed {
72 | return [self randomHexStringWithLength:20];
73 | }
74 |
75 | - (NSString *)randomIdentifier {
76 | return [self randomStringWithCharactersFromString:@"23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz" length:17];
77 | }
78 |
79 | @end
80 |
--------------------------------------------------------------------------------
/src/ios/METRetryStrategy.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import
22 |
23 | NS_ASSUME_NONNULL_BEGIN
24 |
25 | @interface METRetryStrategy : NSObject
26 |
27 | @property (assign, nonatomic) NSTimeInterval minimumTimeInterval;
28 | @property (assign, nonatomic) NSTimeInterval maximumTimeInterval;
29 | @property (assign, nonatomic) NSUInteger numberOfAttemptsAtMinimumTimeInterval;
30 | @property (assign, nonatomic) NSTimeInterval baseTimeInterval;
31 | @property (assign, nonatomic) double exponent;
32 | @property (assign, nonatomic) double randomizationFactor;
33 |
34 | - (NSTimeInterval)retryIntervalForNumberOfAttempts:(NSUInteger)numberOfAttempts;
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/src/ios/METRetryStrategy.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import "METRetryStrategy.h"
22 |
23 | #import "METRandomValueGenerator.h"
24 |
25 | @implementation METRetryStrategy
26 |
27 | - (instancetype)init {
28 | self = [super init];
29 | if (self) {
30 | _maximumTimeInterval = DBL_MAX;
31 | }
32 | return self;
33 | }
34 |
35 | - (NSTimeInterval)retryIntervalForNumberOfAttempts:(NSUInteger)numberOfAttempts {
36 | if (numberOfAttempts < _numberOfAttemptsAtMinimumTimeInterval) {
37 | return _minimumTimeInterval;
38 | } else {
39 | NSTimeInterval timeInterval = fmin(_maximumTimeInterval, _baseTimeInterval * pow(_exponent, numberOfAttempts));
40 | if (_randomizationFactor > 0) {
41 | // 1 + Math.random() * this.randomisationFactor_
42 | timeInterval *= ([[METRandomValueGenerator defaultRandomValueGenerator] randomFraction] * _randomizationFactor) + (1 - _randomizationFactor / 2);
43 | }
44 | return timeInterval;
45 | }
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/src/ios/METTimer.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import
22 |
23 | NS_ASSUME_NONNULL_BEGIN
24 |
25 | @interface METTimer : NSObject
26 |
27 | - (instancetype)initWithQueue:(dispatch_queue_t)queue block:(void (^)())block NS_DESIGNATED_INITIALIZER;
28 | - (instancetype)init NS_UNAVAILABLE;
29 |
30 | @property (assign, nonatomic) NSTimeInterval tolerance;
31 |
32 | - (void)startWithTimeInterval:(NSTimeInterval)timeInterval;
33 | - (void)stop;
34 |
35 | @end
36 |
37 | NS_ASSUME_NONNULL_END
38 |
--------------------------------------------------------------------------------
/src/ios/METTimer.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014-2015 Martijn Walraven
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #import "METTimer.h"
22 |
23 | @implementation METTimer {
24 | dispatch_queue_t _queue;
25 | void (^_block)();
26 |
27 | dispatch_source_t _timer_source;
28 | BOOL _started;
29 | }
30 |
31 | - (instancetype)initWithQueue:(dispatch_queue_t)queue block:(void (^)())block {
32 | self = [super init];
33 | if (self) {
34 | _queue = queue;
35 | _block = [block copy];
36 | _tolerance = 0.1;
37 | _timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _queue);
38 | dispatch_source_set_event_handler(_timer_source, ^{
39 | if (_started) {
40 | dispatch_suspend(_timer_source);
41 | _started = NO;
42 | }
43 | _block();
44 | });
45 | }
46 | return self;
47 | }
48 |
49 | - (void)startWithTimeInterval:(NSTimeInterval)timeInterval {
50 | dispatch_source_set_timer(_timer_source, dispatch_time(DISPATCH_TIME_NOW, timeInterval * NSEC_PER_SEC), 0, _tolerance * NSEC_PER_MSEC);
51 | if (!_started) {
52 | dispatch_resume(_timer_source);
53 | _started = YES;
54 | }
55 | }
56 |
57 | - (void)stop {
58 | if (_started) {
59 | dispatch_suspend(_timer_source);
60 | _started = NO;
61 | }
62 | }
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/src/ios/Utility.swift:
--------------------------------------------------------------------------------
1 | extension Collection {
2 | func find(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Self.Iterator.Element? {
3 | return try index(where: predicate).map({self[$0]})
4 | }
5 | }
6 |
7 | typealias JSONObject = [String:AnyObject]
8 |
9 | // Regex that matches the query string part of a URL
10 | let queryStringRegEx = try! NSRegularExpression(pattern: "(/[^?]+).*", options: [])
11 |
12 | func URLPathByRemovingQueryString(_ URLString: String) -> String {
13 | guard let match = queryStringRegEx.firstMatchInString(URLString) else {
14 | return URLString
15 | }
16 | return (URLString as NSString).substring(with: match.range(at: 1))
17 | }
18 |
19 | // Regex that matches a SHA1 hash
20 | let sha1HashRegEx = try! NSRegularExpression(pattern: "[0-9a-f]{40}", options: [])
21 |
22 | // Regex that matches an ETag with a SHA1 hash
23 | let ETagWithSha1HashRegEx = try! NSRegularExpression(pattern: "\"([0-9a-f]{40})\"", options: [])
24 |
25 | func SHA1HashFromETag(_ ETag: String) -> String? {
26 | guard let match = ETagWithSha1HashRegEx.firstMatchInString(ETag) else {
27 | return nil
28 | }
29 |
30 | return (ETag as NSString).substring(with: match.range(at: 1))
31 | }
32 |
33 | extension NSRegularExpression {
34 | func firstMatchInString(_ string: String) -> NSTextCheckingResult? {
35 | return firstMatch(in: string, options: [],
36 | range: NSRange(location: 0, length: string.utf16.count))
37 | }
38 |
39 | func matches(_ string: String) -> Bool {
40 | return firstMatchInString(string) != nil
41 | }
42 | }
43 |
44 | extension URL {
45 | var isDirectory: Bool? {
46 | let values = try? self.resourceValues(forKeys: [.isDirectoryKey])
47 | return values?.isDirectory
48 | }
49 |
50 | var isRegularFile: Bool? {
51 | let values = try? self.resourceValues(forKeys: [.isRegularFileKey])
52 | return values?.isRegularFile
53 | }
54 | }
55 |
56 | extension HTTPURLResponse {
57 | var isSuccessful: Bool {
58 | return (200..<300).contains(statusCode)
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/ios/WebAppConfiguration.swift:
--------------------------------------------------------------------------------
1 | final class WebAppConfiguration {
2 | let userDefaults = UserDefaults.standard
3 |
4 | /// The appId as defined in the runtime config
5 | var appId: String? {
6 | get {
7 | return userDefaults.string(forKey: "MeteorWebAppId")
8 | }
9 | set {
10 | let oldValue = appId
11 | if newValue != oldValue && newValue != nil {
12 | if oldValue != nil {
13 | NSLog("appId seems to have changed, new: \(newValue!), old: \(oldValue!)")
14 | }
15 |
16 | userDefaults.set(newValue, forKey: "MeteorWebAppId")
17 | userDefaults.synchronize()
18 | }
19 | }
20 | }
21 |
22 | /// The rootURL as defined in the runtime config
23 | var rootURL: URL? {
24 | get {
25 | return userDefaults.url(forKey: "MeteorWebAppRootURL")
26 | }
27 | set {
28 | let oldValue = rootURL
29 | if newValue != oldValue && newValue != nil {
30 | if oldValue != nil {
31 | NSLog("ROOT_URL seems to have changed, new: \(newValue!), old: \(oldValue!)")
32 | }
33 |
34 | userDefaults.set(newValue, forKey: "MeteorWebAppRootURL")
35 | userDefaults.synchronize()
36 | }
37 | }
38 | }
39 |
40 | /// The Cordova compatibility version as specified in the asset manifest
41 | var cordovaCompatibilityVersion: String? {
42 | get {
43 | return userDefaults.string(forKey: "MeteorWebAppCordovaCompatibilityVersion")
44 | }
45 |
46 | set {
47 | if newValue != cordovaCompatibilityVersion {
48 | if newValue == nil {
49 | userDefaults.removeObject(forKey: "MeteorWebAppCordovaCompatibilityVersion")
50 | } else {
51 | userDefaults.set(newValue, forKey: "MeteorWebAppCordovaCompatibilityVersion")
52 | }
53 | userDefaults.synchronize()
54 | }
55 | }
56 | }
57 |
58 | /// The last seen initial version of the asset bundle
59 | var lastSeenInitialVersion: String? {
60 | get {
61 | return userDefaults.string(forKey: "MeteorWebAppLastSeenInitialVersion")
62 | }
63 |
64 | set {
65 | if newValue != lastSeenInitialVersion {
66 | if newValue == nil {
67 | userDefaults.removeObject(forKey: "MeteorWebAppLastSeenInitialVersion")
68 | } else {
69 | userDefaults.set(newValue, forKey: "MeteorWebAppLastSeenInitialVersion")
70 | }
71 | userDefaults.synchronize()
72 | }
73 | }
74 | }
75 |
76 | /// The last downloaded version of the asset bundle
77 | var lastDownloadedVersion: String? {
78 | get {
79 | return userDefaults.string(forKey: "MeteorWebAppLastDownloadedVersion")
80 | }
81 |
82 | set {
83 | if newValue != lastDownloadedVersion {
84 | if newValue == nil {
85 | userDefaults.removeObject(forKey: "MeteorWebAppLastDownloadedVersion")
86 | } else {
87 | userDefaults.set(newValue, forKey: "MeteorWebAppLastDownloadedVersion")
88 | }
89 | userDefaults.synchronize()
90 | }
91 | }
92 | }
93 |
94 | /// The last kwown good version of the asset bundle
95 | var lastKnownGoodVersion: String? {
96 | get {
97 | return userDefaults.string(forKey: "MeteorWebAppLastKnownGoodVersion")
98 | }
99 |
100 | set {
101 | if newValue != lastKnownGoodVersion {
102 | let userDefaults = UserDefaults.standard
103 | if newValue == nil {
104 | userDefaults.removeObject(forKey: "MeteorWebAppLastKnownGoodVersion")
105 | } else {
106 | userDefaults.set(newValue, forKey: "MeteorWebAppLastKnownGoodVersion")
107 | }
108 | userDefaults.synchronize()
109 | }
110 | }
111 | }
112 |
113 | /// Blacklisted asset bundle versions
114 | var blacklistedVersions: [String] {
115 | get {
116 | let versions = userDefaults.array(forKey: "MeteorWebAppBlacklistedVersions") as? [String] ?? []
117 | NSLog("BLACKLIST - blacklistedVersions: \(versions)")
118 | return versions
119 | }
120 |
121 | set {
122 | if newValue != blacklistedVersions {
123 | if newValue.isEmpty {
124 | NSLog("BLACKLIST - removing blacklisted versions");
125 | userDefaults.removeObject(forKey: "MeteorWebAppBlacklistedVersions")
126 | } else {
127 | userDefaults.set(newValue, forKey: "MeteorWebAppBlacklistedVersions")
128 | }
129 | userDefaults.synchronize()
130 | }
131 | }
132 | }
133 |
134 | var versionsToRetry: [String] {
135 | get {
136 | let versions = userDefaults.array(forKey: "MeteorWebAppVersionsToRetry") as? [String] ?? []
137 | NSLog("BLACKLIST - versionsToRetry: \(versions)")
138 | return versions
139 | }
140 | set {
141 | if newValue != versionsToRetry {
142 | if newValue.isEmpty {
143 | NSLog("BLACKLIST - removing versions to retry")
144 | userDefaults.removeObject(forKey: "MeteorWebAppVersionsToRetry")
145 | } else {
146 | userDefaults.set(newValue, forKey: "MeteorWebAppVersionsToRetry")
147 | }
148 | userDefaults.synchronize()
149 | }
150 | }
151 | }
152 |
153 | func addBlacklistedVersion(_ version: String) {
154 | var blacklistedVersions = self.blacklistedVersions
155 | var versionsToRetry = self.versionsToRetry
156 |
157 | if (!versionsToRetry.contains(version) && !blacklistedVersions.contains(version)) {
158 | NSLog("BLACKLIST - adding faulty version to retry: \(version)")
159 | versionsToRetry.append(version)
160 | self.versionsToRetry = versionsToRetry
161 | } else {
162 | if let i = versionsToRetry.index(of: version) {
163 | versionsToRetry.remove(at: i)
164 | self.versionsToRetry = versionsToRetry
165 | }
166 | if (!blacklistedVersions.contains(version)) {
167 | blacklistedVersions.append(version)
168 | NSLog("BLACKLIST - blacklisting version: \(version)")
169 | self.blacklistedVersions = blacklistedVersions
170 | }
171 | }
172 | }
173 |
174 | func reset() {
175 | cordovaCompatibilityVersion = nil
176 | lastSeenInitialVersion = nil
177 | lastDownloadedVersion = nil
178 | lastKnownGoodVersion = nil
179 | blacklistedVersions = []
180 | versionsToRetry = []
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/src/ios/cordova-plugin-meteor-webapp-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "METPlugin.h"
2 | #import "METTimer.h"
3 | #import "METRetryStrategy.h"
4 | #import "METNetworkReachabilityManager.h"
5 | #import "METRandomValueGenerator.h"
6 |
7 | #import "GCDWebServer.h"
8 | #import "GCDWebServerPrivate.h"
9 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/mobileapp.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-file:
--------------------------------------------------------------------------------
1 | some-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/template.mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | Template.body.addContent((function() {
3 | var view = this;
4 | return [ HTML.Raw("Welcome to Meteor!
\n\n "), Spacebars.include(view.lookupTemplate("hello")) ];
5 | }));
6 | Meteor.startup(Template.body.renderToDocument);
7 |
8 | Template.__checkName("hello");
9 | Template["hello"] = new Template("Template.hello", (function() {
10 | var view = this;
11 | return [ HTML.Raw("\n "), HTML.P("You've pressed the button ", Blaze.View("lookup:counter", function() {
12 | return Spacebars.mustache(view.lookup("counter"));
13 | }), " times.") ];
14 | }));
15 |
16 | }).call(this);
17 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/app/template.mobileapp.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor!
\\n\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
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 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | mobileapp
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/merged-stylesheets.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/not-in-manifest:
--------------------------------------------------------------------------------
1 | not-in-manifest
2 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/application/program.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version1",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?979b20f66caf126704c250fbd29ce253c6cb490e",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/979b20f66caf126704c250fbd29ce253c6cb490e.map",
28 | "size": 578,
29 | "hash": "979b20f66caf126704c250fbd29ce253c6cb490e"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 10,
69 | "hash": "23300652a57f3e819038d9a268ba36af0e25d33b"
70 | },
71 | {
72 | "path": "app/some-font.woff",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-font.woff",
77 | "size": 15,
78 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
79 | },
80 | {
81 | "path": "app/some-image.jpg",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-image.jpg",
86 | "size": 15,
87 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
88 | },
89 | {
90 | "path": "app/some-image.png",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.png",
95 | "size": 15,
96 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
97 | },
98 | {
99 | "path": "app/some-javascript.js",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-javascript.js",
104 | "size": 19,
105 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
106 | },
107 | {
108 | "path": "app/some-page.html",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-page.html",
113 | "size": 15,
114 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
115 | },
116 | {
117 | "path": "app/some-stylesheet.css",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-stylesheet.css",
122 | "size": 20,
123 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
124 | },
125 | {
126 | "path": "app/some-text.txt",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-text.txt",
131 | "size": 14,
132 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
133 | },
134 | {
135 | "path": "app/some-video.mp4",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-video.mp4",
140 | "size": 15,
141 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
142 | },
143 | {
144 | "path": "head.html",
145 | "where": "internal",
146 | "type": "head",
147 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
148 | }
149 | ]
150 | }
151 |
--------------------------------------------------------------------------------
/tests/fixtures/bundled_www/cordova_plugins.js:
--------------------------------------------------------------------------------
1 | cordova.define('cordova/plugin_list', function(require, exports, module) {
2 | module.exports = [
3 | {
4 | "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
5 | "id": "cordova-plugin-statusbar.statusbar",
6 | "pluginId": "cordova-plugin-statusbar",
7 | "clobbers": [
8 | "window.StatusBar"
9 | ]
10 | },
11 | {
12 | "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js",
13 | "id": "cordova-plugin-splashscreen.SplashScreen",
14 | "pluginId": "cordova-plugin-splashscreen",
15 | "clobbers": [
16 | "navigator.splashscreen"
17 | ]
18 | },
19 | {
20 | "file": "plugins/cordova-plugin-wkwebview-engine/src/www/ios/ios-wkwebview-exec.js",
21 | "id": "cordova-plugin-wkwebview-engine.ios-wkwebview-exec",
22 | "pluginId": "cordova-plugin-wkwebview-engine",
23 | "clobbers": [
24 | "cordova.exec"
25 | ]
26 | },
27 | {
28 | "file": "plugins/cordova-plugin-meteor-webapp/www/webapp_cordova.js",
29 | "id": "cordova-plugin-meteor-webapp.WebAppLocalServer",
30 | "pluginId": "cordova-plugin-meteor-webapp",
31 | "merges": [
32 | "WebAppLocalServer"
33 | ]
34 | }
35 | ];
36 | module.exports.metadata =
37 | // TOP OF METADATA
38 | {}
39 | // BOTTOM OF METADATA
40 | });
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/127.0.0.1_root_url/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "127.0.0.1_root_url",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": []
9 | }
10 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/different_cordova_compatibility_version/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "different_cordova_compatibility_version",
4 | "cordovaCompatibilityVersions": {
5 | "android": "f9d1e65c341c1b68740d41d35250e6a8e9503236",
6 | "ios": "9a02a7998ece3cf17379eec42582b3618825dc91"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?979b20f66caf126704c250fbd29ce253c6cb490e",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/979b20f66caf126704c250fbd29ce253c6cb490e.map",
28 | "size": 578,
29 | "hash": "979b20f66caf126704c250fbd29ce253c6cb490e"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 10,
69 | "hash": "23300652a57f3e819038d9a268ba36af0e25d33b"
70 | },
71 | {
72 | "path": "app/some-font.woff",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-font.woff",
77 | "size": 15,
78 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
79 | },
80 | {
81 | "path": "app/some-image.jpg",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-image.jpg",
86 | "size": 15,
87 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
88 | },
89 | {
90 | "path": "app/some-image.png",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.png",
95 | "size": 15,
96 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
97 | },
98 | {
99 | "path": "app/some-javascript.js",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-javascript.js",
104 | "size": 19,
105 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
106 | },
107 | {
108 | "path": "app/some-page.html",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-page.html",
113 | "size": 15,
114 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
115 | },
116 | {
117 | "path": "app/some-stylesheet.css",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-stylesheet.css",
122 | "size": 20,
123 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
124 | },
125 | {
126 | "path": "app/some-text.txt",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-text.txt",
131 | "size": 14,
132 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
133 | },
134 | {
135 | "path": "app/some-video.mp4",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-video.mp4",
140 | "size": 15,
141 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
142 | },
143 | {
144 | "path": "head.html",
145 | "where": "internal",
146 | "type": "head",
147 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
148 | }
149 | ]
150 | }
151 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/missing_app_id/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
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 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | mobileapp
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/missing_app_id/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "missing_app_id",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": []
9 | }
10 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/missing_cordova_compatibility_version/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "missing_cordova_compatibility_version",
4 | "manifest": [
5 | {
6 | "path": "packages/meteor.js",
7 | "where": "client",
8 | "type": "js",
9 | "cacheable": true,
10 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
11 | "sourceMap": "packages/meteor.js.map",
12 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
13 | "size": 113991,
14 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
15 | },
16 | {
17 | "path": "app/template.mobileapp.js",
18 | "where": "client",
19 | "type": "js",
20 | "cacheable": true,
21 | "url": "/app/template.mobileapp.js?979b20f66caf126704c250fbd29ce253c6cb490e",
22 | "sourceMap": "app/template.mobileapp.js.map",
23 | "sourceMapUrl": "/app/979b20f66caf126704c250fbd29ce253c6cb490e.map",
24 | "size": 578,
25 | "hash": "979b20f66caf126704c250fbd29ce253c6cb490e"
26 | },
27 | {
28 | "path": "app/mobileapp.js",
29 | "where": "client",
30 | "type": "js",
31 | "cacheable": true,
32 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
33 | "sourceMap": "app/mobileapp.js.map",
34 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
35 | "size": 2275,
36 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
37 | },
38 | {
39 | "path": "merged-stylesheets.css",
40 | "where": "client",
41 | "type": "css",
42 | "cacheable": true,
43 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
44 | "sourceMap": "merged-stylesheets.css.map",
45 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
46 | "size": 30,
47 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
48 | },
49 | {
50 | "path": "app/some-data.json",
51 | "where": "client",
52 | "type": "asset",
53 | "cacheable": false,
54 | "url": "/some-data.json",
55 | "size": 15,
56 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
57 | },
58 | {
59 | "path": "app/some-file",
60 | "where": "client",
61 | "type": "asset",
62 | "cacheable": false,
63 | "url": "/some-file",
64 | "size": 10,
65 | "hash": "23300652a57f3e819038d9a268ba36af0e25d33b"
66 | },
67 | {
68 | "path": "app/some-font.woff",
69 | "where": "client",
70 | "type": "asset",
71 | "cacheable": false,
72 | "url": "/some-font.woff",
73 | "size": 15,
74 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
75 | },
76 | {
77 | "path": "app/some-image.jpg",
78 | "where": "client",
79 | "type": "asset",
80 | "cacheable": false,
81 | "url": "/some-image.jpg",
82 | "size": 15,
83 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
84 | },
85 | {
86 | "path": "app/some-image.png",
87 | "where": "client",
88 | "type": "asset",
89 | "cacheable": false,
90 | "url": "/some-image.png",
91 | "size": 15,
92 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
93 | },
94 | {
95 | "path": "app/some-javascript.js",
96 | "where": "client",
97 | "type": "asset",
98 | "cacheable": false,
99 | "url": "/some-javascript.js",
100 | "size": 19,
101 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
102 | },
103 | {
104 | "path": "app/some-page.html",
105 | "where": "client",
106 | "type": "asset",
107 | "cacheable": false,
108 | "url": "/some-page.html",
109 | "size": 15,
110 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
111 | },
112 | {
113 | "path": "app/some-stylesheet.css",
114 | "where": "client",
115 | "type": "asset",
116 | "cacheable": false,
117 | "url": "/some-stylesheet.css",
118 | "size": 20,
119 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
120 | },
121 | {
122 | "path": "app/some-text.txt",
123 | "where": "client",
124 | "type": "asset",
125 | "cacheable": false,
126 | "url": "/some-text.txt",
127 | "size": 14,
128 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
129 | },
130 | {
131 | "path": "app/some-video.mp4",
132 | "where": "client",
133 | "type": "asset",
134 | "cacheable": false,
135 | "url": "/some-video.mp4",
136 | "size": 15,
137 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
138 | },
139 | {
140 | "path": "head.html",
141 | "where": "internal",
142 | "type": "head",
143 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
144 | }
145 | ]
146 | }
147 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/missing_root_url/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
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 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | mobileapp
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/missing_root_url/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "missing_root_url",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": []
9 | }
10 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/app/979b20f66caf126704c250fbd29ce253c6cb490e.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor!
\\n\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/app/template.mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | Template.body.addContent((function() {
3 | var view = this;
4 | return [ HTML.Raw("Welcome to Meteor!
\n\n "), Spacebars.include(view.lookupTemplate("hello")) ];
5 | }));
6 | Meteor.startup(Template.body.renderToDocument);
7 |
8 | Template.__checkName("hello");
9 | Template["hello"] = new Template("Template.hello", (function() {
10 | var view = this;
11 | return [ HTML.Raw("\n "), HTML.P("You've pressed the button ", Blaze.View("lookup:counter", function() {
12 | return Spacebars.mustache(view.lookup("counter"));
13 | }), " times.") ];
14 | }));
15 |
16 | }).call(this);
17 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version1",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?979b20f66caf126704c250fbd29ce253c6cb490e",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/979b20f66caf126704c250fbd29ce253c6cb490e.map",
28 | "size": 578,
29 | "hash": "979b20f66caf126704c250fbd29ce253c6cb490e"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 10,
69 | "hash": "23300652a57f3e819038d9a268ba36af0e25d33b"
70 | },
71 | {
72 | "path": "app/some-font.woff",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-font.woff",
77 | "size": 15,
78 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
79 | },
80 | {
81 | "path": "app/some-image.jpg",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-image.jpg",
86 | "size": 15,
87 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
88 | },
89 | {
90 | "path": "app/some-image.png",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.png",
95 | "size": 15,
96 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
97 | },
98 | {
99 | "path": "app/some-javascript.js",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-javascript.js",
104 | "size": 19,
105 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
106 | },
107 | {
108 | "path": "app/some-page.html",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-page.html",
113 | "size": 15,
114 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
115 | },
116 | {
117 | "path": "app/some-stylesheet.css",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-stylesheet.css",
122 | "size": 20,
123 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
124 | },
125 | {
126 | "path": "app/some-text.txt",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-text.txt",
131 | "size": 14,
132 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
133 | },
134 | {
135 | "path": "app/some-video.mp4",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-video.mp4",
140 | "size": 15,
141 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
142 | },
143 | {
144 | "path": "head.html",
145 | "where": "internal",
146 | "type": "head",
147 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
148 | }
149 | ]
150 | }
151 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/merged-stylesheets.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/not-in-manifest:
--------------------------------------------------------------------------------
1 | not-in-manifest
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-file:
--------------------------------------------------------------------------------
1 | some-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version1/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/20ae2c8d51b2507244e598844414ecdec2615ce3.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor (again)!
\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/app/template.mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | Template.body.addContent((function() {
3 | var view = this;
4 | return [ HTML.Raw("Welcome to Meteor (again)!
\n "), Spacebars.include(view.lookupTemplate("hello")) ];
5 | }));
6 | Meteor.startup(Template.body.renderToDocument);
7 |
8 | Template.__checkName("hello");
9 | Template["hello"] = new Template("Template.hello", (function() {
10 | var view = this;
11 | return [ HTML.Raw("\n "), HTML.P("You've pressed the button ", Blaze.View("lookup:counter", function() {
12 | return Spacebars.mustache(view.lookup("counter"));
13 | }), " times.") ];
14 | }));
15 |
16 | }).call(this);
17 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version2",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?3f6275657e6db3a21acb37d0f6c207cf83871e90",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map",
28 | "size": 584,
29 | "hash": "3f6275657e6db3a21acb37d0f6c207cf83871e90"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 20,
69 | "hash": "20242aa2ac9c728ca21c7cbbee841fd87e8277aa"
70 | },
71 | {
72 | "path": "app/some-other-file",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-other-file",
77 | "size": 16,
78 | "hash": "aa4405bb6a2eb7d79af8488b44d91e5c66c123a5"
79 | },
80 | {
81 | "path": "app/some-font.woff",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-font.woff",
86 | "size": 15,
87 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
88 | },
89 | {
90 | "path": "app/some-image.jpg",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.jpg",
95 | "size": 15,
96 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
97 | },
98 | {
99 | "path": "app/some-image.png",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-image.png",
104 | "size": 15,
105 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
106 | },
107 | {
108 | "path": "app/some-javascript.js",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-javascript.js",
113 | "size": 19,
114 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
115 | },
116 | {
117 | "path": "app/some-page.html",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-page.html",
122 | "size": 15,
123 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
124 | },
125 | {
126 | "path": "app/some-stylesheet.css",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-stylesheet.css",
131 | "size": 20,
132 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
133 | },
134 | {
135 | "path": "app/some-text.txt",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-text.txt",
140 | "size": 14,
141 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
142 | },
143 | {
144 | "path": "app/some-video.mp4",
145 | "where": "client",
146 | "type": "asset",
147 | "cacheable": false,
148 | "url": "/some-video.mp4",
149 | "size": 15,
150 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
151 | },
152 | {
153 | "path": "head.html",
154 | "where": "internal",
155 | "type": "head",
156 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-file:
--------------------------------------------------------------------------------
1 | some-file (changed)
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-other-file:
--------------------------------------------------------------------------------
1 | some-other-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/20ae2c8d51b2507244e598844414ecdec2615ce3.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor (again)!
\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/app/template.mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | Template.body.addContent((function() {
3 | var view = this;
4 | return [ HTML.Raw("Welcome to Meteor (one more time)!
\n "), Spacebars.include(view.lookupTemplate("hello")) ];
5 | }));
6 | Meteor.startup(Template.body.renderToDocument);
7 |
8 | Template.__checkName("hello");
9 | Template["hello"] = new Template("Template.hello", (function() {
10 | var view = this;
11 | return [ HTML.Raw("\n "), HTML.P("You've pressed the button ", Blaze.View("lookup:counter", function() {
12 | return Spacebars.mustache(view.lookup("counter"));
13 | }), " times.") ];
14 | }));
15 |
16 | }).call(this);
17 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version2",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?3f6275657e6db3a21acb37d0f6c207cf83871e90",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map",
28 | "size": 584,
29 | "hash": "3f6275657e6db3a21acb37d0f6c207cf83871e90"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 20,
69 | "hash": "20242aa2ac9c728ca21c7cbbee841fd87e8277aa"
70 | },
71 | {
72 | "path": "app/some-other-file",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-other-file",
77 | "size": 16,
78 | "hash": "aa4405bb6a2eb7d79af8488b44d91e5c66c123a5"
79 | },
80 | {
81 | "path": "app/some-font.woff",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-font.woff",
86 | "size": 15,
87 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
88 | },
89 | {
90 | "path": "app/some-image.jpg",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.jpg",
95 | "size": 15,
96 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
97 | },
98 | {
99 | "path": "app/some-image.png",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-image.png",
104 | "size": 15,
105 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
106 | },
107 | {
108 | "path": "app/some-javascript.js",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-javascript.js",
113 | "size": 19,
114 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
115 | },
116 | {
117 | "path": "app/some-page.html",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-page.html",
122 | "size": 15,
123 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
124 | },
125 | {
126 | "path": "app/some-stylesheet.css",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-stylesheet.css",
131 | "size": 20,
132 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
133 | },
134 | {
135 | "path": "app/some-text.txt",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-text.txt",
140 | "size": 14,
141 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
142 | },
143 | {
144 | "path": "app/some-video.mp4",
145 | "where": "client",
146 | "type": "asset",
147 | "cacheable": false,
148 | "url": "/some-video.mp4",
149 | "size": 15,
150 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
151 | },
152 | {
153 | "path": "head.html",
154 | "where": "internal",
155 | "type": "head",
156 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-file:
--------------------------------------------------------------------------------
1 | some-file (changed)
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-other-file:
--------------------------------------------------------------------------------
1 | some-other-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_invalid_asset/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/20ae2c8d51b2507244e598844414ecdec2615ce3.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor (again)!
\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version2",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?3f6275657e6db3a21acb37d0f6c207cf83871e90",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map",
28 | "size": 584,
29 | "hash": "3f6275657e6db3a21acb37d0f6c207cf83871e90"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 20,
69 | "hash": "20242aa2ac9c728ca21c7cbbee841fd87e8277aa"
70 | },
71 | {
72 | "path": "app/some-other-file",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-other-file",
77 | "size": 16,
78 | "hash": "aa4405bb6a2eb7d79af8488b44d91e5c66c123a5"
79 | },
80 | {
81 | "path": "app/some-font.woff",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-font.woff",
86 | "size": 15,
87 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
88 | },
89 | {
90 | "path": "app/some-image.jpg",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.jpg",
95 | "size": 15,
96 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
97 | },
98 | {
99 | "path": "app/some-image.png",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-image.png",
104 | "size": 15,
105 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
106 | },
107 | {
108 | "path": "app/some-javascript.js",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-javascript.js",
113 | "size": 19,
114 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
115 | },
116 | {
117 | "path": "app/some-page.html",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-page.html",
122 | "size": 15,
123 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
124 | },
125 | {
126 | "path": "app/some-stylesheet.css",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-stylesheet.css",
131 | "size": 20,
132 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
133 | },
134 | {
135 | "path": "app/some-text.txt",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-text.txt",
140 | "size": 14,
141 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
142 | },
143 | {
144 | "path": "app/some-video.mp4",
145 | "where": "client",
146 | "type": "asset",
147 | "cacheable": false,
148 | "url": "/some-video.mp4",
149 | "size": 15,
150 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
151 | },
152 | {
153 | "path": "head.html",
154 | "where": "internal",
155 | "type": "head",
156 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-file:
--------------------------------------------------------------------------------
1 | some-file (changed)
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-other-file:
--------------------------------------------------------------------------------
1 | some-other-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_missing_asset/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/20ae2c8d51b2507244e598844414ecdec2615ce3.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor (again)!
\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/app/template.mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | Template.body.addContent((function() {
3 | var view = this;
4 | return [ HTML.Raw("Welcome to Meteor (again)!
\n "), Spacebars.include(view.lookupTemplate("hello")) ];
5 | }));
6 | Meteor.startup(Template.body.renderToDocument);
7 |
8 | Template.__checkName("hello");
9 | Template["hello"] = new Template("Template.hello", (function() {
10 | var view = this;
11 | return [ HTML.Raw("\n "), HTML.P("You've pressed the button ", Blaze.View("lookup:counter", function() {
12 | return Spacebars.mustache(view.lookup("counter"));
13 | }), " times.") ];
14 | }));
15 |
16 | }).call(this);
17 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version2",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?3f6275657e6db3a21acb37d0f6c207cf83871e90",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map",
28 | "size": 584,
29 | "hash": "3f6275657e6db3a21acb37d0f6c207cf83871e90"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 20,
69 | "hash": "20242aa2ac9c728ca21c7cbbee841fd87e8277aa"
70 | },
71 | {
72 | "path": "app/some-other-file",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-other-file",
77 | "size": 16,
78 | "hash": "aa4405bb6a2eb7d79af8488b44d91e5c66c123a5"
79 | },
80 | {
81 | "path": "app/some-font.woff",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-font.woff",
86 | "size": 15,
87 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
88 | },
89 | {
90 | "path": "app/some-image.jpg",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.jpg",
95 | "size": 15,
96 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
97 | },
98 | {
99 | "path": "app/some-image.png",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-image.png",
104 | "size": 15,
105 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
106 | },
107 | {
108 | "path": "app/some-javascript.js",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-javascript.js",
113 | "size": 19,
114 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
115 | },
116 | {
117 | "path": "app/some-page.html",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-page.html",
122 | "size": 15,
123 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
124 | },
125 | {
126 | "path": "app/some-stylesheet.css",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-stylesheet.css",
131 | "size": 20,
132 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
133 | },
134 | {
135 | "path": "app/some-text.txt",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-text.txt",
140 | "size": 14,
141 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
142 | },
143 | {
144 | "path": "app/some-video.mp4",
145 | "where": "client",
146 | "type": "asset",
147 | "cacheable": false,
148 | "url": "/some-video.mp4",
149 | "size": 15,
150 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
151 | },
152 | {
153 | "path": "head.html",
154 | "where": "internal",
155 | "type": "head",
156 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-file:
--------------------------------------------------------------------------------
1 | some-file (changed)
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-other-file:
--------------------------------------------------------------------------------
1 | some-other-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version2_with_version_mismatch/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/20ae2c8d51b2507244e598844414ecdec2615ce3.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/app/mobileapp.css"],"names":[],"mappings":"AAAA","sourcesContent":["/* CSS declarations go here */\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/app/36e96c1d40459ae12164569599c9c0a203b36db7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/template.mobileapp.js"],"names":[],"mappings":"YAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/template.mobileapp.js","sourcesContent":["\nTemplate.body.addContent((function() {\n var view = this;\n return [ HTML.Raw(\"Welcome to Meteor (one more time)!
\\n \"), Spacebars.include(view.lookupTemplate(\"hello\")) ];\n}));\nMeteor.startup(Template.body.renderToDocument);\n\nTemplate.__checkName(\"hello\");\nTemplate[\"hello\"] = new Template(\"Template.hello\", (function() {\n var view = this;\n return [ HTML.Raw(\"\\n \"), HTML.P(\"You've pressed the button \", Blaze.View(\"lookup:counter\", function() {\n return Spacebars.mustache(view.lookup(\"counter\"));\n }), \" times.\") ];\n}));\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["meteor://💻app/mobileapp.js"],"names":[],"mappings":";;;;;;;;AAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;;AAEnB,SAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;;AAEjC,UAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACrB,WAAO,EAAE,YAAY;AACnB,aAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAC/B;GACF,CAAC,CAAC;;AAEH,UAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACpB,kBAAc,EAAE,YAAY;;AAE1B,aAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;KACpD;GACF,CAAC,CAAC;CACJ;;AAED,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,QAAM,CAAC,OAAO,CAAC,YAAY;;GAE1B,CAAC,CAAC;CACJ,wE","file":"/mobileapp.js","sourcesContent":["if (Meteor.isClient) {\n // counter starts at 0\n Session.setDefault('counter', 0);\n\n Template.hello.helpers({\n counter: function () {\n return Session.get('counter');\n }\n });\n\n Template.hello.events({\n 'click button': function () {\n // increment the counter when button is clicked\n Session.set('counter', Session.get('counter') + 1);\n }\n });\n}\n\nif (Meteor.isServer) {\n Meteor.startup(function () {\n // code to run on server at startup\n });\n}\n"]}
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/app/mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | /////////////////////////////////////////////////////////////////////////
4 | // //
5 | // mobileapp.js //
6 | // //
7 | /////////////////////////////////////////////////////////////////////////
8 | //
9 | if (Meteor.isClient) { // 1
10 | // counter starts at 0 //
11 | Session.setDefault('counter', 0); // 3
12 | //
13 | Template.hello.helpers({ // 5
14 | counter: function () { // 6
15 | return Session.get('counter'); // 7
16 | } //
17 | }); //
18 | //
19 | Template.hello.events({ // 11
20 | 'click button': function () { // 12
21 | // increment the counter when button is clicked //
22 | Session.set('counter', Session.get('counter') + 1); // 14
23 | } //
24 | }); //
25 | } //
26 | //
27 | if (Meteor.isServer) { // 19
28 | Meteor.startup(function () { // 20
29 | // code to run on server at startup //
30 | }); //
31 | } //
32 | /////////////////////////////////////////////////////////////////////////
33 |
34 | }).call(this);
35 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/app/template.mobileapp.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | Template.body.addContent((function() {
3 | var view = this;
4 | return [ HTML.Raw("Welcome to Meteor (one more time)!
\n "), Spacebars.include(view.lookupTemplate("hello")) ];
5 | }));
6 | Meteor.startup(Template.body.renderToDocument);
7 |
8 | Template.__checkName("hello");
9 | Template["hello"] = new Template("Template.hello", (function() {
10 | var view = this;
11 | return [ HTML.Raw("\n "), HTML.P("You've pressed the button ", Blaze.View("lookup:counter", function() {
12 | return Spacebars.mustache(view.lookup("counter"));
13 | }), " times.") ];
14 | }));
15 |
16 | }).call(this);
17 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/head.html:
--------------------------------------------------------------------------------
1 | mobileapp
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version3",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?36e96c1d40459ae12164569599c9c0a203b36db7",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/36e96c1d40459ae12164569599c9c0a203b36db7.map",
28 | "size": 592,
29 | "hash": "36e96c1d40459ae12164569599c9c0a203b36db7"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 26,
69 | "hash": "eb436b5a9ae39f7b8faef931024a86b73729da9e"
70 | },
71 | {
72 | "path": "app/some-other-file",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-other-file",
77 | "size": 16,
78 | "hash": "aa4405bb6a2eb7d79af8488b44d91e5c66c123a5"
79 | },
80 | {
81 | "path": "app/some-font.woff",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-font.woff",
86 | "size": 15,
87 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
88 | },
89 | {
90 | "path": "app/some-image.jpg",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.jpg",
95 | "size": 15,
96 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
97 | },
98 | {
99 | "path": "app/some-image.png",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-image.png",
104 | "size": 15,
105 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
106 | },
107 | {
108 | "path": "app/some-javascript.js",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-javascript.js",
113 | "size": 19,
114 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
115 | },
116 | {
117 | "path": "app/some-page.html",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-page.html",
122 | "size": 15,
123 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
124 | },
125 | {
126 | "path": "app/some-stylesheet.css",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-stylesheet.css",
131 | "size": 20,
132 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
133 | },
134 | {
135 | "path": "app/some-text.txt",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-text.txt",
140 | "size": 14,
141 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
142 | },
143 | {
144 | "path": "app/some-video.mp4",
145 | "where": "client",
146 | "type": "asset",
147 | "cacheable": false,
148 | "url": "/some-video.mp4",
149 | "size": 15,
150 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
151 | },
152 | {
153 | "path": "head.html",
154 | "where": "internal",
155 | "type": "head",
156 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/merged-stylesheets.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-data.json:
--------------------------------------------------------------------------------
1 | some-data.json
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-file:
--------------------------------------------------------------------------------
1 | some-file (changed again)
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-font.woff:
--------------------------------------------------------------------------------
1 | some-font.woff
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-image.jpg:
--------------------------------------------------------------------------------
1 | some-image.jpg
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-image.png:
--------------------------------------------------------------------------------
1 | some-image.png
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-javascript.js:
--------------------------------------------------------------------------------
1 | some-javascript.js
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-other-file:
--------------------------------------------------------------------------------
1 | some-other-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-page.html:
--------------------------------------------------------------------------------
1 | some-page.html
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-stylesheet.css:
--------------------------------------------------------------------------------
1 | some-stylesheet.css
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-text.txt:
--------------------------------------------------------------------------------
1 | some-text.txt
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/version3/some-video.mp4:
--------------------------------------------------------------------------------
1 | some-video.mp4
2 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/wrong_app_id/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "wrong_app_id",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": []
9 | }
10 |
--------------------------------------------------------------------------------
/tests/fixtures/downloadable_versions/wrong_root_url/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "wrong_root_url",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": []
9 | }
10 |
--------------------------------------------------------------------------------
/tests/fixtures/partially_downloaded_versions/version2/app/some-file:
--------------------------------------------------------------------------------
1 | some-file (changed)
2 |
--------------------------------------------------------------------------------
/tests/fixtures/partially_downloaded_versions/version2/app/some-other-file:
--------------------------------------------------------------------------------
1 | some-other-file
2 |
--------------------------------------------------------------------------------
/tests/fixtures/partially_downloaded_versions/version2/program.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": "web-program-pre1",
3 | "version": "version2",
4 | "cordovaCompatibilityVersions": {
5 | "android": "4017747ca6b4f460f33b121e439b7a11a070205a",
6 | "ios": "0abe549f2adbcf6cd295428aefea628ebe69666a"
7 | },
8 | "manifest": [
9 | {
10 | "path": "packages/meteor.js",
11 | "where": "client",
12 | "type": "js",
13 | "cacheable": true,
14 | "url": "/packages/meteor.js?57d11a30155349aa5106f8150cee35eac5f4764c",
15 | "sourceMap": "packages/meteor.js.map",
16 | "sourceMapUrl": "/packages/57d11a30155349aa5106f8150cee35eac5f4764c.map",
17 | "size": 113991,
18 | "hash": "57d11a30155349aa5106f8150cee35eac5f4764c"
19 | },
20 | {
21 | "path": "app/template.mobileapp.js",
22 | "where": "client",
23 | "type": "js",
24 | "cacheable": true,
25 | "url": "/app/template.mobileapp.js?3f6275657e6db3a21acb37d0f6c207cf83871e90",
26 | "sourceMap": "app/template.mobileapp.js.map",
27 | "sourceMapUrl": "/app/3f6275657e6db3a21acb37d0f6c207cf83871e90.map",
28 | "size": 584,
29 | "hash": "3f6275657e6db3a21acb37d0f6c207cf83871e90"
30 | },
31 | {
32 | "path": "app/mobileapp.js",
33 | "where": "client",
34 | "type": "js",
35 | "cacheable": true,
36 | "url": "/app/mobileapp.js?6db9763f3e0f4e4cbf78111f73823043ab08e3e7",
37 | "sourceMap": "app/mobileapp.js.map",
38 | "sourceMapUrl": "/app/6db9763f3e0f4e4cbf78111f73823043ab08e3e7.map",
39 | "size": 2275,
40 | "hash": "6db9763f3e0f4e4cbf78111f73823043ab08e3e7"
41 | },
42 | {
43 | "path": "merged-stylesheets.css",
44 | "where": "client",
45 | "type": "css",
46 | "cacheable": true,
47 | "url": "/merged-stylesheets.css?20ae2c8d51b2507244e598844414ecdec2615ce3",
48 | "sourceMap": "merged-stylesheets.css.map",
49 | "sourceMapUrl": "/20ae2c8d51b2507244e598844414ecdec2615ce3.map",
50 | "size": 30,
51 | "hash": "20ae2c8d51b2507244e598844414ecdec2615ce3"
52 | },
53 | {
54 | "path": "app/some-data.json",
55 | "where": "client",
56 | "type": "asset",
57 | "cacheable": false,
58 | "url": "/some-data.json",
59 | "size": 15,
60 | "hash": "3edc8875bc0dd76d9f5fce5e823dca6f17a26da7"
61 | },
62 | {
63 | "path": "app/some-file",
64 | "where": "client",
65 | "type": "asset",
66 | "cacheable": false,
67 | "url": "/some-file",
68 | "size": 20,
69 | "hash": "20242aa2ac9c728ca21c7cbbee841fd87e8277aa"
70 | },
71 | {
72 | "path": "app/some-other-file",
73 | "where": "client",
74 | "type": "asset",
75 | "cacheable": false,
76 | "url": "/some-other-file",
77 | "size": 16,
78 | "hash": "aa4405bb6a2eb7d79af8488b44d91e5c66c123a5"
79 | },
80 | {
81 | "path": "app/some-font.woff",
82 | "where": "client",
83 | "type": "asset",
84 | "cacheable": false,
85 | "url": "/some-font.woff",
86 | "size": 15,
87 | "hash": "6ec7e1e1c0199bfb5bcd6877de9fe7abefd26df8"
88 | },
89 | {
90 | "path": "app/some-image.jpg",
91 | "where": "client",
92 | "type": "asset",
93 | "cacheable": false,
94 | "url": "/some-image.jpg",
95 | "size": 15,
96 | "hash": "13f1d459365d5604dbf2b64b203fa583c1c7fc3f"
97 | },
98 | {
99 | "path": "app/some-image.png",
100 | "where": "client",
101 | "type": "asset",
102 | "cacheable": false,
103 | "url": "/some-image.png",
104 | "size": 15,
105 | "hash": "06b05b4c2720cd9ff733d21c594eac4e865a6e73"
106 | },
107 | {
108 | "path": "app/some-javascript.js",
109 | "where": "client",
110 | "type": "asset",
111 | "cacheable": false,
112 | "url": "/some-javascript.js",
113 | "size": 19,
114 | "hash": "51a3422f25ddf466a35e00e327d5f4ca90eee8f4"
115 | },
116 | {
117 | "path": "app/some-page.html",
118 | "where": "client",
119 | "type": "asset",
120 | "cacheable": false,
121 | "url": "/some-page.html",
122 | "size": 15,
123 | "hash": "5dc6878863a1fd4f7f69713b4c072280932255af"
124 | },
125 | {
126 | "path": "app/some-stylesheet.css",
127 | "where": "client",
128 | "type": "asset",
129 | "cacheable": false,
130 | "url": "/some-stylesheet.css",
131 | "size": 20,
132 | "hash": "b33cc1bdaa963ae1cec9afd4c833d80caf7641a2"
133 | },
134 | {
135 | "path": "app/some-text.txt",
136 | "where": "client",
137 | "type": "asset",
138 | "cacheable": false,
139 | "url": "/some-text.txt",
140 | "size": 14,
141 | "hash": "bb874a02400d28518a3d0f7a4c7fd8970735bea1"
142 | },
143 | {
144 | "path": "app/some-video.mp4",
145 | "where": "client",
146 | "type": "asset",
147 | "cacheable": false,
148 | "url": "/some-video.mp4",
149 | "size": 15,
150 | "hash": "45e892d4c7ce693f5cd551fcd671cf227ff1ae3a"
151 | },
152 | {
153 | "path": "head.html",
154 | "where": "internal",
155 | "type": "head",
156 | "hash": "2ce23f770b76d2f1cb0d71f4a43fbbb61afb25be"
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/tests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-meteor-webapptests",
3 | "version": "1.3.1",
4 | "cordova": {
5 | "id": "cordova-plugin-meteor-webapp-tests",
6 | "platforms": [
7 | "android",
8 | "ios"
9 | ]
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/meteor/cordova-plugin-meteor-webapp"
14 | },
15 | "keywords": [
16 | "cordova",
17 | "meteor",
18 | "ecosystem:cordova",
19 | "cordova-android",
20 | "cordova-ios"
21 | ],
22 | "author": "Meteor Development Group",
23 | "license": "MIT"
24 | }
25 |
--------------------------------------------------------------------------------
/tests/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | Meteor Webapp Tests
6 | Meteor Development Group
7 | MIT
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 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/tests/src/ios/GCDWebServer+Testing.h:
--------------------------------------------------------------------------------
1 | #import "GCDWebServer.h"
2 |
3 | @protocol GCDWebServerTestingDelegate
4 | - (void)webServer:(GCDWebServer *)server didReceiveRequest:(GCDWebServerRequest *)request;
5 | @end
6 |
7 | @interface GCDWebServer (Testing)
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/tests/src/ios/GCDWebServer+Testing.m:
--------------------------------------------------------------------------------
1 | #import "GCDWebServer+Testing.h"
2 | #import "GCDWebServerPrivate.h"
3 | #import
4 |
5 | @implementation GCDWebServer (Testing)
6 |
7 | + (void)load {
8 | static dispatch_once_t onceToken;
9 | dispatch_once(&onceToken, ^{
10 | Class class = [self class];
11 |
12 | SEL originalSelector = @selector(addHandlerWithMatchBlock:asyncProcessBlock:);
13 | SEL swizzledSelector = @selector(testing_addHandlerWithMatchBlock:asyncProcessBlock:);
14 |
15 | Method originalMethod = class_getInstanceMethod(class, originalSelector);
16 | Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
17 |
18 | method_exchangeImplementations(originalMethod, swizzledMethod);
19 | });
20 | }
21 |
22 | - (void)testing_addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock)processBlock {
23 | __weak __typeof__(self) weakSelf = self;
24 | [self testing_addHandlerWithMatchBlock:matchBlock asyncProcessBlock:^(GCDWebServerRequest *request, GCDWebServerCompletionBlock completionBlock) {
25 | __strong __typeof(weakSelf) strongSelf = weakSelf;
26 | id delegate = strongSelf.delegate;
27 | if ([delegate respondsToSelector:@selector(webServer:didReceiveRequest:)]) {
28 | dispatch_async(dispatch_get_main_queue(), ^{
29 | [((id)delegate) webServer:strongSelf didReceiveRequest:request];
30 | });
31 | }
32 |
33 | processBlock(request, completionBlock);
34 | }];
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/tests/src/ios/WebAppLocalServer+Testing.swift:
--------------------------------------------------------------------------------
1 | extension WebAppLocalServer {
2 | @objc func simulatePageReload(_ command: CDVInvokedUrlCommand) {
3 | onReset()
4 |
5 | let result = CDVPluginResult(status: CDVCommandStatus_OK)
6 | commandDelegate?.send(result, callbackId:command.callbackId)
7 | }
8 |
9 | @objc func simulateAppRestart(_ command: CDVInvokedUrlCommand) {
10 | initializeAssetBundles()
11 | onReset()
12 |
13 | let result = CDVPluginResult(status: CDVCommandStatus_OK)
14 | commandDelegate?.send(result, callbackId:command.callbackId)
15 | }
16 |
17 | @objc func resetToInitialState(_ command: CDVInvokedUrlCommand) {
18 | commandDelegate?.run() {
19 | self.configuration.reset()
20 | self.initializeAssetBundles()
21 | self.onReset()
22 |
23 | let result = CDVPluginResult(status: CDVCommandStatus_OK)
24 | self.commandDelegate?.send(result, callbackId:command.callbackId)
25 | }
26 | }
27 |
28 | @objc func getAuthTokenKeyValuePair(_ command: CDVInvokedUrlCommand) {
29 | let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: authTokenKeyValuePair)
30 | commandDelegate?.send(result, callbackId:command.callbackId)
31 | }
32 |
33 | @objc func downloadedVersionExists(_ command: CDVInvokedUrlCommand) {
34 | guard let version = command.argument(at: 0) as? String else {
35 | let errorMessage = "'version' argument required"
36 | let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: errorMessage)
37 | commandDelegate?.send(result, callbackId: command.callbackId)
38 | return
39 | }
40 |
41 | let versionExists = assetBundleManager.downloadedAssetBundleWithVersion(version) != nil
42 |
43 | let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: versionExists)
44 | commandDelegate?.send(result, callbackId:command.callbackId)
45 | }
46 |
47 | @objc func simulatePartialDownload(_ command: CDVInvokedUrlCommand) {
48 | guard let version = command.argument(at: 0) as? String else {
49 | let errorMessage = "'version' argument required"
50 | let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: errorMessage)
51 | commandDelegate?.send(result, callbackId: command.callbackId)
52 | return
53 | }
54 |
55 | commandDelegate?.run() {
56 | let wwwDirectoryURL = Bundle.main.resourceURL!.appendingPathComponent("www")
57 | let versionDirectoryURL = wwwDirectoryURL.appendingPathComponent("partially_downloaded_versions/\(version)")
58 |
59 | let versionsDirectoryURL = self.assetBundleManager.versionsDirectoryURL
60 | let downloadDirectoryURL = versionsDirectoryURL.appendingPathComponent("Downloading")
61 |
62 | let fileManager = FileManager.default
63 |
64 | if fileManager.fileExists(atPath: downloadDirectoryURL.path) {
65 | try! fileManager.removeItem(at: downloadDirectoryURL)
66 | }
67 |
68 | try! fileManager.copyItem(at: versionDirectoryURL, to: downloadDirectoryURL)
69 |
70 | let result = CDVPluginResult(status: CDVCommandStatus_OK)
71 | self.commandDelegate?.send(result, callbackId:command.callbackId)
72 | };
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/src/ios/WebAppMockRemoteServer.swift:
--------------------------------------------------------------------------------
1 | extension Data {
2 | func SHA1() -> String {
3 | var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
4 |
5 | withUnsafeBytes { (bytes) -> Void in
6 | CC_SHA1(bytes, CC_LONG(count), &digest)
7 | }
8 |
9 | var hexString = ""
10 | for index in 0.. GCDWebServerRequest! in
75 | if requestMethod != "GET" { return nil }
76 | if !(URLPath.hasPrefix(basePath)) { return nil }
77 |
78 | let request = GCDWebServerRequest(method: requestMethod, url: requestURL, headers: requestHeaders, path: URLPath, query: URLQuery)
79 | return request
80 | }) { (request) -> GCDWebServerResponse! in
81 | let URLPath = request.path.substring(from: basePath.endIndex)
82 | let fileURL = self.versionDirectoryURL.appendingPathComponent(URLPath)
83 |
84 | var response: GCDWebServerResponse
85 |
86 | var isDirectory = ObjCBool(false)
87 | if fileManager.fileExists(atPath: fileURL.path, isDirectory: &isDirectory)
88 | && !isDirectory.boolValue {
89 | response = GCDWebServerFileResponse(file: fileURL.path)!
90 | let fileHash = (try! Data(contentsOf: fileURL)).SHA1()
91 | response.eTag = "\"\(fileHash)\""
92 | } else if request.query!["meteor_dont_serve_index"] == nil {
93 | let indexFileURL = self.versionDirectoryURL.appendingPathComponent("index.html")
94 | response = GCDWebServerFileResponse(file: indexFileURL.path)!
95 | } else {
96 | response = GCDWebServerResponse(statusCode: GCDWebServerClientErrorHTTPStatusCode.httpStatusCode_NotFound.rawValue)
97 | }
98 |
99 | response.cacheControlMaxAge = 0
100 | response.lastModifiedDate = nil
101 | return response
102 | }
103 | }
104 |
105 | @objc func receivedRequests(_ command: CDVInvokedUrlCommand) {
106 | let receivedRequestURLs = receivedRequests!.map {
107 | ["path": $0.path, "query": $0.query, "headers": $0.headers]
108 | }
109 |
110 | let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: receivedRequestURLs)
111 | commandDelegate?.send(result, callbackId:command.callbackId)
112 | }
113 |
114 | // MARK: GCDWebServerTestingDelegate
115 |
116 | func webServerDidStart(_ server: GCDWebServer!) {
117 | receivedRequests = [GCDWebServerRequest]()
118 | }
119 |
120 | func webServer(_ server: GCDWebServer!, didReceive request: GCDWebServerRequest!) {
121 | receivedRequests?.append(request)
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/tests/src/ios/cordova-plugin-meteor-webapp-tests-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "GCDWebServer+Testing.h"
4 |
--------------------------------------------------------------------------------
/tests/www/webapp_local_server_testing.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | resetToInitialState: function(callback) {
3 | cordova.exec(
4 | callback,
5 | console.error,
6 | "WebAppLocalServer",
7 | "resetToInitialState",
8 | []);
9 | },
10 |
11 | simulatePageReload: function(callback) {
12 | cordova.exec(
13 | callback,
14 | console.error,
15 | "WebAppLocalServer",
16 | "simulatePageReload",
17 | []);
18 | },
19 |
20 | simulateAppRestart: function(callback) {
21 | cordova.exec(
22 | callback,
23 | console.error,
24 | "WebAppLocalServer",
25 | "simulateAppRestart",
26 | []);
27 | },
28 |
29 | getAuthTokenKeyValuePair: function(callback) {
30 | cordova.exec(
31 | callback,
32 | console.error,
33 | "WebAppLocalServer",
34 | "getAuthTokenKeyValuePair",
35 | []);
36 | },
37 |
38 | downloadedVersionExists: function(version, callback) {
39 | cordova.exec(
40 | callback,
41 | console.error,
42 | "WebAppLocalServer",
43 | "downloadedVersionExists",
44 | [version]);
45 | },
46 |
47 | simulatePartialDownload: function(version, callback) {
48 | cordova.exec(
49 | callback,
50 | console.error,
51 | "WebAppLocalServer",
52 | "simulatePartialDownload",
53 | [version]);
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/tests/www/webapp_mock_remote_server.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | serveVersion: function(version, callback) {
3 | cordova.exec(
4 | callback,
5 | console.error,
6 | "WebAppMockRemoteServer",
7 | "serveVersion",
8 | [version]);
9 | },
10 |
11 | receivedRequests: function(callback) {
12 | cordova.exec(
13 | callback,
14 | console.error,
15 | "WebAppMockRemoteServer",
16 | "receivedRequests",
17 | []);
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/www/webapp_local_server.js:
--------------------------------------------------------------------------------
1 | var fileUrlRegEx = /^file:\/\/(.*)/;
2 |
3 | module.exports = {
4 | startupDidComplete: function(callback) {
5 | cordova.exec(
6 | callback,
7 | console.error,
8 | "WebAppLocalServer",
9 | "startupDidComplete",
10 | []);
11 | },
12 |
13 | checkForUpdates: function(callback) {
14 | cordova.exec(
15 | callback,
16 | console.error,
17 | "WebAppLocalServer",
18 | "checkForUpdates",
19 | []);
20 | },
21 |
22 | onNewVersionReady: function(callback) {
23 | cordova.exec(
24 | callback,
25 | console.error,
26 | "WebAppLocalServer",
27 | "onNewVersionReady",
28 | []);
29 | },
30 |
31 | switchToPendingVersion: function(callback, errorCallback) {
32 | cordova.exec(
33 | callback,
34 | function(error) {
35 | console.error(error);
36 | if (typeof errorCallback === "function") {
37 | errorCallback(error);
38 | }
39 | },
40 | "WebAppLocalServer",
41 | "switchPendingVersion",
42 | []
43 | );
44 | },
45 |
46 | onError: function(callback) {
47 | cordova.exec(
48 | function(errorMessage) {
49 | // Convert error message to a proper error object
50 | var error = new Error(errorMessage);
51 | callback(error);
52 | },
53 | console.error,
54 | "WebAppLocalServer",
55 | "onError",
56 | []);
57 | },
58 |
59 | localFileSystemUrl: function(fileUrl) {
60 | var match = fileUrlRegEx.exec(fileUrl);
61 | if (!match) return fileUrl;
62 |
63 | var path = match[1];
64 | return "/local-filesystem" + path;
65 | }
66 | };
67 |
--------------------------------------------------------------------------------