@mintlify/previewing 4.0.1539 → 4.0.1541
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/dist/__tests__/dev.test.js +3 -3
- package/dist/__tests__/is-online.test.d.ts +1 -0
- package/dist/__tests__/is-online.test.js +87 -0
- package/dist/__tests__/packages-runtime-wiring.test.js +1 -1
- package/dist/__tests__/validate-build.test.js +2 -2
- package/dist/local-preview/client.js +1 -1
- package/dist/local-preview/export.js +1 -1
- package/dist/local-preview/index.js +1 -1
- package/dist/local-preview/is-online.d.ts +1 -0
- package/dist/local-preview/is-online.js +38 -0
- package/dist/local-preview/validate-build.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { prebuild } from '@mintlify/prebuild';
|
|
2
2
|
import fse from 'fs-extra';
|
|
3
|
-
import isOnline from 'is-online';
|
|
4
3
|
import { mockProcessExit } from 'vitest-mock-process';
|
|
5
4
|
import { dev } from '../index.js';
|
|
5
|
+
import { isOnline } from '../local-preview/is-online.js';
|
|
6
6
|
import { run } from '../local-preview/run.js';
|
|
7
7
|
import { silentUpdateClient } from '../local-preview/update.js';
|
|
8
8
|
import * as logs from '../logging-state.js';
|
|
@@ -27,8 +27,8 @@ vi.mock('../local-preview/update.js', () => ({
|
|
|
27
27
|
vi.mock('../local-preview/preview-lock.js', () => ({
|
|
28
28
|
acquirePreviewLock: vi.fn().mockReturnValue(vi.fn()),
|
|
29
29
|
}));
|
|
30
|
-
vi.mock('is-online', () => ({
|
|
31
|
-
|
|
30
|
+
vi.mock('../local-preview/is-online.js', () => ({
|
|
31
|
+
isOnline: vi.fn().mockResolvedValue(true),
|
|
32
32
|
}));
|
|
33
33
|
vi.mock('@mintlify/prebuild', () => ({
|
|
34
34
|
prebuild: vi.fn().mockResolvedValue(undefined),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import { isOnline } from '../local-preview/is-online.js';
|
|
3
|
+
const externalInterfaces = {
|
|
4
|
+
eth0: [
|
|
5
|
+
{
|
|
6
|
+
address: '203.0.113.5',
|
|
7
|
+
netmask: '255.255.255.0',
|
|
8
|
+
family: 'IPv4',
|
|
9
|
+
mac: '00:00:00:00:00:00',
|
|
10
|
+
internal: false,
|
|
11
|
+
cidr: '203.0.113.5/24',
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
const internalInterfaces = {
|
|
16
|
+
lo: [
|
|
17
|
+
{
|
|
18
|
+
address: '127.0.0.1',
|
|
19
|
+
netmask: '255.0.0.0',
|
|
20
|
+
family: 'IPv4',
|
|
21
|
+
mac: '00:00:00:00:00:00',
|
|
22
|
+
internal: true,
|
|
23
|
+
cidr: '127.0.0.1/8',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
const okResponse = () => ({
|
|
28
|
+
ok: true,
|
|
29
|
+
body: { cancel: vi.fn().mockResolvedValue(undefined) },
|
|
30
|
+
});
|
|
31
|
+
describe('isOnline', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.restoreAllMocks();
|
|
34
|
+
vi.unstubAllGlobals();
|
|
35
|
+
});
|
|
36
|
+
it('returns false without probing when every interface is internal', async () => {
|
|
37
|
+
vi.spyOn(os, 'networkInterfaces').mockReturnValue(internalInterfaces);
|
|
38
|
+
const fetchMock = vi.fn();
|
|
39
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
40
|
+
await expect(isOnline()).resolves.toBe(false);
|
|
41
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
42
|
+
});
|
|
43
|
+
it('returns true when one probe succeeds and aborts the other', async () => {
|
|
44
|
+
vi.spyOn(os, 'networkInterfaces').mockReturnValue(externalInterfaces);
|
|
45
|
+
const unhandled = [];
|
|
46
|
+
const onUnhandled = (reason) => {
|
|
47
|
+
unhandled.push(reason);
|
|
48
|
+
};
|
|
49
|
+
process.on('unhandledRejection', onUnhandled);
|
|
50
|
+
vi.stubGlobal('fetch', vi.fn((url, init) => {
|
|
51
|
+
if (String(url).includes('cloudflare')) {
|
|
52
|
+
return new Promise((_resolve, reject) => {
|
|
53
|
+
init?.signal?.addEventListener('abort', () => {
|
|
54
|
+
reject(init.signal?.reason ?? new Error('The operation was aborted'));
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return Promise.resolve(okResponse());
|
|
59
|
+
}));
|
|
60
|
+
await expect(isOnline(1_000)).resolves.toBe(true);
|
|
61
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
62
|
+
process.off('unhandledRejection', onUnhandled);
|
|
63
|
+
expect(unhandled).toEqual([]);
|
|
64
|
+
});
|
|
65
|
+
it('returns false when every probe fails', async () => {
|
|
66
|
+
vi.spyOn(os, 'networkInterfaces').mockReturnValue(externalInterfaces);
|
|
67
|
+
vi.stubGlobal('fetch', vi.fn(async () => ({ ok: false, status: 503 })));
|
|
68
|
+
await expect(isOnline()).resolves.toBe(false);
|
|
69
|
+
});
|
|
70
|
+
it('aborts a hung probe and does not surface the abort as an unhandled rejection', async () => {
|
|
71
|
+
vi.spyOn(os, 'networkInterfaces').mockReturnValue(externalInterfaces);
|
|
72
|
+
const unhandled = [];
|
|
73
|
+
const onUnhandled = (reason) => {
|
|
74
|
+
unhandled.push(reason);
|
|
75
|
+
};
|
|
76
|
+
process.on('unhandledRejection', onUnhandled);
|
|
77
|
+
vi.stubGlobal('fetch', vi.fn((_url, init) => new Promise((_resolve, reject) => {
|
|
78
|
+
init?.signal?.addEventListener('abort', () => {
|
|
79
|
+
reject(init.signal?.reason ?? new Error('The operation was aborted'));
|
|
80
|
+
});
|
|
81
|
+
})));
|
|
82
|
+
await expect(isOnline(20)).resolves.toBe(false);
|
|
83
|
+
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
84
|
+
process.off('unhandledRejection', onUnhandled);
|
|
85
|
+
expect(unhandled).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -30,7 +30,7 @@ vi.mock('@mintlify/prebuild', () => ({
|
|
|
30
30
|
prebuild: vi.fn().mockResolvedValue(undefined),
|
|
31
31
|
getFileListSync: vi.fn().mockReturnValue([]),
|
|
32
32
|
}));
|
|
33
|
-
vi.mock('is-online', () => ({
|
|
33
|
+
vi.mock('../local-preview/is-online.js', () => ({ isOnline: vi.fn().mockResolvedValue(true) }));
|
|
34
34
|
vi.mock('../local-preview/update.js', () => ({
|
|
35
35
|
silentUpdateClient: vi.fn().mockResolvedValue({ needsUpdate: false, error: undefined }),
|
|
36
36
|
}));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { prebuild } from '@mintlify/prebuild';
|
|
2
|
-
import isOnline from 'is-online';
|
|
2
|
+
import { isOnline } from '../local-preview/is-online.js';
|
|
3
3
|
import { checkBuild } from '../local-preview/validate-build.js';
|
|
4
4
|
import { addLog } from '../logging-state.js';
|
|
5
5
|
vi.mock('@mintlify/prebuild', async (importOriginal) => {
|
|
6
6
|
const mod = await importOriginal();
|
|
7
7
|
return { ...mod, prebuild: vi.fn() };
|
|
8
8
|
});
|
|
9
|
-
vi.mock('is-online', () => ({
|
|
9
|
+
vi.mock('../local-preview/is-online.js', () => ({ isOnline: vi.fn() }));
|
|
10
10
|
vi.mock('fs-extra', () => {
|
|
11
11
|
const mocks = {
|
|
12
12
|
ensureDir: vi.fn().mockResolvedValue(undefined),
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import fse from 'fs-extra';
|
|
2
2
|
import got from 'got';
|
|
3
|
-
import isOnline from 'is-online';
|
|
4
3
|
import yaml from 'js-yaml';
|
|
5
4
|
import { pipeline } from 'node:stream/promises';
|
|
6
5
|
import * as tar from 'tar';
|
|
7
6
|
import { PREVIEW_PATH, PREVIEW_LAST_PATH, VERSION_PATH, TAR_PATH, TARGET_MINT_VERSION_URL, MINT_VERSION_MAP_URL, } from '../constants.js';
|
|
8
7
|
import { restoreMintlifyLast, getTarUrl } from '../util.js';
|
|
8
|
+
import { isOnline } from './is-online.js';
|
|
9
9
|
export const getLatestClientVersion = async () => {
|
|
10
10
|
const hasInternet = await isOnline();
|
|
11
11
|
if (!hasInternet) {
|
|
@@ -5,7 +5,6 @@ import AdmZip from 'adm-zip';
|
|
|
5
5
|
import express from 'express';
|
|
6
6
|
import fse, { pathExists } from 'fs-extra';
|
|
7
7
|
import { createServer } from 'http';
|
|
8
|
-
import isOnline from 'is-online';
|
|
9
8
|
import os from 'os';
|
|
10
9
|
import path from 'path';
|
|
11
10
|
import { fileURLToPath } from 'url';
|
|
@@ -17,6 +16,7 @@ import { applyBasePathToExport, findBasePathConflict, normalizeExportBasePath, }
|
|
|
17
16
|
import { generateExportLlmsTxt } from './export-llms.js';
|
|
18
17
|
import { writeSearchIndex } from './export-search.js';
|
|
19
18
|
import { getGroupFilteredRoutes } from './getGroupFilteredRoutes.js';
|
|
19
|
+
import { isOnline } from './is-online.js';
|
|
20
20
|
import { setupNext } from './setupNext.js';
|
|
21
21
|
import { silentUpdateClient } from './update.js';
|
|
22
22
|
const CONCURRENCY = 10;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { getFileListSync, prebuild } from '@mintlify/prebuild';
|
|
3
3
|
import fse, { pathExists } from 'fs-extra';
|
|
4
|
-
import isOnline from 'is-online';
|
|
5
4
|
import pathUtil from 'path';
|
|
6
5
|
import { CLIENT_PATH, CMD_EXEC_PATH, VERSION_PATH, NEXT_PUBLIC_PATH, NEXT_PROPS_PATH, PREVIEW_PATH, configurePreviewPath, } from '../constants.js';
|
|
7
6
|
import { addLog, clearLogs } from '../logging-state.js';
|
|
@@ -9,6 +8,7 @@ import { ErrorLog, SpinnerLog } from '../logs.js';
|
|
|
9
8
|
import { seedPreviewFromShared } from '../util.js';
|
|
10
9
|
import { timeDev, timeDevSync } from './dev-timing.js';
|
|
11
10
|
import { ensureDocsConfig } from './ensure-docs-config.js';
|
|
11
|
+
import { isOnline } from './is-online.js';
|
|
12
12
|
import { startPackagesDev } from './packages/index.js';
|
|
13
13
|
import { acquirePreviewLock } from './preview-lock.js';
|
|
14
14
|
import { run } from './run.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isOnline: (timeoutMs?: number) => Promise<boolean>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
const PROBE_URLS = [
|
|
3
|
+
'https://captive.apple.com/hotspot-detect.html',
|
|
4
|
+
'https://cloudflare.com/cdn-cgi/trace',
|
|
5
|
+
];
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 5_000;
|
|
7
|
+
const hasExternalNetworkInterface = () => {
|
|
8
|
+
const interfaces = os.networkInterfaces();
|
|
9
|
+
return Object.values(interfaces).some((entries) => entries?.some((entry) => entry && !entry.internal));
|
|
10
|
+
};
|
|
11
|
+
export const isOnline = async (timeoutMs = DEFAULT_TIMEOUT_MS) => {
|
|
12
|
+
if (!hasExternalNetworkInterface()) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
17
|
+
try {
|
|
18
|
+
await Promise.any(PROBE_URLS.map(async (url) => {
|
|
19
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error(`connectivity check failed with status ${response.status}`);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
await response.body?.cancel();
|
|
25
|
+
}
|
|
26
|
+
catch { }
|
|
27
|
+
return true;
|
|
28
|
+
}));
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
clearTimeout(timeout);
|
|
36
|
+
controller.abort();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { prebuild } from '@mintlify/prebuild';
|
|
3
3
|
import fse, { pathExists } from 'fs-extra';
|
|
4
|
-
import isOnline from 'is-online';
|
|
5
4
|
import { CLIENT_PATH, CMD_EXEC_PATH, VERSION_PATH, NEXT_PUBLIC_PATH, NEXT_PROPS_PATH, PREVIEW_PATH, configureSharedPreviewPath, } from '../constants.js';
|
|
6
5
|
import { addLog, clearLogs } from '../logging-state.js';
|
|
7
6
|
import { ErrorLog, SpinnerLog, SuccessLog } from '../logs.js';
|
|
8
7
|
import { timeDev, timeDevSync } from './dev-timing.js';
|
|
8
|
+
import { isOnline } from './is-online.js';
|
|
9
9
|
import { silentUpdateClient } from './update.js';
|
|
10
10
|
export const checkBuild = async (argv) => {
|
|
11
11
|
configureSharedPreviewPath();
|