@webspatial/builder 0.1.15 → 0.1.17
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/README.md +15 -75
- package/dist/index.js +99 -1
- package/dist/lib/cmds/build.js +116 -1
- package/dist/lib/cmds/check.js +41 -1
- package/dist/lib/cmds/help.js +66 -1
- package/dist/lib/cmds/launch.js +14 -1
- package/dist/lib/cmds/shutdown.js +8 -1
- package/dist/lib/cmds/version.js +11 -1
- package/dist/lib/pwa/config.js +208 -1
- package/dist/lib/pwa/index.js +92 -1
- package/dist/lib/pwa/validate.js +240 -1
- package/dist/lib/resource/file.js +45 -1
- package/dist/lib/resource/imageHelper.js +37 -1
- package/dist/lib/resource/index.js +102 -1
- package/dist/lib/resource/load.js +121 -1
- package/dist/lib/types.d.ts +2 -2
- package/dist/lib/types.js +2 -1
- package/dist/lib/utils/CustomError.js +11 -1
- package/dist/lib/utils/FetchUtils-1.js +25 -1
- package/dist/lib/utils/Log.js +98 -1
- package/dist/lib/utils/fetch.js +56 -1
- package/dist/lib/utils/history.d.ts +1 -0
- package/dist/lib/utils/history.js +116 -1
- package/dist/lib/utils/messages.js +102 -1
- package/dist/lib/utils/utils.js +15 -1
- package/dist/lib/xcode/index.js +35 -1
- package/dist/lib/xcode/manifestSwiftTemplate.js +109 -1
- package/dist/lib/xcode/xcodebuild.js +119 -1
- package/dist/lib/xcode/xcodeproject.js +239 -1
- package/dist/lib/xcode/xcrun.d.ts +1 -1
- package/dist/lib/xcode/xcrun.js +433 -1
- package/package.json +3 -3
package/dist/lib/pwa/config.js
CHANGED
|
@@ -1 +1,208 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.safelist = void 0;
|
|
4
|
+
exports.configId = configId;
|
|
5
|
+
exports.configStartUrl = configStartUrl;
|
|
6
|
+
exports.configScope = configScope;
|
|
7
|
+
exports.configDisplay = configDisplay;
|
|
8
|
+
exports.configMainScene = configMainScene;
|
|
9
|
+
exports.configDeeplink = configDeeplink;
|
|
10
|
+
const utils_1 = require("../utils/utils");
|
|
11
|
+
const validate_1 = require("./validate");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
function configId(manifestJson, bundleId) {
|
|
14
|
+
if (bundleId) {
|
|
15
|
+
manifestJson.id = bundleId;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
try {
|
|
19
|
+
const url = new URL(manifestJson.id);
|
|
20
|
+
let arr = url.host.split('.').reverse();
|
|
21
|
+
manifestJson.id = arr.join('.');
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
throw new Error(`id:${manifestJson.id} is not a valid url`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function configStartUrl(manifestJson, base, manifestUrl, isNet) {
|
|
29
|
+
var _a;
|
|
30
|
+
let start_url = (_a = manifestJson.start_url) !== null && _a !== void 0 ? _a : '/';
|
|
31
|
+
const isStartUrl = (0, validate_1.validateURL)(start_url);
|
|
32
|
+
const hasBase = base.length > 0;
|
|
33
|
+
if (hasBase) {
|
|
34
|
+
const isBaseUrl = (0, validate_1.validateURL)(base);
|
|
35
|
+
if (!isStartUrl && !isBaseUrl) {
|
|
36
|
+
const staticWebRoot = (0, path_1.resolve)('./static-web');
|
|
37
|
+
const resolvedPath = (0, path_1.resolve)(staticWebRoot, base, start_url);
|
|
38
|
+
const normalizedPath = (0, path_1.normalize)(resolvedPath);
|
|
39
|
+
const safePath = (0, path_1.join)(staticWebRoot, normalizedPath);
|
|
40
|
+
start_url = (0, path_1.relative)(process.cwd(), safePath)
|
|
41
|
+
.replace(/^(\.\.\/)+/, './')
|
|
42
|
+
.replace(/\/$/, '');
|
|
43
|
+
}
|
|
44
|
+
else if (isStartUrl && !isBaseUrl) {
|
|
45
|
+
const startUrl = new URL(start_url);
|
|
46
|
+
const fullPath = startUrl.pathname + startUrl.search + startUrl.hash;
|
|
47
|
+
let newBase = new URL(base, startUrl.origin);
|
|
48
|
+
start_url = new URL(fullPath, newBase).href;
|
|
49
|
+
}
|
|
50
|
+
else if (!isStartUrl && isBaseUrl) {
|
|
51
|
+
if (start_url.startsWith('/')) {
|
|
52
|
+
const baseUrl = new URL(base);
|
|
53
|
+
start_url = baseUrl.origin + (0, path_1.join)(baseUrl.pathname, start_url);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
start_url = new URL(start_url, base).href;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (isStartUrl && isBaseUrl) {
|
|
60
|
+
const startUrl = new URL(start_url);
|
|
61
|
+
const baseUrl = new URL(base);
|
|
62
|
+
const startFullPath = startUrl.pathname + startUrl.search + startUrl.hash;
|
|
63
|
+
start_url = new URL(startFullPath, baseUrl.origin + baseUrl.pathname).href;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
if (isNet) {
|
|
68
|
+
const murl = new URL(manifestUrl);
|
|
69
|
+
if (!isStartUrl) {
|
|
70
|
+
const newStartUrl = new URL(start_url, murl.origin);
|
|
71
|
+
start_url = newStartUrl.href;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const startUrl = new URL(start_url);
|
|
75
|
+
start_url =
|
|
76
|
+
murl.origin + startUrl.pathname + startUrl.search + startUrl.hash;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (!isStartUrl) {
|
|
80
|
+
const staticWebRoot = (0, path_1.resolve)('./static-web');
|
|
81
|
+
const resolvedPath = (0, path_1.resolve)(staticWebRoot, start_url);
|
|
82
|
+
const normalizedPath = (0, path_1.normalize)(resolvedPath);
|
|
83
|
+
const safePath = (0, path_1.join)(staticWebRoot, normalizedPath);
|
|
84
|
+
start_url = (0, path_1.relative)(process.cwd(), safePath)
|
|
85
|
+
.replace(/^(\.\.\/)+/, './')
|
|
86
|
+
.replace(/\/$/, '');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return start_url;
|
|
90
|
+
}
|
|
91
|
+
function configScope(manifestJson) {
|
|
92
|
+
var _a;
|
|
93
|
+
let scope = (_a = manifestJson.scope) !== null && _a !== void 0 ? _a : '/';
|
|
94
|
+
const isStartUrl = (0, validate_1.validateURL)(manifestJson.start_url);
|
|
95
|
+
const isUrl = (0, validate_1.validateURL)(scope);
|
|
96
|
+
if (isStartUrl && isUrl) {
|
|
97
|
+
const scopeURL = new URL(scope);
|
|
98
|
+
const startURL = new URL(manifestJson.start_url);
|
|
99
|
+
if (scopeURL.host !== startURL.host ||
|
|
100
|
+
manifestJson.start_url.indexOf(scope) !== 0) {
|
|
101
|
+
scope = (0, utils_1.parseRouter)(manifestJson.start_url);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else if (isStartUrl && !isUrl) {
|
|
105
|
+
scope = new URL(scope, manifestJson.start_url).href;
|
|
106
|
+
}
|
|
107
|
+
else if (!isStartUrl && isUrl) {
|
|
108
|
+
const cleanPath = manifestJson.start_url.replace(/\/[^\/]+$/, '');
|
|
109
|
+
scope = (0, path_1.normalize)(cleanPath + '/');
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
scope = (0, path_1.join)((0, utils_1.parseRouter)(manifestJson.start_url), scope);
|
|
113
|
+
}
|
|
114
|
+
manifestJson.scope = scope;
|
|
115
|
+
}
|
|
116
|
+
function configDisplay(manifestJson) {
|
|
117
|
+
let display = manifestJson.display;
|
|
118
|
+
const modes = ['minimal-ui', 'standalone', 'fullscreen'];
|
|
119
|
+
if (!modes.includes(display)) {
|
|
120
|
+
display = 'standalone';
|
|
121
|
+
}
|
|
122
|
+
if (manifestJson.display_override &&
|
|
123
|
+
manifestJson.display_override.length > 0) {
|
|
124
|
+
const validModes = manifestJson.display_override
|
|
125
|
+
.map((mode, index) => ({ mode, index }))
|
|
126
|
+
.filter(({ mode }) => modes.includes(mode))
|
|
127
|
+
.sort((a, b) => a.index - b.index);
|
|
128
|
+
if (validModes.length > 0) {
|
|
129
|
+
display = validModes[0].mode;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
manifestJson.display = display;
|
|
133
|
+
}
|
|
134
|
+
function configMainScene(manifestJson) {
|
|
135
|
+
var _a, _b;
|
|
136
|
+
const resizabilities = ['automatic', 'contentMinSize', 'contentSize'];
|
|
137
|
+
let mainScene = {
|
|
138
|
+
defaultSize: {
|
|
139
|
+
width: 1280,
|
|
140
|
+
height: 1280,
|
|
141
|
+
},
|
|
142
|
+
resizability: 'automatic',
|
|
143
|
+
};
|
|
144
|
+
if (manifestJson.xr_main_scene) {
|
|
145
|
+
if (typeof manifestJson.xr_main_scene === 'object') {
|
|
146
|
+
mainScene.defaultSize.width =
|
|
147
|
+
Number((_a = manifestJson.xr_main_scene.default_size) === null || _a === void 0 ? void 0 : _a.width) > 0
|
|
148
|
+
? manifestJson.xr_main_scene.default_size.width
|
|
149
|
+
: 1280;
|
|
150
|
+
mainScene.defaultSize.height =
|
|
151
|
+
Number((_b = manifestJson.xr_main_scene.default_size) === null || _b === void 0 ? void 0 : _b.height) > 0
|
|
152
|
+
? manifestJson.xr_main_scene.default_size.height
|
|
153
|
+
: 1280;
|
|
154
|
+
mainScene.resizability = resizabilities.includes(manifestJson.xr_main_scene.resizability)
|
|
155
|
+
? manifestJson.xr_main_scene.resizability
|
|
156
|
+
: 'automatic';
|
|
157
|
+
manifestJson.mainScene = mainScene;
|
|
158
|
+
}
|
|
159
|
+
else if (typeof manifestJson.xr_main_scene === 'string') {
|
|
160
|
+
manifestJson.mainScene = 'dynamic'; // only support this
|
|
161
|
+
}
|
|
162
|
+
// other type like string should be ignored
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function configDeeplink(manifestJson) {
|
|
166
|
+
if (manifestJson.protocol_handlers &&
|
|
167
|
+
manifestJson.protocol_handlers.length > 0) {
|
|
168
|
+
for (var i = 0; i < manifestJson.protocol_handlers.length; i++) {
|
|
169
|
+
const item = manifestJson.protocol_handlers[i];
|
|
170
|
+
// The DeepLink protocol must be on the security list or start with web+
|
|
171
|
+
if (item.protocol &&
|
|
172
|
+
(exports.safelist.includes(item.protocol) ||
|
|
173
|
+
item.protocol.indexOf('web+') === 0)) {
|
|
174
|
+
// If the URL is an absolute path, it must be within the scope range
|
|
175
|
+
if (!((0, validate_1.validateURL)(item.url) && item.url.indexOf(manifestJson.scope) < 0))
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
manifestJson.protocol_handlers.splice(i, 1);
|
|
179
|
+
i--;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.safelist = [
|
|
184
|
+
'bitcoin',
|
|
185
|
+
'ftp',
|
|
186
|
+
'ftps',
|
|
187
|
+
'geo',
|
|
188
|
+
'im',
|
|
189
|
+
'irc',
|
|
190
|
+
'ircs',
|
|
191
|
+
'magnet',
|
|
192
|
+
'mailto',
|
|
193
|
+
'matrix',
|
|
194
|
+
'mms',
|
|
195
|
+
'news',
|
|
196
|
+
'nntp',
|
|
197
|
+
'openpgp4fpr',
|
|
198
|
+
'sftp',
|
|
199
|
+
'sip',
|
|
200
|
+
'sms',
|
|
201
|
+
'smsto',
|
|
202
|
+
'ssh',
|
|
203
|
+
'tel',
|
|
204
|
+
'urn',
|
|
205
|
+
'webcal',
|
|
206
|
+
'wtai',
|
|
207
|
+
'xmpp',
|
|
208
|
+
];
|
package/dist/lib/pwa/index.js
CHANGED
|
@@ -1 +1,92 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PWAGenerator = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const config_1 = require("./config");
|
|
6
|
+
const load_1 = require("../resource/load");
|
|
7
|
+
const validate_1 = require("./validate");
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const utils_1 = require("../utils/utils");
|
|
10
|
+
class PWAGenerator {
|
|
11
|
+
static async generator(args, isDev = false) {
|
|
12
|
+
let manifestInfo = await this.validate(args, isDev);
|
|
13
|
+
console.log('check manifest.json: ok');
|
|
14
|
+
await this.config(manifestInfo, args, isDev);
|
|
15
|
+
console.log('reset manifest.json: ok');
|
|
16
|
+
return manifestInfo;
|
|
17
|
+
}
|
|
18
|
+
static async validate(args, isDev = false) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
let manifest = {};
|
|
21
|
+
let url = '';
|
|
22
|
+
let fromNet = false;
|
|
23
|
+
let useDefault = false;
|
|
24
|
+
// load manifest.json
|
|
25
|
+
if (args['manifestUrl']) {
|
|
26
|
+
url = args['manifestUrl'];
|
|
27
|
+
fromNet = true;
|
|
28
|
+
manifest = await (0, load_1.loadJsonFromNet)(args['manifestUrl']);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
if (args['manifest']) {
|
|
32
|
+
url = (0, path_1.join)(process.cwd(), args['manifest']);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
url = (0, path_1.join)(process.cwd(), 'public/manifest.json');
|
|
36
|
+
if (!fs.existsSync(url)) {
|
|
37
|
+
url = (0, path_1.join)(process.cwd(), 'public/manifest.webmanifest');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!fs.existsSync(url)) {
|
|
41
|
+
if (isDev) {
|
|
42
|
+
useDefault = true;
|
|
43
|
+
utils_1.CliLog.warn('manifest.json or manifest.webmanifest not found, use default in run mode');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new Error('manifest.json or manifest.webmanifest not found');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
manifest = useDefault
|
|
50
|
+
? this.defaultManifestJson
|
|
51
|
+
: await (0, load_1.loadJsonFromDisk)(url);
|
|
52
|
+
this.useDefaultManifestJson = useDefault;
|
|
53
|
+
}
|
|
54
|
+
// check manifest.json
|
|
55
|
+
(0, validate_1.checkManifestJson)(manifest, isDev);
|
|
56
|
+
let start_url = (0, config_1.configStartUrl)(manifest, (_a = args['base']) !== null && _a !== void 0 ? _a : '', url, fromNet);
|
|
57
|
+
var isNetWeb = (0, validate_1.checkStartUrl)(start_url, url, fromNet, isDev);
|
|
58
|
+
manifest.start_url = start_url;
|
|
59
|
+
if (!isDev)
|
|
60
|
+
(0, validate_1.checkId)(manifest, (_b = args['bundleId']) !== null && _b !== void 0 ? _b : '');
|
|
61
|
+
await (0, validate_1.checkIcons)(manifest, url, isDev);
|
|
62
|
+
return {
|
|
63
|
+
json: manifest,
|
|
64
|
+
url,
|
|
65
|
+
fromNet: isNetWeb,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// generate manifest
|
|
69
|
+
static config(manifestInfo, args, isDev) {
|
|
70
|
+
var _a;
|
|
71
|
+
let bundleId = (_a = args['bundleId']) !== null && _a !== void 0 ? _a : '';
|
|
72
|
+
if (isDev && !manifestInfo.json.id) {
|
|
73
|
+
bundleId = this.defaultBundleId;
|
|
74
|
+
}
|
|
75
|
+
(0, config_1.configId)(manifestInfo.json, bundleId);
|
|
76
|
+
(0, config_1.configScope)(manifestInfo.json);
|
|
77
|
+
(0, config_1.configDisplay)(manifestInfo.json);
|
|
78
|
+
(0, config_1.configDeeplink)(manifestInfo.json);
|
|
79
|
+
(0, config_1.configMainScene)(manifestInfo.json);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.PWAGenerator = PWAGenerator;
|
|
83
|
+
// Supported display modes for TWA
|
|
84
|
+
PWAGenerator.DisplayModes = ['standalone', 'minimal-ui'];
|
|
85
|
+
PWAGenerator.defaultBundleId = 'com.webspatial.test';
|
|
86
|
+
PWAGenerator.defaultManifestJson = {
|
|
87
|
+
name: 'WebSpatialTest',
|
|
88
|
+
display: 'minimal-ui',
|
|
89
|
+
start_url: '/',
|
|
90
|
+
scope: '/',
|
|
91
|
+
};
|
|
92
|
+
PWAGenerator.useDefaultManifestJson = false;
|
package/dist/lib/pwa/validate.js
CHANGED
|
@@ -1 +1,240 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkManifestJson = checkManifestJson;
|
|
4
|
+
exports.checkStartUrl = checkStartUrl;
|
|
5
|
+
exports.checkIcons = checkIcons;
|
|
6
|
+
exports.checkId = checkId;
|
|
7
|
+
exports.validateBundleId = validateBundleId;
|
|
8
|
+
exports.validateURL = validateURL;
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const CustomError_1 = require("../utils/CustomError");
|
|
11
|
+
const utils_1 = require("../utils/utils");
|
|
12
|
+
const imageHelper_1 = require("../resource/imageHelper");
|
|
13
|
+
const load_1 = require("../resource/load");
|
|
14
|
+
const utils_2 = require("../utils/utils");
|
|
15
|
+
function checkManifestJson(manifestJson, isDev = false) {
|
|
16
|
+
var _a;
|
|
17
|
+
const errors = [];
|
|
18
|
+
if (!manifestJson.name && !manifestJson['short_name'] && !isDev) {
|
|
19
|
+
errors.push({
|
|
20
|
+
code: 3006,
|
|
21
|
+
message: 'In the Web Spatial App Manifest, it is necessary to provide the name property or short_name property (preferably both)',
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
23
|
+
message_staring_params: {},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (!((_a = manifestJson.icons) === null || _a === void 0 ? void 0 : _a.length) && !isDev) {
|
|
27
|
+
errors.push({
|
|
28
|
+
code: 3007,
|
|
29
|
+
message: 'In the Web Spatial App Manifest, the icons property must be provided and it should include at least one icon object',
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
31
|
+
message_staring_params: {},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (!manifestJson['start_url'] && !isDev) {
|
|
35
|
+
errors.push({
|
|
36
|
+
code: 3008,
|
|
37
|
+
message: 'In the Web Spatial App Manifest, the start_url property must be provided',
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
39
|
+
message_staring_params: {},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (errors.length) {
|
|
43
|
+
throw new CustomError_1.CustomError(errors);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function checkStartUrl(startUrl, manifestUrl, isNet, isDev = false) {
|
|
47
|
+
var isNetWeb = false;
|
|
48
|
+
if (isDev) {
|
|
49
|
+
return startUrl.startsWith('https://') || startUrl.startsWith('http://');
|
|
50
|
+
}
|
|
51
|
+
if (isNet) {
|
|
52
|
+
// Determine whether it is of the same origin as the manifest
|
|
53
|
+
if (startUrl.startsWith('https://')) {
|
|
54
|
+
const urlStart = new URL(startUrl);
|
|
55
|
+
const urlManifest = new URL(manifestUrl);
|
|
56
|
+
// The start_url and manifest need to be of the same origin
|
|
57
|
+
if (urlStart.host !== urlManifest.host) {
|
|
58
|
+
throw new CustomError_1.CustomError({
|
|
59
|
+
code: 4000,
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
61
|
+
message: 'In the WebSpatial App Manifest, the start_url must be the same origin with manifest',
|
|
62
|
+
message_staring_params: {},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Start_url must be HTTPS protocol
|
|
67
|
+
else if (startUrl.startsWith('http://')) {
|
|
68
|
+
throw new CustomError_1.CustomError({
|
|
69
|
+
code: 4000,
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
71
|
+
message: 'In the Web Spatial App Manifest, the start_url must use https',
|
|
72
|
+
message_staring_params: {},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (startUrl.startsWith('https://') || startUrl.startsWith('http://')) {
|
|
78
|
+
throw new CustomError_1.CustomError({
|
|
79
|
+
code: 4000,
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
81
|
+
message: 'Local manifest cannot package network project',
|
|
82
|
+
message_staring_params: {},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return isNetWeb;
|
|
87
|
+
}
|
|
88
|
+
async function checkIcons(manifest, manifestUrl, isDev = false) {
|
|
89
|
+
var _a, _b;
|
|
90
|
+
if (!((_a = manifest.icons) === null || _a === void 0 ? void 0 : _a.length) && isDev) {
|
|
91
|
+
manifest.icons = [
|
|
92
|
+
{
|
|
93
|
+
src: (0, path_1.join)(__dirname, '../../assets/icon-default.png'),
|
|
94
|
+
sizes: '1024x1024',
|
|
95
|
+
purpose: 'maskable',
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
utils_2.CliLog.warn('icon not found, use default in run mode');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const relativeUrl = (0, utils_1.parseRouter)(manifestUrl);
|
|
102
|
+
let maxSizeImage;
|
|
103
|
+
let maxSizeImageUrl;
|
|
104
|
+
let maxSizePurpose;
|
|
105
|
+
let maxSize = 0;
|
|
106
|
+
for (var i = 0; i < manifest.icons.length; i++) {
|
|
107
|
+
const item = manifest.icons[i];
|
|
108
|
+
let hasMaskable = ((_b = item.purpose) === null || _b === void 0 ? void 0 : _b.indexOf('maskable')) >= 0;
|
|
109
|
+
if (!hasMaskable)
|
|
110
|
+
continue;
|
|
111
|
+
let has1024 = false;
|
|
112
|
+
let imgUrl = item.src;
|
|
113
|
+
let image;
|
|
114
|
+
let imageSize = 0;
|
|
115
|
+
if (!validateURL(imgUrl)) {
|
|
116
|
+
imgUrl = (0, path_1.join)(relativeUrl, imgUrl);
|
|
117
|
+
}
|
|
118
|
+
// If size has been configured, determine the size; otherwise, download the icon for judgment
|
|
119
|
+
if (item.sizes) {
|
|
120
|
+
const mulSize = item.sizes.split(' ');
|
|
121
|
+
mulSize.forEach((size) => {
|
|
122
|
+
let wh = size.split('x');
|
|
123
|
+
if (Number(wh[0]) >= 1024 && Number(wh[1]) >= 1024) {
|
|
124
|
+
has1024 = true;
|
|
125
|
+
if (Number(wh[0]) > imageSize) {
|
|
126
|
+
imageSize = Number(wh[0]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
image = !imgUrl.startsWith('http')
|
|
133
|
+
? await (0, load_1.loadImageFromDisk)(imgUrl)
|
|
134
|
+
: await (0, load_1.loadImageFromNet)(imgUrl);
|
|
135
|
+
if (image.getWidth() >= 1024 && image.getHeight() >= 1024) {
|
|
136
|
+
has1024 = true;
|
|
137
|
+
if (image.getWidth() > imageSize) {
|
|
138
|
+
imageSize = image.getWidth();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Download all the icons used, check their width and height, and if they meet the size and maskability requirements, finally check their alpha
|
|
143
|
+
if (has1024 && hasMaskable) {
|
|
144
|
+
if (imageSize > maxSize) {
|
|
145
|
+
maxSize = imageSize;
|
|
146
|
+
maxSizeImage = image;
|
|
147
|
+
maxSizeImageUrl = imgUrl;
|
|
148
|
+
maxSizePurpose = item.purpose;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// There is no icon that satisfies both size>=1024 and purpose including Maskable
|
|
153
|
+
if (maxSize === 0) {
|
|
154
|
+
if (isDev) {
|
|
155
|
+
manifest.icons = [
|
|
156
|
+
{
|
|
157
|
+
src: (0, path_1.join)(__dirname, '../../assets/icon-default.png'),
|
|
158
|
+
sizes: '1024x1024',
|
|
159
|
+
purpose: 'maskable',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
utils_2.CliLog.warn('In the Web Spatial App on VisionPro, the icon must be greater than or equal to 1024x1024, and the purpose parameter must include maskable');
|
|
163
|
+
utils_2.CliLog.warn('icon does not meet the standard, use default icon in run mode');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
throw new CustomError_1.CustomError({
|
|
167
|
+
code: 4000,
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
169
|
+
message: 'In the Web Spatial App on VisionPro, the icon must be greater than or equal to 1024x1024, and the purpose parameter must include maskable',
|
|
170
|
+
message_staring_params: {},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
else if (maxSizeImageUrl) {
|
|
174
|
+
maxSizeImage = !maxSizeImageUrl.startsWith('http')
|
|
175
|
+
? await (0, load_1.loadImageFromDisk)(maxSizeImageUrl)
|
|
176
|
+
: await (0, load_1.loadImageFromNet)(maxSizeImageUrl);
|
|
177
|
+
}
|
|
178
|
+
// Check if the image is completely opaque
|
|
179
|
+
if (maxSizeImage && !imageHelper_1.ImageHelper.isFullyOpaque(maxSizeImage)) {
|
|
180
|
+
if (isDev) {
|
|
181
|
+
utils_2.CliLog.warn('In the Web Spatial App on VisionPro, the icon must be greater than or equal to 1024x1024, and the purpose parameter must include maskable');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
throw new CustomError_1.CustomError({
|
|
185
|
+
code: 4000,
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
187
|
+
message: 'In the Web Spatial App on VisionPro, must be a fully opaque bitmap.',
|
|
188
|
+
message_staring_params: {},
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
manifest.icons = [
|
|
192
|
+
{
|
|
193
|
+
src: maxSizeImageUrl,
|
|
194
|
+
sizes: maxSize + 'x' + maxSize,
|
|
195
|
+
purpose: maxSizePurpose,
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
function checkId(manifest, bundleId) {
|
|
200
|
+
if (bundleId) {
|
|
201
|
+
if (!validateBundleId(bundleId)) {
|
|
202
|
+
throw new CustomError_1.CustomError({
|
|
203
|
+
code: 4000,
|
|
204
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
205
|
+
message: 'In the Web Spatial App Manifest, the bundle ID must be in reverse domain format (e.g. com.example.app) and no longer than 128 characters',
|
|
206
|
+
message_staring_params: {},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (!manifest.id) {
|
|
212
|
+
manifest.id = manifest.start_url;
|
|
213
|
+
}
|
|
214
|
+
if (!validateURL(manifest.id) && !bundleId) {
|
|
215
|
+
throw new CustomError_1.CustomError({
|
|
216
|
+
code: 4000,
|
|
217
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
218
|
+
message: 'In the Web Spatial App Manifest, the id or start_url must be a valid URL, or provide it use --bundle-id',
|
|
219
|
+
message_staring_params: {},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function validateBundleId(bundleId) {
|
|
224
|
+
// iOS official specification regex (supports reverse domain name format validation)
|
|
225
|
+
// 1. Allowed: letters/numbers/hyphens/underscores/dots
|
|
226
|
+
// 2. Disallow: consecutive dots/leading or trailing dots
|
|
227
|
+
// 3. Each part starts with a letter or underscore
|
|
228
|
+
// 4. Total length 1-128 characters
|
|
229
|
+
const iosBundleIdRegex = /^(?=.{1,128}$)(?!.*\.\.)(?!^\.|.*\.$)[A-Za-z_][A-Za-z0-9_-]*(?:\.[A-Za-z_][A-Za-z0-9_-]*)+$/;
|
|
230
|
+
return iosBundleIdRegex.test(bundleId);
|
|
231
|
+
}
|
|
232
|
+
function validateURL(url) {
|
|
233
|
+
try {
|
|
234
|
+
new URL(url);
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -1 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copyDir = copyDir;
|
|
4
|
+
exports.clearDir = clearDir;
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
function copyDir(from, to) {
|
|
7
|
+
const paths = fs.readdirSync(from);
|
|
8
|
+
paths.forEach(path => {
|
|
9
|
+
const _from = from + '/' + path;
|
|
10
|
+
const _to = to + '/' + path;
|
|
11
|
+
const stat = fs.statSync(_from);
|
|
12
|
+
if (stat.isFile()) {
|
|
13
|
+
try {
|
|
14
|
+
fs.writeFileSync(_to, fs.readFileSync(_from));
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
console.log(err);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (stat.isDirectory()) {
|
|
21
|
+
if (!fs.existsSync(_to)) {
|
|
22
|
+
fs.mkdirSync(_to, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
copyDir(_from, _to);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function clearDir(from) {
|
|
29
|
+
const paths = fs.readdirSync(from);
|
|
30
|
+
paths.forEach(path => {
|
|
31
|
+
const _from = from + '/' + path;
|
|
32
|
+
const stat = fs.statSync(_from);
|
|
33
|
+
if (stat.isFile()) {
|
|
34
|
+
try {
|
|
35
|
+
fs.unlinkSync(_from);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.log(err);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (stat.isDirectory()) {
|
|
42
|
+
clearDir(_from);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|