Skip to content
This repository has been archived by the owner on Jul 19, 2021. It is now read-only.

ARM64 (Apple M1) support #1107

Open
isAdrisal opened this issue Jan 31, 2021 · 6 comments
Open

ARM64 (Apple M1) support #1107

isAdrisal opened this issue Jan 31, 2021 · 6 comments

Comments

@isAdrisal
Copy link

There is discussion here regarding a crash when trying to install/run Slate on M1 Macs due to the dependency on @shopify/themekit v0.6 in slate-tools and slate-sync.

In a test Slate project, adding a resolution to the latest themekit version in package.json appears to be a viable workaround for this issue.

Specifically, adding the following to the project's package.json:

"resolutions": {
  "**/@shopify/themekit": "^1.1.7"
},

Creating this issue for reference if it helps someone else, but also looking for feedback if there are better approaches.

@ingueferroque
Copy link

ingueferroque commented Feb 17, 2021

Thanks for sharing - could you possibly share an entire package.json? This solution doesn't seem to be working for me.
When I publish changes on my M1 it tells me 'Transfer Complete: File changes successfully synced to store' but no changes were made to the theme.

What steps did you take to install Slate on a M1 Mac?

@gui-gui
Copy link

gui-gui commented Feb 25, 2021

@ingueferroque I got the exact same error as you. After some digging around, i found out that themekit api changed when compared to v0.6.x. I got the above solution to work after I made changes to @shopify/slate-sync. This is only a POC and i did the changes to the node_module itself for now...

The changes basically affect how you send the configs to themekit. Here is what my node_modules/@shopify/slate-sync/index.js looks like (The changes were based on this PR):

const chalk = require('chalk');
const figures = require('figures');
const https = require('https');
const themekit = require('@shopify/themekit');
const slateEnv = require('@shopify/slate-env');
const SlateConfig = require('@shopify/slate-config');

const config = new SlateConfig(require('./slate-sync.schema'));

let deploying = false;
let filesToDeploy = [];

function maybeDeploy() {
  if (deploying) {
    return Promise.reject(new Error('Deploy already in progress.'));
  }

  if (filesToDeploy.length) {
    const files = [...filesToDeploy];
    filesToDeploy = [];
    return deploy('upload', files);
  }

  return Promise.resolve();
}

function _validateEnvValues() {
  const result = slateEnv.validate();

  if (!result.isValid) {
    console.log(
      chalk.red(
        `Some values in environment '${slateEnv.getEnvNameValue()}' are invalid:`,
      ),
    );
    result.errors.forEach((error) => {
      console.log(chalk.red(`- ${error}`));
    });

    process.exit(1);
  }
}

function _generateConfigFlags(cmd) {
  _validateEnvValues();

  const flags = {
    password: slateEnv.getPasswordValue(),
    themeid: slateEnv.getThemeIdValue(),
    store: slateEnv.getStoreValue(),
    env: slateEnv.getEnvNameValue(),
  };
  
  if (cmd === 'upload') {
    flags.nodelete = true;
  }

  if (slateEnv.getTimeoutValue()) {
    flags.timeout = slateEnv.getTimeoutValue();
  }
  if (slateEnv.getIgnoreFilesValue()) {
    flags.ignoredFiles = slateEnv.getIgnoreFilesValue().split(':');
  }

  // Convert object to key value pairs and flatten the array
  return flags;
}

/**
 * Deploy to Shopify using themekit.
 *
 * @param   cmd     String    The command to run
 * @param   files   Array     An array of files to deploy
 * @return          Promise
 */
async function deploy(cmd = '', files = []) {
  if (!['upload', 'replace'].includes(cmd)) {
    throw new Error(
      'shopify-deploy.deploy() first argument must be either "upload", "replace"',
    );
  }

  deploying = true;

  console.log(chalk.magenta(`\n${figures.arrowUp}  Uploading to Shopify...\n`));

  try {
    await themekit.command('configure', _generateConfigFlags(), {
      cwd: config.get('paths.theme.dist'),
    });
    await themekit.command(
      'deploy',
      {
        ..._generateConfigFlags(cmd),
        files,
      },
      {
        cwd: config.get('paths.theme.dist'),
      },
    );
  } catch (error) {
    console.error('My Error', error);
  }

  deploying = false;

  return maybeDeploy;
}

/**
 * Fetch the main theme ID from Shopify
 *
 * @param   env   String  The environment to check against
 * @return        Promise Reason for abort or the main theme ID
 */
function fetchMainThemeId() {
  _validateEnvValues();

  return new Promise((resolve, reject) => {
    https.get(
      {
        hostname: slateEnv.getStoreValue(),
        path: '/admin/themes.json',
        auth: `:${slateEnv.getPasswordValue}`,
        agent: false,
        headers: {
          'X-Shopify-Access-Token': slateEnv.getPasswordValue(),
        },
      },
      (res) => {
        let body = '';

        res.on('data', (datum) => (body += datum));

        res.on('end', () => {
          const parsed = JSON.parse(body);

          if (parsed.errors) {
            reject(
              new Error(
                `API request to fetch main theme ID failed: \n${JSON.stringify(
                  parsed.errors,
                  null,
                  '\t',
                )}`,
              ),
            );
            return;
          }

          if (!Array.isArray(parsed.themes)) {
            reject(
              new Error(
                `Shopify response for /admin/themes.json is not an array. ${JSON.stringify(
                  parsed,
                  null,
                  '\t',
                )}`,
              ),
            );
            return;
          }

          const mainTheme = parsed.themes.find((t) => t.role === 'main');

          if (!mainTheme) {
            reject(
              new Error(
                `No main theme in response. ${JSON.stringify(
                  parsed.themes,
                  null,
                  '\t',
                )}`,
              ),
            );
            return;
          }

          resolve(mainTheme.id);
        });
      },
    );
  });
}

module.exports = {
  sync(files = []) {
    if (!files.length) {
      return Promise.reject(new Error('No files to deploy.'));
    }

    filesToDeploy = [...new Set([...filesToDeploy, ...files])];

    return maybeDeploy();
  },

  replace() {
    return deploy('replace');
  },

  upload() {
    return deploy('upload');
  },

  fetchMainThemeId,
};

PS. we use a forked version of @shopify/slate-tools though, so i haven't tested it against the non-forked slate-tools

@1aurabrown
Copy link

Hey @gui-gui, Could you link to the forked slate-tools repo? I have a couple of slate projects lingering around, and I ran into this issue after upgrading my computer too. It's quite a pain to have to pull out my old laptop to work on those projects. I'll try this fix next time I work on one.

@1aurabrown
Copy link

Hey @gui-gui, Could you link to the forked slate-tools repo? I have a couple of slate projects lingering around, and I ran into this issue after upgrading my computer too. It's quite a pain to have to pull out my old laptop to work on those projects. I'll try this fix next time I work on one.

And just to clarify... did the above solution actually solve the problem and allow you run slate projects successfully on your m1 mac?

@gui-gui
Copy link

gui-gui commented Mar 15, 2021

@1aurabrown, yes, this fix actually got it to work with my m1 mac. Unfortunately we have a private forked version that has diverged from slate tools a bit already so i do not have a link to a forked version available, i will try to get one up this week when i get some free time

@kgea
Copy link

kgea commented Jul 19, 2021

@gui-gui & @isAdrisal
Thanks for this fix! Though I have to use v1.1.9 instead of v1.1.8
@gui-gui - Before I updated the slate-sync file and just added the resolution fix. I kept getting unknown command "[object Object]" for "theme" when running yarn start. So I replaced the slate-sync/index.js file with your updates and not only did yarn start work but also uploaded to shopify which it did not do before any updates.

Cheers to you my friends.🍻

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants