UNPKG

shipthis

Version:

ShipThis manages building and uploading your Godot games to the App Store and Google Play.

123 lines (119 loc) 4.67 kB
import fs__default from 'node:fs'; import { useMutation } from '@tanstack/react-query'; import axios from 'axios'; import fg from 'fast-glob'; import { v4 } from 'uuid'; import { ZipFile } from 'yazl'; import { K as queryClient, v as DEFAULT_SHIPPED_FILES_GLOBS, w as DEFAULT_IGNORED_FILES_GLOBS, a4 as getNewUploadTicket, a5 as startJobsFromUpload } from './index-BwnzoldS.js'; import { c as cacheKeys } from './useAndroidServiceAccountTestResult-CwKeW0ED.js'; import { f as getFileHash, h as getPlatformName } from './index-CJWMt1s-.js'; import { g as getCWDGitInfo } from './git-BpsfNFZ_.js'; import { jsx, Fragment } from 'react/jsx-runtime'; import 'ink'; import 'ink-spinner'; import 'react'; import 'crypto-js'; import 'luxon'; import 'socket.io-client'; import { u as useJobWatching } from './JobLogTail-D35FO5v-.js'; import 'fullscreen-ink'; import 'string-length'; import 'strip-ansi'; import 'open'; import '@inkjs/ui'; import 'node:path'; import './ejs-DirFZbza.js'; import 'marked'; import 'marked-terminal'; import { P as ProgressSpinner } from './ProgressSpinner-Um6ARKlk.js'; import 'qrcode'; import './index-hoHfGrjg.js'; async function ship({ command, log = () => { }, shipFlags }) { log("Fetching game config..."); const projectConfig = await command.getProjectConfig(); if (!projectConfig.project) throw new Error("No project found in project config"); const hasConfiguredIos = Boolean(projectConfig.project.details?.iosBundleId); const hasConfiguredAndroid = Boolean(projectConfig.project.details?.androidPackageName); if (!hasConfiguredAndroid && !hasConfiguredIos) { throw new Error( "No Android or iOS configuration found. Please run `shipthis game wizard android` or `shipthis game wizard ios` to configure your game." ); } log("Retrieving file globs..."); const shippedFilesGlobs = projectConfig.shippedFilesGlobs || DEFAULT_SHIPPED_FILES_GLOBS; const ignoredFilesGlobs = projectConfig.ignoredFilesGlobs || DEFAULT_IGNORED_FILES_GLOBS; log("Finding files to include in zip..."); const files = await fg(shippedFilesGlobs, { dot: true, ignore: ignoredFilesGlobs }); log(`Found ${files.length} files, adding to zip...`); const zipFile = new ZipFile(); for (const file of files) { zipFile.addFile(file, file); } const outputZipToFile = (zip, fileName) => new Promise((resolve) => { const outputStream = fs__default.createWriteStream(fileName); zip.outputStream.pipe(outputStream).on("close", () => resolve()); zip.end(); }); const tmpZipFile = `${process.cwd()}/shipthis-${v4()}.zip`; log(`Creating zip file: ${tmpZipFile}`); await outputZipToFile(zipFile, tmpZipFile); log("Reading zip file buffer..."); const zipBuffer = fs__default.readFileSync(tmpZipFile); const { size } = fs__default.statSync(tmpZipFile); log("Requesting upload ticket..."); const uploadTicket = await getNewUploadTicket(projectConfig.project.id); log("Uploading zip file..."); await axios.put(uploadTicket.url, zipBuffer, { headers: { "Content-Type": "application/zip", "Content-length": size } }); log("Fetching Git info..."); const gitInfo = await getCWDGitInfo(); log("Computing file hash..."); const zipFileMd5 = await getFileHash(tmpZipFile); const uploadDetails = { ...gitInfo, zipFileMd5 }; log("Starting jobs from upload..."); const finalFlags = shipFlags || command.getFlags(); const startJobsOptions = { ...uploadDetails, platform: finalFlags.platform?.toUpperCase(), skipPublish: finalFlags.skipPublish }; const jobs = await startJobsFromUpload(uploadTicket.id, startJobsOptions); log("Cleaning up temporary zip file..."); fs__default.unlinkSync(tmpZipFile); log("Job submission complete."); if (jobs.length === 0) { throw new Error("No jobs were created. Please check your game configuration and try again."); } if (finalFlags?.follow) { log("Waiting for job to start..."); } return jobs; } const useShip = () => useMutation({ mutationFn: ship, async onSuccess(data) { queryClient.invalidateQueries({ queryKey: cacheKeys.jobs({ pageNumber: 0, projectId: data[0].project.id }) }); } }); const JobProgress = (props) => { const { progress } = useJobWatching({ isWatching: true, jobId: props.job.id, onComplete: props.onComplete, onFailure: props.onFailure, projectId: props.job.project.id }); const label = `${getPlatformName(props.job.type)} build progress...`; return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(ProgressSpinner, { label, progress, spinnerType: "dots" }) }); }; export { JobProgress as J, useShip as u };