2025-04-30 20:21:59 +07:00
import { $ , main } from 'bun'
2025-03-21 19:59:16 +07:00
import chalk from 'chalk'
2025-05-19 01:42:47 +07:00
import { exists , mkdir , readdir , rm , writeFile } from 'fs/promises'
2025-06-03 16:24:58 +07:00
import { parse } from 'path'
import { rolldown } from 'rolldown'
2025-09-10 00:09:26 +07:00
import { importGlobPlugin } from 'rolldown/experimental'
2025-05-01 01:29:55 +07:00
import pkg from '../package.json'
2025-09-10 00:18:10 +07:00
import asRequire from './plugins/as-require'
2025-09-10 00:09:26 +07:00
import hermesSwcPlugin from './plugins/hermes-swc'
import hermesCPlugin from './plugins/hermesc'
import shimAliases from './plugins/shim-aliases'
2025-05-01 01:29:55 +07:00
2025-06-01 13:50:21 +07:00
const ShimsDir = ` ${ import . meta . dir } /../shims `
const AssetsDir = ` ${ import . meta . dir } /../src/assets `
const GeneratedAssetsDir = ` ${ import . meta . dir } /../dist/assets/generated `
2025-05-19 01:42:47 +07:00
await rm ( GeneratedAssetsDir , { recursive : true , force : true } )
2025-06-15 17:43:27 +07:00
. then ( ( ) = >
console . debug ( chalk . gray ( '\u{1F5BB} Deleted old generated assets' ) ) ,
)
2025-05-19 01:42:47 +07:00
. catch ( )
2025-06-15 17:43:27 +07:00
const Dev =
process . argv . includes ( '--dev' ) || process . env . NODE_ENV === 'development'
2025-06-15 18:01:30 +07:00
// If this file is being run directly, build the project
if ( main === import . meta . filename ) build ( )
2025-06-15 17:43:27 +07:00
export default async function build ( dev = Dev , log = true ) {
2025-03-21 19:59:16 +07:00
const start = performance . now ( )
2025-05-07 02:53:31 +07:00
if ( log ) console . info ( chalk . gray ( '\u{1F5BB} Generating assets...' ) )
2025-05-07 01:21:27 +07:00
await generateAssets ( )
2025-05-07 02:53:31 +07:00
if ( log ) console . info ( chalk . cyanBright ( '\u{1F5BB} Assets generated' ) )
if ( log ) console . info ( chalk . gray ( '\u{1F5CE} Compiling JS...' ) )
2025-05-07 01:21:27 +07:00
2025-07-12 02:50:48 +07:00
const COMMIT = ( await $ ` git rev-parse HEAD ` . text ( ) ) . trim ( ) . substring ( 0 , 7 )
const REPO = 'revenge-mod/revenge-bundle-next'
2025-03-21 19:59:16 +07:00
const bundle = await rolldown ( {
input : 'src/index.ts' ,
platform : 'neutral' ,
2025-07-30 20:15:58 +07:00
optimization : {
2025-08-13 00:46:50 +07:00
// ! BROKEN, DO NOT USE!
// inlineConst: true,
2025-07-30 20:15:58 +07:00
// @ts-expect-error: Option not documented, but added in 1.0.0-beta.30
pifeForModuleWrappers : true ,
} ,
preserveEntrySignatures : false ,
transform : {
assumptions : {
pureGetters : true ,
setPublicClassFields : true ,
noDocumentAll : true ,
// TODO: "Not implemented"
// objectRestNoSymbols: true,
// ignoreFunctionLength: true,
} ,
2025-04-30 20:20:16 +07:00
} ,
2025-08-25 19:19:22 +07:00
tsconfig : 'tsconfig.json' ,
2025-03-21 19:59:16 +07:00
treeshake : true ,
keepNames : true ,
moduleTypes : {
'.webp' : 'dataurl' ,
} ,
define : {
2025-07-12 02:50:48 +07:00
__BUILD_DISCORD_SERVER_URL__ : JSON.stringify (
'https://discord.com/invite/ddcQf3s2Uq' ,
) ,
__BUILD_SOURCE_REPOSITORY_URL__ : JSON.stringify (
` https://github.com/ ${ REPO } ` ,
2025-06-03 16:24:58 +07:00
) ,
2025-07-12 02:50:48 +07:00
__BUILD_LICENSE_URL__ : JSON.stringify (
` https://raw.githubusercontent.com/ ${ REPO } / ${ COMMIT } /LICENSE ` ,
) ,
__BUILD_VERSION__ : JSON.stringify ( pkg . version ) ,
__BUILD_COMMIT__ : JSON.stringify ( COMMIT ) ,
2025-06-03 16:24:58 +07:00
__BUILD_BRANCH__ : JSON.stringify (
( await $ ` git rev-parse --abbrev-ref HEAD ` . text ( ) ) . trim ( ) ,
) ,
2025-07-10 12:39:25 +07:00
__DEV__ : String ( dev ) ,
2025-06-12 23:25:10 +07:00
2025-08-11 17:40:50 +07:00
// See types/build.d.ts for what these flags do
2025-06-15 17:57:33 +07:00
__BUILD_FLAG_DEBUG_MODULE_LOOKUPS__ : String ( dev ) ,
2025-07-08 11:24:48 +07:00
__BUILD_FLAG_DEBUG_MODULE_WAITS__ : String ( dev ) ,
2025-09-04 01:26:26 +07:00
__BUILD_FLAG_DEBUG_LAZY_VALUES__ : 'false' ,
2025-05-05 19:13:05 +07:00
__BUILD_FLAG_LOG_PROMISE_REJECTIONS__ : String ( dev ) ,
2025-03-21 19:59:16 +07:00
} ,
plugins : [
2025-09-10 00:18:10 +07:00
asRequire ( ) ,
2025-09-10 00:09:26 +07:00
shimAliases ( ShimsDir ) ,
2025-05-22 00:06:36 +07:00
importGlobPlugin ( ) ,
2025-09-10 00:09:26 +07:00
hermesSwcPlugin ( ) ,
2025-03-21 19:59:16 +07:00
hermesCPlugin ( {
flags : [
dev ? '-Og' : '-O' ,
2025-07-08 22:14:22 +07:00
dev ? '-g3' : '-g1' ,
'-reuse-prop-cache' ,
'-optimized-eval' ,
'-strict' ,
2025-03-21 19:59:16 +07:00
'-finline' ,
] ,
2025-06-17 19:12:04 +07:00
before ( ver ) {
if ( log ) {
2025-06-03 16:24:58 +07:00
console . debug (
chalk . cyanBright (
'\u{1F5CE} JS compilation finished...' ,
) ,
)
2025-06-17 19:12:04 +07:00
2025-06-03 16:24:58 +07:00
console . debug (
2025-06-17 19:12:04 +07:00
chalk . gray (
` \ u{1F5CE} Compiling bytecode with ${ ver } ... ` ,
) ,
2025-06-03 16:24:58 +07:00
)
2025-06-17 19:12:04 +07:00
}
2025-05-07 02:53:31 +07:00
} ,
after() {
2025-06-03 16:24:58 +07:00
if ( log )
console . debug (
chalk . cyanBright (
'\u{1F5CE} Bytecode compilation finished' ,
) ,
)
2025-03-21 19:59:16 +07:00
} ,
} ) ,
] ,
} )
await bundle . write ( {
2025-08-25 20:10:25 +07:00
minify : 'dce-only' ,
2025-07-30 20:15:58 +07:00
exports : 'none' ,
esModule : false ,
2025-07-11 00:17:18 +07:00
minifyInternalExports : true ,
2025-07-30 20:15:58 +07:00
hoistTransitiveImports : false ,
2025-03-21 19:59:16 +07:00
file : 'dist/revenge.js' ,
format : 'iife' ,
} )
if ( log )
console . info (
chalk . greenBright (
2025-05-07 02:53:31 +07:00
` \ u{2714} Compiled successfully! ${ chalk . gray ( ` (took ${ ( performance . now ( ) - start ) . toFixed ( 2 ) } ms) ` ) } ` ,
2025-03-21 19:59:16 +07:00
) ,
)
}
2025-05-07 01:21:27 +07:00
async function generateAssets() {
2025-06-03 16:24:58 +07:00
if ( ! ( await exists ( GeneratedAssetsDir ) ) )
await mkdir ( GeneratedAssetsDir , { recursive : true } )
2025-05-07 01:21:27 +07:00
2025-05-07 02:53:07 +07:00
const promises : Promise < void > [ ] = [ ]
2025-05-07 01:21:27 +07:00
for ( const file of await readdir ( AssetsDir ) ) {
const { name , ext } = parse ( file )
const path = ` ${ AssetsDir } / ${ file } `
const path2 = ` ${ GeneratedAssetsDir } / ${ name } .js `
if ( await exists ( path2 ) ) continue
2025-06-07 09:59:30 +07:00
// We attempt to sanitize the path, but not the name as it should fail if name contains invalid characters
const uriPath = JSON . stringify ( path )
const type = JSON . stringify ( ext . slice ( 1 ) )
2025-05-07 02:53:07 +07:00
promises . push (
writeFile (
path2 ,
2025-07-13 19:52:32 +07:00
` import{registerAsset}from'@revenge-mod/assets';import uri from ${ uriPath } ;const ${ name } =registerAsset({name:' ${ name } ',type: ${ type } ,uri});export { ${ name } as default } ` ,
2025-05-07 02:53:07 +07:00
) ,
2025-05-07 01:21:27 +07:00
)
}
2025-05-07 02:53:07 +07:00
await Promise . all ( promises )
2025-05-07 01:21:27 +07:00
}