/ node_modules / pg-protocol / dist / serializer.js
serializer.js
  1  "use strict";
  2  Object.defineProperty(exports, "__esModule", { value: true });
  3  exports.serialize = void 0;
  4  const buffer_writer_1 = require("./buffer-writer");
  5  const writer = new buffer_writer_1.Writer();
  6  const startup = (opts) => {
  7      // protocol version
  8      writer.addInt16(3).addInt16(0);
  9      for (const key of Object.keys(opts)) {
 10          writer.addCString(key).addCString(opts[key]);
 11      }
 12      writer.addCString('client_encoding').addCString('UTF8');
 13      const bodyBuffer = writer.addCString('').flush();
 14      // this message is sent without a code
 15      const length = bodyBuffer.length + 4;
 16      return new buffer_writer_1.Writer().addInt32(length).add(bodyBuffer).flush();
 17  };
 18  const requestSsl = () => {
 19      const response = Buffer.allocUnsafe(8);
 20      response.writeInt32BE(8, 0);
 21      response.writeInt32BE(80877103, 4);
 22      return response;
 23  };
 24  const password = (password) => {
 25      return writer.addCString(password).flush(112 /* code.startup */);
 26  };
 27  const sendSASLInitialResponseMessage = function (mechanism, initialResponse) {
 28      // 0x70 = 'p'
 29      writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse);
 30      return writer.flush(112 /* code.startup */);
 31  };
 32  const sendSCRAMClientFinalMessage = function (additionalData) {
 33      return writer.addString(additionalData).flush(112 /* code.startup */);
 34  };
 35  const query = (text) => {
 36      return writer.addCString(text).flush(81 /* code.query */);
 37  };
 38  const emptyArray = [];
 39  const parse = (query) => {
 40      // expect something like this:
 41      // { name: 'queryName',
 42      //   text: 'select * from blah',
 43      //   types: ['int8', 'bool'] }
 44      // normalize missing query names to allow for null
 45      const name = query.name || '';
 46      if (name.length > 63) {
 47          console.error('Warning! Postgres only supports 63 characters for query names.');
 48          console.error('You supplied %s (%s)', name, name.length);
 49          console.error('This can cause conflicts and silent errors executing queries');
 50      }
 51      const types = query.types || emptyArray;
 52      const len = types.length;
 53      const buffer = writer
 54          .addCString(name) // name of query
 55          .addCString(query.text) // actual query text
 56          .addInt16(len);
 57      for (let i = 0; i < len; i++) {
 58          buffer.addInt32(types[i]);
 59      }
 60      return writer.flush(80 /* code.parse */);
 61  };
 62  const paramWriter = new buffer_writer_1.Writer();
 63  const writeValues = function (values, valueMapper) {
 64      for (let i = 0; i < values.length; i++) {
 65          const mappedVal = valueMapper ? valueMapper(values[i], i) : values[i];
 66          if (mappedVal == null) {
 67              // add the param type (string) to the writer
 68              writer.addInt16(0 /* ParamType.STRING */);
 69              // write -1 to the param writer to indicate null
 70              paramWriter.addInt32(-1);
 71          }
 72          else if (mappedVal instanceof Buffer) {
 73              // add the param type (binary) to the writer
 74              writer.addInt16(1 /* ParamType.BINARY */);
 75              // add the buffer to the param writer
 76              paramWriter.addInt32(mappedVal.length);
 77              paramWriter.add(mappedVal);
 78          }
 79          else {
 80              // add the param type (string) to the writer
 81              writer.addInt16(0 /* ParamType.STRING */);
 82              paramWriter.addInt32(Buffer.byteLength(mappedVal));
 83              paramWriter.addString(mappedVal);
 84          }
 85      }
 86  };
 87  const bind = (config = {}) => {
 88      // normalize config
 89      const portal = config.portal || '';
 90      const statement = config.statement || '';
 91      const binary = config.binary || false;
 92      const values = config.values || emptyArray;
 93      const len = values.length;
 94      writer.addCString(portal).addCString(statement);
 95      writer.addInt16(len);
 96      writeValues(values, config.valueMapper);
 97      writer.addInt16(len);
 98      writer.add(paramWriter.flush());
 99      // all results use the same format code
100      writer.addInt16(1);
101      // format code
102      writer.addInt16(binary ? 1 /* ParamType.BINARY */ : 0 /* ParamType.STRING */);
103      return writer.flush(66 /* code.bind */);
104  };
105  const emptyExecute = Buffer.from([69 /* code.execute */, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]);
106  const execute = (config) => {
107      // this is the happy path for most queries
108      if (!config || (!config.portal && !config.rows)) {
109          return emptyExecute;
110      }
111      const portal = config.portal || '';
112      const rows = config.rows || 0;
113      const portalLength = Buffer.byteLength(portal);
114      const len = 4 + portalLength + 1 + 4;
115      // one extra bit for code
116      const buff = Buffer.allocUnsafe(1 + len);
117      buff[0] = 69 /* code.execute */;
118      buff.writeInt32BE(len, 1);
119      buff.write(portal, 5, 'utf-8');
120      buff[portalLength + 5] = 0; // null terminate portal cString
121      buff.writeUInt32BE(rows, buff.length - 4);
122      return buff;
123  };
124  const cancel = (processID, secretKey) => {
125      const buffer = Buffer.allocUnsafe(16);
126      buffer.writeInt32BE(16, 0);
127      buffer.writeInt16BE(1234, 4);
128      buffer.writeInt16BE(5678, 6);
129      buffer.writeInt32BE(processID, 8);
130      buffer.writeInt32BE(secretKey, 12);
131      return buffer;
132  };
133  const cstringMessage = (code, string) => {
134      const stringLen = Buffer.byteLength(string);
135      const len = 4 + stringLen + 1;
136      // one extra bit for code
137      const buffer = Buffer.allocUnsafe(1 + len);
138      buffer[0] = code;
139      buffer.writeInt32BE(len, 1);
140      buffer.write(string, 5, 'utf-8');
141      buffer[len] = 0; // null terminate cString
142      return buffer;
143  };
144  const emptyDescribePortal = writer.addCString('P').flush(68 /* code.describe */);
145  const emptyDescribeStatement = writer.addCString('S').flush(68 /* code.describe */);
146  const describe = (msg) => {
147      return msg.name
148          ? cstringMessage(68 /* code.describe */, `${msg.type}${msg.name || ''}`)
149          : msg.type === 'P'
150              ? emptyDescribePortal
151              : emptyDescribeStatement;
152  };
153  const close = (msg) => {
154      const text = `${msg.type}${msg.name || ''}`;
155      return cstringMessage(67 /* code.close */, text);
156  };
157  const copyData = (chunk) => {
158      return writer.add(chunk).flush(100 /* code.copyFromChunk */);
159  };
160  const copyFail = (message) => {
161      return cstringMessage(102 /* code.copyFail */, message);
162  };
163  const codeOnlyBuffer = (code) => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]);
164  const flushBuffer = codeOnlyBuffer(72 /* code.flush */);
165  const syncBuffer = codeOnlyBuffer(83 /* code.sync */);
166  const endBuffer = codeOnlyBuffer(88 /* code.end */);
167  const copyDoneBuffer = codeOnlyBuffer(99 /* code.copyDone */);
168  const serialize = {
169      startup,
170      password,
171      requestSsl,
172      sendSASLInitialResponseMessage,
173      sendSCRAMClientFinalMessage,
174      query,
175      parse,
176      bind,
177      execute,
178      describe,
179      close,
180      flush: () => flushBuffer,
181      sync: () => syncBuffer,
182      end: () => endBuffer,
183      copyData,
184      copyDone: () => copyDoneBuffer,
185      copyFail,
186      cancel,
187  };
188  exports.serialize = serialize;
189  //# sourceMappingURL=serializer.js.map