Skip to content

Commit 3f45e44

Browse files
committed
create scripts for managing demos
1 parent f9e2e9c commit 3f45e44

File tree

3 files changed

+381
-0
lines changed

3 files changed

+381
-0
lines changed

scripts/demos-use-backup.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Script that replaces 'demos/.../package.json' with 'demos/.../package.json.bak',
3+
* which is generated by 'scripts/demos-use-workspace.ts'.
4+
*/
5+
6+
import { execSync } from 'child_process';
7+
import * as fs from 'fs';
8+
import * as path from 'path';
9+
10+
const demosDir = path.resolve('demos');
11+
12+
// Function to split user-provided demos into found and not found demos
13+
const filterDemos = (allDemos: string[], providedDemos: string[]): [string[], string[]] => {
14+
const found: string[] = [];
15+
const notFound: string[] = [];
16+
17+
providedDemos.forEach((demo) => {
18+
if (allDemos.includes(demo)) {
19+
found.push(demo);
20+
} else {
21+
notFound.push(demo);
22+
}
23+
});
24+
25+
return [found, notFound];
26+
};
27+
28+
// Function to replace '^x.xx.xx' with 'workspace:*' for workspace packages
29+
const linkDemo = async (demoName: string) => {
30+
const demoSrc = path.join(demosDir, demoName);
31+
console.log(`Unlinking ${demoName}`);
32+
33+
// Update package.json
34+
const packageJsonPath = path.join(demoSrc, 'package.json');
35+
const packageJsonBakPath = path.join(demoSrc, 'package.json.bak');
36+
37+
if (!fs.existsSync(packageJsonBakPath)) {
38+
console.log("⚠️ Warning: No 'package.json.bak'.");
39+
return;
40+
}
41+
42+
// Replace package.json with package.json.bak
43+
fs.copyFileSync(packageJsonBakPath, packageJsonPath);
44+
fs.unlinkSync(packageJsonBakPath);
45+
};
46+
47+
// Main function to read demos directory and process each demo
48+
const main = () => {
49+
const args: string[] = [];
50+
const opts = {
51+
noInstall: false
52+
};
53+
54+
for (const arg of process.argv.slice(2)) {
55+
if (arg === '--no-install') {
56+
opts.noInstall = true;
57+
} else {
58+
args.push(arg);
59+
}
60+
}
61+
62+
const allDemos = fs.readdirSync(demosDir);
63+
let demoNames: string[];
64+
65+
if (args.length > 0) {
66+
const [foundDemos, notFoundDemos] = filterDemos(allDemos, process.argv.slice(2));
67+
68+
if (notFoundDemos.length > 0) {
69+
console.log('⚠️ Warning: Failed to locate some demos:');
70+
for (const demo of notFoundDemos) {
71+
console.log(` - ${demo}`);
72+
}
73+
}
74+
75+
demoNames = foundDemos;
76+
} else {
77+
demoNames = allDemos;
78+
}
79+
80+
console.log('Linking demos...');
81+
for (const demoName of demoNames) {
82+
linkDemo(demoName);
83+
}
84+
console.log('Done.');
85+
86+
if (opts.noInstall) {
87+
process.exit(0);
88+
}
89+
90+
console.log('\nInstalling packages...');
91+
for (const demoName of demoNames) {
92+
const demoSrc = path.join(demosDir, demoName);
93+
try {
94+
execSync('pnpm --ignore-workspace install', { cwd: demoSrc, stdio: 'inherit' });
95+
} catch (e) {
96+
console.error(`Error installing packages: ${e}`);
97+
process.exit(1);
98+
}
99+
console.log('Done.');
100+
}
101+
};
102+
103+
main();

scripts/demos-use-latest.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* ! If you are trying to restore package.json after running
3+
* ! 'demos-use-workspace', please run 'demos-use-backup'
4+
* ! to restore package.json to its original state first.
5+
*
6+
* Script to replace demos' workspace packages with latest published
7+
* versions. Modifies package.json in-place.
8+
*/
9+
10+
import { findWorkspacePackages } from '@pnpm/workspace.find-packages';
11+
import { execSync } from 'child_process';
12+
import * as fs from 'fs';
13+
import * as path from 'path';
14+
15+
const demosDir = path.resolve('demos');
16+
17+
const workspacePackages = await findWorkspacePackages(path.resolve('.'));
18+
19+
// Function to split user-provided demos into found and not found demos
20+
const filterDemos = (allDemos: string[], providedDemos: string[]): [string[], string[]] => {
21+
const found: string[] = [];
22+
const notFound: string[] = [];
23+
24+
providedDemos.forEach((demo) => {
25+
if (allDemos.includes(demo)) {
26+
found.push(demo);
27+
} else {
28+
notFound.push(demo);
29+
}
30+
});
31+
32+
return [found, notFound];
33+
};
34+
35+
// Function to replace workspace package versions with latest published versions
36+
const linkDemo = async (demoName: string) => {
37+
const demoSrc = path.join(demosDir, demoName);
38+
console.log(`\nUpgrading ${demoName}`);
39+
40+
// Update package.json
41+
const packageJsonPath = path.join(demoSrc, 'package.json');
42+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
43+
44+
// Track changed files
45+
let changes = 0;
46+
const updateDeps = (deps: { [key: string]: string }) => {
47+
for (const dep in deps) {
48+
const matchingPackage = workspacePackages.find((p) => p.manifest.name === dep);
49+
if (matchingPackage == undefined) continue;
50+
51+
let latestVersion = matchingPackage.manifest.version;
52+
if (!latestVersion) {
53+
console.error(`Could not find latest version of package '${matchingPackage.manifest.name}'`);
54+
process.exit(1);
55+
}
56+
latestVersion = '^' + latestVersion;
57+
if (deps[dep] === latestVersion) {
58+
console.log(`- ${dep}: '${deps[dep]}' => '${latestVersion}' (no changes)`);
59+
continue;
60+
}
61+
console.log(`- ${dep}: '${deps[dep]}' => '${latestVersion}'`);
62+
deps[dep] = latestVersion;
63+
changes++;
64+
}
65+
};
66+
67+
if (packageJson.dependencies) {
68+
updateDeps(packageJson.dependencies);
69+
}
70+
71+
if (packageJson.peerDependencies) {
72+
updateDeps(packageJson.peerDependencies);
73+
}
74+
75+
if (packageJson.devDependencies) {
76+
updateDeps(packageJson.devDependencies);
77+
}
78+
79+
if (changes) {
80+
fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');
81+
}
82+
};
83+
84+
// Main function to read demos directory and process each demo
85+
const main = () => {
86+
const args: string[] = [];
87+
const opts = {
88+
noInstall: false
89+
};
90+
91+
for (const arg of process.argv.slice(2)) {
92+
if (arg === '--no-install') {
93+
opts.noInstall = true;
94+
} else {
95+
args.push(arg);
96+
}
97+
}
98+
99+
const allDemos = fs.readdirSync(demosDir);
100+
let demoNames: string[];
101+
102+
if (args.length > 0) {
103+
const [foundDemos, notFoundDemos] = filterDemos(allDemos, args);
104+
105+
if (notFoundDemos.length > 0) {
106+
console.log('⚠️ Warning: Failed to locate some demos:');
107+
for (const demo of notFoundDemos) {
108+
console.log(`- ${demo}`);
109+
}
110+
}
111+
112+
demoNames = foundDemos;
113+
} else {
114+
demoNames = allDemos;
115+
}
116+
117+
console.log('Upgrading demos...');
118+
for (const demoName of demoNames) {
119+
linkDemo(demoName);
120+
}
121+
console.log('\nDone.');
122+
123+
if (opts.noInstall) {
124+
process.exit(0);
125+
}
126+
127+
console.log('\nInstalling packages...\n');
128+
for (const demoName of demoNames) {
129+
const demoSrc = path.join(demosDir, demoName);
130+
console.log(`- ${demoName}`);
131+
try {
132+
// Patchy solution with rm -rf'ing node_modules because pnpm tries to reuse existing linked package
133+
execSync('rm -rf node_modules && pnpm --ignore-workspace install', { cwd: demoSrc, stdio: 'inherit' });
134+
} catch (e) {
135+
console.error(`Error installing packages: ${e}`);
136+
process.exit(1);
137+
}
138+
}
139+
console.log('\nDone.');
140+
};
141+
142+
main();

scripts/demos-use-workspace.ts

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/**
2+
* Users want to be able to run 'pnpm build:packages', cd into a demo,
3+
* run 'pnpm install && pnpm build', and have just that demo's packages
4+
* installed. Currently, this is not possible, as demos are included in
5+
* the pnpm workspace and therefore all demos' packages will be installed.
6+
*
7+
* This script goes through every package in 'demos/*' and replaces the
8+
* workspace packages' versions with 'workspace:*', allowing for easy
9+
* testing of new versions for SDK developers, as well as small
10+
* node_modules folders for SDK users.
11+
*
12+
* This way, users can use 'pnpm --ignore-workspace install && pnpm build',
13+
* while SDK devs can use 'tsx ./scripts/link-demos.ts' to build demos.
14+
*
15+
* Most of this code is copied from './scripts/isolated-demo-test.ts'.
16+
*/
17+
18+
import { findWorkspacePackages } from '@pnpm/workspace.find-packages';
19+
import { execSync } from 'child_process';
20+
import * as fs from 'fs';
21+
import * as path from 'path';
22+
23+
const demosDir = path.resolve('demos');
24+
25+
const workspacePackages = await findWorkspacePackages(path.resolve('.'));
26+
27+
// Function to split user-provided demos into found and not found demos
28+
const filterDemos = (allDemos: string[], providedDemos: string[]): [string[], string[]] => {
29+
const found: string[] = [];
30+
const notFound: string[] = [];
31+
32+
providedDemos.forEach((demo) => {
33+
if (allDemos.includes(demo)) {
34+
found.push(demo);
35+
} else {
36+
notFound.push(demo);
37+
}
38+
});
39+
40+
return [found, notFound];
41+
};
42+
43+
// Function to replace '^x.xx.xx' with 'workspace:*' for workspace packages
44+
const linkDemo = async (demoName: string) => {
45+
const newPackageVer = 'workspace:*';
46+
const demoSrc = path.join(demosDir, demoName);
47+
console.log(`Linking ${demoName}`);
48+
49+
// Update package.json
50+
const packageJsonPath = path.join(demoSrc, 'package.json');
51+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
52+
53+
// Track changed files
54+
let changes = 0;
55+
const updateDeps = (deps: { [key: string]: string }) => {
56+
for (const dep in deps) {
57+
const matchingPackage = workspacePackages.find((p) => p.manifest.name === dep);
58+
if (matchingPackage != undefined && deps[dep] != newPackageVer) {
59+
console.log(` - ${dep}: '${deps[dep]}' => '${newPackageVer}'`);
60+
deps[dep] = newPackageVer;
61+
changes++;
62+
}
63+
}
64+
};
65+
66+
if (packageJson.dependencies) {
67+
updateDeps(packageJson.dependencies);
68+
}
69+
70+
if (packageJson.devDependencies) {
71+
updateDeps(packageJson.devDependencies);
72+
}
73+
74+
if (changes) {
75+
// Save copy of original package.json to package.json.bak
76+
fs.copyFileSync(packageJsonPath, packageJsonPath + '.bak');
77+
fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');
78+
} else {
79+
console.log(' - No changes');
80+
}
81+
};
82+
83+
// Main function to read demos directory and process each demo
84+
const main = () => {
85+
const args: string[] = [];
86+
const opts = {
87+
noInstall: false
88+
};
89+
90+
for (const arg of process.argv.slice(2)) {
91+
if (arg === '--no-install') {
92+
opts.noInstall = true;
93+
} else {
94+
args.push(arg);
95+
}
96+
}
97+
98+
const allDemos = fs.readdirSync(demosDir);
99+
let demoNames: string[];
100+
101+
if (args.length > 0) {
102+
const [foundDemos, notFoundDemos] = filterDemos(allDemos, process.argv.slice(2));
103+
104+
if (notFoundDemos.length > 0) {
105+
console.log('⚠️ Warning: Failed to locate some demos:');
106+
for (const demo of notFoundDemos) {
107+
console.log(` - ${demo}`);
108+
}
109+
}
110+
111+
demoNames = foundDemos;
112+
} else {
113+
demoNames = allDemos;
114+
}
115+
116+
console.log('Linking demos...');
117+
for (const demoName of demoNames) {
118+
linkDemo(demoName);
119+
}
120+
console.log('Done.');
121+
122+
if (opts.noInstall) {
123+
process.exit(0);
124+
}
125+
126+
console.log('\nInstalling packages...');
127+
try {
128+
execSync('pnpm install', { stdio: 'inherit' });
129+
} catch (e) {
130+
console.error(`Error installing packages: ${e}`);
131+
process.exit(1);
132+
}
133+
console.log('Done.');
134+
};
135+
136+
main();

0 commit comments

Comments
 (0)