@skrillex1224/playwright-toolkit 3.0.14 → 3.0.16

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/index.d.ts CHANGED
@@ -23,12 +23,18 @@ export interface ModeType {
23
23
  Cloak: 'cloak';
24
24
  }
25
25
 
26
+ export interface ToolkitModeStatic {
27
+ default: 'default';
28
+ cloak: 'cloak';
29
+ }
30
+
26
31
  export type ToolkitMode = 'default' | 'cloak';
27
32
 
28
33
  export interface ConstantsModule {
29
34
  Code: CodeType;
30
35
  Status: StatusType;
31
36
  Mode: ModeType;
37
+ mode: ToolkitModeStatic;
32
38
  PresetOfLiveViewKey: string;
33
39
  Device: {
34
40
  Desktop: 'desktop';
@@ -682,7 +688,7 @@ export interface ShareScreenCaptureOptions {
682
688
  restore?: boolean;
683
689
  /** 最大截图高度 (默认: 8000px) */
684
690
  maxHeight?: number;
685
- /** 截图水印合成模式;`cloak` 时走兼容分支。 */
691
+ /** 截图水印合成模式;默认取当前 toolkit mode,`cloak` 时走兼容分支。 */
686
692
  mode?: 'default' | 'cloak';
687
693
  /** 返回 base64 字符串的最大字节数,默认 5MiB。 */
688
694
  maxBytes?: number;
@@ -890,3 +896,6 @@ export interface BrowserPlaywrightToolKit {
890
896
  export declare function usePlaywrightToolKit(): PlaywrightToolKit;
891
897
  export declare function usePlaywrightToolKit(mode: 'default'): PlaywrightToolKit;
892
898
  export declare function usePlaywrightToolKit(mode: 'cloak'): CloakPlaywrightToolKit;
899
+ export declare namespace usePlaywrightToolKit {
900
+ const Mode: ToolkitModeStatic;
901
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skrillex1224/playwright-toolkit",
3
- "version": "3.0.14",
3
+ "version": "3.0.16",
4
4
  "description": "一个在 Apify/Crawlee Actor 中启用实时截图视图的实用工具库。",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -22,12 +22,14 @@
22
22
  },
23
23
  "scripts": {
24
24
  "build": "node build.js",
25
+ "postinstall": "node ./scripts/postinstall.js",
25
26
  "release": "npm run build && npm version patch && npm publish --registry https://registry.npmjs.org --access public --userconfig ../.npmrc",
26
27
  "prepublishOnly": "npm run build",
27
28
  "test": "echo \"Error: no test specified\" && exit 1"
28
29
  },
29
30
  "files": [
30
31
  "dist/",
32
+ "scripts/",
31
33
  "browser.d.ts",
32
34
  "index.d.ts",
33
35
  "README.md"
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath, pathToFileURL } from 'node:url';
6
+
7
+ const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
8
+ const PACKAGE_ROOT = path.resolve(SCRIPT_DIR, '..');
9
+ const PREFIX = '[playwright-toolkit:postinstall]';
10
+ const SKIP_ENV = 'PLAYWRIGHT_TOOLKIT_SKIP_CLOAK_POSTINSTALL';
11
+
12
+ const log = (message) => console.log(`${PREFIX} ${message}`);
13
+ const warn = (message) => console.warn(`${PREFIX} ${message}`);
14
+
15
+ const isTruthy = (value) => /^(1|true|yes|on)$/i.test(String(value || '').trim());
16
+
17
+ const readTrimmedFile = (filePath) => {
18
+ try {
19
+ return fs.readFileSync(filePath, 'utf8').trim();
20
+ } catch {
21
+ return '';
22
+ }
23
+ };
24
+
25
+ const isBinaryReady = (binaryPath) => {
26
+ if (!binaryPath || !fs.existsSync(binaryPath)) {
27
+ return false;
28
+ }
29
+
30
+ if (process.platform === 'win32') {
31
+ return true;
32
+ }
33
+
34
+ try {
35
+ fs.accessSync(binaryPath, fs.constants.X_OK);
36
+ return true;
37
+ } catch {
38
+ return false;
39
+ }
40
+ };
41
+
42
+ function* walkParentDirs(startDir) {
43
+ let currentDir = path.resolve(startDir);
44
+ while (true) {
45
+ yield currentDir;
46
+
47
+ const parentDir = path.dirname(currentDir);
48
+ if (parentDir === currentDir) {
49
+ return;
50
+ }
51
+
52
+ currentDir = parentDir;
53
+ }
54
+ }
55
+
56
+ const findPackageRoot = (startDir, packageName) => {
57
+ for (const currentDir of walkParentDirs(startDir)) {
58
+ const packageJsonPath = path.join(currentDir, 'package.json');
59
+ if (!fs.existsSync(packageJsonPath)) {
60
+ continue;
61
+ }
62
+
63
+ try {
64
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
65
+ if (packageJson?.name === packageName) {
66
+ return currentDir;
67
+ }
68
+ } catch {
69
+ // Ignore invalid JSON and keep walking.
70
+ }
71
+ }
72
+
73
+ return null;
74
+ };
75
+
76
+ const findInstalledCloakRoot = async () => {
77
+ try {
78
+ const resolvedEntryUrl = await import.meta.resolve('cloakbrowser');
79
+ const resolvedEntryPath = fileURLToPath(resolvedEntryUrl);
80
+ const packageRoot = findPackageRoot(path.dirname(resolvedEntryPath), 'cloakbrowser');
81
+ if (packageRoot) {
82
+ return packageRoot;
83
+ }
84
+ } catch {
85
+ // Fall back to filesystem lookup.
86
+ }
87
+
88
+ const searchRoots = [
89
+ process.env.INIT_CWD,
90
+ process.cwd(),
91
+ process.env.npm_config_local_prefix,
92
+ PACKAGE_ROOT,
93
+ SCRIPT_DIR,
94
+ ].filter(Boolean);
95
+
96
+ for (const searchRoot of new Set(searchRoots)) {
97
+ for (const currentDir of walkParentDirs(searchRoot)) {
98
+ const packageJsonPath = path.join(currentDir, 'node_modules', 'cloakbrowser', 'package.json');
99
+ if (fs.existsSync(packageJsonPath)) {
100
+ return path.dirname(packageJsonPath);
101
+ }
102
+ }
103
+ }
104
+
105
+ return null;
106
+ };
107
+
108
+ const clearStaleVersionMarkers = ({ cacheDir, expectedVersion, platformTag }) => {
109
+ let clearedMarkers = 0;
110
+
111
+ for (const markerName of [`latest_version_${platformTag}`, 'latest_version']) {
112
+ const markerPath = path.join(cacheDir, markerName);
113
+ const markerVersion = readTrimmedFile(markerPath);
114
+
115
+ if (!markerVersion || markerVersion === expectedVersion) {
116
+ continue;
117
+ }
118
+
119
+ fs.rmSync(markerPath, { force: true });
120
+ clearedMarkers += 1;
121
+ log(`Removed stale ${markerName}=${markerVersion} to keep cloakbrowser pinned to ${expectedVersion}.`);
122
+ }
123
+
124
+ return clearedMarkers;
125
+ };
126
+
127
+ const main = async () => {
128
+ if (isTruthy(process.env[SKIP_ENV])) {
129
+ log(`Skipped because ${SKIP_ENV} is set.`);
130
+ return;
131
+ }
132
+
133
+ const cloakRoot = await findInstalledCloakRoot();
134
+ if (!cloakRoot) {
135
+ log('cloakbrowser is not installed; skipping binary preinstall.');
136
+ return;
137
+ }
138
+
139
+ const [cloakModule, cloakConfig] = await Promise.all([
140
+ import(pathToFileURL(path.join(cloakRoot, 'dist', 'index.js')).href),
141
+ import(pathToFileURL(path.join(cloakRoot, 'dist', 'config.js')).href),
142
+ ]);
143
+
144
+ const localBinaryOverride = cloakConfig.getLocalBinaryOverride?.();
145
+ if (localBinaryOverride) {
146
+ if (!fs.existsSync(localBinaryOverride)) {
147
+ throw new Error(`CLOAKBROWSER_BINARY_PATH points to a missing file: ${localBinaryOverride}`);
148
+ }
149
+
150
+ log(`Using CLOAKBROWSER_BINARY_PATH=${localBinaryOverride}; skipping managed binary install.`);
151
+ return;
152
+ }
153
+
154
+ try {
155
+ cloakConfig.checkPlatformAvailable?.();
156
+ } catch (error) {
157
+ warn(`${error?.message || String(error)} Skipping managed binary install.`);
158
+ return;
159
+ }
160
+
161
+ const expectedVersion = cloakConfig.getChromiumVersion();
162
+ const platformTag = cloakConfig.getPlatformTag();
163
+ const cacheDir = cloakConfig.getCacheDir();
164
+ const expectedBinaryPath = cloakConfig.getBinaryPath(expectedVersion);
165
+
166
+ process.env.CLOAKBROWSER_AUTO_UPDATE = 'false';
167
+
168
+ const clearedMarkers = clearStaleVersionMarkers({
169
+ cacheDir,
170
+ expectedVersion,
171
+ platformTag,
172
+ });
173
+
174
+ if (isBinaryReady(expectedBinaryPath)) {
175
+ const suffix = clearedMarkers > 0 ? ' Cleared stale version markers.' : '';
176
+ log(`cloakbrowser ${expectedVersion} already available at ${expectedBinaryPath}.${suffix}`);
177
+ return;
178
+ }
179
+
180
+ log(`Installing cloakbrowser ${expectedVersion} for ${platformTag}...`);
181
+ const resolvedBinaryPath = await cloakModule.ensureBinary();
182
+
183
+ if (!isBinaryReady(expectedBinaryPath)) {
184
+ throw new Error(
185
+ `Expected cloakbrowser binary at ${expectedBinaryPath}, but it is still missing after ensureBinary() returned ${resolvedBinaryPath}.`,
186
+ );
187
+ }
188
+
189
+ if (path.resolve(resolvedBinaryPath) !== path.resolve(expectedBinaryPath)) {
190
+ warn(
191
+ `ensureBinary() returned ${resolvedBinaryPath}, expected ${expectedBinaryPath}. `
192
+ + 'The package-pinned binary is installed and stale version markers were cleared.',
193
+ );
194
+ }
195
+
196
+ log(`cloakbrowser ${expectedVersion} ready at ${expectedBinaryPath}.`);
197
+ };
198
+
199
+ main().catch((error) => {
200
+ const message = error?.stack || error?.message || String(error);
201
+ console.error(`${PREFIX} ${message}`);
202
+ process.exit(1);
203
+ });