@mpgd/cli 0.14.0 → 0.15.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/dist/index.js +137 -8
- package/dist/microsoft-store-starter.d.ts +28 -0
- package/dist/microsoft-store-starter.js +655 -0
- package/dist/production-target-readiness.js +3 -1
- package/package.json +8 -8
- package/templates/phaser-game/.agents/skills/release-microsoft-store/SKILL.md +60 -0
- package/templates/phaser-game/.agents/skills/release-microsoft-store/agents/openai.yaml +4 -0
- package/templates/phaser-game/.agents/skills/use-mpgd-kit/SKILL.md +45 -0
- package/templates/phaser-game/.agents/skills/use-mpgd-kit/agents/openai.yaml +4 -0
- package/templates/phaser-game/AGENTS.md +34 -0
- package/templates/phaser-game/README.md +50 -25
- package/templates/phaser-game/agent/acceptance.md +8 -0
- package/templates/phaser-game/agent/brief.md +13 -1
- package/templates/phaser-game/agent/game-manifest.json +7 -0
- package/templates/phaser-game/apps/target-ait/granite.config.ts +35 -0
- package/templates/phaser-game/apps/target-ait/index.html +15 -0
- package/templates/phaser-game/apps/target-ait/package.json +33 -0
- package/templates/phaser-game/apps/target-ait/src/main.ts +34 -0
- package/templates/phaser-game/apps/target-ait/src/styles.css +33 -0
- package/templates/phaser-game/apps/target-ait/tsconfig.json +8 -0
- package/templates/phaser-game/apps/target-ait/vite.config.ts +53 -0
- package/templates/phaser-game/docs/MPGD_KIT_WORKFLOWS.md +128 -0
- package/templates/phaser-game/gitignore +6 -0
- package/templates/phaser-game/mpgd.targets.json +9 -2
- package/templates/phaser-game/package.json +10 -10
- package/templates/phaser-game/vite.shared.ts +13 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync, } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import completion from '@gunshi/plugin-completion';
|
|
@@ -10,6 +10,7 @@ import { defaultGameAcceptanceCommandTimeoutMs, resolveGameAcceptanceReleaseMani
|
|
|
10
10
|
import { resolveGameplayE2EReportFile } from './gameplay-e2e.js';
|
|
11
11
|
import { createMicrosoftStorePackageAcceptanceRuntime, runMicrosoftStorePackageAcceptance, } from './microsoft-store-package-acceptance.js';
|
|
12
12
|
import { runMicrosoftStorePackageGeneration } from './microsoft-store-package-generation.js';
|
|
13
|
+
import { defaultMpgdKitPath, initializeMicrosoftStoreStarter, listMicrosoftStoreInitializerTemplateFiles, prepareBaseGameTemplateFile, } from './microsoft-store-starter.js';
|
|
13
14
|
import { runMicrosoftStoreSubmissionPreflight } from './microsoft-store-submission.js';
|
|
14
15
|
export { renderGameAcceptanceMarkdown, resolveGameAcceptanceReleaseManifestFile, runGameAcceptance, defaultGameAcceptanceCommandTimeoutMs, maximumGameplayE2EReportBytes, } from './game-acceptance.js';
|
|
15
16
|
export { createBrowserGameplayE2EDriver, } from './browser-gameplay-e2e.js';
|
|
@@ -25,6 +26,10 @@ const detectedKitRoot = resolveDefaultKitRoot();
|
|
|
25
26
|
const gameTemplateDir = path.resolve(packageRoot, 'templates/phaser-game');
|
|
26
27
|
const cliVersion = readPackageVersion(packageRoot);
|
|
27
28
|
const recommendedMatrixTargets = 'web,microsoft-store,verse8,ait,reddit';
|
|
29
|
+
const recommendedMatrixTargetsWithoutMicrosoftStore = recommendedMatrixTargets
|
|
30
|
+
.split(',')
|
|
31
|
+
.filter((target) => target !== 'microsoft-store')
|
|
32
|
+
.join(',');
|
|
28
33
|
const defaultDependencyVersion = `^${cliVersion}`;
|
|
29
34
|
const standaloneTemplateDependencyVersionFallbacks = {
|
|
30
35
|
// Initial-published independently from the CLI release line; package metadata wins once concrete.
|
|
@@ -189,6 +194,10 @@ const gameCommand = defineI18n({
|
|
|
189
194
|
en: 'Print files that would be generated without writing them.',
|
|
190
195
|
ko: '파일을 쓰지 않고 생성 예정 목록만 출력합니다.',
|
|
191
196
|
},
|
|
197
|
+
'microsoft-store': {
|
|
198
|
+
en: 'Include the Microsoft Store PWA target and release workflow.',
|
|
199
|
+
ko: 'Microsoft Store PWA 타깃과 출시 워크플로를 포함합니다.',
|
|
200
|
+
},
|
|
192
201
|
}),
|
|
193
202
|
args: {
|
|
194
203
|
directory: {
|
|
@@ -226,6 +235,11 @@ const gameCommand = defineI18n({
|
|
|
226
235
|
required: false,
|
|
227
236
|
description: 'Print files that would be generated without writing them.',
|
|
228
237
|
},
|
|
238
|
+
'microsoft-store': {
|
|
239
|
+
type: 'boolean',
|
|
240
|
+
required: false,
|
|
241
|
+
description: 'Include the Microsoft Store PWA target and release workflow.',
|
|
242
|
+
},
|
|
229
243
|
},
|
|
230
244
|
run: (ctx) => {
|
|
231
245
|
const positionals = readLocalPositionals(ctx.positionals, ['game', 'create']);
|
|
@@ -244,6 +258,7 @@ const gameCommand = defineI18n({
|
|
|
244
258
|
workspace: ctx.values.workspace === true,
|
|
245
259
|
...(kitPath === undefined ? {} : { kitPath }),
|
|
246
260
|
dryRun: ctx.values['dry-run'] === true,
|
|
261
|
+
microsoftStore: ctx.values['microsoft-store'] === true,
|
|
247
262
|
});
|
|
248
263
|
},
|
|
249
264
|
}),
|
|
@@ -739,6 +754,79 @@ const targetCommand = defineI18n({
|
|
|
739
754
|
ko: '타깃 출시 산출물을 빌드하고 스모크, 패키지 생성, 제출 사전 검증 및 인수 검증을 수행합니다.',
|
|
740
755
|
}),
|
|
741
756
|
subCommands: {
|
|
757
|
+
init: defineI18n({
|
|
758
|
+
name: 'init',
|
|
759
|
+
description: 'Initialize an optional target workflow in an existing game.',
|
|
760
|
+
resource: commandResource({
|
|
761
|
+
en: 'Initialize an optional target workflow in an existing game without overwriting conflicts.',
|
|
762
|
+
ko: '충돌 파일을 덮어쓰지 않고 기존 게임에 선택적 타깃 워크플로를 초기화합니다.',
|
|
763
|
+
}, {
|
|
764
|
+
target: {
|
|
765
|
+
en: 'Target to initialize. Currently supports microsoft-store.',
|
|
766
|
+
ko: '초기화할 타깃. 현재 microsoft-store를 지원합니다.',
|
|
767
|
+
},
|
|
768
|
+
game: {
|
|
769
|
+
en: 'Existing game root. Defaults to the current directory.',
|
|
770
|
+
ko: '기존 게임 루트. 기본값은 현재 디렉터리입니다.',
|
|
771
|
+
},
|
|
772
|
+
'kit-path': {
|
|
773
|
+
en: 'Default mpgd-kit path written into generated target scripts.',
|
|
774
|
+
ko: '생성되는 타깃 스크립트에 기록할 기본 mpgd-kit 경로.',
|
|
775
|
+
},
|
|
776
|
+
'dry-run': {
|
|
777
|
+
en: 'Validate and print planned file changes without writing them.',
|
|
778
|
+
ko: '파일을 쓰지 않고 예정 변경을 검증하고 출력합니다.',
|
|
779
|
+
},
|
|
780
|
+
}),
|
|
781
|
+
args: {
|
|
782
|
+
target: {
|
|
783
|
+
type: 'positional',
|
|
784
|
+
required: true,
|
|
785
|
+
description: 'Target to initialize. Currently supports microsoft-store.',
|
|
786
|
+
},
|
|
787
|
+
game: {
|
|
788
|
+
type: 'string',
|
|
789
|
+
required: false,
|
|
790
|
+
default: '.',
|
|
791
|
+
description: 'Existing game root. Defaults to the current directory.',
|
|
792
|
+
},
|
|
793
|
+
'kit-path': {
|
|
794
|
+
type: 'string',
|
|
795
|
+
required: false,
|
|
796
|
+
description: 'Default mpgd-kit path written into generated target scripts.',
|
|
797
|
+
},
|
|
798
|
+
'dry-run': {
|
|
799
|
+
type: 'boolean',
|
|
800
|
+
required: false,
|
|
801
|
+
description: 'Validate and print planned file changes without writing them.',
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
run: (ctx) => {
|
|
805
|
+
const positionals = readLocalPositionals(ctx.positionals, ['target', 'init']);
|
|
806
|
+
const requestedTarget = readRequiredPositional(positionals, 0, 'target');
|
|
807
|
+
const target = normalizeConfiguredBuildTarget(requestedTarget);
|
|
808
|
+
if (target !== 'microsoft-store') {
|
|
809
|
+
throw new Error(`Target initialization is only available for microsoft-store; received: ${requestedTarget}`);
|
|
810
|
+
}
|
|
811
|
+
const gameRoot = path.resolve(readOptionalString(ctx.values.game) ?? '.');
|
|
812
|
+
const configuredKitPath = readOptionalString(ctx.values['kit-path']);
|
|
813
|
+
const resolvedKitPath = configuredKitPath === undefined
|
|
814
|
+
? detectedKitRoot
|
|
815
|
+
: assertKitRoot(path.resolve(configuredKitPath));
|
|
816
|
+
const defaultKitPath = resolvedKitPath === undefined
|
|
817
|
+
? defaultMpgdKitPath
|
|
818
|
+
: toTemplatePath(path.relative(gameRoot, resolvedKitPath) || '.');
|
|
819
|
+
const dryRun = ctx.values['dry-run'] === true;
|
|
820
|
+
const result = initializeMicrosoftStoreStarter({
|
|
821
|
+
gameRoot,
|
|
822
|
+
templateRoot: gameTemplateDir,
|
|
823
|
+
defaultKitPath,
|
|
824
|
+
dryRun,
|
|
825
|
+
});
|
|
826
|
+
for (const file of result.changedFiles) {
|
|
827
|
+
}
|
|
828
|
+
},
|
|
829
|
+
}),
|
|
742
830
|
build: defineI18n({
|
|
743
831
|
name: 'build',
|
|
744
832
|
description: 'Build one target artifact.',
|
|
@@ -1483,17 +1571,54 @@ function createGameApp(input) {
|
|
|
1483
1571
|
workspace: input.workspace,
|
|
1484
1572
|
...(input.kitPath === undefined ? {} : { kitPath: input.kitPath }),
|
|
1485
1573
|
...(input.title === undefined ? {} : { title: input.title }),
|
|
1574
|
+
microsoftStore: input.microsoftStore,
|
|
1575
|
+
});
|
|
1576
|
+
const files = collectTemplateFiles(gameTemplateDir).flatMap((file) => {
|
|
1577
|
+
const prepared = prepareBaseGameTemplateFile({
|
|
1578
|
+
relativePath: file.relativePath,
|
|
1579
|
+
content: file.content,
|
|
1580
|
+
});
|
|
1581
|
+
return prepared === undefined
|
|
1582
|
+
? []
|
|
1583
|
+
: [{ ...file, content: renderTemplate(prepared, context) }];
|
|
1486
1584
|
});
|
|
1487
|
-
const files = collectTemplateFiles(gameTemplateDir);
|
|
1488
1585
|
if (input.dryRun) {
|
|
1489
|
-
|
|
1586
|
+
const plannedFiles = input.microsoftStore
|
|
1587
|
+
? [...files.map((file) => file.relativePath), ...listMicrosoftStoreInitializerTemplateFiles()]
|
|
1588
|
+
: files.map((file) => file.relativePath);
|
|
1589
|
+
for (const relativePath of [...new Set(plannedFiles)].sort()) {
|
|
1490
1590
|
}
|
|
1491
1591
|
return;
|
|
1492
1592
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
mkdirSync(path.dirname(
|
|
1496
|
-
|
|
1593
|
+
let createdAppDirectory = false;
|
|
1594
|
+
try {
|
|
1595
|
+
mkdirSync(path.dirname(appDir), { recursive: true });
|
|
1596
|
+
mkdirSync(appDir);
|
|
1597
|
+
createdAppDirectory = true;
|
|
1598
|
+
for (const file of files) {
|
|
1599
|
+
const outputFile = path.join(appDir, file.relativePath);
|
|
1600
|
+
mkdirSync(path.dirname(outputFile), { recursive: true });
|
|
1601
|
+
writeFileSync(outputFile, file.content);
|
|
1602
|
+
}
|
|
1603
|
+
if (input.microsoftStore) {
|
|
1604
|
+
initializeMicrosoftStoreStarter({
|
|
1605
|
+
gameRoot: appDir,
|
|
1606
|
+
templateRoot: gameTemplateDir,
|
|
1607
|
+
defaultKitPath: context.defaultKitPath,
|
|
1608
|
+
dryRun: false,
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
catch (error) {
|
|
1613
|
+
if (createdAppDirectory) {
|
|
1614
|
+
try {
|
|
1615
|
+
rmSync(appDir, { force: true, recursive: true });
|
|
1616
|
+
}
|
|
1617
|
+
catch (cleanupError) {
|
|
1618
|
+
console.warn(`Failed to clean up incomplete game directory ${appDir}: ${formatError(cleanupError)}`);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
throw error;
|
|
1497
1622
|
}
|
|
1498
1623
|
}
|
|
1499
1624
|
function assertValidGameName(name) {
|
|
@@ -1567,7 +1692,10 @@ function createTemplateContext(input) {
|
|
|
1567
1692
|
workspaceI18nBuildPrefix: input.workspace
|
|
1568
1693
|
? `pnpm --dir ${workspacePrefix} i18n:build && `
|
|
1569
1694
|
: '',
|
|
1570
|
-
defaultKitPath: kitPath === undefined ?
|
|
1695
|
+
defaultKitPath: kitPath === undefined ? defaultMpgdKitPath : workspacePrefix,
|
|
1696
|
+
recommendedMatrixTargets: input.microsoftStore
|
|
1697
|
+
? recommendedMatrixTargets
|
|
1698
|
+
: recommendedMatrixTargetsWithoutMicrosoftStore,
|
|
1571
1699
|
pnpmWorkspaceKitPackages: input.workspace
|
|
1572
1700
|
? [
|
|
1573
1701
|
` - '${workspacePrefix}/packages/*'`,
|
|
@@ -1659,6 +1787,7 @@ function renderTemplate(content, context) {
|
|
|
1659
1787
|
.replaceAll('__TSCONFIG_WORKSPACE_EXCLUDES__', context.tsconfigWorkspaceExcludes)
|
|
1660
1788
|
.replaceAll('__WORKSPACE_I18N_BUILD_PREFIX__', context.workspaceI18nBuildPrefix)
|
|
1661
1789
|
.replaceAll('__DEFAULT_KIT_PATH__', context.defaultKitPath)
|
|
1790
|
+
.replaceAll('__RECOMMENDED_MATRIX_TARGETS__', context.recommendedMatrixTargets)
|
|
1662
1791
|
.replaceAll('__PNPM_WORKSPACE_KIT_PACKAGES__', context.pnpmWorkspaceKitPackages)
|
|
1663
1792
|
.replaceAll('__PASCAL_NAME__', context.pascalName)
|
|
1664
1793
|
.replaceAll('__CAMEL_NAME__', context.camelName);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const microsoftStoreBlockStart = "<!-- mpgd:microsoft-store:start -->";
|
|
2
|
+
export declare const microsoftStoreBlockEnd = "<!-- mpgd:microsoft-store:end -->";
|
|
3
|
+
export declare const defaultMpgdKitPath = "../mpgd-kit";
|
|
4
|
+
export declare const microsoftStoreDocumentationAnchors: {
|
|
5
|
+
readonly 'README.md': '- Verse8 is a game-owned iframe web target';
|
|
6
|
+
readonly 'agent/acceptance.md': '## Verse8 Agent8 Structured Server';
|
|
7
|
+
readonly 'agent/brief.md': undefined;
|
|
8
|
+
};
|
|
9
|
+
export interface InitializeMicrosoftStoreStarterInput {
|
|
10
|
+
readonly gameRoot: string;
|
|
11
|
+
readonly templateRoot: string;
|
|
12
|
+
readonly defaultKitPath: string;
|
|
13
|
+
readonly dryRun: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface InitializeMicrosoftStoreStarterResult {
|
|
16
|
+
readonly changedFiles: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
interface MicrosoftStoreStarterApplyRuntime {
|
|
19
|
+
readonly beforeCommit?: (relativePath: string) => void;
|
|
20
|
+
readonly beforeRollbackEntry?: (relativePath: string) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function prepareBaseGameTemplateFile(input: {
|
|
23
|
+
readonly relativePath: string;
|
|
24
|
+
readonly content: string;
|
|
25
|
+
}): string | undefined;
|
|
26
|
+
export declare function listMicrosoftStoreInitializerTemplateFiles(): readonly string[];
|
|
27
|
+
export declare function initializeMicrosoftStoreStarter(input: InitializeMicrosoftStoreStarterInput, runtime?: MicrosoftStoreStarterApplyRuntime): InitializeMicrosoftStoreStarterResult;
|
|
28
|
+
export {};
|