Skip to content

Commit a242c0f

Browse files
authored
Convert ts (#45)
* chore: update git ignore * tools: initial convert to ts * tools: migrate ts files * chore: add ts build to release pipeline * chore: remove old config file * chore: remove reference to old config types * chore: add changeset * chore: update changeset
1 parent 41365b8 commit a242c0f

File tree

13 files changed

+305
-141
lines changed

13 files changed

+305
-141
lines changed

.changeset/swift-planets-rescue.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@heymp/scratchpad": minor
3+
---
4+
5+
⚠️ Change config types directory.
6+
7+
```js
8+
export default /** @type {import('@heymp/scratchpad/src/config').Config} */ ({
9+
});
10+
```

.github/workflows/release.yml

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ jobs:
2323
- name: Install Dependencies
2424
run: yarn
2525

26+
- name: Build TS
27+
run: yarn run build
28+
2629
- name: Create Release Pull Request or Publish to npm
2730
id: changesets
2831
uses: changesets/action@v1

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
node_modules
2+
3+
src/**.js
4+
src/**.d.ts
5+
src/**.d.ts.map

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ in your `.ts` files:
106106
An alternative to using the CLI flags, you can create `scratchpad.config.js`.
107107

108108
```js
109-
export default /** @type {import('@heymp/scratchpad/config').Config} */ ({
109+
export default /** @type {import('@heymp/scratchpad/src/config').Config} */ ({
110110
devtools: true,
111111
url: 'https://internal-rhdc-review-itmktgwsa-hklqgj.apps.int.spoke.preprod.us-west-2.aws.paas.redhat.com/en/test-page-2',
112112
headless: true,
@@ -120,7 +120,7 @@ This allows you to interact with the Playwright API to perform actions like bloc
120120
network requests or navigating to different urls.
121121

122122
```js
123-
export default /** @type {import('@heymp/scratchpad/config').Config} */ ({
123+
export default /** @type {import('@heymp/scratchpad/src/config').Config} */ ({
124124
devtools: true,
125125
playwright: async (args) => {
126126
const { context, page } = args;

bin/cli.js

+1-88
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,3 @@
11
#!/usr/bin/env node
22

3-
import fs from 'node:fs';
4-
import { join, dirname } from 'node:path';
5-
import { fileURLToPath } from 'node:url';
6-
import { Command } from 'commander';
7-
import { browser } from '../src/browser.js';
8-
import { getConfig } from '../src/config.js';
9-
import * as esbuild from 'esbuild';
10-
11-
// Get pkg info
12-
const __filename = fileURLToPath(import.meta.url);
13-
const __dirname = dirname(__filename);
14-
const pkg = JSON.parse(fs.readFileSync(join(__dirname, '../package.json'), 'utf8'));
15-
16-
const program = new Command();
17-
program
18-
.argument('<file>', 'file to execute in the browser.')
19-
.option('--headless [boolean]', 'specify running the browser in headless mode.')
20-
.option('--devtools [boolean]', 'open browser devtools automatically.')
21-
.option('--ts-write [boolean]', 'write the js output of the target ts file.')
22-
.option('--url [string]', 'specify a specific url to execute the code in.')
23-
.version(pkg.version)
24-
program.parse(process.argv);
25-
26-
const file = program.args.at(0);
27-
const config = await getConfig();
28-
const opts = { ...config, ...program.opts()};
29-
30-
class Processor extends EventTarget {
31-
constructor() {
32-
super();
33-
this.url = opts['url'];
34-
this.headless = opts['headless'];
35-
this.devtools = opts['devtools'];
36-
this.tsWrite = opts['tsWrite'];
37-
this.playwrightConfig = opts['playwright'];
38-
this._func = '';
39-
this.watcher();
40-
browser(this);
41-
}
42-
43-
get func() {
44-
return this._func;
45-
}
46-
47-
set func(func) {
48-
this._func = func;
49-
this.dispatchEvent(new Event('change'));
50-
}
51-
52-
watcher() {
53-
if (!fs.existsSync(file)) {
54-
throw new Error(`${file} file not found.`);
55-
}
56-
// execute it immediately then start watcher
57-
this.build();
58-
fs.watchFile(file, { interval: 100 }, () => {
59-
this.build();
60-
});
61-
}
62-
63-
async build() {
64-
try {
65-
if (file.endsWith('.ts')) {
66-
const { outputFiles: [stdout]} = await esbuild.build({
67-
entryPoints: [file],
68-
format: 'esm',
69-
bundle: true,
70-
write: false,
71-
});
72-
this.func = new TextDecoder().decode(stdout.contents);
73-
if (this.tsWrite) {
74-
fs.writeFile(join(process.cwd(), file.replace(/\.ts$/g, '.js')), this.func, 'utf8', () => {});
75-
}
76-
}
77-
else {
78-
this.func = fs.readFileSync(file, 'utf8');
79-
}
80-
} catch (e) {
81-
console.error(e);
82-
}
83-
}
84-
85-
start() {
86-
this.dispatchEvent(new Event('change'));
87-
}
88-
}
89-
90-
new Processor();
3+
import '../src/cli.js';

config.d.ts

-15
This file was deleted.

package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
"files": [
1010
"bin/cli.js",
1111
"src/**",
12-
"config.d.ts",
1312
"types.d.ts"
1413
],
1514
"dependencies": {
@@ -18,11 +17,14 @@
1817
"playwright": "^1.44.1"
1918
},
2019
"scripts": {
21-
"start": "node ./bin/cli.js --",
20+
"build": "tsc",
21+
"build:watch": "tsc -w",
2222
"release": "npx @changesets/cli publish"
2323
},
2424
"devDependencies": {
25-
"@changesets/cli": "^2.27.1"
25+
"@changesets/cli": "^2.27.1",
26+
"@types/node": "^22.1.0",
27+
"typescript": "^5.5.4"
2628
},
2729
"publishConfig": {
2830
"access": "public"

src/browser.js src/browser.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import playwright from 'playwright';
22
import util from 'node:util';
3+
import type { Processor } from './cli.js';
34
util.inspect.defaultOptions.maxArrayLength = null;
45
util.inspect.defaultOptions.depth = null;
56

6-
function nodelog(value) {
7+
function nodelog(value:any) {
78
console.log(value);
89
}
910

10-
export async function browser(processor) {
11+
export async function browser(processor: Processor) {
1112
// Launch the browser
1213
const browser = await playwright['chromium'].launch({
1314
headless: !!processor.headless,
@@ -33,18 +34,19 @@ export async function browser(processor) {
3334
});
3435
});
3536

36-
await page.exposeFunction('nodelog', (...value) => {
37+
await page.exposeFunction('nodelog', (...value: any) => {
3738
console.log(...value);
3839
});
3940

4041
async function execute() {
4142
page.evaluate(async (func) => {
42-
function log(...value) {
43+
function log(...value: any[]) {
4344
setTimeout(() => {
4445
console.log(...value);
4546
}, 100);
4647
nodelog(
47-
...value.flatMap(i => {
48+
// @ts-ignore
49+
...value.flatMap((i: any) => {
4850
const protoName = Object.prototype.toString.call(i);
4951
const protoNamePrettyPrint = protoName.replace('object ', '').replace(/\[|\]/g, '') + ':';
5052
if (protoName === '[object Array]') {
@@ -89,8 +91,12 @@ export async function browser(processor) {
8991
}
9092
})()
9193
`);
92-
} catch (Error) {
93-
log(Error.toString())
94+
} catch (error) {
95+
if (!(error instanceof Error)) {
96+
log(`An unkown error has occurred.`);
97+
return;
98+
}
99+
log(error.toString())
94100
}
95101
},
96102
processor.func

src/cli.ts

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'node:fs';
4+
import { join, dirname } from 'node:path';
5+
import { fileURLToPath } from 'node:url';
6+
import { Command } from 'commander';
7+
import { browser } from './browser.js';
8+
import { getConfig } from './config.js';
9+
import * as esbuild from 'esbuild';
10+
11+
// Get pkg info
12+
const __filename = fileURLToPath(import.meta.url);
13+
const __dirname = dirname(__filename);
14+
const pkg = JSON.parse(fs.readFileSync(join(__dirname, '../package.json'), 'utf8'));
15+
16+
const program = new Command();
17+
program
18+
.argument('<file>', 'file to execute in the browser.')
19+
.option('--headless [boolean]', 'specify running the browser in headless mode.')
20+
.option('--devtools [boolean]', 'open browser devtools automatically.')
21+
.option('--ts-write [boolean]', 'write the js output of the target ts file.')
22+
.option('--url [string]', 'specify a specific url to execute the code in.')
23+
.version(pkg.version)
24+
program.parse(process.argv);
25+
26+
const file = program.args.at(0);
27+
const config = await getConfig();
28+
const opts = { ...config, ...program.opts()};
29+
30+
export class Processor extends EventTarget {
31+
url = opts['url'];
32+
headless = opts['headless'];
33+
devtools = opts['devtools'];
34+
tsWrite = opts['tsWrite'];
35+
playwrightConfig = opts['playwright'];
36+
_func = '';
37+
38+
constructor() {
39+
super();
40+
this.watcher();
41+
browser(this);
42+
}
43+
44+
get func() {
45+
return this._func;
46+
}
47+
48+
set func(func) {
49+
this._func = func;
50+
this.dispatchEvent(new Event('change'));
51+
}
52+
53+
watcher() {
54+
if (!file) {
55+
throw new Error(`${file} file not found.`);
56+
}
57+
if (!fs.existsSync(file)) {
58+
throw new Error(`${file} file not found.`);
59+
}
60+
// execute it immediately then start watcher
61+
this.build();
62+
fs.watchFile(join(file), { interval: 100 }, () => {
63+
this.build();
64+
});
65+
}
66+
67+
async build() {
68+
try {
69+
if (!file) {
70+
throw new Error(`${file} file not found.`);
71+
}
72+
if (file.endsWith('.ts')) {
73+
const { outputFiles: [stdout]} = await esbuild.build({
74+
entryPoints: [file],
75+
format: 'esm',
76+
bundle: true,
77+
write: false,
78+
});
79+
this.func = new TextDecoder().decode(stdout.contents);
80+
if (this.tsWrite) {
81+
fs.writeFile(join(process.cwd(), file.replace(/\.ts$/g, '.js')), this.func, 'utf8', () => {});
82+
}
83+
}
84+
else {
85+
this.func = fs.readFileSync(file, 'utf8');
86+
}
87+
} catch (e) {
88+
console.error(e);
89+
}
90+
}
91+
92+
start() {
93+
this.dispatchEvent(new Event('change'));
94+
}
95+
}
96+
97+
new Processor();

src/config.js

-26
This file was deleted.

src/config.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { join } from 'node:path';
2+
import { stat } from 'node:fs/promises';
3+
import type { Page, BrowserContext, Browser } from 'playwright';
4+
5+
export type PlaywrightConfig = {
6+
page: Page,
7+
context: BrowserContext,
8+
browser: Browser,
9+
}
10+
11+
export type Config = {
12+
headless?: boolean;
13+
devtools?: boolean;
14+
tsWrite?: boolean;
15+
url?: string;
16+
playwright?: (page: PlaywrightConfig) => Promise<void>
17+
}
18+
19+
const exists = (path:string) => stat(path).then(() => true, () => false);
20+
21+
async function importConfig(rootDir:string) {
22+
const path = join(rootDir, './scratchpad.config.js');
23+
if (await exists(path)) {
24+
return import(path)
25+
.then(x => x.default)
26+
.catch(e => {
27+
console.error(e);
28+
return {};
29+
});
30+
} else {
31+
return {};
32+
}
33+
}
34+
35+
export async function getConfig() {
36+
const rootDir = process.cwd();
37+
return {
38+
...await importConfig(rootDir),
39+
}
40+
}
41+

0 commit comments

Comments
 (0)