@makefully/adaptfully 4.3.0 → 5.0.1
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 +14 -0
- package/README.md +31 -7
- package/lib/node/artifacts.js +8 -8
- package/lib/node/pipeline.js +7 -12
- package/lib/runtime/auth/google-auth.js +16 -3
- package/lib/runtime/auth/social-auth.js +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 5.0.1 — 2026-09-17
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **`google-auth`** requires `config.googleClientId` (no built-in Entanglement client id default).
|
|
10
|
+
- **`social-auth`** no longer falls back to `config.googleClientId` for Capgo `webClientId` — use `platforms.<name>.socialLogin.google.webClientId` only.
|
|
11
|
+
- Docs: browser GIS vs Capacitor Google client ids are documented as separate fan-out surfaces.
|
|
12
|
+
|
|
13
|
+
## 5.0.0 — 2026-09-11
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Breaking:** Wrapfully extracts always land in `output/<platform>/` (including single-platform `build` / `release` / `deploy`). Sequential runs no longer overwrite siblings. Deploy still falls back to a legacy flat `output/` artifact if present.
|
|
18
|
+
|
|
5
19
|
## 4.3.0 — 2026-09-11
|
|
6
20
|
|
|
7
21
|
### Added
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ adaptfully prebuild web # deploy/ → output/web-prebuild/
|
|
|
30
30
|
adaptfully build steam # Yap /yap/wrapfully chore → artifact zip
|
|
31
31
|
adaptfully deploy web --deployment web-prod # Yap deploy chore
|
|
32
32
|
adaptfully release android --encrypt # optional envelope encryption
|
|
33
|
-
adaptfully release steam,android,ios # sequential platforms;
|
|
33
|
+
adaptfully release steam,android,ios # sequential platforms; each → output/<platform>/
|
|
34
34
|
adaptfully release --platforms steam,android # same, flag form
|
|
35
35
|
adaptfully steam-publish # one-time: log in with steamcmd → assets/meta/deployments/steam/steam.json
|
|
36
36
|
```
|
|
@@ -47,7 +47,7 @@ adaptfully steam-publish # one-time: log in with steamcmd
|
|
|
47
47
|
| `android-keystore` | One-time local setup: generate debug/release keystores and write `android` `build.json` (also updates `.gitignore`) |
|
|
48
48
|
| `apple-signing` | One-time local setup: CSR → Apple `.cer` → `.p12` / provisioning profiles under `ios/apple/` (also updates `.gitignore`) |
|
|
49
49
|
|
|
50
|
-
Comma-separated platforms (or `--platforms`) run **sequentially**.
|
|
50
|
+
Comma-separated platforms (or `--platforms`) run **sequentially**. Build/deploy/release extracts always go to `output/<platform>/` so sibling results are not overwritten; only that folder’s prior `artifacts/` / status files are cleared before each extract.
|
|
51
51
|
|
|
52
52
|
**Server** means the Showfully Yap base (`SHOWFULLY_SERVER` / `wrapfully.json` `showfullyServer` or `server`), default `https://make.makefullystudios.com/`. Wrapfully workers claim chores with a separate service token.
|
|
53
53
|
|
|
@@ -136,7 +136,7 @@ Games should call `adaptfully.has('analytics')` before `get` during rollout if o
|
|
|
136
136
|
|
|
137
137
|
| Plugin key | Registration | Runtime |
|
|
138
138
|
|------------|--------------|---------|
|
|
139
|
-
| `google-auth` | `adaptfully.register('auth', adaptfully.auth.Google)` | Web
|
|
139
|
+
| `google-auth` | `adaptfully.register('auth', adaptfully.auth.Google)` | Web (Google Identity Services) |
|
|
140
140
|
| `steam-auth` | `adaptfully.register('auth', adaptfully.auth.Steam)` | Steam / Electron (via [steamworks.js](https://github.com/ceifa/steamworks.js)) |
|
|
141
141
|
| `social-auth` | `adaptfully.register('auth', adaptfully.auth.Social)` | Capacitor (via [@capgo/capacitor-social-login](https://github.com/Cap-go/capacitor-social-login)) |
|
|
142
142
|
| `dev-auth` | `adaptfully.register('auth', adaptfully.auth.Dev)` | Local / testing |
|
|
@@ -188,6 +188,13 @@ Android/iOS Wrapfully builds use the **`capacitor`** builder family. Cordova/Pho
|
|
|
188
188
|
|
|
189
189
|
**`social-auth` requires `packager: "capacitor"`** and `platforms.<name>.socialLogin` (Capgo provider client IDs). Wrapfully installs `@capgo/capacitor-social-login` when building.
|
|
190
190
|
|
|
191
|
+
Google client IDs are **not** interchangeable across plugins:
|
|
192
|
+
|
|
193
|
+
| Surface | Config | Notes |
|
|
194
|
+
|---------|--------|--------|
|
|
195
|
+
| Browser GIS (`google-auth`) | `config.googleClientId` (via your config registration / bridge) | OAuth **Web** client whose authorized JavaScript origins include the site origin |
|
|
196
|
+
| Capacitor Capgo (`social-auth`) | `platforms.<name>.socialLogin.google.webClientId` | Server / web client id for native Google Sign-In — do **not** put this in `googleClientId` |
|
|
197
|
+
|
|
191
198
|
```json
|
|
192
199
|
{
|
|
193
200
|
"config": {
|
|
@@ -220,6 +227,19 @@ Android/iOS Wrapfully builds use the **`capacitor`** builder family. Cordova/Pho
|
|
|
220
227
|
}
|
|
221
228
|
```
|
|
222
229
|
|
|
230
|
+
#### Google auth (`google-auth`)
|
|
231
|
+
|
|
232
|
+
Browser-only plugin using [Google Identity Services](https://developers.google.com/identity/oauth2/web/guides/overview) (`accounts.google.com/gsi/client`). Requires `config.googleClientId` — there is no built-in default. GIS authorized origins are **per OAuth client**; reusing `socialLogin.google.webClientId` here is a common failure mode when mobile and web need different clients.
|
|
233
|
+
|
|
234
|
+
Optional config keys:
|
|
235
|
+
|
|
236
|
+
| Key | Default | Purpose |
|
|
237
|
+
|-----|---------|---------|
|
|
238
|
+
| `googleClientId` | *(required)* | Browser GIS OAuth client id |
|
|
239
|
+
| `googleTokenKey` | `adaptfully_google_token` | `sessionStorage` key for the access token |
|
|
240
|
+
| `googleScopes` | `openid email profile` | OAuth scopes |
|
|
241
|
+
| `autoLoginStorageKey` | `lastLoggedIn` | Storage key written with the user id on login |
|
|
242
|
+
|
|
223
243
|
#### Steam auth (`steam-auth`)
|
|
224
244
|
|
|
225
245
|
When `steam-auth` is registered on an **`electron`** platform, Adaptfully prebuild writes:
|
|
@@ -242,6 +262,8 @@ The runtime plugin calls Capgo `SocialLogin.initialize` / `login` / `logout` / `
|
|
|
242
262
|
|
|
243
263
|
**Apple-only iOS** (`providers.google: false`, `providers.apple: true`) is supported — Google `webClientId` is not required. On iOS, if `apple.clientId` is omitted, Adaptfully defaults it to the platform `packageName` (Capgo uses this as a plugin label on native iOS, not an Apple Services ID). On Android, Apple Sign-In still requires `apple.clientId`. At runtime, an empty Apple `clientId` also falls back to `window.gameConfig.packageName`.
|
|
244
264
|
|
|
265
|
+
Google Sign-In on Capacitor reads **`socialLogin.google.webClientId` only** (via `social-login-config.js`). It does not fall back to `config.googleClientId`.
|
|
266
|
+
|
|
245
267
|
Optional config keys:
|
|
246
268
|
|
|
247
269
|
| Key | Default | Purpose |
|
|
@@ -283,7 +305,7 @@ import {
|
|
|
283
305
|
|
|
284
306
|
## Wrapfully deploy
|
|
285
307
|
|
|
286
|
-
After prebuild, the build and deploy stages zip `output/<platform>-prebuild/` and POST it to a Wrapfully build server. Artifacts are saved to `./output
|
|
308
|
+
After prebuild, the build and deploy stages zip `output/<platform>-prebuild/` and POST it to a Wrapfully build server. Artifacts are saved to `./output/<platform>/`.
|
|
287
309
|
|
|
288
310
|
## Quick start
|
|
289
311
|
|
|
@@ -322,7 +344,7 @@ npx adaptfully apple-publish [--deployment ios] [--category C] [--identity I] [-
|
|
|
322
344
|
|----------|---------|-------------|
|
|
323
345
|
| `platform` | — | Platform key from `config.platforms` (`web`, `steam`, etc.) |
|
|
324
346
|
| `server` | see below | Wrapfully server base URL (`build` and `deploy` only) |
|
|
325
|
-
| `mode` | `extract` | `extract` unpacks the response zip into `./output
|
|
347
|
+
| `mode` | `extract` | `extract` unpacks the response zip into `./output/<platform>/`; any other value saves `./output/<platform>/{name}-{version}-{builder}.zip` |
|
|
326
348
|
|
|
327
349
|
Examples:
|
|
328
350
|
|
|
@@ -402,7 +424,9 @@ mygame/
|
|
|
402
424
|
│ └── index.html
|
|
403
425
|
├── output/
|
|
404
426
|
│ ├── web-prebuild/ # after adaptfully prebuild web
|
|
405
|
-
│
|
|
427
|
+
│ ├── steam-prebuild/ # after adaptfully prebuild steam
|
|
428
|
+
│ ├── web/ # after adaptfully build/release web
|
|
429
|
+
│ └── steam/ # after adaptfully build/release steam
|
|
406
430
|
└── assets/
|
|
407
431
|
└── meta/ # shared files packaged as meta/ in the zip
|
|
408
432
|
├── icon-foreground.png
|
|
@@ -727,7 +751,7 @@ To sign the app, place your certificate at `assets/meta/deployments/<deployment>
|
|
|
727
751
|
|
|
728
752
|
## Response
|
|
729
753
|
|
|
730
|
-
The server responds with a zip stream containing build artifacts (`.apk`, `.aab`, `.ipa`, `.app`, `.exe`, etc.) and optional status files. By default the client extracts this into `./output
|
|
754
|
+
The server responds with a zip stream containing build artifacts (`.apk`, `.aab`, `.ipa`, `.app`, `.exe`, etc.) and optional status files. By default the client extracts this into `./output/<platform>/`. Use a non-`extract` mode value to save the raw response zip instead.
|
|
731
755
|
|
|
732
756
|
Every build also includes `wrapfully-status.json` with structured `success`, `warn`, and `error` events. The client prints these after extraction and exits with code 1 if any errors were reported, so build failures do not crash the server silently.
|
|
733
757
|
|
package/lib/node/artifacts.js
CHANGED
|
@@ -17,18 +17,17 @@ export function buildOutputDir(pkg, outputRoot = 'output') {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Where a platform's Wrapfully zip is extracted
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Where a platform's Wrapfully zip is extracted: always `output/<platformKey>/`
|
|
21
|
+
* so sequential single-platform and multi-platform runs share one layout.
|
|
22
|
+
* Without a platform key, falls back to `outputRoot`.
|
|
23
23
|
*
|
|
24
24
|
* @param {string} outputRoot
|
|
25
25
|
* @param {string} [platformKey]
|
|
26
|
-
* @param {{ multiPlatform?: boolean }} [options]
|
|
27
26
|
* @returns {string}
|
|
28
27
|
*/
|
|
29
|
-
export function resolveExtractRoot(outputRoot, platformKey
|
|
28
|
+
export function resolveExtractRoot(outputRoot, platformKey) {
|
|
30
29
|
const root = path.resolve(outputRoot);
|
|
31
|
-
if (
|
|
30
|
+
if (platformKey) {
|
|
32
31
|
return path.join(root, platformKey);
|
|
33
32
|
}
|
|
34
33
|
return root;
|
|
@@ -55,9 +54,10 @@ export function clearStaleBuildExtract(extractRoot = 'output') {
|
|
|
55
54
|
|
|
56
55
|
/**
|
|
57
56
|
* Resolve the artifact directory from a prior `adaptfully build` (or compatible zip extract).
|
|
57
|
+
* Prefers `output/<platform>/`; still accepts a legacy flat `output/` extract.
|
|
58
58
|
*
|
|
59
59
|
* @param {{ name: string, version: string, config?: { outputFolder?: string } }} pkg
|
|
60
|
-
* @param {{ outputRoot?: string, platformKey?: string
|
|
60
|
+
* @param {{ outputRoot?: string, platformKey?: string }} [options]
|
|
61
61
|
* @returns {string}
|
|
62
62
|
*/
|
|
63
63
|
export function resolveBuildArtifactDir(pkg, options = {}) {
|
|
@@ -65,7 +65,7 @@ export function resolveBuildArtifactDir(pkg, options = {}) {
|
|
|
65
65
|
const candidates = [];
|
|
66
66
|
|
|
67
67
|
if (options.platformKey) {
|
|
68
|
-
candidates.push(resolveExtractRoot(outputRoot, options.platformKey
|
|
68
|
+
candidates.push(resolveExtractRoot(outputRoot, options.platformKey));
|
|
69
69
|
}
|
|
70
70
|
candidates.push(outputRoot);
|
|
71
71
|
|
package/lib/node/pipeline.js
CHANGED
|
@@ -49,7 +49,7 @@ export function resolveWrapfullyRoute(buildSpec) {
|
|
|
49
49
|
/**
|
|
50
50
|
* @param {AdaptfullyStage} stage
|
|
51
51
|
* @param {string} platformKey
|
|
52
|
-
* @param {{ pkg: object, deployFolder: string, server?: string, mode?: string, deployment?: string, artifactPath?: string, log?: (message: string) => void, outputRoot?: string, accessToken?: string, encrypt?: boolean, encryptPublicKey?: string, wrapfullyConfig?: object, extractRoot?: string
|
|
52
|
+
* @param {{ pkg: object, deployFolder: string, server?: string, mode?: string, deployment?: string, artifactPath?: string, log?: (message: string) => void, outputRoot?: string, accessToken?: string, encrypt?: boolean, encryptPublicKey?: string, wrapfullyConfig?: object, extractRoot?: string }} options
|
|
53
53
|
*/
|
|
54
54
|
export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
55
55
|
if (!VALID_STAGES.has(stage)) {
|
|
@@ -62,7 +62,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
62
62
|
let deployments = resolveDeploymentsForPlatform(platformKey, pkg);
|
|
63
63
|
const outputRoot = buildOutputDir(pkg, options.outputRoot);
|
|
64
64
|
const extractRoot = options.extractRoot
|
|
65
|
-
?? resolveExtractRoot(outputRoot, platformKey
|
|
65
|
+
?? resolveExtractRoot(outputRoot, platformKey);
|
|
66
66
|
|
|
67
67
|
if (options.deployment) {
|
|
68
68
|
if (!deployments.includes(options.deployment)) {
|
|
@@ -85,7 +85,6 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
85
85
|
artifactPath = resolveBuildArtifactDir(pkg, {
|
|
86
86
|
outputRoot: options.outputRoot,
|
|
87
87
|
platformKey,
|
|
88
|
-
multiPlatform: options.multiPlatform,
|
|
89
88
|
});
|
|
90
89
|
}
|
|
91
90
|
|
|
@@ -198,7 +197,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
198
197
|
|
|
199
198
|
/**
|
|
200
199
|
* Run a stage for one or more platforms sequentially.
|
|
201
|
-
*
|
|
200
|
+
* Each platform extracts to `output/<platformKey>/`.
|
|
202
201
|
*
|
|
203
202
|
* @param {AdaptfullyStage} stage
|
|
204
203
|
* @param {string[]} platformKeys
|
|
@@ -206,21 +205,17 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
206
205
|
*/
|
|
207
206
|
export async function runAdaptfullyStages(stage, platformKeys, options) {
|
|
208
207
|
const log = options.log ?? console.log;
|
|
209
|
-
const multiPlatform = platformKeys.length > 1;
|
|
210
208
|
/** @type {{ platformKey: string, ok: boolean, result?: object, error?: Error }[]} */
|
|
211
209
|
const results = [];
|
|
212
210
|
|
|
213
|
-
if (
|
|
211
|
+
if (platformKeys.length > 1) {
|
|
214
212
|
log(`adaptfully: sequential ${stage} for ${platformKeys.join(', ')}`);
|
|
215
213
|
}
|
|
216
214
|
|
|
217
215
|
for (const platformKey of platformKeys) {
|
|
218
216
|
log(`adaptfully: ——— ${stage} ${platformKey} ———`);
|
|
219
217
|
try {
|
|
220
|
-
const result = await runAdaptfullyStage(stage, platformKey,
|
|
221
|
-
...options,
|
|
222
|
-
multiPlatform,
|
|
223
|
-
});
|
|
218
|
+
const result = await runAdaptfullyStage(stage, platformKey, options);
|
|
224
219
|
results.push({ platformKey, ok: true, result });
|
|
225
220
|
} catch (err) {
|
|
226
221
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -286,10 +281,10 @@ export async function adaptfullyFromCli(argv = process.argv) {
|
|
|
286
281
|
+ ' release Yap release chore (build + configured deployments)\n'
|
|
287
282
|
+ '\n'
|
|
288
283
|
+ ' Multiple platforms (comma-separated or --platforms) run sequentially.\n'
|
|
289
|
-
+ '
|
|
284
|
+
+ ' Extracts always go to output/<platform>/ so siblings are preserved.\n'
|
|
290
285
|
+ '\n'
|
|
291
286
|
+ ' --deployment <key> Target a single named deployment.\n'
|
|
292
|
-
+ ' --artifact <path> Prior build artifact directory (deploy only; default: ./output
|
|
287
|
+
+ ' --artifact <path> Prior build artifact directory (deploy only; default: ./output/<platform>/ after build).\n'
|
|
293
288
|
+ ' --encrypt Envelope-encrypt chore to Wrapfully (optional; default key embedded).\n'
|
|
294
289
|
+ ' --encrypt-public-key <pem|path> Override Wrapfully public key when encrypting.\n'
|
|
295
290
|
+ '\n'
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
(function registerGoogleAuth(ns) {
|
|
4
4
|
const { configValue, getStorage } = ns.auth.helpers;
|
|
5
5
|
|
|
6
|
-
const DEFAULT_CLIENT_ID = '225754014403.apps.googleusercontent.com';
|
|
7
6
|
const DEFAULT_SCOPES = 'openid email profile';
|
|
8
7
|
const DEFAULT_TOKEN_KEY = 'adaptfully_google_token';
|
|
9
8
|
const DEFAULT_AUTO_LOGIN_KEY = 'lastLoggedIn';
|
|
@@ -33,8 +32,13 @@
|
|
|
33
32
|
return configValue('googleTokenKey', DEFAULT_TOKEN_KEY);
|
|
34
33
|
}
|
|
35
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Browser GIS OAuth client id only (`config.googleClientId`).
|
|
37
|
+
* Capacitor / Capgo builds use `platforms.<name>.socialLogin.google.webClientId` instead.
|
|
38
|
+
*/
|
|
36
39
|
#clientId() {
|
|
37
|
-
|
|
40
|
+
const clientId = configValue('googleClientId', '');
|
|
41
|
+
return typeof clientId === 'string' ? clientId.trim() : '';
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
#scopes() {
|
|
@@ -47,8 +51,17 @@
|
|
|
47
51
|
|
|
48
52
|
whenReady(done) {
|
|
49
53
|
const setup = () => {
|
|
54
|
+
const clientId = this.#clientId();
|
|
55
|
+
if (!clientId) {
|
|
56
|
+
console.error(
|
|
57
|
+
'google-auth: config.googleClientId is required '
|
|
58
|
+
+ '(browser GIS OAuth client; do not reuse socialLogin.google.webClientId).',
|
|
59
|
+
);
|
|
60
|
+
done({ error: 'google-auth: config.googleClientId is required' });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
50
63
|
this.tokenClient = google.accounts.oauth2.initTokenClient({
|
|
51
|
-
client_id:
|
|
64
|
+
client_id: clientId,
|
|
52
65
|
scope: this.#scopes(),
|
|
53
66
|
callback: () => {},
|
|
54
67
|
});
|
|
@@ -107,9 +107,11 @@
|
|
|
107
107
|
const options = {};
|
|
108
108
|
|
|
109
109
|
if (config.providers?.google !== false) {
|
|
110
|
+
// Capgo webClientId comes only from platforms.<name>.socialLogin
|
|
111
|
+
// (written to __ADAPTFULLY_SOCIAL_LOGIN__). Do not fall back to
|
|
112
|
+
// config.googleClientId — that key is for browser google-auth / GIS.
|
|
110
113
|
options.google = {
|
|
111
|
-
webClientId: config.google?.webClientId
|
|
112
|
-
|| configValue('googleClientId', ''),
|
|
114
|
+
webClientId: config.google?.webClientId || '',
|
|
113
115
|
iOSClientId: config.google?.iOSClientId,
|
|
114
116
|
iOSServerClientId: config.google?.iOSServerClientId
|
|
115
117
|
|| config.google?.webClientId,
|