playwriter 0.0.0 → 0.0.1

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 (50) hide show
  1. package/README.md +60 -0
  2. package/bin.js +3 -0
  3. package/dist/browser-config.d.ts +2 -0
  4. package/dist/browser-config.d.ts.map +1 -0
  5. package/dist/browser-config.js +59 -0
  6. package/dist/browser-config.js.map +1 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +2 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.test.d.ts +2 -0
  12. package/dist/index.test.d.ts.map +1 -0
  13. package/dist/index.test.js +8 -0
  14. package/dist/index.test.js.map +1 -0
  15. package/dist/mcp-client.d.ts +16 -0
  16. package/dist/mcp-client.d.ts.map +1 -0
  17. package/dist/mcp-client.js +52 -0
  18. package/dist/mcp-client.js.map +1 -0
  19. package/dist/mcp.d.ts +2 -0
  20. package/dist/mcp.d.ts.map +1 -0
  21. package/dist/mcp.js +596 -0
  22. package/dist/mcp.js.map +1 -0
  23. package/dist/mcp.test.d.ts +2 -0
  24. package/dist/mcp.test.d.ts.map +1 -0
  25. package/dist/mcp.test.js +205 -0
  26. package/dist/mcp.test.js.map +1 -0
  27. package/dist/playwriter.d.ts +5 -0
  28. package/dist/playwriter.d.ts.map +1 -0
  29. package/dist/playwriter.js +177 -0
  30. package/dist/playwriter.js.map +1 -0
  31. package/dist/profiles.d.ts +16 -0
  32. package/dist/profiles.d.ts.map +1 -0
  33. package/dist/profiles.js +76 -0
  34. package/dist/profiles.js.map +1 -0
  35. package/dist/profiles.test.d.ts +2 -0
  36. package/dist/profiles.test.d.ts.map +1 -0
  37. package/dist/profiles.test.js +169 -0
  38. package/dist/profiles.test.js.map +1 -0
  39. package/package.json +22 -6
  40. package/src/browser-config.ts +66 -0
  41. package/src/mcp-client.ts +73 -0
  42. package/src/mcp.test.ts +240 -0
  43. package/src/mcp.ts +751 -0
  44. package/src/prompt.md +539 -0
  45. package/src/snapshots/hacker-news-focused-accessibility.md +202 -0
  46. package/src/snapshots/hacker-news-initial-accessibility.md +202 -0
  47. package/src/snapshots/hacker-news-tabbed-accessibility.md +202 -0
  48. package/src/snapshots/shadcn-ui-accessibility.md +553 -0
  49. package/src/index.test.ts +0 -9
  50. package/src/index.ts +0 -0
@@ -0,0 +1,205 @@
1
+ import { createMCPClient } from './mcp-client.js';
2
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
3
+ describe('MCP Server Tests', () => {
4
+ let client;
5
+ let cleanup = null;
6
+ beforeAll(async () => {
7
+ const result = await createMCPClient();
8
+ client = result.client;
9
+ cleanup = result.cleanup;
10
+ });
11
+ afterAll(async () => {
12
+ if (cleanup) {
13
+ await cleanup();
14
+ cleanup = null;
15
+ }
16
+ });
17
+ it('should capture console logs', async () => {
18
+ // Connect first (open a new page)
19
+ const connectResult = await client.callTool({
20
+ name: 'new_page',
21
+ arguments: {},
22
+ });
23
+ expect(connectResult.content).toBeDefined();
24
+ expect(connectResult.content).toMatchInlineSnapshot(`
25
+ [
26
+ {
27
+ "text": "Created new page. URL: about:blank. Total pages: 20",
28
+ "type": "text",
29
+ },
30
+ ]
31
+ `);
32
+ // Navigate to a page and log something
33
+ const result = await client.callTool({
34
+ name: 'execute',
35
+ arguments: {
36
+ code: `
37
+ await page.goto('https://news.ycombinator.com');
38
+ await page.evaluate(() => {
39
+ console.log('Test log message');
40
+ console.error('Test error message');
41
+ });
42
+ `,
43
+ },
44
+ });
45
+ expect(result.content).toBeDefined();
46
+ expect(result.content).toMatchInlineSnapshot(`
47
+ [
48
+ {
49
+ "text": "Code executed successfully (no output)",
50
+ "type": "text",
51
+ },
52
+ ]
53
+ `);
54
+ // Get console logs
55
+ const logsResult = (await client.callTool({
56
+ name: 'console_logs',
57
+ arguments: {
58
+ limit: 10,
59
+ },
60
+ }));
61
+ expect(logsResult.content).toBeDefined();
62
+ expect(logsResult.content).toMatchInlineSnapshot(`
63
+ [
64
+ {
65
+ "text": "[log]: Test log message :1:32
66
+ [error]: Test error message :2:32",
67
+ "type": "text",
68
+ },
69
+ ]
70
+ `);
71
+ // Close the page opened
72
+ await client.callTool({
73
+ name: 'close_page',
74
+ arguments: {},
75
+ });
76
+ }, 30000);
77
+ it('should capture accessibility snapshot of hacker news', async () => {
78
+ // Create new page
79
+ await client.callTool({
80
+ name: 'new_page',
81
+ arguments: {},
82
+ });
83
+ // Navigate to a specific old Hacker News story that won't change
84
+ await client.callTool({
85
+ name: 'execute',
86
+ arguments: {
87
+ code: `await page.goto('https://news.ycombinator.com/item?id=1', { waitUntil: 'networkidle' })`,
88
+ },
89
+ });
90
+ // Get initial accessibility snapshot
91
+ const initialSnapshot = await client.callTool({
92
+ name: 'accessibility_snapshot',
93
+ arguments: {},
94
+ });
95
+ expect(initialSnapshot.content).toBeDefined();
96
+ // Save initial snapshot
97
+ const initialData = typeof initialSnapshot === 'object' &&
98
+ initialSnapshot.content?.[0]?.text
99
+ ? tryJsonParse(initialSnapshot.content[0].text)
100
+ : initialSnapshot;
101
+ expect(initialData).toMatchFileSnapshot('snapshots/hacker-news-initial-accessibility.md');
102
+ expect(initialData).toContain('table');
103
+ expect(initialData).toContain('Hacker News');
104
+ // Focus on first link on the page
105
+ await client.callTool({
106
+ name: 'execute',
107
+ arguments: {
108
+ code: `
109
+ // Find and focus the first link
110
+ const firstLink = await page.$('a')
111
+ if (firstLink) {
112
+ await firstLink.focus()
113
+ const linkText = await firstLink.textContent()
114
+ console.log('Focused on first link:', linkText)
115
+ }
116
+ `,
117
+ },
118
+ });
119
+ // Get snapshot after focusing
120
+ const focusedSnapshot = await client.callTool({
121
+ name: 'accessibility_snapshot',
122
+ arguments: {},
123
+ });
124
+ expect(focusedSnapshot.content).toBeDefined();
125
+ // Save focused snapshot
126
+ const focusedData = typeof focusedSnapshot === 'object' &&
127
+ focusedSnapshot.content?.[0]?.text
128
+ ? tryJsonParse(focusedSnapshot.content[0].text)
129
+ : focusedSnapshot;
130
+ expect(focusedData).toMatchFileSnapshot('snapshots/hacker-news-focused-accessibility.md');
131
+ // Verify the snapshot contains expected content
132
+ expect(focusedData).toBeDefined();
133
+ expect(focusedData).toContain('link');
134
+ // Press Tab to go to next item
135
+ await client.callTool({
136
+ name: 'execute',
137
+ arguments: {
138
+ code: `
139
+ await page.keyboard.press('Tab')
140
+ console.log('Pressed Tab key')
141
+ `,
142
+ },
143
+ });
144
+ // Get snapshot after tab navigation
145
+ const tabbedSnapshot = await client.callTool({
146
+ name: 'accessibility_snapshot',
147
+ arguments: {},
148
+ });
149
+ expect(tabbedSnapshot.content).toBeDefined();
150
+ // Save tabbed snapshot
151
+ const tabbedData = typeof tabbedSnapshot === 'object' &&
152
+ tabbedSnapshot.content?.[0]?.text
153
+ ? tryJsonParse(tabbedSnapshot.content[0].text)
154
+ : tabbedSnapshot;
155
+ expect(tabbedData).toMatchFileSnapshot('snapshots/hacker-news-tabbed-accessibility.md');
156
+ // Verify the snapshot is different
157
+ expect(tabbedData).toBeDefined();
158
+ expect(tabbedData).toContain('Hacker News');
159
+ // Close the page opened
160
+ await client.callTool({
161
+ name: 'close_page',
162
+ arguments: {},
163
+ });
164
+ }, 30000);
165
+ it('should capture accessibility snapshot of shadcn UI', async () => {
166
+ // Create new page
167
+ await client.callTool({
168
+ name: 'new_page',
169
+ arguments: {},
170
+ });
171
+ // Navigate to shadcn UI
172
+ await client.callTool({
173
+ name: 'execute',
174
+ arguments: {
175
+ code: `await page.goto('https://ui.shadcn.com/', { waitUntil: 'networkidle' })`,
176
+ },
177
+ });
178
+ // Get accessibility snapshot
179
+ const snapshot = await client.callTool({
180
+ name: 'accessibility_snapshot',
181
+ arguments: {},
182
+ });
183
+ expect(snapshot.content).toBeDefined();
184
+ // Save snapshot
185
+ const data = typeof snapshot === 'object' && snapshot.content?.[0]?.text
186
+ ? tryJsonParse(snapshot.content[0].text)
187
+ : snapshot;
188
+ expect(data).toMatchFileSnapshot('snapshots/shadcn-ui-accessibility.md');
189
+ expect(data).toContain('shadcn');
190
+ // Close the page opened
191
+ await client.callTool({
192
+ name: 'close_page',
193
+ arguments: {},
194
+ });
195
+ }, 30000);
196
+ });
197
+ function tryJsonParse(str) {
198
+ try {
199
+ return JSON.parse(str);
200
+ }
201
+ catch {
202
+ return str;
203
+ }
204
+ }
205
+ //# sourceMappingURL=mcp.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.test.js","sourceRoot":"","sources":["../src/mcp.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function startPlaywriter(emailProfile?: string): Promise<{
2
+ cdpPort: number;
3
+ chromeProcess: import("child_process").ChildProcess;
4
+ }>;
5
+ //# sourceMappingURL=playwriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwriter.d.ts","sourceRoot":"","sources":["../src/playwriter.ts"],"names":[],"mappings":"AAmDA,wBAAsB,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM;;;GAqJ1D"}
@@ -0,0 +1,177 @@
1
+ // Removed Playwright import - launching Chrome directly
2
+ import { spawn } from 'child_process';
3
+ import os from 'node:os';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { getAllProfiles } from './profiles.js';
7
+ // Find Chrome executable path based on OS
8
+ function findChromeExecutablePath() {
9
+ const osPlatform = os.platform();
10
+ const paths = (() => {
11
+ if (osPlatform === 'darwin') {
12
+ return [
13
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
14
+ '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
15
+ '~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
16
+ ];
17
+ }
18
+ if (osPlatform === 'win32') {
19
+ return [
20
+ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
21
+ 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
22
+ `${process.env.LOCALAPPDATA}\\Google\\Chrome\\Application\\chrome.exe`,
23
+ `${process.env.PROGRAMFILES}\\Google\\Chrome\\Application\\chrome.exe`,
24
+ `${process.env['PROGRAMFILES(X86)']}\\Google\\Chrome\\Application\\chrome.exe`,
25
+ ].filter(Boolean);
26
+ }
27
+ // Linux
28
+ return [
29
+ '/usr/bin/google-chrome',
30
+ '/usr/bin/google-chrome-stable',
31
+ '/usr/bin/chromium',
32
+ '/usr/bin/chromium-browser',
33
+ '/snap/bin/chromium',
34
+ ];
35
+ })();
36
+ for (const path of paths) {
37
+ const resolvedPath = path.startsWith('~')
38
+ ? path.replace('~', process.env.HOME || '')
39
+ : path;
40
+ if (fs.existsSync(resolvedPath)) {
41
+ return resolvedPath;
42
+ }
43
+ }
44
+ throw new Error('Could not find Chrome executable. Please install Google Chrome.');
45
+ }
46
+ export async function startPlaywriter(emailProfile) {
47
+ const cdpPort = 9922;
48
+ try {
49
+ // Find Chrome executable
50
+ const executablePath = findChromeExecutablePath();
51
+ console.log(`Found Chrome at: ${executablePath}`);
52
+ // Get available Chrome profiles
53
+ const profiles = getAllProfiles();
54
+ let selectedProfilePath;
55
+ // If no emailProfile provided, we can't proceed
56
+ if (!emailProfile) {
57
+ throw new Error('Email profile is required to start Chrome');
58
+ }
59
+ // Find the profile matching the email
60
+ const matchingProfile = profiles.find(p => p.email === emailProfile);
61
+ if (!matchingProfile) {
62
+ if (profiles.length === 0) {
63
+ // Create a temporary profile directory for automation
64
+ const tempDir = path.join(os.tmpdir(), 'playwriter-automation-profile');
65
+ if (!fs.existsSync(tempDir)) {
66
+ fs.mkdirSync(tempDir, { recursive: true });
67
+ }
68
+ selectedProfilePath = tempDir;
69
+ console.warn(`No Chrome profiles found. Using temporary profile at: ${tempDir}`);
70
+ }
71
+ else {
72
+ throw new Error(`No Chrome profile found for email: ${emailProfile}. Available emails: ${profiles.map(p => p.email).join(', ')}`);
73
+ }
74
+ }
75
+ else {
76
+ selectedProfilePath = matchingProfile.path;
77
+ console.log(`Using profile for ${emailProfile}: ${selectedProfilePath}`);
78
+ }
79
+ // Start browser with CDP enabled
80
+ console.log(`Starting Chrome with CDP on port ${cdpPort}...`);
81
+ // Get the Chrome user data directory and profile folder
82
+ const chromeUserDataDir = path.dirname(selectedProfilePath);
83
+ const profileFolder = path.basename(selectedProfilePath);
84
+ // Build Chrome arguments
85
+ const chromeArgs = [
86
+ `--remote-debugging-port=${cdpPort}`,
87
+ '--window-position=-32000,-32000', // Position window off-screen
88
+ '--window-size=1280,720',
89
+ '--disable-backgrounding-occluded-windows', // Prevents Chrome from throttling/suspending hidden tabs
90
+ '--disable-gpu', // Disable GPU acceleration for better compatibility
91
+ `--user-data-dir=${chromeUserDataDir}`, // Chrome's main user data directory
92
+ '--no-first-run', // Skip first-run dialogs
93
+ '--disable-default-apps', // Disable default app installation
94
+ '--disable-translate', // Disable translate prompts
95
+ '--disable-features=TranslateUI', // Disable translate UI
96
+ '--no-default-browser-check', // Don't check if Chrome is default browser
97
+ '--disable-session-crashed-bubble', // Disable session restore bubble
98
+ '--disable-infobars', // Disable info bars
99
+ '--automation', // Enable automation mode
100
+ ];
101
+ // Add profile-directory for non-default profiles
102
+ if (profileFolder !== 'Default') {
103
+ chromeArgs.push(`--profile-directory=${profileFolder}`);
104
+ }
105
+ // Launch Chrome directly as a subprocess
106
+ console.log('Launching Chrome with args:', chromeArgs);
107
+ const chromeProcess = spawn(executablePath, chromeArgs, {
108
+ detached: false,
109
+ stdio: 'ignore', // Ignore Chrome's output to avoid noise
110
+ });
111
+ chromeProcess.on('error', (error) => {
112
+ console.error('Failed to start Chrome:', error);
113
+ throw error;
114
+ });
115
+ // Give Chrome a moment to start up and open the debugging port
116
+ await new Promise(resolve => setTimeout(resolve, 2000));
117
+ // On macOS, minimize only this Chrome window using its PID
118
+ if (os.platform() === 'darwin' && chromeProcess.pid) {
119
+ try {
120
+ // Minimize the specific Chrome window using its process ID
121
+ // This keeps it running but out of the way
122
+ const minimizeScript = spawn('osascript', [
123
+ '-e', `tell application "System Events"`,
124
+ '-e', `tell (first process whose unix id is ${chromeProcess.pid})`,
125
+ '-e', `try`,
126
+ '-e', `set value of attribute "AXMinimized" of window 1 to true`,
127
+ '-e', `end try`,
128
+ '-e', `end tell`,
129
+ '-e', `end tell`
130
+ ]);
131
+ minimizeScript.on('error', () => {
132
+ // Silently ignore - window might already be hidden
133
+ });
134
+ }
135
+ catch (e) {
136
+ // Ignore errors, this is best-effort
137
+ }
138
+ }
139
+ console.log(`Chrome started with CDP on port ${cdpPort} (window is hidden off-screen)`);
140
+ return { cdpPort, chromeProcess };
141
+ // // Resolve @playwright/mcp package.json path
142
+ // const require = createRequire(import.meta.url)
143
+ // const mcpPackageJsonPath = require.resolve('@playwright/mcp/package.json')
144
+ // const mcpCliPath = path.resolve(mcpPackageJsonPath, '..', 'cli.js')
145
+ // console.log(`Found MCP CLI at: ${mcpCliPath}`)
146
+ // // Start MCP CLI process
147
+ // console.log('Starting MCP CLI...')
148
+ // const mcpProcess = spawn('node', [
149
+ // mcpCliPath,
150
+ // '--cdp-endpoint',
151
+ // `http://localhost:${cdpPort}`
152
+ // ], {
153
+ // stdio: 'inherit', // Forward all logs
154
+ // })
155
+ // mcpProcess.on('error', (error) => {
156
+ // console.error('Failed to start MCP CLI:', error)
157
+ // })
158
+ // mcpProcess.on('exit', (code, signal) => {
159
+ // console.log(`MCP CLI exited with code ${code} and signal ${signal}`)
160
+ // })
161
+ // // Handle cleanup
162
+ // const cleanup = async () => {
163
+ // console.log('Shutting down...')
164
+ // mcpProcess.kill()
165
+ // chromeProcess.kill()
166
+ // process.exit(0)
167
+ // }
168
+ // process.on('SIGINT', cleanup)
169
+ // process.on('SIGTERM', cleanup)
170
+ // return { chromeProcess, mcpProcess }
171
+ }
172
+ catch (error) {
173
+ console.error('Failed to start Playwriter:', error);
174
+ throw error;
175
+ }
176
+ }
177
+ //# sourceMappingURL=playwriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwriter.js","sourceRoot":"","sources":["../src/playwriter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /** Resolve Chrome's "User Data" root on the current OS. */
2
+ export declare function getChromeUserDataDir(): string;
3
+ /** Read and parse the top-level "Local State" JSON once. */
4
+ export declare function readLocalState(): any;
5
+ /** Map <profile-folder> → <signed-in email> (empty string if none). */
6
+ export declare function getProfileEmailMap(): Map<string, string>;
7
+ /** Return the full path to a profile directory for the given email. */
8
+ export declare function getProfilePathByEmail(email: string): string | null;
9
+ /** Get all available Chrome profiles with their paths and emails */
10
+ export declare function getAllProfiles(): Array<{
11
+ folder: string;
12
+ email: string;
13
+ path: string;
14
+ displayName: string;
15
+ }>;
16
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"AAIA,2DAA2D;AAC3D,wBAAgB,oBAAoB,IAAI,MAAM,CAqB7C;AAED,4DAA4D;AAC5D,wBAAgB,cAAc,IAAI,GAAG,CAgBpC;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASxD;AAED,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlE;AAED,oEAAoE;AACpE,wBAAgB,cAAc,IAAI,KAAK,CAAC;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACtB,CAAC,CA8BD"}
@@ -0,0 +1,76 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ /** Resolve Chrome's "User Data" root on the current OS. */
5
+ export function getChromeUserDataDir() {
6
+ const home = os.homedir();
7
+ switch (os.platform()) {
8
+ case 'win32':
9
+ return path.join(process.env.LOCALAPPDATA, 'Google', 'Chrome', 'User Data');
10
+ case 'darwin':
11
+ return path.join(home, 'Library', 'Application Support', 'Google', 'Chrome');
12
+ default: // linux, freebsd, …
13
+ return path.join(home, '.config', 'google-chrome');
14
+ }
15
+ }
16
+ /** Read and parse the top-level "Local State" JSON once. */
17
+ export function readLocalState() {
18
+ try {
19
+ const dir = getChromeUserDataDir();
20
+ const localStatePath = path.join(dir, 'Local State');
21
+ if (!fs.existsSync(localStatePath)) {
22
+ console.warn(`Chrome Local State file not found at: ${localStatePath}`);
23
+ return {};
24
+ }
25
+ const raw = fs.readFileSync(localStatePath, 'utf8');
26
+ return JSON.parse(raw);
27
+ }
28
+ catch (error) {
29
+ console.error('Failed to read Chrome Local State:', error);
30
+ return {};
31
+ }
32
+ }
33
+ /** Map <profile-folder> → <signed-in email> (empty string if none). */
34
+ export function getProfileEmailMap() {
35
+ const localState = readLocalState();
36
+ const infoCache = localState.profile?.info_cache ?? {};
37
+ return new Map(Object.entries(infoCache).map(([folder, obj]) => [
38
+ folder,
39
+ obj.user_name ?? '',
40
+ ]));
41
+ }
42
+ /** Return the full path to a profile directory for the given email. */
43
+ export function getProfilePathByEmail(email) {
44
+ const root = getChromeUserDataDir();
45
+ for (const [folder, userEmail] of getProfileEmailMap()) {
46
+ if (userEmail.toLowerCase() === email.toLowerCase()) {
47
+ return path.join(root, folder); // e.g. "…/User Data/Profile 2"
48
+ }
49
+ }
50
+ return null; // not found
51
+ }
52
+ /** Get all available Chrome profiles with their paths and emails */
53
+ export function getAllProfiles() {
54
+ const root = getChromeUserDataDir();
55
+ const profiles = [];
56
+ for (const [folder, email] of getProfileEmailMap()) {
57
+ profiles.push({
58
+ folder,
59
+ email,
60
+ path: path.join(root, folder),
61
+ displayName: email || `${folder} (no email)`,
62
+ });
63
+ }
64
+ // Also include Default profile if it exists
65
+ const defaultPath = path.join(root, 'Default');
66
+ if (fs.existsSync(defaultPath) && !profiles.some(p => p.folder === 'Default')) {
67
+ profiles.unshift({
68
+ folder: 'Default',
69
+ email: '',
70
+ path: defaultPath,
71
+ displayName: 'Default (no email)',
72
+ });
73
+ }
74
+ return profiles;
75
+ }
76
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=profiles.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.test.d.ts","sourceRoot":"","sources":["../src/profiles.test.ts"],"names":[],"mappings":""}