@vxrn/utils 2.0.0-beta.60.1 → 2.0.0-beta.65.1
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/dist/cjs/nativeAppManifest.cjs +81 -0
- package/dist/cjs/nativeAppManifest.native.cjs +105 -0
- package/dist/cjs/nativeAppManifest.native.js +107 -0
- package/dist/cjs/nativeAppManifest.native.js.map +1 -0
- package/dist/esm/nativeAppManifest.mjs +61 -0
- package/dist/esm/nativeAppManifest.mjs.map +1 -0
- package/dist/esm/nativeAppManifest.native.js +83 -0
- package/dist/esm/nativeAppManifest.native.js.map +1 -0
- package/package.json +11 -4
- package/src/nativeAppManifest.test.ts +142 -0
- package/src/nativeAppManifest.ts +163 -0
- package/types/nativeAppManifest.d.ts +40 -0
- package/types/nativeAppManifest.d.ts.map +1 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
var nativeAppManifest_exports = {};
|
|
22
|
+
__export(nativeAppManifest_exports, { validateNativeApp: () => validateNativeApp });
|
|
23
|
+
module.exports = __toCommonJS(nativeAppManifest_exports);
|
|
24
|
+
const TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
25
|
+
const SCHEME = /^[a-z][a-z0-9+.-]*$/i;
|
|
26
|
+
const VERSION = /^\d+\.\d+\.\d+/;
|
|
27
|
+
const BUILD_NUMBER = /^[A-Za-z0-9.]+$/;
|
|
28
|
+
const REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
|
|
29
|
+
const DEPLOYMENT_TARGET = /^\d+\.\d+$/;
|
|
30
|
+
const HEX_COLOR = /^#[\da-f]{6}$/i;
|
|
31
|
+
function fail(message) {
|
|
32
|
+
throw new Error(`[one] invalid native.app: ${message}`);
|
|
33
|
+
}
|
|
34
|
+
function validateNativeApp(manifest, platform) {
|
|
35
|
+
if (!manifest || typeof manifest !== "object") fail("manifest must be an object");
|
|
36
|
+
if (!manifest.name || typeof manifest.name !== "string") fail("name is required");
|
|
37
|
+
if (!TARGET_NAME.test(manifest.name)) {
|
|
38
|
+
fail(`name "${manifest.name}" must start with a letter and contain only letters, digits, and underscore`);
|
|
39
|
+
}
|
|
40
|
+
const schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [manifest.scheme];
|
|
41
|
+
for (const scheme of schemes) {
|
|
42
|
+
if (typeof scheme !== "string" || !SCHEME.test(scheme)) {
|
|
43
|
+
fail(`scheme "${scheme}" must be a valid uri scheme`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {
|
|
47
|
+
fail(`version "${manifest.version}" must start with major.minor.patch`);
|
|
48
|
+
}
|
|
49
|
+
if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {
|
|
50
|
+
fail("icon requires source and a six-digit hex backgroundColor");
|
|
51
|
+
}
|
|
52
|
+
if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {
|
|
53
|
+
fail("splash requires source, a six-digit hex backgroundColor, and width from 1 to 288");
|
|
54
|
+
}
|
|
55
|
+
if (manifest.imagePicker?.camera !== void 0 && (typeof manifest.imagePicker.camera !== "string" || manifest.imagePicker.camera.trim() === "")) {
|
|
56
|
+
fail("imagePicker.camera must be a non-empty string");
|
|
57
|
+
}
|
|
58
|
+
if (!platform || platform === "ios") {
|
|
59
|
+
if (!manifest.ios?.bundleId || !REVERSE_DNS.test(manifest.ios.bundleId)) {
|
|
60
|
+
fail(`ios.bundleId "${manifest.ios?.bundleId}" must be reverse-dns`);
|
|
61
|
+
}
|
|
62
|
+
if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {
|
|
63
|
+
fail(`ios.deploymentTarget "${manifest.ios.deploymentTarget}" must look like "17.0"`);
|
|
64
|
+
}
|
|
65
|
+
if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {
|
|
66
|
+
fail(`ios.buildNumber "${manifest.ios.buildNumber}" must contain only letters, digits, and dots`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!platform || platform === "android") {
|
|
70
|
+
if (!manifest.android?.applicationId || !REVERSE_DNS.test(manifest.android.applicationId)) {
|
|
71
|
+
fail(`android.applicationId "${manifest.android?.applicationId}" must be reverse-dns`);
|
|
72
|
+
}
|
|
73
|
+
if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {
|
|
74
|
+
fail(`android.minSdk "${manifest.android.minSdk}" must be an integer from 21 to 36`);
|
|
75
|
+
}
|
|
76
|
+
if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {
|
|
77
|
+
fail(`android.versionCode "${manifest.android.versionCode}" must be a positive integer`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return manifest;
|
|
81
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
+
var nativeAppManifest_exports = {};
|
|
24
|
+
__export(nativeAppManifest_exports, { validateNativeApp: () => validateNativeApp });
|
|
25
|
+
module.exports = __toCommonJS(nativeAppManifest_exports);
|
|
26
|
+
var TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
27
|
+
var SCHEME = /^[a-z][a-z0-9+.-]*$/i;
|
|
28
|
+
var VERSION = /^\d+\.\d+\.\d+/;
|
|
29
|
+
var BUILD_NUMBER = /^[A-Za-z0-9.]+$/;
|
|
30
|
+
var REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
|
|
31
|
+
var DEPLOYMENT_TARGET = /^\d+\.\d+$/;
|
|
32
|
+
var HEX_COLOR = /^#[\da-f]{6}$/i;
|
|
33
|
+
function fail(message) {
|
|
34
|
+
throw new Error(`[one] invalid native.app: ${message}`);
|
|
35
|
+
}
|
|
36
|
+
function validateNativeApp(manifest, platform) {
|
|
37
|
+
var _manifest_imagePicker;
|
|
38
|
+
if (!manifest || typeof manifest !== "object") fail("manifest must be an object");
|
|
39
|
+
if (!manifest.name || typeof manifest.name !== "string") fail("name is required");
|
|
40
|
+
if (!TARGET_NAME.test(manifest.name)) {
|
|
41
|
+
fail(`name "${manifest.name}" must start with a letter and contain only letters, digits, and underscore`);
|
|
42
|
+
}
|
|
43
|
+
var schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [manifest.scheme];
|
|
44
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
45
|
+
try {
|
|
46
|
+
for (var _iterator = schemes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
47
|
+
var scheme = _step.value;
|
|
48
|
+
if (typeof scheme !== "string" || !SCHEME.test(scheme)) {
|
|
49
|
+
fail(`scheme "${scheme}" must be a valid uri scheme`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
_didIteratorError = true;
|
|
54
|
+
_iteratorError = err;
|
|
55
|
+
} finally {
|
|
56
|
+
try {
|
|
57
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
58
|
+
_iterator.return();
|
|
59
|
+
}
|
|
60
|
+
} finally {
|
|
61
|
+
if (_didIteratorError) {
|
|
62
|
+
throw _iteratorError;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {
|
|
67
|
+
fail(`version "${manifest.version}" must start with major.minor.patch`);
|
|
68
|
+
}
|
|
69
|
+
if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {
|
|
70
|
+
fail("icon requires source and a six-digit hex backgroundColor");
|
|
71
|
+
}
|
|
72
|
+
if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {
|
|
73
|
+
fail("splash requires source, a six-digit hex backgroundColor, and width from 1 to 288");
|
|
74
|
+
}
|
|
75
|
+
if (((_manifest_imagePicker = manifest.imagePicker) === null || _manifest_imagePicker === void 0 ? void 0 : _manifest_imagePicker.camera) !== void 0 && (typeof manifest.imagePicker.camera !== "string" || manifest.imagePicker.camera.trim() === "")) {
|
|
76
|
+
fail("imagePicker.camera must be a non-empty string");
|
|
77
|
+
}
|
|
78
|
+
if (!platform || platform === "ios") {
|
|
79
|
+
var _manifest_ios;
|
|
80
|
+
if (!((_manifest_ios = manifest.ios) === null || _manifest_ios === void 0 ? void 0 : _manifest_ios.bundleId) || !REVERSE_DNS.test(manifest.ios.bundleId)) {
|
|
81
|
+
var _manifest_ios1;
|
|
82
|
+
fail(`ios.bundleId "${(_manifest_ios1 = manifest.ios) === null || _manifest_ios1 === void 0 ? void 0 : _manifest_ios1.bundleId}" must be reverse-dns`);
|
|
83
|
+
}
|
|
84
|
+
if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {
|
|
85
|
+
fail(`ios.deploymentTarget "${manifest.ios.deploymentTarget}" must look like "17.0"`);
|
|
86
|
+
}
|
|
87
|
+
if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {
|
|
88
|
+
fail(`ios.buildNumber "${manifest.ios.buildNumber}" must contain only letters, digits, and dots`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!platform || platform === "android") {
|
|
92
|
+
var _manifest_android;
|
|
93
|
+
if (!((_manifest_android = manifest.android) === null || _manifest_android === void 0 ? void 0 : _manifest_android.applicationId) || !REVERSE_DNS.test(manifest.android.applicationId)) {
|
|
94
|
+
var _manifest_android1;
|
|
95
|
+
fail(`android.applicationId "${(_manifest_android1 = manifest.android) === null || _manifest_android1 === void 0 ? void 0 : _manifest_android1.applicationId}" must be reverse-dns`);
|
|
96
|
+
}
|
|
97
|
+
if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {
|
|
98
|
+
fail(`android.minSdk "${manifest.android.minSdk}" must be an integer from 21 to 36`);
|
|
99
|
+
}
|
|
100
|
+
if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {
|
|
101
|
+
fail(`android.versionCode "${manifest.android.versionCode}" must be a positive integer`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return manifest;
|
|
105
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
+
var nativeAppManifest_exports = {};
|
|
24
|
+
__export(nativeAppManifest_exports, { validateNativeApp: () => validateNativeApp });
|
|
25
|
+
module.exports = __toCommonJS(nativeAppManifest_exports);
|
|
26
|
+
var TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
27
|
+
var SCHEME = /^[a-z][a-z0-9+.-]*$/i;
|
|
28
|
+
var VERSION = /^\d+\.\d+\.\d+/;
|
|
29
|
+
var BUILD_NUMBER = /^[A-Za-z0-9.]+$/;
|
|
30
|
+
var REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
|
|
31
|
+
var DEPLOYMENT_TARGET = /^\d+\.\d+$/;
|
|
32
|
+
var HEX_COLOR = /^#[\da-f]{6}$/i;
|
|
33
|
+
function fail(message) {
|
|
34
|
+
throw new Error(`[one] invalid native.app: ${message}`);
|
|
35
|
+
}
|
|
36
|
+
function validateNativeApp(manifest, platform) {
|
|
37
|
+
var _manifest_imagePicker;
|
|
38
|
+
if (!manifest || typeof manifest !== "object") fail("manifest must be an object");
|
|
39
|
+
if (!manifest.name || typeof manifest.name !== "string") fail("name is required");
|
|
40
|
+
if (!TARGET_NAME.test(manifest.name)) {
|
|
41
|
+
fail(`name "${manifest.name}" must start with a letter and contain only letters, digits, and underscore`);
|
|
42
|
+
}
|
|
43
|
+
var schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [manifest.scheme];
|
|
44
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
45
|
+
try {
|
|
46
|
+
for (var _iterator = schemes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
47
|
+
var scheme = _step.value;
|
|
48
|
+
if (typeof scheme !== "string" || !SCHEME.test(scheme)) {
|
|
49
|
+
fail(`scheme "${scheme}" must be a valid uri scheme`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
_didIteratorError = true;
|
|
54
|
+
_iteratorError = err;
|
|
55
|
+
} finally {
|
|
56
|
+
try {
|
|
57
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
58
|
+
_iterator.return();
|
|
59
|
+
}
|
|
60
|
+
} finally {
|
|
61
|
+
if (_didIteratorError) {
|
|
62
|
+
throw _iteratorError;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {
|
|
67
|
+
fail(`version "${manifest.version}" must start with major.minor.patch`);
|
|
68
|
+
}
|
|
69
|
+
if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {
|
|
70
|
+
fail("icon requires source and a six-digit hex backgroundColor");
|
|
71
|
+
}
|
|
72
|
+
if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {
|
|
73
|
+
fail("splash requires source, a six-digit hex backgroundColor, and width from 1 to 288");
|
|
74
|
+
}
|
|
75
|
+
if (((_manifest_imagePicker = manifest.imagePicker) === null || _manifest_imagePicker === void 0 ? void 0 : _manifest_imagePicker.camera) !== void 0 && (typeof manifest.imagePicker.camera !== "string" || manifest.imagePicker.camera.trim() === "")) {
|
|
76
|
+
fail("imagePicker.camera must be a non-empty string");
|
|
77
|
+
}
|
|
78
|
+
if (!platform || platform === "ios") {
|
|
79
|
+
var _manifest_ios;
|
|
80
|
+
if (!((_manifest_ios = manifest.ios) === null || _manifest_ios === void 0 ? void 0 : _manifest_ios.bundleId) || !REVERSE_DNS.test(manifest.ios.bundleId)) {
|
|
81
|
+
var _manifest_ios1;
|
|
82
|
+
fail(`ios.bundleId "${(_manifest_ios1 = manifest.ios) === null || _manifest_ios1 === void 0 ? void 0 : _manifest_ios1.bundleId}" must be reverse-dns`);
|
|
83
|
+
}
|
|
84
|
+
if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {
|
|
85
|
+
fail(`ios.deploymentTarget "${manifest.ios.deploymentTarget}" must look like "17.0"`);
|
|
86
|
+
}
|
|
87
|
+
if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {
|
|
88
|
+
fail(`ios.buildNumber "${manifest.ios.buildNumber}" must contain only letters, digits, and dots`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!platform || platform === "android") {
|
|
92
|
+
var _manifest_android;
|
|
93
|
+
if (!((_manifest_android = manifest.android) === null || _manifest_android === void 0 ? void 0 : _manifest_android.applicationId) || !REVERSE_DNS.test(manifest.android.applicationId)) {
|
|
94
|
+
var _manifest_android1;
|
|
95
|
+
fail(`android.applicationId "${(_manifest_android1 = manifest.android) === null || _manifest_android1 === void 0 ? void 0 : _manifest_android1.applicationId}" must be reverse-dns`);
|
|
96
|
+
}
|
|
97
|
+
if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {
|
|
98
|
+
fail(`android.minSdk "${manifest.android.minSdk}" must be an integer from 21 to 36`);
|
|
99
|
+
}
|
|
100
|
+
if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {
|
|
101
|
+
fail(`android.versionCode "${manifest.android.versionCode}" must be a positive integer`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return manifest;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//# sourceMappingURL=nativeAppManifest.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeAppManifest.native.js","names":[],"sources":["cjs/nativeAppManifest.native.js"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\nvar nativeAppManifest_exports = {};\n__export(nativeAppManifest_exports, {\n validateNativeApp: () => validateNativeApp\n});\nmodule.exports = __toCommonJS(nativeAppManifest_exports);\nvar TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;\nvar SCHEME = /^[a-z][a-z0-9+.-]*$/i;\nvar VERSION = /^\\d+\\.\\d+\\.\\d+/;\nvar BUILD_NUMBER = /^[A-Za-z0-9.]+$/;\nvar REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\\.[A-Za-z][A-Za-z0-9-]*)+$/;\nvar DEPLOYMENT_TARGET = /^\\d+\\.\\d+$/;\nvar HEX_COLOR = /^#[\\da-f]{6}$/i;\nfunction fail(message) {\n throw new Error(`[one] invalid native.app: ${message}`);\n}\nfunction validateNativeApp(manifest, platform) {\n var _manifest_imagePicker;\n if (!manifest || typeof manifest !== \"object\") fail(\"manifest must be an object\");\n if (!manifest.name || typeof manifest.name !== \"string\") fail(\"name is required\");\n if (!TARGET_NAME.test(manifest.name)) {\n fail(`name \"${manifest.name}\" must start with a letter and contain only letters, digits, and underscore`);\n }\n var schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [\n manifest.scheme\n ];\n var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;\n try {\n for (var _iterator = schemes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var scheme = _step.value;\n if (typeof scheme !== \"string\" || !SCHEME.test(scheme)) {\n fail(`scheme \"${scheme}\" must be a valid uri scheme`);\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {\n fail(`version \"${manifest.version}\" must start with major.minor.patch`);\n }\n if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {\n fail(\"icon requires source and a six-digit hex backgroundColor\");\n }\n if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {\n fail(\"splash requires source, a six-digit hex backgroundColor, and width from 1 to 288\");\n }\n if (((_manifest_imagePicker = manifest.imagePicker) === null || _manifest_imagePicker === void 0 ? void 0 : _manifest_imagePicker.camera) !== void 0 && (typeof manifest.imagePicker.camera !== \"string\" || manifest.imagePicker.camera.trim() === \"\")) {\n fail(\"imagePicker.camera must be a non-empty string\");\n }\n if (!platform || platform === \"ios\") {\n var _manifest_ios;\n if (!((_manifest_ios = manifest.ios) === null || _manifest_ios === void 0 ? void 0 : _manifest_ios.bundleId) || !REVERSE_DNS.test(manifest.ios.bundleId)) {\n var _manifest_ios1;\n fail(`ios.bundleId \"${(_manifest_ios1 = manifest.ios) === null || _manifest_ios1 === void 0 ? void 0 : _manifest_ios1.bundleId}\" must be reverse-dns`);\n }\n if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {\n fail(`ios.deploymentTarget \"${manifest.ios.deploymentTarget}\" must look like \"17.0\"`);\n }\n if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {\n fail(`ios.buildNumber \"${manifest.ios.buildNumber}\" must contain only letters, digits, and dots`);\n }\n }\n if (!platform || platform === \"android\") {\n var _manifest_android;\n if (!((_manifest_android = manifest.android) === null || _manifest_android === void 0 ? void 0 : _manifest_android.applicationId) || !REVERSE_DNS.test(manifest.android.applicationId)) {\n var _manifest_android1;\n fail(`android.applicationId \"${(_manifest_android1 = manifest.android) === null || _manifest_android1 === void 0 ? void 0 : _manifest_android1.applicationId}\" must be reverse-dns`);\n }\n if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {\n fail(`android.minSdk \"${manifest.android.minSdk}\" must be an integer from 21 to 36`);\n }\n if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {\n fail(`android.versionCode \"${manifest.android.versionCode}\" must be a positive integer`);\n }\n }\n return manifest;\n}\n//# sourceMappingURL=nativeAppManifest.js.map\n"],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
2
|
+
const SCHEME = /^[a-z][a-z0-9+.-]*$/i;
|
|
3
|
+
const VERSION = /^\d+\.\d+\.\d+/;
|
|
4
|
+
const BUILD_NUMBER = /^[A-Za-z0-9.]+$/;
|
|
5
|
+
const REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
|
|
6
|
+
const DEPLOYMENT_TARGET = /^\d+\.\d+$/;
|
|
7
|
+
const HEX_COLOR = /^#[\da-f]{6}$/i;
|
|
8
|
+
function fail(message) {
|
|
9
|
+
throw new Error(`[one] invalid native.app: ${message}`);
|
|
10
|
+
}
|
|
11
|
+
function validateNativeApp(manifest, platform) {
|
|
12
|
+
if (!manifest || typeof manifest !== "object") fail("manifest must be an object");
|
|
13
|
+
if (!manifest.name || typeof manifest.name !== "string") fail("name is required");
|
|
14
|
+
if (!TARGET_NAME.test(manifest.name)) {
|
|
15
|
+
fail(`name "${manifest.name}" must start with a letter and contain only letters, digits, and underscore`);
|
|
16
|
+
}
|
|
17
|
+
const schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [manifest.scheme];
|
|
18
|
+
for (const scheme of schemes) {
|
|
19
|
+
if (typeof scheme !== "string" || !SCHEME.test(scheme)) {
|
|
20
|
+
fail(`scheme "${scheme}" must be a valid uri scheme`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {
|
|
24
|
+
fail(`version "${manifest.version}" must start with major.minor.patch`);
|
|
25
|
+
}
|
|
26
|
+
if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {
|
|
27
|
+
fail("icon requires source and a six-digit hex backgroundColor");
|
|
28
|
+
}
|
|
29
|
+
if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {
|
|
30
|
+
fail("splash requires source, a six-digit hex backgroundColor, and width from 1 to 288");
|
|
31
|
+
}
|
|
32
|
+
if (manifest.imagePicker?.camera !== void 0 && (typeof manifest.imagePicker.camera !== "string" || manifest.imagePicker.camera.trim() === "")) {
|
|
33
|
+
fail("imagePicker.camera must be a non-empty string");
|
|
34
|
+
}
|
|
35
|
+
if (!platform || platform === "ios") {
|
|
36
|
+
if (!manifest.ios?.bundleId || !REVERSE_DNS.test(manifest.ios.bundleId)) {
|
|
37
|
+
fail(`ios.bundleId "${manifest.ios?.bundleId}" must be reverse-dns`);
|
|
38
|
+
}
|
|
39
|
+
if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {
|
|
40
|
+
fail(`ios.deploymentTarget "${manifest.ios.deploymentTarget}" must look like "17.0"`);
|
|
41
|
+
}
|
|
42
|
+
if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {
|
|
43
|
+
fail(`ios.buildNumber "${manifest.ios.buildNumber}" must contain only letters, digits, and dots`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!platform || platform === "android") {
|
|
47
|
+
if (!manifest.android?.applicationId || !REVERSE_DNS.test(manifest.android.applicationId)) {
|
|
48
|
+
fail(`android.applicationId "${manifest.android?.applicationId}" must be reverse-dns`);
|
|
49
|
+
}
|
|
50
|
+
if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {
|
|
51
|
+
fail(`android.minSdk "${manifest.android.minSdk}" must be an integer from 21 to 36`);
|
|
52
|
+
}
|
|
53
|
+
if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {
|
|
54
|
+
fail(`android.versionCode "${manifest.android.versionCode}" must be a positive integer`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return manifest;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { validateNativeApp };
|
|
61
|
+
//# sourceMappingURL=nativeAppManifest.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeAppManifest.js","names":[],"sources":["esm/nativeAppManifest.js"],"sourcesContent":["const TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;\nconst SCHEME = /^[a-z][a-z0-9+.-]*$/i;\nconst VERSION = /^\\d+\\.\\d+\\.\\d+/;\nconst BUILD_NUMBER = /^[A-Za-z0-9.]+$/;\nconst REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\\.[A-Za-z][A-Za-z0-9-]*)+$/;\nconst DEPLOYMENT_TARGET = /^\\d+\\.\\d+$/;\nconst HEX_COLOR = /^#[\\da-f]{6}$/i;\nfunction fail(message) {\n throw new Error(`[one] invalid native.app: ${message}`);\n}\nfunction validateNativeApp(manifest, platform) {\n if (!manifest || typeof manifest !== \"object\") fail(\"manifest must be an object\");\n if (!manifest.name || typeof manifest.name !== \"string\") fail(\"name is required\");\n if (!TARGET_NAME.test(manifest.name)) {\n fail(\n `name \"${manifest.name}\" must start with a letter and contain only letters, digits, and underscore`\n );\n }\n const schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [manifest.scheme];\n for (const scheme of schemes) {\n if (typeof scheme !== \"string\" || !SCHEME.test(scheme)) {\n fail(`scheme \"${scheme}\" must be a valid uri scheme`);\n }\n }\n if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {\n fail(`version \"${manifest.version}\" must start with major.minor.patch`);\n }\n if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {\n fail(\"icon requires source and a six-digit hex backgroundColor\");\n }\n if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {\n fail(\n \"splash requires source, a six-digit hex backgroundColor, and width from 1 to 288\"\n );\n }\n if (manifest.imagePicker?.camera !== void 0 && (typeof manifest.imagePicker.camera !== \"string\" || manifest.imagePicker.camera.trim() === \"\")) {\n fail(\"imagePicker.camera must be a non-empty string\");\n }\n if (!platform || platform === \"ios\") {\n if (!manifest.ios?.bundleId || !REVERSE_DNS.test(manifest.ios.bundleId)) {\n fail(`ios.bundleId \"${manifest.ios?.bundleId}\" must be reverse-dns`);\n }\n if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {\n fail(\n `ios.deploymentTarget \"${manifest.ios.deploymentTarget}\" must look like \"17.0\"`\n );\n }\n if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {\n fail(\n `ios.buildNumber \"${manifest.ios.buildNumber}\" must contain only letters, digits, and dots`\n );\n }\n }\n if (!platform || platform === \"android\") {\n if (!manifest.android?.applicationId || !REVERSE_DNS.test(manifest.android.applicationId)) {\n fail(\n `android.applicationId \"${manifest.android?.applicationId}\" must be reverse-dns`\n );\n }\n if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {\n fail(`android.minSdk \"${manifest.android.minSdk}\" must be an integer from 21 to 36`);\n }\n if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {\n fail(\n `android.versionCode \"${manifest.android.versionCode}\" must be a positive integer`\n );\n }\n }\n return manifest;\n}\nexport {\n validateNativeApp\n};\n//# sourceMappingURL=nativeAppManifest.js.map\n"],"mappings":";AAAA,MAAM,cAAc;AACpB,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,eAAe;AACrB,MAAM,cAAc;AACpB,MAAM,oBAAoB;AAC1B,MAAM,YAAY;AAClB,SAAS,KAAK,SAAS;CACrB,MAAM,IAAI,MAAM,6BAA6B,SAAS;AACxD;AACA,SAAS,kBAAkB,UAAU,UAAU;CAC7C,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU,KAAK,4BAA4B;CAChF,IAAI,CAAC,SAAS,QAAQ,OAAO,SAAS,SAAS,UAAU,KAAK,kBAAkB;CAChF,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,GAAG;EACpC,KACE,SAAS,SAAS,KAAK,4EACzB;CACF;CACA,MAAM,UAAU,SAAS,WAAW,KAAK,IAAI,CAAC,IAAI,MAAM,QAAQ,SAAS,MAAM,IAAI,SAAS,SAAS,CAAC,SAAS,MAAM;CACrH,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,OAAO,WAAW,YAAY,CAAC,OAAO,KAAK,MAAM,GAAG;GACtD,KAAK,WAAW,OAAO,6BAA6B;EACtD;CACF;CACA,IAAI,SAAS,YAAY,KAAK,KAAK,CAAC,QAAQ,KAAK,SAAS,OAAO,GAAG;EAClE,KAAK,YAAY,SAAS,QAAQ,oCAAoC;CACxE;CACA,IAAI,SAAS,SAAS,KAAK,MAAM,CAAC,SAAS,KAAK,UAAU,CAAC,UAAU,KAAK,SAAS,KAAK,eAAe,IAAI;EACzG,KAAK,0DAA0D;CACjE;CACA,IAAI,SAAS,WAAW,KAAK,MAAM,CAAC,SAAS,OAAO,UAAU,CAAC,UAAU,KAAK,SAAS,OAAO,eAAe,KAAK,SAAS,OAAO,UAAU,KAAK,MAAM,CAAC,OAAO,SAAS,SAAS,OAAO,KAAK,KAAK,SAAS,OAAO,QAAQ,KAAK,SAAS,OAAO,QAAQ,OAAO;EAC5P,KACE,kFACF;CACF;CACA,IAAI,SAAS,aAAa,WAAW,KAAK,MAAM,OAAO,SAAS,YAAY,WAAW,YAAY,SAAS,YAAY,OAAO,KAAK,MAAM,KAAK;EAC7I,KAAK,+CAA+C;CACtD;CACA,IAAI,CAAC,YAAY,aAAa,OAAO;EACnC,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC,YAAY,KAAK,SAAS,IAAI,QAAQ,GAAG;GACvE,KAAK,iBAAiB,SAAS,KAAK,SAAS,sBAAsB;EACrE;EACA,IAAI,SAAS,IAAI,qBAAqB,KAAK,KAAK,CAAC,kBAAkB,KAAK,SAAS,IAAI,gBAAgB,GAAG;GACtG,KACE,yBAAyB,SAAS,IAAI,iBAAiB,wBACzD;EACF;EACA,IAAI,SAAS,IAAI,gBAAgB,KAAK,KAAK,CAAC,aAAa,KAAK,SAAS,IAAI,WAAW,GAAG;GACvF,KACE,oBAAoB,SAAS,IAAI,YAAY,8CAC/C;EACF;CACF;CACA,IAAI,CAAC,YAAY,aAAa,WAAW;EACvC,IAAI,CAAC,SAAS,SAAS,iBAAiB,CAAC,YAAY,KAAK,SAAS,QAAQ,aAAa,GAAG;GACzF,KACE,0BAA0B,SAAS,SAAS,cAAc,sBAC5D;EACF;EACA,IAAI,SAAS,QAAQ,WAAW,KAAK,MAAM,CAAC,OAAO,UAAU,SAAS,QAAQ,MAAM,KAAK,SAAS,QAAQ,SAAS,MAAM,SAAS,QAAQ,SAAS,KAAK;GACtJ,KAAK,mBAAmB,SAAS,QAAQ,OAAO,mCAAmC;EACrF;EACA,IAAI,SAAS,QAAQ,gBAAgB,KAAK,MAAM,CAAC,OAAO,UAAU,SAAS,QAAQ,WAAW,KAAK,SAAS,QAAQ,cAAc,IAAI;GACpI,KACE,wBAAwB,SAAS,QAAQ,YAAY,6BACvD;EACF;CACF;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
var TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
2
|
+
var SCHEME = /^[a-z][a-z0-9+.-]*$/i;
|
|
3
|
+
var VERSION = /^\d+\.\d+\.\d+/;
|
|
4
|
+
var BUILD_NUMBER = /^[A-Za-z0-9.]+$/;
|
|
5
|
+
var REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
|
|
6
|
+
var DEPLOYMENT_TARGET = /^\d+\.\d+$/;
|
|
7
|
+
var HEX_COLOR = /^#[\da-f]{6}$/i;
|
|
8
|
+
function fail(message) {
|
|
9
|
+
throw new Error(`[one] invalid native.app: ${message}`);
|
|
10
|
+
}
|
|
11
|
+
function validateNativeApp(manifest, platform) {
|
|
12
|
+
var _manifest_imagePicker;
|
|
13
|
+
if (!manifest || typeof manifest !== "object") fail("manifest must be an object");
|
|
14
|
+
if (!manifest.name || typeof manifest.name !== "string") fail("name is required");
|
|
15
|
+
if (!TARGET_NAME.test(manifest.name)) {
|
|
16
|
+
fail(`name "${manifest.name}" must start with a letter and contain only letters, digits, and underscore`);
|
|
17
|
+
}
|
|
18
|
+
var schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [manifest.scheme];
|
|
19
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
20
|
+
try {
|
|
21
|
+
for (var _iterator = schemes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
22
|
+
var scheme = _step.value;
|
|
23
|
+
if (typeof scheme !== "string" || !SCHEME.test(scheme)) {
|
|
24
|
+
fail(`scheme "${scheme}" must be a valid uri scheme`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch (err) {
|
|
28
|
+
_didIteratorError = true;
|
|
29
|
+
_iteratorError = err;
|
|
30
|
+
} finally {
|
|
31
|
+
try {
|
|
32
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
33
|
+
_iterator.return();
|
|
34
|
+
}
|
|
35
|
+
} finally {
|
|
36
|
+
if (_didIteratorError) {
|
|
37
|
+
throw _iteratorError;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {
|
|
42
|
+
fail(`version "${manifest.version}" must start with major.minor.patch`);
|
|
43
|
+
}
|
|
44
|
+
if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {
|
|
45
|
+
fail("icon requires source and a six-digit hex backgroundColor");
|
|
46
|
+
}
|
|
47
|
+
if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {
|
|
48
|
+
fail("splash requires source, a six-digit hex backgroundColor, and width from 1 to 288");
|
|
49
|
+
}
|
|
50
|
+
if (((_manifest_imagePicker = manifest.imagePicker) === null || _manifest_imagePicker === void 0 ? void 0 : _manifest_imagePicker.camera) !== void 0 && (typeof manifest.imagePicker.camera !== "string" || manifest.imagePicker.camera.trim() === "")) {
|
|
51
|
+
fail("imagePicker.camera must be a non-empty string");
|
|
52
|
+
}
|
|
53
|
+
if (!platform || platform === "ios") {
|
|
54
|
+
var _manifest_ios;
|
|
55
|
+
if (!((_manifest_ios = manifest.ios) === null || _manifest_ios === void 0 ? void 0 : _manifest_ios.bundleId) || !REVERSE_DNS.test(manifest.ios.bundleId)) {
|
|
56
|
+
var _manifest_ios1;
|
|
57
|
+
fail(`ios.bundleId "${(_manifest_ios1 = manifest.ios) === null || _manifest_ios1 === void 0 ? void 0 : _manifest_ios1.bundleId}" must be reverse-dns`);
|
|
58
|
+
}
|
|
59
|
+
if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {
|
|
60
|
+
fail(`ios.deploymentTarget "${manifest.ios.deploymentTarget}" must look like "17.0"`);
|
|
61
|
+
}
|
|
62
|
+
if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {
|
|
63
|
+
fail(`ios.buildNumber "${manifest.ios.buildNumber}" must contain only letters, digits, and dots`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!platform || platform === "android") {
|
|
67
|
+
var _manifest_android;
|
|
68
|
+
if (!((_manifest_android = manifest.android) === null || _manifest_android === void 0 ? void 0 : _manifest_android.applicationId) || !REVERSE_DNS.test(manifest.android.applicationId)) {
|
|
69
|
+
var _manifest_android1;
|
|
70
|
+
fail(`android.applicationId "${(_manifest_android1 = manifest.android) === null || _manifest_android1 === void 0 ? void 0 : _manifest_android1.applicationId}" must be reverse-dns`);
|
|
71
|
+
}
|
|
72
|
+
if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {
|
|
73
|
+
fail(`android.minSdk "${manifest.android.minSdk}" must be an integer from 21 to 36`);
|
|
74
|
+
}
|
|
75
|
+
if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {
|
|
76
|
+
fail(`android.versionCode "${manifest.android.versionCode}" must be a positive integer`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return manifest;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { validateNativeApp };
|
|
83
|
+
//# sourceMappingURL=nativeAppManifest.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeAppManifest.native.js","names":[],"sources":["esm/nativeAppManifest.native.js"],"sourcesContent":["var TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;\nvar SCHEME = /^[a-z][a-z0-9+.-]*$/i;\nvar VERSION = /^\\d+\\.\\d+\\.\\d+/;\nvar BUILD_NUMBER = /^[A-Za-z0-9.]+$/;\nvar REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\\.[A-Za-z][A-Za-z0-9-]*)+$/;\nvar DEPLOYMENT_TARGET = /^\\d+\\.\\d+$/;\nvar HEX_COLOR = /^#[\\da-f]{6}$/i;\nfunction fail(message) {\n throw new Error(`[one] invalid native.app: ${message}`);\n}\nfunction validateNativeApp(manifest, platform) {\n var _manifest_imagePicker;\n if (!manifest || typeof manifest !== \"object\") fail(\"manifest must be an object\");\n if (!manifest.name || typeof manifest.name !== \"string\") fail(\"name is required\");\n if (!TARGET_NAME.test(manifest.name)) {\n fail(`name \"${manifest.name}\" must start with a letter and contain only letters, digits, and underscore`);\n }\n var schemes = manifest.scheme === void 0 ? [] : Array.isArray(manifest.scheme) ? manifest.scheme : [\n manifest.scheme\n ];\n var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;\n try {\n for (var _iterator = schemes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var scheme = _step.value;\n if (typeof scheme !== \"string\" || !SCHEME.test(scheme)) {\n fail(`scheme \"${scheme}\" must be a valid uri scheme`);\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n if (manifest.version !== void 0 && !VERSION.test(manifest.version)) {\n fail(`version \"${manifest.version}\" must start with major.minor.patch`);\n }\n if (manifest.icon !== void 0 && (!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))) {\n fail(\"icon requires source and a six-digit hex backgroundColor\");\n }\n if (manifest.splash !== void 0 && (!manifest.splash.source || !HEX_COLOR.test(manifest.splash.backgroundColor) || manifest.splash.width !== void 0 && (!Number.isFinite(manifest.splash.width) || manifest.splash.width < 1 || manifest.splash.width > 288))) {\n fail(\"splash requires source, a six-digit hex backgroundColor, and width from 1 to 288\");\n }\n if (((_manifest_imagePicker = manifest.imagePicker) === null || _manifest_imagePicker === void 0 ? void 0 : _manifest_imagePicker.camera) !== void 0 && (typeof manifest.imagePicker.camera !== \"string\" || manifest.imagePicker.camera.trim() === \"\")) {\n fail(\"imagePicker.camera must be a non-empty string\");\n }\n if (!platform || platform === \"ios\") {\n var _manifest_ios;\n if (!((_manifest_ios = manifest.ios) === null || _manifest_ios === void 0 ? void 0 : _manifest_ios.bundleId) || !REVERSE_DNS.test(manifest.ios.bundleId)) {\n var _manifest_ios1;\n fail(`ios.bundleId \"${(_manifest_ios1 = manifest.ios) === null || _manifest_ios1 === void 0 ? void 0 : _manifest_ios1.bundleId}\" must be reverse-dns`);\n }\n if (manifest.ios.deploymentTarget !== void 0 && !DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)) {\n fail(`ios.deploymentTarget \"${manifest.ios.deploymentTarget}\" must look like \"17.0\"`);\n }\n if (manifest.ios.buildNumber !== void 0 && !BUILD_NUMBER.test(manifest.ios.buildNumber)) {\n fail(`ios.buildNumber \"${manifest.ios.buildNumber}\" must contain only letters, digits, and dots`);\n }\n }\n if (!platform || platform === \"android\") {\n var _manifest_android;\n if (!((_manifest_android = manifest.android) === null || _manifest_android === void 0 ? void 0 : _manifest_android.applicationId) || !REVERSE_DNS.test(manifest.android.applicationId)) {\n var _manifest_android1;\n fail(`android.applicationId \"${(_manifest_android1 = manifest.android) === null || _manifest_android1 === void 0 ? void 0 : _manifest_android1.applicationId}\" must be reverse-dns`);\n }\n if (manifest.android.minSdk !== void 0 && (!Number.isInteger(manifest.android.minSdk) || manifest.android.minSdk < 21 || manifest.android.minSdk > 36)) {\n fail(`android.minSdk \"${manifest.android.minSdk}\" must be an integer from 21 to 36`);\n }\n if (manifest.android.versionCode !== void 0 && (!Number.isInteger(manifest.android.versionCode) || manifest.android.versionCode < 1)) {\n fail(`android.versionCode \"${manifest.android.versionCode}\" must be a positive integer`);\n }\n }\n return manifest;\n}\nexport {\n validateNativeApp\n};\n//# sourceMappingURL=nativeAppManifest.js.map\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxrn/utils",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.65.1",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./types/index.d.ts",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"types": "./types/publicEnv.d.ts",
|
|
19
19
|
"import": "./dist/esm/publicEnv.mjs",
|
|
20
20
|
"require": "./dist/cjs/publicEnv.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./nativeAppManifest": {
|
|
23
|
+
"types": "./types/nativeAppManifest.d.ts",
|
|
24
|
+
"import": "./dist/esm/nativeAppManifest.mjs",
|
|
25
|
+
"require": "./dist/cjs/nativeAppManifest.cjs"
|
|
21
26
|
}
|
|
22
27
|
},
|
|
23
28
|
"files": [
|
|
@@ -32,16 +37,18 @@
|
|
|
32
37
|
"lint:fix": "npx biome check --write --unsafe src",
|
|
33
38
|
"clean": "tamagui-build clean",
|
|
34
39
|
"clean:build": "tamagui-build clean:build",
|
|
40
|
+
"test": "vitest run --dir src",
|
|
35
41
|
"typecheck": "tsc --noEmit"
|
|
36
42
|
},
|
|
37
43
|
"dependencies": {
|
|
38
|
-
"@vxrn/debug": "2.0.0-beta.
|
|
39
|
-
"@vxrn/resolve": "2.0.0-beta.
|
|
44
|
+
"@vxrn/debug": "2.0.0-beta.65.1",
|
|
45
|
+
"@vxrn/resolve": "2.0.0-beta.65.1",
|
|
40
46
|
"ws": "^8.21.0"
|
|
41
47
|
},
|
|
42
48
|
"devDependencies": {
|
|
43
49
|
"@tamagui/build": "3.0.0-beta.1309.1",
|
|
44
|
-
"@types/ws": "^8.18.1"
|
|
50
|
+
"@types/ws": "^8.18.1",
|
|
51
|
+
"vitest": "^4.1.0"
|
|
45
52
|
},
|
|
46
53
|
"publishConfig": {
|
|
47
54
|
"access": "public"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { validateNativeApp, type NativeAppManifest } from './nativeAppManifest'
|
|
3
|
+
|
|
4
|
+
const app = {
|
|
5
|
+
name: 'MyApp',
|
|
6
|
+
displayName: 'My App',
|
|
7
|
+
scheme: ['myapp', 'myapp-dev'],
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
imagePicker: { camera: 'Take profile photos.' },
|
|
10
|
+
ios: {
|
|
11
|
+
bundleId: 'dev.one.myapp',
|
|
12
|
+
buildNumber: '42',
|
|
13
|
+
tablet: true,
|
|
14
|
+
deploymentTarget: '17.0',
|
|
15
|
+
screensGamma: true,
|
|
16
|
+
useFrameworks: 'static',
|
|
17
|
+
ccache: true,
|
|
18
|
+
usesNonExemptEncryption: false,
|
|
19
|
+
},
|
|
20
|
+
android: { applicationId: 'dev.one.myapp', versionCode: 42, minSdk: 28 },
|
|
21
|
+
} satisfies NativeAppManifest
|
|
22
|
+
|
|
23
|
+
describe('native.app manifest', () => {
|
|
24
|
+
test('accepts a valid manifest', () => {
|
|
25
|
+
expect(() => validateNativeApp(app)).not.toThrow()
|
|
26
|
+
expect(() => validateNativeApp(app, 'ios')).not.toThrow()
|
|
27
|
+
expect(() => validateNativeApp(app, 'android')).not.toThrow()
|
|
28
|
+
expect(validateNativeApp(app)).toBe(app)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('rejects invalid target names and schemes', () => {
|
|
32
|
+
expect(() => validateNativeApp({} as any)).toThrow(/name/)
|
|
33
|
+
expect(() => validateNativeApp({ name: 'my-app' } as any)).toThrow(/name/)
|
|
34
|
+
expect(() => validateNativeApp({ ...app, scheme: 'not a scheme' })).toThrow(
|
|
35
|
+
/scheme/
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('rejects bad versions, icons, and splashes', () => {
|
|
40
|
+
expect(() => validateNativeApp({ ...app, version: 'latest' })).toThrow(/version/)
|
|
41
|
+
expect(() =>
|
|
42
|
+
validateNativeApp({
|
|
43
|
+
...app,
|
|
44
|
+
icon: { source: '', backgroundColor: '#000000' },
|
|
45
|
+
})
|
|
46
|
+
).toThrow(/icon/)
|
|
47
|
+
expect(() =>
|
|
48
|
+
validateNativeApp({
|
|
49
|
+
...app,
|
|
50
|
+
splash: { source: './splash.png', backgroundColor: 'black' },
|
|
51
|
+
})
|
|
52
|
+
).toThrow(/splash/)
|
|
53
|
+
expect(() =>
|
|
54
|
+
validateNativeApp({
|
|
55
|
+
...app,
|
|
56
|
+
splash: { source: './splash.png', backgroundColor: '#000000', width: 0.99 },
|
|
57
|
+
})
|
|
58
|
+
).toThrow(/splash/)
|
|
59
|
+
expect(() =>
|
|
60
|
+
validateNativeApp({
|
|
61
|
+
...app,
|
|
62
|
+
splash: { source: './splash.png', backgroundColor: '#000000', width: 289 },
|
|
63
|
+
})
|
|
64
|
+
).toThrow(/splash/)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('accepts a camera permission string and rejects empty ones', () => {
|
|
68
|
+
expect(() => validateNativeApp({ ...app, imagePicker: undefined })).not.toThrow()
|
|
69
|
+
expect(() =>
|
|
70
|
+
validateNativeApp({ ...app, imagePicker: { camera: '' } })
|
|
71
|
+
).toThrow(/imagePicker\.camera/)
|
|
72
|
+
expect(() =>
|
|
73
|
+
validateNativeApp({ ...app, imagePicker: { camera: ' ' } })
|
|
74
|
+
).toThrow(/imagePicker\.camera/)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('rejects missing platform ids and out-of-range platform values', () => {
|
|
78
|
+
expect(() => validateNativeApp({ name: 'MyApp' } as any)).toThrow(/bundleId/)
|
|
79
|
+
expect(() =>
|
|
80
|
+
validateNativeApp({ name: 'MyApp', android: app.android } as any)
|
|
81
|
+
).toThrow(/bundleId/)
|
|
82
|
+
expect(() =>
|
|
83
|
+
validateNativeApp({
|
|
84
|
+
name: 'MyApp',
|
|
85
|
+
ios: { bundleId: 'not-an-id' },
|
|
86
|
+
android: app.android,
|
|
87
|
+
} as any)
|
|
88
|
+
).toThrow(/bundleId/)
|
|
89
|
+
expect(() =>
|
|
90
|
+
validateNativeApp({ name: 'MyApp', ios: app.ios } as any)
|
|
91
|
+
).toThrow(/applicationId/)
|
|
92
|
+
expect(() =>
|
|
93
|
+
validateNativeApp({
|
|
94
|
+
name: 'MyApp',
|
|
95
|
+
ios: app.ios,
|
|
96
|
+
android: { applicationId: '' },
|
|
97
|
+
} as any)
|
|
98
|
+
).toThrow(/applicationId/)
|
|
99
|
+
expect(() =>
|
|
100
|
+
validateNativeApp({
|
|
101
|
+
...app,
|
|
102
|
+
ios: { bundleId: 'dev.one.myapp', deploymentTarget: 'latest' },
|
|
103
|
+
} as any)
|
|
104
|
+
).toThrow(/deploymentTarget/)
|
|
105
|
+
expect(() =>
|
|
106
|
+
validateNativeApp({ ...app, android: { ...app.android, minSdk: 20 } } as any)
|
|
107
|
+
).toThrow(/minSdk/)
|
|
108
|
+
expect(() =>
|
|
109
|
+
validateNativeApp({
|
|
110
|
+
...app,
|
|
111
|
+
ios: { bundleId: 'dev.one.myapp', buildNumber: '1 2' },
|
|
112
|
+
})
|
|
113
|
+
).toThrow(/buildNumber/)
|
|
114
|
+
expect(() =>
|
|
115
|
+
validateNativeApp({
|
|
116
|
+
...app,
|
|
117
|
+
ios: { bundleId: 'dev.one.myapp', buildNumber: '' },
|
|
118
|
+
})
|
|
119
|
+
).toThrow(/buildNumber/)
|
|
120
|
+
expect(() =>
|
|
121
|
+
validateNativeApp({
|
|
122
|
+
...app,
|
|
123
|
+
android: { applicationId: 'dev.one.myapp', versionCode: 0 },
|
|
124
|
+
})
|
|
125
|
+
).toThrow(/versionCode/)
|
|
126
|
+
expect(() =>
|
|
127
|
+
validateNativeApp({
|
|
128
|
+
...app,
|
|
129
|
+
android: { applicationId: 'dev.one.myapp', versionCode: 1.5 },
|
|
130
|
+
})
|
|
131
|
+
).toThrow(/versionCode/)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('platform scope skips the other platform requirement', () => {
|
|
135
|
+
expect(() =>
|
|
136
|
+
validateNativeApp({ name: 'MyApp', android: app.android } as any, 'android')
|
|
137
|
+
).not.toThrow()
|
|
138
|
+
expect(() =>
|
|
139
|
+
validateNativeApp({ name: 'MyApp', ios: app.ios } as any, 'ios')
|
|
140
|
+
).not.toThrow()
|
|
141
|
+
})
|
|
142
|
+
})
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// typed native.app manifest inside the existing one vite options.
|
|
2
|
+
// name is the native target and appregistry key. one canonical definition:
|
|
3
|
+
// one/native re-exports it for apps and vxrn prebuild consumes it, so a new
|
|
4
|
+
// field is added once, here.
|
|
5
|
+
export interface NativeAppManifest {
|
|
6
|
+
name: string
|
|
7
|
+
displayName?: string
|
|
8
|
+
scheme?: string | string[]
|
|
9
|
+
version?: string
|
|
10
|
+
icon?: {
|
|
11
|
+
source: string
|
|
12
|
+
backgroundColor: string
|
|
13
|
+
}
|
|
14
|
+
splash?: {
|
|
15
|
+
source: string
|
|
16
|
+
backgroundColor: string
|
|
17
|
+
width?: number
|
|
18
|
+
}
|
|
19
|
+
imagePicker?: {
|
|
20
|
+
// ios camera usage description shown at the system prompt. setting it
|
|
21
|
+
// also declares the android camera permission; both are required for
|
|
22
|
+
// One.ImagePicker.launchCamera.
|
|
23
|
+
camera?: string
|
|
24
|
+
}
|
|
25
|
+
ios?: {
|
|
26
|
+
bundleId: string
|
|
27
|
+
buildNumber?: string
|
|
28
|
+
tablet?: boolean
|
|
29
|
+
deploymentTarget?: string
|
|
30
|
+
screensGamma?: boolean
|
|
31
|
+
useFrameworks?: 'static' | 'dynamic'
|
|
32
|
+
ccache?: boolean
|
|
33
|
+
usesNonExemptEncryption?: boolean
|
|
34
|
+
// exposes the app's Documents in the Files app and document pickers.
|
|
35
|
+
fileSharing?: boolean
|
|
36
|
+
}
|
|
37
|
+
android?: {
|
|
38
|
+
applicationId: string
|
|
39
|
+
versionCode?: number
|
|
40
|
+
minSdk?: number
|
|
41
|
+
adaptiveIcon?: {
|
|
42
|
+
foreground?: string
|
|
43
|
+
background?: string
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const TARGET_NAME = /^[A-Za-z][A-Za-z0-9_]*$/
|
|
49
|
+
const SCHEME = /^[a-z][a-z0-9+.-]*$/i
|
|
50
|
+
const VERSION = /^\d+\.\d+\.\d+/
|
|
51
|
+
const BUILD_NUMBER = /^[A-Za-z0-9.]+$/
|
|
52
|
+
const REVERSE_DNS = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/
|
|
53
|
+
const DEPLOYMENT_TARGET = /^\d+\.\d+$/
|
|
54
|
+
const HEX_COLOR = /^#[\da-f]{6}$/i
|
|
55
|
+
|
|
56
|
+
function fail(message: string): never {
|
|
57
|
+
throw new Error(`[one] invalid native.app: ${message}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// platform scopes the platform-id requirement: an ios prebuild skips the
|
|
61
|
+
// android requirement and vice versa. without it both are required, because
|
|
62
|
+
// a manifest without platform ids prebuilds nothing.
|
|
63
|
+
export function validateNativeApp(
|
|
64
|
+
manifest: NativeAppManifest,
|
|
65
|
+
platform?: 'ios' | 'android' | string
|
|
66
|
+
): NativeAppManifest {
|
|
67
|
+
if (!manifest || typeof manifest !== 'object') fail('manifest must be an object')
|
|
68
|
+
if (!manifest.name || typeof manifest.name !== 'string') fail('name is required')
|
|
69
|
+
if (!TARGET_NAME.test(manifest.name)) {
|
|
70
|
+
fail(
|
|
71
|
+
`name "${manifest.name}" must start with a letter and contain only letters, digits, and underscore`
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
const schemes =
|
|
75
|
+
manifest.scheme === undefined
|
|
76
|
+
? []
|
|
77
|
+
: Array.isArray(manifest.scheme)
|
|
78
|
+
? manifest.scheme
|
|
79
|
+
: [manifest.scheme]
|
|
80
|
+
for (const scheme of schemes) {
|
|
81
|
+
if (typeof scheme !== 'string' || !SCHEME.test(scheme)) {
|
|
82
|
+
fail(`scheme "${scheme}" must be a valid uri scheme`)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (manifest.version !== undefined && !VERSION.test(manifest.version)) {
|
|
86
|
+
fail(`version "${manifest.version}" must start with major.minor.patch`)
|
|
87
|
+
}
|
|
88
|
+
if (
|
|
89
|
+
manifest.icon !== undefined &&
|
|
90
|
+
(!manifest.icon.source || !HEX_COLOR.test(manifest.icon.backgroundColor))
|
|
91
|
+
) {
|
|
92
|
+
fail('icon requires source and a six-digit hex backgroundColor')
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
manifest.splash !== undefined &&
|
|
96
|
+
(!manifest.splash.source ||
|
|
97
|
+
!HEX_COLOR.test(manifest.splash.backgroundColor) ||
|
|
98
|
+
(manifest.splash.width !== undefined &&
|
|
99
|
+
(!Number.isFinite(manifest.splash.width) ||
|
|
100
|
+
manifest.splash.width < 1 ||
|
|
101
|
+
manifest.splash.width > 288)))
|
|
102
|
+
) {
|
|
103
|
+
fail(
|
|
104
|
+
'splash requires source, a six-digit hex backgroundColor, and width from 1 to 288'
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
if (
|
|
108
|
+
manifest.imagePicker?.camera !== undefined &&
|
|
109
|
+
(typeof manifest.imagePicker.camera !== 'string' ||
|
|
110
|
+
manifest.imagePicker.camera.trim() === '')
|
|
111
|
+
) {
|
|
112
|
+
fail('imagePicker.camera must be a non-empty string')
|
|
113
|
+
}
|
|
114
|
+
if (!platform || platform === 'ios') {
|
|
115
|
+
if (!manifest.ios?.bundleId || !REVERSE_DNS.test(manifest.ios.bundleId)) {
|
|
116
|
+
fail(`ios.bundleId "${manifest.ios?.bundleId}" must be reverse-dns`)
|
|
117
|
+
}
|
|
118
|
+
if (
|
|
119
|
+
manifest.ios.deploymentTarget !== undefined &&
|
|
120
|
+
!DEPLOYMENT_TARGET.test(manifest.ios.deploymentTarget)
|
|
121
|
+
) {
|
|
122
|
+
fail(
|
|
123
|
+
`ios.deploymentTarget "${manifest.ios.deploymentTarget}" must look like "17.0"`
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
if (
|
|
127
|
+
manifest.ios.buildNumber !== undefined &&
|
|
128
|
+
!BUILD_NUMBER.test(manifest.ios.buildNumber)
|
|
129
|
+
) {
|
|
130
|
+
fail(
|
|
131
|
+
`ios.buildNumber "${manifest.ios.buildNumber}" must contain only letters, digits, and dots`
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (!platform || platform === 'android') {
|
|
136
|
+
if (
|
|
137
|
+
!manifest.android?.applicationId ||
|
|
138
|
+
!REVERSE_DNS.test(manifest.android.applicationId)
|
|
139
|
+
) {
|
|
140
|
+
fail(
|
|
141
|
+
`android.applicationId "${manifest.android?.applicationId}" must be reverse-dns`
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
if (
|
|
145
|
+
manifest.android.minSdk !== undefined &&
|
|
146
|
+
(!Number.isInteger(manifest.android.minSdk) ||
|
|
147
|
+
manifest.android.minSdk < 21 ||
|
|
148
|
+
manifest.android.minSdk > 36)
|
|
149
|
+
) {
|
|
150
|
+
fail(`android.minSdk "${manifest.android.minSdk}" must be an integer from 21 to 36`)
|
|
151
|
+
}
|
|
152
|
+
if (
|
|
153
|
+
manifest.android.versionCode !== undefined &&
|
|
154
|
+
(!Number.isInteger(manifest.android.versionCode) ||
|
|
155
|
+
manifest.android.versionCode < 1)
|
|
156
|
+
) {
|
|
157
|
+
fail(
|
|
158
|
+
`android.versionCode "${manifest.android.versionCode}" must be a positive integer`
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return manifest
|
|
163
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface NativeAppManifest {
|
|
2
|
+
name: string;
|
|
3
|
+
displayName?: string;
|
|
4
|
+
scheme?: string | string[];
|
|
5
|
+
version?: string;
|
|
6
|
+
icon?: {
|
|
7
|
+
source: string;
|
|
8
|
+
backgroundColor: string;
|
|
9
|
+
};
|
|
10
|
+
splash?: {
|
|
11
|
+
source: string;
|
|
12
|
+
backgroundColor: string;
|
|
13
|
+
width?: number;
|
|
14
|
+
};
|
|
15
|
+
imagePicker?: {
|
|
16
|
+
camera?: string;
|
|
17
|
+
};
|
|
18
|
+
ios?: {
|
|
19
|
+
bundleId: string;
|
|
20
|
+
buildNumber?: string;
|
|
21
|
+
tablet?: boolean;
|
|
22
|
+
deploymentTarget?: string;
|
|
23
|
+
screensGamma?: boolean;
|
|
24
|
+
useFrameworks?: 'static' | 'dynamic';
|
|
25
|
+
ccache?: boolean;
|
|
26
|
+
usesNonExemptEncryption?: boolean;
|
|
27
|
+
fileSharing?: boolean;
|
|
28
|
+
};
|
|
29
|
+
android?: {
|
|
30
|
+
applicationId: string;
|
|
31
|
+
versionCode?: number;
|
|
32
|
+
minSdk?: number;
|
|
33
|
+
adaptiveIcon?: {
|
|
34
|
+
foreground?: string;
|
|
35
|
+
background?: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export declare function validateNativeApp(manifest: NativeAppManifest, platform?: 'ios' | 'android' | string): NativeAppManifest;
|
|
40
|
+
//# sourceMappingURL=nativeAppManifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeAppManifest.d.ts","sourceRoot":"","sources":["../src/nativeAppManifest.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,MAAM,CAAA;QACd,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;IACD,MAAM,CAAC,EAAE;QACP,MAAM,EAAE,MAAM,CAAA;QACd,eAAe,EAAE,MAAM,CAAA;QACvB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;IACD,WAAW,CAAC,EAAE;QAIZ,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;IACD,GAAG,CAAC,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,aAAa,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;QACpC,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,uBAAuB,CAAC,EAAE,OAAO,CAAA;QAEjC,WAAW,CAAC,EAAE,OAAO,CAAA;KACtB,CAAA;IACD,OAAO,CAAC,EAAE;QACR,aAAa,EAAE,MAAM,CAAA;QACrB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,YAAY,CAAC,EAAE;YACb,UAAU,CAAC,EAAE,MAAM,CAAA;YACnB,UAAU,CAAC,EAAE,MAAM,CAAA;SACpB,CAAA;KACF,CAAA;CACF;AAiBD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GACpC,iBAAiB,CAiGnB"}
|