falkordb 6.3.0 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,7 @@ await graph.query(`CREATE (:Rider {name:'Valentino Rossi'})-[:rides]->(:Team {na
48
48
  (:Rider {name:'Dani Pedrosa'})-[:rides]->(:Team {name:'Honda'}),
49
49
  (:Rider {name:'Andrea Dovizioso'})-[:rides]->(:Team {name:'Ducati'})`)
50
50
 
51
- result = await graph.query(`MATCH (r:Rider)-[:rides]->(t:Team)
51
+ const result = await graph.query(`MATCH (r:Rider)-[:rides]->(t:Team)
52
52
  WHERE t.name = $name RETURN r.name`,
53
53
  {params: {name: 'Yamaha'}})
54
54
 
@@ -3,6 +3,7 @@ import { QueryOptions } from "../commands";
3
3
  import { ConstraintType, EntityType } from "../graph";
4
4
  import FalkorDB from "../falkordb";
5
5
  import { SingleGraphConnection } from "./single";
6
+ import { MemoryUsageOptions, MemoryUsageReply } from "../commands/MEMORY_USAGE";
6
7
  export interface Client {
7
8
  init(falkordb: FalkorDB): Promise<void>;
8
9
  list(): Promise<Array<string>>;
@@ -15,6 +16,7 @@ export interface Client {
15
16
  copy<T>(srcGraph: string, destGraph: string): Promise<any>;
16
17
  delete(graph: string): Promise<void>;
17
18
  explain(graph: string, query: string): Promise<any>;
19
+ memoryUsage(graph: string, options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
18
20
  slowLog(graph: string): Promise<{
19
21
  timestamp: Date;
20
22
  command: string;
@@ -5,6 +5,7 @@ import commands, { QueryOptions } from "../commands";
5
5
  import { RedisClusterType } from "@redis/client";
6
6
  import FalkorDB from "../falkordb";
7
7
  import { SingleGraphConnection } from "./single";
8
+ import { MemoryUsageOptions, MemoryUsageReply } from "../commands/MEMORY_USAGE";
8
9
  export type ClusterGraphConnection = RedisClusterType<{
9
10
  falkordb: typeof commands;
10
11
  }, RedisFunctions, RedisScripts>;
@@ -49,6 +50,7 @@ export declare class Cluster implements Client {
49
50
  query: string;
50
51
  took: number;
51
52
  }[]>;
53
+ memoryUsage(graph: string, options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
52
54
  constraintCreate(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
53
55
  constraintDrop(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
54
56
  profile<_T>(graph: string, query: string): Promise<string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | /*elided*/ any | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined)[] | null | undefined>;
@@ -75,6 +75,9 @@ class Cluster {
75
75
  slowLog(graph) {
76
76
  return this.#client.falkordb.slowLog(graph);
77
77
  }
78
+ async memoryUsage(graph, options) {
79
+ return this.#client.falkordb.memoryUsage(graph, options);
80
+ }
78
81
  async constraintCreate(graph, constraintType, entityType, label, ...properties) {
79
82
  const reply = this.#client.falkordb.constraintCreate(graph, constraintType, entityType, label, ...properties);
80
83
  return reply.then(() => { });
@@ -4,6 +4,7 @@ import FalkorDB from "../falkordb";
4
4
  import { ConstraintType, EntityType } from "../graph";
5
5
  import { Client } from "./client";
6
6
  import { SingleGraphConnection } from "./single";
7
+ import { MemoryUsageOptions, MemoryUsageReply } from "../commands/MEMORY_USAGE";
7
8
  /**
8
9
  * The `NullClient` class is a placeholder implementation of the `Client` interface.
9
10
  *
@@ -34,6 +35,7 @@ export declare class NullClient implements Client {
34
35
  query: string;
35
36
  took: number;
36
37
  }[]>;
38
+ memoryUsage(_graph: string, _options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
37
39
  constraintCreate(_graph: string, _constraintType: ConstraintType, _entityType: EntityType, _label: string, ..._properties: string[]): Promise<void>;
38
40
  constraintDrop(_graph: string, _constraintType: ConstraintType, _entityType: EntityType, _label: string, ..._properties: string[]): Promise<void>;
39
41
  quit(): Promise<void>;
@@ -52,6 +52,9 @@ class NullClient {
52
52
  slowLog(_graph) {
53
53
  throw new Error("Method not implemented.");
54
54
  }
55
+ memoryUsage(_graph, _options) {
56
+ throw new Error("Method not implemented.");
57
+ }
55
58
  constraintCreate(_graph, _constraintType, _entityType, _label, ..._properties) {
56
59
  throw new Error("Method not implemented.");
57
60
  }
@@ -4,6 +4,7 @@ import { RedisCommandArgument, RedisFunctions, RedisScripts } from "@redis/clien
4
4
  import commands, { QueryOptions } from "../commands";
5
5
  import { RedisClientType } from "@redis/client";
6
6
  import FalkorDB from "../falkordb";
7
+ import { MemoryUsageOptions, MemoryUsageReply } from "../commands/MEMORY_USAGE";
7
8
  export type SingleGraphConnection = RedisClientType<{
8
9
  falkordb: typeof commands;
9
10
  }, RedisFunctions, RedisScripts>;
@@ -43,6 +44,7 @@ export declare class Single implements Client {
43
44
  query: string;
44
45
  took: number;
45
46
  }[]>;
47
+ memoryUsage(graph: string, options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
46
48
  constraintCreate(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
47
49
  constraintDrop(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
48
50
  copy<_T>(srcGraph: string, destGraph: string): Promise<"OK">;
@@ -74,6 +74,14 @@ class Single {
74
74
  }
75
75
  return this.client.falkordb.slowLog(graph);
76
76
  }
77
+ async memoryUsage(graph, options) {
78
+ if (this.#usePool) {
79
+ return this.client.executeIsolated(async (isolatedClient) => {
80
+ return isolatedClient.falkordb.memoryUsage(graph, options);
81
+ });
82
+ }
83
+ return this.client.falkordb.memoryUsage(graph, options);
84
+ }
77
85
  async constraintCreate(graph, constraintType, entityType, label, ...properties) {
78
86
  const reply = this.client.falkordb.constraintCreate(graph, constraintType, entityType, label, ...properties);
79
87
  return reply.then(() => { });
@@ -0,0 +1,6 @@
1
+ export interface MemoryUsageOptions {
2
+ SAMPLES?: number;
3
+ }
4
+ export declare function transformArguments(key: string, options?: MemoryUsageOptions): Array<string>;
5
+ export type MemoryUsageReply = Array<string | number | MemoryUsageReply>;
6
+ export declare function transformReply(): MemoryUsageReply;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformArguments = transformArguments;
4
+ function transformArguments(key, options) {
5
+ const args = ["GRAPH.MEMORY", "USAGE", key];
6
+ return options?.SAMPLES ? [...args, String(options.SAMPLES)] : [...args];
7
+ }
@@ -13,6 +13,7 @@ import * as CONSTRAINT_DROP from './CONSTRAINT_DROP';
13
13
  import * as COPY from './COPY';
14
14
  import * as SENTINEL_MASTER from './SENTINEL_MASTER';
15
15
  import * as SENTINEL_MASTERS from './SENTINEL_MASTERS';
16
+ import * as MEMORY_USAGE from './MEMORY_USAGE';
16
17
  import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
17
18
  declare const _default: {
18
19
  CONFIG_GET: typeof CONFIG_GET;
@@ -45,6 +46,8 @@ declare const _default: {
45
46
  sentinelMaster: typeof SENTINEL_MASTER;
46
47
  SENTINEL_MASTERS: typeof SENTINEL_MASTERS;
47
48
  sentinelMasters: typeof SENTINEL_MASTERS;
49
+ MEMORY_USAGE: typeof MEMORY_USAGE;
50
+ memoryUsage: typeof MEMORY_USAGE;
48
51
  };
49
52
  export default _default;
50
53
  type QueryParam = null | string | number | boolean | QueryParams | Array<QueryParam>;
@@ -16,6 +16,7 @@ const CONSTRAINT_DROP = require("./CONSTRAINT_DROP");
16
16
  const COPY = require("./COPY");
17
17
  const SENTINEL_MASTER = require("./SENTINEL_MASTER");
18
18
  const SENTINEL_MASTERS = require("./SENTINEL_MASTERS");
19
+ const MEMORY_USAGE = require("./MEMORY_USAGE");
19
20
  exports.default = {
20
21
  CONFIG_GET,
21
22
  configGet: CONFIG_GET,
@@ -46,7 +47,9 @@ exports.default = {
46
47
  SENTINEL_MASTER,
47
48
  sentinelMaster: SENTINEL_MASTER,
48
49
  SENTINEL_MASTERS,
49
- sentinelMasters: SENTINEL_MASTERS
50
+ sentinelMasters: SENTINEL_MASTERS,
51
+ MEMORY_USAGE,
52
+ memoryUsage: MEMORY_USAGE,
50
53
  };
51
54
  function pushQueryArguments(args, graph, query, options, compact) {
52
55
  args.push(graph);
@@ -3,8 +3,9 @@ import { QueryOptions } from "./commands";
3
3
  import { QueryReply } from "./commands/QUERY";
4
4
  import { ConstraintType, EntityType } from "./commands/CONSTRAINT_CREATE";
5
5
  import { Client } from "./clients/client";
6
+ import { MemoryUsageOptions } from "./commands/MEMORY_USAGE";
6
7
  export { ConstraintType, EntityType };
7
- export type GraphReply<T> = Omit<QueryReply, 'headers' | 'data'> & {
8
+ export type GraphReply<T> = Omit<QueryReply, "headers" | "data"> & {
8
9
  data?: Array<T>;
9
10
  };
10
11
  export default class Graph {
@@ -15,6 +16,7 @@ export default class Graph {
15
16
  delete(): Promise<void>;
16
17
  explain(query: string): Promise<any>;
17
18
  profile(query: string): Promise<any>;
19
+ memoryUsage(options?: MemoryUsageOptions): Promise<import("./commands/MEMORY_USAGE").MemoryUsageReply>;
18
20
  slowLog(): Promise<{
19
21
  timestamp: Date;
20
22
  command: string;
package/dist/src/graph.js CHANGED
@@ -4,6 +4,7 @@ exports.EntityType = exports.ConstraintType = void 0;
4
4
  const CONSTRAINT_CREATE_1 = require("./commands/CONSTRAINT_CREATE");
5
5
  Object.defineProperty(exports, "ConstraintType", { enumerable: true, get: function () { return CONSTRAINT_CREATE_1.ConstraintType; } });
6
6
  Object.defineProperty(exports, "EntityType", { enumerable: true, get: function () { return CONSTRAINT_CREATE_1.EntityType; } });
7
+ const polyfill_1 = require("@js-temporal/polyfill");
7
8
  // https://github.com/FalkorDB/FalkorDB/blob/master/src/resultset/formatters/resultset_formatter.h#L20
8
9
  var GraphValueTypes;
9
10
  (function (GraphValueTypes) {
@@ -20,6 +21,10 @@ var GraphValueTypes;
20
21
  GraphValueTypes[GraphValueTypes["MAP"] = 10] = "MAP";
21
22
  GraphValueTypes[GraphValueTypes["POINT"] = 11] = "POINT";
22
23
  GraphValueTypes[GraphValueTypes["VECTORF32"] = 12] = "VECTORF32";
24
+ GraphValueTypes[GraphValueTypes["DATETIME"] = 13] = "DATETIME";
25
+ GraphValueTypes[GraphValueTypes["DATE"] = 14] = "DATE";
26
+ GraphValueTypes[GraphValueTypes["TIME"] = 15] = "TIME";
27
+ GraphValueTypes[GraphValueTypes["DURATION"] = 16] = "DURATION";
23
28
  })(GraphValueTypes || (GraphValueTypes = {}));
24
29
  // export type GraphConnection = SingleGraphConnection | ClusterGraphConnection;
25
30
  class Graph {
@@ -47,6 +52,9 @@ class Graph {
47
52
  async profile(query) {
48
53
  return this.#client.profile(this.#name, query);
49
54
  }
55
+ async memoryUsage(options) {
56
+ return this.#client.memoryUsage(this.#name, options);
57
+ }
50
58
  async slowLog() {
51
59
  return this.#client.slowLog(this.#name);
52
60
  }
@@ -61,21 +69,20 @@ class Graph {
61
69
  }
62
70
  #setMetadataPromise;
63
71
  #updateMetadata() {
64
- this.#setMetadataPromise ??= this.#setMetadata()
65
- .finally(() => this.#setMetadataPromise = undefined);
72
+ this.#setMetadataPromise ??= this.#setMetadata().finally(() => (this.#setMetadataPromise = undefined));
66
73
  return this.#setMetadataPromise;
67
74
  }
68
75
  // DO NOT use directly, use #updateMetadata instead
69
76
  async #setMetadata() {
70
77
  const [labels, relationshipTypes, propertyKeys] = await Promise.all([
71
- this.#client.roQuery(this.#name, 'CALL db.labels()', undefined, false),
72
- this.#client.roQuery(this.#name, 'CALL db.relationshipTypes()', undefined, false),
73
- this.#client.roQuery(this.#name, 'CALL db.propertyKeys()', undefined, false)
78
+ this.#client.roQuery(this.#name, "CALL db.labels()", undefined, false),
79
+ this.#client.roQuery(this.#name, "CALL db.relationshipTypes()", undefined, false),
80
+ this.#client.roQuery(this.#name, "CALL db.propertyKeys()", undefined, false),
74
81
  ]);
75
82
  this.#metadata = {
76
83
  labels: this.#cleanMetadataArray(labels.data),
77
84
  relationshipTypes: this.#cleanMetadataArray(relationshipTypes.data),
78
- propertyKeys: this.#cleanMetadataArray(propertyKeys.data)
85
+ propertyKeys: this.#cleanMetadataArray(propertyKeys.data),
79
86
  };
80
87
  return this.#metadata;
81
88
  }
@@ -106,7 +113,7 @@ class Graph {
106
113
  }
107
114
  }
108
115
  return data;
109
- })
116
+ }),
110
117
  };
111
118
  if (promises.length)
112
119
  await Promise.all(promises);
@@ -120,11 +127,11 @@ class Graph {
120
127
  case GraphValueTypes.INTEGER:
121
128
  return value;
122
129
  case GraphValueTypes.BOOLEAN:
123
- return value === 'true';
130
+ return value === "true";
124
131
  case GraphValueTypes.DOUBLE:
125
132
  return parseFloat(value);
126
133
  case GraphValueTypes.ARRAY:
127
- return value.map(x => this.#parseValue(x, promises));
134
+ return value.map((x) => this.#parseValue(x, promises));
128
135
  case GraphValueTypes.EDGE:
129
136
  return this.#parseEdge(value, promises);
130
137
  case GraphValueTypes.NODE:
@@ -132,7 +139,7 @@ class Graph {
132
139
  case GraphValueTypes.PATH:
133
140
  return {
134
141
  nodes: value[0][1].map(([, node]) => this.#parseNode(node, promises)),
135
- edges: value[1][1].map(([, edge]) => this.#parseEdge(edge, promises))
142
+ edges: value[1][1].map(([, edge]) => this.#parseEdge(edge, promises)),
136
143
  };
137
144
  case GraphValueTypes.MAP: {
138
145
  const map = {};
@@ -144,24 +151,44 @@ class Graph {
144
151
  case GraphValueTypes.POINT:
145
152
  return {
146
153
  latitude: parseFloat(value[0]),
147
- longitude: parseFloat(value[1])
154
+ longitude: parseFloat(value[1]),
148
155
  };
149
156
  case GraphValueTypes.VECTORF32:
150
- return value.map(x => Number(x));
157
+ return value.map((x) => Number(x));
158
+ case GraphValueTypes.DATETIME:
159
+ return polyfill_1.Temporal.Instant.fromEpochMilliseconds(value * 1000)
160
+ .toZonedDateTimeISO("UTC")
161
+ .toPlainDateTime();
162
+ case GraphValueTypes.DATE:
163
+ return polyfill_1.Temporal.Instant.fromEpochMilliseconds(value * 1000)
164
+ .toZonedDateTimeISO("UTC")
165
+ .toPlainDate();
166
+ case GraphValueTypes.TIME:
167
+ return polyfill_1.Temporal.Instant.fromEpochMilliseconds(value * 1000)
168
+ .toZonedDateTimeISO("UTC")
169
+ .toPlainTime();
170
+ case GraphValueTypes.DURATION:
171
+ const time = polyfill_1.Temporal.Instant.fromEpochMilliseconds(value * 1000);
172
+ const epoch = polyfill_1.Temporal.Instant.fromEpochMilliseconds(0);
173
+ return epoch
174
+ .toZonedDateTimeISO("UTC")
175
+ .until(time.toZonedDateTimeISO("UTC"), {
176
+ largestUnit: "years",
177
+ });
151
178
  default:
152
179
  throw new Error(`unknown scalar type: ${valueType}`);
153
180
  }
154
181
  }
155
- #parseEdge([id, relationshipTypeId, sourceId, destinationId, properties], promises) {
182
+ #parseEdge([id, relationshipTypeId, sourceId, destinationId, properties,], promises) {
156
183
  const edge = {
157
184
  id,
158
185
  sourceId,
159
186
  destinationId,
160
- properties: this.#parseProperties(properties, promises)
187
+ properties: this.#parseProperties(properties, promises),
161
188
  };
162
- const relationshipType = this.#getMetadata('relationshipTypes', relationshipTypeId);
189
+ const relationshipType = this.#getMetadata("relationshipTypes", relationshipTypeId);
163
190
  if (relationshipType instanceof Promise) {
164
- promises.push(relationshipType.then(value => edge.relationshipType = value));
191
+ promises.push(relationshipType.then((value) => (edge.relationshipType = value)));
165
192
  }
166
193
  else {
167
194
  edge.relationshipType = relationshipType;
@@ -171,9 +198,9 @@ class Graph {
171
198
  #parseNode([id, labelIds, properties], promises) {
172
199
  const labels = new Array(labelIds.length);
173
200
  for (let i = 0; i < labelIds.length; i++) {
174
- const value = this.#getMetadata('labels', labelIds[i]);
201
+ const value = this.#getMetadata("labels", labelIds[i]);
175
202
  if (value instanceof Promise) {
176
- promises.push(value.then(value => labels[i] = value));
203
+ promises.push(value.then((value) => (labels[i] = value)));
177
204
  }
178
205
  else {
179
206
  labels[i] = value;
@@ -182,15 +209,15 @@ class Graph {
182
209
  return {
183
210
  id,
184
211
  labels,
185
- properties: this.#parseProperties(properties, promises)
212
+ properties: this.#parseProperties(properties, promises),
186
213
  };
187
214
  }
188
215
  #parseProperties(raw, promises) {
189
216
  const parsed = {};
190
217
  for (const [id, type, value] of raw) {
191
- const parsedValue = this.#parseValue([type, value], promises), key = this.#getMetadata('propertyKeys', id);
218
+ const parsedValue = this.#parseValue([type, value], promises), key = this.#getMetadata("propertyKeys", id);
192
219
  if (key instanceof Promise) {
193
- promises.push(key.then(key => parsed[key] = parsedValue));
220
+ promises.push(key.then((key) => (parsed[key] = parsedValue)));
194
221
  }
195
222
  else {
196
223
  parsed[key] = parsedValue;
@@ -204,7 +231,7 @@ class Graph {
204
231
  idxType = "";
205
232
  }
206
233
  let query = `CREATE ${idxType ? idxType + " " : ""}INDEX FOR ${pattern} ON (${properties
207
- .map(prop => `e.${prop}`)
234
+ .map((prop) => `e.${prop}`)
208
235
  .join(", ")})`;
209
236
  if (options) {
210
237
  const optionsMap = Object.entries(options)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "falkordb",
3
- "version": "6.3.0",
3
+ "version": "6.4.0",
4
4
  "description": "A FalkorDB javascript library",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
@@ -32,8 +32,11 @@
32
32
  "keywords": [
33
33
  "falkordb"
34
34
  ],
35
+ "engines": {
36
+ "node": ">=20.0.0"
37
+ },
35
38
  "devDependencies": {
36
- "@tsconfig/node14": "^14.1.2",
39
+ "@tsconfig/node20": "^20.1.4",
37
40
  "@types/jest": "^29.5.14",
38
41
  "@types/lodash": "^4.17.13",
39
42
  "@types/node": "^24.0.3",
@@ -44,9 +47,10 @@
44
47
  "jest": "^29.7.0",
45
48
  "release-it": "^19.0.3",
46
49
  "ts-jest": "^29.2.5",
47
- "typescript": "^5.7.2"
50
+ "typescript": "^5.9.3"
48
51
  },
49
52
  "dependencies": {
53
+ "@js-temporal/polyfill": "^0.5.1",
50
54
  "@redis/client": "^1.6.0",
51
55
  "cluster-key-slot": "1.1.2",
52
56
  "generic-pool": "^3.9.0",