Skip to content

Commit

Permalink
fix: child kill condition & add start command & default no watch mode (
Browse files Browse the repository at this point in the history
  • Loading branch information
shulandmimi committed May 22, 2024
1 parent 2ca3132 commit 804e90a
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 52 deletions.
8 changes: 8 additions & 0 deletions .changeset/five-dingos-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'farmup': patch
---

1. fmt
2. child kill condition
3. add start command for html
4. default no watch mode
25 changes: 15 additions & 10 deletions src/config/normalize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
ExecuteMode,
type NodeExecuteOption,
type ResolvedCommonOptions,
TargetEnv,
type TargetEnv,
} from '../../types/options';
import { tryFindEntryFromUserConfig, tryFindFormatFromPackage } from './find-entry';
import { isObject, isUndefined, merge, pick } from 'lodash-es';
Expand Down Expand Up @@ -132,7 +132,7 @@ export function normalizedTargetEnv(config: UserConfig, commonOptions: CommonOpt
} else if (config.compilation?.output?.targetEnv) {
options.target = config.compilation.output.targetEnv;
} else {
let targetFromInput;
let targetFromInput: TargetEnv | undefined;

for (const entryFile of Object.values(options.entry)) {
const ext = path.extname(entryFile).slice(1);
Expand Down Expand Up @@ -169,7 +169,7 @@ async function normalizedSimpleConfig(
config: UserConfig,
commonOptions: CommonOptions,
options: ResolvedCommonOptions,
logger: Logger
logger: Logger,
) {
const inputs = await tryFindEntryFromUserConfig(logger, config, commonOptions);

Expand All @@ -191,17 +191,18 @@ async function normalizedSimpleConfig(
? { target: commonOptions.target || config.compilation?.output?.targetEnv }
: {}),
...(commonOptions.autoExternal ? { autoExternal: !!commonOptions.autoExternal } : {}),
noExecute: commonOptions.noExecute || false,
noExecute: commonOptions.noExecute ?? false,
noWatch: commonOptions.noWatch ?? true,
watchFiles: await normalizeWatchFiles(commonOptions),
} as Partial<ResolvedCommonOptions>);

normalizedExecuted(commonOptions, options);
}

function withServerAndWatch(userConfig: UserConfig, resolvedOption: ResolvedCommonOptions): UserConfig {
function withServerOrWatch(userConfig: UserConfig, resolvedOption: ResolvedCommonOptions): UserConfig {
switch (resolvedOption.execute.type) {
case ExecuteMode.Custom: {
merge(userConfig, { compilation: { watch: true }, server: undefined } as UserConfig);
merge(userConfig, { compilation: { watch: !resolvedOption.noWatch }, server: undefined } as UserConfig);
break;
}

Expand All @@ -211,9 +212,10 @@ function withServerAndWatch(userConfig: UserConfig, resolvedOption: ResolvedComm
}
break;
}

case ExecuteMode.Node: {
if (!userConfig.server) {
merge(userConfig, { compilation: { watch: true }, server: {} } as UserConfig);
merge(userConfig, { compilation: { watch: !resolvedOption.noWatch }, server: {} } as UserConfig);
}
break;
}
Expand All @@ -234,12 +236,15 @@ export class NormalizeOption {
watchFiles: [],
};

constructor(private commonOption: CommonOptions, private logger: Logger) {}
constructor(
private commonOption: CommonOptions,
private logger: Logger,
) {}

async config(config: UserConfig): Promise<UserConfig> {
await normalizedSimpleConfig(config, this.commonOption, this.options, this.logger);

return withServerAndWatch(
return withServerOrWatch(
{
compilation: {
input: this.options.entry,
Expand All @@ -250,7 +255,7 @@ export class NormalizeOption {
...pick(this.options, 'minify'),
},
},
this.options
this.options,
);
}

Expand Down
22 changes: 13 additions & 9 deletions src/executer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { ExecaChildProcess, execaCommand } from 'execa';
import { ExecuteMode, ExecuteOption, ResolvedCommonOptions } from './types/options';
import { Logger } from '@farmfe/core';
import { type ExecaChildProcess, execaCommand } from 'execa';
import { ExecuteMode, type ExecuteOption, type ResolvedCommonOptions } from './types/options';
import type { Logger } from '@farmfe/core';
import { delay } from './util/async';

export class Executer {
child?: ExecaChildProcess;

constructor(public option: ExecuteOption, public logger: Logger, public normalizedOption: ResolvedCommonOptions) {}
constructor(
public option: ExecuteOption,
public logger: Logger,
public normalizedOption: ResolvedCommonOptions,
) {}

execute(path: string, name: string, logger = this.logger) {
switch (this.option.type) {
Expand All @@ -26,13 +30,12 @@ export class Executer {
}

async _execute(command: string, name: string, args: string[], logger: Logger) {
if (!this.child) {
if (this.child) {
await this.closeChild();
}

const child = execaCommand([command, ...args].join(' '), {
cwd: process.cwd(),
// TODO: proxy and use logger
stdio: 'pipe',
});

Expand All @@ -55,10 +58,11 @@ export class Executer {

child.on('exit', (code) => {
if (child) {
const message = `"${name}" PID ${child.pid}`;
if (code === 0) {
this.logger.info(`"${name}" PID ${child.pid} done`);
this.logger.info(`${message} done`);
} else {
this.logger.info(`"${name}" PID ${child.pid} killed`);
this.logger.info(`${message} killed`);
}
this.child = undefined;
}
Expand All @@ -68,7 +72,7 @@ export class Executer {
async closeChild() {
while (this.child && !this.child.killed) {
this.child.kill();
await delay(300);
await delay(50);
}
this.child = undefined;
}
Expand Down
45 changes: 26 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
logger,
watch as farmWatch,
start as farmStart,
build as farmBuild,
Expand All @@ -8,12 +7,13 @@ import {
type FarmCLIOptions,
type UserConfig,
version as FarmCoreVersion,
NoopLogger,
} from '@farmfe/core';
import cac from 'cac';
import { readFileSync } from 'node:fs';
import autoExecute, { NormalizeOption } from './plugins/auto-execute';
import { ExecuteMode, type CommonOptions } from './types/options';
import { autoExternal } from './plugins/auto-external';
import autoExternal from './plugins/auto-external';
import path from 'node:path';
import { isString } from 'lodash-es';

Expand Down Expand Up @@ -41,35 +41,35 @@ function createInlineConfig(options: CommonOptions): InlineConfig {
};
}

async function start(options: CommonOptions) {
const preNormalizeOption = await NormalizeOption.fromCommonOption(options, logger);
async function autoStart(options: CommonOptions) {
const preNormalizeOption = await NormalizeOption.fromCommonOption(options, new NoopLogger());
const inlineConfig = createInlineConfig(options);

switch (preNormalizeOption.options.execute.type) {
case ExecuteMode.Browser:
return farmStart(inlineConfig);
case ExecuteMode.Node:
case ExecuteMode.Custom:
return farmBuild(inlineConfig);
return options.noWatch ? farmBuild(inlineConfig) : farmWatch(inlineConfig);
}
}

async function watch(options: CommonOptions) {
async function start(options: CommonOptions) {
const inlineConfig = createInlineConfig(options);
await farmStart(inlineConfig);
}

await farmWatch(inlineConfig).then(() => {
logger.info('watch start...');
});
async function watch(options: CommonOptions) {
const inlineConfig = createInlineConfig(options);
await farmWatch(inlineConfig);
}

async function build(options: CommonOptions) {
if (options.noExecute) {
if (options.noExecute && !options.noWatch) {
await watch(options);
return;
}

const inlineConfig = createInlineConfig(options);

await farmBuild(inlineConfig);
}

Expand All @@ -85,7 +85,7 @@ cli.option(
.option('--no-config', 'if farm.config.[ext] exists, it will be ignore')
.option('--format [format]', 'choose one from "cjs" or "esm"')
.option('--external [...external]', 'external')
.option('--watch [...files]', 'watch files')
.option('--watch [...files]', 'watch files', { default: false })
.option('-w [...file]', 'watch files')
.option('--no-auto-external', 'if not found module, auto as external', { default: true })
.option('--exec [file]', 'custom execute command')
Expand All @@ -94,7 +94,6 @@ cli.option(
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
async function commonOptionsFromArgs(args: Record<string, any>): Promise<Partial<CommonOptions>> {
const root = process.cwd();

const configPath =
typeof args.config === 'string'
? path.isAbsolute(args.config)
Expand All @@ -115,23 +114,31 @@ async function commonOptionsFromArgs(args: Record<string, any>): Promise<Partial
format: args.format,
config: configPath,
minify: args.minify,

noWatch: !args.watch,
noExecute: args.exec === false,
watchFiles: [args.watch, args.w].flat().filter(Boolean),
watchFiles: [args.watch, args.w]
.flat()
.map((item) => (item === true ? undefined : item))
.filter(Boolean),
};
}

cli.command('build [entry]', 'start watch for node or custom command')
cli.command('[entry]', 'start ts/js/html file').action(async (entry, options) => {
autoStart({
entry: Array.isArray(entry) ? entry : [entry].filter(Boolean),
...(await commonOptionsFromArgs(options)),
});
});

cli.command('build [entry]', 'start watch for node or custom command')
.option('--no-exec', 'disable execute')
.action(async (entry, options) => {
build({
entry: Array.isArray(entry) ? entry : [entry].filter(Boolean),
...(await commonOptionsFromArgs(options)),
});
});

cli.command('[entry]', 'start watch for node or custom command').action(async (entry, options) => {
cli.command('start [entry]', 'start server for html file').action(async (entry, options) => {
start({
entry: Array.isArray(entry) ? entry : [entry].filter(Boolean),
...(await commonOptionsFromArgs(options)),
Expand Down
4 changes: 3 additions & 1 deletion src/plugin-entry.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './plugins/auto-execute';
export { default } from './plugins/auto-execute';
export { default as autoExecute } from './plugins/auto-execute';
export { default as autoExternal } from './plugins/auto-external';
export { CLI_NAME, logger } from './config/constant';
12 changes: 8 additions & 4 deletions src/plugins/auto-execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import { Logger, type Resource, type JsPlugin } from '@farmfe/core';
import path from 'node:path';
import { type CommonOptions, ExecuteMode, type ResolvedCommonOptions } from '../types/options';
import { NormalizeOption } from '../config/normalize';
import { autoExternal } from './auto-external';
import { CLI_NAME, logger } from '../config/constant';
import { Executer } from '../executer';

export { CLI_NAME, logger, autoExternal, NormalizeOption, Executer };
export { NormalizeOption, Executer };

function findOutputEntry(resource: Resource[], options: ResolvedCommonOptions) {
const resourceEntry = resource.find((item) => item.info?.data.isEntry);
Expand All @@ -32,7 +31,7 @@ export default function autoExecute(options: CommonOptions = {}): JsPlugin {
const normalize_option = new NormalizeOption(options, logger);

return {
name: `${CLI_NAME}:watcher`,
name: `${CLI_NAME}:execute`,
priority: Number.NEGATIVE_INFINITY,
async config(config) {
const normalizedOption = await normalize_option.config(config);
Expand All @@ -46,6 +45,11 @@ export default function autoExecute(options: CommonOptions = {}): JsPlugin {
if (!compiler.config.config?.watch) {
return;
}

if (options.noWatch) {
return;
}

const entries = Object.values(compiler.config.config?.input ?? {});

if (entries.length === 0) {
Expand Down Expand Up @@ -87,7 +91,7 @@ export default function autoExecute(options: CommonOptions = {}): JsPlugin {
resourceEntry.name,
new Logger({
name: `${CLI_NAME}:${resourceEntry.name}`,
})
}),
);
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/auto-external.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { JsPlugin, PluginResolveHookResult } from '@farmfe/core';
import { CLI_NAME, logger } from '../config/constant';

export function autoExternal(): JsPlugin {
export default function autoExternal(): JsPlugin {
return {
priority: Number.NEGATIVE_INFINITY,
name: `${CLI_NAME}:AutoExternal`,
Expand Down
21 changes: 13 additions & 8 deletions src/types/options.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { UserConfig } from '@farmfe/core';
import type { UserConfig } from '@farmfe/core';

export type TargetEnv = Exclude<Required<Required<UserConfig>['compilation']>['output']['targetEnv'], undefined | null>;

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
type Get<T extends Record<keyof any, any>, K extends keyof any> = K extends `${infer PREFIX}.${infer LAST}`
? Get<Exclude<T[PREFIX], undefined>, LAST>
: K extends keyof T
? T[K]
: never;
? T[K]
: never;

export type Format = Get<UserConfig, 'compilation.output.format'>
export type Format = Get<UserConfig, 'compilation.output.format'>;

export interface CommonOptions {
/** entry, if not found, it will be find from default file or directory */
Expand Down Expand Up @@ -47,6 +48,8 @@ export interface CommonOptions {
/** auto external */
autoExternal?: boolean;

noWatch?: boolean;

noExecute?: boolean;

root?: string;
Expand All @@ -68,13 +71,15 @@ export interface ResolvedCommonOptions {

noExecute: boolean;

watchFiles: string[]
watchFiles: string[];

noWatch?: boolean;
}

export enum ExecuteMode {
Custom,
Node,
Browser,
Custom = 1,
Node = 2,
Browser = 3,
}

interface CustomExecuteOption {
Expand Down

0 comments on commit 804e90a

Please sign in to comment.