Skip to content

Commit

Permalink
feat: script esm (#38)
Browse files Browse the repository at this point in the history
* feat: script esm

* doc: add no-experience-esm flag

* chore: add changeset file
  • Loading branch information
shulandmimi authored Sep 3, 2024
1 parent 62ab7d6 commit f591344
Show file tree
Hide file tree
Showing 24 changed files with 490 additions and 250 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-monkeys-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'farmup': patch
---

upgrade @farmfe/core version and add exec script without output
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ in your code, if not find `package` or `source`, set external
### sourcemap

- `default`: `undefined`
- option: `boolean` | `'inline'` | `'all'` | `'all-inline'`
- option: `boolean` | `'inline'` | `'all'` | `'all-inline'`

generate sourcemap

### no-experience-esm

- option: `boolean`

disable exec esm without output to filesystem
6 changes: 6 additions & 0 deletions packages/core/farm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ export default defineConfig({
input: {
index: 'src/index.ts',
plugin: 'src/plugin-entry.ts',
import_register: './src/node/esm/register.ts',
import_hooks: './src/node/esm/hooks.ts',
},
output: {
targetEnv: 'node',
format: 'esm',
},
script: {
nativeTopLevelAwait: true,
plugins: [],
},
lazyCompilation: false,
persistentCache: false,
external: ['^@farmfe/core$'],
Expand Down
6 changes: 4 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
},
"bin": "./bin/farmup.js",
"devDependencies": {
"@farmfe/cli": "^1.0.3",
"@farmfe/cli": "^1.0.4",
"@types/fs-extra": "^11.0.4",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.12.7",
"@types/tmp": "^0.2.6",
"cac": "^6.7.14",
"execa": "^8.0.1",
"fs-extra": "^11.2.0",
Expand Down Expand Up @@ -63,6 +64,7 @@
"email": "sshuang141@163.com"
},
"dependencies": {
"@farmfe/core": "^1.3.12"
"@farmfe/core": "^1.3.16",
"tmp": "^0.2.3"
}
}
12 changes: 11 additions & 1 deletion packages/core/src/config/normalize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ function normalizedExecuted(commonOption: CommonOptions, options: ResolvedCommon
args: commonOption.args ?? [],
} as NodeExecuteOption;
}

const execute = options.execute;

if (execute.type === ExecuteMode.Node && commonOption.experienceEsm) {
if (options.format === 'esm' && !execute.args.includes('--import')) {
execute.args.push('--import', path.join(import.meta.dirname, './import_register.js'));
}
}
}

async function normalizedFormat(config: UserConfig, commonOptions: CommonOptions, options: ResolvedCommonOptions) {
Expand Down Expand Up @@ -248,7 +256,7 @@ export class NormalizeOption {

async config(config: UserConfig): Promise<UserConfig> {
await normalizedSimpleConfig(config, this.commonOption, this.options, this.logger);
return withServerOrWatch(
const c = withServerOrWatch(
{
compilation: {
input: this.options.entry,
Expand All @@ -263,6 +271,8 @@ export class NormalizeOption {
},
this.options,
);

return c;
}

async normalizeByCommonOption() {
Expand Down
14 changes: 7 additions & 7 deletions packages/core/src/core/executer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type ExecaChildProcess, execaCommand } from 'execa';
import { type ExecaChildProcess, execaCommand, type Options } from 'execa';
import { ExecuteMode, type ExecuteOption, type ResolvedCommonOptions } from '../types/options';
import type { Logger } from '@farmfe/core';
import { delay } from '../util/async';
Expand All @@ -11,31 +11,31 @@ export class Executer {
public option: ExecuteOption,
public logger: Logger,
public normalizedOption: ResolvedCommonOptions,
) { }
) {}

execute(path: string, name: string, logger = this.logger) {
execute(path: string, name: string, logger = this.logger, options: Options = {}) {
switch (this.option.type) {
case ExecuteMode.Browser: {
// console.log('TODO: use open command');
break;
}
case ExecuteMode.Node: {
this._execute('node', name, [path, ...this.option.args], logger);
this._execute('node', name, [...this.option.args, path], logger, options);
break;
}
case ExecuteMode.Custom: {
this._execute(this.option.command, name, [path, ...this.option.args], logger);
this._execute(this.option.command, name, [...this.option.args, path], logger, options);
break;
}
}
}

async _execute(command: string, name: string, args: string[], logger: Logger) {

async _execute(command: string, name: string, args: string[], logger: Logger, options: Options = {}) {
if (this.child) {
await this.closeChild();
}
const child = execaCommand([command, ...args].join(' '), {
...options,
cwd: process.cwd(),
stdio: 'pipe',
});
Expand Down
28 changes: 28 additions & 0 deletions packages/core/src/core/ipc/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import EventEmitter from 'node:events';
import net from 'node:net';

export class IpcClient<S, R> {
private client!: net.Socket;

events = new EventEmitter();

start(socketPath: string) {
const client = net.createConnection(socketPath);

client.on('data', (data) => {
this.events.emit('data', data);
});

this.client = client;
}

send(data: S) {
this.client.write(JSON.stringify(data));
}

onMessage(callback: (data: R) => void) {
this.events.on('data', (data) => {
callback(JSON.parse(data.toString()));
});
}
}
4 changes: 4 additions & 0 deletions packages/core/src/core/ipc/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum ServiceStatus {
WaitShakeHand = 1,
Ready = 2,
}
68 changes: 68 additions & 0 deletions packages/core/src/core/ipc/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import tmp from 'tmp';
import net from 'node:net';
import { Service } from './service';
import EventEmitter from 'node:events';
import path from 'node:path';

interface TempFileResult {
path: string;
cleanupCallback: () => void;
}

function createTempFile(): Promise<TempFileResult> {
return new Promise((resolve) => {
tmp.dir({}, (_err, name, cleanupCallback) => {
resolve({
path: path.join(name, `socket-${Date.now()}`),
cleanupCallback,
});
});
});
}

export class IpcServer<S, R> {
private sockets = new Set<Service<S, R>>();
private events = new EventEmitter();
private _server!: net.Server;
socket_path!: string;

async start() {
const tempFile = await createTempFile();
this.socket_path = tempFile.path;

const server = net.createServer((socket) => {
const service = new Service<S, R>(socket);
socket.on('close', () => {
this.sockets.delete(service);
});
this.sockets.add(service);
this.events.emit('connection', service);
});

server.listen(tempFile);

this._server = server;
}

onConnection(callback: (socket: Service<S, R>) => void) {
const handler = (socket: Service<S, R>) => {
callback(socket);

socket.onClose(() => {
this.events.off('connection', handler);
});
};
this.events.on('connection', handler);
}

close() {
this._server.close();
this.sockets.clear();
}

send(data: S) {
for (const socket of this.sockets) {
socket.send(data);
}
}
}
38 changes: 38 additions & 0 deletions packages/core/src/core/ipc/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Socket } from 'node:net';

export class Service<S, R> {
// private status = ServiceStatus.WaitShakeHand;

constructor(private _socket: Socket) {}

send(data: S) {
if (this._socket.closed) {
return;
}
this._socket.write(JSON.stringify(data));
}

onMessage(callback: (data: R) => void) {
const handler = (data: Buffer) => {
callback(JSON.parse(data.toString()));
};

this._socket.on('data', handler);

return () => {
this._socket.off('data', handler);
};
}

close() {
this._socket.end();
}

onClose(callback: () => void) {
this._socket.on('close', callback);
}

get isClose() {
return this._socket.closed;
}
}
24 changes: 21 additions & 3 deletions packages/core/src/core/proxyCompiler/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Compiler } from '@farmfe/core';
import EventEmitter from 'node:events';
import { proxyCompilerFn } from './util';
import { proxyCompilerFn, defineProperty } from './util';
import type { FnContext, OmitFnReturn } from './interface';

export class ProxyCompiler {
Expand All @@ -10,6 +10,7 @@ export class ProxyCompiler {

private _preProxyFnList: (keyof Compiler)[] = [];
private alreadyProxyFnList: Set<keyof Compiler> = new Set();
isDisableEmit = false;

start(compiler: Compiler) {
const isRestart = !!this.compiler;
Expand All @@ -32,13 +33,13 @@ export class ProxyCompiler {
}
}

private proxyCompiler<K extends keyof Compiler>(fnName: K) {
private proxyCompiler<K extends keyof Compiler>(fnName: K, force = false) {
if (!this.compiler) {
this._preProxyFnList.push(fnName);
return;
}

if (this.alreadyProxyFnList.has(fnName)) {
if (!force && this.alreadyProxyFnList.has(fnName)) {
return;
}

Expand All @@ -48,6 +49,12 @@ export class ProxyCompiler {
proxyCompilerFn(this.compiler, fnName, (...args: any[]) => this.event.emit(fnName, ...args));
}

private replaceCompiler<K extends keyof Compiler>(fnName: K, fn: Compiler[K]) {
defineProperty(this.compiler, fnName, fn);
// re proxy the compiler
this.proxyCompiler(fnName, true);
}

private on<
T extends Compiler,
K extends keyof OFT,
Expand All @@ -67,4 +74,15 @@ export class ProxyCompiler {
onWriteResourcesToDisk(handler: OmitFnReturn<Compiler['writeResourcesToDisk']>) {
return this.on('writeResourcesToDisk', (r) => handler(...r.args));
}

disableEmit() {
if (this.isDisableEmit) return;
const handler = () => Promise.resolve();
this.replaceCompiler('writeResourcesToDisk', handler);
this.isDisableEmit = true;
}

resources() {
return this.compiler.resources();
}
}
6 changes: 4 additions & 2 deletions packages/core/src/core/proxyCompiler/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ export function defineProperty<O, K extends keyof O, V extends O[K]>(obj: O, key

const descriptor = Object.getOwnPropertyDescriptor(obj, key);
Object.defineProperty(obj, key, {
writable: true,
enumerable: true,
configurable: true,
value,
...descriptor,
});

return origin as V;
Expand All @@ -21,7 +23,7 @@ export function proxyCompilerFn<
},
K extends keyof OFT = keyof OFT,
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
F extends (...args: any) => any = OFT[K]
F extends (...args: any) => any = OFT[K],
>(compiler: T, fnName: K, callback: F) {
const handler = ((...args: Parameters<OFT[K]>) => {
const r = origin.bind(compiler)(...args);
Expand Down
Loading

0 comments on commit f591344

Please sign in to comment.