UNPKG

@storm-stack/core

Version:

A build toolkit and runtime used by Storm Software in TypeScript applications

249 lines (245 loc) 9.32 kB
import { init_esm_shims, __name } from './chunk-QH7NXH7H.js'; import { existsSync } from '@stryke/fs/exists'; import { readJsonFileSync } from '@stryke/fs/json'; import { joinPaths } from '@stryke/path/join-paths'; import { replacePath } from '@stryke/path/replace'; import defu2 from 'defu'; import ts from 'typescript'; import { getWorkspaceConfig } from '@storm-software/config-tools/get-config'; import { getProjectRoot, getWorkspaceRoot } from '@stryke/fs/get-workspace-root'; import { isFunction } from '@stryke/type-checks/is-function'; import { isSetObject } from '@stryke/type-checks/is-set-object'; import { loadConfig } from 'c12'; // src/lib/typescript/tsconfig.ts init_esm_shims(); function getTsconfigFilePath(projectRoot, tsconfig = "tsconfig.json") { let tsconfigFilePath = tsconfig; if (!existsSync(tsconfigFilePath)) { tsconfigFilePath = joinPaths(projectRoot, replacePath(tsconfig, projectRoot)); if (!existsSync(tsconfigFilePath)) { throw new Error(`Cannot find the \`tsconfig.json\` configuration file at ${joinPaths(projectRoot, replacePath(tsconfig, projectRoot))} or ${tsconfigFilePath}`); } } return tsconfigFilePath; } __name(getTsconfigFilePath, "getTsconfigFilePath"); function findMatch(tsconfigType, types, extensions = [ ".ts", ".tsx", ".d.ts" ]) { return types.find((type) => tsconfigType?.toString().toLowerCase() === type?.toString().toLowerCase() || tsconfigType?.toString().toLowerCase() === `./${type?.toString().toLowerCase()}` || `./${tsconfigType?.toString().toLowerCase()}` === type?.toString().toLowerCase() || extensions.some((ext) => `${tsconfigType?.toString().toLowerCase()}${ext}` === type?.toString().toLowerCase() || `${tsconfigType?.toString().toLowerCase()}${ext}` === `./${type?.toString().toLowerCase()}` || `${type?.toString().toLowerCase()}${ext}` === `./${tsconfigType?.toString().toLowerCase()}` || tsconfigType?.toString().toLowerCase() === `${type?.toString().toLowerCase()}${ext}` || tsconfigType?.toString().toLowerCase() === `./${type?.toString().toLowerCase()}${ext}` || type?.toString().toLowerCase() === `./${tsconfigType?.toString().toLowerCase()}${ext}`)); } __name(findMatch, "findMatch"); function findIncludeMatch(tsconfigType, types) { return findMatch(tsconfigType, types, [ ".ts", ".tsx", ".d.ts", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts", "/*.ts", "/*.tsx", "/*.d.ts", "/*.js", "/*.jsx", "/*.mjs", "/*.cjs", "/*.mts", "/*.cts", "/**/*.ts", "/**/*.tsx", "/**/*.d.ts", "/**/*.js", "/**/*.jsx", "/**/*.mjs", "/**/*.cjs", "/**/*.mts", "/**/*.cts" ]); } __name(findIncludeMatch, "findIncludeMatch"); function isIncludeMatchFound(tsconfigType, types) { return findIncludeMatch(tsconfigType, types) !== void 0; } __name(isIncludeMatchFound, "isIncludeMatchFound"); function getParsedTypeScriptConfig(workspaceRoot, projectRoot, tsconfig, tsconfigRaw = {}, host = ts.sys) { const tsconfigFilePath = getTsconfigFilePath(projectRoot, tsconfig); const tsconfigJson = readJsonFileSync(tsconfigFilePath); if (!tsconfigJson) { throw new Error(`Cannot find the \`tsconfig.json\` configuration file at ${joinPaths(projectRoot, tsconfig ?? "tsconfig.json")}`); } const parsedCommandLine = ts.parseJsonConfigFileContent(defu2(tsconfigRaw ?? {}, tsconfigJson), host, joinPaths(workspaceRoot, projectRoot)); if (parsedCommandLine.errors.length > 0) { const errorMessage = `Cannot parse the TypeScript compiler options. Please investigate the following issues: ${parsedCommandLine.errors.map((error) => `- ${(error.category !== void 0 && error.code ? `[${error.category}-${error.code}]: ` : "") + error.messageText.toString()}`).join("\n")} `; throw new Error(errorMessage); } return { ...parsedCommandLine, tsconfigJson, tsconfigFilePath }; } __name(getParsedTypeScriptConfig, "getParsedTypeScriptConfig"); // src/lib/config.ts init_esm_shims(); async function loadUserConfigFile(projectRoot, jiti, command, mode) { let resolvedUserConfig = {}; const resolvedUserConfigFile = existsSync(joinPaths(projectRoot, "storm.config.ts")) ? joinPaths(projectRoot, "storm.config.ts") : existsSync(joinPaths(projectRoot, "storm.config.js")) ? joinPaths(projectRoot, "storm.config.js") : existsSync(joinPaths(projectRoot, "storm.config.mts")) ? joinPaths(projectRoot, "storm.config.mts") : existsSync(joinPaths(projectRoot, "storm.config.mjs")) ? joinPaths(projectRoot, "storm.config.mjs") : void 0; if (resolvedUserConfigFile) { const resolved = await jiti.import(jiti.esmResolve(resolvedUserConfigFile)); if (resolved) { let config = {}; if (isFunction(resolved)) { config = await Promise.resolve(resolved({ command, mode: mode || "production", isSsrBuild: false, isPreview: false })); } if (isSetObject(config)) { resolvedUserConfig = { ...config, config, configFile: resolvedUserConfigFile }; } } } const result = await Promise.all([ loadConfig({ cwd: projectRoot, name: "storm", envName: mode, globalRc: true, packageJson: true, dotenv: true, jiti }), loadConfig({ cwd: projectRoot, name: "storm.config", rcFile: false, globalRc: false, packageJson: false, dotenv: false, jiti }), loadConfig({ cwd: projectRoot, name: "storm-stack", envName: mode, globalRc: true, packageJson: "stormStack", jiti }) ]); return defu2(resolvedUserConfig, isSetObject(result[0]?.config) ? { ...result[0].config, ...result[0] } : {}, isSetObject(result[1]?.config) ? { ...result[1].config, ...result[1] } : {}, isSetObject(result[2]?.config) ? { ...result[2].config, ...result[2] } : {}); } __name(loadUserConfigFile, "loadUserConfigFile"); async function resolveConfig(context, inlineConfig, userConfig, projectRoot) { const resolvedProjectRoot = projectRoot || inlineConfig.root || userConfig?.root || getProjectRoot() || process.cwd(); const workspaceConfig = defu2(await getWorkspaceConfig(), { workspaceRoot: context.options.workspaceConfig?.workspaceRoot ?? getWorkspaceRoot() }); if (!workspaceConfig) { throw new Error("The workspace root could not be determined. Please ensure you are in a Storm Stack project."); } const mergedUserConfig = defu2({ config: userConfig ?? {} }, await loadUserConfigFile(resolvedProjectRoot, context.resolver, context.options.command, inlineConfig.mode || userConfig?.mode || context.options.workspaceConfig?.mode || "production")); const resolvedOptions = defu2({ inlineConfig, userConfig: mergedUserConfig, workspaceConfig, projectRoot: resolvedProjectRoot, workspaceRoot: workspaceConfig.workspaceRoot }, inlineConfig, mergedUserConfig.config ?? {}, { ...context.options, tsconfig: getTsconfigFilePath(resolvedProjectRoot, context.options.tsconfig ?? "tsconfig.json") }, { platform: "neutral", mode: "production", projectType: "application", logLevel: "info", isSsrBuild: false, isPreview: false, babel: { plugins: [], presets: [] }, build: {}, override: {} }); resolvedOptions.output = defu2(resolvedOptions.output ?? {}, { outputPath: resolvedOptions.tsconfigRaw?.compilerOptions?.outDir, outputMode: resolvedOptions.output?.outputMode }, { outputPath: resolvedProjectRoot === workspaceConfig.workspaceRoot ? "dist" : joinPaths("dist", resolvedProjectRoot), outputMode: "virtual", assets: [ { input: resolvedProjectRoot, glob: "README.md", output: "/" }, { input: resolvedProjectRoot, glob: "CHANGELOG.md", output: "/" }, { input: "", glob: "LICENSE", output: "/" } ] }); resolvedOptions.environment ??= defaultEnvironmentName(resolvedOptions); resolvedOptions.sourceRoot ??= joinPaths(resolvedOptions.projectRoot, "src"); resolvedOptions.tsconfig ??= getTsconfigFilePath(resolvedOptions.projectRoot, resolvedOptions.tsconfig); context.options = resolvedOptions; context.options.logLevel = context.options.logLevel === "silent" ? null : context.options.logLevel === "success" ? "info" : context.options.logLevel === "trace" || context.options.logLevel === "all" ? "debug" : context.options.logLevel; context.options.userConfig ??= {}; context.options.userConfig.plugins = mergedUserConfig.plugins ?? []; context.options.plugins = { config: { additionalFiles: [] } }; return resolvedOptions; } __name(resolveConfig, "resolveConfig"); function defaultEnvironmentName(options) { if (options.isSsrBuild) { return "ssr"; } if (options.isPreview) { return "preview"; } if (options.platform === "node" || options.isSsrBuild) { return "server"; } if (options.platform === "browser") { return "client"; } return "shared"; } __name(defaultEnvironmentName, "defaultEnvironmentName"); export { defaultEnvironmentName, getParsedTypeScriptConfig, getTsconfigFilePath, isIncludeMatchFound, resolveConfig };