1
+ //@ts -check
2
+
1
3
import esbuild from 'esbuild' ;
2
- import { readFile , readFileSync , writeFileSync } from 'fs' ;
4
+ import { readFile , writeFile } from 'fs/promises' ;
5
+ import { spawn } from 'child_process' ;
6
+
7
+ const production = process . argv . includes ( '--mode=production' ) ;
8
+ const pkg = JSON . parse ( await readFile ( 'package.json' , 'utf8' ) ) ;
9
+ const copyright = await readFile ( 'README.md' , 'utf8' ) . then ( ( value ) => {
10
+ return value
11
+ ?. replace ( / [ \s \S ] * ?# # C o p y r i g h t / , '' )
12
+ ?. match ( / .{ 1 , 65 } \s + | \S + / g)
13
+ ?. join ( '\n * ' )
14
+ . replace ( / \n { 2 , } / g, '\n' )
15
+ . split ( '\n' ) [ 0 ] ;
16
+ } ) ;
17
+
18
+ console . log ( copyright ) ;
19
+
20
+ /**
21
+ * @param {string } name
22
+ * @param {import('esbuild').BuildOptions } options
23
+ */
24
+ function getContext ( name , options ) {
25
+ return esbuild
26
+ . context ( {
27
+ bundle : true ,
28
+ entryPoints : [ `${ name } /index.ts` ] ,
29
+ outfile : `dist/${ name } .js` ,
30
+ keepNames : true ,
31
+ dropLabels : production ? [ 'DEV' ] : undefined ,
32
+ legalComments : 'inline' ,
33
+ banner : {
34
+ js : `/**\n * ${ copyright } */` ,
35
+ } ,
36
+ plugins : [
37
+ {
38
+ name : 'build' ,
39
+ setup ( build ) {
40
+ build . onEnd ( ( result ) => {
41
+ if ( ! result || result . errors . length === 0 ) console . log ( `Successfully built ${ name } ` ) ;
42
+ } ) ;
43
+ } ,
44
+ } ,
45
+ ] ,
46
+ ...options ,
47
+ } )
48
+ . catch ( ( ) => process . exit ( 1 ) ) ;
49
+ }
3
50
4
- /** @type {import('esbuild').BuildOptions } */
5
- const server = {
51
+ const server = await getContext ( 'server' , {
6
52
platform : 'node' ,
7
53
target : [ 'node16' ] ,
8
54
format : 'cjs' ,
9
- } ;
55
+ } ) ;
10
56
11
- /** @type {import('esbuild').BuildOptions } */
12
- const client = {
57
+ const client = await getContext ( 'client' , {
13
58
platform : 'browser' ,
14
59
target : [ 'es2021' ] ,
15
60
format : 'iife' ,
16
- } ;
61
+ } ) ;
17
62
18
- const production = process . argv . includes ( '--mode=production' ) ;
19
- const buildCmd = production ? esbuild . build : esbuild . context ;
20
- const wordWrap = new RegExp ( `.{1,65}\\s+|\\S+` , 'g' ) ;
21
- const packageJson = JSON . parse ( readFileSync ( 'package.json' , { encoding : 'utf8' } ) ) ;
22
- const copyright = readFileSync ( 'README.md' , { encoding : 'utf8' } )
23
- . replace ( / [ \s \S ] * ?# # C o p y r i g h t / , '' )
24
- . match ( wordWrap )
25
- . join ( '\n * ' )
26
- . replace ( / \n { 2 , } / g, '\n' ) ;
27
-
28
- console . log ( copyright . split ( '\n' ) [ 0 ] ) ;
29
-
30
- writeFileSync (
31
- '.yarn.installed' ,
32
- new Date ( ) . toLocaleString ( 'en-AU' , { timeZone : 'UTC' , timeStyle : 'long' , dateStyle : 'full' } )
33
- ) ;
34
-
35
- writeFileSync (
36
- 'fxmanifest.lua' ,
37
- `fx_version 'cerulean'
63
+ async function build ( ) {
64
+ return Promise . all ( [ server . rebuild ( ) , client . rebuild ( ) ] ) . then ( ( ) => {
65
+ writeFile ( '.yarn.installed' , new Date ( ) . toISOString ( ) ) ;
66
+ writeFile (
67
+ 'fxmanifest.lua' ,
68
+ `fx_version 'cerulean'
38
69
game 'gta5'
39
70
40
- name '${ packageJson . name } '
41
- author '${ packageJson . author } '
42
- version '${ packageJson . version } '
43
- license '${ packageJson . license } '
44
- repository '${ packageJson . repository . url } '
45
- description '${ packageJson . description } '
71
+ name '${ pkg . name } '
72
+ author '${ pkg . author } '
73
+ version '${ pkg . version } '
74
+ license '${ pkg . license } '
75
+ repository '${ pkg . repository . url } '
76
+ description '${ pkg . description } '
46
77
47
78
dependencies {
48
79
'/server:7290',
@@ -52,7 +83,6 @@ dependencies {
52
83
files {
53
84
'lib/init.lua',
54
85
'lib/client/**.lua',
55
- 'imports/client.lua',
56
86
'locales/*.json',
57
87
'common/data/*.json',
58
88
}
@@ -61,38 +91,30 @@ client_script 'dist/client.js'
61
91
server_script 'dist/server.js'
62
92
63
93
`
64
- ) ;
65
-
66
- for ( const context of [ 'client' , 'server' ] ) {
67
- buildCmd ( {
68
- bundle : true ,
69
- entryPoints : [ `${ context } /index.ts` ] ,
70
- outfile : `dist/${ context } .js` ,
71
- keepNames : true ,
72
- dropLabels : production ? [ 'DEV' ] : undefined ,
73
- legalComments : 'inline' ,
74
- banner : {
75
- js : `/**\n * ${ copyright } */` ,
76
- } ,
77
- plugins : production
78
- ? undefined
79
- : [
80
- {
81
- name : 'rebuild' ,
82
- setup ( build ) {
83
- const cb = ( result ) => {
84
- if ( ! result || result . errors . length === 0 ) console . log ( `Successfully built ${ context } ` ) ;
85
- } ;
86
- build . onEnd ( cb ) ;
87
- } ,
88
- } ,
89
- ] ,
90
- ...( context === 'client' ? client : server ) ,
91
- } )
92
- . then ( ( build ) => {
93
- if ( production ) return console . log ( `Successfully built ${ context } ` ) ;
94
+ ) ;
95
+ } ) ;
96
+ }
94
97
95
- build . watch ( ) ;
96
- } )
97
- . catch ( ( ) => process . exit ( 1 ) ) ;
98
+ const tsc = spawn ( `tsc --build ${ production ? '' : '--watch --preserveWatchOutput' } && tsc-alias` , {
99
+ stdio : [ 'inherit' , 'pipe' , 'inherit' ] ,
100
+ shell : true ,
101
+ } ) ;
102
+
103
+ if ( production ) {
104
+ tsc . on ( 'close' , async ( code ) => {
105
+ if ( code !== 0 ) return process . exit ( code ) ;
106
+
107
+ await build ( ) ;
108
+
109
+ process . exit ( 0 ) ;
110
+ } ) ;
98
111
}
112
+
113
+ tsc . stdout . on ( 'data' , async ( data ) => {
114
+ const output = data . toString ( ) ;
115
+ process . stdout . write ( output ) ;
116
+
117
+ if ( output . includes ( 'Found 0 errors.' ) ) {
118
+ await build ( ) ;
119
+ }
120
+ } ) ;
0 commit comments