crossbind 2.0.0-beta.68 → 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.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/package.json +69 -59
  3. package/src/actions/addExtension.js +191 -0
  4. package/src/actions/androidGradle.js +26 -17
  5. package/src/actions/appInstaller.js +69 -153
  6. package/src/actions/appSwift.js +66 -0
  7. package/src/actions/buildApp.js +172 -74
  8. package/src/actions/buildNode.js +6 -1
  9. package/src/actions/buildWasm.js +0 -9
  10. package/src/actions/createInterface.js +17 -8
  11. package/src/actions/createLib.js +0 -4
  12. package/src/actions/extensionApi.js +298 -0
  13. package/src/actions/extensionCommands.js +41 -0
  14. package/src/actions/extensionsInApp.js +19 -0
  15. package/src/actions/gradleProject.js +196 -16
  16. package/src/actions/iosDevice.js +2 -2
  17. package/src/actions/iosSimulator.js +3 -3
  18. package/src/actions/licenses.js +83 -34
  19. package/src/actions/linuxPackages.js +48 -0
  20. package/src/actions/mavenVerification.js +37 -0
  21. package/src/actions/publish.js +220 -0
  22. package/src/actions/windowsSigning.js +1 -1
  23. package/src/actions/xcodeProject.js +49 -24
  24. package/src/actions/xcodeTargets.js +122 -0
  25. package/src/actions/xcodebuild.js +65 -0
  26. package/src/app/index.d.ts +126 -133
  27. package/src/app/index.js +126 -188
  28. package/src/assets/configure/install.sh +0 -0
  29. package/src/assets/toolchain-digests.json +20 -20
  30. package/src/bin.js +20 -28
  31. package/src/index.js +2 -1
  32. package/src/program.js +32 -3
  33. package/src/state/index.js +2 -1
  34. package/src/state/loadConfig.js +16 -5
  35. package/src/utils/appExtensions.js +761 -0
  36. package/src/utils/appFiles.js +58 -0
  37. package/src/utils/appLaunches.js +249 -0
  38. package/src/utils/appOptions.js +109 -100
  39. package/src/utils/appTargets.js +168 -0
  40. package/src/utils/bridgeTools.js +66 -0
  41. package/src/utils/configChanges.js +30 -0
  42. package/src/utils/configWriter.js +143 -26
  43. package/src/utils/extensionSteps.js +135 -0
  44. package/src/utils/openUrl.js +2 -1
  45. package/src/utils/plist.js +5 -0
  46. package/src/utils/resolveAppHost.js +7 -0
  47. package/src/utils/systemConfig.js +16 -3
  48. package/vitest.config.js +6 -1
  49. package/src/actions/appSetup.js +0 -116
  50. package/src/actions/appStoreConnect.js +0 -188
  51. package/src/actions/appUpdate.js +0 -68
  52. package/src/actions/extensions.js +0 -7
  53. package/src/actions/googlePlay.js +0 -213
  54. package/src/actions/googleSignIn.js +0 -78
  55. package/src/actions/playSetup.js +0 -19
  56. package/src/actions/publishAndroid.js +0 -102
  57. package/src/actions/publishIos.js +0 -146
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,7 +19,9 @@ export const handleFatal = (e) => {
19
19
  console.error(e);
20
20
  } else {
21
21
  let message = e?.message || String(e);
22
- if (e?.cause?.message) message += `\n caused by: ${e.cause.message.split('\n')[0]}`;
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
@@ -111,12 +113,30 @@ function listSystemKeys() {
111
113
  console.table(systemKeys);
112
114
  }
113
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
+
114
129
  async function getSystemConfig(systemKey) {
115
130
  if (!systemKey) {
116
131
  await listSystemConfig('system');
117
132
  return;
118
133
  }
119
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
+ }
120
140
  const key = systemKey.toUpperCase();
121
141
  const output = {};
122
142
  if (key in system) {
@@ -143,6 +163,15 @@ function setSystemConfig(key, value) {
143
163
  }
144
164
 
145
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
+ }
146
175
  if (!systemKeys[key]) {
147
176
  throw new Error(`Configuration ${key} is not available. Please choose from the following available configurations: ${Object.keys(systemKeys).join(', ')}`);
148
177
  }
@@ -157,7 +186,7 @@ async function listSystemConfig(type) {
157
186
  : (await import('./state/index.js')).default.config;
158
187
  if (type === 'all' || type === 'system') {
159
188
  console.log('System Configuration');
160
- console.table(systemConfig);
189
+ console.table(shownSettings(systemConfig));
161
190
  }
162
191
 
163
192
  if (type === 'all') {
@@ -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);
@@ -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 default async function loadConfig(configDir = process.cwd(), configName = 'crossbind.config') {
32
- const config = await loadJs(configDir, configName) || {};
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?.forEach(e => {
203
- e?.loadConfig?.after(newConfig);
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';