Skip to content

Commit

Permalink
feat: support watcher
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Feb 15, 2024
1 parent 9c6e747 commit 13e391b
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 36 deletions.
12 changes: 12 additions & 0 deletions docs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Adds two numbers together.
*
* @example
*
* ```js
* add(1, 2); // 3
* ```
*/
export function add(a: number, b: number) {
return a + b;
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"test:types": "tsc --noEmit --skipLibCheck"
},
"dependencies": {
"@parcel/watcher": "^2.4.0",
"c12": "^1.7.0",
"citty": "^0.1.5",
"consola": "^3.2.3",
Expand Down
145 changes: 145 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

87 changes: 73 additions & 14 deletions src/automd.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { existsSync, promises as fsp } from "node:fs";
import { resolve, relative } from "pathe";
import type { SubscribeCallback } from "@parcel/watcher";
import type { Config, ResolvedConfig } from "./config";
import { TransformResult, transform } from "./transform";
import { type TransformResult, transform } from "./transform";
import { loadConfig } from "./config";

export interface AutomdResult extends TransformResult {
_config: ResolvedConfig;
input: string;
output: string;
}

export async function automd(_config: Config = {}): Promise<AutomdResult[]> {
export async function automd(
_config: Config = {},
): Promise<{ results: AutomdResult[]; _config: ResolvedConfig; time: number }> {
const config = await loadConfig(_config.dir, _config);

let inputFiles = config.input;
Expand All @@ -20,40 +22,97 @@ export async function automd(_config: Config = {}): Promise<AutomdResult[]> {
cwd: config.dir,
absolute: false,
onlyFiles: true,
ignore: ["node_modules", "dist", ".*", ...(config.ignore || [])],
ignore: config.ignore,
});
} else {
inputFiles = inputFiles
.map((i) => resolve(config.dir, i))
.filter((i) => existsSync(i))
.map((i) => relative(config.dir, i));
}
const multiFiles = inputFiles.length > 1;

return Promise.all(
inputFiles.map((i) => _automd(i, config, inputFiles.length > 1)),
const cache: ResultCache = new Map();

const start = performance.now();
const results = await Promise.all(
inputFiles.map((i) => _automd(i, config, multiFiles, cache)),
);
const time = Math.round((performance.now() - start) * 1000) / 1000;

if (config.watch) {
await _watch(inputFiles, config, multiFiles, cache);
}

return {
_config: config,
time,
results,
};
}

export async function _automd(
// -- internal --

type ResultCache = Map<string, AutomdResult>;

async function _automd(
relativeInput: string,
config: ResolvedConfig,
multi: boolean,
multiFiles: boolean,
cache: ResultCache,
): Promise<AutomdResult> {
const input = resolve(config.dir, relativeInput);
const contents = await fsp.readFile(input, "utf8");

const result = await transform(contents, config);
const cachedResult = await cache.get(input);
if (cachedResult?.contents === contents) {
return cachedResult;
}

const transformResult = await transform(contents, config);

const output = multi
const output = multiFiles
? resolve(config.dir, config.output || ".", relativeInput)
: resolve(config.dir, config.output || relativeInput);

await fsp.writeFile(output, result.contents, "utf8");
await fsp.writeFile(output, transformResult.contents, "utf8");

return {
_config: config,
const result: AutomdResult = {
input,
output,
...result,
...transformResult,
};
cache.set(input, result);
return result;
}

async function _watch(
inputFiles: string[],
config: ResolvedConfig,
multiFiles: boolean,
cache: ResultCache,
) {
const watcher = await import("@parcel/watcher");

const watchCb: SubscribeCallback = async (_err, events) => {
const filesToUpdate = events
.map((e) => relative(config.dir, e.path))
.filter((p) => inputFiles.includes(p));
const start = performance.now();
const results = await Promise.all(
filesToUpdate.map((f) => _automd(f, config, multiFiles, cache)),
);
const time = performance.now() - start;
if (config.onWatch) {
config.onWatch({ results, time });
}
};

const subscription = await watcher.subscribe(config.dir, watchCb, {
ignore: config.ignore,
});

process.on("SIGINT", () => {
subscription.unsubscribe();
});
}
Loading

0 comments on commit 13e391b

Please sign in to comment.