From 2aaf1faff719ad68c5214c0e2440b192c5940953 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Thu, 11 Mar 2021 15:11:42 -0800 Subject: [PATCH 1/2] [pg-protocol] patch out the const enum in messages.d.ts --- packages/pg-protocol/package.json | 2 +- .../script/remove-public-const-enum.js | 93 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 packages/pg-protocol/script/remove-public-const-enum.js diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 05f74ae10..c3595e853 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -17,7 +17,7 @@ }, "scripts": { "test": "mocha dist/**/*.test.js", - "build": "tsc", + "build": "tsc && node script/remove-public-const-enum.js", "build:watch": "tsc --watch", "prepublish": "yarn build", "pretest": "yarn build" diff --git a/packages/pg-protocol/script/remove-public-const-enum.js b/packages/pg-protocol/script/remove-public-const-enum.js new file mode 100644 index 000000000..649f45a2a --- /dev/null +++ b/packages/pg-protocol/script/remove-public-const-enum.js @@ -0,0 +1,93 @@ +// This task would be better served by recast or something like that. +// https://github.com/travellocal/babel-plugin-declare-const-enum is a good starting point for that. + +const fs = require('fs') +const path = require('path') + +const filepath = path.join(__dirname, '../dist/messages.d.ts') +const backuppath = path.join(__dirname, '../dist/messages.const-enum.d.ts') +/** @type {string} */ +let srcpath +// use the filepath if it's newer +try { + const backupStat = fs.statSync(backuppath) + const fileStat = fs.statSync(filepath) + srcpath = fileStat.mtimeMs > backupStat.mtimeMs ? filepath : backuppath +} catch (err) { + if (err.code !== 'ENOENT') { + throw err + } + srcpath = filepath +} +const src = fs.readFileSync(srcpath, 'utf8') +if (srcpath === filepath) { + fs.writeFileSync(backuppath, src, 'utf8') +} + +/** @type {({startIndex: number, endIndex: number, content: string})[]} */ +let replacements = [] + +// find the const enum declarations +const startRe = /(^|\n)export declare const enum ([A-Za-z][A-Za-z0-9]+) \{\n*/g +const endRe = /\n\}/g + +const constEnums = {} + +/** @type {RegExpExecArray | null} */ +let match +while ((match = startRe.exec(src))) { + const startIndex = match.index + const name = match[2] + const contentStartIndex = (endRe.lastIndex = startRe.lastIndex) + const end = endRe.exec(src) + if (!end) break + const contentEndIndex = end.index + const endIndex = (startRe.lastIndex = endRe.lastIndex) + + // collect the members of the const enum + const constEnumContent = src.slice(contentStartIndex, contentEndIndex) + const itemRe = /\b([A-Za-z][A-Za-z0-9]+)\s*=\s*(.+),/g + const lastRe = /\b([A-Za-z][A-Za-z0-9]+)\s*=\s*(.+)/g + + const enumItems = (constEnums[name] = {}) + const enumValueLiterals = [] + + /** @type {RegExpExecArray | null} */ + let itemMatch + while ((itemMatch = itemRe.exec(constEnumContent))) { + enumValueLiterals.push((enumItems[itemMatch[1]] = itemMatch[2])) + lastRe.lastIndex = itemRe.lastIndex + } + itemMatch = lastRe.exec(constEnumContent) + if (itemMatch) { + enumValueLiterals.push((enumItems[itemMatch[1]] = itemMatch[2])) + } + + replacements.push({ + startIndex, + endIndex, + content: `${match[1]}export type ${name} =\n${enumValueLiterals.map((s) => ` | ${s}`).join('\n')};`, + }) +} + +if (replacements.length > 0) { + // replace the const enum declarations with a literal type union + let out = replacements + .sort((a, b) => a.startIndex - b.startIndex) + .reduce((out, { endIndex, content }, i, r) => { + const next = r[i + 1] + return out + content + src.slice(endIndex, next && next.startIndex) + }, src.slice(0, replacements[0].startIndex)) + + // replace references to the enum with the literals + for (const enumName of Object.keys(constEnums)) { + const enumItems = constEnums[enumName] + const re = new RegExp(`\\b${enumName}\\.(${Object.keys(enumItems).join('|')})\\b`, 'g') + + out = out.replace(re, (s, enumItemName) => enumItems[enumItemName]) + } + + fs.writeFileSync(filepath, out, 'utf8') + const now = new Date() + fs.utimesSync(backuppath, now, now) +} From e82ddaf54f4a9567813f5b95037f35e3a4022c7c Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Thu, 11 Mar 2021 15:36:27 -0800 Subject: [PATCH 2/2] [pg-protocol] add option to const enum script to change src files --- .../script/remove-public-const-enum.js | 61 +++++++++++++------ 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/packages/pg-protocol/script/remove-public-const-enum.js b/packages/pg-protocol/script/remove-public-const-enum.js index 649f45a2a..d8536df90 100644 --- a/packages/pg-protocol/script/remove-public-const-enum.js +++ b/packages/pg-protocol/script/remove-public-const-enum.js @@ -4,31 +4,39 @@ const fs = require('fs') const path = require('path') -const filepath = path.join(__dirname, '../dist/messages.d.ts') -const backuppath = path.join(__dirname, '../dist/messages.const-enum.d.ts') +const PATCH_SOURCE = process.argv.slice(2).indexOf('--src') >= 0 +const filepath = path.join(__dirname, PATCH_SOURCE ? '../src/messages.ts' : '../dist/messages.d.ts') +const backuppath = path.join( + __dirname, + PATCH_SOURCE ? '../src/messages.const-enum.ts' : '../dist/messages.const-enum.d.ts' +) +const otherfiles = ['../src/parser.ts'] /** @type {string} */ let srcpath -// use the filepath if it's newer -try { - const backupStat = fs.statSync(backuppath) - const fileStat = fs.statSync(filepath) - srcpath = fileStat.mtimeMs > backupStat.mtimeMs ? filepath : backuppath -} catch (err) { - if (err.code !== 'ENOENT') { - throw err - } +if (PATCH_SOURCE) { srcpath = filepath +} else { + // use the filepath if it's newer + try { + const backupStat = fs.statSync(backuppath) + const fileStat = fs.statSync(filepath) + srcpath = fileStat.mtimeMs > backupStat.mtimeMs ? filepath : backuppath + } catch (err) { + if (err.code !== 'ENOENT') { + throw err + } + srcpath = filepath + } } const src = fs.readFileSync(srcpath, 'utf8') -if (srcpath === filepath) { - fs.writeFileSync(backuppath, src, 'utf8') -} /** @type {({startIndex: number, endIndex: number, content: string})[]} */ let replacements = [] // find the const enum declarations -const startRe = /(^|\n)export declare const enum ([A-Za-z][A-Za-z0-9]+) \{\n*/g +const startRe = PATCH_SOURCE + ? /(^|\n)export const enum ([A-Za-z][A-Za-z0-9]+) \{\n*/g + : /(^|\n)export declare const enum ([A-Za-z][A-Za-z0-9]+) \{\n*/g const endRe = /\n\}/g const constEnums = {} @@ -87,7 +95,26 @@ if (replacements.length > 0) { out = out.replace(re, (s, enumItemName) => enumItems[enumItemName]) } + if (!PATCH_SOURCE && srcpath === filepath) { + fs.writeFileSync(backuppath, src, 'utf8') + } fs.writeFileSync(filepath, out, 'utf8') - const now = new Date() - fs.utimesSync(backuppath, now, now) + if (!PATCH_SOURCE) { + const now = new Date() + fs.utimesSync(backuppath, now, now) + } else { + for (const f of otherfiles) { + const otherfile = path.join(__dirname, f) + + let otherOut = fs.readFileSync(otherfile, 'utf8') + // replace references to the enum with the literals + for (const enumName of Object.keys(constEnums)) { + const enumItems = constEnums[enumName] + const re = new RegExp(`\\b${enumName}\\.(${Object.keys(enumItems).join('|')})\\b`, 'g') + + otherOut = otherOut.replace(re, (s, enumItemName) => enumItems[enumItemName]) + } + fs.writeFileSync(otherfile, otherOut, 'utf8') + } + } }