@makefully/adaptfully 5.1.0 → 5.1.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/CHANGELOG.md +13 -0
- package/docs/credentials/ios.md +4 -1
- package/docs/host.md +2 -1
- package/lib/node/apple-signing.js +18 -16
- package/lib/node/artifacts.js +13 -6
- package/lib/node/deploy.js +5 -1
- package/lib/runtime/host/_helpers.js +1 -1
- package/lib/runtime/host/car-host.js +53 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 5.1.2 — 2026-11-10
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Deploy preserveArtifacts** — `adaptfully deploy` no longer deletes `artifacts/` and `wrapfully-build.json` before packaging the prior build extract, so the IPA/AAB survives into the deploy chore.
|
|
10
|
+
- **Apple PKCS#12 export** — `apple-signing` (and iOS credential docs) export `.p12` with PBE-SHA1-3DES + SHA1 MAC so macOS `security import` accepts the passphrase.
|
|
11
|
+
|
|
12
|
+
## 5.1.1 — 2026-11-05
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`host.onEnvironment()`** — `car-host` forwards Capacitor CarGames `environment` events (`phone`, `android_auto`, `aaos`) and re-queries `getEnvironment()` on activity resume so a game can restore phone UI while Android Auto stays connected.
|
|
17
|
+
|
|
5
18
|
## 5.1.0 — 2026-11-05
|
|
6
19
|
|
|
7
20
|
### Added
|
package/docs/credentials/ios.md
CHANGED
|
@@ -104,8 +104,11 @@ Skip this if step 1 already exported `development.p12` / `distribution.p12`.
|
|
|
104
104
|
```bash
|
|
105
105
|
# From the folder that has private.key and the downloaded .cer
|
|
106
106
|
openssl x509 -in Certificates.cer -inform DER -out cert.pem -outform PEM
|
|
107
|
-
openssl pkcs12 -export -inkey private.key -in cert.pem -out development.p12
|
|
107
|
+
openssl pkcs12 -export -inkey private.key -in cert.pem -out development.p12 \
|
|
108
|
+
-keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1
|
|
108
109
|
# or distribution.p12 — use the matching kind
|
|
110
|
+
# (AES-256 / SHA-256 PKCS#12 often fails macOS `security import` with a false
|
|
111
|
+
# "wrong password?" MAC error — stick to the classic algorithms above.)
|
|
109
112
|
```
|
|
110
113
|
|
|
111
114
|
Move the `.p12` to `assets/meta/deployments/ios/apple/`.
|
package/docs/host.md
CHANGED
|
@@ -18,6 +18,7 @@ host.onPause((paused) => { /* mute / pause gameplay */ });
|
|
|
18
18
|
host.onCaptionsMuted?.((muted) => { /* … */ });
|
|
19
19
|
host.onVolume?.('music', (level) => { /* 0–1 */ });
|
|
20
20
|
host.onUxRestrictions?.((info) => { /* car only */ });
|
|
21
|
+
host.onEnvironment?.((environment) => { /* car: phone | android_auto | aaos */ });
|
|
21
22
|
|
|
22
23
|
host.setFeatures({ sound: true, captions: true });
|
|
23
24
|
host.notifyProgress(0.5, { stage: 'assets' });
|
|
@@ -77,7 +78,7 @@ Requires Capacitor packager + `platforms.<key>.carGames` (see Wrapfully README
|
|
|
77
78
|
1. Pause gameplay **and audio** when `host.onPause(true)` (activity pause, leave car display, or AAOS UX restrictions).
|
|
78
79
|
2. Do not resume audio until `onPause(false)` / parked again.
|
|
79
80
|
3. Layout for car aspect ratios (avoid heavy pillarboxing on landscape Auto).
|
|
80
|
-
4. Prefer `host.getEnvironment()` over sniffing user agents when you need Auto vs phone vs AAOS.
|
|
81
|
+
4. Prefer `host.getEnvironment()` / `host.onEnvironment()` over sniffing user agents when you need Auto vs phone vs AAOS. `onEnvironment` fires when the activity moves between the car display and the phone, including while Android Auto stays connected. Resume also re-queries `getEnvironment()`.
|
|
81
82
|
|
|
82
83
|
Wrapfully patches the Android manifest (`CAR_LAUNCHER`, `appCategory="game"`, optional automotive feature) and installs the Cap plugin. Play Console form-factor opt-in (Android Auto + Automotive OS) remains a manual Console step.
|
|
83
84
|
|
|
@@ -156,26 +156,28 @@ export async function exportAppleP12(options) {
|
|
|
156
156
|
const pemPath = `${options.cerPath}.pem`;
|
|
157
157
|
await run(['x509', '-in', options.cerPath, '-inform', 'DER', '-out', pemPath, '-outform', 'PEM']);
|
|
158
158
|
|
|
159
|
+
// Prefer classic PBEwithSHA1And3-KeyTripleDES + SHA1 MAC. OpenSSL's newer
|
|
160
|
+
// AES-256 / SHA-256 PKCS#12 defaults often fail macOS `security import`
|
|
161
|
+
// with "MAC verification failed (wrong password?)" even when the passphrase
|
|
162
|
+
// is correct.
|
|
163
|
+
const exportArgs = (certIn) => [
|
|
164
|
+
'pkcs12',
|
|
165
|
+
'-export',
|
|
166
|
+
'-inkey', options.keyPath,
|
|
167
|
+
'-in', certIn,
|
|
168
|
+
'-out', options.p12Path,
|
|
169
|
+
'-passout', `pass:${options.p12Password}`,
|
|
170
|
+
'-keypbe', 'PBE-SHA1-3DES',
|
|
171
|
+
'-certpbe', 'PBE-SHA1-3DES',
|
|
172
|
+
'-macalg', 'sha1',
|
|
173
|
+
];
|
|
174
|
+
|
|
159
175
|
try {
|
|
160
|
-
await run(
|
|
161
|
-
'pkcs12',
|
|
162
|
-
'-export',
|
|
163
|
-
'-inkey', options.keyPath,
|
|
164
|
-
'-in', pemPath,
|
|
165
|
-
'-out', options.p12Path,
|
|
166
|
-
'-passout', `pass:${options.p12Password}`,
|
|
167
|
-
]);
|
|
176
|
+
await run(exportArgs(pemPath));
|
|
168
177
|
} catch (derErr) {
|
|
169
178
|
// Some downloads are already PEM
|
|
170
179
|
try {
|
|
171
|
-
await run(
|
|
172
|
-
'pkcs12',
|
|
173
|
-
'-export',
|
|
174
|
-
'-inkey', options.keyPath,
|
|
175
|
-
'-in', options.cerPath,
|
|
176
|
-
'-out', options.p12Path,
|
|
177
|
-
'-passout', `pass:${options.p12Password}`,
|
|
178
|
-
]);
|
|
180
|
+
await run(exportArgs(options.cerPath));
|
|
179
181
|
} catch {
|
|
180
182
|
throw derErr;
|
|
181
183
|
}
|
package/lib/node/artifacts.js
CHANGED
|
@@ -38,15 +38,22 @@ export function resolveExtractRoot(outputRoot, platformKey) {
|
|
|
38
38
|
* Remove prior extract artifacts in `extractRoot` only (artifacts/, status,
|
|
39
39
|
* manifest). Does not wipe sibling platform folders under output/.
|
|
40
40
|
*
|
|
41
|
+
* Deploy packages from the prior build extract in place — pass
|
|
42
|
+
* `{ preserveArtifacts: true }` so the IPA/AAB and manifest are not deleted
|
|
43
|
+
* before `createDeployArchive` runs.
|
|
44
|
+
*
|
|
41
45
|
* @param {string} [extractRoot='output']
|
|
46
|
+
* @param {{ preserveArtifacts?: boolean }} [options]
|
|
42
47
|
*/
|
|
43
|
-
export function clearStaleBuildExtract(extractRoot = 'output') {
|
|
48
|
+
export function clearStaleBuildExtract(extractRoot = 'output', options = {}) {
|
|
44
49
|
const root = path.resolve(extractRoot);
|
|
45
|
-
const stalePaths =
|
|
46
|
-
path.join(root,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
const stalePaths = options.preserveArtifacts
|
|
51
|
+
? [path.join(root, STATUS_NAME)]
|
|
52
|
+
: [
|
|
53
|
+
path.join(root, 'artifacts'),
|
|
54
|
+
path.join(root, MANIFEST_NAME),
|
|
55
|
+
path.join(root, STATUS_NAME),
|
|
56
|
+
];
|
|
50
57
|
|
|
51
58
|
for (const stalePath of stalePaths) {
|
|
52
59
|
fs.rmSync(stalePath, { recursive: true, force: true });
|
package/lib/node/deploy.js
CHANGED
|
@@ -257,7 +257,11 @@ export async function send (
|
|
|
257
257
|
|
|
258
258
|
if (mode === 'extract') {
|
|
259
259
|
fs.mkdirSync(extractRoot, { recursive: true });
|
|
260
|
-
|
|
260
|
+
// Deploy zips from extractRoot itself; wiping artifacts/manifest here
|
|
261
|
+
// deleted the IPA before createDeployArchive could package it.
|
|
262
|
+
clearStaleBuildExtract(extractRoot, {
|
|
263
|
+
preserveArtifacts: stage === 'deploy',
|
|
264
|
+
});
|
|
261
265
|
}
|
|
262
266
|
|
|
263
267
|
let archiveStream;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Host contract (stable surface games should prefer over raw SpringRoll / Cap plugins):
|
|
7
7
|
* kind, getEnvironment(), onPause(cb), onCaptionsMuted?(cb), onVolume?(ch, cb),
|
|
8
|
-
* onUxRestrictions?(cb), setFeatures(features), notifyLoaded(), notifyProgress(p, detail?),
|
|
8
|
+
* onUxRestrictions?(cb), onEnvironment?(cb), setFeatures(features), notifyLoaded(), notifyProgress(p, detail?),
|
|
9
9
|
* notifyEndGame?(payload?), send(event, data?)
|
|
10
10
|
*/
|
|
11
11
|
(function registerHostHelpers(ns) {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Requires Wrapfully `platforms.<key>.carGames` and `@makefully/capacitor-car-games`.
|
|
6
6
|
*
|
|
7
7
|
* Maps Cap App pause/resume + CarGames UX restrictions → onPause.
|
|
8
|
+
* Forwards CarGames `environment` (and re-queries it on resume) → onEnvironment.
|
|
8
9
|
*/
|
|
9
10
|
(function registerCarHost(ns) {
|
|
10
11
|
const { helpers } = ns.host;
|
|
@@ -38,8 +39,10 @@
|
|
|
38
39
|
sfx: [],
|
|
39
40
|
};
|
|
40
41
|
const uxListeners = [];
|
|
42
|
+
const environmentListeners = [];
|
|
41
43
|
let features = null;
|
|
42
44
|
let paused = false;
|
|
45
|
+
let environment = null;
|
|
43
46
|
/** @type {Array<() => void>} */
|
|
44
47
|
const cleanups = [];
|
|
45
48
|
|
|
@@ -52,13 +55,50 @@
|
|
|
52
55
|
helpers.emit(pauseListeners, paused);
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
function emitEnvironment(next) {
|
|
59
|
+
const value = next ? String(next) : 'phone';
|
|
60
|
+
if (value === environment) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
environment = value;
|
|
64
|
+
helpers.emit(environmentListeners, value);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function readPluginEnvironment(result) {
|
|
68
|
+
if (result && typeof result === 'object' && result.environment) {
|
|
69
|
+
return String(result.environment);
|
|
70
|
+
}
|
|
71
|
+
return String(result || 'phone');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function refreshEnvironment() {
|
|
75
|
+
const car = resolveCarGamesPlugin();
|
|
76
|
+
if (!car || typeof car.getEnvironment !== 'function') {
|
|
77
|
+
emitEnvironment('phone');
|
|
78
|
+
return Promise.resolve('phone');
|
|
79
|
+
}
|
|
80
|
+
return Promise.resolve(car.getEnvironment())
|
|
81
|
+
.then((result) => {
|
|
82
|
+
const value = readPluginEnvironment(result);
|
|
83
|
+
emitEnvironment(value);
|
|
84
|
+
return value;
|
|
85
|
+
})
|
|
86
|
+
.catch(() => {
|
|
87
|
+
emitEnvironment('phone');
|
|
88
|
+
return 'phone';
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
55
92
|
function attachNativeListeners() {
|
|
56
93
|
const car = resolveCarGamesPlugin();
|
|
57
94
|
const app = resolveAppPlugin();
|
|
58
95
|
|
|
59
96
|
if (app && typeof app.addListener === 'function') {
|
|
60
97
|
const pauseHandle = app.addListener('pause', () => setPaused(true));
|
|
61
|
-
const resumeHandle = app.addListener('resume', () =>
|
|
98
|
+
const resumeHandle = app.addListener('resume', () => {
|
|
99
|
+
setPaused(false);
|
|
100
|
+
refreshEnvironment();
|
|
101
|
+
});
|
|
62
102
|
cleanups.push(() => {
|
|
63
103
|
pauseHandle?.then?.((h) => h?.remove?.());
|
|
64
104
|
pauseHandle?.remove?.();
|
|
@@ -80,6 +120,9 @@
|
|
|
80
120
|
setPaused(true);
|
|
81
121
|
}
|
|
82
122
|
});
|
|
123
|
+
const environmentHandle = car.addListener('environment', (event) => {
|
|
124
|
+
emitEnvironment(event?.environment || 'phone');
|
|
125
|
+
});
|
|
83
126
|
cleanups.push(() => {
|
|
84
127
|
pauseHandle?.then?.((h) => h?.remove?.());
|
|
85
128
|
pauseHandle?.remove?.();
|
|
@@ -88,6 +131,10 @@
|
|
|
88
131
|
uxHandle?.then?.((h) => h?.remove?.());
|
|
89
132
|
uxHandle?.remove?.();
|
|
90
133
|
});
|
|
134
|
+
cleanups.push(() => {
|
|
135
|
+
environmentHandle?.then?.((h) => h?.remove?.());
|
|
136
|
+
environmentHandle?.remove?.();
|
|
137
|
+
});
|
|
91
138
|
}
|
|
92
139
|
}
|
|
93
140
|
|
|
@@ -129,18 +176,11 @@
|
|
|
129
176
|
kind: 'car',
|
|
130
177
|
|
|
131
178
|
getEnvironment() {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return String(result.environment);
|
|
138
|
-
}
|
|
139
|
-
return String(result || 'phone');
|
|
140
|
-
})
|
|
141
|
-
.catch(() => 'phone');
|
|
142
|
-
}
|
|
143
|
-
return Promise.resolve('phone');
|
|
179
|
+
return refreshEnvironment();
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
onEnvironment(cb) {
|
|
183
|
+
return helpers.subscribe(environmentListeners, cb);
|
|
144
184
|
},
|
|
145
185
|
|
|
146
186
|
onPause(cb) {
|