@mpgd/cli 0.26.0 → 0.28.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/build-targets.js +16 -1
- package/dist/production-target-readiness.d.ts +1 -0
- package/dist/production-target-readiness.js +20 -0
- package/package.json +12 -12
- package/templates/phaser-game/README.md +11 -2
- package/templates/phaser-game/apps/target-ait/package.json +1 -0
- package/templates/phaser-game/apps/target-ait/src/main.ts +4 -9
- package/templates/phaser-game/apps/target-ait/src/runtime-config.types.ts +12 -0
- package/templates/phaser-game/apps/target-ait/vite.config.ts +29 -7
- package/templates/phaser-game/package.json +1 -0
- package/templates/phaser-game/src/platform/runtimeDetector.ts +2 -0
- package/templates/phaser-game/vite.runtime-target-config.ts +4 -0
- package/templates/phaser-game/vite.shared.ts +10 -0
package/dist/build-targets.js
CHANGED
|
@@ -40,12 +40,16 @@ export function normalizeConfiguredBuildTargets(configuredTargets) {
|
|
|
40
40
|
}
|
|
41
41
|
function resolveBuildTarget(target, configuredTargets) {
|
|
42
42
|
const configuredWebTarget = isConfiguredWebTarget(target, configuredTargets);
|
|
43
|
-
|
|
43
|
+
const configuredMiniGameTarget = isConfiguredMiniGameTarget(target, configuredTargets);
|
|
44
|
+
if (configuredWebTarget || configuredMiniGameTarget) {
|
|
44
45
|
assertDeploymentTargetName(target);
|
|
45
46
|
}
|
|
46
47
|
if (target === 'web' && configuredWebTarget) {
|
|
47
48
|
return target;
|
|
48
49
|
}
|
|
50
|
+
if (configuredMiniGameTarget) {
|
|
51
|
+
return target;
|
|
52
|
+
}
|
|
49
53
|
const builtInTarget = normalizeBuiltInBuildTarget(target);
|
|
50
54
|
if (builtInTarget !== undefined) {
|
|
51
55
|
return builtInTarget;
|
|
@@ -55,6 +59,17 @@ function resolveBuildTarget(target, configuredTargets) {
|
|
|
55
59
|
}
|
|
56
60
|
return undefined;
|
|
57
61
|
}
|
|
62
|
+
function isConfiguredMiniGameTarget(target, configuredTargets) {
|
|
63
|
+
if (!Object.prototype.hasOwnProperty.call(configuredTargets, target)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const configuredTarget = configuredTargets[target];
|
|
67
|
+
return typeof configuredTarget === 'object'
|
|
68
|
+
&& configuredTarget !== null
|
|
69
|
+
&& !Array.isArray(configuredTarget)
|
|
70
|
+
&& 'kind' in configuredTarget
|
|
71
|
+
&& configuredTarget.kind === 'wechat-minigame';
|
|
72
|
+
}
|
|
58
73
|
function normalizeBuiltInBuildTarget(target) {
|
|
59
74
|
if (target === 'browser' || target === 'web') {
|
|
60
75
|
return 'web-preview';
|
|
@@ -5,6 +5,7 @@ export interface ProductionTargetReadinessInput {
|
|
|
5
5
|
readonly gameRoot: string;
|
|
6
6
|
readonly gameServicesUrl?: string;
|
|
7
7
|
readonly targetPolicy?: ProductionTargetPolicy;
|
|
8
|
+
readonly environment?: NodeJS.ProcessEnv;
|
|
8
9
|
}
|
|
9
10
|
export interface ProductionTargetPolicy {
|
|
10
11
|
readonly runtime: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
2
2
|
import { isIP } from 'node:net';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
const wechatStagingAppId = 'wx0000000000000000';
|
|
4
5
|
const ownerPathByTarget = {
|
|
5
6
|
ait: 'wrapperApp',
|
|
6
7
|
android: 'shellApp',
|
|
@@ -23,6 +24,7 @@ export function assertProductionTargetReadiness(input) {
|
|
|
23
24
|
if (!isRecord(targetConfig)) {
|
|
24
25
|
throw new Error(`Missing target configuration for ${input.target}.`);
|
|
25
26
|
}
|
|
27
|
+
assertExperimentalTargetReadiness(input, targetConfig);
|
|
26
28
|
const targetPolicy = targetConfig.authoritativeGameServices === false
|
|
27
29
|
? disableMonetization(input.targetPolicy)
|
|
28
30
|
: input.targetPolicy;
|
|
@@ -83,6 +85,24 @@ export function assertProductionTargetReadiness(input) {
|
|
|
83
85
|
assertAuthoritativeGameServicesUrl(input.gameServicesUrl, input.target);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
88
|
+
function assertExperimentalTargetReadiness(input, targetConfig) {
|
|
89
|
+
if (targetConfig.experimental !== true) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const environment = input.environment ?? process.env;
|
|
93
|
+
if (environment.MPGD_ALLOW_EXPERIMENTAL_TARGET !== '1') {
|
|
94
|
+
throw new Error(`Production build for experimental target ${input.target} is blocked.\n`
|
|
95
|
+
+ 'Set MPGD_ALLOW_EXPERIMENTAL_TARGET=1 only for platform validation builds.');
|
|
96
|
+
}
|
|
97
|
+
if (targetConfig.kind === 'wechat-minigame') {
|
|
98
|
+
const appId = environment.MPGD_WECHAT_APP_ID?.trim();
|
|
99
|
+
if (appId === undefined
|
|
100
|
+
|| appId === wechatStagingAppId
|
|
101
|
+
|| !/^wx[0-9a-f]{16}$/u.test(appId)) {
|
|
102
|
+
throw new Error('Production WeChat Mini Game builds require MPGD_WECHAT_APP_ID.');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
86
106
|
function disableMonetization(policy) {
|
|
87
107
|
if (policy === undefined) {
|
|
88
108
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Gunshi CLI for mpgd-kit starter generation and target workflow orchestration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,19 +52,19 @@
|
|
|
52
52
|
"@types/node": "^24.0.0",
|
|
53
53
|
"ttsc": "0.18.4",
|
|
54
54
|
"typescript": "7.0.2",
|
|
55
|
-
"@mpgd/adapter-ait": "0.
|
|
56
|
-
"@mpgd/adapter-browser": "0.7.
|
|
57
|
-
"@mpgd/adapter-capacitor": "0.4.
|
|
58
|
-
"@mpgd/adapter-devvit": "0.9.
|
|
59
|
-
"@mpgd/adapter-verse8": "0.3.
|
|
60
|
-
"@mpgd/analytics": "0.3.
|
|
55
|
+
"@mpgd/adapter-ait": "0.12.1",
|
|
56
|
+
"@mpgd/adapter-browser": "0.7.3",
|
|
57
|
+
"@mpgd/adapter-capacitor": "0.4.9",
|
|
58
|
+
"@mpgd/adapter-devvit": "0.9.6",
|
|
59
|
+
"@mpgd/adapter-verse8": "0.3.4",
|
|
60
|
+
"@mpgd/analytics": "0.3.12",
|
|
61
|
+
"@mpgd/catalog": "0.7.2",
|
|
62
|
+
"@mpgd/i18n": "0.6.0",
|
|
63
|
+
"@mpgd/game-services": "0.14.0",
|
|
61
64
|
"@mpgd/bridge": "0.9.0",
|
|
62
|
-
"@mpgd/game-services": "0.13.0",
|
|
63
|
-
"@mpgd/i18n": "0.5.6",
|
|
64
|
-
"@mpgd/catalog": "0.7.0",
|
|
65
65
|
"@mpgd/phaser-assets": "0.4.1",
|
|
66
|
-
"@mpgd/
|
|
67
|
-
"@mpgd/
|
|
66
|
+
"@mpgd/platform": "0.12.0",
|
|
67
|
+
"@mpgd/target-config": "0.14.0"
|
|
68
68
|
},
|
|
69
69
|
"main": "./dist/index.js",
|
|
70
70
|
"types": "./dist/index.d.ts",
|
|
@@ -277,13 +277,22 @@ and non-native flow checks:
|
|
|
277
277
|
```sh
|
|
278
278
|
pnpm ait:wrapper:dev
|
|
279
279
|
pnpm ait:wrapper:dev:plain
|
|
280
|
+
pnpm ait:wrapper:dev:sandbox
|
|
280
281
|
```
|
|
281
282
|
|
|
282
283
|
`ait:wrapper:dev` loads the last game bundle copied by `pnpm build:ait` from the
|
|
283
284
|
wrapper's `public/game` directory, so run `pnpm build:ait` again after game
|
|
284
285
|
changes before opening it. The local mock deliberately keeps ads, promotions,
|
|
285
|
-
and IAP unavailable
|
|
286
|
-
|
|
286
|
+
and IAP unavailable.
|
|
287
|
+
|
|
288
|
+
`ait:wrapper:dev:sandbox` disables every local bridge and identity mock so the
|
|
289
|
+
official Apps in Toss Sandbox host can inject its native SDK. Supply any
|
|
290
|
+
game-owned staging endpoints, product SKUs, and server-authority configuration
|
|
291
|
+
as environment variables before starting it. Use this route for native identity,
|
|
292
|
+
one-time IAP, and Game Center tests; it is not a normal browser preview. The
|
|
293
|
+
Sandbox does not support ads, so upload a staging `.ait` bundle and use the
|
|
294
|
+
console `intoss-private://` QR in the Toss app for test-ad and final integration
|
|
295
|
+
checks.
|
|
287
296
|
|
|
288
297
|
The starter includes `@ait-co/console-cli`, the Apps in Toss community console
|
|
289
298
|
CLI, as a dev dependency for project-local console automation:
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "MPGD_AIT_LOCAL_MOCK=1 VITE_MPGD_AIT_MOCK_IDENTITY=1 vite --host 0.0.0.0",
|
|
8
8
|
"dev:plain": "pnpm dev",
|
|
9
|
+
"dev:sandbox": "MPGD_AIT_LOCAL_MOCK=0 VITE_MPGD_AIT_MOCK_IDENTITY=0 vite --host 0.0.0.0",
|
|
9
10
|
"build": "vite build && ait build",
|
|
10
11
|
"ait:build": "ait build",
|
|
11
12
|
"ait:deploy": "ait deploy --api-key \"$AIT_API_KEY\"",
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import './styles.css';
|
|
2
2
|
|
|
3
|
-
import type { AitAdPlacementType } from '@mpgd/adapter-ait/ad-config';
|
|
4
3
|
import { installAitHostBridge, type InstallAitHostBridgeOptions } from '@mpgd/adapter-ait/host';
|
|
5
4
|
import { installAitSafeAreaCssVariables } from '@mpgd/adapter-ait/safe-area';
|
|
6
5
|
import { mountAitGameBundle } from '@mpgd/adapter-ait/wrapper';
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
declare const __MPGD_AIT_AD_GROUP_IDS__: Readonly<Record<string, string>>;
|
|
10
|
-
declare const __MPGD_AIT_AD_PLACEMENT_TYPES__: Readonly<
|
|
11
|
-
Record<string, AitAdPlacementType>
|
|
12
|
-
>;
|
|
7
|
+
import runtimeConfig from 'virtual:mpgd-ait-runtime-config';
|
|
13
8
|
|
|
14
9
|
installAitSafeAreaCssVariables();
|
|
15
10
|
installAitHostBridge({
|
|
16
|
-
appName:
|
|
17
|
-
adGroupIds:
|
|
18
|
-
adPlacementTypes:
|
|
11
|
+
appName: runtimeConfig.appName,
|
|
12
|
+
adGroupIds: runtimeConfig.adGroupIds,
|
|
13
|
+
adPlacementTypes: runtimeConfig.adPlacementTypes,
|
|
19
14
|
...identityBridgeOptions(),
|
|
20
15
|
});
|
|
21
16
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare module 'virtual:mpgd-ait-runtime-config' {
|
|
2
|
+
const runtimeConfig: Readonly<{
|
|
3
|
+
readonly appName: string;
|
|
4
|
+
readonly adGroupIds: Readonly<Record<string, string>>;
|
|
5
|
+
readonly adPlacementTypes: Readonly<Record<
|
|
6
|
+
string,
|
|
7
|
+
import('@mpgd/adapter-ait/ad-config').AitAdPlacementType
|
|
8
|
+
>>;
|
|
9
|
+
}>;
|
|
10
|
+
|
|
11
|
+
export default runtimeConfig;
|
|
12
|
+
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
type AitAdBridgeConfig,
|
|
6
6
|
} from '@mpgd/adapter-ait/ad-config';
|
|
7
7
|
import ttsc from '@ttsc/unplugin/vite';
|
|
8
|
-
import { defineConfig } from 'vite';
|
|
8
|
+
import { defineConfig, type Plugin } from 'vite';
|
|
9
9
|
|
|
10
10
|
const aitAppName = process.env.MPGD_AIT_APP_NAME?.trim() || '__GAME_NAME__';
|
|
11
11
|
const aitAdConfig = readAitAdConfig(process.env.MPGD_AD_PLACEMENTS_FILE);
|
|
@@ -16,11 +16,6 @@ export default defineConfig(({ command, isPreview }) => {
|
|
|
16
16
|
&& process.env.MPGD_AIT_LOCAL_MOCK !== '0';
|
|
17
17
|
|
|
18
18
|
return {
|
|
19
|
-
define: {
|
|
20
|
-
__MPGD_AIT_APP_NAME__: JSON.stringify(aitAppName),
|
|
21
|
-
__MPGD_AIT_AD_GROUP_IDS__: JSON.stringify(aitAdConfig.adGroupIds),
|
|
22
|
-
__MPGD_AIT_AD_PLACEMENT_TYPES__: JSON.stringify(aitAdConfig.adPlacementTypes),
|
|
23
|
-
},
|
|
24
19
|
// Browser-only local development must not pretend that native rewards or
|
|
25
20
|
// purchases are available. Production and console builds use the real SDK.
|
|
26
21
|
...(enableLocalAitMock
|
|
@@ -33,7 +28,14 @@ export default defineConfig(({ command, isPreview }) => {
|
|
|
33
28
|
}
|
|
34
29
|
: {}),
|
|
35
30
|
plugins: [
|
|
36
|
-
|
|
31
|
+
createAitRuntimeConfigPlugin({
|
|
32
|
+
appName: aitAppName,
|
|
33
|
+
adGroupIds: aitAdConfig.adGroupIds,
|
|
34
|
+
adPlacementTypes: aitAdConfig.adPlacementTypes,
|
|
35
|
+
}),
|
|
36
|
+
...(command === 'build'
|
|
37
|
+
? [ttsc({ project: 'tsconfig.json', plugins: false })]
|
|
38
|
+
: []),
|
|
37
39
|
],
|
|
38
40
|
build: {
|
|
39
41
|
target: 'es2022',
|
|
@@ -43,6 +45,26 @@ export default defineConfig(({ command, isPreview }) => {
|
|
|
43
45
|
};
|
|
44
46
|
});
|
|
45
47
|
|
|
48
|
+
function createAitRuntimeConfigPlugin(input: Readonly<{
|
|
49
|
+
readonly appName: string;
|
|
50
|
+
readonly adGroupIds: Readonly<Record<string, string>>;
|
|
51
|
+
readonly adPlacementTypes: AitAdBridgeConfig['adPlacementTypes'];
|
|
52
|
+
}>): Plugin {
|
|
53
|
+
const publicId = 'virtual:mpgd-ait-runtime-config';
|
|
54
|
+
const resolvedId = `\0${publicId}`;
|
|
55
|
+
return {
|
|
56
|
+
name: 'mpgd-ait-runtime-config',
|
|
57
|
+
resolveId(id) {
|
|
58
|
+
return id === publicId ? resolvedId : null;
|
|
59
|
+
},
|
|
60
|
+
load(id) {
|
|
61
|
+
return id === resolvedId
|
|
62
|
+
? `export default Object.freeze(${JSON.stringify(input)});\n`
|
|
63
|
+
: null;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
46
68
|
function readAitAdConfig(path: string | undefined): AitAdBridgeConfig {
|
|
47
69
|
if (path === undefined || path.trim().length === 0) {
|
|
48
70
|
return { adGroupIds: {}, adPlacementTypes: {} };
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"smoke:ait": "pnpm exec mpgd target smoke ait --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
20
20
|
"ait:wrapper:dev": "pnpm --dir apps/target-ait run dev",
|
|
21
21
|
"ait:wrapper:dev:plain": "pnpm --dir apps/target-ait run dev:plain",
|
|
22
|
+
"ait:wrapper:dev:sandbox": "pnpm --dir apps/target-ait run dev:sandbox",
|
|
22
23
|
"ait:console:login": "aitcc login",
|
|
23
24
|
"ait:console:whoami": "aitcc whoami",
|
|
24
25
|
"ait:console:init": "aitcc app init",
|
|
@@ -20,6 +20,8 @@ const runtimeKinds = valueSet({
|
|
|
20
20
|
'apps-in-toss': true,
|
|
21
21
|
'devvit-web': true,
|
|
22
22
|
'verse8-web': true,
|
|
23
|
+
'wechat-minigame': true,
|
|
24
|
+
'tiktok-minigame': true,
|
|
23
25
|
} satisfies Record<TargetRuntimeKind, true>);
|
|
24
26
|
const releaseProfiles = valueSet({
|
|
25
27
|
web: true,
|
|
@@ -30,6 +32,8 @@ const releaseProfiles = valueSet({
|
|
|
30
32
|
'apps-in-toss': true,
|
|
31
33
|
'devvit': true,
|
|
32
34
|
'verse8': true,
|
|
35
|
+
'wechat-minigame': true,
|
|
36
|
+
'tiktok-minigame': true,
|
|
33
37
|
} satisfies Record<ReleaseProfile, true>);
|
|
34
38
|
const storageSupportValues = valueSet({
|
|
35
39
|
local: true,
|
|
@@ -138,6 +138,16 @@ export function resolveBuildGatewayModule(input: {
|
|
|
138
138
|
return 'src/platform/buildGateways/verse8.ts';
|
|
139
139
|
case 'microsoft-store':
|
|
140
140
|
return 'src/platform/buildGateways/microsoftStore.ts';
|
|
141
|
+
case 'telegram':
|
|
142
|
+
case 'tauri':
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Direct APP_TARGET=${input.target} builds are unavailable until its native platform gateway is installed.`,
|
|
145
|
+
);
|
|
146
|
+
case 'wechat':
|
|
147
|
+
case 'tiktok':
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Direct APP_TARGET=${input.target} builds are unavailable until the native mini-game gateway and artifact emitter are installed.`,
|
|
150
|
+
);
|
|
141
151
|
default:
|
|
142
152
|
return 'src/platform/buildGateways/browser.ts';
|
|
143
153
|
}
|