@lynxship/cli 0.1.20 → 0.1.21
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 +66 -5
- package/dist/android/signing.d.ts +16 -0
- package/dist/android/signing.d.ts.map +1 -0
- package/dist/android/signing.js +131 -0
- package/dist/android/types.d.ts +12 -0
- package/dist/android/types.d.ts.map +1 -0
- package/dist/android/types.js +1 -0
- package/dist/android-build.d.ts +4 -13
- package/dist/android-build.d.ts.map +1 -1
- package/dist/android-build.js +14 -133
- package/dist/android-toolchain/inspection.d.ts +3 -0
- package/dist/android-toolchain/inspection.d.ts.map +1 -0
- package/dist/android-toolchain/inspection.js +122 -0
- package/dist/android-toolchain/probes.d.ts +23 -0
- package/dist/android-toolchain/probes.d.ts.map +1 -0
- package/dist/android-toolchain/probes.js +183 -0
- package/dist/android-toolchain/types.d.ts +20 -0
- package/dist/android-toolchain/types.d.ts.map +1 -0
- package/dist/android-toolchain/types.js +1 -0
- package/dist/android-toolchain.d.ts +4 -20
- package/dist/android-toolchain.d.ts.map +1 -1
- package/dist/android-toolchain.js +4 -300
- package/dist/app-config.d.ts +25 -0
- package/dist/app-config.d.ts.map +1 -0
- package/dist/app-config.js +106 -0
- package/dist/bundle-build.d.ts.map +1 -1
- package/dist/bundle-build.js +11 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +66 -0
- package/dist/commands/build-execution.d.ts +41 -0
- package/dist/commands/build-execution.d.ts.map +1 -0
- package/dist/commands/build-execution.js +182 -0
- package/dist/commands/configuration.d.ts +19 -0
- package/dist/commands/configuration.d.ts.map +1 -0
- package/dist/commands/configuration.js +174 -0
- package/dist/commands/development.d.ts +22 -0
- package/dist/commands/development.d.ts.map +1 -0
- package/dist/commands/development.js +132 -0
- package/dist/commands/device.d.ts +3 -0
- package/dist/commands/device.d.ts.map +1 -0
- package/dist/commands/device.js +86 -0
- package/dist/commands/doctor.d.ts +18 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +320 -0
- package/dist/commands/help.d.ts +2 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +118 -0
- package/dist/commands/i18n.d.ts +14 -0
- package/dist/commands/i18n.d.ts.map +1 -0
- package/dist/commands/i18n.js +88 -0
- package/dist/commands/logs.d.ts +3 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +51 -0
- package/dist/commands/metadata.d.ts +3 -0
- package/dist/commands/metadata.d.ts.map +1 -0
- package/dist/commands/metadata.js +45 -0
- package/dist/commands/ota.d.ts +28 -0
- package/dist/commands/ota.d.ts.map +1 -0
- package/dist/commands/ota.js +203 -0
- package/dist/commands/project.d.ts +14 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +122 -0
- package/dist/commands/remote-build.d.ts +35 -0
- package/dist/commands/remote-build.d.ts.map +1 -0
- package/dist/commands/remote-build.js +73 -0
- package/dist/commands/submit.d.ts +27 -0
- package/dist/commands/submit.d.ts.map +1 -0
- package/dist/commands/submit.js +92 -0
- package/dist/ecosystem.d.ts +9 -0
- package/dist/ecosystem.d.ts.map +1 -0
- package/dist/ecosystem.js +95 -0
- package/dist/frameworks.d.ts.map +1 -1
- package/dist/frameworks.js +5 -1
- package/dist/guidance/catalog.d.ts +3 -0
- package/dist/guidance/catalog.d.ts.map +1 -0
- package/dist/guidance/catalog.js +504 -0
- package/dist/guidance/types.d.ts +10 -0
- package/dist/guidance/types.d.ts.map +1 -0
- package/dist/guidance/types.js +1 -0
- package/dist/guidance.d.ts +2 -9
- package/dist/guidance.d.ts.map +1 -1
- package/dist/guidance.js +1 -502
- package/dist/i18n/discovery.d.ts +14 -0
- package/dist/i18n/discovery.d.ts.map +1 -0
- package/dist/i18n/discovery.js +106 -0
- package/dist/i18n/plan.d.ts +12 -0
- package/dist/i18n/plan.d.ts.map +1 -0
- package/dist/i18n/plan.js +95 -0
- package/dist/i18n/setup.d.ts +11 -0
- package/dist/i18n/setup.d.ts.map +1 -0
- package/dist/i18n/setup.js +47 -0
- package/dist/i18n/types.d.ts +17 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2069
- package/dist/ios/assets.d.ts +19 -0
- package/dist/ios/assets.d.ts.map +1 -0
- package/dist/ios/assets.js +128 -0
- package/dist/ios/production-build.d.ts +6 -0
- package/dist/ios/production-build.d.ts.map +1 -0
- package/dist/ios/production-build.js +200 -0
- package/dist/ios/project.d.ts +4 -0
- package/dist/ios/project.d.ts.map +1 -0
- package/dist/ios/project.js +43 -0
- package/dist/ios/simulator-build.d.ts +8 -0
- package/dist/ios/simulator-build.d.ts.map +1 -0
- package/dist/ios/simulator-build.js +188 -0
- package/dist/ios/simulator.d.ts +5 -0
- package/dist/ios/simulator.d.ts.map +1 -0
- package/dist/ios/simulator.js +60 -0
- package/dist/ios/types.d.ts +14 -0
- package/dist/ios/types.d.ts.map +1 -0
- package/dist/ios/types.js +1 -0
- package/dist/ios-build.d.ts +4 -37
- package/dist/ios-build.d.ts.map +1 -1
- package/dist/ios-build.js +3 -575
- package/dist/ios-host.d.ts.map +1 -1
- package/dist/ios-toolchain/inspection.d.ts +4 -0
- package/dist/ios-toolchain/inspection.d.ts.map +1 -0
- package/dist/ios-toolchain/inspection.js +211 -0
- package/dist/ios-toolchain/probes.d.ts +24 -0
- package/dist/ios-toolchain/probes.d.ts.map +1 -0
- package/dist/ios-toolchain/probes.js +127 -0
- package/dist/ios-toolchain/types.d.ts +17 -0
- package/dist/ios-toolchain/types.d.ts.map +1 -0
- package/dist/ios-toolchain/types.js +1 -0
- package/dist/ios-toolchain.d.ts +3 -18
- package/dist/ios-toolchain.d.ts.map +1 -1
- package/dist/ios-toolchain.js +1 -333
- package/dist/plugins/contracts.d.ts +28 -0
- package/dist/plugins/contracts.d.ts.map +1 -0
- package/dist/plugins/contracts.js +1 -0
- package/dist/plugins/discovery.d.ts +19 -0
- package/dist/plugins/discovery.d.ts.map +1 -0
- package/dist/plugins/discovery.js +250 -0
- package/dist/plugins/native-operations.d.ts +28 -0
- package/dist/plugins/native-operations.d.ts.map +1 -0
- package/dist/plugins/native-operations.js +217 -0
- package/dist/plugins/operations.d.ts +9 -0
- package/dist/plugins/operations.d.ts.map +1 -0
- package/dist/plugins/operations.js +76 -0
- package/dist/plugins/validation.d.ts +9 -0
- package/dist/plugins/validation.d.ts.map +1 -0
- package/dist/plugins/validation.js +52 -0
- package/dist/plugins.d.ts +3 -34
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +2 -595
- package/dist/process-runner.d.ts +4 -0
- package/dist/process-runner.d.ts.map +1 -1
- package/dist/process-runner.js +14 -0
- package/dist/remote.d.ts +22 -1
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +141 -2
- package/dist/rspeedy-app-config.d.ts +4 -0
- package/dist/rspeedy-app-config.d.ts.map +1 -0
- package/dist/rspeedy-app-config.js +32 -0
- package/dist/runtime/args.d.ts +3 -0
- package/dist/runtime/args.d.ts.map +1 -0
- package/dist/runtime/args.js +11 -0
- package/dist/runtime/build-commands.d.ts +3 -0
- package/dist/runtime/build-commands.d.ts.map +1 -0
- package/dist/runtime/build-commands.js +282 -0
- package/dist/runtime/context.d.ts +63 -0
- package/dist/runtime/context.d.ts.map +1 -0
- package/dist/runtime/context.js +179 -0
- package/dist/runtime/early-commands.d.ts +4 -0
- package/dist/runtime/early-commands.d.ts.map +1 -0
- package/dist/runtime/early-commands.js +284 -0
- package/dist/runtime/project.d.ts +8 -0
- package/dist/runtime/project.d.ts.map +1 -0
- package/dist/runtime/project.js +38 -0
- package/dist/runtime/state.d.ts +47 -0
- package/dist/runtime/state.d.ts.map +1 -0
- package/dist/runtime/state.js +33 -0
- package/dist/secure-store/backends.d.ts +20 -0
- package/dist/secure-store/backends.d.ts.map +1 -0
- package/dist/secure-store/backends.js +248 -0
- package/dist/secure-store/types.d.ts +27 -0
- package/dist/secure-store/types.d.ts.map +1 -0
- package/dist/secure-store/types.js +1 -0
- package/dist/secure-store.d.ts +2 -26
- package/dist/secure-store.d.ts.map +1 -1
- package/dist/secure-store.js +3 -245
- package/package.json +7 -4
- package/templates/android-host/app/build.gradle +1 -0
- package/templates/android-host/app/src/main/java/template/MainActivity.java +98 -3
- package/templates/ios-host/__IOS_TARGET_NAME__/DemoLynxProvider.swift +26 -16
- package/templates/ios-host/__IOS_TARGET_NAME__/ViewController.swift +107 -19
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { platform } from "node:os";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { captureProcess, commandExists } from "../process-runner.js";
|
|
5
|
+
import { check, commandOutput, findHost, hasValidProvisioningProfile, projectFlag, probeCommand, probeProject, probeVersion, setting, } from "./probes.js";
|
|
6
|
+
export async function inspectIosToolchain(root, profile, target = "device") {
|
|
7
|
+
const checks = [];
|
|
8
|
+
const isMac = platform() === "darwin";
|
|
9
|
+
const host = findHost(root, profile);
|
|
10
|
+
const hostExists = Boolean(host && existsSync(host));
|
|
11
|
+
const scheme = profile.ios?.scheme;
|
|
12
|
+
const simulator = target === "simulator";
|
|
13
|
+
const exportOptions = profile.ios?.exportOptionsPlist
|
|
14
|
+
? resolve(root, profile.ios.exportOptionsPlist)
|
|
15
|
+
: undefined;
|
|
16
|
+
checks.push(check("ios-platform", isMac ? "pass" : "fail", isMac
|
|
17
|
+
? "macOS"
|
|
18
|
+
: `${platform()} · macOS is required for an iOS ${simulator ? "Simulator app" : "IPA"}`, isMac
|
|
19
|
+
? undefined
|
|
20
|
+
: "Run the iOS build on a macOS machine or macOS CI runner"));
|
|
21
|
+
if (!isMac) {
|
|
22
|
+
checks.push(check("ios-host", "warn", hostExists
|
|
23
|
+
? "host found but not inspectable on this OS"
|
|
24
|
+
: "not inspected"));
|
|
25
|
+
return {
|
|
26
|
+
ok: checks.every((item) => item.status !== "fail"),
|
|
27
|
+
checks,
|
|
28
|
+
project: host,
|
|
29
|
+
scheme,
|
|
30
|
+
automaticSigning: false,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const developerDirectory = await probeVersion("xcode-select", ["-p"], root);
|
|
34
|
+
checks.push(check("xcode-select", developerDirectory ? "pass" : "fail", developerDirectory ?? "no active Xcode developer directory", developerDirectory
|
|
35
|
+
? undefined
|
|
36
|
+
: "sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer"));
|
|
37
|
+
const xcodeVersion = await probeVersion("xcodebuild", ["-version"], root);
|
|
38
|
+
checks.push(check("xcode", xcodeVersion ? "pass" : "fail", xcodeVersion ?? "xcodebuild unavailable", xcodeVersion
|
|
39
|
+
? undefined
|
|
40
|
+
: "Install Xcode, open it once, accept its license, then run xcode-select --install if needed"));
|
|
41
|
+
checks.push(check("xcrun", commandExists("xcrun") ? "pass" : "fail", commandExists("xcrun") ? "available" : "missing", commandExists("xcrun")
|
|
42
|
+
? undefined
|
|
43
|
+
: "Install Xcode and select its command-line tools"));
|
|
44
|
+
checks.push(check("codesign", commandExists("codesign") ? "pass" : "fail", commandExists("codesign") ? "available" : "missing", commandExists("codesign")
|
|
45
|
+
? undefined
|
|
46
|
+
: "Install Xcode command-line tools"));
|
|
47
|
+
checks.push(check("unzip", commandExists("unzip") ? "pass" : "fail", commandExists("unzip") ? "available" : "missing", commandExists("unzip")
|
|
48
|
+
? undefined
|
|
49
|
+
: "Install the macOS command-line tools"));
|
|
50
|
+
checks.push(check("ios-host", hostExists ? "pass" : "fail", hostExists ? host : "Xcode project or workspace not found", hostExists
|
|
51
|
+
? undefined
|
|
52
|
+
: "lynxship ios host init --bundle-identifier com.example.myapp"));
|
|
53
|
+
checks.push(check("ios-scheme", scheme ? "pass" : "fail", scheme ?? "missing from the selected build profile", scheme ? undefined : "Set ios.scheme in the selected build profile"));
|
|
54
|
+
const context = await probeProject(root, {
|
|
55
|
+
path: hostExists ? host : undefined,
|
|
56
|
+
flag: host ? projectFlag(host) : "-project",
|
|
57
|
+
scheme,
|
|
58
|
+
}, profile, target);
|
|
59
|
+
const settingsOutput = context.settings
|
|
60
|
+
? commandOutput(context.settings)
|
|
61
|
+
: "";
|
|
62
|
+
checks.push(check("xcode-project-settings", !context.settings
|
|
63
|
+
? "warn"
|
|
64
|
+
: context.settings.code === 0
|
|
65
|
+
? "pass"
|
|
66
|
+
: "fail", !context.settings
|
|
67
|
+
? "not inspected until host and scheme are configured"
|
|
68
|
+
: context.settings.code === 0
|
|
69
|
+
? "scheme and configuration load successfully"
|
|
70
|
+
: "xcodebuild could not load the selected scheme", context.settings?.code === 0 || !context.settings
|
|
71
|
+
? undefined
|
|
72
|
+
: "Open the project in Xcode and verify the scheme is shared and buildable"));
|
|
73
|
+
const automaticSigning = setting(settingsOutput, "CODE_SIGN_STYLE") === "Automatic";
|
|
74
|
+
const team = setting(settingsOutput, "DEVELOPMENT_TEAM");
|
|
75
|
+
checks.push(check("apple-team", simulator
|
|
76
|
+
? "pass"
|
|
77
|
+
: context.settings?.code !== 0 || !context.settings
|
|
78
|
+
? "warn"
|
|
79
|
+
: team
|
|
80
|
+
? "pass"
|
|
81
|
+
: "fail", simulator
|
|
82
|
+
? "not required for iOS Simulator"
|
|
83
|
+
: (team ?? "team not resolved from Xcode build settings"), simulator || team
|
|
84
|
+
? undefined
|
|
85
|
+
: "Select the Apple Developer Team in Xcode Signing & Capabilities"));
|
|
86
|
+
const distribution = profile.distribution ?? profile.ios?.distribution ?? "store";
|
|
87
|
+
const identityResult = simulator
|
|
88
|
+
? undefined
|
|
89
|
+
: await (commandExists("security")
|
|
90
|
+
? captureProcess("security", ["find-identity", "-v", "-p", "codesigning"], {
|
|
91
|
+
cwd: root,
|
|
92
|
+
})
|
|
93
|
+
: undefined);
|
|
94
|
+
const identityOutput = identityResult ? commandOutput(identityResult) : "";
|
|
95
|
+
const identityCount = Number(identityOutput.match(/(\d+) valid identities found/)?.[1] ?? 0);
|
|
96
|
+
const requiredIdentity = distribution === "store" ? "Apple Distribution" : "Apple Development";
|
|
97
|
+
checks.push(check("apple-signing-identity", simulator
|
|
98
|
+
? "pass"
|
|
99
|
+
: identityCount === 0 || !identityOutput.includes(requiredIdentity)
|
|
100
|
+
? "fail"
|
|
101
|
+
: "pass", simulator
|
|
102
|
+
? "not required for iOS Simulator"
|
|
103
|
+
: identityCount === 0
|
|
104
|
+
? "no valid code-signing identity found"
|
|
105
|
+
: identityOutput.includes(requiredIdentity)
|
|
106
|
+
? `${requiredIdentity} identity available`
|
|
107
|
+
: `${requiredIdentity} identity not found`, simulator ||
|
|
108
|
+
(identityCount > 0 && identityOutput.includes(requiredIdentity))
|
|
109
|
+
? undefined
|
|
110
|
+
: "Install or select the Apple certificate in Xcode Settings > Accounts, then rerun doctor"));
|
|
111
|
+
const podfile = join(root, "ios", "Podfile");
|
|
112
|
+
const podRequired = existsSync(podfile);
|
|
113
|
+
const podVersion = podRequired
|
|
114
|
+
? await probeVersion("pod", ["--version"], root)
|
|
115
|
+
: undefined;
|
|
116
|
+
checks.push(check("cocoapods", !podRequired || podVersion ? "pass" : "fail", !podRequired
|
|
117
|
+
? "not required · no ios/Podfile"
|
|
118
|
+
: (podVersion ?? "Podfile found but pod is unavailable"), !podRequired || podVersion
|
|
119
|
+
? undefined
|
|
120
|
+
: "gem install cocoapods, then run pod install in the project"));
|
|
121
|
+
let exportOptionsContent;
|
|
122
|
+
if (exportOptions && existsSync(exportOptions)) {
|
|
123
|
+
try {
|
|
124
|
+
exportOptionsContent = readFileSync(exportOptions, "utf8");
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
exportOptionsContent = undefined;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const exportMethod = exportOptionsContent?.match(/<key>method<\/key>\s*<string>([^<]+)<\/string>/)?.[1];
|
|
131
|
+
const supportedExportMethods = new Set([
|
|
132
|
+
"app-store",
|
|
133
|
+
"ad-hoc",
|
|
134
|
+
"development",
|
|
135
|
+
"enterprise",
|
|
136
|
+
]);
|
|
137
|
+
checks.push(check("export-options", simulator
|
|
138
|
+
? "pass"
|
|
139
|
+
: !exportOptions
|
|
140
|
+
? "fail"
|
|
141
|
+
: !existsSync(exportOptions)
|
|
142
|
+
? "fail"
|
|
143
|
+
: !exportMethod || !supportedExportMethods.has(exportMethod)
|
|
144
|
+
? "fail"
|
|
145
|
+
: "pass", simulator
|
|
146
|
+
? "not required for iOS Simulator"
|
|
147
|
+
: !exportOptions
|
|
148
|
+
? "missing from the production build profile"
|
|
149
|
+
: !existsSync(exportOptions)
|
|
150
|
+
? `${exportOptions} not found`
|
|
151
|
+
: exportMethod && supportedExportMethods.has(exportMethod)
|
|
152
|
+
? `method: ${exportMethod}`
|
|
153
|
+
: "method missing or invalid for an iOS export", simulator ||
|
|
154
|
+
(exportOptions &&
|
|
155
|
+
existsSync(exportOptions) &&
|
|
156
|
+
exportMethod &&
|
|
157
|
+
supportedExportMethods.has(exportMethod))
|
|
158
|
+
? undefined
|
|
159
|
+
: "Set build.production.ios.exportOptionsPlist to a valid ExportOptions.plist"));
|
|
160
|
+
const manualProvisioning = setting(settingsOutput, "CODE_SIGN_STYLE") === "Manual" ||
|
|
161
|
+
exportOptionsContent?.includes("<key>provisioningProfiles</key>") === true;
|
|
162
|
+
const profilesAvailable = await hasValidProvisioningProfile(root, setting(settingsOutput, "PRODUCT_BUNDLE_IDENTIFIER"));
|
|
163
|
+
checks.push(check("ios-provisioning", simulator
|
|
164
|
+
? "pass"
|
|
165
|
+
: manualProvisioning && !profilesAvailable
|
|
166
|
+
? "fail"
|
|
167
|
+
: automaticSigning && !profilesAvailable
|
|
168
|
+
? "warn"
|
|
169
|
+
: "pass", simulator
|
|
170
|
+
? "not required for iOS Simulator"
|
|
171
|
+
: manualProvisioning && !profilesAvailable
|
|
172
|
+
? "manual signing selected but no local provisioning profile was found"
|
|
173
|
+
: automaticSigning && !profilesAvailable
|
|
174
|
+
? "Xcode-managed provisioning will be requested during the build"
|
|
175
|
+
: profilesAvailable
|
|
176
|
+
? "local provisioning profile available"
|
|
177
|
+
: "not required by the detected signing mode", simulator || !(manualProvisioning && !profilesAvailable)
|
|
178
|
+
? undefined
|
|
179
|
+
: "Download a matching .mobileprovision/.provisionprofile from Apple Developer and install it in Xcode"));
|
|
180
|
+
const simctlAvailable = await probeCommand("xcrun", ["--find", "simctl"], root);
|
|
181
|
+
const devicectlAvailable = await probeCommand("xcrun", ["--find", "devicectl"], root);
|
|
182
|
+
checks.push(check("ios-device-tools", simctlAvailable || devicectlAvailable ? "pass" : "warn", simctlAvailable && devicectlAvailable
|
|
183
|
+
? "simctl and devicectl available"
|
|
184
|
+
: simctlAvailable
|
|
185
|
+
? "simctl available · devicectl unavailable"
|
|
186
|
+
: devicectlAvailable
|
|
187
|
+
? "devicectl available · simctl unavailable"
|
|
188
|
+
: "simctl and devicectl unavailable", simctlAvailable || devicectlAvailable
|
|
189
|
+
? undefined
|
|
190
|
+
: "Install the full Xcode toolchain, then rerun lynxship doctor --platform ios"));
|
|
191
|
+
if (simulator) {
|
|
192
|
+
const runtimeResult = await (commandExists("xcrun")
|
|
193
|
+
? captureProcess("xcrun", ["simctl", "list", "runtimes"], { cwd: root })
|
|
194
|
+
: undefined);
|
|
195
|
+
const runtimeOutput = runtimeResult ? commandOutput(runtimeResult) : "";
|
|
196
|
+
const hasRuntime = /iOS\s+[0-9]/.test(runtimeOutput);
|
|
197
|
+
checks.push(check("ios-simulator-runtime", hasRuntime ? "pass" : "fail", hasRuntime
|
|
198
|
+
? "iOS Simulator runtime available"
|
|
199
|
+
: "no iOS Simulator runtime found", hasRuntime
|
|
200
|
+
? undefined
|
|
201
|
+
: "Open Xcode > Settings > Components and install an iOS Simulator runtime"));
|
|
202
|
+
}
|
|
203
|
+
const failures = checks.filter((item) => item.status === "fail");
|
|
204
|
+
return {
|
|
205
|
+
ok: failures.length === 0,
|
|
206
|
+
checks,
|
|
207
|
+
project: host,
|
|
208
|
+
scheme,
|
|
209
|
+
automaticSigning,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IosBuildTarget, IosToolchainCheck, IosToolchainStatus } from "./types.js";
|
|
2
|
+
import type { BuildProfile } from "../config.js";
|
|
3
|
+
import { type CapturedProcessResult } from "../process-runner.js";
|
|
4
|
+
interface ProjectContext {
|
|
5
|
+
path?: string;
|
|
6
|
+
flag: "-workspace" | "-project";
|
|
7
|
+
scheme?: string;
|
|
8
|
+
settings?: CapturedProcessResult;
|
|
9
|
+
}
|
|
10
|
+
export declare function check(name: string, status: IosToolchainStatus, value: string, fix?: string): IosToolchainCheck;
|
|
11
|
+
export declare function findHost(root: string, profile: BuildProfile): string | undefined;
|
|
12
|
+
export declare function projectFlag(path: string): "-workspace" | "-project";
|
|
13
|
+
export declare function commandOutput(result: CapturedProcessResult): string;
|
|
14
|
+
export declare function setting(output: string, name: string): string | undefined;
|
|
15
|
+
export declare function provisioningProfilesDirectory(): string;
|
|
16
|
+
export declare function provisioningProfileFiles(): string[];
|
|
17
|
+
export declare function plistValue(content: string, key: string): string | undefined;
|
|
18
|
+
export declare function validProvisioningProfile(file: string, root: string, bundleIdentifier?: string): Promise<boolean>;
|
|
19
|
+
export declare function hasValidProvisioningProfile(root: string, bundleIdentifier: string | undefined): Promise<boolean>;
|
|
20
|
+
export declare function probeProject(root: string, context: ProjectContext, profile: BuildProfile, target: IosBuildTarget): Promise<ProjectContext>;
|
|
21
|
+
export declare function probeVersion(command: string, args: string[], cwd: string): Promise<string | undefined>;
|
|
22
|
+
export declare function probeCommand(command: string, args: string[], cwd: string): Promise<boolean>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=probes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../../src/ios-toolchain/probes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAE9B,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,GAAG,UAAU,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,MAAM,GACX,iBAAiB,CAEnB;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,GACpB,MAAM,GAAG,SAAS,CAqBpB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,CAEnE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAEnE;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD;AAED,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAQnD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,cAAc,CAAC,CAoBzB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,OAAO,CAAC,CAOlB"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { captureProcess, commandExists, } from "../process-runner.js";
|
|
5
|
+
export function check(name, status, value, fix) {
|
|
6
|
+
return { name, status, ok: status !== "fail", value, fix };
|
|
7
|
+
}
|
|
8
|
+
export function findHost(root, profile) {
|
|
9
|
+
const configured = profile.ios?.workspace ?? profile.ios?.project;
|
|
10
|
+
if (configured) {
|
|
11
|
+
const configuredPath = resolve(root, configured);
|
|
12
|
+
if (configuredPath.endsWith(".xcodeproj")) {
|
|
13
|
+
const workspace = configuredPath.replace(/\.xcodeproj$/, ".xcworkspace");
|
|
14
|
+
if (existsSync(workspace))
|
|
15
|
+
return workspace;
|
|
16
|
+
}
|
|
17
|
+
return configuredPath;
|
|
18
|
+
}
|
|
19
|
+
for (const directory of ["ios", "macos"]) {
|
|
20
|
+
try {
|
|
21
|
+
const candidate = readdirSync(join(root, directory)).find((name) => name.endsWith(".xcworkspace") || name.endsWith(".xcodeproj"));
|
|
22
|
+
if (candidate)
|
|
23
|
+
return join(root, directory, candidate);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// A native host is optional until an iOS build is requested.
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
export function projectFlag(path) {
|
|
32
|
+
return path.endsWith(".xcworkspace") ? "-workspace" : "-project";
|
|
33
|
+
}
|
|
34
|
+
export function commandOutput(result) {
|
|
35
|
+
return `${result.stdout}\n${result.stderr}`.trim();
|
|
36
|
+
}
|
|
37
|
+
export function setting(output, name) {
|
|
38
|
+
return output.match(new RegExp(`^${name}\\s*=\\s*(.+)$`, "m"))?.[1]?.trim();
|
|
39
|
+
}
|
|
40
|
+
export function provisioningProfilesDirectory() {
|
|
41
|
+
return join(homedir(), "Library", "MobileDevice", "Provisioning Profiles");
|
|
42
|
+
}
|
|
43
|
+
export function provisioningProfileFiles() {
|
|
44
|
+
try {
|
|
45
|
+
return readdirSync(provisioningProfilesDirectory())
|
|
46
|
+
.filter((name) => /\.(?:mobileprovision|provisionprofile)$/.test(name))
|
|
47
|
+
.map((name) => join(provisioningProfilesDirectory(), name));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function plistValue(content, key) {
|
|
54
|
+
return content.match(new RegExp(`<key>${key}</key>\\s*<(?:string|date)>([^<]+)</`))?.[1];
|
|
55
|
+
}
|
|
56
|
+
export async function validProvisioningProfile(file, root, bundleIdentifier) {
|
|
57
|
+
if (!commandExists("security"))
|
|
58
|
+
return false;
|
|
59
|
+
try {
|
|
60
|
+
const decoded = await captureProcess("security", ["cms", "-D", "-i", file], { cwd: root });
|
|
61
|
+
if (decoded.code !== 0)
|
|
62
|
+
return false;
|
|
63
|
+
const content = commandOutput(decoded);
|
|
64
|
+
const expiration = plistValue(content, "ExpirationDate");
|
|
65
|
+
if (!expiration || Number.isNaN(Date.parse(expiration)))
|
|
66
|
+
return false;
|
|
67
|
+
if (Date.parse(expiration) <= Date.now())
|
|
68
|
+
return false;
|
|
69
|
+
if (!bundleIdentifier)
|
|
70
|
+
return true;
|
|
71
|
+
const applicationIdentifier = plistValue(content, "application-identifier");
|
|
72
|
+
if (!applicationIdentifier)
|
|
73
|
+
return false;
|
|
74
|
+
const profileBundle = applicationIdentifier.split(".").slice(1).join(".");
|
|
75
|
+
return profileBundle === bundleIdentifier || profileBundle === "*";
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function hasValidProvisioningProfile(root, bundleIdentifier) {
|
|
82
|
+
const files = provisioningProfileFiles();
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
if (await validProvisioningProfile(file, root, bundleIdentifier))
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
export async function probeProject(root, context, profile, target) {
|
|
90
|
+
if (!context.path || !context.scheme || !commandExists("xcodebuild"))
|
|
91
|
+
return context;
|
|
92
|
+
const configuration = profile.ios?.configuration ??
|
|
93
|
+
(target === "simulator" ? "Debug" : "Release");
|
|
94
|
+
const settings = await captureProcess("xcodebuild", [
|
|
95
|
+
context.flag,
|
|
96
|
+
context.path,
|
|
97
|
+
"-scheme",
|
|
98
|
+
context.scheme,
|
|
99
|
+
"-configuration",
|
|
100
|
+
configuration,
|
|
101
|
+
"-showBuildSettings",
|
|
102
|
+
], { cwd: root });
|
|
103
|
+
return { ...context, settings };
|
|
104
|
+
}
|
|
105
|
+
export async function probeVersion(command, args, cwd) {
|
|
106
|
+
if (!commandExists(command))
|
|
107
|
+
return undefined;
|
|
108
|
+
try {
|
|
109
|
+
const result = await captureProcess(command, args, { cwd });
|
|
110
|
+
if (result.code !== 0)
|
|
111
|
+
return undefined;
|
|
112
|
+
return commandOutput(result).split(/\r?\n/)[0]?.trim();
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export async function probeCommand(command, args, cwd) {
|
|
119
|
+
if (!commandExists(command))
|
|
120
|
+
return false;
|
|
121
|
+
try {
|
|
122
|
+
return (await captureProcess(command, args, { cwd })).code === 0;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type IosToolchainStatus = "pass" | "warn" | "fail";
|
|
2
|
+
export interface IosToolchainCheck {
|
|
3
|
+
name: string;
|
|
4
|
+
status: IosToolchainStatus;
|
|
5
|
+
ok: boolean;
|
|
6
|
+
value: string;
|
|
7
|
+
fix?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface IosToolchainReport {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
checks: IosToolchainCheck[];
|
|
12
|
+
project?: string;
|
|
13
|
+
scheme?: string;
|
|
14
|
+
automaticSigning: boolean;
|
|
15
|
+
}
|
|
16
|
+
export type IosBuildTarget = "device" | "simulator";
|
|
17
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ios-toolchain/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/ios-toolchain.d.ts
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
name: string;
|
|
5
|
-
status: IosToolchainStatus;
|
|
6
|
-
ok: boolean;
|
|
7
|
-
value: string;
|
|
8
|
-
fix?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface IosToolchainReport {
|
|
11
|
-
ok: boolean;
|
|
12
|
-
checks: IosToolchainCheck[];
|
|
13
|
-
project?: string;
|
|
14
|
-
scheme?: string;
|
|
15
|
-
automaticSigning: boolean;
|
|
16
|
-
}
|
|
17
|
-
export type IosBuildTarget = "device" | "simulator";
|
|
18
|
-
export declare function inspectIosToolchain(root: string, profile: BuildProfile, target?: IosBuildTarget): Promise<IosToolchainReport>;
|
|
1
|
+
export type { IosBuildTarget, IosToolchainCheck, IosToolchainReport, IosToolchainStatus, } from "./ios-toolchain/types.js";
|
|
2
|
+
export { inspectIosToolchain } from "./ios-toolchain/inspection.js";
|
|
3
|
+
import type { IosToolchainReport } from "./ios-toolchain/types.js";
|
|
19
4
|
export declare function formatIosToolchainFailure(report: IosToolchainReport): string;
|
|
20
5
|
//# sourceMappingURL=ios-toolchain.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ios-toolchain.d.ts","sourceRoot":"","sources":["../src/ios-toolchain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ios-toolchain.d.ts","sourceRoot":"","sources":["../src/ios-toolchain.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAQ5E"}
|