import ts from 'typescript'; import fs from 'fs'; import path from 'path'; import { AmplifyUserError } from '@aws-amplify/platform-core'; import { workerData } from 'worker_threads'; /** * Function to compile TypeScript project using Compiler API */ export const compileProject = (projectDirectory) => { // Resolve the path to the tsconfig.json const configPath = path.resolve(projectDirectory, 'tsconfig.json'); if (!fs.existsSync(configPath)) { return; // Not a typescript project, turn off TS compilation } // Read and parse tsconfig.json const configFile = ts.readConfigFile(configPath, ts.sys.readFile); if (configFile.error) { throw new AmplifyUserError('SyntaxError', { message: 'Failed to parse tsconfig.json.', resolution: 'Fix the syntax and type errors in your tsconfig.json file.', details: ts.formatDiagnostic(configFile.error, ts.createCompilerHost({})), }); } // Parse JSON config into a TypeScript compiler options object const parsedCommandLine = ts.parseJsonConfigFileContent(configFile.config, ts.sys, projectDirectory); const tsBuildInfoFile = path.resolve(projectDirectory, '..', '.amplify', 'tsconfig.tsbuildinfo'); // Modify compiler options to match the command line options parsedCommandLine.options.skipLibCheck = true; parsedCommandLine.options.noEmit = true; parsedCommandLine.options.incremental = true; parsedCommandLine.options.tsBuildInfoFile = tsBuildInfoFile; const host = ts.createIncrementalCompilerHost(parsedCommandLine.options); let oldCachedProgram; // Cache exists, let's use it if (fs.existsSync(tsBuildInfoFile)) { oldCachedProgram = ts.readBuilderProgram(parsedCommandLine.options, host); } const tsProgram = oldCachedProgram ? ts.createEmitAndSemanticDiagnosticsBuilderProgram(parsedCommandLine.fileNames, parsedCommandLine.options, host, oldCachedProgram) : ts.createIncrementalProgram({ options: parsedCommandLine.options, rootNames: parsedCommandLine.fileNames, host, }); // Have to call emit to generate the tsBuildInfo, it won't generate .js or .d.ts since noEmit is true tsProgram.emit(); const diagnostics = ts.getPreEmitDiagnostics(tsProgram.getProgram()); // Report any errors if (diagnostics.length > 0) { const tsFormattedError = ts.formatDiagnosticsWithColorAndContext(diagnostics, { getCanonicalFileName: (path) => path, getCurrentDirectory: ts.sys.getCurrentDirectory, getNewLine: () => ts.sys.newLine, }); if (diagnostics.length === 1 && diagnostics[0].code === 2307) { // if the only TS error is function env var not present, then throw a more specific error const errorMessage = typeof diagnostics[0].messageText === 'string' ? diagnostics[0].messageText : diagnostics[0].messageText.messageText; if (errorMessage.match(/Cannot find module '\$amplify\/env\/.*' or its corresponding type declarations/)) { throw new AmplifyUserError('FunctionEnvVarFileNotGeneratedError', { message: 'Function environment variable files are not generated', resolution: 'Fix the syntax and type errors in your backend definition.', details: tsFormattedError, }); } } throw new AmplifyUserError('SyntaxError', { message: 'TypeScript validation check failed.', resolution: 'Fix the syntax and type errors in your backend definition.', details: tsFormattedError, }); } }; // If the request comes from a parent, execute it right away if (workerData?.projectDirectory) { compileProject(workerData.projectDirectory); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHNfY29tcGlsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHNfY29tcGlsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQzVCLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTVDOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLENBQUMsZ0JBQXdCLEVBQUUsRUFBRTtJQUN6RCx3Q0FBd0M7SUFDeEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUNuRSxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQy9CLE9BQU8sQ0FBQyxvREFBb0Q7SUFDOUQsQ0FBQztJQUVELCtCQUErQjtJQUMvQixNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2xFLElBQUksVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JCLE1BQU0sSUFBSSxnQkFBZ0IsQ0FBQyxhQUFhLEVBQUU7WUFDeEMsT0FBTyxFQUFFLGdDQUFnQztZQUN6QyxVQUFVLEVBQUUsNERBQTREO1lBQ3hFLE9BQU8sRUFBRSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDMUUsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDhEQUE4RDtJQUM5RCxNQUFNLGlCQUFpQixHQUFH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QUU7WUFDeEMsT0FBTyxFQUFFLHFDQUFxQztZQUM5QyxVQUFVLEVBQUUsNERBQTREO1lBQ3hFLE9BQU8sRUFBRSxnQkFBZ0I7U0FDMUIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLDREQUE0RDtBQUM1RCxJQUFJLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO0lBQ2pDLGNBQWMsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUM5QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRzIGZyb20gJ3R5cGVzY3JpcHQnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQW1wbGlmeVVzZXJFcnJvciB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9wbGF0Zm9ybS1jb3JlJztcbmltcG9ydCB7IHdvcmtlckRhdGEgfSBmcm9tICd3b3JrZXJfdGhyZWFkcyc7XG5cbi8qKlxuICogRnVuY3Rpb24gdG8gY29tcGlsZSBUeXBlU2NyaXB0IHByb2plY3QgdXNpbmcgQ29tcGlsZXIgQVBJXG4gKi9cbmV4cG9ydCBjb25zdCBjb21waWxlUHJvamVjdCA9IChwcm9qZWN0RGlyZWN0b3J5OiBzdHJpbmcpID0+IHtcbiAgLy8gUmVzb2x2ZSB0aGUgcGF0aCB0byB0aGUgdHNjb25maWcuanNvblxuICBjb25zdCBjb25maWdQYXRoID0gcGF0aC5yZXNvbHZlKHByb2plY3REaXJlY3RvcnksICd0c2NvbmZpZy5qc29uJyk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgIHJldHVybjsgLy8gTm90IGEgdHlwZXNjcmlwdCBwcm9qZWN0LCB0dXJuIG9mZiBUUyBjb21waWxhdGlvblxuICB9XG5cbiAgLy8gUmVhZCBhbmQgcGFyc2UgdHNjb25maWcuanNvblxuICBjb25zdCBjb25maWdGaWxlID0gdHMucmVhZENvbmZpZ0ZpbGUoY29uZmlnUGF0aCwgdHMuc3lzLnJlYWRGaWxlKTtcbiAgaWYgKGNvbmZpZ0ZpbGUuZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgQW1wbGlmeVVzZXJFcnJvcignU3ludGF4RXJyb3InLCB7XG4gICAgICBtZXNzYWdlOiAnRmFpbGVkIHRvIHBhcnNlIHRzY29uZmlnLmpzb24uJyxcbiAgICAgIHJlc29sdXRpb246ICdGaXggdGhlIHN5bnRheCBhbmQgdHlwZSBlcnJvcnMgaW4geW91ciB0c2NvbmZpZy5qc29uIGZpbGUuJyxcbiAgICAgIGRldGFpbHM6IHRzLmZvcm1hdERpYWdub3N0aWMoY29uZmlnRmlsZS5lcnJvciwgdHMuY3JlYXRlQ29tcGlsZXJIb3N0KHt9KSksXG4gICAgfSk7XG4gIH1cblxuICAvLyBQYXJzZSBKU09OIGNvbmZpZyBpbnRvIGEgVHlwZVNjcmlwdCBjb21waWxlciBvcHRpb25zIG9iamVjdFxuICBjb25zdCBwYXJzZWRDb21tYW5kTGluZSA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KFxuICAgIGNvbmZpZ0ZpbGUuY29uZmlnLFxuICAgIHRzLnN5cyxcbiAgICBwcm9qZWN0RGlyZWN0b3J5LFxuICApO1xuXG4gIGNvbnN0IHRzQnVpbGRJbmZvRmlsZSA9IHBhdGgucmVzb2x2ZShcbiAgICBwcm9qZWN0RGlyZWN0b3J5LFxuICAgICcuLicsXG4gICAgJy5hbXBsaWZ5JyxcbiAgICAndHNjb25maWcudHNidWlsZGluZm8nLFxuICApO1xuICAvLyBNb2RpZnkgY29tcGlsZXIgb3B0aW9ucyB0byBtYXRjaCB0aGUgY29tbWFuZCBsaW5lIG9wdGlvbnNcbiAgcGFyc2VkQ29tbWFuZExpbmUub3B0aW9ucy5za2lwTGliQ2hlY2sgPSB0cnVlO1xuICBwYXJzZWRDb21tYW5kTGluZS5vcHRpb25zLm5vRW1pdCA9IHRydWU7XG4gIHBhcnNlZENvbW1hbmRMaW5lLm9wdGlvbnMuaW5jcmVtZW50YWwgPSB0cnVlO1xuICBwYXJzZWRDb21tYW5kTGluZS5vcHRpb25zLnRzQnVpbGRJbmZvRmlsZSA9IHRzQnVpbGRJbmZvRmlsZTtcblxuICBjb25zdCBob3N0ID0gdHMuY3JlYXRlSW5jcmVtZW50YWxDb21waWxlckhvc3QocGFyc2VkQ29tbWFuZExpbmUub3B0aW9ucyk7XG4gIGxldCBvbGRDYWNoZWRQcm9ncmFtOiB0cy5FbWl0QW5kU2VtYW50aWNEaWFnbm9zdGljc0J1aWxkZXJQcm9ncmFtIHwgdW5kZWZpbmVkO1xuICAvLyBDYWNoZSBleGlzdHMsIGxldCdzIHVzZSBpdFxuICBpZiAoZnMuZXhpc3RzU3luYyh0c0J1aWxkSW5mb0ZpbGUpKSB7XG4gICAgb2xkQ2FjaGVkUHJvZ3JhbSA9IHRzLnJlYWRCdWlsZGVyUHJvZ3JhbShwYXJzZWRDb21tYW5kTGluZS5vcHRpb25zLCBob3N0KTtcbiAgfVxuXG4gIGNvbnN0IHRzUHJvZ3JhbSA9IG9sZENhY2hlZFByb2dyYW1cbiAgICA/IHRzLmNyZWF0ZUVtaXRBbmRTZW1hbnRpY0RpYWdub3N0aWNzQnVpbGRlclByb2dyYW0oXG4gICAgICAgIHBhcnNlZENvbW1hbmRMaW5lLmZpbGVOYW1lcyxcbiAgICAgICAgcGFyc2VkQ29tbWFuZExpbmUub3B0aW9ucyxcbiAgICAgICAgaG9zdCxcbiAgICAgICAgb2xkQ2FjaGVkUHJvZ3JhbSxcbiAgICAgIClcbiAgICA6IHRzLmNyZWF0ZUluY3JlbWVudGFsUHJvZ3JhbSh7XG4gICAgICAgIG9wdGlvbnM6IHBhcnNlZENvbW1hbmRMaW5lLm9wdGlvbnMsXG4gICAgICAgIHJvb3ROYW1lczogcGFyc2VkQ29tbWFuZExpbmUuZmlsZU5hbWVzLFxuICAgICAgICBob3N0LFxuICAgICAgfSk7XG5cbiAgLy8gSGF2ZSB0byBjYWxsIGVtaXQgdG8gZ2VuZXJhdGUgdGhlIHRzQnVpbGRJbmZvLCBpdCB3b24ndCBnZW5lcmF0ZSAuanMgb3IgLmQudHMgc2luY2Ugbm9FbWl0IGlzIHRydWVcbiAgdHNQcm9ncmFtLmVtaXQoKTtcbiAgY29uc3QgZGlhZ25vc3RpY3MgPSB0cy5nZXRQcmVFbWl0RGlhZ25vc3RpY3ModHNQcm9ncmFtLmdldFByb2dyYW0oKSk7XG5cbiAgLy8gUmVwb3J0IGFueSBlcnJvcnNcbiAgaWYgKGRpYWdub3N0aWNzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCB0c0Zvcm1hdHRlZEVycm9yID0gdHMuZm9ybWF0RGlhZ25vc3RpY3NXaXRoQ29sb3JBbmRDb250ZXh0KFxuICAgICAgZGlhZ25vc3RpY3MsXG4gICAgICB7XG4gICAgICAgIGdldENhbm9uaWNhbEZpbGVOYW1lOiAocGF0aCkgPT4gcGF0aCxcbiAgICAgICAgZ2V0Q3VycmVudERpcmVjdG9yeTogdHMuc3lzLmdldEN1cnJlbnREaXJlY3RvcnksXG4gICAgICAgIGdldE5ld0xpbmU6ICgpID0+IHRzLnN5cy5uZXdMaW5lLFxuICAgICAgfSxcbiAgICApO1xuICAgIGlmIChkaWFnbm9zdGljcy5sZW5ndGggPT09IDEgJiYgZGlhZ25vc3RpY3NbMF0uY29kZSA9PT0gMjMwNykge1xuICAgICAgLy8gaWYgdGhlIG9ubHkgVFMgZXJyb3IgaXMgZnVuY3Rpb24gZW52IHZhciBub3QgcHJlc2VudCwgdGhlbiB0aHJvdyBhIG1vcmUgc3BlY2lmaWMgZXJyb3JcbiAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9XG4gICAgICAgIHR5cGVvZiBkaWFnbm9zdGljc1swXS5tZXNzYWdlVGV4dCA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IGRpYWdub3N0aWNzWzBdLm1lc3NhZ2VUZXh0XG4gICAgICAgICAgOiBkaWFnbm9zdGljc1swXS5tZXNzYWdlVGV4dC5tZXNzYWdlVGV4dDtcbiAgICAgIGlmIChcbiAgICAgICAgZXJyb3JNZXNzYWdlLm1hdGNoKFxuICAgICAgICAgIC9DYW5ub3QgZmluZCBtb2R1bGUgJ1xcJGFtcGxpZnlcXC9lbnZcXC8uKicgb3IgaXRzIGNvcnJlc3BvbmRpbmcgdHlwZSBkZWNsYXJhdGlvbnMvLFxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEFtcGxpZnlVc2VyRXJyb3IoJ0Z1bmN0aW9uRW52VmFyRmlsZU5vdEdlbmVyYXRlZEVycm9yJywge1xuICAgICAgICAgIG1lc3NhZ2U6ICdGdW5jdGlvbiBlbnZpcm9ubWVudCB2YXJpYWJsZSBmaWxlcyBhcmUgbm90IGdlbmVyYXRlZCcsXG4gICAgICAgICAgcmVzb2x1dGlvbjpcbiAgICAgICAgICAgICdGaXggdGhlIHN5bnRheCBhbmQgdHlwZSBlcnJvcnMgaW4geW91ciBiYWNrZW5kIGRlZmluaXRpb24uJyxcbiAgICAgICAgICBkZXRhaWxzOiB0c0Zvcm1hdHRlZEVycm9yLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEFtcGxpZnlVc2VyRXJyb3IoJ1N5bnRheEVycm9yJywge1xuICAgICAgbWVzc2FnZTogJ1R5cGVTY3JpcHQgdmFsaWRhdGlvbiBjaGVjayBmYWlsZWQuJyxcbiAgICAgIHJlc29sdXRpb246ICdGaXggdGhlIHN5bnRheCBhbmQgdHlwZSBlcnJvcnMgaW4geW91ciBiYWNrZW5kIGRlZmluaXRpb24uJyxcbiAgICAgIGRldGFpbHM6IHRzRm9ybWF0dGVkRXJyb3IsXG4gICAgfSk7XG4gIH1cbn07XG5cbi8vIElmIHRoZSByZXF1ZXN0IGNvbWVzIGZyb20gYSBwYXJlbnQsIGV4ZWN1dGUgaXQgcmlnaHQgYXdheVxuaWYgKHdvcmtlckRhdGE/LnByb2plY3REaXJlY3RvcnkpIHtcbiAgY29tcGlsZVByb2plY3Qod29ya2VyRGF0YS5wcm9qZWN0RGlyZWN0b3J5KTtcbn1cbiJdfQ==