screenci 0.0.79 → 0.0.81
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 +12 -12
- package/dist/cli.d.ts +7 -21
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +23 -359
- package/dist/cli.js.map +1 -1
- package/dist/docs/video-sources/installation.screenci.js +2 -7
- package/dist/docs/video-sources/installation.screenci.js.map +1 -1
- package/dist/docs/video-sources/landing.screenci.js +1 -6
- package/dist/docs/video-sources/landing.screenci.js.map +1 -1
- package/dist/docs/video-sources/speaking-style.screenci.js +8 -35
- package/dist/docs/video-sources/speaking-style.screenci.js.map +1 -1
- package/dist/docs/video-sources/vertical-video.screenci.js +8 -46
- package/dist/docs/video-sources/vertical-video.screenci.js.map +1 -1
- package/dist/src/events.d.ts +3 -3
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/init.d.ts +10 -10
- package/dist/src/init.d.ts.map +1 -1
- package/dist/src/init.js +74 -57
- package/dist/src/init.js.map +1 -1
- package/dist/src/linkSession.d.ts +25 -28
- package/dist/src/linkSession.d.ts.map +1 -1
- package/dist/src/linkSession.js +74 -58
- package/dist/src/linkSession.js.map +1 -1
- package/dist/src/localize.d.ts +3 -2
- package/dist/src/localize.d.ts.map +1 -1
- package/dist/src/localize.js +3 -3
- package/dist/src/localize.js.map +1 -1
- package/dist/src/video.d.ts +7 -9
- package/dist/src/video.d.ts.map +1 -1
- package/dist/src/video.js +5 -7
- package/dist/src/video.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/skills/screenci/SKILL.md +32 -41
- package/skills/screenci/references/init.md +7 -7
- package/skills/screenci/references/record.md +8 -7
- package/dist/src/openBrowser.d.ts +0 -34
- package/dist/src/openBrowser.d.ts.map +0 -1
- package/dist/src/openBrowser.js +0 -62
- package/dist/src/openBrowser.js.map +0 -1
package/skills/screenci/SKILL.md
CHANGED
|
@@ -50,23 +50,26 @@ ScreenCI uses Playwright-style `.screenci.ts` files and adds recording-specific
|
|
|
50
50
|
- `hide()` removes setup and loading sections from the final recording.
|
|
51
51
|
- `autoZoom()` follows navigation, click-driven, and broader interaction sequences with smooth camera motion. Use it sparingly, and start with its default options unless the user explicitly asks for different zoom behavior or the flow clearly needs a targeted override.
|
|
52
52
|
- `zoomTo()` and `resetZoom()` are better for forms and other steady editing sections where the camera should stay fixed while the user types, selects, toggles, and confirms within one area.
|
|
53
|
-
- `video.
|
|
53
|
+
- `video.narration({ ... })` is mandatory for every video: declare narration in every `.screenci.ts` file and include spoken narration throughout the demo. Pass either a flat object of cue name to text (shared across all languages) or an object keyed by language (`en`, `es`, ...) of cue name to text. The opening narration should first state the purpose of the video, then continue with the explanation or walkthrough. The body receives the `narration` marker object: call `await narration.key()` for the common case where the full line should run before moving on. Use `await narration.key.start()` when narration should overlap with the next action, and `await narration.key.end()` only to close that same active cue later, especially before visible navigation or route changes. Voice is a render option, not part of the narration spec: set a default (and optional per-language overrides) with `video.use({ renderOptions: { narration: { voice: { name: voices.Ava } } } })` or in `screenci.config.ts`.
|
|
54
54
|
- Narration text can include inline speech-control tags such as `[pronounce: screen see eye]`, `[short pause]`, `[medium pause]`, and `[long pause]` when a word needs guided pronunciation or an intentional pause. When narration includes a URL or domain name, add a pronunciation guide or rewrite the line so it will be spoken clearly. Example: `screenci.com [pronounce: screen see eye dot com]`.
|
|
55
55
|
|
|
56
56
|
Example:
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
|
-
video
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
import { video, voices } from 'screenci'
|
|
60
|
+
|
|
61
|
+
// Voice is a render option (how narration is spoken).
|
|
62
|
+
video.use({ renderOptions: { narration: { voice: { name: voices.Ava } } } })
|
|
63
|
+
|
|
64
|
+
video.narration({
|
|
65
|
+
en: {
|
|
66
|
+
intro:
|
|
67
|
+
'This video shows how to update your billing details and save the changes.',
|
|
68
|
+
explainForm:
|
|
69
|
+
'We start on the billing page and update the company name, email, and tax ID.',
|
|
70
|
+
saving: 'Now we save the changes and wait for the confirmation message.',
|
|
71
|
+
nextPage:
|
|
72
|
+
'Next, we open the invoices section to confirm the new billing details are in use.',
|
|
70
73
|
},
|
|
71
74
|
})('Update billing details', async ({ page, narration }) => {
|
|
72
75
|
await narration.intro()
|
|
@@ -83,7 +86,7 @@ video.localize({
|
|
|
83
86
|
|
|
84
87
|
**Every video MUST follow these conventions:**
|
|
85
88
|
|
|
86
|
-
- **Narration on every video (required, no exceptions)** — always declare `video.
|
|
89
|
+
- **Narration on every video (required, no exceptions)** — always declare `video.narration({ ... })` and add narration to every `.screenci.ts` file. Videos without narration are not acceptable.
|
|
87
90
|
- **Open with the video's purpose** — the first spoken narration should clearly state what the video is for before moving into the step-by-step explanation.
|
|
88
91
|
- **Guide pronunciation for URLs and domains** — if narration says a URL, domain, product name, or other term that a voice model might read incorrectly, add a `[pronounce: ...]` hint or phrase it in a clearly spoken way.
|
|
89
92
|
- **Start on the requested page** — the visible video should always begin on the page the user requested.
|
|
@@ -123,48 +126,36 @@ await autoZoom(async () => {
|
|
|
123
126
|
|
|
124
127
|
## Command Notes
|
|
125
128
|
|
|
126
|
-
- `screenci init` (or `npm init screenci`) scaffolds a new project. It can be run at any time, but if the project is already initialized it fails on purpose: it exits with an error like `screenci/ already exists`. That is expected, not a problem to fix. Do not delete the existing project to force a re-init. Continue working with the project that is already there.
|
|
129
|
+
- `screenci init` (or `npm init screenci`) scaffolds a new project. It can be run at any time, but if the project is already initialized it fails on purpose: it exits with an error like `screenci/ already exists`. That is expected, not a problem to fix. Do not delete the existing project to force a re-init. Continue working with the project that is already there. If the user gives you a one-time setup token (it looks like `otp_...`), pass it as the first argument (`npm init screenci@latest otp_... -- --yes`) and init connects the project by writing `SCREENCI_SECRET` into `screenci/.env`.
|
|
127
130
|
- `screenci record` runs the recording flow with local Playwright.
|
|
128
131
|
- `screenci test <playwright args...>` forwards most Playwright test arguments unchanged, while still using `screenci.config.ts`.
|
|
129
132
|
|
|
130
|
-
###
|
|
133
|
+
### Connect the project (do this first)
|
|
131
134
|
|
|
132
|
-
|
|
135
|
+
`screenci record` needs a `SCREENCI_SECRET`. There is no browser sign-in; connect the project one of two ways:
|
|
133
136
|
|
|
134
|
-
1.
|
|
135
|
-
2.
|
|
136
|
-
3. Build and test the video as normal (`npx screenci test`) while they sign in.
|
|
137
|
-
4. For the final recording, run `npx screenci record` yourself (no special flag). If the user already signed in it records immediately; otherwise it prints the link, waits, and records automatically once they finish. Do not hand this step back to the user. If sign-in does not happen before the timeout, `record` exits non-zero and reprints the still-valid link: re-surface it, ask the user to sign in, and run `npx screenci record` again.
|
|
137
|
+
1. **One-time setup token.** If the user gave you a token (`otp_...`), run `npm init screenci@latest <token> -- --yes`. Init exchanges the token for the org's `SCREENCI_SECRET` and writes it into `screenci/.env`, so `record` uploads immediately on the free tier. The token is single-use and short-lived.
|
|
138
|
+
2. **Get Started page or secrets page.** If you have no token (or it was already used or expired), ask the user to open their ScreenCI **Get Started** page and copy the shown init command (it embeds a fresh one-time token), or to copy `SCREENCI_SECRET` from their **secrets page** into `screenci/.env`. The org secret is shared across projects, so either works for a new project. Relay this and keep building and testing the video while they do it. Only the final `record` needs the secret.
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
If `SCREENCI_SECRET` is missing when you run `record`, it prints guidance and exits **non-zero** without recording. That is a setup step, not a code problem: get the secret into `screenci/.env` (token or secrets page) and run `npx screenci record` again. Do not hand the `record` step back to the user otherwise.
|
|
140
141
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
- At an **interactive terminal**, and in a **plain non-interactive run** (the common case for a coding agent: no terminal, no CI), `screenci record` prints a one-time auth link, **waits** for browser sign-in, saves the secret into the configured `envFile` or project `.env`, and continues recording automatically. You do not need `--poll-auth`; waiting is the default. If sign-in does not complete before the timeout, it exits **non-zero** with the link still valid, so rerun `record` once the user signs in.
|
|
144
|
-
- Under **CI** (`CI=true`), or with `SCREENCI_NONINTERACTIVE=1` or `--no-poll-auth`, `screenci record` does **not** wait. It prints the sign-in link and exits cleanly (exit code 0) **without recording**. In these cases a clean exit that printed a sign-in link is a handoff, not a finished recording: set `SCREENCI_SECRET` ahead of time (the expected setup for CI) so recording proceeds without an interactive sign-in.
|
|
145
|
-
|
|
146
|
-
- To skip sign-in entirely, set `SCREENCI_SECRET` ahead of time (env var or project `.env`).
|
|
147
|
-
- Pending auth state is cached in `.screenci/link-session.json`, so rerunning `record` reuses the same link until it expires or completes.
|
|
148
|
-
- `--poll-auth` still works (it forces waiting) but is no longer needed off-CI, where waiting is already the default.
|
|
142
|
+
Free renders include a ScreenCI watermark. Mention that the user can upgrade to remove it.
|
|
149
143
|
|
|
150
144
|
## Recording Workflow
|
|
151
145
|
|
|
152
|
-
1. Start from the existing initialized ScreenCI package. Early on,
|
|
146
|
+
1. Start from the existing initialized ScreenCI package. Early on, make sure the project is connected: either init already wrote `SCREENCI_SECRET` from a one-time setup token, or ask the user to copy `SCREENCI_SECRET` from their secrets page into `screenci/.env`. Only the final recording needs it, so keep building while they do it.
|
|
153
147
|
2. Add or edit `.screenci.ts` files in `recordings/`.
|
|
154
148
|
Remove `recordings/example.screenci.ts` if you are creating new videos and do not need the starter video.
|
|
155
|
-
For narration, declare it on the test with `video.
|
|
149
|
+
For narration, declare it on the test with `video.narration({ en: { ... } })` and trigger lines from the `narration` fixture with `await narration.someKey()` when the full line should finish before moving on. Use `await narration.someKey.start()` only when narration should overlap with the next action, and `await narration.someKey.end()` only to close that same active cue later. This is especially important before visible navigation or page changes. Use inline tags like `[pronounce: ...]` and `[short pause]` inside cue text when needed, especially for URLs and domains such as `screenci.com [pronounce: screen see eye dot com]`.
|
|
156
150
|
Example:
|
|
157
151
|
|
|
158
152
|
```ts
|
|
159
|
-
video.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
filters
|
|
164
|
-
|
|
165
|
-
export:
|
|
166
|
-
'Then we export the report and wait for the download to start.',
|
|
167
|
-
},
|
|
153
|
+
video.narration({
|
|
154
|
+
en: {
|
|
155
|
+
intro: 'This video shows how to export a monthly sales report.',
|
|
156
|
+
filters:
|
|
157
|
+
'First, we set the report range and select the sales channel filters.',
|
|
158
|
+
export: 'Then we export the report and wait for the download to start.',
|
|
168
159
|
},
|
|
169
160
|
})('Export sales report', async ({ page, narration }) => {
|
|
170
161
|
await narration.intro()
|
|
@@ -176,7 +167,7 @@ Signing in does not block writing or testing the video, only the final recording
|
|
|
176
167
|
```
|
|
177
168
|
|
|
178
169
|
3. Run `npx screenci test` until it passes.
|
|
179
|
-
4. For the final recording, run `npx screenci record` yourself
|
|
170
|
+
4. For the final recording, run `npx screenci record` yourself. If `SCREENCI_SECRET` is set it records and uploads immediately. If it is missing, `record` exits non-zero with guidance: get the secret into `screenci/.env` (one-time setup token or the secrets page) and run `npx screenci record` again. Do not hand this step back to the user otherwise.
|
|
180
171
|
5. ScreenCI writes `.screenci/<video-name>/recording.mp4` and `data.json` for each recorded video.
|
|
181
172
|
|
|
182
173
|
## Specific Tasks
|
|
@@ -30,20 +30,20 @@ package.json
|
|
|
30
30
|
## Notes
|
|
31
31
|
|
|
32
32
|
- `init` can be run at any time, but it is non-destructive and will not re-initialize an existing project. If the project is already initialized (a `screenci/` directory already exists), it fails on purpose and exits with an error like `screenci/ already exists`. That is expected. Do not delete the existing project to force a re-init: continue working with the project that is already there.
|
|
33
|
-
-
|
|
34
|
-
-
|
|
33
|
+
- `init` accepts a one-time setup token as its first positional argument (it looks like `otp_...`, copied from the Get Started or secrets page). With a token, init exchanges it for the org's `SCREENCI_SECRET` and writes it into `screenci/.env`, so `record` uploads immediately on the free tier. The token is single-use and short-lived; a used or expired token falls back to the manual path without failing the scaffold.
|
|
34
|
+
- Without a token, init tells you to copy `SCREENCI_SECRET` from the secrets page into `screenci/.env` before the first record. There is no browser sign-in. A fresh token (and a ready-to-run command) is always available on the Get Started page, including for adding a second project; the org secret is shared across projects.
|
|
35
|
+
- Prefer `--yes` for non-interactive setup. Without it, the command prompts for setup choices and defaults the project name to the current directory name when none is provided. A positional that looks like a setup token is treated as the token, not the project name.
|
|
35
36
|
- The name is used as the ScreenCI project display name. Files are always created in the current directory.
|
|
36
37
|
- `--yes` accepts the defaults.
|
|
37
38
|
- `--agent <name>` is passed to the selected skills install command.
|
|
38
39
|
- `--verbose` shows more setup output.
|
|
39
|
-
- `record`
|
|
40
|
+
- `record` requires `SCREENCI_SECRET`; it does not bootstrap it.
|
|
40
41
|
- `record` uses local Playwright.
|
|
41
42
|
|
|
42
43
|
## Typical Flow
|
|
43
44
|
|
|
44
45
|
```bash
|
|
45
|
-
npm init screenci
|
|
46
|
-
npx screenci
|
|
47
|
-
npx screenci
|
|
48
|
-
npx screenci record # capture the final recording (waits for sign-in if pending)
|
|
46
|
+
npm init screenci@latest otp_your_token -- --yes # connects the project (writes SCREENCI_SECRET)
|
|
47
|
+
npx screenci test # verify the video works
|
|
48
|
+
npx screenci record # capture the final recording and upload
|
|
49
49
|
```
|
|
@@ -19,19 +19,20 @@ npx screenci record -c screenci.config.ts
|
|
|
19
19
|
- Saves output under `.screenci/<video-name>/`
|
|
20
20
|
- Produces at least `recording.mp4` and `data.json`
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Connect Before Recording
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
`record` needs `SCREENCI_SECRET`, and there is no browser sign-in. Get it in place before the final recording (it does not block authoring or testing):
|
|
25
|
+
|
|
26
|
+
- If the user has a one-time setup token (`otp_...`), run `npm init screenci@latest <token> -- --yes`; init writes `SCREENCI_SECRET` into `screenci/.env`. A fresh token is on the user's Get Started page.
|
|
27
|
+
- Otherwise ask the user to copy `SCREENCI_SECRET` from their secrets page into `screenci/.env`. The org secret is shared across projects.
|
|
25
28
|
|
|
26
29
|
## Runtime Behavior
|
|
27
30
|
|
|
28
31
|
- Recording runs with local Playwright.
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- `--poll-auth` still forces waiting and is kept for backwards compatibility, but is no longer needed off-CI where waiting is already the default.
|
|
32
|
-
- Pending auth state is cached in `.screenci/link-session.json`, so rerunning `record` reuses the same link until it expires or completes.
|
|
32
|
+
- `SCREENCI_SECRET` is required (from `screenci/.env` or the environment). If it is missing, `screenci record` prints guidance (pointing at the secrets page) and exits **non-zero** without recording. Get the secret in place and rerun. This is a setup step, not a code problem.
|
|
33
|
+
- New accounts start on the free tier; free renders include a ScreenCI watermark, and after upload `record` prints an upgrade link that removes it.
|
|
33
34
|
- Playwright arguments can be passed through after the command.
|
|
34
|
-
- When API configuration and `SCREENCI_SECRET` are available, uploads
|
|
35
|
+
- When API configuration and `SCREENCI_SECRET` are available, uploads run after recording.
|
|
35
36
|
|
|
36
37
|
## Recommended Workflow
|
|
37
38
|
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
export type BrowserOpenSpec = {
|
|
3
|
-
command: string;
|
|
4
|
-
args: string[];
|
|
5
|
-
};
|
|
6
|
-
export type OpenBrowserResult = {
|
|
7
|
-
opened: true;
|
|
8
|
-
} | {
|
|
9
|
-
opened: false;
|
|
10
|
-
reason: string;
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Resolve the platform-specific command that opens a URL in the default
|
|
14
|
-
* browser: `open` on macOS, `cmd /c start` on Windows, and `xdg-open`
|
|
15
|
-
* everywhere else (Linux, BSD). The empty `""` on Windows is `start`'s window
|
|
16
|
-
* title argument, so a quoted URL is not consumed as the title.
|
|
17
|
-
*/
|
|
18
|
-
export declare function resolveBrowserOpenSpec(url: string, platform?: NodeJS.Platform): BrowserOpenSpec;
|
|
19
|
-
/**
|
|
20
|
-
* Try to open `url` in the user's default browser. Best-effort: a synchronous
|
|
21
|
-
* spawn failure or an asynchronous launch error (e.g. `xdg-open` missing on a
|
|
22
|
-
* minimal Linux box) resolves to `{ opened: false, reason }` instead of
|
|
23
|
-
* throwing. A resolved `{ opened: true }` only means the launch was dispatched,
|
|
24
|
-
* not that a browser window actually appeared, so callers still surface the
|
|
25
|
-
* link as a fallback.
|
|
26
|
-
*
|
|
27
|
-
* Dependency-injected (`platform`, `spawnFn`) so tests can drive both outcomes
|
|
28
|
-
* without a real terminal or browser.
|
|
29
|
-
*/
|
|
30
|
-
export declare function openUrlInBrowser(url: string, options?: {
|
|
31
|
-
platform?: NodeJS.Platform;
|
|
32
|
-
spawnFn?: typeof spawn;
|
|
33
|
-
}): Promise<OpenBrowserResult>;
|
|
34
|
-
//# sourceMappingURL=openBrowser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openBrowser.d.ts","sourceRoot":"","sources":["../../src/openBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAQrC,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAAA;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,GAChB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,eAAe,CAQjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CAClB,GACL,OAAO,CAAC,iBAAiB,CAAC,CAqC5B"}
|
package/dist/src/openBrowser.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
/**
|
|
3
|
-
* Resolve the platform-specific command that opens a URL in the default
|
|
4
|
-
* browser: `open` on macOS, `cmd /c start` on Windows, and `xdg-open`
|
|
5
|
-
* everywhere else (Linux, BSD). The empty `""` on Windows is `start`'s window
|
|
6
|
-
* title argument, so a quoted URL is not consumed as the title.
|
|
7
|
-
*/
|
|
8
|
-
export function resolveBrowserOpenSpec(url, platform = process.platform) {
|
|
9
|
-
if (platform === 'darwin') {
|
|
10
|
-
return { command: 'open', args: [url] };
|
|
11
|
-
}
|
|
12
|
-
if (platform === 'win32') {
|
|
13
|
-
return { command: 'cmd', args: ['/c', 'start', '', url] };
|
|
14
|
-
}
|
|
15
|
-
return { command: 'xdg-open', args: [url] };
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Try to open `url` in the user's default browser. Best-effort: a synchronous
|
|
19
|
-
* spawn failure or an asynchronous launch error (e.g. `xdg-open` missing on a
|
|
20
|
-
* minimal Linux box) resolves to `{ opened: false, reason }` instead of
|
|
21
|
-
* throwing. A resolved `{ opened: true }` only means the launch was dispatched,
|
|
22
|
-
* not that a browser window actually appeared, so callers still surface the
|
|
23
|
-
* link as a fallback.
|
|
24
|
-
*
|
|
25
|
-
* Dependency-injected (`platform`, `spawnFn`) so tests can drive both outcomes
|
|
26
|
-
* without a real terminal or browser.
|
|
27
|
-
*/
|
|
28
|
-
export async function openUrlInBrowser(url, options = {}) {
|
|
29
|
-
const platform = options.platform ?? process.platform;
|
|
30
|
-
const spawnFn = options.spawnFn ?? spawn;
|
|
31
|
-
const spec = resolveBrowserOpenSpec(url, platform);
|
|
32
|
-
let child;
|
|
33
|
-
try {
|
|
34
|
-
child = spawnFn(spec.command, spec.args, {
|
|
35
|
-
stdio: 'ignore',
|
|
36
|
-
detached: true,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
return {
|
|
41
|
-
opened: false,
|
|
42
|
-
reason: err instanceof Error ? err.message : String(err),
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
// Keep an error listener attached for the child's lifetime so a late launch
|
|
46
|
-
// error (e.g. ENOENT) is handled rather than thrown as an unhandled event.
|
|
47
|
-
const launchError = new Promise((resolveError) => {
|
|
48
|
-
child.on('error', resolveError);
|
|
49
|
-
});
|
|
50
|
-
// Detach so the parent (login) can exit without waiting on the browser.
|
|
51
|
-
child.unref();
|
|
52
|
-
// ENOENT and friends surface on the next tick, ahead of this setImmediate, so
|
|
53
|
-
// a failed launch wins the race; otherwise we treat the dispatch as success.
|
|
54
|
-
const settled = new Promise((resolveTick) => {
|
|
55
|
-
setImmediate(() => resolveTick(null));
|
|
56
|
-
});
|
|
57
|
-
const result = await Promise.race([launchError, settled]);
|
|
58
|
-
return result === null
|
|
59
|
-
? { opened: true }
|
|
60
|
-
: { opened: false, reason: result.message };
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=openBrowser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openBrowser.js","sourceRoot":"","sources":["../../src/openBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAiBrC;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAW,EACX,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;IACzC,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAA;IAC3D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,UAGI,EAAE;IAEN,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAA;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAA;IACxC,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAElD,IAAI,KAA+B,CAAA;IACnC,IAAI,CAAC;QACH,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE;YACvC,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;SACC,CAAC,CAAA;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAA;IACH,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,WAAW,GAAG,IAAI,OAAO,CAAQ,CAAC,YAAY,EAAE,EAAE;QACtD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,wEAAwE;IACxE,KAAK,CAAC,KAAK,EAAE,CAAA;IAEb,8EAA8E;IAC9E,6EAA6E;IAC7E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,WAAW,EAAE,EAAE;QAChD,YAAY,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;IACzD,OAAO,MAAM,KAAK,IAAI;QACpB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;QAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;AAC/C,CAAC"}
|