Skip to content

Commit 651c008

Browse files
chore: update dependencies script (#314)
* chore: update dependencies script * comments * don't update repo deps and additional tweaks * tweak * spice it up a bit * update package versions defined in object literals as well * simplify regex a little --------- Co-authored-by: AdrianGonz97 <[email protected]>
1 parent 39798e2 commit 651c008

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"format": "pnpm --parallel format",
1616
"lint": "pnpm --parallel lint && eslint --cache --cache-location node_modules/.eslintcache",
1717
"test": "vitest run --silent",
18-
"test:ui": "vitest --ui"
18+
"test:ui": "vitest --ui",
19+
"update-addon-deps": "node ./scripts/update-addon-dependencies.js"
1920
},
2021
"devDependencies": {
2122
"@changesets/cli": "^2.27.9",

scripts/update-addon-dependencies.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import { styleText } from 'node:util';
4+
5+
async function updateAddonDependencies() {
6+
const addonsBasePath = path.resolve('packages', 'addons');
7+
const addonFolders = fs
8+
.readdirSync(addonsBasePath, { withFileTypes: true })
9+
.filter((item) => item.isDirectory())
10+
.map((item) => item.name)
11+
.filter((x) => x !== 'node_modules' && !x.startsWith('_'));
12+
13+
for (const addonFolder of addonFolders) {
14+
const filePath = `${addonsBasePath}/${addonFolder}/index.ts`;
15+
if (!fs.existsSync(filePath)) continue;
16+
17+
console.log(`Checking deps for ${styleText(['cyanBright', 'bold'], addonFolder)} add-on`);
18+
19+
let content = fs.readFileSync(filePath, { encoding: 'utf8' });
20+
21+
// regex to extract package name and version from `sv.dependency` and `sv.devDependency`
22+
const svDepRegex = /sv\.(?:dependency|devDependency)\('([^']+)',\s*'([^']+)'\)/g;
23+
// regex to extract from object literal properties `{ package: '...', version: '...' }` (ex: tailwind add-on)
24+
const objectLiteralRegex = /package:\s*'([^']+)',\s*version:\s*'([^']+)'/g;
25+
26+
const svDepMatches = Array.from(content.matchAll(svDepRegex));
27+
const objectLiteralMatches = Array.from(content.matchAll(objectLiteralRegex));
28+
29+
content = await replaceDeps(content, svDepMatches);
30+
content = await replaceDeps(content, objectLiteralMatches);
31+
32+
fs.writeFileSync(filePath, content);
33+
}
34+
}
35+
36+
/**
37+
* Replaces the matched versions with their latest.
38+
* @param {string} content
39+
* @param {RegExpExecArray[]} matches
40+
* @returns {Promise<string>}
41+
*/
42+
async function replaceDeps(content, matches) {
43+
for (const match of matches) {
44+
const [fullMatch, name, version] = match;
45+
const newVersion = `^${await getLatestVersion(name)}`;
46+
const updatedMatch = fullMatch.replace(version, newVersion);
47+
if (fullMatch !== updatedMatch) {
48+
content = content.replace(fullMatch, updatedMatch);
49+
console.log(
50+
` - ${styleText('blue', name + ':').padEnd(40)} ${styleText('red', version.padEnd(7))} -> ${styleText('green', newVersion)}`
51+
);
52+
}
53+
}
54+
return content;
55+
}
56+
57+
/**
58+
* Gets the latest version of given package from the npm registry
59+
* @param {string} name
60+
* @returns {Promise<string>}
61+
*/
62+
async function getLatestVersion(name) {
63+
const response = await fetch(`https://registry.npmjs.org/${name}/latest`);
64+
const json = await response.json();
65+
return json.version;
66+
}
67+
68+
await updateAddonDependencies();

0 commit comments

Comments
 (0)