Skip to content

Commit 26ef087

Browse files
committed
fix: rework repl handling
1 parent 8108dbf commit 26ef087

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

src/development/repl.ts

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ import fs from 'fs';
33
import path from 'path';
44

55
import { glob } from 'glob';
6+
import { set } from 'lodash';
67

78
import { AnyServiceLocals, ServiceExpress, ServiceLocals } from '../types';
89
import { ConfigurationSchema } from '../config/schema';
910

11+
const REPL_PROP = '$$repl$$';
12+
13+
interface WithReplProp {
14+
[REPL_PROP]?: string;
15+
}
16+
1017
export function serviceRepl<SLocals extends AnyServiceLocals = ServiceLocals<ConfigurationSchema>>(
1118
app: ServiceExpress<SLocals>,
1219
codepath: string | undefined,
@@ -51,23 +58,20 @@ function loadReplFunctions<SLocals extends AnyServiceLocals = ServiceLocals<Conf
5158
// Read the file content as text
5259
const fileContent = fs.readFileSync(file, 'utf-8');
5360

54-
// Check if @repl is present
55-
if (/addToRepl\(/.test(fileContent)) {
61+
// Check if repl$ is present, in a very rudimentary way
62+
if (/repl\$\(/.test(fileContent)) {
5663
// eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires
57-
const module = require(file); // Only require if @repl is found
64+
const module = require(path.resolve(file));
5865

59-
// Look for functions with the __isReplFunction marker
66+
// Look for functions with the REPL_PROP marker
6067
Object.values(module).forEach((exported) => {
6168
if (!exported) {
6269
return;
6370
}
64-
if (typeof exported === 'function' || typeof exported === 'object') {
65-
const obj = exported as Record<string, unknown>;
66-
for (const key of Object.keys(obj)) {
67-
if ((obj[key] as { __openApiServiceReplFunction?: boolean }).__openApiServiceReplFunction) {
68-
const fn = obj[key] as (app: ServiceExpress<SLocals>, ...args: unknown[]) => unknown;
69-
rl.context[key] = (...args: unknown[]) => fn(app, ...args);
70-
}
71+
if (typeof exported === 'function') {
72+
const replName = (exported as WithReplProp)[REPL_PROP];
73+
if (replName) {
74+
set(rl.context, replName, exported.bind(null, app));
7175
}
7276
}
7377
});
@@ -78,17 +82,32 @@ function loadReplFunctions<SLocals extends AnyServiceLocals = ServiceLocals<Conf
7882
});
7983
}
8084

85+
// Can't seem to sort out proper generics here, so we'll just use any since it's dev only
86+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
87+
type ReplAny = any;
88+
8189
/**
8290
* This decorator-like function can be applied to functions and the service will load and expose
8391
* the function when the repl is engaged.
92+
*
93+
* async function myFunction(app: MyService['App'], arg1: string, arg2: number) {
94+
* }
95+
* repl$(myFunction);
96+
*
97+
* or
98+
*
99+
* repl(myFunction, 'some.func.name');
84100
*/
85-
export function addToRepl<SLocals extends AnyServiceLocals = ServiceLocals<ConfigurationSchema>>(
86-
fn: (app: ServiceExpress<SLocals>, ...args: unknown[]) => unknown,
87-
name?: string,
88-
) {
101+
export function repl$<
102+
S extends ServiceExpress<ReplAny>,
103+
T extends (app: S, ...args: ReplAny[]) => ReplAny
104+
>(fn: T, name?: string) {
89105
const functionName = name || fn.name;
90106
if (!functionName) {
91107
throw new Error('Function must have a name or a name must be provided.');
92108
}
93-
(fn as unknown as { __openApiServiceReplFunction: string }).__openApiServiceReplFunction = functionName;
109+
Object.defineProperty(fn, REPL_PROP, {
110+
enumerable: false,
111+
value: functionName,
112+
});
94113
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ export * from './config';
66
export * from './error';
77
export * from './bootstrap';
88
export * from './hook';
9-
export { addToRepl } from './development/repl';
9+
export { repl$ } from './development/repl';

0 commit comments

Comments
 (0)