@makefully/adaptfully 3.10.0 → 3.11.0
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 +12 -0
- package/README.md +3 -1
- package/lib/assets/icon-background.png +0 -0
- package/lib/assets/icon-foreground.png +0 -0
- package/lib/node/archive.js +18 -2
- package/lib/node/icons.js +97 -0
- package/lib/node/index.js +11 -1
- package/lib/node/pipeline.js +26 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 3.11.0 — 2026-07-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Layered icon validation** — build/deploy/release zips always include `meta/icon-foreground.png` and `meta/icon-background.png`. When project icons are missing under `assets/meta/`, Adaptfully **warns** (does not fail) and ships packaged placeholder icons from `lib/assets/`.
|
|
10
|
+
- **`resolveMetaIcons` / `appendMetaIcons`** — exported helpers for resolving project vs placeholder icon paths.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Legacy meta packaging skips re-adding icon filenames so placeholders and project icons are not duplicated in the zip.
|
|
15
|
+
|
|
5
16
|
## 3.10.0 — 2026-07-17
|
|
6
17
|
|
|
7
18
|
### Added
|
|
@@ -13,6 +24,7 @@ All notable changes to this project are documented in this file.
|
|
|
13
24
|
|
|
14
25
|
- **Builder family defaults** — `android` / `ios` / `ios-sim` (and `-dev`) resolve to Wrapfully family **`capacitor`**. Explicit `packager: "cordova"` still selects Cordova for that platform. Composite `cordova` / `apple` routes are not used.
|
|
15
26
|
- **`resolveBuildSpec`** includes `socialLogin: boolean`.
|
|
27
|
+
- **Single-target Wrapfully POSTs** go to the target route (`/android/build`, `/ios/release`, …) instead of the family route (`/capacitor/...`), so OS relay and existing target routes keep working.
|
|
16
28
|
|
|
17
29
|
## 3.9.0 — 2026-07-15
|
|
18
30
|
|
package/README.md
CHANGED
|
@@ -363,7 +363,7 @@ mygame/
|
|
|
363
363
|
|
|
364
364
|
The selected deployment's folder is shipped as `meta/publish/` in the zip, so per-platform credential file names (`build.json`, `sftp.json`, `steam.json`, `apple.json`, `google.json`, `ms.json`, `android/`, `ms/`) live inside `assets/meta/deployments/<key>/`.
|
|
365
365
|
|
|
366
|
-
Icons (`icon-foreground.png`, `icon-background.png`) are required for mobile, desktop, and Steam builds.
|
|
366
|
+
Icons (`icon-foreground.png`, `icon-background.png`) are required for mobile, desktop, and Steam builds. If either file is missing from `assets/meta/`, Adaptfully **warns** and ships packaged placeholder icons for that build so Wrapfully can still run.
|
|
367
367
|
|
|
368
368
|
### Icons
|
|
369
369
|
|
|
@@ -378,6 +378,8 @@ The build server composites the foreground over the background, applies a bindin
|
|
|
378
378
|
|
|
379
379
|
**Recommended format:** 1536×1536 pixel square PNGs for both files. Images with other dimensions are scaled to 1536×1536 automatically, but matching the target size produces the sharpest results.
|
|
380
380
|
|
|
381
|
+
Missing icons do not fail the Adaptfully client: check the `WARNING missing layered icon(s)` log line and replace the placeholders before a store release.
|
|
382
|
+
|
|
381
383
|
## Configuration
|
|
382
384
|
|
|
383
385
|
Build settings are read from `package.json`. The client merges any `wrapfully.json` fields into `package.json`'s `config` object before sending.
|
|
Binary file
|
|
Binary file
|
package/lib/node/archive.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import archiver from 'archiver';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { appendMetaIcons, isMetaIconFilename, META_DIR } from './icons.js';
|
|
4
5
|
|
|
5
6
|
const
|
|
6
|
-
META_DIR = 'assets/meta',
|
|
7
7
|
DEPLOYMENTS_DIRNAME = 'deployments',
|
|
8
8
|
PUBLISH_DIRNAME = 'publish';
|
|
9
9
|
|
|
@@ -38,6 +38,9 @@ function appendMeta(zip, publishDir, deploymentDirs = [], options = {}) {
|
|
|
38
38
|
log = options.log ?? (() => {}),
|
|
39
39
|
metaDir = path.resolve(META_DIR);
|
|
40
40
|
|
|
41
|
+
// Always ship layered icons (project files or Adaptfully placeholders).
|
|
42
|
+
appendMetaIcons(zip, { metaDir, log });
|
|
43
|
+
|
|
41
44
|
if (!fs.existsSync(metaDir)) {
|
|
42
45
|
log(`adaptfully: meta dir missing at ${metaDir}; skipping credentials`);
|
|
43
46
|
return;
|
|
@@ -46,7 +49,17 @@ function appendMeta(zip, publishDir, deploymentDirs = [], options = {}) {
|
|
|
46
49
|
const deploymentsRoot = path.join(metaDir, DEPLOYMENTS_DIRNAME);
|
|
47
50
|
|
|
48
51
|
if (!fs.existsSync(deploymentsRoot)) {
|
|
49
|
-
|
|
52
|
+
for (const entry of fs.readdirSync(metaDir, { withFileTypes: true })) {
|
|
53
|
+
if (isMetaIconFilename(entry.name)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const fullPath = path.join(metaDir, entry.name);
|
|
57
|
+
if (entry.isDirectory()) {
|
|
58
|
+
appendDirectory(zip, fullPath, `meta/${entry.name}`);
|
|
59
|
+
} else {
|
|
60
|
+
zip.file(fullPath, { name: `meta/${entry.name}` });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
50
63
|
return;
|
|
51
64
|
}
|
|
52
65
|
|
|
@@ -54,6 +67,9 @@ function appendMeta(zip, publishDir, deploymentDirs = [], options = {}) {
|
|
|
54
67
|
if (entry.name === DEPLOYMENTS_DIRNAME || entry.name === PUBLISH_DIRNAME) {
|
|
55
68
|
continue;
|
|
56
69
|
}
|
|
70
|
+
if (isMetaIconFilename(entry.name)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
57
73
|
|
|
58
74
|
const fullPath = path.join(metaDir, entry.name);
|
|
59
75
|
if (entry.isDirectory()) {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getPackageRoot } from './paths.js';
|
|
4
|
+
|
|
5
|
+
export const META_DIR = 'assets/meta';
|
|
6
|
+
export const ICON_FOREGROUND = 'icon-foreground.png';
|
|
7
|
+
export const ICON_BACKGROUND = 'icon-background.png';
|
|
8
|
+
|
|
9
|
+
const ICON_FILES = [ICON_FOREGROUND, ICON_BACKGROUND];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Absolute path to a packaged Adaptfully placeholder icon.
|
|
13
|
+
* @param {string} filename
|
|
14
|
+
*/
|
|
15
|
+
export function resolvePlaceholderIconPath(filename) {
|
|
16
|
+
return path.join(getPackageRoot(), 'lib', 'assets', filename);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} [metaDir=META_DIR]
|
|
21
|
+
*/
|
|
22
|
+
export function resolveMetaIconPaths(metaDir = META_DIR) {
|
|
23
|
+
const root = path.resolve(metaDir);
|
|
24
|
+
return {
|
|
25
|
+
metaDir: root,
|
|
26
|
+
foreground: path.join(root, ICON_FOREGROUND),
|
|
27
|
+
background: path.join(root, ICON_BACKGROUND),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolve layered icon paths for Wrapfully packaging. Warns (does not throw) when
|
|
33
|
+
* project icons are missing and falls back to Adaptfully placeholders.
|
|
34
|
+
*
|
|
35
|
+
* @param {{ metaDir?: string, log?: (message: string) => void }} [options]
|
|
36
|
+
* @returns {{
|
|
37
|
+
* metaDir: string,
|
|
38
|
+
* foreground: string,
|
|
39
|
+
* background: string,
|
|
40
|
+
* missing: string[],
|
|
41
|
+
* usedPlaceholders: boolean,
|
|
42
|
+
* }}
|
|
43
|
+
*/
|
|
44
|
+
export function resolveMetaIcons(options = {}) {
|
|
45
|
+
const log = options.log ?? console.log;
|
|
46
|
+
const { metaDir, foreground, background } = resolveMetaIconPaths(options.metaDir);
|
|
47
|
+
/** @type {string[]} */
|
|
48
|
+
const missing = [];
|
|
49
|
+
let resolvedForeground = foreground;
|
|
50
|
+
let resolvedBackground = background;
|
|
51
|
+
|
|
52
|
+
if (!fs.existsSync(foreground)) {
|
|
53
|
+
missing.push(ICON_FOREGROUND);
|
|
54
|
+
resolvedForeground = resolvePlaceholderIconPath(ICON_FOREGROUND);
|
|
55
|
+
}
|
|
56
|
+
if (!fs.existsSync(background)) {
|
|
57
|
+
missing.push(ICON_BACKGROUND);
|
|
58
|
+
resolvedBackground = resolvePlaceholderIconPath(ICON_BACKGROUND);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (missing.length > 0) {
|
|
62
|
+
log(
|
|
63
|
+
`adaptfully: WARNING missing layered icon(s) in ${metaDir}: ${missing.join(', ')}. `
|
|
64
|
+
+ 'Using Adaptfully placeholder icons for this build.',
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
metaDir,
|
|
70
|
+
foreground: resolvedForeground,
|
|
71
|
+
background: resolvedBackground,
|
|
72
|
+
missing,
|
|
73
|
+
usedPlaceholders: missing.length > 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Append layered icons to a zip under meta/. Uses project icons when present;
|
|
79
|
+
* otherwise warns and ships Adaptfully placeholders.
|
|
80
|
+
*
|
|
81
|
+
* @param {import('archiver').Archiver} zip
|
|
82
|
+
* @param {{ metaDir?: string, log?: (message: string) => void }} [options]
|
|
83
|
+
* @returns {ReturnType<typeof resolveMetaIcons>}
|
|
84
|
+
*/
|
|
85
|
+
export function appendMetaIcons(zip, options = {}) {
|
|
86
|
+
const resolved = resolveMetaIcons(options);
|
|
87
|
+
zip.file(resolved.foreground, { name: `meta/${ICON_FOREGROUND}` });
|
|
88
|
+
zip.file(resolved.background, { name: `meta/${ICON_BACKGROUND}` });
|
|
89
|
+
return resolved;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {string} name
|
|
94
|
+
*/
|
|
95
|
+
export function isMetaIconFilename(name) {
|
|
96
|
+
return ICON_FILES.includes(name);
|
|
97
|
+
}
|
package/lib/node/index.js
CHANGED
|
@@ -2,7 +2,17 @@ export { buildOutputDir, clearStaleBuildExtract, resolveBuildArtifactDir } from
|
|
|
2
2
|
export { createArchive, createDeployArchive, createReleaseArchive, createSourceArchive } from './archive.js';
|
|
3
3
|
export { loadProjectConfig, resolveServerUrl } from './config.js';
|
|
4
4
|
export { send } from './deploy.js';
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
appendMetaIcons,
|
|
7
|
+
ICON_BACKGROUND,
|
|
8
|
+
ICON_FOREGROUND,
|
|
9
|
+
isMetaIconFilename,
|
|
10
|
+
META_DIR,
|
|
11
|
+
resolveMetaIconPaths,
|
|
12
|
+
resolveMetaIcons,
|
|
13
|
+
resolvePlaceholderIconPath,
|
|
14
|
+
} from './icons.js';
|
|
15
|
+
export { adaptfullyFromCli, parseStageArgs, resolveWrapfullyRoute, runAdaptfullyStage } from './pipeline.js';
|
|
6
16
|
export { prebuildPlatform, prebuildOutputDir, resolveHtmlInjections } from './prebuild.js';
|
|
7
17
|
export { getPackageRoot, getRuntimeDir, resolveRuntimeScript } from './paths.js';
|
|
8
18
|
export {
|
package/lib/node/pipeline.js
CHANGED
|
@@ -14,6 +14,21 @@ import { steamAuthFromCli } from './steam-auth.js';
|
|
|
14
14
|
|
|
15
15
|
const VALID_STAGES = new Set(['prebuild', 'build', 'deploy', 'release']);
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Wrapfully URL path segment for build/release.
|
|
19
|
+
* Single-target platforms post to the target route (`android`, `ios`, …) so OS relay
|
|
20
|
+
* and long-standing target routes work; multi-target platforms post to the family
|
|
21
|
+
* (`electron`, …).
|
|
22
|
+
*
|
|
23
|
+
* @param {{ family: string, targets: string[] }} buildSpec
|
|
24
|
+
*/
|
|
25
|
+
export function resolveWrapfullyRoute(buildSpec) {
|
|
26
|
+
if (buildSpec.targets.length === 1) {
|
|
27
|
+
return buildSpec.targets[0];
|
|
28
|
+
}
|
|
29
|
+
return buildSpec.family;
|
|
30
|
+
}
|
|
31
|
+
|
|
17
32
|
/**
|
|
18
33
|
* @param {AdaptfullyStage} stage
|
|
19
34
|
* @param {string} platformKey
|
|
@@ -69,10 +84,15 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
69
84
|
/** @type {{ deploymentKey: string, stage: string, family: string }[]} */
|
|
70
85
|
const sent = [];
|
|
71
86
|
|
|
87
|
+
const wrapfullyRoute = resolveWrapfullyRoute(buildSpec);
|
|
88
|
+
|
|
72
89
|
if (stage === 'release') {
|
|
73
90
|
const deploymentDirs = deployments.map((key) => resolvePublishDir(key));
|
|
74
91
|
|
|
75
|
-
log(
|
|
92
|
+
log(
|
|
93
|
+
`adaptfully: ${stage} ${platformKey} → ${buildSpec.family} `
|
|
94
|
+
+ `(${buildSpec.targets.join(', ')}) via /${wrapfullyRoute}/release`,
|
|
95
|
+
);
|
|
76
96
|
|
|
77
97
|
log(
|
|
78
98
|
`adaptfully: release deployments → ${
|
|
@@ -85,7 +105,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
85
105
|
contents,
|
|
86
106
|
options.server,
|
|
87
107
|
'release',
|
|
88
|
-
|
|
108
|
+
wrapfullyRoute,
|
|
89
109
|
prebuiltDir,
|
|
90
110
|
pkg,
|
|
91
111
|
options.mode ?? 'extract',
|
|
@@ -107,7 +127,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
107
127
|
log(
|
|
108
128
|
`adaptfully: ${stage} ${platformKey} → `
|
|
109
129
|
+ `${deploymentKey === 'zip' ? 'artifact zip' : `deployment "${deploymentKey}"`} `
|
|
110
|
-
+ `via Wrapfully ${buildSpec.family}`,
|
|
130
|
+
+ `via Wrapfully /${wrapfullyRoute}/${wrapStage} (${buildSpec.family})`,
|
|
111
131
|
);
|
|
112
132
|
|
|
113
133
|
await send(
|
|
@@ -115,7 +135,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
115
135
|
contents,
|
|
116
136
|
options.server,
|
|
117
137
|
wrapStage,
|
|
118
|
-
|
|
138
|
+
wrapfullyRoute,
|
|
119
139
|
prebuiltDir,
|
|
120
140
|
pkg,
|
|
121
141
|
options.mode ?? 'extract',
|
|
@@ -158,9 +178,9 @@ export async function adaptfullyFromCli(argv = process.argv) {
|
|
|
158
178
|
+ '\n'
|
|
159
179
|
+ 'Stages:\n'
|
|
160
180
|
+ ' prebuild Copy deploy/ and apply platform registrations → output/<platform>-prebuild/\n'
|
|
161
|
-
+ ' build prebuild + POST /{family}/build (zip artifact only)\n'
|
|
181
|
+
+ ' build prebuild + POST /{target|family}/build (zip artifact only)\n'
|
|
162
182
|
+ ' deploy POST /deploy/{key} with prior artifact + deployment credentials\n'
|
|
163
|
-
+ ' release prebuild + POST /{family}/release (build + configured deployments)\n'
|
|
183
|
+
+ ' release prebuild + POST /{target|family}/release (build + configured deployments)\n'
|
|
164
184
|
+ '\n'
|
|
165
185
|
+ ' --deployment <key> Target a single named deployment.\n'
|
|
166
186
|
+ ' --artifact <path> Prior build artifact directory (deploy only; default: ./output/ after build).\n'
|