5
0
mirror of https://gitea.com/actions/setup-python.git synced 2025-10-26 07:16:42 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Tim Felgentreff
cfd55ca824 graalpy: add graalpy early-access and windows builds (#880) 2025-10-22 11:16:57 -05:00
dependabot[bot]
bba65e51ff Bump typescript from 5.4.2 to 5.9.3 and update docs/advanced-usage.md (#1094)
* Bump typescript from 5.4.2 to 5.8.3

Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.4.2 to 5.8.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.4.2...v5.8.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update header text from 'Linux' to 'Ubuntu'

* update target to ES2022

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: priya-kinthali <priya-kinthali@github.com>
2025-10-20 11:11:26 -05:00
13 changed files with 1952 additions and 2079 deletions

View File

@@ -106,7 +106,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, macos-13]
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
steps:
- uses: actions/checkout@v5
- name: Setup GraalPy and check latest

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ import * as path from 'path';
import * as semver from 'semver';
import * as finder from '../src/find-graalpy';
import {IGraalPyManifestRelease, IS_WINDOWS} from '../src/utils';
import {IGraalPyManifestRelease} from '../src/utils';
import manifestData from './data/graalpy.json';
@@ -19,9 +19,6 @@ const architecture = 'x64';
const toolDir = path.join(__dirname, 'runner', 'tools');
const tempDir = path.join(__dirname, 'runner', 'temp');
/* GraalPy doesn't have a windows release yet */
const describeSkipOnWindows = IS_WINDOWS ? describe.skip : describe;
describe('parseGraalPyVersion', () => {
it.each([
['graalpy-23', '23'],
@@ -108,7 +105,7 @@ describe('findGraalPyToolCache', () => {
});
});
describeSkipOnWindows('findGraalPyVersion', () => {
describe('findGraalPyVersion', () => {
let getBooleanInputSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
@@ -358,13 +355,13 @@ describeSkipOnWindows('findGraalPyVersion', () => {
it('found and install successfully, pre-release fallback', async () => {
spyCacheDir = jest.spyOn(tc, 'cacheDir');
spyCacheDir.mockImplementation(() =>
path.join(toolDir, 'GraalPy', '23.1', architecture)
path.join(toolDir, 'GraalPy', '24.1', architecture)
);
spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined);
await expect(
finder.findGraalPyVersion(
'graalpy23.1',
'graalpy24.1',
architecture,
false,
false,
@@ -372,7 +369,7 @@ describeSkipOnWindows('findGraalPyVersion', () => {
)
).rejects.toThrow();
await expect(
finder.findGraalPyVersion('graalpy23.1', architecture, false, false, true)
).resolves.toEqual('23.1.0-a.1');
finder.findGraalPyVersion('graalpy24.1', architecture, false, false, true)
).resolves.toEqual('24.1.0-ea.9');
});
});

View File

@@ -21,24 +21,21 @@ const architecture = 'x64';
const toolDir = path.join(__dirname, 'runner', 'tools');
const tempDir = path.join(__dirname, 'runner', 'temp');
/* GraalPy doesn't have a windows release yet */
const describeSkipOnWindows = IS_WINDOWS ? describe.skip : describe;
describe('graalpyVersionToSemantic', () => {
it.each([
['23.0.0a1', '23.0.0a1'],
['23.0.0', '23.0.0'],
['23.0.x', '23.0.x'],
['23.x', '23.x']
['graalpy-24.1.0-ea.09', '24.1.0-ea.9'],
['graal-23.0.0', '23.0.0'],
['vm-23.0.x', '23.0.x'],
['graal-23.x', '23.x']
])('%s -> %s', (input, expected) => {
expect(installer.graalPyTagToVersion(input)).toEqual(expected);
});
});
describeSkipOnWindows('findRelease', () => {
describe('findRelease', () => {
const result = JSON.stringify(manifestData);
const releases = JSON.parse(result) as IGraalPyManifestRelease[];
const extension = 'tar.gz';
const extension = IS_WINDOWS ? 'zip' : 'tar.gz';
const arch = installer.toGraalPyArchitecture(architecture);
const platform = installer.toGraalPyPlatform(process.platform);
const extensionName = `${platform}-${arch}.${extension}`;
@@ -47,8 +44,8 @@ describeSkipOnWindows('findRelease', () => {
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.0.0/graalpython-23.0.0-${extensionName}`
};
const filesRC1: IGraalPyManifestAsset = {
name: `graalpython-23.1.0a1-${extensionName}`,
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.1.0a1/graalpython-23.1.0a1-${extensionName}`
name: `graalpy-24.1.0-ea.09-${extensionName}`,
browser_download_url: `https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-24.1.0-ea.09/graalpy-24.1.0-ea.09-${extensionName}`
};
let warningSpy: jest.SpyInstance;
@@ -84,15 +81,15 @@ describeSkipOnWindows('findRelease', () => {
});
it('Preview version of GraalPy is found', () => {
const graalpyVersion = installer.graalPyTagToVersion('vm-23.1.0a1');
const graalpyVersion = installer.graalPyTagToVersion('vm-24.1.0-ea.09');
expect(
installer.findRelease(releases, graalpyVersion, architecture, false)
).toMatchObject({
foundAsset: {
name: `graalpython-23.1.0a1-${extensionName}`,
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.1.0a1/graalpython-23.1.0a1-${extensionName}`
name: `graalpy-24.1.0-ea.09-${extensionName}`,
browser_download_url: `https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-24.1.0-ea.09/graalpy-24.1.0-ea.09-${extensionName}`
},
resolvedGraalPyVersion: '23.1.0-a.1'
resolvedGraalPyVersion: '24.1.0-ea.9'
});
});
@@ -107,7 +104,7 @@ describeSkipOnWindows('findRelease', () => {
});
it('GraalPy version matches semver (pre-release)', () => {
const graalpyVersion = '23.1.x';
const graalpyVersion = '24.1.x';
expect(
installer.findRelease(releases, graalpyVersion, architecture, false)
).toBeNull();
@@ -115,12 +112,12 @@ describeSkipOnWindows('findRelease', () => {
installer.findRelease(releases, graalpyVersion, architecture, true)
).toMatchObject({
foundAsset: filesRC1,
resolvedGraalPyVersion: '23.1.0-a.1'
resolvedGraalPyVersion: '24.1.0-ea.9'
});
});
});
describeSkipOnWindows('installGraalPy', () => {
describe('installGraalPy', () => {
let tcFind: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
@@ -232,20 +229,20 @@ describeSkipOnWindows('installGraalPy', () => {
it('found and install GraalPy, pre-release fallback', async () => {
spyCacheDir = jest.spyOn(tc, 'cacheDir');
spyCacheDir.mockImplementation(() =>
path.join(toolDir, 'GraalPy', '23.1.0', architecture)
path.join(toolDir, 'GraalPy', '24.1.0', architecture)
);
spyChmodSync = jest.spyOn(fs, 'chmodSync');
spyChmodSync.mockImplementation(() => undefined);
await expect(
installer.installGraalPy('23.1.x', architecture, false, undefined)
installer.installGraalPy('24.1.x', architecture, false, undefined)
).rejects.toThrow();
await expect(
installer.installGraalPy('23.1.x', architecture, true, undefined)
installer.installGraalPy('24.1.x', architecture, true, undefined)
).resolves.toEqual({
installDir: path.join(toolDir, 'GraalPy', '23.1.0', architecture),
resolvedGraalPyVersion: '23.1.0-a.1'
installDir: path.join(toolDir, 'GraalPy', '24.1.0', architecture),
resolvedGraalPyVersion: '24.1.0-ea.9'
});
expect(spyHttpClient).toHaveBeenCalled();

View File

@@ -87714,22 +87714,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
};
})();
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.State = void 0;
const cache = __importStar(__nccwpck_require__(5116));
@@ -87742,17 +87743,16 @@ var State;
State["CACHE_PATHS"] = "cache-paths";
})(State || (exports.State = State = {}));
class CacheDistributor {
packageManager;
cacheDependencyPath;
CACHE_KEY_PREFIX = 'setup-python';
constructor(packageManager, cacheDependencyPath) {
this.packageManager = packageManager;
this.cacheDependencyPath = cacheDependencyPath;
this.CACHE_KEY_PREFIX = 'setup-python';
}
handleLoadedCache() {
return __awaiter(this, void 0, void 0, function* () { });
}
restoreCache() {
return __awaiter(this, void 0, void 0, function* () {
const { primaryKey, restoreKey } = yield this.computeKeys();
async handleLoadedCache() { }
async restoreCache() {
const { primaryKey, restoreKey } = await this.computeKeys();
if (primaryKey.endsWith('-')) {
const file = this.packageManager === 'pip'
? `${this.cacheDependencyPath
@@ -87761,11 +87761,11 @@ class CacheDistributor {
: this.cacheDependencyPath.split('\n').join(',');
throw new Error(`No file in ${process.cwd()} matched to [${file}], make sure you have checked out the target repository`);
}
const cachePath = yield this.getCacheGlobalDirectories();
const cachePath = await this.getCacheGlobalDirectories();
core.saveState(State.CACHE_PATHS, cachePath);
let matchedKey;
try {
matchedKey = yield cache.restoreCache(cachePath, primaryKey, restoreKey);
matchedKey = await cache.restoreCache(cachePath, primaryKey, restoreKey);
}
catch (err) {
const message = err.message;
@@ -87774,9 +87774,8 @@ class CacheDistributor {
return;
}
core.saveState(State.STATE_CACHE_PRIMARY_KEY, primaryKey);
yield this.handleLoadedCache();
await this.handleLoadedCache();
this.handleMatchResult(matchedKey, primaryKey);
});
}
handleMatchResult(matchedKey, primaryKey) {
if (matchedKey) {
@@ -87827,27 +87826,28 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0;
exports.run = run;
const core = __importStar(__nccwpck_require__(7484));
const cache = __importStar(__nccwpck_require__(5116));
const fs_1 = __importDefault(__nccwpck_require__(9896));
@@ -87855,12 +87855,11 @@ const cache_distributor_1 = __nccwpck_require__(2326);
// Added early exit to resolve issue with slow post action step:
// - https://github.com/actions/setup-node/issues/878
// https://github.com/actions/cache/pull/1217
function run(earlyExit) {
return __awaiter(this, void 0, void 0, function* () {
async function run(earlyExit) {
try {
const cache = core.getInput('cache');
if (cache) {
yield saveCache(cache);
await saveCache(cache);
if (earlyExit) {
process.exit(0);
}
@@ -87870,11 +87869,8 @@ function run(earlyExit) {
const err = error;
core.setFailed(err.message);
}
});
}
exports.run = run;
function saveCache(packageManager) {
return __awaiter(this, void 0, void 0, function* () {
async function saveCache(packageManager) {
const cachePathState = core.getState(cache_distributor_1.State.CACHE_PATHS);
if (!cachePathState) {
core.warning('Cache paths are empty. Please check the previous logs and make sure that the python version is specified');
@@ -87899,7 +87895,7 @@ function saveCache(packageManager) {
}
let cacheId = 0;
try {
cacheId = yield cache.saveCache(cachePaths, primaryKey);
cacheId = await cache.saveCache(cachePaths, primaryKey);
}
catch (err) {
const message = err.message;
@@ -87910,7 +87906,6 @@ function saveCache(packageManager) {
return;
}
core.info(`Cache saved with the key: ${primaryKey}`);
});
}
function isCacheDirectoryExists(cacheDirectory) {
const result = cacheDirectory.reduce((previousValue, currentValue) => {

772
dist/setup/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@
- [Hosted tool cache](advanced-usage.md#hosted-tool-cache)
- [Using `setup-python` with a self-hosted runner](advanced-usage.md#using-setup-python-with-a-self-hosted-runner)
- [Windows](advanced-usage.md#windows)
- [Linux](advanced-usage.md#linux)
- [Ubuntu](advanced-usage.md#Ubuntu)
- [macOS](advanced-usage.md#macos)
- [Using `setup-python` on GHES](advanced-usage.md#using-setup-python-on-ghes)
- [Allow pre-releases](advanced-usage.md#allow-pre-releases)
@@ -578,9 +578,9 @@ If you have a supported self-hosted runner and you would like to use `setup-pyth
>If you are experiencing problems while configuring Python on your self-hosted runner, turn on [step debugging](https://github.com/actions/toolkit/blob/main/docs/action-debugging.md#step-debug-logs) to see additional logs.
### Linux
### Ubuntu
By default, the runner downloads and installs tools into the folder set up by `RUNNER_TOOL_CACHE` environment variable. The environment variable called `AGENT_TOOLSDIRECTORY` can be set to change this location for Linux self-hosted runners:
By default, the runner downloads and installs tools into the folder set up by `RUNNER_TOOL_CACHE` environment variable. The environment variable called `AGENT_TOOLSDIRECTORY` can be set to change this location for Ubuntu self-hosted runners:
- In the same shell that your runner is using, type `export AGENT_TOOLSDIRECTORY=/path/to/folder`.
- More permanent way of setting the environment variable is to create an `.env` file in the same directory as your runner and to add `AGENT_TOOLSDIRECTORY=/path/to/folder`. This ensures the variable is always set if your runner is configured as a service.

9
package-lock.json generated
View File

@@ -34,7 +34,7 @@
"jest-circus": "^29.7.0",
"prettier": "^3.5.3",
"ts-jest": "^29.3.2",
"typescript": "^5.4.2"
"typescript": "^5.9.3"
},
"engines": {
"node": ">=24.0.0"
@@ -5446,10 +5446,11 @@
}
},
"node_modules/typescript": {
"version": "5.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz",
"integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==",
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"

View File

@@ -53,6 +53,6 @@
"jest-circus": "^29.7.0",
"prettier": "^3.5.3",
"ts-jest": "^29.3.2",
"typescript": "^5.4.2"
"typescript": "^5.9.3"
}
}

View File

@@ -1,11 +1,6 @@
import * as path from 'path';
import * as graalpyInstall from './install-graalpy';
import {
IS_WINDOWS,
validateVersion,
IGraalPyManifestRelease,
getBinaryDirectory
} from './utils';
import {IS_WINDOWS, validateVersion, IGraalPyManifestRelease} from './utils';
import * as semver from 'semver';
import * as core from '@actions/core';
@@ -62,11 +57,8 @@ export async function findGraalPyVersion(
const pipDir = IS_WINDOWS ? 'Scripts' : 'bin';
const _binDir = path.join(installDir, pipDir);
const binaryExtension = IS_WINDOWS ? '.exe' : '';
const pythonPath = path.join(
IS_WINDOWS ? installDir : _binDir,
`python${binaryExtension}`
);
const pythonLocation = getBinaryDirectory(installDir);
const pythonPath = path.join(_binDir, `python${binaryExtension}`);
const pythonLocation = path.join(installDir, 'bin');
if (updateEnvironment) {
core.exportVariable('pythonLocation', installDir);
// https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython

View File

@@ -15,7 +15,6 @@ import {
IGraalPyManifestRelease,
createSymlinkInFolder,
isNightlyKeyword,
getBinaryDirectory,
getNextPageUrl
} from './utils';
@@ -64,7 +63,11 @@ export async function installGraalPy(
const graalpyPath = await tc.downloadTool(downloadUrl, undefined, AUTH);
core.info('Extracting downloaded archive...');
if (IS_WINDOWS) {
downloadDir = await tc.extractZip(graalpyPath);
} else {
downloadDir = await tc.extractTar(graalpyPath);
}
// root folder in archive can have unpredictable name so just take the first folder
// downloadDir is unique folder under TEMP and can't contain any other folders
@@ -81,7 +84,7 @@ export async function installGraalPy(
);
}
const binaryPath = getBinaryDirectory(installDir);
const binaryPath = path.join(installDir, 'bin');
await createGraalPySymlink(binaryPath, resolvedGraalPyVersion);
await installPip(binaryPath);
@@ -115,6 +118,9 @@ export async function getAvailableGraalPyVersions() {
headers.authorization = AUTH;
}
/*
Get releases first.
*/
let url: string | null =
'https://api.github.com/repos/oracle/graalpython/releases';
const result: IGraalPyManifestRelease[] = [];
@@ -130,6 +136,23 @@ export async function getAvailableGraalPyVersions() {
url = getNextPageUrl(response);
} while (url);
/*
Add pre-release builds.
*/
url =
'https://api.github.com/repos/graalvm/graal-languages-ea-builds/releases';
do {
const response: ifm.TypedResponse<IGraalPyManifestRelease[]> =
await http.getJson(url, headers);
if (!response.result) {
throw new Error(
`Unable to retrieve the list of available GraalPy versions from '${url}'`
);
}
result.push(...response.result);
url = getNextPageUrl(response);
} while (url);
return result;
}
@@ -175,7 +198,8 @@ async function installPip(pythonLocation: string) {
}
export function graalPyTagToVersion(tag: string) {
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)((?:a|b|rc))?(\d*)?/;
const versionPattern =
/.*-(\d+\.\d+\.\d+(?:\.\d+)?)(?:-((?:ea|a|b|rc))\.0*(\d+))?/;
const match = tag.match(versionPattern);
if (match && match[2]) {
return `${match[1]}-${match[2]}.${match[3]}`;
@@ -251,10 +275,11 @@ export function findAsset(
) {
const graalpyArch = toGraalPyArchitecture(architecture);
const graalpyPlatform = toGraalPyPlatform(platform);
const graalpyExt = platform == 'win32' ? 'zip' : 'tar.gz';
const found = item.assets.filter(
file =>
file.name.startsWith('graalpy') &&
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.tar.gz`)
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.${graalpyExt}`)
);
/*
In the future there could be more variants of GraalPy for a single release. Pick the shortest name, that one is the most likely to be the primary variant.

View File

@@ -379,7 +379,7 @@ export function getVersionInputFromFile(versionFile: string): string[] {
}
/**
* Get the directory containing interpreter binary from installation directory of PyPy or GraalPy
* Get the directory containing interpreter binary from installation directory of PyPy
* - On Linux and macOS, the Python interpreter is in 'bin'.
* - On Windows, it is in the installation root.
*/

View File

@@ -2,7 +2,7 @@
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */