Skip to content

Commit

Permalink
feat(docs): add flow documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
blakebyrnes committed Mar 2, 2022
1 parent 5bb2a92 commit 56c2d98
Show file tree
Hide file tree
Showing 23 changed files with 445 additions and 457 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ Browse the [full API docs](https://ulixee.org/docs).

## Contributing

See [how-to-contribute.md](docs/main/Contribute/how-to-contribute.md) for ways to get started.

This project has a [code of conduct](docs/main/Contribute/code-of-conduct.md). By interacting with this repository, organization, or community you agree to abide by its terms.

We'd love your help in making Hero a better tool. Please don't hesitate to send a pull request.

## License
Expand Down
33 changes: 22 additions & 11 deletions client/lib/DomExtender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import XPathResult from 'awaited-dom/impl/official-klasses/XPathResult';
import { createSuperNode } from 'awaited-dom/impl/create';
import { getAwaitedPathAsMethodArg } from './SetupAwaitedHandler';
import { KeyboardShortcuts } from '@ulixee/hero-interfaces/IKeyboardShortcuts';
import { scriptInstance } from './internal';

const awaitedPathState = StateMachine<
any,
Expand All @@ -34,7 +35,7 @@ interface IBaseExtendNode {
$exists: Promise<boolean>;
$isClickable: Promise<boolean>;
$hasFocus: Promise<boolean>;
$clearValue(): Promise<void>;
$clearInputText(): Promise<void>;
$click(verification?: IElementInteractVerification): Promise<void>;
$type(...typeInteractions: ITypeInteraction[]): Promise<void>;
$waitForExists(options?: { timeoutMs?: number }): Promise<ISuperElement>;
Expand Down Expand Up @@ -68,7 +69,10 @@ declare module 'awaited-dom/base/interfaces/official' {
interface IHTMLCollection extends IBaseExtendNodeList {}
}

type INodeExtensionFns = Omit<IBaseExtendNode, '$isClickable' | '$isVisible' | '$exists' | '$hasFocus'>;
type INodeExtensionFns = Omit<
IBaseExtendNode,
'$isClickable' | '$isVisible' | '$exists' | '$hasFocus'
>;
const NodeExtensionFns: INodeExtensionFns = {
async $click(verification: IElementInteractVerification = 'elementAtPath'): Promise<void> {
const coreFrame = await getCoreFrame(this);
Expand Down Expand Up @@ -114,14 +118,23 @@ const NodeExtensionFns: INodeExtensionFns = {
...options,
});
},
async $clearValue(): Promise<void> {
async $clearInputText(): Promise<void> {
const { awaitedOptions } = awaitedPathState.getState(this);
const coreFrame = await awaitedOptions.coreFrame;
await Interactor.run(coreFrame, [
{ click: this },
{ keyShortcut: KeyboardShortcuts.selectAll },
{ keyPress: KeyboardKey.Backspace },
]);
const callsitePath = scriptInstance.getScriptCallsite();
await coreFrame.coreTab.runFlowCommand(
async () => {
await this.focus();
await Interactor.run(coreFrame, [
{ keyShortcut: KeyboardShortcuts.selectAll },
{ keyPress: KeyboardKey.Backspace },
]);
},
assert => {
assert(this.value, x => !x);
},
callsitePath,
);
},
$xpathSelector(selector: string, orderedNodeResults = false): ISuperNode {
const { awaitedOptions, awaitedPath } = awaitedPathState.getState(this);
Expand Down Expand Up @@ -230,6 +243,4 @@ async function getCoreFrame(element: ISuperElement): Promise<CoreFrameEnvironmen
extendNodes<INodeExtensionFns, INodeExtensionGetters>(NodeExtensionFns, NodeExtensionGetters);
extendNodeLists(NodeListExtensionFns);

export {
awaitedPathState,
};
export { awaitedPathState };
36 changes: 19 additions & 17 deletions client/lib/FlowCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,29 @@ export default class FlowCommands {
flowCommand = this.flowCommands.find(
x => x.parentId === parentFlow.id && callsiteJson === JSON.stringify(x.callsitePath),
) as any;
}
if (flowCommand) {
flowCommand.retryNumber += 1;
return flowCommand;
} else {
flowCommand = new FlowCommand(
this.coreTab,
commandFn,
exitState,
id,
parentFlow,
callsitePath,
options,
);
this.flowCommands.push(flowCommand);
await this.coreTab.commandQueue.runOutOfBand(
'Tab.registerFlowCommand',
flowCommand.id,
flowCommand.parentId,
callsitePath,
);
}

flowCommand = new FlowCommand(
this.coreTab,
commandFn,
exitState,
id,
parentFlow,
callsitePath,
options,
);
this.flowCommands.push(flowCommand);
await this.coreTab.commandQueue.runOutOfBand(
'Tab.registerFlowCommand',
flowCommand.id,
flowCommand.parentId,
callsitePath,
);

return flowCommand;
}

Expand Down
22 changes: 7 additions & 15 deletions docs/main/Advanced/ConnectionToCore.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,22 @@ const { Hero: FullHero } = require('@ulixee');

There are 2 built-in connections in Hero:

- `Default` - instantiates and connects to a locally install Hero `Core`
- `RemoteConnectionToCore` - takes a host to dial over tcp. See more [here](/docs/advanced/remote)
- `Default` - instantiates and connects to a locally install Hero `Core` (used by `@ulixee/hero-fullstack`)
- `RemoteConnectionToCore` - takes a host to dial over a Websocket. See more [here](/docs/advanced/remote)

### Configuration {#configuration}

When you provide a connectionToCore to a [Handler](/docs/basic-interfaces/handler) or [Hero](/docs/basic-interfaces/hero), Hero will accept either an `options` object or a `RemoteConnectionToCore` instance.

The following methods allow you to configure the `connectionToCore`

- [hero.configure()](/docs/basic-interfaces/hero#configure) - apply the connection to the default hero, or to a an hero constructed prior to the first connection.
- [new Hero()](/docs/basic-interfaces/hero#constructor) - the new hero will use this connection.
- [new Handler(...connections)](/docs/basic-interfaces/handler#constructor) - a handler takes one or more coreClientConnection options or instances.
When you provide a connectionToCore to a [Hero](/docs/basic-interfaces/hero) instance, Hero will accept either an `options` object or a `ConnectionToCore` instance.

### Options {#options}

The provided settings configure the connection to `Core`. Note: some configurations will apply to all connected Heros and Handlers (`localProxyPortStart`, `sessionsDir`, `replayServerPort`).
The provided settings configure the connection to `Core`. Note: some configurations will apply to all connected Heroes ( `dataDir`).

- options `object`. A set of settings that controls the creation of a "connection" to a `Hero Core`.
- host `string`. An optional `hostname:port` url that will be used to establish a connection to a Hero Core running on another machine. If no host is provided, a connection to a "locally" running `Core` will be attempted.
- maxConcurrency `number`. The max number of Heros to allow to be dispatched and created at the same time. Heros are "active" until the dispatchHero callback is complete, or the created Hero is closed. If not provided, this number will match the max allowed by a `Core`.
- maxConcurrency `number`. The max number of Heroes to allow to be dispatched and created at the same time. Heroes are "active" until the dispatchHero callback is complete, or the created Hero is closed. If not provided, this number will match the max allowed by a `Core`.
- heroTimeoutMillis `number`. The number of milliseconds to give each Hero in this connection to complete a session. A TimeoutError will be thrown if this time is exceeded.
- localProxyPortStart `number` defaults to `any open port`. Starting internal port to use for the mitm proxy.
- sessionsDir `string` defaults to `os.tmpdir()/.ulixee`. Directory to store session files and mitm certificates.
- replayServerPort `number`. Port to start a live replay server on. Defaults to "any open port".
- dataDir `string` defaults to `os.tmpdir()/.ulixee`. Directory to store session files and mitm certificates.
- connection `CoreClientConnection`. A pre-initialized connection to a `Hero Core`. You can use this option to pre-check your connection to a remote connection, or to provide customization to the connection.

## Methods
Expand All @@ -52,7 +44,7 @@ The provided settings configure the connection to `Core`. Note: some configurati

Initializes the connection to the specified core. You can use this function if you would like to pre-connect to your remote host and ensure connections are properly established before continuing.

NOTE: this will be automatically called when you use a Handler or Hero and pass in this connection.
NOTE: this will be automatically called when you pass in a connection to Hero.

#### **Returns**: `Promise`

Expand Down
7 changes: 3 additions & 4 deletions docs/main/Advanced/Remote.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Hero operates out of the box over WebSockets. You'll eventually want to launch Core on a server where clients can remotely access it.

You'll need a simple script to start the server on the machine where the `ulixee` npm package is installed. Make sure to open the port you allocate on any firewall that a client might have to pass through:
You'll need a simple script to start the server on the machine where the `@ulixee/hero` npm package is installed. Make sure to open the port you allocate on any firewall that a client might have to pass through:

## Setting Up a Server Process

Expand All @@ -23,16 +23,15 @@ const Core = require('@ulixee/hero-core');

## Setting Up the Client

Your [Hero](/docs/basic-interfaces/hero) or [Handler](/docs/basic-interfaces/handler) must be configured to point at this Remote Core (and any others you've set up).
Your [Hero](/docs/basic-interfaces/hero) instance must be configured to point at this Remote Core (and any others you've set up).

NOTE: you can use the `@ulixee/hero` npm package if you don't want to install a full browser engine on the machine coordinating all your scrapes. That example is shown below.

```javascript
const Hero = require('@ulixee/hero');

(async () => {
const hero = new Hero();
await hero.configure({
const hero = new Hero({
connectionToCore: {
host: 'localhost:7007',
},
Expand Down
2 changes: 1 addition & 1 deletion docs/main/Advanced/Session.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Sessions store data into a Sqlite database using a module called SessionState. T

By default, session databases are located in `os.tmpdir()\.ulixee`. Tmpdir refers to the NodeJs function in the [OS module](https://nodejs.org/api/os.html#os_os_tmpdir).

You can control the location sessions are stored using the [`sessionsDir`](/docs/overview/configuration#sessions-dir) configuration when starting a Core server.
You can control the location sessions are stored using the [`dataDir`](/docs/overview/configuration#data-dir) configuration when starting a Core server.

### Managing Sessions

Expand Down
2 changes: 1 addition & 1 deletion docs/main/Advanced/UserProfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const theStoredProfile = await hero.exportUserProfile();
// This browser will be instantiated with all the cookies
// dom storage, etc from the prior session.

const heroWithProfile = await handler.createHero({
const heroWithProfile = new Hero({
userProfile: theStoredProfile,
});
```
Expand Down
2 changes: 2 additions & 0 deletions docs/main/BasicInterfaces/AwaitedDOM.base.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Supers give you access to all properties and methods of dependent classes.

[INTERFACES:Super]

Some helpers are added to the Super classes to make using Hero more intuitive. Find a list [here](/docs/basic-interfaces/dom-extenders)

## Document Interfaces

[INTERFACES:Document]
Expand Down
Loading

0 comments on commit 56c2d98

Please sign in to comment.