diff --git a/farm.config.ts b/farm.config.ts index f86ea88..bbebeeb 100644 --- a/farm.config.ts +++ b/farm.config.ts @@ -1,5 +1,4 @@ import { defineConfig } from '@farmfe/core'; -import dts from '@farmfe/js-plugin-dts'; export default defineConfig({ compilation: { @@ -10,10 +9,10 @@ export default defineConfig({ }, output: { targetEnv: 'node', + format: 'esm' }, persistentCache: false, external: ['^@farmfe/core$'], minify: false, }, - // plugins: [dts()], }); diff --git a/package.json b/package.json index 19acbe5..0bf51c8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ }, "devDependencies": { "@farmfe/cli": "^1.0.2", - "@farmfe/js-plugin-dts": "^0.5.1", "@types/fs-extra": "^11.0.4", "@types/lodash-es": "^4.17.12", "@types/node": "^20.12.7", diff --git a/playground/index.html b/playground/index.html new file mode 100644 index 0000000..15a4494 --- /dev/null +++ b/playground/index.html @@ -0,0 +1,2 @@ + +

hello farmup

diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a85907..490da34 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,9 +36,6 @@ importers: '@farmfe/cli': specifier: ^1.0.2 version: 1.0.2 - '@farmfe/js-plugin-dts': - specifier: ^0.5.1 - version: 0.5.1 '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 @@ -200,9 +197,6 @@ packages: resolution: {integrity: sha512-RBXzPDRkaLr8ccKmRq6pQTH4h2UzwiB5CkqvNwTPbBUHn3kTnjGcEVjbZbvAqXPHd1nCGan6OI/MMFm3NxAuVQ==} engines: {node: '>=16.15.1'} - '@farmfe/js-plugin-dts@0.5.1': - resolution: {integrity: sha512-Y5U7/KyubdtXz1NqWs8jgldoBWaBMXoa0E32HGQRYa+1RovyMP+9VI9RBJvB0TEtEWK772vccPGDJ+b0DTPMMA==} - '@farmfe/runtime-plugin-hmr@3.5.2': resolution: {integrity: sha512-d2zvBfLtBj0iNxhaRtcLIqnNRUspQLOQTiRZ228rtGtqfZ6CPa6l6d8T530+uaWKR8KD5Rf55ZCglQrkakuPZA==} @@ -259,9 +253,6 @@ packages: '@swc/helpers@0.5.10': resolution: {integrity: sha512-CU+RF9FySljn7HVSkkjiB84hWkvTaI3rtLvF433+jRSBL2hMu3zX5bGhHS8C80SM++h4xy8hBSnUHFQHmRXSBw==} - '@ts-morph/common@0.20.0': - resolution: {integrity: sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q==} - '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} @@ -493,9 +484,6 @@ packages: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - code-block-writer@12.0.0: - resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -1272,10 +1260,6 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - minimatch@7.4.6: - resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} - engines: {node: '>=10'} - minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1292,11 +1276,6 @@ packages: resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} engines: {node: '>= 8.0.0'} - mkdirp@2.1.6: - resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} - engines: {node: '>=10'} - hasBin: true - ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -1414,9 +1393,6 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1757,9 +1733,6 @@ packages: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} - ts-morph@19.0.0: - resolution: {integrity: sha512-D6qcpiJdn46tUqV45vr5UGM2dnIEuTGNxVhg0sk5NX11orcouwj6i1bMqZIz2mZTZB1Hcgy7C3oEVhAT+f6mbQ==} - tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -2201,13 +2174,6 @@ snapshots: - supports-color - utf-8-validate - '@farmfe/js-plugin-dts@0.5.1': - dependencies: - chalk: 5.3.0 - fast-glob: 3.3.2 - fs-extra: 11.2.0 - ts-morph: 19.0.0 - '@farmfe/runtime-plugin-hmr@3.5.2': dependencies: core-js: 3.37.0 @@ -2278,13 +2244,6 @@ snapshots: dependencies: tslib: 2.6.2 - '@ts-morph/common@0.20.0': - dependencies: - fast-glob: 3.3.2 - minimatch: 7.4.6 - mkdirp: 2.1.6 - path-browserify: 1.0.1 - '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 @@ -2530,8 +2489,6 @@ snapshots: co@4.6.0: {} - code-block-writer@12.0.0: {} - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -3370,10 +3327,6 @@ snapshots: min-indent@1.0.1: {} - minimatch@7.4.6: - dependencies: - brace-expansion: 2.0.1 - minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 @@ -3388,8 +3341,6 @@ snapshots: mixme@0.5.10: {} - mkdirp@2.1.6: {} - ms@2.1.2: {} ms@2.1.3: {} @@ -3507,8 +3458,6 @@ snapshots: parseurl@1.3.3: {} - path-browserify@1.0.1: {} - path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -3837,11 +3786,6 @@ snapshots: trim-newlines@3.0.1: {} - ts-morph@19.0.0: - dependencies: - '@ts-morph/common': 0.20.0 - code-block-writer: 12.0.0 - tslib@2.6.2: {} tsscmp@1.0.6: {} diff --git a/src/config/normalize/find-entry.ts b/src/config/normalize/find-entry.ts index 05704c3..63bd1a6 100644 --- a/src/config/normalize/find-entry.ts +++ b/src/config/normalize/find-entry.ts @@ -1,8 +1,7 @@ -import { Logger, UserConfig } from '@farmfe/core'; +import type { Logger, UserConfig } from '@farmfe/core'; import { readFile, stat } from 'fs-extra'; import path from 'node:path'; -import { CommonOptions, Format, ResolvedCommonOptions } from '../../types/options'; -import { merge } from 'lodash-es'; +import { ExecuteMode, type CommonOptions, type Format, type ResolvedCommonOptions } from '../../types/options'; import { isExists } from '../../util/file'; const findEntryKeyFromObject = (input: Record) => { @@ -48,7 +47,7 @@ function normalizeCommonEntry(entries: CommonOptions['entry']): ResolvedCommonOp const [key, ...value] = result; - let file = value.join(':'); + const file = value.join(':'); if (!key) { throw new Error(`"${entry}" key is empty`); @@ -62,8 +61,8 @@ function normalizeCommonEntry(entries: CommonOptions['entry']): ResolvedCommonOp const normalizedEntries: Record = {}; - let map: Record = {}; - let sameMap = new Set(); + const map: Record = {}; + const sameMap = new Set(); for (const entry of entries ?? []) { const result = parseSingleEntry(entry); @@ -72,26 +71,22 @@ function normalizeCommonEntry(entries: CommonOptions['entry']): ResolvedCommonOp if (sameMap.has(value)) { continue; - } else { - sameMap.add(value); } - const find_uniq_key = (key?: string, suffix = '') => { - if (!key) { - key = 'index'; - } + sameMap.add(value); - let newKey = key + suffix; + const find_uniq_key = (key?: string, suffix = '') => { + const newKey = (key ?? 'index') + suffix; if (map[newKey]) { map[newKey]++; return find_uniq_key(key, map[newKey].toString()); - } else { - map[newKey] = 1; - return newKey; } + + map[newKey] = 1; + return newKey; }; - let uniq_key = find_uniq_key(key); + const uniq_key = find_uniq_key(key); normalizedEntries[uniq_key] = value; } @@ -100,26 +95,30 @@ function normalizeCommonEntry(entries: CommonOptions['entry']): ResolvedCommonOp } export async function tryFindEntryFromUserConfig(logger: Logger, config: UserConfig, options: CommonOptions) { - const entries_from_option = normalizeCommonEntry(options.entry); + const entriesFromOption = normalizeCommonEntry(options.entry); + + // cli option > config + if (entriesFromOption) { + return entriesFromOption; + } let findEntryKey = findEntryKeyFromObject(config.compilation?.input ?? {}); + + if (findEntryKey) return config.compilation?.input!; + let findEntry: string | null = null; - if (!entries_from_option && !findEntryKey) { - findEntry = await findDefaultExistsEntry(); - findEntryKey = 'index'; - if (!findEntry) { - logger.error('entry is not found, please check your entry file', { exit: true }); - process.exit(1); - } else { - logger.info(`find and use this entry: "${findEntry}"`); - } - return { - [findEntryKey]: findEntry, - }; + findEntry = await findDefaultExistsEntry(); + findEntryKey = 'index'; + if (!findEntry) { + logger.error('entry is not found, please check your entry file correct', { exit: true }); + process.exit(1); } else { - return merge(entries_from_option, config.compilation?.input ?? {}); + logger.info(`automatic find and use this entry: "${findEntry}"`); } + return { + [findEntryKey]: findEntry, + }; } const packageModuleValueMapFormat: Record = { @@ -141,3 +140,29 @@ export async function tryFindFormatFromPackage(root: string): Promise, string> = { + cjs: 'js', + esm: 'mjs', +}; + +export function pinOutputEntryFilename(options: ResolvedCommonOptions) { + if (options.noExecute) return; + + const executeMode = options.execute.type; + + function matchEntryName(name: string, inputs: Record) { + const inputNameKey = name.split('.').slice(0, -1).join('.'); + + if (Object.hasOwn(inputs, inputNameKey)) { + return name; + } + } + + if (executeMode === ExecuteMode.Custom || executeMode === ExecuteMode.Node) { + options.outputEntry = { + matchEntryName, + name: `[entryName].${formatMapExt[options.format ?? 'cjs']}`, + }; + } +} diff --git a/src/config/normalize/index.ts b/src/config/normalize/index.ts index db6e7d3..f175466 100644 --- a/src/config/normalize/index.ts +++ b/src/config/normalize/index.ts @@ -6,25 +6,15 @@ import { type ResolvedCommonOptions, type TargetEnv, } from '../../types/options'; -import { tryFindEntryFromUserConfig, tryFindFormatFromPackage } from './find-entry'; +import { pinOutputEntryFilename, tryFindEntryFromUserConfig, tryFindFormatFromPackage } from './find-entry'; import { isObject, isUndefined, merge, pick } from 'lodash-es'; import path from 'node:path'; import { isExists } from '../../util/file'; import { glob } from 'glob'; -function normalizedCompilation(config: UserConfig) { - if (!config.compilation) { - config.compilation = {}; - } -} - function normalizedMinify(config: UserConfig, commonOptions: CommonOptions, options: ResolvedCommonOptions) { if (!isUndefined(commonOptions.minify)) { - if (!config.compilation) { - config.compilation = {}; - } - - const minify = config.compilation.minify; + const minify = config.compilation?.minify; if (typeof minify === 'boolean' || (isObject(minify) && minify !== null)) { options.minify = commonOptions.minify; } @@ -52,14 +42,14 @@ function normalizedExecuted(commonOption: CommonOptions, options: ResolvedCommon const target = commonOption.target; if (target) { - if (target.startsWith('node')) { + if (target.includes('browser')) { options.execute = { - type: ExecuteMode.Node, + type: ExecuteMode.Browser, args: commonOption.args ?? [], }; - } else if (target.startsWith('browser')) { + } else if (target.includes('node')) { options.execute = { - type: ExecuteMode.Browser, + type: ExecuteMode.Node, args: commonOption.args ?? [], }; } @@ -121,14 +111,18 @@ const extMapTargetEnv: Record = { htm: 'browser', }; -export function normalizedTargetEnv(config: UserConfig, commonOptions: CommonOptions, options: ResolvedCommonOptions) { +export function normalizedTargetEnv( + config: UserConfig, + commonOptions: CommonOptions, + options: ResolvedCommonOptions, + logger: Logger, +) { config.compilation?.output?.targetEnv; - if (commonOptions.target && invalidTargetEnv.includes(commonOptions.target)) { + if (commonOptions.target) { + if (!invalidTargetEnv.includes(commonOptions.target)) { + logger.error(`target ${commonOptions.target} is invalid`); + } options.target = commonOptions.target; - } else if (commonOptions.target?.startsWith('node')) { - options.target = 'node'; - } else if (commonOptions.target?.startsWith('browser')) { - options.target = 'browser'; } else if (config.compilation?.output?.targetEnv) { options.target = config.compilation.output.targetEnv; } else { @@ -151,6 +145,7 @@ export function normalizedTargetEnv(config: UserConfig, commonOptions: CommonOpt async function normalizeWatchFiles(commonOptions: CommonOptions) { const watchFiles = commonOptions.watchFiles ?? []; const result = []; + for (const file of watchFiles) { if (await isExists(file)) { result.push(file); @@ -175,10 +170,10 @@ async function normalizedSimpleConfig( options.entry = inputs; - normalizedCompilation(config); + config.compilation ??= {}; normalizedMinify(config, commonOptions, options); await normalizedFormat(config, commonOptions, options); - normalizedTargetEnv(config, commonOptions, options); + normalizedTargetEnv(config, commonOptions, options, logger); merge(options, { ...(commonOptions.mode || config.compilation?.mode @@ -197,6 +192,8 @@ async function normalizedSimpleConfig( } as Partial); normalizedExecuted(commonOptions, options); + + pinOutputEntryFilename(options); } function withServerOrWatch(userConfig: UserConfig, resolvedOption: ResolvedCommonOptions): UserConfig { @@ -208,14 +205,14 @@ function withServerOrWatch(userConfig: UserConfig, resolvedOption: ResolvedCommo case ExecuteMode.Browser: { if (!userConfig.server) { - merge(userConfig, { server: { port: 12304, cors: true } } as UserConfig); + merge(userConfig, { server: { port: 12306, cors: true } } as UserConfig); } break; } case ExecuteMode.Node: { if (!userConfig.server) { - merge(userConfig, { compilation: { watch: !resolvedOption.noWatch }, server: {} } as UserConfig); + merge(userConfig, { compilation: { watch: !resolvedOption.noWatch }, server: undefined } as UserConfig); } break; } @@ -243,7 +240,6 @@ export class NormalizeOption { async config(config: UserConfig): Promise { await normalizedSimpleConfig(config, this.commonOption, this.options, this.logger); - return withServerOrWatch( { compilation: { @@ -251,6 +247,7 @@ export class NormalizeOption { output: { ...pick(this.options, ['format', 'mode']), ...(this.options.target ? { targetEnv: this.options.target } : {}), + ...(this.options.outputEntry ? { entryFilename: this.options.outputEntry.name } : {}), }, ...pick(this.options, 'minify'), }, diff --git a/src/executer.ts b/src/core/executer.ts similarity index 94% rename from src/executer.ts rename to src/core/executer.ts index dd1510e..76c6c22 100644 --- a/src/executer.ts +++ b/src/core/executer.ts @@ -1,8 +1,8 @@ import { type ExecaChildProcess, execaCommand } from 'execa'; -import { ExecuteMode, type ExecuteOption, type ResolvedCommonOptions } from './types/options'; +import { ExecuteMode, type ExecuteOption, type ResolvedCommonOptions } from '../types/options'; import type { Logger } from '@farmfe/core'; -import { delay } from './util/async'; -import { trimEndLF } from './util/log'; +import { delay } from '../util/async'; +import { trimEndLF } from '../util/log'; export class Executer { child?: ExecaChildProcess; diff --git a/src/core/proxyCompiler/index.ts b/src/core/proxyCompiler/index.ts new file mode 100644 index 0000000..7222fb9 --- /dev/null +++ b/src/core/proxyCompiler/index.ts @@ -0,0 +1,61 @@ +import type { Compiler } from '@farmfe/core'; +import EventEmitter from 'node:events'; +import { proxyCompilerFn } from './util'; +import type { FnContext, OmitFnReturn } from './interface'; + +export class ProxyCompiler { + private compiler!: Compiler; + + private event: EventEmitter = new EventEmitter(); + + private lastResources: string[] = []; + private _preProxyFnList: (keyof Compiler)[] = []; + + start(compiler: Compiler) { + this.compiler = compiler; + + if (this._preProxyFnList.length) { + for (const fnName of this._preProxyFnList) { + this.proxyCompiler(fnName); + } + + this._preProxyFnList = []; + } + this.on('resources', (r) => { + this.lastResources = Object.keys(r.result); + }); + } + + get resource_names() { + return this.lastResources; + } + + proxyCompiler(fnName: K) { + if (!this.compiler) { + this._preProxyFnList.push(fnName); + return; + } + // biome-ignore lint/suspicious/noExplicitAny: + proxyCompilerFn(this.compiler, fnName, (...args: any[]) => this.event.emit(fnName, ...args)); + } + + private on< + T extends Compiler, + K extends keyof OFT, + // biome-ignore lint/suspicious/noExplicitAny: + OFT extends Record any> = { + // biome-ignore lint/suspicious/noExplicitAny: + [KK in keyof T]: T[KK] extends (...args: any[]) => any ? T[KK] : never; + }, + >(fnName: K, fn: (context: FnContext, ReturnType>) => void) { + this.proxyCompiler(fnName as keyof Compiler); + this.event.on(fnName.toString(), fn); + return () => { + this.event.off(fnName.toString(), fn); + }; + } + + onWriteResourcesToDisk(handler: OmitFnReturn) { + return this.on('writeResourcesToDisk', (r) => handler(...r.args)); + } +} diff --git a/src/core/proxyCompiler/interface.ts b/src/core/proxyCompiler/interface.ts new file mode 100644 index 0000000..afaa801 --- /dev/null +++ b/src/core/proxyCompiler/interface.ts @@ -0,0 +1,17 @@ +import type { Compiler } from '@farmfe/core'; + +export type FnKeys = { + // biome-ignore lint/suspicious/noExplicitAny: + [K in keyof T]: T[K] extends (...arg: any[]) => any ? K : never; +}[keyof T]; + +// biome-ignore lint/suspicious/noExplicitAny: +export type OmitFnReturn = T extends (...args: infer Arg) => any ? (...args: Arg) => void : T; + +export type CompilerFnKeys = FnKeys; + +// biome-ignore lint/suspicious/noExplicitAny: +export interface FnContext { + args: Args; + result: R; +} diff --git a/src/core/proxyCompiler/util.ts b/src/core/proxyCompiler/util.ts new file mode 100644 index 0000000..1109630 --- /dev/null +++ b/src/core/proxyCompiler/util.ts @@ -0,0 +1,36 @@ +import type { Compiler } from '@farmfe/core'; + +export function defineProperty(obj: O, key: K, value: V): V { + const origin = obj[key]; + + Object.defineProperty(obj, key, { + value, + }); + + return origin as V; +} + +export function proxyCompilerFn< + T extends Compiler, + // biome-ignore lint/suspicious/noExplicitAny: + OFT extends Record any> = { + // biome-ignore lint/suspicious/noExplicitAny: + [K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : never; + }, + K extends keyof OFT = keyof OFT, + // biome-ignore lint/suspicious/noExplicitAny: + F extends (...args: any) => any = OFT[K], +>(compiler: T, fnName: K, callback: F) { + const handler = ((...args: Parameters) => { + const r = origin.bind(compiler)(...args); + if (r instanceof Promise) { + r.then((res) => callback({ args, result: res })); + } else { + callback({ args, result: r }); + } + + return r; + }) as OFT[K]; + const origin = defineProperty(compiler as unknown as OFT, fnName, handler); + return origin as OFT[K]; +} diff --git a/src/plugins/auto-execute.ts b/src/plugins/auto-execute.ts index d340f08..01a8166 100644 --- a/src/plugins/auto-execute.ts +++ b/src/plugins/auto-execute.ts @@ -1,37 +1,66 @@ -import { Logger, type Resource, type JsPlugin } from '@farmfe/core'; +import { Logger, type JsPlugin } from '@farmfe/core'; import path from 'node:path'; -import { type CommonOptions, ExecuteMode, type ResolvedCommonOptions } from '../types/options'; +import type { CommonOptions } from '../types/options'; import { NormalizeOption } from '../config/normalize'; import { CLI_NAME, logger as defaultLogger } from '../config/constant'; -import { Executer } from '../executer'; +import { Executer } from '../core/executer'; +import { ProxyCompiler } from '../core/proxyCompiler'; export { NormalizeOption, Executer }; -function findOutputEntry(resource: Resource[], options: ResolvedCommonOptions) { - const resourceEntry = resource.find((item) => item.info?.data.isEntry); - - if (resourceEntry) { - return resourceEntry; - } - - switch (options.execute.type) { - case ExecuteMode.Browser: - return resource.find((item) => item.name.endsWith('.html') || item.name.endsWith('.hml')); - case ExecuteMode.Node: - return resource.find((item) => { - return Object.keys(options.entry).find((entry) => new RegExp(`${entry}\\..+$`).test(item.name)); - }); - } -} - export default function autoExecute(options: CommonOptions = {}, logger = defaultLogger): JsPlugin { + const name = options.name ?? CLI_NAME; let outputDir: string | undefined = undefined; let executer: Executer | null = null; const normalizeOption = new NormalizeOption(options, logger); + const proxyCompiler = new ProxyCompiler(); + + proxyCompiler.onWriteResourcesToDisk(() => { + if (normalizeOption.options.noExecute) { + return; + } + + if (!outputDir) { + logger.error('outputDir is not found'); + return; + } + + if (!normalizeOption.options.outputEntry) { + return; + } + + const resourceOutputEntryFormatter = normalizeOption.options.outputEntry; + const resourceOutputEntry = proxyCompiler.resource_names.find((item) => + resourceOutputEntryFormatter.matchEntryName(item, normalizeOption.options.entry) + ); + + if (!resourceOutputEntry) { + logger.error('output entry is not found'); + return; + } + + // TODO: multiple entry + const executePath = path.join(outputDir, resourceOutputEntry); + + if (!executer) { + executer = new Executer(normalizeOption.options.execute, logger, normalizeOption.options); + } + + const nameWithoutExt = path.parse(resourceOutputEntry).name; + + executer.execute( + executePath, + nameWithoutExt, + new Logger({ + name: `${name}:${nameWithoutExt}`, + }) + ); + }); + return { - name: `${CLI_NAME}:execute`, + name: `${name}:execute`, priority: Number.NEGATIVE_INFINITY, async config(config) { return await normalizeOption.config(config); @@ -45,8 +74,10 @@ export default function autoExecute(options: CommonOptions = {}, logger = defaul logger.debug(`[entry: ${entry}] [format: ${format}] [target: ${targetEnv}]`); }, - configureCompiler(compiler) { - if (!compiler.config.config?.watch) { + configureCompiler(c) { + proxyCompiler.start(c); + + if (!c.config.config?.watch) { return; } @@ -54,51 +85,15 @@ export default function autoExecute(options: CommonOptions = {}, logger = defaul return; } - const entries = Object.values(compiler.config.config?.input ?? {}); + const entries = Object.values(c.config.config?.input ?? {}); if (entries.length === 0) { return; } for (const entry of entries) { - compiler.addExtraWatchFile(entry, normalizeOption.options.watchFiles); + c.addExtraWatchFile(entry, normalizeOption.options.watchFiles); } }, - - writeResources: { - async executor(param) { - if (normalizeOption.options.noExecute) { - return; - } - - if (!outputDir) { - logger.error('output is not found'); - return; - } - - const resourceEntry = findOutputEntry(Object.values(param.resourcesMap), normalizeOption.options); - - if (!resourceEntry) { - logger.error('not found output entry'); - return; - } - - // TODO: multiple entry - const executePath = path.join(outputDir, resourceEntry!.name); - - if (!executer) { - executer = new Executer(normalizeOption.options.execute, logger, normalizeOption.options); - } - - const { name: nameWithoutExt } = path.parse(resourceEntry.name); - const execLogger = new Logger({ name: `${CLI_NAME}:${nameWithoutExt}` }); - - executer.execute( - executePath, - nameWithoutExt, - execLogger, - ); - }, - }, }; } diff --git a/src/types/options.ts b/src/types/options.ts index f8090b5..9323ebf 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -55,6 +55,8 @@ export interface CommonOptions { root?: string; watchFiles?: string[]; + + name?: string, } export interface ResolvedCommonOptions { @@ -74,6 +76,11 @@ export interface ResolvedCommonOptions { watchFiles: string[]; noWatch?: boolean; + + outputEntry?: { + matchEntryName: (name: string, inputs: Record) => string | undefined; + name: string; + }; } export enum ExecuteMode { diff --git a/tsconfig.json b/tsconfig.json index 2224cd1..fcadb91 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "skipLibCheck": true,