From 3d32558c87a7dc0cbcabf5e4be67e66ca23f3c40 Mon Sep 17 00:00:00 2001 From: Eli Adelhult Date: Mon, 4 May 2026 15:57:09 +0200 Subject: [PATCH 1/4] Make it clerar that the getPath API should not be used --- src/cache.ts | 8 ++++++-- src/commands/cache/clean-impl.ts | 4 ++-- src/commands/cache/info-impl.ts | 4 ++-- src/commands/gxgames/link.ts | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index 6f77448..2f76caa 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -142,7 +142,9 @@ export class Cache { } /** Initializes and returns the local path, or undefined if local access is not allowed for this cache type. */ - public async getLocalPathStrict(ctx: CacheCtx): Promise { + public async _getInternalLocalPath( + ctx: CacheCtx, + ): Promise { if (!(await this.initLocal(ctx))) { // Not allowed to use shared cache return undefined; @@ -154,7 +156,9 @@ export class Cache { } /** Initializes and returns the shared path, or undefined if shared access is not allowed for this cache. */ - public async getSharedPathStrict(ctx: CacheCtx): Promise { + public async _getInternalSharedPath( + ctx: CacheCtx, + ): Promise { if (!(await this.initShared(ctx))) { // Not allowed to use shared cache return undefined; diff --git a/src/commands/cache/clean-impl.ts b/src/commands/cache/clean-impl.ts index 34dbdd5..e7f6666 100644 --- a/src/commands/cache/clean-impl.ts +++ b/src/commands/cache/clean-impl.ts @@ -38,8 +38,8 @@ export default async function ( ): Promise { validateFlags(flags); const cache = await setupCache(this, flags); - const localPath = await cache.getLocalPathStrict(this); - const sharedPath = await cache.getSharedPathStrict(this); + const localPath = await cache._getInternalLocalPath(this); + const sharedPath = await cache._getInternalSharedPath(this); await cleanPath(this, "Shared cache", sharedPath); await cleanPath(this, "Local cache", localPath); } diff --git a/src/commands/cache/info-impl.ts b/src/commands/cache/info-impl.ts index 09fe479..2cbedc3 100644 --- a/src/commands/cache/info-impl.ts +++ b/src/commands/cache/info-impl.ts @@ -31,8 +31,8 @@ export default async function ( ): Promise { validateFlags(flags); const cache = await setupCache(this, flags); - const localPath = await cache.getLocalPathStrict(this); - const sharedPath = await cache.getSharedPathStrict(this); + const localPath = await cache._getInternalLocalPath(this); + const sharedPath = await cache._getInternalSharedPath(this); this.process.stdout.write(chalk.bold("Shared cache\n")); this.process.stdout.write( `${sharedPath ?? "Not used when explicit --cache-dir is set"}\n`, diff --git a/src/commands/gxgames/link.ts b/src/commands/gxgames/link.ts index ba80830..481c8a3 100644 --- a/src/commands/gxgames/link.ts +++ b/src/commands/gxgames/link.ts @@ -52,7 +52,7 @@ async function writeStore(ctx: Context, store: GxGamesStore): Promise { type: "infer", projectDir: ctx.process.cwd(), }); - const cacheDir = await cache.getLocalPathStrict(ctx); + const cacheDir = await cache._getInternalLocalPath(ctx); if (!cacheDir) { throw new KnownError("Failed to initialize cache directory."); } From 448cbc135092817b5de328e78cc50da646df7b7f Mon Sep 17 00:00:00 2001 From: Eli Adelhult Date: Mon, 4 May 2026 15:59:12 +0200 Subject: [PATCH 2/4] Rename `allowedToBeShared` to `preferShared` --- src/cache.ts | 6 +++--- src/get-latest-version.ts | 2 +- src/igor/install-runtime.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index 2f76caa..fba3612 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -172,11 +172,11 @@ export class Cache { async getSubDirPath( ctx: CacheCtx, name: string, - { allowedToBeShared }: { allowedToBeShared: boolean } = { - allowedToBeShared: false, + { preferShared }: { preferShared: boolean } = { + preferShared: false, }, ): Promise { - if (allowedToBeShared && !this._localOnly) { + if (preferShared && !this._localOnly) { return this.getSubDirPathShared(ctx, name); } return this.getSubDirPathLocal(ctx, name); diff --git a/src/get-latest-version.ts b/src/get-latest-version.ts index 95268f5..46ba75d 100644 --- a/src/get-latest-version.ts +++ b/src/get-latest-version.ts @@ -50,7 +50,7 @@ export async function getLatestVersion(): Promise { } const cache = new Cache(ctx, { type: "shared-only" }); const dir = await cache.getSubDirPath(ctx, "version-check", { - allowedToBeShared: true, + preferShared: true, }); const checkFile = nodePath.join(dir, "check.json"); diff --git a/src/igor/install-runtime.ts b/src/igor/install-runtime.ts index e8cab98..a31ab01 100644 --- a/src/igor/install-runtime.ts +++ b/src/igor/install-runtime.ts @@ -161,7 +161,7 @@ export async function installRuntimeIfNeeded( }, ): Promise { const runtimeDir = await cache.getSubDirPath(ctx, "runtimes-gms2", { - allowedToBeShared: ctx.env.GAMEMAKER_CLI_UNSTABLE_FEATURES === true, + preferShared: ctx.env.GAMEMAKER_CLI_UNSTABLE_FEATURES === true, }); let runtimeLocation = await findRuntimeLocation(ctx, runtimeDir, version); From 5e2f786308ccd2bff4bc22f3f13173aa0614282b Mon Sep 17 00:00:00 2001 From: Eli Adelhult Date: Tue, 5 May 2026 10:56:56 +0200 Subject: [PATCH 3/4] Improve Cache API --- src/cache.ts | 152 +++++++++++++++++++++--------- src/commands/cache/command.ts | 2 +- src/commands/cache/info-impl.ts | 1 + src/commands/gxgames/link.ts | 2 +- src/commands/init/impl.ts | 2 +- src/commands/login/impl.ts | 5 +- src/commands/resourcetool/impl.ts | 2 +- src/common-compile-setup.ts | 2 +- src/get-latest-version.ts | 2 +- src/project.ts | 2 +- 10 files changed, 120 insertions(+), 52 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index fba3612..6489f74 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -21,6 +21,7 @@ import { version } from "../package.json"; import { z } from "zod"; import semver from "semver"; import { KnownError } from "./error"; +import { findProjectFile } from "./project"; /** The subset of the Context object that's used in the cache. * Needed because we make use of the cache in app.ts before the context object is constructed @@ -28,13 +29,20 @@ import { KnownError } from "./error"; type CacheCtx = Pick; export type CacheType = + /** Use a caller-specified absolute path as the local cache directory. Disables the shared cache. */ | { type: "absolute"; path: string } - | { type: "infer"; projectDir: string } + /** + * Infer the cache directory from GAMEMAKER_CLI_CACHE_DIR or current working dir. + * Shared cache is allowed unless GAMEMAKER_CLI_CACHE_DIR or CI env vars are set. projectDir can be set if + * the project is not in the working directory. + */ + | { type: "infer"; projectDir?: string } + /** Use a throwaway directory under the OS temp dir. Disables the shared cache. */ | { type: "temporary" } + /** Skip the local cache entirely and use only the shared system-wide cache. */ | { type: "shared-only" }; export class Cache { - private _localOnly: boolean; private _sharedPath: | { type: "not-allowed"; @@ -45,30 +53,45 @@ export class Cache { } | { type: "not-initialized"; + intendedPath: string; }; - // Local .gmcache directory private _localPath: | { - initialized: true; + type: "initialized"; path: string; } | { - initialized: false; - cacheType: CacheType; - }; + type: "not-initialized"; + intendedPath: string; + } + | { type: "not-allowed" }; - constructor(ctx: CacheCtx, cacheType: CacheType) { - this._localPath = { initialized: false, cacheType }; - // We don't allow using the shared cache if a user has specified an absolute or temporary - // path or if inside a CI runner. - this._localOnly = - cacheType.type === "absolute" || - cacheType.type === "temporary" || - ctx.env.CI === true; - this._sharedPath = this._localOnly - ? { type: "not-allowed" } - : { type: "not-initialized" }; + static async initLazy(ctx: CacheCtx, cacheType: CacheType): Promise { + const { path: localPath, allowShared } = await resolveLocalCachePath( + ctx, + cacheType, + ); + return new Cache( + localPath, + allowShared ? resolveSharedCachePath(ctx) : undefined, + ); + } + + private constructor( + localPath: string | undefined, + sharedPath: string | undefined, + ) { + if (localPath) { + this._localPath = { type: "not-initialized", intendedPath: localPath }; + } else { + this._localPath = { type: "not-allowed" }; + } + if (sharedPath) { + this._sharedPath = { type: "not-initialized", intendedPath: sharedPath }; + } else { + this._sharedPath = { type: "not-allowed" }; + } } private async initCachePath(ctx: CacheCtx, cachePath: string): Promise { @@ -100,30 +123,15 @@ export class Cache { } private async initLocal(ctx: CacheCtx): Promise { - if (this._localPath.initialized) { + if (this._localPath.type === "initialized") { return true; } - - // Resolve the path based on the cache type - const cacheType = this._localPath.cacheType; - let cachePath: string; - if (cacheType.type === "absolute") { - cachePath = cacheType.path; - } else if (cacheType.type === "infer" && ctx.env.GAMEMAKER_CLI_CACHE_DIR) { - cachePath = ctx.env.GAMEMAKER_CLI_CACHE_DIR; - } else if (cacheType.type === "infer") { - cachePath = ctx.path.join(cacheType.projectDir, ".gmcache"); - } else if (cacheType.type === "temporary") { - cachePath = ctx.path.join(ctx.os.tmpdir(), "gm-cli-cache"); - } else if (cacheType.type === "shared-only") { + if (this._localPath.type === "not-allowed") { return false; - } else { - cacheType satisfies never; - throw new Error("unreachable"); } - - await this.initCachePath(ctx, cachePath); - this._localPath = { initialized: true, path: cachePath }; + const path = this._localPath.intendedPath; + await this.initCachePath(ctx, path); + this._localPath = { type: "initialized", path }; return true; } @@ -149,7 +157,7 @@ export class Cache { // Not allowed to use shared cache return undefined; } - if (!this._localPath.initialized) { + if (this._localPath.type !== "initialized") { throw new Error("Unreachable: local cache should be initialized"); } return this._localPath.path; @@ -176,7 +184,7 @@ export class Cache { preferShared: false, }, ): Promise { - if (preferShared && !this._localOnly) { + if (preferShared && this._sharedPath.type !== "not-allowed") { return this.getSubDirPathShared(ctx, name); } return this.getSubDirPathLocal(ctx, name); @@ -187,8 +195,12 @@ export class Cache { name: string, ): Promise { // lazily create the cache directory if needed - await this.initLocal(ctx); - if (!this._localPath.initialized) { + if (!(await this.initLocal(ctx))) { + throw new Error( + "Invariant broken: getSubDirPathLocal should only be called when we know that it's allowed to use a local cache", + ); + } + if (this._localPath.type !== "initialized") { throw Error("Unreachable: local cache should be initialized."); } @@ -201,7 +213,11 @@ export class Cache { ctx: CacheCtx, name: string, ): Promise { - await this.initShared(ctx); + if (!(await this.initShared(ctx))) { + throw new Error( + "Invariant broken: getSubDirPathShared should only be called when we know that it's allowed to use a shared cache", + ); + } if (this._sharedPath.type !== "initialized") { throw Error("Unreachable: shared cache should be initialized."); } @@ -212,6 +228,56 @@ export class Cache { } } +/** Resolve the path based on the cache type and decide if we are allowed to + * used the shared cache as well. + */ +async function resolveLocalCachePath( + ctx: CacheCtx, + cacheType: CacheType, +): Promise<{ path?: string; allowShared: boolean }> { + const isCi = ctx.env.CI; + if (cacheType.type === "absolute") { + return { path: cacheType.path, allowShared: false }; + } + if (cacheType.type === "infer" && ctx.env.GAMEMAKER_CLI_CACHE_DIR) { + return { path: ctx.env.GAMEMAKER_CLI_CACHE_DIR, allowShared: false }; + } + if (cacheType.type === "infer" && cacheType.projectDir !== undefined) { + return { + path: ctx.path.join(cacheType.projectDir, ".gmcache"), + allowShared: !isCi, + }; + } + // Try using cwd if we can find a .yyp file + if (cacheType.type === "infer") { + const cwd = ctx.process.cwd(); + const projectPath = await findProjectFile(ctx, cwd); + if (projectPath === undefined) { + throw new KnownError( + "No .yyp project file found in the current directory", + ); + } + return { path: ctx.path.join(cwd, ".gmcache"), allowShared: !isCi }; + } + if (cacheType.type === "temporary") { + return { + path: ctx.path.join(ctx.os.tmpdir(), "gm-cli-cache"), + allowShared: false, + }; + } + if (cacheType.type === "shared-only") { + if (isCi) { + throw new Error( + "Invariant broken: Can't use a shared-only cache in CI since it does not allow shared caches", + ); + } + return { path: undefined, allowShared: !isCi }; + } + + cacheType satisfies never; + throw new Error("unreachable"); +} + function resolveSharedCachePath(ctx: CacheCtx): string { const home = ctx.os.homedir(); const platform = ctx.os.platform(); diff --git a/src/commands/cache/command.ts b/src/commands/cache/command.ts index 01b5377..49e34ef 100644 --- a/src/commands/cache/command.ts +++ b/src/commands/cache/command.ts @@ -92,7 +92,7 @@ export async function setupCache( } } - return new Cache(ctx, cacheType); + return Cache.initLazy(ctx, cacheType); } export function validateFlags(flags: CacheFlags): void { diff --git a/src/commands/cache/info-impl.ts b/src/commands/cache/info-impl.ts index 2cbedc3..359dc65 100644 --- a/src/commands/cache/info-impl.ts +++ b/src/commands/cache/info-impl.ts @@ -31,6 +31,7 @@ export default async function ( ): Promise { validateFlags(flags); const cache = await setupCache(this, flags); + // TODO: we may want to use lazy versions of these functions here instead const localPath = await cache._getInternalLocalPath(this); const sharedPath = await cache._getInternalSharedPath(this); this.process.stdout.write(chalk.bold("Shared cache\n")); diff --git a/src/commands/gxgames/link.ts b/src/commands/gxgames/link.ts index 481c8a3..d2a0cdb 100644 --- a/src/commands/gxgames/link.ts +++ b/src/commands/gxgames/link.ts @@ -48,7 +48,7 @@ async function readStore(ctx: Context): Promise { } async function writeStore(ctx: Context, store: GxGamesStore): Promise { - const cache = new Cache(ctx, { + const cache = await Cache.initLazy(ctx, { type: "infer", projectDir: ctx.process.cwd(), }); diff --git a/src/commands/init/impl.ts b/src/commands/init/impl.ts index c8f412e..6807378 100644 --- a/src/commands/init/impl.ts +++ b/src/commands/init/impl.ts @@ -104,7 +104,7 @@ export default async function ( } else { s.start("Downloading template"); s.message("Extracting template"); - const cache = new Cache( + const cache = await Cache.initLazy( this, flags.cacheDir ? { type: "absolute", path: flags.cacheDir } diff --git a/src/commands/login/impl.ts b/src/commands/login/impl.ts index 725f3d5..c0f2412 100644 --- a/src/commands/login/impl.ts +++ b/src/commands/login/impl.ts @@ -34,9 +34,10 @@ export default async function ( ? { type: "absolute", path: flags.cacheDir } : projectPath ? { type: "infer", projectDir: this.path.dirname(projectPath) } - : { type: "temporary" }; + : // It's fine not to use the cache in a project dir, if so we just use a temporary one + { type: "temporary" }; - const cache = new Cache(this, cacheType); + const cache = await Cache.initLazy(this, cacheType); if (cacheType.type === "temporary" && !flags.print) { throw new KnownError( diff --git a/src/commands/resourcetool/impl.ts b/src/commands/resourcetool/impl.ts index 1e9ccae..9d88122 100644 --- a/src/commands/resourcetool/impl.ts +++ b/src/commands/resourcetool/impl.ts @@ -47,7 +47,7 @@ export async function run( ); } - const cache = new Cache( + const cache = await Cache.initLazy( ctx, flags.cacheDir ? { type: "absolute", path: flags.cacheDir } diff --git a/src/common-compile-setup.ts b/src/common-compile-setup.ts index cdb735a..eca92df 100644 --- a/src/common-compile-setup.ts +++ b/src/common-compile-setup.ts @@ -174,7 +174,7 @@ export async function commonCompileSetup( ); } - const cache = new Cache( + const cache = await Cache.initLazy( ctx, flags.cacheDir ? { type: "absolute", path: flags.cacheDir } diff --git a/src/get-latest-version.ts b/src/get-latest-version.ts index 46ba75d..81b0ba4 100644 --- a/src/get-latest-version.ts +++ b/src/get-latest-version.ts @@ -48,7 +48,7 @@ export async function getLatestVersion(): Promise { // so let's skip the version check altogether return; } - const cache = new Cache(ctx, { type: "shared-only" }); + const cache = await Cache.initLazy(ctx, { type: "shared-only" }); const dir = await cache.getSubDirPath(ctx, "version-check", { preferShared: true, }); diff --git a/src/project.ts b/src/project.ts index 298c40f..668631c 100644 --- a/src/project.ts +++ b/src/project.ts @@ -27,7 +27,7 @@ export function parseProjectPath(s: string): ProjectPath { } export async function findProjectFile( - ctx: Context, + ctx: Pick, dir: string, ): Promise { const files = await ctx.fs.readdir(dir); From 474f50461b3e458520474791a49936d6a2c617c5 Mon Sep 17 00:00:00 2001 From: Eli Adelhult Date: Tue, 5 May 2026 13:13:14 +0200 Subject: [PATCH 4/4] Attempt improving the cache usage in gxgames subcommands --- src/commands/gxgames/auth.ts | 6 ++- src/commands/gxgames/link-impl.ts | 4 +- src/commands/gxgames/link.ts | 59 ++++++++++++++-------------- src/commands/gxgames/meta-impl.ts | 4 +- src/commands/gxgames/publish-impl.ts | 4 +- src/commands/gxgames/upload-impl.ts | 4 +- 6 files changed, 45 insertions(+), 36 deletions(-) diff --git a/src/commands/gxgames/auth.ts b/src/commands/gxgames/auth.ts index 0ec09bc..3dece68 100644 --- a/src/commands/gxgames/auth.ts +++ b/src/commands/gxgames/auth.ts @@ -18,6 +18,7 @@ import { KnownError } from "~/error"; import crypto from "node:crypto"; import type { Context } from "~/context"; import { readAuth, writeAuth } from "./link"; +import { Cache } from "~/cache"; import { AUTH_BASE, CLIENT_ID, @@ -98,7 +99,8 @@ export function createAuthManager(ctx: Context): AuthManager { } export async function authenticate(ctx: Context): Promise { - const cached = await readAuth(ctx); + const cache = await Cache.initLazy(ctx, { type: "infer" }); + const cached = await readAuth(ctx, cache); if (cached && cached.expiresAt > Date.now()) { return cached.accessToken; } @@ -121,7 +123,7 @@ export async function authenticate(ctx: Context): Promise { log.message("Waiting for browser login..."); const code = await codePromise; const { accessToken, expiresAt } = await exchangeCodeForToken(code, state); - await writeAuth(ctx, { accessToken, expiresAt }); + await writeAuth(ctx, { accessToken, expiresAt }, cache); log.success("Authenticated"); return accessToken; diff --git a/src/commands/gxgames/link-impl.ts b/src/commands/gxgames/link-impl.ts index 6c42c25..635ece3 100644 --- a/src/commands/gxgames/link-impl.ts +++ b/src/commands/gxgames/link-impl.ts @@ -21,6 +21,7 @@ import { createAuthManager } from "./auth"; import { getApiClient } from "./client"; import { unwrapResponse } from "./api/helpers"; import { writeLink } from "./link"; +import { Cache } from "~/cache"; export default async function ( this: Context, @@ -103,6 +104,7 @@ export default async function ( } } - await writeLink(this, { studioId, gameId }); + const cache = await Cache.initLazy(this, { type: "infer" }); + await writeLink(this, { studioId, gameId }, cache); p.log.success(`Linked to studio ${studioId}, game ${gameId}`); } diff --git a/src/commands/gxgames/link.ts b/src/commands/gxgames/link.ts index d2a0cdb..1642235 100644 --- a/src/commands/gxgames/link.ts +++ b/src/commands/gxgames/link.ts @@ -20,6 +20,7 @@ import { Cache } from "~/cache"; import { z } from "zod"; const STORE_FILENAME = "gxgames.json"; +const CACHE_SUBDIR = "gxgames"; const StoreSchema = z.object({ auth: z.object({ accessToken: z.string(), expiresAt: z.number() }).optional(), @@ -30,15 +31,9 @@ type GxGamesStore = z.infer; export type GxGamesLink = NonNullable; export type GxGamesAuth = NonNullable; -function resolveCacheDir(ctx: Context): string { - return ( - ctx.env.GAMEMAKER_CLI_CACHE_DIR ?? - ctx.path.join(ctx.process.cwd(), ".gmcache") - ); -} - -async function readStore(ctx: Context): Promise { - const storePath = ctx.path.join(resolveCacheDir(ctx), STORE_FILENAME); +async function readStore(ctx: Context, cache: Cache): Promise { + const dir = await cache.getSubDirPath(ctx, CACHE_SUBDIR); + const storePath = ctx.path.join(dir, STORE_FILENAME); try { const raw = await ctx.fs.readFile(storePath, "utf-8"); return StoreSchema.parse(JSON.parse(raw)); @@ -47,23 +42,22 @@ async function readStore(ctx: Context): Promise { } } -async function writeStore(ctx: Context, store: GxGamesStore): Promise { - const cache = await Cache.initLazy(ctx, { - type: "infer", - projectDir: ctx.process.cwd(), - }); - const cacheDir = await cache._getInternalLocalPath(ctx); - if (!cacheDir) { - throw new KnownError("Failed to initialize cache directory."); - } - await ctx.fs.writeFile( - ctx.path.join(cacheDir, STORE_FILENAME), - JSON.stringify(store, null, 2), - ); +async function writeStore( + ctx: Context, + store: GxGamesStore, + cache: Cache, +): Promise { + // TODO: later, we may want to store this as part of the "manifest" file instead under a "tools.gxgames" key. + const dir = await cache.getSubDirPath(ctx, CACHE_SUBDIR); + const storePath = ctx.path.join(dir, STORE_FILENAME); + await ctx.fs.writeFile(storePath, JSON.stringify(store, null, 2)); } -export async function readLink(ctx: Context): Promise { - const store = await readStore(ctx); +export async function readLink( + ctx: Context, + cache: Cache, +): Promise { + const store = await readStore(ctx, cache); if (!store.link) { throw new KnownError( "Game not linked. Run `gm-cli gxgames link --studioid --gameid ` first.", @@ -75,20 +69,25 @@ export async function readLink(ctx: Context): Promise { export async function writeLink( ctx: Context, link: GxGamesLink, + cache: Cache, ): Promise { - const store = await readStore(ctx); - await writeStore(ctx, { ...store, link }); + const store = await readStore(ctx, cache); + await writeStore(ctx, { ...store, link }, cache); } -export async function readAuth(ctx: Context): Promise { - const store = await readStore(ctx); +export async function readAuth( + ctx: Context, + cache: Cache, +): Promise { + const store = await readStore(ctx, cache); return store.auth; } export async function writeAuth( ctx: Context, auth: GxGamesAuth, + cache: Cache, ): Promise { - const store = await readStore(ctx); - await writeStore(ctx, { ...store, auth }); + const store = await readStore(ctx, cache); + await writeStore(ctx, { ...store, auth }, cache); } diff --git a/src/commands/gxgames/meta-impl.ts b/src/commands/gxgames/meta-impl.ts index a1bc621..d6f6f88 100644 --- a/src/commands/gxgames/meta-impl.ts +++ b/src/commands/gxgames/meta-impl.ts @@ -21,6 +21,7 @@ import { readLink } from "./link"; import { createAuthManager } from "./auth"; import { getApiClient } from "./client"; import { unwrapResponse } from "./api/helpers"; +import { Cache } from "~/cache"; import type { GameDevUpdateGameRequestAgeRatingEnum, GameDevUpdateGameRequestPlatformsEnum, @@ -57,7 +58,8 @@ interface MetaFlags { } export default async function (this: Context, flags: MetaFlags): Promise { - const link = await readLink(this); + const cache = await Cache.initLazy(this, { type: "infer" }); + const link = await readLink(this, cache); const api = getApiClient(this, createAuthManager(this)); const gameRes = await unwrapResponse(api.getGameDetails(link.gameId)); diff --git a/src/commands/gxgames/publish-impl.ts b/src/commands/gxgames/publish-impl.ts index fec557c..5784fdb 100644 --- a/src/commands/gxgames/publish-impl.ts +++ b/src/commands/gxgames/publish-impl.ts @@ -21,12 +21,14 @@ import { readLink } from "./link"; import { createAuthManager } from "./auth"; import { getApiClient } from "./client"; import { unwrapResponse } from "./api/helpers"; +import { Cache } from "~/cache"; export default async function ( this: Context, _flags: Record, ): Promise { - const link = await readLink(this); + const cache = await Cache.initLazy(this, { type: "infer" }); + const link = await readLink(this, cache); const api = getApiClient(this, createAuthManager(this)); const publishLog = this.makeTaskLogger("Publishing game"); diff --git a/src/commands/gxgames/upload-impl.ts b/src/commands/gxgames/upload-impl.ts index 0007bfc..0340cc4 100644 --- a/src/commands/gxgames/upload-impl.ts +++ b/src/commands/gxgames/upload-impl.ts @@ -21,13 +21,15 @@ import { createAuthManager } from "./auth"; import { unwrapResponse } from "./api/helpers"; import { KnownError } from "~/error"; import { readLink } from "./link"; +import { Cache } from "~/cache"; export default async function ( this: Context, flags: { version?: string }, file: string, ): Promise { - const link = await readLink(this); + const cache = await Cache.initLazy(this, { type: "infer" }); + const link = await readLink(this, cache); const api = getApiClient(this, createAuthManager(this));