diff --git a/.gitignore b/.gitignore index a511978cc..234bc651e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output -dist -tmp -/out-tsc -*.orig +# dist +# tmp +# /out-tsc +# *.orig # dependencies node_modules diff --git a/.npmrc.orig b/.npmrc.orig new file mode 100644 index 000000000..aee1af065 --- /dev/null +++ b/.npmrc.orig @@ -0,0 +1,4 @@ +link-workspace-packages=true +auto-install-peers=true +package-manager-strict=true +package-manager-strict-version=true diff --git a/package.json b/package.json index 246a15b67..44629474d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,25 @@ "version": "0.0.0", "license": "MIT", "type": "module", + "bin": { + "rock": "./packages/cli/dist/src/bin.js" + }, + "files": [ + "packages/cli", + "packages/config", + "packages/tools", + "packages/platform-android", + "packages/platform-harmony", + "packages/platform-ios", + "packages/platform-apple-helpers", + "packages/plugin-metro", + "packages/plugin-repack", + "packages/plugin-brownfield-android", + "packages/plugin-brownfield-ios", + "packages/provider-github", + "packages/provider-s3", + "pnpm-workspace.yaml" + ], "scripts": { "build": "pnpm -r run build", "test": "vitest run", @@ -20,8 +39,14 @@ "verdaccio:publish": "node ./scripts/verdaccio-publish.mjs", "verdaccio:reset": "./scripts/verdaccio-reset.sh" }, - "private": true, "dependencies": { + "@react-native-community/cli-config": "^20.0.0", + "@rock-js/config": "^0.11.9", + "@rock-js/tools": "^0.11.9", + "adm-zip": "^0.5.16", + "commander": "^12.1.0", + "node-apk": "^1.2.1", + "tar": "^7.5.1", "tslib": "^2.8.1" }, "devDependencies": { diff --git a/packages/cli/dist/src/bin.d.ts b/packages/cli/dist/src/bin.d.ts new file mode 100644 index 000000000..b7988016d --- /dev/null +++ b/packages/cli/dist/src/bin.d.ts @@ -0,0 +1,2 @@ +#!/usr/bin/env node +export {}; diff --git a/packages/cli/dist/src/bin.js b/packages/cli/dist/src/bin.js new file mode 100755 index 000000000..41e37c09c --- /dev/null +++ b/packages/cli/dist/src/bin.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +import { cli } from './lib/cli.js'; +cli({ + argv: process.argv, + cwd: process.cwd(), +}); +//# sourceMappingURL=bin.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/bin.js.map b/packages/cli/dist/src/bin.js.map new file mode 100644 index 000000000..90785c513 --- /dev/null +++ b/packages/cli/dist/src/bin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,GAAG,CAAC;IACF,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;CACnB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/cli/dist/src/index.d.ts b/packages/cli/dist/src/index.d.ts new file mode 100644 index 000000000..78dea6bec --- /dev/null +++ b/packages/cli/dist/src/index.d.ts @@ -0,0 +1,2 @@ +export * from './lib/cli.js'; +export type { Config } from '@rock-js/config'; diff --git a/packages/cli/dist/src/index.js b/packages/cli/dist/src/index.js new file mode 100644 index 000000000..bfaed4f5f --- /dev/null +++ b/packages/cli/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/cli.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/index.js.map b/packages/cli/dist/src/index.js.map new file mode 100644 index 000000000..eef485fa0 --- /dev/null +++ b/packages/cli/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/adHocTemplates.d.ts b/packages/cli/dist/src/lib/adHocTemplates.d.ts new file mode 100644 index 000000000..ed87dc873 --- /dev/null +++ b/packages/cli/dist/src/lib/adHocTemplates.d.ts @@ -0,0 +1,18 @@ +export declare function templateIndexHtmlIOS({ appName, version, bundleIdentifier, }: { + appName: string; + version: string; + bundleIdentifier: string; +}): string; +export declare function templateManifestPlist({ baseUrl, ipaName, bundleIdentifier, version, appName, platformIdentifier, }: { + baseUrl: string; + ipaName: string; + bundleIdentifier: string; + version: string; + appName: string; + platformIdentifier: string; +}): string; +export declare function templateIndexHtmlAndroid({ appName, version, packageName, }: { + appName: string; + version: string; + packageName: string; +}): string; diff --git a/packages/cli/dist/src/lib/adHocTemplates.js b/packages/cli/dist/src/lib/adHocTemplates.js new file mode 100644 index 000000000..73d62f321 --- /dev/null +++ b/packages/cli/dist/src/lib/adHocTemplates.js @@ -0,0 +1,415 @@ +// Template functions for ad-hoc iOS and Android distribution +// Shared CSS styles for both iOS and Android templates +const sharedStyles = ` + :root { + /* Light mode variables */ + --bg-primary: #ffffff; + --bg-secondary: #f5f5f7; + --text-primary: #1d1d1f; + --text-secondary: #86868b; + --accent-primary: #8232ff; + --accent-hover: rgba(130, 50, 255, 0.3); + --border-color: #e5e5e7; + --shadow-color: rgba(0, 0, 0, 0.1); + } + + @media (prefers-color-scheme: dark) { + :root { + /* Dark mode variables */ + --bg-primary: #1c1c1e; + --bg-secondary: #2c2c2e; + --text-primary: #ffffff; + --text-secondary: #8e8e93; + --accent-primary: #8232ff; + --accent-hover: rgba(130, 50, 255, 0.4); + --border-color: #38383a; + --shadow-color: rgba(0, 0, 0, 0.3); + } + } + + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + Oxygen, Ubuntu, Cantarell, sans-serif; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + font-size: 16px; + background-color: var(--bg-primary); + color: var(--text-primary); + transition: background-color 0.3s ease, color 0.3s ease; + } + + .container { + text-align: center; + max-width: 500px; + width: 100%; + } + + .app-icon { + width: 100px; + height: 100px; + margin: 0 auto 15px; + display: flex; + align-items: center; + justify-content: center; + font-size: 48px; + color: var(--text-primary); + background: var(--bg-secondary); + border-radius: 25px; + transition: background-color 0.3s ease; + } + + h1 { + color: var(--text-primary); + font-size: 28px; + font-weight: 600; + margin-bottom: 15px; + overflow-wrap: break-word; + transition: color 0.3s ease; + } + + .subtitle { + color: var(--text-secondary); + font-size: 16px; + line-height: 1.5; + margin-bottom: 30px; + transition: color 0.3s ease; + } + + .version { + color: var(--text-primary); + font-size: 16px; + line-height: 1.5; + margin-bottom: 10px; + transition: color 0.3s ease; + } + + .download-button { + background: var(--accent-primary); + color: white; + border: none; + padding: 16px 32px; + border-radius: 4px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + text-decoration: none; + display: inline-block; + margin-bottom: 20px; + box-shadow: 0 4px 12px var(--shadow-color); + } + + .download-button:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px var(--accent-hover); + } + + .download-button:active { + transform: translateY(0); + } + + .instructions { + background: var(--bg-secondary); + border-radius: 4px; + padding: 20px; + margin-top: 20px; + text-align: left; + border: 1px solid var(--border-color); + transition: background-color 0.3s ease, border-color 0.3s ease; + } + + .instructions h3 { + color: var(--text-primary); + font-size: 16px; + margin-bottom: 10px; + transition: color 0.3s ease; + } + + .instructions ol { + color: var(--text-secondary); + font-size: 14px; + line-height: 1.6; + padding-left: 20px; + transition: color 0.3s ease; + } + + .instructions li { + margin-bottom: 8px; + } + + .adhoc-info { + text-align: left; + margin-top: 20px; + padding: 1em 2em; + border-left: 3px solid var(--accent-primary); + background: var(--bg-primary); + border-radius: 4px; + transition: background-color 0.3s ease; + } + + .adhoc-info-title { + font-weight: 600; + margin-bottom: 10px; + color: var(--text-primary); + transition: color 0.3s ease; + } + + .adhoc-info-text { + color: var(--text-primary); + margin: 0; + transition: color 0.3s ease; + } + + .footer { + text-align: center; + margin-top: 40px; + font-size: 12px; + color: var(--text-secondary); + transition: color 0.3s ease; + } + + .link { + color: var(--accent-primary); + text-decoration: none; + transition: color 0.3s ease; + } + + .link:hover { + text-decoration: underline; + } + + .toast { + padding: 1em 3em; + font-size: 14px; + border: 1px solid var(--accent-primary); + color: var(--text-primary); + position: fixed; + bottom: 1em; + left: 50%; + transform: translateX(-50%); + max-width: 500px; + width: calc(100% - 2em); + text-align: left; + border-radius: 4px; + background-color: var(--bg-primary); + display: none; + box-shadow: 0 8px 24px var(--shadow-color); + transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease; + } + + .toast-visible { + display: block; + animation: slideUp 0.3s ease; + } + + @keyframes slideUp { + from { + opacity: 0; + transform: translateX(-50%) translateY(20px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } + } + + .toast-icon { + font-size: 1em; + position: absolute; + left: 1em; + top: 50%; + transform: translateY(-50%); + } + + .toast-close { + font-size: 1em; + padding: 0.5em; + cursor: pointer; + position: absolute; + right: 1em; + top: 50%; + transform: translateY(-50%); + color: var(--text-secondary); + transition: color 0.3s ease; + } + + .toast-close:hover { + color: var(--text-primary); + } + + /* Smooth transitions for all elements */ + * { + transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; + } +`; +// Shared footer HTML +const sharedFooter = ` + +`; +// Shared toast functions for both iOS and Android templates +const sharedToastFunctions = () => ` + function showToast() { + setTimeout(() => { + const toast = document.getElementById('home-screen-toast'); + toast.classList.add('toast-visible'); + }, 2000); + } + + function hideToast() { + const toast = document.getElementById('home-screen-toast'); + toast.classList.remove('toast-visible'); + } +`; +// Base template function for creating ad-hoc distribution pages +function createAdHocTemplate({ platform, appName, version, identifier, icon, buttonText, toastMessage, script, instructions, adhocDescription, }) { + return ` + + + + + Download ${appName} for ${platform} + + + +
+
${icon}
+ +
+ ๐Ÿ’ก +

${toastMessage}

+ โœ• +
+ +

${appName}

+

${identifier} (${version})

+

+ Download and install the latest version of our ${platform} app directly to your + device. +

+ + + ${buttonText} + + + + +
+

Installation Instructions:

+
    ${instructions}
+
+ +
+

Ad-hoc Distribution

+

+ ${adhocDescription} +

+ Learn more at Rock Ad-hoc documentation. +

+
+ ${sharedFooter} +
+ + +`; +} +export function templateIndexHtmlIOS({ appName, version, bundleIdentifier, }) { + return createAdHocTemplate({ + platform: 'iOS', + appName, + version, + identifier: bundleIdentifier, + icon: '๐Ÿ“ฑ', + buttonText: 'Install App', + toastMessage: 'Check Home Screen to see installation progress', + script: ` + // Update the link dynamically to point to the manifest.plist + const link = document.getElementById('action-button'); + const currentUrl = window.location.href; + const manifestUrl = currentUrl.replace('index.html', 'manifest.plist'); + link.href = \`itms-services://?action=download-manifest&url=\${encodeURIComponent(manifestUrl)}\`; + ${sharedToastFunctions()} + `, + instructions: ` +
  • Tap the "Install App" button above
  • +
  • When prompted, tap "Install" in the popup dialog
  • +
  • The app will now start installing and will be available on your home screen
  • + `, + adhocDescription: "This app is distributed via ad-hoc distribution for testing purposes. Your device must either be enrolled in enterprise distribution or have its UDID added to the app's provisioning profile.", + }); +} +export function templateManifestPlist({ baseUrl, ipaName, bundleIdentifier, version, appName, platformIdentifier, }) { + return ` + + + + items + + + assets + + + kind + software-package + url + ${baseUrl}/${ipaName} + + + metadata + + bundle-identifier + ${bundleIdentifier} + bundle-version + ${version} + kind + software + platform-identifier + ${platformIdentifier ?? 'com.apple.platform.iphoneos'} + title + ${appName} + + + + + `; +} +export function templateIndexHtmlAndroid({ appName, version, packageName, }) { + return createAdHocTemplate({ + platform: 'Android', + appName, + version, + identifier: packageName, + icon: '๐Ÿค–', + buttonText: 'Download APK', + toastMessage: 'APK download started. Check your notifications to install.', + script: ` + // Update the link dynamically to point to the APK file + const link = document.getElementById('action-button'); + const currentUrl = window.location.href; + const apkFileName = '${appName}.apk'; + link.href = currentUrl.replace('index.html', apkFileName); + ${sharedToastFunctions()} + `, + instructions: ` +
  • Tap the "Download APK" button above
  • +
  • Once downloaded, open the APK file from your notifications or downloads folder
  • +
  • If prompted, enable "Install from Unknown Sources" in your device settings
  • +
  • Follow the on-screen prompts to complete the installation
  • + `, + adhocDescription: 'This app is distributed via ad-hoc distribution for testing purposes. You may need to enable installation from unknown sources in your Android device settings.', + }); +} +//# sourceMappingURL=adHocTemplates.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/adHocTemplates.js.map b/packages/cli/dist/src/lib/adHocTemplates.js.map new file mode 100644 index 000000000..f1c29eb16 --- /dev/null +++ b/packages/cli/dist/src/lib/adHocTemplates.js.map @@ -0,0 +1 @@ +{"version":3,"file":"adHocTemplates.js","sourceRoot":"","sources":["../../../src/lib/adHocTemplates.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,uDAAuD;AACvD,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0PpB,CAAC;AAEF,qBAAqB;AACrB,MAAM,YAAY,GAAG;;;;;;;CAOpB,CAAC;AAEF,4DAA4D;AAC5D,MAAM,oBAAoB,GAAG,GAAG,EAAE,CAAC;;;;;;;;;;;;CAYlC,CAAC;AAEF,gEAAgE;AAChE,SAAS,mBAAmB,CAAC,EAC3B,QAAQ,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,gBAAgB,GAYjB;IACC,OAAO;;;;;sBAKa,OAAO,QAAQ,QAAQ;aAChC,YAAY;;;;8BAIK,IAAI;;;;aAIrB,YAAY;;;;YAIb,OAAO;2BACQ,UAAU,KAAK,OAAO;;yDAEQ,QAAQ;;;;;UAKvD,UAAU;;;gBAGJ,MAAM;;;;cAIR,YAAY;;;;;;YAMd,gBAAgB;;;;;QAKpB,YAAY;;;;CAInB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,EACnC,OAAO,EACP,OAAO,EACP,gBAAgB,GAKjB;IACC,OAAO,mBAAmB,CAAC;QACzB,QAAQ,EAAE,KAAK;QACf,OAAO;QACP,OAAO;QACP,UAAU,EAAE,gBAAgB;QAC5B,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,aAAa;QACzB,YAAY,EAAE,gDAAgD;QAC9D,MAAM,EAAE;;;;;;QAMJ,oBAAoB,EAAE;KACzB;QACD,YAAY,EAAE;;;;KAIb;QACD,gBAAgB,EACd,gMAAgM;KACnM,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,EACpC,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,kBAAkB,GAQnB;IACC,OAAO;;;;;;;;;;;;;gCAauB,OAAO,IAAI,OAAO;;;;;;4BAMtB,gBAAgB;;4BAEhB,OAAO;;;;4BAKf,kBAAkB,IAAI,6BACxB;;4BAEU,OAAO;;;;;aAKtB,CAAC;AACd,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,EACvC,OAAO,EACP,OAAO,EACP,WAAW,GAKZ;IACC,OAAO,mBAAmB,CAAC;QACzB,QAAQ,EAAE,SAAS;QACnB,OAAO;QACP,OAAO;QACP,UAAU,EAAE,WAAW;QACvB,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,cAAc;QAC1B,YAAY,EAAE,4DAA4D;QAC1E,MAAM,EAAE;;;;6BAIiB,OAAO;;QAE5B,oBAAoB,EAAE;KACzB;QACD,YAAY,EAAE;;;;;KAKb;QACD,gBAAgB,EACd,iKAAiK;KACpK,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/checkDeprecatedOptions.d.ts b/packages/cli/dist/src/lib/checkDeprecatedOptions.d.ts new file mode 100644 index 000000000..e50677ebb --- /dev/null +++ b/packages/cli/dist/src/lib/checkDeprecatedOptions.d.ts @@ -0,0 +1 @@ +export declare const checkDeprecatedOptions: (argv: string[]) => void; diff --git a/packages/cli/dist/src/lib/checkDeprecatedOptions.js b/packages/cli/dist/src/lib/checkDeprecatedOptions.js new file mode 100644 index 000000000..03dcc0d04 --- /dev/null +++ b/packages/cli/dist/src/lib/checkDeprecatedOptions.js @@ -0,0 +1,60 @@ +import { color, logger } from '@rock-js/tools'; +const npxBin = 'npx rock'; +const checkDeprecatedCommand = (argv, oldCmd, newCmd, deprecatedFlags) => { + if (argv.includes(oldCmd)) { + const args = argv.slice(argv.indexOf(oldCmd) + 1); + const formattedFlags = getFormattedFlagsArray(deprecatedFlags, args); + logger.error(`The "${oldCmd}" command was renamed to "${newCmd}".`); + logFlagsAndCommand(formattedFlags, newCmd, args, deprecatedFlags); + process.exit(1); + } +}; +const checkCurrentCommand = (argv, cmd, deprecatedFlags) => { + if (argv.includes(cmd)) { + const args = argv.slice(argv.indexOf(cmd) + 1); + const formattedFlags = getFormattedFlagsArray(deprecatedFlags, args); + if (formattedFlags.length > 0) { + logFlagsAndCommand(formattedFlags, cmd, args, deprecatedFlags); + process.exit(1); + } + } +}; +function getFormattedFlagsArray(flags, args) { + return flags + .map(({ old, new: newFlag }) => args.includes(old) + ? `โ€ข "${color.bold(old)}" changed to "${color.bold(newFlag)}"` + : undefined) + .filter(Boolean); +} +function logFlagsAndCommand(formattedFlags, cmd, args, deprecatedFlags) { + if (formattedFlags.length > 0) { + logger.error(`Found deprecated flags: +${formattedFlags.join('\n')}`); + } + const newArgs = args.map((arg) => { + const newFlag = deprecatedFlags.find((flag) => arg === flag.old); + return newFlag ? newFlag.new : arg; + }); + logger.error(`Use new command${formattedFlags ? ' with new flags' : ''}: + ${color.bold(npxBin)} ${color.bold(cmd)} ${color.bold(newArgs.join(' '))}`); +} +const deprecatedAndroidFlags = [ + { old: '--mode', new: '--variant' }, + { old: '--appId', new: '--app-id' }, + { old: '--appIdSuffix', new: '--app-id-suffix' }, + { old: '--no-remote-cache', new: '--local' }, +]; +const deprecatedIosFlags = [ + { old: '--mode', new: '--configuration' }, + { old: '--buildFolder', new: '--build-folder' }, + { old: '--no-remote-cache', new: '--local' }, +]; +export const checkDeprecatedOptions = (argv) => { + // Check deprecated commands + checkDeprecatedCommand(argv, 'run-android', 'run:android', deprecatedAndroidFlags); + checkDeprecatedCommand(argv, 'run-ios', 'run:ios', deprecatedIosFlags); + // Check current commands for deprecated flags + checkCurrentCommand(argv, 'run:android', deprecatedAndroidFlags); + checkCurrentCommand(argv, 'run:ios', deprecatedIosFlags); +}; +//# sourceMappingURL=checkDeprecatedOptions.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/checkDeprecatedOptions.js.map b/packages/cli/dist/src/lib/checkDeprecatedOptions.js.map new file mode 100644 index 000000000..37317ba01 --- /dev/null +++ b/packages/cli/dist/src/lib/checkDeprecatedOptions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"checkDeprecatedOptions.js","sourceRoot":"","sources":["../../../src/lib/checkDeprecatedOptions.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/cli.d.ts b/packages/cli/dist/src/lib/cli.d.ts new file mode 100644 index 000000000..b5ab78633 --- /dev/null +++ b/packages/cli/dist/src/lib/cli.d.ts @@ -0,0 +1,6 @@ +type CliOptions = { + cwd: string; + argv: string[]; +}; +export declare const cli: ({ cwd, argv }: CliOptions) => Promise; +export {}; diff --git a/packages/cli/dist/src/lib/cli.js b/packages/cli/dist/src/lib/cli.js new file mode 100644 index 000000000..81f20da97 --- /dev/null +++ b/packages/cli/dist/src/lib/cli.js @@ -0,0 +1,101 @@ +import { createRequire } from 'node:module'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { getConfig } from '@rock-js/config'; +import { colorLink, logger, resolveFilenameUp, RockError, } from '@rock-js/tools'; +import { Command } from 'commander'; +import { checkDeprecatedOptions } from './checkDeprecatedOptions.js'; +import { cleanPlugin } from './plugins/clean.js'; +import { fingerprintPlugin } from './plugins/fingerprint.js'; +import { logConfigPlugin } from './plugins/logConfig.js'; +import { remoteCachePlugin } from './plugins/remoteCache.js'; +const require = createRequire(import.meta.url); +const __dirname = dirname(fileURLToPath(import.meta.url)); +const { version } = require(resolveFilenameUp(__dirname, 'package.json')); +export const cli = async ({ cwd, argv }) => { + if (argv) { + logger.setVerbose(argv.includes('--verbose')); + checkDeprecatedOptions(argv); + } + const program = new Command(); + program + .name('rock') + .description('Rock CLI.') + .option('--verbose', 'enable verbose logging') + .version(version); + const internalPlugins = [ + remoteCachePlugin, + logConfigPlugin, + fingerprintPlugin, + cleanPlugin, + ]; + // Register commands from the config + const config = await getConfig(cwd, internalPlugins); + ensureUniqueCommands(config.commands); + config.commands?.forEach((command) => { + const cmd = program + .command(command.name) + .description(command.description || '') + .action(async (...args) => { + try { + await command.action(...args); + } + catch (error) { + if (error instanceof RockError) { + if (logger.isVerbose()) { + logger.error(error); + } + else { + logger.error(error.message); + if (error.cause) { + logger.error(`Cause: ${error.cause}`); + } + } + } + else { + logger.error(`Unexpected error while running "${command.name}":`, error); + } + process.exit(1); + } + }); + // Positional args + for (const arg of command.args || []) { + cmd.argument(arg.name, arg.description, arg.default); + } + // Flags + for (const opt of command.options || []) { + // Note: we cannot use default idempotent parse, as it prevents us from using variadic options. + if (opt.parse) { + cmd.option(opt.name, opt.description, opt.parse, opt.default); + } + else { + cmd.option(opt.name, opt.description, opt.default); + } + } + }); + await program.parseAsync(argv); +}; +function ensureUniqueCommands(commands) { + if (!commands) + return; + const commandNames = new Map(); + for (const command of commands) { + if (commandNames.has(command.name)) { + const duplicate = commandNames.get(command.name); + const samePluginTwice = command.__origin === duplicate.__origin; + if (samePluginTwice) { + logger.error(`Found duplicated command "${command.name}" registered twice by the same "${command.__origin}" plugin in ${colorLink('rock.config.mjs')} file. +Please declare the plugin only once.`); + } + else { + logger.error(`Found duplicated command "${command.name}" registered by 2 plugins in ${colorLink('rock.config.mjs')} file: +1. Added by "${command.__origin}" plugin +2. Added by "${duplicate.__origin}" plugin +Command names must be unique. Please check if you import a plugin multiple times or use incompatible plugins.`); + } + process.exit(1); + } + commandNames.set(command.name, command); + } +} +//# sourceMappingURL=cli.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/cli.js.map b/packages/cli/dist/src/lib/cli.js.map new file mode 100644 index 000000000..19a09ec0a --- /dev/null +++ b/packages/cli/dist/src/lib/cli.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/lib/cli.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/clean.d.ts b/packages/cli/dist/src/lib/plugins/clean.d.ts new file mode 100644 index 000000000..7e428c053 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/clean.d.ts @@ -0,0 +1,2 @@ +import type { PluginApi, PluginOutput } from '@rock-js/config'; +export declare const cleanPlugin: () => (api: PluginApi) => PluginOutput; diff --git a/packages/cli/dist/src/lib/plugins/clean.js b/packages/cli/dist/src/lib/plugins/clean.js new file mode 100644 index 000000000..eafc45dfd --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/clean.js @@ -0,0 +1,317 @@ +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { getProjectRoot, intro, logger, outro, promptMultiselect, RockError, spawn, spinner, } from '@rock-js/tools'; +const CLEANUP_TASK_NAMES = [ + 'android', + 'gradle', + 'cocoapods', + 'metro', + 'watchman', + 'node_modules', + 'npm', + 'yarn', + 'bun', + 'pnpm', + 'rock', +]; +/** + * Validates that the provided task names are valid cleanup tasks. + * @param taskNames - Array of task names to validate + * @throws {RockError} If any task names are invalid + */ +function validateCleanupTasks(taskNames) { + const invalidTasks = taskNames.filter((name) => !CLEANUP_TASK_NAMES.includes(name)); + if (invalidTasks.length > 0) { + throw new RockError(`Invalid cleanup task(s): ${invalidTasks.join(', ')}. ` + + `Valid options are: ${CLEANUP_TASK_NAMES.join(', ')}`); + } +} +function removeDirectorySync(dirPath) { + if (fs.existsSync(dirPath)) { + try { + fs.rmSync(dirPath, { recursive: true, force: true }); + logger.debug(`Cleaned directory: ${dirPath}`); + } + catch (error) { + logger.debug(`Failed to clean directory ${dirPath}: ${error}`); + } + } +} +/** + * Checks if a project has Metro configuration. + * @param projectRoot - The root directory of the project + * @returns True if the project has Metro configuration, false otherwise + */ +function hasMetroProject(projectRoot) { + const metroConfig = path.join(projectRoot, 'metro.config.js'); + const metroConfigTs = path.join(projectRoot, 'metro.config.ts'); + const packageJsonPath = path.join(projectRoot, 'package.json'); + if (fs.existsSync(metroConfig) || fs.existsSync(metroConfigTs)) { + return true; + } + if (fs.existsSync(packageJsonPath)) { + try { + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + return (packageJson.dependencies?.metro || packageJson.devDependencies?.metro); + } + catch { + return false; + } + } + return false; +} +/** + * Cleans temporary directories that match a given pattern. + * @param pattern - The pattern to match temporary directory names + */ +function cleanTempDirectoryPattern(pattern) { + const tmpDir = os.tmpdir(); + try { + const tmpDirContents = fs.readdirSync(tmpDir); + const matchingFiles = tmpDirContents + .filter((name) => name.startsWith(pattern)) + .map((name) => path.join(tmpDir, name)); + for (const file of matchingFiles) { + removeDirectorySync(file); + } + } + catch (error) { + logger.debug(`${pattern} cache cleanup failed: ${error}`); + } +} +/** + * Cleans multiple directories by removing them recursively. + * @param directories - Array of directory paths to clean + * @param baseDir - Base directory to resolve relative paths from + */ +function cleanDirectories(directories, baseDir) { + for (const dir of directories) { + const fullPath = path.isAbsolute(dir) ? dir : path.join(baseDir, dir); + removeDirectorySync(fullPath); + } +} +/** + * Creates an array of cleanup tasks for a specific project. + * @param projectRoot - The root directory of the project + * @param options - Clean options that affect task creation + * @returns Array of cleanup tasks with their configurations + */ +function createCleanupTasks(projectRoot, options) { + const tasks = []; + // Android cleanup + tasks.push({ + name: 'android', + description: '[Android] Gradle build and cache (.gradle, build, .cxx)', + enabled: true, + action: async () => { + const androidDir = path.join(projectRoot, 'android'); + if (fs.existsSync(androidDir)) { + // Clean Android build directories + const directoriesToClean = ['.gradle', 'build', '.cxx']; + cleanDirectories(directoriesToClean, androidDir); + } + }, + }); + // Gradlew cleanup (separate task for slower operation) + tasks.push({ + name: 'gradle', + description: '[Android] gradlew clean', + enabled: true, + action: async () => { + const androidDir = path.join(projectRoot, 'android'); + const gradlewPath = path.join(androidDir, 'gradlew'); + if (fs.existsSync(gradlewPath)) { + await spawn(gradlewPath, ['clean'], { cwd: androidDir }); + } + }, + }); + // CocoaPods cleanup + tasks.push({ + name: 'cocoapods', + description: '[iOS] CocoaPods cache and Pods directory', + enabled: true, + action: async () => { + const iosDir = path.join(projectRoot, 'ios'); + if (fs.existsSync(iosDir)) { + // Remove Pods directory + cleanDirectories(['Pods'], iosDir); + // Clean CocoaPods cache + try { + await spawn('bundle', ['exec', 'pod', 'cache', 'clean', '--all'], { + cwd: iosDir, + }); + } + catch (error) { + logger.debug(`Bundle exec pod cache clean failed: ${error}`); + await spawn('pod', ['cache', 'clean', '--all'], { cwd: iosDir }); + } + } + cleanDirectories(['.cocoapods'], os.homedir()); + }, + }); + // Metro cleanup + tasks.push({ + name: 'metro', + description: '[JS] Metro and haste-map caches', + enabled: true, + action: async () => { + cleanTempDirectoryPattern('metro-'); + cleanTempDirectoryPattern('haste-map'); + }, + }); + // Watchman cleanup (only for Metro projects) + const hasMetro = hasMetroProject(projectRoot); + tasks.push({ + name: 'watchman', + description: '[JS] Watchman cache for this project', + enabled: hasMetro, + action: async () => { + if (hasMetro) { + await spawn('watchman', ['watch-del', projectRoot]); + } + }, + }); + // node_modules cleanup + tasks.push({ + name: 'node_modules', + description: '[JS] node_modules', + enabled: true, + action: async () => { + cleanDirectories(['node_modules'], projectRoot); + }, + }); + // NPM cleanup + tasks.push({ + name: 'npm', + description: '[JS] NPM cache ', + enabled: options['verify-cache'] ?? false, + action: async () => { + await spawn('npm', ['cache', 'verify']); + }, + }); + // Yarn cleanup + tasks.push({ + name: 'yarn', + description: '[JS] Yarn cache', + enabled: true, + action: async () => { + await spawn('yarn', ['cache', 'clean']); + }, + }); + // Bun cleanup + tasks.push({ + name: 'bun', + description: '[JS] Bun cache', + enabled: true, + action: async () => { + await spawn('bun', ['pm', 'cache', 'rm']); + }, + }); + // PNPM cleanup + tasks.push({ + name: 'pnpm', + description: '[JS] pnpm cache', + enabled: true, + action: async () => { + await spawn('pnpm', ['store', 'prune']); + }, + }); + // Rock cleanup + tasks.push({ + name: 'rock', + description: '[Rock] project cache and build artifacts (iOS/Android)', + enabled: true, + action: async () => { + const rockCacheDir = path.join(projectRoot, '.rock', 'cache'); + // Clean project cache file + const projectCacheFile = path.join(rockCacheDir, 'project.json'); + removeDirectorySync(projectCacheFile); + // Clean remote build cache directory + cleanDirectories(['remote-build'], rockCacheDir); + // Clean iOS archive and export cache directory + cleanDirectories(['ios'], rockCacheDir); + // Clean Android build cache directory + cleanDirectories(['android'], rockCacheDir); + }, + }); + return tasks; +} +/** + * Executes cleanup tasks for a specific project. + * @param projectRoot - The root directory of the project to clean + * @param options - Clean options that determine which tasks to run + */ +async function cleanProject(projectRoot, options) { + const tasks = createCleanupTasks(projectRoot, options); + let selectedTasks; + const availableTasks = tasks.filter((task) => task.enabled); + if (options.include && options.include.length > 0) { + validateCleanupTasks(options.include); + selectedTasks = tasks.filter((task) => options.include?.includes(task.name) && task.enabled); + } + else if (options.all) { + selectedTasks = availableTasks; + } + else { + const selected = await promptMultiselect({ + message: 'Select caches to clean:', + options: availableTasks.map((task) => ({ + value: task.name, + label: task.description, + })), + }); + selectedTasks = tasks.filter((task) => selected.includes(task.name)); + } + for (const task of selectedTasks) { + const taskSpinner = spinner(); + taskSpinner.start(`Cleaning ${task.description}`); + try { + await task.action(); + taskSpinner.stop(`Success: ${task.description}`); + } + catch (error) { + taskSpinner.stop(`Failure: ${task.description}`, 1); + logger.debug(`Task ${task.name} failed: ${error}`); + } + } +} +/** + * Main command function that handles the overall clean operation. + * @param options - Clean options that control the cleanup behavior + */ +async function cleanCommand(options) { + intro('๐Ÿงน Rock Clean'); + const projectRoot = getProjectRoot(); + await cleanProject(projectRoot, options); + outro('Success ๐ŸŽ‰.'); +} +export const cleanPlugin = () => (api) => { + api.registerCommand({ + name: 'clean', + description: 'Clean caches and build artifacts for Rock projects', + action: async (options) => { + await cleanCommand(options); + }, + options: [ + { + name: '--include ', + description: `Comma-separated list of caches to clear (${CLEANUP_TASK_NAMES.join(', ')})`, + parse: (val) => val.split(','), + }, + { + name: '--verify-cache', + description: 'Whether to verify the cache (currently only applies to npm cache)', + }, + { + name: '--all', + description: 'Clean all available caches without interactive prompt', + }, + ], + }); + return { + name: 'internal_clean', + description: 'Clean plugin for Rock projects', + }; +}; +//# sourceMappingURL=clean.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/clean.js.map b/packages/cli/dist/src/lib/plugins/clean.js.map new file mode 100644 index 000000000..66d797959 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/clean.js.map @@ -0,0 +1 @@ +{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../../../src/lib/plugins/clean.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/fingerprint.d.ts b/packages/cli/dist/src/lib/plugins/fingerprint.d.ts new file mode 100644 index 000000000..20af78f94 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/fingerprint.d.ts @@ -0,0 +1,12 @@ +import type { PluginApi } from '@rock-js/config'; +import type { FingerprintSources } from '@rock-js/tools'; +type NativeFingerprintCommandOptions = { + platform: 'ios' | 'android' | 'harmony'; + raw?: boolean; +}; +export declare function nativeFingerprintCommand(path: string, { extraSources, ignorePaths, env }: FingerprintSources, options: NativeFingerprintCommandOptions): Promise; +export declare const fingerprintPlugin: () => (api: PluginApi) => { + name: string; + description: string; +}; +export {}; diff --git a/packages/cli/dist/src/lib/plugins/fingerprint.js b/packages/cli/dist/src/lib/plugins/fingerprint.js new file mode 100644 index 000000000..8f863cb90 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/fingerprint.js @@ -0,0 +1,95 @@ +import { createHash } from 'node:crypto'; +import { performance } from 'node:perf_hooks'; +import { color, intro, isInteractive, logger, nativeFingerprint, outro, RockError, spinner, } from '@rock-js/tools'; +const hashValue = (value) => `[HASHED:${createHash('sha256').update(value).digest('hex').substring(0, 8)}]`; +/** + * Redacts sensitive environment variables from fingerprint sources by hashing their values + */ +function redactSensitiveSources(sources) { + return sources.map((source) => { + if (source.key === 'json:env' && 'json' in source) { + const env = source.json; + const redactedEnv = Object.fromEntries(Object.entries(env).map(([key, value]) => [key, hashValue(value)])); + return { ...source, json: redactedEnv }; + } + return source; + }); +} +export async function nativeFingerprintCommand(path, { extraSources, ignorePaths, env }, options) { + validateOptions(options); + const platform = options.platform; + const readablePlatformName = platform === 'ios' + ? 'iOS' + : platform === 'android' + ? 'Android' + : 'HarmonyOS'; + if (options.raw || !isInteractive()) { + const fingerprint = await nativeFingerprint(path, { + platform, + extraSources, + ignorePaths, + env, + }); + console.log(fingerprint.hash); + // log sources to stderr to avoid polluting the standard output + console.error(JSON.stringify({ + hash: fingerprint.hash, + sources: redactSensitiveSources(fingerprint.inputs.filter((source) => source.hash != null)), + }, null, 2)); + return; + } + intro(`${readablePlatformName} Fingerprint`); + const loader = spinner(); + loader.start("Calculating fingerprint for the project's native parts"); + const start = performance.now(); + const fingerprint = await nativeFingerprint(path, { + platform, + extraSources, + ignorePaths, + env, + }); + const duration = performance.now() - start; + loader.stop(`Fingerprint calculated: ${color.bold(color.magenta(fingerprint.hash))}`); + logger.debug('Sources:', JSON.stringify(redactSensitiveSources(fingerprint.inputs.filter((source) => source.hash != null)), null, 2)); + logger.debug(`Duration: ${(duration / 1000).toFixed(1)}s`); + outro('Success ๐ŸŽ‰.'); +} +function validateOptions(options) { + if (!options.platform) { + throw new RockError('The --platform flag is required. Please specify either "ios", "android" or "harmony".'); + } + if (options.platform !== 'ios' && + options.platform !== 'android' && + options.platform !== 'harmony') { + throw new RockError(`Unsupported platform "${options.platform}". Please specify either "ios", "android" or "harmony".`); + } +} +export const fingerprintPlugin = () => (api) => { + api.registerCommand({ + name: 'fingerprint', + description: 'Calculate fingerprint for given platform', + action: async (path, options) => { + const fingerprintOptions = api.getFingerprintOptions(); + const dir = path || api.getProjectRoot(); + await nativeFingerprintCommand(dir, fingerprintOptions, options); + }, + options: [ + { + name: '-p, --platform ', + description: 'Select platform, e.g. ios or android', + }, + { + name: '--raw', + description: 'Output the raw fingerprint hash for piping', + }, + ], + args: [ + { name: '[path]', description: 'Directory to calculate fingerprint for' }, + ], + }); + return { + name: 'internal_fingerprint', + description: 'Fingerprint plugin', + }; +}; +//# sourceMappingURL=fingerprint.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/fingerprint.js.map b/packages/cli/dist/src/lib/plugins/fingerprint.js.map new file mode 100644 index 000000000..eb665f3fb --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/fingerprint.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../../../src/lib/plugins/fingerprint.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/logConfig.d.ts b/packages/cli/dist/src/lib/plugins/logConfig.d.ts new file mode 100644 index 000000000..cd949c4ea --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/logConfig.d.ts @@ -0,0 +1,14 @@ +import type { ConfigOutput, PluginApi } from '@rock-js/config'; +export declare const logConfig: (args: { + platform?: string; +}, ownConfig: { + platforms: ConfigOutput["platforms"]; + root: ConfigOutput["root"]; +}) => Promise; +export declare const logConfigPlugin: (ownConfig: { + platforms: ConfigOutput["platforms"]; + root: ConfigOutput["root"]; +}) => (api: PluginApi) => { + name: string; + description: string; +}; diff --git a/packages/cli/dist/src/lib/plugins/logConfig.js b/packages/cli/dist/src/lib/plugins/logConfig.js new file mode 100644 index 000000000..1613ba399 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/logConfig.js @@ -0,0 +1,56 @@ +function isValidRNDependency(config) { + return (Object.keys(config.platforms).filter((key) => Boolean(config.platforms[key])).length !== 0); +} +function filterConfig(config) { + const filtered = { ...config }; + // `react-native` is not a dependency. When loading it through community CLI it's not an issue, + // but in our case we don't install `@react-native-community/cli-platform-*` as a dependencies + // so the config.platforms key is empty, which makes autolinking treat it as a dependency. + delete filtered.dependencies['react-native']; + // we don't want to show commands in the config + filtered.commands = []; + const dependencies = {}; + Object.keys(filtered.dependencies).forEach((item) => { + if (isValidRNDependency(filtered.dependencies[item])) { + dependencies[item] = filtered.dependencies[item]; + } + }); + return { + ...filtered, + dependencies, + }; +} +export const logConfig = async (args, ownConfig) => { + const { loadConfigAsync } = await import('@react-native-community/cli-config'); + const config = await loadConfigAsync({ + projectRoot: ownConfig.root, + selectedPlatform: args.platform, + }); + const platforms = ownConfig.platforms && args.platform + ? { [args.platform]: ownConfig.platforms[args.platform] } + : ownConfig.platforms; + for (const platform in platforms) { + config.project[platform] = platforms[platform].autolinkingConfig.project; + } + console.log(JSON.stringify(filterConfig(config), null, 2)); +}; +export const logConfigPlugin = (ownConfig) => (api) => { + api.registerCommand({ + name: 'config', + description: 'Output autolinking config', + action: async (args) => { + await logConfig(args, ownConfig); + }, + options: [ + { + name: '-p, --platform ', + description: 'Select platform, e.g. ios, android, or harmony', + }, + ], + }); + return { + name: 'internal_config', + description: 'Configuration plugin', + }; +}; +//# sourceMappingURL=logConfig.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/logConfig.js.map b/packages/cli/dist/src/lib/plugins/logConfig.js.map new file mode 100644 index 000000000..f068d19f3 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/logConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logConfig.js","sourceRoot":"","sources":["../../../../src/lib/plugins/logConfig.ts"],"names":[],"mappings":"AAMA,SAAS,mBAAmB,CAAC,MAAwB;IACnD,OAAO,CACL,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAC3C,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAC/B,CAAC,MAAM,KAAK,CAAC,CACf,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,QAAQ,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC/B,+FAA+F;IAC/F,8FAA8F;IAC9F,0FAA0F;IAC1F,OAAO,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IAC7C,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,GAAG,EAAE,CAAC;IACvB,MAAM,YAAY,GAAqC,EAAE,CAAC;IAC1D,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAClD,IAAI,mBAAmB,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACrD,YAAY,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO;QACL,GAAG,QAAQ;QACX,YAAY;KACb,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,IAA2B,EAC3B,SAGC,EACD,EAAE;IACF,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CACtC,oCAAoC,CACrC,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;QACnC,WAAW,EAAE,SAAS,CAAC,IAAI;QAC3B,gBAAgB,EAAE,IAAI,CAAC,QAAQ;KAChC,CAAC,CAAC;IAEH,MAAM,SAAS,GACb,SAAS,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ;QAClC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACzD,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IAE1B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC;IAC3E,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAC1B,CAAC,SAGA,EAAE,EAAE,CACL,CAAC,GAAc,EAAE,EAAE;IACjB,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,2BAA2B;QACxC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,yBAAyB;gBAC/B,WAAW,EAAE,gDAAgD;aAC9D;SACF;KACF,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,sBAAsB;KACpC,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/remoteCache.d.ts b/packages/cli/dist/src/lib/plugins/remoteCache.d.ts new file mode 100644 index 000000000..4a8a1d2fd --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/remoteCache.d.ts @@ -0,0 +1,2 @@ +import type { PluginApi, PluginOutput } from '@rock-js/config'; +export declare const remoteCachePlugin: () => (api: PluginApi) => PluginOutput; diff --git a/packages/cli/dist/src/lib/plugins/remoteCache.js b/packages/cli/dist/src/lib/plugins/remoteCache.js new file mode 100644 index 000000000..a36fe7726 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/remoteCache.js @@ -0,0 +1,381 @@ +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { color, colorLink, formatArtifactName, getInfoPlist, getLocalArtifactPath, getLocalBinaryPath, handleDownloadResponse, handleUploadResponse, logger, relativeToCwd, RockError, spinner, } from '@rock-js/tools'; +import AdmZip from 'adm-zip'; +import * as tar from 'tar'; +import { templateIndexHtmlAndroid, templateIndexHtmlIOS, templateManifestPlist, } from '../adHocTemplates.js'; +async function remoteCache({ action, args, remoteCacheProvider, projectRoot, fingerprintOptions, }) { + const isJsonOutput = args.json; + if (!remoteCacheProvider) { + return null; + } + const remoteBuildCache = remoteCacheProvider(); + validateArgs(args, action); + const artifactName = args.name ?? + (await formatArtifactName({ + platform: args.platform, + traits: args.traits, + root: projectRoot, + fingerprintOptions, + raw: isJsonOutput, + })); + switch (action) { + case 'list': { + const artifacts = await remoteBuildCache.list({ + artifactName, + limit: args.all ? undefined : 1, + }); + if (artifacts.length > 0 && !args.all) { + const artifact = artifacts[0]; + if (isJsonOutput) { + console.log(JSON.stringify(artifact, null, 2)); + } + else { + logger.log(`Artifact information: +- name: ${color.bold(color.blue(artifact.name))} +- url: ${colorLink(artifact.url)}`); + } + } + else if (artifacts.length > 0 && args.all) { + if (isJsonOutput) { + console.log(JSON.stringify(artifacts, null, 2)); + } + else { + artifacts.forEach((artifact) => { + logger.log(`Artifact information: +- name: ${color.bold(color.blue(artifact.name))} +- url: ${colorLink(artifact.url)}`); + }); + } + } + break; + } + case 'list-all': { + const artifactName = undefined; + const artifacts = await remoteBuildCache.list({ artifactName }); + const platform = args.platform; + const traits = args.traits; + const output = platform && traits + ? artifacts.filter((artifact) => artifact.name.startsWith(`rock-${platform}-${traits.join('-')}`)) + : artifacts; + if (isJsonOutput) { + console.log(JSON.stringify(output, null, 2)); + } + else { + logger.log(`Artifacts: +${output + .map((artifact) => `- name: ${color.bold(color.blue(artifact.name))}\n- url: ${colorLink(artifact.url)}`) + .join('\n')} + `); + } + break; + } + case 'download': { + const localArtifactPath = getLocalArtifactPath(artifactName); + const response = await remoteBuildCache.download({ artifactName }); + const loader = spinner({ silent: isJsonOutput }); + loader.start(`Downloading cached build from ${color.bold(remoteBuildCache.name)}`); + await handleDownloadResponse(response, localArtifactPath, (progress, totalMB) => { + loader.message(`Downloading cached build from ${color.bold(remoteBuildCache.name)} (${progress}% of ${totalMB} MB)`); + }); + const binaryPath = getLocalBinaryPath(localArtifactPath); + loader.stop(`Downloaded cached build from ${color.bold(remoteBuildCache.name)}`); + if (!binaryPath) { + throw new RockError(`Failed to save binary for "${artifactName}".`); + } + if (isJsonOutput) { + console.log(JSON.stringify({ name: artifactName, path: binaryPath }, null, 2)); + } + else { + logger.log(`Artifact information: +- name: ${color.bold(color.blue(artifactName))} +- path: ${colorLink(relativeToCwd(binaryPath))}`); + } + break; + } + case 'upload': { + console.log('TEST UPLOAD STARTS'); + const localArtifactPath = getLocalArtifactPath(artifactName); + const binaryPath = args.binaryPath ?? getLocalBinaryPath(localArtifactPath); + if (!binaryPath) { + throw new RockError(`No binary found for "${artifactName}".`); + } + console.log('TEST UPLOAD BINARY PATH', binaryPath); + const buffer = await getBinaryBuffer(binaryPath, artifactName, localArtifactPath, args); + const isIosPlatformOld = args.platform === 'ios'; + const isIosPlatform = args.binaryPath?.endsWith('.ipa'); + const isAndroidPlatformOld = args.platform === 'android'; + const isAndroidPlatform = args.binaryPath?.endsWith('.apk'); + console.log('TEST PLATFORM', JSON.stringify({ + isIosPlatformOld, + isIosPlatform, + isAndroidPlatformOld, + isAndroidPlatform, + argPlatform: args.platform, + argBinaryPath: args.binaryPath, + }, null, 2)); + try { + let uploadedArtifact; + const appFileName = path.basename(binaryPath); + const appName = appFileName.replace(/\.[^/.]+$/, ''); + const uploadContent = { + messagePrefix: 'build', + artifactName: undefined, + }; + if (args.adHoc && isIosPlatform) { + uploadContent.messagePrefix = 'IPA, index.html and manifest.plist'; + uploadContent.artifactName = `ad-hoc/${artifactName}/${appName}.ipa`; + } + else if (args.adHoc && isAndroidPlatform) { + uploadContent.messagePrefix = 'APK, index.html'; + uploadContent.artifactName = `ad-hoc/${artifactName}/${appName}.apk`; + } + console.log('TEST uploadContent', JSON.stringify(uploadContent, null, 2)); + const { name, url, getResponse } = await remoteBuildCache.upload({ + artifactName, + uploadArtifactName: uploadContent.artifactName, + }); + const uploadMessage = `${uploadContent.messagePrefix} to ${color.bold(remoteBuildCache.name)}`; + const loader = spinner({ silent: isJsonOutput }); + loader.start(`Uploading ${uploadMessage}`); + await handleUploadResponse(getResponse, buffer, (progress, totalMB) => { + loader.message(`Uploading ${uploadMessage} (${progress}% of ${totalMB} MB)`); + }); + uploadedArtifact = { name, url }; + // Upload index.html and manifest.plist for iOS ad-hoc distribution + if (args.adHoc && isIosPlatform) { + console.log('TEST IOS ADHOC UPLOAD STARTS'); + const { version, bundleIdentifier } = await getInfoPlistFromIpa(binaryPath); + const { url: urlIndexHtml, getResponse: getResponseIndexHtml } = await remoteBuildCache.upload({ + artifactName, + uploadArtifactName: `ad-hoc/${artifactName}/index.html`, + }); + getResponseIndexHtml(Buffer.from(templateIndexHtmlIOS({ appName, bundleIdentifier, version })), 'text/html'); + const { getResponse: getResponseManifestPlist } = await remoteBuildCache.upload({ + artifactName, + uploadArtifactName: `ad-hoc/${artifactName}/manifest.plist`, + }); + getResponseManifestPlist((baseUrl) => Buffer.from(templateManifestPlist({ + appName, + version, + baseUrl: baseUrl.replace('/manifest.plist', ''), + ipaName: appFileName, + bundleIdentifier, + platformIdentifier: 'com.apple.platform.iphoneos', + }))); + // For ad-hoc distribution, we want the url to point to the index.html for easier installation + uploadedArtifact = { name, url: urlIndexHtml.split('?')[0] + '' }; + } + // Upload index.html for Android ad-hoc distribution + if (args.adHoc && isAndroidPlatform) { + console.log('TEST ANDROID ADHOC UPLOAD STARTS'); + const { version, packageName } = await getManifestFromApk(binaryPath); + const { url: urlIndexHtml, getResponse: getResponseIndexHtml } = await remoteBuildCache.upload({ + artifactName, + uploadArtifactName: `ad-hoc/${artifactName}/index.html`, + }); + getResponseIndexHtml(Buffer.from(templateIndexHtmlAndroid({ appName, packageName, version })), 'text/html'); + // For ad-hoc distribution, we want the url to point to the index.html for easier installation + uploadedArtifact = { name, url: urlIndexHtml.split('?')[0] + '' }; + } + loader.stop(`Uploaded ${uploadMessage}`); + if (isJsonOutput) { + console.log(JSON.stringify(uploadedArtifact, null, 2)); + } + else { + logger.log(`Artifact information: +- name: ${color.bold(color.blue(uploadedArtifact.name))} +- url: ${colorLink(uploadedArtifact.url)}`); + } + } + catch (error) { + throw new RockError(`Failed to upload build to ${color.bold(remoteBuildCache.name)}`, { cause: error }); + } + break; + } + case 'delete': { + const deletedArtifacts = await remoteBuildCache.delete({ + artifactName, + limit: args.all || args.allButLatest ? undefined : 1, + skipLatest: args.allButLatest, + }); + if (isJsonOutput) { + console.log(JSON.stringify(deletedArtifacts, null, 2)); + } + else { + logger.log(`Deleted artifacts: +${deletedArtifacts + .map((artifact) => `- name: ${color.bold(color.blue(artifact.name))}\n- url: ${colorLink(artifact.url)}`) + .join('\n')}`); + } + break; + } + case 'get-provider-name': { + console.log(remoteBuildCache.name); + break; + } + } + return null; +} +async function getInfoPlistFromIpa(binaryPath) { + const ipaFileName = path.basename(binaryPath); + const appName = path.basename(ipaFileName, '.ipa'); + const ipaPath = binaryPath; + const zip = new AdmZip(ipaPath); + const infoPlistPath = `Payload/${appName}.app/Info.plist`; + const infoPlistEntry = zip.getEntry(infoPlistPath); + if (!infoPlistEntry) { + throw new RockError(`Info.plist not found at ${infoPlistPath} in ${ipaFileName}`); + } + const infoPlistBuffer = infoPlistEntry.getData(); + const tempPlistPath = path.join(os.tmpdir(), 'rock-temp-info.plist'); + fs.writeFileSync(tempPlistPath, infoPlistBuffer); + const infoPlistJson = await getInfoPlist(tempPlistPath); + fs.unlinkSync(tempPlistPath); + return { + version: infoPlistJson?.['CFBundleShortVersionString'] || + infoPlistJson?.['CFBundleVersion'] || + 'unknown', + bundleIdentifier: infoPlistJson?.['CFBundleIdentifier'] || 'unknown', + }; +} +async function getManifestFromApk(binaryPath) { + const apkFileName = path.basename(binaryPath, '.apk'); + try { + const nodeApk = await import('node-apk'); + const { Apk } = nodeApk.default || nodeApk; + const apk = new Apk(binaryPath); + const manifest = await apk.getManifestInfo(); + apk.close(); + return { + packageName: manifest.package || apkFileName, + version: manifest.versionName || '1.0', + }; + } + catch (error) { + logger.debug('Failed to parse APK manifest, using fallback', error); + return { + packageName: apkFileName, + version: '1.0', + }; + } +} +async function getBinaryBuffer(binaryPath, artifactName, localArtifactPath, args) { + // For ad-hoc, we don't need to zip the binary, we just upload the IPA + if (args.adHoc) { + console.log('TEST AD-HOC UPLOAD BINARY PATH', binaryPath); + return fs.readFileSync(binaryPath); + } + console.log('TEST NOT AD-HOC UPLOAD BINARY PATH', binaryPath); + const zip = new AdmZip(); + const isAppDirectory = binaryPath.endsWith('.app') && fs.statSync(binaryPath).isDirectory(); + const absoluteTarballPath = args.binaryPath ?? path.join(localArtifactPath, 'app.tar.gz'); + if (isAppDirectory) { + const appDirectoryName = path.basename(binaryPath); + if (args.binaryPath && !fs.existsSync(absoluteTarballPath)) { + throw new RockError(`No tarball found for "${artifactName}" in "${localArtifactPath}".`); + } + await tar.create({ + file: absoluteTarballPath, + cwd: path.dirname(binaryPath), + gzip: true, + filter: (filePath) => filePath.includes(appDirectoryName), + }, [appDirectoryName]); + zip.addLocalFile(absoluteTarballPath); + } + else { + zip.addLocalFile(binaryPath); + } + const buffer = zip.toBuffer(); + if (isAppDirectory) { + fs.unlinkSync(absoluteTarballPath); + } + return buffer; +} +function validateArgs(args, action) { + if (!action) { + // @todo make Commander handle this + throw new RockError('Action is required. Available actions: list, list-all, download, upload, delete'); + } + if (action === 'list-all' || action === 'get-provider-name') { + // return early as we don't need to validate name or platform + // to list all artifacts or get provider name + return; + } + if (args.name && (args.platform || args.traits)) { + throw new RockError('Cannot use "--name" together with "--platform" or "--traits". Use either name or platform with traits'); + } + if (!args.name) { + if ((args.platform && !args.traits) || (!args.platform && args.traits)) { + throw new RockError('Either "--platform" and "--traits" must be provided together'); + } + if (!args.platform || !args.traits) { + throw new RockError('Either "--name" or "--platform" and "--traits" must be provided'); + } + } +} +export const remoteCachePlugin = () => (api) => { + api.registerCommand({ + name: 'remote-cache', + description: 'Manage remote cache', + action: async (action, args) => { + await remoteCache({ + action, + args, + remoteCacheProvider: (await api.getRemoteCacheProvider()) || null, + projectRoot: api.getProjectRoot(), + fingerprintOptions: api.getFingerprintOptions(), + }); + }, + args: [ + { + name: '[action]', + description: 'Select action, e.g. list, list-all, download, upload, delete, get-provider-name', + }, + ], + options: [ + { + name: '--json', + description: 'Output in JSON format', + }, + { + name: '--name ', + description: 'Full artifact name', + }, + { + name: '--all', + description: 'List or delete all matching artifacts. Affects "list" and "delete" actions only', + }, + { + name: '--all-but-latest', + description: 'Delete all but the latest matching artifact. Affects "delete" action only', + }, + { + name: '-p, --platform ', + description: 'Select platform, e.g. ios, android, or harmony (experimental)', + }, + { + name: '-t, --traits ', + description: `Comma-separated traits that construct final artifact name. Traits for Android are: variant; for iOS: destination and configuration. +Example iOS: --traits simulator,Release +Example Android: --traits debug +Example Harmony: --traits debug`, + parse: (val) => val.split(','), + }, + { + name: '--binary-path ', + description: 'Path to the binary to upload', + }, + { + name: '--ad-hoc', + description: 'Upload IPA or APK for ad-hoc distribution and installation from URL. For iOS: uploads IPA, index.html and manifest.plist. For Android: uploads APK and index.html', + }, + ], + }); + return { + name: 'internal_remote-cache', + description: 'Manage remote cache', + }; +}; +//# sourceMappingURL=remoteCache.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/lib/plugins/remoteCache.js.map b/packages/cli/dist/src/lib/plugins/remoteCache.js.map new file mode 100644 index 000000000..751f61a06 --- /dev/null +++ b/packages/cli/dist/src/lib/plugins/remoteCache.js.map @@ -0,0 +1 @@ +{"version":3,"file":"remoteCache.js","sourceRoot":"","sources":["../../../../src/lib/plugins/remoteCache.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/cli/package.json b/packages/cli/package.json index 681409e1e..2069a60b9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -29,6 +29,7 @@ "@rock-js/tools": "^0.11.9", "adm-zip": "^0.5.16", "commander": "^12.1.0", + "node-apk": "^1.2.1", "tar": "^7.5.1", "tslib": "^2.3.0" }, diff --git a/packages/cli/src/lib/adHocTemplates.ts b/packages/cli/src/lib/adHocTemplates.ts index 0787555e3..2c9588e09 100644 --- a/packages/cli/src/lib/adHocTemplates.ts +++ b/packages/cli/src/lib/adHocTemplates.ts @@ -1,340 +1,391 @@ -// Template functions for ad-hoc iOS distribution -export function templateIndexHtml({ +// Template functions for ad-hoc iOS and Android distribution + +// Shared CSS styles for both iOS and Android templates +const sharedStyles = ` + :root { + /* Light mode variables */ + --bg-primary: #ffffff; + --bg-secondary: #f5f5f7; + --text-primary: #1d1d1f; + --text-secondary: #86868b; + --accent-primary: #8232ff; + --accent-hover: rgba(130, 50, 255, 0.3); + --border-color: #e5e5e7; + --shadow-color: rgba(0, 0, 0, 0.1); + } + + @media (prefers-color-scheme: dark) { + :root { + /* Dark mode variables */ + --bg-primary: #1c1c1e; + --bg-secondary: #2c2c2e; + --text-primary: #ffffff; + --text-secondary: #8e8e93; + --accent-primary: #8232ff; + --accent-hover: rgba(130, 50, 255, 0.4); + --border-color: #38383a; + --shadow-color: rgba(0, 0, 0, 0.3); + } + } + + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + Oxygen, Ubuntu, Cantarell, sans-serif; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + font-size: 16px; + background-color: var(--bg-primary); + color: var(--text-primary); + transition: background-color 0.3s ease, color 0.3s ease; + } + + .container { + text-align: center; + max-width: 500px; + width: 100%; + } + + .app-icon { + width: 100px; + height: 100px; + margin: 0 auto 15px; + display: flex; + align-items: center; + justify-content: center; + font-size: 48px; + color: var(--text-primary); + background: var(--bg-secondary); + border-radius: 25px; + transition: background-color 0.3s ease; + } + + h1 { + color: var(--text-primary); + font-size: 28px; + font-weight: 600; + margin-bottom: 15px; + overflow-wrap: break-word; + transition: color 0.3s ease; + } + + .subtitle { + color: var(--text-secondary); + font-size: 16px; + line-height: 1.5; + margin-bottom: 30px; + transition: color 0.3s ease; + } + + .version { + color: var(--text-primary); + font-size: 16px; + line-height: 1.5; + margin-bottom: 10px; + transition: color 0.3s ease; + } + + .download-button { + background: var(--accent-primary); + color: white; + border: none; + padding: 16px 32px; + border-radius: 4px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + text-decoration: none; + display: inline-block; + margin-bottom: 20px; + box-shadow: 0 4px 12px var(--shadow-color); + } + + .download-button:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px var(--accent-hover); + } + + .download-button:active { + transform: translateY(0); + } + + .instructions { + background: var(--bg-secondary); + border-radius: 4px; + padding: 20px; + margin-top: 20px; + text-align: left; + border: 1px solid var(--border-color); + transition: background-color 0.3s ease, border-color 0.3s ease; + } + + .instructions h3 { + color: var(--text-primary); + font-size: 16px; + margin-bottom: 10px; + transition: color 0.3s ease; + } + + .instructions ol { + color: var(--text-secondary); + font-size: 14px; + line-height: 1.6; + padding-left: 20px; + transition: color 0.3s ease; + } + + .instructions li { + margin-bottom: 8px; + } + + .adhoc-info { + text-align: left; + margin-top: 20px; + padding: 1em 2em; + border-left: 3px solid var(--accent-primary); + background: var(--bg-primary); + border-radius: 4px; + transition: background-color 0.3s ease; + } + + .adhoc-info-title { + font-weight: 600; + margin-bottom: 10px; + color: var(--text-primary); + transition: color 0.3s ease; + } + + .adhoc-info-text { + color: var(--text-primary); + margin: 0; + transition: color 0.3s ease; + } + + .footer { + text-align: center; + margin-top: 40px; + font-size: 12px; + color: var(--text-secondary); + transition: color 0.3s ease; + } + + .link { + color: var(--accent-primary); + text-decoration: none; + transition: color 0.3s ease; + } + + .link:hover { + text-decoration: underline; + } + + .toast { + padding: 1em 3em; + font-size: 14px; + border: 1px solid var(--accent-primary); + color: var(--text-primary); + position: fixed; + bottom: 1em; + left: 50%; + transform: translateX(-50%); + max-width: 500px; + width: calc(100% - 2em); + text-align: left; + border-radius: 4px; + background-color: var(--bg-primary); + display: none; + box-shadow: 0 8px 24px var(--shadow-color); + transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease; + } + + .toast-visible { + display: block; + animation: slideUp 0.3s ease; + } + + @keyframes slideUp { + from { + opacity: 0; + transform: translateX(-50%) translateY(20px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } + } + + .toast-icon { + font-size: 1em; + position: absolute; + left: 1em; + top: 50%; + transform: translateY(-50%); + } + + .toast-close { + font-size: 1em; + padding: 0.5em; + cursor: pointer; + position: absolute; + right: 1em; + top: 50%; + transform: translateY(-50%); + color: var(--text-secondary); + transition: color 0.3s ease; + } + + .toast-close:hover { + color: var(--text-primary); + } + + /* Smooth transitions for all elements */ + * { + transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; + } +`; + +// Shared footer HTML +const sharedFooter = ` + +`; + +// Shared toast functions for both iOS and Android templates +const sharedToastFunctions = () => ` + function showToast() { + setTimeout(() => { + const toast = document.getElementById('home-screen-toast'); + toast.classList.add('toast-visible'); + }, 2000); + } + + function hideToast() { + const toast = document.getElementById('home-screen-toast'); + toast.classList.remove('toast-visible'); + } +`; + +// Base template function for creating ad-hoc distribution pages +function createAdHocTemplate({ + platform, appName, version, - bundleIdentifier, + identifier, + icon, + buttonText, + toastMessage, + script, + instructions, + adhocDescription, }: { + platform: 'iOS' | 'Android'; appName: string; version: string; - bundleIdentifier: string; + identifier: string; + icon: string; + buttonText: string; + toastMessage: string; + script: string; + instructions: string; + adhocDescription: string; }) { return ` - - - - - Download ${appName} for iOS - - - -
    -
    ๐Ÿ“ฑ
    - -
    - ๐Ÿ’ก -

    Check Home Screen to see installation progress

    - โœ• -
    - -

    ${appName}

    -

    ${bundleIdentifier} (${version})

    -

    - Download and install the latest version of our iOS app directly to your - device. + + + + + Download ${appName} for ${platform} + + + +

    +
    ${icon}
    + +
    + ๐Ÿ’ก +

    ${toastMessage}

    + โœ• +
    + +

    ${appName}

    +

    ${identifier} (${version})

    +

    + Download and install the latest version of our ${platform} app directly to your + device. +

    + + + ${buttonText} + + + + +
    +

    Installation Instructions:

    +
      ${instructions}
    +
    + +
    +

    Ad-hoc Distribution

    +

    + ${adhocDescription} +

    + Learn more at Rock Ad-hoc documentation.

    - - - Install App - - - - -
    -

    Installation Instructions:

    -
      -
    1. Tap the "Install App" button above
    2. -
    3. When prompted, tap "Install" in the popup dialog
    4. -
    5. The app will now start installing and will be available on your home screen
    6. -
    -
    - -
    -

    Ad-hoc Distribution

    -

    - This app is distributed via ad-hoc distribution for testing purposes. - Your device must either be enrolled in enterprise distribution or have its UDID added to the app's provisioning profile. -

    - Learn more at Rock Ad-hoc documentation. -

    -
    -
    - - - `; + ${sharedFooter} +
    + + +`; +} + +export function templateIndexHtmlIOS({ + appName, + version, + bundleIdentifier, +}: { + appName: string; + version: string; + bundleIdentifier: string; +}) { + return createAdHocTemplate({ + platform: 'iOS', + appName, + version, + identifier: bundleIdentifier, + icon: '๐Ÿ“ฑ', + buttonText: 'Install App', + toastMessage: 'Check Home Screen to see installation progress', + script: ` + // Update the link dynamically to point to the manifest.plist + const link = document.getElementById('action-button'); + const currentUrl = window.location.href; + const manifestUrl = currentUrl.replace('index.html', 'manifest.plist'); + link.href = \`itms-services://?action=download-manifest&url=\${encodeURIComponent(manifestUrl)}\`; + ${sharedToastFunctions()} + `, + instructions: ` +
  • Tap the "Install App" button above
  • +
  • When prompted, tap "Install" in the popup dialog
  • +
  • The app will now start installing and will be available on your home screen
  • + `, + adhocDescription: + "This app is distributed via ad-hoc distribution for testing purposes. Your device must either be enrolled in enterprise distribution or have its UDID added to the app's provisioning profile.", + }); } export function templateManifestPlist({ @@ -388,3 +439,39 @@ export function templateManifestPlist({ `; } + +export function templateIndexHtmlAndroid({ + appName, + version, + packageName, +}: { + appName: string; + version: string; + packageName: string; +}) { + return createAdHocTemplate({ + platform: 'Android', + appName, + version, + identifier: packageName, + icon: '๐Ÿค–', + buttonText: 'Download APK', + toastMessage: 'APK download started. Check your notifications to install.', + script: ` + // Update the link dynamically to point to the APK file + const link = document.getElementById('action-button'); + const currentUrl = window.location.href; + const apkFileName = '${appName}.apk'; + link.href = currentUrl.replace('index.html', apkFileName); + ${sharedToastFunctions()} + `, + instructions: ` +
  • Tap the "Download APK" button above
  • +
  • Once downloaded, open the APK file from your notifications or downloads folder
  • +
  • If prompted, enable "Install from Unknown Sources" in your device settings
  • +
  • Follow the on-screen prompts to complete the installation
  • + `, + adhocDescription: + 'This app is distributed via ad-hoc distribution for testing purposes. You may need to enable installation from unknown sources in your Android device settings.', + }); +} diff --git a/packages/cli/src/lib/plugins/remoteCache.ts b/packages/cli/src/lib/plugins/remoteCache.ts index 4a0950e61..676bd638f 100644 --- a/packages/cli/src/lib/plugins/remoteCache.ts +++ b/packages/cli/src/lib/plugins/remoteCache.ts @@ -19,7 +19,11 @@ import { } from '@rock-js/tools'; import AdmZip from 'adm-zip'; import * as tar from 'tar'; -import { templateIndexHtml, templateManifestPlist } from '../adHocTemplates.js'; +import { + templateIndexHtmlAndroid, + templateIndexHtmlIOS, + templateManifestPlist, +} from '../adHocTemplates.js'; type Flags = { platform?: 'ios' | 'android'; @@ -157,12 +161,14 @@ ${output break; } case 'upload': { + console.log('TEST UPLOAD STARTS'); const localArtifactPath = getLocalArtifactPath(artifactName); const binaryPath = args.binaryPath ?? getLocalBinaryPath(localArtifactPath); if (!binaryPath) { throw new RockError(`No binary found for "${artifactName}".`); } + console.log('TEST UPLOAD BINARY PATH', binaryPath); const buffer = await getBinaryBuffer( binaryPath, artifactName, @@ -170,19 +176,60 @@ ${output args, ); + const isIosPlatformOld = args.platform === 'ios'; + const isIosPlatform = args.binaryPath?.endsWith('.ipa'); + const isAndroidPlatformOld = args.platform === 'android'; + const isAndroidPlatform = args.binaryPath?.endsWith('.apk'); + + console.log( + 'TEST PLATFORM', + JSON.stringify( + { + isIosPlatformOld, + isIosPlatform, + isAndroidPlatformOld, + isAndroidPlatform, + argPlatform: args.platform, + argBinaryPath: args.binaryPath, + }, + null, + 2, + ), + ); + try { let uploadedArtifact; const appFileName = path.basename(binaryPath); const appName = appFileName.replace(/\.[^/.]+$/, ''); + + const uploadContent: { + messagePrefix: string; + artifactName: string | undefined; + } = { + messagePrefix: 'build', + artifactName: undefined, + }; + + if (args.adHoc && isIosPlatform) { + uploadContent.messagePrefix = 'IPA, index.html and manifest.plist'; + uploadContent.artifactName = `ad-hoc/${artifactName}/${appName}.ipa`; + } else if (args.adHoc && isAndroidPlatform) { + uploadContent.messagePrefix = 'APK, index.html'; + uploadContent.artifactName = `ad-hoc/${artifactName}/${appName}.apk`; + } + + console.log( + 'TEST uploadContent', + JSON.stringify(uploadContent, null, 2), + ); + const { name, url, getResponse } = await remoteBuildCache.upload({ artifactName, - uploadArtifactName: args.adHoc - ? `ad-hoc/${artifactName}/${appName}.ipa` - : undefined, + uploadArtifactName: uploadContent.artifactName, }); - const uploadMessage = `${ - args.adHoc ? 'IPA, index.html and manifest.plist' : 'build' - } to ${color.bold(remoteBuildCache.name)}`; + + const uploadMessage = `${uploadContent.messagePrefix} to ${color.bold(remoteBuildCache.name)}`; + const loader = spinner({ silent: isJsonOutput }); loader.start(`Uploading ${uploadMessage}`); await handleUploadResponse(getResponse, buffer, (progress, totalMB) => { @@ -193,8 +240,9 @@ ${output uploadedArtifact = { name, url }; - // Upload index.html and manifest.plist for ad-hoc distribution - if (args.adHoc) { + // Upload index.html and manifest.plist for iOS ad-hoc distribution + if (args.adHoc && isIosPlatform) { + console.log('TEST IOS ADHOC UPLOAD STARTS'); const { version, bundleIdentifier } = await getInfoPlistFromIpa(binaryPath); const { url: urlIndexHtml, getResponse: getResponseIndexHtml } = @@ -204,7 +252,7 @@ ${output }); getResponseIndexHtml( Buffer.from( - templateIndexHtml({ appName, bundleIdentifier, version }), + templateIndexHtmlIOS({ appName, bundleIdentifier, version }), ), 'text/html', ); @@ -231,6 +279,26 @@ ${output uploadedArtifact = { name, url: urlIndexHtml.split('?')[0] + '' }; } + // Upload index.html for Android ad-hoc distribution + if (args.adHoc && isAndroidPlatform) { + console.log('TEST ANDROID ADHOC UPLOAD STARTS'); + const { version, packageName } = await getManifestFromApk(binaryPath); + const { url: urlIndexHtml, getResponse: getResponseIndexHtml } = + await remoteBuildCache.upload({ + artifactName, + uploadArtifactName: `ad-hoc/${artifactName}/index.html`, + }); + getResponseIndexHtml( + Buffer.from( + templateIndexHtmlAndroid({ appName, packageName, version }), + ), + 'text/html', + ); + + // For ad-hoc distribution, we want the url to point to the index.html for easier installation + uploadedArtifact = { name, url: urlIndexHtml.split('?')[0] + '' }; + } + loader.stop(`Uploaded ${uploadMessage}`); if (isJsonOutput) { @@ -307,6 +375,29 @@ async function getInfoPlistFromIpa(binaryPath: string) { }; } +async function getManifestFromApk(binaryPath: string) { + const apkFileName = path.basename(binaryPath, '.apk'); + + try { + const nodeApk = await import('node-apk'); + const { Apk } = nodeApk.default || nodeApk; + const apk = new Apk(binaryPath); + const manifest = await apk.getManifestInfo(); + apk.close(); + + return { + packageName: manifest.package || apkFileName, + version: manifest.versionName || '1.0', + }; + } catch (error) { + logger.debug('Failed to parse APK manifest, using fallback', error); + return { + packageName: apkFileName, + version: '1.0', + }; + } +} + async function getBinaryBuffer( binaryPath: string, artifactName: string, @@ -315,8 +406,10 @@ async function getBinaryBuffer( ) { // For ad-hoc, we don't need to zip the binary, we just upload the IPA if (args.adHoc) { + console.log('TEST AD-HOC UPLOAD BINARY PATH', binaryPath); return fs.readFileSync(binaryPath); } + console.log('TEST NOT AD-HOC UPLOAD BINARY PATH', binaryPath); const zip = new AdmZip(); const isAppDirectory = binaryPath.endsWith('.app') && fs.statSync(binaryPath).isDirectory(); @@ -444,7 +537,7 @@ Example Harmony: --traits debug`, { name: '--ad-hoc', description: - 'Upload IPA for ad-hoc distribution and installation from URL. Additionally uploads index.html and manifest.plist', + 'Upload IPA or APK for ad-hoc distribution and installation from URL. For iOS: uploads IPA, index.html and manifest.plist. For Android: uploads APK and index.html', }, ], }); diff --git a/packages/config/dist/src/index.d.ts b/packages/config/dist/src/index.d.ts new file mode 100644 index 000000000..1fdbd6822 --- /dev/null +++ b/packages/config/dist/src/index.d.ts @@ -0,0 +1,2 @@ +export * from './lib/config.js'; +export type { ConfigType as Config } from './lib/config.js'; diff --git a/packages/config/dist/src/index.js b/packages/config/dist/src/index.js new file mode 100644 index 000000000..22e97d4b5 --- /dev/null +++ b/packages/config/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/config.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/config/dist/src/index.js.map b/packages/config/dist/src/index.js.map new file mode 100644 index 000000000..7641b2a34 --- /dev/null +++ b/packages/config/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"} \ No newline at end of file diff --git a/packages/config/dist/src/lib/config.d.ts b/packages/config/dist/src/lib/config.d.ts new file mode 100644 index 000000000..3f0589fdc --- /dev/null +++ b/packages/config/dist/src/lib/config.d.ts @@ -0,0 +1,99 @@ +import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools'; +export type PluginOutput = { + name: string; + description: string; +}; +export type DevServerArgs = { + interactive: boolean; + clientLogs: boolean; + port?: string; + host?: string; + https?: boolean; + resetCache?: boolean; + devServer?: boolean; + platforms?: string[]; + [key: string]: unknown; +}; +export type StartDevServerArgs = { + root: string; + args: DevServerArgs; + reactNativeVersion: string; + reactNativePath: string; + platforms: Record; +}; +type StartDevServerFunction = (options: StartDevServerArgs) => Promise; +export type BundlerPluginOutput = { + name: string; + description: string; + start: StartDevServerFunction; +}; +export type PlatformOutput = PluginOutput & { + autolinkingConfig: { + project: Record | undefined; + }; +}; +export type PluginApi = { + registerCommand: (command: CommandType) => void; + getProjectRoot: () => string; + getReactNativeVersion: () => string; + getReactNativePath: () => string; + getPlatforms: () => { + [platform: string]: object; + }; + getRemoteCacheProvider: () => Promise RemoteBuildCache)>; + getFingerprintOptions: () => FingerprintSources; + getBundlerStart: () => ({ args }: { + args: DevServerArgs; + }) => void; +}; +type PluginType = (args: PluginApi) => PluginOutput; +type BundlerPluginType = (args: PluginApi) => BundlerPluginOutput; +type PlatformType = (args: PluginApi) => PlatformOutput; +type ArgValue = string | string[] | boolean; +type ActionType = (...args: T[]) => void | Promise; +export type CommandType = { + name: string; + description: string; + action: ActionType; + /** Positional arguments */ + args?: Array<{ + name: string; + description: string; + default?: ArgValue | undefined; + }>; + /** Flags */ + options?: Array<{ + name: string; + description: string; + default?: ArgValue | undefined; + parse?: (value: string, previous: ArgValue) => ArgValue; + }>; + /** Internal property to assign plugin name to particualr commands */ + __origin?: string; +}; +export type ConfigType = { + root?: string; + reactNativeVersion?: string; + reactNativePath?: string; + bundler?: BundlerPluginType; + plugins?: PluginType[]; + platforms?: Record; + commands?: Array; + remoteCacheProvider?: null | 'github-actions' | (() => RemoteBuildCache); + fingerprint?: { + extraSources?: string[]; + ignorePaths?: string[]; + env?: string[]; + }; +}; +export type ConfigOutput = { + root: string; + commands?: Array; + platforms?: Record; + bundler?: BundlerPluginOutput; +} & PluginApi; +export declare function getConfig(dir: string, internalPlugins: Array<(ownConfig: { + platforms: ConfigOutput['platforms']; + root: ConfigOutput['root']; +}) => PluginType>): Promise; +export {}; diff --git a/packages/config/dist/src/lib/config.js b/packages/config/dist/src/lib/config.js new file mode 100644 index 000000000..096384572 --- /dev/null +++ b/packages/config/dist/src/lib/config.js @@ -0,0 +1,124 @@ +import * as fs from 'node:fs'; +import { createRequire } from 'node:module'; +import * as path from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { colorLink, getReactNativeVersion, logger } from '@rock-js/tools'; +import { ConfigTypeSchema } from './schema.js'; +import { formatValidationError } from './utils.js'; +const extensions = ['.js', '.ts', '.mjs']; +const importUp = async (dir, name) => { + const filePath = path.join(dir, name); + for (const ext of extensions) { + const filePathWithExt = `${filePath}${ext}`; + if (fs.existsSync(filePathWithExt)) { + let config; + if (ext === '.mjs') { + config = await import(pathToFileURL(filePathWithExt).href).then((module) => module.default); + } + else { + const require = createRequire(import.meta.url); + config = require(filePathWithExt); + } + return { config, filePathWithExt, configDir: dir }; + } + } + const parentDir = path.dirname(dir); + if (parentDir === dir) { + throw new Error(`${name} not found in any parent directory of ${dir}`); + } + return importUp(parentDir, name); +}; +export async function getConfig(dir, internalPlugins) { + const { config, filePathWithExt, configDir } = await importUp(dir, 'rock.config'); + const { error, value: validatedConfig } = ConfigTypeSchema.validate(config); + if (error) { + logger.error(`Invalid ${colorLink(path.relative(configDir, filePathWithExt))} file:\n` + formatValidationError(config, error)); + process.exit(1); + } + const projectRoot = validatedConfig.root + ? path.resolve(configDir, validatedConfig.root) + : configDir; + if (!fs.existsSync(projectRoot)) { + logger.error(`Project root ${projectRoot} does not exist. Please check your config file.`); + process.exit(1); + } + let bundler; + const api = { + registerCommand: (command) => { + validatedConfig.commands = [...(validatedConfig.commands || []), command]; + }, + getProjectRoot: () => projectRoot, + getReactNativeVersion: () => getReactNativeVersion(projectRoot), + getReactNativePath: () => resolveReactNativePath(projectRoot), + getPlatforms: () => validatedConfig.platforms, + getRemoteCacheProvider: async () => { + // special case for github-actions + if (validatedConfig.remoteCacheProvider === 'github-actions') { + logger.warnOnce('github-actions')(`Using shorthand "github-actions" as "remoteCacheProvider" value in ${colorLink('rock.config.mjs')} is deprecated. It will be removed in future releases. +Please use "@rock-js/provider-github" plugin explicitly instead. +Read more: ${colorLink('https://rockjs.dev/docs/configuration#github-actions-provider')}`); + const { providerGitHub } = await import('@rock-js/provider-github'); + return providerGitHub(); + } + return validatedConfig.remoteCacheProvider; + }, + getFingerprintOptions: () => validatedConfig.fingerprint, + getBundlerStart: () => ({ args }) => { + return bundler?.start({ + root: api.getProjectRoot(), + args, + reactNativeVersion: api.getReactNativeVersion(), + reactNativePath: api.getReactNativePath(), + platforms: api.getPlatforms(), + }); + }, + }; + const platforms = {}; + if (validatedConfig.platforms) { + // platforms register commands and custom platform functionality (TBD) + for (const platform in validatedConfig.platforms) { + const platformOutput = validatedConfig.platforms[platform](api); + platforms[platform] = platformOutput; + } + } + if (validatedConfig.plugins) { + // plugins register commands + for (const plugin of validatedConfig.plugins) { + assignOriginToCommand(plugin, api, validatedConfig); + } + } + if (validatedConfig.bundler) { + bundler = assignOriginToCommand(validatedConfig.bundler, api, validatedConfig); + } + for (const internalPlugin of internalPlugins) { + assignOriginToCommand(internalPlugin({ root: projectRoot, platforms }), api, validatedConfig); + } + const outputConfig = { + root: projectRoot, + commands: validatedConfig.commands ?? [], + platforms: platforms ?? {}, + bundler, + ...api, + }; + return outputConfig; +} +function resolveReactNativePath(root) { + const require = createRequire(import.meta.url); + return path.join(require.resolve('react-native', { paths: [root] }), '..'); +} +/** + * + * Assigns __origin property to each command in the config for later use in error handling. + */ +function assignOriginToCommand(plugin, api, config) { + const len = config.commands?.length ?? 0; + const { name, ...rest } = plugin(api); + const newlen = config.commands?.length ?? 0; + for (let i = len; i < newlen; i++) { + if (config.commands?.[i]) { + config.commands[i].__origin = name; + } + } + return { name, ...rest }; +} +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/packages/config/dist/src/lib/config.js.map b/packages/config/dist/src/lib/config.js.map new file mode 100644 index 000000000..13d6fb8a0 --- /dev/null +++ b/packages/config/dist/src/lib/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/config/dist/src/lib/schema.d.ts b/packages/config/dist/src/lib/schema.d.ts new file mode 100644 index 000000000..ca38a3ccb --- /dev/null +++ b/packages/config/dist/src/lib/schema.d.ts @@ -0,0 +1,3 @@ +import Joi from 'joi'; +declare const ConfigTypeSchema: Joi.ObjectSchema; +export { ConfigTypeSchema }; diff --git a/packages/config/dist/src/lib/schema.js b/packages/config/dist/src/lib/schema.js new file mode 100644 index 000000000..6c8bba0cb --- /dev/null +++ b/packages/config/dist/src/lib/schema.js @@ -0,0 +1,47 @@ +import Joi from 'joi'; +const ArgValueSchema = Joi.alternatives().try(Joi.string(), Joi.array().items(Joi.string()), Joi.number(), Joi.boolean()); +const CommandTypeSchema = Joi.object({ + name: Joi.string().required(), + description: Joi.string().required(), + action: Joi.function().required(), + args: Joi.array() + .items(Joi.object({ + name: Joi.string().required(), + description: Joi.string().required(), + default: ArgValueSchema.optional(), + })) + .optional(), + options: Joi.array() + .items(Joi.object({ + name: Joi.string().required(), + description: Joi.string().required(), + default: ArgValueSchema.optional(), + parse: Joi.function().optional(), + })) + .optional(), +}).unknown(false); +const ConfigTypeSchema = Joi.object({ + root: Joi.string().optional(), + reactNativeVersion: Joi.string().optional(), + reactNativePath: Joi.string().optional(), + bundler: Joi.function().optional(), + plugins: Joi.array().items(Joi.function()).optional(), + platforms: Joi.object().pattern(Joi.string(), Joi.function()).optional(), + commands: Joi.array().items(CommandTypeSchema).optional(), + remoteCacheProvider: Joi.alternatives() + .try(Joi.string().valid('github-actions'), Joi.function(), Joi.any().valid(null)) + .optional(), + fingerprint: Joi.object({ + extraSources: Joi.array().items(Joi.string()).default([]), + ignorePaths: Joi.array().items(Joi.string()).default([]), + env: Joi.array().items(Joi.string()).default([]), + }) + .default({ + extraSources: [], + ignorePaths: [], + env: [], + }) + .optional(), +}).unknown(false); +export { ConfigTypeSchema }; +//# sourceMappingURL=schema.js.map \ No newline at end of file diff --git a/packages/config/dist/src/lib/schema.js.map b/packages/config/dist/src/lib/schema.js.map new file mode 100644 index 000000000..60728bfe0 --- /dev/null +++ b/packages/config/dist/src/lib/schema.js.map @@ -0,0 +1 @@ +{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/lib/schema.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/config/dist/src/lib/utils.d.ts b/packages/config/dist/src/lib/utils.d.ts new file mode 100644 index 000000000..dcf0f038e --- /dev/null +++ b/packages/config/dist/src/lib/utils.d.ts @@ -0,0 +1 @@ +export declare function formatValidationError(config: unknown, error: any): string; diff --git a/packages/config/dist/src/lib/utils.js b/packages/config/dist/src/lib/utils.js new file mode 100644 index 000000000..89e47af9c --- /dev/null +++ b/packages/config/dist/src/lib/utils.js @@ -0,0 +1,30 @@ +import { codeFrameColumns } from '@babel/code-frame'; +export function formatValidationError(config, error) { + // Functions by default are replaced with null in the preview, so we replace them with [Function] + const configReplacer = (_, value) => { + if (typeof value === 'function') { + return '[Function]'; + } + if (Array.isArray(value) && + value.some((item) => typeof item === 'function')) { + return value.map((item) => typeof item === 'function' ? '[Function]' : item); + } + return value; + }; + const errorDetails = error.details[0]; + const path = errorDetails.path; + const configString = JSON.stringify(config, configReplacer, 2); + const lines = configString.split('\n'); + const lastPathKey = path[path.length - 1]; + let line = 1; + let column = 0; + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes(`"${lastPathKey}"`)) { + line = i + 1; + column = lines[i].indexOf(`"${lastPathKey}"`) + 1; + break; + } + } + return codeFrameColumns(configString, { start: { line, column } }, { message: error.message, highlightCode: true }); +} +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/packages/config/dist/src/lib/utils.js.map b/packages/config/dist/src/lib/utils.js.map new file mode 100644 index 000000000..70451888b --- /dev/null +++ b/packages/config/dist/src/lib/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,UAAU,qBAAqB,CAAC,MAAe,EAAE,KAAU;IAC/D,iGAAiG;IACjG,MAAM,cAAc,GAAG,CAAC,CAAS,EAAE,KAAc,EAAE,EAAE;QACnD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,IACE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,UAAU,CAAC,EAChD,CAAC;YACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACxB,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CACjD,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YAC1C,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YACb,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC;YAClD,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,gBAAgB,CACrB,YAAY,EACZ,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAC3B,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAChD,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/create-app/dist/src/bin.js b/packages/create-app/dist/src/bin.js new file mode 100755 index 000000000..d14603aa8 --- /dev/null +++ b/packages/create-app/dist/src/bin.js @@ -0,0 +1,149 @@ +#!/usr/bin/env node +import e,{copyFileSync as t,existsSync as i,readFileSync as r,renameSync as n,statSync as s,writeFileSync as o}from"node:fs";import u,{basename as a,dirname as l,extname as h,isAbsolute as c,join as d,posix as D,relative as f,win32 as p}from"node:path";import m,{stripVTControlCharacters as g}from"node:util";import E,{stdin as b,stdout as y}from"node:process";import F,{clearLine as C,createInterface as v,emitKeypressEvents as w,moveCursor as _}from"node:readline";import S,{Writable as A}from"node:stream";import R,{stat as O}from"node:fs/promises";import"fs/promises";import"child_process";import{fileURLToPath as B}from"node:url";import{spawn as x}from"node:child_process";import{EventEmitter as N,on as I,once as T}from"node:events";import{pipeline as L}from"node:stream/promises";import k,{EventEmitter as M}from"events";import{StringDecoder as $}from"node:string_decoder";import j from"assert";import{Buffer as P}from"buffer";import z from"node:assert";import{randomBytes as U}from"node:crypto";import{createRequire as H}from"node:module";import G from"node:os";import Z from"node:tty";import*as W from"crypto";import*as V from"fs";import*as Y from"path";import*as X from"zlib";var K,q,J,Q,ee={"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/adm-zip.js":function(e,t,i){let r=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/index.js"),n=i("path"),s=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/zipEntry.js"),o=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/zipFile.js"),u=(...e)=>r.findLast(e,e=>"boolean"==typeof e),a=(...e)=>r.findLast(e,e=>"string"==typeof e),l={noSort:!1,readEntries:!1,method:r.Constants.NONE,fs:null};e.exports=function(e,t){let i=null,h=Object.assign(Object.create(null),l);e&&"object"==typeof e&&(e instanceof Uint8Array||(Object.assign(h,e),e=h.input?h.input:void 0,h.input&&delete h.input),Buffer.isBuffer(e)&&(i=e,h.method=r.Constants.BUFFER,e=void 0)),Object.assign(h,t);let c=new r(h);if(("object"!=typeof h.decoder||"function"!=typeof h.decoder.encode||"function"!=typeof h.decoder.decode)&&(h.decoder=r.decoder),e&&"string"==typeof e)if(c.fs.existsSync(e))h.method=r.Constants.FILE,h.filename=e,i=c.fs.readFileSync(e);else throw r.Errors.INVALID_FILENAME();let d=new o(i,h),{canonical:D,sanitize:f,zipnamefix:p}=r;function m(e){if(e&&d){var t;if("string"==typeof e&&(t=d.getEntry(n.posix.normalize(e))),"object"==typeof e&&void 0!==e.entryName&&void 0!==e.header&&(t=d.getEntry(e.entryName)),t)return t}return null}function g(e){let{join:t,normalize:i,sep:r}=n.posix;return t(".",i(r+e.split("\\").join(r)+r))}function E(e){if(e instanceof RegExp)return function(t){return e.test(t)};return"function"!=typeof e?()=>!0:e}let b=(e,t)=>{let i=t.slice(-1);return i=i===c.sep?c.sep:"",n.relative(e,t)+i};return{readFile:function(e,t){var i=m(e);return i&&i.getData(t)||null},childCount:function(e){let t=m(e);if(t)return d.getChildCount(t)},readFileAsync:function(e,t){var i=m(e);i?i.getDataAsync(t):t(null,"getEntry failed for:"+e)},readAsText:function(e,t){var i=m(e);if(i){var r=i.getData();if(r&&r.length)return r.toString(t||"utf8")}return""},readAsTextAsync:function(e,t,i){var r=m(e);r?r.getDataAsync(function(e,r){if(r)return void t(e,r);e&&e.length?t(e.toString(i||"utf8")):t("")}):t("")},deleteFile:function(e,t=!0){var i=m(e);i&&d.deleteFile(i.entryName,t)},deleteEntry:function(e){var t=m(e);t&&d.deleteEntry(t.entryName)},addZipComment:function(e){d.comment=e},getZipComment:function(){return d.comment||""},addZipEntryComment:function(e,t){var i=m(e);i&&(i.comment=t)},getZipEntryComment:function(e){var t=m(e);return t&&t.comment||""},updateFile:function(e,t){var i=m(e);i&&i.setData(t)},addLocalFile:function(e,t,i,s){if(c.fs.existsSync(e)){t=t?g(t):"";let r=n.win32.basename(n.win32.normalize(e));t+=i||r;let o=c.fs.statSync(e),u=o.isFile()?c.fs.readFileSync(e):Buffer.alloc(0);o.isDirectory()&&(t+=c.sep),this.addFile(t,u,s,o)}else throw r.Errors.FILE_NOT_FOUND(e)},addLocalFileAsync:function(e,t){e="object"==typeof e?e:{localPath:e};let i=n.resolve(e.localPath),{comment:r}=e,{zipPath:s,zipName:o}=e,u=this;c.fs.stat(i,function(e,a){if(e)return t(e,!1);s=s?g(s):"";let l=n.win32.basename(n.win32.normalize(i));if(s+=o||l,a.isFile())c.fs.readFile(i,function(e,i){return e?t(e,!1):(u.addFile(s,i,r,a),setImmediate(t,void 0,!0))});else if(a.isDirectory())return s+=c.sep,u.addFile(s,Buffer.alloc(0),r,a),setImmediate(t,void 0,!0)})},addLocalFolder:function(e,t,i){if(i=E(i),t=t?g(t):"",e=n.normalize(e),c.fs.existsSync(e)){let r=c.findFiles(e);if(r.length)for(let s of r){let r=n.join(t,b(e,s));i(r)&&this.addLocalFile(s,n.dirname(r))}}else throw r.Errors.FILE_NOT_FOUND(e)},addLocalFolderAsync:function(e,t,i,s){s=E(s),i=i?g(i):"",e=n.normalize(e);var o=this;c.fs.open(e,"r",function(n){if(n&&"ENOENT"===n.code)t(void 0,r.Errors.FILE_NOT_FOUND(e));else if(n)t(void 0,n);else{var u=c.findFiles(e),a=-1,l=function(){if((a+=1){l()})}else t(!0,void 0)};l()}})},addLocalFolderAsync2:function(e,t){let i=this;e="object"==typeof e?e:{localPath:e},localPath=n.resolve(g(e.localPath));let{zipPath:s,filter:o,namefix:u}=e;if(o instanceof RegExp){var a;a=o,o=function(e){return a.test(e)}}else"function"!=typeof o&&(o=function(){return!0});s=s?g(s):"","latin1"==u&&(u=e=>e.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^\x20-\x7E]/g,"")),"function"!=typeof u&&(u=e=>e);let l=e=>n.join(s,u(b(localPath,e)));c.fs.open(localPath,"r",function(e){e&&"ENOENT"===e.code?t(void 0,r.Errors.FILE_NOT_FOUND(localPath)):e?t(void 0,e):c.findFilesAsync(localPath,function(e,r){if(e)return t(e);(r=r.filter(e=>o(l(e)))).length||t(void 0,!1),setImmediate(r.reverse().reduce(function(e,t){return function(r,s){if(r||!1===s)return setImmediate(e,r,!1);i.addLocalFileAsync({localPath:t,zipPath:n.dirname(l(t)),zipName:n.win32.basename(n.win32.normalize(u(t)))},e)}},t))})})},addLocalFolderPromise:function(e,t){return new Promise((i,r)=>{this.addLocalFolderAsync2(Object.assign({localPath:e},t),(e,t)=>{e&&r(e),t&&i(this)})})},addFile:function(e,t,i,r){let n=m(e=p(e)),o=null!=n;o||((n=new s(h)).entryName=e),n.comment=i||"";let u="object"==typeof r&&r instanceof c.fs.Stats;u&&(n.header.time=r.mtime);var a=16*!!n.isDirectory;let l=n.isDirectory?16384:32768;return u?l|=4095&r.mode:"number"==typeof r?l|=4095&r:l|=n.isDirectory?493:420,a=(a|l<<16)>>>0,n.attr=a,n.setData(t),o||d.setEntry(n),n},getEntries:function(e){return d.password=e,d?d.entries:[]},getEntry:function(e){return m(e)},getEntryCount:function(){return d.getEntryCount()},forEach:function(e){return d.forEach(e)},extractEntryTo:function(e,t,i,s,o,l){s=u(!1,s),o=u(!1,o),i=u(!0,i),l=a(o,l);var h=m(e);if(!h)throw r.Errors.NO_ENTRY();var p=D(h.entryName),g=f(t,l&&!h.isDirectory?l:i?p:n.basename(p));if(h.isDirectory)return d.getEntryChildren(h).forEach(function(e){if(e.isDirectory)return;var u=e.getData();if(!u)throw r.Errors.CANT_EXTRACT_FILE();var a=D(e.entryName),l=f(t,i?a:n.basename(a));let h=o?e.header.fileAttr:void 0;c.writeFileTo(l,u,s,h)}),!0;var E=h.getData(d.password);if(!E)throw r.Errors.CANT_EXTRACT_FILE();if(c.fs.existsSync(g)&&!s)throw r.Errors.CANT_OVERRIDE();let b=o?e.header.fileAttr:void 0;return c.writeFileTo(g,E,s,b),!0},test:function(e){if(!d)return!1;for(var t in d.entries)try{if(t.isDirectory)continue;if(!d.entries[t].getData(e))return!1}catch(e){return!1}return!0},extractAllTo:function(e,t,i,n){if(n=a(i=u(!1,i),n),t=u(!1,t),!d)throw r.Errors.NO_ZIP();d.entries.forEach(function(s){var o=f(e,D(s.entryName));if(s.isDirectory)return void c.makeDir(o);var u=s.getData(n);if(!u)throw r.Errors.CANT_EXTRACT_FILE();let a=i?s.header.fileAttr:void 0;c.writeFileTo(o,u,t,a);try{c.fs.utimesSync(o,s.header.time,s.header.time)}catch(e){throw r.Errors.CANT_EXTRACT_FILE()}})},extractAllToAsync:function(e,t,i,s){if(s=((...e)=>r.findLast(e,e=>"function"==typeof e))(t,i,s),i=u(!1,i),t=u(!1,t),!s)return new Promise((r,n)=>{this.extractAllToAsync(e,t,i,function(e){e?n(e):r(this)})});if(!d)return void s(r.Errors.NO_ZIP());e=n.resolve(e);let o=t=>f(e,n.normalize(D(t.entryName))),a=(e,t)=>Error(e+': "'+t+'"'),l=[],h=[];for(let e of(d.entries.forEach(e=>{e.isDirectory?l.push(e):h.push(e)}),l)){let t=o(e),r=i?e.header.fileAttr:void 0;try{c.makeDir(t),r&&c.fs.chmodSync(t,r),c.fs.utimesSync(t,e.header.time,e.header.time)}catch(e){s(a("Unable to create folder",t))}}h.reverse().reduce(function(s,o){return function(u){if(u)s(u);else{let u=n.normalize(D(o.entryName)),l=f(e,u);o.getDataAsync(function(e,n){if(n)s(n);else if(e){let r=i?o.header.fileAttr:void 0;c.writeFileToAsync(l,e,t,r,function(e){e||s(a("Unable to write file",l)),c.fs.utimes(l,o.header.time,o.header.time,function(e){e?s(a("Unable to set times",l)):s()})})}else s(r.Errors.CANT_EXTRACT_FILE())})}}},s)()},writeZip:function(e,t){if(1==arguments.length&&"function"==typeof e&&(t=e,e=""),!e&&h.filename&&(e=h.filename),e){var i=d.compressToBuffer();if(i){var r=c.writeFileTo(e,i,!0);"function"==typeof t&&t(r?null:Error("failed"),"")}}},writeZipPromise:function(e,t){let{overwrite:i,perm:r}=Object.assign({overwrite:!0},t);return new Promise((t,n)=>{!e&&h.filename&&(e=h.filename),e||n("ADM-ZIP: ZIP File Name Missing"),this.toBufferPromise().then(s=>{c.writeFileToAsync(e,s,i,r,e=>e?t(e):n("ADM-ZIP: Wasn't able to write zip file"))},n)})},toBufferPromise:function(){return new Promise((e,t)=>{d.toAsyncBuffer(e,t)})},toBuffer:function(e,t,i,r){return"function"==typeof e?(d.toAsyncBuffer(e,t,i,r),null):d.compressToBuffer()}}}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/entryHeader.js":function(e,t,i){var r=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/index.js"),n=r.Constants;e.exports=function(){var e,t=10,i=0,s=0,o=0,u=0,a=0,l=0,h=0,c=0,d=0,D=0,f=0,p=0,m=0;e=20|(r.isWin?2560:768),i|=n.FLG_EFS;let g={extraLen:0},E=e=>Math.max(0,e)>>>0;return o=r.fromDate2DOS(new Date),{get made(){return e},set made(val){e=val},get version(){return t},set version(val){t=val},get flags(){return i},set flags(val){i=val},get flags_efs(){return(i&n.FLG_EFS)>0},set flags_efs(val){val?i|=n.FLG_EFS:i&=~n.FLG_EFS},get flags_desc(){return(i&n.FLG_DESC)>0},set flags_desc(val){val?i|=n.FLG_DESC:i&=~n.FLG_DESC},get method(){return s},set method(val){switch(val){case n.STORED:this.version=10;case n.DEFLATED:default:this.version=20}s=val},get time(){return r.fromDOS2Date(this.timeval)},set time(val){this.timeval=r.fromDate2DOS(val)},get timeval(){return o},set timeval(val){o=E(val)},get timeHighByte(){return 255&Math.max(0,o>>>8)},get crc(){return u},set crc(val){u=E(val)},get compressedSize(){return a},set compressedSize(val){a=E(val)},get size(){return l},set size(val){l=E(val)},get fileNameLength(){return h},set fileNameLength(val){h=val},get extraLength(){return c},set extraLength(val){c=val},get extraLocalLength(){return g.extraLen},set extraLocalLength(val){g.extraLen=val},get commentLength(){return d},set commentLength(val){d=val},get diskNumStart(){return D},set diskNumStart(val){D=E(val)},get inAttr(){return f},set inAttr(val){f=E(val)},get attr(){return p},set attr(val){p=E(val)},get fileAttr(){return(p||0)>>16&4095},get offset(){return m},set offset(val){m=E(val)},get encrypted(){return(i&n.FLG_ENC)===n.FLG_ENC},get centralHeaderSize(){return n.CENHDR+h+c+d},get realDataOffset(){return m+n.LOCHDR+g.fnameLen+g.extraLen},get localHeader(){return g},loadLocalHeaderFromBinary:function(e){var t=e.slice(m,m+n.LOCHDR);if(t.readUInt32LE(0)!==n.LOCSIG)throw r.Errors.INVALID_LOC();g.version=t.readUInt16LE(n.LOCVER),g.flags=t.readUInt16LE(n.LOCFLG),g.method=t.readUInt16LE(n.LOCHOW),g.time=t.readUInt32LE(n.LOCTIM),g.crc=t.readUInt32LE(n.LOCCRC),g.compressedSize=t.readUInt32LE(n.LOCSIZ),g.size=t.readUInt32LE(n.LOCLEN),g.fnameLen=t.readUInt16LE(n.LOCNAM),g.extraLen=t.readUInt16LE(n.LOCEXT);let i=m+n.LOCHDR+g.fnameLen,s=i+g.extraLen;return e.slice(i,s)},loadFromBinary:function(g){if(g.length!==n.CENHDR||g.readUInt32LE(0)!==n.CENSIG)throw r.Errors.INVALID_CEN();e=g.readUInt16LE(n.CENVEM),t=g.readUInt16LE(n.CENVER),i=g.readUInt16LE(n.CENFLG),s=g.readUInt16LE(n.CENHOW),o=g.readUInt32LE(n.CENTIM),u=g.readUInt32LE(n.CENCRC),a=g.readUInt32LE(n.CENSIZ),l=g.readUInt32LE(n.CENLEN),h=g.readUInt16LE(n.CENNAM),c=g.readUInt16LE(n.CENEXT),d=g.readUInt16LE(n.CENCOM),D=g.readUInt16LE(n.CENDSK),f=g.readUInt16LE(n.CENATT),p=g.readUInt32LE(n.CENATX),m=g.readUInt32LE(n.CENOFF)},localHeaderToBinary:function(){var e=Buffer.alloc(n.LOCHDR);return e.writeUInt32LE(n.LOCSIG,0),e.writeUInt16LE(t,n.LOCVER),e.writeUInt16LE(i,n.LOCFLG),e.writeUInt16LE(s,n.LOCHOW),e.writeUInt32LE(o,n.LOCTIM),e.writeUInt32LE(u,n.LOCCRC),e.writeUInt32LE(a,n.LOCSIZ),e.writeUInt32LE(l,n.LOCLEN),e.writeUInt16LE(h,n.LOCNAM),e.writeUInt16LE(g.extraLen,n.LOCEXT),e},centralHeaderToBinary:function(){var r=Buffer.alloc(n.CENHDR+h+c+d);return r.writeUInt32LE(n.CENSIG,0),r.writeUInt16LE(e,n.CENVEM),r.writeUInt16LE(t,n.CENVER),r.writeUInt16LE(i,n.CENFLG),r.writeUInt16LE(s,n.CENHOW),r.writeUInt32LE(o,n.CENTIM),r.writeUInt32LE(u,n.CENCRC),r.writeUInt32LE(a,n.CENSIZ),r.writeUInt32LE(l,n.CENLEN),r.writeUInt16LE(h,n.CENNAM),r.writeUInt16LE(c,n.CENEXT),r.writeUInt16LE(d,n.CENCOM),r.writeUInt16LE(D,n.CENDSK),r.writeUInt16LE(f,n.CENATT),r.writeUInt32LE(p,n.CENATX),r.writeUInt32LE(m,n.CENOFF),r},toJSON:function(){let o=function(e){return e+" bytes"};return{made:e,version:t,flags:i,method:r.methodToString(s),time:this.time,crc:"0x"+u.toString(16).toUpperCase(),compressedSize:o(a),size:o(l),fileNameLength:o(h),extraLength:o(c),commentLength:o(d),diskNumStart:D,inAttr:f,attr:p,offset:m,centralHeaderSize:o(n.CENHDR+h+c+d)}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/index.js":function(e,t,i){t.EntryHeader=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/entryHeader.js"),t.MainHeader=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/mainHeader.js")},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/mainHeader.js":function(e,t,i){var r=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/index.js"),n=r.Constants;e.exports=function(){var e=0,t=0,i=0,s=0,o=0;return{get diskEntries(){return e},set diskEntries(val){e=t=val},get totalEntries(){return t},set totalEntries(val){t=e=val},get size(){return i},set size(val){i=val},get offset(){return s},set offset(val){s=val},get commentLength(){return o},set commentLength(val){o=val},get mainHeaderSize(){return n.ENDHDR+o},loadFromBinary:function(u){if((u.length!==n.ENDHDR||u.readUInt32LE(0)!==n.ENDSIG)&&(u.length=15&&t>0?{maxOutputLength:t}:{};return{inflate:function(){return n.inflateRawSync(e,s)},inflateAsync:function(t){var i=n.createInflateRaw(s),r=[],o=0;i.on("data",function(e){r.push(e),o+=e.length}),i.on("end",function(){var e=Buffer.alloc(o),i=0;e.fill(0);for(var n=0;n{for(let e=0;e<8;e++)0!=(1&t)?t=t>>>1^0xedb88320:t>>>=1;return t>>>0}),o=(e,t)=>Math.imul(e,t)>>>0,u=(e,t)=>s[(e^t)&255]^e>>>8,a=()=>"function"==typeof r?r(Buffer.alloc(12)):a.node();a.node=()=>{let e=Buffer.alloc(12),t=e.length;for(let i=0;i>>24),e},h.prototype.next=function(){let e=(2|this.keys[2])>>>0;return o(e,1^e)>>8&255},e.exports={decrypt:function(e,t,i){if(!e||!Buffer.isBuffer(e)||e.length<12)return Buffer.alloc(0);let r=function(e){let t=new h(e);return function(e){let i=Buffer.alloc(e.length),r=0;for(let n of e)i[r++]=t.updateKeys(n^t.next());return i}}(i),s=r(e.slice(0,12)),o=(8&t.flags)==8?t.timeHighByte:t.crc>>>24;if(s[11]!==o)throw n.WRONG_PASSWORD();return r(e.slice(12))},encrypt:function(e,t,i,r=!1){null==e&&(e=Buffer.alloc(0)),Buffer.isBuffer(e)||(e=Buffer.from(e.toString()));let n=function(e){let t=new h(e);return function(e,i,r=0){for(let n of(i||(i=Buffer.alloc(e.length)),e)){let e=t.next();i[r++]=n^e,t.updateKeys(n)}return i}}(i),s=l.genSalt();s[11]=t.crc>>>24&255,r&&(s[10]=t.crc>>>16&255);let o=Buffer.alloc(e.length+12);return n(s,o),n(e,o,12)},_salter:function(e){Buffer.isBuffer(e)&&e.length>=12?l.genSalt=function(){return e.slice(0,12)}:"node"===e?l.genSalt=a.node:l.genSalt=a}}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/constants.js":function(e){e.exports={LOCHDR:30,LOCSIG:0x4034b50,LOCVER:4,LOCFLG:6,LOCHOW:8,LOCTIM:10,LOCCRC:14,LOCSIZ:18,LOCLEN:22,LOCNAM:26,LOCEXT:28,EXTSIG:0x8074b50,EXTHDR:16,EXTCRC:4,EXTSIZ:8,EXTLEN:12,CENHDR:46,CENSIG:0x2014b50,CENVEM:4,CENVER:6,CENFLG:8,CENHOW:10,CENTIM:12,CENCRC:16,CENSIZ:20,CENLEN:24,CENNAM:28,CENEXT:30,CENCOM:32,CENDSK:34,CENATT:36,CENATX:38,CENOFF:42,ENDHDR:22,ENDSIG:0x6054b50,ENDSUB:8,ENDTOT:10,ENDSIZ:12,ENDOFF:16,ENDCOM:20,END64HDR:20,END64SIG:0x7064b50,END64START:4,END64OFF:8,END64NUMDISKS:16,ZIP64SIG:0x6064b50,ZIP64HDR:56,ZIP64LEAD:12,ZIP64SIZE:4,ZIP64VEM:12,ZIP64VER:14,ZIP64DSK:16,ZIP64DSKDIR:20,ZIP64SUB:24,ZIP64TOT:32,ZIP64SIZB:40,ZIP64OFF:48,ZIP64EXTRA:56,STORED:0,SHRUNK:1,REDUCED1:2,REDUCED2:3,REDUCED3:4,REDUCED4:5,IMPLODED:6,DEFLATED:8,ENHANCED_DEFLATED:9,PKWARE:10,BZIP2:12,LZMA:14,IBM_TERSE:18,IBM_LZ77:19,AES_ENCRYPT:99,FLG_ENC:1,FLG_COMP1:2,FLG_COMP2:4,FLG_DESC:8,FLG_ENH:16,FLG_PATCH:32,FLG_STR:64,FLG_EFS:2048,FLG_MSK:4096,FILE:2,BUFFER:1,NONE:0,EF_ID:0,EF_SIZE:2,ID_ZIP64:1,ID_AVINFO:7,ID_PFS:8,ID_OS2:9,ID_NTFS:10,ID_OPENVMS:12,ID_UNIX:13,ID_FORK:14,ID_PATCH:15,ID_X509_PKCS7:20,ID_X509_CERTID_F:21,ID_X509_CERTID_C:22,ID_STRONGENC:23,ID_RECORD_MGT:24,ID_X509_PKCS7_RL:25,ID_IBM1:101,ID_IBM2:102,ID_POSZIP:18064,EF_ZIP64_OR_32:0xffffffff,EF_ZIP64_OR_16:65535,EF_ZIP64_SUNCOMP:0,EF_ZIP64_SCOMP:8,EF_ZIP64_RHO:16,EF_ZIP64_DSN:24}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/decoder.js":function(e){e.exports={efs:!0,encode:e=>Buffer.from(e,"utf8"),decode:e=>e.toString("utf8")}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/errors.js":function(e,t){let i={INVALID_LOC:"Invalid LOC header (bad signature)",INVALID_CEN:"Invalid CEN header (bad signature)",INVALID_END:"Invalid END header (bad signature)",DESCRIPTOR_NOT_EXIST:"No descriptor present",DESCRIPTOR_UNKNOWN:"Unknown descriptor format",DESCRIPTOR_FAULTY:"Descriptor data is malformed",NO_DATA:"Nothing to decompress",BAD_CRC:"CRC32 checksum failed {0}",FILE_IN_THE_WAY:"There is a file in the way: {0}",UNKNOWN_METHOD:"Invalid/unsupported compression method",AVAIL_DATA:"inflate::Available inflate data did not terminate",INVALID_DISTANCE:"inflate::Invalid literal/length or distance code in fixed or dynamic block",TO_MANY_CODES:"inflate::Dynamic block code description: too many length or distance codes",INVALID_REPEAT_LEN:"inflate::Dynamic block code description: repeat more than specified lengths",INVALID_REPEAT_FIRST:"inflate::Dynamic block code description: repeat lengths with no first length",INCOMPLETE_CODES:"inflate::Dynamic block code description: code lengths codes incomplete",INVALID_DYN_DISTANCE:"inflate::Dynamic block code description: invalid distance code lengths",INVALID_CODES_LEN:"inflate::Dynamic block code description: invalid literal/length code lengths",INVALID_STORE_BLOCK:"inflate::Stored block length did not match one's complement",INVALID_BLOCK_TYPE:"inflate::Invalid block type (type == 3)",CANT_EXTRACT_FILE:"Could not extract the file",CANT_OVERRIDE:"Target file already exists",DISK_ENTRY_TOO_LARGE:"Number of disk entries is too large",NO_ZIP:"No zip file was loaded",NO_ENTRY:"Entry doesn't exist",DIRECTORY_CONTENT_ERROR:"A directory cannot have content",FILE_NOT_FOUND:'File not found: "{0}"',NOT_IMPLEMENTED:"Not implemented",INVALID_FILENAME:"Invalid filename",INVALID_FORMAT:"Invalid or unsupported zip format. No END header found",INVALID_PASS_PARAM:"Incompatible password parameter",WRONG_PASSWORD:"Wrong Password",COMMENT_TOO_LONG:"Comment is too long",EXTRA_FIELD_PARSE_ERROR:"Extra field parsing error"};for(let e of Object.keys(i))t[e]=function(e){return function(...t){return t.length&&(e=e.replace(/\{(\d)\}/g,(e,i)=>t[i]||"")),Error("ADM-ZIP: "+e)}}(i[e])},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/fattr.js":function(e,t,i){let r=i("path");e.exports=function(e,{fs:t}){var i=e||"",n={directory:!1,readonly:!1,hidden:!1,executable:!1,mtime:0,atime:0},s=null;return i&&t.existsSync(i)?(n.directory=(s=t.statSync(i)).isDirectory(),n.mtime=s.mtime,n.atime=s.atime,n.executable=(73&s.mode)!=0,n.readonly=(128&s.mode)==0,n.hidden="."===r.basename(i)[0]):console.warn("Invalid path: "+i),{get directory(){return n.directory},get readOnly(){return n.readonly},get hidden(){return n.hidden},get mtime(){return n.mtime},get atime(){return n.atime},get executable(){return n.executable},decodeAttributes:function(){},encodeAttributes:function(){},toJSON:function(){return{path:i,isDirectory:n.directory,isReadOnly:n.readonly,isHidden:n.hidden,isExecutable:n.executable,mTime:n.mtime,aTime:n.atime}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/index.js":function(e,t,i){e.exports=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/utils.js"),e.exports.Constants=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/constants.js"),e.exports.Errors=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/errors.js"),e.exports.FileAttr=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/fattr.js"),e.exports.decoder=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/decoder.js")},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/utils.js":function(e,t,i){let r=i("fs"),n=i("path"),s=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/constants.js"),o=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/errors.js"),u="object"==typeof process&&"win32"===process.platform,a=e=>"object"==typeof e&&null!==e,l=new Uint32Array(256).map((e,t)=>{for(let e=0;e<8;e++)(1&t)!=0?t=0xedb88320^t>>>1:t>>>=1;return t>>>0});function h(e){this.sep=n.sep,this.fs=r,a(e)&&a(e.fs)&&"function"==typeof e.fs.statSync&&(this.fs=e.fs)}e.exports=h,h.prototype.makeDir=function(e){let t,i=this;t=e.split(i.sep)[0],e.split(i.sep).forEach(function(e){var r;if(e&&":"!==e.substr(-1,1)){t+=i.sep+e;try{r=i.fs.statSync(t)}catch(e){i.fs.mkdirSync(t)}if(r&&r.isFile())throw o.FILE_IN_THE_WAY(`"${t}"`)}})},h.prototype.writeFileTo=function(e,t,i,r){if(this.fs.existsSync(e)){var s;if(!i||this.fs.statSync(e).isDirectory())return!1}var o=n.dirname(e);this.fs.existsSync(o)||this.makeDir(o);try{s=this.fs.openSync(e,"w",438)}catch(t){this.fs.chmodSync(e,438),s=this.fs.openSync(e,"w",438)}if(s)try{this.fs.writeSync(s,t,0,t.length,0)}finally{this.fs.closeSync(s)}return this.fs.chmodSync(e,r||438),!0},h.prototype.writeFileToAsync=function(e,t,i,r,s){"function"==typeof r&&(s=r,r=void 0);let o=this;o.fs.exists(e,function(u){if(u&&!i)return s(!1);o.fs.stat(e,function(i,a){if(u&&a.isDirectory())return s(!1);var l=n.dirname(e);o.fs.exists(l,function(i){i||o.makeDir(l),o.fs.open(e,"w",438,function(i,n){i?o.fs.chmod(e,438,function(){o.fs.open(e,"w",438,function(i,n){o.fs.write(n,t,0,t.length,0,function(){o.fs.close(n,function(){o.fs.chmod(e,r||438,function(){s(!0)})})})})}):n?o.fs.write(n,t,0,t.length,0,function(){o.fs.close(n,function(){o.fs.chmod(e,r||438,function(){s(!0)})})}):o.fs.chmod(e,r||438,function(){s(!0)})})})})})},h.prototype.findFiles=function(e){let t=this;return function e(i,r,s){"boolean"==typeof r&&(s=r,r=void 0);let o=[];return t.fs.readdirSync(i).forEach(function(u){let a=n.join(i,u),l=t.fs.statSync(a);(!r||r.test(a))&&o.push(n.normalize(a)+(l.isDirectory()?t.sep:"")),l.isDirectory()&&s&&(o=o.concat(e(a,r,s)))}),o}(e,void 0,!0)},h.prototype.findFilesAsync=function(e,t){let i=this,r=[];i.fs.readdir(e,function(s,o){if(s)return t(s);let u=o.length;if(!u)return t(null,r);o.forEach(function(s){s=n.join(e,s),i.fs.stat(s,function(e,o){if(e)return t(e);o&&(r.push(n.normalize(s)+(o.isDirectory()?i.sep:"")),o.isDirectory()?i.findFilesAsync(s,function(e,i){if(e)return t(e);r=r.concat(i),--u||t(null,r)}):--u||t(null,r))})})})},h.prototype.getAttributes=function(){},h.prototype.setAttributes=function(){},h.crc32update=function(e,t){return l[(e^t)&255]^e>>>8},h.crc32=function(e){"string"==typeof e&&(e=Buffer.from(e,"utf8"));let t=e.length,i=-1;for(let r=0;r>>0},h.methodToString=function(e){switch(e){case s.STORED:return"STORED ("+e+")";case s.DEFLATED:return"DEFLATED ("+e+")";default:return"UNSUPPORTED ("+e+")"}},h.canonical=function(e){if(!e)return"";let t=n.posix.normalize("/"+e.split("\\").join("/"));return n.join(".",t)},h.zipnamefix=function(e){if(!e)return"";let t=n.posix.normalize("/"+e.split("\\").join("/"));return n.posix.join(".",t)},h.findLast=function(e,t){if(!Array.isArray(e))throw TypeError("arr is not array");let i=e.length>>>0;for(let r=i-1;r>=0;r--)if(t(e[r],r,e))return e[r]},h.sanitize=function(e,t){e=n.resolve(n.normalize(e));for(var i=t.split("/"),r=0,s=i.length;r>25&127)+1980,Math.max((e>>21&15)-1,0),Math.max(e>>16&31,1),e>>11&31,e>>5&63,(31&e)<<1)},h.fromDate2DOS=function(e){let t=0,i=0;return e.getFullYear()>1979&&(t=(e.getFullYear()-1980&127)<<9|e.getMonth()+1<<5|e.getDate(),i=e.getHours()<<11|e.getMinutes()<<5|e.getSeconds()>>1),t<<16|i},h.isWin=u,h.crcTable=l},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/zipEntry.js":function(e,t,i){var r=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/index.js"),n=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/index.js"),s=r.Constants,o=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/methods/index.js");e.exports=function(e,t){var i=new n.EntryHeader,u=Buffer.alloc(0),a=Buffer.alloc(0),l=!1,h=null,c=Buffer.alloc(0),d=Buffer.alloc(0),D=!0;let f="object"==typeof e.decoder?e.decoder:r.decoder;function p(){return t&&t instanceof Uint8Array?(d=i.loadLocalHeaderFromBinary(t),t.slice(i.realDataOffset,i.realDataOffset+i.compressedSize)):Buffer.alloc(0)}function m(e){if(i.flags_desc){let n={},o=i.realDataOffset+i.compressedSize;if(t.readUInt32LE(o)==s.LOCSIG||t.readUInt32LE(o)==s.CENSIG)throw r.Errors.DESCRIPTOR_NOT_EXIST();if(t.readUInt32LE(o)==s.EXTSIG)n.crc=t.readUInt32LE(o+s.EXTCRC),n.compressedSize=t.readUInt32LE(o+s.EXTSIZ),n.size=t.readUInt32LE(o+s.EXTLEN);else if(19280===t.readUInt16LE(o+12))n.crc=t.readUInt32LE(o+s.EXTCRC-4),n.compressedSize=t.readUInt32LE(o+s.EXTSIZ-4),n.size=t.readUInt32LE(o+s.EXTLEN-4);else throw r.Errors.DESCRIPTOR_UNKNOWN();if(n.compressedSize!==i.compressedSize||n.size!==i.size||n.crc!==i.crc)throw r.Errors.DESCRIPTOR_FAULTY();if(r.crc32(e)!==n.crc)return!1}else if(r.crc32(e)!==i.localHeader.crc)return!1;return!0}function g(e,t,n){if(void 0===t&&"string"==typeof e&&(n=e,e=void 0),l)return e&&t&&t(Buffer.alloc(0),r.Errors.DIRECTORY_CONTENT_ERROR()),Buffer.alloc(0);var s=p();if(0===s.length)return e&&t&&t(s),s;if(i.encrypted){if("string"!=typeof n&&!Buffer.isBuffer(n))throw r.Errors.INVALID_PASS_PARAM();s=o.ZipCrypto.decrypt(s,i,n)}var a=Buffer.alloc(i.size);switch(i.method){case r.Constants.STORED:if(s.copy(a),m(a))return e&&t&&t(a),a;throw e&&t&&t(a,r.Errors.BAD_CRC()),r.Errors.BAD_CRC();case r.Constants.DEFLATED:var h=new o.Inflater(s,i.size);if(e)h.inflateAsync(function(e){e.copy(e,0),t&&(m(e)?t(e):t(e,r.Errors.BAD_CRC()))});else{if(h.inflate(a).copy(a,0),!m(a))throw r.Errors.BAD_CRC(`"${f.decode(u)}"`);return a}break;default:throw e&&t&&t(Buffer.alloc(0),r.Errors.UNKNOWN_METHOD()),r.Errors.UNKNOWN_METHOD()}}function E(e,n){if((!h||!h.length)&&Buffer.isBuffer(t))return e&&n&&n(p()),p();if(h.length&&!l){var s;switch(i.method){case r.Constants.STORED:return i.compressedSize=i.size,s=Buffer.alloc(h.length),h.copy(s),e&&n&&n(s),s;default:case r.Constants.DEFLATED:var u=new o.Deflater(h);if(e)u.deflateAsync(function(e){s=Buffer.alloc(e.length),i.compressedSize=e.length,e.copy(s),n&&n(s)});else{var a=u.deflate();return i.compressedSize=a.length,a}u=null}}else{if(!e||!n)return Buffer.alloc(0);n(Buffer.alloc(0))}}function b(e,t){return(e.readUInt32LE(t+4)<<4)+e.readUInt32LE(t)}return D=!!f.hasOwnProperty("efs")&&f.efs,{get entryName(){return f.decode(u)},get rawEntryName(){return u},set entryName(val){var y=(u=r.toBuffer(val,f.encode))[u.length-1];l=47===y||92===y,i.fileNameLength=u.length},get efs(){if("function"==typeof D)return D(this.entryName);return D},get extra(){return c},set extra(val){c=val,i.extraLength=val.length;try{for(var F,C,v,w=0;w+4=s.EF_ZIP64_SCOMP&&(t=b(e,s.EF_ZIP64_SUNCOMP),i.size===s.EF_ZIP64_OR_32&&(i.size=t)),e.length>=s.EF_ZIP64_RHO&&(r=b(e,s.EF_ZIP64_SCOMP),i.compressedSize===s.EF_ZIP64_OR_32&&(i.compressedSize=r)),e.length>=s.EF_ZIP64_DSN&&(n=b(e,s.EF_ZIP64_RHO),i.offset===s.EF_ZIP64_OR_32&&(i.offset=n)),e.length>=s.EF_ZIP64_DSN+4&&(o=e.readUInt32LE(s.EF_ZIP64_DSN),i.diskNumStart===s.EF_ZIP64_OR_16&&(i.diskNumStart=o))}(v)}catch(e){throw r.Errors.EXTRA_FIELD_PARSE_ERROR()}},get comment(){return f.decode(a)},set comment(val){if(i.commentLength=(a=r.toBuffer(val,f.encode)).length,a.length>65535)throw r.Errors.COMMENT_TOO_LONG()},get name(){var _=f.decode(u);return l?_.substr(_.length-1).split("/").pop():_.split("/").pop()},get isDirectory(){return l},getCompressedData:function(){return E(!1,null)},getCompressedDataAsync:function(e){E(!0,e)},setData:function(e){h=r.toBuffer(e,r.decoder.encode),!l&&h.length?(i.size=h.length,i.method=r.Constants.DEFLATED,i.crc=r.crc32(e),i.changed=!0):i.method=r.Constants.STORED},getData:function(e){return i.changed?h:g(!1,null,e)},getDataAsync:function(e,t){i.changed?e(h):g(!0,e,t)},set attr(attr){i.attr=attr},get attr(){return i.attr},set header(data){i.loadFromBinary(data)},get header(){return i},packCentralHeader:function(){i.flags_efs=this.efs,i.extraLength=c.length;var e=i.centralHeaderToBinary(),t=r.Constants.CENHDR;return u.copy(e,t),t+=u.length,c.copy(e,t),t+=i.extraLength,a.copy(e,t),e},packLocalHeader:function(){let e=0;i.flags_efs=this.efs,i.extraLocalLength=d.length;let t=i.localHeaderToBinary(),r=Buffer.alloc(t.length+u.length+i.extraLocalLength);return t.copy(r,e),e+=t.length,u.copy(r,e),e+=u.length,d.copy(r,e),e+=d.length,r},toJSON:function(){let e=function(e){return"<"+(e&&e.length+" bytes buffer"||"null")+">"};return{entryName:this.entryName,name:this.name,comment:this.comment,isDirectory:this.isDirectory,header:i.toJSON(),compressedData:e(t),data:e(h)}},toString:function(){return JSON.stringify(this.toJSON(),null," ")}}}},"../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/zipFile.js":function(e,t,i){let r=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/zipEntry.js"),n=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/headers/index.js"),s=i("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/util/index.js");e.exports=function(e,t){var i=[],o={},u=Buffer.alloc(0),a=new n.MainHeader,l=!1;let h=new Set,{noSort:c,decoder:d}=t;function D(){if(l=!0,o={},a.diskEntries>(e.length-a.offset)/s.Constants.CENHDR)throw s.Errors.DISK_ENTRY_TOO_LARGE();i=Array(a.diskEntries);for(var n=a.offset,u=0;u1&&!c&&i.sort((e,t)=>e.entryName.toLowerCase().localeCompare(t.entryName.toLowerCase()))}return e?function(i){var r=e.length-s.Constants.ENDHDR,n=Math.max(0,r-65535),o=n,l=e.length,h=-1,c=0;for("boolean"==typeof t.trailingSpace&&t.trailingSpace&&(n=0);r>=o;r--)if(80===e[r]){if(e.readUInt32LE(r)===s.Constants.ENDSIG){h=r,c=r,l=r+s.Constants.ENDHDR,o=r-s.Constants.END64HDR;continue}if(e.readUInt32LE(r)===s.Constants.END64SIG){o=n;continue}if(e.readUInt32LE(r)===s.Constants.ZIP64SIG){h=r,l=r+s.readBigUInt64LE(e,r+s.Constants.ZIP64SIZE)+s.Constants.ZIP64LEAD;break}}if(-1==h)throw s.Errors.INVALID_FORMAT();a.loadFromBinary(e.slice(h,l)),a.commentLength&&(u=e.slice(c+s.Constants.ENDHDR)),i&&D()}(t.readEntries):l=!0,{get entries(){return l||D(),i.filter(e=>!h.has(e))},get comment(){return d.decode(u)},set comment(val){a.commentLength=(u=s.toBuffer(val,d.encode)).length},getEntryCount:function(){return l?i.length:a.diskEntries},forEach:function(e){this.entries.forEach(e)},getEntry:function(e){return l||D(),o[e]||null},setEntry:function(e){l||D(),i.push(e),o[e.entryName]=e,a.totalEntries=i.length},deleteFile:function(e,t=!0){l||D();let i=o[e];this.getEntryChildren(i,t).map(e=>e.entryName).forEach(this.deleteEntry)},deleteEntry:function(e){l||D();let t=o[e],r=i.indexOf(t);r>=0&&(i.splice(r,1),delete o[e],a.totalEntries=i.length)},getEntryChildren:function(e,t=!0){if(l||D(),"object"==typeof e)if(!e.isDirectory||!t)return[e];else{let t=[],r=e.entryName;for(let e of i)e.entryName.startsWith(r)&&t.push(e);return t}return[]},getChildCount:function(e){if(e&&e.isDirectory){let t=this.getEntryChildren(e);return t.includes(e)?t.length-1:t.length}return 0},compressToBuffer:function(){l||D(),f();let t=[],i=[],r=0,n=0;a.size=0,a.offset=0;let o=0;for(let e of this.entries){let s=e.getCompressedData();e.header.offset=n;let u=e.packLocalHeader(),l=u.length+s.length;n+=l,t.push(u),t.push(s);let h=e.packCentralHeader();i.push(h),a.size+=h.length,r+=l+h.length,o++}r+=a.mainHeaderSize,a.offset=n,a.totalEntries=o,n=0;let h=Buffer.alloc(r);for(let e of t)e.copy(h,n),n+=e.length;for(let e of i)e.copy(h,n),n+=e.length;let c=a.toBinary();return u&&u.copy(c,s.Constants.ENDHDR),c.copy(h,n),e=h,l=!1,h},toAsyncBuffer:function(t,i,r,n){try{l||D(),f();let i=[],o=[],h=0,c=0,d=0;a.size=0,a.offset=0;let p=function(D){if(D.length>0){let e=D.shift(),t=e.entryName+e.extra.toString();r&&r(t),e.getCompressedDataAsync(function(r){n&&n(t),e.header.offset=c;let s=e.packLocalHeader(),u=s.length+r.length;c+=u,i.push(s),i.push(r);let l=e.packCentralHeader();o.push(l),a.size+=l.length,h+=u+l.length,d++,p(D)})}else{h+=a.mainHeaderSize,a.offset=c,a.totalEntries=d,c=0;let r=Buffer.alloc(h);i.forEach(function(e){e.copy(r,c),c+=e.length}),o.forEach(function(e){e.copy(r,c),c+=e.length});let n=a.toBinary();u&&u.copy(n,s.Constants.ENDHDR),n.copy(r,c),e=r,l=!1,t(r)}};p(Array.from(this.entries))}catch(e){i(e)}}}}},"../../node_modules/.pnpm/minimist@1.2.8/node_modules/minimist/index.js":function(e){function t(e){return!!("number"==typeof e||/^0x[0-9a-f]+$/i.test(e))||/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(e)}function i(e,t){return"constructor"===t&&"function"==typeof e[t]||"__proto__"===t}e.exports=function(e,r){r||(r={});var n={bools:{},strings:{},unknownFn:null};"function"==typeof r.unknown&&(n.unknownFn=r.unknown),"boolean"==typeof r.boolean&&r.boolean?n.allBools=!0:[].concat(r.boolean).filter(Boolean).forEach(function(e){n.bools[e]=!0});var s={};function o(e){return s[e].some(function(e){return n.bools[e]})}Object.keys(r.alias||{}).forEach(function(e){s[e]=[].concat(r.alias[e]),s[e].forEach(function(t){s[t]=[e].concat(s[e].filter(function(e){return t!==e}))})}),[].concat(r.string).filter(Boolean).forEach(function(e){n.strings[e]=!0,s[e]&&[].concat(s[e]).forEach(function(e){n.strings[e]=!0})});var u=r.default||{},a={_:[]};function l(e,t,r){for(var s=e,o=0;or=>{let n=""+r,s=n.indexOf(t,e.length);return~s?e+o(n,t,i,s)+t:e+n+t},o=(e,t,i,r)=>{let n="",s=0;do n+=e.substring(s,r)+i,s=r+t.length,r=e.indexOf(t,s);while(~r);return n+e.substring(s)},u=(e=n)=>{let t=e?s:()=>String;return{isColorSupported:e,reset:t("\x1b[0m","\x1b[0m"),bold:t("\x1b[1m","\x1b[22m","\x1b[22m\x1b[1m"),dim:t("\x1b[2m","\x1b[22m","\x1b[22m\x1b[2m"),italic:t("\x1b[3m","\x1b[23m"),underline:t("\x1b[4m","\x1b[24m"),inverse:t("\x1b[7m","\x1b[27m"),hidden:t("\x1b[8m","\x1b[28m"),strikethrough:t("\x1b[9m","\x1b[29m"),black:t("\x1b[30m","\x1b[39m"),red:t("\x1b[31m","\x1b[39m"),green:t("\x1b[32m","\x1b[39m"),yellow:t("\x1b[33m","\x1b[39m"),blue:t("\x1b[34m","\x1b[39m"),magenta:t("\x1b[35m","\x1b[39m"),cyan:t("\x1b[36m","\x1b[39m"),white:t("\x1b[37m","\x1b[39m"),gray:t("\x1b[90m","\x1b[39m"),bgBlack:t("\x1b[40m","\x1b[49m"),bgRed:t("\x1b[41m","\x1b[49m"),bgGreen:t("\x1b[42m","\x1b[49m"),bgYellow:t("\x1b[43m","\x1b[49m"),bgBlue:t("\x1b[44m","\x1b[49m"),bgMagenta:t("\x1b[45m","\x1b[49m"),bgCyan:t("\x1b[46m","\x1b[49m"),bgWhite:t("\x1b[47m","\x1b[49m"),blackBright:t("\x1b[90m","\x1b[39m"),redBright:t("\x1b[91m","\x1b[39m"),greenBright:t("\x1b[92m","\x1b[39m"),yellowBright:t("\x1b[93m","\x1b[39m"),blueBright:t("\x1b[94m","\x1b[39m"),magentaBright:t("\x1b[95m","\x1b[39m"),cyanBright:t("\x1b[96m","\x1b[39m"),whiteBright:t("\x1b[97m","\x1b[39m"),bgBlackBright:t("\x1b[100m","\x1b[49m"),bgRedBright:t("\x1b[101m","\x1b[49m"),bgGreenBright:t("\x1b[102m","\x1b[49m"),bgYellowBright:t("\x1b[103m","\x1b[49m"),bgBlueBright:t("\x1b[104m","\x1b[49m"),bgMagentaBright:t("\x1b[105m","\x1b[49m"),bgCyanBright:t("\x1b[106m","\x1b[49m"),bgWhiteBright:t("\x1b[107m","\x1b[49m")}};e.exports=u(),e.exports.createColors=u},"../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js":function(e){let t=`\x1b[`,i={to:(e,i)=>i?`${t}${i+1};${e+1}H`:`${t}${e+1}G`,move(e,i){let r="";return e<0?r+=`${t}${-e}D`:e>0&&(r+=`${t}${e}C`),i<0?r+=`${t}${-i}A`:i>0&&(r+=`${t}${i}B`),r},up:(e=1)=>`${t}${e}A`,down:(e=1)=>`${t}${e}B`,forward:(e=1)=>`${t}${e}C`,backward:(e=1)=>`${t}${e}D`,nextLine:(e=1)=>`${t}E`.repeat(e),prevLine:(e=1)=>`${t}F`.repeat(e),left:`${t}G`,hide:`${t}?25l`,show:`${t}?25h`,save:`\x1b7`,restore:`\x1b8`},r={screen:`${t}2J`,up:(e=1)=>`${t}1J`.repeat(e),down:(e=1)=>`${t}J`.repeat(e),line:`${t}2K`,lineEnd:`${t}K`,lineStart:`${t}1K`,lines(e){let t="";for(let r=0;r`${t}S`.repeat(e),down:(e=1)=>`${t}T`.repeat(e)},erase:r,beep:"\x07"}},"../../node_modules/.pnpm/tinygradient@1.1.5/node_modules/tinygradient/index.js":function(e,t,i){let r=i("../../node_modules/.pnpm/tinycolor2@1.6.0/node_modules/tinycolor2/cjs/tinycolor.js"),n={r:256,g:256,b:256,a:1},s={h:360,s:1,v:1,a:1};function o(e,t,i){let r={};for(let n in e)e.hasOwnProperty(n)&&(r[n]=0===i?0:(t[n]-e[n])/i);return r}function u(e,t,i,r){let n={};for(let s in t)t.hasOwnProperty(s)&&(n[s]=e[s]*i+t[s],n[s]=n[s]<0?n[s]+r[s]:1!==r[s]?n[s]%r[s]:n[s]);return n}function a(e,t,i){let s=e.color.toRgb(),a=o(s,t.color.toRgb(),i),l=[e.color];for(let e=1;ed.h&&c.h-d.h>180;l="long"===n&&e||"short"===n&&!e}let D=o(c,d,i),f=[e.color];h=c.h<=d.h&&!l||c.h>=d.h&&l?d.h-c.h:l?360-d.h+c.h:360-c.h+d.h,D.h=Math.pow(-1,+!!l)*Math.abs(h)/i;for(let e=1;e1)throw Error("Position must be between 0 and 1");for(let i=0,r=e.length;i=e[i].pos&&t{let u=void 0!==e.pos;if(t^u)throw Error("Cannot mix positionned and not posionned color stops");if(u){let t=void 0!==e.color;if(!t&&(s||0===o||o===i-1))throw Error("Cannot define two consecutive position-only stops");if(s=!t,(e={color:t?r(e.color):null,colorLess:!t,pos:e.pos}).pos<0||e.pos>1)throw Error("Color stops positions must be between 0 and 1");if(e.pos{e.push({color:t.color,pos:t.pos/2})}),this.stops.slice(0,-1).forEach(e=>{t.push({color:e.color,pos:1-e.pos/2})}),new d(e.concat(t.reverse()))}rgb(e){let t=h(this.stops,e),i=[];this.stops.forEach((e,t)=>{e.colorLess&&(e.color=a(this.stops[t-1],this.stops[t+1],2)[1])});for(let e=0,r=this.stops.length;e{e.colorLess&&(e.color=l(this.stops[i-1],this.stops[i+1],2,t)[1])});for(let e=0,n=this.stops.length;euf});var K=Y("../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"),q=Y("../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"),J=Y.n(q);let Q=function({onlyFirst:e=!1}={}){return RegExp("[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))",e?void 0:"g")}();function ee(e){if("string"!=typeof e)throw TypeError(`Expected a \`string\`, got \`${typeof e}\``);return e.replace(Q,"")}function et(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ei={exports:{}},er={};function en(e){return e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g)||[]}ei.exports=er,er.eastAsianWidth=function(e){var t=e.charCodeAt(0),i=2==e.length?e.charCodeAt(1):0,r=t;return 55296<=t&&t<=56319&&56320<=i&&i<=57343&&(t&=1023,i&=1023,r=(t<<10|i)+65536),12288==r||65281<=r&&r<=65376||65504<=r&&r<=65510?"F":8361==r||65377<=r&&r<=65470||65474<=r&&r<=65479||65482<=r&&r<=65487||65490<=r&&r<=65495||65498<=r&&r<=65500||65512<=r&&r<=65518?"H":4352<=r&&r<=4447||4515<=r&&r<=4519||4602<=r&&r<=4607||9001<=r&&r<=9002||11904<=r&&r<=11929||11931<=r&&r<=12019||12032<=r&&r<=12245||12272<=r&&r<=12283||12289<=r&&r<=12350||12353<=r&&r<=12438||12441<=r&&r<=12543||12549<=r&&r<=12589||12593<=r&&r<=12686||12688<=r&&r<=12730||12736<=r&&r<=12771||12784<=r&&r<=12830||12832<=r&&r<=12871||12880<=r&&r<=13054||13056<=r&&r<=19903||19968<=r&&r<=42124||42128<=r&&r<=42182||43360<=r&&r<=43388||44032<=r&&r<=55203||55216<=r&&r<=55238||55243<=r&&r<=55291||63744<=r&&r<=64255||65040<=r&&r<=65049||65072<=r&&r<=65106||65108<=r&&r<=65126||65128<=r&&r<=65131||110592<=r&&r<=110593||127488<=r&&r<=127490||127504<=r&&r<=127546||127552<=r&&r<=127560||127568<=r&&r<=127569||131072<=r&&r<=194367||177984<=r&&r<=196605||196608<=r&&r<=262141?"W":32<=r&&r<=126||162<=r&&r<=163||165<=r&&r<=166||172==r||175==r||10214<=r&&r<=10221||10629<=r&&r<=10630?"Na":161==r||164==r||167<=r&&r<=168||170==r||173<=r&&r<=174||176<=r&&r<=180||182<=r&&r<=186||188<=r&&r<=191||198==r||208==r||215<=r&&r<=216||222<=r&&r<=225||230==r||232<=r&&r<=234||236<=r&&r<=237||240==r||242<=r&&r<=243||247<=r&&r<=250||252==r||254==r||257==r||273==r||275==r||283==r||294<=r&&r<=295||299==r||305<=r&&r<=307||312==r||319<=r&&r<=322||324==r||328<=r&&r<=331||333==r||338<=r&&r<=339||358<=r&&r<=359||363==r||462==r||464==r||466==r||468==r||470==r||472==r||474==r||476==r||593==r||609==r||708==r||711==r||713<=r&&r<=715||717==r||720==r||728<=r&&r<=731||733==r||735==r||768<=r&&r<=879||913<=r&&r<=929||931<=r&&r<=937||945<=r&&r<=961||963<=r&&r<=969||1025==r||1040<=r&&r<=1103||1105==r||8208==r||8211<=r&&r<=8214||8216<=r&&r<=8217||8220<=r&&r<=8221||8224<=r&&r<=8226||8228<=r&&r<=8231||8240==r||8242<=r&&r<=8243||8245==r||8251==r||8254==r||8308==r||8319==r||8321<=r&&r<=8324||8364==r||8451==r||8453==r||8457==r||8467==r||8470==r||8481<=r&&r<=8482||8486==r||8491==r||8531<=r&&r<=8532||8539<=r&&r<=8542||8544<=r&&r<=8555||8560<=r&&r<=8569||8585==r||8592<=r&&r<=8601||8632<=r&&r<=8633||8658==r||8660==r||8679==r||8704==r||8706<=r&&r<=8707||8711<=r&&r<=8712||8715==r||8719==r||8721==r||8725==r||8730==r||8733<=r&&r<=8736||8739==r||8741==r||8743<=r&&r<=8748||8750==r||8756<=r&&r<=8759||8764<=r&&r<=8765||8776==r||8780==r||8786==r||8800<=r&&r<=8801||8804<=r&&r<=8807||8810<=r&&r<=8811||8814<=r&&r<=8815||8834<=r&&r<=8835||8838<=r&&r<=8839||8853==r||8857==r||8869==r||8895==r||8978==r||9312<=r&&r<=9449||9451<=r&&r<=9547||9552<=r&&r<=9587||9600<=r&&r<=9615||9618<=r&&r<=9621||9632<=r&&r<=9633||9635<=r&&r<=9641||9650<=r&&r<=9651||9654<=r&&r<=9655||9660<=r&&r<=9661||9664<=r&&r<=9665||9670<=r&&r<=9672||9675==r||9678<=r&&r<=9681||9698<=r&&r<=9701||9711==r||9733<=r&&r<=9734||9737==r||9742<=r&&r<=9743||9748<=r&&r<=9749||9756==r||9758==r||9792==r||9794==r||9824<=r&&r<=9825||9827<=r&&r<=9829||9831<=r&&r<=9834||9836<=r&&r<=9837||9839==r||9886<=r&&r<=9887||9918<=r&&r<=9919||9924<=r&&r<=9933||9935<=r&&r<=9953||9955==r||9960<=r&&r<=9983||10045==r||10071==r||10102<=r&&r<=10111||11093<=r&&r<=11097||12872<=r&&r<=12879||57344<=r&&r<=63743||65024<=r&&r<=65039||65533==r||127232<=r&&r<=127242||127248<=r&&r<=127277||127280<=r&&r<=127337||127344<=r&&r<=127386||917760<=r&&r<=917999||983040<=r&&r<=1048573||1048576<=r&&r<=1114109?"A":"N"},er.characterLength=function(e){var t=this.eastAsianWidth(e);return"F"==t||"W"==t||"A"==t?2:1},er.length=function(e){for(var t=en(e),i=0,r=0;r=t-(2==a))if(n+a<=i)r+=u;else break;n+=a}return r};let es=et(ei.exports),eo=et(function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g});function eu(e,t={}){if("string"!=typeof e||0===e.length||(t={ambiguousIsNarrow:!0,...t},0===(e=ee(e)).length))return 0;e=e.replace(eo()," ");let i=t.ambiguousIsNarrow?1:2,r=0;for(let t of e){let e=t.codePointAt(0);if(!(e<=31)&&(!(e>=127)||!(e<=159))&&(!(e>=768)||!(e<=879)))switch(es.eastAsianWidth(t)){case"F":case"W":r+=2;break;case"A":r+=i;break;default:r+=1}}return r}let ea=(e=0)=>t=>`\x1b[${t+e}m`,el=(e=0)=>t=>`\x1b[${38+e};5;${t}m`,eh=(e=0)=>(t,i,r)=>`\x1b[${38+e};2;${t};${i};${r}m`,ec={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(ec.modifier),[...Object.keys(ec.color),...Object.keys(ec.bgColor)];let ed=function(){let e=new Map;for(let[t,i]of Object.entries(ec)){for(let[t,r]of Object.entries(i))ec[t]={open:`\x1b[${r[0]}m`,close:`\x1b[${r[1]}m`},i[t]=ec[t],e.set(r[0],r[1]);Object.defineProperty(ec,t,{value:i,enumerable:!1})}return Object.defineProperty(ec,"codes",{value:e,enumerable:!1}),ec.color.close="\x1b[39m",ec.bgColor.close="\x1b[49m",ec.color.ansi=ea(),ec.color.ansi256=el(),ec.color.ansi16m=eh(),ec.bgColor.ansi=ea(10),ec.bgColor.ansi256=el(10),ec.bgColor.ansi16m=eh(10),Object.defineProperties(ec,{rgbToAnsi256:{value:(e,t,i)=>e===t&&t===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(i/255*5),enumerable:!1},hexToRgb:{value:e=>{let t=/[a-f\d]{6}|[a-f\d]{3}/i.exec(e.toString(16));if(!t)return[0,0,0];let[i]=t;3===i.length&&(i=[...i].map(e=>e+e).join(""));let r=Number.parseInt(i,16);return[r>>16&255,r>>8&255,255&r]},enumerable:!1},hexToAnsi256:{value:e=>ec.rgbToAnsi256(...ec.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value:e=>{let t,i,r;if(e<8)return 30+e;if(e<16)return 90+(e-8);if(e>=232)i=t=((e-232)*10+8)/255,r=t;else{let n=(e-=16)%36;t=Math.floor(e/36)/5,i=Math.floor(n/6)/5,r=n%6/5}let n=2*Math.max(t,i,r);if(0===n)return 30;let s=30+(Math.round(r)<<2|Math.round(i)<<1|Math.round(t));return 2===n&&(s+=60),s},enumerable:!1},rgbToAnsi:{value:(e,t,i)=>ec.ansi256ToAnsi(ec.rgbToAnsi256(e,t,i)),enumerable:!1},hexToAnsi:{value:e=>ec.ansi256ToAnsi(ec.hexToAnsi256(e)),enumerable:!1}}),ec}(),eD=new Set(["\x1b","\x9b"]),ef="]8;;",ep=e=>`${eD.values().next().value}[${e}m`,em=e=>`${eD.values().next().value}${ef}${e}\x07`,eg=(e,t,i)=>{let r=[...t],n=!1,s=!1,o=eu(ee(e[e.length-1]));for(let[t,u]of r.entries()){let a=eu(u);if(o+a<=i?e[e.length-1]+=u:(e.push(u),o=0),eD.has(u)&&(n=!0,s=r.slice(t+1).join("").startsWith(ef)),n){s?"\x07"===u&&(n=!1,s=!1):"m"===u&&(n=!1);continue}(o+=a)===i&&t0&&e.length>1&&(e[e.length-2]+=e.pop())};function eE(e,t,i){return String(e).normalize().replace(/\r\n/g,` +`).split(` +`).map(e=>((e,t,i={})=>{if(!1!==i.trim&&""===e.trim())return"";let r="",n,s,o=e.split(" ").map(e=>eu(e)),u=[""];for(let[r,n]of e.split(" ").entries()){!1!==i.trim&&(u[u.length-1]=u[u.length-1].trimStart());let e=eu(u[u.length-1]);if(0!==r&&(e>=t&&(!1===i.wordWrap||!1===i.trim)&&(u.push(""),e=0),(e>0||!1===i.trim)&&(u[u.length-1]+=" ",e++)),i.hard&&o[r]>t){let i=t-e,s=1+Math.floor((o[r]-i-1)/t);Math.floor((o[r]-1)/t)t&&e>0&&o[r]>0){if(!1===i.wordWrap&&et&&!1===i.wordWrap){eg(u,n,t);continue}u[u.length-1]+=n}!1!==i.trim&&(u=u.map(e=>(e=>{let t=e.split(" "),i=t.length;for(;i>0&&!(eu(t[i-1])>0);)i--;return i===t.length?e:t.slice(0,i).join(" ")+t.slice(i).join("")})(e)));let a=[...u.join(` +`)];for(let[e,t]of a.entries()){if(r+=t,eD.has(t)){let{groups:t}=RegExp(`(?:\\[(?\\d+)m|\\${ef}(?.*)\x07)`).exec(a.slice(e).join(""))||{groups:{}};if(void 0!==t.code){let e=Number.parseFloat(t.code);n=39===e?void 0:e}else void 0!==t.uri&&(s=0===t.uri.length?void 0:t.uri)}let i=ed.codes.get(Number(n));a[e+1]===` +`?(s&&(r+=em("")),n&&i&&(r+=ep(i))):t===` +`&&(n&&i&&(r+=ep(n)),s&&(r+=em(s)))}return r})(e,t,i)).join(` +`)}let eb={actions:new Set(["up","down","left","right","space","enter","cancel"]),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]])};function ey(e,t){if("string"==typeof e)return eb.aliases.get(e)===t;for(let i of e)if(void 0!==i&&ey(i,t))return!0;return!1}let eF=globalThis.process.platform.startsWith("win"),eC=Symbol("clack:cancel");function ev(e,t){e.isTTY&&e.setRawMode(t)}var ew=Object.defineProperty,e_=(e,t,i)=>{let r;return(r="symbol"!=typeof t?t+"":t)in e?ew(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i,i};class eS{constructor(e,t=!0){e_(this,"input"),e_(this,"output"),e_(this,"_abortSignal"),e_(this,"rl"),e_(this,"opts"),e_(this,"_render"),e_(this,"_track",!1),e_(this,"_prevFrame",""),e_(this,"_subscribers",new Map),e_(this,"_cursor",0),e_(this,"state","initial"),e_(this,"error",""),e_(this,"value");let{input:i=b,output:r=y,render:n,signal:s,...o}=e;this.opts=o,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=n.bind(this),this._track=t,this._abortSignal=s,this.input=i,this.output=r}unsubscribe(){this._subscribers.clear()}setSubscriber(e,t){let i=this._subscribers.get(e)??[];i.push(t),this._subscribers.set(e,i)}on(e,t){this.setSubscriber(e,{cb:t})}once(e,t){this.setSubscriber(e,{cb:t,once:!0})}emit(e,...t){let i=this._subscribers.get(e)??[],r=[];for(let e of i)e.cb(...t),e.once&&r.push(()=>i.splice(i.indexOf(e),1));for(let e of r)e()}prompt(){return new Promise((e,t)=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),e(eC);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}let i=new A;i._write=(e,t,i)=>{this._track&&(this.value=this.rl?.line.replace(/\t/g,""),this._cursor=this.rl?.cursor??0,this.emit("value",this.value)),i()},this.input.pipe(i),this.rl=F.createInterface({input:this.input,output:i,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),F.emitKeypressEvents(this.input,this.rl),this.rl.prompt(),void 0!==this.opts.initialValue&&this._track&&this.rl.write(this.opts.initialValue),this.input.on("keypress",this.onKeypress),ev(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(K.cursor.show),this.output.off("resize",this.render),ev(this.input,!1),e(this.value)}),this.once("cancel",()=>{this.output.write(K.cursor.show),this.output.off("resize",this.render),ev(this.input,!1),e(eC)})})}onKeypress(e,t){if("error"===this.state&&(this.state="active"),t?.name&&(!this._track&&eb.aliases.has(t.name)&&this.emit("cursor",eb.aliases.get(t.name)),eb.actions.has(t.name)&&this.emit("cursor",t.name)),e&&("y"===e.toLowerCase()||"n"===e.toLowerCase())&&this.emit("confirm","y"===e.toLowerCase())," "===e&&this.opts.placeholder&&(this.value||(this.rl?.write(this.opts.placeholder),this.emit("value",this.opts.placeholder))),e&&this.emit("key",e.toLowerCase()),t?.name==="return"){if(this.opts.validate){let e=this.opts.validate(this.value);e&&(this.error=e instanceof Error?e.message:e,this.state="error",this.rl?.write(this.value))}"error"!==this.state&&(this.state="submit")}ey([e,t?.name,t?.sequence],"cancel")&&(this.state="cancel"),("submit"===this.state||"cancel"===this.state)&&this.emit("finalize"),this.render(),("submit"===this.state||"cancel"===this.state)&&this.close()}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(` +`),ev(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let e=eE(this._prevFrame,process.stdout.columns,{hard:!0}).split(` +`).length-1;this.output.write(K.cursor.move(-999,-1*e))}render(){let e=eE(this._render(this)??"",process.stdout.columns,{hard:!0});if(e!==this._prevFrame){if("initial"===this.state)this.output.write(K.cursor.hide);else{let t=function(e,t){if(e===t)return;let i=e.split(` +`),r=t.split(` +`),n=[];for(let e=0;e1){let i=t[0];this.output.write(K.cursor.move(0,i)),this.output.write(K.erase.down());let r=e.split(` +`).slice(i);this.output.write(r.join(` +`)),this._prevFrame=e;return}this.output.write(K.erase.down())}this.output.write(e),"initial"===this.state&&(this.state="active"),this._prevFrame=e}}}new WeakMap;var eA=Object.defineProperty,eR=(e,t,i)=>{let r;return(r="symbol"!=typeof t?t+"":t)in e?eA(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i,i};let eO=class extends eS{constructor(e){super(e,!1),eR(this,"options"),eR(this,"cursor",0),this.options=e.options,this.value=[...e.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:t})=>t===e.cursorAt),0),this.on("key",e=>{"a"===e&&this.toggleAll()}),this.on("cursor",e=>{switch(e){case"left":case"up":this.cursor=0===this.cursor?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break;case"space":this.toggleValue()}})}get _value(){return this.options[this.cursor].value}toggleAll(){let e=this.value.length===this.options.length;this.value=e?[]:this.options.map(e=>e.value)}toggleValue(){let e=this.value.includes(this._value);this.value=e?this.value.filter(e=>e!==this._value):[...this.value,this._value]}};var eB=Object.defineProperty,ex=(e,t,i)=>{let r;return(r="symbol"!=typeof t?t+"":t)in e?eB(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i,i};class eN extends eS{constructor(e){super(e,!1),ex(this,"options"),ex(this,"cursor",0),this.options=e.options,this.cursor=this.options.findIndex(({value:t})=>t===e.initialValue),-1===this.cursor&&(this.cursor=0),this.changeValue(),this.on("cursor",e=>{switch(e){case"left":case"up":this.cursor=0===this.cursor?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1}this.changeValue()})}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value}}class eI extends eS{get valueWithCursor(){if("submit"===this.state)return this.value;if(this.cursor>=this.value.length)return`${this.value}\u2588`;let e=this.value.slice(0,this.cursor),[t,...i]=this.value.slice(this.cursor);return`${e}${q.inverse(t)}${i.join("")}`}get cursor(){return this._cursor}constructor(e){super(e),this.on("finalize",()=>{this.value||(this.value=e.defaultValue)})}}let eT="win32"!==E.platform?"linux"!==E.env.TERM:!!E.env.CI||!!E.env.WT_SESSION||!!E.env.TERMINUS_SUBLIME||"{cmd::Cmder}"===E.env.ConEmuTask||"Terminus-Sublime"===E.env.TERM_PROGRAM||"vscode"===E.env.TERM_PROGRAM||"xterm-256color"===E.env.TERM||"alacritty"===E.env.TERM||"JetBrains-JediTerm"===E.env.TERMINAL_EMULATOR,eL=(e,t)=>eT?e:t,ek=eL("โ—†","*"),eM=eL("โ– ","x"),e$=eL("โ–ฒ","x"),ej=eL("โ—‡","o"),eP=eL("โ”Œ","T"),ez=eL("โ”‚","|"),eU=eL("โ””","โ€”"),eH=eL("โ—",">"),eG=eL("โ—‹"," "),eZ=eL("โ—ป","[โ€ข]"),eW=eL("โ—ผ","[+]"),eV=eL("โ—ป","[ ]"),eY=(eL("โ–ช","โ€ข"),eL("โ”€","-")),eX=eL("โ•ฎ","+"),eK=eL("โ”œ","+"),eq=eL("โ•ฏ","+"),eJ=eL("โ—","โ€ข"),eQ=eL("โ—†","*"),e0=eL("โ–ฒ","!"),e1=eL("โ– ","x"),e2=e=>{switch(e){case"initial":case"active":return q.cyan(ek);case"cancel":return q.red(eM);case"error":return q.yellow(e$);case"submit":return q.green(ej)}},e3=e=>{let{cursor:t,options:i,style:r}=e,n=e.maxItems??1/0,s=Math.min(Math.max(process.stdout.rows-4,0),Math.max(n,5)),o=0;t>=0+s-3?o=Math.max(Math.min(t-s+3,i.length-s),0):t0,a=s{let s=i===n.length-1&&a;return 0===i&&u||s?q.dim("..."):r(e,i+o===t)})},e8=e=>{let t=(e,t)=>{let i=e.label??String(e.value);switch(t){case"selected":return`${q.dim(i)}`;case"active":return`${q.green(eH)} ${i} ${e.hint?q.dim(`(${e.hint})`):""}`;case"cancelled":return`${q.strikethrough(q.dim(i))}`;default:return`${q.dim(eG)} ${q.dim(i)}`}};return new eN({options:e.options,initialValue:e.initialValue,render(){let i=`${q.gray(ez)} +${e2(this.state)} ${e.message} +`;switch(this.state){case"submit":return`${i}${q.gray(ez)} ${t(this.options[this.cursor],"selected")}`;case"cancel":return`${i}${q.gray(ez)} ${t(this.options[this.cursor],"cancelled")} +${q.gray(ez)}`;default:return`${i}${q.cyan(ez)} ${e3({cursor:this.cursor,options:this.options,maxItems:e.maxItems,style:(e,i)=>t(e,i?"active":"inactive")}).join(` +${q.cyan(ez)} `)} +${q.cyan(eU)} +`}}}).prompt()},e6={message:(e="",{symbol:t=q.gray(ez)}={})=>{let i=[`${q.gray(ez)}`];if(e){let[r,...n]=e.split(` +`);i.push(`${t} ${r}`,...n.map(e=>`${q.gray(ez)} ${e}`))}process.stdout.write(`${i.join(` +`)} +`)},info:e=>{e6.message(e,{symbol:q.blue(eJ)})},success:e=>{e6.message(e,{symbol:q.green(eQ)})},step:e=>{e6.message(e,{symbol:q.green(ej)})},warn:e=>{e6.message(e,{symbol:q.yellow(e0)})},warning:e=>{e6.warn(e)},error:e=>{e6.message(e,{symbol:q.red(e1)})}},e5=(q.gray(ez),async(e,t)=>{let i={};for(let r of Object.keys(e)){let n=e[r],s=await n({results:i})?.catch(e=>{throw e});if("function"==typeof t?.onCancel&&s===eC){i[r]="canceled",t.onCancel({results:i});continue}i[r]=s}return i});function e4({stream:e=process.stdout}={}){return!!(e&&e.isTTY&&"dumb"!==process.env.TERM&&!("CI"in process.env))}class e9 extends Error{constructor(e,{cause:t}={}){super(e,{cause:t}),this.name=this.constructor.name,Error.captureStackTrace(this,this.constructor)}}let e7=function(){let{env:e}=E,{TERM:t,TERM_PROGRAM:i}=e;return"win32"!==E.platform?"linux"!==t:!!e.WT_SESSION||!!e.TERMINUS_SUBLIME||"{cmd::Cmder}"===e.ConEmuTask||"Terminus-Sublime"===i||"vscode"===i||"xterm-256color"===t||"alacritty"===t||"rxvt-unicode"===t||"rxvt-unicode-256color"===t||"JetBrains-JediTerm"===e.TERMINAL_EMULATOR}()?"โ—":"โ€ข",te={info:(...e)=>{let t=m.format(...e);e6.info(t)},warn:(...e)=>{let t=m.format(...e);e6.warn(tt(t,J().yellow))},error:(...e)=>{let t=m.format(...e);e6.error(tt(t,J().red))},debug:(...e)=>{0},log:(...e)=>{let t=m.format(...e);e6.step(t)},isVerbose:()=>!e4()};function tt(e,t){return e.split("\n").map(t).join("\n")}function ti(e){return((e="")=>{process.stdout.write(`${q.gray(ez)} +${q.gray(eU)} ${e} + +`)})(e)}function tr(e,t){return((e="",t="")=>{let i=` +${e} +`.split(` +`),r=g(t).length,n=Math.max(i.reduce((e,t)=>{let i=g(t);return i.length>e?i.length:e},0),r)+2,s=i.map(e=>`${q.gray(ez)} ${q.dim(e)}${" ".repeat(n-g(e).length)}${q.gray(ez)}`).join(` +`);process.stdout.write(`${q.gray(ez)} +${q.green(ej)} ${q.reset(t)} ${q.gray(eY.repeat(Math.max(n-r-1,1))+eX)} +${s} +${q.gray(eK+eY.repeat(n+2)+eq)} +`)})(e,t)}async function tn(e){let t=await new eI({validate:e.validate,placeholder:e.placeholder,defaultValue:e.defaultValue,initialValue:e.initialValue,render(){let t=`${q.gray(ez)} +${e2(this.state)} ${e.message} +`,i=e.placeholder?q.inverse(e.placeholder[0])+q.dim(e.placeholder.slice(1)):q.inverse(q.hidden("_")),r=this.value?this.valueWithCursor:i;switch(this.state){case"error":return`${t.trim()} +${q.yellow(ez)} ${r} +${q.yellow(eU)} ${q.yellow(this.error)} +`;case"submit":return`${t}${q.gray(ez)} ${q.dim(this.value||e.placeholder)}`;case"cancel":return`${t}${q.gray(ez)} ${q.strikethrough(q.dim(this.value??""))}${this.value?.trim()?` +${q.gray(ez)}`:""}`;default:return`${t}${q.cyan(ez)} ${r} +${q.cyan(eU)} +`}}}).prompt();return t===eC&&tc(),t}async function ts(e){if(1===e.options.length)return e.options[0].value;let t=await e8(e);return t===eC&&tc(),t}async function to(e){let t=await e8({message:e.message,options:[{value:!0,label:e.confirmLabel??"Confirm"},{value:!1,label:e.cancelLabel??"Cancel"}]});return t===eC&&tc(),!0===t}async function tu(e){let t=await (e=>{let t=(e,t)=>{let i=e.label??String(e.value);return"active"===t?`${q.cyan(eZ)} ${i} ${e.hint?q.dim(`(${e.hint})`):""}`:"selected"===t?`${q.green(eW)} ${q.dim(i)} ${e.hint?q.dim(`(${e.hint})`):""}`:"cancelled"===t?`${q.strikethrough(q.dim(i))}`:"active-selected"===t?`${q.green(eW)} ${i} ${e.hint?q.dim(`(${e.hint})`):""}`:"submitted"===t?`${q.dim(i)}`:`${q.dim(eV)} ${q.dim(i)}`};return new eO({options:e.options,initialValues:e.initialValues,required:e.required??!0,cursorAt:e.cursorAt,validate(e){if(this.required&&0===e.length)return`Please select at least one option. +${q.reset(q.dim(`Press ${q.gray(q.bgWhite(q.inverse(" space ")))} to select, ${q.gray(q.bgWhite(q.inverse(" enter ")))} to submit`))}`},render(){let i=`${q.gray(ez)} +${e2(this.state)} ${e.message} +`,r=(e,i)=>{let r=this.value.includes(e.value);return i&&r?t(e,"active-selected"):r?t(e,"selected"):t(e,i?"active":"inactive")};switch(this.state){case"submit":return`${i}${q.gray(ez)} ${this.options.filter(({value:e})=>this.value.includes(e)).map(e=>t(e,"submitted")).join(q.dim(", "))||q.dim("none")}`;case"cancel":{let e=this.options.filter(({value:e})=>this.value.includes(e)).map(e=>t(e,"cancelled")).join(q.dim(", "));return`${i}${q.gray(ez)} ${e.trim()?`${e} +${q.gray(ez)}`:""}`}case"error":{let t=this.error.split(` +`).map((e,t)=>0===t?`${q.yellow(eU)} ${q.yellow(e)}`:` ${e}`).join(` +`);return`${i+q.yellow(ez)} ${e3({options:this.options,cursor:this.cursor,maxItems:e.maxItems,style:r}).join(` +${q.yellow(ez)} `)} +${t} +`}default:return`${i}${q.cyan(ez)} ${e3({options:this.options,cursor:this.cursor,maxItems:e.maxItems,style:r}).join(` +${q.cyan(ez)} `)} +${q.cyan(eU)} +`}}}).prompt()})(e);return t===eC&&tc(),t}async function ta(e,t){let i=await e5(e,t);return i===eC&&tc(),i}function tl(e){if(null==e?void 0:e.silent)return{start:()=>{},stop:()=>{},message:()=>{}};if(te.isVerbose()||!e4())return{start:e=>te.log(th(e)),stop:(e,t=0)=>0===t?te.log(e):te.error(e),message:e=>te.log(th(e))};let t=(({indicator:e="dots"}={})=>{let t=eT?["โ—’","โ—","โ—“","โ—‘"]:["โ€ข","o","O","0"],i=eT?80:120,r="true"===process.env.CI,n,s,o=!1,u="",a,l=performance.now(),h=e=>{o&&m(e>1?"Something went wrong":"Canceled",e)},c=()=>h(2),d=()=>h(1),D=()=>{if(void 0===a)return;r&&process.stdout.write(` +`);let e=a.split(` +`);process.stdout.write(K.cursor.move(-999,e.length-1)),process.stdout.write(K.erase.down(e.length))},f=e=>e.replace(/\.+$/,""),p=e=>{let t=(performance.now()-e)/1e3,i=Math.floor(t/60),r=Math.floor(t%60);return i>0?`[${i}m ${r}s]`:`[${r}s]`},m=(t="",i=0)=>{o=!1,clearInterval(s),D();let r=0===i?q.green(ej):1===i?q.red(eM):q.red(e$);u=f(t??u),"timer"===e?process.stdout.write(`${r} ${u} ${p(l)} +`):process.stdout.write(`${r} ${u} +`),process.removeListener("uncaughtExceptionMonitor",c),process.removeListener("unhandledRejection",c),process.removeListener("SIGINT",d),process.removeListener("SIGTERM",d),process.removeListener("exit",h),n()};return{start:(m="")=>{o=!0,n=function({input:e=b,output:t=y,overwrite:i=!0,hideCursor:r=!0}={}){let n=v({input:e,output:t,prompt:"",tabSize:1});w(e,n),e.isTTY&&e.setRawMode(!0);let s=(n,{name:o,sequence:u})=>{if(ey([String(n),o,u],"cancel")){r&&t.write(K.cursor.show),process.exit(0);return}i&&_(t,"return"===o?0:-1,"return"===o?-1:0,()=>{C(t,1,()=>{e.once("keypress",s)})})};return r&&t.write(K.cursor.hide),e.once("keypress",s),()=>{e.off("keypress",s),r&&t.write(K.cursor.show),e.isTTY&&!eF&&e.setRawMode(!1),n.terminal=!1,n.close()}}(),u=f(m),l=performance.now(),process.stdout.write(`${q.gray(ez)} +`);let g=0,E=0;process.on("uncaughtExceptionMonitor",c),process.on("unhandledRejection",c),process.on("SIGINT",d),process.on("SIGTERM",d),process.on("exit",h),s=setInterval(()=>{if(r&&u===a)return;D(),a=u;let i=q.magenta(t[g]);if(r)process.stdout.write(`${i} ${u}...`);else if("timer"===e)process.stdout.write(`${i} ${u} ${p(l)}`);else{let e=".".repeat(Math.floor(E)).slice(0,3);process.stdout.write(`${i} ${u}${e}`)}g=g+1{u=f(e??u)}}})(e);return{start:e=>{t.start(e)},stop:(e,i)=>{t.stop(e,i)},message:e=>{t.message(e)}}}function th(e){if(void 0===e)return;let t=e.replace(/\.+$/,"");return`${t}...`}function tc(e){((e="")=>{process.stdout.write(`${q.gray(eU)} ${q.red(e)} + +`)})(e??"Operation cancelled by user."),process.exit(0)}Y("crypto");var td=Y("path"),tD=Y("fs");let tf=(e,t)=>e.at(-1)===t?e:tf([...e,t],u.resolve(t,"..")),tp=async(e,t,i)=>await tm(e,i)?[tC(e),t.map(e=>tF(e)),{...i,shell:!0}]:[e,t,i],tm=async(e,{shell:t,cwd:i,env:r=E.env})=>"win32"===E.platform&&!t&&!await tg(e,i,r),tg=async(e,t,{Path:i="",PATH:r=i})=>ty.some(t=>e.toLowerCase().endsWith(t))||(tE[`${e}\0${t}\0${r}`]??=await tb(e,t,r)),tE={},tb=async(e,t,i)=>{let r=i.split(u.delimiter).filter(Boolean).map(e=>e.replace(/^"(.*)"$/,"$1"));try{await Promise.all(ty.flatMap(i=>[t,...r].map(t=>`${u.resolve(t,e)}${i}`)).map(async e=>{try{await O(e)}catch{return}throw 0}))}catch{return!0}return!1},ty=[".exe",".com"],tF=e=>tC(tC(`"${e.replaceAll(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1")}"`)),tC=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,"^$1"),tv=async(e,{input:t},i)=>{let r=await e;void 0!==t&&r.stdin.end(t);let n=T(r,"close");try{return await Promise.race([n,...r.stdio.filter(Boolean).map(e=>tw(e))]),t_(i,tO(r)),tB(i)}catch(e){throw await Promise.allSettled([n]),tS(e,r,i)}},tw=async e=>{for await(let[t]of I(e,"error"))if(!["ERR_STREAM_PREMATURE_CLOSE","EPIPE"].includes(t?.code))throw t},t_=({command:e},{exitCode:t,signalName:i})=>{if(void 0!==i)throw new tR(`Command was terminated with ${i}: ${e}`);if(void 0!==t)throw new tR(`Command failed with exit code ${t}: ${e}`)},tS=(e,t,i)=>Object.assign(tA(e,i),tO(t),tB(i)),tA=(e,{command:t})=>e instanceof tR?e:new tR(`Command failed: ${t}`,{cause:e});class tR extends Error{name="SubprocessError"}let tO=({exitCode:e,signalCode:t})=>({...e<1?{}:{exitCode:e},...null===t?{}:{signalName:t}}),tB=({state:{stdout:e,stderr:t,output:i},command:r,start:n})=>({stdout:tx(e),stderr:tx(t),output:tx(i),command:r,durationMs:Number(E.hrtime.bigint()-n)/1e6}),tx=e=>"\n"===e.at(-1)?e.slice(0,"\r"===e.at(-2)?-2:-1):e,tN=async(e,t,i,r)=>{try{[e,t]=["node","node.exe"].includes(e.toLowerCase())?[E.execPath,[...E.execArgv.filter(e=>!e.startsWith("--inspect")),...t]]:[e,t],[e,t,i]=await tp(e,t,i),[e,t,i]=tI(e,t,i);let n=x(e,t,i);return tT(n.stdout,r,"stdout"),tT(n.stderr,r,"stderr"),n.once("error",()=>{}),await T(n,"spawn"),n}catch(e){throw tS(e,{},r)}},tI=(e,t,i)=>i.shell&&t.length>0?[[e,...t].join(" "),[],i]:[e,t,i],tT=(e,{state:t},i)=>{e&&(e.setEncoding("utf8"),t.isIterating||(t.isIterating=!1,e.on("data",e=>{t[i]+=e,t.output+=e})))},tL=async e=>{let[[t,i]]=await Promise.all([Promise.allSettled(e),tk(e)]);if(i.reason)throw i.reason.pipedFrom=t.reason??t.value,i.reason;if(t.reason)throw t.reason;return{...i.value,pipedFrom:t.value}},tk=async e=>{try{let[{stdout:t},{stdin:i}]=await Promise.all(e.map(({nodeChildProcess:e})=>e));if(null===i)throw Error('The "stdin" option must be set on the first "spawn()" call in the pipeline.');if(null===t)throw Error('The "stdout" option must be set on the last "spawn()" call in the pipeline.');L(t,i).catch(()=>{})}catch(t){throw await Promise.allSettled(e.map(({nodeChildProcess:e})=>tM(e))),t}},tM=async e=>{let{stdin:t}=await e;t.end()},t$=async function*(e,{state:t},i){if(!1===t.isIterating)throw Error(`The subprocess must be iterated right away, for example: + for await (const line of spawn(...)) { ... }`);t.isIterating=!0;try{let{[i]:t}=await e.nodeChildProcess;if(!t)return;let r="";for await(let e of t.iterator({destroyOnReturn:!1})){let t=`${r}${e}`.split(/\r?\n/);r=t.pop(),yield*t}r&&(yield r)}finally{await e}},tj=async function*(...e){try{let t=[];for(;e.length>0;){t=e.map((e,i)=>t[i]??tP(e));let[{value:i,done:r},n]=await Promise.race(t.map((e,t)=>Promise.all([e,t]))),[s]=e.splice(n,1);t.splice(n,1),r||(e.push(s),yield i)}}finally{await Promise.all(e.map(e=>e.return()))}},tP=async e=>{try{return await e.next()}catch(t){await e.throw(t)}};function tz(e,t,i){let r=te.isVerbose()?"inherit":"pipe";te.debug(`Running: ${e}`,...t??[]);let n=function e(t,i,r,n){let s,[o=[],a={}]=Array.isArray(i)?[i,r]:[[],i],l=(s=[t,...o],{start:E.hrtime.bigint(),command:s.map(e=>{let t;return t=g(e),/[^\w./-]/.test(t)?`'${t.replaceAll("'","'\\''")}'`:t}).join(" "),state:{stdout:"",stderr:"",output:""}}),h=(({stdin:e,stdout:t,stderr:i,stdio:r=[e,t,i],env:n,preferLocal:s,cwd:o=".",...a})=>{let l=o instanceof URL?B(o):u.resolve(o),h=n?{...E.env,...n}:void 0,c=r[0]?.string;return{...a,input:c,stdio:void 0===c?r:["pipe",...r.slice(1)],env:s?(({Path:e="",PATH:t=e,...i},r)=>{let n=t.split(u.delimiter),s=tf([],u.resolve(r)).map(e=>u.join(e,"node_modules/.bin")).filter(e=>!n.includes(e));return{...i,PATH:[...s,t].filter(Boolean).join(u.delimiter)}})(h??E.env,l):h,cwd:l}})(a),c=tN(t,o,h,l),d=tv(c,h,l);Object.assign(d,{nodeChildProcess:c});let D=t$(d=n?tL([n,d]):d,l,"stdout"),f=t$(d,l,"stderr");return Object.assign(d,{nodeChildProcess:c,stdout:D,stderr:f,[Symbol.asyncIterator]:()=>tj(D,f),pipe:(t,i,r)=>e(t,i,r,d)})}(e,t,{stdin:r,stdout:r,stderr:"pipe",...i});return function(e){process.stdin.isTTY&&process.stdin.setRawMode(!1);let t=async()=>{try{(await e.nodeChildProcess).kill(),process.exit(1)}catch{}},i=()=>t(),r=()=>t();process.on("SIGINT",i),process.on("SIGTERM",r),e.nodeChildProcess.finally(()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(n),n}function tU(e){return c(e)?e:d(process.cwd(),e)}Y("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/adm-zip.js");let tH="object"==typeof process&&process?process:{stdout:null,stderr:null},tG=e=>!!e&&"object"==typeof e&&(e instanceof iy||e instanceof S||tZ(e)||tW(e)),tZ=e=>!!e&&"object"==typeof e&&e instanceof N&&"function"==typeof e.pipe&&e.pipe!==S.Writable.prototype.pipe,tW=e=>!!e&&"object"==typeof e&&e instanceof N&&"function"==typeof e.write&&"function"==typeof e.end,tV=Symbol("EOF"),tY=Symbol("maybeEmitEnd"),tX=Symbol("emittedEnd"),tK=Symbol("emittingEnd"),tq=Symbol("emittedError"),tJ=Symbol("closed"),tQ=Symbol("read"),t0=Symbol("flush"),t1=Symbol("flushChunk"),t2=Symbol("encoding"),t3=Symbol("decoder"),t8=Symbol("flowing"),t6=Symbol("paused"),t5=Symbol("resume"),t4=Symbol("buffer"),t9=Symbol("pipes"),t7=Symbol("bufferLength"),ie=Symbol("bufferPush"),it=Symbol("bufferShift"),ii=Symbol("objectMode"),ir=Symbol("destroyed"),is=Symbol("error"),io=Symbol("emitData"),iu=Symbol("emitEnd"),ia=Symbol("emitEnd2"),il=Symbol("async"),ih=Symbol("abort"),ic=Symbol("aborted"),id=Symbol("signal"),iD=Symbol("dataListeners"),ip=Symbol("discarded"),im=e=>Promise.resolve().then(e),ig=e=>e();class iE{src;dest;opts;ondrain;constructor(e,t,i){this.src=e,this.dest=t,this.opts=i,this.ondrain=()=>e[t5](),this.dest.on("drain",this.ondrain)}unpipe(){this.dest.removeListener("drain",this.ondrain)}proxyErrors(e){}end(){this.unpipe(),this.opts.end&&this.dest.end()}}class ib extends iE{unpipe(){this.src.removeListener("error",this.proxyErrors),super.unpipe()}constructor(e,t,i){super(e,t,i),this.proxyErrors=e=>t.emit("error",e),e.on("error",this.proxyErrors)}}class iy extends N{[t8]=!1;[t6]=!1;[t9]=[];[t4]=[];[ii];[t2];[il];[t3];[tV]=!1;[tX]=!1;[tK]=!1;[tJ]=!1;[tq]=null;[t7]=0;[ir]=!1;[id];[ic]=!1;[iD]=0;[ip]=!1;writable=!0;readable=!0;constructor(...e){let t=e[0]||{};if(super(),t.objectMode&&"string"==typeof t.encoding)throw TypeError("Encoding and objectMode may not be used together");if(t.objectMode)this[ii]=!0,this[t2]=null;else t.objectMode||!t.encoding||"buffer"===t.encoding?(this[ii]=!1,this[t2]=null):(this[t2]=t.encoding,this[ii]=!1);this[il]=!!t.async,this[t3]=this[t2]?new $(this[t2]):null,t&&!0===t.debugExposeBuffer&&Object.defineProperty(this,"buffer",{get:()=>this[t4]}),t&&!0===t.debugExposePipes&&Object.defineProperty(this,"pipes",{get:()=>this[t9]});let{signal:i}=t;i&&(this[id]=i,i.aborted?this[ih]():i.addEventListener("abort",()=>this[ih]()))}get bufferLength(){return this[t7]}get encoding(){return this[t2]}set encoding(e){throw Error("Encoding must be set at instantiation time")}setEncoding(e){throw Error("Encoding must be set at instantiation time")}get objectMode(){return this[ii]}set objectMode(e){throw Error("objectMode must be set at instantiation time")}get async(){return this[il]}set async(e){this[il]=this[il]||!!e}[ih](){this[ic]=!0,this.emit("abort",this[id]?.reason),this.destroy(this[id]?.reason)}get aborted(){return this[ic]}set aborted(e){}write(e,t,i){if(this[ic])return!1;if(this[tV])throw Error("write after end");if(this[ir])return this.emit("error",Object.assign(Error("Cannot call write after a stream was destroyed"),{code:"ERR_STREAM_DESTROYED"})),!0;"function"==typeof t&&(i=t,t="utf8"),t||(t="utf8");let r=this[il]?im:ig;if(!this[ii]&&!Buffer.isBuffer(e)){let t;if(t=e,!Buffer.isBuffer(t)&&ArrayBuffer.isView(t))e=Buffer.from(e.buffer,e.byteOffset,e.byteLength);else{let t;if((t=e)instanceof ArrayBuffer||t&&"object"==typeof t&&t.constructor&&"ArrayBuffer"===t.constructor.name&&t.byteLength>=0)e=Buffer.from(e);else if("string"!=typeof e)throw Error("Non-contiguous data written to non-objectMode stream")}}return this[ii]?(this[t8]&&0!==this[t7]&&this[t0](!0),this[t8]?this.emit("data",e):this[ie](e)):e.length&&("string"==typeof e&&(t!==this[t2]||this[t3]?.lastNeed)&&(e=Buffer.from(e,t)),Buffer.isBuffer(e)&&this[t2]&&(e=this[t3].write(e)),this[t8]&&0!==this[t7]&&this[t0](!0),this[t8]?this.emit("data",e):this[ie](e)),0!==this[t7]&&this.emit("readable"),i&&r(i),this[t8]}read(e){if(this[ir])return null;if(this[ip]=!1,0===this[t7]||0===e||e&&e>this[t7])return this[tY](),null;this[ii]&&(e=null),this[t4].length>1&&!this[ii]&&(this[t4]=[this[t2]?this[t4].join(""):Buffer.concat(this[t4],this[t7])]);let t=this[tQ](e||null,this[t4][0]);return this[tY](),t}[tQ](e,t){if(this[ii])this[it]();else{let i=t;e===i.length||null===e?this[it]():("string"==typeof i?(this[t4][0]=i.slice(e),t=i.slice(0,e)):(this[t4][0]=i.subarray(e),t=i.subarray(0,e)),this[t7]-=e)}return this.emit("data",t),this[t4].length||this[tV]||this.emit("drain"),t}end(e,t,i){return"function"==typeof e&&(i=e,e=void 0),"function"==typeof t&&(i=t,t="utf8"),void 0!==e&&this.write(e,t),i&&this.once("end",i),this[tV]=!0,this.writable=!1,(this[t8]||!this[t6])&&this[tY](),this}[t5](){this[ir]||(this[iD]||this[t9].length||(this[ip]=!0),this[t6]=!1,this[t8]=!0,this.emit("resume"),this[t4].length?this[t0]():this[tV]?this[tY]():this.emit("drain"))}resume(){return this[t5]()}pause(){this[t8]=!1,this[t6]=!0,this[ip]=!1}get destroyed(){return this[ir]}get flowing(){return this[t8]}get paused(){return this[t6]}[ie](e){this[ii]?this[t7]+=1:this[t7]+=e.length,this[t4].push(e)}[it](){return this[ii]?this[t7]-=1:this[t7]-=this[t4][0].length,this[t4].shift()}[t0](e=!1){do;while(this[t1](this[it]())&&this[t4].length);e||this[t4].length||this[tV]||this.emit("drain")}[t1](e){return this.emit("data",e),this[t8]}pipe(e,t){if(this[ir])return e;this[ip]=!1;let i=this[tX];return t=t||{},e===tH.stdout||e===tH.stderr?t.end=!1:t.end=!1!==t.end,t.proxyErrors=!!t.proxyErrors,i?t.end&&e.end():(this[t9].push(t.proxyErrors?new ib(this,e,t):new iE(this,e,t)),this[il]?im(()=>this[t5]()):this[t5]()),e}unpipe(e){let t=this[t9].find(t=>t.dest===e);t&&(1===this[t9].length?(this[t8]&&0===this[iD]&&(this[t8]=!1),this[t9]=[]):this[t9].splice(this[t9].indexOf(t),1),t.unpipe())}addListener(e,t){return this.on(e,t)}on(e,t){let i=super.on(e,t);if("data"===e)this[ip]=!1,this[iD]++,this[t9].length||this[t8]||this[t5]();else if("readable"===e&&0!==this[t7])super.emit("readable");else("end"===e||"finish"===e||"prefinish"===e)&&this[tX]?(super.emit(e),this.removeAllListeners(e)):"error"===e&&this[tq]&&(this[il]?im(()=>t.call(this,this[tq])):t.call(this,this[tq]));return i}removeListener(e,t){return this.off(e,t)}off(e,t){let i=super.off(e,t);return"data"===e&&(this[iD]=this.listeners("data").length,0!==this[iD]||this[ip]||this[t9].length||(this[t8]=!1)),i}removeAllListeners(e){let t=super.removeAllListeners(e);return("data"===e||void 0===e)&&(this[iD]=0,this[ip]||this[t9].length||(this[t8]=!1)),t}get emittedEnd(){return this[tX]}[tY](){this[tK]||this[tX]||this[ir]||0!==this[t4].length||!this[tV]||(this[tK]=!0,this.emit("end"),this.emit("prefinish"),this.emit("finish"),this[tJ]&&this.emit("close"),this[tK]=!1)}emit(e,...t){let i=t[0];if("error"!==e&&"close"!==e&&e!==ir&&this[ir])return!1;if("data"===e)return(!!this[ii]||!!i)&&(this[il]?(im(()=>this[io](i)),!0):this[io](i));if("end"===e)return this[iu]();if("close"===e){if(this[tJ]=!0,!this[tX]&&!this[ir])return!1;let e=super.emit("close");return this.removeAllListeners("close"),e}if("error"===e){this[tq]=i,super.emit(is,i);let e=(!this[id]||!!this.listeners("error").length)&&super.emit("error",i);return this[tY](),e}else if("resume"===e){let e=super.emit("resume");return this[tY](),e}else if("finish"===e||"prefinish"===e){let t=super.emit(e);return this.removeAllListeners(e),t}let r=super.emit(e,...t);return this[tY](),r}[io](e){for(let t of this[t9])!1===t.dest.write(e)&&this.pause();let t=!this[ip]&&super.emit("data",e);return this[tY](),t}[iu](){return!this[tX]&&(this[tX]=!0,this.readable=!1,this[il]?(im(()=>this[ia]()),!0):this[ia]())}[ia](){if(this[t3]){let e=this[t3].end();if(e){for(let t of this[t9])t.dest.write(e);this[ip]||super.emit("data",e)}}for(let e of this[t9])e.end();let e=super.emit("end");return this.removeAllListeners("end"),e}async collect(){let e=Object.assign([],{dataLength:0});this[ii]||(e.dataLength=0);let t=this.promise();return this.on("data",t=>{e.push(t),this[ii]||(e.dataLength+=t.length)}),await t,e}async concat(){if(this[ii])throw Error("cannot concat in objectMode");let e=await this.collect();return this[t2]?e.join(""):Buffer.concat(e,e.dataLength)}async promise(){return new Promise((e,t)=>{this.on(ir,()=>t(Error("stream destroyed"))),this.on("error",e=>t(e)),this.on("end",()=>e())})}[Symbol.asyncIterator](){this[ip]=!1;let e=!1,t=async()=>(this.pause(),e=!0,{value:void 0,done:!0});return{next:()=>{let i,r;if(e)return t();let n=this.read();if(null!==n)return Promise.resolve({done:!1,value:n});if(this[tV])return t();let s=e=>{this.off("data",o),this.off("end",u),this.off(ir,a),t(),r(e)},o=e=>{this.off("error",s),this.off("end",u),this.off(ir,a),this.pause(),i({value:e,done:!!this[tV]})},u=()=>{this.off("error",s),this.off("data",o),this.off(ir,a),t(),i({done:!0,value:void 0})},a=()=>s(Error("stream destroyed"));return new Promise((e,t)=>{r=t,i=e,this.once(ir,a),this.once("error",s),this.once("end",u),this.once("data",o)})},throw:t,return:t,[Symbol.asyncIterator](){return this}}}[Symbol.iterator](){this[ip]=!1;let e=!1,t=()=>(this.pause(),this.off(is,t),this.off(ir,t),this.off("end",t),e=!0,{done:!0,value:void 0}),i=()=>{if(e)return t();let i=this.read();return null===i?t():{done:!1,value:i}};return this.once("end",t),this.once(is,t),this.once(ir,t),{next:i,throw:t,return:t,[Symbol.iterator](){return this}}}destroy(e){return this[ir]||(this[ir]=!0,this[ip]=!0,this[t4].length=0,this[t7]=0,"function"!=typeof this.close||this[tJ]||this.close()),e?this.emit("error",e):this.emit(ir),this}static get isStream(){return tG}}let iF=tD.default.writev,iC=Symbol("_autoClose"),iv=Symbol("_close"),iw=Symbol("_ended"),i_=Symbol("_fd"),iS=Symbol("_finished"),iA=Symbol("_flags"),iR=Symbol("_flush"),iO=Symbol("_handleChunk"),iB=Symbol("_makeBuf"),ix=Symbol("_mode"),iN=Symbol("_needDrain"),iI=Symbol("_onerror"),iT=Symbol("_onopen"),iL=Symbol("_onread"),ik=Symbol("_onwrite"),iM=Symbol("_open"),i$=Symbol("_path"),ij=Symbol("_pos"),iP=Symbol("_queue"),iz=Symbol("_read"),iU=Symbol("_readSize"),iH=Symbol("_reading"),iG=Symbol("_remain"),iZ=Symbol("_size"),iW=Symbol("_write"),iV=Symbol("_writing"),iY=Symbol("_defaultFlag"),iX=Symbol("_errored");class iK extends iy{[iX]=!1;[i_];[i$];[iU];[iH]=!1;[iZ];[iG];[iC];constructor(e,t){if(super(t=t||{}),this.readable=!0,this.writable=!1,"string"!=typeof e)throw TypeError("path must be a string");this[iX]=!1,this[i_]="number"==typeof t.fd?t.fd:void 0,this[i$]=e,this[iU]=t.readSize||0x1000000,this[iH]=!1,this[iZ]="number"==typeof t.size?t.size:1/0,this[iG]=this[iZ],this[iC]="boolean"!=typeof t.autoClose||t.autoClose,"number"==typeof this[i_]?this[iz]():this[iM]()}get fd(){return this[i_]}get path(){return this[i$]}write(){throw TypeError("this is a readable stream")}end(){throw TypeError("this is a readable stream")}[iM](){tD.default.open(this[i$],"r",(e,t)=>this[iT](e,t))}[iT](e,t){e?this[iI](e):(this[i_]=t,this.emit("open",t),this[iz]())}[iB](){return Buffer.allocUnsafe(Math.min(this[iU],this[iG]))}[iz](){if(!this[iH]){this[iH]=!0;let e=this[iB]();if(0===e.length)return process.nextTick(()=>this[iL](null,0,e));tD.default.read(this[i_],e,0,e.length,null,(e,t,i)=>this[iL](e,t,i))}}[iL](e,t,i){this[iH]=!1,e?this[iI](e):this[iO](t,i)&&this[iz]()}[iv](){if(this[iC]&&"number"==typeof this[i_]){let e=this[i_];this[i_]=void 0,tD.default.close(e,e=>e?this.emit("error",e):this.emit("close"))}}[iI](e){this[iH]=!0,this[iv](),this.emit("error",e)}[iO](e,t){let i=!1;return this[iG]-=e,e>0&&(i=super.write(ethis[iT](e,t))}[iT](e,t){this[iY]&&"r+"===this[iA]&&e&&"ENOENT"===e.code?(this[iA]="w",this[iM]()):e?this[iI](e):(this[i_]=t,this.emit("open",t),this[iV]||this[iR]())}end(e,t){return e&&this.write(e,t),this[iw]=!0,this[iV]||this[iP].length||"number"!=typeof this[i_]||this[ik](null,0),this}write(e,t){return("string"==typeof e&&(e=Buffer.from(e,t)),this[iw])?(this.emit("error",Error("write() after end()")),!1):void 0===this[i_]||this[iV]||this[iP].length?(this[iP].push(e),this[iN]=!0,!1):(this[iV]=!0,this[iW](e),!0)}[iW](e){tD.default.write(this[i_],e,0,e.length,this[ij],(e,t)=>this[ik](e,t))}[ik](e,t){e?this[iI](e):(void 0!==this[ij]&&"number"==typeof t&&(this[ij]+=t),this[iP].length?this[iR]():(this[iV]=!1,this[iw]&&!this[iS]?(this[iS]=!0,this[iv](),this.emit("finish")):this[iN]&&(this[iN]=!1,this.emit("drain"))))}[iR](){if(0===this[iP].length)this[iw]&&this[ik](null,0);else if(1===this[iP].length)this[iW](this[iP].pop());else{let e=this[iP];this[iP]=[],iF(this[i_],e,this[ij],(e,t)=>this[ik](e,t))}}[iv](){if(this[iC]&&"number"==typeof this[i_]){let e=this[i_];this[i_]=void 0,tD.default.close(e,e=>e?this.emit("error",e):this.emit("close"))}}}class iQ extends iJ{[iM](){let e;if(this[iY]&&"r+"===this[iA])try{e=tD.default.openSync(this[i$],this[iA],this[ix])}catch(e){if(e?.code==="ENOENT")return this[iA]="w",this[iM]();throw e}else e=tD.default.openSync(this[i$],this[iA],this[ix]);this[iT](null,e)}[iv](){if(this[iC]&&"number"==typeof this[i_]){let e=this[i_];this[i_]=void 0,tD.default.closeSync(e),this.emit("close")}}[iW](e){let t=!0;try{this[ik](null,tD.default.writeSync(this[i_],e,0,e.length,this[ij])),t=!1}finally{if(t)try{this[iv]()}catch{}}}}let i0=new Map([["C","cwd"],["f","file"],["z","gzip"],["P","preservePaths"],["U","unlink"],["strip-components","strip"],["stripComponents","strip"],["keep-newer","newer"],["keepNewer","newer"],["keep-newer-files","newer"],["keepNewerFiles","newer"],["k","keep"],["keep-existing","keep"],["keepExisting","keep"],["m","noMtime"],["no-mtime","noMtime"],["p","preserveOwner"],["L","follow"],["h","follow"],["onentry","onReadEntry"]]),i1=e=>{let t=i0.get(e);return t||e},i2=(e={})=>{if(!e)return{};let t={};for(let[i,r]of Object.entries(e))t[i1(i)]=r;return void 0===t.chmod&&!1===t.noChmod&&(t.chmod=!0),delete t.noChmod,t},i3=(e,t,i,r,n)=>Object.assign((s=[],o,u)=>{Array.isArray(s)&&(o=s,s={}),"function"==typeof o&&(u=o,o=void 0),o=o?Array.from(o):[];let a=i2(s);if(n?.(a,o),!a.sync||!a.file){if(a.sync||!a.file){if(!a.sync||a.file){if(a.sync||a.file)throw Error("impossible options??");if("function"==typeof u)throw TypeError("callback only supported with file option");return r(a,o)}if("function"==typeof u)throw TypeError("callback not supported for sync tar functions");return i(a,o)}{let e=t(a,o),i=u||void 0;return i?e.then(()=>i(),i):e}}if("function"==typeof u)throw TypeError("callback not supported for sync tar functions");return e(a,o)},{syncFile:e,asyncFile:t,syncNoFile:i,asyncNoFile:r,validate:n});var i8=Y("zlib");let i6=i8.default.constants||{ZLIB_VERNUM:4736},i5=Object.freeze(Object.assign(Object.create(null),{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_VERSION_ERROR:-6,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,Z_MIN_WINDOWBITS:8,Z_MAX_WINDOWBITS:15,Z_DEFAULT_WINDOWBITS:15,Z_MIN_CHUNK:64,Z_MAX_CHUNK:1/0,Z_DEFAULT_CHUNK:16384,Z_MIN_MEMLEVEL:1,Z_MAX_MEMLEVEL:9,Z_DEFAULT_MEMLEVEL:8,Z_MIN_LEVEL:-1,Z_MAX_LEVEL:9,Z_DEFAULT_LEVEL:-1,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},i6)),i4=P.concat,i9=Object.getOwnPropertyDescriptor(P,"concat"),i7=e=>e,re=i9?.writable===!0||i9?.set!==void 0?e=>{P.concat=e?i7:i4}:e=>{},rt=Symbol("_superWrite");class ri extends Error{code;errno;constructor(e,t){super("zlib: "+e.message,{cause:e}),this.code=e.code,this.errno=e.errno,this.code||(this.code="ZLIB_ERROR"),this.message="zlib: "+e.message,Error.captureStackTrace(this,t??this.constructor)}get name(){return"ZlibError"}}let rr=Symbol("flushFlag");class rn extends iy{#e=!1;#t=!1;#i;#r;#n;#s;#o;get sawError(){return this.#e}get handle(){return this.#s}get flushFlag(){return this.#i}constructor(e,t){if(!e||"object"!=typeof e)throw TypeError("invalid options for ZlibBase constructor");if(super(e),this.#i=e.flush??0,this.#r=e.finishFlush??0,this.#n=e.fullFlushFlag??0,"function"!=typeof i8[t])throw TypeError("Compression method not supported: "+t);try{this.#s=new i8[t](e)}catch(e){throw new ri(e,this.constructor)}this.#o=e=>{this.#e||(this.#e=!0,this.close(),this.emit("error",e))},this.#s?.on("error",e=>this.#o(new ri(e))),this.once("end",()=>this.close)}close(){this.#s&&(this.#s.close(),this.#s=void 0,this.emit("close"))}reset(){if(!this.#e)return j(this.#s,"zlib binding closed"),this.#s.reset?.()}flush(e){this.ended||("number"!=typeof e&&(e=this.#n),this.write(Object.assign(P.alloc(0),{[rr]:e})))}end(e,t,i){return"function"==typeof e&&(i=e,t=void 0,e=void 0),"function"==typeof t&&(i=t,t=void 0),e&&(t?this.write(e,t):this.write(e)),this.flush(this.#r),this.#t=!0,super.end(i)}get ended(){return this.#t}[rt](e){return super.write(e)}write(e,t,i){let r,n;if("function"==typeof t&&(i=t,t="utf8"),"string"==typeof e&&(e=P.from(e,t)),this.#e)return;j(this.#s,"zlib binding closed");let s=this.#s._handle,o=s.close;s.close=()=>{};let u=this.#s.close;this.#s.close=()=>{},re(!0);try{let t="number"==typeof e[rr]?e[rr]:this.#i;n=this.#s._processChunk(e,t),re(!1)}catch(e){re(!1),this.#o(new ri(e,this.write))}finally{this.#s&&(this.#s._handle=s,s.close=o,this.#s.close=u,this.#s.removeAllListeners("error"))}if(this.#s&&this.#s.on("error",e=>this.#o(new ri(e,this.write))),n)if(Array.isArray(n)&&n.length>0){let e=n[0];r=this[rt](P.from(e));for(let e=1;e{"function"==typeof e&&(t=e,e=this.flushFlag),this.flush(e),t?.()};try{this.handle.params(e,t)}finally{this.handle.flush=i}this.handle&&(this.#u=e,this.#a=t)}}}}class ro extends rs{#l;constructor(e){super(e,"Gzip"),this.#l=e&&!!e.portable}[rt](e){return this.#l&&(this.#l=!1,e[9]=255),super[rt](e)}}class ru extends rs{constructor(e){super(e,"Unzip")}}class ra extends rn{constructor(e,t){(e=e||{}).flush=e.flush||i5.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||i5.BROTLI_OPERATION_FINISH,e.fullFlushFlag=i5.BROTLI_OPERATION_FLUSH,super(e,t)}}class rl extends ra{constructor(e){super(e,"BrotliCompress")}}class rh extends ra{constructor(e){super(e,"BrotliDecompress")}}class rc extends rn{constructor(e,t){(e=e||{}).flush=e.flush||i5.ZSTD_e_continue,e.finishFlush=e.finishFlush||i5.ZSTD_e_end,e.fullFlushFlag=i5.ZSTD_e_flush,super(e,t)}}class rd extends rc{constructor(e){super(e,"ZstdCompress")}}class rD extends rc{constructor(e){super(e,"ZstdDecompress")}}let rf=e=>(255^e)&255,rp=e=>(255^e)+1&255,rm=e=>rg.has(e),rg=new Map([["0","File"],["","OldFile"],["1","Link"],["2","SymbolicLink"],["3","CharacterDevice"],["4","BlockDevice"],["5","Directory"],["6","FIFO"],["7","ContiguousFile"],["g","GlobalExtendedHeader"],["x","ExtendedHeader"],["A","SolarisACL"],["D","GNUDumpDir"],["I","Inode"],["K","NextFileHasLongLinkpath"],["L","NextFileHasLongPath"],["M","ContinuationFile"],["N","OldGnuLongPath"],["S","SparseFile"],["V","TapeVolumeHeader"],["X","OldExtendedHeader"]]),rE=new Map(Array.from(rg).map(e=>[e[1],e[0]]));class rb{cksumValid=!1;needPax=!1;nullBlock=!1;block;path;mode;uid;gid;size;cksum;#h="Unsupported";linkpath;uname;gname;devmaj=0;devmin=0;atime;ctime;mtime;charset;comment;constructor(e,t=0,i,r){Buffer.isBuffer(e)?this.decode(e,t||0,i,r):e&&this.#c(e)}decode(e,t,i,r){if(t||(t=0),!e||!(e.length>=t+512))throw Error("need 512 bytes for header");this.path=rF(e,t,100),this.mode=rw(e,t+100,8),this.uid=rw(e,t+108,8),this.gid=rw(e,t+116,8),this.size=rw(e,t+124,12),this.mtime=rC(e,t+136,12),this.cksum=rw(e,t+148,12),r&&this.#c(r,!0),i&&this.#c(i);let n=rF(e,t+156,1);if(rm(n)&&(this.#h=n||"0"),"0"===this.#h&&"/"===this.path.slice(-1)&&(this.#h="5"),"5"===this.#h&&(this.size=0),this.linkpath=rF(e,t+157,100),"ustar\x0000"===e.subarray(t+257,t+265).toString())if(this.uname=rF(e,t+265,32),this.gname=rF(e,t+297,32),this.devmaj=rw(e,t+329,8)??0,this.devmin=rw(e,t+337,8)??0,0!==e[t+475]){let i=rF(e,t+345,155);this.path=i+"/"+this.path}else{let i=rF(e,t+345,130);i&&(this.path=i+"/"+this.path),this.atime=rC(e,t+476,12),this.ctime=rC(e,t+488,12)}let s=256;for(let i=t;i!(null==i||"path"===e&&t||"linkpath"===e&&t||"global"===e))))}encode(e,t=0){if(e||(e=this.block=Buffer.alloc(512)),"Unsupported"===this.#h&&(this.#h="0"),!(e.length>=t+512))throw Error("need 512 bytes for header");let i=this.ctime||this.atime?130:155,r=ry(this.path||"",i),n=r[0],s=r[1];this.needPax=!!r[2],this.needPax=rI(e,t,100,n)||this.needPax,this.needPax=rA(e,t+100,8,this.mode)||this.needPax,this.needPax=rA(e,t+108,8,this.uid)||this.needPax,this.needPax=rA(e,t+116,8,this.gid)||this.needPax,this.needPax=rA(e,t+124,12,this.size)||this.needPax,this.needPax=rx(e,t+136,12,this.mtime)||this.needPax,e[t+156]=this.#h.charCodeAt(0),this.needPax=rI(e,t+157,100,this.linkpath)||this.needPax,e.write("ustar\x0000",t+257,8),this.needPax=rI(e,t+265,32,this.uname)||this.needPax,this.needPax=rI(e,t+297,32,this.gname)||this.needPax,this.needPax=rA(e,t+329,8,this.devmaj)||this.needPax,this.needPax=rA(e,t+337,8,this.devmin)||this.needPax,this.needPax=rI(e,t+345,i,s)||this.needPax,0!==e[t+475]?this.needPax=rI(e,t+345,155,s)||this.needPax:(this.needPax=rI(e,t+345,130,s)||this.needPax,this.needPax=rx(e,t+476,12,this.atime)||this.needPax,this.needPax=rx(e,t+488,12,this.ctime)||this.needPax);let o=256;for(let i=t;i{let i,r=e,n="",s=D.parse(e).root||".";if(100>Buffer.byteLength(r))i=[r,n,!1];else{n=D.dirname(r),r=D.basename(r);do 100>=Buffer.byteLength(r)&&Buffer.byteLength(n)<=t?i=[r,n,!1]:Buffer.byteLength(r)>100&&Buffer.byteLength(n)<=t?i=[r.slice(0,99),n,!0]:(r=D.join(D.basename(n),r),n=D.dirname(n));while(n!==s&&void 0===i);i||(i=[e.slice(0,99),"",!0])}return i},rF=(e,t,i)=>e.subarray(t,t+i).toString("utf8").replace(/\0.*/,""),rC=(e,t,i)=>rv(rw(e,t,i)),rv=e=>void 0===e?void 0:new Date(1e3*e),rw=(e,t,i)=>128&Number(e[t])?(e=>{let t=e[0],i=128===t?(e=>{for(var t=e.length,i=0,r=t-1;r>-1;r--){var n=Number(e[r]);0!==n&&(i+=n*Math.pow(256,t-r-1))}return i})(e.subarray(1,e.length)):255===t?(e=>{for(var t=e.length,i=0,r=!1,n=t-1;n>-1;n--){var s,o=Number(e[n]);r?s=rf(o):0===o?s=o:(r=!0,s=rp(o)),0!==s&&(i-=s*Math.pow(256,t-n-1))}return i})(e):null;if(null===i)throw Error("invalid base256 encoding");if(!Number.isSafeInteger(i))throw Error("parsed number outside of javascript safe integer range");return i})(e.subarray(t,t+i)):r_(e,t,i),r_=(e,t,i)=>{let r;return isNaN(r=parseInt(e.subarray(t,t+i).toString("utf8").replace(/\0.*$/,"").trim(),8))?void 0:r},rS={12:0x1ffffffff,8:2097151},rA=(e,t,i,r)=>void 0!==r&&(r>rS[i]||r<0?(((e,t)=>{if(Number.isSafeInteger(e))e<0?((e,t)=>{t[0]=255;var i=!1;e*=-1;for(var r=t.length;r>1;r--){var n=255&e;e=Math.floor(e/256),i?t[r-1]=rf(n):0===n?t[r-1]=0:(i=!0,t[r-1]=rp(n))}})(e,t):((e,t)=>{t[0]=128;for(var i=t.length;i>1;i--)t[i-1]=255&e,e=Math.floor(e/256)})(e,t);else throw Error("cannot encode number outside of javascript safe integer range")})(r,e.subarray(t,t+i)),!0):(rR(e,t,i,r),!1)),rR=(e,t,i,r)=>e.write(rO(r,i),t,i,"ascii"),rO=(e,t)=>rB(Math.floor(e).toString(8),t),rB=(e,t)=>(e.length===t-1?e:Array(t-e.length-1).join("0")+e+" ")+"\0",rx=(e,t,i,r)=>void 0!==r&&rA(e,t,i,r.getTime()/1e3),rN=Array(156).join("\0"),rI=(e,t,i,r)=>void 0!==r&&(e.write(r+rN,t,i,"utf8"),r.length!==Buffer.byteLength(r)||r.length>i);class rT{atime;mtime;ctime;charset;comment;gid;uid;gname;uname;linkpath;dev;ino;nlink;path;size;mode;global;constructor(e,t=!1){this.atime=e.atime,this.charset=e.charset,this.comment=e.comment,this.ctime=e.ctime,this.dev=e.dev,this.gid=e.gid,this.global=t,this.gname=e.gname,this.ino=e.ino,this.linkpath=e.linkpath,this.mtime=e.mtime,this.nlink=e.nlink,this.path=e.path,this.size=e.size,this.uid=e.uid,this.uname=e.uname}encode(){let e=this.encodeBody();if(""===e)return Buffer.allocUnsafe(0);let t=Buffer.byteLength(e),i=512*Math.ceil(1+t/512),r=Buffer.allocUnsafe(i);for(let e=0;e<512;e++)r[e]=0;new rb({path:("PaxHeader/"+a(this.path??"")).slice(0,99),mode:this.mode||420,uid:this.uid,gid:this.gid,size:t,mtime:this.mtime,type:this.global?"GlobalExtendedHeader":"ExtendedHeader",linkpath:"",uname:this.uname||"",gname:this.gname||"",devmaj:0,devmin:0,atime:this.atime,ctime:this.ctime}).encode(r),r.write(e,512,t,"utf8");for(let e=t+512;e=Math.pow(10,n)&&(n+=1),n+r+i}static parse(e,t,i=!1){return new rT(rL(rk(e),t),i)}}let rL=(e,t)=>t?Object.assign({},t,e):e,rk=e=>e.replace(/\n$/,"").split("\n").reduce(rM,Object.create(null)),rM=(e,t)=>{let i=parseInt(t,10);if(i!==Buffer.byteLength(t)+1)return e;let r=(t=t.slice((i+" ").length)).split("="),n=r.shift();if(!n)return e;let s=n.replace(/^SCHILY\.(dev|ino|nlink)/,"$1"),o=r.join("=");return e[s]=/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(s)?new Date(1e3*Number(o)):/^[0-9]+$/.test(o)?+o:o,e},r$="win32"!==(process.env.TESTING_TAR_FAKE_PLATFORM||process.platform)?e=>e:e=>e&&e.replace(/\\/g,"/");class rj extends iy{extended;globalExtended;header;startBlockSize;blockRemain;remain;type;meta=!1;ignore=!1;path;mode;uid;gid;uname;gname;size=0;mtime;atime;ctime;linkpath;dev;ino;nlink;invalid=!1;absolute;unsupported=!1;constructor(e,t,i){switch(super({}),this.pause(),this.extended=t,this.globalExtended=i,this.header=e,this.remain=e.size??0,this.startBlockSize=512*Math.ceil(this.remain/512),this.blockRemain=this.startBlockSize,this.type=e.type,this.type){case"File":case"OldFile":case"Link":case"SymbolicLink":case"CharacterDevice":case"BlockDevice":case"Directory":case"FIFO":case"ContiguousFile":case"GNUDumpDir":break;case"NextFileHasLongLinkpath":case"NextFileHasLongPath":case"OldGnuLongPath":case"GlobalExtendedHeader":case"ExtendedHeader":case"OldExtendedHeader":this.meta=!0;break;default:this.ignore=!0}if(!e.path)throw Error("no path provided for tar.ReadEntry");this.path=r$(e.path),this.mode=e.mode,this.mode&&(this.mode=4095&this.mode),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=this.remain,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=e.linkpath?r$(e.linkpath):void 0,this.uname=e.uname,this.gname=e.gname,t&&this.#c(t),i&&this.#c(i,!0)}write(e){let t=e.length;if(t>this.blockRemain)throw Error("writing more to entry than is appropriate");let i=this.remain,r=this.blockRemain;return this.remain=Math.max(0,i-t),this.blockRemain=Math.max(0,r-t),!!this.ignore||(i>=t?super.write(e):super.write(e.subarray(0,i)))}#c(e,t=!1){e.path&&(e.path=r$(e.path)),e.linkpath&&(e.linkpath=r$(e.linkpath)),Object.assign(this,Object.fromEntries(Object.entries(e).filter(([e,i])=>!(null==i||"path"===e&&t))))}}let rP=(e,t,i,r={})=>{e.file&&(r.file=e.file),e.cwd&&(r.cwd=e.cwd),r.code=i instanceof Error&&i.code||t,r.tarCode=t,e.strict||!1===r.recoverable?i instanceof Error?e.emit("error",Object.assign(i,r)):e.emit("error",Object.assign(Error(`${t}: ${i}`),r)):(i instanceof Error&&(r=Object.assign(i,r),i=i.message),e.emit("warn",t,i,r))},rz=Buffer.from([31,139]),rU=Buffer.from([40,181,47,253]),rH=Math.max(rz.length,rU.length),rG=Symbol("state"),rZ=Symbol("writeEntry"),rW=Symbol("readEntry"),rV=Symbol("nextEntry"),rY=Symbol("processEntry"),rX=Symbol("extendedHeader"),rK=Symbol("globalExtendedHeader"),rq=Symbol("meta"),rJ=Symbol("emitMeta"),rQ=Symbol("buffer"),r0=Symbol("queue"),r1=Symbol("ended"),r2=Symbol("emittedEnd"),r3=Symbol("emit"),r8=Symbol("unzip"),r6=Symbol("consumeChunk"),r5=Symbol("consumeChunkSub"),r4=Symbol("consumeBody"),r9=Symbol("consumeMeta"),r7=Symbol("consumeHeader"),ne=Symbol("consuming"),nt=Symbol("bufferConcat"),ni=Symbol("maybeEnd"),nr=Symbol("writing"),nn=Symbol("aborted"),ns=Symbol("onDone"),no=Symbol("sawValidEntry"),nu=Symbol("sawNullBlock"),na=Symbol("sawEOF"),nl=Symbol("closeStream"),nh=()=>!0;class nc extends M{file;strict;maxMetaEntrySize;filter;brotli;zstd;writable=!0;readable=!1;[r0]=[];[rQ];[rW];[rZ];[rG]="begin";[rq]="";[rX];[rK];[r1]=!1;[r8];[nn]=!1;[no];[nu]=!1;[na]=!1;[nr]=!1;[ne]=!1;[r2]=!1;constructor(e={}){super(),this.file=e.file||"",this.on(ns,()=>{("begin"===this[rG]||!1===this[no])&&this.warn("TAR_BAD_ARCHIVE","Unrecognized archive format")}),e.ondone?this.on(ns,e.ondone):this.on(ns,()=>{this.emit("prefinish"),this.emit("finish"),this.emit("end")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||1048576,this.filter="function"==typeof e.filter?e.filter:nh;let t=e.file&&(e.file.endsWith(".tar.br")||e.file.endsWith(".tbr"));this.brotli=e.gzip||e.zstd||void 0===e.brotli?!!t&&void 0:e.brotli;let i=e.file&&(e.file.endsWith(".tar.zst")||e.file.endsWith(".tzst"));this.zstd=e.gzip||e.brotli||void 0===e.zstd?!!i||void 0:e.zstd,this.on("end",()=>this[nl]()),"function"==typeof e.onwarn&&this.on("warn",e.onwarn),"function"==typeof e.onReadEntry&&this.on("entry",e.onReadEntry)}warn(e,t,i={}){rP(this,e,t,i)}[r7](e,t){let i;void 0===this[no]&&(this[no]=!1);try{i=new rb(e,t,this[rX],this[rK])}catch(e){return this.warn("TAR_ENTRY_INVALID",e)}if(i.nullBlock)this[nu]?(this[na]=!0,"begin"===this[rG]&&(this[rG]="header"),this[r3]("eof")):(this[nu]=!0,this[r3]("nullBlock"));else if(this[nu]=!1,i.cksumValid)if(i.path){let e=i.type;if(/^(Symbolic)?Link$/.test(e)&&!i.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath required",{header:i});else if(/^(Symbolic)?Link$/.test(e)||/^(Global)?ExtendedHeader$/.test(e)||!i.linkpath){let e=this[rZ]=new rj(i,this[rX],this[rK]);if(!this[no])if(e.remain){let t=()=>{e.invalid||(this[no]=!0)};e.on("end",t)}else this[no]=!0;e.meta?e.size>this.maxMetaEntrySize?(e.ignore=!0,this[r3]("ignoredEntry",e),this[rG]="ignore",e.resume()):e.size>0&&(this[rq]="",e.on("data",e=>this[rq]+=e),this[rG]="meta"):(this[rX]=void 0,e.ignore=e.ignore||!this.filter(e.path,e),e.ignore?(this[r3]("ignoredEntry",e),this[rG]=e.remain?"ignore":"header",e.resume()):(e.remain?this[rG]="body":(this[rG]="header",e.end()),this[rW]?this[r0].push(e):(this[r0].push(e),this[rV]())))}else this.warn("TAR_ENTRY_INVALID","linkpath forbidden",{header:i})}else this.warn("TAR_ENTRY_INVALID","path is required",{header:i});else this.warn("TAR_ENTRY_INVALID","checksum failure",{header:i})}[nl](){queueMicrotask(()=>this.emit("close"))}[rY](e){let t=!0;if(e)if(Array.isArray(e)){let[t,...i]=e;this.emit(t,...i)}else this[rW]=e,this.emit("entry",e),e.emittedEnd||(e.on("end",()=>this[rV]()),t=!1);else this[rW]=void 0,t=!1;return t}[rV](){do;while(this[rY](this[r0].shift()));if(!this[r0].length){let e=this[rW];!e||e.flowing||e.size===e.remain?this[nr]||this.emit("drain"):e.once("drain",()=>this.emit("drain"))}}[r4](e,t){let i=this[rZ];if(!i)throw Error("attempt to consume body without entry??");let r=i.blockRemain??0,n=r>=e.length&&0===t?e:e.subarray(t,t+r);return i.write(n),i.blockRemain||(this[rG]="header",this[rZ]=void 0,i.end()),n.length}[r9](e,t){let i=this[rZ],r=this[r4](e,t);return!this[rZ]&&i&&this[rJ](i),r}[r3](e,t,i){this[r0].length||this[rW]?this[r0].push([e,t,i]):this.emit(e,t,i)}[rJ](e){switch(this[r3]("meta",this[rq]),e.type){case"ExtendedHeader":case"OldExtendedHeader":this[rX]=rT.parse(this[rq],this[rX],!1);break;case"GlobalExtendedHeader":this[rK]=rT.parse(this[rq],this[rK],!0);break;case"NextFileHasLongPath":case"OldGnuLongPath":{let e=this[rX]??Object.create(null);this[rX]=e,e.path=this[rq].replace(/\0.*/,"");break}case"NextFileHasLongLinkpath":{let e=this[rX]||Object.create(null);this[rX]=e,e.linkpath=this[rq].replace(/\0.*/,"");break}default:throw Error("unknown meta: "+e.type)}}abort(e){this[nn]=!0,this.emit("abort",e),this.warn("TAR_ABORT",e,{recoverable:!1})}write(e,t,i){if("function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,"string"==typeof t?t:"utf8")),this[nn])return i?.(),!1;if((void 0===this[r8]||void 0===this.brotli&&!1===this[r8])&&e){if(this[rQ]&&(e=Buffer.concat([this[rQ],e]),this[rQ]=void 0),e.lengththis[r6](e)),this[r8].on("error",e=>this.abort(e)),this[r8].on("end",()=>{this[r1]=!0,this[r6]()}),this[nr]=!0;let n=!!this[r8][r?"end":"write"](e);return this[nr]=!1,i?.(),n}}this[nr]=!0,this[r8]?this[r8].write(e):this[r6](e),this[nr]=!1;let r=!this[r0].length&&(!this[rW]||this[rW].flowing);return r||this[r0].length||this[rW]?.once("drain",()=>this.emit("drain")),i?.(),r}[nt](e){e&&!this[nn]&&(this[rQ]=this[rQ]?Buffer.concat([this[rQ],e]):e)}[ni](){if(this[r1]&&!this[r2]&&!this[nn]&&!this[ne]){this[r2]=!0;let e=this[rZ];if(e&&e.blockRemain){let t=this[rQ]?this[rQ].length:0;this.warn("TAR_BAD_ARCHIVE",`Truncated input (needed ${e.blockRemain} more bytes, only ${t} available)`,{entry:e}),this[rQ]&&e.write(this[rQ]),e.end()}this[r3](ns)}}[r6](e){if(this[ne]&&e)this[nt](e);else if(e||this[rQ]){if(e){if(this[ne]=!0,this[rQ]){this[nt](e);let t=this[rQ];this[rQ]=void 0,this[r5](t)}else this[r5](e);for(;this[rQ]&&this[rQ]?.length>=512&&!this[nn]&&!this[na];){let e=this[rQ];this[rQ]=void 0,this[r5](e)}this[ne]=!1}}else this[ni]();(!this[rQ]||this[r1])&&this[ni]()}[r5](e){let t=0,i=e.length;for(;t+512<=i&&!this[nn]&&!this[na];)switch(this[rG]){case"begin":case"header":this[r7](e,t),t+=512;break;case"ignore":case"body":t+=this[r4](e,t);break;case"meta":t+=this[r9](e,t);break;default:throw Error("invalid state: "+this[rG])}t{let t=e.length-1,i=-1;for(;t>-1&&"/"===e.charAt(t);)i=t,t--;return -1===i?e:e.slice(0,i)},nD=(e,t)=>{let i=new Map(t.map(e=>[nd(e),!0])),r=e.filter,n=(e,t="")=>{let r,s=t||(0,td.parse)(e).root||".";if(e===s)r=!1;else{let t=i.get(e);r=void 0!==t?t:n((0,td.dirname)(e),s)}return i.set(e,r),r};e.filter=r?(e,t)=>r(e,t)&&n(nd(e)):e=>n(nd(e))},nf=i3(t=>{let i,r=new nc(t),n=t.file;try{i=e.openSync(n,"r");let s=e.fstatSync(i),o=t.maxReadSize||0x1000000;if(s.size{let r=new nc(t),n=t.maxReadSize||0x1000000,s=t.file;return new Promise((t,i)=>{r.on("error",i),r.on("end",t),e.stat(s,(e,t)=>{if(e)i(e);else{let e=new iK(s,{readSize:n,size:t.size});e.on("error",i),e.pipe(r)}})})},e=>new nc(e),e=>new nc(e),(e,t)=>{t?.length&&nD(e,t),e.noResume||(e=>{let t=e.onReadEntry;e.onReadEntry=t?e=>{t(e),e.resume()}:e=>e.resume()})(e)}),np=(e,t,i)=>(e&=4095,i&&(e=(384|e)&-19),t&&(256&e&&(e|=64),32&e&&(e|=8),4&e&&(e|=1)),e),{isAbsolute:nm,parse:ng}=p,nE=e=>{let t="",i=ng(e);for(;nm(e)||i.root;){let r="/"===e.charAt(0)&&"//?/"!==e.slice(0,4)?"/":i.root;e=e.slice(r.length),t+=r,i=ng(e)}return[t,e]},nb=["|","<",">","?",":"],ny=nb.map(e=>String.fromCharCode(61440+e.charCodeAt(0))),nF=new Map(nb.map((e,t)=>[e,ny[t]])),nC=new Map(ny.map((e,t)=>[e,nb[t]])),nv=e=>nb.reduce((e,t)=>e.split(t).join(nF.get(t)),e),nw=(e,t)=>t?(e=r$(e).replace(/^\.(\/|$)/,""),nd(t)+"/"+e):r$(e),n_=Symbol("process"),nS=Symbol("file"),nA=Symbol("directory"),nR=Symbol("symlink"),nO=Symbol("hardlink"),nB=Symbol("header"),nx=Symbol("read"),nN=Symbol("lstat"),nI=Symbol("onlstat"),nT=Symbol("onread"),nL=Symbol("onreadlink"),nk=Symbol("openfile"),nM=Symbol("onopenfile"),n$=Symbol("close"),nj=Symbol("mode"),nP=Symbol("awaitDrain"),nz=Symbol("ondrain"),nU=Symbol("prefix");class nH extends iy{path;portable;myuid=process.getuid&&process.getuid()||0;myuser=process.env.USER||"";maxReadSize;linkCache;statCache;preservePaths;cwd;strict;mtime;noPax;noMtime;prefix;fd;blockLen=0;blockRemain=0;buf;pos=0;remain=0;length=0;offset=0;win32;absolute;header;type;linkpath;stat;onWriteEntry;#d=!1;constructor(e,t={}){let i=i2(t);super(),this.path=r$(e),this.portable=!!i.portable,this.maxReadSize=i.maxReadSize||0x1000000,this.linkCache=i.linkCache||new Map,this.statCache=i.statCache||new Map,this.preservePaths=!!i.preservePaths,this.cwd=r$(i.cwd||process.cwd()),this.strict=!!i.strict,this.noPax=!!i.noPax,this.noMtime=!!i.noMtime,this.mtime=i.mtime,this.prefix=i.prefix?r$(i.prefix):void 0,this.onWriteEntry=i.onWriteEntry,"function"==typeof i.onwarn&&this.on("warn",i.onwarn);let r=!1;if(!this.preservePaths){let[e,t]=nE(this.path);e&&"string"==typeof t&&(this.path=t,r=e)}if(this.win32=!!i.win32||"win32"===process.platform,this.win32){let t;this.path=(t=this.path.replace(/\\/g,"/"),ny.reduce((e,t)=>e.split(t).join(nC.get(t)),t)),e=e.replace(/\\/g,"/")}this.absolute=r$(i.absolute||td.default.resolve(this.cwd,e)),""===this.path&&(this.path="./"),r&&this.warn("TAR_ENTRY_INFO",`stripping ${r} from absolute path`,{entry:this,path:r+this.path});let n=this.statCache.get(this.absolute);n?this[nI](n):this[nN]()}warn(e,t,i={}){return rP(this,e,t,i)}emit(e,...t){return"error"===e&&(this.#d=!0),super.emit(e,...t)}[nN](){tD.default.lstat(this.absolute,(e,t)=>{if(e)return this.emit("error",e);this[nI](t)})}[nI](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=nW(e),this.emit("stat",e),this[n_]()}[n_](){switch(this.type){case"File":return this[nS]();case"Directory":return this[nA]();case"SymbolicLink":return this[nR]();default:return this.end()}}[nj](e){return np(e,"Directory"===this.type,this.portable)}[nU](e){return nw(e,this.prefix)}[nB](){if(!this.stat)throw Error("cannot write header before stat");"Directory"===this.type&&this.portable&&(this.noMtime=!0),this.onWriteEntry?.(this),this.header=new rb({path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,mode:this[nj](this.stat.mode),uid:this.portable?void 0:this.stat.uid,gid:this.portable?void 0:this.stat.gid,size:this.stat.size,mtime:this.noMtime?void 0:this.mtime||this.stat.mtime,type:"Unsupported"===this.type?void 0:this.type,uname:this.portable?void 0:this.stat.uid===this.myuid?this.myuser:"",atime:this.portable?void 0:this.stat.atime,ctime:this.portable?void 0:this.stat.ctime}),this.header.encode()&&!this.noPax&&super.write(new rT({atime:this.portable?void 0:this.header.atime,ctime:this.portable?void 0:this.header.ctime,gid:this.portable?void 0:this.header.gid,mtime:this.noMtime?void 0:this.mtime||this.header.mtime,path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,size:this.header.size,uid:this.portable?void 0:this.header.uid,uname:this.portable?void 0:this.header.uname,dev:this.portable?void 0:this.stat.dev,ino:this.portable?void 0:this.stat.ino,nlink:this.portable?void 0:this.stat.nlink}).encode());let e=this.header?.block;if(!e)throw Error("failed to encode header");super.write(e)}[nA](){if(!this.stat)throw Error("cannot create directory entry without stat");"/"!==this.path.slice(-1)&&(this.path+="/"),this.stat.size=0,this[nB](),this.end()}[nR](){tD.default.readlink(this.absolute,(e,t)=>{if(e)return this.emit("error",e);this[nL](t)})}[nL](e){this.linkpath=r$(e),this[nB](),this.end()}[nO](e){if(!this.stat)throw Error("cannot create link entry without stat");this.type="Link",this.linkpath=r$(td.default.relative(this.cwd,e)),this.stat.size=0,this[nB](),this.end()}[nS](){if(!this.stat)throw Error("cannot create file entry without stat");if(this.stat.nlink>1){let e=`${this.stat.dev}:${this.stat.ino}`,t=this.linkCache.get(e);if(t?.indexOf(this.cwd)===0)return this[nO](t);this.linkCache.set(e,this.absolute)}if(this[nB](),0===this.stat.size)return this.end();this[nk]()}[nk](){tD.default.open(this.absolute,"r",(e,t)=>{if(e)return this.emit("error",e);this[nM](t)})}[nM](e){if(this.fd=e,this.#d)return this[n$]();if(!this.stat)throw Error("should stat before calling onopenfile");this.blockLen=512*Math.ceil(this.stat.size/512),this.blockRemain=this.blockLen;let t=Math.min(this.blockLen,this.maxReadSize);this.buf=Buffer.allocUnsafe(t),this.offset=0,this.pos=0,this.remain=this.stat.size,this.length=this.buf.length,this[nx]()}[nx](){let{fd:e,buf:t,offset:i,length:r,pos:n}=this;if(void 0===e||void 0===t)throw Error("cannot read file without first opening");tD.default.read(e,t,i,r,n,(e,t)=>{if(e)return this[n$](()=>this.emit("error",e));this[nT](t)})}[n$](e=()=>{}){void 0!==this.fd&&tD.default.close(this.fd,e)}[nT](e){if(e<=0&&this.remain>0){let e=Object.assign(Error("encountered unexpected EOF"),{path:this.absolute,syscall:"read",code:"EOF"});return this[n$](()=>this.emit("error",e))}if(e>this.remain){let e=Object.assign(Error("did not encounter expected EOF"),{path:this.absolute,syscall:"read",code:"EOF"});return this[n$](()=>this.emit("error",e))}if(!this.buf)throw Error("should have created buffer prior to reading");if(e===this.remain)for(let t=e;tthis[nz]())}[nP](e){this.once("drain",e)}write(e,t,i){if("function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,"string"==typeof t?t:"utf8")),this.blockRemaine?this.emit("error",e):this.end());if(!this.buf)throw Error("buffer lost somehow in ONDRAIN");this.offset>=this.length&&(this.buf=Buffer.allocUnsafe(Math.min(this.blockRemain,this.buf.length)),this.offset=0),this.length=this.buf.length-this.offset,this[nx]()}}class nG extends nH{sync=!0;[nN](){this[nI](tD.default.lstatSync(this.absolute))}[nR](){this[nL](tD.default.readlinkSync(this.absolute))}[nk](){this[nM](tD.default.openSync(this.absolute,"r"))}[nx](){let e=!0;try{let{fd:t,buf:i,offset:r,length:n,pos:s}=this;if(void 0===t||void 0===i)throw Error("fd and buf must be set in READ method");let o=tD.default.readSync(t,i,r,n,s);this[nT](o),e=!1}finally{if(e)try{this[n$](()=>{})}catch(e){}}}[nP](e){e()}[n$](e=()=>{}){void 0!==this.fd&&tD.default.closeSync(this.fd),e()}}class nZ extends iy{blockLen=0;blockRemain=0;buf=0;pos=0;remain=0;length=0;preservePaths;portable;strict;noPax;noMtime;readEntry;type;prefix;path;mode;uid;gid;uname;gname;header;mtime;atime;ctime;linkpath;size;onWriteEntry;warn(e,t,i={}){return rP(this,e,t,i)}constructor(e,t={}){let i=i2(t);super(),this.preservePaths=!!i.preservePaths,this.portable=!!i.portable,this.strict=!!i.strict,this.noPax=!!i.noPax,this.noMtime=!!i.noMtime,this.onWriteEntry=i.onWriteEntry,this.readEntry=e;let{type:r}=e;if("Unsupported"===r)throw Error("writing entry that should be ignored");this.type=r,"Directory"===this.type&&this.portable&&(this.noMtime=!0),this.prefix=i.prefix,this.path=r$(e.path),this.mode=void 0!==e.mode?this[nj](e.mode):void 0,this.uid=this.portable?void 0:e.uid,this.gid=this.portable?void 0:e.gid,this.uname=this.portable?void 0:e.uname,this.gname=this.portable?void 0:e.gname,this.size=e.size,this.mtime=this.noMtime?void 0:i.mtime||e.mtime,this.atime=this.portable?void 0:e.atime,this.ctime=this.portable?void 0:e.ctime,this.linkpath=void 0!==e.linkpath?r$(e.linkpath):void 0,"function"==typeof i.onwarn&&this.on("warn",i.onwarn);let n=!1;if(!this.preservePaths){let[e,t]=nE(this.path);e&&"string"==typeof t&&(this.path=t,n=e)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.onWriteEntry?.(this),this.header=new rb({path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,mode:this.mode,uid:this.portable?void 0:this.uid,gid:this.portable?void 0:this.gid,size:this.size,mtime:this.noMtime?void 0:this.mtime,type:this.type,uname:this.portable?void 0:this.uname,atime:this.portable?void 0:this.atime,ctime:this.portable?void 0:this.ctime}),n&&this.warn("TAR_ENTRY_INFO",`stripping ${n} from absolute path`,{entry:this,path:n+this.path}),this.header.encode()&&!this.noPax&&super.write(new rT({atime:this.portable?void 0:this.atime,ctime:this.portable?void 0:this.ctime,gid:this.portable?void 0:this.gid,mtime:this.noMtime?void 0:this.mtime,path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,size:this.size,uid:this.portable?void 0:this.uid,uname:this.portable?void 0:this.uname,dev:this.portable?void 0:this.readEntry.dev,ino:this.portable?void 0:this.readEntry.ino,nlink:this.portable?void 0:this.readEntry.nlink}).encode());let s=this.header?.block;if(!s)throw Error("failed to encode header");super.write(s),e.pipe(this)}[nU](e){return nw(e,this.prefix)}[nj](e){return np(e,"Directory"===this.type,this.portable)}write(e,t,i){"function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,"string"==typeof t?t:"utf8"));let r=e.length;if(r>this.blockRemain)throw Error("writing more to entry than is appropriate");return this.blockRemain-=r,super.write(e,i)}end(e,t,i){return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),"function"==typeof e&&(i=e,t=void 0,e=void 0),"function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,t??"utf8")),i&&this.once("finish",i),e?super.end(e,i):super.end(i),this}}let nW=e=>e.isFile()?"File":e.isDirectory()?"Directory":e.isSymbolicLink()?"SymbolicLink":"Unsupported";class nV{tail;head;length=0;static create(e=[]){return new nV(e)}constructor(e=[]){for(let t of e)this.push(t)}*[Symbol.iterator](){for(let e=this.head;e;e=e.next)yield e.value}removeNode(e){if(e.list!==this)throw Error("removing node which does not belong to this list");let t=e.next,i=e.prev;return t&&(t.prev=i),i&&(i.next=t),e===this.head&&(this.head=t),e===this.tail&&(this.tail=i),this.length--,e.next=void 0,e.prev=void 0,e.list=void 0,t}unshiftNode(e){if(e===this.head)return;e.list&&e.list.removeNode(e);let t=this.head;e.list=this,e.next=t,t&&(t.prev=e),this.head=e,this.tail||(this.tail=e),this.length++}pushNode(e){if(e===this.tail)return;e.list&&e.list.removeNode(e);let t=this.tail;e.list=this,e.prev=t,t&&(t.next=e),this.tail=e,this.head||(this.head=e),this.length++}push(...e){for(let i=0,r=e.length;i1)i=t;else if(this.head)r=this.head.next,i=this.head.value;else throw TypeError("Reduce of empty list with no initial value");for(var n=0;r;n++)i=e(i,r.value,n),r=r.next;return i}reduceReverse(e,t){let i,r=this.tail;if(arguments.length>1)i=t;else if(this.tail)r=this.tail.prev,i=this.tail.value;else throw TypeError("Reduce of empty list with no initial value");for(let t=this.length-1;r;t--)i=e(i,r.value,t),r=r.prev;return i}toArray(){let e=Array(this.length);for(let t=0,i=this.head;i;t++)e[t]=i.value,i=i.next;return e}toArrayReverse(){let e=Array(this.length);for(let t=0,i=this.tail;i;t++)e[t]=i.value,i=i.prev;return e}slice(e=0,t=this.length){t<0&&(t+=this.length),e<0&&(e+=this.length);let i=new nV;if(tthis.length&&(t=this.length);let r=this.head,n=0;for(n=0;r&&nthis.length&&(t=this.length);let r=this.length,n=this.tail;for(;n&&r>t;r--)n=n.prev;for(;n&&r>e;r--,n=n.prev)i.push(n.value);return i}splice(e,t=0,...i){e>this.length&&(e=this.length-1),e<0&&(e=this.length+e);let r=this.head;for(let t=0;r&&t1)throw TypeError("gzip, brotli, zstd are mutually exclusive");if(e.gzip&&("object"!=typeof e.gzip&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new ro(e.gzip)),e.brotli&&("object"!=typeof e.brotli&&(e.brotli={}),this.zip=new rl(e.brotli)),e.zstd&&("object"!=typeof e.zstd&&(e.zstd={}),this.zip=new rd(e.zstd)),!this.zip)throw Error("impossible");let t=this.zip;t.on("data",e=>super.write(e)),t.on("end",()=>super.end()),t.on("drain",()=>this[so]()),this.on("resume",()=>t.resume())}else this.on("drain",this[so]);this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,e.mtime&&(this.mtime=e.mtime),this.filter="function"==typeof e.filter?e.filter:()=>!0,this[nQ]=new nV,this[n8]=0,this.jobs=Number(e.jobs)||4,this[n2]=!1,this[nJ]=!1}[ss](e){return super.write(e)}add(e){return this.write(e),this}end(e,t,i){return"function"==typeof e&&(i=e,e=void 0),"function"==typeof t&&(i=t,t=void 0),e&&this.add(e),this[nJ]=!0,this[n1](),i&&i(),this}write(e){if(this[nJ])throw Error("write after end");return e instanceof rj?this[n4](e):this[n5](e),this.flowing}[n4](e){let t=r$(td.default.resolve(this.cwd,e.path));if(this.filter(e.path,e)){let i=new nX(e.path,t);i.entry=new nZ(e,this[sr](i)),i.entry.on("end",()=>this[n6](i)),this[n8]+=1,this[nQ].push(i)}else e.resume();this[n1]()}[n5](e){let t=r$(td.default.resolve(this.cwd,e));this[nQ].push(new nX(e,t)),this[n1]()}[n9](e){e.pending=!0,this[n8]+=1;let t=this.follow?"stat":"lstat";tD.default[t](e.absolute,(t,i)=>{e.pending=!1,this[n8]-=1,t?this.emit("error",t):this[nq](e,i)})}[nq](e,t){this.statCache.set(e.absolute,t),e.stat=t,this.filter(e.path,t)||(e.ignore=!0),this[n1]()}[n7](e){e.pending=!0,this[n8]+=1,tD.default.readdir(e.absolute,(t,i)=>{if(e.pending=!1,this[n8]-=1,t)return this.emit("error",t);this[se](e,i)})}[se](e,t){this.readdirCache.set(e.absolute,t),e.readdir=t,this[n1]()}[n1](){if(!this[n2]){this[n2]=!0;for(let e=this[nQ].head;e&&this[n8]this.warn(e,t,i),noPax:this.noPax,cwd:this.cwd,absolute:e.absolute,preservePaths:this.preservePaths,maxReadSize:this.maxReadSize,strict:this.strict,portable:this.portable,linkCache:this.linkCache,statCache:this.statCache,noMtime:this.noMtime,mtime:this.mtime,prefix:this.prefix,onWriteEntry:this.onWriteEntry}}[si](e){this[n8]+=1;try{return new this[sn](e.path,this[sr](e)).on("end",()=>this[n6](e)).on("error",e=>this.emit("error",e))}catch(e){this.emit("error",e)}}[so](){this[n0]&&this[n0].entry&&this[n0].entry.resume()}[st](e){e.piped=!0,e.readdir&&e.readdir.forEach(t=>{let i=e.path,r="./"===i?"":i.replace(/\/*$/,"/");this[n5](r+t)});let t=e.entry,i=this.zip;if(!t)throw Error("cannot pipe without source");i?t.on("data",e=>{i.write(e)||t.pause()}):t.on("data",e=>{super.write(e)||t.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}warn(e,t,i={}){rP(this,e,t,i)}}class sa extends su{sync=!0;constructor(e){super(e),this[sn]=nG}pause(){}resume(){}[n9](e){let t=this.follow?"statSync":"lstatSync";this[nq](e,tD.default[t](e.absolute))}[n7](e){this[se](e,tD.default.readdirSync(e.absolute))}[st](e){let t=e.entry,i=this.zip;if(e.readdir&&e.readdir.forEach(t=>{let i=e.path,r="./"===i?"":i.replace(/\/*$/,"/");this[n5](r+t)}),!t)throw Error("Cannot pipe without source");i?t.on("data",e=>{i.write(e)}):t.on("data",e=>{super[ss](e)})}}let sl=(e,t)=>{t.forEach(t=>{"@"===t.charAt(0)?nf({file:u.resolve(e.cwd,t.slice(1)),sync:!0,noResume:!0,onReadEntry:t=>e.add(t)}):e.add(t)}),e.end()},sh=async(e,t)=>{for(let i=0;i{e.add(t)}}):e.add(r)}e.end()};i3((e,t)=>{let i=new sa(e),r=new iQ(e.file,{mode:e.mode||438});i.pipe(r),sl(i,t)},(e,t)=>{let i=new su(e),r=new iJ(e.file,{mode:e.mode||438});i.pipe(r);let n=new Promise((e,t)=>{r.on("error",t),r.on("close",e),i.on("error",t)});return sh(i,t),n},(e,t)=>{let i=new sa(e);return sl(i,t),i},(e,t)=>{let i=new su(e);return sh(i,t),i},(e,t)=>{if(!t?.length)throw TypeError("no paths specified to add to archive")});let sc=process.env.__FAKE_PLATFORM__||process.platform,{O_CREAT:sd,O_TRUNC:sD,O_WRONLY:sf}=tD.default.constants,sp=Number(process.env.__FAKE_FS_O_FILENAME__)||tD.default.constants.UV_FS_O_FILEMAP||0,sm=sp|sD|sd|sf,sg="win32"===sc&&sp?e=>e<524288?sm:"w":()=>"w",sE=(t,i,r)=>{try{return e.lchownSync(t,i,r)}catch(e){if(e?.code!=="ENOENT")throw e}},sb=(t,i,r,n)=>{e.lchown(t,i,r,e=>{n(e&&e?.code!=="ENOENT"?e:null)})},sy=(e,t,i,r,n)=>{t.isDirectory()?sF(u.resolve(e,t.name),i,r,s=>{if(s)return n(s);sb(u.resolve(e,t.name),i,r,n)}):sb(u.resolve(e,t.name),i,r,n)},sF=(t,i,r,n)=>{e.readdir(t,{withFileTypes:!0},(e,s)=>{if(e){if("ENOENT"===e.code)return n();else if("ENOTDIR"!==e.code&&"ENOTSUP"!==e.code)return n(e)}if(e||!s.length)return sb(t,i,r,n);let o=s.length,u=null,a=e=>{if(!u){if(e)return n(u=e);if(0==--o)return sb(t,i,r,n)}};for(let e of s)sy(t,e,i,r,a)})},sC=(e,t,i,r)=>{t.isDirectory()&&sv(u.resolve(e,t.name),i,r),sE(u.resolve(e,t.name),i,r)},sv=(t,i,r)=>{let n;try{n=e.readdirSync(t,{withFileTypes:!0})}catch(e){if(e?.code==="ENOENT")return;if(e?.code==="ENOTDIR"||e?.code==="ENOTSUP")return sE(t,i,r);throw e}for(let e of n)sC(t,e,i,r);return sE(t,i,r)};class sw extends Error{path;code;syscall="chdir";constructor(e,t){super(`${t}: Cannot cd into '${e}'`),this.path=e,this.code=t}get name(){return"CwdError"}}class s_ extends Error{path;symlink;syscall="symlink";code="TAR_SYMLINK_ERROR";constructor(e,t){super("TAR_SYMLINK_ERROR: Cannot extract through symbolic link"),this.symlink=e,this.path=t}get name(){return"SymlinkError"}}let sS=(t,i,r,n,s,o,a)=>{if(!i.length)return a(null,o);let l=i.shift(),h=r$(u.resolve(t+"/"+l));e.mkdir(h,r,sA(h,i,r,n,s,o,a))},sA=(t,i,r,n,s,o,u)=>a=>{a?e.lstat(t,(l,h)=>{if(l)l.path=l.path&&r$(l.path),u(l);else if(h.isDirectory())sS(t,i,r,n,s,o,u);else if(n)e.unlink(t,a=>{if(a)return u(a);e.mkdir(t,r,sA(t,i,r,n,s,o,u))});else{if(h.isSymbolicLink())return u(new s_(t,t+"/"+i.join("/")));u(a)}}):(o=o||t,sS(t,i,r,n,s,o,u))},sR=Object.create(null),sO=new Set,sB="win32"===(process.env.TESTING_TAR_FAKE_PLATFORM||process.platform);class sx{#D=new Map;#f=new Map;#p=new Set;reserve(e,t){let i=new Set((e=sB?["win32 parallelization disabled"]:e.map(e=>nd(d((e=>{sO.has(e)?sO.delete(e):sR[e]=e.normalize("NFD"),sO.add(e);let t=sR[e],i=sO.size-1e4;if(i>1e3){for(let e of sO)if(sO.delete(e),delete sR[e],--i<=0)break}return t})(e))).toLowerCase())).map(e=>e.split("/").slice(0,-1).reduce((e,t)=>{let i=e[e.length-1];return void 0!==i&&(t=d(i,t)),e.push(t||"/"),e},[])).reduce((e,t)=>e.concat(t)));for(let r of(this.#f.set(t,{dirs:i,paths:e}),e)){let e=this.#D.get(r);e?e.push(t):this.#D.set(r,[t])}for(let e of i){let i=this.#D.get(e);if(i){let e=i[i.length-1];e instanceof Set?e.add(t):i.push(new Set([t]))}else this.#D.set(e,[new Set([t])])}return this.#m(t)}#g(e){let t=this.#f.get(e);if(!t)throw Error("function does not have any path reservations");return{paths:t.paths.map(e=>this.#D.get(e)),dirs:[...t.dirs].map(e=>this.#D.get(e))}}check(e){let{paths:t,dirs:i}=this.#g(e);return t.every(t=>t&&t[0]===e)&&i.every(t=>t&&t[0]instanceof Set&&t[0].has(e))}#m(e){return!this.#p.has(e)&&!!this.check(e)&&(this.#p.add(e),e(()=>this.#E(e)),!0)}#E(e){if(!this.#p.has(e))return!1;let t=this.#f.get(e);if(!t)throw Error("invalid reservation");let{paths:i,dirs:r}=t,n=new Set;for(let t of i){let i=this.#D.get(t);if(!i||i?.[0]!==e)continue;let r=i[1];if(!r){this.#D.delete(t);continue}if(i.shift(),"function"==typeof r)n.add(r);else for(let e of r)n.add(e)}for(let t of r){let i=this.#D.get(t),r=i?.[0];if(i&&r instanceof Set)if(1===r.size&&1===i.length){this.#D.delete(t);continue}else if(1===r.size){i.shift();let e=i[0];"function"==typeof e&&n.add(e)}else r.delete(e)}return this.#p.delete(e),n.forEach(e=>this.#m(e)),!0}}let sN=Symbol("onEntry"),sI=Symbol("checkFs"),sT=Symbol("checkFs2"),sL=Symbol("isReusable"),sk=Symbol("makeFs"),sM=Symbol("file"),s$=Symbol("directory"),sj=Symbol("link"),sP=Symbol("symlink"),sz=Symbol("hardlink"),sU=Symbol("unsupported"),sH=Symbol("checkPath"),sG=Symbol("mkdir"),sZ=Symbol("onError"),sW=Symbol("pending"),sV=Symbol("pend"),sY=Symbol("unpend"),sX=Symbol("ended"),sK=Symbol("maybeClose"),sq=Symbol("skip"),sJ=Symbol("doChown"),sQ=Symbol("uid"),s0=Symbol("gid"),s1=Symbol("checkedCwd"),s2="win32"===(process.env.TESTING_TAR_FAKE_PLATFORM||process.platform),s3=(e,t,i)=>void 0!==e&&e===e>>>0?e:void 0!==t&&t===t>>>0?t:i;class s8 extends nc{[sX]=!1;[s1]=!1;[sW]=0;reservations=new sx;transform;writable=!0;readable=!1;uid;gid;setOwner;preserveOwner;processGid;processUid;maxDepth;forceChown;win32;newer;keep;noMtime;preservePaths;unlink;cwd;strip;processUmask;umask;dmode;fmode;chmod;constructor(e={}){if(e.ondone=()=>{this[sX]=!0,this[sK]()},super(e),this.transform=e.transform,this.chmod=!!e.chmod,"number"==typeof e.uid||"number"==typeof e.gid){if("number"!=typeof e.uid||"number"!=typeof e.gid)throw TypeError("cannot set owner without number uid and gid");if(e.preserveOwner)throw TypeError("cannot preserve owner in archive and also set owner explicitly");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=void 0,this.gid=void 0,this.setOwner=!1;void 0===e.preserveOwner&&"number"!=typeof e.uid?this.preserveOwner=!!(process.getuid&&0===process.getuid()):this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():void 0,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():void 0,this.maxDepth="number"==typeof e.maxDepth?e.maxDepth:1024,this.forceChown=!0===e.forceChown,this.win32=!!e.win32||s2,this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=r$(u.resolve(e.cwd||process.cwd())),this.strip=Number(e.strip)||0,this.processUmask=this.chmod?"number"==typeof e.processUmask?e.processUmask:process.umask():0,this.umask="number"==typeof e.umask?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on("entry",e=>this[sN](e))}warn(e,t,i={}){return("TAR_BAD_ARCHIVE"===e||"TAR_ABORT"===e)&&(i.recoverable=!1),super.warn(e,t,i)}[sK](){this[sX]&&0===this[sW]&&(this.emit("prefinish"),this.emit("finish"),this.emit("end"))}[sH](e){let t=r$(e.path),i=t.split("/");if(this.strip){if(i.length=this.strip))return!1;e.linkpath=t.slice(this.strip).join("/")}i.splice(0,this.strip),e.path=i.join("/")}if(isFinite(this.maxDepth)&&i.length>this.maxDepth)return this.warn("TAR_ENTRY_ERROR","path excessively deep",{entry:e,path:t,depth:i.length,maxDepth:this.maxDepth}),!1;if(!this.preservePaths){if(i.includes("..")||s2&&/^[a-z]:\.\.$/i.test(i[0]??""))return this.warn("TAR_ENTRY_ERROR","path contains '..'",{entry:e,path:t}),!1;let[r,n]=nE(t);r&&(e.path=String(n),this.warn("TAR_ENTRY_INFO",`stripping ${r} from absolute path`,{entry:e,path:t}))}if(u.isAbsolute(e.path)?e.absolute=r$(u.resolve(e.path)):e.absolute=r$(u.resolve(this.cwd,e.path)),!this.preservePaths&&"string"==typeof e.absolute&&0!==e.absolute.indexOf(this.cwd+"/")&&e.absolute!==this.cwd)return this.warn("TAR_ENTRY_ERROR","path escaped extraction target",{entry:e,path:r$(e.path),resolvedPath:e.absolute,cwd:this.cwd}),!1;if(e.absolute===this.cwd&&"Directory"!==e.type&&"GNUDumpDir"!==e.type)return!1;if(this.win32){let{root:t}=u.win32.parse(String(e.absolute));e.absolute=t+nv(String(e.absolute).slice(t.length));let{root:i}=u.win32.parse(e.path);e.path=i+nv(e.path.slice(i.length))}return!0}[sN](e){if(!this[sH](e))return e.resume();switch(z.equal(typeof e.absolute,"string"),e.type){case"Directory":case"GNUDumpDir":e.mode&&(e.mode=448|e.mode);case"File":case"OldFile":case"ContiguousFile":case"Link":case"SymbolicLink":return this[sI](e);default:return this[sU](e)}}[sZ](e,t){"CwdError"===e.name?this.emit("error",e):(this.warn("TAR_ENTRY_ERROR",e,{entry:t}),this[sY](),t.resume())}[sG](t,i,r){((t,i,r)=>{t=r$(t);let n=i.umask??18,s=448|i.mode,o=(s&n)!=0,a=i.uid,l=i.gid,h="number"==typeof a&&"number"==typeof l&&(a!==i.processUid||l!==i.processGid),c=i.preserve,d=i.unlink,D=r$(i.cwd),f=(i,n)=>{i?r(i):n&&h?sF(n,a,l,e=>f(e)):o?e.chmod(t,s,r):r()};if(t===D){var p;return p=t,e.stat(p,(e,t)=>{(e||!t.isDirectory())&&(e=new sw(p,e?.code||"ENOTDIR")),f(e)})}if(c)return R.mkdir(t,{mode:s,recursive:!0}).then(e=>f(null,e??void 0),f);let m=r$(u.relative(D,t)).split("/");sS(D,m,s,d,D,void 0,f)})(r$(t),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cwd:this.cwd,mode:i},r)}[sJ](e){return this.forceChown||this.preserveOwner&&("number"==typeof e.uid&&e.uid!==this.processUid||"number"==typeof e.gid&&e.gid!==this.processGid)||"number"==typeof this.uid&&this.uid!==this.processUid||"number"==typeof this.gid&&this.gid!==this.processGid}[sQ](e){return s3(this.uid,e.uid,this.processUid)}[s0](e){return s3(this.gid,e.gid,this.processGid)}[sM](t,i){let r="number"==typeof t.mode?4095&t.mode:this.fmode,n=new iJ(String(t.absolute),{flags:sg(t.size),mode:r,autoClose:!1});n.on("error",r=>{n.fd&&e.close(n.fd,()=>{}),n.write=()=>!0,this[sZ](r,t),i()});let s=1,o=r=>{if(r){n.fd&&e.close(n.fd,()=>{}),this[sZ](r,t),i();return}0==--s&&void 0!==n.fd&&e.close(n.fd,e=>{e?this[sZ](e,t):this[sY](),i()})};n.on("finish",()=>{let i=String(t.absolute),r=n.fd;if("number"==typeof r&&t.mtime&&!this.noMtime){s++;let n=t.atime||new Date,u=t.mtime;e.futimes(r,n,u,t=>t?e.utimes(i,n,u,e=>o(e&&t)):o())}if("number"==typeof r&&this[sJ](t)){s++;let n=this[sQ](t),u=this[s0](t);"number"==typeof n&&"number"==typeof u&&e.fchown(r,n,u,t=>t?e.chown(i,n,u,e=>o(e&&t)):o())}o()});let u=this.transform&&this.transform(t)||t;u!==t&&(u.on("error",e=>{this[sZ](e,t),i()}),t.pipe(u)),u.pipe(n)}[s$](t,i){let r="number"==typeof t.mode?4095&t.mode:this.dmode;this[sG](String(t.absolute),r,r=>{if(r){this[sZ](r,t),i();return}let n=1,s=()=>{0==--n&&(i(),this[sY](),t.resume())};t.mtime&&!this.noMtime&&(n++,e.utimes(String(t.absolute),t.atime||new Date,t.mtime,s)),this[sJ](t)&&(n++,e.chown(String(t.absolute),Number(this[sQ](t)),Number(this[s0](t)),s)),s()})}[sU](e){e.unsupported=!0,this.warn("TAR_ENTRY_UNSUPPORTED",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[sP](e,t){this[sj](e,String(e.linkpath),"symlink",t)}[sz](e,t){let i=r$(u.resolve(this.cwd,String(e.linkpath)));this[sj](e,i,"link",t)}[sV](){this[sW]++}[sY](){this[sW]--,this[sK]()}[sq](e){this[sY](),e.resume()}[sL](e,t){return"File"===e.type&&!this.unlink&&t.isFile()&&t.nlink<=1&&!s2}[sI](e){this[sV]();let t=[e.path];e.linkpath&&t.push(e.linkpath),this.reservations.reserve(t,t=>this[sT](e,t))}[sT](t,i){let r=e=>{i(e)},n=()=>{this[sG](this.cwd,this.dmode,e=>{if(e){this[sZ](e,t),r();return}this[s1]=!0,s()})},s=()=>{if(t.absolute!==this.cwd){let e=r$(u.dirname(String(t.absolute)));if(e!==this.cwd)return this[sG](e,this.dmode,e=>{if(e){this[sZ](e,t),r();return}o()})}o()},o=()=>{e.lstat(String(t.absolute),(i,n)=>{if(n&&(this.keep||this.newer&&n.mtime>(t.mtime??n.mtime))){this[sq](t),r();return}if(i||this[sL](t,n))return this[sk](null,t,r);if(n.isDirectory()){if("Directory"===t.type){let i=this.chmod&&t.mode&&(4095&n.mode)!==t.mode,s=e=>this[sk](e??null,t,r);return i?e.chmod(String(t.absolute),Number(t.mode),s):s()}if(t.absolute!==this.cwd)return e.rmdir(String(t.absolute),e=>this[sk](e??null,t,r))}if(t.absolute===this.cwd)return this[sk](null,t,r);((t,i)=>{if(!s2)return e.unlink(t,i);let r=t+".DELETE."+U(16).toString("hex");e.rename(t,r,t=>{if(t)return i(t);e.unlink(r,i)})})(String(t.absolute),e=>this[sk](e??null,t,r))})};this[s1]?s():n()}[sk](e,t,i){if(e){this[sZ](e,t),i();return}switch(t.type){case"File":case"OldFile":case"ContiguousFile":return this[sM](t,i);case"Link":return this[sz](t,i);case"SymbolicLink":return this[sP](t,i);case"Directory":case"GNUDumpDir":return this[s$](t,i)}}[sj](t,i,r,n){e[r](i,String(t.absolute),e=>{e?this[sZ](e,t):(this[sY](),t.resume()),n()})}}let s6=e=>{try{return[null,e()]}catch(e){return[e,null]}};class s5 extends s8{sync=!0;[sk](e,t){return super[sk](e,t,()=>{})}[sI](t){if(!this[s1]){let e=this[sG](this.cwd,this.dmode);if(e)return this[sZ](e,t);this[s1]=!0}if(t.absolute!==this.cwd){let e=r$(u.dirname(String(t.absolute)));if(e!==this.cwd){let i=this[sG](e,this.dmode);if(i)return this[sZ](i,t)}}let[i,r]=s6(()=>e.lstatSync(String(t.absolute)));if(r&&(this.keep||this.newer&&r.mtime>(t.mtime??r.mtime)))return this[sq](t);if(i||this[sL](t,r))return this[sk](null,t);if(r.isDirectory()){if("Directory"===t.type){let[i]=this.chmod&&t.mode&&(4095&r.mode)!==t.mode?s6(()=>{e.chmodSync(String(t.absolute),Number(t.mode))}):[];return this[sk](i,t)}let[i]=s6(()=>e.rmdirSync(String(t.absolute)));this[sk](i,t)}let[n]=t.absolute===this.cwd?[]:s6(()=>(t=>{if(!s2)return e.unlinkSync(t);let i=t+".DELETE."+U(16).toString("hex");e.renameSync(t,i),e.unlinkSync(i)})(String(t.absolute)));this[sk](n,t)}[sM](t,i){let r,n="number"==typeof t.mode?4095&t.mode:this.fmode,s=n=>{let s;try{e.closeSync(r)}catch(e){s=e}(n||s)&&this[sZ](n||s,t),i()};try{r=e.openSync(String(t.absolute),sg(t.size),n)}catch(e){return s(e)}let o=this.transform&&this.transform(t)||t;o!==t&&(o.on("error",e=>this[sZ](e,t)),t.pipe(o)),o.on("data",t=>{try{e.writeSync(r,t,0,t.length)}catch(e){s(e)}}),o.on("end",()=>{let i=null;if(t.mtime&&!this.noMtime){let n=t.atime||new Date,s=t.mtime;try{e.futimesSync(r,n,s)}catch(r){try{e.utimesSync(String(t.absolute),n,s)}catch(e){i=r}}}if(this[sJ](t)){let n=this[sQ](t),s=this[s0](t);try{e.fchownSync(r,Number(n),Number(s))}catch(r){try{e.chownSync(String(t.absolute),Number(n),Number(s))}catch(e){i=i||r}}}s(i)})}[s$](t,i){let r="number"==typeof t.mode?4095&t.mode:this.dmode,n=this[sG](String(t.absolute),r);if(n){this[sZ](n,t),i();return}if(t.mtime&&!this.noMtime)try{e.utimesSync(String(t.absolute),t.atime||new Date,t.mtime)}catch(e){}if(this[sJ](t))try{e.chownSync(String(t.absolute),Number(this[sQ](t)),Number(this[s0](t)))}catch(e){}i(),t.resume()}[sG](t,i){try{return((t,i)=>{let r;t=r$(t);let n=i.umask??18,s=448|i.mode,o=(s&n)!=0,a=i.uid,l=i.gid,h="number"==typeof a&&"number"==typeof l&&(a!==i.processUid||l!==i.processGid),c=i.preserve,d=i.unlink,D=r$(i.cwd),f=i=>{i&&h&&sv(i,a,l),o&&e.chmodSync(t,s)};if(t===D){let t,i=!1;try{i=e.statSync(D).isDirectory()}catch(e){t=e?.code}finally{if(!i)throw new sw(D,t??"ENOTDIR")}return f()}if(c)return f(e.mkdirSync(t,{mode:s,recursive:!0})??void 0);let p=r$(u.relative(D,t)).split("/");for(let t=p.shift(),i=D;t&&(i+="/"+t);t=p.shift()){i=r$(u.resolve(i));try{e.mkdirSync(i,s),r=r||i}catch(n){let t=e.lstatSync(i);if(t.isDirectory())continue;if(d){e.unlinkSync(i),e.mkdirSync(i,s),r=r||i;continue}if(t.isSymbolicLink())return new s_(i,i+"/"+p.join("/"))}}return f(r)})(r$(t),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cwd:this.cwd,mode:i})}catch(e){return e}}[sj](t,i,r,n){let s=`${r}Sync`;try{e[s](i,String(t.absolute)),n(),t.resume()}catch(e){return this[sZ](e,t)}}}let s4=i3(t=>{let i=new s5(t),r=t.file,n=e.statSync(r);new iq(r,{readSize:t.maxReadSize||0x1000000,size:n.size}).pipe(i)},(t,i)=>{let r=new s8(t),n=t.maxReadSize||0x1000000,s=t.file;return new Promise((t,i)=>{r.on("error",i),r.on("close",t),e.stat(s,(e,t)=>{if(e)i(e);else{let e=new iK(s,{readSize:n,size:t.size});e.on("error",i),e.pipe(r)}})})},e=>new s5(e),e=>new s8(e),(e,t)=>{t?.length&&nD(e,t)}),s9=(e,t)=>{t.forEach(t=>{"@"===t.charAt(0)?nf({file:u.resolve(e.cwd,t.slice(1)),sync:!0,noResume:!0,onReadEntry:t=>e.add(t)}):e.add(t)}),e.end()},s7=async(e,t)=>{for(let i=0;ie.add(t)}):e.add(r)}e.end()},oe=i3((t,i)=>{let r,n,s=new sa(t),o=!0;try{try{r=e.openSync(t.file,"r+")}catch(i){if(i?.code==="ENOENT")r=e.openSync(t.file,"w+");else throw i}let u=e.fstatSync(r),a=Buffer.alloc(512);e:for(n=0;nu.size)break;n+=s,t.mtimeCache&&i.mtime&&t.mtimeCache.set(String(i.path),i.mtime)}o=!1,((e,t,i,r,n)=>{let s=new iQ(e.file,{fd:r,start:i});t.pipe(s),s9(t,n)})(t,s,n,r,i)}finally{if(o)try{e.closeSync(r)}catch(e){}}},(t,i)=>{i=Array.from(i);let r=new su(t);return new Promise((n,s)=>{r.on("error",s);let o="r+",u=(a,l)=>a&&"ENOENT"===a.code&&"r+"===o?(o="w+",e.open(t.file,o,u)):a||!l?s(a):void e.fstat(l,(o,u)=>{if(o)return e.close(l,()=>s(o));((i,r,n)=>{let s=(t,r)=>{t?e.close(i,e=>n(t)):n(null,r)},o=0;if(0===r)return s(null,0);let u=0,a=Buffer.alloc(512),l=(n,h)=>{if(n||void 0===h)return s(n);if((u+=h)<512&&h)return e.read(i,a,u,a.length-u,o+u,l);if(0===o&&31===a[0]&&139===a[1])return s(Error("cannot append to compressed archives"));if(u<512)return s(null,o);let c=new rb(a);if(!c.cksumValid)return s(null,o);let d=512*Math.ceil((c.size??0)/512);if(o+d+512>r||(o+=d+512)>=r)return s(null,o);t.mtimeCache&&c.mtime&&t.mtimeCache.set(String(c.path),c.mtime),u=0,e.read(i,a,0,512,o,l)};e.read(i,a,0,512,o,l)})(l,u.size,(e,o)=>{if(e)return s(e);let u=new iJ(t.file,{fd:l,start:o});r.pipe(u),u.on("error",s),u.on("close",n),s7(r,i)})});e.open(t.file,o,u)})},()=>{throw TypeError("file is required")},()=>{throw TypeError("file is required")},(e,t)=>{if(!e.file)throw TypeError("file is required");if(e.gzip||e.brotli||e.zstd||e.file.endsWith(".br")||e.file.endsWith(".tbr"))throw TypeError("cannot append to compressed archives");if(!t?.length)throw TypeError("no paths specified to add/replace")});i3(oe.syncFile,oe.asyncFile,oe.syncNoFile,oe.asyncNoFile,(e,t=[])=>{oe.validate?.(e,t),ot(e)});let ot=e=>{let t=e.filter;e.mtimeCache||(e.mtimeCache=new Map),e.filter=t?(i,r)=>t(i,r)&&!((e.mtimeCache?.get(i)??r.mtime??0)>(r.mtime??0)):(t,i)=>!((e.mtimeCache?.get(t)??i.mtime??0)>(i.mtime??0))};async function oi(e,t){if(!await on())return void te.info("Git client not found, skipping git initialization");if(await os(e))return void te.debug("Git repo already initialized, skipping git initialization");let i=tl();i.start("Initializing git repo");let r=`Initial commit + +Generated by rock${t?`@${t}`:""}.`;await or(e,r),i.stop("Git repo initialized.")}async function or(e,t){try{await tz("git",["init"],{cwd:e}),await tz("git",["branch","-M","main"],{cwd:e}),await tz("git",["add","."],{cwd:e}),await tz("git",["commit","-m",t],{cwd:e})}catch(e){te.warn("Failed to initialize git repository",e)}}async function on(){try{return await tz("git",["--version"],{stdio:"ignore"}),!0}catch{return!1}}async function os(e){try{return await tz("git",["rev-parse","--is-inside-work-tree"],{stdio:"ignore",cwd:e}),!0}catch{return!1}}let oo=[{type:"npm",name:"default",displayName:"default",packageName:"@rock-js/template-default",version:"latest",directory:"."}],ou=[{type:"npm",name:"brownfield-ios",displayName:"Brownfield iOS",packageName:"@rock-js/plugin-brownfield-ios",hint:"Setup packaging React Native app as a XCFramework",version:"latest",directory:"template",importName:"pluginBrownfieldIos"},{type:"npm",name:"brownfield-android",displayName:"Brownfield Android",packageName:"@rock-js/plugin-brownfield-android",hint:"Setup packaging React Native app as an AAR",version:"latest",directory:"template",importName:"pluginBrownfieldAndroid"}],oa=[{type:"npm",name:"metro",displayName:"Metro",packageName:"@rock-js/plugin-metro",version:"latest",directory:"template",importName:"pluginMetro"},{type:"npm",name:"repack",displayName:"Re.Pack",packageName:"@rock-js/plugin-repack",version:"latest",directory:"template",importName:"pluginRepack"}],ol=[{type:"npm",name:"ios",displayName:"iOS",packageName:"@rock-js/platform-ios",version:"latest",directory:"template",importName:"platformIOS"},{type:"npm",name:"android",displayName:"Android",packageName:"@rock-js/platform-android",version:"latest",directory:"template",importName:"platformAndroid"},{type:"npm",name:"harmony",displayName:"Harmony (experimental)",packageName:"@rock-js/platform-harmony",version:"latest",directory:"template",importName:"platformHarmony"}];function oh(e){return e.filter(e=>!Array.isArray(e)||!!e[1]).map(e=>Array.isArray(e)?e[0]:e).join("\n ")}function oc(e,t){let i=e.find(e=>e.name===t);if(i)return i;if(t.startsWith("./")||t.startsWith("../")||t.startsWith("/")||t.startsWith("file:///")){t.startsWith("file://")&&(t=t.slice(7));let e=a(t),i=h(e);return{type:"local",name:e.slice(0,e.length-i.length),displayName:e.slice(0,e.length-i.length),localPath:tU(t),directory:".",packageName:e.slice(0,e.length-i.length)}}return{type:"npm",name:od(t),displayName:od(t),packageName:od(t),directory:".",version:function(e){let t=e.split("@");return 3===t.length&&""===t[0]?t[2]:2===t.length&&""!==t[0]?t[1]:null}(t)??"latest"}}function od(e){let t=e.split("@");return 3===t.length&&""===t[0]?`@${t[1]}`:2===t.length&&""!==t[0]?t[0]:e}function oD(e,t,i){void 0!==i&&(e[t]=i)}function of(n,s,{skipFiles:a=[]}={}){for(let l of(e.mkdirSync(s,{recursive:!0}),e.readdirSync(n))){let h=u.resolve(n,l),c=e.statSync(h),d=u.resolve(s,l);if(c.isDirectory())of(h,d,{skipFiles:a});else if("package.json"===u.basename(h)){let e=JSON.parse(r(h,"utf-8"));i(d)||t(h,d);let n=JSON.parse(r(d,"utf-8"));n.scripts={...n.scripts,...e.scripts},n.dependencies={...n.dependencies,...e.dependencies},n.devDependencies={...n.devDependencies,...e.devDependencies},n.peerDependencies={...n.peerDependencies,...e.peerDependencies},o(d,JSON.stringify(n,null,2))}else(null==a?void 0:a.includes(u.basename(h)))||e.copyFileSync(h,d)}}function op(t){e.existsSync(t)&&e.rmSync(t,{recursive:!0})}function om(t,i,r){let n=u.join(u.dirname(t),u.basename(t).replaceAll(i,r));e.renameSync(t,n)}let og="HelloWorld";function oE(){return e.existsSync(u.join(process.cwd(),"pnpm-lock.yaml"))?"pnpm":e.existsSync(u.join(process.cwd(),"yarn.lock"))||e.existsSync(u.join(process.cwd(),".yarn"))?"yarn":e.existsSync(u.join(process.cwd(),"bun.lockb"))||e.existsSync(u.join(process.cwd(),"bun.lock"))?"bun":"npm"}async function ob(t){var i,r,n;let s=oE(),o=tl();o.start(`Adding ${J().bold("Rock")} dependencies with ${J().bold(s)}`),await oy(t,s,["rock","@rock-js/plugin-metro","@rock-js/platform-android","@rock-js/platform-ios"]),o.stop(`Added ${J().bold("Rock")} dependencies`),o.start(`Removing ${J().bold("React Native Community CLI")} packages`),await oF(t,s,["@react-native-community/cli","@react-native-community/cli-platform-android","@react-native-community/cli-platform-ios"]),o.stop(`Removed ${J().bold("React Native Community CLI")} packages`),o.start(`Adding ${J().bold(".gitignore")} entry for .rock/`),function(t,i){let r=u.join(t,".gitignore");e.existsSync(r)&&!e.readFileSync(r,"utf8").includes(i)&&e.appendFileSync(r,` +# Rock +${i} +`)}(t,".rock/"),o.stop(`Added ${J().bold(".gitignore")} entry for .rock/`),o.start(`Generating ${J().bold("rock.config.mjs")}`);let a=function(t){let i=u.join(t,"react-native.config.js");if(!e.existsSync(i))return{};try{var r,n;let e=H(import.meta.url)(i);return{ios:null==(r=e.project)?void 0:r.ios,android:null==(n=e.project)?void 0:n.android}}catch{return{}}}(t);(function(t,i){let r=u.join(t,"rock.config.mjs"),n=i.ios?`({ + ${Object.entries(i.ios).map(([e,t])=>`${e}: '${t}'`).join(",\n ")}, + })`:"()",s=i.android?`({ + ${Object.entries(i.android).map(([e,t])=>`${e}: '${t}'`).join(",\n ")}, + })`:"()",o=`// @ts-check +import { platformIOS } from '@rock-js/platform-ios'; +import { platformAndroid } from '@rock-js/platform-android'; +import { pluginMetro } from '@rock-js/plugin-metro'; + +/** @type {import('rock').Config} */ +export default { + bundler: pluginMetro(), + platforms: { + ios: platformIOS${n}, + android: platformAndroid${s}, + }, + remoteCacheProvider: null, +}; +`;e.writeFileSync(r,o)})(t,a),o.stop(`Generated ${J().bold("rock.config.mjs")}`);let l=(null==(i=a.ios)?void 0:i.sourceDir)??"ios",h=(null==(r=a.android)?void 0:r.sourceDir)??"android";o.start(`Updating ${J().bold(`${h}/app/build.gradle`)} and ${J().bold(`${h}/settings.gradle`)}`),function(t,i){let r=u.join(t,i,"app","build.gradle");if(!e.existsSync(r))return;let n='cliFile = file("../../node_modules/rock/dist/src/bin.js")',s=e.readFileSync(r,"utf8");if(s.includes(n))return te.debug(`${r} already contains "${n}"`);let o=s.replace(/(?:\/\/\s+)?cliFile\s*=\s*file\([^)]*\)/g,n);if(o===s)return te.warn(`Unable to update ${J().bold(r)}. +Please update the "CLI file" build phase manually with: + cliFile = file("../../node_modules/rock/dist/src/bin.js") +`);e.writeFileSync(r,o)}(t,h),function(t,i){let r=u.join(t,i,"settings.gradle");if(!e.existsSync(r))return;let n=e.readFileSync(r,"utf8"),s=n.replace(/extensions\.configure\(com\.facebook\.react\.ReactSettingsExtension\)\{[^}]*autolinkLibrariesFromCommand\([^)]*\)[^}]*\}/gs,"extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand(['npx', 'rock', 'config', '-p', 'android']) }");s===n&&(s=n.replace(/autolinkLibrariesFromCommand\([^)]*\)/g,"autolinkLibrariesFromCommand(['npx', 'rock', 'config', '-p', 'android'])")),s!==n&&e.writeFileSync(r,s)}(t,h),o.stop(`Updated ${J().bold(`${h}/app/build.gradle`)} and ${J().bold(`${h}/settings.gradle`)}`),o.start(`Updating ${J().bold(`${l}/Podfile`)}`),function(t,i){let r=u.join(t,i,"Podfile");if(!e.existsSync(r))return;let n=e.readFileSync(r,"utf8"),s=n.replace(/(config\s*=\s*use_native_modules!)(\s*)/g,"$1(['npx', 'rock', 'config', '-p', 'ios'])$2");n.includes("(['npx', 'rock', 'config', '-p', 'ios'])")||s===n||e.writeFileSync(r,s)}(t,l),o.stop(`Updated ${J().bold(`${l}/Podfile`)}`),o.start(`Updating ${J().bold(`${l}/project.pbxproj`)}`),function(t,i){let r=e.readdirSync(u.join(t,i)).find(e=>e.endsWith(".xcodeproj")),n=r?u.join(t,i,r,"project.pbxproj"):void 0;if(!n)return te.debug(`No Xcode project found in ${i}`);let s=e.readFileSync(n,"utf8"),o=s.replace('shellScript = "set -e\\n\\nWITH_ENVIRONMENT=\\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\\"\\nREACT_NATIVE_XCODE=\\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\\"\\n\\n/bin/sh -c \\"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\\"\\n";','shellScript = "set -e\\nif [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\nsource \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\nsource \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\nexport CONFIG_CMD=\\"dummy-workaround-value\\"\\nexport CLI_PATH=\\"$(\\"$NODE_BINARY\\" --print \\"require(\'path\').dirname(require.resolve(\'rock/package.json\')) + \'/dist/src/bin.js\'\\")\\"\\nWITH_ENVIRONMENT=\\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\\"\\n";');o!==s?e.writeFileSync(n,o):te.warn(`Unable to update ${J().bold(n)}. +Please update the "Bundle React Native code and images" build phase manually with: + set -e + if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then + source "$PODS_ROOT/../.xcode.env" + fi + if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then + source "$PODS_ROOT/../.xcode.env.local" + fi + export CONFIG_CMD="dummy-workaround-value" + export CLI_PATH="$("$NODE_BINARY" --print "require('path').dirname(require.resolve('rock/package.json')) + '/dist/src/bin.js'")" + WITH_ENVIRONMENT="$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh" +`)}(t,l),o.stop(`Updated ${J().bold(`${l}/project.pbxproj`)}`),o.start(`Updating ${J().bold("package.json")} scripts`),function(t){let i=u.join(t,"package.json");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8").replaceAll("react-native start","rock start").replaceAll("react-native run-android","rock run:android").replaceAll("react-native build-android","rock build:android").replaceAll("react-native run-ios","rock run:ios").replaceAll("react-native build-ios","rock build:ios").replaceAll(/run:android(.*)--mode(.*)/g,"run:android$1--variant$2").replaceAll(/run:ios(.*)--mode(.*)/g,"run:ios$1--configuration$2").replaceAll(/build:android(.*)--mode(.*)/g,"build:android$1--variant$2").replaceAll(/build:ios(.*)--mode(.*)/g,"build:ios$1--configuration$2").replaceAll("--appIdSuffix","--app-id-suffix").replaceAll("--appId","--app-id").replaceAll("--buildFolder","--build-folder");e.writeFileSync(i,r)}(t),o.stop(`Updated ${J().bold("package.json")} scripts`),tr(`1. Run ${J().bold("git diff")} to see the changes. Adjust as necessary e.g.: + - paths in monorepo + - commands in shell scripts + - commands in CI workflows +2. Run the dev server as you would normally do +3. Run iOS and Android apps as you would normally do +4. Setup Remote Cache: ${(n="https://rockjs.dev/docs/configuration#remote-cache-configuration",q.cyan(q.underline(q.bold(n))))}`,"Next steps"),ti("Success \uD83C\uDF89.")}async function oy(e,t,i){let r={npm:["install","-D",...i],pnpm:["add","-D",...i],yarn:["add","-D",...i],bun:["add","-D",...i]}[t]??["install","-D",...i];await tz(t,r,{cwd:e})}async function oF(e,t,i){let r={npm:["remove",...i],pnpm:["remove",...i],yarn:["remove",...i],bun:["remove",...i]}[t]??["remove",...i];try{await tz(t,r,{cwd:e})}catch(e){te.debug(e.message,"Continuing with the rest of the steps\n")}}async function oC(t){let i=oE(),r=tl(),n={"@rnef/cli":"rock","@rnef/platform-android":"@rock-js/platform-android","@rnef/platform-ios":"@rock-js/platform-ios","@rnef/plugin-metro":"@rock-js/plugin-metro","@rnef/plugin-repack":"@rock-js/plugin-repack","@rnef/provider-github":"@rock-js/provider-github","@rnef/provider-s3":"@rock-js/provider-s3","@rnef/welcome-screen":"@rock-js/welcome-screen"},s=function(t){let i=u.join(t,"package.json"),r=JSON.parse(e.readFileSync(i,"utf8"));return[...Object.keys(r.dependencies).filter(e=>e.startsWith("@rnef/")),...Object.keys(r.devDependencies).filter(e=>e.startsWith("@rnef/"))]}(t);r.start(`Removing ${J().bold("RNEF")} packages`),await ow(t,i,s),r.stop(`Removed ${J().bold("RNEF")} packages`),r.start(`Adding ${J().bold("Rock")} packages with ${J().bold(i)}`),await ov(t,i,s.map(e=>n[e])),r.stop(`Added ${J().bold("Rock")} packages`),r.start(`Updating ${J().bold(".gitignore")}`),function(t){let i=u.join(t,".gitignore");if(e.existsSync(i)){let t=e.readFileSync(i,"utf8");t=t.replace(/\.rnef\//g,".rock/"),e.writeFileSync(i,t)}}(t),r.stop(`Updated ${J().bold(".gitignore")}`),r.start("Updating cache"),function(t){let i=u.join(t,".rnef"),r=u.join(t,".rock");e.existsSync(i)&&(e.existsSync(r)&&e.rmSync(r,{recursive:!0,force:!0}),e.renameSync(i,r))}(t),function(t){let i=u.join(t,".rock","cache","remote-build");e.existsSync(i)&&e.readdirSync(i).forEach(t=>{if(t.includes("rnef")){let r=t.replace(/rnef/g,"rock"),n=u.join(i,t),s=u.join(i,r);e.renameSync(n,s)}})}(t),r.stop("Updated cache"),r.start(`Renaming and updating ${J().bold("rnef.config.mjs")} to ${J().bold("rock.config.mjs")}`),function(t){let i=u.join(t,"rnef.config.mjs"),r=u.join(t,"rock.config.mjs");if(e.existsSync(i)){let t=e.readFileSync(i,"utf8");t=(t=t.replace(/@rnef\//g,"@rock-js/")).replace(/@rnef\/cli/g,"rock"),e.writeFileSync(r,t),e.unlinkSync(i)}}(t),r.stop(`Renamed and updated ${J().bold("rnef.config.mjs")} to ${J().bold("rock.config.mjs")}`),r.start(`Updating ${J().bold("android/app/build.gradle")}`),function(t){let i=u.join(t,"android","app","build.gradle");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/@rnef\/cli\/dist\/src\/bin\.js/g,"rock/dist/src/bin.js"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("android/app/build.gradle")}`),r.start(`Updating ${J().bold("ios/Podfile")}`),function(t){let i=u.join(t,"ios","Podfile");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/rnef/g,"rock"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("ios/Podfile")}`),r.start(`Updating ${J().bold("android/settings.gradle")}`),function(t){let i=u.join(t,"android","settings.gradle");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/rnef/g,"rock"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("android/settings.gradle")}`),r.start(`Updating ${J().bold("ios/project.pbxproj")}`),function(t){let i=u.join(t,"ios");if(!e.existsSync(i))return;let r=e.readdirSync(i).find(e=>e.endsWith(".xcodeproj"));if(!r)return;let n=u.join(i,r,"project.pbxproj");if(!e.existsSync(n))return;let s=e.readFileSync(n,"utf8");s=s.replace(/@rnef\/cli/g,"rock"),e.writeFileSync(n,s)}(t),r.stop(`Updated ${J().bold("ios/project.pbxproj")}`),r.start(`Updating ${J().bold("package.json")} scripts`),function(t){let i=u.join(t,"package.json");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/rnef/g,"rock"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("package.json")} scripts`),tr(`1. Run ${J().bold("git diff")} to see the changes. Adjust as necessary e.g.: + - paths in monorepo + - commands in shell scripts + - commands in CI workflows +2. Run the dev server as you would normally do +3. Run iOS and Android apps as you would normally do +4. Setup Remote Cache: ${J().bold("https://rockjs.dev/docs/configuration#remote-cache-configuration")}`,"Next steps"),ti("RNEF to Rock migration completed successfully \uD83C\uDF89.")}async function ov(e,t,i){let r={npm:["install","-D",...i],pnpm:["add","-D",...i],yarn:["add","-D",...i],bun:["add","-D",...i]}[t]??["install","-D",...i];await tz(t,r,{cwd:e})}async function ow(e,t,i){let r={npm:["remove",...i],pnpm:["remove",...i],yarn:["remove",...i],bun:["remove",...i]}[t]??["remove",...i];try{await tz(t,r,{cwd:e})}catch(e){te.debug(e.message,"Continuing with the rest of the steps\n")}}var o_=Y("../../node_modules/.pnpm/minimist@1.2.8/node_modules/minimist/index.js"),oS=Y.n(o_);function oA(e){if(void 0!=e)return Array.isArray(e)?e[e.length-1]:e}function oR(e){if(void 0!=e)return Array.isArray(e)?e:[e]}let oO=/^[A-Z][0-9A-Z_-]*$/i,oB=["react","react-native","abstract","continue","for","new","switch","assert","default","goto","package","synchronized","boolean","do","if","private","this","break","double","implements","protected","throw","byte","else","import","public","throws","case","enum","instanceof","return","transient","catch","extends","int","short","try","char","final","interface","static","void","class","finally","long","strictfp","volatile","const","float","native","super","while"];function ox(e){if(0===e.length)return"Project name cannot be empty.";if(!e.match(oO))return`Invalid project name: "${e}". Please use a valid identifier name (alphanumeric, hyphen, underscore).`;let t=e.toLowerCase();if(oB.includes(t))return`Invalid project name: "${e}". Can't use reserved name. Please use another name.`}let oN=(e=0)=>t=>`\u001B[${t+e}m`,oI=(e=0)=>t=>`\u001B[${38+e};5;${t}m`,oT=(e=0)=>(t,i,r)=>`\u001B[${38+e};2;${t};${i};${r}m`,oL={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(oL.modifier),[...Object.keys(oL.color),...Object.keys(oL.bgColor)];let ok=function(){let e=new Map;for(let[t,i]of Object.entries(oL)){for(let[t,r]of Object.entries(i))oL[t]={open:`\u001B[${r[0]}m`,close:`\u001B[${r[1]}m`},i[t]=oL[t],e.set(r[0],r[1]);Object.defineProperty(oL,t,{value:i,enumerable:!1})}return Object.defineProperty(oL,"codes",{value:e,enumerable:!1}),oL.color.close="\x1b[39m",oL.bgColor.close="\x1b[49m",oL.color.ansi=oN(),oL.color.ansi256=oI(),oL.color.ansi16m=oT(),oL.bgColor.ansi=oN(10),oL.bgColor.ansi256=oI(10),oL.bgColor.ansi16m=oT(10),Object.defineProperties(oL,{rgbToAnsi256:{value:(e,t,i)=>e===t&&t===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(i/255*5),enumerable:!1},hexToRgb:{value(e){let t=/[a-f\d]{6}|[a-f\d]{3}/i.exec(e.toString(16));if(!t)return[0,0,0];let[i]=t;3===i.length&&(i=[...i].map(e=>e+e).join(""));let r=Number.parseInt(i,16);return[r>>16&255,r>>8&255,255&r]},enumerable:!1},hexToAnsi256:{value:e=>oL.rgbToAnsi256(...oL.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value(e){let t,i,r;if(e<8)return 30+e;if(e<16)return 90+(e-8);if(e>=232)i=t=((e-232)*10+8)/255,r=t;else{let n=(e-=16)%36;t=Math.floor(e/36)/5,i=Math.floor(n/6)/5,r=n%6/5}let n=2*Math.max(t,i,r);if(0===n)return 30;let s=30+(Math.round(r)<<2|Math.round(i)<<1|Math.round(t));return 2===n&&(s+=60),s},enumerable:!1},rgbToAnsi:{value:(e,t,i)=>oL.ansi256ToAnsi(oL.rgbToAnsi256(e,t,i)),enumerable:!1},hexToAnsi:{value:e=>oL.ansi256ToAnsi(oL.hexToAnsi256(e)),enumerable:!1}}),oL}();function oM(e,t=globalThis.Deno?globalThis.Deno.args:E.argv){let i=e.startsWith("-")?"":1===e.length?"-":"--",r=t.indexOf(i+e),n=t.indexOf("--");return -1!==r&&(-1===n||r=10&&Number(e[2])>=10586?Number(e[2])>=14931?3:2:1}if("CI"in o$)return"GITHUB_ACTIONS"in o$||"GITEA_ACTIONS"in o$?3:["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(e=>e in o$)||"codeship"===o$.CI_NAME?1:s;if("TEAMCITY_VERSION"in o$)return+!!/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(o$.TEAMCITY_VERSION);if("truecolor"===o$.COLORTERM||"xterm-kitty"===o$.TERM)return 3;if("TERM_PROGRAM"in o$){let e=Number.parseInt((o$.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(o$.TERM_PROGRAM){case"iTerm.app":return e>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(o$.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(o$.TERM)||"COLORTERM"in o$?1:s}(e,{streamIsTTY:e&&e.isTTY,...t}))&&{level:i,hasBasic:!0,has256:i>=2,has16m:i>=3}}oM("no-color")||oM("no-colors")||oM("color=false")||oM("color=never")?X=0:(oM("color")||oM("colors")||oM("color=true")||oM("color=always"))&&(X=1);let{stdout:oP,stderr:oz}={stdout:oj({isTTY:Z.isatty(1)}),stderr:oj({isTTY:Z.isatty(2)})},oU=Symbol("GENERATOR"),oH=Symbol("STYLER"),oG=Symbol("IS_EMPTY"),oZ=["ansi","ansi","ansi256","ansi16m"],oW=Object.create(null);function oV(e){let t=(...e)=>e.join(" ");return((e,t={})=>{if(t.level&&!(Number.isInteger(t.level)&&t.level>=0&&t.level<=3))throw Error("The `level` option should be an integer from 0 to 3");let i=oP?oP.level:0;e.level=void 0===t.level?i:t.level})(t,e),Object.setPrototypeOf(t,oV.prototype),t}for(let[e,t]of(Object.setPrototypeOf(oV.prototype,Function.prototype),Object.entries(ok)))oW[e]={get(){let i=oq(this,oK(t.open,t.close,this[oH]),this[oG]);return Object.defineProperty(this,e,{value:i}),i}};oW.visible={get(){let e=oq(this,this[oH],!0);return Object.defineProperty(this,"visible",{value:e}),e}};let oY=(e,t,i,...r)=>"rgb"===e?"ansi16m"===t?ok[i].ansi16m(...r):"ansi256"===t?ok[i].ansi256(ok.rgbToAnsi256(...r)):ok[i].ansi(ok.rgbToAnsi(...r)):"hex"===e?oY("rgb",t,i,...ok.hexToRgb(...r)):ok[i][e](...r);for(let e of["rgb","hex","ansi256"])oW[e]={get(){let{level:t}=this;return function(...i){return oq(this,oK(oY(e,oZ[t],"color",...i),ok.color.close,this[oH]),this[oG])}}},oW["bg"+e[0].toUpperCase()+e.slice(1)]={get(){let{level:t}=this;return function(...i){return oq(this,oK(oY(e,oZ[t],"bgColor",...i),ok.bgColor.close,this[oH]),this[oG])}}};let oX=Object.defineProperties(()=>{},{...oW,level:{enumerable:!0,get(){return this[oU].level},set(e){this[oU].level=e}}}),oK=(e,t,i)=>{let r,n;return void 0===i?(r=e,n=t):(r=i.openAll+e,n=t+i.closeAll),{open:e,close:t,openAll:r,closeAll:n,parent:i}},oq=(e,t,i)=>{let r=(...e)=>oJ(r,1===e.length?""+e[0]:e.join(" "));return Object.setPrototypeOf(r,oX),r[oU]=e,r[oH]=t,r[oG]=i,r},oJ=(e,t)=>{if(e.level<=0||!t)return e[oG]?"":t;let i=e[oH];if(void 0===i)return t;let{openAll:r,closeAll:n}=i;if(t.includes("\x1b"))for(;void 0!==i;)t=function(e,t,i){let r=e.indexOf(t);if(-1===r)return e;let n=t.length,s=0,o="";do o+=e.slice(s,r)+t+i,s=r+n,r=e.indexOf(t,s);while(-1!==r);return o+e.slice(s)}(t,i.close,i.open),i=i.parent;let s=t.indexOf("\n");return -1!==s&&(t=function(e,t,i,r){let n=0,s="";do{let o="\r"===e[r-1];s+=e.slice(n,o?r-1:r)+t+(o?"\r\n":"\n")+i,n=r+1,r=e.indexOf("\n",n)}while(-1!==r);return s+e.slice(n)}(t,n,r,s)),r+t+n};Object.defineProperties(oV.prototype,oW);let oQ=oV();oV({level:oz?oz.level:0});var o0=Y("../../node_modules/.pnpm/tinygradient@1.1.5/node_modules/tinygradient/index.js");let o1=(...e)=>{let t,i;if(0===e.length)throw Error("Missing gradient colors");if(Array.isArray(e[0]))t=o0(e[0]),i=o3(e[1]);else{if(1===e.length)throw Error(`Expected an array of colors, received ${JSON.stringify(e[0])}`);t=o0(...e)}let r=(e,r)=>(function(e,t,i){let r=o3(i),n=Math.max(e.replace(/\s/g,"").length,t.stops.length),s=o2(t,r,n),o="";for(let t of e)o+=t.match(/\s/g)?t:oQ.hex(s.shift()?.toHex()||"#000")(t);return o})(e?e.toString():"",t,r??i);return r.multiline=(e,r)=>(function(e,t,i){let r=o3(i),n=e.split("\n"),s=Math.max(...n.map(e=>e.length),t.stops.length),o=o2(t,r,s),u=[];for(let e of n){let t=o.slice(0),i="";for(let r of e)i+=oQ.hex(t.shift()?.toHex()||"#000")(r);u.push(i)}return u.join("\n")})(e?e.toString():"",t,r??i),r},o2=(e,t,i)=>t.interpolation?.toLowerCase()==="hsv"?e.hsv(i,t.hsvSpin?.toLowerCase()||!1):e.rgb(i);function o3(e){let t={interpolation:"rgb",hsvSpin:"short",...e};if(void 0!==e&&"object"!=typeof e)throw TypeError(`Expected \`options\` to be an \`object\`, got \`${typeof e}\``);if("string"!=typeof t.interpolation)throw TypeError(`Expected \`options.interpolation\` to be \`rgb\` or \`hsv\`, got \`${typeof t.interpolation}\``);if("hsv"===t.interpolation.toLowerCase()&&"string"!=typeof t.hsvSpin)throw TypeError(`Expected \`options.hsvSpin\` to be a \`short\` or \`long\`, got \`${typeof t.hsvSpin}\``);return t}function o8(e){let t=t=>o1(...e.colors)(t,e.options);return t.multiline=(t="")=>o1(...e.colors).multiline(t,e.options),t}let o6=o8({colors:["#feac5e","#c779d0","#4bc0c8"],options:{}}),o5=o8({colors:["#bdfff3","#4ac29a"],options:{}}),o4=o8({colors:["#77a1d3","#79cbca","#e684ae"],options:{}}),o9=o8({colors:["#473b7b","#3584a7","#30d2be"],options:{}}),o7=o8({colors:["#ff5f6d","#ffc371"],options:{interpolation:"hsv"}}),ue=o8({colors:["#5ee7df","#b490ca"],options:{interpolation:"hsv"}}),ut=o8({colors:["#f43b47","#453a94"],options:{}}),ui=o8({colors:["#ff4e50","#f9d423"],options:{}}),ur=o8({colors:["#833ab4","#fd1d1d","#fcb045"],options:{}}),un=o8({colors:["#3f51b1","#5a55ae","#7b5fac","#8f6aae","#a86aa4","#cc6b8e","#f18271","#f3a469","#f7c978"],options:{}}),us=o8({colors:["#fdbb2d","#22c1c3"],options:{}}),uo=o8({colors:["#ff0000","#ff0100"],options:{interpolation:"hsv",hsvSpin:"long"}}),uu=o8({colors:["#74ebd5","#74ecd5"],options:{interpolation:"hsv",hsvSpin:"long"}});function ua(){try{let e=l(B(import.meta.url)),t=d(e,"../../package.json");return JSON.parse(r(t,"utf-8")).version}catch(e){return te.warn("Failed to get Rock version",e),null}}function ul(e){return tn({message:"What is your app named?",initialValue:e,validate:ox})}async function uh(e){if(0===e.length)throw new e9("No templates found");return ts({message:"Select a template:",options:e.map(e=>({value:e,label:e.displayName}))})}async function uc(t,i="latest",r){try{var n;let s=null==(n=(await ud(t,i)).dist)?void 0:n.tarball;if(!s)throw new e9("Tarball URL not found.");let o=await fetch(s);if(!o.ok)throw new e9(`Failed to fetch package ${t}: ${o.statusText}`);let a=u.join(r,`${t.replace("/","-")}.tgz`),l=await o.arrayBuffer();return e.writeFileSync(a,new Uint8Array(l)),a}catch(e){throw new e9(`Error downloading package ${t}`,{cause:e})}}async function ud(e,t){var i,r,n;let s=`${process.env.NPM_CONFIG_REGISTRY||"https://registry.npmjs.org"}/${e}`,o=await fetch(s);if(!o.ok)throw new e9(`Failed to fetch package metadata for ${e}: ${o.statusText}`);let u=await o.json(),a=null==(i=u["dist-tags"])?void 0:i[t],l=a?null==(r=u.versions)?void 0:r[a]:null==(n=u.versions)?void 0:n[t];if(!l)throw new e9(`Version ${t} not found for package ${e}`);return l}async function uD(t,i){let r=u.join(t,`.temp-${u.basename(i,u.extname(i))}-${Date.now()}`);return e.mkdirSync(r,{recursive:!0}),await s4({file:i,cwd:r,strip:1}),r}async function uf(){let t=function(e){let t=oS()(e,{alias:{h:"help",v:"version",p:"platform",t:"template",d:"dir"},boolean:["help","version","override","install"],string:["template","platform","dir","plugin","bundler"]});return{name:t._[0],template:oA(t.template),platforms:oR(t.platform),plugins:oR(t.plugin),bundler:t.bundler,help:t.help,version:t.version,dir:oA(t.dir),override:t.override,remoteCacheProvider:t["remote-cache-provider"],install:t.install}}(process.argv.slice(2)),l=ua();if(t.help)return void console.log(` + Usage: create-rock [options] + + Options: + + -h, --help Display help for command + -v, --version Output the version number + -d, --dir Create project in specified directory + -t, --template Specify template to use + -p, --platform Specify platform(s) to use + --plugin Specify plugin(s) to use + --bundler Specify bundler to use + --remote-cache-provider Specify remote cache provider + --override Override files in target directory + --install Install Node.js dependencies + + Available templates: + ${oo.map(e=>e.name).join(", ")} + + Available platforms: + ${ol.map(e=>e.name).join(", ")} + `);if(t.version)return void console.log(`${ua()}`);console.log(""),((e="")=>{process.stdout.write(`${q.gray(eP)} ${e} +`)})(`Welcome to ${J().bold(ue("Rock"))}!`);let h=tU(t.dir||process.cwd());if(function(t){var i,r;let n=u.join(t,"package.json");if(!e.existsSync(n))return!1;let s=JSON.parse(e.readFileSync(n,"utf8"));return(null==(i=s.dependencies)?void 0:i["@rnef/cli"])!==void 0||(null==(r=s.devDependencies)?void 0:r["@rnef/cli"])!==void 0}(h)){await up(h),await to({message:"Detected existing RNEF project. Would you like to migrate it to Rock?",confirmLabel:"Yes",cancelLabel:"No"})||tc(),await oC(h);return}if(function(t){var i,r;let n=u.join(t,"package.json");if(!e.existsSync(n))return!1;let s=JSON.parse(e.readFileSync(n,"utf8"));return(null==(i=s.dependencies)?void 0:i["react-native"])!==void 0||(null==(r=s.devDependencies)?void 0:r["react-native"])!==void 0}(h)){await up(h),await to({message:"Detected existing React Native project. Would you like to migrate it to Rock?",confirmLabel:"Yes",cancelLabel:"No"})||tc(),await ob(h);return}let c=(t.dir||t.name)??await ul();ox(c)&&(c=await ul(c));let{targetDir:D}=function(e){let t=e.trim().replace(/\/+$/g,"");return{packageName:t.startsWith("@")?t:u.basename(t),targetDir:t}}(c),p=tU(D);!t.override&&e.existsSync(p)&&!function(t){let i=e.readdirSync(t);return 0===i.length||1===i.length&&".git"===i[0]}(p)&&(await to({message:`"${p}" is not empty, please choose:`,confirmLabel:"Continue and override files",cancelLabel:"Cancel operation"})||tc()),op(p),e.mkdirSync(p,{recursive:!0});let m=t.template?oc(oo,t.template):await uh(oo),g=t.platforms?t.platforms.map(e=>oc(ol,e)):await function(e){if(0===e.length)throw new e9("No platforms found");let t=e.filter(e=>"android"===e.name||"ios"===e.name);return tu({message:`What platforms do you want to start with? ${J().dim("(Press to select, to skip)")}:`,initialValues:t,options:e.map(e=>({value:e,label:e.displayName}))})}(ol),E=t.bundler?oc(oa,t.bundler):await function(e){if(0===e.length)throw new e9("No bundlers found");return ts({message:"Which bundler do you want to use?",initialValues:[e[0]],options:e.map(e=>({value:e,label:e.displayName}))})}(oa),b=t.plugins?t.plugins.map(e=>oc(ou,e)):await (0===ou.length||!e4()?Promise.resolve(null):tu({message:`Select plugins ${J().dim("(Press to skip)")}:`,options:ou.map(e=>({value:e,label:e.displayName,hint:e.hint})),required:!1})),y=void 0!==t.remoteCacheProvider||!1===t.remoteCacheProvider?null:await ts({message:"What do you want to use as cache for your remote builds?",initialValue:"github-actions",options:[{value:"github-actions",label:"GitHub Actions",hint:"The easiest way to start if you store your code on GitHub"},{value:"s3",label:"S3",hint:"Work with any S3-compatible storage, including AWS S3 and Cloudflare R2"},{value:null,label:"None",hint:"Local cache only which isn't shared across team members or CI/CD environments"}]}),F=y?await function(e){let t="Ensure the below environment variables are set";switch(e){case"github-actions":return tr(`GITHUB_TOKEN Your GitHub personal access token (PAT) + +\u{1F4A1} Set this in your ${J().bold(".env")} file or pass it as an argument to ${J().bold("run:*")} commands.`,t),ta({owner:()=>tn({message:"GitHub repository owner"}),repository:()=>tn({message:"GitHub repository name"})});case"s3":return tr(`AWS_ACCESS_KEY_ID Your AWS access key ID +AWS_SECRET_ACCESS_KEY Your AWS secret access key + +\u{1F4A1} Set these in your ${J().bold(".env")} file or pass them as arguments to ${J().bold("run:*")} commands.`,t),ta({bucket:()=>tn({message:"Pass your bucket name:",placeholder:"bucket-name",defaultValue:"bucket-name"}),region:()=>tn({message:"Pass your bucket region:",placeholder:"us-west-1",defaultValue:"us-west-1"}),endpoint:()=>tn({message:`If you're using self-hosted S3 or Cloudflare R2, pass your endpoint ${J().dim("(Press to skip)")}:`,placeholder:"https://.r2.cloudflarestorage.com",defaultValue:void 0})})}}(y):null,C=!!(t.install||e4())&&await to({message:"Do you want to install dependencies?",confirmLabel:"Yes",cancelLabel:"No"}),v=tl();for(let e of(v.start("Applying template, platforms and plugins"),await ug(p,m),g))await ug(p,e);let w=g.map(e=>e.name).includes("harmony")?["metro.config.js"]:void 0;for(let e of(await ug(p,E,w),b??[]))await ug(p,e);let _=d(p,"gitignore");i(_)&&n(_,d(p,".gitignore"));let S=d(p,"harmony","gitignore");i(S)&&n(S,d(p,"harmony",".gitignore"));var A,R=(A=c)?A.split("-").filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""):"";if(R!==og)for(let t of(function t(i){if(!e.lstatSync(i).isDirectory())return[i];let r=e.readdirSync(i).flatMap(e=>t(u.join(i,e)));return[i,...r]})(p).reverse())s(t).isDirectory()||function(e,t){let i=r(e,"utf8"),n=i.replaceAll(og,t).replaceAll(og.toLowerCase(),t.toLowerCase());i!==n&&o(e,n,"utf8")}(t,R),a(t).includes(og)?om(t,og,R):a(t).includes(og.toLowerCase())&&om(t,og.toLowerCase(),R.toLowerCase());!function(e,t){let n=d(e,"package.json");if(!i(n))return;let s=JSON.parse(r(n,"utf-8"));s.name=t,s.version="1.0.0",s.private=!0,delete s.publishConfig,s.dependencies&&(s.dependencies=Object.fromEntries(Object.entries(s.dependencies).sort())),s.devDependencies&&(s.devDependencies=Object.fromEntries(Object.entries(s.devDependencies).sort())),s.peerDependencies&&(s.peerDependencies=Object.fromEntries(Object.entries(s.peerDependencies).sort())),o(n,JSON.stringify(function(e){let{name:t,version:i,private:r,scripts:n,dependencies:s,devDependencies:o,peerDependencies:u,...a}=e,l={};for(let e in oD(l,"name",t),oD(l,"version",i),oD(l,"private",r),oD(l,"scripts",n),oD(l,"dependencies",s),oD(l,"devDependencies",o),oD(l,"peerDependencies",u),a)l[e]=a[e];return l}(s),null,2))}(p,c),function(t,i,r,n,s){let o=u.join(t,"rock.config.mjs");e.writeFileSync(o,function(e,t,i,r){let n=e.filter(e=>e.importName),s=t?t.filter(e=>e.importName):null;return`${[...[...n,...s??[],i].map(e=>`import { ${e.importName} } from '${e.packageName}';`),(null==r?void 0:r.name)?function(e){switch(e){case"github-actions":return"import { providerGitHub } from '@rock-js/provider-github';";case"s3":return"import { providerS3 } from '@rock-js/provider-s3';"}}(r.name):""].filter(Boolean).join("\n")} + +export default { + ${[s&&s.length>0?`plugins: [ + ${s.map(e=>`${e.importName}(),`).join("\n ")} + ],`:"",`bundler: ${i.importName}(),`,`platforms: { + ${n.map(e=>`${e.name}: ${e.importName}(),`).join("\n ")} + },`,(null==r?void 0:r.name)?function(e,t){switch(e){case"github-actions":return oh(["remoteCacheProvider: providerGitHub({",` owner: '${t.owner}',`,` repository: '${t.repository}',`,"}),"]);case"s3":return oh(["remoteCacheProvider: providerS3({",` bucket: '${t.bucket}',`,` region: '${t.region}',`,[` endpoint: '${t.endpoint}',`,!!t.endpoint],"}),"])}}(r.name,r.args):""].filter(Boolean).join("\n ")} +}; +`}(i,r,n,s))}(p,g,b,E,y&&F?{name:y,args:F}:null),v.stop("Applied template, platforms and plugins.");let O=function(){let e=function(e){if(!e)return;let t=e.split(" ")[0].split("/");return{name:t[0],version:t[1]}}(process.env.npm_config_user_agent);return e?e.name:oE()}();C&&await um(p,O),await oi(p,l);let B=f(process.cwd(),p);tr([`cd ${B}`,C?void 0:`${O} install`,`${O} run start starts dev server`,`${O} run ios builds and runs iOS app`,`${O} run android builds and runs Android app`].filter(Boolean).join("\n"),"Next steps"),ti("Success \uD83C\uDF89.")}async function up(e){if(await os(e)&&await on()){let{output:t}=await tz("git",["status","--porcelain"],{cwd:e});""!==t.trim()&&(await to({message:"Git has uncommitted changes. Would you like to continue with initializing Rock in existing project?",confirmLabel:"Yes",cancelLabel:"No"})||tc())}}async function um(e,t){let i=tl();i.start(`Installing dependencies with ${t}`),await tz(t,["install"],{cwd:e}),i.stop(`Installed dependencies with ${t}`)}async function ug(t,i,r){var n,s,o;let a=null;if("npm"===i.type?a=await uc(i.packageName,i.version,t):((null==(n=i.localPath)?void 0:n.endsWith(".tgz"))||(null==(s=i.localPath)?void 0:s.endsWith(".tar.gz"))||(null==(o=i.localPath)?void 0:o.endsWith(".tar")))&&(a=i.localPath),a){let n=await uD(t,a);i.packageName&&e.unlinkSync(a),of(u.join(n,i.directory??""),t,{skipFiles:r}),op(n);return}if("local"===i.type)return void of(u.join(i.localPath,i.directory??""),t,{skipFiles:r});throw new e9(`Invalid state: template not found: ${JSON.stringify(i,null,2)}`)}o1.atlas=o6,o1.cristal=o5,o1.teen=o4,o1.mind=o9,o1.morning=o7,o1.vice=ue,o1.passion=ut,o1.fruit=ui,o1.instagram=ur,o1.retro=un,o1.summer=us,o1.rainbow=uo,o1.pastel=uu},crypto:function(e){e.exports=W},fs:function(e){e.exports=V},path:function(e){e.exports=Y},zlib:function(e){e.exports=X},"../../node_modules/.pnpm/tinycolor2@1.6.0/node_modules/tinycolor2/cjs/tinycolor.js":function(e){e.exports=function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}var t,i,r,n=/^\s+/,s=/\s+$/;function o(t,i){if(i=i||{},(t=t||"")instanceof o)return t;if(!(this instanceof o))return new o(t,i);var r,u,a,l,h,c,d,D,f,p,m,g,E,b,y,F,C,w,A,O,x=(u={r:0,g:0,b:0},a=1,l=null,h=null,c=null,d=!1,D=!1,"string"==typeof(r=t)&&(r=function(e){e=e.replace(n,"").replace(s,"").toLowerCase();var t,i=!1;if(v[e])e=v[e],i=!0;else if("transparent"==e)return{r:0,g:0,b:0,a:0,format:"name"};return(t=N.rgb.exec(e))?{r:t[1],g:t[2],b:t[3]}:(t=N.rgba.exec(e))?{r:t[1],g:t[2],b:t[3],a:t[4]}:(t=N.hsl.exec(e))?{h:t[1],s:t[2],l:t[3]}:(t=N.hsla.exec(e))?{h:t[1],s:t[2],l:t[3],a:t[4]}:(t=N.hsv.exec(e))?{h:t[1],s:t[2],v:t[3]}:(t=N.hsva.exec(e))?{h:t[1],s:t[2],v:t[3],a:t[4]}:(t=N.hex8.exec(e))?{r:R(t[1]),g:R(t[2]),b:R(t[3]),a:R(t[4])/255,format:i?"name":"hex8"}:(t=N.hex6.exec(e))?{r:R(t[1]),g:R(t[2]),b:R(t[3]),format:i?"name":"hex"}:(t=N.hex4.exec(e))?{r:R(t[1]+""+t[1]),g:R(t[2]+""+t[2]),b:R(t[3]+""+t[3]),a:R(t[4]+""+t[4])/255,format:i?"name":"hex8"}:!!(t=N.hex3.exec(e))&&{r:R(t[1]+""+t[1]),g:R(t[2]+""+t[2]),b:R(t[3]+""+t[3]),format:i?"name":"hex"}}(r)),"object"==e(r)&&(I(r.r)&&I(r.g)&&I(r.b)?(f=r.r,p=r.g,m=r.b,u={r:255*S(f,255),g:255*S(p,255),b:255*S(m,255)},d=!0,D="%"===String(r.r).substr(-1)?"prgb":"rgb"):I(r.h)&&I(r.s)&&I(r.v)?(l=B(r.s),h=B(r.v),g=r.h,E=l,b=h,g=6*S(g,360),E=S(E,100),b=S(b,100),y=Math.floor(g),F=g-y,C=b*(1-E),w=b*(1-F*E),A=b*(1-(1-F)*E),u={r:255*[b,w,C,C,A,b][O=y%6],g:255*[A,b,b,w,C,C][O],b:255*[C,C,A,b,b,w][O]},d=!0,D="hsv"):I(r.h)&&I(r.s)&&I(r.l)&&(l=B(r.s),c=B(r.l),u=function(e,t,i){var r,n,s;function o(e,t,i){return(i<0&&(i+=1),i>1&&(i-=1),i<1/6)?e+(t-e)*6*i:i<.5?t:i<2/3?e+(t-e)*(2/3-i)*6:e}if(e=S(e,360),t=S(t,100),i=S(i,100),0===t)r=n=s=i;else{var u=i<.5?i*(1+t):i+t-i*t,a=2*i-u;r=o(a,u,e+1/3),n=o(a,u,e),s=o(a,u,e-1/3)}return{r:255*r,g:255*n,b:255*s}}(r.h,l,c),d=!0,D="hsl"),r.hasOwnProperty("a")&&(a=r.a)),a=_(a),{ok:d,format:r.format||D,r:Math.min(255,Math.max(u.r,0)),g:Math.min(255,Math.max(u.g,0)),b:Math.min(255,Math.max(u.b,0)),a:a});this._originalInput=t,this._r=x.r,this._g=x.g,this._b=x.b,this._a=x.a,this._roundA=Math.round(100*this._a)/100,this._format=i.format||x.format,this._gradientType=i.gradientType,this._r<1&&(this._r=Math.round(this._r)),this._g<1&&(this._g=Math.round(this._g)),this._b<1&&(this._b=Math.round(this._b)),this._ok=x.ok}function u(e,t,i){e=S(e,255);var r,n,s=Math.max(e,t=S(t,255),i=S(i,255)),o=Math.min(e,t,i),u=(s+o)/2;if(s==o)r=n=0;else{var a=s-o;switch(n=u>.5?a/(2-s-o):a/(s+o),s){case e:r=(t-i)/a+6*(t>1)+720)%360;--t;)r.h=(r.h+n)%360,s.push(o(r));return s}function C(e,t){t=t||6;for(var i=o(e).toHsv(),r=i.h,n=i.s,s=i.v,u=[],a=1/t;t--;)u.push(o({h:r,s:n,v:s})),s=(s+a)%1;return u}o.prototype={isDark:function(){return 128>this.getBrightness()},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},getLuminance:function(){var e,t,i,r=this.toRgb();return e=r.r/255,t=r.g/255,.2126*(e<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4))+.7152*(t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4))+.0722*((i=r.b/255)<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4))},setAlpha:function(e){return this._a=_(e),this._roundA=Math.round(100*this._a)/100,this},toHsv:function(){var e=a(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=a(this._r,this._g,this._b),t=Math.round(360*e.h),i=Math.round(100*e.s),r=Math.round(100*e.v);return 1==this._a?"hsv("+t+", "+i+"%, "+r+"%)":"hsva("+t+", "+i+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var e=u(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=u(this._r,this._g,this._b),t=Math.round(360*e.h),i=Math.round(100*e.s),r=Math.round(100*e.l);return 1==this._a?"hsl("+t+", "+i+"%, "+r+"%)":"hsla("+t+", "+i+"%, "+r+"%, "+this._roundA+")"},toHex:function(e){return l(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(e){var t,i,r,n,s,o;return t=this._r,i=this._g,r=this._b,n=this._a,s=e,o=[O(Math.round(t).toString(16)),O(Math.round(i).toString(16)),O(Math.round(r).toString(16)),O(x(n))],s&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1)?o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0):o.join("")},toHex8String:function(e){return"#"+this.toHex8(e)},toRgb:function(){return{r:Math.round(this._r),g:Math.round(this._g),b:Math.round(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+")":"rgba("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:Math.round(100*S(this._r,255))+"%",g:Math.round(100*S(this._g,255))+"%",b:Math.round(100*S(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+Math.round(100*S(this._r,255))+"%, "+Math.round(100*S(this._g,255))+"%, "+Math.round(100*S(this._b,255))+"%)":"rgba("+Math.round(100*S(this._r,255))+"%, "+Math.round(100*S(this._g,255))+"%, "+Math.round(100*S(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(w[l(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var t="#"+h(this._r,this._g,this._b,this._a),i=t,r=this._gradientType?"GradientType = 1, ":"";if(e){var n=o(e);i="#"+h(n._r,n._g,n._b,n._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+t+",endColorstr="+i+")"},toString:function(e){var t=!!e;e=e||this._format;var i=!1,r=this._a<1&&this._a>=0;return!t&&r&&("hex"===e||"hex6"===e||"hex3"===e||"hex4"===e||"hex8"===e||"name"===e)?"name"===e&&0===this._a?this.toName():this.toRgbString():("rgb"===e&&(i=this.toRgbString()),"prgb"===e&&(i=this.toPercentageRgbString()),("hex"===e||"hex6"===e)&&(i=this.toHexString()),"hex3"===e&&(i=this.toHexString(!0)),"hex4"===e&&(i=this.toHex8String(!0)),"hex8"===e&&(i=this.toHex8String()),"name"===e&&(i=this.toName()),"hsl"===e&&(i=this.toHslString()),"hsv"===e&&(i=this.toHsvString()),i||this.toHexString())},clone:function(){return o(this.toString())},_applyModification:function(e,t){var i=e.apply(null,[this].concat([].slice.call(t)));return this._r=i._r,this._g=i._g,this._b=i._b,this.setAlpha(i._a),this},lighten:function(){return this._applyModification(f,arguments)},brighten:function(){return this._applyModification(p,arguments)},darken:function(){return this._applyModification(m,arguments)},desaturate:function(){return this._applyModification(c,arguments)},saturate:function(){return this._applyModification(d,arguments)},greyscale:function(){return this._applyModification(D,arguments)},spin:function(){return this._applyModification(g,arguments)},_applyCombination:function(e,t){return e.apply(null,[this].concat([].slice.call(t)))},analogous:function(){return this._applyCombination(F,arguments)},complement:function(){return this._applyCombination(E,arguments)},monochromatic:function(){return this._applyCombination(C,arguments)},splitcomplement:function(){return this._applyCombination(y,arguments)},triad:function(){return this._applyCombination(b,[3])},tetrad:function(){return this._applyCombination(b,[4])}},o.fromRatio=function(t,i){if("object"==e(t)){var r={};for(var n in t)t.hasOwnProperty(n)&&("a"===n?r[n]=t[n]:r[n]=B(t[n]));t=r}return o(t,i)},o.equals=function(e,t){return!!e&&!!t&&o(e).toRgbString()==o(t).toRgbString()},o.random=function(){return o.fromRatio({r:Math.random(),g:Math.random(),b:Math.random()})},o.mix=function(e,t,i){i=0===i?0:i||50;var r=o(e).toRgb(),n=o(t).toRgb(),s=i/100;return o({r:(n.r-r.r)*s+r.r,g:(n.g-r.g)*s+r.g,b:(n.b-r.b)*s+r.b,a:(n.a-r.a)*s+r.a})},o.readability=function(e,t){var i=o(e),r=o(t);return(Math.max(i.getLuminance(),r.getLuminance())+.05)/(Math.min(i.getLuminance(),r.getLuminance())+.05)},o.isReadable=function(e,t,i){var r,n,s,u,a,l=o.readability(e,t);switch(a=!1,(n=((r=(r=i)||{level:"AA",size:"small"}).level||"AA").toUpperCase(),s=(r.size||"small").toLowerCase(),"AA"!==n&&"AAA"!==n&&(n="AA"),"small"!==s&&"large"!==s&&(s="small"),u={level:n,size:s}).level+u.size){case"AAsmall":case"AAAlarge":a=l>=4.5;break;case"AAlarge":a=l>=3;break;case"AAAsmall":a=l>=7}return a},o.mostReadable=function(e,t,i){var r,n,s,u,a=null,l=0;n=(i=i||{}).includeFallbackColors,s=i.level,u=i.size;for(var h=0;hl&&(l=r,a=o(t[h]));return o.isReadable(e,a,{level:s,size:u})||!n?a:(i.includeFallbackColors=!1,o.mostReadable(e,["#fff","#000"],i))};var v=o.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},w=o.hexNames=function(e){var t={};for(var i in e)e.hasOwnProperty(i)&&(t[e[i]]=i);return t}(v);function _(e){return(isNaN(e=parseFloat(e))||e<0||e>1)&&(e=1),e}function S(e,t){"string"==typeof(i=e)&&-1!=i.indexOf(".")&&1===parseFloat(i)&&(e="100%");var i,r,n="string"==typeof(r=e)&&-1!=r.indexOf("%");return(e=Math.min(t,Math.max(0,parseFloat(e))),n&&(e=parseInt(e*t,10)/100),1e-6>Math.abs(e-t))?1:e%t/parseFloat(t)}function A(e){return Math.min(1,Math.max(0,e))}function R(e){return parseInt(e,16)}function O(e){return 1==e.length?"0"+e:""+e}function B(e){return e<=1&&(e=100*e+"%"),e}function x(e){return Math.round(255*parseFloat(e)).toString(16)}var N=(i="[\\s|\\(]+("+(t="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+t+")[,|\\s]+("+t+")\\s*\\)?",r="[\\s|\\(]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")\\s*\\)?",{CSS_UNIT:new RegExp(t),rgb:RegExp("rgb"+i),rgba:RegExp("rgba"+r),hsl:RegExp("hsl"+i),hsla:RegExp("hsla"+r),hsv:RegExp("hsv"+i),hsva:RegExp("hsva"+r),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function I(e){return!!N.CSS_UNIT.exec(e)}return o}()}},et={};function ei(e){var t=et[e];if(void 0!==t)return t.exports;var i=et[e]={exports:{}};return ee[e].call(i.exports,i,i.exports,ei),i.exports}K="function"==typeof Symbol?Symbol("webpack queues"):"__webpack_queues__",q="function"==typeof Symbol?Symbol("webpack exports"):"__webpack_exports__",J="function"==typeof Symbol?Symbol("webpack error"):"__webpack_error__",Q=e=>{e&&e.d<1&&(e.d=1,e.forEach(e=>e.r--),e.forEach(e=>e.r--?e.r++:e()))},ei.a=(e,t,i)=>{i&&((r=[]).d=-1);var r,n,s,o,u=new Set,a=e.exports,l=new Promise((e,t)=>{o=t,s=e});l[q]=a,l[K]=e=>{r&&e(r),u.forEach(e),l.catch(function(){})},e.exports=l,t(e=>{n=e.map(e=>{if(null!==e&&"object"==typeof e){if(e[K])return e;if(e.then){var t=[];t.d=0,e.then(e=>{i[q]=e,Q(t)},e=>{i[J]=e,Q(t)});var i={};return i[K]=e=>e(t),i}}var r={};return r[K]=function(){},r[q]=e,r});var t,i=()=>n.map(e=>{if(e[J])throw e[J];return e[q]}),s=new Promise(e=>{(t=()=>e(i)).r=0;var s=e=>e!==r&&!u.has(e)&&(u.add(e),e&&!e.d&&(t.r++,e.push(t)));n.map(e=>e[K](s))});return t.r?s:i()},e=>(e?o(l[J]=e):s(a),Q(r))),r&&r.d<0&&(r.d=0)},ei.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return ei.d(t,{a:t}),t},ei.d=(e,t)=>{for(var i in t)ei.o(t,i)&&!ei.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},ei.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),ei.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},ei("./src/bin.ts"); \ No newline at end of file diff --git a/packages/platform-android/dist/src/index.d.ts b/packages/platform-android/dist/src/index.d.ts new file mode 100644 index 000000000..5d9b6a5c6 --- /dev/null +++ b/packages/platform-android/dist/src/index.d.ts @@ -0,0 +1,3 @@ +export * from './lib/platformAndroid.js'; +export { type PackageAarFlags, packageAar, options as packageAarOptions, } from './lib/commands/aar/packageAar.js'; +export { publishLocalAar, options as publishLocalAarOptions, } from './lib/commands/aar/publishLocalAar.js'; diff --git a/packages/platform-android/dist/src/index.js b/packages/platform-android/dist/src/index.js new file mode 100644 index 000000000..3d946d010 --- /dev/null +++ b/packages/platform-android/dist/src/index.js @@ -0,0 +1,4 @@ +export * from './lib/platformAndroid.js'; +export { packageAar, options as packageAarOptions, } from './lib/commands/aar/packageAar.js'; +export { publishLocalAar, options as publishLocalAarOptions, } from './lib/commands/aar/publishLocalAar.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/index.js.map b/packages/platform-android/dist/src/index.js.map new file mode 100644 index 000000000..ad327389f --- /dev/null +++ b/packages/platform-android/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAEL,UAAU,EACV,OAAO,IAAI,iBAAiB,GAC7B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,OAAO,IAAI,sBAAsB,GAClC,MAAM,uCAAuC,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/aar/packageAar.d.ts b/packages/platform-android/dist/src/lib/commands/aar/packageAar.d.ts new file mode 100644 index 000000000..2e62fcf4f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/aar/packageAar.d.ts @@ -0,0 +1,14 @@ +export interface AarProject { + sourceDir: string; + moduleName: string; +} +export type PackageAarFlags = { + variant: string; + moduleName?: string; +}; +export declare function packageAar(aarProject: AarProject, args: PackageAarFlags): Promise; +export declare function localPublishAar(aarProject: AarProject, args: PackageAarFlags): Promise; +export declare const options: { + name: string; + description: string; +}[]; diff --git a/packages/platform-android/dist/src/lib/commands/aar/packageAar.js b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js new file mode 100644 index 000000000..2d542d4c7 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js @@ -0,0 +1,34 @@ +import { outro } from '@rock-js/tools'; +import { runGradleAar } from '../runGradle.js'; +import { toPascalCase } from '../toPascalCase.js'; +export async function packageAar(aarProject, args) { + normalizeArgs(args); + const tasks = [`assemble${toPascalCase(args.variant)}`]; + await runGradleAar({ tasks, aarProject, variant: args.variant }); + outro('Success ๐ŸŽ‰.'); +} +export async function localPublishAar(aarProject, args) { + const tasks = ['publishToMavenLocal']; + await runGradleAar({ + tasks, + aarProject, + variant: args.variant, + }); + outro('Success ๐ŸŽ‰.'); +} +function normalizeArgs(args) { + if (!args.variant) { + args.variant = 'debug'; + } +} +export const options = [ + { + name: '--variant ', + description: "Specify your app's build variant, which is constructed from build type and product flavor, e.g. 'debug' or 'freeRelease'.", + }, + { + name: '--module-name ', + description: 'AAR module name', + }, +]; +//# sourceMappingURL=packageAar.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/aar/packageAar.js.map b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js.map new file mode 100644 index 000000000..013ee5f0f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js.map @@ -0,0 +1 @@ +{"version":3,"file":"packageAar.js","sourceRoot":"","sources":["../../../../../src/lib/commands/aar/packageAar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAYlD,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,UAAsB,EACtB,IAAqB;IAErB,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,MAAM,KAAK,GAAG,CAAC,WAAW,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAExD,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAsB,EACtB,IAAqB;IAErB,MAAM,KAAK,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEtC,MAAM,YAAY,CAAC;QACjB,KAAK;QACL,UAAU;QACV,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;IACH,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,aAAa,CAAC,IAAqB;IAC1C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,2HAA2H;KAC9H;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,iBAAiB;KAC/B;CACF,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.d.ts b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.d.ts new file mode 100644 index 000000000..5126fb7bd --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.d.ts @@ -0,0 +1,6 @@ +import type { AarProject } from './packageAar.js'; +export declare function publishLocalAar(aarProject: AarProject): Promise; +export declare const options: { + name: string; + description: string; +}[]; diff --git a/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js new file mode 100644 index 000000000..a853f7b2f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js @@ -0,0 +1,17 @@ +import { outro } from '@rock-js/tools'; +import { runGradleAar } from '../runGradle.js'; +export async function publishLocalAar(aarProject) { + const tasks = ['publishToMavenLocal']; + await runGradleAar({ + tasks, + aarProject, + }); + outro('Success ๐ŸŽ‰.'); +} +export const options = [ + { + name: '--module-name ', + description: 'AAR module name', + }, +]; +//# sourceMappingURL=publishLocalAar.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js.map b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js.map new file mode 100644 index 000000000..e3fae0cdb --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js.map @@ -0,0 +1 @@ +{"version":3,"file":"publishLocalAar.js","sourceRoot":"","sources":["../../../../../src/lib/commands/aar/publishLocalAar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAsB;IAC1D,MAAM,KAAK,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEtC,MAAM,YAAY,CAAC;QACjB,KAAK;QACL,UAAU;KACX,CAAC,CAAC;IACH,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,iBAAiB;KAC/B;CACF,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts new file mode 100644 index 000000000..b936afea2 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts @@ -0,0 +1,21 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +import type { RemoteBuildCache } from '@rock-js/tools'; +import { type FingerprintSources } from '@rock-js/tools'; +export interface BuildFlags { + variant: string; + aab?: boolean; + activeArchOnly?: boolean; + tasks?: Array; + extraParams?: Array; + local?: boolean; +} +export declare function buildAndroid(androidProject: AndroidProjectConfig, args: BuildFlags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise; +export declare const options: ({ + name: string; + description: string; + parse?: undefined; +} | { + name: string; + description: string; + parse: (val: string) => string[]; +})[]; diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js new file mode 100644 index 000000000..873eeffbb --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js @@ -0,0 +1,69 @@ +import { colorLink, formatArtifactName, getBinaryPath, logger, outro, parseArgs, relativeToCwd, } from '@rock-js/tools'; +import { findOutputFile } from '../runAndroid/findOutputFile.js'; +import { runGradle } from '../runGradle.js'; +import { toPascalCase } from '../toPascalCase.js'; +export async function buildAndroid(androidProject, args, projectRoot, remoteCacheProvider, fingerprintOptions) { + normalizeArgs(args); + // Use assemble task by default, but bundle if the flag is set + const buildTaskBase = args.aab ? 'bundle' : 'assemble'; + const tasks = args.tasks ?? [`${buildTaskBase}${toPascalCase(args.variant)}`]; + const artifactName = await formatArtifactName({ + platform: 'android', + traits: [args.variant], + root: projectRoot, + fingerprintOptions, + }); + const binaryPath = await getBinaryPath({ + platformName: 'android', + artifactName, + localFlag: args.local, + remoteCacheProvider, + fingerprintOptions, + sourceDir: androidProject.sourceDir, + }); + if (!binaryPath) { + await runGradle({ tasks, androidProject, args, artifactName }); + } + const outputFilePath = binaryPath ?? (await findOutputFile(androidProject, tasks)); + if (outputFilePath) { + logger.log(`Build available at: ${colorLink(relativeToCwd(outputFilePath))}`); + } + outro('Success ๐ŸŽ‰.'); +} +function normalizeArgs(args) { + if (args.tasks && args.variant) { + logger.warn('Both "--tasks" and "--variant" parameters were passed. Using "--tasks" for building the app.'); + } + if (!args.variant) { + args.variant = 'debug'; + } +} +export const options = [ + { + name: '--variant ', + description: `Specify your app's build variant, which is constructed from build type and product flavor, e.g. "debug" or "freeRelease".`, + }, + { + name: '--aab', + description: 'Produces an Android App Bundle (AAB) suited for app stores such as Google Play. If not set, APK is created.', + }, + { + name: '--tasks ', + description: 'Run custom Gradle tasks. Will override the "--variant" and "--bundle" arguments.', + parse: (val) => val.split(','), + }, + { + name: '--active-arch-only', + description: 'Build native libraries only for the current device architecture. Set by default in debug builds and interactive environments.', + }, + { + name: '--extra-params ', + description: 'Custom params passed to gradle build command', + parse: parseArgs, + }, + { + name: '--local', + description: 'Force local build with Gradle wrapper.', + }, +]; +//# sourceMappingURL=buildAndroid.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js.map b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js.map new file mode 100644 index 000000000..3ec0c8f8e --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buildAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/buildAndroid/buildAndroid.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,SAAS,EAET,kBAAkB,EAClB,aAAa,EACb,MAAM,EACN,KAAK,EACL,SAAS,EACT,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAWlD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,cAAoC,EACpC,IAAgB,EAChB,WAAmB,EACnB,mBAAgE,EAChE,kBAAsC;IAEtC,aAAa,CAAC,IAAI,CAAC,CAAC;IACpB,8DAA8D;IAC9D,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;QACtB,IAAI,EAAE,WAAW;QACjB,kBAAkB;KACnB,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;QACrC,YAAY,EAAE,SAAS;QACvB,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,mBAAmB;QACnB,kBAAkB;QAClB,SAAS,EAAE,cAAc,CAAC,SAAS;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,SAAS,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,cAAc,GAClB,UAAU,IAAI,CAAC,MAAM,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC;IAE9D,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,CACR,uBAAuB,SAAS,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB;IACrC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CACT,8FAA8F,CAC/F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,2HAA2H;KACzI;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EACT,6GAA6G;KAChH;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,kFAAkF;QACpF,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;KACvC;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,+HAA+H;KAClI;IACD;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,8CAA8C;QAC3D,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,wCAAwC;KACtD;CACF,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/command.d.ts b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.d.ts new file mode 100644 index 000000000..9dc586b7c --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.d.ts @@ -0,0 +1,3 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +import type { PluginApi } from '@rock-js/config'; +export declare function registerBuildCommand(api: PluginApi, pluginConfig: Partial | undefined): void; diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js new file mode 100644 index 000000000..b16a010cc --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js @@ -0,0 +1,14 @@ +import { getValidProjectConfig } from '../getValidProjectConfig.js'; +import { buildAndroid, options } from './buildAndroid.js'; +export function registerBuildCommand(api, pluginConfig) { + api.registerCommand({ + name: 'build:android', + description: 'Builds your app for Android platform.', + action: async (args) => { + const androidConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig); + await buildAndroid(androidConfig, args, api.getProjectRoot(), await api.getRemoteCacheProvider(), api.getFingerprintOptions()); + }, + options: options, + }); +} +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js.map b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js.map new file mode 100644 index 000000000..2089f8886 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/buildAndroid/command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,UAAU,oBAAoB,CAClC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,uCAAuC;QACpD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,aAAa,GAAG,qBAAqB,CACzC,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;YACF,MAAM,YAAY,CAChB,aAAa,EACb,IAAkB,EAClB,GAAG,CAAC,cAAc,EAAE,EACpB,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,CAC5B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/generateKeystore.d.ts b/packages/platform-android/dist/src/lib/commands/generateKeystore.d.ts new file mode 100644 index 000000000..2d8b9b39e --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/generateKeystore.d.ts @@ -0,0 +1,13 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +import type { PluginApi } from '@rock-js/config'; +export declare function registerCreateKeystoreCommand(api: PluginApi, pluginConfig: Partial | undefined): void; +export declare function generateKeystore(androidProject: AndroidProjectConfig, args: Flags): Promise; +type Flags = { + name?: string; + alias?: string; +}; +export declare const generateKeystoreOptions: { + name: string; + description: string; +}[]; +export {}; diff --git a/packages/platform-android/dist/src/lib/commands/generateKeystore.js b/packages/platform-android/dist/src/lib/commands/generateKeystore.js new file mode 100644 index 000000000..0e65a454a --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/generateKeystore.js @@ -0,0 +1,80 @@ +import path from 'node:path'; +import { color, colorLink, intro, logger, outro, promptGroup, promptText, RockError, spawn, } from '@rock-js/tools'; +import { getValidProjectConfig } from './getValidProjectConfig.js'; +export function registerCreateKeystoreCommand(api, pluginConfig) { + api.registerCommand({ + name: 'create-keystore:android', + description: 'Creates a keystore file for signing Android release builds.', + action: async (args) => { + const androidConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig); + await generateKeystore(androidConfig, args); + }, + options: generateKeystoreOptions, + }); +} +export async function generateKeystore(androidProject, args) { + intro('Generate a keystore file for signing Android release builds.'); + await runKeytool(androidProject, args); + outro('Success ๐ŸŽ‰.'); +} +async function runKeytool(androidProject, args) { + const { name, alias } = await prompts({ name: args.name, alias: args.alias }); + const keystoreOutputPath = path.join(androidProject.sourceDir, androidProject.appName, `${name}.keystore`); + logger.info(`Running "keytool" command. You'll be further prompted for password and extra information.`); + logger.log(''); + try { + // keytool -genkey -v -keystore release.keystore -alias rock-alias -keyalg RSA -keysize 2048 -validity 10000 + await spawn('keytool', [ + '-genkey', + '-v', + '-keystore', + keystoreOutputPath, + '-alias', + alias, + '-keyalg', + 'RSA', + '-keysize', + '2048', + '-validity', + '10000', + ], { stdio: 'inherit' }); + logger.success(`Keystore generated at: ${colorLink(keystoreOutputPath)}`); + logger.warn(`Edit the ${colorLink('~/.gradle/gradle.properties')} or ${colorLink('./android/gradle.properties')} file, and add the following (replace ***** with the correct keystore password):`); + // use console log to make it easy to copy-paste without messing with "|" characters injected by `logger.log` + console.log(color.yellow(` + ROCK_UPLOAD_STORE_FILE=release.keystore + ROCK_UPLOAD_KEY_ALIAS=rock-alias + ROCK_UPLOAD_STORE_PASSWORD=***** + ROCK_UPLOAD_KEY_PASSWORD=*****`)); + } + catch (error) { + throw new RockError(`Failed to generate keystore. Please try manually by following instructions at: ${colorLink('https://reactnative.dev/docs/signed-apk-android')}`, { cause: error.stderr }); + } +} +async function prompts({ name, alias }) { + return promptGroup({ + name: () => name + ? Promise.resolve(name) + : promptText({ + message: 'Provide keystore name', + initialValue: 'release', + }), + alias: () => alias + ? Promise.resolve(alias) + : promptText({ + message: 'Provide keystore alias', + initialValue: 'rock-alias', + }), + }); +} +export const generateKeystoreOptions = [ + { + name: '--name ', + description: 'Name of the keystore file.', + }, + { + name: '--alias ', + description: 'Alias for the key.', + }, +]; +//# sourceMappingURL=generateKeystore.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/generateKeystore.js.map b/packages/platform-android/dist/src/lib/commands/generateKeystore.js.map new file mode 100644 index 000000000..c38b13f99 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/generateKeystore.js.map @@ -0,0 +1 @@ +{"version":3,"file":"generateKeystore.js","sourceRoot":"","sources":["../../../../src/lib/commands/generateKeystore.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.d.ts b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.d.ts new file mode 100644 index 000000000..ab987ec29 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.d.ts @@ -0,0 +1,2 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +export declare function getValidProjectConfig(projectRoot: string, pluginConfig?: Partial): AndroidProjectConfig; diff --git a/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js new file mode 100644 index 000000000..b785053c2 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js @@ -0,0 +1,10 @@ +import { projectConfig } from '@react-native-community/cli-config-android'; +import { RockError } from '@rock-js/tools'; +export function getValidProjectConfig(projectRoot, pluginConfig) { + const androidConfig = projectConfig(projectRoot, pluginConfig); + if (!androidConfig) { + throw new RockError('Android project not found.'); + } + return androidConfig; +} +//# sourceMappingURL=getValidProjectConfig.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js.map b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js.map new file mode 100644 index 000000000..d0a6cf7eb --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getValidProjectConfig.js","sourceRoot":"","sources":["../../../../src/lib/commands/getValidProjectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAE3E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,YAA4C;IAE5C,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC/D,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/adb.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.d.ts new file mode 100644 index 000000000..de1b858a8 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.d.ts @@ -0,0 +1,5 @@ +export declare function getAdbPath(): string; +/** + * Executes the commands needed to get a list of devices from ADB + */ +export declare function getDevices(): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js new file mode 100644 index 000000000..85d25088f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js @@ -0,0 +1,38 @@ +import path from 'node:path'; +import { spawn } from '@rock-js/tools'; +export function getAdbPath() { + return process.env['ANDROID_HOME'] + ? path.join(process.env['ANDROID_HOME'], 'platform-tools', 'adb') + : 'adb'; +} +/** + * Parses the output of the 'adb devices' command + */ +function parseDevicesResult(result) { + if (!result) { + return []; + } + const devices = []; + const lines = result.trim().split(/\r?\n/); + for (let i = 0; i < lines.length; i++) { + const words = lines[i].split(/[ ,\t]+/).filter((w) => w !== ''); + if (words[1] === 'device') { + devices.push(words[0]); + } + } + return devices; +} +/** + * Executes the commands needed to get a list of devices from ADB + */ +export async function getDevices() { + const adbPath = getAdbPath(); + try { + const { output } = await spawn(adbPath, ['devices'], { stdio: 'pipe' }); + return parseDevicesResult(output); + } + catch { + return []; + } +} +//# sourceMappingURL=adb.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js.map new file mode 100644 index 000000000..9e25f1e5f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js.map @@ -0,0 +1 @@ +{"version":3,"file":"adb.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/adb.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAChC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC;QACjE,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAEhE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACxE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/command.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/command.d.ts new file mode 100644 index 000000000..009106a88 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/command.d.ts @@ -0,0 +1,3 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +import type { PluginApi } from '@rock-js/config'; +export declare function registerRunCommand(api: PluginApi, pluginConfig: Partial | undefined): void; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/command.js b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js new file mode 100644 index 000000000..ada9aef42 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js @@ -0,0 +1,18 @@ +import { intro, outro } from '@rock-js/tools'; +import { getValidProjectConfig } from '../getValidProjectConfig.js'; +import { runAndroid, runOptions } from './runAndroid.js'; +export function registerRunCommand(api, pluginConfig) { + api.registerCommand({ + name: 'run:android', + description: 'Builds your app and starts it on a connected Android emulator or a device.', + action: async (args) => { + intro('Running Android app'); + const projectRoot = api.getProjectRoot(); + const androidConfig = getValidProjectConfig(projectRoot, pluginConfig); + await runAndroid(androidConfig, args, projectRoot, await api.getRemoteCacheProvider(), api.getFingerprintOptions(), api.getBundlerStart(), api.getReactNativeVersion(), api.getReactNativePath(), api.getPlatforms()); + outro('Success ๐ŸŽ‰.'); + }, + options: runOptions, + }); +} +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/command.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js.map new file mode 100644 index 000000000..c9048380a --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,UAAU,kBAAkB,CAChC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,4EAA4E;QAC9E,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,qBAAqB,CAAC,CAAC;YAC7B,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,UAAU,CACd,aAAa,EACb,IAAa,EACb,WAAW,EACX,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,EAC3B,GAAG,CAAC,eAAe,EAAE,EACrB,GAAG,CAAC,qBAAqB,EAAE,EAC3B,GAAG,CAAC,kBAAkB,EAAE,EACxB,GAAG,CAAC,YAAY,EAAE,CACnB,CAAC;YACF,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.d.ts new file mode 100644 index 000000000..8b9885303 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.d.ts @@ -0,0 +1,2 @@ +import type { AndroidProject } from './runAndroid.js'; +export declare function findOutputFile(androidProject: AndroidProject, tasks: string[], device?: string): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js new file mode 100644 index 000000000..2938c2975 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js @@ -0,0 +1,67 @@ +import { existsSync } from 'node:fs'; +import { logger, spawn } from '@rock-js/tools'; +import { getAdbPath } from './adb.js'; +export async function findOutputFile(androidProject, tasks, device) { + const { appName, sourceDir } = androidProject; + const selectedTask = tasks.find((t) => t.startsWith('install') || + t.startsWith('assemble') || + t.startsWith('bundle')); + if (!selectedTask) { + return false; + } + // handle if selected task includes build flavour as well, eg. installProductionDebug should create ['production','debug'] array + const variantFromSelectedTask = selectedTask + ?.replace('install', '') + ?.replace('assemble', '') + ?.replace('bundle', '') + .split(/(?=[A-Z])/); + // create path to output file, eg. `production/debug` + const variantPath = variantFromSelectedTask?.join('/')?.toLowerCase(); + // create output file name, eg. `production-debug` + const variantAppName = variantFromSelectedTask?.join('-')?.toLowerCase(); + const apkOrBundle = selectedTask?.includes('bundle') ? 'bundle' : 'apk'; + const buildDirectory = `${sourceDir}/${appName}/build/outputs/${apkOrBundle}/${variantPath}`; + const outputFile = await getInstallOutputFileName(appName, variantAppName, buildDirectory, apkOrBundle === 'apk' ? 'apk' : 'aab', device); + return outputFile ? `${buildDirectory}/${outputFile}` : undefined; +} +async function getInstallOutputFileName(appName, variant, buildDirectory, apkOrAab, device) { + const availableCPUs = await getAvailableCPUs(device); + // check if there is an apk file like app-armeabi-v7a-debug.apk + for (const availableCPU of availableCPUs.concat('universal')) { + const outputFile = `${appName}-${availableCPU}-${variant}.${apkOrAab}`; + if (existsSync(`${buildDirectory}/${outputFile}`)) { + return outputFile; + } + } + // check if there is a default file like app-debug.apk + const outputFile = `${appName}-${variant}.${apkOrAab}`; + if (existsSync(`${buildDirectory}/${outputFile}`)) { + return outputFile; + } + logger.debug('Could not find the output file:', { + buildDirectory, + outputFile, + appName, + variant, + apkOrAab, + }); + return undefined; +} +/** + * Gets available CPUs of devices from ADB + */ +async function getAvailableCPUs(device) { + const adbPath = getAdbPath(); + try { + const adbArgs = ['shell', 'getprop', 'ro.product.cpu.abilist']; + if (device) { + adbArgs.unshift('-s', device); + } + const { output } = await spawn(adbPath, adbArgs, { stdio: 'pipe' }); + return output.trim().split(','); + } + catch { + return []; + } +} +//# sourceMappingURL=findOutputFile.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js.map new file mode 100644 index 000000000..a66ffcd38 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findOutputFile.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/findOutputFile.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts new file mode 100644 index 000000000..abde41d81 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts @@ -0,0 +1,7 @@ +export type DeviceData = { + deviceId: string | undefined; + readableName: string; + connected: boolean; + type: 'emulator' | 'phone'; +}; +export declare function listAndroidDevices(): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js new file mode 100644 index 000000000..316286aaf --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js @@ -0,0 +1,69 @@ +import os from 'node:os'; +import { spawn } from '@rock-js/tools'; +import { getAdbPath, getDevices } from './adb.js'; +import { getEmulators } from './tryLaunchEmulator.js'; +/** + * + * @param deviceId string + * @returns name of Android emulator + */ +async function getEmulatorName(deviceId) { + const adbPath = getAdbPath(); + const { output } = await spawn(adbPath, ['-s', deviceId, 'emu', 'avd', 'name'], { stdio: 'pipe' }); + // 1st line should get us emu name + return output + .split(os.EOL)[0] + .replace(/(\r\n|\n|\r)/gm, '') + .trim(); +} +/** + * + * @param deviceId string + * @returns Android device name in readable format + */ +async function getPhoneName(deviceId) { + const adbPath = getAdbPath(); + const { output } = await spawn(adbPath, ['-s', deviceId, 'shell', 'getprop', 'ro.product.model'], { stdio: 'pipe' }); + return output.replace(/\[ro\.product\.model\]:\s*\[(.*)\]/, '$1').trim(); +} +export async function listAndroidDevices() { + const devices = await getDevices(); + let allDevices = []; + for (const deviceId of devices) { + if (deviceId.includes('emulator')) { + const emulatorData = { + deviceId, + readableName: await getEmulatorName(deviceId), + connected: true, + type: 'emulator', + }; + allDevices = [...allDevices, emulatorData]; + } + else { + const phoneData = { + deviceId, + readableName: await getPhoneName(deviceId), + type: 'phone', + connected: true, + }; + allDevices = [...allDevices, phoneData]; + } + } + const emulators = await getEmulators(); + // Find not booted ones: + emulators.forEach((emulatorName) => { + // skip those already booted + if (allDevices.some((device) => device.readableName === emulatorName)) { + return; + } + const emulatorData = { + deviceId: undefined, + readableName: emulatorName, + type: 'emulator', + connected: false, + }; + allDevices = [...allDevices, emulatorData]; + }); + return allDevices; +} +//# sourceMappingURL=listAndroidDevices.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map new file mode 100644 index 000000000..701abf075 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listAndroidDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAStD;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAAC,QAAgB;IAC7C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EACtC,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;IAEF,kCAAkC;IAClC,OAAO,MAAM;SACV,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAChB,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,EACxD,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,IAAI,UAAU,GAAsB,EAAE,CAAC;IAEvC,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,MAAM,YAAY,GAAe;gBAC/B,QAAQ;gBACR,YAAY,EAAE,MAAM,eAAe,CAAC,QAAQ,CAAC;gBAC7C,SAAS,EAAE,IAAI;gBACf,IAAI,EAAE,UAAU;aACjB,CAAC;YACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAe;gBAC5B,QAAQ;gBACR,YAAY,EAAE,MAAM,YAAY,CAAC,QAAQ,CAAC;gBAC1C,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,IAAI;aAChB,CAAC;YACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,wBAAwB;IACxB,SAAS,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE;QACjC,4BAA4B;QAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,EAAE,CAAC;YACtE,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAe;YAC/B,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,YAAY;YAC1B,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC;QACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts new file mode 100644 index 000000000..0e281eb4f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts @@ -0,0 +1,7 @@ +type User = { + id: string; + name: string; +}; +export declare function checkUsers(device: string): Promise; +export declare function promptForUser(deviceId: string): Promise; +export {}; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js new file mode 100644 index 000000000..996021669 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js @@ -0,0 +1,42 @@ +import { logger, promptSelect, spawn } from '@rock-js/tools'; +import { getAdbPath } from './adb.js'; +const regex = new RegExp(/^\s*UserInfo\{(?\d+):(?.*):(?[0-9a-f]*)}/); +export async function checkUsers(device) { + const adbPath = getAdbPath(); + const adbArgs = ['-s', device, 'shell', 'pm', 'list', 'users']; + try { + const { stdout, stderr } = await spawn(adbPath, adbArgs, { stdio: 'pipe' }); + if (stderr) { + logger.debug(`Failed to check users on the device. ${stderr}`, 1); + return []; + } + const lines = stdout.split('\n'); + const users = []; + for (const line of lines) { + const res = regex.exec(line); + if (res?.groups) { + users.push({ id: res.groups['userId'], name: res.groups['userName'] }); + } + } + return users; + } + catch (error) { + logger.debug(`Unexpected error while checking users on the device. Continuing without user selection. Error details: ${error.message}.`, 1); + return []; + } +} +export async function promptForUser(deviceId) { + const users = await checkUsers(deviceId); + if (users.length > 1) { + const selectedUser = await promptSelect({ + message: 'Which user profile would you like to launch your app into?', + options: users.map((user) => ({ + label: user.name, + value: user, + })), + }); + return selectedUser; + } + return null; +} +//# sourceMappingURL=listAndroidUsers.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map new file mode 100644 index 000000000..c3a6e0ef7 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listAndroidUsers.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidUsers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOtC,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,uEAAuE,CACxE,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC7C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAE5E,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,wCAAwC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YAClE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,EAAE,CAAC;QAEjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,0GACG,KAA6B,CAAC,OACjC,GAAG,EACH,CAAC,CACF,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC;YACtC,OAAO,EAAE,4DAA4D;YACrE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC5B,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.d.ts new file mode 100644 index 000000000..81eecd913 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.d.ts @@ -0,0 +1,36 @@ +import type { AndroidProjectConfig, Config } from '@react-native-community/cli-types'; +import type { StartDevServerArgs } from '@rock-js/config'; +import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools'; +import type { BuildFlags } from '../buildAndroid/buildAndroid.js'; +export interface Flags extends BuildFlags { + appId: string; + appIdSuffix: string; + mainActivity?: string; + port: string; + device?: string; + binaryPath?: string; + user?: string; + local?: boolean; + devServer?: boolean; + clientLogs?: boolean; +} +export type AndroidProject = NonNullable; +/** + * Starts the app on a connected Android emulator or device. + */ +export declare function runAndroid(androidProject: AndroidProjectConfig, args: Flags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources, startDevServer: (options: StartDevServerArgs) => void, reactNativeVersion: string, reactNativePath: string, platforms: { + [platform: string]: object; +}): Promise; +export declare const runOptions: ({ + name: string; + description: string; + parse?: undefined; +} | { + name: string; + description: string; + parse: (val: string) => string[]; +} | { + name: string; + description: string; + default: string; +})[]; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js new file mode 100644 index 000000000..410a54c0b --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js @@ -0,0 +1,203 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { color, formatArtifactName, isInteractive, logger, promptSelect, RockError, spinner, } from '@rock-js/tools'; +import { getBinaryPath } from '@rock-js/tools'; +import { options } from '../buildAndroid/buildAndroid.js'; +import { runGradle } from '../runGradle.js'; +import { toPascalCase } from '../toPascalCase.js'; +import { getDevices } from './adb.js'; +import { listAndroidDevices } from './listAndroidDevices.js'; +import { tryInstallAppOnDevice } from './tryInstallAppOnDevice.js'; +import { tryLaunchAppOnDevice } from './tryLaunchAppOnDevice.js'; +import { tryLaunchEmulator } from './tryLaunchEmulator.js'; +/** + * Starts the app on a connected Android emulator or device. + */ +export async function runAndroid(androidProject, args, projectRoot, remoteCacheProvider, fingerprintOptions, startDevServer, reactNativeVersion, reactNativePath, platforms) { + const startDevServerHelper = () => { + if (args.devServer) { + logger.info('Starting dev server...'); + startDevServer({ + root: projectRoot, + reactNativePath, + reactNativeVersion, + platforms, + args: { + interactive: isInteractive(), + clientLogs: args.clientLogs ?? true, + }, + }); + } + }; + normalizeArgs(args, projectRoot); + const devices = await listAndroidDevices(); + const device = await selectDevice(devices, args); + const mainTaskType = device ? 'assemble' : 'install'; + const tasks = args.tasks ?? [`${mainTaskType}${toPascalCase(args.variant)}`]; + const artifactName = await formatArtifactName({ + platform: 'android', + traits: [args.variant], + root: projectRoot, + fingerprintOptions, + }); + const binaryPath = await getBinaryPath({ + platformName: 'android', + artifactName, + binaryPathFlag: args.binaryPath, + localFlag: args.local, + remoteCacheProvider, + fingerprintOptions, + sourceDir: androidProject.sourceDir, + }); + if (device) { + if (!(await getDevices()).find((d) => d === device.deviceId)) { + // deviceId is undefined until it's launched, hence overwriting it here + device.deviceId = await tryLaunchEmulator(device.readableName); + } + if (device.deviceId) { + if (!binaryPath) { + await runGradle({ tasks, androidProject, args, artifactName }); + } + await runOnDevice({ device, androidProject, args, tasks, binaryPath }); + } + } + else { + if ((await getDevices()).length === 0) { + if (isInteractive()) { + await selectAndLaunchDevice(); + } + else { + logger.debug('No booted devices or emulators found. Launching first available emulator.'); + await tryLaunchEmulator(); + } + } + if (!binaryPath) { + await runGradle({ tasks, androidProject, args, artifactName }); + } + for (const device of await listAndroidDevices()) { + if (device.connected) { + await runOnDevice({ device, androidProject, args, tasks, binaryPath }); + } + } + } + startDevServerHelper(); +} +async function selectAndLaunchDevice() { + const allDevices = await listAndroidDevices(); + const device = await promptForDeviceSelection(allDevices); + if (!device.connected) { + await tryLaunchEmulator(device.readableName); + // list devices once again when emulator is booted + const allDevices = await listAndroidDevices(); + const newDevice = allDevices.find((d) => d.readableName === device.readableName) ?? device; + return newDevice; + } + return device; +} +async function selectDevice(devices, args) { + const device = args.device ? matchingDevice(devices, args.device) : undefined; + if (!device && args.device) { + logger.warn(`No devices or emulators found matching "${args.device}". Using available one instead.`); + } + return device; +} +function matchingDevice(devices, deviceArg) { + const deviceByName = devices.find((device) => device.readableName === deviceArg); + const deviceById = devices.find((d) => d.deviceId === deviceArg); + return deviceByName || deviceById; +} +function normalizeArgs(args, projectRoot) { + if (args.tasks && args.variant) { + logger.warn('Both "--tasks" and "--variant" parameters were passed. Using "--tasks" for building the app.'); + } + if (!args.variant) { + args.variant = 'debug'; + } + // turn on activeArchOnly for debug to speed up local builds + if (args.variant !== 'release' && + !args.variant.endsWith('Release') && + args.activeArchOnly === undefined && + isInteractive()) { + args.activeArchOnly = true; + } + if (args.binaryPath) { + if (args.tasks) { + throw new RockError('Both "--binary-path" and "--tasks" flags were specified, which are incompatible. Please specify only one.'); + } + args.binaryPath = path.isAbsolute(args.binaryPath) + ? args.binaryPath + : path.join(projectRoot, args.binaryPath); + if (args.binaryPath && !fs.existsSync(args.binaryPath)) { + throw new RockError(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`); + } + } +} +async function promptForDeviceSelection(allDevices) { + if (!allDevices.length) { + throw new RockError('No devices and/or emulators connected. Please create emulator with Android Studio or connect Android device.'); + } + const selected = await promptSelect({ + message: 'Select the device / emulator you want to use', + options: allDevices.map((d) => ({ + label: `${d.readableName}${d.type === 'phone' ? ' - (physical device)' : ''}${d.connected ? ' (connected)' : ''}`, + value: d, + })), + }); + return selected; +} +async function runOnDevice({ device, androidProject, args, tasks, binaryPath, }) { + const loader = spinner(); + loader.start('Installing the app'); + await tryInstallAppOnDevice(device, androidProject, args, tasks, binaryPath); + loader.message('Launching the app'); + const { applicationIdWithSuffix } = await tryLaunchAppOnDevice(device, androidProject, args); + if (applicationIdWithSuffix) { + loader.stop(`Installed and launched the app on ${color.bold(device.readableName)}`); + } + else { + loader.stop(`Failed: installing and launching the app on ${color.bold(device.readableName)}`); + } +} +export const runOptions = [ + ...options, + { + name: '--port ', + description: 'Part for packager.', + default: process.env['RCT_METRO_PORT'] || '8081', + }, + { + name: '--app-id ', + description: 'Specify an applicationId to launch after build. If not specified, `package` from AndroidManifest.xml will be used.', + default: '', + }, + { + name: '--app-id-suffix ', + description: 'Specify an applicationIdSuffix to launch after build.', + default: '', + }, + { + name: '--main-activity ', + description: 'Name of the activity to start', + }, + { + name: '--device ', + description: 'Explicitly set the device or emulator to use by name or ID (if launched).', + }, + { + name: '--binary-path ', + description: 'Path relative to project root where pre-built .apk binary lives.', + }, + { + name: '--user ', + description: 'Id of the User Profile you want to install the app on.', + }, + { + name: '--client-logs', + description: 'Enable client logs in dev server.', + }, + { + name: '--dev-server', + description: 'Automatically start a dev server (bundler) after building the app.', + }, +]; +//# sourceMappingURL=runAndroid.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js.map new file mode 100644 index 000000000..635a094dc --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/runAndroid.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts new file mode 100644 index 000000000..d0d332b5c --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts @@ -0,0 +1,3 @@ +import type { DeviceData } from './listAndroidDevices.js'; +import type { AndroidProject, Flags } from './runAndroid.js'; +export declare function tryInstallAppOnDevice(device: DeviceData, androidProject: AndroidProject, args: Flags, tasks: string[], binaryPath: string | undefined): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js new file mode 100644 index 000000000..4fc85dc1d --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js @@ -0,0 +1,63 @@ +import { color, logger, RockError, spawn, } from '@rock-js/tools'; +import { getAdbPath } from './adb.js'; +import { findOutputFile } from './findOutputFile.js'; +import { promptForUser } from './listAndroidUsers.js'; +export async function tryInstallAppOnDevice(device, androidProject, args, tasks, binaryPath) { + let deviceId; + if (!device.deviceId) { + logger.debug(`No "deviceId" for ${device}, skipping launching the app`); + return; + } + else { + deviceId = device.deviceId; + } + logger.debug(`Connected to device ${color.bold(device.readableName)}`); + let pathToApk; + if (!binaryPath) { + const outputFilePath = await findOutputFile(androidProject, tasks, deviceId); + if (!outputFilePath) { + logger.warn("Skipping installation because there's no build output file."); + return; + } + pathToApk = outputFilePath; + } + else { + pathToApk = binaryPath; + } + const adbArgs = ['-s', deviceId, 'install', '-r', '-d']; + const user = args.user ?? (await promptForUser(deviceId))?.id; + if (user !== undefined) { + adbArgs.push('--user', `${user}`); + } + adbArgs.push(pathToApk); + const adbPath = getAdbPath(); + try { + await spawn(adbPath, adbArgs, { stdio: 'pipe' }); + } + catch (error) { + logger.debug(`Failed: Installing the app`, error); + const errorMessage = error.stderr || error.stdout; + const isInsufficientStorage = errorMessage.includes('INSTALL_FAILED_INSUFFICIENT_STORAGE'); + const isUpdateIncompatible = errorMessage.includes('INSTALL_FAILED_UPDATE_INCOMPATIBLE'); + if (isInsufficientStorage || isUpdateIncompatible) { + try { + const message = isInsufficientStorage + ? 'Recovery: Trying to re-install the app due to insufficient storage' + : 'Recovery: Trying to re-install the app due to binary incompatibility'; + logger.debug(message); + const appId = args.appId || androidProject.applicationId; + await spawn(adbPath, ['-s', deviceId, 'uninstall', appId]); + await spawn(adbPath, adbArgs); + logger.debug(`Recovery: Re-installed the app`); + return; + } + catch (error) { + const errorMessage = error.stderr || + error.stdout; + throw new RockError(`The "adb" command failed with: ${errorMessage}.`); + } + } + throw new RockError(`The "adb" command failed with: ${errorMessage}.`); + } +} +//# sourceMappingURL=tryInstallAppOnDevice.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map new file mode 100644 index 000000000..f81b0dcb9 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryInstallAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryInstallAppOnDevice.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts new file mode 100644 index 000000000..68f7e5371 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts @@ -0,0 +1,7 @@ +import type { DeviceData } from './listAndroidDevices.js'; +import type { AndroidProject, Flags } from './runAndroid.js'; +export declare function tryLaunchAppOnDevice(device: DeviceData, androidProject: AndroidProject, args: Flags): Promise<{ + applicationIdWithSuffix?: undefined; +} | { + applicationIdWithSuffix: string; +}>; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js new file mode 100644 index 000000000..158178a26 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js @@ -0,0 +1,51 @@ +import { logger, RockError, spawn } from '@rock-js/tools'; +import { getAdbPath } from './adb.js'; +import { tryRunAdbReverse } from './tryRunAdbReverse.js'; +export async function tryLaunchAppOnDevice(device, androidProject, args) { + let deviceId; + if (!device.deviceId) { + logger.debug(`No "deviceId" for ${device}, skipping launching the app`); + return {}; + } + else { + deviceId = device.deviceId; + } + await tryRunAdbReverse(args.port, deviceId); + const { appId, appIdSuffix } = args; + const { packageName, mainActivity, applicationId } = androidProject; + const applicationIdWithSuffix = [appId || applicationId, appIdSuffix] + .filter(Boolean) + .join('.'); + const activity = args.mainActivity ?? mainActivity; + const activityToLaunch = activity.startsWith(packageName) || + (!activity.startsWith('.') && activity.includes('.')) + ? activity + : activity.startsWith('.') + ? [packageName, activity].join('') + : [packageName, activity].filter(Boolean).join('.'); + // Here we're using the same flags as Android Studio to launch the app + const adbArgs = [ + 'shell', + 'am', + 'start', + '-n', + `${applicationIdWithSuffix}/${activityToLaunch}`, + '-a', + 'android.intent.action.MAIN', + '-c', + 'android.intent.category.LAUNCHER', + ]; + adbArgs.unshift('-s', deviceId); + const adbPath = getAdbPath(); + logger.debug(`Running ${adbPath} ${adbArgs.join(' ')}.`); + try { + await spawn(adbPath, adbArgs); + } + catch (error) { + throw new RockError(`Failed to launch the app on ${device.readableName}`, { + cause: error.stderr, + }); + } + return { applicationIdWithSuffix }; +} +//# sourceMappingURL=tryLaunchAppOnDevice.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map new file mode 100644 index 000000000..8d4d2d13e --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryLaunchAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAkB,EAClB,cAA8B,EAC9B,IAAW;IAEX,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,qBAAqB,MAAM,8BAA8B,CAC1D,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;IAEpE,MAAM,uBAAuB,GAAG,CAAC,KAAK,IAAI,aAAa,EAAE,WAAW,CAAC;SAClE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;IAEnD,MAAM,gBAAgB,GACpB,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;QAChC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1D,sEAAsE;IACtE,MAAM,OAAO,GAAG;QACd,OAAO;QACP,IAAI;QACJ,OAAO;QACP,IAAI;QACJ,GAAG,uBAAuB,IAAI,gBAAgB,EAAE;QAChD,IAAI;QACJ,4BAA4B;QAC5B,IAAI;QACJ,kCAAkC;KACnC,CAAC;IAEF,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,WAAW,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,EAAE;YACxE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACrC,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts new file mode 100644 index 000000000..210dea110 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts @@ -0,0 +1,2 @@ +export declare const getEmulators: () => Promise; +export declare function tryLaunchEmulator(name?: string): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js new file mode 100644 index 000000000..313c2af54 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js @@ -0,0 +1,120 @@ +import os from 'node:os'; +import { color, RockError, spawn, spinner } from '@rock-js/tools'; +import { getAdbPath, getDevices } from './adb.js'; +const emulatorCommand = process.env['ANDROID_HOME'] + ? `${process.env['ANDROID_HOME']}/emulator/emulator` + : 'emulator'; +export const getEmulators = async () => { + try { + const { output } = await spawn(emulatorCommand, ['-list-avds'], { + stdio: 'pipe', + }); + // The `name` is AVD ID which is expected to not contain whitespace. + // The `emulator` command, however, can occasionally return verbose + // information about crashes or similar. Hence filtering out anything + // that has basic whitespace. + return output + .split(os.EOL) + .filter((name) => name !== '' && !name.includes(' ')); + } + catch { + return []; + } +}; +const launchEmulator = async ({ emulatorName, port, onConnected, }) => { + const manualCommand = `${emulatorCommand} @${emulatorName}`; + const cp = spawn(emulatorCommand, [`@${emulatorName}`, '-port', `${port}`], { + detached: true, + stdio: 'ignore', + }); + (await cp.nodeChildProcess).unref(); + const timeout = 120; + return new Promise((resolve, reject) => { + const bootCheckInterval = setInterval(async () => { + const devices = await getDevices(); + const connected = port + ? devices.find((d) => d.includes(`${port}`)) + : false; + if (connected) { + onConnected(); + if (await isEmulatorBooted(connected)) { + cleanup(); + resolve(connected); + } + } + }, 1000); + // Reject command after timeout + const rejectTimeout = setTimeout(() => { + stopWaitingAndReject(`It took too long to start and connect with Android emulator: ${emulatorName}. You can try starting the emulator manually from the terminal with: ${manualCommand}`); + }, timeout * 1000); + const cleanup = () => { + clearTimeout(rejectTimeout); + clearInterval(bootCheckInterval); + }; + const stopWaitingAndReject = (message) => { + cleanup(); + reject(new Error(message)); + }; + cp.nodeChildProcess.catch((error) => { + stopWaitingAndReject(error); + }); + }); +}; +const defaultPort = 5552; +async function getAvailableDevicePort(port = defaultPort) { + /** + * The default value is 5554 for the first virtual device instance running on your machine. A virtual device normally occupies a pair of adjacent ports: a console port and an adb port. The console of the first virtual device running on a particular machine uses console port 5554 and adb port 5555. Subsequent instances use port numbers increasing by two. For example, 5556/5557, 5558/5559, and so on. The range is 5554 to 5682, allowing for 64 concurrent virtual devices. + */ + const devices = await getDevices(); + if (port > 5682) { + throw new RockError('Failed to launch emulator'); + } + if (devices.some((d) => d.includes(port.toString()))) { + return await getAvailableDevicePort(port + 2); + } + return port; +} +export async function tryLaunchEmulator(name) { + const port = await getAvailableDevicePort(); + const loader = spinner(); + loader.start(`Looking for available emulators"`); + const emulators = await getEmulators(); + const emulatorName = name ?? emulators[0]; + const displayEmulatorName = color.bold(emulatorName); + let deviceId; + if (emulators.length > 0) { + try { + loader.message(`Launching emulator ${displayEmulatorName}`); + deviceId = await launchEmulator({ + emulatorName, + port, + onConnected: () => { + loader.message(`Emulator ${color.bold(emulatorName)} is connected. Waiting for boot`); + }, + }); + loader.stop(`Launched ${displayEmulatorName} emulator.`); + } + catch (error) { + loader.stop(`Failed to launch ${displayEmulatorName} emulator. ${error.message}`, 1); + } + } + else { + loader.stop('No emulators found as an output of `emulator -list-avds`. Please launch an emulator manually or connect a device', 1); + } + return deviceId; +} +/** + * Check if emulator is booted + */ +async function isEmulatorBooted(device) { + const adbPath = getAdbPath(); + const adbArgs = ['-s', device, 'shell', 'getprop', 'sys.boot_completed']; + try { + const { output } = await spawn(adbPath, adbArgs, { stdio: 'pipe' }); + return output.trim() === '1'; + } + catch { + return false; + } +} +//# sourceMappingURL=tryLaunchEmulator.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map new file mode 100644 index 000000000..d3bd94f07 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryLaunchEmulator.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchEmulator.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts new file mode 100644 index 000000000..398200cfc --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts @@ -0,0 +1 @@ +export declare function tryRunAdbReverse(packagerPort: number | string, device: string): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js new file mode 100644 index 000000000..361c8812f --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js @@ -0,0 +1,21 @@ +import { logger, RockError, spawn } from '@rock-js/tools'; +import { getAdbPath } from './adb.js'; +// Runs ADB reverse tcp:8081 tcp:8081 to allow loading the jsbundle from the packager +export async function tryRunAdbReverse(packagerPort, device) { + try { + const adbPath = getAdbPath(); + const adbArgs = [ + '-s', + device, + 'reverse', + `tcp:${packagerPort}`, + `tcp:${packagerPort}`, + ]; + logger.debug(`Connecting "${device}" to the development server`); + await spawn(adbPath, adbArgs); + } + catch (error) { + throw new RockError(`Failed to connect "${device}" to development server using "adb reverse"`, { cause: error.stderr }); + } +} +//# sourceMappingURL=tryRunAdbReverse.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map new file mode 100644 index 000000000..f9b0a29e9 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryRunAdbReverse.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryRunAdbReverse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA6B,EAC7B,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG;YACd,IAAI;YACJ,MAAM;YACN,SAAS;YACT,OAAO,YAAY,EAAE;YACrB,OAAO,YAAY,EAAE;SACtB,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,6BAA6B,CAAC,CAAC;QACjE,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,sBAAsB,MAAM,6CAA6C,EACzE,EAAE,KAAK,EAAG,KAAyB,CAAC,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runGradle.d.ts b/packages/platform-android/dist/src/lib/commands/runGradle.d.ts new file mode 100644 index 000000000..6a7255880 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runGradle.d.ts @@ -0,0 +1,18 @@ +import type { AarProject } from './aar/packageAar.js'; +import type { BuildFlags } from './buildAndroid/buildAndroid.js'; +import type { AndroidProject, Flags } from './runAndroid/runAndroid.js'; +type RunGradleAarArgs = { + tasks: string[]; + aarProject: AarProject; + variant?: string; +}; +export type RunGradleArgs = { + tasks: string[]; + androidProject: AndroidProject; + args: BuildFlags | Flags; + artifactName: string; +}; +export declare function runGradle({ tasks, androidProject, args, artifactName, }: RunGradleArgs): Promise; +export declare function runGradleAar({ tasks, aarProject, variant, }: RunGradleAarArgs): Promise; +export declare function getGradleWrapper(): "gradlew.bat" | "./gradlew"; +export {}; diff --git a/packages/platform-android/dist/src/lib/commands/runGradle.js b/packages/platform-android/dist/src/lib/commands/runGradle.js new file mode 100644 index 000000000..0ac455c66 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runGradle.js @@ -0,0 +1,124 @@ +import { color, logger, RockError, saveLocalBuildCache, spawn, spinner, } from '@rock-js/tools'; +import { getAdbPath, getDevices } from './runAndroid/adb.js'; +import { findOutputFile } from './runAndroid/findOutputFile.js'; +const getCleanedErrorMessage = (error) => { + return error.stderr + .split('\n') + .filter((line) => !gradleLinesToRemove.some((l) => line.includes(l))) + .join('\n') + .trim(); +}; +export async function runGradle({ tasks, androidProject, args, artifactName, }) { + const humanReadableTasks = tasks.join(', '); + const { appId, appIdSuffix } = args; + const { applicationId } = androidProject; + const applicationIdWithSuffix = [appId || applicationId, appIdSuffix] + .filter(Boolean) + .join('.'); + logger.log(`Build Settings: +App ID ${color.bold(color.blue(applicationIdWithSuffix))} +Variant ${color.bold(args.variant)} +Tasks ${color.bold(humanReadableTasks)}`); + const loader = spinner({ indicator: 'timer' }); + const message = `Building the app`; + loader.start(message); + const gradleArgs = getTaskNames(androidProject.appName, tasks); + gradleArgs.push('-x', 'lint'); + if (args.extraParams) { + gradleArgs.push(...args.extraParams); + } + if ('port' in args && args.port != null) { + gradleArgs.push('-PreactNativeDevServerPort=' + args.port); + } + if (args.activeArchOnly) { + const devices = await getDevices(); + const cpus = await Promise.all(devices.map(getCPU)); + const architectures = cpus.filter((arch, index, array) => arch != null && array.indexOf(arch) === index); + if (architectures.length > 0) { + gradleArgs.push('-PreactNativeArchitectures=' + architectures.join(',')); + } + } + const gradleWrapper = getGradleWrapper(); + try { + await spawn(gradleWrapper, gradleArgs, { cwd: androidProject.sourceDir }); + loader.stop(`Built the app`); + } + catch (error) { + loader.stop('Failed to build the app'); + const cleanedErrorMessage = getCleanedErrorMessage(error); + if (cleanedErrorMessage) { + logger.error(cleanedErrorMessage); + } + const hints = getErrorHints(error.stdout ?? ''); + throw new RockError(hints || + 'Failed to build the app. See the error above for details from Gradle.'); + } + const outputFilePath = await findOutputFile(androidProject, tasks); + if (outputFilePath) { + saveLocalBuildCache(artifactName, outputFilePath); + } +} +export async function runGradleAar({ tasks, aarProject, variant, }) { + const loader = spinner({ indicator: 'timer' }); + const message = variant + ? `Building the AAR with Gradle in ${variant} build variant` + : 'Publishing the AAR'; + loader.start(message); + const gradleArgs = getTaskNames(aarProject.moduleName, tasks); + gradleArgs.push('-x', 'lint'); + const gradleWrapper = getGradleWrapper(); + try { + logger.debug(`Running ${gradleWrapper} ${gradleArgs.join(' ')}.`); + await spawn(gradleWrapper, gradleArgs, { cwd: aarProject.sourceDir }); + loader.stop(variant + ? `Built the AAR in ${variant} build variant.` + : 'Published the AAR to local maven (~/.m2/repository)'); + } + catch (error) { + loader.stop(`Failed to ${variant ? 'build' : 'publish'} the AAR`); + const cleanedErrorMessage = getCleanedErrorMessage(error); + if (cleanedErrorMessage) { + logger.error(cleanedErrorMessage); + } + const hints = getErrorHints(error.stdout ?? ''); + throw new RockError(hints || + `Failed to ${variant ? 'build' : 'publish'} the AAR. See the error above for details from Gradle.`, { cause: error.stderr }); + } +} +function getErrorHints(output) { + const signingMessage = output.includes('validateSigningRelease FAILED') + ? `Hint: You can run "${color.bold('rock create-keystore:android')}" to create a keystore file.` + : ''; + return signingMessage; +} +const gradleLinesToRemove = [ + 'FAILURE: Build failed with an exception.', + '* Try:', + '> Run with --stacktrace option to get the stack trace.', + '> Run with --info or --debug option to get more log output.', + '> Run with --scan to get full insights.', + '> Get more help at [undefined](https://help.gradle.org).', + '> Get more help at https://help.gradle.org.', + 'BUILD FAILED', +]; +export function getGradleWrapper() { + return process.platform.startsWith('win') ? 'gradlew.bat' : './gradlew'; +} +function getTaskNames(appName, tasks) { + return tasks.map((task) => `${appName}:${task}`); +} +/** + * Gets the CPU architecture of a device from ADB + */ +async function getCPU(device) { + const adbPath = getAdbPath(); + try { + const { output } = await spawn(adbPath, ['-s', device, 'shell', 'getprop', 'ro.product.cpu.abi'], { stdio: 'pipe' }); + const cpus = output.trim(); + return cpus.length > 0 ? cpus : null; + } + catch { + return null; + } +} +//# sourceMappingURL=runGradle.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/runGradle.js.map b/packages/platform-android/dist/src/lib/commands/runGradle.js.map new file mode 100644 index 000000000..d3d2465b2 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/runGradle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runGradle.js","sourceRoot":"","sources":["../../../../src/lib/commands/runGradle.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.d.ts b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.d.ts new file mode 100644 index 000000000..247b9ec1d --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.d.ts @@ -0,0 +1,8 @@ +type BuildJsBundleOptions = { + bundleOutputPath: string; + assetsDestPath: string; + sourcemapOutputPath: string; + useHermes?: boolean; +}; +export declare function buildJsBundle(options: BuildJsBundleOptions): Promise; +export {}; diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js new file mode 100644 index 000000000..f9b2ab0fd --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js @@ -0,0 +1,58 @@ +import fs from 'node:fs'; +import { logger, runHermes, spawn } from '@rock-js/tools'; +export async function buildJsBundle(options) { + if (fs.existsSync(options.bundleOutputPath)) { + fs.unlinkSync(options.bundleOutputPath); + logger.debug('Removed existing JS bundle:', options.bundleOutputPath); + } + if (fs.existsSync(options.sourcemapOutputPath)) { + fs.unlinkSync(options.sourcemapOutputPath); + logger.debug('Removed existing sourcemap:', options.sourcemapOutputPath); + } + if (fs.existsSync(options.assetsDestPath)) { + fs.rmSync(options.assetsDestPath, { recursive: true }); + logger.debug('Removed existing assets:', options.assetsDestPath); + } + // Captured params: + // bundle + // --platform android + // --dev false + // --reset-cache + // --entry-file /index.js + // --bundle-output /android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle + // --assets-dest /android/app/build/generated/res/createBundleReleaseJsAndAssets + // --sourcemap-output /android/app/build/intermediates/sourcemaps/react/release/index.android.bundle.packager.map + // --minify false + // --verbose + // Reasonable defaults + // If user wants to build bundle differently, they should use `rock bundle` command directly + // and provide the JS bundle path to `--jsbundle` flag + const rockBundleArgs = [ + 'bundle', + '--platform', + 'android', + `--dev`, + 'false', + '--reset-cache', + `--entry-file`, + `index.js`, + '--bundle-output', + options.bundleOutputPath, + '--assets-dest', + options.assetsDestPath, + '--sourcemap-output', + options.sourcemapOutputPath, + '--minify', + 'false', + '--verbose', + ]; + await spawn('rock', rockBundleArgs, { preferLocal: true }); + if (!options.useHermes) { + return; + } + await runHermes({ + bundleOutputPath: options.bundleOutputPath, + sourcemapOutputPath: options.sourcemapOutputPath, + }); +} +//# sourceMappingURL=bundle.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js.map b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js.map new file mode 100644 index 000000000..bf2508f13 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../../../src/lib/commands/signAndroid/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAS1D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5C,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/C,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1C,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnE,CAAC;IAED,mBAAmB;IACnB,SAAS;IACT,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,wCAAwC;IACxC,yHAAyH;IACzH,+FAA+F;IAC/F,gIAAgI;IAChI,mBAAmB;IACnB,cAAc;IAEd,sBAAsB;IACtB,4FAA4F;IAC5F,sDAAsD;IACtD,MAAM,cAAc,GAAG;QACrB,QAAQ;QACR,YAAY;QACZ,SAAS;QACT,OAAO;QACP,OAAO;QACP,eAAe;QACf,cAAc;QACd,UAAU;QACV,iBAAiB;QACjB,OAAO,CAAC,gBAAgB;QACxB,eAAe;QACf,OAAO,CAAC,cAAc;QACtB,oBAAoB;QACpB,OAAO,CAAC,mBAAmB;QAC3B,UAAU;QACV,OAAO;QACP,WAAW;KACZ,CAAC;IACF,MAAM,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3D,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC;QACd,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/command.d.ts b/packages/platform-android/dist/src/lib/commands/signAndroid/command.d.ts new file mode 100644 index 000000000..53bf78193 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/command.d.ts @@ -0,0 +1,14 @@ +import type { PluginApi } from '@rock-js/config'; +export type SignFlags = { + verbose?: boolean; + path: string; + output?: string; + keystore?: string; + keystorePassword?: string; + keyAlias?: string; + keyPassword?: string; + buildJsbundle?: boolean; + jsbundle?: string; + noHermes?: boolean; +}; +export declare const registerSignCommand: (api: PluginApi) => void; diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/command.js b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js new file mode 100644 index 000000000..e0fce174b --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js @@ -0,0 +1,67 @@ +import { signAndroid } from './signAndroid.js'; +const ARGUMENTS = [ + { + name: 'binaryPath', + description: 'Archive (apk or aab) file path', + }, +]; +const OPTIONS = [ + { + name: '--verbose', + description: '', + }, + { + name: '--keystore ', + description: 'Path to keystore file', + }, + { + name: '--keystore-password ', + description: 'Password for keystore file', + }, + { + name: '--key-alias ', + description: 'Alias for key in keystore file', + }, + { + name: '--key-password ', + description: 'Password for key in keystore file', + }, + { + name: '--output ', + description: 'Path to the output APK/AAB file.', + }, + { + name: '--build-jsbundle', + description: 'Build the JS bundle before signing.', + }, + { + name: '--jsbundle ', + description: 'Path to the JS bundle to apply before signing.', + }, + { + name: '--no-hermes', + description: 'Do not use Hermes to build the JS bundle.', + }, +]; +export const registerSignCommand = (api) => { + api.registerCommand({ + name: 'sign:android', + description: 'Sign the Android app with modified JS bundle.', + args: ARGUMENTS, + options: OPTIONS, + action: async (binaryPath, flags) => { + await signAndroid({ + binaryPath, + keystorePath: flags.keystore, + keystorePassword: flags.keystorePassword, + keyAlias: flags.keyAlias, + keyPassword: flags.keyPassword, + outputPath: flags.output, + buildJsBundle: flags.buildJsbundle, + jsBundlePath: flags.jsbundle, + useHermes: !flags.noHermes, + }); + }, + }); +}; +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/command.js.map b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js.map new file mode 100644 index 000000000..89d7bbac5 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/signAndroid/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAe/C,MAAM,SAAS,GAAG;IAChB;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gCAAgC;KAC9C;CACF,CAAC;AAEF,MAAM,OAAO,GAAG;IACd;QACE,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,EAAE;KAChB;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,uBAAuB;KACrC;IACD;QACE,IAAI,EAAE,8BAA8B;QACpC,WAAW,EAAE,4BAA4B;KAC1C;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,gCAAgC;KAC9C;IACD;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,mCAAmC;KACjD;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,kCAAkC;KAChD;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,qCAAqC;KACnD;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,gDAAgD;KAC9D;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,2CAA2C;KACzD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAc,EAAE,EAAE;IACpD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,+CAA+C;QAC5D,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAgB,EAAE,EAAE;YAC7C,MAAM,WAAW,CAAC;gBAChB,UAAU;gBACV,YAAY,EAAE,KAAK,CAAC,QAAQ;gBAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;gBACxC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,YAAY,EAAE,KAAK,CAAC,QAAQ;gBAC5B,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ;aAC3B,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.d.ts b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.d.ts new file mode 100644 index 000000000..a576c37bb --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.d.ts @@ -0,0 +1,12 @@ +export type SignAndroidOptions = { + binaryPath: string; + keystorePath?: string; + keystorePassword?: string; + keyAlias?: string; + keyPassword?: string; + outputPath?: string; + buildJsBundle?: boolean; + jsBundlePath?: string; + useHermes?: boolean; +}; +export declare function signAndroid(options: SignAndroidOptions): Promise; diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js new file mode 100644 index 000000000..bf00b00c6 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js @@ -0,0 +1,169 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { colorLink, getDotRockPath, intro, outro, relativeToCwd, RockError, spawn, spinner, } from '@rock-js/tools'; +import AdmZip from 'adm-zip'; +import { findAndroidBuildTool, getAndroidBuildToolsPath } from '../../paths.js'; +import { buildJsBundle } from './bundle.js'; +export async function signAndroid(options) { + validateOptions(options); + const extension = path.extname(options.binaryPath).slice(1); + intro(`Modifying ${extension.toUpperCase()} file`); + const tempPath = getSignOutputPath(); + if (fs.existsSync(tempPath)) { + fs.rmSync(tempPath, { recursive: true }); + } + const loader = spinner(); + // 1. Build JS bundle if needed + if (options.buildJsBundle) { + const bundleOutputPath = path.join(tempPath, 'index.android.bundle'); + loader.start('Building JS bundle...'); + await buildJsBundle({ + bundleOutputPath, + assetsDestPath: path.join(tempPath, 'res'), + sourcemapOutputPath: path.join(tempPath, 'index.android.bundle.packager.map'), + useHermes: options.useHermes ?? true, + }); + loader.stop(`Built JS bundle: ${colorLink(relativeToCwd(bundleOutputPath))}`); + options.jsBundlePath = bundleOutputPath; + } + // 2. Initialize temporary archive file + const tempArchivePath = path.join(tempPath, `output-app.${extension}`); + loader.start(`Initializing output ${extension.toUpperCase()}...`); + try { + const zip = new AdmZip(options.binaryPath); + // Remove old signature files + zip.deleteFile('META-INF/*'); + zip.writeZip(tempArchivePath); + } + catch (error) { + throw new RockError(`Failed to initialize output file: ${options.outputPath}`, { cause: error.stderr }); + } + loader.stop(`Initialized output ${extension.toUpperCase()}`); + // 3. Replace JS bundle if provided + if (options.jsBundlePath) { + loader.start('Replacing JS bundle...'); + await replaceJsBundle({ + archivePath: tempArchivePath, + jsBundlePath: options.jsBundlePath, + }); + loader.stop(`Replaced JS bundle with ${colorLink(relativeToCwd(options.jsBundlePath))}.`); + } + // 4. Align archive + loader.start('Aligning output file...'); + const outputPath = options.outputPath ?? options.binaryPath; + await alignArchiveFile(tempArchivePath, outputPath); + loader.stop(`Created output ${extension.toUpperCase()} file: ${colorLink(relativeToCwd(outputPath))}.`); + // 5. Sign archive file + loader.start(`Signing the ${extension.toUpperCase()} file...`); + const keystorePath = options.keystorePath ?? 'android/app/debug.keystore'; + await signArchive({ + binaryPath: outputPath, + keystorePath, + keystorePassword: options.keystorePassword ?? 'pass:android', + keyAlias: options.keyAlias, + keyPassword: options.keyPassword, + }); + loader.stop(`Signed the ${extension.toUpperCase()} file with keystore: ${colorLink(keystorePath)}.`); + outro('Success ๐ŸŽ‰.'); +} +function validateOptions(options) { + if (!fs.existsSync(options.binaryPath)) { + throw new RockError(`File not found "${options.binaryPath}"`); + } + if (options.buildJsBundle && options.jsBundlePath) { + throw new RockError('The "--build-jsbundle" flag is incompatible with "--jsbundle". Pick one.'); + } + if (options.jsBundlePath && !fs.existsSync(options.jsBundlePath)) { + throw new RockError(`JS bundle file not found "${options.jsBundlePath}"`); + } +} +async function replaceJsBundle({ archivePath, jsBundlePath, }) { + try { + const zip = new AdmZip(archivePath); + const assetsPath = isAab(archivePath) ? 'base/assets' : 'assets'; + zip.deleteFile(path.join(assetsPath, 'index.android.bundle')); + zip.addLocalFile(jsBundlePath, assetsPath, 'index.android.bundle'); + zip.writeZip(archivePath); + } + catch (error) { + throw new RockError(`Failed to replace JS bundle in destination file: ${archivePath}`, { cause: error }); + } +} +function isSdkGTE35(versionString) { + const match = versionString.match(/build-tools\/([\d.]+)/); + if (!match) + return false; + return match[1].localeCompare('35.0.0', undefined, { numeric: true }) >= 0; +} +async function alignArchiveFile(inputArchivePath, outputPath) { + const zipAlignPath = findAndroidBuildTool('zipalign'); + if (!zipAlignPath) { + throw new RockError(`"zipalign" not found in Android Build-Tools directory: ${colorLink(getAndroidBuildToolsPath())} +Please follow instructions at: https://reactnative.dev/docs/set-up-your-environment?platform=android'`); + } + // See: https://developer.android.com/tools/zipalign#usage + const zipalignArgs = [ + // aligns uncompressed .so files to the specified page size in KiB. Available since SDK 35 + ...(isSdkGTE35(zipAlignPath) ? ['-P', '16'] : ['-p']), + '-f', // Overwrites existing output file. + '-v', // Overwrites existing output file. + '4', // alignment in bytes, e.g. '4' provides 32-bit alignment + inputArchivePath, + outputPath, + ]; + try { + await spawn(zipAlignPath, zipalignArgs); + } + catch (error) { + throw new RockError(`Failed to align archive file: ${zipAlignPath} ${zipalignArgs.join(' ')}`, { cause: error.stderr }); + } +} +async function signArchive({ binaryPath, keystorePath, keystorePassword, keyAlias, keyPassword, }) { + if (!fs.existsSync(keystorePath)) { + throw new RockError(`Keystore file not found "${keystorePath}". Provide a valid keystore path using the "--keystore" option.`); + } + const apksignerPath = findAndroidBuildTool('apksigner'); + if (!apksignerPath) { + throw new RockError(`"apksigner" not found in Android Build-Tools directory: ${colorLink(getAndroidBuildToolsPath())} +Please follow instructions at: https://reactnative.dev/docs/set-up-your-environment?platform=android'`); + } + // apksigner sign --ks-pass "pass:android" --ks "android/app/debug.keystore" --ks-key-alias "androiddebugkey" --key-pass "pass:android" "$OUTPUT2_APK" + const apksignerArgs = [ + 'sign', + '--ks', + keystorePath, + '--ks-pass', + formatPassword(keystorePassword), + ...(keyAlias ? ['--ks-key-alias', keyAlias] : []), + ...(keyPassword ? ['--key-pass', formatPassword(keyPassword)] : []), + ...(isAab(binaryPath) ? ['--min-sdk-version', '36'] : []), + binaryPath, + ]; + try { + await spawn(apksignerPath, apksignerArgs); + } + catch (error) { + throw new RockError(`Failed to sign APK file: ${apksignerPath} ${apksignerArgs.join(' ')}`, { cause: error.stderr }); + } +} +/** + * apksigner expects the password info to be prefixed by the password type. + * + * @see https://developer.android.com/tools/apksigner + */ +function formatPassword(password) { + if (password.startsWith('pass:') || + password.startsWith('env:') || + password.startsWith('file:') || + password === 'stdin') { + return password; + } + return `pass:${password}`; +} +function getSignOutputPath() { + return path.join(getDotRockPath(), 'android/sign'); +} +function isAab(filePath) { + return path.extname(filePath).toLowerCase() === '.aab'; +} +//# sourceMappingURL=signAndroid.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js.map b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js.map new file mode 100644 index 000000000..0bbf022e4 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"signAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/signAndroid/signAndroid.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/toPascalCase.d.ts b/packages/platform-android/dist/src/lib/commands/toPascalCase.d.ts new file mode 100644 index 000000000..cdd38c9e5 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/toPascalCase.d.ts @@ -0,0 +1 @@ +export declare function toPascalCase(value: string): string; diff --git a/packages/platform-android/dist/src/lib/commands/toPascalCase.js b/packages/platform-android/dist/src/lib/commands/toPascalCase.js new file mode 100644 index 000000000..656bebdbb --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/toPascalCase.js @@ -0,0 +1,4 @@ +export function toPascalCase(value) { + return value !== '' ? value[0].toUpperCase() + value.slice(1) : value; +} +//# sourceMappingURL=toPascalCase.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/commands/toPascalCase.js.map b/packages/platform-android/dist/src/lib/commands/toPascalCase.js.map new file mode 100644 index 000000000..3986ae069 --- /dev/null +++ b/packages/platform-android/dist/src/lib/commands/toPascalCase.js.map @@ -0,0 +1 @@ +{"version":3,"file":"toPascalCase.js","sourceRoot":"","sources":["../../../../src/lib/commands/toPascalCase.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACxE,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/getApkInfo.d.ts b/packages/platform-android/dist/src/lib/getApkInfo.d.ts new file mode 100644 index 000000000..50fc4208f --- /dev/null +++ b/packages/platform-android/dist/src/lib/getApkInfo.d.ts @@ -0,0 +1,12 @@ +export interface ApkInfo { + packageName: string; + version: string; +} +/** + * Extracts package information from an APK file using app-info-parser. + * Similar to getInfoPlist for iOS, but for Android APK files. + * + * @param apkPath - Path to the APK file + * @returns Object containing packageName and version + */ +export declare function getApkInfo(apkPath: string): Promise; diff --git a/packages/platform-android/dist/src/lib/getApkInfo.js b/packages/platform-android/dist/src/lib/getApkInfo.js new file mode 100644 index 000000000..ffe97120b --- /dev/null +++ b/packages/platform-android/dist/src/lib/getApkInfo.js @@ -0,0 +1,29 @@ +import path from 'node:path'; +// @ts-expect-error - app-info-parser doesn't have types +import AppInfoParser from 'app-info-parser'; +/** + * Extracts package information from an APK file using app-info-parser. + * Similar to getInfoPlist for iOS, but for Android APK files. + * + * @param apkPath - Path to the APK file + * @returns Object containing packageName and version + */ +export async function getApkInfo(apkPath) { + try { + const parser = new AppInfoParser(apkPath); + const appInfo = await parser.parse(); + return { + packageName: appInfo.package || 'unknown', + version: appInfo.versionName || appInfo.versionCode?.toString() || '1.0', + }; + } + catch { + // Fallback to filename if parsing fails + const apkFileName = path.basename(apkPath, '.apk'); + return { + packageName: apkFileName, + version: '1.0', + }; + } +} +//# sourceMappingURL=getApkInfo.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/getApkInfo.js.map b/packages/platform-android/dist/src/lib/getApkInfo.js.map new file mode 100644 index 000000000..465d5ff0c --- /dev/null +++ b/packages/platform-android/dist/src/lib/getApkInfo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getApkInfo.js","sourceRoot":"","sources":["../../../src/lib/getApkInfo.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,wDAAwD;AACxD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAO5C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAErC,OAAO;YACL,WAAW,EAAE,OAAO,CAAC,OAAO,IAAI,SAAS;YACzC,OAAO,EAAE,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,KAAK;SACzE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO;YACL,WAAW,EAAE,WAAW;YACxB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/paths.d.ts b/packages/platform-android/dist/src/lib/paths.d.ts new file mode 100644 index 000000000..67b9fe02e --- /dev/null +++ b/packages/platform-android/dist/src/lib/paths.d.ts @@ -0,0 +1,7 @@ +export declare function getAndroidSdkPath(): string; +export declare function getAndroidBuildToolsPath(): string; +/** + * Build tools are located in the /build-tools// directory. + */ +export declare function findAndroidBuildTool(toolName: string): string | null; +export declare function versionCompare(first: string, second: string): number; diff --git a/packages/platform-android/dist/src/lib/paths.js b/packages/platform-android/dist/src/lib/paths.js new file mode 100644 index 000000000..8655e7fbd --- /dev/null +++ b/packages/platform-android/dist/src/lib/paths.js @@ -0,0 +1,60 @@ +import fs from 'node:fs'; +import path from 'node:path'; +export function getAndroidSdkPath() { + const sdkRoot = process.env['ANDROID_HOME'] || process.env['ANDROID_SDK_ROOT']; + if (!sdkRoot) { + throw new Error('ANDROID_HOME or ANDROID_SDK_ROOT environment variable is not set. Please follow instructions at: https://reactnative.dev/docs/set-up-your-environment?platform=android'); + } + return sdkRoot; +} +export function getAndroidBuildToolsPath() { + return path.join(getAndroidSdkPath(), 'build-tools'); +} +/** + * Build tools are located in the /build-tools// directory. + */ +export function findAndroidBuildTool(toolName) { + const buildToolsPath = path.join(getAndroidBuildToolsPath()); + const versions = fs + .readdirSync(buildToolsPath, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort(versionCompare) + .reverse(); + for (const version of versions) { + const toolPath = path.join(buildToolsPath, version, toolName); + if (fs.existsSync(toolPath)) { + return toolPath; + } + } + return null; +} +export function versionCompare(first, second) { + const firstVersion = parseVersionString(first); + const secondVersion = parseVersionString(second); + if (!firstVersion || !secondVersion) { + return first.localeCompare(second); + } + if (firstVersion.major !== secondVersion.major) { + return firstVersion.major - secondVersion.major; + } + if (firstVersion.minor !== secondVersion.minor) { + return firstVersion.minor - secondVersion.minor; + } + return firstVersion.patch - secondVersion.patch; +} +function parseVersionString(version) { + if (!isVersionString(version)) { + return null; + } + const [major, minor, patch] = version.split('.').map(Number); + return { + major: Number(major), + minor: Number(minor), + patch: Number(patch), + }; +} +function isVersionString(version) { + return /^[0-9]+\.[0-9]+\.[0-9]+$/.test(version); +} +//# sourceMappingURL=paths.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/paths.js.map b/packages/platform-android/dist/src/lib/paths.js.map new file mode 100644 index 000000000..6661f2d0e --- /dev/null +++ b/packages/platform-android/dist/src/lib/paths.js.map @@ -0,0 +1 @@ +{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,wKAAwK,CACzK,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,aAAa,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,EAAE;SAChB,WAAW,CAAC,cAAc,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SACpD,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;SACtC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC1B,IAAI,CAAC,cAAc,CAAC;SACpB,OAAO,EAAE,CAAC;IAEb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC9D,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,MAAc;IAC1D,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAEjD,IAAI,CAAC,YAAY,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;IAClD,CAAC;IACD,IAAI,YAAY,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;IAClD,CAAC;IAED,OAAO,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;AAClD,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAe;IACzC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7D,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC"} \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/platformAndroid.d.ts b/packages/platform-android/dist/src/lib/platformAndroid.d.ts new file mode 100644 index 000000000..5628e9814 --- /dev/null +++ b/packages/platform-android/dist/src/lib/platformAndroid.d.ts @@ -0,0 +1,5 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +import type { PlatformOutput, PluginApi } from '@rock-js/config'; +type PluginConfig = AndroidProjectConfig; +export declare const platformAndroid: (pluginConfig?: Partial) => (api: PluginApi) => PlatformOutput; +export default platformAndroid; diff --git a/packages/platform-android/dist/src/lib/platformAndroid.js b/packages/platform-android/dist/src/lib/platformAndroid.js new file mode 100644 index 000000000..89fd2aed4 --- /dev/null +++ b/packages/platform-android/dist/src/lib/platformAndroid.js @@ -0,0 +1,23 @@ +import { registerBuildCommand } from './commands/buildAndroid/command.js'; +import { registerCreateKeystoreCommand } from './commands/generateKeystore.js'; +import { getValidProjectConfig } from './commands/getValidProjectConfig.js'; +import { registerRunCommand } from './commands/runAndroid/command.js'; +import { registerSignCommand } from './commands/signAndroid/command.js'; +export const platformAndroid = (pluginConfig) => (api) => { + registerBuildCommand(api, pluginConfig); + registerRunCommand(api, pluginConfig); + registerCreateKeystoreCommand(api, pluginConfig); + registerSignCommand(api); + return { + name: '@rock-js/platform-android', + description: 'Rock plugin for everything Android.', + autolinkingConfig: { + get project() { + const androidConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig); + return { ...androidConfig }; + }, + }, + }; +}; +export default platformAndroid; +//# sourceMappingURL=platformAndroid.js.map \ No newline at end of file diff --git a/packages/platform-android/dist/src/lib/platformAndroid.js.map b/packages/platform-android/dist/src/lib/platformAndroid.js.map new file mode 100644 index 000000000..185c74a84 --- /dev/null +++ b/packages/platform-android/dist/src/lib/platformAndroid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"platformAndroid.js","sourceRoot":"","sources":["../../../src/lib/platformAndroid.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAIxE,MAAM,CAAC,MAAM,eAAe,GAC1B,CAAC,YAAoC,EAAE,EAAE,CACzC,CAAC,GAAc,EAAkB,EAAE;IACjC,oBAAoB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACxC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACtC,6BAA6B,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACjD,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAEzB,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,qCAAqC;QAClD,iBAAiB,EAAE;YACjB,IAAI,OAAO;gBACT,MAAM,aAAa,GAAG,qBAAqB,CACzC,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;gBACF,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAC9B,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,eAAe,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/index.d.ts b/packages/platform-apple-helpers/dist/src/index.d.ts new file mode 100644 index 000000000..09c185e22 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/index.d.ts @@ -0,0 +1 @@ +export * from './lib/index.js'; diff --git a/packages/platform-apple-helpers/dist/src/index.js b/packages/platform-apple-helpers/dist/src/index.js new file mode 100644 index 000000000..6be7947e9 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/index.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/index.js.map b/packages/platform-apple-helpers/dist/src/index.js.map new file mode 100644 index 000000000..15330ef5a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.d.ts new file mode 100644 index 000000000..698a369a9 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.d.ts @@ -0,0 +1,33 @@ +import { parseArgs } from '@rock-js/tools'; +import type { BuilderCommand } from '../../types/index.js'; +export type BuildFlags = { + verbose?: boolean; + configuration?: string; + scheme?: string; + target?: string; + extraParams?: string[]; + exportExtraParams?: string[]; + exportOptionsPlist?: string; + buildFolder?: string; + destination?: string[]; + archive?: boolean; + installPods: boolean; + newArch: boolean; + local?: boolean; +}; +export declare const getBuildOptions: ({ platformName }: BuilderCommand) => ({ + name: string; + description: string; + parse?: undefined; + value?: undefined; +} | { + name: string; + description: string; + parse: typeof parseArgs; + value?: undefined; +} | { + name: string; + description: string; + value: string; + parse?: undefined; +})[]; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js new file mode 100644 index 000000000..ba205d470 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js @@ -0,0 +1,65 @@ +import { parseArgs } from '@rock-js/tools'; +import { getPlatformInfo } from '../../utils/getPlatformInfo.js'; +export const getBuildOptions = ({ platformName }) => { + const { readableName } = getPlatformInfo(platformName); + return [ + { + name: '--verbose', + description: '', + }, + { + name: '--configuration ', + description: 'Explicitly set the scheme configuration to use. This option is case sensitive.', + }, + { + name: '--scheme ', + description: 'Explicitly set Xcode scheme to use', + }, + { + name: '--target ', + description: 'Explicitly set Xcode target to use.', + }, + { + name: '--extra-params ', + description: 'Custom params that will be passed to xcodebuild command.', + parse: parseArgs, + }, + { + name: '--export-extra-params ', + description: 'Custom params that will be passed to xcodebuild export archive command.\n' + + 'Example:\n' + + ' --export-extra-params "-allowProvisioningUpdates"', + parse: parseArgs, + }, + { + name: '--export-options-plist ', + description: 'Name of the export options file for archiving. Defaults to: ExportOptions.plist', + }, + { + name: '--build-folder ', + description: `Location for ${readableName} build artifacts. Corresponds to Xcode's "-derivedDataPath".`, + value: 'build', + }, + { + name: '--destination ', + description: 'Define destination(s) for the build. You can pass multiple destinations as separate values or repeated use of the flag. Values can be either: "simulator", "device" or destinations supported by "xcodebuild -destination" flag, e.g. "generic/platform=iOS"', + }, + { + name: '--archive', + description: 'Create an Xcode archive (IPA) of the build, required for uploading to App Store Connect or distributing to TestFlight', + }, + { + name: '--no-install-pods', + description: 'Skip automatic CocoaPods installation', + }, + { + name: '--no-new-arch', + description: 'Run React Native in legacy async architecture.', + }, + { + name: '--local', + description: 'Force local build with xcodebuild.', + }, + ]; +}; +//# sourceMappingURL=buildOptions.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js.map new file mode 100644 index 000000000..4b0b82490 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buildOptions.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/buildOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAkBjE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,YAAY,EAAkB,EAAE,EAAE;IAClE,MAAM,EAAE,YAAY,EAAE,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAEvD,OAAO;QACL;YACE,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,EAAE;SAChB;QACD;YACE,IAAI,EAAE,0BAA0B;YAChC,WAAW,EACT,gFAAgF;SACnF;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,oCAAoC;SAClD;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,qCAAqC;SACnD;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,0DAA0D;YACvE,KAAK,EAAE,SAAS;SACjB;QACD;YACE,IAAI,EAAE,gCAAgC;YACtC,WAAW,EACT,2EAA2E;gBAC3E,YAAY;gBACZ,qDAAqD;YACvD,KAAK,EAAE,SAAS;SACjB;QACD;YACE,IAAI,EAAE,iCAAiC;YACvC,WAAW,EACT,iFAAiF;SACpF;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,gBAAgB,YAAY,8DAA8D;YACvG,KAAK,EAAE,OAAO;SACf;QACD;YACE,IAAI,EAAE,4BAA4B;YAClC,WAAW,EACT,8PAA8P;SACjQ;QACD;YACE,IAAI,EAAE,WAAW;YACjB,WAAW,EACT,uHAAuH;SAC1H;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,uCAAuC;SACrD;QACD;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,gDAAgD;SAC9D;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,oCAAoC;SAClD;KACF,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.d.ts new file mode 100644 index 000000000..5558502d7 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.d.ts @@ -0,0 +1,12 @@ +import type { ApplePlatform, XcodeProjectInfo } from '../../types/index.js'; +import type { RunFlags } from '../run/runOptions.js'; +import type { BuildFlags } from './buildOptions.js'; +export declare const buildProject: ({ xcodeProject, sourceDir, platformName, scheme, configuration, destinations, args, }: { + xcodeProject: XcodeProjectInfo; + sourceDir: string; + platformName: ApplePlatform; + scheme: string; + configuration: string; + destinations: string[]; + args: RunFlags | BuildFlags; +}) => Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js new file mode 100644 index 000000000..61234acee --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js @@ -0,0 +1,109 @@ +import path from 'node:path'; +import { color, logger, RockError, spawn, spinner } from '@rock-js/tools'; +import { getBuildPaths } from '../../utils/getBuildPaths.js'; +import { supportedPlatforms } from '../../utils/supportedPlatforms.js'; +let lastProgress = 0; +/** + * Creates an ASCII progress bar + * @param percent - Percentage of completion (0-100) + * @param length - Length of the progress bar in characters + * @returns ASCII progress bar string + */ +function createProgressBar(percent, length = 20) { + const latestPercent = percent > lastProgress ? percent : lastProgress; + lastProgress = latestPercent; + const filledLength = Math.round(length * (latestPercent / 100)); + const emptyLength = length - filledLength; + const filled = 'โ–ˆ'.repeat(filledLength); + const empty = 'โ–‘'.repeat(emptyLength); + return `[${filled}${empty}]`; +} +function reportProgress(chunk, loader, message) { + if (chunk.includes('PhaseScriptExecution')) { + if (chunk.includes('[CP-User]\\ [Hermes]\\ Replace\\ Hermes\\')) { + const progressBar = createProgressBar(10); + loader.message(`${message} ${progressBar}`); + } + if (chunk.includes('[CP-User]\\ [RN]Check\\ rncore') && + chunk.includes('React-Fabric')) { + const progressBar = createProgressBar(35); + loader.message(`${message} ${progressBar}`); + } + if (chunk.includes('[CP-User]\\ [RN]Check\\ FBReactNativeSpec')) { + const progressBar = createProgressBar(53); + loader.message(`${message} ${progressBar}`); + } + if (chunk.includes('[CP-User]\\ [RN]Check\\ rncore') && + chunk.includes('React-FabricComponents')) { + const progressBar = createProgressBar(66); + loader.message(`${message} ${progressBar}`); + } + if (chunk.includes('[CP]\\ Check\\ Pods\\ Manifest.lock')) { + const progressBar = createProgressBar(90); + loader.message(`${message} ${progressBar}`); + } + } + else if (chunk.includes('BUILD SUCCEEDED')) { + const progressBar = createProgressBar(100); + loader.message(`${message} ${progressBar}`); + } +} +export const buildProject = async ({ xcodeProject, sourceDir, platformName, scheme, configuration, destinations, args, }) => { + if (!supportedPlatforms[platformName]) { + throw new RockError(`Unknown platform: ${platformName}. Please, use one of: ${Object.values(supportedPlatforms).join(', ')}.`); + } + const xcodebuildArgs = [ + xcodeProject.isWorkspace ? '-workspace' : '-project', + xcodeProject.name, + ...(args.buildFolder ? ['-derivedDataPath', args.buildFolder] : []), + '-configuration', + configuration, + '-scheme', + scheme, + ...destinations.flatMap((destination) => ['-destination', destination]), + ]; + if (args.archive) { + const { archiveDir } = getBuildPaths(platformName); + const archiveName = `${xcodeProject.name.replace('.xcworkspace', '')}.xcarchive`; + xcodebuildArgs.push('-archivePath', path.join(archiveDir, archiveName), 'archive'); + } + if (args.extraParams) { + xcodebuildArgs.push(...args.extraParams); + } + logger.log(`Build Settings: +Scheme ${color.bold(scheme)} +Configuration ${color.bold(configuration)}`); + const loader = spinner({ indicator: 'timer' }); + const message = `${args.archive ? 'Archiving' : 'Building'} the app`; + let commandOutput = ''; + loader.start(message); + try { + const process = spawn('xcodebuild', xcodebuildArgs, { + cwd: sourceDir, + }); + if (!logger.isVerbose()) { + // Process the output from the AsyncIterable + for await (const chunk of process) { + commandOutput += chunk + '\n'; + reportProgress(chunk, loader, message); + } + } + await process; + loader.stop(`${args.archive ? 'Archived' : 'Built'} the app.`); + } + catch (error) { + loader.stop(`Failed: ${message}.`, 1); + if (!xcodeProject.isWorkspace) { + logger.error(`If your project uses CocoaPods, make sure to install pods with "pod install" in ${sourceDir} directory.`); + } + if (commandOutput) { + // Use lightweight console.error instead of logger.error to avoid stack overflow issues when Xcode logs go crazy + console.error(color.red(`xcodebuild output: ${commandOutput}`)); + throw new RockError('Running xcodebuild failed. See error details above.'); + } + throw new RockError('Running xcodebuild failed', { + cause: error.stderr || error.command, + }); + } +}; +//# sourceMappingURL=buildProject.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js.map new file mode 100644 index 000000000..e4b9661f7 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buildProject.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/buildProject.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.d.ts new file mode 100644 index 000000000..7aba01cf8 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.d.ts @@ -0,0 +1,15 @@ +import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools'; +import type { BuilderCommand, ProjectConfig } from '../../types/index.js'; +import type { BuildFlags } from './buildOptions.js'; +export declare const createBuild: ({ platformName, projectConfig, args, projectRoot, reactNativePath, fingerprintOptions, brownfield, remoteCacheProvider, }: { + platformName: BuilderCommand["platformName"]; + projectConfig: ProjectConfig; + args: BuildFlags; + projectRoot: string; + reactNativePath: string; + fingerprintOptions: FingerprintSources; + brownfield?: boolean; + remoteCacheProvider: null | (() => RemoteBuildCache) | undefined; +}) => Promise<{ + scheme: string | undefined; +}>; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js new file mode 100644 index 000000000..445be8614 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js @@ -0,0 +1,106 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { colorLink, formatArtifactName, getBinaryPath, isInteractive, logger, promptSelect, relativeToCwd, RockError, saveLocalBuildCache, } from '@rock-js/tools'; +import { buildApp } from '../../utils/buildApp.js'; +import { getBuildPaths } from '../../utils/getBuildPaths.js'; +import { exportArchive } from './exportArchive.js'; +export const createBuild = async ({ platformName, projectConfig, args, projectRoot, reactNativePath, fingerprintOptions, brownfield, remoteCacheProvider, }) => { + await validateArgs(args); + let xcodeProject; + let sourceDir; + let scheme = args.scheme; + const deviceOrSimulator = args.destination + ? // there can be multiple destinations, so we'll pick the first one + args.destination[0].match(/simulator/i) + ? 'simulator' + : 'device' + : 'simulator'; + const artifactName = await formatArtifactName({ + platform: 'ios', + traits: [deviceOrSimulator, args.configuration ?? 'Debug'], + root: projectRoot, + fingerprintOptions, + }); + const binaryPath = await getBinaryPath({ + platformName, + artifactName, + localFlag: args.local, + remoteCacheProvider, + fingerprintOptions, + sourceDir: projectConfig.sourceDir, + }); + if (binaryPath) { + logger.log(`Build available at: ${colorLink(relativeToCwd(binaryPath))}`); + if (args.archive) { + const { exportDir } = getBuildPaths(platformName); + if (fs.existsSync(exportDir) && fs.statSync(exportDir).isDirectory()) { + logger.log(`Archives available at: ${colorLink(relativeToCwd(exportDir))}`); + } + } + return { scheme }; + } + try { + const { appPath, ...buildAppResult } = await buildApp({ + projectRoot, + projectConfig, + platformName, + args, + reactNativePath, + brownfield, + artifactName, + deviceOrSimulator, + fingerprintOptions, + }); + logger.log(`Build available at: ${colorLink(relativeToCwd(appPath))}`); + xcodeProject = buildAppResult.xcodeProject; + sourceDir = buildAppResult.sourceDir; + scheme = buildAppResult.scheme; + } + catch (error) { + const message = `Failed to create ${args.archive ? 'archive' : 'build'}`; + throw new RockError(message, { cause: error }); + } + if (args.archive) { + const { archiveDir } = getBuildPaths(platformName); + const archivePath = path.join(archiveDir, `${xcodeProject.name.replace('.xcworkspace', '')}.xcarchive`); + const { ipaPath } = await exportArchive({ + sourceDir, + archivePath, + platformName, + exportExtraParams: args.exportExtraParams ?? [], + exportOptionsPlist: args.exportOptionsPlist, + }); + // Save the IPA to the local build cache so it's available for remote-cache command + saveLocalBuildCache(artifactName, ipaPath); + } + return { scheme }; +}; +async function validateArgs(args) { + if (!args.destination) { + if (isInteractive()) { + const destination = await promptSelect({ + message: 'Select destination for a generic build', + options: [ + { + label: 'Simulator', + value: 'simulator', + }, + { + label: 'Device', + value: 'device', + }, + ], + }); + args.destination = [destination]; + logger.info(`You can set configuration manually next time using "--destination ${destination}" flag.`); + } + else { + logger.error(`The "--destination" flag is required in non-interactive environments. Available flag values: +- "simulator" โ€“ suitable for unsigned simulator builds for developers +- "device" โ€“ suitable for signed device builds for testers +- or values supported by "xcodebuild -destination" flag, e.g. "generic/platform=iOS"`); + process.exit(1); + } + } +} +//# sourceMappingURL=createBuild.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js.map new file mode 100644 index 000000000..0dccc6b8e --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js.map @@ -0,0 +1 @@ +{"version":3,"file":"createBuild.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/createBuild.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,MAAM,EACN,YAAY,EACZ,aAAa,EACb,SAAS,EACT,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,EAChC,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,mBAAmB,GAUpB,EAAE,EAAE;IACH,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAEzB,IAAI,YAA8B,CAAC;IACnC,IAAI,SAAiB,CAAC;IACtB,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzB,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW;QACxC,CAAC,CAAC,kEAAkE;YAClE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;gBACvC,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,QAAQ;QACZ,CAAC,CAAC,WAAW,CAAC;IAEhB,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC;QAC1D,IAAI,EAAE,WAAW;QACjB,kBAAkB;KACnB,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;QACrC,YAAY;QACZ,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,mBAAmB;QACnB,kBAAkB;QAClB,SAAS,EAAE,aAAa,CAAC,SAAS;KACnC,CAAC,CAAC;IAEH,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,uBAAuB,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;QAE1E,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;YAClD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrE,MAAM,CAAC,GAAG,CACR,0BAA0B,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,CAChE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,CAAC;IACpB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,QAAQ,CAAC;YACpD,WAAW;YACX,aAAa;YACb,YAAY;YACZ,IAAI;YACJ,eAAe;YACf,UAAU;YACV,YAAY;YACZ,iBAAiB;YACjB,kBAAkB;SACnB,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,uBAAuB,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QAEvE,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC;QAC3C,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC;QACrC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,oBAAoB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QACzE,MAAM,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,EAAE,UAAU,EAAE,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;QAEnD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,UAAU,EACV,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,YAAY,CAC7D,CAAC;QAEF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC;YACtC,SAAS;YACT,WAAW;YACX,YAAY;YACZ,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,EAAE;YAC/C,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;SAC5C,CAAC,CAAC;QAEH,mFAAmF;QACnF,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC,CAAC;AAEF,KAAK,UAAU,YAAY,CAAC,IAAgB;IAC1C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACtB,IAAI,aAAa,EAAE,EAAE,CAAC;YACpB,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC;gBACrC,OAAO,EAAE,wCAAwC;gBACjD,OAAO,EAAE;oBACP;wBACE,KAAK,EAAE,WAAW;wBAClB,KAAK,EAAE,WAAW;qBACnB;oBACD;wBACE,KAAK,EAAE,QAAQ;wBACf,KAAK,EAAE,QAAQ;qBAChB;iBACF;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,WAAW,GAAG,CAAC,WAAW,CAAC,CAAC;YAEjC,MAAM,CAAC,IAAI,CACT,qEAAqE,WAAW,SAAS,CAC1F,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CACV;;;qFAG6E,CAC9E,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.d.ts new file mode 100644 index 000000000..8fa7492a1 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.d.ts @@ -0,0 +1,9 @@ +export declare const exportArchive: ({ sourceDir, archivePath, platformName, exportExtraParams, exportOptionsPlist, }: { + sourceDir: string; + archivePath: string; + platformName: string; + exportExtraParams: string[]; + exportOptionsPlist?: string; +}) => Promise<{ + ipaPath: string; +}>; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js new file mode 100644 index 000000000..9547cee46 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js @@ -0,0 +1,46 @@ +import { colorLink, relativeToCwd, RockError, spawn, spinner, } from '@rock-js/tools'; +import { existsSync, readdirSync } from 'fs'; +import path from 'path'; +import { getBuildPaths } from '../../utils/getBuildPaths.js'; +export const exportArchive = async ({ sourceDir, archivePath, platformName, exportExtraParams, exportOptionsPlist, }) => { + const loader = spinner(); + loader.start('Exporting the archive...'); + const exportOptionsPlistPath = path.join(sourceDir, exportOptionsPlist ?? 'ExportOptions.plist'); + if (!existsSync(exportOptionsPlistPath)) { + loader.stop('Failed to export the archive.', 1); + throw new RockError(`ExportOptions.plist not found, please create ${colorLink(relativeToCwd(exportOptionsPlistPath))} file with valid configuration for Archive export.`); + } + const { exportDir } = getBuildPaths(platformName); + const xcodebuildArgs = [ + '-exportArchive', + '-archivePath', + archivePath, + '-exportPath', + exportDir, + '-exportOptionsPlist', + exportOptionsPlistPath, + ...exportExtraParams, + ]; + try { + let ipaFiles = []; + await spawn('xcodebuild', xcodebuildArgs, { + cwd: sourceDir, + stdio: 'pipe', + }); + try { + ipaFiles = readdirSync(exportDir).filter((file) => file.endsWith('.ipa')); + } + catch { + ipaFiles = []; + } + loader.stop(`Archive available at: ${colorLink(path.join(exportDir, ipaFiles[0]) ?? exportDir)}`); + return { ipaPath: path.join(exportDir, ipaFiles[0]) }; + } + catch (error) { + loader.stop('Running xcodebuild failed.', 1); + throw new Error('Running xcodebuild failed', { + cause: error.stderr, + }); + } +}; +//# sourceMappingURL=exportArchive.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js.map new file mode 100644 index 000000000..02856d4bb --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exportArchive.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/exportArchive.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,aAAa,EACb,SAAS,EACT,KAAK,EACL,OAAO,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,SAAS,EACT,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,GAOnB,EAAgC,EAAE;IACjC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IAEzB,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACzC,MAAM,sBAAsB,GAAG,IAAI,CAAC,IAAI,CACtC,SAAS,EACT,kBAAkB,IAAI,qBAAqB,CAC5C,CAAC;IAEF,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,IAAI,SAAS,CACjB,gDAAgD,SAAS,CACvD,aAAa,CAAC,sBAAsB,CAAC,CACtC,oDAAoD,CACtD,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG;QACrB,gBAAgB;QAChB,cAAc;QACd,WAAW;QACX,aAAa;QACb,SAAS;QACT,qBAAqB;QACrB,sBAAsB;QACtB,GAAG,iBAAiB;KACrB,CAAC;IAEF,IAAI,CAAC;QACH,IAAI,QAAQ,GAAa,EAAE,CAAC;QAE5B,MAAM,KAAK,CAAC,YAAY,EAAE,cAAc,EAAE;YACxC,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,IAAI,CAAC;YACH,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,IAAI,CACT,yBAAyB,SAAS,CAChC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAC/C,EAAE,CACJ,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE;YAC3C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.d.ts new file mode 100644 index 000000000..c145cafab --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.d.ts @@ -0,0 +1,2 @@ +import type { ApplePlatform } from '../../types/index.js'; +export declare const simulatorDestinationMap: Record; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js new file mode 100644 index 000000000..f8e79383c --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js @@ -0,0 +1,7 @@ +export const simulatorDestinationMap = { + ios: 'iOS Simulator', + macos: 'macOS', + visionos: 'visionOS Simulator', + tvos: 'tvOS Simulator', +}; +//# sourceMappingURL=simulatorDestinationMap.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js.map new file mode 100644 index 000000000..20c846553 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"simulatorDestinationMap.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/simulatorDestinationMap.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAkC;IACpE,GAAG,EAAE,eAAe;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,oBAAoB;IAC9B,IAAI,EAAE,gBAAgB;CACvB,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.d.ts new file mode 100644 index 000000000..f3e8e4e11 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.d.ts @@ -0,0 +1,18 @@ +import type { StartDevServerArgs } from '@rock-js/config'; +import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools'; +import type { ApplePlatform, ProjectConfig } from '../../types/index.js'; +import type { RunFlags } from './runOptions.js'; +export declare const createRun: ({ platformName, projectConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions, reactNativePath, reactNativeVersion, platforms, startDevServer, }: { + platformName: ApplePlatform; + projectConfig: ProjectConfig; + args: RunFlags; + projectRoot: string; + remoteCacheProvider: null | (() => RemoteBuildCache) | undefined; + fingerprintOptions: FingerprintSources; + reactNativePath: string; + reactNativeVersion: string; + platforms: { + [platform: string]: object; + }; + startDevServer: (options: StartDevServerArgs) => void; +}) => Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js new file mode 100644 index 000000000..a815d0641 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js @@ -0,0 +1,232 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { color, formatArtifactName, getBinaryPath, isInteractive, logger, promptSelect, RockError, } from '@rock-js/tools'; +import { buildApp } from '../../utils/buildApp.js'; +import { getPlatformInfo } from '../../utils/getPlatformInfo.js'; +import { listDevicesAndSimulators } from '../../utils/listDevices.js'; +import { matchingDevice } from './matchingDevice.js'; +import { cacheRecentDevice, sortByRecentDevices } from './recentDevices.js'; +import { runOnDevice } from './runOnDevice.js'; +import { runOnMac } from './runOnMac.js'; +import { runOnMacCatalyst } from './runOnMacCatalyst.js'; +import { launchSimulator, runOnSimulator } from './runOnSimulator.js'; +export const createRun = async ({ platformName, projectConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions, reactNativePath, reactNativeVersion, platforms, startDevServer, }) => { + const startDevServerHelper = () => { + if (args.devServer) { + logger.info('Starting dev server...'); + startDevServer({ + root: projectRoot, + reactNativePath, + reactNativeVersion, + platforms, + args: { + interactive: isInteractive(), + clientLogs: args.clientLogs ?? true, + }, + }); + } + }; + validateArgs(args, projectRoot); + const deviceOrSimulator = args.destination + ? // there can be multiple destinations, so we'll pick the first one + args.destination[0].match(/simulator/i) + ? 'simulator' + : 'device' + : 'simulator'; + const artifactName = await formatArtifactName({ + platform: 'ios', + traits: [deviceOrSimulator, args.configuration ?? 'Debug'], + root: projectRoot, + fingerprintOptions, + }); + const binaryPath = await getBinaryPath({ + platformName: 'ios', + artifactName, + binaryPathFlag: args.binaryPath, + localFlag: args.local, + remoteCacheProvider, + fingerprintOptions, + sourceDir: projectConfig.sourceDir, + }); + // Check if the device argument looks like a UDID + // (assuming UDIDs are alphanumeric and have specific length) + const udid = args.device && /^[A-Fa-f0-9-]{25,}$/.test(args.device) + ? args.device + : undefined; + const deviceName = udid ? undefined : args.device; + if (platformName === 'macos') { + const { appPath } = await buildApp({ + args, + projectConfig, + platformName, + projectRoot, + udid, + deviceName, + reactNativePath, + binaryPath, + artifactName, + deviceOrSimulator, + fingerprintOptions, + }); + await runOnMac(appPath); + startDevServerHelper(); + return; + } + else if (args.catalyst) { + const { appPath, scheme } = await buildApp({ + args, + projectConfig, + platformName, + projectRoot, + udid, + deviceName, + reactNativePath, + binaryPath, + artifactName, + deviceOrSimulator, + fingerprintOptions, + }); + if (scheme) { + await runOnMacCatalyst(appPath, scheme); + startDevServerHelper(); + return; + } + else { + throw new RockError('Failed to get project scheme'); + } + } + const devices = await listDevicesAndSimulators(platformName); + if (devices.length === 0) { + const { readableName } = getPlatformInfo(platformName); + throw new RockError(`No devices or simulators detected. Install simulators via Xcode or connect a physical ${readableName} device.`); + } + const device = await selectDevice(devices, args); + if (device) { + if (device.type !== deviceOrSimulator) { + throw new RockError(`Selected device "${device.name}" is not a ${deviceOrSimulator}. +Please either use "--destination ${deviceOrSimulator === 'simulator' ? 'device' : 'simulator'}" flag or select available ${deviceOrSimulator}: +${devices + .filter(({ type }) => type === deviceOrSimulator) + .map(({ name }) => `โ€ข ${name}`) + .join('\n')}`); + } + cacheRecentDevice(device, platformName); + if (device.type === 'simulator') { + const [, { appPath, infoPlistPath }] = await Promise.all([ + launchSimulator(device), + buildApp({ + args, + projectConfig, + platformName, + udid: device.udid, + projectRoot, + reactNativePath, + binaryPath, + artifactName, + deviceOrSimulator, + fingerprintOptions, + }), + ]); + await runOnSimulator(device, appPath, infoPlistPath); + startDevServerHelper(); + } + else if (device.type === 'device') { + const { appPath, bundleIdentifier } = await buildApp({ + args, + projectConfig, + platformName, + udid: device.udid, + projectRoot, + reactNativePath, + binaryPath, + artifactName, + deviceOrSimulator, + fingerprintOptions, + }); + await runOnDevice(device, appPath, projectConfig.sourceDir, bundleIdentifier); + startDevServerHelper(); + } + return; + } + else { + const bootedDevices = devices.filter(({ state, type }) => state === 'Booted' && type === deviceOrSimulator); + if (bootedDevices.length === 0) { + // fallback to present all devices when no device is selected + if (isInteractive()) { + const simulator = await promptForDeviceSelection(devices.filter(({ type }) => type === deviceOrSimulator), platformName); + bootedDevices.push(simulator); + cacheRecentDevice(simulator, platformName); + } + else { + logger.debug('No booted devices or simulators found. Launching first available simulator...'); + const simulator = devices.filter((device) => device.type === 'simulator')[0]; + if (simulator) { + bootedDevices.push(simulator); + } + else { + throw new RockError('No Apple simulators found. Install simulators via Xcode.'); + } + } + } + for (const bootedDevice of bootedDevices) { + const [, { appPath, infoPlistPath, bundleIdentifier }] = await Promise.all([ + launchSimulator(bootedDevice), + buildApp({ + args, + projectConfig, + platformName, + udid: bootedDevice.udid, + projectRoot, + reactNativePath, + binaryPath, + artifactName, + deviceOrSimulator, + fingerprintOptions, + }), + ]); + if (bootedDevice.type === 'simulator') { + await runOnSimulator(bootedDevice, appPath, infoPlistPath); + } + else { + await runOnDevice(bootedDevice, appPath, projectConfig.sourceDir, bundleIdentifier); + } + } + startDevServerHelper(); + } +}; +async function selectDevice(devices, args) { + let device; + if (args.device) { + device = matchingDevice(devices, args.device); + } + if (!device && args.device) { + logger.warn(`No devices or simulators found matching "${args.device}". Falling back to default simulator.`); + } + return device; +} +function validateArgs(args, projectRoot) { + if (args.binaryPath) { + args.binaryPath = path.isAbsolute(args.binaryPath) + ? args.binaryPath + : path.join(projectRoot, args.binaryPath); + if (!fs.existsSync(args.binaryPath)) { + throw new Error(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`); + } + // No need to install pods if binary path is provided + args.installPods = false; + } +} +function promptForDeviceSelection(devices, platformName) { + const sortedDevices = sortByRecentDevices(devices, platformName); + return promptSelect({ + message: 'Select the device / simulator you want to use', + options: sortedDevices.map((d) => { + const markDevice = d.type === 'device' ? ` - (physical device)` : ''; + return { + label: `${d.name} ${color.dim(`(${d.version})${markDevice}`)}`, + value: d, + }; + }), + }); +} +//# sourceMappingURL=createRun.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js.map new file mode 100644 index 000000000..25d7d0c5e --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js.map @@ -0,0 +1 @@ +{"version":3,"file":"createRun.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/createRun.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.d.ts new file mode 100644 index 000000000..61cad5a8b --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.d.ts @@ -0,0 +1,15 @@ +import type { ApplePlatform, XcodeProjectInfo } from '../../types/index.js'; +export declare function getBuildSettings({ xcodeProject, sourceDir, platformName, configuration, destinations, scheme, target, buildFolder, }: { + xcodeProject: XcodeProjectInfo; + sourceDir: string; + platformName: ApplePlatform; + configuration: string; + destinations: string[]; + scheme: string; + target?: string; + buildFolder?: string; +}): Promise<{ + appPath: string; + infoPlistPath: string; + bundleIdentifier: string; +}>; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js new file mode 100644 index 000000000..464538708 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js @@ -0,0 +1,98 @@ +import path from 'node:path'; +import { color, logger, RockError, spawn } from '@rock-js/tools'; +export async function getBuildSettings({ xcodeProject, sourceDir, platformName, configuration, destinations, scheme, target, buildFolder, }) { + const destination = destinations[0]; + const sdk = destination.match(/simulator/i) + ? getSimulatorPlatformSDK(platformName) + : getDevicePlatformSDK(platformName); + const { stdout: buildSettingsOutput } = await spawn('xcodebuild', [ + xcodeProject.isWorkspace ? '-workspace' : '-project', + xcodeProject.name, + ...(buildFolder ? ['-derivedDataPath', buildFolder] : []), + '-scheme', + scheme, + '-configuration', + configuration, + '-sdk', + sdk, + // -showBuildSettings supports exactly one -destination argument + '-destination', + destination, + '-showBuildSettings', + '-json', + ], { cwd: sourceDir, stdio: 'pipe' }); + const settings = JSON.parse(buildSettingsOutput).filter(({ buildSettings: { WRAPPER_EXTENSION }, }) => WRAPPER_EXTENSION === 'app' || WRAPPER_EXTENSION === 'framework'); + const targets = settings.map(({ target: settingsTarget }) => settingsTarget); + if (settings.length === 0) { + throw new RockError(`Failed to get build settings for your project. Looking for "app" or "framework" wrapper extensions but found none.`); + } + let selectedTarget = targets[0]; + if (target) { + if (!targets.includes(target)) { + logger.info(`Target ${color.bold(target)} not found for scheme ${color.bold(scheme)}, automatically selected target ${color.bold(selectedTarget)}`); + } + else { + selectedTarget = target; + } + } + logger.debug(`Selected target: ${selectedTarget}`); + // Find app in all building settings - look for WRAPPER_EXTENSION: 'app', + const targetIndex = targets.indexOf(selectedTarget); + const buildSettings = settings[targetIndex].buildSettings; + if (!buildSettings) { + throw new RockError('Failed to get build settings for your project'); + } + const appPath = getBuildPath(buildSettings, platformName); + const infoPlistPath = buildSettings.INFOPLIST_PATH; + const targetBuildDir = buildSettings.TARGET_BUILD_DIR; + return { + appPath, + infoPlistPath: path.join(targetBuildDir, infoPlistPath), + bundleIdentifier: buildSettings.PRODUCT_BUNDLE_IDENTIFIER, + }; +} +function getBuildPath(buildSettings, platformName) { + const targetBuildDir = buildSettings.TARGET_BUILD_DIR; + const executableFolderPath = buildSettings.EXECUTABLE_FOLDER_PATH; + const fullProductName = buildSettings.FULL_PRODUCT_NAME; + if (!targetBuildDir) { + throw new Error('Failed to get the target build directory.'); + } + if (!executableFolderPath) { + throw new Error('Failed to get the app name.'); + } + if (!fullProductName) { + throw new Error('Failed to get product name.'); + } + if (platformName === 'macos') { + return path.join(targetBuildDir, fullProductName); + } + else { + return path.join(targetBuildDir, executableFolderPath); + } +} +function getSimulatorPlatformSDK(platform) { + switch (platform) { + case 'ios': + return 'iphonesimulator'; + case 'macos': + return 'macosx'; + case 'tvos': + return 'appletvsimulator'; + case 'visionos': + return 'xrsimulator'; + } +} +function getDevicePlatformSDK(platform) { + switch (platform) { + case 'ios': + return 'iphoneos'; + case 'macos': + return 'macosx'; + case 'tvos': + return 'appletvos'; + case 'visionos': + return 'xr'; + } +} +//# sourceMappingURL=getBuildSettings.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js.map new file mode 100644 index 000000000..8f58926a4 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getBuildSettings.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/getBuildSettings.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.d.ts new file mode 100644 index 000000000..8724b0581 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.d.ts @@ -0,0 +1,3 @@ +import type { Device } from '../../types/index.js'; +export declare function matchingDevice(devices: Array, deviceArg: string): Device | undefined; +export declare function formattedDeviceName(simulator: Device): string; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js new file mode 100644 index 000000000..a7e4e9aa5 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js @@ -0,0 +1,11 @@ +export function matchingDevice(devices, deviceArg) { + const deviceByName = devices.find((device) => device.name === deviceArg || formattedDeviceName(device) === deviceArg); + const deviceByUdid = devices.find((d) => d.udid === deviceArg); + return deviceByName || deviceByUdid; +} +export function formattedDeviceName(simulator) { + return simulator.version + ? `${simulator.name} (${simulator.version})` + : simulator.name; +} +//# sourceMappingURL=matchingDevice.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js.map new file mode 100644 index 000000000..d7ad48b97 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js.map @@ -0,0 +1 @@ +{"version":3,"file":"matchingDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/matchingDevice.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,OAAsB,EAAE,SAAiB;IACtE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAC/B,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,mBAAmB,CAAC,MAAM,CAAC,KAAK,SAAS,CACzE,CAAC;IACF,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAC/D,OAAO,YAAY,IAAI,YAAY,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,OAAO,SAAS,CAAC,OAAO;QACtB,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,GAAG;QAC5C,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;AACrB,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.d.ts new file mode 100644 index 000000000..080c7a205 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.d.ts @@ -0,0 +1,3 @@ +import type { ApplePlatform, Device } from '../../types/index.js'; +export declare function cacheRecentDevice(device: Device, platform: ApplePlatform): void; +export declare function sortByRecentDevices(devices: Device[], platform: ApplePlatform): Device[]; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js new file mode 100644 index 000000000..1028fd909 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js @@ -0,0 +1,32 @@ +import { cacheManager, logger } from '@rock-js/tools'; +export function cacheRecentDevice(device, platform) { + const cacheKey = 'recentDevicesUDID-' + platform; + try { + const recentDevices = getRecentDevices(platform); + const newRecentDevices = [device.udid, ...recentDevices]; + const uniqueDevices = Array.from(new Set(newRecentDevices)).slice(0, 5); + cacheManager.set(cacheKey, JSON.stringify(uniqueDevices)); + } + catch (error) { + logger.debug(`Failed to cache recent device ${device.name} with UDID ${device.udid}. ${error}`); + } +} +function getRecentDevices(platform) { + const cacheKey = 'recentDevicesUDID-' + platform; + const recentDevicesString = cacheManager.get(cacheKey); + try { + return recentDevicesString ? JSON.parse(recentDevicesString) : []; + } + catch (error) { + logger.debug(`Failed to read recent devices from cache. ${error}`); + return []; + } +} +export function sortByRecentDevices(devices, platform) { + const recentDevices = getRecentDevices(platform); + const udids = Array.from(new Set([...recentDevices, ...devices.map(({ udid }) => udid)])); + return udids + .map((udid) => devices.find((device) => device.udid === udid)) + .filter(Boolean); +} +//# sourceMappingURL=recentDevices.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js.map new file mode 100644 index 000000000..266d0b642 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js.map @@ -0,0 +1 @@ +{"version":3,"file":"recentDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/recentDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAAuB;IACvE,MAAM,QAAQ,GAAG,oBAAoB,GAAG,QAAQ,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,gBAAgB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,aAAa,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,iCAAiC,MAAM,CAAC,IAAI,cAAc,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAClF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAuB;IAC/C,MAAM,QAAQ,GAAG,oBAAoB,GAAG,QAAQ,CAAC;IACjD,MAAM,mBAAmB,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,6CAA6C,KAAK,EAAE,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAiB,EACjB,QAAuB;IAEvB,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACtB,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAChE,CAAC;IACF,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;SAC7D,MAAM,CAAC,OAAO,CAAa,CAAC;AACjC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.d.ts new file mode 100644 index 000000000..5bc1e05ea --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.d.ts @@ -0,0 +1,2 @@ +import type { Device } from '../../types/index.js'; +export declare function runOnDevice(selectedDevice: Device, binaryPath: string, sourceDir: string, bundleIdentifier: string): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js new file mode 100644 index 000000000..df7897515 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js @@ -0,0 +1,32 @@ +import { color, RockError, spawn, spinner } from '@rock-js/tools'; +export async function runOnDevice(selectedDevice, binaryPath, sourceDir, bundleIdentifier) { + const loader = spinner(); + loader.start(`Installing and launching your app on ${color.bold(selectedDevice.name)}`); + try { + await spawn('xcrun', [ + 'devicectl', + 'device', + 'install', + 'app', + '--device', + selectedDevice.udid, + binaryPath, + ], { cwd: sourceDir }); + await spawn('xcrun', [ + 'devicectl', + 'device', + 'process', + 'launch', + '--device', + selectedDevice.udid, + bundleIdentifier, + ], { cwd: sourceDir }); + } + catch (error) { + loader.stop(`Failed: Installing and launching your app on ${color.bold(selectedDevice.name)}`); + throw new RockError(error.stderr); + } + loader.stop(`Installed the app on ${color.bold(selectedDevice.name)}.`); + return; +} +//# sourceMappingURL=runOnDevice.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js.map new file mode 100644 index 000000000..1af9f970f --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnDevice.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGlE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,cAAsB,EACtB,UAAkB,EAClB,SAAiB,EACjB,gBAAwB;IAExB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,MAAM,CAAC,KAAK,CACV,wCAAwC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAC;IACF,IAAI,CAAC;QACH,MAAM,KAAK,CACT,OAAO,EACP;YACE,WAAW;YACX,QAAQ;YACR,SAAS;YACT,KAAK;YACL,UAAU;YACV,cAAc,CAAC,IAAI;YACnB,UAAU;SACX,EACD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;QACF,MAAM,KAAK,CACT,OAAO,EACP;YACE,WAAW;YACX,QAAQ;YACR,SAAS;YACT,QAAQ;YACR,UAAU;YACV,cAAc,CAAC,IAAI;YACnB,gBAAgB;SACjB,EACD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CACT,gDAAgD,KAAK,CAAC,IAAI,CACxD,cAAc,CAAC,IAAI,CACpB,EAAE,CACJ,CAAC;QACF,MAAM,IAAI,SAAS,CAAE,KAAyB,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,OAAO;AACT,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.d.ts new file mode 100644 index 000000000..c10f449e6 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.d.ts @@ -0,0 +1 @@ +export declare function runOnMac(binaryPath: string): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js new file mode 100644 index 000000000..1f1b26e35 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js @@ -0,0 +1,13 @@ +import { color, logger, RockError, spawn } from '@rock-js/tools'; +export async function runOnMac(binaryPath) { + logger.debug(`Opening "${color.bold(binaryPath)}"`); + try { + await spawn('open', [binaryPath]); + } + catch (error) { + throw new RockError('Failed to launch the app', { + cause: error.stderr, + }); + } +} +//# sourceMappingURL=runOnMac.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js.map new file mode 100644 index 000000000..c1f499e6a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runOnMac.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnMac.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB;IAC/C,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,0BAA0B,EAAE;YAC9C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.d.ts new file mode 100644 index 000000000..482491548 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.d.ts @@ -0,0 +1 @@ +export declare function runOnMacCatalyst(binaryPath: string, scheme: string): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js new file mode 100644 index 000000000..343104e9a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js @@ -0,0 +1,9 @@ +import { spawn } from '@rock-js/tools'; +export async function runOnMacCatalyst(binaryPath, scheme) { + const appProcess = spawn(`${binaryPath}/${scheme}`, [], { + detached: true, + stdio: 'ignore', + }); + (await appProcess.nodeChildProcess).unref(); +} +//# sourceMappingURL=runOnMacCatalyst.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js.map new file mode 100644 index 000000000..8cd6646a0 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runOnMacCatalyst.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnMacCatalyst.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAkB,EAAE,MAAc;IACvE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,UAAU,IAAI,MAAM,EAAE,EAAE,EAAE,EAAE;QACtD,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IACH,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,CAAC;AAC9C,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.d.ts new file mode 100644 index 000000000..f964fbfef --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.d.ts @@ -0,0 +1,5 @@ +import type { Device } from '../../types/index.js'; +export declare function launchSimulator(device: Device): Promise; +export declare function runOnSimulator(device: Device, binaryPath: string, infoPlistPath: string): Promise; +export default function installAppOnSimulator(udid: string, binaryPath: string): Promise; +export declare function launchAppOnSimulator(udid: string, binaryPath: string, infoPlistPath: string): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js new file mode 100644 index 000000000..4d0bb353d --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js @@ -0,0 +1,85 @@ +import path from 'node:path'; +import { color, logger, RockError, spawn, spinner } from '@rock-js/tools'; +import { readKeyFromPlist } from '../../utils/plist.js'; +export async function launchSimulator(device) { + if (device.type !== 'simulator') { + // bail if device is not a simulator + return undefined; + } + /** + * Booting simulator through `xcrun simctl boot` will boot it in the `headless` mode + * (running in the background). + * + * In order for user to see the app and the simulator itself, we have to make sure + * that the Simulator.app is running. + * + * We also pass it `-CurrentDeviceUDID` so that when we launch it for the first time, + * it will not boot the "default" device, but the one we set. If the app is already running, + * this flag has no effect. + */ + const { output: activeDeveloperDir } = await spawn('xcode-select', ['-p'], { + stdio: 'pipe', + }); + await spawn('open', [ + `${activeDeveloperDir}/Applications/Simulator.app`, + '--args', + '-CurrentDeviceUDID', + device.udid, + ]); + if (device.state !== 'Booted') { + await bootSimulator(device); + } +} +export async function runOnSimulator(device, binaryPath, infoPlistPath) { + const loader = spinner(); + loader.start(`Installing the app on ${color.bold(device.name)}`); + await installAppOnSimulator(device.udid, binaryPath); + loader.message(`Launching the app on ${color.bold(device.name)}`); + await launchAppOnSimulator(device.udid, binaryPath, infoPlistPath); + loader.stop(`Installed and launched the app on ${color.bold(device.name)}.`); +} +async function bootSimulator(selectedSimulator) { + try { + await spawn('xcrun', ['simctl', 'boot', selectedSimulator.udid]); + } + catch (error) { + if ( + // It may happen on GitHub Actions when the simulator is already booted, + // even though the simctl returns its state as Shutdown + error.stderr.includes('Unable to boot device in current state: Booted')) { + logger.debug(`Simulator ${selectedSimulator.udid} already booted. Skipping.`); + return; + } + throw new RockError('Failed to boot Simulator', { + cause: error.stderr, + }); + } +} +export default async function installAppOnSimulator(udid, binaryPath) { + logger.debug(`Installing "${path.basename(binaryPath)}"`); + try { + await spawn('xcrun', ['simctl', 'install', udid, binaryPath]); + } + catch (error) { + throw new RockError('Failed to install the app on Simulator', { + cause: error.stderr, + }); + } +} +export async function launchAppOnSimulator(udid, binaryPath, infoPlistPath) { + const infoPlist = binaryPath + ? // @todo Info.plist is hardcoded when reading from binaryPath + path.join(binaryPath, 'Info.plist') + : infoPlistPath; + const bundleID = await readKeyFromPlist(infoPlist, 'CFBundleIdentifier'); + logger.debug(`Launching "${bundleID}"`); + try { + await spawn('xcrun', ['simctl', 'launch', udid, bundleID]); + } + catch (error) { + throw new RockError(`Failed to launch the app on Simulator`, { + cause: error.stderr, + }); + } +} +//# sourceMappingURL=runOnSimulator.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js.map new file mode 100644 index 000000000..811d47450 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runOnSimulator.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnSimulator.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.d.ts new file mode 100644 index 000000000..db61c0646 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.d.ts @@ -0,0 +1,30 @@ +import type { BuilderCommand } from '../../types/index.js'; +import type { BuildFlags } from '../build/buildOptions.js'; +export interface RunFlags extends BuildFlags { + binaryPath?: string; + port: string; + device?: string; + catalyst?: boolean; + local?: boolean; + devServer?: boolean; + clientLogs?: boolean; +} +export declare const getRunOptions: ({ platformName }: BuilderCommand) => ({ + name: string; + description: string; + parse?: undefined; + value?: undefined; +} | { + name: string; + description: string; + parse: typeof import("packages/tools/dist/src/index.js").parseArgs; + value?: undefined; +} | { + name: string; + description: string; + value: string; + parse?: undefined; +} | { + name: string; + default: string; +})[]; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js new file mode 100644 index 000000000..dd9c9cc32 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js @@ -0,0 +1,31 @@ +import { getBuildOptions } from '../build/buildOptions.js'; +export const getRunOptions = ({ platformName }) => { + return [ + { + name: '--port ', + default: process.env['RCT_METRO_PORT'] || '8081', + }, + { + name: '--binary-path ', + description: 'Path relative to project root where pre-built .app binary lives.', + }, + { + name: '--device ', + description: 'Explicitly set the device or simulator to use by name or by UDID.', + }, + { + name: '--catalyst', + description: 'Run on Mac Catalyst.', + }, + { + name: '--client-logs', + description: 'Enable client logs in dev server.', + }, + { + name: '--dev-server', + description: 'Automatically start a dev server (bundler) after building the app.', + }, + ...getBuildOptions({ platformName }), + ]; +}; +//# sourceMappingURL=runOptions.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js.map new file mode 100644 index 000000000..640506fcf --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runOptions.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOptions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAY3D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,YAAY,EAAkB,EAAE,EAAE;IAChE,OAAO;QACL;YACE,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,MAAM;SACjD;QACD;YACE,IAAI,EAAE,wBAAwB;YAC9B,WAAW,EACT,kEAAkE;SACrE;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EACT,mEAAmE;SACtE;QACD;YACE,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,sBAAsB;SACpC;QACD;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,mCAAmC;SACjD;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,oEAAoE;SAClF;QACD,GAAG,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;KACrC,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.d.ts new file mode 100644 index 000000000..de6f3f978 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.d.ts @@ -0,0 +1,11 @@ +type BuildJsBundleOptions = { + bundleOutputPath: string; + assetsDestPath: string; + useHermes?: boolean; + sourcemapOutputPath?: string; +}; +/** + * This function is modelled after [react-native-xcode.sh](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react-native-xcode.sh). + */ +export declare function buildJsBundle(options: BuildJsBundleOptions): Promise; +export {}; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js new file mode 100644 index 000000000..1ef33abc2 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js @@ -0,0 +1,49 @@ +import fs from 'node:fs'; +import { logger, RockError, runHermes, spawn } from '@rock-js/tools'; +/** + * This function is modelled after [react-native-xcode.sh](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react-native-xcode.sh). + */ +export async function buildJsBundle(options) { + if (fs.existsSync(options.bundleOutputPath)) { + fs.unlinkSync(options.bundleOutputPath); + logger.debug('Removed existing JS bundle:', options.bundleOutputPath); + } + // Reasonable defaults + // If user wants to build bundle differently, they should use `rock bundle` command directly + // and provide the JS bundle path to `--jsbundle` flag + const rockBundleArgs = [ + 'bundle', + `--entry-file`, + `index.js`, + '--platform', + 'ios', + `--dev`, + 'false', + '--minify', + 'false', + '--reset-cache', + '--bundle-output', + options.bundleOutputPath, + '--assets-dest', + options.assetsDestPath, + ...(options.sourcemapOutputPath + ? ['--sourcemap-output', options.sourcemapOutputPath] + : []), + ]; + try { + await spawn('rock', rockBundleArgs, { preferLocal: true }); + } + catch (error) { + throw new RockError('Failed to build JS bundle', { + cause: error.stderr, + }); + } + if (!options.useHermes) { + return; + } + await runHermes({ + bundleOutputPath: options.bundleOutputPath, + sourcemapOutputPath: options.sourcemapOutputPath, + }); +} +//# sourceMappingURL=bundle.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js.map new file mode 100644 index 000000000..8a2a4c54b --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AASrE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5C,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxE,CAAC;IAED,sBAAsB;IACtB,4FAA4F;IAC5F,sDAAsD;IACtD,MAAM,cAAc,GAAG;QACrB,QAAQ;QACR,cAAc;QACd,UAAU;QACV,YAAY;QACZ,KAAK;QACL,OAAO;QACP,OAAO;QACP,UAAU;QACV,OAAO;QACP,eAAe;QACf,iBAAiB;QACjB,OAAO,CAAC,gBAAgB;QACxB,eAAe;QACf,OAAO,CAAC,cAAc;QACtB,GAAG,CAAC,OAAO,CAAC,mBAAmB;YAC7B,CAAC,CAAC,CAAC,oBAAoB,EAAE,OAAO,CAAC,mBAAmB,CAAC;YACrD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,2BAA2B,EAAE;YAC/C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC;QACd,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.d.ts new file mode 100644 index 000000000..6c5d33a92 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.d.ts @@ -0,0 +1,8 @@ +export type ModifyAppOptions = { + appPath: string; + outputPath?: string; + buildJsBundle?: boolean; + jsBundlePath?: string; + useHermes?: boolean; +}; +export declare const modifyApp: (options: ModifyAppOptions) => Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js new file mode 100644 index 000000000..fa2ac99cc --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js @@ -0,0 +1,48 @@ +import fs from 'node:fs'; +import { colorLink, intro, logger, outro, relativeToCwd, RockError, spinner, } from '@rock-js/tools'; +import { buildJsBundle } from './bundle.js'; +import { getAppPaths } from './utils.js'; +export const modifyApp = async (options) => { + validateOptions(options); + intro(`Modifying APP file`); + const loader = spinner(); + // 1. Copy APP file to output path if provided + if (options.outputPath) { + try { + fs.cpSync(options.appPath, options.outputPath, { recursive: true }); + } + catch (error) { + throw new RockError(`Failed to copy APP file to ${colorLink(relativeToCwd(options.outputPath))}.`, { cause: error }); + } + } + // 2. Make APP content changes if needed: build or swap JS bundle + const appPaths = getAppPaths(options.outputPath ?? options.appPath); + if (options.buildJsBundle) { + loader.start('Building JS bundle'); + await buildJsBundle({ + bundleOutputPath: appPaths.jsBundle, + assetsDestPath: appPaths.assetsDest, + useHermes: options.useHermes ?? true, + }); + loader.stop(`Built JS bundle: ${colorLink(relativeToCwd(appPaths.jsBundle))}`); + } + else if (options.jsBundlePath) { + loader.start('Replacing JS bundle'); + fs.copyFileSync(options.jsBundlePath, appPaths.jsBundle); + loader.stop(`Replaced JS bundle with ${colorLink(relativeToCwd(options.jsBundlePath))}`); + } + logger.log(`Modified APP file with new JS bundle. Available at: ${colorLink(relativeToCwd(options.outputPath ?? options.appPath))}`); + outro('Success ๐ŸŽ‰.'); +}; +function validateOptions(options) { + if (!fs.existsSync(options.appPath)) { + throw new RockError(`APP file (directory) not found at "${options.appPath}". Please provide a correct path.`); + } + if (options.buildJsBundle && options.jsBundlePath) { + throw new RockError('The "--build-jsbundle" flag is incompatible with "--jsbundle". Pick one.'); + } + if (options.jsBundlePath && !fs.existsSync(options.jsBundlePath)) { + throw new RockError(`JS bundle file not found at "${options.jsBundlePath}". Please provide a correct path.`); + } +} +//# sourceMappingURL=modifyApp.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js.map new file mode 100644 index 000000000..8e43c8260 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js.map @@ -0,0 +1 @@ +{"version":3,"file":"modifyApp.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/modifyApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,KAAK,EACL,aAAa,EACb,SAAS,EACT,OAAO,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAUzC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC3D,eAAe,CAAC,OAAO,CAAC,CAAC;IAEzB,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAE5B,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IAEzB,8CAA8C;IAC9C,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,SAAS,CACjB,8BAA8B,SAAS,CACrC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAClC,GAAG,EACJ,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACnC,MAAM,aAAa,CAAC;YAClB,gBAAgB,EAAE,QAAQ,CAAC,QAAQ;YACnC,cAAc,EAAE,QAAQ,CAAC,UAAU;YACnC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CACT,oBAAoB,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACpC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CACT,2BAA2B,SAAS,CAClC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CACpC,EAAE,CACJ,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,GAAG,CACR,uDAAuD,SAAS,CAC9D,aAAa,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CACrD,EAAE,CACJ,CAAC;IAEF,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,OAAyB;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CACjB,sCAAsC,OAAO,CAAC,OAAO,mCAAmC,CACzF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CACjB,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,SAAS,CACjB,gCAAgC,OAAO,CAAC,YAAY,mCAAmC,CACxF,CAAC;IACJ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.d.ts new file mode 100644 index 000000000..9ad991bdf --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.d.ts @@ -0,0 +1,10 @@ +export type ModifyIpaOptions = { + platformName: string; + ipaPath: string; + identity?: string; + outputPath?: string; + buildJsBundle?: boolean; + jsBundlePath?: string; + useHermes?: boolean; +}; +export declare const modifyIpa: (options: ModifyIpaOptions) => Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js new file mode 100644 index 000000000..88e9fefe3 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js @@ -0,0 +1,85 @@ +import fs from 'node:fs'; +import { color, colorLink, intro, isInteractive, logger, outro, relativeToCwd, RockError, spawn, spinner, } from '@rock-js/tools'; +import { promptSigningIdentity } from '../../utils/signingIdentities.js'; +import { buildJsBundle } from './bundle.js'; +import { decodeProvisioningProfileToPlist, generateEntitlementsPlist, getIdentityFromProvisioningPlist, } from './provisioningProfile.js'; +import { getAppPaths, getTempPaths, packIpa, unpackIpa } from './utils.js'; +export const modifyIpa = async (options) => { + validateOptions(options); + intro(`Modifying IPA file`); + // 1. Extract IPA contents + const loader = spinner(); + loader.start(`Unzipping the IPA file`); + const tempPaths = getTempPaths(options.platformName); + const appPath = unpackIpa(options.ipaPath, tempPaths.content); + loader.stop(`Unzipped IPA contents: ${colorLink(relativeToCwd(appPath))}`); + // 2. Make IPA content changes if needed: build or swap JS bundle + const appPaths = getAppPaths(appPath); + if (options.buildJsBundle) { + loader.start('Building JS bundle'); + await buildJsBundle({ + bundleOutputPath: appPaths.jsBundle, + assetsDestPath: appPaths.assetsDest, + useHermes: options.useHermes ?? true, + }); + loader.stop(`Built JS bundle: ${colorLink(relativeToCwd(appPaths.jsBundle))}`); + } + else if (options.jsBundlePath) { + loader.start('Replacing JS bundle'); + fs.copyFileSync(options.jsBundlePath, appPaths.jsBundle); + loader.stop(`Replaced JS bundle with ${colorLink(relativeToCwd(options.jsBundlePath))}`); + } + // 3. Sign the IPA contents + await decodeProvisioningProfileToPlist(appPaths.provisioningProfile, tempPaths.provisioningPlist); + let identity = options.identity; + if (!identity) { + const currentIdentity = await getIdentityFromProvisioningPlist(tempPaths.provisioningPlist); + if (currentIdentity) { + logger.debug(`Extracted identity from provisioning profile: ${currentIdentity}`); + } + identity = await promptSigningIdentity(currentIdentity); + } + loader.start('Signing the app'); + await generateEntitlementsPlist({ + provisioningPlistPath: tempPaths.provisioningPlist, + outputPath: tempPaths.entitlementsPlist, + }); + const codeSignArgs = [ + '--force', + '--sign', + identity, + '--entitlements', + tempPaths.entitlementsPlist, + appPath, + ]; + try { + await spawn('codesign', codeSignArgs, { cwd: tempPaths.content }); + } + catch (error) { + throw new RockError('Codesign failed', { + cause: error.stderr, + }); + } + loader.stop(`Signed the IPA contents with identity: ${color.cyan(identity)}`); + // 4. Repack the IPA file + loader.start('Creating final IPA file'); + const outputPath = options.outputPath ?? options.ipaPath; + packIpa(tempPaths.content, outputPath); + loader.stop(`Created final IPA file: ${colorLink(outputPath)}`); + outro('Success ๐ŸŽ‰.'); +}; +function validateOptions(options) { + if (!fs.existsSync(options.ipaPath)) { + throw new RockError(`IPA file not found at "${options.ipaPath}". Please provide a correct path.`); + } + if (!options.identity && !isInteractive()) { + throw new RockError('The "--identity" flag is required in non-interactive environments, such as CI. Please pass one.'); + } + if (options.buildJsBundle && options.jsBundlePath) { + throw new RockError('The "--build-jsbundle" flag is incompatible with "--jsbundle". Pick one.'); + } + if (options.jsBundlePath && !fs.existsSync(options.jsBundlePath)) { + throw new RockError(`JS bundle file not found at "${options.jsBundlePath}". Please provide a correct path.`); + } +} +//# sourceMappingURL=modifyIpa.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js.map new file mode 100644 index 000000000..c41216bbd --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js.map @@ -0,0 +1 @@ +{"version":3,"file":"modifyIpa.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/modifyIpa.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.d.ts new file mode 100644 index 000000000..bfa3639e9 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.d.ts @@ -0,0 +1,27 @@ +/** + * Decodes provisioning profile to XML plist. + * @param profilePath - Path to the provisioning profile. + * @param outputPath - Path to the output plist file. + */ +export declare function decodeProvisioningProfileToPlist(profilePath: string, outputPath: string): Promise; +export type GenerateEntitlementsFileOptions = { + provisioningPlistPath: string; + outputPath: string; +}; +/** + * Generates entitlements plist from provisioning profile plist. + * @param provisioningPlistPath - Path to the provisioning profile plist. + * @param outputPath - Path to the output entitlements plist file. + */ +export declare const generateEntitlementsPlist: ({ outputPath, provisioningPlistPath, }: GenerateEntitlementsFileOptions) => Promise; +/** + * Extract code sign identity from provisioning profile plist file. + * @param plistPath - Path to the provisioning profile plist file. + * @returns Code sign identity name. + */ +export declare function getIdentityFromProvisioningPlist(plistPath: string): Promise; +/** + * Extracts certificate name used from subject field. This names corresponds to + * the name of the signing identity. + */ +export declare function extractCertificateName(subject: string): string | null; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js new file mode 100644 index 000000000..fda52fd3d --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js @@ -0,0 +1,50 @@ +import crypto from 'node:crypto'; +import fs from 'node:fs'; +import { logger, relativeToCwd, RockError, spawn } from '@rock-js/tools'; +import { readBufferFromPlist, readKeyFromPlist } from '../../utils/plist.js'; +/** + * Decodes provisioning profile to XML plist. + * @param profilePath - Path to the provisioning profile. + * @param outputPath - Path to the output plist file. + */ +export async function decodeProvisioningProfileToPlist(profilePath, outputPath) { + try { + await spawn('security', ['cms', '-D', '-i', profilePath, '-o', outputPath]); + logger.debug(`Decoded provisioning profile to plist: ${relativeToCwd(outputPath)}`); + } + catch (error) { + throw new RockError(`Failed to decode provisioning profile: ${profilePath}`, { cause: error.stderr }); + } +} +/** + * Generates entitlements plist from provisioning profile plist. + * @param provisioningPlistPath - Path to the provisioning profile plist. + * @param outputPath - Path to the output entitlements plist file. + */ +export const generateEntitlementsPlist = async ({ outputPath, provisioningPlistPath, }) => { + const entitlements = await readKeyFromPlist(provisioningPlistPath, 'Entitlements', { + xml: true, + }); + fs.writeFileSync(outputPath, entitlements); + logger.debug(`Generated entitlements file: ${relativeToCwd(outputPath)}`); +}; +/** + * Extract code sign identity from provisioning profile plist file. + * @param plistPath - Path to the provisioning profile plist file. + * @returns Code sign identity name. + */ +export async function getIdentityFromProvisioningPlist(plistPath) { + const cert = await readBufferFromPlist(plistPath, 'DeveloperCertificates:0'); + const decodedCert = new crypto.X509Certificate(cert); + return extractCertificateName(decodedCert.subject); +} +/** + * Extracts certificate name used from subject field. This names corresponds to + * the name of the signing identity. + */ +export function extractCertificateName(subject) { + const regex = /CN=(.+)$/m; + const match = subject.match(regex); + return match ? match[1] : null; +} +//# sourceMappingURL=provisioningProfile.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js.map new file mode 100644 index 000000000..2021cc096 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js.map @@ -0,0 +1 @@ +{"version":3,"file":"provisioningProfile.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/provisioningProfile.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,WAAmB,EACnB,UAAkB;IAElB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CACV,0CAA0C,aAAa,CAAC,UAAU,CAAC,EAAE,CACtE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,0CAA0C,WAAW,EAAE,EACvD,EAAE,KAAK,EAAG,KAAyB,CAAC,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;AACH,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAAE,EAC9C,UAAU,EACV,qBAAqB,GACW,EAAE,EAAE;IACpC,MAAM,YAAY,GAAG,MAAM,gBAAgB,CACzC,qBAAqB,EACrB,cAAc,EACd;QACE,GAAG,EAAE,IAAI;KACV,CACF,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,gCAAgC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,SAAiB;IACtE,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,sBAAsB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,MAAM,KAAK,GAAG,WAAW,CAAC;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.d.ts new file mode 100644 index 000000000..a2d22de90 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.d.ts @@ -0,0 +1,40 @@ +/** + * Temporary paths for sign operation. + * @param platformName - Platform name. + */ +export declare function getTempPaths(platformName: string): { + /** Root path for sign operation. */ + root: string; + /** Path to extracted IPA contents. */ + content: string; + /** Path to the temporary provisioning plist. */ + provisioningPlist: string; + /** Path to the temporary entitlements plist. */ + entitlementsPlist: string; +}; +/** + * Paths inside .app directory in extracted IPA file. + * @param appPath - Path to the .app directory. + */ +export declare function getAppPaths(appPath: string): { + /** Path to assets directory. */ + assetsDest: string; + /** Path to the JS bundle. */ + jsBundle: string; + /** Path to embedded provisioning profile. */ + provisioningProfile: string; +}; +/** + * Unpack IPA file contents to given path. + * @param ipaPath - Path to the IPA file. + * @param destination - Path to the destination folder. + * @returns Path to .app directory (package) inside the IPA file. + */ +export declare const unpackIpa: (ipaPath: string, destination: string) => string; +/** + * Pack IPA file from content path. + * @param contentPath - Path to pack as IPA contents. + * @param ipaPath - Path to the output IPA file. + * @returns Path to the output IPA file. + */ +export declare const packIpa: (contentPath: string, ipaPath: string) => string; diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js new file mode 100644 index 000000000..cfc9a22a6 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js @@ -0,0 +1,74 @@ +import { existsSync, mkdirSync, rmSync } from 'node:fs'; +import path from 'node:path'; +import { findDirectoriesWithPattern, getDotRockPath, RockError, } from '@rock-js/tools'; +import AdmZip from 'adm-zip'; +/** + * Temporary paths for sign operation. + * @param platformName - Platform name. + */ +export function getTempPaths(platformName) { + const root = path.join(getDotRockPath(), platformName, 'sign'); + return { + /** Root path for sign operation. */ + root, + /** Path to extracted IPA contents. */ + content: path.join(root, 'content'), + /** Path to the temporary provisioning plist. */ + provisioningPlist: path.join(root, 'provisioning.plist'), + /** Path to the temporary entitlements plist. */ + entitlementsPlist: path.join(root, 'entitlements.plist'), + }; +} +/** + * Paths inside .app directory in extracted IPA file. + * @param appPath - Path to the .app directory. + */ +export function getAppPaths(appPath) { + return { + /** Path to assets directory. */ + assetsDest: path.join(appPath, 'assets'), + /** Path to the JS bundle. */ + jsBundle: path.join(appPath, 'main.jsbundle'), + /** Path to embedded provisioning profile. */ + provisioningProfile: path.join(appPath, 'embedded.mobileprovision'), + }; +} +/** + * Unpack IPA file contents to given path. + * @param ipaPath - Path to the IPA file. + * @param destination - Path to the destination folder. + * @returns Path to .app directory (package) inside the IPA file. + */ +export const unpackIpa = (ipaPath, destination) => { + if (existsSync(destination)) { + rmSync(destination, { recursive: true, force: true }); + } + mkdirSync(destination, { recursive: true }); + const zip = new AdmZip(ipaPath); + zip.extractAllTo(destination, true); + const payloadPath = `${destination}/Payload`; + if (!existsSync(payloadPath)) { + throw new Error('Payload folder not found in the extracted IPA file'); + } + const appPath = findDirectoriesWithPattern(payloadPath, /\.app$/)[0]; + if (!appPath) { + throw new RockError(`.app package not found in the extracted IPA file ${payloadPath}`); + } + return appPath; +}; +/** + * Pack IPA file from content path. + * @param contentPath - Path to pack as IPA contents. + * @param ipaPath - Path to the output IPA file. + * @returns Path to the output IPA file. + */ +export const packIpa = (contentPath, ipaPath) => { + if (existsSync(ipaPath)) { + rmSync(ipaPath, { recursive: true, force: true }); + } + const zip = new AdmZip(); + zip.addLocalFolder(contentPath); + zip.writeZip(ipaPath); + return ipaPath; +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js.map new file mode 100644 index 000000000..238c7ef5b --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,YAAoB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;IAC/D,OAAO;QACL,oCAAoC;QACpC,IAAI;QACJ,sCAAsC;QACtC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACnC,gDAAgD;QAChD,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC;QACxD,gDAAgD;QAChD,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC;KACzD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO;QACL,gCAAgC;QAChC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;QACxC,6BAA6B;QAC7B,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;QAC7C,6CAA6C;QAC7C,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC;KACpE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,WAAmB,EAAU,EAAE;IACxE,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAEpC,MAAM,WAAW,GAAG,GAAG,WAAW,UAAU,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,OAAO,GAAG,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CACjB,oDAAoD,WAAW,EAAE,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,WAAmB,EAAE,OAAe,EAAE,EAAE;IAC9D,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;IACzB,GAAG,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IAChC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEtB,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/index.d.ts b/packages/platform-apple-helpers/dist/src/lib/index.d.ts new file mode 100644 index 000000000..2c592387a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/index.d.ts @@ -0,0 +1,12 @@ +export { createBuild } from './commands/build/createBuild.js'; +export { createRun } from './commands/run/createRun.js'; +export { getBuildOptions, BuildFlags } from './commands/build/buildOptions.js'; +export { getRunOptions, RunFlags } from './commands/run/runOptions.js'; +export { modifyIpa, type ModifyIpaOptions } from './commands/sign/modifyIpa.js'; +export { modifyApp, type ModifyAppOptions } from './commands/sign/modifyApp.js'; +export { genericDestinations } from './utils/destionation.js'; +export { getBuildPaths } from './utils/getBuildPaths.js'; +export { getInfo } from './utils/getInfo.js'; +export { getScheme } from './utils/getScheme.js'; +export { getValidProjectConfig } from './utils/getValidProjectConfig.js'; +export { promptSigningIdentity } from './utils/signingIdentities.js'; diff --git a/packages/platform-apple-helpers/dist/src/lib/index.js b/packages/platform-apple-helpers/dist/src/lib/index.js new file mode 100644 index 000000000..b6bf4b10a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/index.js @@ -0,0 +1,13 @@ +export { createBuild } from './commands/build/createBuild.js'; +export { createRun } from './commands/run/createRun.js'; +export { getBuildOptions } from './commands/build/buildOptions.js'; +export { getRunOptions } from './commands/run/runOptions.js'; +export { modifyIpa } from './commands/sign/modifyIpa.js'; +export { modifyApp } from './commands/sign/modifyApp.js'; +export { genericDestinations } from './utils/destionation.js'; +export { getBuildPaths } from './utils/getBuildPaths.js'; +export { getInfo } from './utils/getInfo.js'; +export { getScheme } from './utils/getScheme.js'; +export { getValidProjectConfig } from './utils/getValidProjectConfig.js'; +export { promptSigningIdentity } from './utils/signingIdentities.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/index.js.map b/packages/platform-apple-helpers/dist/src/lib/index.js.map new file mode 100644 index 000000000..616d7c2cc --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAc,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAY,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,SAAS,EAAyB,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,SAAS,EAAyB,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/types/index.d.ts b/packages/platform-apple-helpers/dist/src/lib/types/index.d.ts new file mode 100644 index 000000000..a6bba7827 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/types/index.d.ts @@ -0,0 +1,35 @@ +import type { supportedPlatforms } from '../utils/supportedPlatforms.js'; +type ObjectValues = T[keyof T]; +export type ApplePlatform = ObjectValues; +export interface Device { + name: string; + udid: string; + version: string; + platform: ApplePlatform | undefined; + type: DeviceType; + state: 'Booted' | 'Shutdown'; +} +export type DeviceType = 'simulator' | 'device'; +export interface Info { + name: string; + schemes?: string[]; + configurations?: string[]; + targets?: string[]; +} +export interface BuilderCommand { + platformName: ApplePlatform; +} +export interface XcodeProjectInfo { + name: string; + path: string; + isWorkspace: boolean; +} +export interface Params { + sourceDir?: string; + assets?: string[]; +} +export interface ProjectConfig { + sourceDir: string; + xcodeProject: XcodeProjectInfo; +} +export {}; diff --git a/packages/platform-apple-helpers/dist/src/lib/types/index.js b/packages/platform-apple-helpers/dist/src/lib/types/index.js new file mode 100644 index 000000000..f8a711af8 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/types/index.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/types/index.js.map b/packages/platform-apple-helpers/dist/src/lib/types/index.js.map new file mode 100644 index 000000000..c65e2c333 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/types/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/types/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js new file mode 100644 index 000000000..a62db64a7 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js @@ -0,0 +1,40 @@ +import { describe, expect, it } from 'vitest'; +import { parseSigningIdentities } from '../signingIdentities.js'; +describe('parseSigningIdentities', () => { + it('should parse valid signing identities output', () => { + const input = ` + 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)" + 2) ABCDEF1234567890ABCDEF1234567890ABCDEF12 "Apple Distribution: Jane Smith (TEAMID5678)" + `; + const result = parseSigningIdentities(input); + expect(result).toEqual([ + { + hash: '1234567890ABCDEF1234567890ABCDEF12345678', + name: 'Apple Development: John Doe (TEAMID1234)', + }, + { + hash: 'ABCDEF1234567890ABCDEF1234567890ABCDEF12', + name: 'Apple Distribution: Jane Smith (TEAMID5678)', + }, + ]); + }); + it('should handle empty input', () => { + const result = parseSigningIdentities(''); + expect(result).toEqual([]); + }); + it('should handle input with invalid lines', () => { + const input = ` + Invalid line + 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)" + Another invalid line + `; + const result = parseSigningIdentities(input); + expect(result).toEqual([ + { + hash: '1234567890ABCDEF1234567890ABCDEF12345678', + name: 'Apple Development: John Doe (TEAMID1234)', + }, + ]); + }); +}); +//# sourceMappingURL=signgningIdentity.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js.map new file mode 100644 index 000000000..f5c0e9a58 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js.map @@ -0,0 +1 @@ +{"version":3,"file":"signgningIdentity.js","sourceRoot":"","sources":["../../../../../src/lib/utils/__tests__/signgningIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG;;;KAGb,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB;gBACE,IAAI,EAAE,0CAA0C;gBAChD,IAAI,EAAE,0CAA0C;aACjD;YACD;gBACE,IAAI,EAAE,0CAA0C;gBAChD,IAAI,EAAE,6CAA6C;aACpD;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,KAAK,GAAG;;;;KAIb,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB;gBACE,IAAI,EAAE,0CAA0C;gBAChD,IAAI,EAAE,0CAA0C;aACjD;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.d.ts new file mode 100644 index 000000000..175c3556e --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.d.ts @@ -0,0 +1,27 @@ +import type { IOSProjectConfig } from '@react-native-community/cli-types'; +import { type FingerprintSources } from '@rock-js/tools'; +import type { BuildFlags } from '../commands/build/buildOptions.js'; +import type { RunFlags } from '../commands/run/runOptions.js'; +import type { ApplePlatform, ProjectConfig } from '../types/index.js'; +export declare function buildApp({ args, projectConfig, pluginConfig, platformName, udid, projectRoot, deviceName, reactNativePath, binaryPath, brownfield, artifactName, fingerprintOptions, deviceOrSimulator, }: { + args: RunFlags | BuildFlags; + projectConfig: ProjectConfig; + pluginConfig?: IOSProjectConfig; + platformName: ApplePlatform; + udid?: string; + deviceName?: string; + projectRoot: string; + reactNativePath: string; + binaryPath?: string; + brownfield?: boolean; + artifactName: string; + fingerprintOptions: FingerprintSources; + deviceOrSimulator: string; +}): Promise<{ + appPath: string; + bundleIdentifier: any; + infoPlistPath: string; + scheme: string | undefined; + xcodeProject: import("../types/index.js").XcodeProjectInfo; + sourceDir: string; +}>; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js new file mode 100644 index 000000000..50937a5a2 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js @@ -0,0 +1,116 @@ +import path from 'node:path'; +import { formatArtifactName, getInfoPlist, RockError, saveLocalBuildCache, } from '@rock-js/tools'; +import { buildProject } from '../commands/build/buildProject.js'; +import { getBuildSettings } from '../commands/run/getBuildSettings.js'; +import { getGenericDestination } from './destionation.js'; +import { getConfiguration } from './getConfiguration.js'; +import { getInfo } from './getInfo.js'; +import { getScheme } from './getScheme.js'; +import { getValidProjectConfig } from './getValidProjectConfig.js'; +import { installPodsIfNeeded } from './pods.js'; +export async function buildApp({ args, projectConfig, pluginConfig, platformName, udid, projectRoot, deviceName, reactNativePath, binaryPath, brownfield, artifactName, fingerprintOptions, deviceOrSimulator, }) { + if (binaryPath) { + // @todo Info.plist is hardcoded when reading from binaryPath + const infoPlistPath = path.join(binaryPath, 'Info.plist'); + const infoPlistJson = await getInfoPlist(infoPlistPath); + const bundleIdentifier = infoPlistJson?.['CFBundleIdentifier'] ?? 'unknown'; + return { + appPath: binaryPath, + bundleIdentifier, + infoPlistPath, + scheme: args.scheme, + xcodeProject: projectConfig.xcodeProject, + sourceDir: projectConfig.sourceDir, + }; + } + let artifactNameToSave = artifactName; + let { xcodeProject, sourceDir } = projectConfig; + if (args.installPods) { + const didInstallPods = await installPodsIfNeeded(projectRoot, platformName, sourceDir, args.newArch, reactNativePath, brownfield); + // When the project is not a workspace, we need to get the project config again, + // because running pods install might have generated .xcworkspace project. + // This should be only case in new project. + if (xcodeProject.isWorkspace === false) { + const newProjectConfig = getValidProjectConfig(platformName, projectRoot, pluginConfig); + xcodeProject = newProjectConfig.xcodeProject; + sourceDir = newProjectConfig.sourceDir; + } + if (didInstallPods) { + // After installing pods the fingerprint likely changes. + // We update the artifact name to reflect the new fingerprint and store proper entry in the local cache. + artifactNameToSave = await formatArtifactName({ + platform: 'ios', + traits: [deviceOrSimulator, args.configuration ?? 'Debug'], + root: projectRoot, + fingerprintOptions, + type: 'update', + }); + } + } + const info = await getInfo(xcodeProject, sourceDir); + if (!info) { + throw new RockError('Failed to get Xcode project information'); + } + const scheme = await getScheme(info.schemes, args.scheme, xcodeProject.name); + const configuration = await getConfiguration(info.configurations, args.configuration); + const destinations = determineDestinations({ + destination: args.destination, + isCatalyst: 'catalyst' in args && args.catalyst, + platformName, + udid, + deviceName, + }); + await buildProject({ + xcodeProject, + sourceDir, + platformName, + scheme, + configuration, + destinations, + args, + }); + const buildSettings = await getBuildSettings({ + xcodeProject, + sourceDir, + platformName, + configuration, + destinations, + scheme, + target: args.target, + buildFolder: args.buildFolder, + }); + saveLocalBuildCache(artifactNameToSave, buildSettings.appPath); + return { + appPath: buildSettings.appPath, + infoPlistPath: buildSettings.infoPlistPath, + scheme: scheme, + xcodeProject, + sourceDir, + bundleIdentifier: buildSettings.bundleIdentifier, + }; +} +function determineDestinations({ destination, isCatalyst, platformName, udid, deviceName, }) { + if (isCatalyst) { + return ['platform=macOS,variant=Mac Catalyst']; + } + if (udid) { + return [`id=${udid}`]; + } + if (deviceName) { + return [`name=${deviceName}`]; + } + if (destination && destination.length > 0) { + return destination.map((destination) => resolveDestination(destination, platformName)); + } + return [getGenericDestination(platformName, 'device')]; +} +function resolveDestination(destination, platformName) { + if (destination === 'device') { + return getGenericDestination(platformName, 'device'); + } + if (destination === 'simulator') { + return getGenericDestination(platformName, 'simulator'); + } + return destination; +} +//# sourceMappingURL=buildApp.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js.map new file mode 100644 index 000000000..136bd6fb5 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buildApp.js","sourceRoot":"","sources":["../../../../src/lib/utils/buildApp.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/codegen.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.d.ts new file mode 100644 index 000000000..597e5953c --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.d.ts @@ -0,0 +1,9 @@ +import type { ApplePlatform } from '../types/index.js'; +interface CodegenOptions { + projectRoot: string; + platformName: ApplePlatform; + reactNativePath: string; + sourceDir: string; +} +declare function runCodegen(options: CodegenOptions): Promise; +export default runCodegen; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js new file mode 100644 index 000000000..c9fa9a7d2 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js @@ -0,0 +1,29 @@ +import { spawn } from '@rock-js/tools'; +import { RockError } from '@rock-js/tools'; +import fs from 'fs'; +import path from 'path'; +async function runCodegen(options) { + const buildDir = path.join(options.sourceDir, 'build'); + if (fs.existsSync(buildDir)) { + fs.rmSync(buildDir, { recursive: true }); + } + const codegenScript = path.join(options.reactNativePath, 'scripts/generate-codegen-artifacts.js'); + try { + await spawn('node', [ + codegenScript, + '-p', + options.projectRoot, + '-o', + options.sourceDir, + '-t', + options.platformName, + ]); + } + catch (error) { + throw new RockError('Failed to run React Native codegen script', { + cause: error.output, + }); + } +} +export default runCodegen; +//# sourceMappingURL=codegen.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js.map new file mode 100644 index 000000000..2365207e1 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js.map @@ -0,0 +1 @@ +{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../../../src/lib/utils/codegen.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAUxB,KAAK,UAAU,UAAU,CAAC,OAAuB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACvD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAC7B,OAAO,CAAC,eAAe,EACvB,uCAAuC,CACxC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,EAAE;YAClB,aAAa;YACb,IAAI;YACJ,OAAO,CAAC,WAAW;YACnB,IAAI;YACJ,OAAO,CAAC,SAAS;YACjB,IAAI;YACJ,OAAO,CAAC,YAAY;SACrB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,2CAA2C,EAAE;YAC/D,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,eAAe,UAAU,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/destionation.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.d.ts new file mode 100644 index 000000000..079801a04 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.d.ts @@ -0,0 +1,24 @@ +import type { ApplePlatform, DeviceType } from '../types/index.js'; +export type DestinationInfo = { + device: string; + simulator: string; +}; +export declare const genericDestinations: { + readonly ios: { + readonly device: "generic/platform=iOS"; + readonly simulator: "generic/platform=iOS Simulator"; + }; + readonly macos: { + readonly device: "generic/platform=macOS"; + readonly simulator: "generic/platform=macOS"; + }; + readonly visionos: { + readonly device: "generic/platform=visionOS"; + readonly simulator: "generic/platform=visionOS Simulator"; + }; + readonly tvos: { + readonly device: "generic/platform=tvOS"; + readonly simulator: "generic/platform=tvOS Simulator"; + }; +}; +export declare function getGenericDestination(platform: ApplePlatform, deviceType: DeviceType): string; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js new file mode 100644 index 000000000..558726979 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js @@ -0,0 +1,22 @@ +export const genericDestinations = { + ios: { + device: 'generic/platform=iOS', + simulator: 'generic/platform=iOS Simulator', + }, + macos: { + device: 'generic/platform=macOS', + simulator: 'generic/platform=macOS', + }, + visionos: { + device: 'generic/platform=visionOS', + simulator: 'generic/platform=visionOS Simulator', + }, + tvos: { + device: 'generic/platform=tvOS', + simulator: 'generic/platform=tvOS Simulator', + }, +}; +export function getGenericDestination(platform, deviceType) { + return genericDestinations[platform][deviceType]; +} +//# sourceMappingURL=destionation.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js.map new file mode 100644 index 000000000..e1abce860 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"destionation.js","sourceRoot":"","sources":["../../../../src/lib/utils/destionation.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,EAAE;QACH,MAAM,EAAE,sBAAsB;QAC9B,SAAS,EAAE,gCAAgC;KAC5C;IACD,KAAK,EAAE;QACL,MAAM,EAAE,wBAAwB;QAChC,SAAS,EAAE,wBAAwB;KACpC;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,2BAA2B;QACnC,SAAS,EAAE,qCAAqC;KACjD;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,uBAAuB;QAC/B,SAAS,EAAE,iCAAiC;KAC7C;CACwD,CAAC;AAE5D,MAAM,UAAU,qBAAqB,CACnC,QAAuB,EACvB,UAAsB;IAEtB,OAAO,mBAAmB,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.d.ts new file mode 100644 index 000000000..7512c4519 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.d.ts @@ -0,0 +1,7 @@ +export declare const getBuildPaths: (platformName: string) => { + buildDir: string; + exportDir: string; + archiveDir: string; + packageDir: string; + derivedDataDir: string; +}; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js new file mode 100644 index 000000000..65bc617a9 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js @@ -0,0 +1,13 @@ +import path from 'node:path'; +import { getCacheRootPath } from '@rock-js/tools'; +export const getBuildPaths = (platformName) => { + const buildDir = path.join(getCacheRootPath(), platformName); + return { + buildDir, + exportDir: path.join(buildDir, 'export'), + archiveDir: path.join(buildDir, 'archive'), + packageDir: path.join(buildDir, 'package'), + derivedDataDir: path.join(buildDir, 'derivedData'), + }; +}; +//# sourceMappingURL=getBuildPaths.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js.map new file mode 100644 index 000000000..f90f0c10d --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getBuildPaths.js","sourceRoot":"","sources":["../../../../src/lib/utils/getBuildPaths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,YAAoB,EAAE,EAAE;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,YAAY,CAAC,CAAC;IAE7D,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACxC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;QAC1C,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;QAC1C,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC;KACnD,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.d.ts new file mode 100644 index 000000000..ec7868bab --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.d.ts @@ -0,0 +1,2 @@ +import type { Info } from '../types/index.js'; +export declare function getConfiguration(configurations: Info['configurations'], preselectedConfiguration: string | undefined): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js new file mode 100644 index 000000000..a4cbe3164 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js @@ -0,0 +1,46 @@ +import { isInteractive, logger, promptSelect, RockError } from '@rock-js/tools'; +export async function getConfiguration(configurations, preselectedConfiguration) { + let configuration = preselectedConfiguration; + if (configurations && + configurations.length > 1 && + !preselectedConfiguration) { + // This is default and common configuration for React Native projects. + // In such cases we 90% want a Debug configuration. + // For the rest 10% user can pass the --configuration flag. + if (configurations.length === 2 && + configurations.includes('Debug') && + configurations.includes('Release')) { + configuration = 'Debug'; + } + else if (isInteractive()) { + configuration = await promptForConfigurationSelection(configurations); + logger.info(`You can set configuration manually next time using "--configuration ${configuration}" flag.`); + } + } + if (!configuration) { + configuration = 'Debug'; + } + invalidateConfiguration(configurations, configuration); + return configuration; +} +function invalidateConfiguration(configurations, configuration) { + if (!configurations || configurations.length === 0) { + logger.warn(`Unable to check whether "${configuration}" configuration exists in your project`); + return; + } + if (!configurations.includes(configuration)) { + throw new RockError(`Configuration "${configuration}" doesn't exist. Please use one of the existing configurations: ${configurations + .map((configuration) => `\n- ${configuration}`) + .join('')}`); + } +} +function promptForConfigurationSelection(configurations) { + return promptSelect({ + message: 'Select the configuration you want to use', + options: configurations.map((value) => ({ + label: value, + value: value, + })), + }); +} +//# sourceMappingURL=getConfiguration.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js.map new file mode 100644 index 000000000..05fb6ffc6 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getConfiguration.js","sourceRoot":"","sources":["../../../../src/lib/utils/getConfiguration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,cAAsC,EACtC,wBAA4C;IAE5C,IAAI,aAAa,GAAG,wBAAwB,CAAC;IAC7C,IACE,cAAc;QACd,cAAc,CAAC,MAAM,GAAG,CAAC;QACzB,CAAC,wBAAwB,EACzB,CAAC;QACD,sEAAsE;QACtE,mDAAmD;QACnD,2DAA2D;QAC3D,IACE,cAAc,CAAC,MAAM,KAAK,CAAC;YAC3B,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,EAClC,CAAC;YACD,aAAa,GAAG,OAAO,CAAC;QAC1B,CAAC;aAAM,IAAI,aAAa,EAAE,EAAE,CAAC;YAC3B,aAAa,GAAG,MAAM,+BAA+B,CAAC,cAAc,CAAC,CAAC;YACtE,MAAM,CAAC,IAAI,CACT,uEAAuE,aAAa,SAAS,CAC9F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC;IACD,uBAAuB,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IACvD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,uBAAuB,CAC9B,cAAsC,EACtC,aAAqB;IAErB,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CACT,4BAA4B,aAAa,wCAAwC,CAClF,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,SAAS,CACjB,kBAAkB,aAAa,mEAAmE,cAAc;aAC7G,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,OAAO,aAAa,EAAE,CAAC;aAC9C,IAAI,CAAC,EAAE,CAAC,EAAE,CACd,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,CAAC,cAAwB;IAC/D,OAAO,YAAY,CAAC;QAClB,OAAO,EAAE,0CAA0C;QACnD,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACtC,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.d.ts new file mode 100644 index 000000000..f901db56d --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.d.ts @@ -0,0 +1,2 @@ +import type { Info, XcodeProjectInfo } from '../types/index.js'; +export declare function getInfo(projectInfo: XcodeProjectInfo, sourceDir: string): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js new file mode 100644 index 000000000..6161a6cef --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js @@ -0,0 +1,85 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { logger, RockError, spawn } from '@rock-js/tools'; +import { XMLParser } from 'fast-xml-parser'; +function parseTargetList(json) { + try { + const info = JSON.parse(json); + if ('project' in info) { + return info.project; + } + else if ('workspace' in info) { + return info.workspace; + } + return undefined; + } + catch (error) { + throw new RockError('Failed to parse target list', { cause: error }); + } +} +export async function getInfo(projectInfo, sourceDir) { + if (!projectInfo.isWorkspace) { + try { + const { stdout } = await spawn('xcodebuild', ['-list', '-json'], { + cwd: sourceDir, + stdio: 'pipe', + }); + const info = parseTargetList(stdout); + if (!info) { + throw new RockError('Failed to get Xcode project information'); + } + return info; + } + catch (error) { + throw new RockError('Failed to get a target list.', { + cause: error, + }); + } + } + const xmlParser = new XMLParser({ ignoreAttributes: false }); + const xcworkspacedata = path.join(sourceDir, projectInfo.name, 'contents.xcworkspacedata'); + const workspace = fs.readFileSync(xcworkspacedata, { encoding: 'utf-8' }); + const fileRef = xmlParser.parse(workspace).Workspace.FileRef; + const refs = Array.isArray(fileRef) ? fileRef : [fileRef]; + const locations = refs + .map((ref) => ref['@_location']) + .filter((location) => !location.endsWith('/Pods.xcodeproj') && // Ignore the project generated by CocoaPods + location.endsWith('.xcodeproj')); + let info = undefined; + for (const location of locations) { + let stdout = ''; + try { + const buildOutput = await spawn('xcodebuild', ['-list', '-json', '-project', location.replace('group:', '')], { cwd: sourceDir, stdio: 'pipe' }); + stdout = buildOutput.stdout; + logger.debug(stdout); + logger.debug(buildOutput.stderr); + } + catch (error) { + throw new RockError('Failed to get project info', { + cause: error.stderr, + }); + } + const projectInfo = parseTargetList(stdout); + if (!projectInfo) { + continue; + } + const schemes = projectInfo.schemes; + // If this is the first project, use it as the "main" project + if (!info) { + if (!Array.isArray(schemes)) { + projectInfo.schemes = []; + } + info = projectInfo; + continue; + } + if (!Array.isArray(info.schemes)) { + throw new RockError("This shouldn't happen since we set it earlier"); + } + // For subsequent projects, merge schemes list + if (Array.isArray(schemes) && schemes.length > 0) { + info.schemes = info.schemes.concat(schemes); + } + } + return info; +} +//# sourceMappingURL=getInfo.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js.map new file mode 100644 index 000000000..3f5e38cef --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getInfo.js","sourceRoot":"","sources":["../../../../src/lib/utils/getInfo.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.d.ts new file mode 100644 index 000000000..e26040e4a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.d.ts @@ -0,0 +1,10 @@ +import type { ApplePlatform } from '../types/index.js'; +interface PlatformInfo { + readableName: string; +} +/** + * Returns platform readable name. + * Falls back to iOS if platform is not supported. + */ +export declare function getPlatformInfo(platform: ApplePlatform): PlatformInfo; +export {}; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js new file mode 100644 index 000000000..93f071e21 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js @@ -0,0 +1,26 @@ +/** + * Returns platform readable name. + * Falls back to iOS if platform is not supported. + */ +export function getPlatformInfo(platform) { + switch (platform) { + case 'tvos': + return { + readableName: 'tvOS', + }; + case 'visionos': + return { + readableName: 'visionOS', + }; + case 'macos': + return { + readableName: 'macOS', + }; + case 'ios': + default: + return { + readableName: 'iOS', + }; + } +} +//# sourceMappingURL=getPlatformInfo.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js.map new file mode 100644 index 000000000..277cd9c2a --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getPlatformInfo.js","sourceRoot":"","sources":["../../../../src/lib/utils/getPlatformInfo.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB;IACrD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,OAAO;gBACL,YAAY,EAAE,MAAM;aACrB,CAAC;QACJ,KAAK,UAAU;YACb,OAAO;gBACL,YAAY,EAAE,UAAU;aACzB,CAAC;QACJ,KAAK,OAAO;YACV,OAAO;gBACL,YAAY,EAAE,OAAO;aACtB,CAAC;QACJ,KAAK,KAAK,CAAC;QACX;YACE,OAAO;gBACL,YAAY,EAAE,KAAK;aACpB,CAAC;IACN,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.d.ts new file mode 100644 index 000000000..519e6b286 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.d.ts @@ -0,0 +1,2 @@ +import type { Info } from '../types/index.js'; +export declare function getScheme(schemes: Info['schemes'], preselectedScheme: string | undefined, projectName: string): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js new file mode 100644 index 000000000..2c8e2b7e1 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js @@ -0,0 +1,37 @@ +import { isInteractive, logger, promptSelect, RockError } from '@rock-js/tools'; +import path from 'path'; +export async function getScheme(schemes, preselectedScheme, projectName) { + let scheme = preselectedScheme; + if (schemes && schemes.length > 1 && !preselectedScheme) { + if (isInteractive()) { + scheme = await promptForSchemeSelection(schemes); + logger.info(`You can set scheme manually next time using "--scheme ${scheme}" flag.`); + } + } + if (!scheme) { + scheme = path.basename(projectName, path.extname(projectName)); + } + invalidateScheme(schemes, scheme); + return scheme; +} +function invalidateScheme(schemes, scheme) { + if (!schemes || schemes.length === 0) { + logger.warn(`Unable to check whether "${scheme}" scheme exists in your project`); + return; + } + if (!schemes.includes(scheme)) { + throw new RockError(`Scheme "${scheme}" doesn't exist. Please use one of the existing schemes: ${schemes + .map((scheme) => `\n- ${scheme}`) + .join('')}`); + } +} +function promptForSchemeSelection(schemes) { + return promptSelect({ + message: 'Select the scheme you want to use', + options: schemes.map((value) => ({ + label: value, + value: value, + })), + }); +} +//# sourceMappingURL=getScheme.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js.map new file mode 100644 index 000000000..c465c0d28 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getScheme.js","sourceRoot":"","sources":["../../../../src/lib/utils/getScheme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAwB,EACxB,iBAAqC,EACrC,WAAmB;IAEnB,IAAI,MAAM,GAAG,iBAAiB,CAAC;IAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxD,IAAI,aAAa,EAAE,EAAE,CAAC;YACpB,MAAM,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CACT,yDAAyD,MAAM,SAAS,CACzE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAwB,EAAE,MAAc;IAChE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CACT,4BAA4B,MAAM,iCAAiC,CACpE,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CACjB,WAAW,MAAM,4DAA4D,OAAO;aACjF,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,EAAE,CAAC;aAChC,IAAI,CAAC,EAAE,CAAC,EAAE,CACd,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,OAAiB;IACjD,OAAO,YAAY,CAAC;QAClB,OAAO,EAAE,mCAAmC;QAC5C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC/B,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.d.ts new file mode 100644 index 000000000..78e731944 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.d.ts @@ -0,0 +1,7 @@ +import type { IOSProjectParams } from '@react-native-community/cli-types'; +import type { ApplePlatform, ProjectConfig } from '../types/index.js'; +/** + * Get the valid project config with non-null `xcodeProject` for the given Apple platform. + * To be used before running commands or after installing pods. + */ +export declare function getValidProjectConfig(platformName: ApplePlatform, projectRoot: string, userConfig?: IOSProjectParams): ProjectConfig; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js new file mode 100644 index 000000000..8ec5cd684 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js @@ -0,0 +1,17 @@ +import { getProjectConfig } from '@react-native-community/cli-config-apple'; +import { RockError } from '@rock-js/tools'; +/** + * Get the valid project config with non-null `xcodeProject` for the given Apple platform. + * To be used before running commands or after installing pods. + */ +export function getValidProjectConfig(platformName, projectRoot, userConfig = {}) { + const newProjectConfig = getProjectConfig({ platformName })(projectRoot, userConfig); + if (!newProjectConfig || newProjectConfig.xcodeProject === null) { + throw new RockError('Failed to get Xcode project information'); + } + return { + sourceDir: newProjectConfig.sourceDir, + xcodeProject: newProjectConfig.xcodeProject, + }; +} +//# sourceMappingURL=getValidProjectConfig.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js.map new file mode 100644 index 000000000..d142a79cc --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getValidProjectConfig.js","sourceRoot":"","sources":["../../../../src/lib/utils/getValidProjectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,YAA2B,EAC3B,WAAmB,EACnB,aAA+B,EAAE;IAEjC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC,CACzD,WAAW,EACX,UAAU,CACX,CAAC;IACF,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO;QACL,SAAS,EAAE,gBAAgB,CAAC,SAAS;QACrC,YAAY,EAAE,gBAAgB,CAAC,YAAY;KAC5C,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.d.ts new file mode 100644 index 000000000..490fa71cc --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.d.ts @@ -0,0 +1,2 @@ +import type { ApplePlatform, Device } from '../types/index.js'; +export declare function listDevicesAndSimulators(platform: ApplePlatform): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js new file mode 100644 index 000000000..42df057f5 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js @@ -0,0 +1,80 @@ +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { RockError, spawn } from '@rock-js/tools'; +function parseDevicectlList(devicectlOutput) { + const devices = devicectlOutput.map((device) => ({ + name: device.deviceProperties.name, + udid: device.hardwareProperties.udid, + version: `${device.hardwareProperties.platform} ${device.deviceProperties.osVersionNumber}`, + platform: getPlatformFromOsVersion(device.hardwareProperties.platform), + state: device.deviceProperties.bootState === 'booted' ? 'Booted' : 'Shutdown', + type: 'device', + })); + return devices; +} +async function getDevices() { + const tmpPath = path.resolve(os.tmpdir(), 'iosPhysicalDevices.json'); // same as Minisim.app + try { + await spawn('xcrun', ['devicectl', 'list', 'devices', '-j', tmpPath]); + const output = JSON.parse(fs.readFileSync(tmpPath, 'utf8')); + return parseDevicectlList(output.result.devices); + } + catch (error) { + throw new RockError('Failed to get devices', { + cause: error.stderr, + }); + } +} +async function getSimulators() { + const { output } = await spawn('xcrun', ['simctl', 'list', 'devices', 'available'], { stdio: 'pipe' }); + return parseSimctlOutput(output); +} +export async function listDevicesAndSimulators(platform) { + const simulators = await getSimulators(); + const devices = await getDevices(); + return [...simulators, ...devices].filter((device) => device.platform === platform); +} +function parseSimctlOutput(input) { + const lines = input.split('\n'); + const devices = []; + const currentOSIdx = 1; + const deviceNameIdx = 1; + const identifierIdx = 4; + const deviceStateIdx = 5; + let osVersion = ''; + lines.forEach((line) => { + const currentOsMatch = line.match(/-- (.*?) --/); + if (currentOsMatch && currentOsMatch.length > 0) { + osVersion = currentOsMatch[currentOSIdx]; + } + const deviceMatch = line.match(/(.*?) (\(([0-9.]+)\) )?\(([0-9A-F-]+)\) \((.*?)\)/); + if (deviceMatch && deviceMatch.length > 0) { + devices.push({ + name: deviceMatch[deviceNameIdx].trim(), + udid: deviceMatch[identifierIdx], + version: osVersion, + platform: getPlatformFromOsVersion(osVersion.split(' ')[0]), + state: deviceMatch[deviceStateIdx], + type: 'simulator', + }); + } + }); + return devices; +} +function getPlatformFromOsVersion(osVersion) { + switch (osVersion) { + case 'iOS': + return 'ios'; + case 'tvOS': + return 'tvos'; + case 'macOS': + return 'macos'; + case 'xrOS': + case 'visionOS': + return 'visionos'; + default: + return undefined; + } +} +//# sourceMappingURL=listDevices.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js.map new file mode 100644 index 000000000..1fc2cfb80 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listDevices.js","sourceRoot":"","sources":["../../../../src/lib/utils/listDevices.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/plist.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/plist.d.ts new file mode 100644 index 000000000..dc1afdc95 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/plist.d.ts @@ -0,0 +1,6 @@ +type PListBuddyOptions = { + xml?: boolean; +}; +export declare function readKeyFromPlist(plistPath: string, key: string, options?: PListBuddyOptions): Promise; +export declare function readBufferFromPlist(plistPath: string, key: string): Promise; +export {}; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/plist.js b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js new file mode 100644 index 000000000..9628a11cb --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js @@ -0,0 +1,48 @@ +import { execFile } from 'node:child_process'; +import { promisify } from 'node:util'; +import { RockError, spawn, SubprocessError } from '@rock-js/tools'; +const execFileAsync = promisify(execFile); +export async function readKeyFromPlist(plistPath, key, options = {}) { + try { + const result = await plistBuddy(plistPath, `Print:${key}`, options); + return result.stdout.trim(); + } + catch (error) { + throw new RockError(`Error reading key ${key} from ${plistPath}`, { + cause: error instanceof SubprocessError ? error.stderr : error, + }); + } +} +async function plistBuddy(path, command, options) { + const args = ['-c', command, path]; + if (options?.xml) { + args.unshift('-x'); + } + const result = await spawn('/usr/libexec/PlistBuddy', args, { + stdio: 'pipe', + }); + return result; +} +export async function readBufferFromPlist(plistPath, key) { + try { + const result = await binaryPlistBuddy(plistPath, `Print:${key}`); + return Buffer.from(result.stdout, 'binary'); + } + catch (error) { + throw new RockError(`Error reading key ${key} from ${plistPath}`, { + cause: error instanceof SubprocessError ? error.stderr : error, + }); + } +} +/** + * Special version of plistBuddy that reads the output as binary. Use `execFile` + * instead of nano-spawn which does not support binary output. + */ +async function binaryPlistBuddy(path, command) { + const args = ['-c', command, path]; + const result = await execFileAsync('/usr/libexec/PlistBuddy', args, { + encoding: 'binary', + }); + return result; +} +//# sourceMappingURL=plist.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/plist.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js.map new file mode 100644 index 000000000..4c5c2a230 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plist.js","sourceRoot":"","sources":["../../../../src/lib/utils/plist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAM1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,GAAW,EACX,UAA6B,EAAE;IAE/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACpE,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,qBAAqB,GAAG,SAAS,SAAS,EAAE,EAAE;YAChE,KAAK,EAAE,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;SAC/D,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,IAAY,EACZ,OAAe,EACf,OAA2B;IAE3B,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,yBAAyB,EAAE,IAAI,EAAE;QAC1D,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,GAAW;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,CAAC,CAAC;QACjE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,qBAAqB,GAAG,SAAS,SAAS,EAAE,EAAE;YAChE,KAAK,EAAE,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;SAC/D,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,yBAAyB,EAAE,IAAI,EAAE;QAClE,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/pods.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/pods.d.ts new file mode 100644 index 000000000..05f05c3ab --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/pods.d.ts @@ -0,0 +1,2 @@ +import type { ApplePlatform } from '../types/index.js'; +export declare function installPodsIfNeeded(projectRoot: string, platformName: ApplePlatform, sourceDir: string, newArch: boolean, reactNativePath: string, brownfield?: boolean): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/pods.js b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js new file mode 100644 index 000000000..e5531f67f --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js @@ -0,0 +1,266 @@ +import { createHash } from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; +import { cacheManager, color, colorLink, getReactNativeVersion, logger, RockError, spawn, spinner, } from '@rock-js/tools'; +import runCodegen from './codegen.js'; +const podErrorHelpMessage = `Please make sure your environment is correctly set up. +Learn more at: ${color.dim('https://cocoapods.org/')} +To skip automatic CocoaPods installation run with "--no-install-pods" flag after installing CocoaPods manually.`; +export async function installPodsIfNeeded(projectRoot, platformName, sourceDir, newArch, reactNativePath, brownfield) { + const podsPath = path.join(sourceDir, 'Pods'); + const podfilePath = path.join(sourceDir, 'Podfile'); + // There's a possibility to define a custom dependencies in `react-native.config.js`, that contain native code for a platform and that should also trigger install CocoaPods + const nativeDependencies = await getNativeDependencies(platformName); + const cacheKey = `pods-dependencies`; + const cachedDependenciesHash = cacheManager.get(cacheKey); + const podsDirExists = fs.existsSync(podsPath); + const hashChanged = cachedDependenciesHash + ? !compareMd5Hashes(calculateCurrentHash({ podfilePath, podsPath, nativeDependencies }), cachedDependenciesHash) + : true; + if (!podsDirExists || hashChanged) { + await runCodegen({ projectRoot, platformName, reactNativePath, sourceDir }); + await installPods({ + projectRoot, + sourceDir, + podfilePath, + newArch, + brownfield, + }); + cacheManager.set(cacheKey, calculateCurrentHash({ podfilePath, podsPath, nativeDependencies })); + return true; + } + return false; +} +const calculateCurrentHash = ({ podfilePath, podsPath, nativeDependencies, }) => { + const podfileLockPath = podfilePath + '.lock'; + const manifestLockPath = path.join(podsPath, 'Manifest.lock'); + let podfile; + try { + podfile = fs.readFileSync(podfilePath, 'utf-8'); + } + catch { + throw new RockError(`No Podfile found at: ${podfilePath}. +${podErrorHelpMessage}`); + } + let podfileLock; + try { + podfileLock = fs.readFileSync(podfileLockPath, 'utf-8'); + } + catch { + logger.debug('No Podfile.lock, continue'); + } + return generateDependenciesHash([ + generateMd5Hash(podfile), + generateMd5Hash(podfileLock ?? ''), + getLockfileChecksum(podfileLockPath), + getLockfileChecksum(manifestLockPath), + generateDependenciesHash(nativeDependencies), + ]); +}; +async function runPodInstall(options) { + if (!options.useBundler) { + await validatePodCommand(options.sourceDir); + } + // Remove build folder to avoid codegen path clashes when developing native modules + if (fs.existsSync('./build')) { + fs.rmSync('build', { recursive: true }); + } + const shouldHandleRepoUpdate = options?.shouldHandleRepoUpdate || true; + const loader = spinner({ indicator: 'timer' }); + loader.start('Installing CocoaPods dependencies'); + const reactNativeVersion = await getReactNativeVersion(options.projectRoot); + const isReactNative81OrHigher = reactNativeVersion.localeCompare('0.81.0', undefined, { + numeric: true, + sensitivity: 'base', + }) >= 0; + const usePrebuiltReactNative = !options.brownfield && isReactNative81OrHigher; + const command = options.useBundler ? 'bundle' : 'pod'; + const args = options.useBundler ? ['exec', 'pod', 'install'] : ['install']; + try { + await spawn(command, args, { + env: { + RCT_NEW_ARCH_ENABLED: options.newArch ? '1' : '0', + RCT_IGNORE_PODS_DEPRECATION: '1', + RCT_USE_RN_DEP: process.env['RCT_USE_RN_DEP'] != undefined + ? String(process.env['RCT_USE_RN_DEP']) + : usePrebuiltReactNative ? '1' : '0', + RCT_USE_PREBUILT_RNCORE: process.env['RCT_USE_PREBUILT_RNCORE'] != undefined + ? String(process.env['RCT_USE_PREBUILT_RNCORE']) + : usePrebuiltReactNative ? '1' : '0', + ...(options.brownfield && { USE_FRAMEWORKS: 'static' }), + ...(process.env['USE_THIRD_PARTY_JSC'] && { + USE_THIRD_PARTY_JSC: process.env['USE_THIRD_PARTY_JSC'], + }), + }, + cwd: options.sourceDir, + }); + } + catch (error) { + loader.stop('Failed: Installing CocoaPods dependencies', 1); + const stderr = error.stderr; + const fullOutput = error.output; + let errorMessage = stderr; + /** + * CocoaPods occasionally provides a markdown template with error message. + * We don't need the part above the Error secion. + */ + if (fullOutput.includes('### Error')) { + errorMessage = fullOutput.split('### Error')[1].trim(); + } + /** + * If CocoaPods failed due to repo being out of date, it will + * include the update command in the error message. + * + * `shouldHandleRepoUpdate` will be set to `false` to + * prevent infinite loop (unlikely scenario) + */ + if (fullOutput.includes('pod repo update') && shouldHandleRepoUpdate) { + await runPodUpdate(options.sourceDir, options.useBundler); + await runPodInstall({ + shouldHandleRepoUpdate: false, + sourceDir: options.sourceDir, + newArch: options.newArch, + useBundler: options.useBundler, + brownfield: options.brownfield, + projectRoot: options.projectRoot, + }); + } + else { + throw new RockError(`CocoaPods installation failed. +${podErrorHelpMessage}`, { cause: errorMessage }); + } + } + loader.stop('Installed CocoaPods dependencies successfully'); +} +async function runPodUpdate(cwd, useBundler) { + const loader = spinner({ indicator: 'timer' }); + try { + loader.start('Updating CocoaPods repositories'); + if (useBundler) { + await spawn('bundle', ['exec', 'pod', 'repo', 'update'], { cwd }); + } + else { + await spawn('pod', ['repo', 'update'], { cwd }); + } + } + catch (error) { + const stderr = error.stderr || error.stdout; + loader.stop('Failed: Updating CocoaPods repositories', 1); + throw new RockError(`Failed to update CocoaPods repositories for iOS project. +${podErrorHelpMessage}`, { cause: stderr }); + } +} +async function installPods(options) { + if (!fs.existsSync(options.podfilePath)) { + logger.debug(`No Podfile at ${options.podfilePath}. Skipping pod installation.`); + return; + } + const useBundler = await runBundleInstall(options.sourceDir, options.projectRoot); + if (!useBundler) { + logger.info('Unable to use Ruby bundler, falling back to "pod install"'); + } + await runPodInstall({ + sourceDir: options.sourceDir, + newArch: options.newArch, + useBundler, + brownfield: options.brownfield, + projectRoot: options.projectRoot, + }); +} +/* + * Check if "pod" is available and usable. It happens that there are + * multiple versions of "pod" command and even though it's there, it exits + * with a failure + */ +async function validatePodCommand(sourceDir) { + try { + await spawn('pod', ['--version'], { cwd: sourceDir }); + } + catch (error) { + const cause = error.cause; + if (cause instanceof Error && cause.message.includes('ENOENT')) { + throw new RockError(`The "pod" command is not available. +${podErrorHelpMessage}`); + } + const stderr = error.stderr || error.stdout; + throw new RockError(`CocoaPods "pod" command failed. +${podErrorHelpMessage}`, { cause: stderr }); + } +} +function checkGemfileForCocoaPods(gemfilePath) { + try { + const gemfileContent = fs.readFileSync(gemfilePath, 'utf-8'); + // Check for common CocoaPods gem declarations, because some projects might have Gemfile but for other purposes + return /^\s*gem\s+['"]cocoapods['"]/m.test(gemfileContent); + } + catch (error) { + logger.debug(`Failed to read Gemfile at: ${gemfilePath}`); + logger.debug(error); + return false; + } +} +async function runBundleInstall(sourceDir, projectRoot) { + const gemfilePath = path.join(projectRoot, 'Gemfile'); + if (!fs.existsSync(gemfilePath)) { + logger.debug(`Could not find the Gemfile at: ${colorLink(gemfilePath)} +The default React Native Template uses Gemfile to leverage Ruby Bundler and we advice the same. +If you use Gemfile, make sure it's ${color.bold('in the project root directory')}. +Falling back to installing CocoaPods using globally installed "pod".`); + return false; + } + if (!checkGemfileForCocoaPods(gemfilePath)) { + logger.debug(`CocoaPods not found in Gemfile at: ${colorLink(gemfilePath)} +skipping Ruby Gems installation.`); + return false; + } + const loader = spinner(); + try { + loader.start('Installing Ruby Gems'); + await spawn('bundle', ['install'], { cwd: sourceDir }); + } + catch (error) { + const stderr = error.stderr || error.stdout; + loader.stop('Failed: Installing Ruby Gems', 1); + throw new RockError(`Failed to install Ruby Gems with "bundle install". +${podErrorHelpMessage}`, { cause: stderr }); + } + loader.stop('Installed Ruby Gems'); + return true; +} +async function getNativeDependencies(platformName) { + const { loadConfigAsync } = await import('@react-native-community/cli-config'); + const config = await loadConfigAsync({ selectedPlatform: platformName }); + const dependencies = config.dependencies; + return Object.keys(dependencies) + .filter((dependency) => dependencies[dependency].platforms?.[platformName]) + .map((dependency) => `${dependency}@${(dependencies[dependency].platforms?.[platformName]).version}`) + .sort(); +} +function generateMd5Hash(text) { + return createHash('md5').update(text).digest('hex'); +} +function compareMd5Hashes(hash1, hash2) { + return hash1 === hash2; +} +function generateDependenciesHash(deps) { + return generateMd5Hash(JSON.stringify(deps)); +} +/** + * Gets the checksum of Podfile.lock or Pods/Manifest.lock + */ +function getLockfileChecksum(lockfilePath) { + try { + const checksumLine = fs + .readFileSync(lockfilePath, 'utf8') + .split('\n') + .find((line) => line.includes('PODFILE CHECKSUM')); + if (checksumLine) { + return checksumLine.split(': ')[1]; + } + } + catch (error) { + logger.debug(`Failed to load the lockfile ${lockfilePath}`, error); + } + return ''; +} +//# sourceMappingURL=pods.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/pods.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js.map new file mode 100644 index 000000000..ae9b5c6c6 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pods.js","sourceRoot":"","sources":["../../../../src/lib/utils/pods.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.d.ts new file mode 100644 index 000000000..284ef9ff7 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.d.ts @@ -0,0 +1,16 @@ +export type SigningIdentity = { + hash: string; + name: string; +}; +/** + * Input is in the form of: + * ``` + * 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)" + * 2) ABCDEF1234567890ABCDEF1234567890ABCDEF12 "Apple Distribution: Jane Smith (TEAMID5678)" + * ``` + * @param output + * @returns + */ +export declare function parseSigningIdentities(output: string): SigningIdentity[]; +export declare function getValidSigningIdentities(): Promise; +export declare function promptSigningIdentity(currentIdentity?: string | null): Promise; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js new file mode 100644 index 000000000..150841cba --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js @@ -0,0 +1,52 @@ +import { promptSelect, RockError, spawn } from '@rock-js/tools'; +/** + * Input is in the form of: + * ``` + * 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)" + * 2) ABCDEF1234567890ABCDEF1234567890ABCDEF12 "Apple Distribution: Jane Smith (TEAMID5678)" + * ``` + * @param output + * @returns + */ +export function parseSigningIdentities(output) { + const result = []; + const lines = output.split('\n'); + const regex = /^\s*(\d+)\)\s+([A-F0-9]+)\s+"(.+)"$/; + for (const line of lines) { + const match = line.match(regex); + if (match) { + const hash = match[2]; + const name = match[3]; + result.push({ hash, name }); + } + } + return result; +} +export async function getValidSigningIdentities() { + try { + const { output } = await spawn('security', ['find-identity', '-v', '-p', 'codesigning'], { stdio: 'pipe' }); + return parseSigningIdentities(output); + } + catch (error) { + throw new RockError('Failed to load signing identities', { + cause: error, + }); + } +} +export async function promptSigningIdentity(currentIdentity) { + const identities = await getValidSigningIdentities(); + const current = currentIdentity + ? identities.find((i) => i.name === currentIdentity) + : undefined; + const other = identities.filter((i) => i.name !== currentIdentity); + const list = current ? [current, ...other] : other; + return await promptSelect({ + message: 'Select a signing identity:', + options: list.map((identity) => ({ + label: identity.name, + value: identity.name, + hint: identity.name === currentIdentity ? 'Current' : undefined, + })), + }); +} +//# sourceMappingURL=signingIdentities.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js.map new file mode 100644 index 000000000..7ce7e0989 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js.map @@ -0,0 +1 @@ +{"version":3,"file":"signingIdentities.js","sourceRoot":"","sources":["../../../../src/lib/utils/signingIdentities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAOhE;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,KAAK,GAAG,qCAAqC,CAAC;IAEpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,UAAU,EACV,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,EAC5C,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;QAEF,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,mCAAmC,EAAE;YACvD,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,eAA+B;IACzE,MAAM,UAAU,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAErD,MAAM,OAAO,GAAG,eAAe;QAC7B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC;QACpD,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAEnD,OAAO,MAAM,YAAY,CAAC;QACxB,OAAO,EAAE,4BAA4B;QACrC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC/B,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,IAAI,EAAE,QAAQ,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;SAChE,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.d.ts new file mode 100644 index 000000000..fd245c515 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.d.ts @@ -0,0 +1,6 @@ +export declare const supportedPlatforms: { + readonly ios: "ios"; + readonly macos: "macos"; + readonly visionos: "visionos"; + readonly tvos: "tvos"; +}; diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js new file mode 100644 index 000000000..4d05348a9 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js @@ -0,0 +1,7 @@ +export const supportedPlatforms = { + ios: 'ios', + macos: 'macos', + visionos: 'visionos', + tvos: 'tvos', +}; +//# sourceMappingURL=supportedPlatforms.js.map \ No newline at end of file diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js.map new file mode 100644 index 000000000..80cc708d5 --- /dev/null +++ b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js.map @@ -0,0 +1 @@ +{"version":3,"file":"supportedPlatforms.js","sourceRoot":"","sources":["../../../../src/lib/utils/supportedPlatforms.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,MAAM;CACJ,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/index.d.ts b/packages/platform-harmony/dist/src/index.d.ts new file mode 100644 index 000000000..91ed5743c --- /dev/null +++ b/packages/platform-harmony/dist/src/index.d.ts @@ -0,0 +1 @@ +export * from './lib/platformHarmony.js'; diff --git a/packages/platform-harmony/dist/src/index.js b/packages/platform-harmony/dist/src/index.js new file mode 100644 index 000000000..1b66e2ace --- /dev/null +++ b/packages/platform-harmony/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/platformHarmony.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/index.js.map b/packages/platform-harmony/dist/src/index.js.map new file mode 100644 index 000000000..eeccc5d6f --- /dev/null +++ b/packages/platform-harmony/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.d.ts b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.d.ts new file mode 100644 index 000000000..09cab8bbb --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.d.ts @@ -0,0 +1,21 @@ +import type { RemoteBuildCache } from '@rock-js/tools'; +import { type FingerprintSources } from '@rock-js/tools'; +export interface BuildFlags { + buildMode: string; + module: string; + product: string; + local?: boolean; +} +export declare function buildHarmony(harmonyConfig: { + sourceDir: string; + bundleName: string; +}, args: BuildFlags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise; +export declare const options: ({ + name: string; + description: string; + default?: undefined; +} | { + name: string; + description: string; + default: string; +})[]; diff --git a/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js new file mode 100644 index 000000000..efe162b2e --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js @@ -0,0 +1,69 @@ +import { colorLink, formatArtifactName, getBinaryPath, logger, outro, relativeToCwd, } from '@rock-js/tools'; +import { findOutputFile } from '../run/findOutputFile.js'; +import { runHvigor } from '../runHvigor.js'; +export async function buildHarmony(harmonyConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions) { + const { sourceDir, bundleName } = harmonyConfig; + const artifactName = await formatArtifactName({ + platform: 'harmony', + traits: [args.buildMode], + root: projectRoot, + fingerprintOptions, + }); + const binaryPath = await getBinaryPath({ + platformName: 'harmony', + artifactName, + localFlag: args.local, + remoteCacheProvider, + fingerprintOptions, + sourceDir, + }); + if (!binaryPath) { + await runHvigor({ sourceDir, args, artifactName, bundleName }); + } + if (binaryPath) { + logger.log(`Build available at: ${colorLink(relativeToCwd(binaryPath))}`); + } + else { + const signedHapPath = await findOutputFile(sourceDir, args.module, { + deviceId: undefined, + readableName: undefined, + type: 'phone', + connected: false, + }); + if (signedHapPath) { + logger.log(`Signed build available at: ${colorLink(relativeToCwd(signedHapPath))}`); + } + const unsignedHapPath = await findOutputFile(sourceDir, args.module, { + deviceId: undefined, + readableName: undefined, + type: 'emulator', + connected: false, + }); + if (unsignedHapPath) { + logger.log(`Unsigned build available at: ${colorLink(relativeToCwd(unsignedHapPath))}`); + } + } + outro('Success ๐ŸŽ‰.'); +} +export const options = [ + { + name: '--local', + description: 'Force local build with Gradle wrapper.', + }, + { + name: '--module ', + description: 'Name of the OH module to run.', + default: 'entry', + }, + { + name: '--build-mode ', + description: `Specify your app's build mode, e.g. "debug" or "release".`, + default: 'debug', + }, + { + name: '--product ', + description: 'OpenHarmony product defined in build-profile.json5.', + default: 'default', + }, +]; +//# sourceMappingURL=buildHarmony.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js.map b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js.map new file mode 100644 index 000000000..1f6552c4f --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buildHarmony.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/buildHarmony.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EAET,kBAAkB,EAClB,aAAa,EACb,MAAM,EACN,KAAK,EACL,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,aAGC,EACD,IAAgB,EAChB,WAAmB,EACnB,mBAAgE,EAChE,kBAAsC;IAEtC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,aAAa,CAAC;IAChD,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;QACxB,IAAI,EAAE,WAAW;QACjB,kBAAkB;KACnB,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;QACrC,YAAY,EAAE,SAAS;QACvB,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,mBAAmB;QACnB,kBAAkB;QAClB,SAAS;KACV,CAAC,CAAC;IACH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,uBAAuB,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;SAAM,CAAC;QACN,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;YACjE,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,SAAS;YACvB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,CACR,8BAA8B,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,EAAE,CACxE,CAAC;QACJ,CAAC;QACD,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;YACnE,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,SAAS;YACvB,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,CACR,gCAAgC,SAAS,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,EAAE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,wCAAwC;KACtD;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,+BAA+B;QAC5C,OAAO,EAAE,OAAO;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,2DAA2D;QACxE,OAAO,EAAE,OAAO;KACjB;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,SAAS;KACnB;CACF,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/build/command.d.ts b/packages/platform-harmony/dist/src/lib/commands/build/command.d.ts new file mode 100644 index 000000000..7348c6abb --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/build/command.d.ts @@ -0,0 +1,3 @@ +import type { PluginApi } from '@rock-js/config'; +import { type HarmonyProjectConfig } from '../getValidProjectConfig.js'; +export declare function registerBuildCommand(api: PluginApi, pluginConfig: Partial | undefined): void; diff --git a/packages/platform-harmony/dist/src/lib/commands/build/command.js b/packages/platform-harmony/dist/src/lib/commands/build/command.js new file mode 100644 index 000000000..0140960c2 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/build/command.js @@ -0,0 +1,15 @@ +import { getValidProjectConfig, } from '../getValidProjectConfig.js'; +import { buildHarmony, options } from './buildHarmony.js'; +export function registerBuildCommand(api, pluginConfig) { + api.registerCommand({ + name: 'build:harmony', + description: 'Builds your app for HarmonyOS Next platform.', + action: async (args) => { + const projectRoot = api.getProjectRoot(); + const harmonyConfig = getValidProjectConfig(projectRoot, pluginConfig); + await buildHarmony(harmonyConfig, args, projectRoot, await api.getRemoteCacheProvider(), api.getFingerprintOptions()); + }, + options: options, + }); +} +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/build/command.js.map b/packages/platform-harmony/dist/src/lib/commands/build/command.js.map new file mode 100644 index 000000000..db26a6989 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/build/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/command.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,GAEtB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,UAAU,oBAAoB,CAClC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,8CAA8C;QAC3D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,YAAY,CAChB,aAAa,EACb,IAAkB,EAClB,WAAW,EACX,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,CAC5B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.d.ts b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.d.ts new file mode 100644 index 000000000..651bf3a3a --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.d.ts @@ -0,0 +1,10 @@ +export type HarmonyProjectConfig = { + sourceDir: string; + bundleName: string; + signingConfigs: boolean | undefined; +}; +export declare function getValidProjectConfig(projectRoot: string, pluginConfig?: Partial): { + sourceDir: string; + bundleName: string; + signingConfigs: boolean | undefined; +}; diff --git a/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js new file mode 100644 index 000000000..5aea3531b --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js @@ -0,0 +1,39 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { logger, RockError } from '@rock-js/tools'; +import json5 from 'json5'; +export function getValidProjectConfig(projectRoot, pluginConfig) { + const sourceDir = pluginConfig?.sourceDir + ? path.isAbsolute(pluginConfig?.sourceDir) + ? pluginConfig?.sourceDir + : path.join(projectRoot, pluginConfig?.sourceDir) + : path.join(projectRoot, 'harmony'); + if (!fs.existsSync(sourceDir)) { + throw new RockError(`Harmony project not found under ${sourceDir}.`); + } + let bundleName; + try { + bundleName = json5.parse(fs.readFileSync(path.join(sourceDir, 'AppScope', 'app.json5'), 'utf8')).app.bundleName; + } + catch (error) { + throw new RockError('Error reading app.json5 file.', { + cause: error, + }); + } + let signingConfigs; + try { + const buildProfile = json5.parse(fs.readFileSync(path.join(sourceDir, 'build-profile.json5'), 'utf8')); + signingConfigs = Boolean(buildProfile.app.signingConfigs); + } + catch (error) { + logger.debug('Error reading build-profile.json5 file.', { + cause: error.message, + }); + } + return { + sourceDir, + bundleName, + signingConfigs, + }; +} +//# sourceMappingURL=getValidProjectConfig.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js.map b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js.map new file mode 100644 index 000000000..a6137a9c1 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getValidProjectConfig.js","sourceRoot":"","sources":["../../../../src/lib/commands/getValidProjectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,YAA4C;IAE5C,MAAM,SAAS,GAAG,YAAY,EAAE,SAAS;QACvC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,SAAS,CAAC;YACxC,CAAC,CAAC,YAAY,EAAE,SAAS;YACzB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC;QACnD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAEtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,mCAAmC,SAAS,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,KAAK,CAAC,KAAK,CACtB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CACvE,CAAC,GAAG,CAAC,UAAU,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,EAAE;YACnD,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IAED,IAAI,cAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,MAAM,CAAC,CACrE,CAAC;QACF,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE;YACtD,KAAK,EAAG,KAAe,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,SAAS;QACT,UAAU;QACV,cAAc;KACf,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/command.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/command.d.ts new file mode 100644 index 000000000..a5329d651 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/command.d.ts @@ -0,0 +1,3 @@ +import type { PluginApi } from '@rock-js/config'; +import { type HarmonyProjectConfig } from '../getValidProjectConfig.js'; +export declare function registerRunCommand(api: PluginApi, pluginConfig: Partial | undefined): void; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/command.js b/packages/platform-harmony/dist/src/lib/commands/run/command.js new file mode 100644 index 000000000..88a0cbc62 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/command.js @@ -0,0 +1,15 @@ +import { getValidProjectConfig, } from '../getValidProjectConfig.js'; +import { runHarmony, runOptions } from './runHarmony.js'; +export function registerRunCommand(api, pluginConfig) { + api.registerCommand({ + name: 'run:harmony', + description: 'Builds your app and starts it on a connected HarmonyOS Next device.', + action: async (args) => { + const projectRoot = api.getProjectRoot(); + const harmonyConfig = getValidProjectConfig(projectRoot, pluginConfig); + await runHarmony(harmonyConfig, args, projectRoot, await api.getRemoteCacheProvider(), api.getFingerprintOptions()); + }, + options: runOptions, + }); +} +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/command.js.map b/packages/platform-harmony/dist/src/lib/commands/run/command.js.map new file mode 100644 index 000000000..936629338 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/command.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,GAEtB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,UAAU,kBAAkB,CAChC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,qEAAqE;QACvE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,UAAU,CACd,aAAa,EACb,IAAa,EACb,WAAW,EACX,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,CAC5B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.d.ts new file mode 100644 index 000000000..cb68d6678 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.d.ts @@ -0,0 +1,2 @@ +import type { DeviceData } from './listHarmonyDevices.js'; +export declare function findOutputFile(sourceDir: string, module: string, device?: DeviceData): Promise; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js new file mode 100644 index 000000000..da5e6292c --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js @@ -0,0 +1,14 @@ +import fs from 'node:fs'; +import path from 'node:path'; +export async function findOutputFile(sourceDir, module, device) { + let hapName; + if (device?.type === 'emulator') { + hapName = `${module}-default-unsigned.hap`; + } + else { + hapName = `${module}-default-signed.hap`; + } + const pathToHap = path.join(sourceDir, module, 'build', 'default', 'outputs', 'default', hapName); + return fs.existsSync(pathToHap) ? pathToHap : undefined; +} +//# sourceMappingURL=findOutputFile.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js.map b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js.map new file mode 100644 index 000000000..d4772032d --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findOutputFile.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/findOutputFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,MAAc,EACd,MAAmB;IAEnB,IAAI,OAAe,CAAC;IACpB,IAAI,MAAM,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QAChC,OAAO,GAAG,GAAG,MAAM,uBAAuB,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,GAAG,MAAM,qBAAqB,CAAC;IAC3C,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,SAAS,EACT,MAAM,EACN,OAAO,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,OAAO,CACR,CAAC;IACF,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/hdc.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/hdc.d.ts new file mode 100644 index 000000000..469bb63e0 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/hdc.d.ts @@ -0,0 +1,11 @@ +export declare function getHdcPath(): string; +/** + * Executes the commands needed to get a list of devices from ADB + */ +export declare function getDevices(): Promise<{ + name: string; + method: string; + state: string; + locate: string; + connectTool: string; +}[]>; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/hdc.js b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js new file mode 100644 index 000000000..af3fa25db --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js @@ -0,0 +1,35 @@ +import path from 'node:path'; +import { spawn } from '@rock-js/tools'; +import { getDevEcoSdkPath } from '../../paths.js'; +export function getHdcPath() { + return path.join(getDevEcoSdkPath(), 'default', 'openharmony', 'toolchains', 'hdc'); +} +/** + * Executes the commands needed to get a list of devices from ADB + */ +export async function getDevices() { + const hdcPath = getHdcPath(); + try { + const { output } = await spawn(hdcPath, ['list', 'targets', '-v'], { + stdio: 'pipe', + }); + const lines = output.trim().split('\n'); + return (lines + .map((line) => { + const parts = line.split(/\s+/); + return { + name: parts[0], + method: parts[1], // USB + state: parts[2], // Connected, Offline + locate: parts[3], // localhost + connectTool: parts[4], + }; + }) + // hdc will report no devices as [Empty] sometimes + .filter((line) => line.state != undefined)); + } + catch { + return []; + } +} +//# sourceMappingURL=hdc.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/hdc.js.map b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js.map new file mode 100644 index 000000000..37f0efaa6 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hdc.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/hdc.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CACd,gBAAgB,EAAE,EAClB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,KAAK,CACN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;YACjE,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,CACL,KAAK;aACF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAChC,OAAO;gBACL,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;gBACd,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM;gBACxB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,qBAAqB;gBACtC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY;gBAC9B,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;aACtB,CAAC;QACJ,CAAC,CAAC;YACF,kDAAkD;aACjD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,CAC7C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.d.ts new file mode 100644 index 000000000..fd20f8c6e --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.d.ts @@ -0,0 +1,7 @@ +export type DeviceData = { + deviceId: string | undefined; + readableName: string | undefined; + connected: boolean; + type: 'emulator' | 'phone'; +}; +export declare function listHarmonyDevices(): Promise; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js new file mode 100644 index 000000000..447842596 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js @@ -0,0 +1,17 @@ +import { getDevices } from './hdc.js'; +export async function listHarmonyDevices() { + const devices = await getDevices(); + const allDevices = []; + for (const device of devices) { + const phoneData = { + deviceId: device.name, + // @todo get readable name + readableName: device.name, + type: 'phone', + connected: device.state === 'Connected', + }; + allDevices.push(phoneData); + } + return allDevices; +} +//# sourceMappingURL=listHarmonyDevices.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js.map b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js.map new file mode 100644 index 000000000..dd63c8617 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listHarmonyDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/listHarmonyDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAStC,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,MAAM,UAAU,GAAsB,EAAE,CAAC;IAEzC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAe;YAC5B,QAAQ,EAAE,MAAM,CAAC,IAAI;YACrB,0BAA0B;YAC1B,YAAY,EAAE,MAAM,CAAC,IAAI;YACzB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,MAAM,CAAC,KAAK,KAAK,WAAW;SACxC,CAAC;QACF,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.d.ts new file mode 100644 index 000000000..b515f5a3e --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.d.ts @@ -0,0 +1,24 @@ +import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools'; +import type { BuildFlags } from '../build/buildHarmony.js'; +export interface Flags extends BuildFlags { + ability: string; + port: string; + device?: string; + binaryPath?: string; +} +/** + * Starts the app on a connected HarmonyOS emulator or device. + */ +export declare function runHarmony(harmonyConfig: { + sourceDir: string; + bundleName: string; +}, args: Flags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise; +export declare const runOptions: ({ + name: string; + description: string; + default?: undefined; +} | { + name: string; + description: string; + default: string; +})[]; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js new file mode 100644 index 000000000..0e6a43275 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js @@ -0,0 +1,148 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { color, formatArtifactName, intro, isInteractive, logger, outro, promptSelect, RockError, spinner, } from '@rock-js/tools'; +import { getBinaryPath } from '@rock-js/tools'; +import { options } from '../build/buildHarmony.js'; +import { runHvigor } from '../runHvigor.js'; +import { getDevices } from './hdc.js'; +import { listHarmonyDevices } from './listHarmonyDevices.js'; +import { tryInstallAppOnDevice } from './tryInstallAppOnDevice.js'; +import { tryLaunchAppOnDevice } from './tryLaunchAppOnDevice.js'; +/** + * Starts the app on a connected HarmonyOS emulator or device. + */ +export async function runHarmony(harmonyConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions) { + intro('Running HarmonyOS Next app'); + normalizeArgs(args, projectRoot); + const { sourceDir, bundleName } = harmonyConfig; + const devices = await listHarmonyDevices(); + const device = await selectDevice(devices, args); + const artifactName = await formatArtifactName({ + platform: 'harmony', + traits: [args.buildMode], + root: projectRoot, + fingerprintOptions, + }); + const binaryPath = await getBinaryPath({ + platformName: 'harmony', + artifactName, + binaryPathFlag: args.binaryPath, + localFlag: args.local, + remoteCacheProvider, + fingerprintOptions, + sourceDir: sourceDir, + }); + if (device) { + if (device.deviceId) { + if (!binaryPath) { + await runHvigor({ sourceDir, args, artifactName, device, bundleName }); + } + await runOnDevice({ device, sourceDir, args, binaryPath, bundleName }); + } + } + else { + if ((await getDevices()).length === 0) { + if (isInteractive()) { + await selectAndLaunchDevice(); + } + else { + logger.warn('No booted devices or emulators found. Launching first available emulator.'); + // @todo add emulators + } + } + if (!binaryPath) { + await runHvigor({ sourceDir, args, artifactName, bundleName }); + } + for (const device of await listHarmonyDevices()) { + if (device.connected) { + await runOnDevice({ device, sourceDir, args, binaryPath, bundleName }); + } + } + } + outro('Success ๐ŸŽ‰.'); +} +async function selectAndLaunchDevice() { + const allDevices = await listHarmonyDevices(); + const device = await promptForDeviceSelection(allDevices); + if (!device.connected) { + // @todo add emulators + // list devices once again when emulator is booted + const allDevices = await listHarmonyDevices(); + const newDevice = allDevices.find((d) => d.readableName === device.readableName) ?? device; + return newDevice; + } + return device; +} +async function selectDevice(devices, args) { + const device = args.device ? matchingDevice(devices, args.device) : undefined; + if (!device && args.device) { + logger.warn(`No devices or emulators found matching "${args.device}". Using available one instead.`); + } + return device; +} +function matchingDevice(devices, deviceArg) { + const deviceByName = devices.find((device) => device.readableName === deviceArg); + const deviceById = devices.find((d) => d.deviceId === deviceArg); + return deviceByName || deviceById; +} +function normalizeArgs(args, projectRoot) { + if (args.binaryPath) { + args.binaryPath = path.isAbsolute(args.binaryPath) + ? args.binaryPath + : path.join(projectRoot, args.binaryPath); + if (args.binaryPath && !fs.existsSync(args.binaryPath)) { + throw new RockError(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`); + } + } +} +async function promptForDeviceSelection(allDevices) { + if (!allDevices.length) { + throw new RockError( + // @todo add emulators + 'No devices connected. Please create connect HarmonyOS device.'); + } + const selected = await promptSelect({ + // @todo add emulators + message: 'Select the device you want to use', + options: allDevices.map((d) => ({ + label: `${d.readableName}${d.type === 'phone' ? ' - (physical device)' : ''}${d.connected ? ' (connected)' : ''}`, + value: d, + })), + }); + return selected; +} +async function runOnDevice({ device, sourceDir, args, binaryPath, bundleName, }) { + const loader = spinner(); + loader.start('Installing the app'); + await tryInstallAppOnDevice(device, sourceDir, args, binaryPath); + loader.message('Launching the app'); + const { applicationIdWithSuffix } = await tryLaunchAppOnDevice(device, bundleName, args); + if (applicationIdWithSuffix) { + loader.stop(`Installed and launched the app on ${color.bold(device.readableName)}`); + } + else { + loader.stop(`Failed: installing and launching the app on ${color.bold(device.readableName)}`); + } +} +export const runOptions = [ + ...options, + { + name: '--port ', + description: 'Part for packager.', + default: process.env['RCT_METRO_PORT'] || '8081', + }, + { + name: '--ability ', + description: 'Name of the ability to start.', + default: 'EntryAbility', + }, + { + name: '--device ', + description: 'Explicitly set the device or emulator to use by name or ID (if launched).', + }, + { + name: '--binary-path ', + description: 'Path relative to project root where pre-built .apk binary lives.', + }, +]; +//# sourceMappingURL=runHarmony.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js.map b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js.map new file mode 100644 index 000000000..00f1a913b --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runHarmony.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runHarmony.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.d.ts new file mode 100644 index 000000000..7d238e689 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.d.ts @@ -0,0 +1,3 @@ +import type { DeviceData } from './listHarmonyDevices.js'; +import type { Flags } from './runHarmony.js'; +export declare function tryInstallAppOnDevice(device: DeviceData, sourceDir: string, args: Flags, binaryPath: string | undefined): Promise; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js new file mode 100644 index 000000000..e6ae0dab2 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js @@ -0,0 +1,42 @@ +import path from 'node:path'; +import { color, colorLink, logger, RockError, spawn, } from '@rock-js/tools'; +import { findOutputFile } from './findOutputFile.js'; +import { getHdcPath } from './hdc.js'; +export async function tryInstallAppOnDevice(device, sourceDir, args, binaryPath) { + if (!device.deviceId) { + logger.debug(`No "deviceId" for ${device}, skipping launching the app`); + return; + } + logger.debug(`Connected to device ${color.bold(device.readableName)}`); + let pathToHap; + if (!binaryPath) { + const outputFilePath = await findOutputFile(sourceDir, args.module, device); + if (!outputFilePath) { + if (device.type === 'phone') { + throw new RockError(`There was no signed build output file for the physical device. +This usually means you're missing signing config in your ${colorLink(path.join(sourceDir, 'build-profile.json5'))} file. +Please open DevEco Studio, proceed to: ${color.bold('File > Project Structure... > Signing Configs')} +and log in to your Huawei account to fill the signing information.`); + } + else { + logger.warn("Skipping installation because there's no build output file."); + return; + } + } + pathToHap = outputFilePath; + } + else { + pathToHap = binaryPath; + } + const hdcPath = getHdcPath(); + try { + await spawn(hdcPath, ['-t', device.deviceId, 'install', '-r', pathToHap]); + } + catch (error) { + const errorMessage = error.stderr || error.stdout; + if (errorMessage.includes('failed to install')) { + throw new RockError(`Installation failed. If an application with the same bundle name is already installed, try uninstalling it`, { cause: error }); + } + } +} +//# sourceMappingURL=tryInstallAppOnDevice.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js.map b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js.map new file mode 100644 index 000000000..eeb86be19 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryInstallAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/tryInstallAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,KAAK,EACL,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,GAEN,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAItC,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAkB,EAClB,SAAiB,EACjB,IAAW,EACX,UAA8B;IAE9B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,qBAAqB,MAAM,8BAA8B,CAC1D,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,uBAAuB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACvE,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5E,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,IAAI,SAAS,CACjB;2DACiD,SAAS,CACxD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAC5C;yCAC8B,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC;mEACjC,CAC1D,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CACT,6DAA6D,CAC9D,CAAC;gBACF,OAAO;YACT,CAAC;QACH,CAAC;QACD,SAAS,GAAG,cAAc,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,UAAU,CAAC;IACzB,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GACf,KAAyB,CAAC,MAAM,IAAK,KAAyB,CAAC,MAAM,CAAC;QACzE,IAAI,YAAY,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,SAAS,CACjB,4GAA4G,EAC5G,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.d.ts new file mode 100644 index 000000000..b92bb0e80 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.d.ts @@ -0,0 +1,7 @@ +import type { DeviceData } from './listHarmonyDevices.js'; +import type { Flags } from './runHarmony.js'; +export declare function tryLaunchAppOnDevice(device: DeviceData, bundleName: string, args: Flags): Promise<{ + applicationIdWithSuffix?: undefined; +} | { + applicationIdWithSuffix: string; +}>; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js new file mode 100644 index 000000000..2ae1a1ea9 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js @@ -0,0 +1,43 @@ +import { logger, RockError, spawn } from '@rock-js/tools'; +import { getHdcPath } from './hdc.js'; +import { tryRunHdcReverse } from './tryRunHdcReverse.js'; +export async function tryLaunchAppOnDevice(device, bundleName, args) { + let deviceId; + if (!device.deviceId) { + logger.debug(`No "deviceId" for ${device}, skipping launching the app`); + return {}; + } + else { + deviceId = device.deviceId; + } + await tryRunHdcReverse(args.port, deviceId); + const hdcPath = getHdcPath(); + try { + await spawn(hdcPath, [ + '-t', + device.deviceId, + 'shell', + 'aa', + 'force-stop', + bundleName, + ]); + await spawn(hdcPath, [ + '-t', + device.deviceId, + 'shell', + 'aa', + 'start', + '-a', + args.ability, + '-b', + bundleName, + ]); + } + catch (error) { + throw new RockError(`Failed to launch the app on ${device.readableName}`, { + cause: error.stderr, + }); + } + return { applicationIdWithSuffix: bundleName }; +} +//# sourceMappingURL=tryLaunchAppOnDevice.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js.map b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js.map new file mode 100644 index 000000000..078f79ec2 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryLaunchAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/tryLaunchAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAkB,EAClB,UAAkB,EAClB,IAAW;IAEX,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,qBAAqB,MAAM,8BAA8B,CAC1D,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE;YACnB,IAAI;YACJ,MAAM,CAAC,QAAQ;YACf,OAAO;YACP,IAAI;YACJ,YAAY;YACZ,UAAU;SACX,CAAC,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE;YACnB,IAAI;YACJ,MAAM,CAAC,QAAQ;YACf,OAAO;YACP,IAAI;YACJ,OAAO;YACP,IAAI;YACJ,IAAI,CAAC,OAAO;YACZ,IAAI;YACJ,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,EAAE;YACxE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,CAAC;AACjD,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.d.ts new file mode 100644 index 000000000..d97740f45 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.d.ts @@ -0,0 +1 @@ +export declare function tryRunHdcReverse(packagerPort: number | string, device: string): Promise; diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js new file mode 100644 index 000000000..8c4f36313 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js @@ -0,0 +1,21 @@ +import { logger, RockError, spawn } from '@rock-js/tools'; +import { getHdcPath } from './hdc.js'; +// Runs hdc rport tcp:8081 tcp:8081 to allow loading the jsbundle from the packager +export async function tryRunHdcReverse(packagerPort, device) { + try { + const hdcPath = getHdcPath(); + const hdcArgs = [ + '-t', + device, + 'rport', + `tcp:${packagerPort}`, + `tcp:${packagerPort}`, + ]; + logger.debug(`Connecting "${device}" to the development server`); + await spawn(hdcPath, hdcArgs); + } + catch (error) { + throw new RockError(`Failed to connect "${device}" to development server using "hdb rport"`, { cause: error.stderr }); + } +} +//# sourceMappingURL=tryRunHdcReverse.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js.map b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js.map new file mode 100644 index 000000000..a4b592717 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tryRunHdcReverse.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/tryRunHdcReverse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA6B,EAC7B,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG;YACd,IAAI;YACJ,MAAM;YACN,OAAO;YACP,OAAO,YAAY,EAAE;YACrB,OAAO,YAAY,EAAE;SACtB,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,6BAA6B,CAAC,CAAC;QACjE,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,sBAAsB,MAAM,2CAA2C,EACvE,EAAE,KAAK,EAAG,KAAyB,CAAC,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/runHvigor.d.ts b/packages/platform-harmony/dist/src/lib/commands/runHvigor.d.ts new file mode 100644 index 000000000..6081052f5 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/runHvigor.d.ts @@ -0,0 +1,11 @@ +import type { BuildFlags } from './build/buildHarmony.js'; +import type { DeviceData } from './run/listHarmonyDevices.js'; +import type { Flags } from './run/runHarmony.js'; +export type RunHvigorArgs = { + sourceDir: string; + bundleName: string; + args: BuildFlags | Flags; + artifactName: string; + device?: DeviceData; +}; +export declare function runHvigor({ sourceDir, bundleName, args, artifactName, device, }: RunHvigorArgs): Promise; diff --git a/packages/platform-harmony/dist/src/lib/commands/runHvigor.js b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js new file mode 100644 index 000000000..4b3628efe --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js @@ -0,0 +1,56 @@ +import path from 'node:path'; +import { color, logger, RockError, saveLocalBuildCache, spawn, spinner, } from '@rock-js/tools'; +import { getDevEcoBuildToolsPath } from '../paths.js'; +import { findOutputFile } from './run/findOutputFile.js'; +async function runOhpm(sourceDir, loader) { + loader.message('Installing dependencies with ohpm'); + const ohpmPath = path.join(getDevEcoBuildToolsPath(), 'ohpm', 'bin', process.platform === 'win32' ? 'ohpm.bat' : 'ohpm'); + try { + await spawn(ohpmPath, ['install', '--all', '--strict_ssl', 'true'], { + cwd: sourceDir, + }); + } + catch (error) { + loader.stop('Failed to install dependencies with ohpm', 1); + throw new RockError('Failed to install native dependencies with ohpm', { + cause: error.output, + }); + } +} +export async function runHvigor({ sourceDir, bundleName, args, artifactName, device, }) { + logger.log(`Build Settings: +Bundle Name ${color.bold(bundleName)} +Build Mode ${color.bold(args.buildMode)}`); + const loader = spinner({ indicator: 'timer' }); + const message = `Building the app`; + loader.start(message); + await runOhpm(sourceDir, loader); + const hvigorPath = path.join(getDevEcoBuildToolsPath(), 'hvigor', 'bin', 'hvigorw.js'); + try { + loader.message('Building the app with Hvigor'); + await spawn('node', [ + hvigorPath, + `-p`, + `module=${args.module}@default`, + `-p`, + `product=${args.product}`, + `-p`, + `buildMode=${args.buildMode}`, + `-p`, + `requiredDeviceType=phone`, + `assembleHap`, + ], { cwd: sourceDir }); + loader.stop(`Built the app`); + } + catch (error) { + loader.stop('Failed to build the app', 1); + throw new RockError('Failed to build the app with Hvigor', { + cause: error.output, + }); + } + const outputFilePath = await findOutputFile(sourceDir, args.module, device); + if (outputFilePath) { + saveLocalBuildCache(artifactName, outputFilePath); + } +} +//# sourceMappingURL=runHvigor.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/runHvigor.js.map b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js.map new file mode 100644 index 000000000..46fbe1730 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runHvigor.js","sourceRoot":"","sources":["../../../../src/lib/commands/runHvigor.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,KAAK,EACL,MAAM,EACN,SAAS,EACT,mBAAmB,EACnB,KAAK,EACL,OAAO,GAER,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAYzD,KAAK,UAAU,OAAO,CAAC,SAAiB,EAAE,MAAkC;IAC1E,MAAM,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,uBAAuB,EAAE,EACzB,MAAM,EACN,KAAK,EACL,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CACnD,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE;YAClE,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,SAAS,CAAC,iDAAiD,EAAE;YACrE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,SAAS,EACT,UAAU,EACV,IAAI,EACJ,YAAY,EACZ,MAAM,GACQ;IACd,MAAM,CAAC,GAAG,CAAC;gBACG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,kBAAkB,CAAC;IAEnC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEtB,MAAM,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,uBAAuB,EAAE,EACzB,QAAQ,EACR,KAAK,EACL,YAAY,CACb,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;QAC/C,MAAM,KAAK,CACT,MAAM,EACN;YACE,UAAU;YACV,IAAI;YACJ,UAAU,IAAI,CAAC,MAAM,UAAU;YAC/B,IAAI;YACJ,WAAW,IAAI,CAAC,OAAO,EAAE;YACzB,IAAI;YACJ,aAAa,IAAI,CAAC,SAAS,EAAE;YAC7B,IAAI;YACJ,0BAA0B;YAC1B,aAAa;SACd,EACD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,CAAC,CAAC;QAE1C,MAAM,IAAI,SAAS,CAAC,qCAAqC,EAAE;YACzD,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5E,IAAI,cAAc,EAAE,CAAC;QACnB,mBAAmB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACpD,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/toPascalCase.d.ts b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.d.ts new file mode 100644 index 000000000..cdd38c9e5 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.d.ts @@ -0,0 +1 @@ +export declare function toPascalCase(value: string): string; diff --git a/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js new file mode 100644 index 000000000..656bebdbb --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js @@ -0,0 +1,4 @@ +export function toPascalCase(value) { + return value !== '' ? value[0].toUpperCase() + value.slice(1) : value; +} +//# sourceMappingURL=toPascalCase.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js.map b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js.map new file mode 100644 index 000000000..3986ae069 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js.map @@ -0,0 +1 @@ +{"version":3,"file":"toPascalCase.js","sourceRoot":"","sources":["../../../../src/lib/commands/toPascalCase.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACxE,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/paths.d.ts b/packages/platform-harmony/dist/src/lib/paths.d.ts new file mode 100644 index 000000000..3abd2ec53 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/paths.d.ts @@ -0,0 +1,2 @@ +export declare function getDevEcoSdkPath(): string; +export declare function getDevEcoBuildToolsPath(): string; diff --git a/packages/platform-harmony/dist/src/lib/paths.js b/packages/platform-harmony/dist/src/lib/paths.js new file mode 100644 index 000000000..4ac3319ed --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/paths.js @@ -0,0 +1,12 @@ +import path from 'node:path'; +export function getDevEcoSdkPath() { + const sdkRoot = process.env['DEVECO_SDK_HOME']; + if (!sdkRoot) { + throw new Error('DEVECO_SDK_HOME environment variable is not set. Please set it and run again'); + } + return sdkRoot; +} +export function getDevEcoBuildToolsPath() { + return path.join(getDevEcoSdkPath(), '..', 'tools'); +} +//# sourceMappingURL=paths.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/paths.js.map b/packages/platform-harmony/dist/src/lib/paths.js.map new file mode 100644 index 000000000..2c88285da --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/paths.js.map @@ -0,0 +1 @@ +{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC"} \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/platformHarmony.d.ts b/packages/platform-harmony/dist/src/lib/platformHarmony.d.ts new file mode 100644 index 000000000..8c5a4815d --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/platformHarmony.d.ts @@ -0,0 +1,5 @@ +import type { PlatformOutput, PluginApi } from '@rock-js/config'; +import { type HarmonyProjectConfig } from './commands/getValidProjectConfig.js'; +type PluginConfig = HarmonyProjectConfig; +export declare const platformHarmony: (pluginConfig?: Partial) => (api: PluginApi) => PlatformOutput; +export default platformHarmony; diff --git a/packages/platform-harmony/dist/src/lib/platformHarmony.js b/packages/platform-harmony/dist/src/lib/platformHarmony.js new file mode 100644 index 000000000..a4f8ab883 --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/platformHarmony.js @@ -0,0 +1,19 @@ +import { registerBuildCommand } from './commands/build/command.js'; +import { getValidProjectConfig, } from './commands/getValidProjectConfig.js'; +import { registerRunCommand } from './commands/run/command.js'; +export const platformHarmony = (pluginConfig) => (api) => { + registerBuildCommand(api, pluginConfig); + registerRunCommand(api, pluginConfig); + return { + name: '@rock-js/platform-harmony', + description: 'Rock plugin for HarmonyOS Next.', + autolinkingConfig: { + get project() { + const harmonyConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig); + return harmonyConfig; + }, + }, + }; +}; +export default platformHarmony; +//# sourceMappingURL=platformHarmony.js.map \ No newline at end of file diff --git a/packages/platform-harmony/dist/src/lib/platformHarmony.js.map b/packages/platform-harmony/dist/src/lib/platformHarmony.js.map new file mode 100644 index 000000000..28164cd2e --- /dev/null +++ b/packages/platform-harmony/dist/src/lib/platformHarmony.js.map @@ -0,0 +1 @@ +{"version":3,"file":"platformHarmony.js","sourceRoot":"","sources":["../../../src/lib/platformHarmony.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,qBAAqB,GAEtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI/D,MAAM,CAAC,MAAM,eAAe,GAC1B,CAAC,YAAoC,EAAE,EAAE,CACzC,CAAC,GAAc,EAAkB,EAAE;IACjC,oBAAoB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACxC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEtC,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,iCAAiC;QAC9C,iBAAiB,EAAE;YACjB,IAAI,OAAO;gBACT,MAAM,aAAa,GAAG,qBAAqB,CACzC,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;gBACF,OAAO,aAAa,CAAC;YACvB,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,eAAe,CAAC"} \ No newline at end of file diff --git a/packages/platform-ios/dist/src/index.d.ts b/packages/platform-ios/dist/src/index.d.ts new file mode 100644 index 000000000..b11daa579 --- /dev/null +++ b/packages/platform-ios/dist/src/index.d.ts @@ -0,0 +1 @@ +export * from './lib/platformIOS.js'; diff --git a/packages/platform-ios/dist/src/index.js b/packages/platform-ios/dist/src/index.js new file mode 100644 index 000000000..cab7b2a75 --- /dev/null +++ b/packages/platform-ios/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/platformIOS.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/platform-ios/dist/src/index.js.map b/packages/platform-ios/dist/src/index.js.map new file mode 100644 index 000000000..92bf7ff59 --- /dev/null +++ b/packages/platform-ios/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"} \ No newline at end of file diff --git a/packages/platform-ios/dist/src/lib/commands/signIos.d.ts b/packages/platform-ios/dist/src/lib/commands/signIos.d.ts new file mode 100644 index 000000000..a1a683003 --- /dev/null +++ b/packages/platform-ios/dist/src/lib/commands/signIos.d.ts @@ -0,0 +1,10 @@ +import type { PluginApi } from '@rock-js/config'; +export type SignFlags = { + app: string; + output?: string; + identity?: string; + buildJsbundle?: boolean; + jsbundle?: string; + noHermes?: boolean; +}; +export declare const registerSignCommand: (api: PluginApi) => void; diff --git a/packages/platform-ios/dist/src/lib/commands/signIos.js b/packages/platform-ios/dist/src/lib/commands/signIos.js new file mode 100644 index 000000000..a71886837 --- /dev/null +++ b/packages/platform-ios/dist/src/lib/commands/signIos.js @@ -0,0 +1,64 @@ +import { modifyApp, modifyIpa } from '@rock-js/platform-apple-helpers'; +const ARGUMENTS = [ + { + name: 'binaryPath', + description: 'Path to the IPA or APP file.', + }, +]; +const OPTIONS = [ + { + name: '--app', + description: 'Modify APP file (directory) instead of IPA file. No signing is done.', + }, + { + name: '--identity ', + description: 'Certificate Identity name to use for code signing, e.g. "Apple Distribution: Your Team (HFJASKHDDS)".', + }, + { + name: '--output ', + description: 'Path to the output IPA file.', + }, + { + name: '--build-jsbundle', + description: 'Build the JS bundle before signing.', + }, + { + name: '--jsbundle ', + description: 'Path to the JS bundle to apply before signing.', + }, + { + name: '--no-hermes', + description: 'Do not use Hermes to build the JS bundle.', + }, +]; +export const registerSignCommand = (api) => { + api.registerCommand({ + name: 'sign:ios', + description: 'Sign the iOS app (IPA or APP file) with modified JS bundle.', + args: ARGUMENTS, + options: OPTIONS, + action: async (binaryPath, flags) => { + if (flags.app) { + await modifyApp({ + appPath: binaryPath, + outputPath: flags.output, + buildJsBundle: flags.buildJsbundle, + jsBundlePath: flags.jsbundle, + useHermes: !flags.noHermes, + }); + } + else { + await modifyIpa({ + platformName: 'ios', + ipaPath: binaryPath, + identity: flags.identity, + outputPath: flags.output, + buildJsBundle: flags.buildJsbundle, + jsBundlePath: flags.jsbundle, + useHermes: !flags.noHermes, + }); + } + }, + }); +}; +//# sourceMappingURL=signIos.js.map \ No newline at end of file diff --git a/packages/platform-ios/dist/src/lib/commands/signIos.js.map b/packages/platform-ios/dist/src/lib/commands/signIos.js.map new file mode 100644 index 000000000..2a2a15b6c --- /dev/null +++ b/packages/platform-ios/dist/src/lib/commands/signIos.js.map @@ -0,0 +1 @@ +{"version":3,"file":"signIos.js","sourceRoot":"","sources":["../../../../src/lib/commands/signIos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAWvE,MAAM,SAAS,GAAG;IAChB;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,8BAA8B;KAC5C;CACF,CAAC;AAEF,MAAM,OAAO,GAAG;IACd;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EACT,sEAAsE;KACzE;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EACT,uGAAuG;KAC1G;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,8BAA8B;KAC5C;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,qCAAqC;KACnD;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,gDAAgD;KAC9D;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,2CAA2C;KACzD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAc,EAAE,EAAE;IACpD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,6DAA6D;QAC1E,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAgB,EAAE,EAAE;YAC7C,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBACd,MAAM,SAAS,CAAC;oBACd,OAAO,EAAE,UAAU;oBACnB,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,YAAY,EAAE,KAAK,CAAC,QAAQ;oBAC5B,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ;iBAC3B,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,CAAC;oBACd,YAAY,EAAE,KAAK;oBACnB,OAAO,EAAE,UAAU;oBACnB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,YAAY,EAAE,KAAK,CAAC,QAAQ;oBAC5B,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/platform-ios/dist/src/lib/platformIOS.d.ts b/packages/platform-ios/dist/src/lib/platformIOS.d.ts new file mode 100644 index 000000000..b4f15c276 --- /dev/null +++ b/packages/platform-ios/dist/src/lib/platformIOS.d.ts @@ -0,0 +1,4 @@ +import type { IOSProjectConfig } from '@react-native-community/cli-types'; +import type { PlatformOutput, PluginApi } from '@rock-js/config'; +export declare const platformIOS: (pluginConfig?: Partial) => (api: PluginApi) => PlatformOutput; +export default platformIOS; diff --git a/packages/platform-ios/dist/src/lib/platformIOS.js b/packages/platform-ios/dist/src/lib/platformIOS.js new file mode 100644 index 000000000..c4a555ac4 --- /dev/null +++ b/packages/platform-ios/dist/src/lib/platformIOS.js @@ -0,0 +1,64 @@ +import { createBuild, createRun, getBuildOptions, getRunOptions, getValidProjectConfig, } from '@rock-js/platform-apple-helpers'; +import { intro, outro } from '@rock-js/tools'; +import { registerSignCommand } from './commands/signIos.js'; +const buildOptions = getBuildOptions({ platformName: 'ios' }); +const runOptions = getRunOptions({ platformName: 'ios' }); +export const platformIOS = (pluginConfig) => (api) => { + api.registerCommand({ + name: 'build:ios', + description: 'Build iOS app.', + action: async (args) => { + intro('Building iOS app'); + const projectRoot = api.getProjectRoot(); + const iosConfig = getValidProjectConfig('ios', projectRoot, pluginConfig); + await createBuild({ + platformName: 'ios', + projectConfig: iosConfig, + args: args, + projectRoot, + reactNativePath: api.getReactNativePath(), + fingerprintOptions: api.getFingerprintOptions(), + remoteCacheProvider: await api.getRemoteCacheProvider(), + }); + outro('Success ๐ŸŽ‰.'); + }, + options: buildOptions, + }); + api.registerCommand({ + name: 'run:ios', + description: 'Run iOS app.', + action: async (args) => { + intro('Running iOS app'); + const projectRoot = api.getProjectRoot(); + const iosConfig = getValidProjectConfig('ios', projectRoot, pluginConfig); + await createRun({ + platformName: 'ios', + projectConfig: iosConfig, + args: args, + projectRoot, + remoteCacheProvider: await api.getRemoteCacheProvider(), + fingerprintOptions: api.getFingerprintOptions(), + reactNativePath: api.getReactNativePath(), + reactNativeVersion: api.getReactNativeVersion(), + platforms: api.getPlatforms(), + startDevServer: api.getBundlerStart(), + }); + outro('Success ๐ŸŽ‰.'); + }, + // @ts-expect-error: fix `simulator` is not defined in `RunFlags` + options: runOptions, + }); + registerSignCommand(api); + return { + name: '@rock-js/platform-ios', + description: 'Rock plugin for everything iOS.', + autolinkingConfig: { + get project() { + const iosConfig = getValidProjectConfig('ios', api.getProjectRoot(), pluginConfig); + return { ...iosConfig }; + }, + }, + }; +}; +export default platformIOS; +//# sourceMappingURL=platformIOS.js.map \ No newline at end of file diff --git a/packages/platform-ios/dist/src/lib/platformIOS.js.map b/packages/platform-ios/dist/src/lib/platformIOS.js.map new file mode 100644 index 000000000..b42af02aa --- /dev/null +++ b/packages/platform-ios/dist/src/lib/platformIOS.js.map @@ -0,0 +1 @@ +{"version":3,"file":"platformIOS.js","sourceRoot":"","sources":["../../../src/lib/platformIOS.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,EACX,SAAS,EACT,eAAe,EACf,aAAa,EACb,qBAAqB,GACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,YAAY,GAAG,eAAe,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9D,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,WAAW,GACtB,CAAC,YAAwC,EAAE,EAAE,CAC7C,CAAC,GAAc,EAAkB,EAAE;IACjC,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,gBAAgB;QAC7B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAC1B,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,qBAAqB,CACrC,KAAK,EACL,WAAW,EACX,YAAY,CACb,CAAC;YACF,MAAM,WAAW,CAAC;gBAChB,YAAY,EAAE,KAAK;gBACnB,aAAa,EAAE,SAAS;gBACxB,IAAI,EAAE,IAAkB;gBACxB,WAAW;gBACX,eAAe,EAAE,GAAG,CAAC,kBAAkB,EAAE;gBACzC,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,mBAAmB,EAAE,MAAM,GAAG,CAAC,sBAAsB,EAAE;aACxD,CAAC,CAAC;YACH,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,EAAE,YAAY;KACtB,CAAC,CAAC;IAEH,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,cAAc;QAC3B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACzB,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,qBAAqB,CACrC,KAAK,EACL,WAAW,EACX,YAAY,CACb,CAAC;YACF,MAAM,SAAS,CAAC;gBACd,YAAY,EAAE,KAAK;gBACnB,aAAa,EAAE,SAAS;gBACxB,IAAI,EAAE,IAAgB;gBACtB,WAAW;gBACX,mBAAmB,EAAE,MAAM,GAAG,CAAC,sBAAsB,EAAE;gBACvD,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,eAAe,EAAE,GAAG,CAAC,kBAAkB,EAAE;gBACzC,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,SAAS,EAAE,GAAG,CAAC,YAAY,EAAE;gBAC7B,cAAc,EAAE,GAAG,CAAC,eAAe,EAAE;aACtC,CAAC,CAAC;YACH,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,iEAAiE;QACjE,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;IAEH,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAEzB,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,iCAAiC;QAC9C,iBAAiB,EAAE;YACjB,IAAI,OAAO;gBACT,MAAM,SAAS,GAAG,qBAAqB,CACrC,KAAK,EACL,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;gBACF,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;YAC1B,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,WAAW,CAAC"} \ No newline at end of file diff --git a/packages/plugin-brownfield-android/dist/src/index.d.ts b/packages/plugin-brownfield-android/dist/src/index.d.ts new file mode 100644 index 000000000..42964b1db --- /dev/null +++ b/packages/plugin-brownfield-android/dist/src/index.d.ts @@ -0,0 +1 @@ +export * from './lib/pluginBrownfieldAndroid.js'; diff --git a/packages/plugin-brownfield-android/dist/src/index.js b/packages/plugin-brownfield-android/dist/src/index.js new file mode 100644 index 000000000..47854fdf8 --- /dev/null +++ b/packages/plugin-brownfield-android/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/pluginBrownfieldAndroid.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/plugin-brownfield-android/dist/src/index.js.map b/packages/plugin-brownfield-android/dist/src/index.js.map new file mode 100644 index 000000000..0678482b8 --- /dev/null +++ b/packages/plugin-brownfield-android/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC"} \ No newline at end of file diff --git a/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.d.ts b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.d.ts new file mode 100644 index 000000000..a741f9a4b --- /dev/null +++ b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.d.ts @@ -0,0 +1,3 @@ +import type { AndroidProjectConfig } from '@react-native-community/cli-types'; +import type { PluginApi, PluginOutput } from '@rock-js/config'; +export declare const pluginBrownfieldAndroid: (pluginConfig?: AndroidProjectConfig) => (api: PluginApi) => PluginOutput; diff --git a/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js new file mode 100644 index 000000000..e38b40d0d --- /dev/null +++ b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js @@ -0,0 +1,50 @@ +import { projectConfig } from '@react-native-community/cli-config-android'; +import { packageAar, packageAarOptions, publishLocalAar, publishLocalAarOptions, } from '@rock-js/platform-android'; +import { intro, RockError } from '@rock-js/tools'; +const getAarConfig = (args, androidConfig) => { + const config = { + sourceDir: androidConfig.sourceDir, + moduleName: args.moduleName ?? '', + }; + return config; +}; +export const pluginBrownfieldAndroid = (pluginConfig) => (api) => { + const projectRoot = api.getProjectRoot(); + api.registerCommand({ + name: 'package:aar', + description: 'Produces an AAR file suitable for including React Native app in native projects.', + action: async (args) => { + intro('Creating an AAR file'); + const androidConfig = projectConfig(projectRoot, pluginConfig); + if (androidConfig) { + const config = getAarConfig(args, androidConfig); + await packageAar(config, args); + } + else { + throw new RockError('Android project not found.'); + } + }, + options: packageAarOptions, + }); + api.registerCommand({ + name: 'publish-local:aar', + description: 'Publishes a AAR to local maven repo', + action: async (args) => { + intro('Publishing AAR'); + const androidConfig = projectConfig(projectRoot, pluginConfig); + if (androidConfig) { + const config = getAarConfig(args, androidConfig); + await publishLocalAar(config); + } + else { + throw new RockError('Android project not found.'); + } + }, + options: publishLocalAarOptions, + }); + return { + name: 'plugin-brownfield-android', + description: 'Rock plugin for brownfield Android.', + }; +}; +//# sourceMappingURL=pluginBrownfieldAndroid.js.map \ No newline at end of file diff --git a/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js.map b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js.map new file mode 100644 index 000000000..d5449c80a --- /dev/null +++ b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pluginBrownfieldAndroid.js","sourceRoot":"","sources":["../../../src/lib/pluginBrownfieldAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAG3E,OAAO,EACL,UAAU,EAEV,iBAAiB,EACjB,eAAe,EACf,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,YAAY,GAAG,CACnB,IAAqB,EACrB,aAAmC,EACnC,EAAE;IACF,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;KAClC,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,uBAAuB,GAClC,CAAC,YAAmC,EAAE,EAAE,CACxC,CAAC,GAAc,EAAgB,EAAE;IAC/B,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;IAEzC,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,kFAAkF;QACpF,MAAM,EAAE,KAAK,EAAE,IAAqB,EAAE,EAAE;YACtC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAE9B,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAE/D,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;gBACjD,MAAM,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QACD,OAAO,EAAE,iBAAiB;KAC3B,CAAC,CAAC;IAEH,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,qCAAqC;QAClD,MAAM,EAAE,KAAK,EAAE,IAAqB,EAAE,EAAE;YACtC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAExB,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAE/D,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;gBACjD,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QACD,OAAO,EAAE,sBAAsB;KAChC,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,qCAAqC;KACnD,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/index.d.ts b/packages/plugin-brownfield-ios/dist/src/index.d.ts new file mode 100644 index 000000000..eb9f9afa8 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/index.d.ts @@ -0,0 +1 @@ +export * from './lib/pluginBrownfieldIos.js'; diff --git a/packages/plugin-brownfield-ios/dist/src/index.js b/packages/plugin-brownfield-ios/dist/src/index.js new file mode 100644 index 000000000..25c79e991 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/pluginBrownfieldIos.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/index.js.map b/packages/plugin-brownfield-ios/dist/src/index.js.map new file mode 100644 index 000000000..ad9690e80 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC"} \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.d.ts b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.d.ts new file mode 100644 index 000000000..e0548dca6 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.d.ts @@ -0,0 +1,4 @@ +export declare function copyHermesXcframework({ sourceDir, destinationDir, }: { + sourceDir: string; + destinationDir: string; +}): void; diff --git a/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js new file mode 100644 index 000000000..cb69784a9 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js @@ -0,0 +1,15 @@ +import fs, { existsSync } from 'node:fs'; +import path from 'node:path'; +import { color, logger, spinner } from '@rock-js/tools'; +export function copyHermesXcframework({ sourceDir, destinationDir, }) { + const loader = spinner(); + loader.start(`Copying ${color.bold('hermes.xcframework')}`); + const hermesDestination = path.join(destinationDir, 'hermes.xcframework'); + if (existsSync(hermesDestination)) { + logger.debug(`Removing old hermes copy`); + fs.rmSync(hermesDestination, { recursive: true, force: true }); + } + fs.cpSync(path.join(sourceDir, 'Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework'), hermesDestination, { recursive: true, force: true }); + loader.stop(`Copied ${color.bold('hermes.xcframework')}`); +} +//# sourceMappingURL=copyHermesXcframework.js.map \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js.map b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js.map new file mode 100644 index 000000000..767658157 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js.map @@ -0,0 +1 @@ +{"version":3,"file":"copyHermesXcframework.js","sourceRoot":"","sources":["../../../src/lib/copyHermesXcframework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,UAAU,qBAAqB,CAAC,EACpC,SAAS,EACT,cAAc,GAIf;IACC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IAEzB,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;IAC5D,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;IAE1E,IAAI,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACzC,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,EAAE,CAAC,MAAM,CACP,IAAI,CAAC,IAAI,CACP,SAAS,EACT,6EAA6E,CAC9E,EACD,iBAAiB,EACjB,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CACjC,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC"} \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.d.ts b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.d.ts new file mode 100644 index 000000000..c1343572a --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.d.ts @@ -0,0 +1,9 @@ +/** + * Xcode emits different `.framework` file based on the destination (simulator arm64/x86_64, iphone arm64 etc.) + * This takes those `.frameworks` files and merges them to a single `.xcframework` file for easier distribution. + */ +export declare function mergeFrameworks({ frameworkPaths, outputPath, sourceDir, }: { + frameworkPaths: string[]; + outputPath: string; + sourceDir: string; +}): Promise; diff --git a/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js new file mode 100644 index 000000000..6bb999095 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js @@ -0,0 +1,33 @@ +import fs, { existsSync } from 'node:fs'; +import path from 'node:path'; +import { color, logger, spawn, spinner } from '@rock-js/tools'; +/** + * Xcode emits different `.framework` file based on the destination (simulator arm64/x86_64, iphone arm64 etc.) + * This takes those `.frameworks` files and merges them to a single `.xcframework` file for easier distribution. + */ +export async function mergeFrameworks({ frameworkPaths, outputPath, sourceDir, }) { + const loader = spinner(); + const xcframeworkName = path.basename(outputPath); + if (existsSync(outputPath)) { + logger.debug(`Removing `); + fs.rmSync(outputPath, { recursive: true, force: true }); + } + loader.start(`Creating ${color.bold(xcframeworkName)}`); + const xcodebuildArgs = [ + '-create-xcframework', + ...frameworkPaths.flatMap((frameworkPath) => ['-framework', frameworkPath]), + '-output', + outputPath, + ]; + try { + await spawn('xcodebuild', xcodebuildArgs, { cwd: sourceDir }); + loader.stop(`Created ${color.bold(xcframeworkName)}`); + } + catch (error) { + loader.stop(`Couldn't create ${color.bold(xcframeworkName)}.`, 1); + throw new Error('Running xcodebuild failed', { + cause: error.stderr, + }); + } +} +//# sourceMappingURL=mergeFrameworks.js.map \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js.map b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js.map new file mode 100644 index 000000000..5dd5ba5fc --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mergeFrameworks.js","sourceRoot":"","sources":["../../../src/lib/mergeFrameworks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,cAAc,EACd,UAAU,EACV,SAAS,GAKV;IACC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAElD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1B,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAExD,MAAM,cAAc,GAAG;QACrB,qBAAqB;QACrB,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAC3E,SAAS;QACT,UAAU;KACX,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,YAAY,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAE9D,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE;YAC3C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.d.ts b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.d.ts new file mode 100644 index 000000000..3e58a05bd --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.d.ts @@ -0,0 +1,4 @@ +import type { IOSProjectConfig } from '@react-native-community/cli-types'; +import type { PluginApi, PluginOutput } from '@rock-js/config'; +export declare const pluginBrownfieldIos: (pluginConfig?: IOSProjectConfig) => (api: PluginApi) => PluginOutput; +export default pluginBrownfieldIos; diff --git a/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js new file mode 100644 index 000000000..a04cb6e93 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js @@ -0,0 +1,71 @@ +import path from 'node:path'; +import { createBuild, genericDestinations, getBuildOptions, getBuildPaths, getValidProjectConfig, } from '@rock-js/platform-apple-helpers'; +import { colorLink, intro, logger, outro, relativeToCwd } from '@rock-js/tools'; +import { copyHermesXcframework } from './copyHermesXcframework.js'; +import { mergeFrameworks } from './mergeFrameworks.js'; +const buildOptions = getBuildOptions({ platformName: 'ios' }); +export const pluginBrownfieldIos = (pluginConfig) => (api) => { + api.registerCommand({ + name: 'package:ios', + description: 'Emit a .xcframework file from React Native code.', + action: async (args) => { + intro('Packaging iOS project'); + // 1) Build the project + const projectRoot = api.getProjectRoot(); + const iosConfig = getValidProjectConfig('ios', projectRoot, pluginConfig); + const { derivedDataDir } = getBuildPaths('ios'); + const destination = args.destination ?? [ + genericDestinations.ios.device, + genericDestinations.ios.simulator, + ]; + const buildFolder = args.buildFolder ?? derivedDataDir; + const configuration = args.configuration ?? 'Debug'; + const { sourceDir } = iosConfig; + const { scheme } = await createBuild({ + platformName: 'ios', + projectConfig: iosConfig, + args: { ...args, destination, buildFolder }, + projectRoot, + reactNativePath: api.getReactNativePath(), + fingerprintOptions: api.getFingerprintOptions(), + brownfield: true, + remoteCacheProvider: await api.getRemoteCacheProvider(), + }); + // 2) Merge the .framework outputs of the framework target + const productsPath = path.join(buildFolder, 'Build', 'Products'); + const { packageDir: frameworkTargetOutputDir } = getBuildPaths('ios'); + await mergeFrameworks({ + sourceDir, + frameworkPaths: [ + path.join(productsPath, `${configuration}-iphoneos`, `${scheme}.framework`), + path.join(productsPath, `${configuration}-iphonesimulator`, `${scheme}.framework`), + ], + outputPath: path.join(frameworkTargetOutputDir, `${scheme}.xcframework`), + }); + // 3) Merge React Native Brownfield paths + await mergeFrameworks({ + sourceDir, + frameworkPaths: [ + path.join(productsPath, `${configuration}-iphoneos`, 'ReactBrownfield', 'ReactBrownfield.framework'), + path.join(productsPath, `${configuration}-iphonesimulator`, 'ReactBrownfield', 'ReactBrownfield.framework'), + ], + outputPath: path.join(frameworkTargetOutputDir, 'ReactBrownfield.xcframework'), + }); + // 4) Copy hermes xcframework to the output path + copyHermesXcframework({ + sourceDir, + destinationDir: frameworkTargetOutputDir, + }); + // 5) Inform the user + logger.log(`XCFrameworks are available at: ${colorLink(relativeToCwd(frameworkTargetOutputDir))}`); + outro('Success ๐ŸŽ‰.'); + }, + options: buildOptions, + }); + return { + name: 'plugin-brownfield-ios', + description: 'Rock plugin for brownfield iOS.', + }; +}; +export default pluginBrownfieldIos; +//# sourceMappingURL=pluginBrownfieldIos.js.map \ No newline at end of file diff --git a/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js.map b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js.map new file mode 100644 index 000000000..598bea473 --- /dev/null +++ b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pluginBrownfieldIos.js","sourceRoot":"","sources":["../../../src/lib/pluginBrownfieldIos.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/index.d.ts b/packages/plugin-metro/dist/src/index.d.ts new file mode 100644 index 000000000..aa80ef452 --- /dev/null +++ b/packages/plugin-metro/dist/src/index.d.ts @@ -0,0 +1,2 @@ +export * from './lib/pluginMetro.js'; +export { startDevServer } from './lib/start/command.js'; diff --git a/packages/plugin-metro/dist/src/index.js b/packages/plugin-metro/dist/src/index.js new file mode 100644 index 000000000..69fbb0c00 --- /dev/null +++ b/packages/plugin-metro/dist/src/index.js @@ -0,0 +1,3 @@ +export * from './lib/pluginMetro.js'; +export { startDevServer } from './lib/start/command.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/index.js.map b/packages/plugin-metro/dist/src/index.js.map new file mode 100644 index 000000000..3c3140c47 --- /dev/null +++ b/packages/plugin-metro/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/bundle/command.d.ts b/packages/plugin-metro/dist/src/lib/bundle/command.d.ts new file mode 100644 index 000000000..b1ecd3e91 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/bundle/command.d.ts @@ -0,0 +1,2 @@ +import type { PluginApi } from '@rock-js/config'; +export declare function registerBundleCommand(api: PluginApi): void; diff --git a/packages/plugin-metro/dist/src/lib/bundle/command.js b/packages/plugin-metro/dist/src/lib/bundle/command.js new file mode 100644 index 000000000..365c7e832 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/bundle/command.js @@ -0,0 +1,135 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { colorLink, intro, logger, outro, RockError, runHermes, spinner, } from '@rock-js/tools'; +import { getReactNativeCommunityCliPlugin } from '../getReactNativeDeps.js'; +export function registerBundleCommand(api) { + api.registerCommand({ + name: 'bundle', + description: 'Build the bundle for the provided JavaScript entry file with Metro.', + action: async (args) => { + if (!args.platform || !args.bundleOutput || !args.entryFile) { + throw new RockError('"rock bundle" command requires all of these flags to bundle JavaScript with Metro: \n "--platform", "--bundle-output", "--entry-file"'); + } + intro('Compiling JS bundle with Metro'); + const root = api.getProjectRoot(); + const reactNativeVersion = api.getReactNativeVersion(); + const reactNativePath = api.getReactNativePath(); + const platforms = api.getPlatforms(); + // create the bundle output directory if it doesn't exist + const bundleOutputDir = path.dirname(args.bundleOutput); + fs.mkdirSync(bundleOutputDir, { recursive: true }); + const { bundleCommand } = await getReactNativeCommunityCliPlugin(reactNativePath); + await bundleCommand.func(undefined, { root, reactNativeVersion, reactNativePath, platforms }, args); + if (args.hermes) { + const loader = spinner(); + loader.start('Running Hermes compiler...'); + await runHermes({ + bundleOutputPath: args.bundleOutput, + sourcemapOutputPath: args.sourcemapOutput, + }); + loader.stop(`Hermes bytecode bundle created at: ${colorLink(args.bundleOutput)}`); + } + else { + logger.info(`JavaScript bundle created at: ${colorLink(args.bundleOutput)}`); + } + outro('Success ๐ŸŽ‰.'); + }, + options: [ + { + name: '--entry-file ', + description: 'Path to the root JS file, either absolute or relative to JS root', + }, + { + name: '--platform ', + description: 'Either "ios" or "android"', + default: 'ios', + }, + { + name: '--transformer ', + description: 'Specify a custom transformer to be used', + }, + { + name: '--dev [boolean]', + description: 'If false, warnings are disabled and the bundle is minified', + parse: (val) => val !== 'false', + default: true, + }, + { + name: '--minify [boolean]', + description: 'Allows overriding whether bundle is minified. This defaults to ' + + 'false if dev is true, and true if dev is false. Disabling minification ' + + 'can be useful for speeding up production builds for testing purposes.', + parse: (val) => val !== 'false', + }, + { + name: '--bundle-output ', + description: 'File name where to store the resulting bundle, ex. /tmp/groups.bundle', + }, + { + name: '--bundle-encoding ', + description: 'Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).', + default: 'utf8', + }, + { + name: '--max-workers ', + description: 'Specifies the maximum number of workers the worker-pool ' + + 'will spawn for transforming files. This defaults to the number of the ' + + 'cores available on your machine.', + }, + { + name: '--sourcemap-output ', + description: 'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map', + }, + { + name: '--sourcemap-sources-root ', + description: "Path to make sourcemap's sources entries relative to, ex. /root/dir", + }, + { + name: '--sourcemap-use-absolute-path', + description: 'Report SourceMapURL using its full path', + default: false, + }, + { + name: '--assets-dest ', + description: 'Directory name where to store assets referenced in the bundle', + }, + { + name: '--unstable-transform-profile ', + description: 'Experimental, transform JS for a specific JS engine. Currently supported: hermes, hermes-canary, default', + default: 'default', + }, + { + name: '--asset-catalog-dest [string]', + description: 'Path where to create an iOS Asset Catalog for images', + }, + { + name: '--reset-cache', + description: 'Removes cached files', + default: false, + }, + { + name: '--read-global-cache', + description: 'Try to fetch transformed JS code from the global cache, if configured.', + default: false, + }, + { + name: '--config ', + description: 'Path to the CLI configuration file', + parse: (val) => path.resolve(val), + }, + { + name: '--resolver-option ', + description: 'Custom resolver options of the form key=value. URL-encoded. May be specified multiple times.', + }, + { + name: '--config-cmd [string]', + description: '[Internal] A hack for Xcode build script pointing to wrong bundle command that recognizes this flag. Do not use.', + }, + { + name: '--hermes', + description: 'Passes the output JS bundle to Hermes compiler and outputs a bytecode file.', + }, + ], + }); +} +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/bundle/command.js.map b/packages/plugin-metro/dist/src/lib/bundle/command.js.map new file mode 100644 index 000000000..4e70349a1 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/bundle/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../src/lib/bundle/command.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/getReactNativeDeps.d.ts b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.d.ts new file mode 100644 index 000000000..d5e5c6d34 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.d.ts @@ -0,0 +1,3 @@ +import type devMiddleware from '@react-native/dev-middleware'; +export declare function getDevMiddleware(reactNativePath: string): Promise; +export declare function getReactNativeCommunityCliPlugin(reactNativePath: string): Promise; diff --git a/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js new file mode 100644 index 000000000..d523e094e --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js @@ -0,0 +1,15 @@ +import { createRequire } from 'node:module'; +export async function getDevMiddleware(reactNativePath) { + const require = createRequire(import.meta.url); + const reactNativeCommunityCliPluginPath = require.resolve('@react-native/community-cli-plugin', { paths: [reactNativePath] }); + const devMiddlewarePath = require.resolve('@react-native/dev-middleware', { + paths: [reactNativeCommunityCliPluginPath], + }); + return import(devMiddlewarePath); +} +export async function getReactNativeCommunityCliPlugin(reactNativePath) { + const require = createRequire(import.meta.url); + const reactNativeCommunityCliPluginPath = require.resolve('@react-native/community-cli-plugin', { paths: [reactNativePath] }); + return import(reactNativeCommunityCliPluginPath); +} +//# sourceMappingURL=getReactNativeDeps.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js.map b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js.map new file mode 100644 index 000000000..adbcfd054 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getReactNativeDeps.js","sourceRoot":"","sources":["../../../src/lib/getReactNativeDeps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,eAAuB;IAEvB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,iCAAiC,GAAG,OAAO,CAAC,OAAO,CACvD,oCAAoC,EACpC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,CAC7B,CAAC;IAEF,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,8BAA8B,EAAE;QACxE,KAAK,EAAE,CAAC,iCAAiC,CAAC;KAC3C,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,eAAuB;IAEvB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,iCAAiC,GAAG,OAAO,CAAC,OAAO,CACvD,oCAAoC,EACpC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,CAC7B,CAAC;IAEF,OAAO,MAAM,CAAC,iCAAiC,CAAC,CAAC;AACnD,CAAC"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/pluginMetro.d.ts b/packages/plugin-metro/dist/src/lib/pluginMetro.d.ts new file mode 100644 index 000000000..83032bbae --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/pluginMetro.d.ts @@ -0,0 +1,3 @@ +import type { BundlerPluginOutput, PluginApi } from '@rock-js/config'; +export declare const pluginMetro: () => (api: PluginApi) => BundlerPluginOutput; +export default pluginMetro; diff --git a/packages/plugin-metro/dist/src/lib/pluginMetro.js b/packages/plugin-metro/dist/src/lib/pluginMetro.js new file mode 100644 index 000000000..3ebc678ac --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/pluginMetro.js @@ -0,0 +1,13 @@ +import { registerBundleCommand } from './bundle/command.js'; +import { registerStartCommand, startDevServer } from './start/command.js'; +export const pluginMetro = () => (api) => { + registerStartCommand(api); + registerBundleCommand(api); + return { + name: '@rock-js/plugin-metro', + description: 'Rock plugin for Metro bundler.', + start: startDevServer, + }; +}; +export default pluginMetro; +//# sourceMappingURL=pluginMetro.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/pluginMetro.js.map b/packages/plugin-metro/dist/src/lib/pluginMetro.js.map new file mode 100644 index 000000000..ba4aa4f90 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/pluginMetro.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pluginMetro.js","sourceRoot":"","sources":["../../../src/lib/pluginMetro.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,CAAC,MAAM,WAAW,GACtB,GAAG,EAAE,CACL,CAAC,GAAc,EAAuB,EAAE;IACtC,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAC1B,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,gCAAgC;QAC7C,KAAK,EAAE,cAAc;KACtB,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,WAAW,CAAC"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.d.ts b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.d.ts new file mode 100644 index 000000000..95992e889 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.d.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import type { TerminalReporter } from 'metro'; +export default class OpenDebuggerKeyboardHandler { + #private; + constructor({ devServerUrl, reporter, }: { + devServerUrl: string; + reporter: TerminalReporter; + }); + /** + * Used in response to 'j' to debug - fetch the available debug targets and: + * - If no targets, warn + * - If one target, open it + * - If more, show a list. The keyboard listener should run subsequent key + * presses through maybeHandleTargetSelection, which will launch the + * debugger if a match is made. + */ + handleOpenDebugger(): Promise; + /** + * Handle key presses that correspond to a valid selection from a visible + * selection list. + * + * @return true if we've handled the key as a target selection, false if the + * caller should handle the key. + */ + maybeHandleTargetSelection(keyName: string): boolean; + /** + * Dismiss any target selection UI, if shown. + */ + dismiss(): void; +} diff --git a/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js new file mode 100644 index 000000000..3d22efee9 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js @@ -0,0 +1,128 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import { color } from '@rock-js/tools'; +export default class OpenDebuggerKeyboardHandler { + #devServerUrl; + #reporter; + #targetsShownForSelection = null; + constructor({ devServerUrl, reporter, }) { + this.#devServerUrl = devServerUrl; + this.#reporter = reporter; + } + async #tryOpenDebuggerForTarget(target) { + this.#targetsShownForSelection = null; + this.#clearTerminalMenu(); + try { + await fetch(new URL('/open-debugger?target=' + encodeURIComponent(target.id), this.#devServerUrl).href, { method: 'POST' }); + } + catch (e) { + this.#log('error', 'Failed to open debugger for %s (%s): %s', target.title, target.description, 'Network error'); + // @ts-expect-error - TBD + if (e.cause != null) { + // @ts-expect-error - it's not null + this.#log('error', 'Cause: %s', e.cause); + } + this.#clearTerminalMenu(); + } + } + /** + * Used in response to 'j' to debug - fetch the available debug targets and: + * - If no targets, warn + * - If one target, open it + * - If more, show a list. The keyboard listener should run subsequent key + * presses through maybeHandleTargetSelection, which will launch the + * debugger if a match is made. + */ + async handleOpenDebugger() { + this.#setTerminalMenu('Fetching available debugging targets...'); + this.#targetsShownForSelection = null; + try { + const res = await fetch(this.#devServerUrl + '/json/list', { + method: 'POST', + }); + if (res.status !== 200) { + throw new Error(`Unexpected status code: ${res.status}`); + } + const targets = (await res.json()); + if (!Array.isArray(targets)) { + throw new Error('Expected array.'); + } + if (targets.length === 0) { + this.#log('warn', 'No connected targets'); + this.#clearTerminalMenu(); + } + else if (targets.length === 1) { + const target = targets[0]; + void this.#tryOpenDebuggerForTarget(target); + } + else { + this.#targetsShownForSelection = targets; + if (targets.length > 9) { + this.#log('warn', '10 or more debug targets available, showing the first 9.'); + } + this.#setTerminalMenu(`Multiple debug targets available, please select:\n ${targets + .slice(0, 9) + .map(({ title }, i) => `${color.inverse(` ${i + 1} `)} - "${title}"`) + .join('\n ')}`); + } + } + catch (e) { + // @ts-expect-error - error is not typed + this.#log('error', `Failed to fetch debug targets: ${e.message}`); + this.#clearTerminalMenu(); + } + } + /** + * Handle key presses that correspond to a valid selection from a visible + * selection list. + * + * @return true if we've handled the key as a target selection, false if the + * caller should handle the key. + */ + maybeHandleTargetSelection(keyName) { + if (keyName >= '1' && keyName <= '9') { + const targetIndex = Number(keyName) - 1; + if (this.#targetsShownForSelection != null && + targetIndex < this.#targetsShownForSelection.length) { + const target = this.#targetsShownForSelection[targetIndex]; + void this.#tryOpenDebuggerForTarget(target); + return true; + } + } + return false; + } + /** + * Dismiss any target selection UI, if shown. + */ + dismiss() { + this.#clearTerminalMenu(); + this.#targetsShownForSelection = null; + } + #log(level, ...data) { + this.#reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + // @ts-expect-error - metro types are not updated + level, + data, + }); + } + #setTerminalMenu(message) { + this.#reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_menu_updated', + message, + }); + } + #clearTerminalMenu() { + this.#reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_menu_cleared', + }); + } +} +//# sourceMappingURL=OpenDebuggerKeyboardHandler.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js.map b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js.map new file mode 100644 index 000000000..e1d351d44 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js.map @@ -0,0 +1 @@ +{"version":3,"file":"OpenDebuggerKeyboardHandler.js","sourceRoot":"","sources":["../../../../src/lib/start/OpenDebuggerKeyboardHandler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AASvC,MAAM,CAAC,OAAO,OAAO,2BAA2B;IAC9C,aAAa,CAAS;IACtB,SAAS,CAAmB;IAC5B,yBAAyB,GAA0C,IAAI,CAAC;IAExE,YAAY,EACV,YAAY,EACZ,QAAQ,GAIT;QACC,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,MAAuB;QACrD,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE1B,IAAI,CAAC;YACH,MAAM,KAAK,CACT,IAAI,GAAG,CACL,wBAAwB,GAAG,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,EACxD,IAAI,CAAC,aAAa,CACnB,CAAC,IAAI,EACN,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CACP,OAAO,EACP,yCAAyC,EACzC,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,WAAW,EAClB,eAAe,CAChB,CAAC;YACF,yBAAyB;YACzB,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACpB,mCAAmC;gBACnC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC,gBAAgB,CAAC,yCAAyC,CAAC,CAAC;QACjE,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,YAAY,EAAE;gBACzD,MAAM,EAAE,MAAM;aACf,CAAC,CAAC;YAEH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAC3D,CAAC;YACD,MAAM,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmC,CAAC;YACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;gBAC1C,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;iBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAE1B,KAAK,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,yBAAyB,GAAG,OAAO,CAAC;gBAEzC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,IAAI,CAAC,IAAI,CACP,MAAM,EACN,0DAA0D,CAC3D,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,gBAAgB,CACnB,uDAAuD,OAAO;qBAC3D,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;qBACX,GAAG,CACF,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,KAAK,GAAG,CAChE;qBACA,IAAI,CAAC,MAAM,CAAC,EAAE,CAClB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,wCAAwC;YACxC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAClE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,0BAA0B,CAAC,OAAe;QACxC,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,IAAI,GAAG,EAAE,CAAC;YACrC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACxC,IACE,IAAI,CAAC,yBAAyB,IAAI,IAAI;gBACtC,WAAW,GAAG,IAAI,CAAC,yBAAyB,CAAC,MAAM,EACnD,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAC;gBAE3D,KAAK,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC;gBAC5C,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;IACxC,CAAC;IAED,IAAI,CAAC,KAAgC,EAAE,GAAG,IAAoB;QAC5D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACpB,iDAAiD;YACjD,IAAI,EAAE,qBAAqB;YAC3B,iDAAiD;YACjD,KAAK;YACL,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,OAAe;QAC9B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACpB,iDAAiD;YACjD,IAAI,EAAE,8BAA8B;YACpC,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACpB,iDAAiD;YACjD,IAAI,EAAE,8BAA8B;SACrC,CAAC,CAAC;IACL,CAAC;CACF"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.d.ts b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.d.ts new file mode 100644 index 000000000..89dfe2e88 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.d.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import type { TerminalReporter } from 'metro'; +export default function attachKeyHandlers({ devServerUrl, messageSocket, reporter, }: { + devServerUrl: string; + messageSocket: { + broadcast: (type: string, params?: Record | null) => void; + }; + reporter: TerminalReporter; +}): void; diff --git a/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js new file mode 100644 index 000000000..41a201ba1 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js @@ -0,0 +1,109 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import readline from 'node:readline'; +import { ReadStream } from 'node:tty'; +import { color, RockError } from '@rock-js/tools'; +import OpenDebuggerKeyboardHandler from './OpenDebuggerKeyboardHandler.js'; +const CTRL_C = '\u0003'; +const CTRL_D = '\u0004'; +const RELOAD_TIMEOUT = 500; +const throttle = (callback, timeout) => { + let previousCallTimestamp = 0; + return () => { + const currentCallTimestamp = new Date().getTime(); + if (currentCallTimestamp - previousCallTimestamp > timeout) { + previousCallTimestamp = currentCallTimestamp; + callback(); + } + }; +}; +export default function attachKeyHandlers({ devServerUrl, messageSocket, reporter, }) { + if (process.stdin.isTTY !== true) { + reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + level: 'info', + // @ts-expect-error - metro types are not updated + data: 'Interactive mode is not supported in this environment', + }); + return; + } + readline.emitKeypressEvents(process.stdin); + setRawMode(true); + // resume stdin to allow reading keypresses + process.stdin.resume(); + const reload = throttle(() => { + reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + level: 'info', + // @ts-expect-error - metro types are not updated + data: 'Reloading connected app(s)...', + }); + messageSocket.broadcast('reload', null); + }, RELOAD_TIMEOUT); + const openDebuggerKeyboardHandler = new OpenDebuggerKeyboardHandler({ + reporter, + devServerUrl, + }); + process.stdin.on('keypress', (str, key) => { + if (openDebuggerKeyboardHandler.maybeHandleTargetSelection(key.name)) { + return; + } + switch (key.sequence) { + case 'r': + reload(); + break; + case 'd': + reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + level: 'info', + // @ts-expect-error - metro types are not updated + data: 'Opening Dev Menu...', + }); + messageSocket.broadcast('devMenu', null); + break; + case 'j': + void openDebuggerKeyboardHandler.handleOpenDebugger(); + break; + case CTRL_C: + case CTRL_D: + openDebuggerKeyboardHandler.dismiss(); + reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + level: 'info', + // @ts-expect-error - metro types are not updated + data: 'Stopping server', + }); + setRawMode(false); + process.stdin.pause(); + process.emit('SIGINT'); + process.exit(); + } + }); + reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + level: 'info', + // @ts-expect-error - metro types are not updated + data: `Key commands available: + + ${color.bold(color.inverse(' r '))} - reload app(s) + ${color.bold(color.inverse(' d '))} - open Dev Menu + ${color.bold(color.inverse(' j '))} - open DevTools +`, + }); +} +function setRawMode(enable) { + if (!(process.stdin instanceof ReadStream)) { + throw new RockError('process.stdin must be a readable stream to modify raw mode'); + } + process.stdin.setRawMode(enable); +} +//# sourceMappingURL=attachKeyHandlers.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js.map b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js.map new file mode 100644 index 000000000..03159d2d6 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"attachKeyHandlers.js","sourceRoot":"","sources":["../../../../src/lib/start/attachKeyHandlers.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/command.d.ts b/packages/plugin-metro/dist/src/lib/start/command.d.ts new file mode 100644 index 000000000..4faafa4ae --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/command.d.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import type { PluginApi } from '@rock-js/config'; +import type { StartDevServerArgs } from '@rock-js/config'; +export declare function startDevServer({ root, args, reactNativeVersion, reactNativePath, platforms, }: StartDevServerArgs): Promise; +export declare const registerStartCommand: (api: PluginApi) => void; diff --git a/packages/plugin-metro/dist/src/lib/start/command.js b/packages/plugin-metro/dist/src/lib/start/command.js new file mode 100644 index 000000000..cfd7cd6d6 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/command.js @@ -0,0 +1,110 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import path from 'node:path'; +import { findDevServerPort, intro } from '@rock-js/tools'; +import runServer from './runServer.js'; +export async function startDevServer({ root, args, reactNativeVersion, reactNativePath, platforms, }) { + const { port, startDevServer } = await findDevServerPort(args.port ? Number(args.port) : 8081, root); + if (!startDevServer) { + return; + } + return runServer({ root, reactNativeVersion, reactNativePath, platforms }, { ...args, port, platforms: Object.keys(platforms) }); +} +export const registerStartCommand = (api) => { + api.registerCommand({ + name: 'start', + action: async (args) => { + intro('Starting Metro dev server'); + startDevServer({ + root: api.getProjectRoot(), + reactNativeVersion: api.getReactNativeVersion(), + reactNativePath: api.getReactNativePath(), + platforms: api.getPlatforms(), + args, + }); + }, + description: 'Start the Metro development server.', + options: [ + { + name: '--port ', + description: 'Port to run the server on', + }, + { + name: '--host ', + description: 'Host to run the server on', + default: '', + }, + { + name: '--project-root, --projectRoot ', + description: 'Path to a custom project root', + parse: (val) => path.resolve(val), + }, + { + name: '--watch-folders, --watchFolders ', + description: 'Specify any additional folders to be added to the watch list', + parse: (val) => val.split(',').map((folder) => path.resolve(folder)), + }, + { + name: '--asset-plugins, --assetPlugins ', + description: 'Specify any additional asset plugins to be used by the packager by full filepath', + parse: (val) => val.split(','), + }, + { + name: '--source-exts, --sourceExts ', + description: 'Specify any additional source extensions to be used by the packager', + parse: (val) => val.split(','), + }, + { + name: '--max-workers ', + description: 'Specifies the maximum number of workers the worker-pool ' + + 'will spawn for transforming files. This defaults to the number of the ' + + 'cores available on your machine.', + }, + { + name: '--transformer ', + description: 'Specify a custom transformer to be used', + }, + { + name: '--reset-cache, --resetCache', + description: 'Removes cached files', + }, + { + name: '--custom-log-reporter-path, --customLogReporterPath ', + description: 'Path to a JavaScript file that exports a log reporter as a replacement for TerminalReporter', + }, + { + name: '--https', + description: 'Enables https connections to the server', + }, + { + name: '--key ', + description: 'Path to custom SSL key', + }, + { + name: '--cert ', + description: 'Path to custom SSL cert', + }, + { + name: '--config ', + description: 'Path to the CLI configuration file', + parse: (val) => path.resolve(val), + }, + { + name: '--no-interactive', + description: 'Disables interactive mode', + }, + { + name: '--client-logs', + description: '[Deprecated] Enable plain text JavaScript log streaming for all ' + + 'connected apps. This feature is deprecated and will be removed in ' + + 'future.', + default: false, + }, + ], + }); +}; +//# sourceMappingURL=command.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/command.js.map b/packages/plugin-metro/dist/src/lib/start/command.js.map new file mode 100644 index 000000000..0af7e3ea3 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../src/lib/start/command.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,IAAI,EACJ,IAAI,EACJ,kBAAkB,EAClB,eAAe,EACf,SAAS,GACU;IACnB,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,MAAM,iBAAiB,CACtD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EACpC,IAAI,CACL,CAAC;IAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IAED,OAAO,SAAS,CACd,EAAE,IAAI,EAAE,kBAAkB,EAAE,eAAe,EAAE,SAAS,EAAE,EACxD,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CACrD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAc,EAAE,EAAE;IACrD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,KAAK,EAAE,IAAsB,EAAE,EAAE;YACvC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACnC,cAAc,CAAC;gBACb,IAAI,EAAE,GAAG,CAAC,cAAc,EAAE;gBAC1B,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,eAAe,EAAE,GAAG,CAAC,kBAAkB,EAAE;gBACzC,SAAS,EAAE,GAAG,CAAC,YAAY,EAAE;gBAC7B,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QACD,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,iBAAiB;gBACvB,WAAW,EAAE,2BAA2B;aACzC;YACD;gBACE,IAAI,EAAE,iBAAiB;gBACvB,WAAW,EAAE,2BAA2B;gBACxC,OAAO,EAAE,EAAE;aACZ;YACD;gBACE,IAAI,EAAE,sCAAsC;gBAC5C,WAAW,EAAE,+BAA+B;gBAC5C,KAAK,EAAE,CAAC,GAAW,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;aAClD;YACD;gBACE,IAAI,EAAE,wCAAwC;gBAC9C,WAAW,EACT,8DAA8D;gBAChE,KAAK,EAAE,CAAC,GAAW,EAAiB,EAAE,CACpC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;aAC/D;YACD;gBACE,IAAI,EAAE,wCAAwC;gBAC9C,WAAW,EACT,kFAAkF;gBACpF,KAAK,EAAE,CAAC,GAAW,EAAiB,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;aACtD;YACD;gBACE,IAAI,EAAE,oCAAoC;gBAC1C,WAAW,EACT,qEAAqE;gBACvE,KAAK,EAAE,CAAC,GAAW,EAAiB,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;aACtD;YACD;gBACE,IAAI,EAAE,wBAAwB;gBAC9B,WAAW,EACT,0DAA0D;oBAC1D,wEAAwE;oBACxE,kCAAkC;aACrC;YACD;gBACE,IAAI,EAAE,wBAAwB;gBAC9B,WAAW,EAAE,yCAAyC;aACvD;YACD;gBACE,IAAI,EAAE,6BAA6B;gBACnC,WAAW,EAAE,sBAAsB;aACpC;YACD;gBACE,IAAI,EAAE,8DAA8D;gBACpE,WAAW,EACT,6FAA6F;aAChG;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,yCAAyC;aACvD;YACD;gBACE,IAAI,EAAE,cAAc;gBACpB,WAAW,EAAE,wBAAwB;aACtC;YACD;gBACE,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,yBAAyB;aACvC;YACD;gBACE,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,oCAAoC;gBACjD,KAAK,EAAE,CAAC,GAAW,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;aAClD;YACD;gBACE,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,2BAA2B;aACzC;YACD;gBACE,IAAI,EAAE,eAAe;gBACrB,WAAW,EACT,kEAAkE;oBAClE,oEAAoE;oBACpE,SAAS;gBACX,OAAO,EAAE,KAAK;aACf;SACF;KACF,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.d.ts b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.d.ts new file mode 100644 index 000000000..576371fbe --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.d.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import type { TerminalReporter } from 'metro'; +type LoggerFn = (...message: ReadonlyArray) => void; +/** + * Create a dev-middleware logger object that will emit logs via Metro's + * terminal reporter. + */ +export default function createDevMiddlewareLogger(reporter: TerminalReporter): Readonly<{ + info: LoggerFn; + error: LoggerFn; + warn: LoggerFn; +}>; +export {}; diff --git a/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js new file mode 100644 index 000000000..936efd8ca --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** + * Create a dev-middleware logger object that will emit logs via Metro's + * terminal reporter. + */ +export default function createDevMiddlewareLogger(reporter) { + return { + info: makeLogger(reporter, 'info'), + warn: makeLogger(reporter, 'warn'), + error: makeLogger(reporter, 'error'), + }; +} +function makeLogger(reporter, level) { + return (...data) => reporter.update({ + // @ts-expect-error - metro types are not updated + type: 'unstable_server_log', + // @ts-expect-error - metro types are not updated + level, + data, + }); +} +//# sourceMappingURL=createDevMiddlewareLogger.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js.map b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js.map new file mode 100644 index 000000000..49ec024ab --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"createDevMiddlewareLogger.js","sourceRoot":"","sources":["../../../../src/lib/start/createDevMiddlewareLogger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,QAA0B;IAM1B,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;QAClC,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;QAClC,KAAK,EAAE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CACjB,QAA0B,EAC1B,KAAgC;IAEhC,OAAO,CAAC,GAAG,IAAoB,EAAE,EAAE,CACjC,QAAQ,CAAC,MAAM,CAAC;QACd,iDAAiD;QACjD,IAAI,EAAE,qBAAqB;QAC3B,iDAAiD;QACjD,KAAK;QACL,IAAI;KACL,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.d.ts b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.d.ts new file mode 100644 index 000000000..5b5fa9eb6 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.d.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import type { ConfigT, YargArguments } from 'metro-config'; +export type ConfigLoadingContext = Readonly<{ + root: string; + reactNativePath: string; + platforms: Record; +}>; +/** + * Load Metro config. + * + * Allows the CLI to override select values in `metro.config.js` based on + * dynamic user options in `ctx`. + */ +export default function loadMetroConfig(ctx: { + platforms: Record; + reactNativeVersion: string; + reactNativePath: string; + root: string; +}, options?: YargArguments): Promise; diff --git a/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js new file mode 100644 index 000000000..761308c62 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js @@ -0,0 +1,101 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import { createRequire } from 'node:module'; +import path from 'node:path'; +import { logger, RockError } from '@rock-js/tools'; +import { loadConfig, mergeConfig, resolveConfig } from 'metro-config'; +import { reactNativePlatformResolver } from './metroPlatformResolver.js'; +/** + * Get the config options to override based on RN CLI inputs. + */ +function getCommunityCliDefaultConfig(ctx, config) { + const outOfTreePlatforms = Object.keys(ctx.platforms).filter( + // @ts-expect-error - TBD + (platform) => ctx.platforms[platform].npmPackageName); + const resolver = { + platforms: [...Object.keys(ctx.platforms), 'native'], + }; + if (outOfTreePlatforms.length) { + // @ts-expect-error - TBD + resolver.resolveRequest = reactNativePlatformResolver(outOfTreePlatforms.reduce((result, platform) => { + // @ts-expect-error - TBD + result[platform] = ctx.platforms[platform].npmPackageName; + return result; + }, {}), config.resolver?.resolveRequest); + } + const require = createRequire(import.meta.url); + return { + resolver, + serializer: { + // We can include multiple copies of InitializeCore here because metro will + // only add ones that are already part of the bundle + getModulesRunBeforeMainModule: () => [ + require.resolve(path.join(ctx.reactNativePath, 'Libraries/Core/InitializeCore'), { paths: [ctx.root] }), + ...outOfTreePlatforms.map((platform) => require.resolve( + // @ts-expect-error - TBD + `${ctx.platforms[platform].npmPackageName}/Libraries/Core/InitializeCore`, { paths: [ctx.root] })), + ], + }, + }; +} +/** + * Load Metro config. + * + * Allows the CLI to override select values in `metro.config.js` based on + * dynamic user options in `ctx`. + */ +export default async function loadMetroConfig(ctx, options = {}) { + const require = createRequire(import.meta.url); + let RNMetroConfig = null; + try { + RNMetroConfig = await import(require.resolve('@react-native/metro-config', { paths: [ctx.root] })); + } + catch { + throw new Error("Cannot resolve `@react-native/metro-config`. Ensure it is listed in your project's `devDependencies`."); + } + // Get the RN defaults before our customisations + const defaultConfig = RNMetroConfig.getDefaultConfig(ctx.root); + // Unflag the config as being loaded - it must be loaded again in userland. + // @ts-expect-error - overriding global + global.__REACT_NATIVE_METRO_CONFIG_LOADED = false; + // Add our defaults to `@react-native/metro-config` before the user config + // loads them. + // Available since RN 0.81 + if (typeof RNMetroConfig.setFrameworkDefaults === 'function') { + RNMetroConfig.setFrameworkDefaults(getCommunityCliDefaultConfig(ctx, defaultConfig)); + } + const cwd = ctx.root; + const projectConfig = await resolveConfig(options.config, cwd); + if (projectConfig.isEmpty) { + throw new RockError(`No Metro config found in ${cwd}`); + } + logger.debug(`Reading Metro config from ${projectConfig.filepath}`); + // @ts-expect-error - we're fine with this + if (!global.__REACT_NATIVE_METRO_CONFIG_LOADED) { + const warning = ` +================================================================================================= +From React Native 0.73, your project's Metro config should extend '@react-native/metro-config' +or it will fail to build. Please copy the template at: +https://github.com/react-native-community/template/blob/main/template/metro.config.js +This warning will be removed in future (https://github.com/facebook/metro/issues/1018). +================================================================================================= + `; + for (const line of warning.trim().split('\n')) { + console.warn(line); + } + } + const config = await loadConfig({ cwd, ...options }); + if (typeof RNMetroConfig.setFrameworkDefaults === 'function') { + return config; + } + else { + // Fallback to the old API for RN < 0.81 + const overrideConfig = getCommunityCliDefaultConfig(ctx, config); + return mergeConfig(config, overrideConfig); + } +} +//# sourceMappingURL=loadMetroConfig.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js.map b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js.map new file mode 100644 index 000000000..d1bb19233 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"loadMetroConfig.js","sourceRoot":"","sources":["../../../../src/lib/start/loadMetroConfig.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.d.ts b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.d.ts new file mode 100644 index 000000000..b156e337d --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.d.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import type { CustomResolver } from 'metro-resolver'; +/** + * This is an implementation of a metro resolveRequest option which will remap react-native imports + * to different npm packages based on the platform requested. This allows a single metro instance/config + * to produce bundles for multiple out of tree platforms at a time. + * + * @param platformImplementations + * A map of platform to npm package that implements that platform + * + * Ex: + * { + * windows: 'react-native-windows' + * macos: 'react-native-macos' + * } + */ +export declare function reactNativePlatformResolver(platformImplementations: { + [platform: string]: string; +}, customResolver: CustomResolver | null | undefined): CustomResolver; diff --git a/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js new file mode 100644 index 000000000..ba2f50841 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js @@ -0,0 +1,38 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** + * This is an implementation of a metro resolveRequest option which will remap react-native imports + * to different npm packages based on the platform requested. This allows a single metro instance/config + * to produce bundles for multiple out of tree platforms at a time. + * + * @param platformImplementations + * A map of platform to npm package that implements that platform + * + * Ex: + * { + * windows: 'react-native-windows' + * macos: 'react-native-macos' + * } + */ +export function reactNativePlatformResolver(platformImplementations, customResolver) { + return (context, moduleName, platform) => { + let modifiedModuleName = moduleName; + if (platform != null && platformImplementations[platform]) { + if (moduleName === 'react-native') { + modifiedModuleName = platformImplementations[platform]; + } + else if (moduleName.startsWith('react-native/')) { + modifiedModuleName = `${platformImplementations[platform]}/${modifiedModuleName.slice('react-native/'.length)}`; + } + } + if (customResolver) { + return customResolver(context, modifiedModuleName, platform); + } + return context.resolveRequest(context, modifiedModuleName, platform); + }; +} +//# sourceMappingURL=metroPlatformResolver.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js.map b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js.map new file mode 100644 index 000000000..047f8f306 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js.map @@ -0,0 +1 @@ +{"version":3,"file":"metroPlatformResolver.js","sourceRoot":"","sources":["../../../../src/lib/start/metroPlatformResolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,2BAA2B,CACzC,uBAEC,EACD,cAAiD;IAEjD,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;QACvC,IAAI,kBAAkB,GAAG,UAAU,CAAC;QACpC,IAAI,QAAQ,IAAI,IAAI,IAAI,uBAAuB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1D,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;gBAClC,kBAAkB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACzD,CAAC;iBAAM,IAAI,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;gBAClD,kBAAkB,GAAG,GACnB,uBAAuB,CAAC,QAAQ,CAClC,IAAI,kBAAkB,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,CAAC;QACH,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/runServer.d.ts b/packages/plugin-metro/dist/src/lib/start/runServer.d.ts new file mode 100644 index 000000000..760ec9c5f --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/runServer.d.ts @@ -0,0 +1,32 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +export type StartCommandArgs = { + assetPlugins?: string[]; + cert?: string; + customLogReporterPath?: string; + host?: string; + https?: boolean; + maxWorkers?: string; + key?: string; + platforms: string[]; + port?: string; + resetCache?: boolean; + sourceExts?: string[]; + transformer?: string; + watchFolders?: string[]; + config?: string; + projectRoot?: string; + interactive: boolean; + clientLogs: boolean; +}; +declare function runServer(options: { + platforms: Record; + reactNativeVersion: string; + reactNativePath: string; + root: string; +}, args: StartCommandArgs): Promise; +export default runServer; diff --git a/packages/plugin-metro/dist/src/lib/start/runServer.js b/packages/plugin-metro/dist/src/lib/start/runServer.js new file mode 100644 index 000000000..40bb4269a --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/runServer.js @@ -0,0 +1,138 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import { createRequire } from 'node:module'; +import path from 'node:path'; +import url from 'node:url'; +import { createDevServerMiddleware } from '@react-native-community/cli-server-api'; +import { color } from '@rock-js/tools'; +import Metro from 'metro'; +import { Terminal } from 'metro-core'; +import { getDevMiddleware } from '../getReactNativeDeps.js'; +import attachKeyHandlers from './attachKeyHandlers.js'; +import createDevMiddlewareLogger from './createDevMiddlewareLogger.js'; +import loadMetroConfig from './loadMetroConfig.js'; +async function runServer(options, args) { + const metroConfig = await loadMetroConfig({ + platforms: options.platforms, + reactNativeVersion: options.reactNativeVersion, + reactNativePath: options.reactNativePath, + root: options.root, + }, { + config: args.config, + maxWorkers: args.maxWorkers, + port: args.port, + resetCache: args.resetCache, + watchFolders: args.watchFolders, + projectRoot: args.projectRoot, + sourceExts: args.sourceExts, + }); + const hostname = args.host?.length ? args.host : 'localhost'; + const { projectRoot, server: { port }, watchFolders, } = metroConfig; + const protocol = args.https === true ? 'https' : 'http'; + const devServerUrl = url.format({ protocol, hostname, port }); + console.info(`Starting dev server on ${devServerUrl}\n`); + if (args.assetPlugins) { + // @ts-expect-error Assigning to readonly property + metroConfig.transformer.assetPlugins = args.assetPlugins.map((plugin) => require.resolve(plugin)); + } + // TODO(T214991636): Remove legacy Metro log forwarding + if (!args.clientLogs) { + // @ts-expect-error Assigning to readonly property + metroConfig.server.forwardClientLogs = false; + } + let reportEvent = () => { + // do nothing + }; + const terminal = new Terminal(process.stdout); + const ReporterImpl = getReporterImpl(args.customLogReporterPath); + // @ts-expect-error - metro types are not updated + const terminalReporter = new ReporterImpl(terminal); + const { middleware: communityMiddleware, websocketEndpoints: communityWebsocketEndpoints, messageSocketEndpoint, eventsSocketEndpoint, } = createDevServerMiddleware({ + host: hostname, + port, + watchFolders, + }); + const { createDevMiddleware } = await getDevMiddleware(options.reactNativePath); + const { middleware, websocketEndpoints } = createDevMiddleware({ + projectRoot, + serverBaseUrl: devServerUrl, + logger: createDevMiddlewareLogger(terminalReporter), + }); + const reporter = { + update(event) { + terminalReporter.update(event); + if (reportEvent) { + reportEvent(event); + } + if (args.interactive && event.type === 'initialize_done') { + terminalReporter.update({ + type: 'unstable_server_log', + level: 'info', + data: `Dev server ready. ${color.dim('Press Ctrl+C to exit.')}`, + }); + attachKeyHandlers({ + devServerUrl, + // @ts-expect-error - TBD + messageSocket: messageSocketEndpoint, + reporter: terminalReporter, + }); + } + }, + }; + // @ts-expect-error Assigning to readonly property + metroConfig.reporter = reporter; + const { httpServer: serverInstance } = await Metro.runServer(metroConfig, { + host: args.host, + secure: args.https, + secureCert: args.cert, + secureKey: args.key, + unstable_extraMiddleware: [communityMiddleware, middleware], + websocketEndpoints: { + ...communityWebsocketEndpoints, + ...websocketEndpoints, + }, + }); + reportEvent = eventsSocketEndpoint.reportEvent; + // In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In + // early versions of Node 8, this was implemented in a buggy way which caused + // some HTTP responses (like those containing large JS bundles) to be + // terminated early. + // + // As a workaround, arbitrarily increase the keep-alive from 5 to 30 seconds, + // which should be enough to send even the largest of JS bundles. + // + // For more info: https://github.com/nodejs/node/issues/13391 + // + serverInstance.keepAliveTimeout = 30000; +} +const require = createRequire(import.meta.url); +function getReporterImpl(customLogReporterPath) { + if (customLogReporterPath == null) { + try { + return require('metro').TerminalReporter; + } + catch { + // Fallback to legacy path for Metro < 0.83 + return require('metro/src/lib/TerminalReporter'); + } + } + try { + // First we let require resolve it, so we can require packages in node_modules + // as expected. eg: require('my-package/reporter'); + return require(customLogReporterPath); + } + catch (e) { + if (e instanceof Error && 'code' in e && e.code !== 'MODULE_NOT_FOUND') { + throw e; + } + // If that doesn't work, then we next try relative to the cwd, eg: + // require('./reporter'); + return require(path.resolve(customLogReporterPath)); + } +} +export default runServer; +//# sourceMappingURL=runServer.js.map \ No newline at end of file diff --git a/packages/plugin-metro/dist/src/lib/start/runServer.js.map b/packages/plugin-metro/dist/src/lib/start/runServer.js.map new file mode 100644 index 000000000..78076d438 --- /dev/null +++ b/packages/plugin-metro/dist/src/lib/start/runServer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runServer.js","sourceRoot":"","sources":["../../../../src/lib/start/runServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAOvC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,iBAAiB,MAAM,wBAAwB,CAAC;AACvD,OAAO,yBAAyB,MAAM,gCAAgC,CAAC;AACvE,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAsBnD,KAAK,UAAU,SAAS,CACtB,OAKC,EACD,IAAsB;IAEtB,MAAM,WAAW,GAAG,MAAM,eAAe,CACvC;QACE,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,EACD;QACE,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CACF,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7D,MAAM,EACJ,WAAW,EACX,MAAM,EAAE,EAAE,IAAI,EAAE,EAChB,YAAY,GACb,GAAG,WAAW,CAAC;IAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IACxD,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO,CAAC,IAAI,CAAC,0BAA0B,YAAY,IAAI,CAAC,CAAC;IAEzD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,kDAAkD;QAClD,WAAW,CAAC,WAAW,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACtE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CACxB,CAAC;IACJ,CAAC;IACD,uDAAuD;IACvD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACrB,kDAAkD;QAClD,WAAW,CAAC,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;IAC/C,CAAC;IAED,IAAI,WAAW,GAA6C,GAAG,EAAE;QAC/D,aAAa;IACf,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACjE,iDAAiD;IACjD,MAAM,gBAAgB,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEpD,MAAM,EACJ,UAAU,EAAE,mBAAmB,EAC/B,kBAAkB,EAAE,2BAA2B,EAC/C,qBAAqB,EACrB,oBAAoB,GACrB,GAAG,yBAAyB,CAAC;QAC5B,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,YAAY;KACb,CAAC,CAAC;IACH,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,gBAAgB,CACpD,OAAO,CAAC,eAAe,CACxB,CAAC;IACF,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,GAAG,mBAAmB,CAAC;QAC7D,WAAW;QACX,aAAa,EAAE,YAAY;QAC3B,MAAM,EAAE,yBAAyB,CAAC,gBAAgB,CAAC;KACpD,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAa;QACzB,MAAM,CAAC,KAA8B;YACnC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACzD,gBAAgB,CAAC,MAAM,CAAC;oBACtB,IAAI,EAAE,qBAAqB;oBAC3B,KAAK,EAAE,MAAM;oBACb,IAAI,EAAE,qBAAqB,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE;iBAChE,CAAC,CAAC;gBACH,iBAAiB,CAAC;oBAChB,YAAY;oBACZ,yBAAyB;oBACzB,aAAa,EAAE,qBAAqB;oBACpC,QAAQ,EAAE,gBAAgB;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC;IACF,kDAAkD;IAClD,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAEhC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE;QACxE,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,KAAK;QAClB,UAAU,EAAE,IAAI,CAAC,IAAI;QACrB,SAAS,EAAE,IAAI,CAAC,GAAG;QACnB,wBAAwB,EAAE,CAAC,mBAAmB,EAAE,UAAU,CAAC;QAC3D,kBAAkB,EAAE;YAClB,GAAG,2BAA2B;YAC9B,GAAG,kBAAkB;SACtB;KACF,CAAC,CAAC;IAEH,WAAW,GAAG,oBAAoB,CAAC,WAAW,CAAC;IAE/C,4EAA4E;IAC5E,6EAA6E;IAC7E,qEAAqE;IACrE,oBAAoB;IACpB,EAAE;IACF,6EAA6E;IAC7E,iEAAiE;IACjE,EAAE;IACF,6DAA6D;IAC7D,EAAE;IACF,cAAc,CAAC,gBAAgB,GAAG,KAAK,CAAC;AAC1C,CAAC;AAED,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,SAAS,eAAe,CAAC,qBAA8B;IACrD,IAAI,qBAAqB,IAAI,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;YAC3C,OAAO,OAAO,CAAC,gCAAgC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,IAAI,CAAC;QACH,8EAA8E;QAC9E,mDAAmD;QACnD,OAAO,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,KAAK,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACvE,MAAM,CAAC,CAAC;QACV,CAAC;QACD,kEAAkE;QAClE,yBAAyB;QACzB,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,eAAe,SAAS,CAAC"} \ No newline at end of file diff --git a/packages/plugin-repack/dist/src/index.d.ts b/packages/plugin-repack/dist/src/index.d.ts new file mode 100644 index 000000000..10556cbda --- /dev/null +++ b/packages/plugin-repack/dist/src/index.d.ts @@ -0,0 +1,2 @@ +export * from './lib/pluginRepack.js'; +export { startDevServer } from './lib/pluginRepack.js'; diff --git a/packages/plugin-repack/dist/src/index.js b/packages/plugin-repack/dist/src/index.js new file mode 100644 index 000000000..2a157da20 --- /dev/null +++ b/packages/plugin-repack/dist/src/index.js @@ -0,0 +1,3 @@ +export * from './lib/pluginRepack.js'; +export { startDevServer } from './lib/pluginRepack.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/plugin-repack/dist/src/index.js.map b/packages/plugin-repack/dist/src/index.js.map new file mode 100644 index 000000000..93ad4a218 --- /dev/null +++ b/packages/plugin-repack/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"} \ No newline at end of file diff --git a/packages/plugin-repack/dist/src/lib/pluginRepack.d.ts b/packages/plugin-repack/dist/src/lib/pluginRepack.d.ts new file mode 100644 index 000000000..499378502 --- /dev/null +++ b/packages/plugin-repack/dist/src/lib/pluginRepack.d.ts @@ -0,0 +1,9 @@ +import type { BundlerPluginOutput, PluginApi, StartDevServerArgs } from '@rock-js/config'; +type PluginConfig = { + platforms?: { + [key: string]: object; + }; +}; +export declare function startDevServer({ root, args, reactNativeVersion: _reactNativeVersion, reactNativePath, platforms, }: StartDevServerArgs, pluginConfig?: PluginConfig): Promise; +export declare const pluginRepack: (pluginConfig?: PluginConfig) => (api: PluginApi) => BundlerPluginOutput; +export default pluginRepack; diff --git a/packages/plugin-repack/dist/src/lib/pluginRepack.js b/packages/plugin-repack/dist/src/lib/pluginRepack.js new file mode 100644 index 000000000..402a72cb8 --- /dev/null +++ b/packages/plugin-repack/dist/src/lib/pluginRepack.js @@ -0,0 +1,85 @@ +import commands from '@callstack/repack/commands/rspack'; +import { colorLink, findDevServerPort, intro, logger, RockError, runHermes, spinner, } from '@rock-js/tools'; +const startCommand = commands.find((command) => command.name === 'start'); +const bundleCommand = commands.find((command) => command.name === 'bundle'); +export async function startDevServer({ root, args, reactNativeVersion: _reactNativeVersion, reactNativePath, platforms, }, pluginConfig = {}) { + const { port, startDevServer } = await findDevServerPort(args.port ? Number(args.port) : 8081, root); + if (!startDevServer) { + return; + } + if (!startCommand) { + throw new RockError('Re.Pack "start" command not found.'); + } + logger.info('Starting Re.Pack dev server...'); + startCommand.func([], + // @ts-expect-error TODO fix getPlatforms type + { reactNativePath, root, platforms, ...pluginConfig }, { ...args, port }); +} +export const pluginRepack = (pluginConfig = {}) => (api) => { + if (!startCommand) { + throw new RockError('Re.Pack "start" command not found.'); + } + if (!bundleCommand) { + throw new RockError('Re.Pack "bundle" command not found.'); + } + api.registerCommand({ + name: 'start', + description: 'Starts Re.Pack dev server.', + action: async (args) => { + startDevServer({ + root: api.getProjectRoot(), + reactNativeVersion: api.getReactNativeVersion(), + reactNativePath: api.getReactNativePath(), + platforms: api.getPlatforms(), + // @ts-expect-error Re.Pack doesn't have clientLogs + args, + }); + }, + // @ts-expect-error fixup types + options: startCommand.options, + }); + api.registerCommand({ + name: 'bundle', + description: 'Bundles JavaScript with Re.Pack.', + action: async (args) => { + if (!args.entryFile) { + throw new RockError('"rock bundle" command is missing "--entry-file" argument.'); + } + intro('Compiling JS bundle with Re.Pack'); + const root = api.getProjectRoot(); + const platforms = api.getPlatforms(); + await bundleCommand.func([], + // @ts-expect-error TODO fix getPlatforms type + { root, platforms, ...pluginConfig }, args); + if (args.hermes) { + if (!args.bundleOutput) { + throw new RockError('Missing "--bundle-output" argument to run "bundle --hermes".'); + } + const loader = spinner(); + loader.start('Running Hermes compiler...'); + await runHermes({ + bundleOutputPath: args.bundleOutput, + sourcemapOutputPath: args.sourcemapOutput, + }); + loader.stop(`Hermes bytecode bundle created at: ${colorLink(args.bundleOutput)}`); + } + else if (args.bundleOutput) { + logger.info(`JavaScript bundle created at: ${colorLink(args.bundleOutput)}`); + } + }, + options: [ + ...bundleCommand.options, + { + name: '--hermes', + description: 'Passes the output JS bundle to Hermes compiler and outputs a bytecode file.', + }, + ], + }); + return { + name: '@rock-js/plugin-repack', + description: 'Rock plugin for Re.Pack toolkit with Rspack.', + start: startDevServer, + }; +}; +export default pluginRepack; +//# sourceMappingURL=pluginRepack.js.map \ No newline at end of file diff --git a/packages/plugin-repack/dist/src/lib/pluginRepack.js.map b/packages/plugin-repack/dist/src/lib/pluginRepack.js.map new file mode 100644 index 000000000..ff01b53ef --- /dev/null +++ b/packages/plugin-repack/dist/src/lib/pluginRepack.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pluginRepack.js","sourceRoot":"","sources":["../../../src/lib/pluginRepack.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/provider-github/dist/src/index.d.ts b/packages/provider-github/dist/src/index.d.ts new file mode 100644 index 000000000..b160ce9ea --- /dev/null +++ b/packages/provider-github/dist/src/index.d.ts @@ -0,0 +1 @@ +export { providerGitHub } from './lib/providerGitHub.js'; diff --git a/packages/provider-github/dist/src/index.js b/packages/provider-github/dist/src/index.js new file mode 100644 index 000000000..d69a7143f --- /dev/null +++ b/packages/provider-github/dist/src/index.js @@ -0,0 +1,2 @@ +export { providerGitHub } from './lib/providerGitHub.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/provider-github/dist/src/index.js.map b/packages/provider-github/dist/src/index.js.map new file mode 100644 index 000000000..37cbc7b6c --- /dev/null +++ b/packages/provider-github/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"} \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/artifacts.d.ts b/packages/provider-github/dist/src/lib/artifacts.d.ts new file mode 100644 index 000000000..d6948fcdb --- /dev/null +++ b/packages/provider-github/dist/src/lib/artifacts.d.ts @@ -0,0 +1,12 @@ +import { type RemoteArtifact } from '@rock-js/tools'; +import { type GitHubRepoDetails } from './config.js'; +type GitHubArtifact = { + id: number; + name: string; + expiresAt: string | null; + sizeInBytes: number; + downloadUrl: string; +}; +export declare function fetchGitHubArtifactsByName(name: string | undefined, repoDetails: GitHubRepoDetails, limit?: number): Promise; +export declare function deleteGitHubArtifacts(artifacts: GitHubArtifact[], repoDetails: GitHubRepoDetails, artifactName: string): Promise; +export {}; diff --git a/packages/provider-github/dist/src/lib/artifacts.js b/packages/provider-github/dist/src/lib/artifacts.js new file mode 100644 index 000000000..a996824de --- /dev/null +++ b/packages/provider-github/dist/src/lib/artifacts.js @@ -0,0 +1,98 @@ +import { cacheManager, color, colorLink, logger, RockError, } from '@rock-js/tools'; +const PAGE_SIZE = 100; // Maximum allowed by GitHub API +export async function fetchGitHubArtifactsByName(name, repoDetails, limit) { + let page = 1; + const result = []; + const owner = repoDetails.owner; + const repo = repoDetails.repository; + try { + while (true) { + const url = `https://api.github.com/repos/${owner}/${repo}/actions/artifacts?per_page=${limit ?? PAGE_SIZE}&page=${page}${name ? `&name=${name}` : ''}`; + let data; + try { + const response = await fetch(url, { + headers: { Authorization: `token ${repoDetails.token}` }, + }); + if (!response.ok) { + throw new Error(`HTTP error: ${response.status} ${response.statusText}`); + } + data = await response.json(); + } + catch (error) { + throw new Error(`Error fetching artifacts from ${colorLink(url)}: ${error}`); + } + const artifacts = data.artifacts + .filter((artifact) => !artifact.expired && artifact.workflow_run?.id) + .map((artifact) => ({ + id: artifact.id, + name: artifact.name, + sizeInBytes: artifact.size_in_bytes, + expiresAt: artifact.expires_at, + downloadUrl: artifact.archive_download_url, + })); + result.push(...artifacts); + if (artifacts.length < PAGE_SIZE) { + break; + } + page += 1; + } + } + catch (error) { + if (error.message.includes('401 Unauthorized')) { + cacheManager.remove('githubToken'); + throw new RockError(`Failed to fetch GitHub artifacts due to invalid or expired GitHub Personal Access Token provided. +Update the token under "${color.bold('remoteCacheProvider')}" key in ${colorLink('rock.config.mjs')} config file. + +๐Ÿ“˜ Read more about generating a new token: ${colorLink('https://rockjs.dev/docs/github-actions/configuration#generate-github-personal-access-token-for-downloading-cached-builds')}`); + } + if (error.message.includes('404 Not Found')) { + throw new RockError(`Failed to fetch GitHub artifacts due to "404 Not Found" error. This can happen for the following reasons: +- permission mismatch between your GitHub Personal Access Token and the repository +- you're blocked by the owner of the repository +- repository address is incorrect + +Make sure the repository information and token under "${color.bold('remoteCacheProvider')}" key in ${colorLink('rock.config.mjs')} config file is valid. + +๐Ÿ“˜ Read more about generating a new token: ${colorLink('https://rockjs.dev/docs/github-actions/configuration#generate-github-personal-access-token-for-downloading-cached-builds')}`); + } + throw new RockError(`Failed to fetch GitHub artifacts`, { cause: error }); + } + result.sort((a, b) => { + const expiresA = a.expiresAt ?? '0000-00-00'; + const expiresB = b.expiresAt ?? '0000-00-00'; + // Sort in descending order + return expiresB.localeCompare(expiresA); + }); + return result; +} +export async function deleteGitHubArtifacts(artifacts, repoDetails, artifactName) { + const deletedArtifacts = []; + try { + const owner = repoDetails.owner; + const repo = repoDetails.repository; + // Delete all matching artifacts + for (const artifact of artifacts) { + const artifactId = artifact.id; + const url = `https://api.github.com/repos/${owner}/${repo}/actions/artifacts/${artifactId}`; + const response = await fetch(url, { + method: 'DELETE', + headers: { + Authorization: `Bearer ${repoDetails.token}`, + Accept: 'application/vnd.github+json', + }, + }); + if (!response.ok) { + logger.warn(`Failed to delete artifact ID ${artifactId}: ${response.status} ${response.statusText}`); + continue; + } + deletedArtifacts.push({ name: artifact.name, url: artifact.downloadUrl }); + } + return deletedArtifacts; + } + catch (error) { + throw new RockError(`Failed to delete artifacts named "${artifactName}"`, { + cause: error, + }); + } +} +//# sourceMappingURL=artifacts.js.map \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/artifacts.js.map b/packages/provider-github/dist/src/lib/artifacts.js.map new file mode 100644 index 000000000..85b82981c --- /dev/null +++ b/packages/provider-github/dist/src/lib/artifacts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/lib/artifacts.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/config.d.ts b/packages/provider-github/dist/src/lib/config.d.ts new file mode 100644 index 000000000..5d767e731 --- /dev/null +++ b/packages/provider-github/dist/src/lib/config.d.ts @@ -0,0 +1,8 @@ +export declare function getGitHubToken(): string | undefined; +export declare function promptForGitHubToken(): Promise; +export type GitHubRepoDetails = { + owner: string; + repository: string; + token: string; +}; +export declare function detectGitHubRepoDetails(): Promise; diff --git a/packages/provider-github/dist/src/lib/config.js b/packages/provider-github/dist/src/lib/config.js new file mode 100644 index 000000000..02ba9ee22 --- /dev/null +++ b/packages/provider-github/dist/src/lib/config.js @@ -0,0 +1,56 @@ +import { cacheManager, colorLink, logger, promptPassword, RockError, spawn, } from '@rock-js/tools'; +import * as r from 'ts-regex-builder'; +import { getGitRemote } from './getGitRemote.js'; +const GITHUB_REPO_REGEX = r.buildRegExp([ + r.startOfString, + r.choiceOf('git@', 'https://'), + r.oneOrMore(/[^:/]/), + r.anyOf(':/'), + r.capture(r.oneOrMore(/[^/]/)), // organization + '/', + r.capture(r.oneOrMore(r.any, { greedy: false })), // repository + r.optional('.git'), + r.endOfString, +]); +export function getGitHubToken() { + return cacheManager.get('githubToken'); +} +export async function promptForGitHubToken() { + const githubToken = (await promptPassword({ + message: 'Paste your GitHub Personal Access Token', + validate: (value) => value.length === 0 ? 'Value is required.' : undefined, + })); + cacheManager.set('githubToken', githubToken); + return githubToken; +} +export async function detectGitHubRepoDetails() { + const gitRemote = await getGitRemote(); + if (!gitRemote) { + throw new RockError(`No git remote found for GitHub repository.`); + } + try { + const { output: url } = await spawn('git', ['config', '--get', `remote.${gitRemote}.url`], { stdio: 'pipe' }); + const match = url.match(GITHUB_REPO_REGEX); + if (!match) { + throw new RockError(`The remote URL "${url}" doesn't look like a GitHub repo.`); + } + let token = getGitHubToken(); + if (!token) { + logger.warn(`No GitHub Personal Access Token found necessary to download cached builds. +Please generate one at: ${colorLink('https://github.com/settings/tokens')} +Include "repo", "workflow", and "read:org" permissions.`); + token = await promptForGitHubToken(); + } + return { + owner: match[1], + repository: match[2], + token, + }; + } + catch (error) { + throw new RockError('Unable to detect GitHub repository details.', { + cause: error, + }); + } +} +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/config.js.map b/packages/provider-github/dist/src/lib/config.js.map new file mode 100644 index 000000000..34de5d319 --- /dev/null +++ b/packages/provider-github/dist/src/lib/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,SAAS,EACT,MAAM,EACN,cAAc,EACd,SAAS,EACT,KAAK,GACN,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,CAAC,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,iBAAiB,GAAG,CAAC,CAAC,WAAW,CAAC;IACtC,CAAC,CAAC,aAAa;IACf,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC9B,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;IACpB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IACb,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe;IAC/C,GAAG;IACH,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,aAAa;IAC/D,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IAClB,CAAC,CAAC,WAAW;CACd,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc;IAC5B,OAAO,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,WAAW,GAAG,CAAC,MAAM,cAAc,CAAC;QACxC,OAAO,EAAE,yCAAyC;QAClD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS;KACxD,CAAC,CAAW,CAAC;IACd,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC7C,OAAO,WAAW,CAAC;AACrB,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,KAAK,CACjC,KAAK,EACL,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,SAAS,MAAM,CAAC,EAC9C,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;QAEF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CACjB,mBAAmB,GAAG,oCAAoC,CAC3D,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,GAAG,cAAc,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CACT;0BACkB,SAAS,CAAC,oCAAoC,CAAC;wDACjB,CACjD,CAAC;YACF,KAAK,GAAG,MAAM,oBAAoB,EAAE,CAAC;QACvC,CAAC;QAED,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YACf,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;YACpB,KAAK;SACN,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,6CAA6C,EAAE;YACjE,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/getGitRemote.d.ts b/packages/provider-github/dist/src/lib/getGitRemote.d.ts new file mode 100644 index 000000000..41dcb5e7a --- /dev/null +++ b/packages/provider-github/dist/src/lib/getGitRemote.d.ts @@ -0,0 +1 @@ +export declare function getGitRemote(): Promise; diff --git a/packages/provider-github/dist/src/lib/getGitRemote.js b/packages/provider-github/dist/src/lib/getGitRemote.js new file mode 100644 index 000000000..38f22e465 --- /dev/null +++ b/packages/provider-github/dist/src/lib/getGitRemote.js @@ -0,0 +1,29 @@ +import { cacheManager, promptSelect, spawn } from '@rock-js/tools'; +export async function getGitRemote() { + let gitRemote = cacheManager.get('gitRemote'); + if (gitRemote) { + return gitRemote; + } + const { output: remoteOutput } = await spawn('git', ['remote'], { + stdio: 'pipe', + }); + const remotes = remoteOutput.split('\n').filter(Boolean); + if (remotes.length > 1) { + gitRemote = await promptSelect({ + message: 'Select git remote of the upstream repository:', + options: remotes.map((remote) => ({ + value: remote, + label: remote, + })), + }); + cacheManager.set('gitRemote', gitRemote); + } + else if (remotes.length === 1) { + gitRemote = remotes[0]; + } + else { + return null; + } + return gitRemote; +} +//# sourceMappingURL=getGitRemote.js.map \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/getGitRemote.js.map b/packages/provider-github/dist/src/lib/getGitRemote.js.map new file mode 100644 index 000000000..6ef6f231d --- /dev/null +++ b/packages/provider-github/dist/src/lib/getGitRemote.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getGitRemote.js","sourceRoot":"","sources":["../../../src/lib/getGitRemote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE;QAC9D,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,SAAS,GAAG,MAAM,YAAY,CAAC;YAC7B,OAAO,EAAE,+CAA+C;YACxD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAChC,KAAK,EAAE,MAAM;gBACb,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"} \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/providerGitHub.d.ts b/packages/provider-github/dist/src/lib/providerGitHub.d.ts new file mode 100644 index 000000000..39968e377 --- /dev/null +++ b/packages/provider-github/dist/src/lib/providerGitHub.d.ts @@ -0,0 +1,32 @@ +import type { RemoteArtifact, RemoteBuildCache } from '@rock-js/tools'; +import { type GitHubRepoDetails } from './config.js'; +export declare class GitHubBuildCache implements RemoteBuildCache { + name: string; + repoDetails: GitHubRepoDetails | null; + constructor(config?: { + owner: string; + repository: string; + token: string; + }); + getRepoDetails(): Promise; + list({ artifactName, limit, }: { + artifactName?: string; + limit?: number; + }): Promise; + download({ artifactName, }: { + artifactName: string; + }): Promise; + delete({ artifactName, limit, skipLatest, }: { + artifactName: string; + limit?: number; + skipLatest?: boolean; + }): Promise; + upload(): Promise Buffer), contentType?: string | undefined) => Response; + }>; +} +export declare const providerGitHub: (options?: { + owner: string; + repository: string; + token: string; +}) => () => RemoteBuildCache; diff --git a/packages/provider-github/dist/src/lib/providerGitHub.js b/packages/provider-github/dist/src/lib/providerGitHub.js new file mode 100644 index 000000000..6f0dcc845 --- /dev/null +++ b/packages/provider-github/dist/src/lib/providerGitHub.js @@ -0,0 +1,61 @@ +import { deleteGitHubArtifacts, fetchGitHubArtifactsByName, } from './artifacts.js'; +import { detectGitHubRepoDetails } from './config.js'; +export class GitHubBuildCache { + name = 'GitHub'; + repoDetails = null; + constructor(config) { + if (config) { + const token = config.token || process.env['GITHUB_TOKEN']; + if (!token) { + throw new Error('GitHub Personal Access Token is required to fetch remote cache. Configure `GITHUB_TOKEN` variable in .env file or pass it as a `token` argument.'); + } + this.repoDetails = { + owner: config.owner, + repository: config.repository, + token, + }; + } + } + async getRepoDetails() { + if (!this.repoDetails) { + this.repoDetails = await detectGitHubRepoDetails(); + } + return this.repoDetails; + } + async list({ artifactName, limit, }) { + const repoDetails = await this.getRepoDetails(); + const artifacts = await fetchGitHubArtifactsByName(artifactName, repoDetails, limit); + return artifacts.map((artifact) => ({ + name: artifact.name, + url: artifact.downloadUrl, + id: String(artifact.id), + })); + } + async download({ artifactName, }) { + const repoDetails = await this.getRepoDetails(); + const artifacts = await this.list({ artifactName }); + if (artifacts.length === 0) { + throw new Error(`No artifact found with name "${artifactName}"`); + } + return fetch(artifacts[0].url, { + headers: { + Authorization: `token ${repoDetails.token}`, + 'Accept-Encoding': 'None', + }, + }); + } + async delete({ artifactName, limit, skipLatest, }) { + const repoDetails = await this.getRepoDetails(); + const artifacts = await fetchGitHubArtifactsByName(artifactName, repoDetails, limit); + if (artifacts.length === 0) { + throw new Error(`No artifact found with name "${artifactName}"`); + } + const [, ...rest] = artifacts; + return await deleteGitHubArtifacts(skipLatest ? rest : artifacts, repoDetails, artifactName); + } + async upload() { + throw new Error('Uploading artifacts to GitHub is not supported through GitHub API. See: https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28'); + } +} +export const providerGitHub = (options) => () => new GitHubBuildCache(options); +//# sourceMappingURL=providerGitHub.js.map \ No newline at end of file diff --git a/packages/provider-github/dist/src/lib/providerGitHub.js.map b/packages/provider-github/dist/src/lib/providerGitHub.js.map new file mode 100644 index 000000000..bca548770 --- /dev/null +++ b/packages/provider-github/dist/src/lib/providerGitHub.js.map @@ -0,0 +1 @@ +{"version":3,"file":"providerGitHub.js","sourceRoot":"","sources":["../../../src/lib/providerGitHub.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/provider-s3/dist/src/index.d.ts b/packages/provider-s3/dist/src/index.d.ts new file mode 100644 index 000000000..fc11f84c7 --- /dev/null +++ b/packages/provider-s3/dist/src/index.d.ts @@ -0,0 +1 @@ +export { providerS3 } from './lib/providerS3.js'; diff --git a/packages/provider-s3/dist/src/index.js b/packages/provider-s3/dist/src/index.js new file mode 100644 index 000000000..fcdcc8f57 --- /dev/null +++ b/packages/provider-s3/dist/src/index.js @@ -0,0 +1,2 @@ +export { providerS3 } from './lib/providerS3.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/provider-s3/dist/src/index.js.map b/packages/provider-s3/dist/src/index.js.map new file mode 100644 index 000000000..66a32ae1f --- /dev/null +++ b/packages/provider-s3/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"} \ No newline at end of file diff --git a/packages/provider-s3/dist/src/lib/providerS3.d.ts b/packages/provider-s3/dist/src/lib/providerS3.d.ts new file mode 100644 index 000000000..8c4160c18 --- /dev/null +++ b/packages/provider-s3/dist/src/lib/providerS3.d.ts @@ -0,0 +1,80 @@ +import * as clientS3 from '@aws-sdk/client-s3'; +import type { RemoteArtifact, RemoteBuildCache } from '@rock-js/tools'; +type ProviderConfig = { + /** + * Optional endpoint, necessary for self-hosted S3 servers or Cloudflare R2 integration. + */ + endpoint?: string; + /** + * The bucket name to use for the S3 server. + */ + bucket: string; + /** + * The region of the S3 server. + */ + region: string; + /** + * The access key ID for the S3 server. Not required when using IAM roles or other auth methods. + */ + accessKeyId?: string; + /** + * The secret access key for the S3 server. Not required when using IAM roles or other auth methods. + */ + secretAccessKey?: string; + /** + * The directory to store artifacts in the S3 server. + */ + directory?: string; + /** + * The display name of the provider + */ + name?: string; + /** + * The time in seconds for the presigned URL to expire. By default, it is 24 hours. + */ + linkExpirationTime?: number; + /** + * AWS profile name to use for authentication. Useful for local development. + */ + profile?: string; + /** + * Role ARN to assume for authentication. Useful for cross-account access. + */ + roleArn?: string; + /** + * Session name when assuming a role. + */ + roleSessionName?: string; + /** + * External ID when assuming a role (for additional security). + */ + externalId?: string; +}; +export declare class S3BuildCache implements RemoteBuildCache { + name: string; + directory: string; + s3: clientS3.S3Client; + bucket: string; + config: ProviderConfig; + linkExpirationTime: number; + constructor(config: ProviderConfig); + private uploadFileWithProgress; + list({ artifactName, }: { + artifactName?: string; + }): Promise; + download({ artifactName, }: { + artifactName: string; + }): Promise; + delete({ artifactName, skipLatest, }: { + artifactName: string; + skipLatest?: boolean; + }): Promise; + upload({ artifactName, uploadArtifactName, }: { + artifactName: string; + uploadArtifactName?: string; + }): Promise Buffer), contentType?: string) => Response; + }>; +} +export declare const providerS3: (options: ProviderConfig) => () => RemoteBuildCache; +export {}; diff --git a/packages/provider-s3/dist/src/lib/providerS3.js b/packages/provider-s3/dist/src/lib/providerS3.js new file mode 100644 index 000000000..1d9331bca --- /dev/null +++ b/packages/provider-s3/dist/src/lib/providerS3.js @@ -0,0 +1,172 @@ +import * as clientS3 from '@aws-sdk/client-s3'; +import { fromIni } from '@aws-sdk/credential-provider-ini'; +import { fromTemporaryCredentials } from '@aws-sdk/credential-providers'; +import { Upload } from '@aws-sdk/lib-storage'; +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; +function toWebStream(stream) { + return new ReadableStream({ + start(controller) { + stream.on('data', (chunk) => controller.enqueue(chunk)); + stream.on('end', () => controller.close()); + stream.on('error', (err) => controller.error(err)); + }, + }); +} +export class S3BuildCache { + name = 'S3'; + directory = 'rock-artifacts'; + s3; + bucket; + config; + linkExpirationTime; + constructor(config) { + this.config = config; + const s3Config = { + endpoint: config.endpoint, + region: config.region, + }; + if (config.accessKeyId && config.secretAccessKey) { + s3Config.credentials = { + accessKeyId: config.accessKeyId, + secretAccessKey: config.secretAccessKey, + }; + } + else if (config.roleArn) { + // Use STS to assume a role + s3Config.credentials = fromTemporaryCredentials({ + params: { + RoleArn: config.roleArn, + RoleSessionName: config.roleSessionName ?? 's3-build-cache-session', + ExternalId: config.externalId, + }, + // Optional: use named profile as source credentials + masterCredentials: config.profile + ? fromIni({ profile: config.profile }) + : undefined, + }); + } + else if (config.profile) { + // Use shared config file (e.g. ~/.aws/credentials) with a profile + s3Config.credentials = fromIni({ profile: config.profile }); + } + this.s3 = new clientS3.S3Client(s3Config); + const awsBucket = config.bucket ?? ''; + const bucketTokens = awsBucket.split('/'); + this.bucket = bucketTokens.shift(); + this.directory = config.directory ?? this.directory; + this.name = config.name ?? this.name; + this.linkExpirationTime = config.linkExpirationTime ?? 3600 * 24; + } + async uploadFileWithProgress(key, buffer, contentType, onProgress) { + const upload = new Upload({ + client: this.s3, + params: { + Bucket: this.bucket, + Key: key, + Body: buffer, + ContentType: contentType || 'application/octet-stream', + Metadata: { + createdAt: new Date().toISOString(), + }, + }, + }); + upload.on('httpUploadProgress', (progress) => { + if (progress.loaded !== undefined && progress.total !== undefined) { + onProgress(progress.loaded, progress.total); + } + }); + return upload.done(); + } + async list({ artifactName, }) { + const artifacts = await this.s3.send(new clientS3.ListObjectsV2Command({ + Bucket: this.bucket, + Prefix: artifactName + ? `${this.directory}/${artifactName}.zip` + : `${this.directory}/`, + })); + const results = []; + for (const artifact of artifacts.Contents ?? []) { + if (!artifact.Key) + continue; + const name = artifactName ?? artifact.Key.split('/').pop() ?? ''; + const presignedUrl = await getSignedUrl(this.s3, new clientS3.GetObjectCommand({ + Bucket: this.bucket, + Key: artifact.Key, + }), { expiresIn: this.linkExpirationTime }); + results.push({ name, url: presignedUrl }); + } + return results; + } + async download({ artifactName, }) { + const res = await this.s3.send(new clientS3.GetObjectCommand({ + Bucket: this.bucket, + Key: `${this.directory}/${artifactName}.zip`, + })); + return new Response(toWebStream(res.Body), { + headers: { + 'content-length': String(res.ContentLength), + }, + }); + } + async delete({ artifactName, skipLatest, }) { + if (skipLatest) { + // Artifacts on S3 are unique by name, so skipping latest means we don't delete anything + // @todo revisit with bucket versioning + return []; + } + await this.s3.send(new clientS3.DeleteObjectCommand({ + Bucket: this.bucket, + Key: `${this.directory}/${artifactName}.zip`, + })); + return [ + { + name: artifactName, + url: `${this.bucket}/${this.directory}/${artifactName}.zip`, + }, + ]; + } + async upload({ artifactName, uploadArtifactName, }) { + const key = uploadArtifactName + ? `${this.directory}/${uploadArtifactName}` + : `${this.directory}/${artifactName}.zip`; + const presignedUrl = await getSignedUrl(this.s3, new clientS3.GetObjectCommand({ Bucket: this.bucket, Key: key }), { expiresIn: this.linkExpirationTime }); + return { + name: artifactName, + url: presignedUrl, + getResponse: (buffer, contentType) => { + const bufferToUpload = typeof buffer === 'function' + ? buffer(presignedUrl.split('?')[0]) + : buffer; + const readable = new ReadableStream({ + start: (controller) => { + let lastEmittedBytes = 0; + try { + this.uploadFileWithProgress(key, bufferToUpload, contentType, (loaded, total) => { + const newBytes = loaded - lastEmittedBytes; + if (newBytes > 0) { + const chunk = bufferToUpload.subarray(lastEmittedBytes, loaded); + controller.enqueue(chunk); + lastEmittedBytes = loaded; + if (loaded >= total) { + controller.close(); + } + } + }); + } + catch (error) { + controller.error(error); + } + }, + }); + return new Response(readable, { + headers: { + 'content-length': String(bufferToUpload.length), + 'content-type': contentType || 'application/octet-stream', + }, + }); + }, + }; + } +} +export const providerS3 = (options) => () => new S3BuildCache(options); +//# sourceMappingURL=providerS3.js.map \ No newline at end of file diff --git a/packages/provider-s3/dist/src/lib/providerS3.js.map b/packages/provider-s3/dist/src/lib/providerS3.js.map new file mode 100644 index 000000000..fefe11852 --- /dev/null +++ b/packages/provider-s3/dist/src/lib/providerS3.js.map @@ -0,0 +1 @@ +{"version":3,"file":"providerS3.js","sourceRoot":"","sources":["../../../src/lib/providerS3.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/test-helpers/dist/src/index.d.ts b/packages/test-helpers/dist/src/index.d.ts new file mode 100644 index 000000000..117b1cd41 --- /dev/null +++ b/packages/test-helpers/dist/src/index.d.ts @@ -0,0 +1,3 @@ +export * from './lib/exec.js'; +export * from './lib/random.js'; +export * from './lib/test-helpers.js'; diff --git a/packages/test-helpers/dist/src/index.js b/packages/test-helpers/dist/src/index.js new file mode 100644 index 000000000..0b9dd8466 --- /dev/null +++ b/packages/test-helpers/dist/src/index.js @@ -0,0 +1,4 @@ +export * from './lib/exec.js'; +export * from './lib/random.js'; +export * from './lib/test-helpers.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/test-helpers/dist/src/index.js.map b/packages/test-helpers/dist/src/index.js.map new file mode 100644 index 000000000..0f9f73c26 --- /dev/null +++ b/packages/test-helpers/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC"} \ No newline at end of file diff --git a/packages/test-helpers/dist/src/lib/exec.d.ts b/packages/test-helpers/dist/src/lib/exec.d.ts new file mode 100644 index 000000000..dc7346267 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/exec.d.ts @@ -0,0 +1,2 @@ +import type { ExecOptions } from 'node:child_process'; +export declare const execAsync: (command: string, options?: ExecOptions) => Promise; diff --git a/packages/test-helpers/dist/src/lib/exec.js b/packages/test-helpers/dist/src/lib/exec.js new file mode 100644 index 000000000..8f4972354 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/exec.js @@ -0,0 +1,13 @@ +import { exec } from 'node:child_process'; +export const execAsync = (command, options) => { + return new Promise((resolve, reject) => { + exec(command, options, (error, stdout, stderr) => { + if (error) { + reject(`exec error: ${error}\n\n${stdout}\n\n${stderr}`); + return; + } + resolve(stdout); + }); + }); +}; +//# sourceMappingURL=exec.js.map \ No newline at end of file diff --git a/packages/test-helpers/dist/src/lib/exec.js.map b/packages/test-helpers/dist/src/lib/exec.js.map new file mode 100644 index 000000000..f9aa521f8 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/exec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/lib/exec.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,OAAqB,EAAE,EAAE;IAClE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC/C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,eAAe,KAAK,OAAO,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC;gBACzD,OAAO;YACT,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/test-helpers/dist/src/lib/random.d.ts b/packages/test-helpers/dist/src/lib/random.d.ts new file mode 100644 index 000000000..183cd0a94 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/random.d.ts @@ -0,0 +1 @@ +export declare function getRandomString(length: number): string; diff --git a/packages/test-helpers/dist/src/lib/random.js b/packages/test-helpers/dist/src/lib/random.js new file mode 100644 index 000000000..e667dadd4 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/random.js @@ -0,0 +1,6 @@ +export function getRandomString(length) { + return Math.random() + .toString(36) + .substring(2, length + 2); +} +//# sourceMappingURL=random.js.map \ No newline at end of file diff --git a/packages/test-helpers/dist/src/lib/random.js.map b/packages/test-helpers/dist/src/lib/random.js.map new file mode 100644 index 000000000..3073b5914 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/random.js.map @@ -0,0 +1 @@ +{"version":3,"file":"random.js","sourceRoot":"","sources":["../../../src/lib/random.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,IAAI,CAAC,MAAM,EAAE;SACjB,QAAQ,CAAC,EAAE,CAAC;SACZ,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC"} \ No newline at end of file diff --git a/packages/test-helpers/dist/src/lib/test-helpers.d.ts b/packages/test-helpers/dist/src/lib/test-helpers.d.ts new file mode 100644 index 000000000..036168bb0 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/test-helpers.d.ts @@ -0,0 +1,15 @@ +export declare const getTempDirectory: (name: string) => string; +export declare const cleanup: (directory: string) => void; +/** + * Creates a nested directory with files and their contents + * writeFiles( + * '/home/tmp', + * { + * 'package.json': '{}', + * 'dir/file.js': 'module.exports = "x";', + * } + * ); + */ +export declare const writeFiles: (directory: string, files: { + [filename: string]: string | NodeJS.ArrayBufferView; +}) => void; diff --git a/packages/test-helpers/dist/src/lib/test-helpers.js b/packages/test-helpers/dist/src/lib/test-helpers.js new file mode 100644 index 000000000..3b4426a3f --- /dev/null +++ b/packages/test-helpers/dist/src/lib/test-helpers.js @@ -0,0 +1,39 @@ +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +export const getTempDirectory = (name) => path.resolve(os.tmpdir(), name); +export const cleanup = (directory) => { + fs.rmSync(directory, { recursive: true, force: true, maxRetries: 10 }); +}; +/** + * Creates a nested directory with files and their contents + * writeFiles( + * '/home/tmp', + * { + * 'package.json': '{}', + * 'dir/file.js': 'module.exports = "x";', + * } + * ); + */ +export const writeFiles = (directory, files) => { + createDirectory(directory); + Object.keys(files).forEach((fileOrPath) => { + const dirname = path.dirname(fileOrPath); + if (dirname !== '/') { + createDirectory(path.join(directory, dirname)); + } + fs.writeFileSync(path.resolve(directory, ...fileOrPath.split('/')), files[fileOrPath]); + }); +}; +function createDirectory(path) { + try { + fs.mkdirSync(path, { recursive: true }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } + catch (error) { + if (error.code !== 'EEXIST') { + throw error; + } + } +} +//# sourceMappingURL=test-helpers.js.map \ No newline at end of file diff --git a/packages/test-helpers/dist/src/lib/test-helpers.js.map b/packages/test-helpers/dist/src/lib/test-helpers.js.map new file mode 100644 index 000000000..d12d983d5 --- /dev/null +++ b/packages/test-helpers/dist/src/lib/test-helpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../../src/lib/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,EAAE,CAC/C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAE,EAAE;IAC3C,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,SAAiB,EACjB,KAA8D,EAC9D,EAAE;IACF,eAAe,CAAC,SAAS,CAAC,CAAC;IAE3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAEzC,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;YACpB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EACjD,KAAK,CAAC,UAAU,CAAC,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,8DAA8D;IAChE,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/index.d.ts b/packages/tools/dist/src/index.d.ts new file mode 100644 index 000000000..a140626bf --- /dev/null +++ b/packages/tools/dist/src/index.d.ts @@ -0,0 +1,21 @@ +export * from './lib/prompts.js'; +export * from './lib/env.js'; +export * from './lib/error.js'; +export { default as logger } from './lib/logger.js'; +export * from './lib/fingerprint/index.js'; +export { default as cacheManager } from './lib/cacheManager.js'; +export * from './lib/parse-args.js'; +export * from './lib/path.js'; +export * from './lib/project.js'; +export * from './lib/build-cache/common.js'; +export * from './lib/build-cache/localBuildCache.js'; +export { getBinaryPath } from './lib/build-cache/getBinaryPath.js'; +export { findDevServerPort } from './lib/dev-server/findDevServerPort.js'; +export { isDevServerRunning } from './lib/dev-server/isDevServerRunning.js'; +export { isInteractive } from './lib/isInteractive.js'; +export { spawn, SubprocessError } from './lib/spawn.js'; +export { color, colorLink } from './lib/color.js'; +export { runHermes } from './lib/hermes.js'; +export { fetchCachedBuild, handleDownloadResponse, handleUploadResponse, } from './lib/build-cache/fetchCachedBuild.js'; +export { getInfoPlist } from './lib/getInfoPlist.js'; +export { getReactNativeVersion } from './lib/getReactNativeVersion.js'; diff --git a/packages/tools/dist/src/index.js b/packages/tools/dist/src/index.js new file mode 100644 index 000000000..b66558065 --- /dev/null +++ b/packages/tools/dist/src/index.js @@ -0,0 +1,22 @@ +export * from './lib/prompts.js'; +export * from './lib/env.js'; +export * from './lib/error.js'; +export { default as logger } from './lib/logger.js'; +export * from './lib/fingerprint/index.js'; +export { default as cacheManager } from './lib/cacheManager.js'; +export * from './lib/parse-args.js'; +export * from './lib/path.js'; +export * from './lib/project.js'; +export * from './lib/build-cache/common.js'; +export * from './lib/build-cache/localBuildCache.js'; +export { getBinaryPath } from './lib/build-cache/getBinaryPath.js'; +export { findDevServerPort } from './lib/dev-server/findDevServerPort.js'; +export { isDevServerRunning } from './lib/dev-server/isDevServerRunning.js'; +export { isInteractive } from './lib/isInteractive.js'; +export { spawn, SubprocessError } from './lib/spawn.js'; +export { color, colorLink } from './lib/color.js'; +export { runHermes } from './lib/hermes.js'; +export { fetchCachedBuild, handleDownloadResponse, handleUploadResponse, } from './lib/build-cache/fetchCachedBuild.js'; +export { getInfoPlist } from './lib/getInfoPlist.js'; +export { getReactNativeVersion } from './lib/getReactNativeVersion.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/index.js.map b/packages/tools/dist/src/index.js.map new file mode 100644 index 000000000..9dc978802 --- /dev/null +++ b/packages/tools/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sCAAsC,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/common.d.ts b/packages/tools/dist/src/lib/build-cache/common.d.ts new file mode 100644 index 000000000..c4e169db7 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/common.d.ts @@ -0,0 +1,81 @@ +import type { FingerprintSources } from '../fingerprint/index.js'; +export declare const BUILD_CACHE_DIR = "remote-build"; +export declare const supportedRemoteCacheProviders: readonly ["github-actions", "s3"]; +export type SupportedRemoteCacheProviders = typeof supportedRemoteCacheProviders[number]; +export type RemoteArtifact = { + name: string; + url: string; + id?: string; +}; +export type LocalArtifact = { + name: string; +}; +/** + * Interface for implementing remote build cache providers. + * Remote cache providers allow storing and retrieving native build artifacts (e.g. APK, IPA) + * from remote storage like S3, GitHub Artifacts etc. + */ +export interface RemoteBuildCache { + /** Unique identifier for this cache provider, will be displayed in logs */ + name: string; + /** + * List available artifacts matching the given name pattern + * @param artifactName - Passed after fingerprinting the build, e.g. `rock-android-debug-1234567890` for android in debug variant + * @param limit - Optional maximum number of artifacts to return + * @returns Array of matching remote artifacts, or empty array if none found + */ + list({ artifactName, limit, }: { + artifactName: string | undefined; + limit?: number; + }): Promise; + /** + * Download a remote artifact to local storage + * @param artifactName - Name of the artifact to download, e.g. `rock-android-debug-1234567890` for android in debug variant + * @returns Response object from fetch, which will be used to download the artifact + */ + download({ artifactName }: { + artifactName: string; + }): Promise; + /** + * Delete a remote artifact + * @param artifactName - Name of the artifact to delete, e.g. `rock-android-debug-1234567890` for android in debug variant + * @param limit - Optional maximum number of artifacts to delete + * @param skipLatest - Optional flag to skip the latest artifact, helpful when deleting all but the latest artifact + * @returns Array of deleted artifacts + * @throws {Error} Throws if artifact is not found or deletion fails + */ + delete({ artifactName, limit, skipLatest, }: { + artifactName: string; + limit?: number; + skipLatest?: boolean; + }): Promise; + /** + * Upload a local artifact stored in build cache to remote storage + * @param artifactName - Name of the artifact to upload, e.g. `rock-android-debug-1234567890` for android in debug variant + * @param uploadArtifactName - Name of the artifact to upload, e.g. `ad-hoc/rock-ios-device-Release-1234567890/YourApp.ipa` for ad-hoc distribution + * @returns Remote artifact info with response function for upload control + * @throws {Error} Throws if upload fails + */ + upload({ artifactName, uploadArtifactName, }: { + artifactName: string; + uploadArtifactName?: string; + }): Promise Buffer), contentType?: string) => Response; + }>; +} +/** + * Used formats: + * - rock-android-debug-1234567890 + * - rock-ios-simulator-debug-1234567890 + * - rock-ios-device-debug-1234567890 + */ +export declare function formatArtifactName({ platform, traits, root, fingerprintOptions, raw, type, }: { + platform?: 'ios' | 'android' | 'harmony'; + traits?: string[]; + root: string; + fingerprintOptions: FingerprintSources; + raw?: boolean; + type?: 'create' | 'update'; +}): Promise; +export declare function getLocalArtifactPath(artifactName: string): string; +export declare function getLocalBinaryPath(artifactPath: string): string | null; diff --git a/packages/tools/dist/src/lib/build-cache/common.js b/packages/tools/dist/src/lib/build-cache/common.js new file mode 100644 index 000000000..d354835a3 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/common.js @@ -0,0 +1,47 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { color } from '../color.js'; +import { nativeFingerprint } from '../fingerprint/index.js'; +import { isInteractive } from '../isInteractive.js'; +import { getCacheRootPath } from '../project.js'; +import { spinner } from '../prompts.js'; +export const BUILD_CACHE_DIR = 'remote-build'; +export const supportedRemoteCacheProviders = ['github-actions', 's3']; +/** + * Used formats: + * - rock-android-debug-1234567890 + * - rock-ios-simulator-debug-1234567890 + * - rock-ios-device-debug-1234567890 + */ +export async function formatArtifactName({ platform, traits, root, fingerprintOptions, raw, type, }) { + if (!platform || !traits) { + return ''; + } + if (raw || !isInteractive()) { + const { hash } = await nativeFingerprint(root, { + ...fingerprintOptions, + platform, + }); + return `rock-${platform}-${traits.join('-')}-${hash}`; + } + const startMessage = type === 'update' ? 'Updating' : 'Calculating'; + const stopMessage = type === 'update' ? 'Updated' : 'Calculated'; + const loader = spinner(); + loader.start(`${startMessage} project fingerprint`); + const { hash } = await nativeFingerprint(root, { + ...fingerprintOptions, + platform, + }); + loader.stop(`${stopMessage} project fingerprint: ${color.bold(color.magenta(hash))}`); + return `rock-${platform}-${traits.join('-')}-${hash}`; +} +export function getLocalArtifactPath(artifactName) { + return path.join(getCacheRootPath(), BUILD_CACHE_DIR, artifactName); +} +export function getLocalBinaryPath(artifactPath) { + const files = fs.readdirSync(artifactPath); + // Get the first non-hidden file as the binary + const binaryName = files.find((file) => file && !file.startsWith('.')); + return binaryName ? path.join(artifactPath, binaryName) : null; +} +//# sourceMappingURL=common.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/common.js.map b/packages/tools/dist/src/lib/build-cache/common.js.map new file mode 100644 index 000000000..8423a52fc --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/common.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../src/lib/build-cache/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC;AAE9C,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAU,CAAC;AAqF/E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,kBAAkB,EAClB,GAAG,EACH,IAAI,GAQL;IACC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;QAC5B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE;YAC7C,GAAG,kBAAkB;YACrB,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,QAAQ,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACxD,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;IACpE,MAAM,WAAW,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;IAEjE,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,sBAAsB,CAAC,CAAC;IACpD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE;QAC7C,GAAG,kBAAkB;QACrB,QAAQ;KACT,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CACT,GAAG,WAAW,yBAAyB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CACzE,CAAC;IACF,OAAO,QAAQ,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,YAAoB;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,YAAoB;IACrD,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAC3C,8CAA8C;IAC9C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjE,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.d.ts b/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.d.ts new file mode 100644 index 000000000..5b294a912 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.d.ts @@ -0,0 +1,12 @@ +import { type RemoteBuildCache } from './common.js'; +import type { LocalBuild } from './localBuildCache.js'; +type FetchCachedBuildOptions = { + artifactName: string; + remoteCacheProvider: undefined | null | { + (): RemoteBuildCache; + }; +}; +export declare function fetchCachedBuild({ artifactName, remoteCacheProvider, }: FetchCachedBuildOptions): Promise; +export declare function handleDownloadResponse(response: Response, localArtifactPath: string, onProgress: (progress: string, totalMB: string) => void): Promise; +export declare function handleUploadResponse(getResponse: (buffer: Buffer) => Response, buffer: Buffer, onProgress: (progress: string, totalMB: string) => void): Promise; +export {}; diff --git a/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.js b/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.js new file mode 100644 index 000000000..583abfb59 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.js @@ -0,0 +1,128 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import AdmZip from 'adm-zip'; +import * as tar from 'tar'; +import { color, colorLink } from '../color.js'; +import { RockError } from '../error.js'; +import logger from '../logger.js'; +import { relativeToCwd } from '../path.js'; +import { spinner } from '../prompts.js'; +import { getLocalArtifactPath, getLocalBinaryPath, } from './common.js'; +export async function fetchCachedBuild({ artifactName, remoteCacheProvider, }) { + if (remoteCacheProvider === null) { + return undefined; + } + if (remoteCacheProvider === undefined) { + logger.warn(`No remote cache provider set. You won't be able to access reusable builds from e.g. GitHub Actions. +To configure it, set the "remoteCacheProvider" key in ${colorLink('rock.config.mjs')} file. For example: + +import { providerGitHub } from '@rock-js/provider-github'; +export default { + // ... + remoteCacheProvider: providerGitHub() +} + +To disable this warning, set the provider to null: +{ + remoteCacheProvider: null +}`); + return undefined; + } + const loader = spinner(); + const localArtifactPath = getLocalArtifactPath(artifactName); + const remoteBuildCache = remoteCacheProvider(); + const response = await remoteBuildCache.download({ artifactName }); + loader.start(`Downloading cached build from ${color.bold(remoteBuildCache.name)}`); + await handleDownloadResponse(response, localArtifactPath, (progress, totalMB) => { + loader.message(`Downloading cached build from ${color.bold(remoteBuildCache.name)} (${progress}% of ${totalMB} MB)`); + }); + await extractArtifactTarballIfNeeded(localArtifactPath); + const binaryPath = getLocalBinaryPath(localArtifactPath); + if (!binaryPath) { + loader.stop(`No binary found for ${color.bold(artifactName)}.`); + return undefined; + } + loader.stop(`Downloaded cached build to: ${colorLink(relativeToCwd(localArtifactPath))}`); + return { + name: artifactName, + artifactPath: localArtifactPath, + binaryPath, + }; +} +async function trackProgressFromStream(response, onProgress) { + const contentLength = response.headers.get('content-length'); + if (!contentLength || !response.body) { + return response; + } + const totalBytes = parseInt(contentLength, 10); + const totalMB = (totalBytes / 1024 / 1024).toFixed(2); + let processedBytes = 0; + const reader = response.body.getReader(); + const stream = new ReadableStream({ + async start(controller) { + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + processedBytes += value.length; + const progress = ((processedBytes / totalBytes) * 100).toFixed(0); + onProgress(progress, totalMB); + controller.enqueue(value); + } + controller.close(); + }, + }); + return new Response(stream); +} +export async function handleDownloadResponse(response, localArtifactPath, onProgress) { + try { + fs.mkdirSync(localArtifactPath, { recursive: true }); + if (!response.ok || !response.body) { + throw new Error(`Failed to download artifact: ${response.statusText}`); + } + const responseWithProgress = await trackProgressFromStream(response, onProgress); + const zipPath = localArtifactPath + '.zip'; + const buffer = await responseWithProgress.arrayBuffer(); + fs.writeFileSync(zipPath, new Uint8Array(buffer)); + unzipFile(zipPath, localArtifactPath); + fs.unlinkSync(zipPath); + } + catch (error) { + throw new RockError(`Unexpected error`, { cause: error }); + } +} +export async function handleUploadResponse(getResponse, buffer, onProgress) { + try { + const response = getResponse(buffer); + if (!response.body) { + throw new Error('Response body is empty'); + } + const responseWithProgress = await trackProgressFromStream(response, onProgress); + await responseWithProgress.arrayBuffer(); + } + catch (error) { + throw new RockError(`Unexpected error during upload`, { cause: error }); + } +} +function unzipFile(zipPath, targetPath) { + const zip = new AdmZip(zipPath); + zip.extractAllTo(targetPath, true); +} +async function extractArtifactTarballIfNeeded(artifactPath) { + const tarPath = path.join(artifactPath, 'app.tar.gz'); + // If the tarball is not found, it means the artifact is already unpacked. + if (!fs.existsSync(tarPath)) { + return; + } + // iOS simulator build artifact (*.app directory) is packed in .tar.gz file to + // preserve execute file permission. + // See: https://github.com/actions/upload-artifact?tab=readme-ov-file#permission-loss + await tar.extract({ + file: tarPath, + cwd: artifactPath, + gzip: true, + }); + fs.unlinkSync(tarPath); +} +//# sourceMappingURL=fetchCachedBuild.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.js.map b/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.js.map new file mode 100644 index 000000000..6f15a07f0 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/fetchCachedBuild.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fetchCachedBuild.js","sourceRoot":"","sources":["../../../../src/lib/build-cache/fetchCachedBuild.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/getBinaryPath.d.ts b/packages/tools/dist/src/lib/build-cache/getBinaryPath.d.ts new file mode 100644 index 000000000..6a2055c36 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/getBinaryPath.d.ts @@ -0,0 +1,11 @@ +import { type FingerprintSources } from '../fingerprint/index.js'; +import type { RemoteBuildCache } from './common.js'; +export declare function getBinaryPath({ artifactName, binaryPathFlag, localFlag, remoteCacheProvider, fingerprintOptions, sourceDir, platformName, }: { + artifactName: string; + binaryPathFlag?: string; + localFlag?: boolean; + remoteCacheProvider: null | (() => RemoteBuildCache) | undefined; + fingerprintOptions: FingerprintSources; + sourceDir: string; + platformName: string; +}): Promise; diff --git a/packages/tools/dist/src/lib/build-cache/getBinaryPath.js b/packages/tools/dist/src/lib/build-cache/getBinaryPath.js new file mode 100644 index 000000000..6cd20f492 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/getBinaryPath.js @@ -0,0 +1,76 @@ +import path from 'node:path'; +import { color, colorLink } from '../color.js'; +import { getAllIgnorePaths } from '../fingerprint/ignorePaths.js'; +import logger from '../logger.js'; +import { getProjectRoot } from '../project.js'; +import { spawn } from '../spawn.js'; +import { fetchCachedBuild } from './fetchCachedBuild.js'; +import { getLocalBuildCacheBinaryPath } from './localBuildCache.js'; +export async function getBinaryPath({ artifactName, binaryPathFlag, localFlag, remoteCacheProvider, fingerprintOptions, sourceDir, platformName, }) { + // 1. First check if the binary path is provided + let binaryPath = binaryPathFlag; + // 2. If not, check if the local build is requested + if (!binaryPath && !localFlag) { + binaryPath = getLocalBuildCacheBinaryPath(artifactName); + } + // 3. If not, check if the remote cache is requested + if (!binaryPath && !localFlag) { + try { + const cachedBuild = await fetchCachedBuild({ + artifactName, + remoteCacheProvider, + }); + if (cachedBuild) { + binaryPath = cachedBuild.binaryPath; + } + } + catch (error) { + const message = error.message; + const cause = error.cause; + logger.warn(`Remote Cache: Failed to fetch cached build for ${color.bold(artifactName)}. +Cause: ${message}${cause ? `\n${cause.toString()}` : ''} +Read more: ${colorLink('https://rockjs.dev/docs/configuration#remote-cache-configuration')}`); + await warnIgnoredFiles(fingerprintOptions, platformName, sourceDir); + logger.debug('Remote cache failure error:', error); + logger.info('Continuing with local build'); + } + } + return binaryPath; +} +async function warnIgnoredFiles(fingerprintOptions, platformName, sourceDir) { + // @todo unify git helpers from create-app + try { + await spawn('git', ['rev-parse', '--is-inside-work-tree'], { + stdio: 'ignore', + cwd: sourceDir, + }); + } + catch { + // Not a git repository, skip the git clean check + return; + } + const projectRoot = getProjectRoot(); + const ignorePaths = [ + ...(fingerprintOptions?.ignorePaths ?? []), + ...getAllIgnorePaths(platformName, path.relative(projectRoot, sourceDir), // git expects relative paths + projectRoot), + ]; + const { output } = await spawn('git', [ + 'clean', + '-fdx', + '--dry-run', + sourceDir, + ...ignorePaths.flatMap((path) => ['-e', `${path}`]), + ]); + const ignoredFiles = output + .split('\n') + .map((line) => line.replace('Would remove ', '')) + .filter((line) => line !== ''); + if (ignoredFiles.length > 0) { + logger.warn(`There are files that likely affect fingerprint: +${ignoredFiles.map((file) => `- ${color.bold(file)}`).join('\n')} +Consider removing them or update ${color.bold('fingerprint.ignorePaths')} in ${colorLink('rock.config.mjs')}: +Read more: ${colorLink('https://www.rockjs.dev/docs/configuration#fingerprint-configuration')}`); + } +} +//# sourceMappingURL=getBinaryPath.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/getBinaryPath.js.map b/packages/tools/dist/src/lib/build-cache/getBinaryPath.js.map new file mode 100644 index 000000000..74bd02696 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/getBinaryPath.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getBinaryPath.js","sourceRoot":"","sources":["../../../../src/lib/build-cache/getBinaryPath.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/localBuildCache.d.ts b/packages/tools/dist/src/lib/build-cache/localBuildCache.d.ts new file mode 100644 index 000000000..de6e714c0 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/localBuildCache.d.ts @@ -0,0 +1,8 @@ +export type LocalBuild = { + name: string; + artifactPath: string; + binaryPath: string; +}; +export declare function queryLocalBuildCache(artifactName: string): LocalBuild | null; +export declare function saveLocalBuildCache(artifactName: string, binaryPath: string): void; +export declare function getLocalBuildCacheBinaryPath(artifactName: string): string | undefined; diff --git a/packages/tools/dist/src/lib/build-cache/localBuildCache.js b/packages/tools/dist/src/lib/build-cache/localBuildCache.js new file mode 100644 index 000000000..c52d1cfcd --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/localBuildCache.js @@ -0,0 +1,50 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { color, colorLink } from '../color.js'; +import logger from '../logger.js'; +import { relativeToCwd } from '../path.js'; +import { getLocalArtifactPath, getLocalBinaryPath } from './common.js'; +export function queryLocalBuildCache(artifactName) { + const artifactPath = getLocalArtifactPath(artifactName); + if (!fs.statSync(artifactPath, { throwIfNoEntry: false })?.isDirectory()) { + return null; + } + const binaryPath = getLocalBinaryPath(artifactPath); + if (binaryPath == null || !fs.existsSync(binaryPath)) { + return null; + } + return { + name: artifactName, + artifactPath, + binaryPath, + }; +} +export function saveLocalBuildCache(artifactName, binaryPath) { + try { + const cachePath = getLocalArtifactPath(artifactName); + if (!fs.existsSync(cachePath)) { + fs.mkdirSync(cachePath, { recursive: true }); + } + if (fs.statSync(binaryPath).isDirectory()) { + fs.cpSync(binaryPath, path.join(cachePath, path.basename(binaryPath)), { + recursive: true, + }); + } + else { + fs.copyFileSync(binaryPath, path.join(cachePath, path.basename(binaryPath))); + } + logger.debug(`Saved build cache to: ${colorLink(relativeToCwd(cachePath))}`); + } + catch (error) { + logger.debug('Failed to copy binary to local build cache', error); + } +} +export function getLocalBuildCacheBinaryPath(artifactName) { + const localBuild = queryLocalBuildCache(artifactName); + if (localBuild) { + logger.log(`Found build cache for: ${color.bold(color.blue(localBuild.name))}`); + return localBuild.binaryPath; + } + return undefined; +} +//# sourceMappingURL=localBuildCache.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/build-cache/localBuildCache.js.map b/packages/tools/dist/src/lib/build-cache/localBuildCache.js.map new file mode 100644 index 000000000..4dda97273 --- /dev/null +++ b/packages/tools/dist/src/lib/build-cache/localBuildCache.js.map @@ -0,0 +1 @@ +{"version":3,"file":"localBuildCache.js","sourceRoot":"","sources":["../../../../src/lib/build-cache/localBuildCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQvE,MAAM,UAAU,oBAAoB,CAAC,YAAoB;IACvD,MAAM,YAAY,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IACpD,IAAI,UAAU,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,YAAY;QACZ,UAAU;KACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,YAAoB,EAAE,UAAkB;IAC1E,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1C,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE;gBACrE,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,YAAY,CACb,UAAU,EACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAChD,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,KAAK,CACV,yBAAyB,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,CAC/D,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,YAAoB;IAEpB,MAAM,UAAU,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CACR,0BAA0B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CACpE,CAAC;QACF,OAAO,UAAU,CAAC,UAAU,CAAC;IAC/B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/cacheManager.d.ts b/packages/tools/dist/src/lib/cacheManager.d.ts new file mode 100644 index 000000000..ecc50ce50 --- /dev/null +++ b/packages/tools/dist/src/lib/cacheManager.d.ts @@ -0,0 +1,15 @@ +import { getCacheRootPath } from './project.js'; +type CacheKey = string; +export declare function getCacheFile(): string; +declare function removeProjectCache(): void; +declare function get(key: CacheKey): string | undefined; +declare function set(key: CacheKey, value: string): void; +declare function remove(key: CacheKey): void; +declare const _default: { + get: typeof get; + set: typeof set; + remove: typeof remove; + removeProjectCache: typeof removeProjectCache; + getCacheRootPath: typeof getCacheRootPath; +}; +export default _default; diff --git a/packages/tools/dist/src/lib/cacheManager.js b/packages/tools/dist/src/lib/cacheManager.js new file mode 100644 index 000000000..9b2396cd9 --- /dev/null +++ b/packages/tools/dist/src/lib/cacheManager.js @@ -0,0 +1,63 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { colorLink } from './color.js'; +import { RockError } from './error.js'; +import logger from './logger.js'; +import { getCacheRootPath } from './project.js'; +const CACHE_FILE_NAME = 'project.json'; +export function getCacheFile() { + return path.join(getCacheRootPath(), CACHE_FILE_NAME); +} +function loadCache() { + try { + const cachePath = path.resolve(getCacheFile()); + if (!fs.existsSync(cachePath)) { + logger.debug(`No cache found at: ${cachePath}`); + return {}; + } + const content = fs.readFileSync(cachePath, 'utf8'); + return JSON.parse(content); + } + catch (error) { + logger.warn('Failed to load cache', error); + return {}; + } +} +function saveCache(cache) { + const cachePath = path.resolve(getCacheFile()); + fs.mkdirSync(path.dirname(cachePath), { recursive: true }); + fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2)); +} +function removeProjectCache() { + try { + const cachePath = path.resolve(getCacheFile()); + if (fs.existsSync(cachePath)) { + fs.rmSync(cachePath, { recursive: true }); + } + } + catch (error) { + throw new RockError(`Failed to remove cache for ${name}. If you experience any issues when running freshly initialized project, please remove the "${colorLink(path.join(getCacheFile()))}" folder manually.`, { cause: error }); + } +} +function get(key) { + const cache = loadCache(); + return cache[key]; +} +function set(key, value) { + const cache = loadCache(); + cache[key] = value; + saveCache(cache); +} +function remove(key) { + const cache = loadCache(); + delete cache[key]; + saveCache(cache); +} +export default { + get, + set, + remove, + removeProjectCache, + getCacheRootPath, +}; +//# sourceMappingURL=cacheManager.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/cacheManager.js.map b/packages/tools/dist/src/lib/cacheManager.js.map new file mode 100644 index 000000000..719072853 --- /dev/null +++ b/packages/tools/dist/src/lib/cacheManager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cacheManager.js","sourceRoot":"","sources":["../../../src/lib/cacheManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,eAAe,GAAG,cAAc,CAAC;AAKvC,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,eAAe,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;YAChD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC3C,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAY;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC/C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,8BAA8B,IAAI,+FAA+F,SAAS,CACxI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAC1B,oBAAoB,EACrB,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,GAAa;IACxB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,GAAG,CAAC,GAAa,EAAE,KAAa;IACvC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,SAAS,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,MAAM,CAAC,GAAa;IAC3B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC;AAED,eAAe;IACb,GAAG;IACH,GAAG;IACH,MAAM;IACN,kBAAkB;IAClB,gBAAgB;CACjB,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/color.d.ts b/packages/tools/dist/src/lib/color.d.ts new file mode 100644 index 000000000..5ab982d26 --- /dev/null +++ b/packages/tools/dist/src/lib/color.d.ts @@ -0,0 +1,3 @@ +import color from 'picocolors'; +export { color }; +export declare function colorLink(text: string): string; diff --git a/packages/tools/dist/src/lib/color.js b/packages/tools/dist/src/lib/color.js new file mode 100644 index 000000000..abdaea864 --- /dev/null +++ b/packages/tools/dist/src/lib/color.js @@ -0,0 +1,6 @@ +import color from 'picocolors'; +export { color }; +export function colorLink(text) { + return color.cyan(color.underline(color.bold(text))); +} +//# sourceMappingURL=color.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/color.js.map b/packages/tools/dist/src/lib/color.js.map new file mode 100644 index 000000000..338ab11d4 --- /dev/null +++ b/packages/tools/dist/src/lib/color.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color.js","sourceRoot":"","sources":["../../../src/lib/color.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,OAAO,EAAE,KAAK,EAAE,CAAC;AAEjB,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/findDevServerPort.d.ts b/packages/tools/dist/src/lib/dev-server/findDevServerPort.d.ts new file mode 100644 index 000000000..eef39bee4 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/findDevServerPort.d.ts @@ -0,0 +1,4 @@ +export declare const findDevServerPort: (initialPort: number, root: string) => Promise<{ + port: string; + startDevServer: boolean; +}>; diff --git a/packages/tools/dist/src/lib/dev-server/findDevServerPort.js b/packages/tools/dist/src/lib/dev-server/findDevServerPort.js new file mode 100644 index 000000000..430ff86d2 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/findDevServerPort.js @@ -0,0 +1,27 @@ +import { handlePortUnavailable } from './handlePortUnavailable.js'; +import { isDevServerRunning } from './isDevServerRunning.js'; +import { logAlreadyRunningBundler } from './logAlreadyRunningBundler.js'; +export const findDevServerPort = async (initialPort, root) => { + let port = initialPort; + let startDevServer = true; + const devServerStatus = await isDevServerRunning(port); + if (devServerStatus.status === 'running') { + if (devServerStatus.root === root) { + startDevServer = false; + logAlreadyRunningBundler(port); + } + else { + const result = await handlePortUnavailable(port, root); + [port, startDevServer] = [result.port, result.startDevServer]; + } + } + else if (devServerStatus.status === 'unrecognized') { + const result = await handlePortUnavailable(port, root); + [port, startDevServer] = [result.port, result.startDevServer]; + } + return { + port: String(port), + startDevServer, + }; +}; +//# sourceMappingURL=findDevServerPort.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/findDevServerPort.js.map b/packages/tools/dist/src/lib/dev-server/findDevServerPort.js.map new file mode 100644 index 000000000..83cb38fd3 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/findDevServerPort.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findDevServerPort.js","sourceRoot":"","sources":["../../../../src/lib/dev-server/findDevServerPort.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACpC,WAAmB,EACnB,IAAY,EAIX,EAAE;IACH,IAAI,IAAI,GAAG,WAAW,CAAC;IACvB,IAAI,cAAc,GAAG,IAAI,CAAC;IAE1B,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAEvD,IAAI,eAAe,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACzC,IAAI,eAAe,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAClC,cAAc,GAAG,KAAK,CAAC;YACvB,wBAAwB,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvD,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;SAAM,IAAI,eAAe,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAChE,CAAC;IAED,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;QAClB,cAAc;KACf,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/getNextPort.d.ts b/packages/tools/dist/src/lib/dev-server/getNextPort.d.ts new file mode 100644 index 000000000..ad7a0bc15 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/getNextPort.d.ts @@ -0,0 +1,11 @@ +type Result = { + start: boolean; + nextPort: number; +}; +/** + * Increases by one the port number until it finds an available port. + * @param port Port number to start with. + * @param root Root of the project. + */ +declare const getNextPort: (port: number, root: string) => Promise; +export default getNextPort; diff --git a/packages/tools/dist/src/lib/dev-server/getNextPort.js b/packages/tools/dist/src/lib/dev-server/getNextPort.js new file mode 100644 index 000000000..b00ee9646 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/getNextPort.js @@ -0,0 +1,22 @@ +import { isDevServerRunning } from './isDevServerRunning.js'; +/** + * Increases by one the port number until it finds an available port. + * @param port Port number to start with. + * @param root Root of the project. + */ +const getNextPort = async (port, root) => { + const nextPort = port + 1; + let start = true; + const result = await isDevServerRunning(nextPort); + const isRunning = result.status === 'running'; + if (isRunning && result.root === root) { + // Found running bundler for this project, so we do not need to start dev server! + start = false; + } + else if (isRunning || result.status === 'unrecognized') { + return getNextPort(nextPort, root); + } + return { start, nextPort }; +}; +export default getNextPort; +//# sourceMappingURL=getNextPort.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/getNextPort.js.map b/packages/tools/dist/src/lib/dev-server/getNextPort.js.map new file mode 100644 index 000000000..1b2335d94 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/getNextPort.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getNextPort.js","sourceRoot":"","sources":["../../../../src/lib/dev-server/getNextPort.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAO7D;;;;GAIG;AAEH,MAAM,WAAW,GAAG,KAAK,EAAE,IAAY,EAAE,IAAY,EAAmB,EAAE;IACxE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC;IAC1B,IAAI,KAAK,GAAG,IAAI,CAAC;IAEjB,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC;IAE9C,IAAI,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACtC,iFAAiF;QACjF,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;SAAM,IAAI,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACzD,OAAO,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.d.ts b/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.d.ts new file mode 100644 index 000000000..98c00fcfc --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.d.ts @@ -0,0 +1,4 @@ +export declare const handlePortUnavailable: (initialPort: number, projectRoot: string) => Promise<{ + port: number; + startDevServer: boolean; +}>; diff --git a/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.js b/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.js new file mode 100644 index 000000000..3266cbf32 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.js @@ -0,0 +1,33 @@ +import logger from '../logger.js'; +import { promptConfirm } from '../prompts.js'; +import getNextPort from './getNextPort.js'; +import { logAlreadyRunningBundler } from './logAlreadyRunningBundler.js'; +export const handlePortUnavailable = async (initialPort, projectRoot) => { + const { nextPort, start } = await getNextPort(initialPort, projectRoot); + let startDevServer = true; + let port = initialPort; + if (!start) { + startDevServer = false; + logAlreadyRunningBundler(nextPort); + } + else { + const change = await askForPortChange(port, nextPort); + if (change) { + port = nextPort; + } + else { + startDevServer = false; + logger.info('Exiting. You can try again with a different port using "--port" flag'); + } + } + return { port, startDevServer }; +}; +const askForPortChange = (port, nextPort) => { + logger.info(`Another process is running on port ${port}.`); + return promptConfirm({ + message: `Use port ${nextPort} instead?`, + confirmLabel: 'Yes', + cancelLabel: 'No', + }); +}; +//# sourceMappingURL=handlePortUnavailable.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.js.map b/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.js.map new file mode 100644 index 000000000..be5b9bf6a --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/handlePortUnavailable.js.map @@ -0,0 +1 @@ +{"version":3,"file":"handlePortUnavailable.js","sourceRoot":"","sources":["../../../../src/lib/dev-server/handlePortUnavailable.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,WAAmB,EACnB,WAAmB,EAIlB,EAAE;IACH,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACxE,IAAI,cAAc,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,GAAG,WAAW,CAAC;IAEvB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,cAAc,GAAG,KAAK,CAAC;QACvB,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEtD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,GAAG,QAAQ,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,KAAK,CAAC;YACvB,MAAM,CAAC,IAAI,CACT,sEAAsE,CACvE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE;IAC1D,MAAM,CAAC,IAAI,CAAC,sCAAsC,IAAI,GAAG,CAAC,CAAC;IAE3D,OAAO,aAAa,CAAC;QACnB,OAAO,EAAE,YAAY,QAAQ,WAAW;QACxC,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/isDevServerRunning.d.ts b/packages/tools/dist/src/lib/dev-server/isDevServerRunning.d.ts new file mode 100644 index 000000000..e38646b60 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/isDevServerRunning.d.ts @@ -0,0 +1,13 @@ +/** + * Indicates whether or not the dev server is running. It returns a promise that + * returns one of these possible values: + * - `{status: 'running', root: string}`: the dev server is running + * - `{status: 'not_running'}`: the dev server nor any process is running on the expected port. + * - `{status: 'unrecognized'}`: one other process is running on the port we expect the dev server to be running. + */ +export declare function isDevServerRunning(port?: string | number): Promise<{ + status: 'running'; + root: string; +} | { + status: 'not_running' | 'unrecognized'; +}>; diff --git a/packages/tools/dist/src/lib/dev-server/isDevServerRunning.js b/packages/tools/dist/src/lib/dev-server/isDevServerRunning.js new file mode 100644 index 000000000..e686ac1f6 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/isDevServerRunning.js @@ -0,0 +1,29 @@ +/** + * Indicates whether or not the dev server is running. It returns a promise that + * returns one of these possible values: + * - `{status: 'running', root: string}`: the dev server is running + * - `{status: 'not_running'}`: the dev server nor any process is running on the expected port. + * - `{status: 'unrecognized'}`: one other process is running on the port we expect the dev server to be running. + */ +export async function isDevServerRunning(port = process.env['RCT_METRO_PORT'] || '8081') { + try { + const response = await fetch(`http://localhost:${port}/status`); + const data = await response.text(); + try { + if (data === 'packager-status:running') { + return { + status: 'running', + root: response.headers.get('X-React-Native-Project-Root') ?? '', + }; + } + } + catch (_error) { + return { status: 'unrecognized' }; + } + return { status: 'unrecognized' }; + } + catch (_error) { + return { status: 'not_running' }; + } +} +//# sourceMappingURL=isDevServerRunning.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/isDevServerRunning.js.map b/packages/tools/dist/src/lib/dev-server/isDevServerRunning.js.map new file mode 100644 index 000000000..537ee6797 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/isDevServerRunning.js.map @@ -0,0 +1 @@ +{"version":3,"file":"isDevServerRunning.js","sourceRoot":"","sources":["../../../../src/lib/dev-server/isDevServerRunning.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAwB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,MAAM;IAK/D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,oBAAoB,IAAI,SAAS,CAAC,CAAC;QAEhE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEnC,IAAI,CAAC;YACH,IAAI,IAAI,KAAK,yBAAyB,EAAE,CAAC;gBACvC,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,IAAI,EAAE;iBAChE,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QACpC,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACnC,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.d.ts b/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.d.ts new file mode 100644 index 000000000..99bf29e54 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.d.ts @@ -0,0 +1 @@ +export declare const logAlreadyRunningBundler: (port: number) => void; diff --git a/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.js b/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.js new file mode 100644 index 000000000..55ae93474 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.js @@ -0,0 +1,5 @@ +import logger from '../logger.js'; +export const logAlreadyRunningBundler = (port) => { + logger.info(`A dev server is already running for this project on port ${port}. Pass "--port" option to use a different port`); +}; +//# sourceMappingURL=logAlreadyRunningBundler.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.js.map b/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.js.map new file mode 100644 index 000000000..6698d7e16 --- /dev/null +++ b/packages/tools/dist/src/lib/dev-server/logAlreadyRunningBundler.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logAlreadyRunningBundler.js","sourceRoot":"","sources":["../../../../src/lib/dev-server/logAlreadyRunningBundler.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,IAAY,EAAE,EAAE;IACvD,MAAM,CAAC,IAAI,CACT,4DAA4D,IAAI,gDAAgD,CACjH,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/env.d.ts b/packages/tools/dist/src/lib/env.d.ts new file mode 100644 index 000000000..e66e01cd1 --- /dev/null +++ b/packages/tools/dist/src/lib/env.d.ts @@ -0,0 +1,2 @@ +export type OperatingSystem = 'macos' | 'linux' | 'windows'; +export declare function getLocalOS(): OperatingSystem; diff --git a/packages/tools/dist/src/lib/env.js b/packages/tools/dist/src/lib/env.js new file mode 100644 index 000000000..460e41d63 --- /dev/null +++ b/packages/tools/dist/src/lib/env.js @@ -0,0 +1,11 @@ +export function getLocalOS() { + if (process.platform === 'darwin') { + return 'macos'; + } + if (process.platform === 'win32') { + return 'windows'; + } + // Otherwise, assume it's linux-like + return 'linux'; +} +//# sourceMappingURL=env.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/env.js.map b/packages/tools/dist/src/lib/env.js.map new file mode 100644 index 000000000..c3c8e1905 --- /dev/null +++ b/packages/tools/dist/src/lib/env.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/lib/env.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU;IACxB,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,oCAAoC;IACpC,OAAO,OAAO,CAAC;AACjB,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/error.d.ts b/packages/tools/dist/src/lib/error.d.ts new file mode 100644 index 000000000..49ce58119 --- /dev/null +++ b/packages/tools/dist/src/lib/error.d.ts @@ -0,0 +1,6 @@ +export type RockErrorOptions = { + cause?: unknown; +}; +export declare class RockError extends Error { + constructor(message: string, { cause }?: RockErrorOptions); +} diff --git a/packages/tools/dist/src/lib/error.js b/packages/tools/dist/src/lib/error.js new file mode 100644 index 000000000..effc5d7d7 --- /dev/null +++ b/packages/tools/dist/src/lib/error.js @@ -0,0 +1,11 @@ +// See: +// - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types +// - https://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript +export class RockError extends Error { + constructor(message, { cause } = {}) { + super(message, { cause }); // Pass the cause to the Error constructor + this.name = this.constructor.name; // Set the error name + Error.captureStackTrace(this, this.constructor); // Capture stack trace + } +} +//# sourceMappingURL=error.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/error.js.map b/packages/tools/dist/src/lib/error.js.map new file mode 100644 index 000000000..d96cb7db1 --- /dev/null +++ b/packages/tools/dist/src/lib/error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/lib/error.ts"],"names":[],"mappings":"AAIA,OAAO;AACP,8GAA8G;AAC9G,+FAA+F;AAC/F,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe,EAAE,EAAE,KAAK,KAAuB,EAAE;QAC3D,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,0CAA0C;QACrE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,qBAAqB;QACxD,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,sBAAsB;IACzE,CAAC;CACF"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/fingerprint/ignorePaths.d.ts b/packages/tools/dist/src/lib/fingerprint/ignorePaths.d.ts new file mode 100644 index 000000000..c39cb0fb2 --- /dev/null +++ b/packages/tools/dist/src/lib/fingerprint/ignorePaths.d.ts @@ -0,0 +1,8 @@ +/** + * Returns all ignore paths for the given platform, source directory and project root. + * @param platform - The platform to get the ignore paths for. + * @param sourceDir - The relative source directory of that platform to get the ignore paths for. + * @param projectRoot - The project root to get the ignore paths for. + * @returns All ignore paths for the given platform, source directory and project root. + */ +export declare function getAllIgnorePaths(platform: string, sourceDir: string, projectRoot: string): string[]; diff --git a/packages/tools/dist/src/lib/fingerprint/ignorePaths.js b/packages/tools/dist/src/lib/fingerprint/ignorePaths.js new file mode 100644 index 000000000..874aaa8ee --- /dev/null +++ b/packages/tools/dist/src/lib/fingerprint/ignorePaths.js @@ -0,0 +1,81 @@ +import { getGitIgnoredPaths } from 'fs-fingerprint'; +function getAndroidIgnorePaths(sourceDir) { + return [ + `${sourceDir}/app/.gradle`, + `${sourceDir}/build`, + `${sourceDir}/**/build`, + `${sourceDir}/**/.cxx`, + `${sourceDir}/.kotlin`, + `${sourceDir}/local.properties`, + `${sourceDir}/.idea`, + `${sourceDir}/.gradle`, + `${sourceDir}/gradlew.bat`, // Often has different line endings, thus we have to ignore it + // Android annotations - revisit + '**/android-annotation/build', + '**/android-annotation/.cxx', + '**/android-annotation/.gradle', + '**/android-annotation-processor/build', + '**/android-annotation-processor/.cxx', + '**/android-annotation-processor/.gradle', + // Android gradle plugins + '**/*-gradle-plugin/build', + '**/*-gradle-plugin/.cxx', + '**/*-gradle-plugin/.gradle', + ]; +} +function getIOSIgnorePaths(sourceDir) { + return [ + `${sourceDir}/build`, + `${sourceDir}/.xcode.env.local`, + `${sourceDir}/**/project.xcworkspace`, + `${sourceDir}/*.xcworkspace/xcuserdata`, + `${sourceDir}/DerivedData`, + `${sourceDir}/Pods`, + `${sourceDir}/tmp.xcconfig`, // added by react-native-config, + `${sourceDir}/**/*.xcworkspace`, + ]; +} +function getHarmonyIgnorePaths(sourceDir) { + return [ + `${sourceDir}/.hvigor`, + `${sourceDir}/**/.idea`, + `${sourceDir}/**/oh_modules`, + `${sourceDir}/**/build`, + `${sourceDir}/**/.cxx`, + `${sourceDir}/**/.preview`, + `${sourceDir}/**/.clangd`, + `${sourceDir}/**/.clang-format`, + `${sourceDir}/**/.clang-tidy`, + `${sourceDir}/**/test`, + ]; +} +function getDefaultIgnorePaths() { + return ['**/.DS_Store']; +} +function getPlatformDirIgnorePaths(platform, sourceDir) { + if (platform === 'android') { + return getAndroidIgnorePaths(sourceDir); + } + else if (platform === 'ios') { + return getIOSIgnorePaths(sourceDir); + } + else if (platform === 'harmony') { + return getHarmonyIgnorePaths(sourceDir); + } + return []; +} +/** + * Returns all ignore paths for the given platform, source directory and project root. + * @param platform - The platform to get the ignore paths for. + * @param sourceDir - The relative source directory of that platform to get the ignore paths for. + * @param projectRoot - The project root to get the ignore paths for. + * @returns All ignore paths for the given platform, source directory and project root. + */ +export function getAllIgnorePaths(platform, sourceDir, projectRoot) { + return [ + ...getDefaultIgnorePaths(), + ...getGitIgnoredPaths(projectRoot), + ...getPlatformDirIgnorePaths(platform, sourceDir), + ]; +} +//# sourceMappingURL=ignorePaths.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/fingerprint/ignorePaths.js.map b/packages/tools/dist/src/lib/fingerprint/ignorePaths.js.map new file mode 100644 index 000000000..63ad7a5bb --- /dev/null +++ b/packages/tools/dist/src/lib/fingerprint/ignorePaths.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ignorePaths.js","sourceRoot":"","sources":["../../../../src/lib/fingerprint/ignorePaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,SAAS,qBAAqB,CAAC,SAAiB;IAC9C,OAAO;QACL,GAAG,SAAS,cAAc;QAC1B,GAAG,SAAS,QAAQ;QACpB,GAAG,SAAS,WAAW;QACvB,GAAG,SAAS,UAAU;QACtB,GAAG,SAAS,UAAU;QACtB,GAAG,SAAS,mBAAmB;QAC/B,GAAG,SAAS,QAAQ;QACpB,GAAG,SAAS,UAAU;QACtB,GAAG,SAAS,cAAc,EAAE,8DAA8D;QAE1F,gCAAgC;QAChC,6BAA6B;QAC7B,4BAA4B;QAC5B,+BAA+B;QAC/B,uCAAuC;QACvC,sCAAsC;QACtC,yCAAyC;QAEzC,yBAAyB;QACzB,0BAA0B;QAC1B,yBAAyB;QACzB,4BAA4B;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,OAAO;QACL,GAAG,SAAS,QAAQ;QACpB,GAAG,SAAS,mBAAmB;QAC/B,GAAG,SAAS,yBAAyB;QACrC,GAAG,SAAS,2BAA2B;QACvC,GAAG,SAAS,cAAc;QAC1B,GAAG,SAAS,OAAO;QACnB,GAAG,SAAS,eAAe,EAAE,gCAAgC;QAC7D,GAAG,SAAS,mBAAmB;KAChC,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAiB;IAC9C,OAAO;QACL,GAAG,SAAS,UAAU;QACtB,GAAG,SAAS,WAAW;QACvB,GAAG,SAAS,gBAAgB;QAC5B,GAAG,SAAS,WAAW;QACvB,GAAG,SAAS,UAAU;QACtB,GAAG,SAAS,cAAc;QAC1B,GAAG,SAAS,aAAa;QACzB,GAAG,SAAS,mBAAmB;QAC/B,GAAG,SAAS,iBAAiB;QAC7B,GAAG,SAAS,UAAU;KACvB,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,CAAC,cAAc,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,yBAAyB,CAAC,QAAgB,EAAE,SAAiB;IACpE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;SAAM,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC9B,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,SAAiB,EACjB,WAAmB;IAEnB,OAAO;QACL,GAAG,qBAAqB,EAAE;QAC1B,GAAG,kBAAkB,CAAC,WAAW,CAAC;QAClC,GAAG,yBAAyB,CAAC,QAAQ,EAAE,SAAS,CAAC;KAClD,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/fingerprint/index.d.ts b/packages/tools/dist/src/lib/fingerprint/index.d.ts new file mode 100644 index 000000000..a99abbd8d --- /dev/null +++ b/packages/tools/dist/src/lib/fingerprint/index.d.ts @@ -0,0 +1,17 @@ +import { type FingerprintResult } from 'fs-fingerprint'; +export type { FingerprintInputHash } from 'fs-fingerprint'; +export type FingerprintSources = { + extraSources: string[]; + ignorePaths: string[]; + env: string[]; +}; +export type FingerprintOptions = { + platform: 'ios' | 'android' | 'harmony'; + extraSources: string[]; + ignorePaths: string[]; + env: string[]; +}; +/** + * Calculates the fingerprint of the native parts project of the project. + */ +export declare function nativeFingerprint(projectRoot: string, options: FingerprintOptions): Promise; diff --git a/packages/tools/dist/src/lib/fingerprint/index.js b/packages/tools/dist/src/lib/fingerprint/index.js new file mode 100644 index 000000000..24800f562 --- /dev/null +++ b/packages/tools/dist/src/lib/fingerprint/index.js @@ -0,0 +1,95 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { calculateFingerprint } from 'fs-fingerprint'; +import { getReactNativeVersion, logger } from '../../index.js'; +import { spawn } from '../spawn.js'; +import { getAllIgnorePaths } from './ignorePaths.js'; +/** + * Calculates the fingerprint of the native parts project of the project. + */ +export async function nativeFingerprint(projectRoot, options) { + let autolinkingConfig; + try { + // Use stdout to avoid deprecation warnings + const { stdout: autolinkingConfigString } = await spawn('rock', ['config', '-p', options.platform], { cwd: projectRoot, stdio: 'pipe' }); + autolinkingConfig = JSON.parse(autolinkingConfigString); + } + catch { + throw new Error('Failed to read autolinking config'); + } + const packageJSONPath = path.join(projectRoot, 'package.json'); + const packageJSON = await readPackageJSON(packageJSONPath); + const scripts = packageJSON['scripts']; + const sourceDir = autolinkingConfig.project[options.platform]?.sourceDir; + if (!options.platform || !sourceDir) { + throw new Error('No platforms found in autolinking project config'); + } + let env = undefined; + if (options.env.length > 0) { + env = options.env.reduce((acc, key) => { + acc[key] = process.env[key] ?? ''; + return acc; + }, {}); + } + const fingerprint = await calculateFingerprint(projectRoot, { + include: [ + sourceDir, + ...options.extraSources.map((source) => path.isAbsolute(source) ? path.relative(projectRoot, source) : source), + ], + extraInputs: [ + { key: 'scripts', json: scripts }, + { + key: 'autolinkingSources', + json: parseAutolinkingSources(autolinkingConfig), + }, + { + key: 'reactNativeVersion', + json: { version: getReactNativeVersion(projectRoot) }, + }, + ...(env ? [{ key: 'env', json: env }] : []), + ], + exclude: [ + ...getAllIgnorePaths(options.platform, sourceDir, projectRoot), + ...(options.ignorePaths ?? []), + ], + }); + return fingerprint; +} +const readPackageJSON = async (packageJSONPath) => { + try { + const packageJSONContent = await fs.readFile(packageJSONPath, 'utf-8'); + return JSON.parse(packageJSONContent); + } + catch { + throw new Error(`Failed to read package.json at: ${packageJSONPath}`); + } +}; +function toPosixPath(filePath) { + return filePath.replace(/\\/g, '/'); +} +function parseAutolinkingSources(config) { + const { root } = config; + for (const [depName, depData] of Object.entries(config.dependencies)) { + try { + stripAutolinkingAbsolutePaths(depData, root); + } + catch (e) { + logger.debug(`Error adding react-native core autolinking - ${depName}.\n${e}`); + } + } + return config.dependencies; +} +function stripAutolinkingAbsolutePaths(dependency, root) { + const dependencyRoot = dependency.root; + const posixDependencyRoot = toPosixPath(dependencyRoot); + dependency.root = toPosixPath(path.relative(root, dependencyRoot)); + for (const platformData of Object.values(dependency.platforms)) { + for (const [key, value] of Object.entries(platformData ?? {})) { + const newValue = value?.startsWith?.(posixDependencyRoot) + ? toPosixPath(path.relative(root, value)) + : value; + platformData[key] = newValue; + } + } +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/fingerprint/index.js.map b/packages/tools/dist/src/lib/fingerprint/index.js.map new file mode 100644 index 000000000..e8d416405 --- /dev/null +++ b/packages/tools/dist/src/lib/fingerprint/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/fingerprint/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAA0B,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAgBrD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,OAA2B;IAE3B,IAAI,iBAAiB,CAAC;IAEtB,IAAI,CAAC;QACH,2CAA2C;QAC3C,MAAM,EAAE,MAAM,EAAE,uBAAuB,EAAE,GAAG,MAAM,KAAK,CACrD,MAAM,EACN,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,EAClC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,CACpC,CAAC;QAEF,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,eAAe,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAEzE,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,GAAG,GAAG,SAAS,CAAC;IAEpB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAA2B,EAAE,GAAW,EAAE,EAAE;YACpE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAClC,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE;QAC1D,OAAO,EAAE;YACP,SAAS;YACT,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACrC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CACtE;SACF;QACD,WAAW,EAAE;YACX,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;YACjC;gBACE,GAAG,EAAE,oBAAoB;gBACzB,IAAI,EAAE,uBAAuB,CAAC,iBAAiB,CAAC;aACjD;YACD;gBACE,GAAG,EAAE,oBAAoB;gBACzB,IAAI,EAAE,EAAE,OAAO,EAAE,qBAAqB,CAAC,WAAW,CAAC,EAAE;aACtD;YACD,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5C;QACD,OAAO,EAAE;YACP,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC;YAC9D,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;SAC/B;KACF,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,eAAe,GAAG,KAAK,EAAE,eAAuB,EAAE,EAAE;IACxD,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mCAAmC,eAAe,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC,CAAC;AAEF,SAAS,WAAW,CAAC,QAAgB;IACnC,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAW;IAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAM,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1E,IAAI,CAAC;YACH,6BAA6B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CACV,gDAAgD,OAAO,MAAM,CAAC,EAAE,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,YAAY,CAAC;AAC7B,CAAC;AAED,SAAS,6BAA6B,CAAC,UAAe,EAAE,IAAY;IAClE,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;IACvC,MAAM,mBAAmB,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAExD,UAAU,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IACnE,KAAK,MAAM,YAAY,IAAI,MAAM,CAAC,MAAM,CAAM,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAM,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,KAAK,EAAE,UAAU,EAAE,CAAC,mBAAmB,CAAC;gBACvD,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACzC,CAAC,CAAC,KAAK,CAAC;YACV,YAAY,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;QAC/B,CAAC;IACH,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/getInfoPlist.d.ts b/packages/tools/dist/src/lib/getInfoPlist.d.ts new file mode 100644 index 000000000..ca90972d4 --- /dev/null +++ b/packages/tools/dist/src/lib/getInfoPlist.d.ts @@ -0,0 +1 @@ +export declare function getInfoPlist(infoPlistPath: string): Promise | null>; diff --git a/packages/tools/dist/src/lib/getInfoPlist.js b/packages/tools/dist/src/lib/getInfoPlist.js new file mode 100644 index 000000000..2ffc8dc8c --- /dev/null +++ b/packages/tools/dist/src/lib/getInfoPlist.js @@ -0,0 +1,12 @@ +import { logger, spawn } from '../index.js'; +export async function getInfoPlist(infoPlistPath) { + try { + const { stdout } = await spawn('plutil', ['-convert', 'json', '-o', '-', infoPlistPath], { stdio: 'pipe' }); + return JSON.parse(stdout); + } + catch (error) { + logger.debug(`Failed to get Info.plist: ${error}`); + } + return null; +} +//# sourceMappingURL=getInfoPlist.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/getInfoPlist.js.map b/packages/tools/dist/src/lib/getInfoPlist.js.map new file mode 100644 index 000000000..5f2d4315e --- /dev/null +++ b/packages/tools/dist/src/lib/getInfoPlist.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getInfoPlist.js","sourceRoot":"","sources":["../../../src/lib/getInfoPlist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,aAAqB;IAErB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,QAAQ,EACR,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,CAAC,EAC9C,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/getReactNativeVersion.d.ts b/packages/tools/dist/src/lib/getReactNativeVersion.d.ts new file mode 100644 index 000000000..538af4154 --- /dev/null +++ b/packages/tools/dist/src/lib/getReactNativeVersion.d.ts @@ -0,0 +1 @@ +export declare function getReactNativeVersion(root: string): any; diff --git a/packages/tools/dist/src/lib/getReactNativeVersion.js b/packages/tools/dist/src/lib/getReactNativeVersion.js new file mode 100644 index 000000000..110a62992 --- /dev/null +++ b/packages/tools/dist/src/lib/getReactNativeVersion.js @@ -0,0 +1,13 @@ +import fs from 'node:fs'; +import { createRequire } from 'node:module'; +import path from 'node:path'; +export function getReactNativeVersion(root) { + try { + const require = createRequire(import.meta.url); + return JSON.parse(fs.readFileSync(path.join(require.resolve('react-native', { paths: [root] }), '..', 'package.json'), 'utf-8')).version; + } + catch { + return 'unknown'; + } +} +//# sourceMappingURL=getReactNativeVersion.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/getReactNativeVersion.js.map b/packages/tools/dist/src/lib/getReactNativeVersion.js.map new file mode 100644 index 000000000..ed08a23a4 --- /dev/null +++ b/packages/tools/dist/src/lib/getReactNativeVersion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getReactNativeVersion.js","sourceRoot":"","sources":["../../../src/lib/getReactNativeVersion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CACf,EAAE,CAAC,YAAY,CACb,IAAI,CAAC,IAAI,CACP,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAClD,IAAI,EACJ,cAAc,CACf,EACD,OAAO,CACR,CACF,CAAC,OAAO,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/hermes.d.ts b/packages/tools/dist/src/lib/hermes.d.ts new file mode 100644 index 000000000..5ec26e078 --- /dev/null +++ b/packages/tools/dist/src/lib/hermes.d.ts @@ -0,0 +1,4 @@ +export declare function runHermes({ bundleOutputPath, sourcemapOutputPath, }: { + bundleOutputPath: string; + sourcemapOutputPath?: string; +}): Promise; diff --git a/packages/tools/dist/src/lib/hermes.js b/packages/tools/dist/src/lib/hermes.js new file mode 100644 index 000000000..26c83a01e --- /dev/null +++ b/packages/tools/dist/src/lib/hermes.js @@ -0,0 +1,141 @@ +import fs from 'node:fs'; +import { createRequire } from 'node:module'; +import path from 'node:path'; +import { getLocalOS } from './env.js'; +import { RockError } from './error.js'; +import { getProjectRoot } from './project.js'; +import { spawn } from './spawn.js'; +function getReactNativePackagePath() { + const require = createRequire(import.meta.url); + const root = getProjectRoot(); + const input = require.resolve('react-native', { paths: [root] }); + return path.dirname(input); +} +/** + * Returns the path to the react-native compose-source-maps.js script. + */ +function getComposeSourceMapsPath() { + const rnPackagePath = getReactNativePackagePath(); + const composeSourceMapsPath = path.join(rnPackagePath, 'scripts', 'compose-source-maps.js'); + if (!fs.existsSync(composeSourceMapsPath)) { + throw new RockError("Could not find react-native's compose-source-maps.js script."); + } + return composeSourceMapsPath; +} +/** + * Extracts debugId from sourcemap file. + * @see https://github.com/tc39/ecma426/blob/main/proposals/debug-id.md + * @param sourceMapPath - Sourcemap file path + * @returns debugId value. Returns null if extraction fails + */ +function extractDebugId(sourceMapPath) { + try { + const sourceMapContent = fs.readFileSync(sourceMapPath, 'utf-8'); + const sourceMap = JSON.parse(sourceMapContent); + return sourceMap.debugId; + } + catch { + return null; + } +} +/** + * Inject debugId into sourcemap file at the top level. + * @see https://github.com/tc39/ecma426/blob/main/proposals/debug-id.md + * @param sourceMapPath - Sourcemap file path + * @param debugId - debugId value to inject + * @throws {RockError} Throws an error if injection fails + */ +function injectDebugId(sourceMapPath, debugId) { + try { + const sourceMapContent = fs.readFileSync(sourceMapPath, 'utf-8'); + const sourceMap = JSON.parse(sourceMapContent); + sourceMap.debugId = debugId; + fs.writeFileSync(sourceMapPath, JSON.stringify(sourceMap)); + } + catch { + throw new RockError(`Failed to inject debugId into sourcemap: ${sourceMapPath}`); + } +} +export async function runHermes({ bundleOutputPath, sourcemapOutputPath, }) { + const hermescPath = getHermescPath(); + if (!hermescPath) { + throw new RockError('Hermesc binary not found. Use `--no-hermes` flag to disable Hermes.'); + } + // Output will be .hbc file + const hbcOutputPath = `${bundleOutputPath}.hbc`; + const hermescArgs = [ + '-emit-binary', + '-max-diagnostic-width=80', + '-O', + '-w', + '-out', + hbcOutputPath, + bundleOutputPath, + ]; + // Add sourcemap flag if enabled + if (sourcemapOutputPath) { + hermescArgs.push('-output-source-map'); + } + try { + await spawn(hermescPath, hermescArgs); + } + catch (error) { + throw new RockError('Compiling JS bundle with Hermes failed. Use `--no-hermes` flag to disable Hermes.', { cause: error.stderr }); + } + // Handle sourcemap composition if enabled + if (sourcemapOutputPath) { + const hermesSourceMapFile = `${hbcOutputPath}.map`; + const composeSourceMapsPath = getComposeSourceMapsPath(); + try { + // Extract debugId from original sourcemap + const debugId = extractDebugId(sourcemapOutputPath); + await spawn('node', [ + composeSourceMapsPath, + sourcemapOutputPath, + hermesSourceMapFile, + '-o', + sourcemapOutputPath, + ]); + // Inject debugId back into the composed sourcemap + if (debugId) { + injectDebugId(sourcemapOutputPath, debugId); + } + } + catch (error) { + throw new RockError('Failed to run compose-source-maps script', { + cause: error.stderr, + }); + } + } + // Move .hbc file to overwrite the original bundle file + try { + if (fs.existsSync(bundleOutputPath)) { + fs.unlinkSync(bundleOutputPath); + } + fs.renameSync(hbcOutputPath, bundleOutputPath); + } + catch (error) { + throw new RockError(`Failed to move compiled Hermes bytecode to bundle output path: ${error}`); + } +} +/** + * Get `hermesc` binary path. + * Based on: https://github.com/facebook/react-native/blob/f2c78af56ae492f49b90d0af61ca9bf4d124fca0/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt#L48-L55 + */ +function getHermescPath() { + const reactNativePath = getReactNativePackagePath(); + // Local build from source: node_modules/react-native/sdks/hermes/build/bin/hermesc + const localBuildPath = path.join(reactNativePath, 'sdks/hermes/build/bin/hermesc'); + if (fs.existsSync(localBuildPath)) { + return localBuildPath; + } + // Precompiled binaries: node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc + const prebuildPaths = { + macos: `${reactNativePath}/sdks/hermesc/osx-bin/hermesc`, + linux: `${reactNativePath}/sdks/hermesc/linux64-bin/hermesc`, + windows: `${reactNativePath}/sdks/hermesc/win64-bin/hermesc.exe`, + }; + const os = getLocalOS(); + return prebuildPaths[os]; +} +//# sourceMappingURL=hermes.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/hermes.js.map b/packages/tools/dist/src/lib/hermes.js.map new file mode 100644 index 000000000..2c7d1e822 --- /dev/null +++ b/packages/tools/dist/src/lib/hermes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hermes.js","sourceRoot":"","sources":["../../../src/lib/hermes.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/isInteractive.d.ts b/packages/tools/dist/src/lib/isInteractive.d.ts new file mode 100644 index 000000000..7b5cb7e6b --- /dev/null +++ b/packages/tools/dist/src/lib/isInteractive.d.ts @@ -0,0 +1,8 @@ +/** + * Source from https://github.com/sindresorhus/is-interactive/blob/main/index.js + */ +export declare function isInteractive({ stream }?: { + stream?: (NodeJS.WriteStream & { + fd: 1; + }) | undefined; +}): boolean; diff --git a/packages/tools/dist/src/lib/isInteractive.js b/packages/tools/dist/src/lib/isInteractive.js new file mode 100644 index 000000000..67759ae7a --- /dev/null +++ b/packages/tools/dist/src/lib/isInteractive.js @@ -0,0 +1,10 @@ +/** + * Source from https://github.com/sindresorhus/is-interactive/blob/main/index.js + */ +export function isInteractive({ stream = process.stdout } = {}) { + return Boolean(stream && + stream.isTTY && + process.env['TERM'] !== 'dumb' && + !('CI' in process.env)); +} +//# sourceMappingURL=isInteractive.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/isInteractive.js.map b/packages/tools/dist/src/lib/isInteractive.js.map new file mode 100644 index 000000000..a8e7b9d3d --- /dev/null +++ b/packages/tools/dist/src/lib/isInteractive.js.map @@ -0,0 +1 @@ +{"version":3,"file":"isInteractive.js","sourceRoot":"","sources":["../../../src/lib/isInteractive.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;IAC5D,OAAO,OAAO,CACZ,MAAM;QACJ,MAAM,CAAC,KAAK;QACZ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,MAAM;QAC9B,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,CACzB,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/logger.d.ts b/packages/tools/dist/src/lib/logger.d.ts new file mode 100644 index 000000000..fbac71d4a --- /dev/null +++ b/packages/tools/dist/src/lib/logger.d.ts @@ -0,0 +1,12 @@ +declare const _default: { + success: (...messages: Array) => void; + info: (...messages: Array) => void; + warn: (...messages: Array) => void; + warnOnce: (key: string) => (...messages: Array) => void; + error: (...messages: Array) => void; + debug: (...messages: Array) => void; + log: (...messages: Array) => void; + setVerbose: (level: boolean) => void; + isVerbose: () => boolean; +}; +export default _default; diff --git a/packages/tools/dist/src/lib/logger.js b/packages/tools/dist/src/lib/logger.js new file mode 100644 index 000000000..f47f7b495 --- /dev/null +++ b/packages/tools/dist/src/lib/logger.js @@ -0,0 +1,67 @@ +import util from 'node:util'; +import { log as clackLog } from '@clack/prompts'; +import isUnicodeSupported from 'is-unicode-supported'; +import cacheManager from './cacheManager.js'; +import { color } from './color.js'; +import { isInteractive } from './isInteractive.js'; +const unicode = isUnicodeSupported(); +const unicodeWithFallback = (c, fallback) => unicode ? c : fallback; +const SYMBOL_DEBUG = unicodeWithFallback('โ—', 'โ€ข'); +let verbose = false; +const success = (...messages) => { + const output = util.format(...messages); + clackLog.success(output); +}; +const info = (...messages) => { + const output = util.format(...messages); + clackLog.info(output); +}; +const warn = (...messages) => { + const output = util.format(...messages); + clackLog.warn(mapLines(output, color.yellow)); +}; +const warnOnce = (key) => (...messages) => { + if (cacheManager.get(`warnOnce-${key}`)) { + return; + } + warn(...messages); + cacheManager.set(`warnOnce-${key}`, 'true'); +}; +const error = (...messages) => { + const output = util.format(...messages); + clackLog.error(mapLines(output, color.red)); +}; +const log = (...messages) => { + const output = util.format(...messages); + clackLog.step(output); +}; +const debug = (...messages) => { + if (verbose) { + const output = util.format(...messages); + clackLog.message(mapLines(output, color.dim), { + symbol: color.dim(SYMBOL_DEBUG), + }); + } +}; +const setVerbose = (level) => { + verbose = level; +}; +const isVerbose = () => { + // For non-interactive environments, always show verbose logs + return !isInteractive() || verbose; +}; +export default { + success, + info, + warn, + warnOnce, + error, + debug, + log, + setVerbose, + isVerbose, +}; +function mapLines(text, colorFn) { + return text.split('\n').map(colorFn).join('\n'); +} +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/logger.js.map b/packages/tools/dist/src/lib/logger.js.map new file mode 100644 index 000000000..b6ee431c0 --- /dev/null +++ b/packages/tools/dist/src/lib/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/lib/logger.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/parse-args.d.ts b/packages/tools/dist/src/lib/parse-args.d.ts new file mode 100644 index 000000000..ecd756def --- /dev/null +++ b/packages/tools/dist/src/lib/parse-args.d.ts @@ -0,0 +1 @@ +export declare function parseArgs(args: string): string[]; diff --git a/packages/tools/dist/src/lib/parse-args.js b/packages/tools/dist/src/lib/parse-args.js new file mode 100644 index 000000000..7cb3a53ab --- /dev/null +++ b/packages/tools/dist/src/lib/parse-args.js @@ -0,0 +1,5 @@ +import { parseArgsStringToArgv } from 'string-argv'; +export function parseArgs(args) { + return parseArgsStringToArgv(args); +} +//# sourceMappingURL=parse-args.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/parse-args.js.map b/packages/tools/dist/src/lib/parse-args.js.map new file mode 100644 index 000000000..90a5ed59f --- /dev/null +++ b/packages/tools/dist/src/lib/parse-args.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parse-args.js","sourceRoot":"","sources":["../../../src/lib/parse-args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/path.d.ts b/packages/tools/dist/src/lib/path.d.ts new file mode 100644 index 000000000..6927ef455 --- /dev/null +++ b/packages/tools/dist/src/lib/path.d.ts @@ -0,0 +1,4 @@ +export declare function relativeToCwd(path: string): string; +export declare function resolveAbsolutePath(path: string): string; +export declare function resolveFilenameUp(path: string, filename: string): string; +export declare function findDirectoriesWithPattern(path: string, pattern: RegExp): string[]; diff --git a/packages/tools/dist/src/lib/path.js b/packages/tools/dist/src/lib/path.js new file mode 100644 index 000000000..0dbf68374 --- /dev/null +++ b/packages/tools/dist/src/lib/path.js @@ -0,0 +1,36 @@ +import * as fs from 'node:fs'; +import * as nodePath from 'node:path'; +import { RockError } from './error.js'; +export function relativeToCwd(path) { + return nodePath.relative(process.cwd(), path); +} +export function resolveAbsolutePath(path) { + return nodePath.isAbsolute(path) ? path : nodePath.join(process.cwd(), path); +} +export function resolveFilenameUp(path, filename) { + const filePath = nodePath.join(path, filename); + if (fs.existsSync(filePath)) { + return filePath; + } + const parentDir = nodePath.dirname(path); + if (parentDir === path) { + throw new RockError(`${filename} not found in any parent directory of ${path}`); + } + return resolveFilenameUp(parentDir, filename); +} +export function findDirectoriesWithPattern(path, pattern) { + const files = fs.readdirSync(path); + const result = []; + for (const file of files) { + const filePath = nodePath.join(path, file); + const stat = fs.statSync(filePath); + if (stat.isDirectory()) { + if (file.match(pattern)) { + result.push(filePath); + } + result.push(...findDirectoriesWithPattern(filePath, pattern)); + } + } + return result; +} +//# sourceMappingURL=path.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/path.js.map b/packages/tools/dist/src/lib/path.js.map new file mode 100644 index 000000000..5ddfa6ba5 --- /dev/null +++ b/packages/tools/dist/src/lib/path.js.map @@ -0,0 +1 @@ +{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/lib/path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IAC9D,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CACjB,GAAG,QAAQ,yCAAyC,IAAI,EAAE,CAC3D,CAAC;IACJ,CAAC;IAED,OAAO,iBAAiB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAY,EAAE,OAAe;IACtE,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,0BAA0B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/project.d.ts b/packages/tools/dist/src/lib/project.d.ts new file mode 100644 index 000000000..58c575bf2 --- /dev/null +++ b/packages/tools/dist/src/lib/project.d.ts @@ -0,0 +1,9 @@ +export declare function getProjectConfig(dir?: string): string; +export declare function getProjectRoot(dir?: string): string; +export declare function getDotRockPath(): string; +/** + * Returns path to cache root. + * + * Cache is stored in: `.rock/cache` directory in the project root. + */ +export declare function getCacheRootPath(): string; diff --git a/packages/tools/dist/src/lib/project.js b/packages/tools/dist/src/lib/project.js new file mode 100644 index 000000000..dcffe7823 --- /dev/null +++ b/packages/tools/dist/src/lib/project.js @@ -0,0 +1,33 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +const PROJECT_CONFIG_BASE_NAME = 'rock.config'; +const PROJECT_CONFIG_FILE_EXTENSIONS = ['js', 'ts', 'mjs', 'mts', 'cjs', `cts`]; +export function getProjectConfig(dir = process.cwd()) { + for (const ext of PROJECT_CONFIG_FILE_EXTENSIONS) { + const configPath = path.join(dir, `${PROJECT_CONFIG_BASE_NAME}.${ext}`); + if (fs.existsSync(configPath)) { + return configPath; + } + } + const parentDir = path.dirname(dir); + if (parentDir === dir) { + throw new Error(`Project config not found`); + } + return getProjectConfig(parentDir); +} +export function getProjectRoot(dir) { + const configPath = getProjectConfig(dir); + return path.dirname(configPath); +} +export function getDotRockPath() { + return path.join(getProjectRoot(), '.rock'); +} +/** + * Returns path to cache root. + * + * Cache is stored in: `.rock/cache` directory in the project root. + */ +export function getCacheRootPath() { + return path.join(getProjectRoot(), '.rock/cache'); +} +//# sourceMappingURL=project.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/project.js.map b/packages/tools/dist/src/lib/project.js.map new file mode 100644 index 000000000..1caac5074 --- /dev/null +++ b/packages/tools/dist/src/lib/project.js.map @@ -0,0 +1 @@ +{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/lib/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAC/C,MAAM,8BAA8B,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEhF,MAAM,UAAU,gBAAgB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC1D,KAAK,MAAM,GAAG,IAAI,8BAA8B,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,wBAAwB,IAAI,GAAG,EAAE,CAAC,CAAC;QACxE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,aAAa,CAAC,CAAC;AACpD,CAAC"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/prompts.d.ts b/packages/tools/dist/src/lib/prompts.d.ts new file mode 100644 index 000000000..0a1848ebb --- /dev/null +++ b/packages/tools/dist/src/lib/prompts.d.ts @@ -0,0 +1,25 @@ +import * as clack from '@clack/prompts'; +export declare function intro(title?: string): void; +export declare function outro(message?: string): void; +export declare function note(message?: string, title?: string): void; +export declare function promptText(options: clack.TextOptions): Promise; +export declare function promptPassword(options: clack.PasswordOptions): Promise; +export declare function promptSelect(options: clack.SelectOptions): Promise; +type ConfirmOptions = { + message: string; + confirmLabel?: string; + cancelLabel?: string; +}; +export declare function promptConfirm(options: ConfirmOptions): Promise; +export declare function promptMultiselect(options: clack.MultiSelectOptions): Promise; +export declare function promptGroup(prompts: clack.PromptGroup, options?: clack.PromptGroupOptions | undefined): Promise<{ [P in keyof clack.PromptGroupAwaitedReturn]: clack.PromptGroupAwaitedReturn[P]; }>; +export declare function spinner(options?: clack.SpinnerOptions & { + silent?: boolean; +}): { + start: (message?: string) => void; + stop: (message?: string, code?: number) => void; + message: (message?: string) => void; +}; +export declare function formatStartMessage(text: string | undefined): string | undefined; +export declare function cancelPromptAndExit(message?: string): never; +export {}; diff --git a/packages/tools/dist/src/lib/prompts.js b/packages/tools/dist/src/lib/prompts.js new file mode 100644 index 000000000..0935a9aef --- /dev/null +++ b/packages/tools/dist/src/lib/prompts.js @@ -0,0 +1,106 @@ +import * as clack from '@clack/prompts'; +import { isInteractive } from './isInteractive.js'; +import logger from './logger.js'; +export function intro(title) { + return clack.intro(title); +} +export function outro(message) { + return clack.outro(message); +} +export function note(message, title) { + return clack.note(message, title); +} +export async function promptText(options) { + const result = await clack.text(options); + if (clack.isCancel(result)) { + cancelPromptAndExit(); + } + return result; +} +export async function promptPassword(options) { + const result = await clack.password(options); + if (clack.isCancel(result)) { + cancelPromptAndExit(); + } + return result; +} +export async function promptSelect(options) { + // If there is only one option, return it immediately + if (options.options.length === 1) { + return options.options[0].value; + } + const result = await clack.select(options); + if (clack.isCancel(result)) { + cancelPromptAndExit(); + } + return result; +} +export async function promptConfirm(options) { + const result = await clack.select({ + message: options.message, + options: [ + { value: true, label: options.confirmLabel ?? 'Confirm' }, + { value: false, label: options.cancelLabel ?? 'Cancel' }, + ], + }); + if (clack.isCancel(result)) { + cancelPromptAndExit(); + } + return result === true; +} +export async function promptMultiselect(options) { + const result = await clack.multiselect(options); + if (clack.isCancel(result)) { + cancelPromptAndExit(); + } + return result; +} +export async function promptGroup(prompts, options) { + const result = await clack.group(prompts, options); + if (clack.isCancel(result)) { + cancelPromptAndExit(); + } + return result; +} +export function spinner(options) { + if (options?.silent) { + return { + start: () => { }, + stop: () => { }, + message: () => { }, + }; + } + if (logger.isVerbose() || !isInteractive()) { + return { + start: (message) => logger.log(formatStartMessage(message)), + stop: (message, code = 0) => { + return code === 0 ? logger.log(message) : logger.error(message); + }, + message: (message) => logger.log(formatStartMessage(message)), + }; + } + const clackSpinner = clack.spinner(options); + return { + start: (message) => { + clackSpinner.start(message); + }, + stop: (message, code) => { + clackSpinner.stop(message, code); + }, + message: (message) => { + clackSpinner.message(message); + }, + }; +} +export function formatStartMessage(text) { + if (text === undefined) { + return undefined; + } + const messageWithoutDots = text.replace(/\.+$/, ''); + return `${messageWithoutDots}...`; +} +export function cancelPromptAndExit(message) { + clack.cancel(message ?? 'Operation cancelled by user.'); + process.exit(0); +} +//# sourceMappingURL=prompts.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/prompts.js.map b/packages/tools/dist/src/lib/prompts.js.map new file mode 100644 index 000000000..ac0b3288d --- /dev/null +++ b/packages/tools/dist/src/lib/prompts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/lib/prompts.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/tools/dist/src/lib/spawn.d.ts b/packages/tools/dist/src/lib/spawn.d.ts new file mode 100644 index 000000000..ded54b625 --- /dev/null +++ b/packages/tools/dist/src/lib/spawn.d.ts @@ -0,0 +1,4 @@ +import type { Options, Subprocess } from 'nano-spawn'; +import { SubprocessError } from 'nano-spawn'; +export declare function spawn(file: string, args?: readonly string[], options?: Options): Subprocess; +export { SubprocessError }; diff --git a/packages/tools/dist/src/lib/spawn.js b/packages/tools/dist/src/lib/spawn.js new file mode 100644 index 000000000..2bcca2e22 --- /dev/null +++ b/packages/tools/dist/src/lib/spawn.js @@ -0,0 +1,43 @@ +import nanoSpawn, { SubprocessError } from 'nano-spawn'; +import logger from './logger.js'; +export function spawn(file, args, options) { + const defaultStream = logger.isVerbose() ? 'inherit' : 'pipe'; + const defaultOptions = { + stdin: defaultStream, + stdout: defaultStream, + // Always 'pipe' stderr to handle errors properly down the line + stderr: 'pipe', + }; + logger.debug(`Running: ${file}`, ...(args ?? [])); + const childProcess = nanoSpawn(file, args, { ...defaultOptions, ...options }); + setupChildProcessCleanup(childProcess); + return childProcess; +} +export { SubprocessError }; +function setupChildProcessCleanup(childProcess) { + // https://stackoverflow.com/questions/53049939/node-daemon-wont-start-with-process-stdin-setrawmodetrue/53050098#53050098 + if (process.stdin.isTTY) { + // overwrite @clack/prompts setting raw mode for spinner and prompts, + // which prevents listening for SIGINT and SIGTERM + process.stdin.setRawMode(false); + } + const terminate = async () => { + try { + (await childProcess.nodeChildProcess).kill(); + process.exit(1); + } + catch { + // ignore + } + }; + const sigintHandler = () => terminate(); + const sigtermHandler = () => terminate(); + process.on('SIGINT', sigintHandler); + process.on('SIGTERM', sigtermHandler); + const cleanup = () => { + process.off('SIGINT', sigintHandler); + process.off('SIGTERM', sigtermHandler); + }; + childProcess.nodeChildProcess.finally(cleanup); +} +//# sourceMappingURL=spawn.js.map \ No newline at end of file diff --git a/packages/tools/dist/src/lib/spawn.js.map b/packages/tools/dist/src/lib/spawn.js.map new file mode 100644 index 000000000..bf7c2ba0f --- /dev/null +++ b/packages/tools/dist/src/lib/spawn.js.map @@ -0,0 +1 @@ +{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../src/lib/spawn.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,EAAE,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,UAAU,KAAK,CACnB,IAAY,EACZ,IAAwB,EACxB,OAAiB;IAEjB,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,cAAc,GAAY;QAC9B,KAAK,EAAE,aAAa;QACpB,MAAM,EAAE,aAAa;QACrB,+DAA+D;QAC/D,MAAM,EAAE,MAAM;KACf,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC9E,wBAAwB,CAAC,YAAY,CAAC,CAAC;IACvC,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,SAAS,wBAAwB,CAAC,YAAwB;IACxD,0HAA0H;IAC1H,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,qEAAqE;QACrE,kDAAkD;QAClD,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,IAAI,CAAC;YACH,CAAC,MAAM,YAAY,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;IACxC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;IAEzC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACzC,CAAC,CAAC;IAEF,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC"} \ No newline at end of file diff --git a/packages/welcome-screen/dist/src/assets/assets/book-open.png b/packages/welcome-screen/dist/src/assets/assets/book-open.png new file mode 100644 index 000000000..1fa4ea321 Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/assets/book-open.png differ diff --git a/packages/welcome-screen/dist/src/assets/assets/debug-check.png b/packages/welcome-screen/dist/src/assets/assets/debug-check.png new file mode 100644 index 000000000..fd9a6a010 Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/assets/debug-check.png differ diff --git a/packages/welcome-screen/dist/src/assets/assets/rock.png b/packages/welcome-screen/dist/src/assets/assets/rock.png new file mode 100644 index 000000000..c313dc5e2 Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/assets/rock.png differ diff --git a/packages/welcome-screen/dist/src/assets/assets/zap.png b/packages/welcome-screen/dist/src/assets/assets/zap.png new file mode 100644 index 000000000..da1757c8d Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/assets/zap.png differ diff --git a/packages/welcome-screen/dist/src/assets/book-open.png b/packages/welcome-screen/dist/src/assets/book-open.png new file mode 100644 index 000000000..1fa4ea321 Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/book-open.png differ diff --git a/packages/welcome-screen/dist/src/assets/debug-check.png b/packages/welcome-screen/dist/src/assets/debug-check.png new file mode 100644 index 000000000..fd9a6a010 Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/debug-check.png differ diff --git a/packages/welcome-screen/dist/src/assets/rock.png b/packages/welcome-screen/dist/src/assets/rock.png new file mode 100644 index 000000000..c313dc5e2 Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/rock.png differ diff --git a/packages/welcome-screen/dist/src/assets/zap.png b/packages/welcome-screen/dist/src/assets/zap.png new file mode 100644 index 000000000..da1757c8d Binary files /dev/null and b/packages/welcome-screen/dist/src/assets/zap.png differ diff --git a/packages/welcome-screen/dist/src/index.d.ts b/packages/welcome-screen/dist/src/index.d.ts new file mode 100644 index 000000000..50d61f7e1 --- /dev/null +++ b/packages/welcome-screen/dist/src/index.d.ts @@ -0,0 +1,3 @@ +import React from 'react'; +declare function WelcomeScreen(): React.JSX.Element; +export default WelcomeScreen; diff --git a/packages/welcome-screen/dist/src/index.jsx b/packages/welcome-screen/dist/src/index.jsx new file mode 100644 index 000000000..853649c32 --- /dev/null +++ b/packages/welcome-screen/dist/src/index.jsx @@ -0,0 +1,170 @@ +import React from 'react'; +import { Animated, Image, Platform, Pressable, StyleSheet, Text, useColorScheme, View, } from 'react-native'; +// @ts-expect-error deep import without declaration +import openURLInBrowser from 'react-native/Libraries/Core/Devtools/openURLInBrowser'; +const ICONS = { + // eslint-disable-next-line @typescript-eslint/no-require-imports + book: require('./assets/book-open.png'), + // eslint-disable-next-line @typescript-eslint/no-require-imports + logo: require('./assets/rock.png'), + // eslint-disable-next-line @typescript-eslint/no-require-imports + debug: require('./assets/debug-check.png'), + // eslint-disable-next-line @typescript-eslint/no-require-imports + zap: require('./assets/zap.png'), +}; +function Card({ dark, icon, title, description, }) { + return ( + + + + + + {title} + + {description} + + ); +} +function WelcomeScreen() { + const isDarkMode = useColorScheme() === 'dark'; + const bgColor = isDarkMode ? '#000' : '#fff'; + const textColor = isDarkMode ? '#fff' : '#000'; + const scaleValue = React.useRef(new Animated.Value(1)).current; + const animatedStyle = { transform: [{ scale: scaleValue }] }; + const onPressIn = () => { + Animated.spring(scaleValue, { + toValue: 0.95, + useNativeDriver: true, + speed: 20, + bounciness: 5, + }).start(); + }; + const onPressOut = () => { + Animated.spring(scaleValue, { + toValue: 1, + useNativeDriver: true, + speed: 20, + bounciness: 5, + }).start(); + }; + const onPress = () => { + openURLInBrowser('https://rockjs.dev'); + }; + return ( + + + + + + Welcome to Rock! + + + + + + + + + + + + + View Documentation + + + + + ); +} +const styles = StyleSheet.create({ + container: { + flex: 2, + }, + header: { + flex: 1, + justifyContent: 'flex-end', + alignItems: 'center', + padding: 24, + }, + logoContainer: { + width: 80, + height: 80, + marginBottom: 20, + justifyContent: 'center', + alignItems: 'center', + }, + logo: { + width: 48, + height: 48, + }, + title: { + fontSize: 36, + fontWeight: 'bold', + textAlign: 'center', + color: '#000', + }, + content: { + flex: 1.2, + justifyContent: 'flex-start', + marginHorizontal: 16, + }, + featureList: { + flex: 1, + flexShrink: 1, + }, + footer: { + flex: 1, + justifyContent: 'flex-end', + }, + buttonContainer: { + marginBottom: 60, + borderRadius: 12, + overflow: 'hidden', + }, + button: { + backgroundColor: 'rgb(120,55,245)', + borderRadius: 12, + padding: 16, + alignItems: 'center', + }, + buttonText: { + color: '#fff', + fontSize: 16, + fontWeight: '600', + }, + featureCard: { + flexDirection: 'row', + alignItems: 'center', + padding: 12, + }, + featureIconContainer: { + width: 40, + height: 40, + borderRadius: 12, + marginRight: 24, + justifyContent: 'center', + alignItems: 'center', + }, + featureIcon: { + width: 30, + height: 30, + }, + featureContent: { + flex: 1, + flexShrink: 1, + }, + featureTitle: { + fontSize: 16, + fontWeight: '600', + marginBottom: 4, + }, + featureDescription: { + fontSize: 14, + color: '#666', + }, +}); +export default WelcomeScreen; +//# sourceMappingURL=index.jsx.map \ No newline at end of file diff --git a/packages/welcome-screen/dist/src/index.jsx.map b/packages/welcome-screen/dist/src/index.jsx.map new file mode 100644 index 000000000..9b6107e2b --- /dev/null +++ b/packages/welcome-screen/dist/src/index.jsx.map @@ -0,0 +1 @@ +{"version":3,"file":"index.jsx","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 460dae45a..b178612e1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,6 +87,9 @@ importers: commander: specifier: ^12.1.0 version: 12.1.0 + node-apk: + specifier: ^1.2.1 + version: 1.2.1 tar: specifier: ^7.5.1 version: 7.5.1 @@ -4938,6 +4941,9 @@ packages: resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==} engines: {node: '>=12.0.0'} + node-apk@1.2.1: + resolution: {integrity: sha512-I0TY1x5m1pkFzjYdaGrrAu/Mh9qnnk2/BoMAU6bvBxTTD/oNQyTWbu3LTdONgV2rnLHf23jJ00Y/VV4BzZ6YXQ==} + node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -12700,6 +12706,10 @@ snapshots: nocache@3.0.4: {} + node-apk@1.2.1: + dependencies: + node-forge: 1.3.1 + node-fetch@2.6.7: dependencies: whatwg-url: 5.0.0