@applicaster/zapplicaster-cli 16.0.0-rc.9 → 16.0.0-rc.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/commands/prepareWorkspace/__tests__/__snapshots__/configurator.test.js.snap +2 -0
- package/src/commands/prepareWorkspace/appBootstrapper.js +9 -0
- package/src/commands/prepareWorkspace/configurator.js +26 -1
- package/src/commands/prepareWorkspace/parseFonts.js +6 -0
- package/src/commands/publishPlugin/generateManifest.js +1 -0
- package/src/commands/reloadConfig/__tests__/__snapshots__/reloadConfig.test.js.snap +58 -0
- package/src/commands/reloadConfig/__tests__/reloadConfig.test.js +86 -0
- package/src/commands/reloadConfig/index.js +6 -6
- package/src/download/__tests__/download.test.js +53 -0
- package/src/download/index.js +65 -1
- package/src/file/index.js +15 -9
- package/src/templates/__tests__/__snapshots__/templates.test.js.snap +1 -1
- package/src/templates/index.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapplicaster-cli",
|
|
3
|
-
"version": "16.0.0-rc.
|
|
3
|
+
"version": "16.0.0-rc.90",
|
|
4
4
|
"description": "CLI Tool for the zapp app and Quick Brick project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/zapp-react-dom-cli-template": "16.0.0-rc.
|
|
32
|
-
"@applicaster/zapp-react-native-android-tv-cli-template": "16.0.0-rc.
|
|
33
|
-
"@applicaster/zapp-react-native-cli-template": "16.0.0-rc.
|
|
34
|
-
"@applicaster/zapp-react-native-tvos-cli-template": "16.0.0-rc.
|
|
31
|
+
"@applicaster/zapp-react-dom-cli-template": "16.0.0-rc.90",
|
|
32
|
+
"@applicaster/zapp-react-native-android-tv-cli-template": "16.0.0-rc.90",
|
|
33
|
+
"@applicaster/zapp-react-native-cli-template": "16.0.0-rc.90",
|
|
34
|
+
"@applicaster/zapp-react-native-tvos-cli-template": "16.0.0-rc.90",
|
|
35
35
|
"axios": "^0.28.0",
|
|
36
36
|
"camelize": "^1.0.0",
|
|
37
37
|
"chalk": "^2.3.2",
|
|
@@ -8,6 +8,7 @@ exports[`configurator builds the configuration object 1`] = `
|
|
|
8
8
|
"appVersionId": "APP_VERSION_ID",
|
|
9
9
|
"assets_url": "https://assets-secure.applicaster.com/zapp/accounts/5ae06cef8fba0f00084bd3c6/apps/com.quickbricktest/apple_store/1.8/styles/assets_styles.json",
|
|
10
10
|
"otherParam": "param",
|
|
11
|
+
"vidaa_client_partner_id": undefined,
|
|
11
12
|
},
|
|
12
13
|
"destinationPath": "development-app",
|
|
13
14
|
"deviceTarget": undefined,
|
|
@@ -32,6 +33,7 @@ exports[`configurator sets a null path if none is provided and the cli doesn't r
|
|
|
32
33
|
"appVersionId": "APP_VERSION_ID",
|
|
33
34
|
"assets_url": "https://assets-secure.applicaster.com/zapp/accounts/5ae06cef8fba0f00084bd3c6/apps/com.quickbricktest/apple_store/1.8/styles/assets_styles.json",
|
|
34
35
|
"otherParam": "param",
|
|
36
|
+
"vidaa_client_partner_id": undefined,
|
|
35
37
|
},
|
|
36
38
|
"destinationPath": null,
|
|
37
39
|
"deviceTarget": undefined,
|
|
@@ -193,6 +193,15 @@ async function appBootstrapper(configuration) {
|
|
|
193
193
|
.map(toDayJSLocaleMap)
|
|
194
194
|
.filter((v) => v !== "en");
|
|
195
195
|
|
|
196
|
+
if (
|
|
197
|
+
configuration.buildParams.device_target === "vidaa" &&
|
|
198
|
+
!configuration.buildParams.vidaa_client_partner_id
|
|
199
|
+
) {
|
|
200
|
+
logger.warn(
|
|
201
|
+
"In order to use the VIDAA SDK you will need to set vidaa_client_partner_id"
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
196
205
|
configuration.excludedNodeModules = getExcludedNodeModules(plugins);
|
|
197
206
|
const { filesToRender } = template.files;
|
|
198
207
|
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
const R = require("ramda");
|
|
2
2
|
const axios = require("axios");
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
platformIsTV,
|
|
6
|
+
} = require("@applicaster/zapp-react-native-utils/manifestUtils/platformIsTV");
|
|
7
|
+
|
|
3
8
|
const { getAppVersionParams } = require("../../zapp");
|
|
4
9
|
const { resolveAppTemplate } = require("../../templates");
|
|
5
10
|
const { isZappReactNativeRepo } = require("../../settings");
|
|
6
11
|
|
|
12
|
+
function resolveVidaaClientPartnerId(buildParams = {}) {
|
|
13
|
+
const fromBuildParams = buildParams.vidaa_client_partner_id;
|
|
14
|
+
|
|
15
|
+
if (typeof fromBuildParams === "string" && fromBuildParams.trim()) {
|
|
16
|
+
return fromBuildParams.trim();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const fromEnv = process.env.vidaa_client_partner_id;
|
|
20
|
+
|
|
21
|
+
if (typeof fromEnv === "string" && fromEnv.trim()) {
|
|
22
|
+
return fromEnv.trim();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
7
28
|
const store_map = {
|
|
8
29
|
amazon: "amazon",
|
|
9
30
|
google_play: "android",
|
|
@@ -11,6 +32,7 @@ const store_map = {
|
|
|
11
32
|
samsung_app_store: "samsung_tv",
|
|
12
33
|
lg_content_store: "lg_tv",
|
|
13
34
|
vizio_app_store: "vizio",
|
|
35
|
+
vidaa_app_store: "vidaa",
|
|
14
36
|
};
|
|
15
37
|
|
|
16
38
|
/**
|
|
@@ -21,7 +43,7 @@ const store_map = {
|
|
|
21
43
|
*/
|
|
22
44
|
async function retrievesSpinnerColor(url, platform) {
|
|
23
45
|
try {
|
|
24
|
-
if (!
|
|
46
|
+
if (!platformIsTV(platform)) {
|
|
25
47
|
return;
|
|
26
48
|
}
|
|
27
49
|
|
|
@@ -72,6 +94,9 @@ async function configurator({ cliArgs, cliOptions }) {
|
|
|
72
94
|
|
|
73
95
|
const buildParams = await getAppVersionParams(appVersionId);
|
|
74
96
|
|
|
97
|
+
buildParams.vidaa_client_partner_id =
|
|
98
|
+
resolveVidaaClientPartnerId(buildParams);
|
|
99
|
+
|
|
75
100
|
delete buildParams.styles_url; // deprecated
|
|
76
101
|
|
|
77
102
|
const platform = resolvePlatform(buildParams.assets_url);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`reloadConfig runs the reload config task 1`] = `
|
|
4
|
+
[
|
|
5
|
+
[
|
|
6
|
+
"reload configuration",
|
|
7
|
+
"We're reloading the configuration for your app",
|
|
8
|
+
],
|
|
9
|
+
]
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
exports[`reloadConfig runs the reload config task 2`] = `[]`;
|
|
13
|
+
|
|
14
|
+
exports[`reloadConfig runs the reload config task 3`] = `[]`;
|
|
15
|
+
|
|
16
|
+
exports[`reloadConfig runs the reload config task 4`] = `[]`;
|
|
17
|
+
|
|
18
|
+
exports[`reloadConfig runs the reload config task 5`] = `
|
|
19
|
+
[
|
|
20
|
+
[
|
|
21
|
+
"checking prerequisites...",
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
"Gathering configuration",
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
"Creating workspace",
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"Creating runtime URLs configuration file",
|
|
31
|
+
],
|
|
32
|
+
[
|
|
33
|
+
"Retrieving configuration files",
|
|
34
|
+
],
|
|
35
|
+
]
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
exports[`reloadConfig runs the reload config task 6`] = `
|
|
39
|
+
[
|
|
40
|
+
[
|
|
41
|
+
"All good - moving on",
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
"configuration retrieved",
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
"Workspace created !",
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
"Runtime configuration URLs file created",
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"Configuration files retrieved !",
|
|
54
|
+
],
|
|
55
|
+
]
|
|
56
|
+
`;
|
|
57
|
+
|
|
58
|
+
exports[`reloadConfig runs the reload config task 7`] = `[]`;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const { reloadConfig } = require("../index");
|
|
2
|
+
|
|
3
|
+
const appVersionId = "e7a17c6f-4113-41ac-9450-6281d22153a1";
|
|
4
|
+
|
|
5
|
+
const options = {
|
|
6
|
+
appVersionId,
|
|
7
|
+
openSdk: true,
|
|
8
|
+
config: "some_file",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
jest.mock("../../../logger", () => ({
|
|
12
|
+
welcome: jest.fn(),
|
|
13
|
+
log: jest.fn(),
|
|
14
|
+
error: jest.fn(),
|
|
15
|
+
warn: jest.fn(),
|
|
16
|
+
startStep: jest.fn(),
|
|
17
|
+
endStep: jest.fn(),
|
|
18
|
+
success: jest.fn(),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
jest.mock("../../prepareWorkspace/prerequisitesChecker.js", () => ({
|
|
22
|
+
prerequisitesChecker: jest.fn(() => true),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
const mockConfig = { appVersionId, buildParams: {} };
|
|
26
|
+
|
|
27
|
+
jest.mock("../../prepareWorkspace/configurator.js", () => ({
|
|
28
|
+
configurator: jest.fn(() => mockConfig),
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
jest.mock("../../prepareWorkspace/workspaceCreator.js", () => ({
|
|
32
|
+
workspaceCreator: jest.fn(),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
jest.mock("../../prepareWorkspace/configFilesRetriever.js", () => ({
|
|
36
|
+
configFilesRetriever: jest.fn(),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
jest.mock("../../prepareWorkspace/runtimeConfigurationUrlsCreator.js", () => ({
|
|
40
|
+
runtimeConfigurationUrlsCreator: jest.fn(),
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
prerequisitesChecker,
|
|
45
|
+
} = require("../../prepareWorkspace/prerequisitesChecker");
|
|
46
|
+
|
|
47
|
+
const { configurator } = require("../../prepareWorkspace/configurator");
|
|
48
|
+
const { workspaceCreator } = require("../../prepareWorkspace/workspaceCreator");
|
|
49
|
+
|
|
50
|
+
const {
|
|
51
|
+
configFilesRetriever,
|
|
52
|
+
} = require("../../prepareWorkspace/configFilesRetriever");
|
|
53
|
+
|
|
54
|
+
const {
|
|
55
|
+
runtimeConfigurationUrlsCreator,
|
|
56
|
+
} = require("../../prepareWorkspace/runtimeConfigurationUrlsCreator");
|
|
57
|
+
|
|
58
|
+
const logger = require("../../../logger");
|
|
59
|
+
|
|
60
|
+
describe("reloadConfig", () => {
|
|
61
|
+
it("runs the reload config task", async () => {
|
|
62
|
+
await reloadConfig(appVersionId, options);
|
|
63
|
+
|
|
64
|
+
expect(logger.welcome.mock.calls).toMatchSnapshot();
|
|
65
|
+
expect(logger.log.mock.calls).toMatchSnapshot();
|
|
66
|
+
expect(logger.error.mock.calls).toMatchSnapshot();
|
|
67
|
+
expect(logger.warn.mock.calls).toMatchSnapshot();
|
|
68
|
+
expect(logger.startStep.mock.calls).toMatchSnapshot();
|
|
69
|
+
expect(logger.endStep.mock.calls).toMatchSnapshot();
|
|
70
|
+
expect(logger.success.mock.calls).toMatchSnapshot();
|
|
71
|
+
|
|
72
|
+
expect(prerequisitesChecker).toHaveBeenCalledWith({
|
|
73
|
+
cliArgs: [appVersionId],
|
|
74
|
+
cliOptions: options,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
expect(configurator).toHaveBeenCalledWith({
|
|
78
|
+
cliArgs: [appVersionId],
|
|
79
|
+
cliOptions: options,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(workspaceCreator).toHaveBeenCalledWith(mockConfig);
|
|
83
|
+
expect(runtimeConfigurationUrlsCreator).toHaveBeenCalledWith(mockConfig);
|
|
84
|
+
expect(configFilesRetriever).toHaveBeenCalledWith(mockConfig);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -27,18 +27,18 @@ const reloadConfigTask = {
|
|
|
27
27
|
error: "Could not create workspace",
|
|
28
28
|
completion: "Workspace created !",
|
|
29
29
|
},
|
|
30
|
-
{
|
|
31
|
-
start: "Retrieving configuration files",
|
|
32
|
-
run: configFilesRetriever,
|
|
33
|
-
error: "Could not retrieve configuration files",
|
|
34
|
-
completion: "Configuration files retrieved !",
|
|
35
|
-
},
|
|
36
30
|
{
|
|
37
31
|
start: "Creating runtime URLs configuration file",
|
|
38
32
|
run: runtimeConfigurationUrlsCreator,
|
|
39
33
|
error: "Could not create runtime_configuration_urls.json",
|
|
40
34
|
completion: "Runtime configuration URLs file created",
|
|
41
35
|
},
|
|
36
|
+
{
|
|
37
|
+
start: "Retrieving configuration files",
|
|
38
|
+
run: configFilesRetriever,
|
|
39
|
+
error: "Could not retrieve configuration files",
|
|
40
|
+
completion: "Configuration files retrieved !",
|
|
41
|
+
},
|
|
42
42
|
],
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { saveRemoteJsonToFile, saveAssets, saveFontFiles } = require("../index");
|
|
2
2
|
const nock = require("nock");
|
|
3
3
|
const R = require("ramda");
|
|
4
|
+
const fs = require("fs");
|
|
4
5
|
const logger = require("../../logger");
|
|
5
6
|
|
|
6
7
|
const getFileName = R.compose(R.last, R.split("/"));
|
|
@@ -109,9 +110,37 @@ describe("saveAssets", () => {
|
|
|
109
110
|
|
|
110
111
|
afterEach(() => {
|
|
111
112
|
clearAllMocks();
|
|
113
|
+
|
|
114
|
+
["existsSync", "openSync", "closeSync", "readSync", "readFileSync"].forEach(
|
|
115
|
+
(method) => {
|
|
116
|
+
if (fs[method] && fs[method].mockRestore) {
|
|
117
|
+
fs[method].mockRestore();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
);
|
|
112
121
|
});
|
|
113
122
|
|
|
123
|
+
function mockDownloadedFile({ isZip, content } = {}) {
|
|
124
|
+
jest.spyOn(fs, "existsSync").mockReturnValue(true);
|
|
125
|
+
jest.spyOn(fs, "openSync").mockReturnValue(1);
|
|
126
|
+
jest.spyOn(fs, "closeSync").mockImplementation(() => ({}));
|
|
127
|
+
|
|
128
|
+
jest.spyOn(fs, "readSync").mockImplementation((fd, buffer) => {
|
|
129
|
+
const header = isZip
|
|
130
|
+
? Buffer.from([0x50, 0x4b, 0x03, 0x04])
|
|
131
|
+
: Buffer.from("<?xm");
|
|
132
|
+
|
|
133
|
+
header.copy(buffer);
|
|
134
|
+
|
|
135
|
+
return 4;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
jest.spyOn(fs, "readFileSync").mockReturnValue(content || "");
|
|
139
|
+
}
|
|
140
|
+
|
|
114
141
|
it("downloads the files with cURL, and unzips the assets", () => {
|
|
142
|
+
mockDownloadedFile({ isZip: true });
|
|
143
|
+
|
|
115
144
|
saveAssets({ destinationPath, platform }, assetsUrl);
|
|
116
145
|
|
|
117
146
|
expect(loggerSpy).toHaveBeenCalledWith(`saving assets from ${assetsUrl}`);
|
|
@@ -122,6 +151,30 @@ describe("saveAssets", () => {
|
|
|
122
151
|
filePath
|
|
123
152
|
);
|
|
124
153
|
});
|
|
154
|
+
|
|
155
|
+
it("throws a clear error and skips unzip when the bundle is not a zip", () => {
|
|
156
|
+
mockDownloadedFile({
|
|
157
|
+
isZip: false,
|
|
158
|
+
content:
|
|
159
|
+
'<?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code></Error>',
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
expect(() => saveAssets({ destinationPath, platform }, assetsUrl)).toThrow(
|
|
163
|
+
/AccessDenied/
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(shell.unzip).not.toHaveBeenCalled();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("throws a clear error when the bundle was not downloaded", () => {
|
|
170
|
+
jest.spyOn(fs, "existsSync").mockReturnValue(false);
|
|
171
|
+
|
|
172
|
+
expect(() => saveAssets({ destinationPath, platform }, assetsUrl)).toThrow(
|
|
173
|
+
/was not downloaded/
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
expect(shell.unzip).not.toHaveBeenCalled();
|
|
177
|
+
});
|
|
125
178
|
});
|
|
126
179
|
|
|
127
180
|
describe("saveFontFiles", () => {
|
package/src/download/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const R = require("ramda");
|
|
2
|
+
const fs = require("fs");
|
|
2
3
|
const axios = require("axios");
|
|
3
4
|
const { resolve } = require("path");
|
|
4
5
|
const { curlFile, curlMultipleFiles, unzip } = require("../shell");
|
|
@@ -12,6 +13,64 @@ const getFileName = R.ifElse(
|
|
|
12
13
|
R.prop("name")
|
|
13
14
|
);
|
|
14
15
|
|
|
16
|
+
// Local file signature for a zip archive: "PK\x03\x04"
|
|
17
|
+
const ZIP_SIGNATURE = "504b0304";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* checks whether a file on disk is a real zip archive by reading its magic bytes.
|
|
21
|
+
* @param {String} file path to the file to inspect
|
|
22
|
+
* @returns {Boolean} true if the file starts with the zip local file signature
|
|
23
|
+
*/
|
|
24
|
+
function isZipFile(file) {
|
|
25
|
+
const fd = fs.openSync(file, "r");
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const header = Buffer.alloc(4);
|
|
29
|
+
const bytesRead = fs.readSync(fd, header, 0, 4, 0);
|
|
30
|
+
|
|
31
|
+
return bytesRead === 4 && header.toString("hex") === ZIP_SIGNATURE;
|
|
32
|
+
} finally {
|
|
33
|
+
fs.closeSync(fd);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* verifies that the downloaded assets bundle is a real zip archive.
|
|
39
|
+
* The assets CDN responds with a small XML/HTML body (e.g. S3 "AccessDenied")
|
|
40
|
+
* when the bundle is missing or not yet published. Because the download uses
|
|
41
|
+
* `curl -O` without `-f`, that error body is saved as assets.zip and the process
|
|
42
|
+
* continues, only to crash later in webpack with a confusing parse error. This
|
|
43
|
+
* check fails fast in the prepare step with an actionable message instead.
|
|
44
|
+
* @param {String} file path to the downloaded assets bundle
|
|
45
|
+
* @param {String} assetsUrl original url, surfaced in the error message
|
|
46
|
+
*/
|
|
47
|
+
function assertValidAssetsBundle(file, assetsUrl) {
|
|
48
|
+
if (!fs.existsSync(file)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Assets bundle was not downloaded from ${assetsUrl}. ` +
|
|
51
|
+
"Verify the app has a published build with generated assets for this platform."
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (isZipFile(file)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const preview = fs
|
|
60
|
+
.readFileSync(file, "utf8")
|
|
61
|
+
.replace(/\s+/g, " ")
|
|
62
|
+
.trim()
|
|
63
|
+
.slice(0, 300);
|
|
64
|
+
|
|
65
|
+
throw new Error(
|
|
66
|
+
`Invalid assets bundle downloaded from ${assetsUrl} - expected a zip archive ` +
|
|
67
|
+
`but received non-zip content:\n "${preview}"\n` +
|
|
68
|
+
"This usually means the assets bundle has not been generated/published for " +
|
|
69
|
+
'this platform, or the URL is not accessible (e.g. S3 "AccessDenied"). ' +
|
|
70
|
+
"Publish a build with assets for this platform before preparing the workspace."
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
15
74
|
/**
|
|
16
75
|
* saves a remote json file in the app's configuration folder.
|
|
17
76
|
* curried function of the shape saveRemoteJsonToFile(configuration)(fileUrl)
|
|
@@ -65,7 +124,12 @@ function saveAssets({ destinationPath, platform }, assetsUrl) {
|
|
|
65
124
|
});
|
|
66
125
|
|
|
67
126
|
curlFile(assetsUrl, filePath);
|
|
68
|
-
|
|
127
|
+
|
|
128
|
+
const downloadedFile = resolve(filePath, fileName);
|
|
129
|
+
|
|
130
|
+
assertValidAssetsBundle(downloadedFile, assetsUrl);
|
|
131
|
+
|
|
132
|
+
unzip(downloadedFile, filePath);
|
|
69
133
|
}
|
|
70
134
|
|
|
71
135
|
/**
|
package/src/file/index.js
CHANGED
|
@@ -61,8 +61,13 @@ function destinationFileNameMapper(destinationFileName) {
|
|
|
61
61
|
/**
|
|
62
62
|
* Copies an array of files from a folder to another
|
|
63
63
|
*
|
|
64
|
+
* Each entry can either be a string (same relative path for source and
|
|
65
|
+
* destination) or an object `{ source, destination }` when a file should be
|
|
66
|
+
* read from one relative path and written to another. The latter lets several
|
|
67
|
+
* platforms reuse a single set of bundled assets without duplicating them.
|
|
68
|
+
*
|
|
64
69
|
* @param {String} source folder of the files
|
|
65
|
-
* @param {String[]} files list of the files
|
|
70
|
+
* @param {(String|{source: String, destination: String})[]} files list of the files
|
|
66
71
|
* @param {String} destination path
|
|
67
72
|
* @returns {Promise[]} array of promises with the status of the copied files
|
|
68
73
|
*/
|
|
@@ -72,14 +77,15 @@ function copyFiles(source, filesOrFilesGetter, destination, config) {
|
|
|
72
77
|
? filesOrFilesGetter(config)
|
|
73
78
|
: filesOrFilesGetter;
|
|
74
79
|
|
|
75
|
-
return R.map(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
),
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
return R.map((file) => {
|
|
81
|
+
const sourceFile = typeof file === "string" ? file : file.source;
|
|
82
|
+
const destinationFile = typeof file === "string" ? file : file.destination;
|
|
83
|
+
|
|
84
|
+
return copyFileSync(
|
|
85
|
+
join(source, sourceFile),
|
|
86
|
+
destinationFileNameMapper(join(destination, destinationFile))
|
|
87
|
+
);
|
|
88
|
+
}, files);
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
module.exports = {
|
|
@@ -32,4 +32,4 @@ exports[`resolveAppTemplate retrieves the template from the provided path if pro
|
|
|
32
32
|
}
|
|
33
33
|
`;
|
|
34
34
|
|
|
35
|
-
exports[`resolveAppTemplate throws if resolving a template for an unknown platform 1`] = `"could not find template for foo - available templates: ios,android,samsung_tv,lg_tv,vizio,apple_tv,android_tv,amazon"`;
|
|
35
|
+
exports[`resolveAppTemplate throws if resolving a template for an unknown platform 1`] = `"could not find template for foo - available templates: ios,android,samsung_tv,lg_tv,vidaa,vizio,apple_tv,android_tv,amazon"`;
|
package/src/templates/index.js
CHANGED
|
@@ -27,6 +27,7 @@ const templatesMap = {
|
|
|
27
27
|
android: "@applicaster/zapp-react-native-cli-template",
|
|
28
28
|
samsung_tv: "@applicaster/zapp-react-dom-cli-template",
|
|
29
29
|
lg_tv: "@applicaster/zapp-react-dom-cli-template",
|
|
30
|
+
vidaa: "@applicaster/zapp-react-dom-cli-template",
|
|
30
31
|
vizio: "@applicaster/zapp-react-dom-cli-template",
|
|
31
32
|
apple_tv: "@applicaster/zapp-react-native-tvos-cli-template",
|
|
32
33
|
android_tv: "@applicaster/zapp-react-native-android-tv-cli-template",
|