single-file-cli 2.0.27 → 2.0.28

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/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@single-file/single-file-cli",
3
- "version": "2.0.27",
3
+ "version": "2.0.28",
4
4
  "description": "SingleFile CLI",
5
5
  "nodeModulesDir": true,
6
6
  "exports": {
package/lib/cdp-client.js CHANGED
@@ -161,64 +161,78 @@ async function loadPage({ Page, Runtime }, options) {
161
161
  }
162
162
  }
163
163
 
164
- function getTopFrameContextId({ Page, Runtime }, options) {
165
- return new Promise((resolve, reject) => {
166
- const FRAME_NAVIGATED_EVENT = "frameNavigated";
167
- const CONTEXT_CREATED_EVENT = "executionContextCreated";
168
- const contextIds = [];
169
- let frameId;
164
+ async function getTopFrameContextId({ Page, Runtime }, options) {
165
+ const FRAME_NAVIGATED_EVENT = "frameNavigated";
166
+ const CONTEXT_CREATED_EVENT = "executionContextCreated";
167
+ const contextIds = [];
168
+ let topFrameId;
169
+ try {
170
170
  Page.addEventListener(FRAME_NAVIGATED_EVENT, onFrameNavigated);
171
171
  Runtime.addEventListener(CONTEXT_CREATED_EVENT, onExecutionContextCreated);
172
-
173
- async function onFrameNavigated({ params }) {
174
- try {
175
- const { frame } = params;
176
- if (!frame.parentId) {
177
- if (frame.unreachableUrl) {
178
- reject(new Error("Unreachable URL: " + frame.unreachableUrl));
179
- } else {
180
- frameId = frame.id;
181
- await onTopFrameNavigated();
182
- }
183
- }
184
- } finally {
185
- Page.removeEventListener(FRAME_NAVIGATED_EVENT, onFrameNavigated);
186
- Runtime.removeEventListener(CONTEXT_CREATED_EVENT, onExecutionContextCreated);
187
- }
172
+ await waitForPageReady({ Page }, options);
173
+ const contextId = await getContextId();
174
+ if (contextId === undefined) {
175
+ throw new Error("Execution context not found");
176
+ } else {
177
+ return contextId;
188
178
  }
179
+ } finally {
180
+ Page.removeEventListener(FRAME_NAVIGATED_EVENT, onFrameNavigated);
181
+ Runtime.removeEventListener(CONTEXT_CREATED_EVENT, onExecutionContextCreated);
182
+ }
189
183
 
190
- async function onTopFrameNavigated() {
191
- await waitForPageReady({ Page }, frameId, options);
192
- const contextId = await getContextId();
193
- if (contextId === undefined) {
194
- reject(new Error("Execution context not found"));
184
+ function onFrameNavigated({ params }) {
185
+ const { frame } = params;
186
+ if (!frame.parentId) {
187
+ if (frame.unreachableUrl) {
188
+ throw new Error("Unreachable URL: " + frame.unreachableUrl);
195
189
  } else {
196
- resolve(contextId);
190
+ topFrameId = frame.id;
197
191
  }
198
192
  }
193
+ }
199
194
 
200
- async function getContextId() {
201
- let contextId;
202
- if (contextIds.length) {
203
- let contextIdIndex = 0;
204
- do {
205
- if (await testExecutionContext(contextIds[contextIdIndex])) {
206
- contextId = contextIds[contextIdIndex];
195
+ function onExecutionContextCreated({ params }) {
196
+ const { context } = params;
197
+ const { name, auxData = {} } = context;
198
+ if (name === SINGLE_FILE_WORLD_NAME && topFrameId !== undefined && auxData.frameId === topFrameId) {
199
+ contextIds.unshift(context.id);
200
+ }
201
+ }
202
+
203
+ async function waitForPageReady({ Page }, options) {
204
+ await Page.setLifecycleEventsEnabled({ enabled: true });
205
+ try {
206
+ await new Promise(resolve => {
207
+ const LIFE_CYCLE_EVENT = "lifecycleEvent";
208
+ Page.addEventListener(LIFE_CYCLE_EVENT, onLifecycleEvent);
209
+
210
+ function onLifecycleEvent({ params }) {
211
+ const { frameId, name } = params;
212
+ if (frameId === topFrameId && (name === options.browserWaitUntil || name === DEFAULT_NETWORK_STATE)) {
213
+ Page.removeEventListener(LIFE_CYCLE_EVENT, onLifecycleEvent);
214
+ resolve();
207
215
  }
208
- contextIdIndex++;
209
- } while (contextId === undefined && contextIdIndex < contextIds.length);
210
- }
211
- return contextId;
216
+ }
217
+ });
218
+ } finally {
219
+ await Page.setLifecycleEventsEnabled({ enabled: false });
212
220
  }
221
+ }
213
222
 
214
- function onExecutionContextCreated({ params }) {
215
- const { context } = params;
216
- const { name, origin, auxData } = context;
217
- if (frameId !== undefined && origin === "://" && name === SINGLE_FILE_WORLD_NAME && auxData && auxData.frameId === frameId) {
218
- contextIds.push(context.id);
219
- }
223
+ async function getContextId() {
224
+ let contextId;
225
+ if (contextIds.length) {
226
+ let contextIdIndex = 0;
227
+ do {
228
+ if (await testExecutionContext(contextIds[contextIdIndex])) {
229
+ contextId = contextIds[contextIdIndex];
230
+ }
231
+ contextIdIndex++;
232
+ } while (contextId === undefined && contextIdIndex < contextIds.length);
220
233
  }
221
- });
234
+ return contextId;
235
+ }
222
236
 
223
237
  async function testExecutionContext(contextId) {
224
238
  try {
@@ -253,26 +267,6 @@ function waitForLoadTimeout(abortSignal, maxDelay) {
253
267
  });
254
268
  }
255
269
 
256
- async function waitForPageReady({ Page }, topFrameId, options) {
257
- await Page.setLifecycleEventsEnabled({ enabled: true });
258
- try {
259
- await new Promise(resolve => {
260
- const LIFE_CYCLE_EVENT = "lifecycleEvent";
261
- Page.addEventListener(LIFE_CYCLE_EVENT, onLifecycleEvent);
262
-
263
- function onLifecycleEvent({ params }) {
264
- const { name, frameId } = params;
265
- if (frameId === topFrameId && (name === options.browserWaitUntil || name === DEFAULT_NETWORK_STATE)) {
266
- Page.removeEventListener(LIFE_CYCLE_EVENT, onLifecycleEvent);
267
- resolve();
268
- }
269
- }
270
- });
271
- } finally {
272
- await Page.setLifecycleEventsEnabled({ enabled: false });
273
- }
274
- }
275
-
276
270
  async function waitForDebuggerReady({ Debugger }) {
277
271
  await Debugger.enable();
278
272
  try {
@@ -80,7 +80,7 @@ const Command = DENO_RUNTIME_DETECTED ? Deno.Command : class Command {
80
80
  return {
81
81
  status: new Promise((resolve, reject) => {
82
82
  child.on("exit", code => {
83
- if (code === 0 || code === 143) {
83
+ if (code === 0 || code === 143 || code === 130) {
84
84
  resolve();
85
85
  } else {
86
86
  reject(new Error(`Process exited with code ${code}`));
@@ -108,6 +108,7 @@ const DenoAPI = {
108
108
  remove,
109
109
  stdout,
110
110
  exit,
111
+ addSignalListener,
111
112
  build,
112
113
  errors,
113
114
  Command
@@ -207,6 +208,14 @@ function exit(code) {
207
208
  }
208
209
  }
209
210
 
211
+ function addSignalListener(signal, listener) {
212
+ if (DENO_RUNTIME_DETECTED) {
213
+ Deno.addSignalListener(signal, listener);
214
+ } else {
215
+ process.once(signal, listener);
216
+ }
217
+ }
218
+
210
219
  async function dirname(filePath) {
211
220
  return path.dirname(filePath);
212
221
  }
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "2.0.27";
1
+ export const version = "2.0.28";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-cli",
3
- "version": "2.0.27",
3
+ "version": "2.0.28",
4
4
  "description": "SingleFile CLI",
5
5
  "author": "Gildas Lormeau",
6
6
  "engines": {
@@ -22,10 +22,21 @@
22
22
  */
23
23
 
24
24
  import { initialize } from "./single-file-cli-api.js";
25
+ import { closeBrowser } from "./lib/browser.js";
25
26
  import { Deno } from "./lib/deno-polyfill.js";
26
27
  import options from "./options.js";
27
28
 
28
- const { readTextFile, exit } = Deno;
29
+ const { readTextFile, exit, addSignalListener } = Deno;
30
+
31
+ addSignalListener("SIGTERM", async () => {
32
+ await closeBrowser();
33
+ exit();
34
+ });
35
+
36
+ addSignalListener("SIGINT", async () => {
37
+ await closeBrowser();
38
+ exit();
39
+ });
29
40
 
30
41
  export { run };
31
42
 
@@ -104,4 +115,4 @@ function parseCookies(textValue) {
104
115
  }
105
116
  })
106
117
  .filter(cookieData => cookieData);
107
- }
118
+ }