@mpgd/cli 0.66.0 → 0.68.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/dist/app-store-release-asc.d.ts +39 -0
- package/dist/app-store-release-asc.js +274 -0
- package/dist/app-store-release-command.d.ts +73 -0
- package/dist/app-store-release-command.js +280 -0
- package/dist/app-store-release-port.d.ts +168 -0
- package/dist/app-store-release-port.js +24 -0
- package/dist/app-store-release.d.ts +238 -0
- package/dist/app-store-release.js +1246 -0
- package/dist/asc-session.d.ts +6 -2
- package/dist/asc-session.js +12 -3
- package/dist/index.d.ts +5 -0
- package/dist/index.js +289 -2
- package/dist/native-build-info.json +2 -2
- package/dist/native-build-target.js +7 -4
- package/dist/native-deploy-submission.d.ts +11 -0
- package/dist/native-deploy-submission.js +26 -2
- package/dist/native-deploy-workflow.js +9 -2
- package/dist/play-release-options.d.ts +11 -0
- package/dist/play-release-options.js +40 -14
- package/dist/store-presence-app-store.js +6 -4
- package/dist/store-products-app-store.js +3 -3
- package/dist/testflight-distribution-asc.d.ts +35 -0
- package/dist/testflight-distribution-asc.js +170 -0
- package/dist/testflight-distribution-port.d.ts +73 -0
- package/dist/testflight-distribution-port.js +6 -0
- package/dist/testflight-distribution.d.ts +162 -0
- package/dist/testflight-distribution.js +642 -0
- package/dist/testflight-submission.d.ts +11 -0
- package/dist/testflight-submission.js +20 -1
- package/package.json +16 -16
- package/templates/phaser-game/src/i18n/messages.ts +9 -0
- package/templates/phaser-game/src/scenes/PlayScene.ts +61 -5
|
@@ -275,7 +275,8 @@ async function submitVerifiedIosBuildResolved(input, run, { marketingVersion, bu
|
|
|
275
275
|
let membershipFailure;
|
|
276
276
|
try {
|
|
277
277
|
const memberships = await run(['testflight', 'groups', 'list', '--build-id', build.id, '--internal'], lookupTimeoutMs);
|
|
278
|
-
if (
|
|
278
|
+
if (readBuildGroupMembership(memberships, build.id).some((group) => group.id === input.internalGroupId
|
|
279
|
+
&& group.type === 'internal')) {
|
|
279
280
|
return { ...base, status: 'testflight-ready', ...uploadReference, buildId: build.id };
|
|
280
281
|
}
|
|
281
282
|
}
|
|
@@ -405,6 +406,24 @@ function findInternalGroup(response, groupId) {
|
|
|
405
406
|
&& value.type === 'betaGroups' && value.id === groupId
|
|
406
407
|
&& isRecord(value.attributes) && value.attributes.isInternalGroup === true);
|
|
407
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* asc 5.5.0 prints `testflight groups list --build-id` as its own membership
|
|
411
|
+
* result, not as App Store Connect resources:
|
|
412
|
+
* `{ buildId, appId, complete, groups: [{ id, name, type, membership }] }`
|
|
413
|
+
* (`internal/cli/testflight/build_group_membership.go`). An incomplete lookup
|
|
414
|
+
* is never read as "not a member".
|
|
415
|
+
*/
|
|
416
|
+
export function readBuildGroupMembership(response, buildId) {
|
|
417
|
+
if (!isRecord(response) || response.buildId !== buildId || !Array.isArray(response.groups)
|
|
418
|
+
|| response.groups.some((group) => !isRecord(group) || typeof group.id !== 'string'
|
|
419
|
+
|| group.id === '' || typeof group.type !== 'string')) {
|
|
420
|
+
throw new Error('asc testflight groups list --build-id returned an invalid membership result.');
|
|
421
|
+
}
|
|
422
|
+
if (response.complete !== true) {
|
|
423
|
+
throw new Error('asc could not read every TestFlight group of the build.');
|
|
424
|
+
}
|
|
425
|
+
return response.groups;
|
|
426
|
+
}
|
|
408
427
|
function readDataArray(response, command) {
|
|
409
428
|
if (!isRecord(response) || !Array.isArray(response.data)) {
|
|
410
429
|
throw new Error(`asc ${command} returned an invalid JSON schema.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
4
4
|
"description": "Gunshi CLI for mpgd-kit starter generation and target workflow orchestration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -70,10 +70,10 @@
|
|
|
70
70
|
"parse5": "7.3.0",
|
|
71
71
|
"postcss": "8.5.28",
|
|
72
72
|
"postcss-value-parser": "4.2.0",
|
|
73
|
-
"@mpgd/catalog": "0.
|
|
73
|
+
"@mpgd/catalog": "0.15.0",
|
|
74
|
+
"@mpgd/target-config": "0.24.7",
|
|
74
75
|
"@mpgd/phaser-assets": "0.9.1",
|
|
75
|
-
"@mpgd/platform": "0.
|
|
76
|
-
"@mpgd/target-config": "0.24.5"
|
|
76
|
+
"@mpgd/platform": "0.35.0"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@types/node": "^24.0.0",
|
|
@@ -81,19 +81,19 @@
|
|
|
81
81
|
"@types/yauzl": "3.4.0",
|
|
82
82
|
"ttsc": "0.34.2",
|
|
83
83
|
"typescript": "7.0.2",
|
|
84
|
-
"@mpgd/adapter-ait": "0.21.
|
|
85
|
-
"@mpgd/adapter-
|
|
86
|
-
"@mpgd/adapter-
|
|
87
|
-
"@mpgd/adapter-devvit": "0.14.
|
|
88
|
-
"@mpgd/
|
|
89
|
-
"@mpgd/bridge": "0.18.
|
|
90
|
-
"@mpgd/capacitor-play-billing": "0.6.
|
|
91
|
-
"@mpgd/
|
|
92
|
-
"@mpgd/
|
|
93
|
-
"@mpgd/
|
|
94
|
-
"@mpgd/game-services": "0.
|
|
84
|
+
"@mpgd/adapter-ait": "0.21.9",
|
|
85
|
+
"@mpgd/adapter-browser": "0.12.4",
|
|
86
|
+
"@mpgd/adapter-capacitor": "0.19.1",
|
|
87
|
+
"@mpgd/adapter-devvit": "0.14.11",
|
|
88
|
+
"@mpgd/analytics": "0.5.8",
|
|
89
|
+
"@mpgd/bridge": "0.18.1",
|
|
90
|
+
"@mpgd/capacitor-play-billing": "0.6.2",
|
|
91
|
+
"@mpgd/adapter-verse8": "0.7.20",
|
|
92
|
+
"@mpgd/game-runtime": "0.10.1",
|
|
93
|
+
"@mpgd/capacitor-storekit": "0.7.1",
|
|
94
|
+
"@mpgd/game-services": "0.33.1",
|
|
95
95
|
"@mpgd/lite-shell": "0.1.0",
|
|
96
|
-
"@mpgd/i18n": "0.6.
|
|
96
|
+
"@mpgd/i18n": "0.6.29"
|
|
97
97
|
},
|
|
98
98
|
"main": "./dist/index.js",
|
|
99
99
|
"types": "./dist/index.d.ts",
|
|
@@ -14,6 +14,9 @@ export type GameMessageKey =
|
|
|
14
14
|
| 'reward'
|
|
15
15
|
| 'rewardError'
|
|
16
16
|
| 'rewardPending'
|
|
17
|
+
| 'rewardNotReady'
|
|
18
|
+
| 'rewardReconciling'
|
|
19
|
+
| 'rewardHistoryFull'
|
|
17
20
|
| 'rewardUnavailable'
|
|
18
21
|
| 'analytics'
|
|
19
22
|
| 'bootError'
|
|
@@ -59,6 +62,9 @@ const messages = {
|
|
|
59
62
|
reward: 'Rewarded ad smoke: {status}',
|
|
60
63
|
rewardError: 'Rewarded ad smoke failed',
|
|
61
64
|
rewardPending: 'Press R to request a rewarded ad smoke',
|
|
65
|
+
rewardNotReady: 'Rewarded ad smoke waits for the current purchase or ad',
|
|
66
|
+
rewardReconciling: 'Rewarded ad smoke waits until an earlier result is confirmed',
|
|
67
|
+
rewardHistoryFull: 'Rewarded ad smoke is unavailable until the game restarts',
|
|
62
68
|
rewardUnavailable: 'Rewarded ads unavailable on this target',
|
|
63
69
|
analytics: 'Analytics events: {count}',
|
|
64
70
|
bootError: 'Failed to start game',
|
|
@@ -108,6 +114,9 @@ const messages = {
|
|
|
108
114
|
reward: '리워드 광고 스모크: {status}',
|
|
109
115
|
rewardError: '리워드 광고 스모크 실패',
|
|
110
116
|
rewardPending: 'R 키로 리워드 광고 스모크 요청',
|
|
117
|
+
rewardNotReady: '진행 중인 구매나 광고가 끝나면 리워드 광고 스모크 요청 가능',
|
|
118
|
+
rewardReconciling: '이전 결과가 확인되면 리워드 광고 스모크 요청 가능',
|
|
119
|
+
rewardHistoryFull: '게임을 다시 시작할 때까지 리워드 광고 스모크를 사용할 수 없음',
|
|
111
120
|
rewardUnavailable: '이 타깃에서는 리워드 광고를 사용할 수 없음',
|
|
112
121
|
analytics: '애널리틱스 이벤트: {count}',
|
|
113
122
|
bootError: '게임 시작 실패',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GameActionController } from '@mpgd/game-runtime/actions';
|
|
1
|
+
import type { GameActionAvailability, GameActionController } from '@mpgd/game-runtime/actions';
|
|
2
2
|
import { bindPhaserGameScene } from '@mpgd/game-runtime/phaser';
|
|
3
3
|
import Phaser from 'phaser';
|
|
4
4
|
|
|
@@ -21,6 +21,8 @@ export class PlayScene extends Phaser.Scene {
|
|
|
21
21
|
private analyticsText!: Phaser.GameObjects.Text;
|
|
22
22
|
private context!: StarterContext;
|
|
23
23
|
private rewardedAction: GameActionController<'rewarded-ad'> | undefined;
|
|
24
|
+
private showingNotReady = false;
|
|
25
|
+
private requesting = false;
|
|
24
26
|
private lastScore = -1;
|
|
25
27
|
private lastAnalyticsCount = -1;
|
|
26
28
|
|
|
@@ -83,19 +85,67 @@ export class PlayScene extends Phaser.Scene {
|
|
|
83
85
|
})
|
|
84
86
|
.setOrigin(0.5);
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
const actions = this.context.gameRuntime.actions;
|
|
89
|
+
this.rewardedAction = actions?.createRewardedAdController();
|
|
87
90
|
const action = this.rewardedAction;
|
|
91
|
+
// Follow the runtime's availability, so the hint changes while any purchase
|
|
92
|
+
// (one from the shop included) or ad holds the screen, without a key press.
|
|
93
|
+
this.showingNotReady = false;
|
|
94
|
+
this.requesting = false;
|
|
95
|
+
const stopAvailability = actions?.subscribeAvailability((availability) => {
|
|
96
|
+
this.showAvailability(availability);
|
|
97
|
+
});
|
|
98
|
+
if (actions !== undefined) {
|
|
99
|
+
this.showAvailability(actions.getAvailability());
|
|
100
|
+
}
|
|
88
101
|
const keyboard = this.input.keyboard;
|
|
89
102
|
const onReward = () => {
|
|
90
103
|
void this.requestRewardedAd();
|
|
91
104
|
};
|
|
92
105
|
keyboard?.on('keydown-R', onReward);
|
|
93
106
|
this.events.once('shutdown', () => {
|
|
107
|
+
stopAvailability?.();
|
|
94
108
|
action?.dispose();
|
|
95
109
|
keyboard?.off('keydown-R', onReward);
|
|
96
110
|
});
|
|
97
111
|
}
|
|
98
112
|
|
|
113
|
+
private showAvailability(availability: GameActionAvailability): void {
|
|
114
|
+
// This scene's own request makes the actions busy too; its result text
|
|
115
|
+
// follows, so only someone else's purchase or ad shows the waiting text.
|
|
116
|
+
if (!this.rewardedAdsAvailable() || this.rewardedAction === undefined || availability === 'disposed'
|
|
117
|
+
|| this.requesting) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (availability === 'ready') {
|
|
121
|
+
// Restore the hint only over the waiting text, never over a result.
|
|
122
|
+
if (this.showingNotReady) {
|
|
123
|
+
this.showingNotReady = false;
|
|
124
|
+
this.rewardText.setText(this.rewardHint());
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.showingNotReady = true;
|
|
129
|
+
// `history-full` lasts until the runtime is recreated; only `busy` ends
|
|
130
|
+
// with the other purchase or ad.
|
|
131
|
+
this.rewardText.setText(
|
|
132
|
+
t(
|
|
133
|
+
this.context.locale,
|
|
134
|
+
availability === 'history-full'
|
|
135
|
+
? 'rewardHistoryFull'
|
|
136
|
+
: availability === 'reconciliation-required'
|
|
137
|
+
? 'rewardReconciling'
|
|
138
|
+
: 'rewardNotReady',
|
|
139
|
+
),
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** A result or error replaces the waiting text for good: `ready` must not restore the hint over it. */
|
|
144
|
+
private showRewardText(text: string): void {
|
|
145
|
+
this.showingNotReady = false;
|
|
146
|
+
this.rewardText.setText(text);
|
|
147
|
+
}
|
|
148
|
+
|
|
99
149
|
override update(_time: number, delta: number): void {
|
|
100
150
|
this.state = stepStarterRunState(this.state, delta);
|
|
101
151
|
|
|
@@ -139,13 +189,15 @@ export class PlayScene extends Phaser.Scene {
|
|
|
139
189
|
const action = this.rewardedAction;
|
|
140
190
|
|
|
141
191
|
if (!this.rewardedAdsAvailable() || action === undefined) {
|
|
142
|
-
this.
|
|
192
|
+
this.showRewardText(t(this.context.locale, 'rewardUnavailable'));
|
|
143
193
|
return;
|
|
144
194
|
}
|
|
145
195
|
|
|
196
|
+
// The tap-time guard stays: availability can change before the next frame.
|
|
146
197
|
if (this.context.gameRuntime.actions?.getAvailability() !== 'ready') {
|
|
147
198
|
return;
|
|
148
199
|
}
|
|
200
|
+
this.requesting = true;
|
|
149
201
|
try {
|
|
150
202
|
const result = await action.execute({
|
|
151
203
|
placementId: rewardedPlacementId,
|
|
@@ -155,7 +207,7 @@ export class PlayScene extends Phaser.Scene {
|
|
|
155
207
|
if (action.isDisposed() || this.rewardedAction !== action) {
|
|
156
208
|
return;
|
|
157
209
|
}
|
|
158
|
-
this.
|
|
210
|
+
this.showRewardText(
|
|
159
211
|
result.claim?.granted === true
|
|
160
212
|
? t(this.context.locale, 'reward', { status: result.status })
|
|
161
213
|
: t(this.context.locale, 'rewardError'),
|
|
@@ -169,9 +221,13 @@ export class PlayScene extends Phaser.Scene {
|
|
|
169
221
|
},
|
|
170
222
|
});
|
|
171
223
|
if (!action.isDisposed() && this.rewardedAction === action) {
|
|
172
|
-
this.
|
|
224
|
+
this.showRewardText(t(this.context.locale, 'rewardError'));
|
|
173
225
|
}
|
|
174
226
|
console.error('[rewarded-ad]', error);
|
|
227
|
+
} finally {
|
|
228
|
+
if (this.rewardedAction === action) {
|
|
229
|
+
this.requesting = false;
|
|
230
|
+
}
|
|
175
231
|
}
|
|
176
232
|
}
|
|
177
233
|
}
|