crossbind 2.0.0-beta.67 → 2.0.0-beta.69
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 +33 -24
- package/package.json +69 -59
- package/src/actions/addExtension.js +191 -0
- package/src/actions/androidGradle.js +69 -25
- package/src/actions/appInstaller.js +69 -153
- package/src/actions/appSwift.js +66 -0
- package/src/actions/appleSigning.js +32 -14
- package/src/actions/buildApp.js +229 -67
- package/src/actions/buildNode.js +6 -1
- package/src/actions/buildWasm.js +0 -9
- package/src/actions/createInterface.js +17 -8
- package/src/actions/createLib.js +5 -7
- package/src/actions/extensionApi.js +298 -0
- package/src/actions/extensionCommands.js +41 -0
- package/src/actions/extensionsInApp.js +19 -0
- package/src/actions/getCmakeParameters.js +2 -3
- package/src/actions/gradleProject.js +199 -16
- package/src/actions/iosDevice.js +200 -0
- package/src/actions/iosSimulator.js +3 -3
- package/src/actions/licenses.js +83 -34
- package/src/actions/linuxPackages.js +48 -0
- package/src/actions/mavenVerification.js +37 -0
- package/src/actions/publish.js +220 -0
- package/src/actions/uploadKey.js +134 -0
- package/src/actions/windowsSigning.js +1 -1
- package/src/actions/xcodeProject.js +63 -17
- package/src/actions/xcodeTargets.js +122 -0
- package/src/actions/xcodebuild.js +65 -0
- package/src/app/index.d.ts +126 -133
- package/src/app/index.js +126 -188
- package/src/assets/configure/install.sh +0 -0
- package/src/assets/toolchain-digests.json +20 -20
- package/src/bin.js +79 -26
- package/src/index.js +5 -1
- package/src/program.js +35 -4
- package/src/state/index.js +2 -1
- package/src/state/loadConfig.js +16 -5
- package/src/utils/appApiHeader.js +4 -0
- package/src/utils/appExtensions.js +761 -0
- package/src/utils/appFiles.js +58 -0
- package/src/utils/appLaunches.js +249 -0
- package/src/utils/appOptions.js +144 -95
- package/src/utils/appTargets.js +168 -0
- package/src/utils/ask.js +38 -0
- package/src/utils/bridgeTools.js +66 -0
- package/src/utils/configChanges.js +30 -0
- package/src/utils/configWriter.js +181 -0
- package/src/utils/extensionSteps.js +135 -0
- package/src/utils/hermes.js +24 -0
- package/src/utils/keychain.js +54 -0
- package/src/utils/openUrl.js +12 -0
- package/src/utils/password.js +34 -0
- package/src/utils/plist.js +5 -0
- package/src/utils/requiredReasonApis.js +77 -0
- package/src/utils/resolveAppHost.js +7 -0
- package/src/utils/secretFile.js +23 -0
- package/src/utils/systemConfig.js +19 -0
- package/src/utils/systemKeys.js +16 -0
- package/vitest.config.js +6 -1
- package/src/actions/appUpdate.js +0 -68
- package/src/actions/extensions.js +0 -7
package/src/program.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from './actions/cloudCommands.js';
|
|
7
7
|
import { cloudUrl } from './utils/cloudAccount.js';
|
|
8
8
|
import flattenConfigForTable from './utils/flattenConfigForTable.js';
|
|
9
|
-
import loadSystemConfig, { systemConfigPath } from './utils/systemConfig.js';
|
|
9
|
+
import loadSystemConfig, { extensionSettingsOf, systemConfigPath } from './utils/systemConfig.js';
|
|
10
10
|
import systemKeys from './utils/systemKeys.js';
|
|
11
11
|
import writeJson from './utils/writeJson.js';
|
|
12
12
|
|
|
@@ -19,10 +19,14 @@ export const handleFatal = (e) => {
|
|
|
19
19
|
console.error(e);
|
|
20
20
|
} else {
|
|
21
21
|
let message = e?.message || String(e);
|
|
22
|
-
|
|
22
|
+
// A cause the message tells already, as an extension's failed step does, is told once.
|
|
23
|
+
const cause = e?.cause?.message?.split('\n')[0];
|
|
24
|
+
if (cause && !message.includes(cause)) message += `\n caused by: ${cause}`;
|
|
23
25
|
console.error(message);
|
|
24
26
|
}
|
|
25
|
-
|
|
27
|
+
// Writes to a pipe are asynchronous, so exiting at once would cut what is still queued, such as the failed
|
|
28
|
+
// command's output run.js printed: exit after both streams have written it.
|
|
29
|
+
process.stdout.write('', () => process.stderr.write('', () => process.exit(1)));
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
export const createProgram = () => new Command()
|
|
@@ -109,12 +113,30 @@ function listSystemKeys() {
|
|
|
109
113
|
console.table(systemKeys);
|
|
110
114
|
}
|
|
111
115
|
|
|
116
|
+
// An extension's own setting, as its name and the setting's name it: demo-store.TOKEN.
|
|
117
|
+
function extensionSetting(text) {
|
|
118
|
+
const [, extension, key] = /^([a-z][a-z0-9-]*)\.([A-Za-z][A-Za-z0-9_]*)$/.exec(text) ?? [];
|
|
119
|
+
return extension ? { extension, key: key.toUpperCase() } : null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// crossbind's settings, and each extension's own by its name and the setting's.
|
|
123
|
+
function shownSettings(system) {
|
|
124
|
+
const { extensions = {}, ...settings } = system;
|
|
125
|
+
const owned = Object.keys(extensions).flatMap((name) => Object.entries(extensionSettingsOf(system, name)).map(([key, value]) => [`${name}.${key}`, value]));
|
|
126
|
+
return { ...settings, ...Object.fromEntries(owned) };
|
|
127
|
+
}
|
|
128
|
+
|
|
112
129
|
async function getSystemConfig(systemKey) {
|
|
113
130
|
if (!systemKey) {
|
|
114
131
|
await listSystemConfig('system');
|
|
115
132
|
return;
|
|
116
133
|
}
|
|
117
134
|
const system = loadSystemConfig();
|
|
135
|
+
const own = extensionSetting(systemKey);
|
|
136
|
+
if (own) {
|
|
137
|
+
console.table({ [`${own.extension}.${own.key}`]: { value: extensionSettingsOf(system, own.extension)[own.key] ?? 'undefined' } });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
118
140
|
const key = systemKey.toUpperCase();
|
|
119
141
|
const output = {};
|
|
120
142
|
if (key in system) {
|
|
@@ -141,6 +163,15 @@ function setSystemConfig(key, value) {
|
|
|
141
163
|
}
|
|
142
164
|
|
|
143
165
|
function deleteSystemConfig(key) {
|
|
166
|
+
const own = extensionSetting(key);
|
|
167
|
+
if (own) {
|
|
168
|
+
const system = loadSystemConfig();
|
|
169
|
+
const { [own.key]: deleted, ...kept } = extensionSettingsOf(system, own.extension);
|
|
170
|
+
if (deleted === undefined) throw new Error(`Configuration ${own.extension}.${own.key} is not set.`);
|
|
171
|
+
const { [own.extension]: emptied, ...others } = system.extensions;
|
|
172
|
+
writeJson(systemConfigPath(), { ...system, extensions: Object.keys(kept).length > 0 ? { ...others, [own.extension]: kept } : others });
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
144
175
|
if (!systemKeys[key]) {
|
|
145
176
|
throw new Error(`Configuration ${key} is not available. Please choose from the following available configurations: ${Object.keys(systemKeys).join(', ')}`);
|
|
146
177
|
}
|
|
@@ -155,7 +186,7 @@ async function listSystemConfig(type) {
|
|
|
155
186
|
: (await import('./state/index.js')).default.config;
|
|
156
187
|
if (type === 'all' || type === 'system') {
|
|
157
188
|
console.log('System Configuration');
|
|
158
|
-
console.table(systemConfig);
|
|
189
|
+
console.table(shownSettings(systemConfig));
|
|
159
190
|
}
|
|
160
191
|
|
|
161
192
|
if (type === 'all') {
|
package/src/state/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { findCargoModuleImportsIn, writeCargoMarker } from '../utils/cargoImport.js';
|
|
8
8
|
import { exportWasiSdkPath } from '../utils/wasiToolchain.js';
|
|
9
9
|
import loadConfig, { assertBinarySelection } from './loadConfig.js';
|
|
10
|
+
import { configChangesOf } from '../utils/configChanges.js';
|
|
10
11
|
import refreshConanDependencies from './refreshConanDependencies.js';
|
|
11
12
|
|
|
12
13
|
const cacheDir = `${process.cwd()}/.crossbind`;
|
|
@@ -25,7 +26,7 @@ await initProcessState();
|
|
|
25
26
|
|
|
26
27
|
async function initProcessState() {
|
|
27
28
|
state.cache = loadCacheState();
|
|
28
|
-
state.config = await loadConfig();
|
|
29
|
+
state.config = await loadConfig(undefined, undefined, { changes: configChangesOf() });
|
|
29
30
|
assertBinarySelection(state.config);
|
|
30
31
|
refreshConanDependencies(state.config);
|
|
31
32
|
exportWasiSdkPath(state.config.system);
|
package/src/state/loadConfig.js
CHANGED
|
@@ -14,6 +14,8 @@ import logger from '../utils/logger.js';
|
|
|
14
14
|
import { RUNTIME_ENVS } from '../utils/targets.js';
|
|
15
15
|
import { normalizeConanDependencies } from '../utils/conanDependencies.js';
|
|
16
16
|
import isSourceCmakePackage from '../utils/isSourceCmakePackage.js';
|
|
17
|
+
import { listedExtension } from '../utils/appExtensions.js';
|
|
18
|
+
import { mergePatch } from '../utils/configChanges.js';
|
|
17
19
|
// import getCmakeParameters from './getCmakeParameters.js';
|
|
18
20
|
|
|
19
21
|
// For the project being built only: dependency builds load published configs that may still set
|
|
@@ -28,8 +30,14 @@ export function assertBinarySelection(config) {
|
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
+
// The export each loaded config was filled from, as crossbind read it, which an extension's api shows.
|
|
34
|
+
const exports = new WeakMap();
|
|
35
|
+
export const exportOf = (config) => exports.get(config) ?? null;
|
|
36
|
+
|
|
37
|
+
// The project's config, with the changes a publisher makes for its build, as a JSON merge patch of the export.
|
|
38
|
+
export default async function loadConfig(configDir = process.cwd(), configName = 'crossbind.config', { changes = null } = {}) {
|
|
39
|
+
const exported = await loadJs(configDir, configName) || {};
|
|
40
|
+
const config = changes ? mergePatch(exported, changes) : exported;
|
|
33
41
|
if (config.excludedDependencies?.length) {
|
|
34
42
|
logger.info('crossbind: `excludedDependencies` in crossbind.config.js is no longer read — declare exclusions in crossbind.overrides.js as { <name>: { exclude: true } }.');
|
|
35
43
|
}
|
|
@@ -85,6 +93,7 @@ export default async function loadConfig(configDir = process.cwd(), configName =
|
|
|
85
93
|
output.paths.systemConfig = systemConfigPath();
|
|
86
94
|
output.system = loadSystemConfig();
|
|
87
95
|
|
|
96
|
+
exports.set(output, config);
|
|
88
97
|
return output;
|
|
89
98
|
}
|
|
90
99
|
|
|
@@ -135,6 +144,7 @@ export function getFilledConfig(config, options = { isDepend: false }) {
|
|
|
135
144
|
target: config.target || {},
|
|
136
145
|
// An app's identity: its bundle id, on iOS the Apple team that signs it, the name it shows and its desktop window.
|
|
137
146
|
app: config.app || {},
|
|
147
|
+
// What an app's host builds in beside its own extensions.
|
|
138
148
|
extensions: config.extensions || [],
|
|
139
149
|
package: null,
|
|
140
150
|
functions: config.functions || {},
|
|
@@ -199,9 +209,10 @@ export function getFilledConfig(config, options = { isDepend: false }) {
|
|
|
199
209
|
|
|
200
210
|
newConfig.allDependencies = flattenDependencies(newConfig.dependencies);
|
|
201
211
|
|
|
202
|
-
newConfig.extensions
|
|
203
|
-
|
|
204
|
-
});
|
|
212
|
+
if (!Array.isArray(newConfig.extensions)) throw new Error('crossbind: "extensions" must be a list of extensions, as their packages\' crossbind.extension.js gives them.');
|
|
213
|
+
newConfig.extensions = newConfig.extensions.map((extension, i) => listedExtension(extension, `extensions[${i}]`, newConfig.paths.base));
|
|
214
|
+
const twice = newConfig.extensions.find(({ name }, i) => newConfig.extensions.findIndex((other) => other.name === name) !== i);
|
|
215
|
+
if (twice) throw new Error(`crossbind: "extensions" lists two extensions named ${twice.name}.`);
|
|
205
216
|
|
|
206
217
|
if (newConfig.target.runtime !== 'mt' && newConfig.allDependencies.some((d) => d?.target?.runtime === 'mt')) {
|
|
207
218
|
newConfig.target.runtime = 'mt';
|
|
@@ -12,6 +12,10 @@ export function compilesAsApp(target) {
|
|
|
12
12
|
return state.config.target?.runtimeEnv === 'app' && runtimeEnvsOf(target.platform).includes('app');
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// What an app's own code compiles with: CROSSBIND_APP, and on iOS its debug information, from which the archive's dSYM
|
|
16
|
+
// gives App Store Connect its files and lines; Android's NDK keeps that by default.
|
|
17
|
+
export const appCompileOptions = (target) => (compilesAsApp(target) ? ['-DCROSSBIND_APP', ...(target.platform === 'ios' ? ['-g'] : [])] : []);
|
|
18
|
+
|
|
15
19
|
export function appApiHeader() {
|
|
16
20
|
const header = `${resolveAppHostRoot()}/cpp/include/crossbind/app.h`;
|
|
17
21
|
if (!fs.existsSync(header)) {
|