@ultipa-graph/ultipa-driver
Version:
NodeJS SDK for Ultipa GQL
867 lines • 115 kB
JavaScript
"use strict";
/**
* Response handling for GQLDB Node.js driver.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Response = exports.AliasResult = exports.Row = void 0;
const types_1 = require("./types");
/**
* Represents a single row in the query result.
*
* Positional access via `row.get(i)` is always available. Name-based
* access via `row.getByName(name)` / `row.has(name)` requires the parent
* Response to have populated {@link Row.columnNames} (Response's
* constructor does this automatically).
*
* The row is iterable — `for (const v of row) ...` yields decoded
* column values (same as repeated `row.get(i)`).
*/
class Row {
values;
types;
/**
* Column names for name-based access. Injected by the parent Response
* constructor so that `row.getByName('col')` works without going
* through Response.getByName(row, 'col').
*/
columnNames = [];
constructor(values, types = []) {
this.values = values;
this.types = types;
}
/** Get the value at the given column index */
get(index) {
if (index < 0 || index >= this.values.length) {
throw new Error(`Column index out of range: ${index}`);
}
const value = this.values[index];
// If value is a TypedValue object, convert it
if (value && typeof value === 'object' && 'type' in value && 'data' in value && 'isNull' in value) {
return (0, types_1.typedValueToJS)(value);
}
return value;
}
/**
* Get the value for the given column name. Requires `columnNames` to
* have been populated by the parent Response.
*/
getByName(name) {
if (this.columnNames.length === 0) {
throw new Error(`Row columnNames not populated; cannot look up '${name}' by name`);
}
const idx = this.columnNames.indexOf(name);
if (idx < 0) {
throw new Error(`Column not found: ${name}; available: ${this.columnNames.join(', ')}`);
}
return this.get(idx);
}
/** Returns true if this row knows the given column name. */
has(name) {
return this.columnNames.indexOf(name) >= 0;
}
/** Number of columns in this row. */
get length() {
return this.values.length;
}
/** Iterate over decoded column values. */
*[Symbol.iterator]() {
for (let i = 0; i < this.values.length; i++) {
yield this.get(i);
}
}
/**
* Formatted representation. When `columnNames` is populated:
* `Row(name1=value1, name2=value2)`
* Otherwise:
* `Row(value0, value1)`
* Mirrors the Python driver's `repr(row)` layout.
*/
toString() {
const parts = [];
for (let i = 0; i < this.values.length; i++) {
const v = this.get(i);
const formatted = typeof v === 'string' ? `'${v}'` : String(v);
if (i < this.columnNames.length) {
parts.push(`${this.columnNames[i]}=${formatted}`);
}
else {
parts.push(formatted);
}
}
return `Row(${parts.join(', ')})`;
}
/**
* Structural equality: same column names (or both empty) AND decoded
* column values compare equal pairwise. Mirrors Python `Row.__eq__`.
* Uses JSON.stringify for nested value comparison — adequate for the
* primitive/object types decoded from the wire.
*/
equals(other) {
if (this === other)
return true;
if (!(other instanceof Row))
return false;
if (this.columnNames.length !== other.columnNames.length)
return false;
for (let i = 0; i < this.columnNames.length; i++) {
if (this.columnNames[i] !== other.columnNames[i])
return false;
}
if (this.values.length !== other.values.length)
return false;
for (let i = 0; i < this.values.length; i++) {
const a = this.get(i);
const b = other.get(i);
if (a === b)
continue;
if (a !== a && b !== b)
continue; // NaN === NaN
if (typeof a !== typeof b)
return false;
if (typeof a === 'object' && a !== null && b !== null) {
if (JSON.stringify(a) !== JSON.stringify(b))
return false;
}
else {
return false;
}
}
return true;
}
/** Get the PropertyType at the given column index */
getType(index) {
if (index < 0 || index >= this.types.length) {
return types_1.PropertyType.UNSET;
}
return this.types[index];
}
/** Get the value at the given column index as a string */
getString(index) {
const val = this.get(index);
if (val === null || val === undefined)
return '';
if (typeof val === 'string')
return val;
return String(val);
}
/** Get the value at the given column index as a number */
getNumber(index) {
const val = this.get(index);
if (val === null || val === undefined)
return 0;
if (typeof val === 'number')
return val;
const num = Number(val);
if (isNaN(num))
throw new Error(`Cannot convert ${typeof val} to number`);
return num;
}
/** Get the value at the given column index as a boolean */
getBoolean(index) {
const val = this.get(index);
if (val === null || val === undefined)
return false;
if (typeof val === 'boolean')
return val;
throw new Error(`Cannot convert ${typeof val} to boolean`);
}
}
exports.Row = Row;
/**
* Represents a single column's data from the response.
* Allows chaining operations like resp.alias("n").asNodes() or resp.get(0).asNodes().
*/
class AliasResult {
aliasName;
columnIdx;
response;
constructor(aliasName, columnIdx, response) {
this.aliasName = aliasName;
this.columnIdx = columnIdx;
this.response = response;
}
/** Get the alias name */
get alias() {
return this.aliasName;
}
/** Get the column index */
get columnIndex() {
return this.columnIdx;
}
/**
* Extract nodes from the aliased column with schema info.
* Throws TypeError if the column contains non-NODE types.
*/
collectNode(val, nodes, schemas) {
if (val && typeof val.id === 'string' && 'labels' in val) {
const node = {
id: val.id,
labels: val.labels || [],
properties: val.properties || {},
};
nodes.push(node);
for (const label of node.labels) {
if (!schemas.has(label)) {
schemas.set(label, this.buildSchemaFromNode(label, node));
}
}
}
}
collectEdge(val, edges, schemas) {
if (val && typeof val.id === 'string' && 'label' in val) {
const edge = {
id: val.id,
label: val.label || '',
fromNodeId: val.fromNodeId || '',
toNodeId: val.toNodeId || '',
properties: val.properties || {},
};
edges.push(edge);
if (edge.label && !schemas.has(edge.label)) {
schemas.set(edge.label, this.buildSchemaFromEdge(edge.label, edge));
}
}
}
/**
* Extract nodes from the aliased column with schema info.
* Supports both direct NODE columns and LIST of NODE columns
* (e.g., group variables from quantified patterns).
*/
asNodes() {
const nodes = [];
const schemas = new Map();
for (const row of this.response.rows) {
if (this.columnIdx >= row.values.length) {
continue;
}
let itemType = row.getType(this.columnIdx);
const rawValue = row.values[this.columnIdx];
if (itemType === types_1.PropertyType.UNSET && rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
itemType = rawValue.type;
}
if (!rawValue || (typeof rawValue === 'object' && 'isNull' in rawValue && rawValue.isNull)) {
continue;
}
if (itemType === types_1.PropertyType.NODE) {
this.collectNode(row.get(this.columnIdx), nodes, schemas);
}
else if (itemType === types_1.PropertyType.LIST) {
// LIST of NODE (group variable from quantified pattern)
const list = row.get(this.columnIdx);
if (Array.isArray(list)) {
for (const item of list) {
this.collectNode(item, nodes, schemas);
}
}
}
else {
throw new TypeError(`Type mismatch: column '${this.aliasName}' (index ${this.columnIdx}) contains ${types_1.PropertyType[itemType]}, expected NODE or LIST of NODE`);
}
}
return { nodes, schemas };
}
/**
* Extract edges from the aliased column with schema info.
* Supports both direct EDGE columns and LIST of EDGE columns
* (e.g., group variables from quantified patterns).
*/
asEdges() {
const edges = [];
const schemas = new Map();
for (const row of this.response.rows) {
if (this.columnIdx >= row.values.length) {
continue;
}
let itemType = row.getType(this.columnIdx);
const rawValue = row.values[this.columnIdx];
if (itemType === types_1.PropertyType.UNSET && rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
itemType = rawValue.type;
}
if (!rawValue || (typeof rawValue === 'object' && 'isNull' in rawValue && rawValue.isNull)) {
continue;
}
if (itemType === types_1.PropertyType.EDGE) {
this.collectEdge(row.get(this.columnIdx), edges, schemas);
}
else if (itemType === types_1.PropertyType.LIST) {
// LIST of EDGE (group variable from quantified pattern)
const list = row.get(this.columnIdx);
if (Array.isArray(list)) {
for (const item of list) {
this.collectEdge(item, edges, schemas);
}
}
}
else {
throw new TypeError(`Type mismatch: column '${this.aliasName}' (index ${this.columnIdx}) contains ${types_1.PropertyType[itemType]}, expected EDGE or LIST of EDGE`);
}
}
return { edges, schemas };
}
/**
* Extract paths from the aliased column.
* Throws TypeError if the column contains non-PATH types.
*/
asPaths() {
const paths = [];
for (const row of this.response.rows) {
if (this.columnIdx >= row.values.length) {
continue;
}
// Check type from types array or from TypedValue object
let itemType = row.getType(this.columnIdx);
const rawValue = row.values[this.columnIdx];
if (itemType === types_1.PropertyType.UNSET && rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
itemType = rawValue.type;
}
// Skip null values
if (!rawValue || (typeof rawValue === 'object' && 'isNull' in rawValue && rawValue.isNull)) {
continue;
}
// Type checking: must be PATH type
if (itemType !== types_1.PropertyType.PATH) {
throw new TypeError(`Type mismatch: column '${this.aliasName}' (index ${this.columnIdx}) contains ${types_1.PropertyType[itemType]}, expected PATH`);
}
// Convert TypedValue to GqldbPath
const val = row.get(this.columnIdx);
if (val && Array.isArray(val.nodes)) {
// Convert GqldbNode/GqldbEdge to Node/Edge
const nodes = (val.nodes || []).map((n) => ({
id: n.id || '',
labels: n.labels || [],
properties: n.properties || {},
}));
const edges = (val.edges || []).map((e) => ({
id: e.id || '',
label: e.label || '',
fromNodeId: e.fromNodeId || '',
toNodeId: e.toNodeId || '',
properties: e.properties || {},
}));
paths.push({ nodes, edges });
}
}
return paths;
}
/** Convert the aliased column to a single-column table */
asTable() {
// Check if first non-null value is a GqldbTable — if so, unwrap it
for (const row of this.response.rows) {
if (this.columnIdx < row.values.length) {
const itemType = row.getType(this.columnIdx);
if (itemType === types_1.PropertyType.TABLE) {
const val = row.get(this.columnIdx);
if (val && 'columns' in val && 'rows' in val) {
return this.unwrapGqldbTable(val);
}
}
}
break; // only check first row
}
// Fallback: generic single-column table
const headers = [{
name: this.aliasName,
type: types_1.PropertyType.UNSET,
}];
if (this.response.rows.length > 0) {
for (const row of this.response.rows) {
if (this.columnIdx < row.values.length) {
const type = row.getType(this.columnIdx);
if (type !== types_1.PropertyType.UNSET) {
headers[0].type = type;
break;
}
}
}
}
const tableRows = this.response.rows.map(row => {
if (this.columnIdx < row.values.length) {
return [row.get(this.columnIdx)];
}
return [null];
});
return { name: '', headers, rows: tableRows };
}
unwrapGqldbTable(gt) {
const headers = gt.columns.map((col, i) => {
let colType = types_1.PropertyType.UNSET;
if (gt.rows.length > 0 && i < gt.rows[0].length) {
const v = gt.rows[0][i];
if (typeof v === 'number')
colType = Number.isInteger(v) ? types_1.PropertyType.INT64 : types_1.PropertyType.DOUBLE;
else if (typeof v === 'string')
colType = types_1.PropertyType.STRING;
else if (typeof v === 'boolean')
colType = types_1.PropertyType.BOOL;
}
return { name: col, type: colType };
});
return { name: this.aliasName, headers, rows: gt.rows };
}
/** Extract scalar or list attribute values from the aliased column */
asAttr() {
const values = [];
let attrType = types_1.PropertyType.UNSET;
for (const row of this.response.rows) {
if (this.columnIdx < row.values.length) {
// Try to get type from row.types first, then from TypedValue object
if (attrType === types_1.PropertyType.UNSET) {
attrType = row.getType(this.columnIdx);
if (attrType === types_1.PropertyType.UNSET) {
const rawValue = row.values[this.columnIdx];
if (rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
attrType = rawValue.type;
}
}
}
const value = row.get(this.columnIdx); // Use get() to convert TypedValue
values.push(value);
}
}
return { name: this.aliasName, type: attrType, values };
}
/** Extract raw JavaScript values from the aliased column */
asValues() {
const values = [];
for (const row of this.response.rows) {
if (this.columnIdx < row.values.length) {
values.push(row.get(this.columnIdx));
}
}
return values;
}
// Helper methods
buildSchemaFromNode(label, node) {
const properties = Object.entries(node.properties).map(([name, value]) => ({
name,
type: this.inferPropertyType(value),
}));
return { name: label, properties };
}
buildSchemaFromEdge(label, edge) {
const properties = Object.entries(edge.properties).map(([name, value]) => ({
name,
type: this.inferPropertyType(value),
}));
return { name: label, properties };
}
inferPropertyType(value) {
if (value === null || value === undefined)
return types_1.PropertyType.NULL;
if (typeof value === 'boolean')
return types_1.PropertyType.BOOL;
if (typeof value === 'number') {
return Number.isInteger(value) ? types_1.PropertyType.INT64 : types_1.PropertyType.DOUBLE;
}
if (typeof value === 'string')
return types_1.PropertyType.STRING;
if (Buffer.isBuffer(value))
return types_1.PropertyType.BLOB;
if (Array.isArray(value))
return types_1.PropertyType.LIST;
if (typeof value === 'object')
return types_1.PropertyType.MAP;
return types_1.PropertyType.UNSET;
}
}
exports.AliasResult = AliasResult;
/** Represents the result of a GQL query */
class Response {
columns;
rows;
rowCount;
hasMore;
warnings;
rowsAffected;
currentGraph;
timeCostNs;
diskCostNs;
computeCostNs;
constructor(columns, rows, rowCount, hasMore, warnings, rowsAffected = 0,
/**
* Session's current graph after this RPC executed, as authoritatively
* reported by the server. Always populated on success against new
* servers (covers single/compound USE GRAPH at any position,
* last-write-wins). Empty when running against a pre-fix server, in
* which case the driver falls back to its USE GRAPH text-parsing path
* internally to keep the local default-graph cache in sync.
*/
currentGraph = '',
/**
* Server-side timing (nanoseconds), read from the engine's ResultSet.
* Network / client-side time is NOT included.
* - timeCostNs: total wall-clock parse + plan + execute
* - diskCostNs: subset spent in storage / LSM layer
* - computeCostNs: subset spent in the in-memory compute engine
* (k-hop, shortest path, algo.* via topology
* accelerator); 0 when compute is disabled or
* the query path did not invoke the accelerator.
* Old servers omit these proto3 fields → treat 0 as "not reported",
* not "took zero time". Streaming queries populate only on the
* final batch (hasMore=false), matching currentGraph / rowsAffected.
*/
timeCostNs = 0, diskCostNs = 0, computeCostNs = 0) {
this.columns = columns;
this.rows = rows;
this.rowCount = rowCount;
this.hasMore = hasMore;
this.warnings = warnings;
this.rowsAffected = rowsAffected;
this.currentGraph = currentGraph;
this.timeCostNs = timeCostNs;
this.diskCostNs = diskCostNs;
this.computeCostNs = computeCostNs;
// Push column names into each Row so name-based access (row.getByName)
// works without going through Response.getByName(row, ...). Matches
// Python's Response.__post_init__ behavior.
if (this.columns.length > 0) {
for (const row of this.rows) {
if (row && row.columnNames.length === 0) {
row.columnNames = this.columns;
}
}
}
}
/** Check if the response has no rows */
isEmpty() {
return this.rows.length === 0;
}
/** Get the first row */
first() {
return this.rows[0];
}
/** Get the last row */
last() {
return this.rows[this.rows.length - 1];
}
/** Get the value for a column by name */
getByName(row, columnName) {
const index = this.columns.indexOf(columnName);
if (index === -1) {
throw new Error(`Column not found: ${columnName}`);
}
return row.get(index);
}
/** Iterate over all rows with a callback */
forEach(fn) {
this.rows.forEach(fn);
}
/** Transform each row using a callback */
map(fn) {
return this.rows.map(fn);
}
/** Convert the response to an array of objects */
toObjects() {
return this.rows.map(row => {
const obj = {};
this.columns.forEach((col, i) => {
// Add boundary check to handle mismatched columns/values
obj[col] = i < row.values.length ? row.get(i) : null;
});
return obj;
});
}
/** Convert the response to JSON */
toJSON() {
return JSON.stringify(this.toObjects());
}
/** Get the single value from a single-row, single-column response */
singleValue() {
if (this.rows.length === 0)
return null;
if (this.rows.length > 1) {
throw new Error(`Expected single row, got ${this.rows.length}`);
}
if (this.rows[0].values.length === 0)
return null;
if (this.rows[0].values.length > 1) {
throw new Error(`Expected single column, got ${this.rows[0].values.length}`);
}
return this.rows[0].get(0);
}
/** Get the single number value */
singleNumber() {
const val = this.singleValue();
if (val === null || val === undefined)
return 0;
if (typeof val === 'number')
return val;
const num = Number(val);
if (isNaN(num))
throw new Error(`Cannot convert ${typeof val} to number`);
return num;
}
/** Get the single string value */
singleString() {
const val = this.singleValue();
if (val === null || val === undefined)
return '';
if (typeof val === 'string')
return val;
return String(val);
}
/** Iterator support */
[Symbol.iterator]() {
return this.rows[Symbol.iterator]();
}
/** Get the number of rows */
get length() {
return this.rows.length;
}
/**
* Get an AliasResult for the specified column name.
* Use this to extract data from a specific column by name.
* Example: resp.alias("n").asNodes()
*/
alias(columnName) {
const colIdx = this.columns.indexOf(columnName);
if (colIdx === -1) {
throw new Error(`Column alias not found: ${columnName}`);
}
return new AliasResult(columnName, colIdx, this);
}
/**
* Get an AliasResult for the column at the specified index.
* Use this to extract data from a specific column by index.
* Example: resp.get(0).asNodes()
*/
get(index) {
if (index < 0 || index >= this.columns.length) {
throw new Error(`Column index out of range: ${index} (total: ${this.columns.length})`);
}
return new AliasResult(this.columns[index], index, this);
}
/**
* @deprecated Use alias() or get() instead. This method will be removed in a future version.
* Extract nodes from response with schema info.
* Supports both NODE and LIST of NODE columns.
*/
asNodes() {
const nodes = [];
const schemas = new Map();
const collectNode = (val) => {
if (val && typeof val.id === 'string' && 'labels' in val) {
const node = {
id: val.id,
labels: val.labels || [],
properties: val.properties || {},
};
nodes.push(node);
for (const label of node.labels) {
if (!schemas.has(label)) {
schemas.set(label, this.buildSchemaFromNode(label, node));
}
}
}
};
for (const row of this.rows) {
for (let i = 0; i < row.values.length; i++) {
let itemType = row.getType(i);
const rawValue = row.values[i];
if (itemType === types_1.PropertyType.UNSET && rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
itemType = rawValue.type;
}
if (itemType === types_1.PropertyType.NODE) {
collectNode(row.get(i));
}
else if (itemType === types_1.PropertyType.LIST) {
const list = row.get(i);
if (Array.isArray(list)) {
for (const item of list) {
collectNode(item);
}
}
}
}
}
return { nodes, schemas };
}
/**
* @deprecated Use alias() or get() instead. This method will be removed in a future version.
* Extract edges from response with schema info.
* Supports both EDGE and LIST of EDGE columns.
*/
asEdges() {
const edges = [];
const schemas = new Map();
const collectEdge = (val) => {
if (val && typeof val.id === 'string' && 'label' in val) {
const edge = {
id: val.id,
label: val.label || '',
fromNodeId: val.fromNodeId || '',
toNodeId: val.toNodeId || '',
properties: val.properties || {},
};
edges.push(edge);
if (edge.label && !schemas.has(edge.label)) {
schemas.set(edge.label, this.buildSchemaFromEdge(edge.label, edge));
}
}
};
for (const row of this.rows) {
for (let i = 0; i < row.values.length; i++) {
let itemType = row.getType(i);
const rawValue = row.values[i];
if (itemType === types_1.PropertyType.UNSET && rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
itemType = rawValue.type;
}
if (itemType === types_1.PropertyType.EDGE) {
collectEdge(row.get(i));
}
else if (itemType === types_1.PropertyType.LIST) {
const list = row.get(i);
if (Array.isArray(list)) {
for (const item of list) {
collectEdge(item);
}
}
}
}
}
return { edges, schemas };
}
/**
* @deprecated Use alias() or get() instead. This method will be removed in a future version.
* Extract paths from response.
* Paths are identified by PropertyType.PATH type in the TypedValue.
*/
asPaths() {
const paths = [];
for (const row of this.rows) {
for (let i = 0; i < row.values.length; i++) {
// Check type from types array or from TypedValue object
let itemType = row.getType(i);
const rawValue = row.values[i];
if (itemType === types_1.PropertyType.UNSET && rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
itemType = rawValue.type;
}
if (itemType === types_1.PropertyType.PATH) {
// Convert TypedValue to GqldbPath
const val = row.get(i);
if (val && Array.isArray(val.nodes)) {
// Convert GqldbNode/GqldbEdge to Node/Edge
const nodes = (val.nodes || []).map((n) => ({
id: n.id || '',
labels: n.labels || [],
properties: n.properties || {},
}));
const edges = (val.edges || []).map((e) => ({
id: e.id || '',
label: e.label || '',
fromNodeId: e.fromNodeId || '',
toNodeId: e.toNodeId || '',
properties: e.properties || {},
}));
paths.push({ nodes, edges });
}
}
}
}
return paths;
}
/**
* @deprecated Use alias() or get() instead. This method will be removed in a future version.
* Return response as generic table.
* If response is a single TABLE column, unwraps the GqldbTable into proper headers/rows.
*/
asTable() {
// If single column of TABLE type, unwrap GqldbTable
if (this.columns.length === 1 && this.rows.length > 0) {
const itemType = this.rows[0].getType(0);
if (itemType === types_1.PropertyType.TABLE) {
const val = this.rows[0].get(0);
if (val && 'columns' in val && 'rows' in val) {
const gt = val;
const headers = gt.columns.map((col, i) => {
let colType = types_1.PropertyType.UNSET;
if (gt.rows.length > 0 && i < gt.rows[0].length) {
const v = gt.rows[0][i];
if (typeof v === 'number')
colType = Number.isInteger(v) ? types_1.PropertyType.INT64 : types_1.PropertyType.DOUBLE;
else if (typeof v === 'string')
colType = types_1.PropertyType.STRING;
else if (typeof v === 'boolean')
colType = types_1.PropertyType.BOOL;
}
return { name: col, type: colType };
});
return { name: this.columns[0], headers, rows: gt.rows };
}
}
}
// Fallback: generic multi-column table
const headers = this.columns.map(col => ({
name: col,
type: types_1.PropertyType.UNSET,
}));
const tableRows = this.rows.map(row => {
return this.columns.map((_, i) => (i < row.values.length ? row.get(i) : null));
});
return { name: '', headers, rows: tableRows };
}
/**
* @deprecated Use alias() or get() instead. This method will be removed in a future version.
* Extract scalar or list attribute values
*/
asAttr(columnName) {
const colIndex = this.columns.indexOf(columnName);
if (colIndex === -1) {
throw new Error(`Column not found: ${columnName}`);
}
const values = [];
let attrType = types_1.PropertyType.UNSET;
for (const row of this.rows) {
if (colIndex < row.values.length) {
// Try to get type from row.types first, then from TypedValue object
if (attrType === types_1.PropertyType.UNSET) {
attrType = row.getType(colIndex);
if (attrType === types_1.PropertyType.UNSET) {
const rawValue = row.values[colIndex];
if (rawValue && typeof rawValue === 'object' && 'type' in rawValue) {
attrType = rawValue.type;
}
}
}
const value = row.get(colIndex); // Use get() to convert TypedValue
values.push(value);
}
}
return { name: columnName, type: attrType, values };
}
// Helper methods
buildSchemaFromNode(label, node) {
const properties = Object.entries(node.properties).map(([name, value]) => ({
name,
type: this.inferPropertyType(value),
}));
return { name: label, properties };
}
buildSchemaFromEdge(label, edge) {
const properties = Object.entries(edge.properties).map(([name, value]) => ({
name,
type: this.inferPropertyType(value),
}));
return { name: label, properties };
}
inferPropertyType(value) {
if (value === null || value === undefined)
return types_1.PropertyType.NULL;
if (typeof value === 'boolean')
return types_1.PropertyType.BOOL;
if (typeof value === 'number') {
return Number.isInteger(value) ? types_1.PropertyType.INT64 : types_1.PropertyType.DOUBLE;
}
if (typeof value === 'string')
return types_1.PropertyType.STRING;
if (Buffer.isBuffer(value))
return types_1.PropertyType.BLOB;
if (Array.isArray(value))
return types_1.PropertyType.LIST;
if (typeof value === 'object')
return types_1.PropertyType.MAP;
return types_1.PropertyType.UNSET;
}
}
exports.Response = Response;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcmVzcG9uc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHOzs7QUFFSCxtQ0FBOEk7QUFFOUk7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQWEsR0FBRztJQVNJO0lBQ0E7SUFUbEI7Ozs7T0FJRztJQUNILFdBQVcsR0FBc0IsRUFBRSxDQUFDO0lBRXBDLFlBQ2tCLE1BQWEsRUFDYixRQUF3QixFQUFFO1FBRDFCLFdBQU0sR0FBTixNQUFNLENBQU87UUFDYixVQUFLLEdBQUwsS0FBSyxDQUFxQjtJQUN6QyxDQUFDO0lBRUosOENBQThDO0lBQzlDLEdBQUcsQ0FBQyxLQUFhO1FBQ2YsSUFBSSxLQUFLLEdBQUcsQ0FBQyxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzdDLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekQsQ0FBQztRQUNELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakMsOENBQThDO1FBQzlDLElBQUksS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxNQUFNLElBQUksS0FBSyxJQUFJLE1BQU0sSUFBSSxLQUFLLElBQUksUUFBUSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ2xHLE9BQU8sSUFBQSxzQkFBYyxFQUFDLEtBQW1CLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsU0FBUyxDQUFDLElBQVk7UUFDcEIsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxJQUFJLFdBQVcsQ0FBQyxDQUFDO1FBQ3JGLENBQUM7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