@@ -4,33 +4,103 @@ import os from 'os';
4
4
import fs from 'fs' ;
5
5
import path from 'path' ;
6
6
import process from 'process' ;
7
- import childProcess from 'child_process' ;
8
7
import esbuild from 'esbuild' ;
9
8
import packageJSON from '../package.json' assert { type : 'json ' } ;
10
9
import { fileURLToPath } from 'url' ;
10
+ import { $ } from "execa" ;
11
+ import tscOutputParser from '@aivenio/tsc-output-parser' ;
11
12
12
13
const platform = os . platform ( ) ;
13
14
const __filename = fileURLToPath ( import . meta. url ) ;
14
15
const __dirname = path . dirname ( __filename ) ;
15
16
17
+ const pemReadFilePlugin = {
18
+ name : 'base64-plugin' ,
19
+ setup ( build ) {
20
+ build . onLoad ( { filter : / \. j s $ / } , async ( args ) => {
21
+ let contents = fs . readFileSync ( args . path , 'utf8' ) ;
22
+
23
+ const regex = / a w a i t \s + f s \. p r o m i s e s \. r e a d F i l e \( \s * p a t h \. r e s o l v e \( _ _ d i r n a m e , \s * [ ' " ` ] ( .* \. p e m ) [ ' " ` ] \s * \) \) / g;
24
+ let match ;
25
+
26
+ while ( ( match = regex . exec ( contents ) ) !== null ) {
27
+ const pemFilePath = path . resolve ( path . dirname ( args . path ) , match [ 1 ] ) ;
28
+ const pemContents = fs . readFileSync ( pemFilePath , 'utf8' ) ;
29
+ const base64Contents = Buffer . from ( pemContents ) . toString ( 'base64' ) ;
30
+ contents = contents . replace ( match [ 0 ] , `await Promise.resolve(Buffer.from("${ base64Contents } ", 'base64').toString())` ) ;
31
+ }
32
+
33
+ return {
34
+ contents,
35
+ loader : 'js' ,
36
+ } ;
37
+ } ) ;
38
+ } ,
39
+ } ;
40
+
41
+ const tscDiagnosticToEsbuild = async (
42
+ diagnostic ,
43
+ ) => {
44
+ const lineText =
45
+ await $ `sed -n ${ diagnostic . value . cursor . value . line } p ${ diagnostic . value . path . value } ` ;
46
+
47
+ const [ firstLine , rest ] = diagnostic . value . message . value . split ( "\n" , 2 ) ;
48
+
49
+ return {
50
+ location : {
51
+ column : diagnostic . value . cursor . value . col - 1 ,
52
+ line : diagnostic . value . cursor . value . line ,
53
+ file : diagnostic . value . path . value ,
54
+ lineText : lineText . stdout ,
55
+ } ,
56
+ notes : rest && rest . trim ( ) . length > 0 ? [ { text : rest } ] : [ ] ,
57
+ text : `${ firstLine } [${ diagnostic . value . tsError . value . errorString } ]` ,
58
+ } ;
59
+ } ;
60
+
61
+ const checkTypesPlugin = ( ) => {
62
+ return {
63
+ name : 'check-types' ,
64
+ setup ( build ) {
65
+ build . onEnd ( async ( result ) => {
66
+ if ( result . errors . length > 0 ) {
67
+ return ;
68
+ }
69
+
70
+ const buildArgs = [ '--noEmit' , '-p' , './tsconfig.build.json' , '--pretty' , 'false' ] ;
71
+ try {
72
+ await $ ( 'tsc' , buildArgs ) ;
73
+ } catch ( err ) {
74
+ const tscOutput = tscOutputParser . parse ( err . stdout ) ;
75
+ const messages = await Promise . all ( tscOutput . map ( output => tscDiagnosticToEsbuild ( output ) ) ) ;
76
+ const formatted = await esbuild . formatMessages (
77
+ messages ,
78
+ {
79
+ kind : 'error' ,
80
+ color : true ,
81
+ terminalWidth : 100 ,
82
+ }
83
+ ) ;
84
+ console . log ( formatted . join ( '\n' ) ) ;
85
+ process . exit ( 1 ) ;
86
+ }
87
+ } ) ;
88
+ } ,
89
+ } ;
90
+ } ;
91
+
16
92
async function main ( argv = process . argv ) {
17
93
argv = argv . slice ( 2 ) ;
18
94
const projectRoot = path . join ( __dirname , '..' ) ;
19
- const buildPath = path . join ( projectRoot , 'build ' ) ;
95
+ const srcPath = path . join ( projectRoot , 'src ' ) ;
20
96
const distPath = path . join ( projectRoot , 'dist' ) ;
21
97
const gitPath = process . env . GIT_DIR ?? path . join ( projectRoot , '.git' ) ;
22
98
await fs . promises . rm ( distPath , {
23
99
recursive : true ,
24
100
force : true ,
25
101
} ) ;
26
- const buildArgs = [ '-p' , './tsconfig.build.json' , ...argv ] ;
27
- console . error ( 'Running tsc:' ) ;
28
- console . error ( [ 'tsc' , ...buildArgs ] . join ( ' ' ) ) ;
29
- childProcess . execFileSync ( 'tsc' , buildArgs , {
30
- stdio : [ 'inherit' , 'inherit' , 'inherit' ] ,
31
- windowsHide : true ,
32
- encoding : 'utf-8' ,
33
- shell : platform === 'win32' ? true : false ,
102
+ await fs . promises . mkdir ( distPath , {
103
+ recursive : true ,
34
104
} ) ;
35
105
// This collects the build metadata and adds it to the build folder so that dynamic imports to it will resolve correctly.
36
106
let gitHead = process . env . COMMIT_HASH ;
@@ -52,17 +122,17 @@ async function main(argv = process.argv) {
52
122
console . error ( 'Writing build metadata (build.json):' ) ;
53
123
console . error ( buildJSON ) ;
54
124
await fs . promises . writeFile (
55
- path . join ( buildPath , 'build.json' ) ,
125
+ path . join ( distPath , 'build.json' ) ,
56
126
JSON . stringify ( buildJSON , null , 2 ) ,
57
127
) ;
58
128
// This specifies import paths that is left as an external require
59
129
// This is kept to packages that have a native binding
60
130
const externalDependencies = Object . keys ( packageJSON . nativeDependencies ?? { } ) ;
61
131
const esbuildOptions = {
62
132
entryPoints : [
63
- path . join ( buildPath , ' index.js' ) ,
133
+ 'src/ index.ts'
64
134
] ,
65
- sourceRoot : buildPath ,
135
+ sourceRoot : srcPath ,
66
136
bundle : true ,
67
137
platform : 'node' ,
68
138
format : 'cjs' ,
@@ -74,7 +144,8 @@ async function main(argv = process.argv) {
74
144
minify : true ,
75
145
keepNames : true ,
76
146
outfile : path . join ( distPath , 'index.cjs' ) ,
77
- metafile : true
147
+ metafile : true ,
148
+ plugins : [ checkTypesPlugin ( ) , pemReadFilePlugin ] ,
78
149
} ;
79
150
console . error ( 'Running esbuild:' ) ;
80
151
console . error ( esbuildOptions ) ;
0 commit comments