@allwright.dev/core 0.1.4 → 0.1.5

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.
package/README.md CHANGED
@@ -20,6 +20,19 @@ await page.click(
20
20
  await browser.close();
21
21
  ```
22
22
 
23
+ Register a typed hook before an action that opens a tab, then wait for its
24
+ typed result afterward:
25
+
26
+ ```ts
27
+ import { firefox, hooks } from "@allwright.dev/core";
28
+
29
+ const browser = await firefox.launch();
30
+ const page = browser.page();
31
+ const hook = await browser.registerHook(hooks.newPage);
32
+ await page.click("a[target=_blank]");
33
+ const newPage = await hook.wait();
34
+ ```
35
+
23
36
  Runnable examples live in [examples/web-basic.ts](./examples/web-basic.ts) and [examples/android-basic.ts](./examples/android-basic.ts).
24
37
 
25
38
  Shared config files are stack-agnostic and can live in `allwright.config.yaml` or `allwright.config.json`.
package/dist/bootstrap.js CHANGED
@@ -12,7 +12,7 @@ const ALLWRIGHT_HOME_ENV_VAR = "ALLWRIGHT_HOME";
12
12
  const ALLWRIGHT_REPOSITORY_ENV_VAR = "ALLWRIGHT_REPOSITORY";
13
13
  const ALLWRIGHT_VERSION_ENV_VAR = "ALLWRIGHT_VERSION";
14
14
  const DEFAULT_RELEASE_REPOSITORY = "allwright-dev/allwright";
15
- const DEFAULT_RELEASE_VERSION = "0.1.4";
15
+ const DEFAULT_RELEASE_VERSION = "0.1.5";
16
16
  const STARTUP_TIMEOUT_MS = 20_000;
17
17
  const PING_TIMEOUT_MS = 1_000;
18
18
  const PROTO_ROOT = fileURLToPath(new URL("../proto/", import.meta.url));
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Browser, BrowserInfo, BrowserKind, BrowserLaunchState, BrowserType, CommandOptions, LaunchOptions, Page } from "./types.js";
1
+ import type { Browser, BrowserInfo, BrowserKind, BrowserLaunchState, BrowserType, CommandOptions, Hook, HookType, LaunchOptions, Page } from "./types.js";
2
2
  export declare class BrowserTypeImpl implements BrowserType {
3
3
  #private;
4
4
  constructor(browserKind?: BrowserKind);
@@ -16,6 +16,7 @@ export declare class BrowserImpl implements Browser {
16
16
  initialPage(): Page;
17
17
  pages(): Page[];
18
18
  newPage(options?: CommandOptions): Promise<Page>;
19
+ registerHook<T>(type: HookType<T>): Promise<Hook<T>>;
19
20
  close(): Promise<void>;
20
21
  ping(message?: string): Promise<string>;
21
22
  browserInfo(): BrowserInfo;
package/dist/browser.js CHANGED
@@ -66,6 +66,48 @@ export class BrowserImpl {
66
66
  }
67
67
  }
68
68
  }
69
+ async registerHook(type) {
70
+ this.#ensureOpen();
71
+ if (type.name !== "newPage") {
72
+ throw formatActionError("register hook", `unsupported hook type: ${type.name}`);
73
+ }
74
+ this.#stream.write({ registerHook: { newPage: {} } });
75
+ while (true) {
76
+ const event = await this.#queue.next();
77
+ if (event.hookRegistered?.hookId) {
78
+ const hookId = event.hookRegistered.hookId;
79
+ return {
80
+ id: hookId,
81
+ type,
82
+ wait: (options = {}) => this.#waitForHook(hookId, type, options),
83
+ };
84
+ }
85
+ if (event.error?.message) {
86
+ throw formatActionError(`register ${type.name} hook`, event.error.message);
87
+ }
88
+ }
89
+ }
90
+ async #waitForHook(hookId, type, options) {
91
+ this.#ensureOpen();
92
+ this.#stream.write({
93
+ waitForHook: {
94
+ hookId,
95
+ retryOptions: options.timeoutMs ? { timeoutMs: options.timeoutMs } : undefined,
96
+ },
97
+ });
98
+ while (true) {
99
+ const event = await this.#queue.next();
100
+ if (event.hookCompleted?.hookId === hookId) {
101
+ if (type.name === "newPage" && event.hookCompleted.newPage?.contextSessionId) {
102
+ return this.#createPage(event.hookCompleted.newPage.contextSessionId);
103
+ }
104
+ throw formatActionError(`wait for ${type.name} hook`, "hook returned an invalid result");
105
+ }
106
+ if (event.error?.message) {
107
+ throw formatActionError(`wait for ${type.name} hook`, event.error.message);
108
+ }
109
+ }
110
+ }
69
111
  async close() {
70
112
  if (this.#closed) {
71
113
  return;
package/dist/index.d.ts CHANGED
@@ -3,11 +3,14 @@ import { findConfigFile, loadConfigFile, resolveConfig } from "./config.js";
3
3
  import { mobile } from "./mobile.js";
4
4
  import { PageImpl } from "./page.js";
5
5
  import { setServerAddr, shutdown } from "./runtime.js";
6
- import type { Browser, BrowserKind, BrowserType, LaunchOptions, Page, ResolveConfigOptions, ResolvedAllwrightConfig } from "./types.js";
6
+ import type { Browser, BrowserKind, BrowserType, LaunchOptions, Page, HookType, ResolveConfigOptions, ResolvedAllwrightConfig } from "./types.js";
7
7
  export { findConfigFile, loadConfigFile, resolveConfig, setServerAddr, shutdown };
8
- export type { AccessibilitySnapshotOptions, AllwrightConfig, Browser, BrowserInfo, BrowserKind, BrowserType, ClickResult, CommandOptions, CountResult, ElementResult, FillResult, HighlightOptions, HighlightResult, LaunchOptions, MobileAndroidConnectOptions, MobileAndroidDevice, MobileAndroidLaunchOptions, MobileAndroidLocator, MobileAndroidApp, Locator, LocatorInfo, MobileSurfaceNamespace, NavigateResult, Page, PageInfo, PressOptions, PressResult, ResolveConfigOptions, ResolvedAllwrightConfig, RetryConfig, ScreenshotOptions, ScreenshotResult, TextResult, WaitForSelectorOptions, WaitForSelectorResult, } from "./types.js";
8
+ export type { AccessibilitySnapshotOptions, AllwrightConfig, Browser, BrowserInfo, BrowserKind, BrowserType, Hook, HookType, ClickResult, CommandOptions, CountResult, ElementResult, FillResult, HighlightOptions, HighlightResult, LaunchOptions, MobileAndroidConnectOptions, MobileAndroidDevice, MobileAndroidLaunchOptions, MobileAndroidLocator, MobileAndroidApp, Locator, LocatorInfo, MobileSurfaceNamespace, NavigateResult, Page, PageInfo, PressOptions, PressResult, ResolveConfigOptions, ResolvedAllwrightConfig, RetryConfig, ScreenshotOptions, ScreenshotResult, TextResult, WaitForSelectorOptions, WaitForSelectorResult, } from "./types.js";
9
9
  export declare const chromium: BrowserType;
10
10
  export declare const firefox: BrowserType;
11
+ export declare const hooks: {
12
+ newPage: HookType<Page>;
13
+ };
11
14
  export { mobile };
12
15
  export type Tab = Page;
13
16
  export declare function ping(): Promise<string>;
package/dist/index.js CHANGED
@@ -7,6 +7,9 @@ import { createBrowserSessionHandle, getRuntime, launchConfiguredBrowser as laun
7
7
  export { findConfigFile, loadConfigFile, resolveConfig, setServerAddr, shutdown };
8
8
  export const chromium = new BrowserTypeImpl("chromium");
9
9
  export const firefox = new BrowserTypeImpl("firefox");
10
+ export const hooks = {
11
+ newPage: Object.freeze({ name: "newPage" }),
12
+ };
10
13
  export { mobile };
11
14
  export async function ping() {
12
15
  return runtimePing();
package/dist/types.d.ts CHANGED
@@ -98,6 +98,16 @@ export interface LocatorInfo {
98
98
  export interface BrowserType {
99
99
  launch(options?: LaunchOptions): Promise<Browser>;
100
100
  }
101
+ declare const hookOutput: unique symbol;
102
+ export interface HookType<T> {
103
+ readonly name: string;
104
+ readonly [hookOutput]: T;
105
+ }
106
+ export interface Hook<T> {
107
+ readonly id: string;
108
+ readonly type: HookType<T>;
109
+ wait(options?: CommandOptions): Promise<T>;
110
+ }
101
111
  export interface Browser extends BrowserInfo {
102
112
  page(): Page;
103
113
  initialPage(): Page;
@@ -105,6 +115,7 @@ export interface Browser extends BrowserInfo {
105
115
  pages(): Page[];
106
116
  newPage(options?: CommandOptions): Promise<Page>;
107
117
  newTab(options?: CommandOptions): Promise<Page>;
118
+ registerHook<T>(type: HookType<T>): Promise<Hook<T>>;
108
119
  close(): Promise<void>;
109
120
  ping(message?: string): Promise<string>;
110
121
  browserInfo(): BrowserInfo;
@@ -338,6 +349,18 @@ export interface SurfaceSessionEvent {
338
349
  contextSessionId?: string;
339
350
  note?: string;
340
351
  };
352
+ hookRegistered?: {
353
+ hookId?: string;
354
+ hookType?: number;
355
+ };
356
+ hookCompleted?: {
357
+ hookId?: string;
358
+ hookType?: number;
359
+ newPage?: {
360
+ contextSessionId?: string;
361
+ note?: string;
362
+ };
363
+ };
341
364
  pong?: {
342
365
  message?: string;
343
366
  };
@@ -455,6 +478,19 @@ export interface OpenContextRequest {
455
478
  };
456
479
  };
457
480
  }
481
+ export interface RegisterHookRequest {
482
+ registerHook: {
483
+ newPage?: Record<string, never>;
484
+ };
485
+ }
486
+ export interface WaitForHookRequest {
487
+ waitForHook: {
488
+ hookId: string;
489
+ retryOptions?: {
490
+ timeoutMs?: number;
491
+ };
492
+ };
493
+ }
458
494
  export interface ConnectMobileRequest {
459
495
  connectMobile: {
460
496
  platform: number;
@@ -633,7 +669,7 @@ export interface CloseContextRequest {
633
669
  contextSessionId: string;
634
670
  close: Record<string, never>;
635
671
  }
636
- export type SurfaceSessionRequest = LaunchBrowserRequest | LaunchChromeRequest | OpenContextRequest | ConnectMobileRequest | LaunchAppRequest | SurfacePingRequest | CloseSurfaceRequest;
672
+ export type SurfaceSessionRequest = LaunchBrowserRequest | LaunchChromeRequest | OpenContextRequest | RegisterHookRequest | WaitForHookRequest | ConnectMobileRequest | LaunchAppRequest | SurfacePingRequest | CloseSurfaceRequest;
637
673
  export type ContextSessionRequest = ContextPingRequest | NavigateRequest | ClickRequest | CountRequest | HighlightRequest | FocusRequest | FillRequest | HoverRequest | PressRequest | TextContentRequest | InnerTextRequest | WaitForSelectorRequest | AccessibilitySnapshotRequest | ScreenshotRequest | CloseContextRequest;
638
674
  export type SurfaceSessionStream = grpc.ClientDuplexStream<SurfaceSessionRequest, SurfaceSessionEvent>;
639
675
  export type ContextSessionStream = grpc.ClientDuplexStream<ContextSessionRequest, ContextSessionEvent>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allwright.dev/core",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "High-level TypeScript client for the allwright automation engine.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,6 +18,8 @@ message SurfaceSessionCommand {
18
18
  LaunchBrowserCommand launch_browser = 5;
19
19
  ConnectMobileCommand connect_mobile = 6;
20
20
  LaunchAppCommand launch_app = 7;
21
+ RegisterHookCommand register_hook = 8;
22
+ WaitForHookCommand wait_for_hook = 9;
21
23
  }
22
24
  }
23
25
 
@@ -31,6 +33,17 @@ message SessionPingCommand {
31
33
 
32
34
  message CloseSurfaceSessionCommand {}
33
35
 
36
+ message RegisterHookCommand {
37
+ oneof hook {
38
+ RegisterNewPageHook new_page = 1;
39
+ }
40
+ }
41
+
42
+ message WaitForHookCommand {
43
+ string hook_id = 1;
44
+ optional CommandRetryOptions retry_options = 2;
45
+ }
46
+
34
47
  message SurfaceSessionEvent {
35
48
  string session_id = 1;
36
49
 
@@ -43,6 +56,8 @@ message SurfaceSessionEvent {
43
56
  BrowserLaunchedEvent browser_launched = 7;
44
57
  MobileConnectedEvent mobile_connected = 8;
45
58
  AppLaunchedEvent app_launched = 9;
59
+ HookRegisteredEvent hook_registered = 10;
60
+ HookCompletedEvent hook_completed = 11;
46
61
  }
47
62
  }
48
63
 
@@ -62,3 +77,15 @@ message SurfaceSessionClosedEvent {
62
77
  message SurfaceSessionErrorEvent {
63
78
  string message = 1;
64
79
  }
80
+
81
+ message HookRegisteredEvent {
82
+ string hook_id = 1;
83
+ }
84
+
85
+ message HookCompletedEvent {
86
+ string hook_id = 1;
87
+
88
+ oneof result {
89
+ NewPageHookResult new_page = 2;
90
+ }
91
+ }
@@ -39,3 +39,10 @@ message ChromeLaunchedEvent {
39
39
  string user_data_dir = 4;
40
40
  string initial_page_session_id = 5;
41
41
  }
42
+
43
+ message RegisterNewPageHook {}
44
+
45
+ message NewPageHookResult {
46
+ string context_session_id = 1;
47
+ string note = 2;
48
+ }