@mpgd/cli 0.61.0 → 0.62.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/capacitor-shell-starter.js +18 -1
- package/dist/crash-reporting-starter.d.ts +5 -3
- package/dist/crash-reporting-starter.js +10 -7
- package/dist/crash-symbols-upload.d.ts +67 -0
- package/dist/crash-symbols-upload.js +232 -0
- package/dist/index.js +48 -1
- package/dist/native-build-info.json +2 -2
- package/dist/native-build-symbols.d.ts +95 -0
- package/dist/native-build-symbols.js +261 -0
- package/dist/native-build-target.js +700 -428
- package/dist/native-deploy-run.d.ts +2 -0
- package/dist/native-deploy-run.js +60 -10
- package/dist/native-deploy-submission.d.ts +8 -0
- package/dist/native-deploy-submission.js +50 -8
- package/dist/pnpm-build-approvals.d.ts +59 -0
- package/dist/pnpm-build-approvals.js +157 -0
- package/dist/release-state.d.ts +69 -0
- package/dist/release-state.js +150 -5
- package/dist/release-workspace.d.ts +3 -0
- package/dist/release-workspace.js +44 -1
- package/package.json +11 -11
- package/templates/phaser-game/apps/target-ait/package.json +2 -2
- package/templates/phaser-game/package.json +1 -1
- package/templates/phaser-game/pnpm-workspace.yaml +2 -0
package/dist/release-state.js
CHANGED
|
@@ -6,6 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import { isDeepStrictEqual } from 'node:util';
|
|
7
7
|
import { allocatePlatformVersions, assertPlatformVersionLedger, createMpgdReleaseIdentity, formatMpgdReleaseId, } from '@mpgd/target-config';
|
|
8
8
|
import { runReleaseProcess } from './deploy-process.js';
|
|
9
|
+
import { isDsymIdentityList } from './native-build-symbols.js';
|
|
9
10
|
import { inspectAndroidBundleSigner } from './android-bundle-signer.js';
|
|
10
11
|
export function isNativeSubmissionSettled(status) {
|
|
11
12
|
return status === 'committed' || status === 'testflight-ready';
|
|
@@ -195,6 +196,7 @@ export async function reserveNativeRelease(input) {
|
|
|
195
196
|
reservations: { ...(game?.reservations ?? {}), [input.releaseKey]: allocation.plan },
|
|
196
197
|
builds: game?.builds ?? {},
|
|
197
198
|
...(game?.submissions === undefined ? {} : { submissions: game.submissions }),
|
|
199
|
+
...(game?.symbolUploads === undefined ? {} : { symbolUploads: game.symbolUploads }),
|
|
198
200
|
};
|
|
199
201
|
const next = {
|
|
200
202
|
schemaVersion: 1,
|
|
@@ -238,7 +240,26 @@ export async function recordNativeReleaseBuild(input) {
|
|
|
238
240
|
|| !statSync(input.releaseManifestFile).isFile()) {
|
|
239
241
|
throw new Error('Native build record requires file artifacts.');
|
|
240
242
|
}
|
|
241
|
-
|
|
243
|
+
if ((input.r8Mapping !== undefined && input.target !== 'android')
|
|
244
|
+
|| (input.crashlyticsSymbols !== undefined && (input.target !== 'ios'
|
|
245
|
+
|| !isDsymIdentityList(input.crashlyticsSymbols.dsyms)))) {
|
|
246
|
+
throw new Error('Native build symbols do not match the build target.');
|
|
247
|
+
}
|
|
248
|
+
const r8Mapping = input.r8Mapping === undefined
|
|
249
|
+
? undefined
|
|
250
|
+
: await recordSymbolFile(input.r8Mapping);
|
|
251
|
+
const crashlyticsSymbols = input.crashlyticsSymbols === undefined
|
|
252
|
+
? undefined
|
|
253
|
+
: {
|
|
254
|
+
dsymArchive: await recordSymbolFile(input.crashlyticsSymbols.dsymArchive),
|
|
255
|
+
dsyms: input.crashlyticsSymbols.dsyms.map((entry) => ({
|
|
256
|
+
bundle: entry.bundle,
|
|
257
|
+
uuids: [...entry.uuids],
|
|
258
|
+
})),
|
|
259
|
+
uploadTool: await recordSymbolFile(input.crashlyticsSymbols.uploadTool),
|
|
260
|
+
googleServiceInfo: await recordSymbolFile(input.crashlyticsSymbols.googleServiceInfo),
|
|
261
|
+
};
|
|
262
|
+
const artifactSha256 = await sha256File(input.artifactFile);
|
|
242
263
|
const manifestBytes = readFileSync(input.releaseManifestFile);
|
|
243
264
|
const releaseManifestSha256 = createHash('sha256').update(manifestBytes).digest('hex');
|
|
244
265
|
if (artifactSha256 !== input.expectedArtifactSha256
|
|
@@ -331,6 +352,8 @@ export async function recordNativeReleaseBuild(input) {
|
|
|
331
352
|
...(input.target === 'android'
|
|
332
353
|
? { inspectedSignerSha256: signer }
|
|
333
354
|
: { inspectedTeamId: input.inspectedTeamId ?? '' }),
|
|
355
|
+
...(r8Mapping === undefined ? {} : { r8Mapping }),
|
|
356
|
+
...(crashlyticsSymbols === undefined ? {} : { crashlyticsSymbols }),
|
|
334
357
|
};
|
|
335
358
|
const key = `${input.releaseKey}/${input.target}`;
|
|
336
359
|
const previous = ownValue(game.builds, key);
|
|
@@ -377,6 +400,8 @@ export async function readNativeReleaseStatus(input) {
|
|
|
377
400
|
...(game.submissions?.[iosKey] === undefined
|
|
378
401
|
? {} : { ios: game.submissions[iosKey] }),
|
|
379
402
|
},
|
|
403
|
+
symbolUploads: game.symbolUploads?.[iosKey] === undefined
|
|
404
|
+
? {} : { ios: game.symbolUploads[iosKey] },
|
|
380
405
|
stateCommit: session.previousCommit,
|
|
381
406
|
};
|
|
382
407
|
});
|
|
@@ -529,6 +554,57 @@ export async function releaseNativeSubmissionLease(input) {
|
|
|
529
554
|
return checkpoint;
|
|
530
555
|
});
|
|
531
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Record the outcome of a Crashlytics dSYM upload for one recorded iOS build.
|
|
559
|
+
* A failure can be recorded again and retried; once `uploaded`, it stays so.
|
|
560
|
+
*/
|
|
561
|
+
export async function recordCrashSymbolUpload(input) {
|
|
562
|
+
assertReleaseKey(input.releaseKey);
|
|
563
|
+
const upload = {
|
|
564
|
+
releaseKey: input.releaseKey,
|
|
565
|
+
target: 'ios',
|
|
566
|
+
buildRunId: input.buildRunId,
|
|
567
|
+
dsymArchiveSha256: input.dsymArchiveSha256,
|
|
568
|
+
status: input.status,
|
|
569
|
+
updatedAt: new Date().toISOString(),
|
|
570
|
+
...(input.status === 'failed' && input.failure !== undefined
|
|
571
|
+
? { failure: boundedFailure(input.failure) } : {}),
|
|
572
|
+
};
|
|
573
|
+
assertCrashSymbolUploadRecord(upload);
|
|
574
|
+
return withStateSession(input, async (session) => {
|
|
575
|
+
const game = ownValue(session.state.games, input.gameId);
|
|
576
|
+
const key = `${input.releaseKey}/ios`;
|
|
577
|
+
const build = game === undefined ? undefined : ownValue(game.builds, key);
|
|
578
|
+
if (game === undefined || build === undefined
|
|
579
|
+
|| build.buildRunId !== input.buildRunId
|
|
580
|
+
|| build.crashlyticsSymbols?.dsymArchive.sha256 !== input.dsymArchiveSha256) {
|
|
581
|
+
throw new Error('A dSYM upload must reference the immutable iOS build record.');
|
|
582
|
+
}
|
|
583
|
+
const previous = ownValue(game.symbolUploads ?? {}, key);
|
|
584
|
+
if (previous?.status === 'uploaded') {
|
|
585
|
+
if (input.status === 'uploaded') {
|
|
586
|
+
return previous;
|
|
587
|
+
}
|
|
588
|
+
throw new Error('The dSYMs of this build were already uploaded.');
|
|
589
|
+
}
|
|
590
|
+
const next = {
|
|
591
|
+
schemaVersion: 1,
|
|
592
|
+
games: {
|
|
593
|
+
...session.state.games,
|
|
594
|
+
[input.gameId]: {
|
|
595
|
+
...game,
|
|
596
|
+
symbolUploads: { ...(game.symbolUploads ?? {}), [key]: upload },
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
};
|
|
600
|
+
await commitState(session, next, `Symbols ${input.gameId}/${key} ${input.status}`);
|
|
601
|
+
return upload;
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
function boundedFailure(text) {
|
|
605
|
+
const line = text.replace(/[\u0000-\u001f\u007f]+/gu, ' ').trim();
|
|
606
|
+
return line.length > 300 ? `${line.slice(0, 297)}...` : (line === '' ? 'failed' : line);
|
|
607
|
+
}
|
|
532
608
|
/** Exported for tests: the checkpoint status moves a store submission may make. */
|
|
533
609
|
export function allowedSubmissionTransition(from, to) {
|
|
534
610
|
if (from === to) {
|
|
@@ -719,13 +795,14 @@ function parseReleaseState(json) {
|
|
|
719
795
|
}
|
|
720
796
|
const game = rawGame;
|
|
721
797
|
if (Object.keys(game).some((key) => ![
|
|
722
|
-
'initialLedger', 'ledger', 'reservations', 'builds', 'submissions',
|
|
798
|
+
'initialLedger', 'ledger', 'reservations', 'builds', 'submissions', 'symbolUploads',
|
|
723
799
|
].includes(key))
|
|
724
800
|
|| typeof game.reservations !== 'object' || game.reservations === null
|
|
725
801
|
|| Array.isArray(game.reservations)
|
|
726
802
|
|| typeof game.builds !== 'object' || game.builds === null
|
|
727
803
|
|| Array.isArray(game.builds)
|
|
728
|
-
|| (game.submissions !== undefined && !isRecord(game.submissions))
|
|
804
|
+
|| (game.submissions !== undefined && !isRecord(game.submissions))
|
|
805
|
+
|| (game.symbolUploads !== undefined && !isRecord(game.symbolUploads))) {
|
|
729
806
|
throw new Error(`Release state game ${gameId} has invalid entries.`);
|
|
730
807
|
}
|
|
731
808
|
const initialLedger = assertPlatformVersionLedger(game.initialLedger);
|
|
@@ -789,6 +866,20 @@ function parseReleaseState(json) {
|
|
|
789
866
|
throw new Error(`Release state game ${gameId} has an invalid submission ${key}.`);
|
|
790
867
|
}
|
|
791
868
|
}
|
|
869
|
+
for (const [key, rawUpload] of Object.entries(game.symbolUploads ?? {})) {
|
|
870
|
+
const build = game.builds[key];
|
|
871
|
+
try {
|
|
872
|
+
assertCrashSymbolUploadRecord(rawUpload);
|
|
873
|
+
}
|
|
874
|
+
catch {
|
|
875
|
+
throw new Error(`Release state game ${gameId} has an invalid dSYM upload ${key}.`);
|
|
876
|
+
}
|
|
877
|
+
if (key !== `${rawUpload.releaseKey}/ios` || build === undefined
|
|
878
|
+
|| rawUpload.buildRunId !== build.buildRunId
|
|
879
|
+
|| rawUpload.dsymArchiveSha256 !== build.crashlyticsSymbols?.dsymArchive.sha256) {
|
|
880
|
+
throw new Error(`Release state game ${gameId} has an invalid dSYM upload ${key}.`);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
792
883
|
}
|
|
793
884
|
return value;
|
|
794
885
|
}
|
|
@@ -813,6 +904,8 @@ const buildRecordFields = [
|
|
|
813
904
|
'inspectedAppId',
|
|
814
905
|
'inspectedSignerSha256',
|
|
815
906
|
'inspectedTeamId',
|
|
907
|
+
'r8Mapping',
|
|
908
|
+
'crashlyticsSymbols',
|
|
816
909
|
];
|
|
817
910
|
function assertStoredBuildRecord(gameId, buildKey, value, reservations) {
|
|
818
911
|
const malformed = () => {
|
|
@@ -853,7 +946,11 @@ function assertStoredBuildRecord(gameId, buildKey, value, reservations) {
|
|
|
853
946
|
|| !sha256Pattern.test(String(record.inspectedSignerSha256))))
|
|
854
947
|
|| (record.target === 'ios' && (record.inspectedSignerSha256 !== undefined
|
|
855
948
|
|| !teamIdPattern.test(String(record.inspectedTeamId))))
|
|
856
|
-
|| !isRecord(record.platformVersion)
|
|
949
|
+
|| !isRecord(record.platformVersion)
|
|
950
|
+
|| (record.r8Mapping !== undefined
|
|
951
|
+
&& (record.target !== 'android' || !isRecordedSymbolFile(record.r8Mapping)))
|
|
952
|
+
|| (record.crashlyticsSymbols !== undefined
|
|
953
|
+
&& (record.target !== 'ios' || !isRecordedCrashlyticsSymbols(record.crashlyticsSymbols)))) {
|
|
857
954
|
malformed();
|
|
858
955
|
}
|
|
859
956
|
const plan = ownValue(reservations, record.releaseKey);
|
|
@@ -930,6 +1027,53 @@ export function assertNativeSubmissionCheckpoint(value) {
|
|
|
930
1027
|
throw new Error('Native submission checkpoint is malformed.');
|
|
931
1028
|
}
|
|
932
1029
|
}
|
|
1030
|
+
const recordedLocationPattern = /^[A-Za-z0-9._-][A-Za-z0-9._ +-]*(?:\/[A-Za-z0-9._-][A-Za-z0-9._ +-]*)*$/u;
|
|
1031
|
+
/** A game-relative location without `..` segments. */
|
|
1032
|
+
export function isRecordedLocation(location) {
|
|
1033
|
+
return typeof location === 'string' && location.length <= 512
|
|
1034
|
+
&& recordedLocationPattern.test(location)
|
|
1035
|
+
&& !location.split('/').some((segment) => segment === '.' || segment === '..');
|
|
1036
|
+
}
|
|
1037
|
+
function isRecordedSymbolFile(value) {
|
|
1038
|
+
return isRecord(value) && Object.keys(value).every((key) => key === 'location' || key === 'sha256')
|
|
1039
|
+
&& isRecordedLocation(value.location) && sha256Pattern.test(String(value.sha256));
|
|
1040
|
+
}
|
|
1041
|
+
function isRecordedCrashlyticsSymbols(value) {
|
|
1042
|
+
return isRecord(value)
|
|
1043
|
+
&& Object.keys(value).every((key) => ['dsymArchive', 'dsyms', 'uploadTool', 'googleServiceInfo'].includes(key))
|
|
1044
|
+
&& isRecordedSymbolFile(value.dsymArchive) && isRecordedSymbolFile(value.uploadTool)
|
|
1045
|
+
&& isRecordedSymbolFile(value.googleServiceInfo) && isDsymIdentityList(value.dsyms);
|
|
1046
|
+
}
|
|
1047
|
+
const symbolUploadFields = [
|
|
1048
|
+
'releaseKey',
|
|
1049
|
+
'target',
|
|
1050
|
+
'buildRunId',
|
|
1051
|
+
'dsymArchiveSha256',
|
|
1052
|
+
'status',
|
|
1053
|
+
'updatedAt',
|
|
1054
|
+
'failure',
|
|
1055
|
+
];
|
|
1056
|
+
function assertCrashSymbolUploadRecord(value) {
|
|
1057
|
+
if (!isRecord(value)
|
|
1058
|
+
|| Object.keys(value).some((key) => !symbolUploadFields.includes(key))
|
|
1059
|
+
|| typeof value.releaseKey !== 'string' || !releaseKeyPattern.test(value.releaseKey)
|
|
1060
|
+
|| value.target !== 'ios'
|
|
1061
|
+
|| typeof value.buildRunId !== 'string' || value.buildRunId.trim() === ''
|
|
1062
|
+
|| !sha256Pattern.test(String(value.dsymArchiveSha256))
|
|
1063
|
+
|| (value.status !== 'uploaded' && value.status !== 'failed')
|
|
1064
|
+
|| typeof value.updatedAt !== 'string' || !Number.isFinite(Date.parse(value.updatedAt))
|
|
1065
|
+
|| (value.failure !== undefined && (value.status !== 'failed'
|
|
1066
|
+
|| typeof value.failure !== 'string' || value.failure.length > 300))) {
|
|
1067
|
+
throw new Error('Crashlytics dSYM upload record is malformed.');
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
async function recordSymbolFile(input) {
|
|
1071
|
+
if (!isRecordedLocation(input.location) || !existsSync(input.file)
|
|
1072
|
+
|| !statSync(input.file).isFile() || statSync(input.file).size === 0) {
|
|
1073
|
+
throw new Error('Native build symbol file is missing or has an invalid location.');
|
|
1074
|
+
}
|
|
1075
|
+
return { location: input.location, sha256: await sha256File(input.file) };
|
|
1076
|
+
}
|
|
933
1077
|
function assertReservationHistory(gameId, initialLedger, ledger, plans) {
|
|
934
1078
|
if (plans.length === 0) {
|
|
935
1079
|
throw new Error(`Release state game ${gameId} has no reservation history.`);
|
|
@@ -993,7 +1137,8 @@ function assertReleaseKey(key) {
|
|
|
993
1137
|
throw new Error('Release key must be a lowercase, path-safe identifier.');
|
|
994
1138
|
}
|
|
995
1139
|
}
|
|
996
|
-
|
|
1140
|
+
/** Streamed SHA-256 of a file, hex. */
|
|
1141
|
+
export async function sha256File(file) {
|
|
997
1142
|
const hash = createHash('sha256');
|
|
998
1143
|
for await (const chunk of createReadStream(file)) {
|
|
999
1144
|
hash.update(chunk);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type NativeDeploymentPlan } from './deploy-planning.js';
|
|
2
|
+
import { type NativeBuildSymbols } from './native-build-symbols.js';
|
|
2
3
|
export interface PinnedReleaseInput {
|
|
3
4
|
readonly gameRoot: string;
|
|
4
5
|
readonly deploymentProfile: string;
|
|
@@ -21,6 +22,8 @@ export interface PinnedNativeBuildResult {
|
|
|
21
22
|
readonly artifact: string;
|
|
22
23
|
readonly releaseManifest: string;
|
|
23
24
|
readonly runId: string;
|
|
25
|
+
/** Crash symbols of this build, as absolute paths inside the pinned game. */
|
|
26
|
+
readonly symbols?: NativeBuildSymbols;
|
|
24
27
|
}
|
|
25
28
|
/** Freeze a read-only deployment plan into the exact inputs used by a release run. */
|
|
26
29
|
export declare function pinNativeDeploymentPlan(plan: NativeDeploymentPlan, kit: {
|
|
@@ -4,6 +4,7 @@ import { tmpdir } from 'node:os';
|
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { planNativeDeployment } from './deploy-planning.js';
|
|
7
|
+
import { assertNativeBuildSymbols, isNativeOutputPath, } from './native-build-symbols.js';
|
|
7
8
|
import { runReleaseProcess, } from './deploy-process.js';
|
|
8
9
|
const gitShaPattern = /^[0-9a-f]{40}$/u;
|
|
9
10
|
const sha256Pattern = /^[0-9a-f]{64}$/u;
|
|
@@ -287,7 +288,49 @@ export async function runPinnedNativeBuild(workspace, input) {
|
|
|
287
288
|
|| manifest.kitGitSha !== workspace.input.kitGitSha) {
|
|
288
289
|
throw new Error('Pinned native build manifest provenance does not match its inputs.');
|
|
289
290
|
}
|
|
290
|
-
|
|
291
|
+
const symbols = status.symbols === undefined
|
|
292
|
+
? undefined
|
|
293
|
+
: resolvePinnedBuildSymbols(workspace.gameRoot, input.target, status.symbols);
|
|
294
|
+
return {
|
|
295
|
+
artifact,
|
|
296
|
+
releaseManifest,
|
|
297
|
+
runId: status.runId,
|
|
298
|
+
...(symbols === undefined ? {} : { symbols }),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/** Resolve the status file's symbol paths to regular files inside the pinned game. */
|
|
302
|
+
function resolvePinnedBuildSymbols(gameRoot, target, value) {
|
|
303
|
+
assertNativeBuildSymbols(value, (file) => isNativeOutputPath(file, target));
|
|
304
|
+
const canonicalGameRoot = realpathSync(gameRoot);
|
|
305
|
+
const resolve = (file) => {
|
|
306
|
+
const absolute = assertInsideWorkspace(gameRoot, file);
|
|
307
|
+
if (!existsSync(absolute) || !lstatSync(absolute).isFile()) {
|
|
308
|
+
throw new Error(`Pinned native build symbol file is missing: ${file}`);
|
|
309
|
+
}
|
|
310
|
+
const relative = path.relative(canonicalGameRoot, realpathSync(absolute));
|
|
311
|
+
if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
312
|
+
throw new Error('Pinned native build symbol file resolves outside its workspace.');
|
|
313
|
+
}
|
|
314
|
+
return absolute;
|
|
315
|
+
};
|
|
316
|
+
if (value.r8Mapping !== undefined) {
|
|
317
|
+
if (target !== 'android') {
|
|
318
|
+
throw new Error('Only an Android build records an R8 mapping file.');
|
|
319
|
+
}
|
|
320
|
+
return { r8Mapping: resolve(value.r8Mapping) };
|
|
321
|
+
}
|
|
322
|
+
const crashlytics = value.crashlytics;
|
|
323
|
+
if (crashlytics === undefined || target !== 'ios') {
|
|
324
|
+
throw new Error('Only an iOS build records Crashlytics dSYMs.');
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
crashlytics: {
|
|
328
|
+
dsymArchive: resolve(crashlytics.dsymArchive),
|
|
329
|
+
dsyms: crashlytics.dsyms,
|
|
330
|
+
uploadTool: resolve(crashlytics.uploadTool),
|
|
331
|
+
googleServiceInfo: resolve(crashlytics.googleServiceInfo),
|
|
332
|
+
},
|
|
333
|
+
};
|
|
291
334
|
}
|
|
292
335
|
function assertPinnedInput(input) {
|
|
293
336
|
if (!gitShaPattern.test(input.gameGitSha) || !gitShaPattern.test(input.kitGitSha)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.0",
|
|
4
4
|
"description": "Gunshi CLI for mpgd-kit starter generation and target workflow orchestration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"postcss": "8.5.28",
|
|
72
72
|
"postcss-value-parser": "4.2.0",
|
|
73
73
|
"@mpgd/catalog": "0.11.3",
|
|
74
|
-
"@mpgd/
|
|
74
|
+
"@mpgd/phaser-assets": "0.9.1",
|
|
75
75
|
"@mpgd/target-config": "0.24.1",
|
|
76
|
-
"@mpgd/
|
|
76
|
+
"@mpgd/platform": "0.32.0"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@types/node": "^24.0.0",
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
"@types/yauzl": "3.4.0",
|
|
82
82
|
"ttsc": "0.32.1",
|
|
83
83
|
"typescript": "7.0.2",
|
|
84
|
-
"@mpgd/adapter-ait": "0.21.
|
|
84
|
+
"@mpgd/adapter-ait": "0.21.3",
|
|
85
85
|
"@mpgd/adapter-browser": "0.12.1",
|
|
86
|
-
"@mpgd/adapter-capacitor": "0.16.
|
|
87
|
-
"@mpgd/adapter-verse8": "0.7.
|
|
88
|
-
"@mpgd/adapter-devvit": "0.14.4",
|
|
86
|
+
"@mpgd/adapter-capacitor": "0.16.1",
|
|
87
|
+
"@mpgd/adapter-verse8": "0.7.14",
|
|
89
88
|
"@mpgd/bridge": "0.16.4",
|
|
89
|
+
"@mpgd/capacitor-play-billing": "0.4.3",
|
|
90
|
+
"@mpgd/adapter-devvit": "0.14.5",
|
|
91
|
+
"@mpgd/capacitor-storekit": "0.4.3",
|
|
90
92
|
"@mpgd/analytics": "0.5.5",
|
|
91
|
-
"@mpgd/
|
|
92
|
-
"@mpgd/
|
|
93
|
-
"@mpgd/game-runtime": "0.8.6",
|
|
94
|
-
"@mpgd/game-services": "0.30.2",
|
|
93
|
+
"@mpgd/game-runtime": "0.8.7",
|
|
94
|
+
"@mpgd/game-services": "0.30.3",
|
|
95
95
|
"@mpgd/i18n": "0.6.26",
|
|
96
96
|
"@mpgd/lite-shell": "0.1.0"
|
|
97
97
|
},
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"fix": "ttsc fix"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@apps-in-toss/web-framework": "3.
|
|
19
|
+
"@apps-in-toss/web-framework": "3.9.0",
|
|
20
20
|
"@mpgd/adapter-ait": "__MPGD_DEPENDENCY_VERSION_ADAPTER_AIT__"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@apps-in-toss/cli": "3.
|
|
23
|
+
"@apps-in-toss/cli": "3.9.0",
|
|
24
24
|
"@ttsc/unplugin": "0.32.1",
|
|
25
25
|
"@types/node": "^24.0.0",
|
|
26
26
|
"ttsc": "0.32.1",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@ait-co/polyfill": "^0.1.19",
|
|
59
|
-
"@apps-in-toss/web-framework": "3.
|
|
59
|
+
"@apps-in-toss/web-framework": "3.9.0",
|
|
60
60
|
"@capacitor/app": "8.1.1",
|
|
61
61
|
"@capacitor/core": "8.5.2",
|
|
62
62
|
"@mpgd/adapter-ait": "__MPGD_DEPENDENCY_VERSION_ADAPTER_AIT__",
|