@mpgd/cli 0.54.1 → 0.55.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.
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface DevvitSdkVersion {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly declared: string;
|
|
4
|
+
readonly installed: string;
|
|
5
|
+
readonly latest: string;
|
|
6
|
+
readonly source?: 'adapter';
|
|
7
|
+
}
|
|
8
|
+
export interface CheckDevvitSdkOptions {
|
|
9
|
+
/** Test seam. Production looks up the npm `latest` dist-tag. */
|
|
10
|
+
readonly lookupLatest?: (name: string) => Promise<string>;
|
|
11
|
+
}
|
|
12
|
+
export declare function assertLatestDevvitSdk(entries: readonly DevvitSdkVersion[]): void;
|
|
13
|
+
/** Read-only pre-upload gate. Never install a new SDK between verified build and upload. */
|
|
14
|
+
export declare function checkDevvitSdk(project: string, options?: CheckDevvitSdkOptions): Promise<readonly DevvitSdkVersion[]>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { readFile, realpath } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
const execFile = promisify(execFileCallback);
|
|
6
|
+
const stable = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u;
|
|
7
|
+
function isFirstPartyDevvitPackage(name) {
|
|
8
|
+
return name === 'devvit' || name.startsWith('@devvit/');
|
|
9
|
+
}
|
|
10
|
+
function devvitPackageNames(dependencies) {
|
|
11
|
+
return Object.keys(dependencies).filter(isFirstPartyDevvitPackage);
|
|
12
|
+
}
|
|
13
|
+
function record(value) {
|
|
14
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
15
|
+
throw new Error('Invalid package metadata.');
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
async function npmLatestStable(name, cwd) {
|
|
20
|
+
const { stdout } = await execFile(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['view', `${name}@latest`, 'version', '--json', '--registry=https://registry.npmjs.org'], {
|
|
21
|
+
cwd,
|
|
22
|
+
encoding: 'utf8',
|
|
23
|
+
timeout: 20_000,
|
|
24
|
+
maxBuffer: 16_384,
|
|
25
|
+
shell: process.platform === 'win32',
|
|
26
|
+
});
|
|
27
|
+
return requireStableVersion(name, JSON.parse(stdout));
|
|
28
|
+
}
|
|
29
|
+
function requireStableVersion(name, latest) {
|
|
30
|
+
if (typeof latest !== 'string' || !stable.test(latest)) {
|
|
31
|
+
throw new Error('Registry did not return a stable Devvit version: ' + name);
|
|
32
|
+
}
|
|
33
|
+
return latest;
|
|
34
|
+
}
|
|
35
|
+
export function assertLatestDevvitSdk(entries) {
|
|
36
|
+
if (!entries.some((e) => e.name === 'devvit' || e.name === '@devvit/cli') || !entries.some((e) => e.name === '@devvit/web' || e.name === '@devvit/public-api')) {
|
|
37
|
+
throw new Error('Devvit upload needs both an installed CLI and SDK in this project.');
|
|
38
|
+
}
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
if (!stable.test(entry.latest) || (entry.source !== 'adapter' && entry.declared !== entry.latest) || entry.installed !== entry.latest) {
|
|
41
|
+
throw new Error(`${entry.name}: declared=${entry.declared}, installed=${entry.installed}, latest=${entry.latest}. Update exact SDK/CLI pins and lockfile, rebuild and test, then retry upload.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Read-only pre-upload gate. Never install a new SDK between verified build and upload. */
|
|
46
|
+
export async function checkDevvitSdk(project, options = {}) {
|
|
47
|
+
const manifestPath = path.resolve(project, 'package.json');
|
|
48
|
+
const manifest = record(JSON.parse(await readFile(manifestPath, 'utf8')));
|
|
49
|
+
const dependencies = {
|
|
50
|
+
...(manifest.dependencies === undefined ? {} : record(manifest.dependencies)),
|
|
51
|
+
...(manifest.devDependencies === undefined ? {} : record(manifest.devDependencies)),
|
|
52
|
+
};
|
|
53
|
+
async function installedPackage(from, name) {
|
|
54
|
+
let directory = from;
|
|
55
|
+
for (;;) {
|
|
56
|
+
const file = path.join(directory, 'node_modules', name, 'package.json');
|
|
57
|
+
try {
|
|
58
|
+
const metadata = record(JSON.parse(await readFile(file, 'utf8')));
|
|
59
|
+
if (metadata.name !== name || typeof metadata.version !== 'string') {
|
|
60
|
+
throw new Error('Invalid installed package: ' + name);
|
|
61
|
+
}
|
|
62
|
+
return { metadata, directory: path.dirname(await realpath(file)) };
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (!(error instanceof Error) || !('code' in error) || error.code !== 'ENOENT') {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const parent = path.dirname(directory);
|
|
70
|
+
if (parent === directory) {
|
|
71
|
+
throw new Error('Cannot resolve installed Devvit package: ' + name);
|
|
72
|
+
}
|
|
73
|
+
directory = parent;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const targetDirectory = path.dirname(manifestPath);
|
|
77
|
+
const subjects = devvitPackageNames(dependencies).map((name) => ({
|
|
78
|
+
name,
|
|
79
|
+
declared: dependencies[name],
|
|
80
|
+
directory: targetDirectory,
|
|
81
|
+
transitive: false,
|
|
82
|
+
}));
|
|
83
|
+
if (Object.hasOwn(dependencies, '@mpgd/adapter-devvit')) {
|
|
84
|
+
const adapter = await installedPackage(targetDirectory, '@mpgd/adapter-devvit');
|
|
85
|
+
const adapterDependencies = record(adapter.metadata.dependencies);
|
|
86
|
+
for (const name of devvitPackageNames(adapterDependencies)) {
|
|
87
|
+
subjects.push({
|
|
88
|
+
name,
|
|
89
|
+
declared: adapterDependencies[name],
|
|
90
|
+
directory: adapter.directory,
|
|
91
|
+
transitive: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const entries = await Promise.all(subjects.map(async ({ name, declared, directory, transitive }) => {
|
|
96
|
+
if (typeof declared !== 'string') {
|
|
97
|
+
throw new Error('Invalid Devvit dependency: ' + name);
|
|
98
|
+
}
|
|
99
|
+
const resolved = await installedPackage(directory, name);
|
|
100
|
+
const installed = resolved.metadata.version;
|
|
101
|
+
if (typeof installed !== 'string') {
|
|
102
|
+
throw new Error('Missing installed Devvit version: ' + name);
|
|
103
|
+
}
|
|
104
|
+
const latest = options.lookupLatest
|
|
105
|
+
? requireStableVersion(name, await options.lookupLatest(name))
|
|
106
|
+
: await npmLatestStable(name, path.dirname(manifestPath));
|
|
107
|
+
// A consumer may use a reviewed exact override until the adapter release catches up.
|
|
108
|
+
return { name, declared, installed, latest, ...(transitive ? { source: 'adapter' } : {}) };
|
|
109
|
+
}));
|
|
110
|
+
assertLatestDevvitSdk(entries);
|
|
111
|
+
return entries;
|
|
112
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ import { runMicrosoftStorePackageGeneration } from './microsoft-store-package-ge
|
|
|
27
27
|
import { defaultMpgdKitPath, initializeMicrosoftStoreStarter, listMicrosoftStoreInitializerTemplateFiles, prepareBaseGameTemplateFile, resolveMicrosoftStoreAdapterDependencyVersion, } from './microsoft-store-starter.js';
|
|
28
28
|
import { applyNotificationsStarter, notificationsProviderId, readGameCreateProviders, } from './notifications-starter.js';
|
|
29
29
|
import { applyKitUpgrade, planKitUpgrade } from './kit-upgrade.js';
|
|
30
|
+
import { checkDevvitSdk } from './devvit-sdk-check.js';
|
|
30
31
|
import { applyToolingMigration, planToolingMigration } from './tooling-migration.js';
|
|
31
32
|
import { runMicrosoftStoreSubmissionPreflight } from './microsoft-store-submission.js';
|
|
32
33
|
import { defaultOfflinePlaytestArtifactDir, defaultOfflinePlaytestMaximumBytes, defaultOfflinePlaytestOutputDir, runOfflinePlaytestPackaging, } from './offline-playtest.js';
|
|
@@ -2525,6 +2526,18 @@ const kitCommand = defineI18n({
|
|
|
2525
2526
|
ko: '현재 mpgd-kit 체크아웃을 점검합니다.',
|
|
2526
2527
|
}),
|
|
2527
2528
|
subCommands: {
|
|
2529
|
+
'devvit-check': defineI18n({
|
|
2530
|
+
name: 'devvit-check',
|
|
2531
|
+
description: 'Require exact installed latest stable Devvit SDK and CLI before upload.',
|
|
2532
|
+
resource: commandResource({ en: 'Check latest stable Devvit SDK before upload.', ko: '업로드 전 Devvit 최신 안정 SDK를 확인합니다.' }),
|
|
2533
|
+
args: { project: { type: 'string', default: '.', description: 'Devvit target directory.' } },
|
|
2534
|
+
run: async (ctx) => {
|
|
2535
|
+
const entries = await checkDevvitSdk(readOptionalString(ctx.values.project) ?? '.');
|
|
2536
|
+
for (const entry of entries) {
|
|
2537
|
+
console.info(entry.name + '@' + entry.installed + ' (latest stable)');
|
|
2538
|
+
}
|
|
2539
|
+
},
|
|
2540
|
+
}),
|
|
2528
2541
|
upgrade: defineI18n({
|
|
2529
2542
|
name: 'upgrade',
|
|
2530
2543
|
description: 'Plan or apply the latest published Kit package versions for a game.',
|
|
@@ -6990,9 +6990,6 @@ var releaseBackoffMs = 60 * secondMs;
|
|
|
6990
6990
|
// node_modules/.cache/mpgd-native-build/adapters/devvit/src/server/redis-notification-store.js
|
|
6991
6991
|
var defaultPurgeLimit = Number.POSITIVE_INFINITY;
|
|
6992
6992
|
|
|
6993
|
-
// node_modules/.cache/mpgd-native-build/adapters/devvit/src/notifications-contract.js
|
|
6994
|
-
var devvitHostCodeCharacters = "[A-Za-z0-9_.:-]{1,128}";
|
|
6995
|
-
|
|
6996
6993
|
// node_modules/.cache/mpgd-native-build/adapters/devvit/src/server/notifications-delivery.js
|
|
6997
6994
|
var devvitNotificationProviderCodes = Object.freeze({
|
|
6998
6995
|
deviceRecipient: "DEVVIT_DEVICE_RECIPIENT",
|
|
@@ -7023,13 +7020,17 @@ var devvitNotificationSchedulerTasks = Object.freeze({
|
|
|
7023
7020
|
})
|
|
7024
7021
|
});
|
|
7025
7022
|
|
|
7023
|
+
// node_modules/.cache/mpgd-native-build/packages/bridge/src/notifications.js
|
|
7024
|
+
var hostCodeCharacters = "[A-Za-z0-9_.:-]{1,128}";
|
|
7025
|
+
var hostCodeValue = new RegExp(`^${hostCodeCharacters}$`, "u");
|
|
7026
|
+
var hostCodeSuffix = new RegExp(`\\(host code (${hostCodeCharacters})\\)$`, "u");
|
|
7027
|
+
|
|
7026
7028
|
// node_modules/.cache/mpgd-native-build/adapters/devvit/src/server/notifications-bridge.js
|
|
7027
7029
|
var devvitNotificationHostCodes = Object.freeze({
|
|
7028
7030
|
optInRefused: "DEVVIT_OPT_IN_REFUSED",
|
|
7029
7031
|
optOutRefused: "DEVVIT_OPT_OUT_REFUSED",
|
|
7030
7032
|
pluginFailed: "DEVVIT_NOTIFICATIONS_PLUGIN_FAILED"
|
|
7031
7033
|
});
|
|
7032
|
-
var hostCodeValue = new RegExp(`^${devvitHostCodeCharacters}$`, "u");
|
|
7033
7034
|
|
|
7034
7035
|
// node_modules/.cache/mpgd-native-build/packages/cli/src/target-name.js
|
|
7035
7036
|
var deploymentTargetNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.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.10.
|
|
74
|
-
"@mpgd/
|
|
75
|
-
"@mpgd/
|
|
76
|
-
"@mpgd/
|
|
73
|
+
"@mpgd/catalog": "0.10.7",
|
|
74
|
+
"@mpgd/target-config": "0.23.7",
|
|
75
|
+
"@mpgd/platform": "0.27.2",
|
|
76
|
+
"@mpgd/phaser-assets": "0.9.1"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@types/node": "^24.0.0",
|
|
@@ -81,18 +81,18 @@
|
|
|
81
81
|
"@types/yauzl": "3.4.0",
|
|
82
82
|
"ttsc": "0.32.1",
|
|
83
83
|
"typescript": "7.0.2",
|
|
84
|
-
"@mpgd/adapter-
|
|
85
|
-
"@mpgd/adapter-
|
|
86
|
-
"@mpgd/adapter-
|
|
87
|
-
"@mpgd/adapter-
|
|
88
|
-
"@mpgd/
|
|
89
|
-
"@mpgd/analytics": "0.4.
|
|
90
|
-
"@mpgd/
|
|
91
|
-
"@mpgd/
|
|
92
|
-
"@mpgd/capacitor-storekit": "0.3.
|
|
93
|
-
"@mpgd/game-runtime": "0.
|
|
94
|
-
"@mpgd/game-services": "0.27.
|
|
95
|
-
"@mpgd/i18n": "0.6.
|
|
84
|
+
"@mpgd/adapter-ait": "0.20.3",
|
|
85
|
+
"@mpgd/adapter-browser": "0.11.7",
|
|
86
|
+
"@mpgd/adapter-capacitor": "0.12.3",
|
|
87
|
+
"@mpgd/adapter-devvit": "0.13.5",
|
|
88
|
+
"@mpgd/adapter-verse8": "0.7.7",
|
|
89
|
+
"@mpgd/analytics": "0.4.16",
|
|
90
|
+
"@mpgd/capacitor-play-billing": "0.3.7",
|
|
91
|
+
"@mpgd/bridge": "0.15.0",
|
|
92
|
+
"@mpgd/capacitor-storekit": "0.3.7",
|
|
93
|
+
"@mpgd/game-runtime": "0.8.0",
|
|
94
|
+
"@mpgd/game-services": "0.27.2",
|
|
95
|
+
"@mpgd/i18n": "0.6.21",
|
|
96
96
|
"@mpgd/lite-shell": "0.1.0"
|
|
97
97
|
},
|
|
98
98
|
"main": "./dist/index.js",
|
|
@@ -6,29 +6,30 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepare:icon": "pnpm --dir ../.. icons:generate:devvit",
|
|
8
8
|
"prepare:icon:production": "pnpm --dir ../.. icons:generate:devvit:production",
|
|
9
|
-
"init": "pnpm run prepare:icon:production && devvit upload --config devvit.json",
|
|
10
|
-
"init:copy-paste": "pnpm run prepare:icon:production && devvit upload --copy-paste --config devvit.json",
|
|
11
|
-
"dev": "pnpm run prepare:icon && devvit playtest --config devvit.json",
|
|
9
|
+
"init": "pnpm run check:sdk && pnpm run prepare:icon:production && devvit upload --config devvit.json",
|
|
10
|
+
"init:copy-paste": "pnpm run check:sdk && pnpm run prepare:icon:production && devvit upload --copy-paste --config devvit.json",
|
|
11
|
+
"dev": "pnpm run check:sdk && pnpm run prepare:icon && devvit playtest --config devvit.json",
|
|
12
12
|
"build": "pnpm --dir ../.. build:devvit",
|
|
13
13
|
"whoami": "devvit whoami",
|
|
14
|
-
"upload": "pnpm run prepare:icon:production && devvit upload --config devvit.json",
|
|
15
|
-
"publish": "pnpm run prepare:icon:production && devvit publish --config devvit.json",
|
|
14
|
+
"upload": "pnpm run check:sdk && pnpm run prepare:icon:production && devvit upload --config devvit.json",
|
|
15
|
+
"publish": "pnpm run check:sdk && pnpm run prepare:icon:production && devvit publish --config devvit.json",
|
|
16
16
|
"check": "ttsc --noEmit -p tsconfig.json",
|
|
17
17
|
"lint": "ttsc --noEmit -p tsconfig.json",
|
|
18
18
|
"format": "ttsc format",
|
|
19
|
-
"fix": "ttsc fix"
|
|
19
|
+
"fix": "ttsc fix",
|
|
20
|
+
"check:sdk": "pnpm exec mpgd kit devvit-check --project ."
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@devvit/web": "0.
|
|
23
|
+
"@devvit/web": "0.15.0",
|
|
23
24
|
"@mpgd/adapter-devvit": "__MPGD_DEPENDENCY_VERSION_ADAPTER_DEVVIT__",
|
|
24
25
|
"@mpgd/bridge": "__MPGD_DEPENDENCY_VERSION_BRIDGE__",
|
|
25
26
|
"@mpgd/catalog": "__MPGD_DEPENDENCY_VERSION_CATALOG__"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
|
-
"@devvit/start": "0.
|
|
29
|
+
"@devvit/start": "0.15.0",
|
|
29
30
|
"@ttsc/unplugin": "0.32.1",
|
|
30
31
|
"@types/node": "^24.0.0",
|
|
31
|
-
"devvit": "0.
|
|
32
|
+
"devvit": "0.15.0",
|
|
32
33
|
"ttsc": "0.32.1",
|
|
33
34
|
"typescript": "7.0.2",
|
|
34
35
|
"vite": "7.3.6"
|