laxy-verify 1.1.32 → 1.2.0

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.
Files changed (38) hide show
  1. package/README.md +322 -322
  2. package/dist/audit/broken-links.d.ts +21 -21
  3. package/dist/audit/broken-links.js +86 -86
  4. package/dist/auth.d.ts +11 -6
  5. package/dist/auth.js +222 -188
  6. package/dist/cli.js +806 -724
  7. package/dist/comment.d.ts +21 -21
  8. package/dist/comment.js +134 -131
  9. package/dist/crawler.d.ts +36 -35
  10. package/dist/crawler.js +357 -356
  11. package/dist/e2e.d.ts +49 -49
  12. package/dist/e2e.js +565 -539
  13. package/dist/entitlement.d.ts +11 -11
  14. package/dist/entitlement.js +90 -88
  15. package/dist/init.js +87 -87
  16. package/dist/multi-viewport.d.ts +31 -31
  17. package/dist/multi-viewport.js +298 -298
  18. package/dist/playwright-runner.d.ts +16 -16
  19. package/dist/playwright-runner.js +208 -208
  20. package/dist/report-markdown.d.ts +39 -39
  21. package/dist/report-markdown.js +386 -386
  22. package/dist/security-audit.d.ts +9 -9
  23. package/dist/security-audit.js +64 -64
  24. package/dist/serve.d.ts +13 -13
  25. package/dist/serve.js +249 -246
  26. package/dist/trend.d.ts +50 -49
  27. package/dist/trend.js +148 -147
  28. package/dist/verification-core/index.d.ts +3 -3
  29. package/dist/verification-core/index.js +19 -19
  30. package/dist/verification-core/report.d.ts +14 -14
  31. package/dist/verification-core/report.js +409 -404
  32. package/dist/verification-core/tier-policy.d.ts +13 -13
  33. package/dist/verification-core/tier-policy.js +60 -60
  34. package/dist/verification-core/types.d.ts +108 -108
  35. package/dist/verification-core/types.js +2 -2
  36. package/dist/visual-diff.d.ts +26 -26
  37. package/dist/visual-diff.js +178 -178
  38. package/package.json +67 -67
package/dist/serve.js CHANGED
@@ -1,246 +1,249 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.DevServerTimeoutError = exports.PortConflictError = void 0;
40
- exports.probeServerStatus = probeServerStatus;
41
- exports.startDevServer = startDevServer;
42
- exports.stopDevServer = stopDevServer;
43
- const node_child_process_1 = require("node:child_process");
44
- const fs = __importStar(require("node:fs"));
45
- const http = __importStar(require("node:http"));
46
- const os = __importStar(require("node:os"));
47
- const path = __importStar(require("node:path"));
48
- const tree_kill_1 = __importDefault(require("tree-kill"));
49
- class PortConflictError extends Error {
50
- constructor(port) {
51
- super(`Port ${port} is already in use. Please free the port or configure a different one in .laxy.yml`);
52
- this.name = "PortConflictError";
53
- }
54
- }
55
- exports.PortConflictError = PortConflictError;
56
- class DevServerTimeoutError extends Error {
57
- constructor(port, timeoutSec) {
58
- super(`Dev server did not respond with a healthy page on port ${port} within ${timeoutSec}s`);
59
- this.name = "DevServerTimeoutError";
60
- }
61
- }
62
- exports.DevServerTimeoutError = DevServerTimeoutError;
63
- async function killProcessTree(pid) {
64
- await new Promise((resolve) => {
65
- let settled = false;
66
- const finish = () => {
67
- if (settled)
68
- return;
69
- settled = true;
70
- resolve();
71
- };
72
- const fallbackTimer = setTimeout(finish, 5000);
73
- fallbackTimer.unref?.();
74
- try {
75
- (0, tree_kill_1.default)(pid, "SIGKILL", () => {
76
- clearTimeout(fallbackTimer);
77
- finish();
78
- });
79
- }
80
- catch {
81
- clearTimeout(fallbackTimer);
82
- finish();
83
- }
84
- });
85
- }
86
- function writeWindowsDevWrapper(command, port, cwd) {
87
- const wrapperDir = path.join(os.tmpdir(), "laxy-verify");
88
- fs.mkdirSync(wrapperDir, { recursive: true });
89
- const wrapperPath = path.join(wrapperDir, `dev-wrapper-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.cjs`);
90
- const source = `"use strict";
91
- const { spawn } = require("node:child_process");
92
-
93
- const parentPid = Number(process.env.LAXY_VERIFY_PARENT_PID || "0");
94
- const command = ${JSON.stringify(command)};
95
- const childCwd = ${JSON.stringify(cwd ?? null)};
96
- const port = ${JSON.stringify(String(port))};
97
-
98
- function killChildTree(pid) {
99
- try {
100
- const killer = spawn(process.env.ComSpec || "cmd.exe", ["/d", "/c", "taskkill /T /F /PID " + pid], {
101
- stdio: "ignore",
102
- });
103
- killer.on("exit", () => process.exit(1));
104
- } catch {
105
- process.exit(1);
106
- }
107
- }
108
-
109
- const child = spawn(process.env.ComSpec || "cmd.exe", ["/d", "/c", command], {
110
- stdio: ["ignore", "pipe", "pipe"],
111
- cwd: childCwd || undefined,
112
- env: { ...process.env, PORT: port },
113
- });
114
-
115
- child.stdout?.on("data", (chunk) => process.stdout.write(chunk));
116
- child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
117
-
118
- child.on("error", (err) => {
119
- process.stderr.write((err && err.message ? err.message : String(err)) + "\\n");
120
- process.exit(1);
121
- });
122
-
123
- child.on("exit", (code) => {
124
- clearInterval(watchdog);
125
- process.exit(code ?? 1);
126
- });
127
-
128
- const watchdog = setInterval(() => {
129
- if (!parentPid) return;
130
- try {
131
- process.kill(parentPid, 0);
132
- } catch {
133
- clearInterval(watchdog);
134
- if (child.pid) {
135
- killChildTree(child.pid);
136
- return;
137
- }
138
- process.exit(1);
139
- }
140
- }, 1000);
141
-
142
- watchdog.unref?.();
143
- `;
144
- fs.writeFileSync(wrapperPath, source, "utf-8");
145
- return wrapperPath;
146
- }
147
- function httpGet(url) {
148
- return new Promise((resolve) => {
149
- http
150
- .get(url, { timeout: 2000 }, (res) => {
151
- resolve(res.statusCode ?? null);
152
- })
153
- .on("error", () => {
154
- resolve(null);
155
- });
156
- });
157
- }
158
- function probeServerStatus(port) {
159
- return httpGet(`http://localhost:${port}/`);
160
- }
161
- async function startDevServer(command, port, timeoutSec, cwd) {
162
- return new Promise((resolve, reject) => {
163
- console.log(`Starting dev server: ${command}${cwd ? ` (cwd: ${cwd})` : ""}`);
164
- let settled = false;
165
- const wrapperPath = process.platform === "win32"
166
- ? writeWindowsDevWrapper(command, port, cwd)
167
- : null;
168
- const proc = process.platform === "win32"
169
- ? (0, node_child_process_1.spawn)("node", [wrapperPath], {
170
- stdio: ["ignore", "pipe", "pipe"],
171
- env: {
172
- ...process.env,
173
- PORT: String(port),
174
- LAXY_VERIFY_PARENT_PID: String(process.pid),
175
- },
176
- })
177
- : (0, node_child_process_1.spawn)(command, {
178
- shell: true,
179
- stdio: ["ignore", "pipe", "pipe"],
180
- env: { ...process.env, PORT: String(port) },
181
- cwd,
182
- });
183
- proc.stdout?.on("data", (chunk) => {
184
- const lines = chunk.toString().split("\n").filter(Boolean);
185
- for (const line of lines)
186
- console.log(` [dev] ${line}`);
187
- });
188
- proc.stderr?.on("data", (chunk) => {
189
- const lines = chunk.toString().split("\n").filter(Boolean);
190
- for (const line of lines)
191
- console.error(` [dev] ${line}`);
192
- });
193
- proc.on("error", (err) => {
194
- if (settled)
195
- return;
196
- settled = true;
197
- if (err.code === "EADDRINUSE") {
198
- reject(new PortConflictError(port));
199
- }
200
- else {
201
- reject(new Error(`Dev server error: ${err.message}`));
202
- }
203
- });
204
- proc.on("exit", (code) => {
205
- if (wrapperPath) {
206
- fs.rmSync(wrapperPath, { force: true });
207
- }
208
- if (settled)
209
- return;
210
- settled = true;
211
- reject(new Error(`Dev server exited before becoming ready (exit code ${code ?? 1}).`));
212
- });
213
- const deadline = Date.now() + timeoutSec * 1000;
214
- const poll = async () => {
215
- if (Date.now() >= deadline) {
216
- if (settled)
217
- return;
218
- settled = true;
219
- if (proc.pid) {
220
- await killProcessTree(proc.pid);
221
- }
222
- reject(new DevServerTimeoutError(port, timeoutSec));
223
- return;
224
- }
225
- const status = await probeServerStatus(port);
226
- if (status !== null) {
227
- if (status >= 200 && status < 400) {
228
- if (settled)
229
- return;
230
- settled = true;
231
- console.log(`Dev server ready on port ${port} (HTTP ${status})`);
232
- resolve({ pid: proc.pid, port });
233
- return;
234
- }
235
- console.log(`Dev server returned HTTP ${status}, waiting for a healthy app surface...`);
236
- }
237
- const nextPoll = setTimeout(poll, 500);
238
- nextPoll.unref?.();
239
- };
240
- poll();
241
- });
242
- }
243
- async function stopDevServer(pid) {
244
- console.log(`Stopping dev server (PID ${pid})`);
245
- await killProcessTree(pid);
246
- }
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.DevServerTimeoutError = exports.PortConflictError = void 0;
40
+ exports.probeServerStatus = probeServerStatus;
41
+ exports.startDevServer = startDevServer;
42
+ exports.stopDevServer = stopDevServer;
43
+ const node_child_process_1 = require("node:child_process");
44
+ const fs = __importStar(require("node:fs"));
45
+ const http = __importStar(require("node:http"));
46
+ const os = __importStar(require("node:os"));
47
+ const path = __importStar(require("node:path"));
48
+ const tree_kill_1 = __importDefault(require("tree-kill"));
49
+ class PortConflictError extends Error {
50
+ constructor(port) {
51
+ super(`Port ${port} is already in use. Please free the port or configure a different one in .laxy.yml`);
52
+ this.name = "PortConflictError";
53
+ }
54
+ }
55
+ exports.PortConflictError = PortConflictError;
56
+ class DevServerTimeoutError extends Error {
57
+ constructor(port, timeoutSec) {
58
+ super(`Dev server did not respond with a healthy page on port ${port} within ${timeoutSec}s`);
59
+ this.name = "DevServerTimeoutError";
60
+ }
61
+ }
62
+ exports.DevServerTimeoutError = DevServerTimeoutError;
63
+ async function killProcessTree(pid) {
64
+ await new Promise((resolve) => {
65
+ let settled = false;
66
+ const finish = () => {
67
+ if (settled)
68
+ return;
69
+ settled = true;
70
+ resolve();
71
+ };
72
+ const fallbackTimer = setTimeout(finish, 5000);
73
+ fallbackTimer.unref?.();
74
+ try {
75
+ (0, tree_kill_1.default)(pid, "SIGKILL", () => {
76
+ clearTimeout(fallbackTimer);
77
+ finish();
78
+ });
79
+ }
80
+ catch {
81
+ clearTimeout(fallbackTimer);
82
+ finish();
83
+ }
84
+ });
85
+ }
86
+ function writeWindowsDevWrapper(command, port, cwd) {
87
+ const wrapperDir = path.join(os.tmpdir(), "laxy-verify");
88
+ fs.mkdirSync(wrapperDir, { recursive: true });
89
+ const wrapperPath = path.join(wrapperDir, `dev-wrapper-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.cjs`);
90
+ const source = `"use strict";
91
+ const { spawn } = require("node:child_process");
92
+
93
+ const parentPid = Number(process.env.LAXY_VERIFY_PARENT_PID || "0");
94
+ const command = ${JSON.stringify(command)};
95
+ const childCwd = ${JSON.stringify(cwd ?? null)};
96
+ const port = ${JSON.stringify(String(port))};
97
+
98
+ function killChildTree(pid) {
99
+ try {
100
+ const killer = spawn(process.env.ComSpec || "cmd.exe", ["/d", "/c", "taskkill /T /F /PID " + pid], {
101
+ stdio: "ignore",
102
+ });
103
+ killer.on("exit", () => process.exit(1));
104
+ } catch {
105
+ process.exit(1);
106
+ }
107
+ }
108
+
109
+ const child = spawn(process.env.ComSpec || "cmd.exe", ["/d", "/c", command], {
110
+ stdio: ["ignore", "pipe", "pipe"],
111
+ cwd: childCwd || undefined,
112
+ env: { ...process.env, PORT: port },
113
+ });
114
+
115
+ child.stdout?.on("data", (chunk) => process.stdout.write(chunk));
116
+ child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
117
+
118
+ child.on("error", (err) => {
119
+ process.stderr.write((err && err.message ? err.message : String(err)) + "\\n");
120
+ process.exit(1);
121
+ });
122
+
123
+ child.on("exit", (code) => {
124
+ clearInterval(watchdog);
125
+ process.exit(code ?? 1);
126
+ });
127
+
128
+ const watchdog = setInterval(() => {
129
+ if (!parentPid) return;
130
+ try {
131
+ process.kill(parentPid, 0);
132
+ } catch {
133
+ clearInterval(watchdog);
134
+ if (child.pid) {
135
+ killChildTree(child.pid);
136
+ return;
137
+ }
138
+ process.exit(1);
139
+ }
140
+ }, 1000);
141
+
142
+ watchdog.unref?.();
143
+ `;
144
+ fs.writeFileSync(wrapperPath, source, "utf-8");
145
+ return wrapperPath;
146
+ }
147
+ function httpGet(url) {
148
+ return new Promise((resolve) => {
149
+ http
150
+ .get(url, { timeout: 2000 }, (res) => {
151
+ resolve(res.statusCode ?? null);
152
+ })
153
+ .on("error", () => {
154
+ resolve(null);
155
+ });
156
+ });
157
+ }
158
+ function probeServerStatus(port) {
159
+ return httpGet(`http://localhost:${port}/`);
160
+ }
161
+ async function startDevServer(command, port, timeoutSec, cwd) {
162
+ return new Promise((resolve, reject) => {
163
+ console.log(`Starting dev server: ${command}${cwd ? ` (cwd: ${cwd})` : ""}`);
164
+ let settled = false;
165
+ const wrapperPath = process.platform === "win32"
166
+ ? writeWindowsDevWrapper(command, port, cwd)
167
+ : null;
168
+ const proc = process.platform === "win32"
169
+ ? (0, node_child_process_1.spawn)("node", [wrapperPath], {
170
+ stdio: ["ignore", "pipe", "pipe"],
171
+ env: {
172
+ ...process.env,
173
+ PORT: String(port),
174
+ LAXY_VERIFY_PARENT_PID: String(process.pid),
175
+ },
176
+ })
177
+ : (0, node_child_process_1.spawn)(command, {
178
+ shell: true,
179
+ stdio: ["ignore", "pipe", "pipe"],
180
+ env: { ...process.env, PORT: String(port) },
181
+ cwd,
182
+ });
183
+ proc.stdout?.on("data", (chunk) => {
184
+ const lines = chunk.toString().split("\n").filter(Boolean);
185
+ for (const line of lines)
186
+ console.log(` [dev] ${line}`);
187
+ });
188
+ proc.stderr?.on("data", (chunk) => {
189
+ const lines = chunk.toString().split("\n").filter(Boolean);
190
+ for (const line of lines)
191
+ console.error(` [dev] ${line}`);
192
+ });
193
+ proc.on("error", (err) => {
194
+ if (settled)
195
+ return;
196
+ settled = true;
197
+ if (err.code === "EADDRINUSE") {
198
+ reject(new PortConflictError(port));
199
+ }
200
+ else {
201
+ reject(new Error(`Dev server error: ${err.message}`));
202
+ }
203
+ });
204
+ proc.on("exit", (code) => {
205
+ if (wrapperPath) {
206
+ fs.rmSync(wrapperPath, { force: true });
207
+ }
208
+ if (settled)
209
+ return;
210
+ settled = true;
211
+ reject(new Error(`Dev server exited before becoming ready (exit code ${code ?? 1}).`));
212
+ });
213
+ const deadline = Date.now() + timeoutSec * 1000;
214
+ const poll = async () => {
215
+ if (Date.now() >= deadline) {
216
+ if (settled)
217
+ return;
218
+ settled = true;
219
+ if (proc.pid) {
220
+ await killProcessTree(proc.pid);
221
+ }
222
+ if (wrapperPath) {
223
+ fs.rmSync(wrapperPath, { force: true });
224
+ }
225
+ reject(new DevServerTimeoutError(port, timeoutSec));
226
+ return;
227
+ }
228
+ const status = await probeServerStatus(port);
229
+ if (status !== null) {
230
+ if (status >= 200 && status < 400) {
231
+ if (settled)
232
+ return;
233
+ settled = true;
234
+ console.log(`Dev server ready on port ${port} (HTTP ${status})`);
235
+ resolve({ pid: proc.pid, port });
236
+ return;
237
+ }
238
+ console.log(`Dev server returned HTTP ${status}, waiting for a healthy app surface...`);
239
+ }
240
+ const nextPoll = setTimeout(poll, 500);
241
+ nextPoll.unref?.();
242
+ };
243
+ poll();
244
+ });
245
+ }
246
+ async function stopDevServer(pid) {
247
+ console.log(`Stopping dev server (PID ${pid})`);
248
+ await killProcessTree(pid);
249
+ }
package/dist/trend.d.ts CHANGED
@@ -1,49 +1,50 @@
1
- export interface TrendSnapshot {
2
- grade: string;
3
- lighthouse: {
4
- performance: number;
5
- accessibility: number;
6
- seo: number;
7
- bestPractices: number;
8
- } | null;
9
- e2e?: {
10
- passed: number;
11
- total: number;
12
- } | null;
13
- timestamp: string;
14
- }
15
- export interface TrendDelta {
16
- grade: {
17
- current: string;
18
- base: string;
19
- changed: boolean;
20
- };
21
- performance: {
22
- current: number | null;
23
- base: number | null;
24
- delta: number | null;
25
- };
26
- accessibility: {
27
- current: number | null;
28
- base: number | null;
29
- delta: number | null;
30
- };
31
- seo: {
32
- current: number | null;
33
- base: number | null;
34
- delta: number | null;
35
- };
36
- bestPractices: {
37
- current: number | null;
38
- base: number | null;
39
- delta: number | null;
40
- };
41
- e2e: {
42
- current: string | null;
43
- base: string | null;
44
- };
45
- }
46
- export declare function loadBaseSnapshot(baseResultPath: string): TrendSnapshot | null;
47
- export declare function computeTrendDelta(current: TrendSnapshot, base: TrendSnapshot): TrendDelta;
48
- export declare function renderTrendSection(delta: TrendDelta): string;
49
- export declare function getBaseResultPath(projectDir: string): string;
1
+ export interface TrendSnapshot {
2
+ grade: string;
3
+ lighthouse: {
4
+ performance: number;
5
+ accessibility: number;
6
+ seo: number;
7
+ bestPractices: number;
8
+ } | null;
9
+ e2e?: {
10
+ passed: number;
11
+ total: number;
12
+ } | null;
13
+ timestamp: string;
14
+ }
15
+ export interface TrendDelta {
16
+ grade: {
17
+ current: string;
18
+ base: string;
19
+ changed: boolean;
20
+ };
21
+ performance: {
22
+ current: number | null;
23
+ base: number | null;
24
+ delta: number | null;
25
+ };
26
+ accessibility: {
27
+ current: number | null;
28
+ base: number | null;
29
+ delta: number | null;
30
+ };
31
+ seo: {
32
+ current: number | null;
33
+ base: number | null;
34
+ delta: number | null;
35
+ };
36
+ bestPractices: {
37
+ current: number | null;
38
+ base: number | null;
39
+ delta: number | null;
40
+ };
41
+ e2e: {
42
+ current: string | null;
43
+ base: string | null;
44
+ };
45
+ }
46
+ export declare function gradeIndex(grade: string): number;
47
+ export declare function loadBaseSnapshot(baseResultPath: string): TrendSnapshot | null;
48
+ export declare function computeTrendDelta(current: TrendSnapshot, base: TrendSnapshot): TrendDelta;
49
+ export declare function renderTrendSection(delta: TrendDelta): string;
50
+ export declare function getBaseResultPath(projectDir: string): string;