student life social platform
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 125 lines 4.2 kB view raw
1import { execa } from 'execa'; 2import { readFile, writeFile } from 'node:fs/promises'; 3import path from 'node:path'; 4 5const GENERATED_START_MARKER = '// @generated buildinfo'; 6const GENERATED_END_MARKER = '// end generated buildinfo'; 7 8const stub = process.argv.length >= 3 && process.argv[2] === '--stub'; 9 10type Package = 'api' | 'app' | 'sync' | 'db'; 11 12/** files to inject in */ 13let targets: Array<[string, Package]> = [ 14 ['packages/app/src/lib/buildinfo.ts', 'app'], 15 ['packages/api/src/lib/buildinfo.ts', 'api'], 16 ['packages/app/svelte.config.js', 'app'], 17]; 18 19// TODO use command line arguments (this) to not inject in e.g. API package from app package's script 20if (stub && process.argv.length >= 4) 21 targets = process.argv.slice(3).map((arg) => arg.split(':') as [string, Package]); 22if (!stub && process.argv.length >= 3) 23 targets = process.argv.slice(2).map((arg) => arg.split(':') as [string, Package]); 24 25async function git(args: string): Promise<string> { 26 const additionalConfig = { 27 // see https://stackoverflow.com/a/22634649/9943464 28 'versionsort.suffix': '-alpha -beta -pre -rc', 29 }; 30 const { stdout } = await execa('git', [ 31 '-c', 32 ...Object.entries(additionalConfig).map(([k, v]) => `${k}='${v}'`), 33 ...args.split(' '), 34 ]); 35 return stdout; 36} 37 38const hash = stub ? 'dev' : await git('rev-parse HEAD').then((hash) => hash.trim()); 39const toplevel = await git('rev-parse --show-toplevel'); 40const variables = { 41 CURRENT_COMMIT: hash, 42 CURRENT_VERSIONS: { 43 api: process.env.TAG || 'dev', 44 app: process.env.TAG || 'dev', 45 sync: process.env.TAG || 'dev', 46 db: process.env.TAG || 'dev', 47 }, 48}; 49 50console.info(`Build info: ${JSON.stringify(variables)}`); 51console.info(`Injecting into ${targets.join(', ')}`); 52 53// Inject in graphinx config 54const graphinxConfigPath = path.join(toplevel.trim(), 'packages/api/.graphinx.yaml'); 55 56await writeFile( 57 graphinxConfigPath, 58 (await readFile(graphinxConfigPath, 'utf-8')) 59 .replace( 60 /^(\s*)CURRENT_COMMIT: .+$/m, 61 `$1CURRENT_COMMIT: ${JSON.stringify(variables.CURRENT_COMMIT)}`, 62 ) 63 .replace( 64 /^(\s*)CURRENT_COMMIT_SHORT: .+$/m, 65 `$1CURRENT_COMMIT_SHORT: ${JSON.stringify(variables.CURRENT_COMMIT.slice(0, 7))}`, 66 ) 67 .replace( 68 /^(\s*)CURRENT_VERSION: .+$/m, 69 `$1CURRENT_VERSION: ${JSON.stringify(variables.CURRENT_VERSIONS.api)}`, 70 ), 71); 72 73function singlequotes(literal: string): string { 74 if ((literal.match(/"/g) || []).length !== 2) return literal; 75 return `'${literal.replace(/"/g, '')}'`; 76} 77 78function constDeclaration( 79 name: string, 80 value: unknown, 81 { typescript = true, exported = true } = {}, 82) { 83 return `${exported ? 'export ' : ''}const ${name} = ${singlequotes(JSON.stringify(value))}${typescript ? ' as string' : ''};`; 84} 85 86function replaceBetweenLines(start: string, end: string, replacement: string, contents: string) { 87 const lines = contents.split('\n'); 88 const startIndex = lines.findIndex((line) => line.trim().includes(start.trim())); 89 const endIndex = lines.findIndex((line) => line.trim().includes(end.trim())); 90 return [...lines.slice(0, startIndex + 1), replacement, ...lines.slice(endIndex)].join('\n'); 91} 92 93await Promise.all( 94 targets.map(async ([relativePath, pkg]) => { 95 const filepath = path.join(toplevel.trim(), relativePath); 96 const typescript = path.extname(filepath) === '.ts'; 97 const oldContents = await readFile(filepath, 'utf-8').catch(() => ''); 98 99 /** isolated means the file contains nothing other than these two variables */ 100 const isolated = 101 !oldContents.includes(GENERATED_START_MARKER) && !oldContents.includes(GENERATED_END_MARKER); 102 103 const declarations = [ 104 constDeclaration('CURRENT_COMMIT', variables.CURRENT_COMMIT, { 105 typescript, 106 exported: isolated, 107 }), 108 constDeclaration('CURRENT_VERSION', variables.CURRENT_VERSIONS[pkg], { 109 typescript, 110 exported: isolated, 111 }), 112 ]; 113 await writeFile( 114 filepath, 115 isolated 116 ? declarations.join('\n') + '\n' 117 : replaceBetweenLines( 118 GENERATED_START_MARKER, 119 GENERATED_END_MARKER, 120 declarations.join('\n'), 121 oldContents, 122 ), 123 ); 124 }), 125);