catalyst-core 1.1.0 → 1.2.0-canary.2
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/bin/catalyst.js +54 -6
- package/changelog.md +27 -1
- package/dist/errors/registry.js +306 -18
- package/dist/errors-index.json +273 -70
- package/dist/native/androidProject/app/build.gradle.kts +53 -79
- package/dist/native/androidProject/app/src/main/AndroidManifest.xml +1 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CatalystConstants.kt +3 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +32 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +5 -1
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ConfigMappingTest.kt +25 -0
- package/dist/native/androidSetup.js +76 -170
- package/dist/native/androidToolchain.js +642 -0
- package/dist/native/appIcon.js +100 -0
- package/dist/native/buildAndroid/assets.js +29 -5
- package/dist/native/buildAndroid/build.js +110 -223
- package/dist/native/buildAndroid/config.js +57 -65
- package/dist/native/buildAndroid/devices.js +176 -0
- package/dist/native/buildAndroid/index.js +271 -46
- package/dist/native/buildAndroid/output.js +43 -0
- package/dist/native/buildAndroid/signing.js +456 -0
- package/dist/native/buildAppAndroid.js +27 -7
- package/dist/native/buildAppIos.js +139 -20
- package/dist/native/buildIos/assets.js +76 -4
- package/dist/native/buildIos/build.js +31 -181
- package/dist/native/buildIos/config.js +126 -11
- package/dist/native/buildIos/index.js +354 -34
- package/dist/native/buildIos/localhostCert.js +87 -0
- package/dist/native/buildIos/output.js +28 -0
- package/dist/native/buildIos/signing.js +596 -0
- package/dist/native/credentials.js +309 -0
- package/dist/native/exportCredentials.js +51 -0
- package/dist/native/iosToolchain.js +583 -0
- package/dist/native/iosnativeWebView/Configurations/Shared.xcconfig +1 -3
- package/dist/native/iosnativeWebView/iosnativeWebView/Info-Release.plist +2 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/PrivacyInfo.xcprivacy +40 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebView.entitlements +0 -2
- package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +4 -4
- package/dist/native/localState.js +148 -0
- package/dist/native/nativeConfig.js +621 -0
- package/dist/native/releaseOutput.js +53 -0
- package/dist/native/renameAndroidProject.js +154 -369
- package/dist/native/setupEmulatorIos.js +58 -275
- package/dist/native/setupServer.js +520 -124
- package/dist/native/utils.js +418 -115
- package/dist/vite/resolveDevServerConfig.js +21 -0
- package/mcp_v2/knowledge-base.json +13 -11
- package/mcp_v2/test/config.test.ts +40 -0
- package/mcp_v2/tools/build.js +80 -104
- package/mcp_v2/tools/config.js +181 -174
- package/package.json +1 -1
- package/test/cli/nativeFlags.test.ts +97 -0
- package/test/native/androidDevices.test.ts +230 -0
- package/test/native/androidElfAlignment.test.ts +148 -0
- package/test/native/androidSigning.test.ts +646 -0
- package/test/native/androidToolchain.test.ts +766 -0
- package/test/native/appIcon.test.ts +124 -0
- package/test/native/credentials.test.ts +241 -0
- package/test/native/interaction.test.ts +179 -0
- package/test/native/iosConfigPhase.test.ts +611 -0
- package/test/native/iosSigning.test.ts +1060 -0
- package/test/native/iosToolchain.test.ts +821 -0
- package/test/native/localState.test.ts +80 -0
- package/test/native/nativeConfig.test.ts +602 -0
- package/test/native/setupServer.test.ts +529 -0
- package/test/native/utils.test.ts +102 -127
- package/test/vite/resolveDevServerConfig.test.js +25 -0
- package/dist/native/androidProject/keystore/Untitled +0 -0
- package/dist/native/androidProject/keystore/release-key.jks +0 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/localhost.p12 +0 -0
|
@@ -75,6 +75,46 @@ function generateSwiftProperty(key, value, indent = " ") {
|
|
|
75
75
|
return `${indent}public static let ${key} = "${value}"`;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// ios.* keys that only steer the build and never reach ConfigConstants.
|
|
79
|
+
// ascApiKey is no longer read (the key lives in credentials/ios/), but an
|
|
80
|
+
// older config that still has it must not ship it in the binary either.
|
|
81
|
+
const BUILD_ONLY_IOS_KEYS = new Set(["ascApiKey", "exportMethod"]);
|
|
82
|
+
|
|
83
|
+
// WEBVIEW_CONFIG keys the generic emitter skips: the platform blocks, and
|
|
84
|
+
// nativeConfig.js RESOLVER_ONLY_KEYS, which only the resolver reads (it turns
|
|
85
|
+
// url, appId and appName into the legacy keys, so ConfigConstants gets one
|
|
86
|
+
// url). Copied, not required: this CJS file is loaded with plain require in
|
|
87
|
+
// tests, which cannot load the ESM resolver.
|
|
88
|
+
const SKIPPED_TOP_LEVEL_KEYS = new Set(["ios", "android", "url", "appId", "appName", "allowPrivateHost"]);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The xcconfig signing block. Manual (an explicit profile) keeps the
|
|
92
|
+
* settings existing ios.provisioningProfile users had; everything else is
|
|
93
|
+
* Automatic for DEVELOPMENT_TEAM, with no identity or profile pinned, so
|
|
94
|
+
* Xcode (or -allowProvisioningUpdates) picks them.
|
|
95
|
+
*
|
|
96
|
+
* @param {object} signing
|
|
97
|
+
* @param {"manual"|"automatic"|"none"} [signing.style]
|
|
98
|
+
* @param {string} [signing.provisioningProfile]
|
|
99
|
+
* @param {string} [signing.identity] - CODE_SIGN_IDENTITY for device builds
|
|
100
|
+
*/
|
|
101
|
+
function xcconfigSigningBlock({
|
|
102
|
+
style,
|
|
103
|
+
provisioningProfile,
|
|
104
|
+
identity
|
|
105
|
+
} = {}) {
|
|
106
|
+
if (style === "manual" && provisioningProfile) {
|
|
107
|
+
return ["CODE_SIGN_STYLE = Manual", "CODE_SIGN_IDENTITY = Apple Development", `CODE_SIGN_IDENTITY[sdk=iphoneos*] = ${identity || "iPhone Developer"}`, "PROVISIONING_PROFILE_SPECIFIER =", `PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*] = ${provisioningProfile}`].join("\n");
|
|
108
|
+
}
|
|
109
|
+
return "CODE_SIGN_STYLE = Automatic";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** MARKETING_VERSION must be one to three dot-separated integers; "2.5.0-beta.1" becomes "2.5.0". */
|
|
113
|
+
function marketingVersionOf(versionName) {
|
|
114
|
+
const match = /^\d+(?:\.\d+){0,2}/.exec(String(versionName || ""));
|
|
115
|
+
return match ? match[0] : null;
|
|
116
|
+
}
|
|
117
|
+
|
|
78
118
|
// ─── Module factory ───────────────────────────────────────────────────────────
|
|
79
119
|
|
|
80
120
|
module.exports = function createConfigPhase(ctx) {
|
|
@@ -89,6 +129,20 @@ module.exports = function createConfigPhase(ctx) {
|
|
|
89
129
|
readPlistObject,
|
|
90
130
|
writePlistObject
|
|
91
131
|
} = ctx;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* CFBundleShortVersionString and CFBundleVersion: package.json's version
|
|
135
|
+
* and the build number (nativeConfig.js resolveAppVersion), falling back
|
|
136
|
+
* to ios.version as shipped.
|
|
137
|
+
*/
|
|
138
|
+
function appVersion(version) {
|
|
139
|
+
const resolvedVersion = version || ctx.version;
|
|
140
|
+
const configuredVersion = iosConfig.version ? `${iosConfig.version.major || 1}.${iosConfig.version.minor || 0}.${iosConfig.version.patch || 0}` : "1.0.0";
|
|
141
|
+
return {
|
|
142
|
+
marketingVersion: marketingVersionOf(resolvedVersion?.versionName) || configuredVersion,
|
|
143
|
+
buildNumber: resolvedVersion?.buildNumber || iosConfig.version?.buildNumber || 1
|
|
144
|
+
};
|
|
145
|
+
}
|
|
92
146
|
function mergeIntoTopLevelObject(target, source, fieldName) {
|
|
93
147
|
for (const [key, value] of Object.entries(source || {})) {
|
|
94
148
|
target[key] = mergeStructuredValues(target[key], value, `${fieldName}.${key}`);
|
|
@@ -151,7 +205,7 @@ public enum ConfigConstants {
|
|
|
151
205
|
const addedKeys = new Set();
|
|
152
206
|
if (WEBVIEW_CONFIG && typeof WEBVIEW_CONFIG === "object") {
|
|
153
207
|
for (const [key, value] of Object.entries(WEBVIEW_CONFIG)) {
|
|
154
|
-
if (key
|
|
208
|
+
if (SKIPPED_TOP_LEVEL_KEYS.has(key)) continue;
|
|
155
209
|
if (key === "notifications") progress.log(`Processing notifications config: ${JSON.stringify(value)}`, "info");
|
|
156
210
|
configContent += "\n" + generateSwiftProperty(key, value);
|
|
157
211
|
addedKeys.add(key);
|
|
@@ -161,6 +215,9 @@ public enum ConfigConstants {
|
|
|
161
215
|
configContent += "\n \n // iOS-specific configuration";
|
|
162
216
|
for (const [key, value] of Object.entries(iosConfig)) {
|
|
163
217
|
if (addedKeys.has(key)) continue;
|
|
218
|
+
// Build-machine signing settings, not app config: key paths
|
|
219
|
+
// and IDs have no business in the shipped binary.
|
|
220
|
+
if (BUILD_ONLY_IOS_KEYS.has(key)) continue;
|
|
164
221
|
configContent += "\n" + generateSwiftProperty(key, value);
|
|
165
222
|
addedKeys.add(key);
|
|
166
223
|
}
|
|
@@ -255,7 +312,16 @@ public enum ConfigConstants {
|
|
|
255
312
|
throw error;
|
|
256
313
|
}
|
|
257
314
|
}
|
|
258
|
-
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* @param {object} [options]
|
|
318
|
+
* @param {object} [options.signing] - from planIosSigning (plus the CI profile and identity); defaults to ios.provisioningProfile or Automatic
|
|
319
|
+
* @param {{ versionName?: string, buildNumber?: number }} [options.version] - from resolveAppVersion
|
|
320
|
+
*/
|
|
321
|
+
async function generateXCConfig({
|
|
322
|
+
signing,
|
|
323
|
+
version
|
|
324
|
+
} = {}) {
|
|
259
325
|
try {
|
|
260
326
|
const xconfigPath = path.join(PROJECT_DIR, "Configurations", "Shared.xcconfig"); // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
|
|
261
327
|
const configDir = path.dirname(xconfigPath);
|
|
@@ -264,12 +330,17 @@ public enum ConfigConstants {
|
|
|
264
330
|
});
|
|
265
331
|
const bundleId = iosConfig.bundleIdentifier || iosConfig.appBundleId || "com.catalyst.framework.app";
|
|
266
332
|
const appName = iosConfig.appName || "Catalyst App";
|
|
267
|
-
const
|
|
333
|
+
const signingPlan = signing || {
|
|
334
|
+
style: iosConfig.provisioningProfile ? "manual" : "automatic",
|
|
335
|
+
provisioningProfile: iosConfig.provisioningProfile
|
|
336
|
+
};
|
|
337
|
+
const teamId = signingPlan.teamId || iosConfig.developmentTeam || "";
|
|
268
338
|
const swiftVersion = iosConfig.deployment?.swiftVersion || "5.9";
|
|
269
339
|
const deploymentTarget = iosConfig.deployment?.target || "17.0";
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
340
|
+
const {
|
|
341
|
+
marketingVersion,
|
|
342
|
+
buildNumber
|
|
343
|
+
} = appVersion(version);
|
|
273
344
|
const xconfigContent = `// This file is auto-generated by buildAppIos.js. Do not edit.
|
|
274
345
|
//
|
|
275
346
|
// Shared configuration for both Debug and Release builds
|
|
@@ -301,11 +372,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
|
|
301
372
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor
|
|
302
373
|
|
|
303
374
|
// Code signing
|
|
304
|
-
|
|
305
|
-
CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer
|
|
306
|
-
CODE_SIGN_STYLE = Manual
|
|
307
|
-
PROVISIONING_PROFILE_SPECIFIER =
|
|
308
|
-
PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*] = ${provisioningProfile}
|
|
375
|
+
${xcconfigSigningBlock(signingPlan)}
|
|
309
376
|
|
|
310
377
|
// Module settings
|
|
311
378
|
CLANG_ENABLE_MODULES = NO
|
|
@@ -357,6 +424,10 @@ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPo
|
|
|
357
424
|
throw new Error("Google Sign-In enabled but no valid clientId found");
|
|
358
425
|
}
|
|
359
426
|
const plistTargets = [infoPlistPath, infoReleasePlistPath];
|
|
427
|
+
const {
|
|
428
|
+
marketingVersion,
|
|
429
|
+
buildNumber
|
|
430
|
+
} = appVersion();
|
|
360
431
|
const pluginUrlSchemes = pluginComposition.urlSchemes || [];
|
|
361
432
|
const pluginQuerySchemes = pluginComposition.querySchemes || [];
|
|
362
433
|
const pluginInfoPlist = pluginComposition.infoPlist || {};
|
|
@@ -375,16 +446,60 @@ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPo
|
|
|
375
446
|
}
|
|
376
447
|
mergeUrlSchemes(plistObject, pluginUrlSchemes);
|
|
377
448
|
mergeQuerySchemes(plistObject, pluginQuerySchemes);
|
|
449
|
+
// Literal values, so the plist says what the IPA carries.
|
|
450
|
+
plistObject.CFBundleShortVersionString = String(marketingVersion);
|
|
451
|
+
plistObject.CFBundleVersion = String(buildNumber);
|
|
452
|
+
if (plistPath === infoReleasePlistPath) {
|
|
453
|
+
// Without it App Store Connect asks the export compliance
|
|
454
|
+
// questions for every upload. A plugin that ships non-exempt
|
|
455
|
+
// encryption sets it to true through its infoPlist.
|
|
456
|
+
if (plistObject.ITSAppUsesNonExemptEncryption === undefined) {
|
|
457
|
+
plistObject.ITSAppUsesNonExemptEncryption = false;
|
|
458
|
+
}
|
|
459
|
+
} else {
|
|
460
|
+
applyDebugTransportSecurity(plistObject);
|
|
461
|
+
}
|
|
378
462
|
writePlistObject(plistPath, plistObject);
|
|
379
463
|
});
|
|
380
464
|
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Info.plist is the Debug configuration's plist. When a debug build loads
|
|
468
|
+
* the dev server (ctx.localNetworking), NSAllowsLocalNetworking lets it
|
|
469
|
+
* reach `<mac>.local`, a LAN IP or localhost over plain HTTP. On iOS 10
|
|
470
|
+
* and later its presence makes the OS ignore NSAllowsArbitraryLoads, so
|
|
471
|
+
* it is added only when the plist does not already allow arbitrary loads
|
|
472
|
+
* (the template's debug plist does, and that already covers local hosts).
|
|
473
|
+
* Release builds use Info-Release.plist and never get it.
|
|
474
|
+
*/
|
|
475
|
+
function applyDebugTransportSecurity(plistObject) {
|
|
476
|
+
const ats = isPlainObject(plistObject.NSAppTransportSecurity) ? {
|
|
477
|
+
...plistObject.NSAppTransportSecurity
|
|
478
|
+
} : {};
|
|
479
|
+
if (ctx.localNetworking && ats.NSAllowsArbitraryLoads !== true) ats.NSAllowsLocalNetworking = true;else delete ats.NSAllowsLocalNetworking;
|
|
480
|
+
plistObject.NSAppTransportSecurity = ats;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* The app's entitlements: the template, the plugins' additions, and
|
|
485
|
+
* aps-environment only when notifications are on. A push entitlement
|
|
486
|
+
* nobody uses makes App Store Connect warn and needs a push-enabled
|
|
487
|
+
* profile for nothing. The value follows the signing profile (see
|
|
488
|
+
* planIosSigning): "development", or "production" for a manually signed
|
|
489
|
+
* release.
|
|
490
|
+
*/
|
|
381
491
|
async function updateEntitlements(pluginComposition = {}) {
|
|
382
492
|
const PROJECT_NAME = ctx.PROJECT_NAME;
|
|
383
493
|
const entitlementsPath = path.join(PROJECT_DIR, PROJECT_NAME, `${PROJECT_NAME}.entitlements`); // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
|
|
384
494
|
if (!fs.existsSync(entitlementsPath)) return;
|
|
385
495
|
restoreManagedFileFromBaseline(entitlementsPath);
|
|
386
496
|
const entitlementsObject = readPlistObject(entitlementsPath);
|
|
497
|
+
// A baseline saved by an older Catalyst still has the key.
|
|
498
|
+
delete entitlementsObject["aps-environment"];
|
|
387
499
|
mergeIntoTopLevelObject(entitlementsObject, pluginComposition.entitlements || {}, "ios.entitlements");
|
|
500
|
+
if (WEBVIEW_CONFIG.notifications?.enabled) {
|
|
501
|
+
entitlementsObject["aps-environment"] = ctx.apsEnvironment || "development";
|
|
502
|
+
}
|
|
388
503
|
writePlistObject(entitlementsPath, entitlementsObject);
|
|
389
504
|
}
|
|
390
505
|
return {
|