UNPKG

@sanity/pkg-utils

Version:

Simple utilities for modern npm packages.

147 lines (146 loc) 5.36 kB
import path from "node:path"; import { Observable, switchMap } from "rxjs"; import { getTargetPaths, loadConfig, loadPkgWithReporting, resolveBuildContext } from "./consoleSpy.js"; import { createLogger } from "./isRecord.js"; import { watchTaskHandlers } from "./index.js"; import { scan, startWith, distinctUntilChanged } from "rxjs/operators"; import globby from "globby"; import * as chokidar from "chokidar"; function resolveWatchTasks(ctx) { const { pkg, target } = ctx, tasks = [], exports = Object.entries(ctx.exports || {}).map( ([_path, exp]) => ({ _path, ...exp }) ), dtsTask = { type: "watch:dts", entries: [] }, rollupTasks = {}; function addRollupTaskEntry(format, runtime, entry) { const buildId = `${format}:${runtime}`; rollupTasks[buildId] ? rollupTasks[buildId].entries.push(entry) : rollupTasks[buildId] = { type: "watch:js", buildId, entries: [entry], runtime, format, target: target[runtime] }; } for (const exp of exports) { const importId = path.join(pkg.name, exp._path); exp.source?.endsWith(".ts") && dtsTask.entries.push({ importId, exportPath: exp._path, sourcePath: exp.source, targetPaths: getTargetPaths(pkg.type, exp) }), exp.browser?.source?.endsWith(".ts") && dtsTask.entries.push({ importId, exportPath: exp._path, sourcePath: exp.browser.source, targetPaths: getTargetPaths(pkg.type, exp.browser) }), exp.node?.source?.endsWith(".ts") && dtsTask.entries.push({ importId, exportPath: exp._path, sourcePath: exp.node.source, targetPaths: getTargetPaths(pkg.type, exp.node) }); } for (const exp of exports) { const output = exp.require; output && addRollupTaskEntry("commonjs", ctx.runtime, { path: exp._path, source: exp.source, output }); } for (const exp of exports) { const output = exp.browser?.require; output && addRollupTaskEntry("commonjs", "browser", { path: exp._path, source: exp.browser?.source || exp.source, output }); } for (const exp of exports) { const output = exp.import; output && addRollupTaskEntry("esm", ctx.runtime, { path: exp._path, source: exp.source, output }); } for (const exp of exports) { const output = exp.browser?.import; output && addRollupTaskEntry("esm", "browser", { path: exp._path, source: exp.browser?.source || exp.source, output }); } return dtsTask.entries.length && tasks.push(dtsTask), tasks.push(...Object.values(rollupTasks)), tasks; } function globFiles(patterns) { return globby(patterns.map((pattern) => pattern.split(path.sep).join(path.posix.sep))); } function watchFiles(patterns) { return new Observable((observer) => { const watcher = chokidar.watch(patterns, { ignoreInitial: !0 }); function handleFileEvent(type, file) { type === "error" || file instanceof Error ? observer.error(file) : observer.next({ type, file }); } return watcher.on("all", handleFileEvent), () => { watcher.off("all", handleFileEvent), watcher.close(); }; }); } async function watchConfigFiles(options) { const { cwd, logger } = options, initialFiles = await globFiles([ path.resolve(cwd, "package.json"), path.resolve(cwd, "package.config.cjs"), path.resolve(cwd, "package.config.js"), path.resolve(cwd, "package.config.ts") ]); return watchFiles([ path.resolve(cwd, "package.json"), path.resolve(cwd, "package.config.cjs"), path.resolve(cwd, "package.config.js"), path.resolve(cwd, "package.config.ts") ]).pipe( scan((files, fileEvent) => fileEvent.type === "add" ? files.concat(fileEvent.file) : fileEvent.type === "unlink" ? files.filter((f) => f !== fileEvent.file) : fileEvent.type === "change" ? (logger.log( "--------------------------------------------------------------------------------" ), logger.info(path.relative(cwd, fileEvent.file), "changed"), logger.log(""), files.slice(0)) : files, initialFiles), startWith(initialFiles), distinctUntilChanged() ); } async function watch(options) { const { cwd, strict = !1, tsconfig: tsconfigOption } = options, logger = createLogger(); (await watchConfigFiles({ cwd, logger })).pipe( switchMap(async (configFiles) => { if (!configFiles.map((f) => path.relative(cwd, f)).find((f) => f === "package.json")) throw new Error("missing package.json"); const config = await loadConfig({ cwd }), pkg = await loadPkgWithReporting({ cwd, logger, strict }), tsconfig = tsconfigOption || config?.tsconfig || "tsconfig.json"; return resolveBuildContext({ config, cwd, logger, pkg, strict, tsconfig }); }) ).subscribe(async (ctx) => { const watchTasks = resolveWatchTasks(ctx); for (const task of watchTasks) { const handler = watchTaskHandlers[task.type]; handler.exec(ctx, task).subscribe({ error: (err) => { ctx.logger.error(err), ctx.logger.log(), process.exit(1); }, next: (result) => { handler.complete(ctx, task, result); }, complete: () => { ctx.logger.success(handler.name(ctx, task)), ctx.logger.log(); } }); } }); } export { watch }; //# sourceMappingURL=watch.js.map