diff --git a/packages/pglite/src/interface.ts b/packages/pglite/src/interface.ts index 58a94b61..46b1ca8d 100644 --- a/packages/pglite/src/interface.ts +++ b/packages/pglite/src/interface.ts @@ -91,6 +91,7 @@ export interface PGliteOptions { fsBundle?: Blob | File parsers?: ParserOptions serializers?: SerializerOptions + postgresqlConf?: Record } export type PGliteInterface = diff --git a/packages/pglite/src/pglite.ts b/packages/pglite/src/pglite.ts index 56211494..e3c737b6 100644 --- a/packages/pglite/src/pglite.ts +++ b/packages/pglite/src/pglite.ts @@ -419,6 +419,8 @@ export class PGlite 'INITDB created a new datadir, but an alternative db/user was requested', ) } + // time to mark extensions that need special treatment on startup. + if (options.postgresqlConf) this.updateConf(options.postgresqlConf) } } @@ -777,4 +779,52 @@ export class PGlite _runExclusiveTransaction(fn: () => Promise): Promise { return this.#transactionMutex.runExclusive(fn) } + + /** + * Update the PostgreSQL configuration file with the provided key-value pairs. + * @param config Key-value pairs to update in the configuration. + */ + async updateConf(config: Record) { + const codec = new TextDecoder() + const configPath = `${PGDATA}/postgresql.conf` + const lines = codec.decode(this.mod!.FS.readFile(configPath)).split('\n') + + const updatedLines = new Set() + const newLines: string[] = [] + + for (const [key, value] of Object.entries(config)) { + const existingLineIndex = lines.findIndex((line) => line.startsWith(key)) + // TODO: In future we may want to extract the array from the existing line + // and merge it with the new value. + const newValue = Array.isArray(value) ? value.join(',') : value.toString() + const newLine = `${key} = ${newValue}` + + if (existingLineIndex !== -1) { + const oldLine = lines[existingLineIndex] + if (oldLine !== newLine) { + this.#log('postgresql.conf edited line:', oldLine, '->', newLine) + lines[existingLineIndex] = newLine + } else { + this.#log('postgresql.conf unchanged line:', newLine) + } + updatedLines.add(newLine) + } else { + this.#log('postgresql.conf new line:', newLine) + newLines.push(newLine) + } + } + + if (newLines.length > 0 || updatedLines.size > 0) { + const finalLines = lines + .filter((line) => !updatedLines.has(line)) + .concat(newLines) + this.mod!.FS.writeFile(configPath, finalLines.join('\n')) + this.mod!.FS.syncfs(false, (error) => { + if (error) { + this.#log('updateConf error:', error) + throw error + } + }) + } + } }