Skip to content

Commit da05776

Browse files
committed
chore: new cache generation
1 parent 9f4ef40 commit da05776

14 files changed

+431
-545
lines changed

packages/cache/src/cli/cliEntrypoint.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ export const cliEntrypoint = async () => {
3434
.addHelpText('afterAll', `\n${footer}\n`)
3535
.parse(process.argv)
3636

37-
let walletSetupDir = program.args[0]
38-
if (!walletSetupDir) {
39-
walletSetupDir = path.join(process.cwd(), 'test', WALLET_SETUP_DIR_NAME)
37+
let walletSetupDir = path.join(process.cwd(), 'test', WALLET_SETUP_DIR_NAME)
38+
39+
if (program.args[0]) {
40+
walletSetupDir = path.join(process.cwd(), program.args[0])
4041
}
4142

4243
const flags: CliFlags = program.opts()
@@ -47,7 +48,14 @@ export const cliEntrypoint = async () => {
4748

4849
if (flags.debug) {
4950
console.log('[DEBUG] Running with the following options:')
50-
console.log({ cacheDir: walletSetupDir, ...flags, headless: Boolean(process.env.HEADLESS) ?? false }, '\n')
51+
console.log(
52+
{
53+
cacheDir: walletSetupDir,
54+
...flags,
55+
headless: Boolean(process.env.HEADLESS) ?? false
56+
},
57+
'\n'
58+
)
5159
}
5260

5361
if (os.platform() === 'win32') {
@@ -62,10 +70,15 @@ export const cliEntrypoint = async () => {
6270
process.exit(1)
6371
}
6472

65-
const { outDir: compiledWalletSetupDirPath, functionStrings } = await compileWalletSetupFunctions(walletSetupDir, flags.debug)
73+
console.log(chalk.greenBright('🚀 Building the cache for wallet setup functions... 🚀\n'))
74+
75+
const { outDir: compiledWalletSetupDirPath, setupFunctionHashes } = await compileWalletSetupFunctions(
76+
walletSetupDir,
77+
flags.debug
78+
)
6679

67-
// TODO: We should be using `prepareExtension` function from the wallet itself!
68-
await createCache(compiledWalletSetupDirPath, functionStrings, prepareExtension, flags.force)
80+
// TODO: We should be using `prepareExtension` function from the wallet itself!
81+
await createCache(compiledWalletSetupDirPath, setupFunctionHashes, prepareExtension, flags.force)
6982

7083
if (!flags.debug) {
7184
await rimraf(compiledWalletSetupDirPath)
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,73 @@
1-
import path from "node:path";
2-
import { glob } from "glob";
3-
import { build } from "tsup";
4-
import { ensureCacheDirExists } from "../ensureCacheDirExists";
5-
import { FIXES_BANNER } from "./compilationFixes";
6-
import buildWalletSetupFunction from "../utils/buildWalletSetupFunction";
1+
import path from 'node:path'
2+
import fs from 'fs-extra'
3+
import { glob } from 'glob'
4+
import { build } from 'tsup'
75

8-
const OUT_DIR_NAME = "wallet-setup-dist";
6+
import { ensureCacheDirExists } from '../ensureCacheDirExists'
7+
import buildWalletSetupFunction from '../utils/buildWalletSetupFunction'
8+
import { extractWalletSetupFunction } from '../utils/extractWalletSetupFunction'
9+
import { getWalletSetupFuncHash } from '../utils/getWalletSetupFuncHash'
10+
import { FIXES_BANNER } from './compilationFixes'
911

10-
const createGlobPattern = (walletSetupDir: string) =>
11-
path.join(walletSetupDir, "**", "*.setup.{ts,js,mjs}");
12+
const OUT_DIR_NAME = '.wallet-setup-dist'
1213

13-
export async function compileWalletSetupFunctions(
14-
walletSetupDir: string,
15-
debug: boolean
16-
) {
17-
const outDir = path.join(ensureCacheDirExists(), OUT_DIR_NAME);
14+
const createGlobPattern = (walletSetupDir: string) => path.join(walletSetupDir, '**', '*.setup.{ts,js,mjs}')
1815

19-
const globPattern = createGlobPattern(walletSetupDir);
20-
const fileList = await glob(globPattern);
16+
export async function compileWalletSetupFunctions(walletSetupDir: string, debug: boolean) {
17+
const outDir = path.join(ensureCacheDirExists(), OUT_DIR_NAME)
18+
19+
fs.ensureDirSync(outDir)
20+
21+
const globPattern = createGlobPattern(walletSetupDir)
22+
const fileList = await glob(globPattern)
2123

2224
if (debug) {
23-
console.log("[DEBUG] Found the following wallet setup files:");
24-
console.log(fileList, "\n");
25+
console.log('[DEBUG] Found the following wallet setup files:')
26+
console.log(fileList, '\n')
2527
}
2628

2729
// TODO: This error message is copied over from another function. Refactor this.
2830
if (!fileList.length) {
2931
throw new Error(
3032
[
3133
`No wallet setup files found at ${walletSetupDir}`,
32-
"Remember that all wallet setup files must end with `.setup.{ts,js,mjs}` extension!",
33-
].join("\n")
34-
);
34+
'Remember that all wallet setup files must end with `.setup.{ts,js,mjs}` extension!'
35+
].join('\n')
36+
)
3537
}
3638

3739
await build({
38-
name: "cli-build",
40+
name: 'cli-build',
3941
silent: true,
4042
entry: fileList,
4143
clean: true,
4244
outDir,
43-
format: "esm",
45+
format: 'esm',
4446
splitting: true,
4547
sourcemap: false,
4648
config: false,
4749
// TODO: Make this list configurable.
48-
external: [
49-
"@synthetixio/synpress",
50-
"@playwright/test",
51-
"playwright-core",
52-
"esbuild",
53-
"tsup",
54-
],
50+
external: ['@synthetixio/synpress', '@playwright/test', 'playwright-core', 'esbuild', 'tsup'],
5551
banner: {
56-
js: FIXES_BANNER,
52+
js: FIXES_BANNER
5753
},
5854
esbuildOptions(options) {
5955
// TODO: In this step, if the debug file is present, we should modify `console.log` so it prints from which file the log is coming from.
6056
// We're dropping `console.log` and `debugger` statements because they do not play nicely with the Playwright Test Runner.
61-
options.drop = debug ? [] : ["console", "debugger"];
62-
},
63-
});
57+
options.drop = debug ? [] : ['console', 'debugger']
58+
}
59+
})
6460

65-
const functionStrings = await Promise.all(
66-
fileList.map(async (fileName) => {
67-
const walletSetupFunction = await import(fileName);
61+
const setupFunctionHashes = await Promise.all(
62+
fileList.map(async (filePath) => {
63+
const sourceCode = fs.readFileSync(filePath, 'utf8')
64+
const functionString = extractWalletSetupFunction(sourceCode)
6865

69-
return buildWalletSetupFunction(walletSetupFunction.toString());
70-
})
71-
);
66+
const rawFunctionBuild = buildWalletSetupFunction(functionString)
7267

73-
console.log({functionStrings})
68+
return getWalletSetupFuncHash(rawFunctionBuild)
69+
})
70+
)
7471

75-
return { outDir, functionStrings: functionStrings };
72+
return { outDir, setupFunctionHashes }
7673
}

packages/cache/src/createCache.ts

+9-16
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
1-
import { getUniqueWalletSetupFunctions } from "./utils/getUniqueWalletSetupFunctions";
2-
import { triggerCacheCreation } from "./utils/triggerCacheCreation";
1+
import { getUniqueWalletSetupFunctions } from './utils/getUniqueWalletSetupFunctions'
2+
import { triggerCacheCreation } from './utils/triggerCacheCreation'
33

44
export async function createCache(
55
walletSetupDirPath: string,
6-
functionStrings: string[],
6+
hashes: string[],
77
downloadExtension: () => Promise<string>,
88
force = false
99
) {
10-
const setupFunctions = await getUniqueWalletSetupFunctions(
11-
walletSetupDirPath
12-
);
10+
const setupFunctions = await getUniqueWalletSetupFunctions(walletSetupDirPath)
1311

14-
const cacheCreationPromises = await triggerCacheCreation(
15-
setupFunctions,
16-
functionStrings,
17-
downloadExtension,
18-
force
19-
);
12+
const cacheCreationPromises = await triggerCacheCreation(setupFunctions, hashes, downloadExtension, force)
2013

2114
if (cacheCreationPromises.length === 0) {
22-
console.log("No new setup functions to cache. Exiting...");
23-
return;
15+
console.log('No new setup functions to cache. Exiting...')
16+
return
2417
}
2518

2619
// TODO: This line has no unit test. Not sure how to do it. Look into it later.
27-
await Promise.all(cacheCreationPromises);
20+
await Promise.all(cacheCreationPromises)
2821

29-
console.log("All wallet setup functions are now cached!");
22+
console.log('All wallet setup functions are now cached!')
3023
}

packages/cache/src/defineWalletSetup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { BrowserContext, Page } from 'playwright-core'
2+
import buildWalletSetupFunction from './utils/buildWalletSetupFunction'
23
import { getWalletSetupFuncHash } from './utils/getWalletSetupFuncHash'
3-
import buildWalletSetupFunction from './utils/buildWalletSetupFunction';
44

55
// TODO: Should we export this type in the `release` package?
66
export type WalletSetupFunction = (context: BrowserContext, walletPage: Page) => Promise<void>
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
import { transformSync } from "esbuild";
2-
import { FIXES_BANNER } from "../cli/compilationFixes";
1+
import { transformSync } from 'esbuild'
32

4-
export default function buildWalletSetupFunction(
5-
walletSetupFunctionString: string
6-
) {
3+
export default function buildWalletSetupFunction(walletSetupFunctionString: string) {
74
const { code } = transformSync(walletSetupFunctionString, {
8-
format: "esm",
5+
format: 'esm',
96
minifyWhitespace: true,
10-
target: "es2022",
11-
drop: ["console", "debugger"],
12-
loader: "ts",
13-
logLevel: "silent",
14-
platform: "node",
15-
banner: FIXES_BANNER,
16-
});
7+
target: 'es2022',
8+
drop: ['console', 'debugger'],
9+
loader: 'ts',
10+
logLevel: 'silent',
11+
platform: 'node'
12+
})
1713

18-
return code;
14+
return code
1915
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function extractWalletSetupFunction(sourceCode: string): string {
2+
const match = sourceCode.match(/defineWalletSetup\s*\([^,]*,\s*(async\s*\([^)]*\)\s*=>\s*{[\s\S]*?})\s*\)/)
3+
4+
if (!match || !match[1]) {
5+
console.log('Failed to extract defineWalletSetup callback from:', sourceCode)
6+
throw new Error('Could not find defineWalletSetup callback')
7+
}
8+
9+
// Return just the callback function (second parameter)
10+
return match[1]
11+
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import { createHash } from "node:crypto";
1+
import { createHash } from 'node:crypto'
22

33
// Same length as the file part (first part before the `-`) of a Playwright Test ID.
4-
export const WALLET_SETUP_FUNC_HASH_LENGTH = 10;
4+
export const WALLET_SETUP_FUNC_HASH_LENGTH = 10
55

66
export function getWalletSetupFuncHash(walletSetupString: string) {
7-
const hash = createHash("shake256", {
8-
outputLength: WALLET_SETUP_FUNC_HASH_LENGTH,
9-
});
7+
const hash = createHash('shake256', {
8+
outputLength: WALLET_SETUP_FUNC_HASH_LENGTH
9+
})
1010

11-
return hash.update(walletSetupString).digest("hex");
11+
return hash.update(walletSetupString).digest('hex')
1212
}
13-
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,48 @@
1-
import path from "node:path";
2-
import fs from "fs-extra";
3-
import { ensureCacheDirExists } from "../ensureCacheDirExists";
4-
import { createCacheForWalletSetupFunction } from "./createCacheForWalletSetupFunction";
5-
import { isDirEmpty } from "./isDirEmpty";
6-
import { getWalletSetupFuncHash } from "./getWalletSetupFuncHash";
7-
import type { WalletSetupFunction } from "../defineWalletSetup";
1+
import path from 'node:path'
2+
import fs from 'fs-extra'
3+
import type { WalletSetupFunction } from '../defineWalletSetup'
4+
import { ensureCacheDirExists } from '../ensureCacheDirExists'
5+
import { createCacheForWalletSetupFunction } from './createCacheForWalletSetupFunction'
6+
import { isDirEmpty } from './isDirEmpty'
87

98
export async function triggerCacheCreation(
10-
setupFunctions: Map<
11-
string,
12-
{ fileName: string; setupFunction: WalletSetupFunction }
13-
>,
14-
functionStrings: string[],
9+
setupFunctions: Map<string, { fileName: string; setupFunction: WalletSetupFunction }>,
10+
hashes: string[],
1511
downloadExtension: () => Promise<string>,
1612
force: boolean
1713
) {
18-
const cacheDirPath = ensureCacheDirExists();
19-
const extensionPath = await downloadExtension();
14+
const cacheDirPath = ensureCacheDirExists()
15+
const extensionPath = await downloadExtension()
2016

21-
return Array.from(setupFunctions).map(
22-
async ([_, { fileName, setupFunction }], index) => {
23-
// @ts-ignore
24-
const funcHash = getWalletSetupFuncHash(functionStrings[index]);
17+
return Array.from(setupFunctions).map(async ([_, { fileName, setupFunction }], index) => {
18+
if (!hashes[index]) {
19+
throw new Error(`No hash found for ${fileName}`)
20+
}
2521

26-
const cachePath = path.join(cacheDirPath, funcHash);
27-
const doesCacheDirExist = await fs.exists(cachePath);
28-
const isCacheDirEmpty = await isDirEmpty(cachePath);
22+
const funcHash = hashes[index]
2923

30-
if (doesCacheDirExist) {
31-
if (isCacheDirEmpty) {
32-
// In case of incorrect Playwright setup, the cache dir will be empty. For now, we're just deleting it.
33-
await fs.remove(cachePath);
34-
} else {
35-
if (!force) {
36-
console.log(`Cache already exists for ${funcHash}. Skipping...`);
37-
return;
38-
}
24+
const cachePath = path.join(cacheDirPath, funcHash || 'unknown')
25+
const doesCacheDirExist = await fs.exists(cachePath)
26+
const isCacheDirEmpty = await isDirEmpty(cachePath)
3927

40-
console.log(
41-
`Cache already exists for ${funcHash} but force flag is set. Deleting cache...`
42-
);
43-
await fs.remove(cachePath);
28+
if (doesCacheDirExist) {
29+
if (isCacheDirEmpty) {
30+
// In case of incorrect Playwright setup, the cache dir will be empty. For now, we're just deleting it.
31+
await fs.remove(cachePath)
32+
} else {
33+
if (!force) {
34+
console.log(`Cache already exists for ${funcHash}. Skipping...`)
35+
return
4436
}
45-
}
4637

47-
const fileNameWithCorrectExtension = fileName.replace(
48-
/\.(ts|js|mjs)$/,
49-
".{ts,js,mjs}"
50-
);
51-
console.log(
52-
`Triggering cache creation for: ${funcHash} (${fileNameWithCorrectExtension})`
53-
);
54-
// We're not inferring the return type here to make sure we don't accidentally await the function.
55-
return createCacheForWalletSetupFunction(
56-
extensionPath,
57-
cachePath,
58-
setupFunction,
59-
fileNameWithCorrectExtension
60-
);
38+
console.log(`Cache already exists for ${funcHash} but force flag is set. Deleting cache...`)
39+
await fs.remove(cachePath)
40+
}
6141
}
62-
);
42+
43+
const fileNameWithCorrectExtension = fileName.replace(/\.(ts|js|mjs)$/, '.{ts,js,mjs}')
44+
console.log(`Triggering cache creation for: ${funcHash} (${fileNameWithCorrectExtension})`)
45+
// We're not inferring the return type here to make sure we don't accidentally await the function.
46+
return createCacheForWalletSetupFunction(extensionPath, cachePath, setupFunction, fileNameWithCorrectExtension)
47+
})
6348
}

0 commit comments

Comments
 (0)