-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: content api for frontend events from backend, ui updates and res…
…et command (#101) * fix: move context to it's own class * fix: result stream moved to it's own model * fix: set raw result string to a buffer output when provided * fix: attach context to the event list to runtime query * fix: add context event handling * fix: use dynamic event name list based on events * fix: prevent events after abort * fix: safe hook runtime usage * fix: reset command
- Loading branch information
1 parent
aac890d
commit d8fbce5
Showing
22 changed files
with
386 additions
and
201 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import { Workspace } from './workspace' | ||
import { Command, ResultContentEvent, ResultStreamEvent, Runtime } from './runtime' | ||
import { WebContents } from 'electron' | ||
import { readFile } from 'fs-extra' | ||
import short from 'short-uuid' | ||
import { ResultStream } from './result-stream' | ||
|
||
export interface RuntimeContentHandle { | ||
id: string | ||
update(html: string): void | ||
on(event: string, handler: RuntimeContentEventCallback): void | ||
} | ||
|
||
export interface RuntimeContentEvent { | ||
event: string | ||
} | ||
|
||
export type RuntimeContentEventCallback = (event: RuntimeContentEvent) => Promise<void> | void | ||
|
||
export class ExecuteContext { | ||
public readonly start: number = Date.now() | ||
public readonly id: string = short.generate() | ||
|
||
public readonly events: ResultContentEvent[] = [] | ||
private readonly eventHandlers = new Map<string, RuntimeContentEventCallback>() | ||
|
||
constructor( | ||
public readonly platform: string, | ||
public readonly sender: WebContents, | ||
public readonly workspace: Workspace, | ||
public readonly runtime: Runtime, | ||
public readonly command: Command, | ||
public readonly profile: string, | ||
public readonly history: { | ||
enabled: boolean | ||
results: boolean | ||
max: number | ||
} | ||
) {} | ||
|
||
out(text: string, error: boolean = false): ResultStream | null { | ||
const isFinished = this.command.aborted || this.command.complete | ||
if (isFinished) { | ||
if (!this.command.result.edit) { | ||
return null | ||
} | ||
} | ||
const streamEntry = new ResultStream(text, error) | ||
|
||
this.command.result.stream.push(streamEntry) | ||
|
||
const streamEvent: ResultStreamEvent = { | ||
entry: streamEntry, | ||
runtime: this.runtime.id, | ||
command: this.command.id | ||
} | ||
|
||
if (!this.sender.isDestroyed()) { | ||
this.sender.send('runtime.commandEvent', streamEvent) | ||
} | ||
|
||
return streamEntry | ||
} | ||
|
||
content(html: string): RuntimeContentHandle { | ||
const contextId = this.id | ||
const runtimeId = this.runtime.id | ||
const commandId = this.command.id | ||
|
||
const command = this.command | ||
|
||
const id = short.generate() | ||
const events = this.events | ||
const container = (html: string): string => `<span id="${id}">${html}</span>` | ||
|
||
const R = this.out(container(html), false) | ||
const sender = this.sender | ||
const eventHandlers = this.eventHandlers | ||
return { | ||
id, | ||
update(newHTML: string): void { | ||
if (R !== null && !command.aborted && !command.complete) { | ||
R.setText(container(newHTML)) | ||
|
||
sender.send('runtime.commandEvent') | ||
} | ||
}, | ||
on(event: string, callback: RuntimeContentEventCallback): void { | ||
const eventHandlerId = short.generate() | ||
|
||
eventHandlers.set(eventHandlerId, callback) | ||
|
||
events.push({ | ||
event, | ||
commandId, | ||
contextId, | ||
runtimeId, | ||
contentId: id, | ||
handlerId: eventHandlerId | ||
}) | ||
|
||
sender.send('runtime.observe', { | ||
contextId, | ||
contentId: id, | ||
eventHandlerId, | ||
event | ||
}) | ||
|
||
sender.send('runtime.commandEvent') | ||
} | ||
} | ||
} | ||
|
||
async fireEvent(eventName: string, handlerId: string): Promise<void> { | ||
const event = this.eventHandlers.get(handlerId) | ||
if (this.command.aborted || this.command.complete) { | ||
return | ||
} | ||
if (!event) { | ||
return | ||
} | ||
|
||
await event({ | ||
event: eventName | ||
}) | ||
} | ||
|
||
async edit(path: string, callback: (text: string) => void): Promise<void> { | ||
const file = await readFile(path) | ||
|
||
this.command.result.edit = { | ||
path, | ||
modified: false, | ||
content: file.toString(), | ||
callback | ||
} | ||
|
||
this.sender.send('runtime.commandEvent') | ||
} | ||
|
||
finish(code: number): void { | ||
if (this.command.aborted || this.command.complete) { | ||
return | ||
} | ||
|
||
this.command.result.code = code | ||
this.command.complete = true | ||
this.command.error = this.command.result.code !== 0 | ||
|
||
if (this.history.enabled) { | ||
this.workspace.history.append(this.command, this.start, this.profile, this.history.results) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { sanitizeOutput } from '../util' | ||
|
||
export class ResultStream { | ||
public text: string | ||
constructor( | ||
public raw: string, | ||
public error: boolean = false | ||
) { | ||
this.raw = this.raw.toString() | ||
this.text = sanitizeOutput(raw) | ||
} | ||
|
||
setText(raw: string, error: boolean = this.error): void { | ||
this.raw = raw | ||
this.text = sanitizeOutput(raw) | ||
this.error = error | ||
} | ||
} |
Oops, something went wrong.