Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publishing to NPM repository is incompatible with new VSCE #90

Open
joelspadin-garmin opened this issue Nov 4, 2024 · 1 comment
Open
Labels
bug Something isn't working documentation Improvements or additions to documentation

Comments

@joelspadin-garmin
Copy link
Owner

Current versions of VSCE interpret the files property in package.json as a list of files which should be included in the VSIX itself, overriding the default rules for what to include. This is incompatible with using that same property to select which files get included in the private extension package that is published to an NPM repository, since for that we want to only include the .vsix file.

One possible workaround to this is as follows:

  1. Remove "files": [...] from package.json
  2. Add "private": true to package.json to make sure it can't accidentally be published
  3. Create a separate directory with its own package.json which will be used to publish the package to the NPM repository. The publish package.json should be identical to the original except:
    • Add back in the files field that was removed from the main package.json.
    • Remove the private field to allow it to be published.
    • Fields such as scripts, dependencies, and devDependencies can optionally be removed.
  4. Copy the .vsix file and any resources such as README, LICENSE, and CHANGELOG files to the publish directory.
  5. Publish the NPM package from the publish directory.

Here is a script that could be used as a starting point for automating this:

prepublish.mjs

/**
 * The VSCE tool uses package.json's "files" field to determine which files to
 * include in the .vsix package, but we want to use that to control which files
 * get included in the npm package instead.
 *
 * This script copies the files to publish into a "publish" directory and
 * creates a new package.json there with the "files" field set.
 */

// @ts-check

import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import * as process from 'node:process';
import { parseArgs } from 'node:util';

const RESOURCES = [
    'CHANGELOG.md',
    'README.md',
    'LICENSE',
];

/**
 * @param {string} packagePath Path to the directory containing the package.json.
 * @param {string} publishPath Path to the directory to publish to.
 * @returns {Promise<string[]>} List of copied files.
 */
async function copyResources(packagePath, publishPath) {
    const resources = [];

    for (const resource of RESOURCES) {
        try {
            await fs.copyFile(path.join(packagePath, resource), path.join(publishPath, resource));
            resources.push(resource);
        } catch (err) {
            if (err.code !== 'ENOENT') {
                throw err;
            }
        }
    }

    return resources;
}

/**
 * @param {string} packagePath Path to the directory containing the package.json.
 */
async function preparePublishPackage(packagePath) {
    const publishPath = path.join(packagePath, 'publish');

    await fs.rm(publishPath, { recursive: true, force: true });
    await fs.mkdir(publishPath);
    const files = await copyResources(packagePath, publishPath);

    const packageJson = JSON.parse(await fs.readFile(path.join(packagePath, 'package.json'), 'utf8'));

    delete packageJson['dependencies'];
    delete packageJson['devDependencies'];
    delete packageJson['private'];
    delete packageJson['scripts'];
    
    packageJson['files'] = ['extension.vsix', ...files];

    await fs.writeFile(path.join(publishPath, 'package.json'), JSON.stringify(packageJson, null, 2));
}

const { values, positionals } = parseArgs({
    allowPositionals: true,
    options: {
        help: { type: 'boolean', alias: 'h' },
    },
});

if (values.help || positionals.length > 1) {
    console.log('Usage: node prepublish.mjs [path]');
    console.log();
    console.log('Creates a "publish" directory with the files to publish an extension.');
    console.log('After running this, package the extension with "vsce package -o publish/extension.vsix",');
    console.log('then move to the "publish" directory before running "npm publish".');

    process.exit(0);
}

await preparePublishPackage(positionals[0] ?? process.cwd());
@joelspadin-garmin joelspadin-garmin added bug Something isn't working documentation Improvements or additions to documentation labels Nov 4, 2024
@joelspadin-garmin joelspadin-garmin pinned this issue Nov 4, 2024
@joelspadin-garmin joelspadin-garmin changed the title Publishing to NPM repository is incompatible with new versions of VSCE Publishing to NPM repository is incompatible with new VSCE Nov 4, 2024
@Stephanevg
Copy link

Stephanevg commented Nov 13, 2024

Hi, I believe I am facing this exact issue. I'll try your fixes and give feedback

edit: Indeed this process fixed the issue I had (I dind't use your script tho)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants