mirror of
				https://github.com/actions/setup-node.git
				synced 2025-11-04 03:08:21 +08:00 
			
		
		
		
	Add node's caching implementation (#2)
* first iteration for implementation of caching * add logs * add debug line * fix build command * fix path * add possible post-if * remove braces * test new action post-if variant * work on built-in caching * remove post-if * pass version * work on yarn support * fix return value * change names and remove logs * worked on resolving comments * check post-if for null * add success() condition * remove primary key field * work on resolving comments * remove logs * resolving comments * resolving comments * resolving comments * resolving comments * fix getpackageManagerVersion * run clean for unstaged changes * fix falling version tests * work on resolving comments * resolving comments * fix comment * resolve comments * Add tests to cover node's caching (#3) * add tests to cover node's caching * work on fixing tests * fix e2e tests * rebuild and fix test * fixing tests * change name of describes, it and fix test * add names for jobs * fix issue
This commit is contained in:
		
							
								
								
									
										1
									
								
								.github/workflows/build-test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/build-test.yml
									
									
									
									
										vendored
									
									
								
							@@ -27,6 +27,7 @@ jobs:
 | 
			
		||||
      - run: npm run build
 | 
			
		||||
      - run: npm run format-check
 | 
			
		||||
      - run: npm test
 | 
			
		||||
      - run: git add .
 | 
			
		||||
      - name: Verify no unstaged changes
 | 
			
		||||
        if: runner.os != 'windows'
 | 
			
		||||
        run: __tests__/verify-no-unstaged-changes.sh
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										101
									
								
								.github/workflows/e2e-cache.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								.github/workflows/e2e-cache.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
name: e2e-cache
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    paths-ignore:
 | 
			
		||||
      - '**.md'    
 | 
			
		||||
  push:    
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
      - releases/*
 | 
			
		||||
    paths-ignore:
 | 
			
		||||
      - '**.md'
 | 
			
		||||
      
 | 
			
		||||
jobs:
 | 
			
		||||
  node-npm-depencies-caching:
 | 
			
		||||
    name: Test npm (Node ${{ matrix.node-version}}, ${{ matrix.os }})
 | 
			
		||||
    runs-on: ${{ matrix.os }}
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        os: [ubuntu-latest, windows-latest, macos-latest]
 | 
			
		||||
        node-version: [10, 12, 14]
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
      - name: Clean global cache
 | 
			
		||||
        run: npm cache clean --force
 | 
			
		||||
      - name: Setup Node
 | 
			
		||||
        uses: ./
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: ${{ matrix.node-version }}
 | 
			
		||||
          cache: 'npm'
 | 
			
		||||
      - name: Install dependencies
 | 
			
		||||
        run: npm install
 | 
			
		||||
      - name: Verify node and npm
 | 
			
		||||
        run: __tests__/verify-node.sh "${{ matrix.node-version }}"
 | 
			
		||||
        shell: bash
 | 
			
		||||
 | 
			
		||||
  node-yarn1-depencies-caching:
 | 
			
		||||
    name: Test yarn 1 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
 | 
			
		||||
    runs-on: ${{ matrix.os }}
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        os: [ubuntu-latest, windows-latest, macos-latest]
 | 
			
		||||
        node-version: [10, 12, 14]
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
      - name: Yarn version
 | 
			
		||||
        run: yarn --version
 | 
			
		||||
      - name: Generate yarn file
 | 
			
		||||
        run: yarn install
 | 
			
		||||
      - name: Remove dependencies
 | 
			
		||||
        shell: pwsh
 | 
			
		||||
        run: Remove-Item node_modules -Force -Recurse
 | 
			
		||||
      - name: Clean global cache
 | 
			
		||||
        run: yarn cache clean
 | 
			
		||||
      - name: Setup Node
 | 
			
		||||
        uses: ./
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: ${{ matrix.node-version }}
 | 
			
		||||
          cache: 'yarn'
 | 
			
		||||
      - name: Install dependencies
 | 
			
		||||
        run: yarn install
 | 
			
		||||
      - name: Verify node and yarn
 | 
			
		||||
        run: __tests__/verify-node.sh "${{ matrix.node-version }}"
 | 
			
		||||
        shell: bash
 | 
			
		||||
 | 
			
		||||
  node-yarn2-depencies-caching:
 | 
			
		||||
    name: Test yarn 2 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
 | 
			
		||||
    runs-on: ${{ matrix.os }}
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        os: [ubuntu-latest, windows-latest, macos-latest]
 | 
			
		||||
        node-version: [10, 12, 14]
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
      - name: Update yarn
 | 
			
		||||
        run: yarn set version berry
 | 
			
		||||
      - name: Yarn version
 | 
			
		||||
        run: yarn --version
 | 
			
		||||
      - name: Generate simple .yarnrc.yml
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "nodeLinker: node-modules" >> .yarnrc.yml
 | 
			
		||||
      - name: Generate yarn file
 | 
			
		||||
        run: yarn install
 | 
			
		||||
      - name: Remove dependencies
 | 
			
		||||
        shell: pwsh
 | 
			
		||||
        run: Remove-Item node_modules -Force -Recurse
 | 
			
		||||
      - name: Clean global cache
 | 
			
		||||
        run: yarn cache clean --all
 | 
			
		||||
      - name: Setup Node
 | 
			
		||||
        uses: ./
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: ${{ matrix.node-version }}
 | 
			
		||||
          cache: 'yarn'
 | 
			
		||||
      - name: Install dependencies
 | 
			
		||||
        run: yarn install
 | 
			
		||||
      - name: Verify node and yarn
 | 
			
		||||
        run: __tests__/verify-node.sh "${{ matrix.node-version }}"
 | 
			
		||||
        shell: bash
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							@@ -109,4 +109,4 @@ jobs:
 | 
			
		||||
          architecture: 'x86'
 | 
			
		||||
      - name: Verify node
 | 
			
		||||
        run: __tests__/verify-arch.sh "ia32"
 | 
			
		||||
        shell: bash
 | 
			
		||||
        shell: bash
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										168
									
								
								__tests__/cache-restore.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								__tests__/cache-restore.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import * as cache from '@actions/cache';
 | 
			
		||||
import * as path from 'path';
 | 
			
		||||
import * as glob from '@actions/glob';
 | 
			
		||||
 | 
			
		||||
import * as utils from '../src/cache-utils';
 | 
			
		||||
import {restoreCache} from '../src/cache-restore';
 | 
			
		||||
 | 
			
		||||
describe('cache-restore', () => {
 | 
			
		||||
  process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
 | 
			
		||||
  if (!process.env.RUNNER_OS) {
 | 
			
		||||
    process.env.RUNNER_OS = 'Linux';
 | 
			
		||||
  }
 | 
			
		||||
  const platform = process.env.RUNNER_OS;
 | 
			
		||||
  const commonPath = '/some/random/path';
 | 
			
		||||
  const npmCachePath = `${commonPath}/npm`;
 | 
			
		||||
  const yarn1CachePath = `${commonPath}/yarn1`;
 | 
			
		||||
  const yarn2CachePath = `${commonPath}/yarn2`;
 | 
			
		||||
  const yarnFileHash =
 | 
			
		||||
    'b8a0bae5243251f7c07dd52d1f78ff78281dfefaded700a176261b6b54fa245b';
 | 
			
		||||
  const npmFileHash =
 | 
			
		||||
    'abf7c9b306a3149dcfba4673e2362755503bcceaab46f0e4e6fee0ade493e20c';
 | 
			
		||||
  const cachesObject = {
 | 
			
		||||
    [npmCachePath]: npmFileHash,
 | 
			
		||||
    [yarn1CachePath]: yarnFileHash,
 | 
			
		||||
    [yarn2CachePath]: yarnFileHash
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  function findCacheFolder(command: string) {
 | 
			
		||||
    switch (command) {
 | 
			
		||||
      case utils.supportedPackageManagers.npm.getCacheFolderCommand:
 | 
			
		||||
        return npmCachePath;
 | 
			
		||||
      case utils.supportedPackageManagers.yarn1.getCacheFolderCommand:
 | 
			
		||||
        return yarn1CachePath;
 | 
			
		||||
      case utils.supportedPackageManagers.yarn2.getCacheFolderCommand:
 | 
			
		||||
        return yarn2CachePath;
 | 
			
		||||
      default:
 | 
			
		||||
        return 'packge/not/found';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let saveStateSpy: jest.SpyInstance;
 | 
			
		||||
  let infoSpy: jest.SpyInstance;
 | 
			
		||||
  let debugSpy: jest.SpyInstance;
 | 
			
		||||
  let setOutputSpy: jest.SpyInstance;
 | 
			
		||||
  let getCommandOutputSpy: jest.SpyInstance;
 | 
			
		||||
  let restoreCacheSpy: jest.SpyInstance;
 | 
			
		||||
  let hashFilesSpy: jest.SpyInstance;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    // core
 | 
			
		||||
    infoSpy = jest.spyOn(core, 'info');
 | 
			
		||||
    infoSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    debugSpy = jest.spyOn(core, 'debug');
 | 
			
		||||
    debugSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    setOutputSpy = jest.spyOn(core, 'setOutput');
 | 
			
		||||
    setOutputSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    saveStateSpy = jest.spyOn(core, 'saveState');
 | 
			
		||||
    saveStateSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    // glob
 | 
			
		||||
    hashFilesSpy = jest.spyOn(glob, 'hashFiles');
 | 
			
		||||
    hashFilesSpy.mockImplementation((pattern: string) => {
 | 
			
		||||
      if (pattern.includes('package-lock.json')) {
 | 
			
		||||
        return npmFileHash;
 | 
			
		||||
      } else if (pattern.includes('yarn.lock')) {
 | 
			
		||||
        return yarnFileHash;
 | 
			
		||||
      } else {
 | 
			
		||||
        return '';
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // cache
 | 
			
		||||
    restoreCacheSpy = jest.spyOn(cache, 'restoreCache');
 | 
			
		||||
    restoreCacheSpy.mockImplementation(
 | 
			
		||||
      (cachePaths: Array<string>, key: string) => {
 | 
			
		||||
        if (!cachePaths || cachePaths.length === 0) {
 | 
			
		||||
          return undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const cachPath = cachePaths[0];
 | 
			
		||||
        const fileHash = cachesObject[cachPath];
 | 
			
		||||
 | 
			
		||||
        if (key.includes(fileHash)) {
 | 
			
		||||
          return key;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return undefined;
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // cache-utils
 | 
			
		||||
    getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Validate provided package manager', () => {
 | 
			
		||||
    it.each([['npm7'], ['npm6'], ['yarn1'], ['yarn2'], ['random']])(
 | 
			
		||||
      'Throw an error because %s is not supported',
 | 
			
		||||
      async packageManager => {
 | 
			
		||||
        await expect(restoreCache(packageManager)).rejects.toThrowError(
 | 
			
		||||
          `Caching for '${packageManager}' is not supported`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Restore dependencies', () => {
 | 
			
		||||
    it.each([
 | 
			
		||||
      ['yarn', '2.1.2', yarnFileHash],
 | 
			
		||||
      ['yarn', '1.2.3', yarnFileHash],
 | 
			
		||||
      ['npm', '', npmFileHash]
 | 
			
		||||
    ])(
 | 
			
		||||
      'restored dependencies for %s',
 | 
			
		||||
      async (packageManager, toolVersion, fileHash) => {
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) => {
 | 
			
		||||
          if (command.includes('version')) {
 | 
			
		||||
            return toolVersion;
 | 
			
		||||
          } else {
 | 
			
		||||
            return findCacheFolder(command);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await restoreCache(packageManager);
 | 
			
		||||
        expect(hashFilesSpy).toHaveBeenCalled();
 | 
			
		||||
        expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Cache restored from key: ${platform}-${packageManager}-${fileHash}`
 | 
			
		||||
        );
 | 
			
		||||
        expect(infoSpy).not.toHaveBeenCalledWith(
 | 
			
		||||
          `${packageManager} cache is not found`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Dependencies changed', () => {
 | 
			
		||||
    it.each([
 | 
			
		||||
      ['yarn', '2.1.2', yarnFileHash],
 | 
			
		||||
      ['yarn', '1.2.3', yarnFileHash],
 | 
			
		||||
      ['npm', '', npmFileHash]
 | 
			
		||||
    ])(
 | 
			
		||||
      'dependencies are changed %s',
 | 
			
		||||
      async (packageManager, toolVersion, fileHash) => {
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) => {
 | 
			
		||||
          if (command.includes('version')) {
 | 
			
		||||
            return toolVersion;
 | 
			
		||||
          } else {
 | 
			
		||||
            return findCacheFolder(command);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        restoreCacheSpy.mockImplementationOnce(() => undefined);
 | 
			
		||||
        await restoreCache(packageManager);
 | 
			
		||||
        expect(hashFilesSpy).toHaveBeenCalled();
 | 
			
		||||
        expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `${packageManager} cache is not found`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterEach(() => {
 | 
			
		||||
    jest.resetAllMocks();
 | 
			
		||||
    jest.clearAllMocks();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										248
									
								
								__tests__/cache-save.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								__tests__/cache-save.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,248 @@
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import * as cache from '@actions/cache';
 | 
			
		||||
import * as glob from '@actions/glob';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
 | 
			
		||||
import * as utils from '../src/cache-utils';
 | 
			
		||||
import {run} from '../src/cache-save';
 | 
			
		||||
import {State} from '../src/constants';
 | 
			
		||||
 | 
			
		||||
describe('run', () => {
 | 
			
		||||
  const yarnFileHash =
 | 
			
		||||
    'b8a0bae5243251f7c07dd52d1f78ff78281dfefaded700a176261b6b54fa245b';
 | 
			
		||||
  const npmFileHash =
 | 
			
		||||
    'abf7c9b306a3149dcfba4673e2362755503bcceaab46f0e4e6fee0ade493e20c';
 | 
			
		||||
  const commonPath = '/some/random/path';
 | 
			
		||||
  process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
 | 
			
		||||
 | 
			
		||||
  let inputs = {} as any;
 | 
			
		||||
 | 
			
		||||
  let getInputSpy: jest.SpyInstance;
 | 
			
		||||
  let infoSpy: jest.SpyInstance;
 | 
			
		||||
  let warningSpy: jest.SpyInstance;
 | 
			
		||||
  let debugSpy: jest.SpyInstance;
 | 
			
		||||
  let setFailedSpy: jest.SpyInstance;
 | 
			
		||||
  let getStateSpy: jest.SpyInstance;
 | 
			
		||||
  let saveCacheSpy: jest.SpyInstance;
 | 
			
		||||
  let getCommandOutputSpy: jest.SpyInstance;
 | 
			
		||||
  let hashFilesSpy: jest.SpyInstance;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    getInputSpy = jest.spyOn(core, 'getInput');
 | 
			
		||||
    getInputSpy.mockImplementation((name: string) => inputs[name]);
 | 
			
		||||
 | 
			
		||||
    infoSpy = jest.spyOn(core, 'info');
 | 
			
		||||
    infoSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    warningSpy = jest.spyOn(core, 'warning');
 | 
			
		||||
    warningSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    setFailedSpy = jest.spyOn(core, 'setFailed');
 | 
			
		||||
    setFailedSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    debugSpy = jest.spyOn(core, 'debug');
 | 
			
		||||
    debugSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    getStateSpy = jest.spyOn(core, 'getState');
 | 
			
		||||
 | 
			
		||||
    // cache
 | 
			
		||||
    saveCacheSpy = jest.spyOn(cache, 'saveCache');
 | 
			
		||||
    saveCacheSpy.mockImplementation(() => undefined);
 | 
			
		||||
 | 
			
		||||
    // glob
 | 
			
		||||
    hashFilesSpy = jest.spyOn(glob, 'hashFiles');
 | 
			
		||||
    hashFilesSpy.mockImplementation((pattern: string) => {
 | 
			
		||||
      if (pattern.includes('package-lock.json')) {
 | 
			
		||||
        return npmFileHash;
 | 
			
		||||
      } else if (pattern.includes('yarn.lock')) {
 | 
			
		||||
        return yarnFileHash;
 | 
			
		||||
      } else {
 | 
			
		||||
        return '';
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // utils
 | 
			
		||||
    getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Package manager validation', () => {
 | 
			
		||||
    it('Package manager is not provided, skip caching', async () => {
 | 
			
		||||
      inputs['cache'] = '';
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalled();
 | 
			
		||||
      expect(saveCacheSpy).not.toHaveBeenCalled();
 | 
			
		||||
      expect(debugSpy).toHaveBeenLastCalledWith(
 | 
			
		||||
        "Caching for '' is not supported"
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Package manager is not valid, skip caching', async () => {
 | 
			
		||||
      inputs['cache'] = 'yarn3';
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalled();
 | 
			
		||||
      expect(saveCacheSpy).not.toHaveBeenCalled();
 | 
			
		||||
      expect(debugSpy).toHaveBeenLastCalledWith(
 | 
			
		||||
        "Caching for 'yarn3' is not supported"
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Validate unchanged cache is not saved', () => {
 | 
			
		||||
    it('should not save cache for yarn1', async () => {
 | 
			
		||||
      inputs['cache'] = 'yarn';
 | 
			
		||||
      getStateSpy.mockImplementation(() => yarnFileHash);
 | 
			
		||||
      getCommandOutputSpy
 | 
			
		||||
        .mockImplementationOnce(() => '1.2.3')
 | 
			
		||||
        .mockImplementationOnce(() => `${commonPath}/yarn1`);
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
 | 
			
		||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
      );
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should not save cache for yarn2', async () => {
 | 
			
		||||
      inputs['cache'] = 'yarn';
 | 
			
		||||
      getStateSpy.mockImplementation(() => yarnFileHash);
 | 
			
		||||
      getCommandOutputSpy
 | 
			
		||||
        .mockImplementationOnce(() => '2.2.3')
 | 
			
		||||
        .mockImplementationOnce(() => `${commonPath}/yarn2`);
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
 | 
			
		||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
      );
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should not save cache for npm', async () => {
 | 
			
		||||
      inputs['cache'] = 'npm';
 | 
			
		||||
      getStateSpy.mockImplementation(() => npmFileHash);
 | 
			
		||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
 | 
			
		||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
			
		||||
      );
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('action saves the cache', () => {
 | 
			
		||||
    it('saves cache from yarn 1', async () => {
 | 
			
		||||
      inputs['cache'] = 'yarn';
 | 
			
		||||
      getStateSpy.mockImplementation((name: string) => {
 | 
			
		||||
        if (name === State.CacheMatchedKey) {
 | 
			
		||||
          return yarnFileHash;
 | 
			
		||||
        } else {
 | 
			
		||||
          return npmFileHash;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      getCommandOutputSpy
 | 
			
		||||
        .mockImplementationOnce(() => '1.2.3')
 | 
			
		||||
        .mockImplementationOnce(() => `${commonPath}/yarn1`);
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
      );
 | 
			
		||||
      expect(saveCacheSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(infoSpy).toHaveBeenLastCalledWith(
 | 
			
		||||
        `Cache saved with the key: ${npmFileHash}`
 | 
			
		||||
      );
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('saves cache from yarn 2', async () => {
 | 
			
		||||
      inputs['cache'] = 'yarn';
 | 
			
		||||
      getStateSpy.mockImplementation((name: string) => {
 | 
			
		||||
        if (name === State.CacheMatchedKey) {
 | 
			
		||||
          return yarnFileHash;
 | 
			
		||||
        } else {
 | 
			
		||||
          return npmFileHash;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      getCommandOutputSpy
 | 
			
		||||
        .mockImplementationOnce(() => '2.2.3')
 | 
			
		||||
        .mockImplementationOnce(() => `${commonPath}/yarn2`);
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
      );
 | 
			
		||||
      expect(saveCacheSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(infoSpy).toHaveBeenLastCalledWith(
 | 
			
		||||
        `Cache saved with the key: ${npmFileHash}`
 | 
			
		||||
      );
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('saves cache from npm', async () => {
 | 
			
		||||
      inputs['cache'] = 'npm';
 | 
			
		||||
      getStateSpy.mockImplementation((name: string) => {
 | 
			
		||||
        if (name === State.CacheMatchedKey) {
 | 
			
		||||
          return npmFileHash;
 | 
			
		||||
        } else {
 | 
			
		||||
          return yarnFileHash;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
			
		||||
 | 
			
		||||
      await run();
 | 
			
		||||
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
			
		||||
      );
 | 
			
		||||
      expect(saveCacheSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(infoSpy).toHaveBeenLastCalledWith(
 | 
			
		||||
        `Cache saved with the key: ${yarnFileHash}`
 | 
			
		||||
      );
 | 
			
		||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterEach(() => {
 | 
			
		||||
    jest.resetAllMocks();
 | 
			
		||||
    jest.clearAllMocks();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										52
									
								
								__tests__/cache-utils.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								__tests__/cache-utils.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
import * as utils from '../src/cache-utils';
 | 
			
		||||
 | 
			
		||||
describe('cache-utils', () => {
 | 
			
		||||
  const commonPath = '/some/random/path';
 | 
			
		||||
  const versionYarn1 = '1.2.3';
 | 
			
		||||
  const versionYarn2 = '2.3.4';
 | 
			
		||||
 | 
			
		||||
  let debugSpy: jest.SpyInstance;
 | 
			
		||||
  let getCommandOutputSpy: jest.SpyInstance;
 | 
			
		||||
 | 
			
		||||
  function getPackagePath(name: string) {
 | 
			
		||||
    if (name === utils.supportedPackageManagers.npm.getCacheFolderCommand) {
 | 
			
		||||
      return `${commonPath}/npm`;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (name === utils.supportedPackageManagers.yarn1.getCacheFolderCommand) {
 | 
			
		||||
        return `${commonPath}/yarn1`;
 | 
			
		||||
      } else {
 | 
			
		||||
        return `${commonPath}/yarn2`;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
 | 
			
		||||
    debugSpy = jest.spyOn(core, 'debug');
 | 
			
		||||
    debugSpy.mockImplementation(msg => {});
 | 
			
		||||
 | 
			
		||||
    getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getPackageManagerInfo', () => {
 | 
			
		||||
    it.each([
 | 
			
		||||
      ['npm', utils.supportedPackageManagers.npm],
 | 
			
		||||
      ['yarn', utils.supportedPackageManagers.yarn1],
 | 
			
		||||
      ['yarn1', null],
 | 
			
		||||
      ['yarn2', null],
 | 
			
		||||
      ['npm7', null]
 | 
			
		||||
    ])('getPackageManagerInfo for %s is %o', async (packageManager, result) => {
 | 
			
		||||
      getCommandOutputSpy.mockImplementationOnce(() => versionYarn1);
 | 
			
		||||
      await expect(utils.getPackageManagerInfo(packageManager)).resolves.toBe(
 | 
			
		||||
        result
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterEach(() => {
 | 
			
		||||
    jest.resetAllMocks();
 | 
			
		||||
    jest.clearAllMocks();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										395
									
								
								__tests__/data/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										395
									
								
								__tests__/data/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,395 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "test",
 | 
			
		||||
    "version": "1.0.0",
 | 
			
		||||
    "lockfileVersion": 1,
 | 
			
		||||
    "requires": true,
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
      "accepts": {
 | 
			
		||||
        "version": "1.3.7",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
 | 
			
		||||
        "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "mime-types": "~2.1.24",
 | 
			
		||||
          "negotiator": "0.6.2"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "array-flatten": {
 | 
			
		||||
        "version": "1.1.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
 | 
			
		||||
        "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
 | 
			
		||||
      },
 | 
			
		||||
      "body-parser": {
 | 
			
		||||
        "version": "1.19.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
 | 
			
		||||
        "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "bytes": "3.1.0",
 | 
			
		||||
          "content-type": "~1.0.4",
 | 
			
		||||
          "debug": "2.6.9",
 | 
			
		||||
          "depd": "~1.1.2",
 | 
			
		||||
          "http-errors": "1.7.2",
 | 
			
		||||
          "iconv-lite": "0.4.24",
 | 
			
		||||
          "on-finished": "~2.3.0",
 | 
			
		||||
          "qs": "6.7.0",
 | 
			
		||||
          "raw-body": "2.4.0",
 | 
			
		||||
          "type-is": "~1.6.17"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "bytes": {
 | 
			
		||||
        "version": "3.1.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
 | 
			
		||||
        "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
 | 
			
		||||
      },
 | 
			
		||||
      "content-disposition": {
 | 
			
		||||
        "version": "0.5.3",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
 | 
			
		||||
        "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "safe-buffer": "5.1.2"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "content-type": {
 | 
			
		||||
        "version": "1.0.4",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
 | 
			
		||||
        "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
 | 
			
		||||
      },
 | 
			
		||||
      "cookie": {
 | 
			
		||||
        "version": "0.4.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
 | 
			
		||||
        "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
 | 
			
		||||
      },
 | 
			
		||||
      "cookie-signature": {
 | 
			
		||||
        "version": "1.0.6",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
 | 
			
		||||
        "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
 | 
			
		||||
      },
 | 
			
		||||
      "debug": {
 | 
			
		||||
        "version": "2.6.9",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 | 
			
		||||
        "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "ms": "2.0.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "depd": {
 | 
			
		||||
        "version": "1.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
 | 
			
		||||
        "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
 | 
			
		||||
      },
 | 
			
		||||
      "destroy": {
 | 
			
		||||
        "version": "1.0.4",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
 | 
			
		||||
        "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
 | 
			
		||||
      },
 | 
			
		||||
      "ee-first": {
 | 
			
		||||
        "version": "1.1.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 | 
			
		||||
        "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
 | 
			
		||||
      },
 | 
			
		||||
      "encodeurl": {
 | 
			
		||||
        "version": "1.0.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
 | 
			
		||||
        "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
 | 
			
		||||
      },
 | 
			
		||||
      "escape-html": {
 | 
			
		||||
        "version": "1.0.3",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 | 
			
		||||
        "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
 | 
			
		||||
      },
 | 
			
		||||
      "etag": {
 | 
			
		||||
        "version": "1.8.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
 | 
			
		||||
        "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
 | 
			
		||||
      },
 | 
			
		||||
      "express": {
 | 
			
		||||
        "version": "4.17.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
 | 
			
		||||
        "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "accepts": "~1.3.7",
 | 
			
		||||
          "array-flatten": "1.1.1",
 | 
			
		||||
          "body-parser": "1.19.0",
 | 
			
		||||
          "content-disposition": "0.5.3",
 | 
			
		||||
          "content-type": "~1.0.4",
 | 
			
		||||
          "cookie": "0.4.0",
 | 
			
		||||
          "cookie-signature": "1.0.6",
 | 
			
		||||
          "debug": "2.6.9",
 | 
			
		||||
          "depd": "~1.1.2",
 | 
			
		||||
          "encodeurl": "~1.0.2",
 | 
			
		||||
          "escape-html": "~1.0.3",
 | 
			
		||||
          "etag": "~1.8.1",
 | 
			
		||||
          "finalhandler": "~1.1.2",
 | 
			
		||||
          "fresh": "0.5.2",
 | 
			
		||||
          "merge-descriptors": "1.0.1",
 | 
			
		||||
          "methods": "~1.1.2",
 | 
			
		||||
          "on-finished": "~2.3.0",
 | 
			
		||||
          "parseurl": "~1.3.3",
 | 
			
		||||
          "path-to-regexp": "0.1.7",
 | 
			
		||||
          "proxy-addr": "~2.0.5",
 | 
			
		||||
          "qs": "6.7.0",
 | 
			
		||||
          "range-parser": "~1.2.1",
 | 
			
		||||
          "safe-buffer": "5.1.2",
 | 
			
		||||
          "send": "0.17.1",
 | 
			
		||||
          "serve-static": "1.14.1",
 | 
			
		||||
          "setprototypeof": "1.1.1",
 | 
			
		||||
          "statuses": "~1.5.0",
 | 
			
		||||
          "type-is": "~1.6.18",
 | 
			
		||||
          "utils-merge": "1.0.1",
 | 
			
		||||
          "vary": "~1.1.2"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "finalhandler": {
 | 
			
		||||
        "version": "1.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
 | 
			
		||||
        "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "debug": "2.6.9",
 | 
			
		||||
          "encodeurl": "~1.0.2",
 | 
			
		||||
          "escape-html": "~1.0.3",
 | 
			
		||||
          "on-finished": "~2.3.0",
 | 
			
		||||
          "parseurl": "~1.3.3",
 | 
			
		||||
          "statuses": "~1.5.0",
 | 
			
		||||
          "unpipe": "~1.0.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "forwarded": {
 | 
			
		||||
        "version": "0.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
 | 
			
		||||
        "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
 | 
			
		||||
      },
 | 
			
		||||
      "fresh": {
 | 
			
		||||
        "version": "0.5.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
 | 
			
		||||
        "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
 | 
			
		||||
      },
 | 
			
		||||
      "http-errors": {
 | 
			
		||||
        "version": "1.7.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
 | 
			
		||||
        "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "depd": "~1.1.2",
 | 
			
		||||
          "inherits": "2.0.3",
 | 
			
		||||
          "setprototypeof": "1.1.1",
 | 
			
		||||
          "statuses": ">= 1.5.0 < 2",
 | 
			
		||||
          "toidentifier": "1.0.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "iconv-lite": {
 | 
			
		||||
        "version": "0.4.24",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
 | 
			
		||||
        "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "safer-buffer": ">= 2.1.2 < 3"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "inherits": {
 | 
			
		||||
        "version": "2.0.3",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
 | 
			
		||||
        "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
 | 
			
		||||
      },
 | 
			
		||||
      "ipaddr.js": {
 | 
			
		||||
        "version": "1.9.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
 | 
			
		||||
        "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
 | 
			
		||||
      },
 | 
			
		||||
      "lru-cache": {
 | 
			
		||||
        "version": "6.0.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
 | 
			
		||||
        "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "yallist": "^4.0.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "media-typer": {
 | 
			
		||||
        "version": "0.3.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
 | 
			
		||||
        "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
 | 
			
		||||
      },
 | 
			
		||||
      "merge-descriptors": {
 | 
			
		||||
        "version": "1.0.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
 | 
			
		||||
        "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
 | 
			
		||||
      },
 | 
			
		||||
      "methods": {
 | 
			
		||||
        "version": "1.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
 | 
			
		||||
        "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
 | 
			
		||||
      },
 | 
			
		||||
      "mime": {
 | 
			
		||||
        "version": "1.6.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
 | 
			
		||||
        "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
 | 
			
		||||
      },
 | 
			
		||||
      "mime-db": {
 | 
			
		||||
        "version": "1.47.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
 | 
			
		||||
        "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw=="
 | 
			
		||||
      },
 | 
			
		||||
      "mime-types": {
 | 
			
		||||
        "version": "2.1.30",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
 | 
			
		||||
        "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "mime-db": "1.47.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "ms": {
 | 
			
		||||
        "version": "2.0.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
			
		||||
        "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
 | 
			
		||||
      },
 | 
			
		||||
      "negotiator": {
 | 
			
		||||
        "version": "0.6.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
 | 
			
		||||
        "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
 | 
			
		||||
      },
 | 
			
		||||
      "on-finished": {
 | 
			
		||||
        "version": "2.3.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
 | 
			
		||||
        "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "ee-first": "1.1.1"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "parseurl": {
 | 
			
		||||
        "version": "1.3.3",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
 | 
			
		||||
        "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
 | 
			
		||||
      },
 | 
			
		||||
      "path-to-regexp": {
 | 
			
		||||
        "version": "0.1.7",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
 | 
			
		||||
        "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
 | 
			
		||||
      },
 | 
			
		||||
      "proxy-addr": {
 | 
			
		||||
        "version": "2.0.6",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
 | 
			
		||||
        "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "forwarded": "~0.1.2",
 | 
			
		||||
          "ipaddr.js": "1.9.1"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "qs": {
 | 
			
		||||
        "version": "6.7.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
 | 
			
		||||
        "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
 | 
			
		||||
      },
 | 
			
		||||
      "range-parser": {
 | 
			
		||||
        "version": "1.2.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
 | 
			
		||||
        "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
 | 
			
		||||
      },
 | 
			
		||||
      "raw-body": {
 | 
			
		||||
        "version": "2.4.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
 | 
			
		||||
        "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "bytes": "3.1.0",
 | 
			
		||||
          "http-errors": "1.7.2",
 | 
			
		||||
          "iconv-lite": "0.4.24",
 | 
			
		||||
          "unpipe": "1.0.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "safe-buffer": {
 | 
			
		||||
        "version": "5.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
 | 
			
		||||
        "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
 | 
			
		||||
      },
 | 
			
		||||
      "safer-buffer": {
 | 
			
		||||
        "version": "2.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 | 
			
		||||
        "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
 | 
			
		||||
      },
 | 
			
		||||
      "semver": {
 | 
			
		||||
        "version": "7.3.5",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
 | 
			
		||||
        "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "lru-cache": "^6.0.0"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "send": {
 | 
			
		||||
        "version": "0.17.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
 | 
			
		||||
        "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "debug": "2.6.9",
 | 
			
		||||
          "depd": "~1.1.2",
 | 
			
		||||
          "destroy": "~1.0.4",
 | 
			
		||||
          "encodeurl": "~1.0.2",
 | 
			
		||||
          "escape-html": "~1.0.3",
 | 
			
		||||
          "etag": "~1.8.1",
 | 
			
		||||
          "fresh": "0.5.2",
 | 
			
		||||
          "http-errors": "~1.7.2",
 | 
			
		||||
          "mime": "1.6.0",
 | 
			
		||||
          "ms": "2.1.1",
 | 
			
		||||
          "on-finished": "~2.3.0",
 | 
			
		||||
          "range-parser": "~1.2.1",
 | 
			
		||||
          "statuses": "~1.5.0"
 | 
			
		||||
        },
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "ms": {
 | 
			
		||||
            "version": "2.1.1",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
 | 
			
		||||
            "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "serve-static": {
 | 
			
		||||
        "version": "1.14.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
 | 
			
		||||
        "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "encodeurl": "~1.0.2",
 | 
			
		||||
          "escape-html": "~1.0.3",
 | 
			
		||||
          "parseurl": "~1.3.3",
 | 
			
		||||
          "send": "0.17.1"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "setprototypeof": {
 | 
			
		||||
        "version": "1.1.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
 | 
			
		||||
        "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
 | 
			
		||||
      },
 | 
			
		||||
      "statuses": {
 | 
			
		||||
        "version": "1.5.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
 | 
			
		||||
        "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
 | 
			
		||||
      },
 | 
			
		||||
      "toidentifier": {
 | 
			
		||||
        "version": "1.0.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
 | 
			
		||||
        "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
 | 
			
		||||
      },
 | 
			
		||||
      "type-is": {
 | 
			
		||||
        "version": "1.6.18",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
 | 
			
		||||
        "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
 | 
			
		||||
        "requires": {
 | 
			
		||||
          "media-typer": "0.3.0",
 | 
			
		||||
          "mime-types": "~2.1.24"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "unpipe": {
 | 
			
		||||
        "version": "1.0.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
 | 
			
		||||
        "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
 | 
			
		||||
      },
 | 
			
		||||
      "utils-merge": {
 | 
			
		||||
        "version": "1.0.1",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
 | 
			
		||||
        "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
 | 
			
		||||
      },
 | 
			
		||||
      "vary": {
 | 
			
		||||
        "version": "1.1.2",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
 | 
			
		||||
        "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
 | 
			
		||||
      },
 | 
			
		||||
      "yallist": {
 | 
			
		||||
        "version": "4.0.0",
 | 
			
		||||
        "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
			
		||||
        "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
							
								
								
									
										368
									
								
								__tests__/data/yarn.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								__tests__/data/yarn.lock
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,368 @@
 | 
			
		||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 | 
			
		||||
# yarn lockfile v1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
accepts@~1.3.7:
 | 
			
		||||
  version "1.3.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
 | 
			
		||||
  integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    mime-types "~2.1.24"
 | 
			
		||||
    negotiator "0.6.2"
 | 
			
		||||
 | 
			
		||||
array-flatten@1.1.1:
 | 
			
		||||
  version "1.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
 | 
			
		||||
  integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
 | 
			
		||||
 | 
			
		||||
body-parser@1.19.0:
 | 
			
		||||
  version "1.19.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
 | 
			
		||||
  integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    bytes "3.1.0"
 | 
			
		||||
    content-type "~1.0.4"
 | 
			
		||||
    debug "2.6.9"
 | 
			
		||||
    depd "~1.1.2"
 | 
			
		||||
    http-errors "1.7.2"
 | 
			
		||||
    iconv-lite "0.4.24"
 | 
			
		||||
    on-finished "~2.3.0"
 | 
			
		||||
    qs "6.7.0"
 | 
			
		||||
    raw-body "2.4.0"
 | 
			
		||||
    type-is "~1.6.17"
 | 
			
		||||
 | 
			
		||||
bytes@3.1.0:
 | 
			
		||||
  version "3.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
 | 
			
		||||
  integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
 | 
			
		||||
 | 
			
		||||
content-disposition@0.5.3:
 | 
			
		||||
  version "0.5.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
 | 
			
		||||
  integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    safe-buffer "5.1.2"
 | 
			
		||||
 | 
			
		||||
content-type@~1.0.4:
 | 
			
		||||
  version "1.0.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
 | 
			
		||||
  integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 | 
			
		||||
 | 
			
		||||
cookie-signature@1.0.6:
 | 
			
		||||
  version "1.0.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
 | 
			
		||||
  integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
 | 
			
		||||
 | 
			
		||||
cookie@0.4.0:
 | 
			
		||||
  version "0.4.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
 | 
			
		||||
  integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
 | 
			
		||||
 | 
			
		||||
debug@2.6.9:
 | 
			
		||||
  version "2.6.9"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
 | 
			
		||||
  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ms "2.0.0"
 | 
			
		||||
 | 
			
		||||
depd@~1.1.2:
 | 
			
		||||
  version "1.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
 | 
			
		||||
  integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
 | 
			
		||||
 | 
			
		||||
destroy@~1.0.4:
 | 
			
		||||
  version "1.0.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
 | 
			
		||||
  integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
 | 
			
		||||
 | 
			
		||||
ee-first@1.1.1:
 | 
			
		||||
  version "1.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
 | 
			
		||||
  integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
 | 
			
		||||
 | 
			
		||||
encodeurl@~1.0.2:
 | 
			
		||||
  version "1.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
 | 
			
		||||
  integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
 | 
			
		||||
 | 
			
		||||
escape-html@~1.0.3:
 | 
			
		||||
  version "1.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
 | 
			
		||||
  integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
 | 
			
		||||
 | 
			
		||||
etag@~1.8.1:
 | 
			
		||||
  version "1.8.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
 | 
			
		||||
  integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
 | 
			
		||||
 | 
			
		||||
express@^4.17.1:
 | 
			
		||||
  version "4.17.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
 | 
			
		||||
  integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    accepts "~1.3.7"
 | 
			
		||||
    array-flatten "1.1.1"
 | 
			
		||||
    body-parser "1.19.0"
 | 
			
		||||
    content-disposition "0.5.3"
 | 
			
		||||
    content-type "~1.0.4"
 | 
			
		||||
    cookie "0.4.0"
 | 
			
		||||
    cookie-signature "1.0.6"
 | 
			
		||||
    debug "2.6.9"
 | 
			
		||||
    depd "~1.1.2"
 | 
			
		||||
    encodeurl "~1.0.2"
 | 
			
		||||
    escape-html "~1.0.3"
 | 
			
		||||
    etag "~1.8.1"
 | 
			
		||||
    finalhandler "~1.1.2"
 | 
			
		||||
    fresh "0.5.2"
 | 
			
		||||
    merge-descriptors "1.0.1"
 | 
			
		||||
    methods "~1.1.2"
 | 
			
		||||
    on-finished "~2.3.0"
 | 
			
		||||
    parseurl "~1.3.3"
 | 
			
		||||
    path-to-regexp "0.1.7"
 | 
			
		||||
    proxy-addr "~2.0.5"
 | 
			
		||||
    qs "6.7.0"
 | 
			
		||||
    range-parser "~1.2.1"
 | 
			
		||||
    safe-buffer "5.1.2"
 | 
			
		||||
    send "0.17.1"
 | 
			
		||||
    serve-static "1.14.1"
 | 
			
		||||
    setprototypeof "1.1.1"
 | 
			
		||||
    statuses "~1.5.0"
 | 
			
		||||
    type-is "~1.6.18"
 | 
			
		||||
    utils-merge "1.0.1"
 | 
			
		||||
    vary "~1.1.2"
 | 
			
		||||
 | 
			
		||||
finalhandler@~1.1.2:
 | 
			
		||||
  version "1.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
 | 
			
		||||
  integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    debug "2.6.9"
 | 
			
		||||
    encodeurl "~1.0.2"
 | 
			
		||||
    escape-html "~1.0.3"
 | 
			
		||||
    on-finished "~2.3.0"
 | 
			
		||||
    parseurl "~1.3.3"
 | 
			
		||||
    statuses "~1.5.0"
 | 
			
		||||
    unpipe "~1.0.0"
 | 
			
		||||
 | 
			
		||||
forwarded@~0.1.2:
 | 
			
		||||
  version "0.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
 | 
			
		||||
  integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
 | 
			
		||||
 | 
			
		||||
fresh@0.5.2:
 | 
			
		||||
  version "0.5.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
 | 
			
		||||
  integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
 | 
			
		||||
 | 
			
		||||
http-errors@1.7.2:
 | 
			
		||||
  version "1.7.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
 | 
			
		||||
  integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    depd "~1.1.2"
 | 
			
		||||
    inherits "2.0.3"
 | 
			
		||||
    setprototypeof "1.1.1"
 | 
			
		||||
    statuses ">= 1.5.0 < 2"
 | 
			
		||||
    toidentifier "1.0.0"
 | 
			
		||||
 | 
			
		||||
http-errors@~1.7.2:
 | 
			
		||||
  version "1.7.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
 | 
			
		||||
  integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    depd "~1.1.2"
 | 
			
		||||
    inherits "2.0.4"
 | 
			
		||||
    setprototypeof "1.1.1"
 | 
			
		||||
    statuses ">= 1.5.0 < 2"
 | 
			
		||||
    toidentifier "1.0.0"
 | 
			
		||||
 | 
			
		||||
iconv-lite@0.4.24:
 | 
			
		||||
  version "0.4.24"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
 | 
			
		||||
  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    safer-buffer ">= 2.1.2 < 3"
 | 
			
		||||
 | 
			
		||||
inherits@2.0.3:
 | 
			
		||||
  version "2.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
 | 
			
		||||
  integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
 | 
			
		||||
 | 
			
		||||
inherits@2.0.4:
 | 
			
		||||
  version "2.0.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
 | 
			
		||||
  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
 | 
			
		||||
 | 
			
		||||
ipaddr.js@1.9.1:
 | 
			
		||||
  version "1.9.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
 | 
			
		||||
  integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
 | 
			
		||||
 | 
			
		||||
media-typer@0.3.0:
 | 
			
		||||
  version "0.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
 | 
			
		||||
  integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
 | 
			
		||||
 | 
			
		||||
merge-descriptors@1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
 | 
			
		||||
  integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
 | 
			
		||||
 | 
			
		||||
methods@~1.1.2:
 | 
			
		||||
  version "1.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
 | 
			
		||||
  integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
 | 
			
		||||
 | 
			
		||||
mime-db@1.47.0:
 | 
			
		||||
  version "1.47.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
 | 
			
		||||
  integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
 | 
			
		||||
 | 
			
		||||
mime-types@~2.1.24:
 | 
			
		||||
  version "2.1.30"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
 | 
			
		||||
  integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    mime-db "1.47.0"
 | 
			
		||||
 | 
			
		||||
mime@1.6.0:
 | 
			
		||||
  version "1.6.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
 | 
			
		||||
  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
 | 
			
		||||
 | 
			
		||||
ms@2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
 | 
			
		||||
  integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
 | 
			
		||||
 | 
			
		||||
ms@2.1.1:
 | 
			
		||||
  version "2.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
 | 
			
		||||
  integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
 | 
			
		||||
 | 
			
		||||
negotiator@0.6.2:
 | 
			
		||||
  version "0.6.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
 | 
			
		||||
  integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
 | 
			
		||||
 | 
			
		||||
on-finished@~2.3.0:
 | 
			
		||||
  version "2.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
 | 
			
		||||
  integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ee-first "1.1.1"
 | 
			
		||||
 | 
			
		||||
parseurl@~1.3.3:
 | 
			
		||||
  version "1.3.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
 | 
			
		||||
  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
 | 
			
		||||
 | 
			
		||||
path-to-regexp@0.1.7:
 | 
			
		||||
  version "0.1.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
 | 
			
		||||
  integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
 | 
			
		||||
 | 
			
		||||
proxy-addr@~2.0.5:
 | 
			
		||||
  version "2.0.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
 | 
			
		||||
  integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    forwarded "~0.1.2"
 | 
			
		||||
    ipaddr.js "1.9.1"
 | 
			
		||||
 | 
			
		||||
qs@6.7.0:
 | 
			
		||||
  version "6.7.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
 | 
			
		||||
  integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
 | 
			
		||||
 | 
			
		||||
range-parser@~1.2.1:
 | 
			
		||||
  version "1.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
 | 
			
		||||
  integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
 | 
			
		||||
 | 
			
		||||
raw-body@2.4.0:
 | 
			
		||||
  version "2.4.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
 | 
			
		||||
  integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    bytes "3.1.0"
 | 
			
		||||
    http-errors "1.7.2"
 | 
			
		||||
    iconv-lite "0.4.24"
 | 
			
		||||
    unpipe "1.0.0"
 | 
			
		||||
 | 
			
		||||
safe-buffer@5.1.2:
 | 
			
		||||
  version "5.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
 | 
			
		||||
  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 | 
			
		||||
 | 
			
		||||
"safer-buffer@>= 2.1.2 < 3":
 | 
			
		||||
  version "2.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
 | 
			
		||||
  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 | 
			
		||||
 | 
			
		||||
send@0.17.1:
 | 
			
		||||
  version "0.17.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
 | 
			
		||||
  integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    debug "2.6.9"
 | 
			
		||||
    depd "~1.1.2"
 | 
			
		||||
    destroy "~1.0.4"
 | 
			
		||||
    encodeurl "~1.0.2"
 | 
			
		||||
    escape-html "~1.0.3"
 | 
			
		||||
    etag "~1.8.1"
 | 
			
		||||
    fresh "0.5.2"
 | 
			
		||||
    http-errors "~1.7.2"
 | 
			
		||||
    mime "1.6.0"
 | 
			
		||||
    ms "2.1.1"
 | 
			
		||||
    on-finished "~2.3.0"
 | 
			
		||||
    range-parser "~1.2.1"
 | 
			
		||||
    statuses "~1.5.0"
 | 
			
		||||
 | 
			
		||||
serve-static@1.14.1:
 | 
			
		||||
  version "1.14.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
 | 
			
		||||
  integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    encodeurl "~1.0.2"
 | 
			
		||||
    escape-html "~1.0.3"
 | 
			
		||||
    parseurl "~1.3.3"
 | 
			
		||||
    send "0.17.1"
 | 
			
		||||
 | 
			
		||||
setprototypeof@1.1.1:
 | 
			
		||||
  version "1.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
 | 
			
		||||
  integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
 | 
			
		||||
 | 
			
		||||
"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
 | 
			
		||||
  version "1.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
 | 
			
		||||
  integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
 | 
			
		||||
 | 
			
		||||
toidentifier@1.0.0:
 | 
			
		||||
  version "1.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
 | 
			
		||||
  integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
 | 
			
		||||
 | 
			
		||||
type-is@~1.6.17, type-is@~1.6.18:
 | 
			
		||||
  version "1.6.18"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
 | 
			
		||||
  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    media-typer "0.3.0"
 | 
			
		||||
    mime-types "~2.1.24"
 | 
			
		||||
 | 
			
		||||
unpipe@1.0.0, unpipe@~1.0.0:
 | 
			
		||||
  version "1.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
 | 
			
		||||
  integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
 | 
			
		||||
 | 
			
		||||
utils-merge@1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
 | 
			
		||||
  integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
 | 
			
		||||
 | 
			
		||||
vary@~1.1.2:
 | 
			
		||||
  version "1.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
 | 
			
		||||
  integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
 | 
			
		||||
@@ -19,6 +19,8 @@ inputs:
 | 
			
		||||
  token:
 | 
			
		||||
    description: Used to pull node distributions from node-versions.  Since there's a default, this is typically not supplied by the user.
 | 
			
		||||
    default: ${{ github.token }}
 | 
			
		||||
  cache:
 | 
			
		||||
    description: 'Used to specify package manager for caching in default directory. Supported values: npm, yarn'
 | 
			
		||||
# TODO: add input to control forcing to pull from cloud or dist. 
 | 
			
		||||
#       escape valve for someone having issues or needing the absolute latest which isn't cached yet
 | 
			
		||||
# Deprecated option, do not use. Will not be supported after October 1, 2019
 | 
			
		||||
@@ -27,4 +29,6 @@ inputs:
 | 
			
		||||
    deprecationMessage: 'The version property will not be supported after October 1, 2019. Use node-version instead'
 | 
			
		||||
runs:
 | 
			
		||||
  using: 'node12'
 | 
			
		||||
  main: 'dist/index.js'
 | 
			
		||||
  main: 'dist/setup/index.js'
 | 
			
		||||
  post: 'dist/cache-save/index.js'
 | 
			
		||||
  post-if: success()
 | 
			
		||||
							
								
								
									
										60523
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60523
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										17314
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17314
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										85250
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										85250
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										5544
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5544
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -5,7 +5,7 @@
 | 
			
		||||
  "description": "setup node action",
 | 
			
		||||
  "main": "lib/setup-node.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "tsc && ncc build",
 | 
			
		||||
    "build": "ncc build -o dist/setup src/setup-node.ts && ncc build -o dist/cache-save src/cache-save.ts",
 | 
			
		||||
    "format": "prettier --write **/*.ts",
 | 
			
		||||
    "format-check": "prettier --check **/*.ts",
 | 
			
		||||
    "test": "jest",
 | 
			
		||||
@@ -23,9 +23,11 @@
 | 
			
		||||
  "author": "GitHub",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@actions/cache": "^1.0.7",
 | 
			
		||||
    "@actions/core": "^1.2.6",
 | 
			
		||||
    "@actions/exec": "^1.0.3",
 | 
			
		||||
    "@actions/exec": "^1.1.0",
 | 
			
		||||
    "@actions/github": "^1.1.0",
 | 
			
		||||
    "@actions/glob": "^0.2.0",
 | 
			
		||||
    "@actions/http-client": "^1.0.6",
 | 
			
		||||
    "@actions/io": "^1.0.2",
 | 
			
		||||
    "@actions/tool-cache": "^1.5.4",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								src/cache-restore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/cache-restore.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
import * as cache from '@actions/cache';
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import * as glob from '@actions/glob';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
 | 
			
		||||
import {State, Outputs} from './constants';
 | 
			
		||||
import {
 | 
			
		||||
  getCacheDirectoryPath,
 | 
			
		||||
  getPackageManagerInfo,
 | 
			
		||||
  PackageManagerInfo
 | 
			
		||||
} from './cache-utils';
 | 
			
		||||
 | 
			
		||||
export const restoreCache = async (packageManager: string) => {
 | 
			
		||||
  const packageManagerInfo = await getPackageManagerInfo(packageManager);
 | 
			
		||||
  if (!packageManagerInfo) {
 | 
			
		||||
    throw new Error(`Caching for '${packageManager}' is not supported`);
 | 
			
		||||
  }
 | 
			
		||||
  const platform = process.env.RUNNER_OS;
 | 
			
		||||
 | 
			
		||||
  const cachePath = await getCacheDirectoryPath(
 | 
			
		||||
    packageManagerInfo,
 | 
			
		||||
    packageManager
 | 
			
		||||
  );
 | 
			
		||||
  const lockFilePath = findLockFile(packageManagerInfo);
 | 
			
		||||
  const fileHash = await glob.hashFiles(lockFilePath);
 | 
			
		||||
 | 
			
		||||
  const primaryKey = `${platform}-${packageManager}-${fileHash}`;
 | 
			
		||||
  core.debug(`primary key is ${primaryKey}`);
 | 
			
		||||
 | 
			
		||||
  core.saveState(State.CachePrimaryKey, primaryKey);
 | 
			
		||||
 | 
			
		||||
  const cacheKey = await cache.restoreCache([cachePath], primaryKey);
 | 
			
		||||
 | 
			
		||||
  if (!cacheKey) {
 | 
			
		||||
    core.info(`${packageManager} cache is not found`);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  core.saveState(State.CacheMatchedKey, cacheKey);
 | 
			
		||||
  core.info(`Cache restored from key: ${cacheKey}`);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const findLockFile = (packageManager: PackageManagerInfo) => {
 | 
			
		||||
  let lockFiles = packageManager.lockFilePatterns;
 | 
			
		||||
  const workspace = process.env.GITHUB_WORKSPACE!;
 | 
			
		||||
  const rootContent = fs.readdirSync(workspace);
 | 
			
		||||
 | 
			
		||||
  const lockFile = lockFiles.find(item => rootContent.includes(item));
 | 
			
		||||
  if (!lockFile) {
 | 
			
		||||
    throw new Error(
 | 
			
		||||
      `Dependencies lock file is not found in ${workspace}. Supported file patterns: ${lockFiles.toString()}`
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return path.join(workspace, lockFile);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										50
									
								
								src/cache-save.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/cache-save.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import * as cache from '@actions/cache';
 | 
			
		||||
import {State} from './constants';
 | 
			
		||||
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
 | 
			
		||||
 | 
			
		||||
export async function run() {
 | 
			
		||||
  const cacheLock = core.getInput('cache');
 | 
			
		||||
  try {
 | 
			
		||||
    await cachePackages(cacheLock);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    core.setFailed(error.message);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const cachePackages = async (packageManager: string) => {
 | 
			
		||||
  const state = core.getState(State.CacheMatchedKey);
 | 
			
		||||
  const primaryKey = core.getState(State.CachePrimaryKey);
 | 
			
		||||
 | 
			
		||||
  const packageManagerInfo = await getPackageManagerInfo(packageManager);
 | 
			
		||||
  if (!packageManagerInfo) {
 | 
			
		||||
    core.debug(`Caching for '${packageManager}' is not supported`);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const cachePath = await getCacheDirectoryPath(
 | 
			
		||||
    packageManagerInfo,
 | 
			
		||||
    packageManager
 | 
			
		||||
  );
 | 
			
		||||
  if (primaryKey === state) {
 | 
			
		||||
    core.info(
 | 
			
		||||
      `Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
 | 
			
		||||
    );
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    await cache.saveCache([cachePath], primaryKey);
 | 
			
		||||
    core.info(`Cache saved with the key: ${primaryKey}`);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    if (error.name === cache.ValidationError.name) {
 | 
			
		||||
      throw error;
 | 
			
		||||
    } else if (error.name === cache.ReserveCacheError.name) {
 | 
			
		||||
      core.info(error.message);
 | 
			
		||||
    } else {
 | 
			
		||||
      core.warning(`${error.message}`);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
run();
 | 
			
		||||
							
								
								
									
										84
									
								
								src/cache-utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/cache-utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import * as exec from '@actions/exec';
 | 
			
		||||
 | 
			
		||||
type SupportedPackageManagers = {
 | 
			
		||||
  [prop: string]: PackageManagerInfo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface PackageManagerInfo {
 | 
			
		||||
  lockFilePatterns: Array<string>;
 | 
			
		||||
  getCacheFolderCommand: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const supportedPackageManagers: SupportedPackageManagers = {
 | 
			
		||||
  npm: {
 | 
			
		||||
    lockFilePatterns: ['package-lock.json', 'yarn.lock'],
 | 
			
		||||
    getCacheFolderCommand: 'npm config get cache'
 | 
			
		||||
  },
 | 
			
		||||
  yarn1: {
 | 
			
		||||
    lockFilePatterns: ['yarn.lock'],
 | 
			
		||||
    getCacheFolderCommand: 'yarn cache dir'
 | 
			
		||||
  },
 | 
			
		||||
  yarn2: {
 | 
			
		||||
    lockFilePatterns: ['yarn.lock'],
 | 
			
		||||
    getCacheFolderCommand: 'yarn config get cacheFolder'
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getCommandOutput = async (toolCommand: string) => {
 | 
			
		||||
  const {stdout, stderr, exitCode} = await exec.getExecOutput(toolCommand);
 | 
			
		||||
 | 
			
		||||
  if (stderr) {
 | 
			
		||||
    throw new Error(stderr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return stdout;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getPackageManagerVersion = async (
 | 
			
		||||
  packageManager: string,
 | 
			
		||||
  command: string
 | 
			
		||||
) => {
 | 
			
		||||
  const stdOut = await getCommandOutput(`${packageManager} ${command}`);
 | 
			
		||||
 | 
			
		||||
  if (!stdOut) {
 | 
			
		||||
    throw new Error(`Could not retrieve version of ${packageManager}`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return stdOut;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getPackageManagerInfo = async (packageManager: string) => {
 | 
			
		||||
  if (packageManager === 'npm') {
 | 
			
		||||
    return supportedPackageManagers.npm;
 | 
			
		||||
  } else if (packageManager === 'yarn') {
 | 
			
		||||
    const yarnVersion = await getPackageManagerVersion('yarn', '--version');
 | 
			
		||||
 | 
			
		||||
    core.debug(`Consumed yarn version is ${yarnVersion}`);
 | 
			
		||||
 | 
			
		||||
    if (yarnVersion.startsWith('1.')) {
 | 
			
		||||
      return supportedPackageManagers.yarn1;
 | 
			
		||||
    } else {
 | 
			
		||||
      return supportedPackageManagers.yarn2;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getCacheDirectoryPath = async (
 | 
			
		||||
  packageManagerInfo: PackageManagerInfo,
 | 
			
		||||
  packageManager: string
 | 
			
		||||
) => {
 | 
			
		||||
  const stdOut = await getCommandOutput(
 | 
			
		||||
    packageManagerInfo.getCacheFolderCommand
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  if (!stdOut) {
 | 
			
		||||
    throw new Error(`Could not get cache folder path for ${packageManager}`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  core.debug(`${packageManager} path is ${stdOut}`);
 | 
			
		||||
 | 
			
		||||
  return stdOut;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								src/constants.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/constants.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
export enum LockType {
 | 
			
		||||
  Npm = 'npm',
 | 
			
		||||
  Yarn = 'yarn'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum State {
 | 
			
		||||
  CachePrimaryKey = 'CACHE_KEY',
 | 
			
		||||
  CacheMatchedKey = 'CACHE_RESULT'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum Outputs {
 | 
			
		||||
  CacheHit = 'cache-hit'
 | 
			
		||||
}
 | 
			
		||||
@@ -128,7 +128,7 @@ export async function getNode(
 | 
			
		||||
    let extPath: string;
 | 
			
		||||
    info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here
 | 
			
		||||
    if (osPlat == 'win32') {
 | 
			
		||||
      let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
 | 
			
		||||
      let _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe');
 | 
			
		||||
      extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
 | 
			
		||||
      // 7z extracts to folder matching file name
 | 
			
		||||
      let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z'));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/main.ts
									
									
									
									
									
								
							@@ -2,6 +2,7 @@ import * as core from '@actions/core';
 | 
			
		||||
import * as installer from './installer';
 | 
			
		||||
import * as auth from './authutil';
 | 
			
		||||
import * as path from 'path';
 | 
			
		||||
import {restoreCache} from './cache-restore';
 | 
			
		||||
import {URL} from 'url';
 | 
			
		||||
import os = require('os');
 | 
			
		||||
 | 
			
		||||
@@ -17,6 +18,7 @@ export async function run() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let arch = core.getInput('architecture');
 | 
			
		||||
    const cache = core.getInput('cache');
 | 
			
		||||
 | 
			
		||||
    // if architecture supplied but node-version is not
 | 
			
		||||
    // if we don't throw a warning, the already installed x64 node will be used which is not probably what user meant.
 | 
			
		||||
@@ -45,7 +47,14 @@ export async function run() {
 | 
			
		||||
      auth.configAuthentication(registryUrl, alwaysAuth);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const matchersPath = path.join(__dirname, '..', '.github');
 | 
			
		||||
    if (cache) {
 | 
			
		||||
      if (isGhes()) {
 | 
			
		||||
        throw new Error('Caching is not supported on GHES');
 | 
			
		||||
      }
 | 
			
		||||
      await restoreCache(cache);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const matchersPath = path.join(__dirname, '../..', '.github');
 | 
			
		||||
    core.info(`##[add-matcher]${path.join(matchersPath, 'tsc.json')}`);
 | 
			
		||||
    core.info(
 | 
			
		||||
      `##[add-matcher]${path.join(matchersPath, 'eslint-stylish.json')}`
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user