UNPKG

@storm-stack/core

Version:

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

203 lines (200 loc) 8.61 kB
import { restoreVfs, createVfs, __VFS_VIRTUAL__ } from './chunk-4PZQYL6T.js'; import { resolveConfig } from './chunk-3SXIWFA7.js'; import { getParsedTypeScriptConfig } from './chunk-F3VGKNLX.js'; import { createLog } from './chunk-OKGWWQFP.js'; import { createResolver } from './chunk-XFWES7LF.js'; import { __name } from './chunk-IRPJW6HH.js'; import { LogLevelLabel } from '@storm-software/config-tools/types'; import { getEnvPaths } from '@stryke/env/get-env-paths'; import { existsSync } from '@stryke/fs/exists'; import { getWorkspaceRoot, getProjectRoot, relativeToWorkspaceRoot } from '@stryke/fs/get-workspace-root'; import { readJsonFile } from '@stryke/fs/json'; import { listFiles } from '@stryke/fs/list-files'; import { removeFile } from '@stryke/fs/remove-file'; import { resolvePackage } from '@stryke/fs/resolve'; import { hash } from '@stryke/hash/hash'; import { hashDirectory } from '@stryke/hash/hash-files'; import { getUnique } from '@stryke/helpers/get-unique'; import { hasFileExtension } from '@stryke/path/file-path-fns'; import { joinPaths } from '@stryke/path/join-paths'; import { kebabCase } from '@stryke/string-format/kebab-case'; import { uuid } from '@stryke/unique-id/uuid'; import defu from 'defu'; var PROJECT_ROOT_HASH_LENGTH = 45; function getPrefixedProjectRootHash(name, projectRootHash) { const combined = `${kebabCase(name)}_${projectRootHash}`; return combined.length > PROJECT_ROOT_HASH_LENGTH ? combined.slice(0, PROJECT_ROOT_HASH_LENGTH) : combined; } __name(getPrefixedProjectRootHash, "getPrefixedProjectRootHash"); async function discoverTemplatePath(path) { return (await Promise.all([ Promise.resolve(/.tsx?$/.test(path) && !path.includes("*") && path), Promise.resolve(!hasFileExtension(path) && joinPaths(path, ".ts")), Promise.resolve(!hasFileExtension(path) && joinPaths(path, ".tsx")), Promise.resolve(!hasFileExtension(path) && listFiles(joinPaths(path, "**/*.ts"))), Promise.resolve(!hasFileExtension(path) && listFiles(joinPaths(path, "**/*.tsx"))) ])).flat().filter(Boolean); } __name(discoverTemplatePath, "discoverTemplatePath"); async function discoverTemplates(context, paths = []) { return getUnique((await Promise.all([ ...paths.map(discoverTemplatePath), discoverTemplatePath(joinPaths(context.options.sourceRoot, "plugin")), discoverTemplatePath(joinPaths(context.envPaths.config, "templates")), discoverTemplatePath(joinPaths(context.options.projectRoot, "templates")) ])).flat().reduce((ret, path) => { if (existsSync(path)) { ret.push(path); } return ret; }, [])); } __name(discoverTemplates, "discoverTemplates"); async function getChecksum(path) { return hashDirectory(path, { ignore: [ "node_modules", ".git", ".nx", ".cache", ".storm", "tmp", "dist" ] }); } __name(getChecksum, "getChecksum"); async function getPersistedMeta(context) { const metaFilePath = joinPaths(context.dataPath, "meta.json"); if (existsSync(metaFilePath)) { try { return await readJsonFile(metaFilePath); } catch { context.log(LogLevelLabel.WARN, `Failed to read meta file at ${metaFilePath}. It may be corrupted.`); await removeFile(metaFilePath); context.persistedMeta = void 0; } } return void 0; } __name(getPersistedMeta, "getPersistedMeta"); async function createContext(inlineConfig, workspaceConfig, options = {}) { const workspaceRoot = workspaceConfig?.workspaceRoot ?? getWorkspaceRoot(); const projectRoot = (inlineConfig.root ?? getProjectRoot()) || process.cwd(); const resolvedWorkspaceConfig = defu(workspaceConfig, { workspaceRoot }); let projectJson; const projectJsonPath = joinPaths(projectRoot, "project.json"); if (existsSync(projectJsonPath)) { projectJson = await readJsonFile(projectJsonPath); } let packageJson; const packageJsonPath = joinPaths(projectRoot, "package.json"); if (existsSync(packageJsonPath)) { packageJson = await readJsonFile(packageJsonPath); } else if (inlineConfig.command === "new") { const workspacePackageJsonPath = joinPaths(workspaceRoot, "package.json"); packageJson = await readJsonFile(workspacePackageJsonPath); resolvedWorkspaceConfig.repository ??= typeof packageJson?.repository === "string" ? packageJson.repository : packageJson?.repository?.url; } else { throw new Error(`The package.json file is missing in the project root directory: ${projectRoot}. Please run the "new" command to create a new Storm Stack project.`); } const checksum = await getChecksum(projectRoot); const meta = { buildId: uuid(), releaseId: uuid(), checksum, timestamp: Date.now(), projectRootHash: hash(joinPaths(workspaceRoot, projectRoot), { maxLength: PROJECT_ROOT_HASH_LENGTH }), runtimeIdMap: {}, virtualFiles: {} }; const artifactsPath = joinPaths(workspaceRoot, projectRoot, ".storm"); const runtimePath = joinPaths(artifactsPath, "runtime"); const entryPath = joinPaths(artifactsPath, "entry"); const envPaths = getEnvPaths({ orgId: "storm-software", appId: "storm-stack", workspaceRoot }); if (!envPaths.cache) { throw new Error("The cache directory could not be determined."); } envPaths.cache = joinPaths(envPaths.cache, "projects", meta.projectRootHash); const partiallyResolvedContext = { options: { ...resolvedWorkspaceConfig, name: projectJson?.name || options.name, ...inlineConfig, userConfig: { config: {} }, inlineConfig, projectRoot, workspaceConfig: resolvedWorkspaceConfig, plugins: {} }, log: createLog(options.name ?? null, defu(inlineConfig, resolvedWorkspaceConfig)), meta, entry: [], envPaths, artifactsPath, runtimePath, entryPath, dtsPath: joinPaths(envPaths.cache, "dts"), runtimeDtsFilePath: joinPaths(projectRoot, "storm.d.ts"), dataPath: joinPaths(envPaths.data, "projects", meta.projectRootHash), cachePath: envPaths.cache, projectJson, packageJson, runtime: { logs: [], storage: [], init: [] }, packageDeps: {}, reflections: {}, resolver: createResolver({ workspaceRoot, projectRoot, cacheDir: envPaths.cache }), relativeToWorkspaceRoot: relativeToWorkspaceRoot(projectRoot) }; const resolvedOptions = await resolveConfig(partiallyResolvedContext, inlineConfig, void 0, projectRoot); const context = partiallyResolvedContext; context.options = resolvedOptions; context.dataPath = joinPaths(context.envPaths.data, "projects", getPrefixedProjectRootHash(context.options.name, context.meta.projectRootHash)); context.persistedMeta = await getPersistedMeta(context); context.runtimeDtsFilePath = context.options.output.dts ? context.options.output.dts.startsWith(context.options.workspaceRoot) ? context.options.output.dts : joinPaths(context.options.workspaceRoot, context.options.output.dts) : joinPaths(context.options.workspaceRoot, context.options.projectRoot, "storm.d.ts"); context.tsconfig = getParsedTypeScriptConfig(context.options.workspaceRoot, context.options.projectRoot, context.options.tsconfig); if (context.persistedMeta?.checksum === context.meta.checksum) { context.log(LogLevelLabel.TRACE, `Restoring the virtual file system (VFS) as the meta checksum has not changed.`); context.vfs = restoreVfs(context, { runtimeIdMap: context.persistedMeta.runtimeIdMap, virtualFiles: context.persistedMeta.virtualFiles }); } else { context.vfs = createVfs(context); } const packagePath = process.env.STORM_STACK_LOCAL ? joinPaths(context.options.workspaceRoot, "dist/packages/core") : await resolvePackage("@storm-stack/core"); if (!packagePath) { throw new Error("Could not resolve the Storm Stack core package. Please ensure it is installed."); } return context; } __name(createContext, "createContext"); async function writeMetaFile(context) { const metaFilePath = joinPaths(context.dataPath, "meta.json"); context.log(LogLevelLabel.DEBUG, `Writing runtime metadata to ${metaFilePath}`); await context.vfs.writeFileToDisk(metaFilePath, JSON.stringify({ ...context.meta, runtimeIdMap: Object.fromEntries(context.vfs.runtimeIdMap.entries()), virtualFiles: context.vfs[__VFS_VIRTUAL__].toJSON(context.artifactsPath) }, null, 2)); } __name(writeMetaFile, "writeMetaFile"); export { PROJECT_ROOT_HASH_LENGTH, createContext, discoverTemplates, getChecksum, getPersistedMeta, getPrefixedProjectRootHash, writeMetaFile };