1+ #!/usr/bin/env node
2+
3+ const fs = require ( 'fs' ) ;
4+ const path = require ( 'path' ) ;
5+
6+ // Version configurations
7+ const VERSION_CONFIGS = {
8+ '13' : {
9+ libpgQueryTag : '13-2.2.0' ,
10+ useEmscriptenPatch : true
11+ } ,
12+ '14' : {
13+ libpgQueryTag : '14-3.0.0' ,
14+ useEmscriptenPatch : false
15+ } ,
16+ '15' : {
17+ libpgQueryTag : '15-4.2.4' ,
18+ useEmscriptenPatch : false
19+ } ,
20+ '16' : {
21+ libpgQueryTag : '16-5.2.0' ,
22+ useEmscriptenPatch : false
23+ } ,
24+ '17' : {
25+ libpgQueryTag : '17-6.1.0' ,
26+ useEmscriptenPatch : false
27+ }
28+ } ;
29+
30+ // Headers for different file types
31+ const HEADERS = {
32+ // JavaScript/TypeScript/C style comment
33+ default : `/**
34+ * DO NOT MODIFY MANUALLY — this is generated from the templates dir
35+ *
36+ * To make changes, edit the files in the templates/ directory and run:
37+ * npm run copy:templates
38+ */
39+
40+ ` ,
41+ // Makefile style comment
42+ makefile : `# DO NOT MODIFY MANUALLY — this is generated from the templates dir
43+ #
44+ # To make changes, edit the files in the templates/ directory and run:
45+ # npm run copy:templates
46+
47+ `
48+ } ;
49+
50+ // File extensions that should get headers
51+ const HEADER_EXTENSIONS = [ '.ts' , '.js' , '.c' ] ;
52+ const MAKEFILE_NAMES = [ 'Makefile' , 'makefile' ] ;
53+
54+ /**
55+ * Process template content with simple mustache-like syntax
56+ * @param {string } content - Template content
57+ * @param {object } config - Configuration object
58+ * @returns {string } Processed content
59+ */
60+ function processTemplate ( content , config ) {
61+ // Replace simple variables
62+ content = content . replace ( / \{ \{ L I B P G _ Q U E R Y _ T A G \} \} / g, config . libpgQueryTag ) ;
63+
64+ // Handle conditional blocks
65+ // {{#USE_EMSCRIPTEN_PATCH}}...{{/USE_EMSCRIPTEN_PATCH}}
66+ const conditionalRegex = / \{ \{ # ( \w + ) \} \} ( [ \s \S ] * ?) \{ \{ \/ \1\} \} / g;
67+
68+ content = content . replace ( conditionalRegex , ( match , flag , blockContent ) => {
69+ if ( flag === 'USE_EMSCRIPTEN_PATCH' && config . useEmscriptenPatch ) {
70+ return blockContent ;
71+ }
72+ return '' ;
73+ } ) ;
74+
75+ return content ;
76+ }
77+
78+ /**
79+ * Add header to file content if applicable
80+ * @param {string } filePath - Path to the file
81+ * @param {string } content - File content
82+ * @returns {string } Content with header if applicable
83+ */
84+ function addHeaderIfNeeded ( filePath , content ) {
85+ const basename = path . basename ( filePath ) ;
86+ const ext = path . extname ( filePath ) ;
87+
88+ // Check if it's a Makefile
89+ if ( MAKEFILE_NAMES . includes ( basename ) ) {
90+ return HEADERS . makefile + content ;
91+ }
92+
93+ // Check if it's a source file that needs a header
94+ if ( HEADER_EXTENSIONS . includes ( ext ) ) {
95+ return HEADERS . default + content ;
96+ }
97+
98+ return content ;
99+ }
100+
101+ /**
102+ * Copy a file from template to destination with processing
103+ * @param {string } templatePath - Source template path
104+ * @param {string } destPath - Destination path
105+ * @param {object } config - Version configuration
106+ */
107+ function copyTemplate ( templatePath , destPath , config ) {
108+ const content = fs . readFileSync ( templatePath , 'utf8' ) ;
109+ const processedContent = processTemplate ( content , config ) ;
110+ const finalContent = addHeaderIfNeeded ( destPath , processedContent ) ;
111+
112+ // Ensure destination directory exists
113+ const destDir = path . dirname ( destPath ) ;
114+ if ( ! fs . existsSync ( destDir ) ) {
115+ fs . mkdirSync ( destDir , { recursive : true } ) ;
116+ }
117+
118+ fs . writeFileSync ( destPath , finalContent ) ;
119+ }
120+
121+ /**
122+ * Copy all templates for a specific version
123+ * @param {string } version - Version number
124+ * @param {object } config - Version configuration
125+ */
126+ function copyTemplatesForVersion ( version , config ) {
127+ const templatesDir = path . join ( __dirname , '..' , 'templates' ) ;
128+ const versionDir = path . join ( __dirname , '..' , 'versions' , version ) ;
129+
130+ // Check if version directory exists
131+ if ( ! fs . existsSync ( versionDir ) ) {
132+ console . warn ( `Warning: Directory ${ versionDir } does not exist. Skipping...` ) ;
133+ return ;
134+ }
135+
136+ // Files to copy
137+ const filesToCopy = [
138+ 'LICENSE' ,
139+ 'Makefile' ,
140+ 'src/index.ts' ,
141+ 'src/libpg-query.d.ts' ,
142+ 'src/wasm_wrapper.c'
143+ ] ;
144+
145+ filesToCopy . forEach ( file => {
146+ const templatePath = path . join ( templatesDir , file ) ;
147+ const destPath = path . join ( versionDir , file ) ;
148+
149+ if ( ! fs . existsSync ( templatePath ) ) {
150+ console . error ( `Error: Template file ${ templatePath } does not exist!` ) ;
151+ return ;
152+ }
153+
154+ copyTemplate ( templatePath , destPath , config ) ;
155+ } ) ;
156+
157+ console . log ( `✓ Version ${ version } completed` ) ;
158+ }
159+
160+ /**
161+ * Main function
162+ */
163+ function main ( ) {
164+ console . log ( 'Copying template files to version directories...\n' ) ;
165+
166+ // Process each version
167+ Object . entries ( VERSION_CONFIGS ) . forEach ( ( [ version , config ] ) => {
168+ console . log ( `Processing version ${ version } ...` ) ;
169+ copyTemplatesForVersion ( version , config ) ;
170+ } ) ;
171+
172+ console . log ( '\nAll versions processed successfully!' ) ;
173+ }
174+
175+ // Run if called directly
176+ if ( require . main === module ) {
177+ main ( ) ;
178+ }
179+
180+ module . exports = { processTemplate, copyTemplatesForVersion } ;
0 commit comments