@sanity/pkg-utils
Version:
Simple utilities for modern npm packages.
147 lines (146 loc) • 5.36 kB
JavaScript
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