HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/self/root/usr/local/lib/node_modules/@ionic/cli/commands/monitoring/syncmaps.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MonitoringSyncSourcemapsCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_terminal_1 = require("@ionic/utils-terminal");
const debug_1 = require("debug");
const path = tslib_1.__importStar(require("path"));
const guards_1 = require("../../guards");
const color_1 = require("../../lib/color");
const command_1 = require("../../lib/command");
const errors_1 = require("../../lib/errors");
const debug = (0, debug_1.debug)('ionic:commands:monitoring:syncmaps');
const SOURCEMAP_DIRECTORY = '.sourcemaps';
class MonitoringSyncSourcemapsCommand extends command_1.Command {
    async getMetadata() {
        return {
            name: 'syncmaps',
            type: 'project',
            summary: 'Build & upload sourcemaps to Ionic Appflow Monitoring service',
            description: `
By default, ${(0, color_1.input)('ionic monitoring syncmaps')} will upload the sourcemap files within ${(0, color_1.strong)(SOURCEMAP_DIRECTORY)}. To optionally perform a production build before uploading sourcemaps, specify the ${(0, color_1.input)('--build')} flag.
      `,
            inputs: [
                {
                    name: 'snapshot_id',
                    summary: `Specify a Snapshot ID to associate the uploaded sourcemaps with`,
                },
            ],
            options: [
                {
                    name: 'build',
                    summary: 'Invoke a production Ionic build',
                    type: Boolean,
                },
            ],
        };
    }
    async run(inputs, options) {
        const { loadCordovaConfig } = await Promise.resolve().then(() => tslib_1.__importStar(require('../../lib/integrations/cordova/config')));
        if (!this.project) {
            throw new errors_1.FatalException(`Cannot run ${(0, color_1.input)('ionic monitoring syncmaps')} outside a project directory.`);
        }
        const token = await this.env.session.getUserToken();
        const appflowId = await this.project.requireAppflowId();
        const [snapshotId] = inputs;
        const doBuild = options.build ? true : false;
        const cordova = this.project.requireIntegration('cordova');
        const conf = await loadCordovaConfig(cordova);
        const cordovaInfo = conf.getProjectInfo();
        const appVersion = cordovaInfo.version;
        const commitHash = (await this.env.shell.output('git', ['rev-parse', 'HEAD'], { cwd: this.project.directory })).trim();
        debug(`Commit hash: ${(0, color_1.strong)(commitHash)}`);
        const sourcemapsDir = path.resolve(this.project.directory, SOURCEMAP_DIRECTORY);
        let sourcemapsExist = await (0, utils_fs_1.pathExists)(sourcemapsDir);
        if (doBuild || !sourcemapsExist) {
            const runner = await this.project.requireBuildRunner();
            const runnerOpts = runner.createOptionsFromCommandLine([], { _: [], prod: true });
            await runner.run(runnerOpts);
        }
        sourcemapsExist = await (0, utils_fs_1.pathExists)(sourcemapsDir);
        if (sourcemapsExist) {
            this.env.log.msg(`Using existing sourcemaps in ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(sourcemapsDir))}`);
        }
        else { // TODO: this is hard-coded for ionic-angular, make it work for all project types
            throw new errors_1.FatalException(`Cannot find directory: ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(sourcemapsDir))}.\n` +
                `Make sure you have the latest ${(0, color_1.strong)('@ionic/app-scripts')}. Then, re-run this command.`);
        }
        let count = 0;
        const tasks = this.createTaskChain();
        const syncTask = tasks.next('Syncing sourcemaps');
        const sourcemapFiles = (await (0, utils_fs_1.readdirSafe)(sourcemapsDir)).filter(f => f.endsWith('.js.map'));
        debug(`Found ${sourcemapFiles.length} sourcemap files: ${sourcemapFiles.map(f => (0, color_1.strong)(f)).join(', ')}`);
        await Promise.all(sourcemapFiles.map(async (f) => {
            await this.syncSourcemap(path.resolve(sourcemapsDir, f), snapshotId, appVersion, commitHash, appflowId, token);
            count += 1;
            syncTask.msg = `Syncing sourcemaps: ${(0, color_1.strong)(`${count} / ${sourcemapFiles.length}`)}`;
        }));
        syncTask.msg = `Syncing sourcemaps: ${(0, color_1.strong)(`${sourcemapFiles.length} / ${sourcemapFiles.length}`)}`;
        tasks.end();
        const details = (0, utils_terminal_1.columnar)([
            ['App ID', (0, color_1.strong)(appflowId)],
            ['Version', (0, color_1.strong)(appVersion)],
            ['Package ID', (0, color_1.strong)(cordovaInfo.id)],
            ['Snapshot ID', snapshotId ? (0, color_1.strong)(snapshotId) : (0, color_1.weak)('not set')],
        ], { vsep: ':' });
        this.env.log.ok(`Sourcemaps synced!\n` +
            details + '\n\n' +
            `See the Error Monitoring docs for usage information and next steps: ${(0, color_1.strong)('https://ionicframework.com/docs/appflow/monitoring')}`);
    }
    async syncSourcemap(file, snapshotId, appVersion, commitHash, appflowId, token) {
        const { req } = await this.env.client.make('POST', `/monitoring/${appflowId}/sourcemaps`);
        req
            .set('Authorization', `Bearer ${token}`)
            .send({
            name: path.basename(file),
            version: appVersion,
            commit: commitHash,
            snapshot_id: snapshotId,
        });
        try {
            const res = await this.env.client.do(req);
            return this.uploadSourcemap(res, file);
        }
        catch (e) {
            if ((0, guards_1.isSuperAgentError)(e)) {
                this.env.log.error(`Unable to sync map ${file}: ` + e.message);
                if (e.response.status === 401) {
                    this.env.log.error('Try logging out and back in again.');
                }
            }
            else {
                throw e;
            }
        }
    }
    async uploadSourcemap(sourcemap, file) {
        const { createRequest } = await Promise.resolve().then(() => tslib_1.__importStar(require('../../lib/utils/http')));
        const sm = sourcemap;
        const fileData = await (0, utils_fs_1.readFile)(file, { encoding: 'utf8' });
        const sourcemapPost = sm.data.sourcemap_post;
        const { req } = await createRequest('POST', sourcemapPost.url, this.env.config.getHTTPConfig());
        req
            .field(sourcemapPost.fields)
            .field('file', fileData);
        const res = await req;
        if (res.status !== 204) {
            throw new errors_1.FatalException(`Unexpected status code from AWS: ${res.status}`);
        }
    }
}
exports.MonitoringSyncSourcemapsCommand = MonitoringSyncSourcemapsCommand;