@haibun/web-server-express 1.62.1 → 1.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ import { AStepper, IHasOptions } from '@haibun/core/build/lib/astepper.js';
2
+ import { TNamed, IStepperCycles } from '@haibun/core/build/lib/defs.js';
3
+ export declare class ExecutorApiStepper extends AStepper implements IHasOptions {
4
+ private executionContexts;
5
+ private httpPrompters;
6
+ options: {
7
+ EXECUTOR_API_PATH: {
8
+ desc: string;
9
+ parse: (path: string) => {
10
+ result: string;
11
+ };
12
+ };
13
+ CONTEXT_TIMEOUT: {
14
+ desc: string;
15
+ parse: (timeout: string) => {
16
+ result: number;
17
+ };
18
+ };
19
+ };
20
+ cycles: IStepperCycles;
21
+ steps: {
22
+ setupExecutorApi: {
23
+ gwta: string;
24
+ action: ({ path }: TNamed) => Promise<import("@haibun/core/build/lib/defs.js").TNotOKActionResult> | Promise<import("@haibun/core/build/lib/defs.js").TOKActionResult>;
25
+ };
26
+ };
27
+ private startContextCleanup;
28
+ private cleanupContext;
29
+ private setupExecutorRoutes;
30
+ }
31
+ export default ExecutorApiStepper;
32
+ //# sourceMappingURL=executor-api-stepper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor-api-stepper.d.ts","sourceRoot":"","sources":["../src/executor-api-stepper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,cAAc,EAAmG,MAAM,gCAAgC,CAAC;AAmFzK,qBAAa,kBAAmB,SAAQ,QAAS,YAAW,WAAW;IACtE,OAAO,CAAC,iBAAiB,CAA6C;IACtE,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO;;;0BAGS,MAAM;;;;;;6BAIH,MAAM;;;;MAEvB;IAEF,MAAM,EAAE,cAAc,CA8CpB;IAEF,KAAK;;;+BAGgB,MAAM;;MAiBzB;IAEF,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,mBAAmB;CAsQ3B;AAED,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,391 @@
1
+ import { AStepper } from '@haibun/core/build/lib/astepper.js';
2
+ import { actionNotOK, actionOK, getFromRuntime, getStepperOption } from '@haibun/core/build/lib/util/index.js';
3
+ import { WEBSERVER } from './defs.js';
4
+ import { Executor } from '@haibun/core/build/phases/Executor.js';
5
+ import { asFeatures } from '@haibun/core/build/lib/resolver-features.js';
6
+ import { createSteppers, setStepperWorlds } from '@haibun/core/build/lib/util/index.js';
7
+ import { Resolver } from '@haibun/core/build/phases/Resolver.js';
8
+ import { expand } from '@haibun/core/build/lib/features.js';
9
+ import { applyEffectFeatures } from '@haibun/core/build/applyEffectFeatures.js';
10
+ // HTTP Prompter for web-based debugging
11
+ class HttpPrompter {
12
+ contexts;
13
+ contextId;
14
+ pendingPrompts = new Map();
15
+ constructor(contexts, contextId) {
16
+ this.contexts = contexts;
17
+ this.contextId = contextId;
18
+ }
19
+ async prompt(prompt) {
20
+ const promptId = `${this.contextId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
21
+ return new Promise((resolve) => {
22
+ this.pendingPrompts.set(promptId, { resolve, prompt });
23
+ // Store prompt in context for HTTP retrieval
24
+ const context = this.contexts.get(this.contextId);
25
+ if (context) {
26
+ context.isPaused = true;
27
+ context.lastActivity = Date.now();
28
+ }
29
+ });
30
+ }
31
+ resolvePrompt(promptId, response) {
32
+ const pending = this.pendingPrompts.get(promptId);
33
+ if (pending) {
34
+ pending.resolve(response);
35
+ this.pendingPrompts.delete(promptId);
36
+ const context = this.contexts.get(this.contextId);
37
+ if (context) {
38
+ context.isPaused = false;
39
+ context.lastActivity = Date.now();
40
+ }
41
+ }
42
+ }
43
+ getPendingPrompts() {
44
+ return Array.from(this.pendingPrompts.entries()).map(([id, { prompt }]) => ({
45
+ id,
46
+ ...prompt
47
+ }));
48
+ }
49
+ cancel() {
50
+ // Cancel all pending prompts
51
+ this.pendingPrompts.forEach(({ resolve }) => resolve(undefined));
52
+ this.pendingPrompts.clear();
53
+ }
54
+ }
55
+ export class ExecutorApiStepper extends AStepper {
56
+ executionContexts = new Map();
57
+ httpPrompters = new Map();
58
+ options = {
59
+ EXECUTOR_API_PATH: {
60
+ desc: 'API path for executor endpoints (default: /api/executor)',
61
+ parse: (path) => ({ result: path }),
62
+ },
63
+ CONTEXT_TIMEOUT: {
64
+ desc: 'Execution context timeout in minutes (default: 60)',
65
+ parse: (timeout) => ({ result: parseInt(timeout) || 60 }),
66
+ },
67
+ };
68
+ cycles = {
69
+ beforeStep: async ({ featureStep, action }) => {
70
+ // Track step execution in active contexts
71
+ for (const context of this.executionContexts.values()) {
72
+ if (context.isRunning) {
73
+ context.currentStep = { featureStep, action, timestamp: Date.now() };
74
+ context.stepHistory.push(context.currentStep);
75
+ context.lastActivity = Date.now();
76
+ // Check for breakpoints
77
+ if (context.breakpoints.has(action.actionName) || context.breakpoints.has('*')) {
78
+ context.isPaused = true;
79
+ const prompter = this.httpPrompters.get(context.id);
80
+ if (prompter) {
81
+ await prompter.prompt({
82
+ message: `Breakpoint hit at ${action.actionName}`,
83
+ options: ['continue', 'step', 'abort']
84
+ });
85
+ }
86
+ }
87
+ }
88
+ }
89
+ },
90
+ afterStep: ({ actionResult }) => {
91
+ // Update step results in active contexts
92
+ for (const context of this.executionContexts.values()) {
93
+ if (context.isRunning && context.currentStep) {
94
+ context.currentStep.result = actionResult;
95
+ context.currentStep.completed = Date.now();
96
+ context.lastActivity = Date.now();
97
+ }
98
+ }
99
+ return Promise.resolve({});
100
+ },
101
+ onFailure: () => {
102
+ // Handle failures in active contexts
103
+ for (const context of this.executionContexts.values()) {
104
+ if (context.isRunning) {
105
+ context.isPaused = true;
106
+ context.lastActivity = Date.now();
107
+ }
108
+ }
109
+ return Promise.resolve();
110
+ }
111
+ };
112
+ steps = {
113
+ setupExecutorApi: {
114
+ gwta: 'setup executor API at {path}',
115
+ action: ({ path }) => {
116
+ try {
117
+ const apiPath = path || getStepperOption(this, 'EXECUTOR_API_PATH', this.getWorld().moduleOptions) || '/api/executor';
118
+ const webserver = getFromRuntime(this.getWorld().runtime, WEBSERVER);
119
+ if (!webserver) {
120
+ return Promise.resolve(actionNotOK('Web server not available. Ensure web-server-stepper is configured.'));
121
+ }
122
+ this.setupExecutorRoutes(webserver, apiPath);
123
+ this.startContextCleanup();
124
+ return Promise.resolve(actionOK());
125
+ }
126
+ catch (error) {
127
+ return Promise.resolve(actionNotOK(`Failed to setup executor API: ${error.message}`));
128
+ }
129
+ },
130
+ },
131
+ };
132
+ startContextCleanup() {
133
+ const timeoutMinutes = parseInt(getStepperOption(this, 'CONTEXT_TIMEOUT', this.getWorld().moduleOptions) || '60');
134
+ const timeoutMs = timeoutMinutes * 60 * 1000;
135
+ setInterval(() => {
136
+ const now = Date.now();
137
+ for (const [id, context] of this.executionContexts.entries()) {
138
+ if (now - context.lastActivity > timeoutMs) {
139
+ this.cleanupContext(id);
140
+ }
141
+ }
142
+ }, 5 * 60 * 1000); // Check every 5 minutes
143
+ }
144
+ cleanupContext(contextId) {
145
+ const context = this.executionContexts.get(contextId);
146
+ if (context) {
147
+ // Cancel any pending prompts
148
+ const prompter = this.httpPrompters.get(contextId);
149
+ if (prompter) {
150
+ prompter.cancel();
151
+ this.httpPrompters.delete(contextId);
152
+ }
153
+ // Remove from world prompter if subscribed
154
+ if (context.world?.prompter) {
155
+ context.world.prompter.unsubscribe(prompter);
156
+ }
157
+ this.executionContexts.delete(contextId);
158
+ this.getWorld().logger.debug(`Cleaned up execution context ${contextId}`);
159
+ }
160
+ }
161
+ setupExecutorRoutes(webserver, basePath) {
162
+ const world = this.getWorld();
163
+ // POST /api/executor/features - Execute features with context
164
+ webserver.addRoute('post', `${basePath}/features`, (req, res) => {
165
+ void (async () => {
166
+ try {
167
+ const { features, steppers, options, contextId, debug = false } = req.body;
168
+ if (!features || !Array.isArray(features)) {
169
+ res.status(400).json({
170
+ error: 'Invalid request: features array is required'
171
+ });
172
+ return;
173
+ }
174
+ // Create or reuse execution context
175
+ const execContextId = contextId || `ctx-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
176
+ let context = this.executionContexts.get(execContextId);
177
+ if (!context) {
178
+ // Create steppers first
179
+ const stepperClasses = steppers || [];
180
+ const createdSteppers = await createSteppers(stepperClasses);
181
+ // Create execution world
182
+ const executionWorld = {
183
+ ...world,
184
+ ...(options || {}),
185
+ tag: { ...world.tag, source: 'api', contextId: execContextId }
186
+ };
187
+ // Set up debugging if requested
188
+ if (debug) {
189
+ const httpPrompter = new HttpPrompter(this.executionContexts, execContextId);
190
+ this.httpPrompters.set(execContextId, httpPrompter);
191
+ executionWorld.prompter.subscribe(httpPrompter);
192
+ }
193
+ await setStepperWorlds(createdSteppers, executionWorld);
194
+ // Create context
195
+ context = {
196
+ id: execContextId,
197
+ steppers: createdSteppers,
198
+ world: executionWorld,
199
+ isRunning: false,
200
+ isPaused: false,
201
+ breakpoints: new Set(),
202
+ stepHistory: [],
203
+ createdAt: Date.now(),
204
+ lastActivity: Date.now()
205
+ };
206
+ this.executionContexts.set(execContextId, context);
207
+ }
208
+ // Mark as running
209
+ context.isRunning = true;
210
+ context.lastActivity = Date.now();
211
+ // Resolve and execute features
212
+ const featureObjects = asFeatures(features.map(f => ({
213
+ path: f.path || '/api/feature',
214
+ content: f.content
215
+ })));
216
+ const expandedFeatures = await expand({ features: featureObjects, backgrounds: [] });
217
+ const resolver = new Resolver(context.steppers);
218
+ const resolvedFeatures = await resolver.resolveStepsFromFeatures(expandedFeatures);
219
+ const appliedFeatures = await applyEffectFeatures(context.world, resolvedFeatures, context.steppers);
220
+ const result = await Executor.executeFeatures(context.steppers, context.world, appliedFeatures);
221
+ // Mark as completed
222
+ context.isRunning = false;
223
+ context.lastActivity = Date.now();
224
+ res.json({
225
+ success: true,
226
+ contextId: execContextId,
227
+ result: {
228
+ ok: result.ok,
229
+ featureResults: result.featureResults?.map(fr => ({
230
+ path: fr.path,
231
+ ok: fr.ok,
232
+ stepCount: fr.stepResults.length,
233
+ failedSteps: fr.stepResults.filter(sr => !sr.ok).length
234
+ })),
235
+ summary: {
236
+ totalFeatures: result.featureResults?.length || 0,
237
+ passedFeatures: result.featureResults?.filter(fr => fr.ok).length || 0,
238
+ failedFeatures: result.featureResults?.filter(fr => !fr.ok).length || 0
239
+ }
240
+ }
241
+ });
242
+ }
243
+ catch (error) {
244
+ world.logger.error('API execution error:', error);
245
+ res.status(500).json({
246
+ error: 'Execution failed',
247
+ message: error.message
248
+ });
249
+ }
250
+ })();
251
+ });
252
+ // GET /api/executor/contexts - List execution contexts
253
+ webserver.addRoute('get', `${basePath}/contexts`, (req, res) => {
254
+ const contexts = Array.from(this.executionContexts.values()).map(ctx => ({
255
+ id: ctx.id,
256
+ isRunning: ctx.isRunning,
257
+ isPaused: ctx.isPaused,
258
+ createdAt: ctx.createdAt,
259
+ lastActivity: ctx.lastActivity,
260
+ stepCount: ctx.stepHistory.length,
261
+ breakpointCount: ctx.breakpoints.size
262
+ }));
263
+ res.json({ contexts });
264
+ });
265
+ // GET /api/executor/contexts/:id - Get context details
266
+ webserver.addRoute('get', `${basePath}/contexts/:id`, (req, res) => {
267
+ const contextId = req.params?.id;
268
+ const context = this.executionContexts.get(contextId);
269
+ if (!context) {
270
+ res.status(404).json({ error: 'Context not found' });
271
+ return;
272
+ }
273
+ const prompter = this.httpPrompters.get(contextId);
274
+ res.json({
275
+ id: context.id,
276
+ isRunning: context.isRunning,
277
+ isPaused: context.isPaused,
278
+ currentStep: context.currentStep,
279
+ stepHistory: context.stepHistory.slice(-20), // Last 20 steps
280
+ breakpoints: Array.from(context.breakpoints),
281
+ pendingPrompts: prompter ? prompter.getPendingPrompts() : [],
282
+ createdAt: context.createdAt,
283
+ lastActivity: context.lastActivity
284
+ });
285
+ });
286
+ // POST /api/executor/contexts/:id/breakpoints - Manage breakpoints
287
+ webserver.addRoute('post', `${basePath}/contexts/:id/breakpoints`, (req, res) => {
288
+ const contextId = req.params?.id;
289
+ const context = this.executionContexts.get(contextId);
290
+ if (!context) {
291
+ res.status(404).json({ error: 'Context not found' });
292
+ return;
293
+ }
294
+ const { action, stepperName } = req.body;
295
+ const breakpoint = stepperName ? `${stepperName}.${action}` : action;
296
+ if (req.body.operation === 'add') {
297
+ context.breakpoints.add(breakpoint);
298
+ }
299
+ else if (req.body.operation === 'remove') {
300
+ context.breakpoints.delete(breakpoint);
301
+ }
302
+ context.lastActivity = Date.now();
303
+ res.json({ breakpoints: Array.from(context.breakpoints) });
304
+ });
305
+ // POST /api/executor/contexts/:id/prompts/:promptId - Respond to prompts
306
+ webserver.addRoute('post', `${basePath}/contexts/:id/prompts/:promptId`, (req, res) => {
307
+ const contextId = req.params?.id;
308
+ const promptId = req.params?.promptId;
309
+ const context = this.executionContexts.get(contextId);
310
+ if (!context) {
311
+ res.status(404).json({ error: 'Context not found' });
312
+ return;
313
+ }
314
+ const prompter = this.httpPrompters.get(contextId);
315
+ if (!prompter) {
316
+ res.status(400).json({ error: 'No prompter available for this context' });
317
+ return;
318
+ }
319
+ prompter.resolvePrompt(promptId, req.body.response);
320
+ context.lastActivity = Date.now();
321
+ res.json({ success: true });
322
+ });
323
+ // DELETE /api/executor/contexts/:id - Clean up context
324
+ webserver.addRoute('delete', `${basePath}/contexts/:id`, (req, res) => {
325
+ const contextId = req.params?.id;
326
+ if (this.executionContexts.has(contextId)) {
327
+ this.cleanupContext(contextId);
328
+ res.json({ success: true });
329
+ }
330
+ else {
331
+ res.status(404).json({ error: 'Context not found' });
332
+ }
333
+ });
334
+ // GET /api/executor/status - Get executor status
335
+ webserver.addRoute('get', `${basePath}/status`, (req, res) => {
336
+ res.json({
337
+ status: 'ready',
338
+ timestamp: new Date().toISOString(),
339
+ version: '1.0.0',
340
+ activeContexts: this.executionContexts.size,
341
+ runningContexts: Array.from(this.executionContexts.values()).filter(ctx => ctx.isRunning).length
342
+ });
343
+ });
344
+ // POST /api/executor/validate - Validate features without execution
345
+ webserver.addRoute('post', `${basePath}/validate`, (req, res) => {
346
+ void (async () => {
347
+ try {
348
+ const { features, steppers } = req.body;
349
+ if (!features || !Array.isArray(features)) {
350
+ res.status(400).json({
351
+ error: 'Invalid request: features array is required'
352
+ });
353
+ return;
354
+ }
355
+ const featureObjects = asFeatures(features.map(f => ({
356
+ path: f.path || '/api/feature',
357
+ content: f.content
358
+ })));
359
+ const stepperClasses = steppers || [];
360
+ const createdSteppers = await createSteppers(stepperClasses);
361
+ await setStepperWorlds(createdSteppers, world);
362
+ const expandedFeatures = await expand({ features: featureObjects, backgrounds: [] });
363
+ const resolver = new Resolver(createdSteppers);
364
+ const resolvedFeatures = await resolver.resolveStepsFromFeatures(expandedFeatures);
365
+ res.json({
366
+ success: true,
367
+ validation: {
368
+ featuresCount: resolvedFeatures.length,
369
+ totalSteps: resolvedFeatures.reduce((sum, f) => sum + f.featureSteps.length, 0),
370
+ features: resolvedFeatures.map(f => ({
371
+ path: f.path,
372
+ stepCount: f.featureSteps.length,
373
+ valid: true
374
+ }))
375
+ }
376
+ });
377
+ }
378
+ catch (error) {
379
+ world.logger.error('API validation error:', error);
380
+ res.status(500).json({
381
+ error: 'Validation failed',
382
+ message: error.message
383
+ });
384
+ }
385
+ })();
386
+ });
387
+ world.logger.log(`Executor API routes configured at ${basePath}`);
388
+ }
389
+ }
390
+ export default ExecutorApiStepper;
391
+ //# sourceMappingURL=executor-api-stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor-api-stepper.js","sourceRoot":"","sources":["../src/executor-api-stepper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { AStepper, IHasOptions } from '@haibun/core/build/lib/astepper.js';
2
+ import { TWorld } from '@haibun/core/build/lib/defs.js';
3
+ export default class HttpExecutorStepper extends AStepper implements IHasOptions {
4
+ options: {
5
+ LISTEN_PORT: {
6
+ desc: string;
7
+ parse: (port: string) => {
8
+ result: number;
9
+ };
10
+ };
11
+ ACCESS_TOKEN: {
12
+ desc: string;
13
+ parse: (token: string) => {
14
+ result: string;
15
+ };
16
+ };
17
+ };
18
+ private routeAdded;
19
+ private steppers;
20
+ configuredToken: string;
21
+ port: number;
22
+ setWorld(world: TWorld, steppers: AStepper[]): Promise<void>;
23
+ addRemoteExecutorRoute(): void;
24
+ steps: {
25
+ enableRemoteExecutor: {
26
+ gwta: string;
27
+ action: () => Promise<import("@haibun/core/build/lib/defs.js").TOKActionResult>;
28
+ };
29
+ };
30
+ }
31
+ //# sourceMappingURL=http-executor-stepper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-executor-stepper.d.ts","sourceRoot":"","sources":["../src/http-executor-stepper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAe,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAOrE,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,QAAS,YAAW,WAAW;IAC/E,OAAO;;;0BAGS,MAAM;;;;;;2BAIL,MAAM;;;;MAErB;IAEF,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAkB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IAEP,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE;IAgBlD,sBAAsB;IAsDtB,KAAK;;;;;MAQH;CACF"}
@@ -0,0 +1,87 @@
1
+ import { AStepper } from '@haibun/core/build/lib/astepper.js';
2
+ import { FeatureExecutor } from '@haibun/core/build/phases/Executor.js';
3
+ import { actionOK, getFromRuntime, getStepperOption, intOrError } from '@haibun/core/build/lib/util/index.js';
4
+ import { WEBSERVER } from './defs.js';
5
+ import WebServerStepper from './web-server-stepper.js';
6
+ import { getActionableStatement } from '@haibun/core/build/phases/Resolver.js';
7
+ export default class HttpExecutorStepper extends AStepper {
8
+ options = {
9
+ LISTEN_PORT: {
10
+ desc: 'Port for remote execution API',
11
+ parse: (port) => ({ result: parseInt(port, 10) }),
12
+ },
13
+ ACCESS_TOKEN: {
14
+ desc: 'Access token for remote execution API authentication',
15
+ parse: (token) => ({ result: token }),
16
+ },
17
+ };
18
+ routeAdded = false;
19
+ steppers = [];
20
+ configuredToken;
21
+ port;
22
+ async setWorld(world, steppers) {
23
+ await super.setWorld(world, steppers);
24
+ this.port = intOrError(getStepperOption(this, 'LISTEN_PORT', world.moduleOptions) || '').result || NaN;
25
+ this.configuredToken = getStepperOption(this, 'ACCESS_TOKEN', this.getWorld().moduleOptions);
26
+ this.steppers = steppers;
27
+ if (!isNaN(this.port)) {
28
+ if (!this.configuredToken) {
29
+ throw new Error('ACCESS_TOKEN is required when enabling remote executor');
30
+ }
31
+ const webServerStepper = steppers.find(s => s instanceof WebServerStepper);
32
+ if (webServerStepper) {
33
+ webServerStepper.port = this.port;
34
+ }
35
+ }
36
+ }
37
+ addRemoteExecutorRoute() {
38
+ if (this.routeAdded) {
39
+ return;
40
+ }
41
+ const webserver = getFromRuntime(this.getWorld().runtime, WEBSERVER);
42
+ if (!webserver) {
43
+ throw new Error('WebServer not available - ensure web-server-stepper is loaded');
44
+ }
45
+ webserver.addRoute('post', '/execute-step', (req, res) => {
46
+ void (async () => {
47
+ try {
48
+ const authHeader = req.headers.authorization;
49
+ const providedToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;
50
+ if (!providedToken || providedToken !== this.configuredToken) {
51
+ res.status(401).json({ error: 'Invalid or missing access token' });
52
+ return;
53
+ }
54
+ if (!['statement', 'source'].every(key => typeof req.body[key] === 'string')) {
55
+ res.status(400).json({ error: 'statement and source are required' });
56
+ return;
57
+ }
58
+ const { statement, source } = req.body;
59
+ const world = this.getWorld();
60
+ const steppers = this.steppers;
61
+ const { featureStep } = await getActionableStatement(steppers, statement, source);
62
+ const result = await FeatureExecutor.doFeatureStep(steppers, featureStep, world);
63
+ res.json(result);
64
+ }
65
+ catch (error) {
66
+ const errorMessage = error instanceof Error ? error.message : String(error);
67
+ res.status(500).json({
68
+ error: errorMessage,
69
+ success: false
70
+ });
71
+ }
72
+ })();
73
+ });
74
+ this.routeAdded = true;
75
+ this.getWorld().logger.warn('⚠️ DANGEROUS: Remote executor route added at /execute-step');
76
+ }
77
+ steps = {
78
+ enableRemoteExecutor: {
79
+ gwta: 'enable remote executor',
80
+ action: () => {
81
+ this.addRemoteExecutorRoute();
82
+ return Promise.resolve(actionOK());
83
+ },
84
+ },
85
+ };
86
+ }
87
+ //# sourceMappingURL=http-executor-stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-executor-stepper.js","sourceRoot":"","sources":["../src/http-executor-stepper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { AStepper, IHasOptions } from '@haibun/core/build/lib/astepper.js';
2
+ import { TWorld } from '@haibun/core/build/lib/defs.js';
3
+ export default class RemoteExecutorStepper extends AStepper implements IHasOptions {
4
+ options: {
5
+ REMOTE_PORT: {
6
+ desc: string;
7
+ parse: (port: string) => {
8
+ result: number;
9
+ };
10
+ };
11
+ ACCESS_TOKEN: {
12
+ desc: string;
13
+ parse: (token: string) => {
14
+ result: string;
15
+ };
16
+ };
17
+ };
18
+ private routeAdded;
19
+ private steppers;
20
+ configuredToken: string;
21
+ setWorld(world: TWorld, steppers: AStepper[]): Promise<void>;
22
+ addRemoteExecutorRoute(): void;
23
+ steps: {
24
+ enableRemoteExecutor: {
25
+ gwta: string;
26
+ action: () => Promise<import("@haibun/core/build/lib/defs.js").TOKActionResult>;
27
+ };
28
+ };
29
+ }
30
+ //# sourceMappingURL=remote-executor-stepper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-executor-stepper.d.ts","sourceRoot":"","sources":["../src/remote-executor-stepper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAe,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAOrE,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,QAAS,YAAW,WAAW;IACjF,OAAO;;;0BAGS,MAAM;;;;;;2BAIL,MAAM;;;;MAErB;IAEF,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAkB;IAClC,eAAe,EAAE,MAAM,CAAC;IAElB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE;IAelD,sBAAsB;IA2DtB,KAAK;;;;;MAQH;CACF"}
@@ -0,0 +1,90 @@
1
+ import { AStepper } from '@haibun/core/build/lib/astepper.js';
2
+ import { FeatureExecutor } from '@haibun/core/build/phases/Executor.js';
3
+ import { actionOK, getFromRuntime, getStepperOption } from '@haibun/core/build/lib/util/index.js';
4
+ import { WEBSERVER } from './defs.js';
5
+ import WebServerStepper from './web-server-stepper.js';
6
+ import { getActionableStatement } from '@haibun/core/build/phases/Resolver.js';
7
+ export default class RemoteExecutorStepper extends AStepper {
8
+ options = {
9
+ REMOTE_PORT: {
10
+ desc: 'Port for remote execution API (DANGEROUS - development only)',
11
+ parse: (port) => ({ result: parseInt(port, 10) }),
12
+ },
13
+ ACCESS_TOKEN: {
14
+ desc: 'Access token for remote execution API authentication',
15
+ parse: (token) => ({ result: token }),
16
+ },
17
+ };
18
+ routeAdded = false;
19
+ steppers = [];
20
+ configuredToken;
21
+ async setWorld(world, steppers) {
22
+ await super.setWorld(world, steppers);
23
+ this.configuredToken = getStepperOption(this, 'ACCESS_TOKEN', this.getWorld().moduleOptions);
24
+ this.steppers = steppers;
25
+ const port = getStepperOption(this, 'REMOTE_PORT', world.moduleOptions);
26
+ if (port && typeof port === 'number') {
27
+ // Configure the web server to use the same port
28
+ const webServerStepper = steppers.find(s => s instanceof WebServerStepper);
29
+ if (webServerStepper) {
30
+ webServerStepper.port = port;
31
+ }
32
+ // Add route after world is set and webserver should be available
33
+ setTimeout(() => void this.addRemoteExecutorRoute(), 100);
34
+ }
35
+ }
36
+ addRemoteExecutorRoute() {
37
+ if (this.routeAdded) {
38
+ return;
39
+ }
40
+ const webserver = getFromRuntime(this.getWorld().runtime, WEBSERVER);
41
+ if (!webserver) {
42
+ throw new Error('WebServer not available - ensure web-server-stepper is loaded');
43
+ }
44
+ // Add the remote execution route
45
+ webserver.addRoute('post', '/execute-step', (req, res) => {
46
+ void (async () => {
47
+ try {
48
+ if (this.configuredToken) {
49
+ const authHeader = req.headers.authorization;
50
+ const providedToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;
51
+ if (!providedToken || providedToken !== this.configuredToken) {
52
+ res.status(401).json({ error: 'Invalid or missing access token' });
53
+ return;
54
+ }
55
+ }
56
+ if (!['statement', 'source'].every(key => typeof req.body[key] === 'string')) {
57
+ res.status(400).json({ error: 'statement and source are required' });
58
+ return;
59
+ }
60
+ const { statement, source } = req.body;
61
+ const world = this.getWorld();
62
+ const steppers = this.steppers;
63
+ const { featureStep } = await getActionableStatement(steppers, statement, source);
64
+ const result = await FeatureExecutor.doFeatureStep(steppers, featureStep, world);
65
+ res.json(result);
66
+ }
67
+ catch (error) {
68
+ const errorMessage = error instanceof Error ? error.message : String(error);
69
+ res.status(500).json({
70
+ error: errorMessage,
71
+ success: false
72
+ });
73
+ }
74
+ })();
75
+ });
76
+ this.routeAdded = true;
77
+ this.getWorld().logger.warn('⚠️ DANGEROUS: Remote executor route added at /execute-step');
78
+ this.getWorld().logger.warn('⚠️ This exposes execution context - use only in secure environments');
79
+ }
80
+ steps = {
81
+ enableRemoteExecutor: {
82
+ gwta: 'enable remote executor',
83
+ action: () => {
84
+ this.addRemoteExecutorRoute();
85
+ return Promise.resolve(actionOK());
86
+ },
87
+ },
88
+ };
89
+ }
90
+ //# sourceMappingURL=remote-executor-stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-executor-stepper.js","sourceRoot":"","sources":["../src/remote-executor-stepper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export declare const TEST_PORTS: {
2
+ readonly HTTP_EXECUTOR_BASE: 12001;
3
+ readonly HTTP_EXECUTOR_AUTH: 12002;
4
+ readonly HTTP_EXECUTOR_RETRY: 12003;
5
+ readonly HTTP_EXECUTOR_TIMEOUT: 12004;
6
+ readonly WEB_SERVER_FILES: 12101;
7
+ readonly WEB_SERVER_ROUTE: 12102;
8
+ readonly WEB_SERVER_EXPRESS: 12103;
9
+ readonly WEB_SERVER_INDEX: 12104;
10
+ readonly WEB_SERVER_STATIC: 12105;
11
+ readonly WEB_PLAYWRIGHT: 12201;
12
+ readonly WEB_PLAYWRIGHT_BROWSER: 12202;
13
+ readonly WEB_PLAYWRIGHT_HEADLESS: 12203;
14
+ readonly MCP_REMOTE_EXECUTOR: 12301;
15
+ readonly MCP_REMOTE_EXECUTION: 12302;
16
+ readonly MCP_SERVER_STDIO: 12303;
17
+ readonly MCP_CLIENT_TEST: 12304;
18
+ readonly INTEGRATION_BASE: 12401;
19
+ readonly INTEGRATION_AUTH: 12402;
20
+ readonly INTEGRATION_MULTI: 12403;
21
+ readonly PERF_BASE: 12501;
22
+ readonly LOAD_TEST: 12502;
23
+ readonly MOCK_SERVER: 12601;
24
+ readonly TEST_UTILS: 12602;
25
+ };
26
+ //# sourceMappingURL=test-constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-constants.d.ts","sourceRoot":"","sources":["../src/test-constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;CAqCb,CAAC"}
@@ -0,0 +1,36 @@
1
+ // Test port constants to avoid conflicts with live server instances
2
+ // Live servers use ports 8123-8125, so tests use 12000+ range
3
+ // Each category gets a 100-port range for expansion
4
+ export const TEST_PORTS = {
5
+ // HTTP Executor tests (12000-12099)
6
+ HTTP_EXECUTOR_BASE: 12001,
7
+ HTTP_EXECUTOR_AUTH: 12002,
8
+ HTTP_EXECUTOR_RETRY: 12003,
9
+ HTTP_EXECUTOR_TIMEOUT: 12004,
10
+ // Web server tests (12100-12199)
11
+ WEB_SERVER_FILES: 12101,
12
+ WEB_SERVER_ROUTE: 12102,
13
+ WEB_SERVER_EXPRESS: 12103,
14
+ WEB_SERVER_INDEX: 12104,
15
+ WEB_SERVER_STATIC: 12105,
16
+ // Web Playwright tests (12200-12299)
17
+ WEB_PLAYWRIGHT: 12201,
18
+ WEB_PLAYWRIGHT_BROWSER: 12202,
19
+ WEB_PLAYWRIGHT_HEADLESS: 12203,
20
+ // MCP tests (12300-12399)
21
+ MCP_REMOTE_EXECUTOR: 12301,
22
+ MCP_REMOTE_EXECUTION: 12302,
23
+ MCP_SERVER_STDIO: 12303,
24
+ MCP_CLIENT_TEST: 12304,
25
+ // Integration tests (12400-12499)
26
+ INTEGRATION_BASE: 12401,
27
+ INTEGRATION_AUTH: 12402,
28
+ INTEGRATION_MULTI: 12403,
29
+ // Performance/Load tests (12500-12599)
30
+ PERF_BASE: 12501,
31
+ LOAD_TEST: 12502,
32
+ // Utility/Mock servers (12600-12699)
33
+ MOCK_SERVER: 12601,
34
+ TEST_UTILS: 12602,
35
+ };
36
+ //# sourceMappingURL=test-constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-constants.js","sourceRoot":"","sources":["../src/test-constants.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,8DAA8D;AAC9D,oDAAoD;AAEpD,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,oCAAoC;IACpC,kBAAkB,EAAE,KAAK;IACzB,kBAAkB,EAAE,KAAK;IACzB,mBAAmB,EAAE,KAAK;IAC1B,qBAAqB,EAAE,KAAK;IAE5B,iCAAiC;IACjC,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,KAAK;IACvB,kBAAkB,EAAE,KAAK;IACzB,gBAAgB,EAAE,KAAK;IACvB,iBAAiB,EAAE,KAAK;IAExB,qCAAqC;IACrC,cAAc,EAAE,KAAK;IACrB,sBAAsB,EAAE,KAAK;IAC7B,uBAAuB,EAAE,KAAK;IAE9B,0BAA0B;IAC1B,mBAAmB,EAAE,KAAK;IAC1B,oBAAoB,EAAE,KAAK;IAC3B,gBAAgB,EAAE,KAAK;IACvB,eAAe,EAAE,KAAK;IAEtB,kCAAkC;IAClC,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,KAAK;IACvB,iBAAiB,EAAE,KAAK;IAExB,uCAAuC;IACvC,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,KAAK;IAEhB,qCAAqC;IACrC,WAAW,EAAE,KAAK;IAClB,UAAU,EAAE,KAAK;CACT,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@haibun/web-server-express",
3
3
  "type": "module",
4
- "version": "1.62.1",
4
+ "version": "1.64.0",
5
5
  "description": "",
6
6
  "main": "build/web-server-stepper.js",
7
7
  "files": ["build/**"],
@@ -18,13 +18,13 @@
18
18
  "author": "",
19
19
  "license": "ISC",
20
20
  "dependencies": {
21
- "@haibun/core": "1.62.1",
21
+ "@haibun/core": "1.64.0",
22
22
  "cookie-parser": "^1.4.5",
23
23
  "express": "^4.17.1",
24
24
  "serve-index": "^1.9.1"
25
25
  },
26
26
  "devDependencies": {
27
- "@haibun/web-http": "1.62.1",
27
+ "@haibun/web-http": "1.64.0",
28
28
  "@types/cookie-parser": "^1.4.2",
29
29
  "@types/express": "^4.17.15"
30
30
  },