@sochdb/sochdb 0.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.
Files changed (78) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +3349 -0
  3. package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
  4. package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
  5. package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
  6. package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
  7. package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
  8. package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
  9. package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
  10. package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
  11. package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
  12. package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
  13. package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
  14. package/bin/sochdb-bulk.js +80 -0
  15. package/bin/sochdb-grpc-server.js +80 -0
  16. package/bin/sochdb-server.js +84 -0
  17. package/dist/cjs/analytics.js +196 -0
  18. package/dist/cjs/database.js +929 -0
  19. package/dist/cjs/embedded/database.js +236 -0
  20. package/dist/cjs/embedded/ffi/bindings.js +113 -0
  21. package/dist/cjs/embedded/ffi/library-finder.js +135 -0
  22. package/dist/cjs/embedded/index.js +14 -0
  23. package/dist/cjs/embedded/transaction.js +172 -0
  24. package/dist/cjs/errors.js +71 -0
  25. package/dist/cjs/format.js +176 -0
  26. package/dist/cjs/grpc-client.js +328 -0
  27. package/dist/cjs/index.js +75 -0
  28. package/dist/cjs/ipc-client.js +504 -0
  29. package/dist/cjs/query.js +154 -0
  30. package/dist/cjs/server-manager.js +295 -0
  31. package/dist/cjs/sql-engine.js +874 -0
  32. package/dist/esm/analytics.js +196 -0
  33. package/dist/esm/database.js +931 -0
  34. package/dist/esm/embedded/database.js +239 -0
  35. package/dist/esm/embedded/ffi/bindings.js +142 -0
  36. package/dist/esm/embedded/ffi/library-finder.js +135 -0
  37. package/dist/esm/embedded/index.js +14 -0
  38. package/dist/esm/embedded/transaction.js +176 -0
  39. package/dist/esm/errors.js +71 -0
  40. package/dist/esm/format.js +179 -0
  41. package/dist/esm/grpc-client.js +333 -0
  42. package/dist/esm/index.js +75 -0
  43. package/dist/esm/ipc-client.js +505 -0
  44. package/dist/esm/query.js +159 -0
  45. package/dist/esm/server-manager.js +295 -0
  46. package/dist/esm/sql-engine.js +875 -0
  47. package/dist/types/analytics.d.ts +66 -0
  48. package/dist/types/analytics.d.ts.map +1 -0
  49. package/dist/types/database.d.ts +523 -0
  50. package/dist/types/database.d.ts.map +1 -0
  51. package/dist/types/embedded/database.d.ts +105 -0
  52. package/dist/types/embedded/database.d.ts.map +1 -0
  53. package/dist/types/embedded/ffi/bindings.d.ts +24 -0
  54. package/dist/types/embedded/ffi/bindings.d.ts.map +1 -0
  55. package/dist/types/embedded/ffi/library-finder.d.ts +17 -0
  56. package/dist/types/embedded/ffi/library-finder.d.ts.map +1 -0
  57. package/dist/types/embedded/index.d.ts +9 -0
  58. package/dist/types/embedded/index.d.ts.map +1 -0
  59. package/dist/types/embedded/transaction.d.ts +21 -0
  60. package/dist/types/embedded/transaction.d.ts.map +1 -0
  61. package/dist/types/errors.d.ts +36 -0
  62. package/dist/types/errors.d.ts.map +1 -0
  63. package/dist/types/format.d.ts +117 -0
  64. package/dist/types/format.d.ts.map +1 -0
  65. package/dist/types/grpc-client.d.ts +120 -0
  66. package/dist/types/grpc-client.d.ts.map +1 -0
  67. package/dist/types/index.d.ts +50 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/ipc-client.d.ts +177 -0
  70. package/dist/types/ipc-client.d.ts.map +1 -0
  71. package/dist/types/query.d.ts +85 -0
  72. package/dist/types/query.d.ts.map +1 -0
  73. package/dist/types/server-manager.d.ts +29 -0
  74. package/dist/types/server-manager.d.ts.map +1 -0
  75. package/dist/types/sql-engine.d.ts +100 -0
  76. package/dist/types/sql-engine.d.ts.map +1 -0
  77. package/package.json +90 -0
  78. package/scripts/postinstall.js +50 -0
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ /**
3
+ * SochDB Query Builder
4
+ *
5
+ * Fluent query interface for SochDB.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.Query = void 0;
11
+ /**
12
+ * Fluent query builder for SochDB.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const results = await db.query('users/')
17
+ * .limit(10)
18
+ * .select(['name', 'email'])
19
+ * .toList();
20
+ * ```
21
+ */
22
+ class Query {
23
+ _client;
24
+ _pathPrefix;
25
+ _limit;
26
+ _offset;
27
+ _columns;
28
+ constructor(client, pathPrefix) {
29
+ this._client = client;
30
+ this._pathPrefix = pathPrefix;
31
+ }
32
+ /**
33
+ * Limit the number of results.
34
+ *
35
+ * @param n - Maximum number of results to return
36
+ * @returns This query builder for chaining
37
+ */
38
+ limit(n) {
39
+ this._limit = n;
40
+ return this;
41
+ }
42
+ /**
43
+ * Skip the first n results.
44
+ *
45
+ * @param n - Number of results to skip
46
+ * @returns This query builder for chaining
47
+ */
48
+ offset(n) {
49
+ this._offset = n;
50
+ return this;
51
+ }
52
+ /**
53
+ * Select specific columns to return.
54
+ *
55
+ * @param columns - Array of column names to select
56
+ * @returns This query builder for chaining
57
+ */
58
+ select(columns) {
59
+ this._columns = columns;
60
+ return this;
61
+ }
62
+ /**
63
+ * Execute the query and return results as TOON string.
64
+ *
65
+ * @returns TOON formatted string (e.g., "result[N]{cols}: row1; row2")
66
+ */
67
+ async execute() {
68
+ return this._client.query(this._pathPrefix, {
69
+ limit: this._limit,
70
+ offset: this._offset,
71
+ columns: this._columns,
72
+ });
73
+ }
74
+ /**
75
+ * Execute and parse results into a list of objects.
76
+ *
77
+ * @returns Array of result objects
78
+ */
79
+ async toList() {
80
+ const toonStr = await this.execute();
81
+ return this._parseToon(toonStr);
82
+ }
83
+ /**
84
+ * Execute and return the first result, or null if none.
85
+ *
86
+ * @returns First result or null
87
+ */
88
+ async first() {
89
+ const originalLimit = this._limit;
90
+ this._limit = 1;
91
+ const results = await this.toList();
92
+ this._limit = originalLimit;
93
+ return results.length > 0 ? results[0] : null;
94
+ }
95
+ /**
96
+ * Execute and return the count of results.
97
+ *
98
+ * @returns Number of matching results
99
+ */
100
+ async count() {
101
+ const results = await this.toList();
102
+ return results.length;
103
+ }
104
+ /**
105
+ * Simple TOON parser.
106
+ *
107
+ * Parses TOON format: "result[N]{col1,col2}: val1,val2; val3,val4"
108
+ */
109
+ _parseToon(toonStr) {
110
+ if (!toonStr || toonStr === 'result[0]{}:') {
111
+ return [];
112
+ }
113
+ // Parse header: result[N]{cols}:
114
+ const headerMatch = toonStr.match(/^result\[(\d+)\]\{([^}]*)\}:\s*/);
115
+ if (!headerMatch) {
116
+ // Try to parse as JSON if not TOON format
117
+ try {
118
+ return JSON.parse(toonStr);
119
+ }
120
+ catch {
121
+ return [];
122
+ }
123
+ }
124
+ const count = parseInt(headerMatch[1], 10);
125
+ if (count === 0) {
126
+ return [];
127
+ }
128
+ const columns = headerMatch[2].split(',').map((c) => c.trim());
129
+ const body = toonStr.substring(headerMatch[0].length);
130
+ // Split rows by semicolon
131
+ const rows = body.split(';').map((r) => r.trim()).filter((r) => r.length > 0);
132
+ return rows.map((row) => {
133
+ const values = row.split(',').map((v) => v.trim());
134
+ const result = {};
135
+ columns.forEach((col, idx) => {
136
+ if (col && idx < values.length) {
137
+ // Try to parse as JSON/number
138
+ let value = values[idx];
139
+ if (value === 'null') {
140
+ value = null;
141
+ }
142
+ else if (value === 'true') {
143
+ value = true;
144
+ }
145
+ else if (value === 'false') {
146
+ value = false;
147
+ }
148
+ else if (!isNaN(Number(value))) {
149
+ value = Number(value);
150
+ }
151
+ result[col] = value;
152
+ }
153
+ });
154
+ return result;
155
+ });
156
+ }
157
+ }
158
+ exports.Query = Query;
159
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcXVlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7O0FBbUJIOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFhLEtBQUs7SUFDUixPQUFPLENBQVk7SUFDbkIsV0FBVyxDQUFTO0lBQ3BCLE1BQU0sQ0FBVTtJQUNoQixPQUFPLENBQVU7SUFDakIsUUFBUSxDQUFZO0lBRTVCLFlBQVksTUFBaUIsRUFBRSxVQUFrQjtRQUMvQyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUN0QixJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsQ0FBUztRQUNiLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLENBQVM7UUFDZCxJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztRQUNqQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxPQUFpQjtRQUN0QixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQztRQUN4QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLE9BQU87UUFDWCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDMUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ2xCLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNwQixPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVE7U0FDdkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsTUFBTTtRQUNWLE1B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LENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ2pDLElBQUksS0FBSyxLQUFLLE1BQU0sRUFBRSxDQUFDO3dCQUNyQixLQUFLLEdBQUcsSUFBSSxDQUFDO29CQUNmLENBQUM7eUJBQU0sSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFLENBQUM7d0JBQzVCLEtBQUssR0FBRyxJQUFJLENBQUM7b0JBQ2YsQ0FBQzt5QkFBTSxJQUFJLEtBQUssS0FBSyxPQUFPLEVBQUUsQ0FBQzt3QkFDN0IsS0FBSyxHQUFHLEtBQUssQ0FBQztvQkFDaEIsQ0FBQzt5QkFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7d0JBQ2pDLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3hCLENBQUM7b0JBQ0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztnQkFDdEIsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1lBRUgsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUFuSkQsc0JBbUpDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTb2NoREIgUXVlcnkgQnVpbGRlclxuICpcbiAqIEZsdWVudCBxdWVyeSBpbnRlcmZhY2UgZm9yIFNvY2hEQi5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuXG4vLyBDb3B5cmlnaHQgMjAyNSBTdXNoYW50aCAoaHR0cHM6Ly9naXRodWIuY29tL3N1c2hhbnRocHkpXG4vL1xuLy8gTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbi8vIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbi8vIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuLy9cbi8vICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuaW1wb3J0IHsgSXBjQ2xpZW50IH0gZnJvbSAnLi9pcGMtY2xpZW50JztcblxuLyoqXG4gKiBRdWVyeSByZXN1bHQgcm93LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5UmVzdWx0IHtcbiAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuLyoqXG4gKiBGbHVlbnQgcXVlcnkgYnVpbGRlciBmb3IgU29jaERCLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByZXN1bHRzID0gYXdhaXQgZGIucXVlcnkoJ3VzZXJzLycpXG4gKiAgIC5saW1pdCgxMClcbiAqICAgLnNlbGVjdChbJ25hbWUnLCAnZW1haWwnXSlcbiAqICAgLnRvTGlzdCgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBRdWVyeSB7XG4gIHByaXZhdGUgX2NsaWVudDogSXBjQ2xpZW50O1xuICBwcml2YXRlIF9wYXRoUHJlZml4OiBzdHJpbmc7XG4gIHByaXZhdGUgX2xpbWl0PzogbnVtYmVyO1xuICBwcml2YXRlIF9vZmZzZXQ/OiBudW1iZXI7XG4gIHByaXZhdGUgX2NvbHVtbnM/OiBzdHJpbmdbXTtcblxuICBjb25zdHJ1Y3RvcihjbGllbnQ6IElwY0NsaWVudCwgcGF0aFByZWZpeDogc3RyaW5nKSB7XG4gICAgdGhpcy5fY2xpZW50ID0gY2xpZW50O1xuICAgIHRoaXMuX3BhdGhQcmVmaXggPSBwYXRoUHJlZml4O1xuICB9XG5cbiAgLyoqXG4gICAqIExpbWl0IHRoZSBudW1iZXIgb2YgcmVzdWx0cy5cbiAgICpcbiAgICogQHBhcmFtIG4gLSBNYXhpbXVtIG51bWJlciBvZiByZXN1bHRzIHRvIHJldHVyblxuICAgKiBAcmV0dXJucyBUaGlzIHF1ZXJ5IGJ1aWxkZXIgZm9yIGNoYWluaW5nXG4gICAqL1xuICBsaW1pdChuOiBudW1iZXIpOiBRdWVyeSB7XG4gICAgdGhpcy5fbGltaXQgPSBuO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNraXAgdGhlIGZpcnN0IG4gcmVzdWx0cy5cbiAgICpcbiAgICogQHBhcmFtIG4gLSBOdW1iZXIgb2YgcmVzdWx0cyB0byBza2lwXG4gICAqIEByZXR1cm5zIFRoaXMgcXVlcnkgYnVpbGRlciBmb3IgY2hhaW5pbmdcbiAgICovXG4gIG9mZnNldChuOiBudW1iZXIpOiBRdWVyeSB7XG4gICAgdGhpcy5fb2Zmc2V0ID0gbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZWxlY3Qgc3BlY2lmaWMgY29sdW1ucyB0byByZXR1cm4uXG4gICAqXG4gICAqIEBwYXJhbSBjb2x1bW5zIC0gQXJyYXkgb2YgY29sdW1uIG5hbWVzIHRvIHNlbGVjdFxuICAgKiBAcmV0dXJucyBUaGlzIHF1ZXJ5IGJ1aWxkZXIgZm9yIGNoYWluaW5nXG4gICAqL1xuICBzZWxlY3QoY29sdW1uczogc3RyaW5nW10pOiBRdWVyeSB7XG4gICAgdGhpcy5fY29sdW1ucyA9IGNvbHVtbnM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSB0aGUgcXVlcnkgYW5kIHJldHVybiByZXN1bHRzIGFzIFRPT04gc3RyaW5nLlxuICAgKlxuICAgKiBAcmV0dXJucyBUT09OIGZvcm1hdHRlZCBzdHJpbmcgKGUuZy4sIFwicmVzdWx0W05de2NvbHN9OiByb3cxOyByb3cyXCIpXG4gICAqL1xuICBhc3luYyBleGVjdXRlKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5xdWVyeSh0aGlzLl9wYXRoUHJlZml4LCB7XG4gICAgICBsaW1pdDogdGhpcy5fbGltaXQsXG4gICAgICBvZmZzZXQ6IHRoaXMuX29mZnNldCxcbiAgICAgIGNvbHVtbnM6IHRoaXMuX2NvbHVtbnMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSBhbmQgcGFyc2UgcmVzdWx0cyBpbnRvIGEgbGlzdCBvZiBvYmplY3RzLlxuICAgKlxuICAgKiBAcmV0dXJucyBBcnJheSBvZiByZXN1bHQgb2JqZWN0c1xuICAgKi9cbiAgYXN5bmMgdG9MaXN0KCk6IFByb21pc2U8UXVlcnlSZXN1bHRbXT4ge1xuICAgIGNvbnN0IHRvb25TdHIgPSBhd2FpdCB0aGlzLmV4ZWN1dGUoKTtcbiAgICByZXR1cm4gdGhpcy5fcGFyc2VUb29uKHRvb25TdHIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgYW5kIHJldHVybiB0aGUgZmlyc3QgcmVzdWx0LCBvciBudWxsIGlmIG5vbmUuXG4gICAqXG4gICAqIEByZXR1cm5zIEZpcnN0IHJlc3VsdCBvciBudWxsXG4gICAqL1xuICBhc3luYyBmaXJzdCgpOiBQcm9taXNlPFF1ZXJ5UmVzdWx0IHwgbnVsbD4ge1xuICAgIGNvbnN0IG9yaWdpbmFsTGltaXQgPSB0aGlzLl9saW1pdDtcbiAgICB0aGlzLl9saW1pdCA9IDE7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMudG9MaXN0KCk7XG4gICAgdGhpcy5fbGltaXQgPSBvcmlnaW5hbExpbWl0O1xuICAgIHJldHVybiByZXN1bHRzLmxlbmd0aCA+IDAgPyByZXN1bHRzWzBdIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFuZCByZXR1cm4gdGhlIGNvdW50IG9mIHJlc3VsdHMuXG4gICAqXG4gICAqIEByZXR1cm5zIE51bWJlciBvZiBtYXRjaGluZyByZXN1bHRzXG4gICAqL1xuICBhc3luYyBjb3VudCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLnRvTGlzdCgpO1xuICAgIHJldHVybiByZXN1bHRzLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaW1wbGUgVE9PTiBwYXJzZXIuXG4gICAqXG4gICAqIFBhcnNlcyBUT09OIGZvcm1hdDogXCJyZXN1bHRbTl17Y29sMSxjb2wyfTogdmFsMSx2YWwyOyB2YWwzLHZhbDRcIlxuICAgKi9cbiAgcHJpdmF0ZSBfcGFyc2VUb29uKHRvb25TdHI6IHN0cmluZyk6IFF1ZXJ5UmVzdWx0W10ge1xuICAgIGlmICghdG9vblN0ciB8fCB0b29uU3RyID09PSAncmVzdWx0WzBde306Jykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIC8vIFBhcnNlIGhlYWRlcjogcmVzdWx0W05de2NvbHN9OlxuICAgIGNvbnN0IGhlYWRlck1hdGNoID0gdG9vblN0ci5tYXRjaCgvXnJlc3VsdFxcWyhcXGQrKVxcXVxceyhbXn1dKilcXH06XFxzKi8pO1xuICAgIGlmICghaGVhZGVyTWF0Y2gpIHtcbiAgICAgIC8vIFRyeSB0byBwYXJzZSBhcyBKU09OIGlmIG5vdCBUT09OIGZvcm1hdFxuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodG9vblN0cik7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGNvdW50ID0gcGFyc2VJbnQoaGVhZGVyTWF0Y2hbMV0sIDEwKTtcbiAgICBpZiAoY291bnQgPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2x1bW5zID0gaGVhZGVyTWF0Y2hbMl0uc3BsaXQoJywnKS5tYXAoKGMpID0+IGMudHJpbSgpKTtcbiAgICBjb25zdCBib2R5ID0gdG9vblN0ci5zdWJzdHJpbmcoaGVhZGVyTWF0Y2hbMF0ubGVuZ3RoKTtcblxuICAgIC8vIFNwbGl0IHJvd3MgYnkgc2VtaWNvbG9uXG4gICAgY29uc3Qgcm93cyA9IGJvZHkuc3BsaXQoJzsnKS5tYXAoKHIpID0+IHIudHJpbSgpKS5maWx0ZXIoKHIpID0+IHIubGVuZ3RoID4gMCk7XG5cbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgY29uc3QgdmFsdWVzID0gcm93LnNwbGl0KCcsJykubWFwKCh2KSA9PiB2LnRyaW0oKSk7XG4gICAgICBjb25zdCByZXN1bHQ6IFF1ZXJ5UmVzdWx0ID0ge307XG5cbiAgICAgIGNvbHVtbnMuZm9yRWFjaCgoY29sLCBpZHgpID0+IHtcbiAgICAgICAgaWYgKGNvbCAmJiBpZHggPCB2YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgLy8gVHJ5IHRvIHBhcnNlIGFzIEpTT04vbnVtYmVyXG4gICAgICAgICAgbGV0IHZhbHVlOiB1bmtub3duID0gdmFsdWVzW2lkeF07XG4gICAgICAgICAgaWYgKHZhbHVlID09PSAnbnVsbCcpIHtcbiAgICAgICAgICAgIHZhbHVlID0gbnVsbDtcbiAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAndHJ1ZScpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAnZmFsc2UnKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGZhbHNlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIWlzTmFOKE51bWJlcih2YWx1ZSkpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IE51bWJlcih2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdFtjb2xdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ /**
3
+ * SochDB Embedded Server Manager
4
+ *
5
+ * Manages the lifecycle of the SochDB server process for embedded mode.
6
+ * Automatically starts the server when needed and stops it on cleanup.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.startEmbeddedServer = startEmbeddedServer;
45
+ exports.stopEmbeddedServer = stopEmbeddedServer;
46
+ exports.stopAllEmbeddedServers = stopAllEmbeddedServers;
47
+ exports.isServerRunning = isServerRunning;
48
+ // Copyright 2025 Sushanth (https://github.com/sushanthpy)
49
+ //
50
+ // Licensed under the Apache License, Version 2.0 (the "License");
51
+ // you may not use this file except in compliance with the License.
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ const net = __importStar(require("net"));
55
+ const child_process_1 = require("child_process");
56
+ const errors_1 = require("./errors");
57
+ /**
58
+ * Find the sochdb-server binary (provides IPC interface)
59
+ *
60
+ * Note: sochdb-server uses Unix domain sockets, not available on Windows.
61
+ * On Windows, use the gRPC client instead for cross-platform compatibility.
62
+ */
63
+ function findServerBinary() {
64
+ const platform = process.platform;
65
+ const arch = process.arch;
66
+ // Windows doesn't support Unix sockets, sochdb-server is not available
67
+ if (platform === 'win32') {
68
+ throw new errors_1.DatabaseError('sochdb-server is not available on Windows (requires Unix domain sockets). ' +
69
+ 'Use the gRPC client for cross-platform support: ' +
70
+ 'const client = await GrpcClient.connect("localhost:50051")');
71
+ }
72
+ let target;
73
+ if (platform === 'darwin') {
74
+ target = arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin';
75
+ }
76
+ else {
77
+ target = arch === 'arm64' ? 'aarch64-unknown-linux-gnu' : 'x86_64-unknown-linux-gnu';
78
+ }
79
+ const binaryName = 'sochdb-server';
80
+ // Search paths - prioritize bundled binaries
81
+ const searchPaths = [
82
+ // Bundled in package (installed via npm) - from dist/cjs or dist/esm
83
+ path.join(__dirname, '..', '_bin', target, binaryName),
84
+ path.join(__dirname, '..', '..', '_bin', target, binaryName),
85
+ path.join(__dirname, '..', '..', '..', '_bin', target, binaryName),
86
+ // When running from source (src/) during development/testing
87
+ path.resolve(__dirname, '..', '_bin', target, binaryName),
88
+ // Development paths - from project root
89
+ path.join(__dirname, '..', '..', 'target', 'release', binaryName),
90
+ path.join(__dirname, '..', '..', 'target', 'debug', binaryName),
91
+ path.join(__dirname, '..', '..', '..', 'target', 'release', binaryName),
92
+ path.join(__dirname, '..', '..', '..', 'target', 'debug', binaryName),
93
+ // Absolute paths for sochdb workspace
94
+ path.resolve(process.cwd(), '_bin', target, binaryName),
95
+ path.resolve(process.cwd(), 'target', 'release', binaryName),
96
+ path.resolve(process.cwd(), '..', 'target', 'release', binaryName),
97
+ ];
98
+ for (const p of searchPaths) {
99
+ if (fs.existsSync(p)) {
100
+ return p;
101
+ }
102
+ }
103
+ // Try PATH
104
+ const pathDirs = (process.env.PATH || '').split(path.delimiter);
105
+ for (const dir of pathDirs) {
106
+ const p = path.join(dir, binaryName);
107
+ if (fs.existsSync(p)) {
108
+ return p;
109
+ }
110
+ }
111
+ throw new errors_1.DatabaseError(`Could not find ${binaryName}. ` +
112
+ `The pre-built binary may not be available for your platform (${platform}/${arch}). ` +
113
+ `Install via: cargo build --release -p sochdb-tools`);
114
+ }
115
+ /**
116
+ * Wait for a Unix socket to become available
117
+ */
118
+ async function waitForSocket(socketPath, timeoutMs = 10000) {
119
+ const startTime = Date.now();
120
+ const checkInterval = 100;
121
+ while (Date.now() - startTime < timeoutMs) {
122
+ if (fs.existsSync(socketPath)) {
123
+ // Try to connect to verify it's actually listening
124
+ try {
125
+ await new Promise((resolve, reject) => {
126
+ const socket = net.createConnection({ path: socketPath }, () => {
127
+ socket.destroy();
128
+ resolve();
129
+ });
130
+ socket.on('error', reject);
131
+ socket.setTimeout(1000);
132
+ });
133
+ return;
134
+ }
135
+ catch {
136
+ // Socket exists but not ready yet
137
+ }
138
+ }
139
+ await new Promise(resolve => setTimeout(resolve, checkInterval));
140
+ }
141
+ throw new errors_1.ConnectionError(`Timeout waiting for server socket at ${socketPath} after ${timeoutMs}ms`);
142
+ }
143
+ // Track running server instances
144
+ const runningServers = new Map();
145
+ /**
146
+ * Start an embedded SochDB server for the given database path.
147
+ * If a server is already running for this path, return the existing instance.
148
+ *
149
+ * @param dbPath - Path to the database directory
150
+ * @returns The socket path for connecting
151
+ */
152
+ async function startEmbeddedServer(dbPath) {
153
+ const absolutePath = path.resolve(dbPath);
154
+ const socketPath = path.join(absolutePath, 'sochdb.sock');
155
+ // Check if server already running for this path
156
+ const existing = runningServers.get(absolutePath);
157
+ if (existing && existing.process.exitCode === null) {
158
+ // Server still running
159
+ return socketPath;
160
+ }
161
+ // Check if another process already has a server running
162
+ if (fs.existsSync(socketPath)) {
163
+ try {
164
+ // Try to connect - if successful, server is running
165
+ await waitForSocket(socketPath, 1000);
166
+ return socketPath;
167
+ }
168
+ catch {
169
+ // Socket exists but dead - clean it up
170
+ try {
171
+ fs.unlinkSync(socketPath);
172
+ }
173
+ catch {
174
+ // Ignore
175
+ }
176
+ }
177
+ }
178
+ // Ensure database directory exists
179
+ if (!fs.existsSync(absolutePath)) {
180
+ fs.mkdirSync(absolutePath, { recursive: true });
181
+ }
182
+ // Find and spawn server
183
+ const serverBinary = findServerBinary();
184
+ const serverProcess = (0, child_process_1.spawn)(serverBinary, ['--db', absolutePath, '--socket', socketPath], {
185
+ stdio: ['ignore', 'pipe', 'pipe'],
186
+ detached: false,
187
+ });
188
+ // Collect stderr for error reporting
189
+ let stderrOutput = '';
190
+ serverProcess.stderr?.on('data', (data) => {
191
+ stderrOutput += data.toString();
192
+ });
193
+ // Handle process exit
194
+ serverProcess.on('exit', (code, signal) => {
195
+ runningServers.delete(absolutePath);
196
+ if (code !== 0 && code !== null) {
197
+ console.error(`SochDB server exited with code ${code}: ${stderrOutput}`);
198
+ }
199
+ });
200
+ serverProcess.on('error', (err) => {
201
+ runningServers.delete(absolutePath);
202
+ console.error(`Failed to start SochDB server: ${err.message}`);
203
+ });
204
+ // Store instance
205
+ runningServers.set(absolutePath, {
206
+ process: serverProcess,
207
+ socketPath,
208
+ dbPath: absolutePath,
209
+ });
210
+ // Wait for server to be ready
211
+ try {
212
+ await waitForSocket(socketPath, 10000);
213
+ }
214
+ catch (err) {
215
+ // Kill the process if it didn't start properly
216
+ serverProcess.kill();
217
+ runningServers.delete(absolutePath);
218
+ throw new errors_1.DatabaseError(`Failed to start embedded server: ${stderrOutput || err.message}`);
219
+ }
220
+ return socketPath;
221
+ }
222
+ /**
223
+ * Stop the embedded server for a specific database path
224
+ */
225
+ async function stopEmbeddedServer(dbPath) {
226
+ const absolutePath = path.resolve(dbPath);
227
+ const instance = runningServers.get(absolutePath);
228
+ if (!instance) {
229
+ return;
230
+ }
231
+ // Send SIGTERM and wait for graceful shutdown
232
+ instance.process.kill('SIGTERM');
233
+ // Wait for process to exit (max 5 seconds)
234
+ await new Promise((resolve) => {
235
+ const timeout = setTimeout(() => {
236
+ // Force kill if still running
237
+ if (instance.process.exitCode === null) {
238
+ instance.process.kill('SIGKILL');
239
+ }
240
+ resolve();
241
+ }, 5000);
242
+ instance.process.on('exit', () => {
243
+ clearTimeout(timeout);
244
+ resolve();
245
+ });
246
+ });
247
+ runningServers.delete(absolutePath);
248
+ // Clean up socket file
249
+ try {
250
+ if (fs.existsSync(instance.socketPath)) {
251
+ fs.unlinkSync(instance.socketPath);
252
+ }
253
+ }
254
+ catch {
255
+ // Ignore cleanup errors
256
+ }
257
+ }
258
+ /**
259
+ * Stop all running embedded servers
260
+ */
261
+ async function stopAllEmbeddedServers() {
262
+ const stopPromises = [];
263
+ for (const [dbPath] of runningServers) {
264
+ stopPromises.push(stopEmbeddedServer(dbPath));
265
+ }
266
+ await Promise.all(stopPromises);
267
+ }
268
+ /**
269
+ * Check if an embedded server is running for a database path
270
+ */
271
+ function isServerRunning(dbPath) {
272
+ const absolutePath = path.resolve(dbPath);
273
+ const instance = runningServers.get(absolutePath);
274
+ return instance !== undefined && instance.process.exitCode === null;
275
+ }
276
+ // Cleanup on process exit
277
+ process.on('exit', () => {
278
+ for (const instance of runningServers.values()) {
279
+ try {
280
+ instance.process.kill('SIGKILL');
281
+ }
282
+ catch {
283
+ // Ignore
284
+ }
285
+ }
286
+ });
287
+ process.on('SIGINT', async () => {
288
+ await stopAllEmbeddedServers();
289
+ process.exit(0);
290
+ });
291
+ process.on('SIGTERM', async () => {
292
+ await stopAllEmbeddedServers();
293
+ process.exit(0);
294
+ });
295
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmVyLW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7O0dBT0c7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUlILGtEQStFQztBQUtELGdEQXFDQztBQUtELHdEQU1DO0FBS0QsMENBSUM7QUFoUkQsMERBQTBEO0FBQzFELEVBQUU7QUFDRixrRUFBa0U7QUFDbEUsbUVBQW1FO0FBRW5FLHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFDN0IseUNBQTJCO0FBQzNCLGlEQUFvRDtBQUNwRCxxQ0FBMEQ7QUFFMUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGdCQUFnQjtJQUN2QixNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDO0lBQ2xDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7SUFFMUIsdUVBQXVFO0lBQ3ZFLElBQUksUUFBUSxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQ3pCLE1BQU0sSUFBSSxzQkFBYSxDQUNyQiw0RUFBNEU7WUFDNUUsa0RBQWtEO1lBQ2xELDREQUE0RCxDQUM3RCxDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksTUFBYyxDQUFDO0lBQ25CLElBQUksUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzFCLE1BQU0sR0FBRyxJQUFJLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMscUJBQXFCLENBQUM7SUFDN0UsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLEdBQUcsSUFBSSxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsMkJBQTJCLENBQUMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDO0lBQ3ZGLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxlQUFlLENBQUM7SUFFbkMsNkNBQTZDO0lBQzdDLE1BQU0sV0FBVyxHQUFHO1FBQ2xCLHFFQUFxRTtRQUNyRSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUM7UUFDdEQsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQztRQUM1RCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQztRQUNsRSw2REFBNkQ7UUFDN0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxDQUFDO1FBQ3pELHdDQUF3QztRQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDO1FBQ2pFLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUM7UUFDL0QsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUM7UUFDdkUsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUM7UUFDckUsc0NBQXNDO1FBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFD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QUFzQixFQUFFLENBQUM7SUFDL0IsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUMsQ0FBQztBQUVILE9BQU8sQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQy9CLE1BQU0sc0JBQXNCLEVBQUUsQ0FBQztJQUMvQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTb2NoREIgRW1iZWRkZWQgU2VydmVyIE1hbmFnZXJcbiAqXG4gKiBNYW5hZ2VzIHRoZSBsaWZlY3ljbGUgb2YgdGhlIFNvY2hEQiBzZXJ2ZXIgcHJvY2VzcyBmb3IgZW1iZWRkZWQgbW9kZS5cbiAqIEF1dG9tYXRpY2FsbHkgc3RhcnRzIHRoZSBzZXJ2ZXIgd2hlbiBuZWVkZWQgYW5kIHN0b3BzIGl0IG9uIGNsZWFudXAuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cblxuLy8gQ29weXJpZ2h0IDIwMjUgU3VzaGFudGggKGh0dHBzOi8vZ2l0aHViLmNvbS9zdXNoYW50aHB5KVxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBuZXQgZnJvbSAnbmV0JztcbmltcG9ydCB7IHNwYXduLCBDaGlsZFByb2Nlc3MgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IENvbm5lY3Rpb25FcnJvciwgRGF0YWJhc2VFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcblxuLyoqXG4gKiBGaW5kIHRoZSBzb2NoZGItc2VydmVyIGJpbmFyeSAocHJvdmlkZXMgSVBDIGludGVyZmFjZSlcbiAqIFxuICogTm90ZTogc29jaGRiLXNlcnZlciB1c2VzIFVuaXggZG9tYWluIHNvY2tldHMsIG5vdCBhdmFpbGFibGUgb24gV2luZG93cy5cbiAqIE9uIFdpbmRvd3MsIHVzZSB0aGUgZ1JQQyBjbGllbnQgaW5zdGVhZCBmb3IgY3Jvc3MtcGxhdGZvcm0gY29tcGF0aWJpbGl0eS5cbiAqL1xuZnVuY3Rpb24gZmluZFNlcnZlckJpbmFyeSgpOiBzdHJpbmcge1xuICBjb25zdCBwbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm07XG4gIGNvbnN0IGFyY2ggPSBwcm9jZXNzLmFyY2g7XG5cbiAgLy8gV2luZG93cyBkb2Vzbid0IHN1cHBvcnQgVW5peCBzb2NrZXRzLCBzb2NoZGItc2VydmVyIGlzIG5vdCBhdmFpbGFibGVcbiAgaWYgKHBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgdGhyb3cgbmV3IERhdGFiYXNlRXJyb3IoXG4gICAgICAnc29jaGRiLXNlcnZlciBpcyBub3QgYXZhaWxhYmxlIG9uIFdpbmRvd3MgKHJlcXVpcmVzIFVuaXggZG9tYWluIHNvY2tldHMpLiAnICtcbiAgICAgICdVc2UgdGhlIGdSUEMgY2xpZW50IGZvciBjcm9zcy1wbGF0Zm9ybSBzdXBwb3J0OiAnICtcbiAgICAgICdjb25zdCBjbGllbnQgPSBhd2FpdCBHcnBjQ2xpZW50LmNvbm5lY3QoXCJsb2NhbGhvc3Q6NTAwNTFcIiknXG4gICAgKTtcbiAgfVxuXG4gIGxldCB0YXJnZXQ6IHN0cmluZztcbiAgaWYgKHBsYXRmb3JtID09PSAnZGFyd2luJykge1xuICAgIHRhcmdldCA9IGFyY2ggPT09ICdhcm02NCcgPyAnYWFyY2g2NC1hcHBsZS1kYXJ3aW4nIDogJ3g4Nl82NC1hcHBsZS1kYXJ3aW4nO1xuICB9IGVsc2Uge1xuICAgIHRhcmdldCA9IGFyY2ggPT09ICdhcm02NCcgPyAnYWFyY2g2NC11bmtub3duLWxpbnV4LWdudScgOiAneDg2XzY0LXVua25vd24tbGludXgtZ251JztcbiAgfVxuXG4gIGNvbnN0IGJpbmFyeU5hbWUgPSAnc29jaGRiLXNlcnZlcic7XG5cbiAgLy8gU2VhcmNoIHBhdGhzIC0gcHJpb3JpdGl6ZSBidW5kbGVkIGJpbmFyaWVzXG4gIGNvbnN0IHNlYXJjaFBhdGhzID0gW1xuICAgIC8vIEJ1bmRsZWQgaW4gcGFja2FnZSAoaW5zdGFsbGVkIHZpYSBucG0pIC0gZnJvbSBkaXN0L2NqcyBvciBkaXN0L2VzbVxuICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICdfYmluJywgdGFyZ2V0LCBiaW5hcnlOYW1lKSxcbiAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAnX2JpbicsIHRhcmdldCwgYmluYXJ5TmFtZSksXG4gICAgcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uJywgJy4uJywgJy4uJywgJ19iaW4nLCB0YXJnZXQsIGJpbmFyeU5hbWUpLFxuICAgIC8vIFdoZW4gcnVubmluZyBmcm9tIHNvdXJjZSAoc3JjLykgZHVyaW5nIGRldmVsb3BtZW50L3Rlc3RpbmdcbiAgICBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4nLCAnX2JpbicsIHRhcmdldCwgYmluYXJ5TmFtZSksXG4gICAgLy8gRGV2ZWxvcG1lbnQgcGF0aHMgLSBmcm9tIHByb2plY3Qgcm9vdFxuICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICcuLicsICd0YXJnZXQnLCAncmVsZWFzZScsIGJpbmFyeU5hbWUpLFxuICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICcuLicsICd0YXJnZXQnLCAnZGVidWcnLCBiaW5hcnlOYW1lKSxcbiAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAnLi4nLCAndGFyZ2V0JywgJ3JlbGVhc2UnLCBiaW5hcnlOYW1lKSxcbiAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAnLi4nLCAndGFyZ2V0JywgJ2RlYnVnJywgYmluYXJ5TmFtZSksXG4gICAgLy8gQWJzb2x1dGUgcGF0aHMgZm9yIHNvY2hkYiB3b3Jrc3BhY2VcbiAgICBwYXRoLnJlc29sdmUocHJvY2Vzcy5jd2QoKSwgJ19iaW4nLCB0YXJnZXQsIGJpbmFyeU5hbWUpLFxuICAgIHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAndGFyZ2V0JywgJ3JlbGVhc2UnLCBiaW5hcnlOYW1lKSxcbiAgICBwYXRoLnJlc29sdmUocHJvY2Vzcy5jd2QoKSwgJy4uJywgJ3RhcmdldCcsICdyZWxlYXNlJywgYmluYXJ5TmFtZSksXG4gIF07XG5cbiAgZm9yIChjb25zdCBwIG9mIHNlYXJjaFBhdGhzKSB7XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMocCkpIHtcbiAgICAgIHJldHVybiBwO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRyeSBQQVRIXG4gIGNvbnN0IHBhdGhEaXJzID0gKHByb2Nlc3MuZW52LlBBVEggfHwgJycpLnNwbGl0KHBhdGguZGVsaW1pdGVyKTtcbiAgZm9yIChjb25zdCBkaXIgb2YgcGF0aERpcnMpIHtcbiAgICBjb25zdCBwID0gcGF0aC5qb2luKGRpciwgYmluYXJ5TmFtZSk7XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMocCkpIHtcbiAgICAgIHJldHVybiBwO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBEYXRhYmFzZUVycm9yKFxuICAgIGBDb3VsZCBub3QgZmluZCAke2JpbmFyeU5hbWV9LiBgICtcbiAgICBgVGhlIHByZS1idWlsdCBiaW5hcnkgbWF5IG5vdCBiZSBhdmFpbGFibGUgZm9yIHlvdXIgcGxhdGZvcm0gKCR7cGxhdGZvcm19LyR7YXJjaH0pLiBgICtcbiAgICBgSW5zdGFsbCB2aWE6IGNhcmdvIGJ1aWxkIC0tcmVsZWFzZSAtcCBzb2NoZGItdG9vbHNgXG4gICk7XG59XG5cbi8qKlxuICogV2FpdCBmb3IgYSBVbml4IHNvY2tldCB0byBiZWNvbWUgYXZhaWxhYmxlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JTb2NrZXQoc29ja2V0UGF0aDogc3RyaW5nLCB0aW1lb3V0TXM6IG51bWJlciA9IDEwMDAwKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gIGNvbnN0IGNoZWNrSW50ZXJ2YWwgPSAxMDA7XG5cbiAgd2hpbGUgKERhdGUubm93KCkgLSBzdGFydFRpbWUgPCB0aW1lb3V0TXMpIHtcbiAgICBpZiAoZnMuZXhpc3RzU3luYyhzb2NrZXRQYXRoKSkge1xuICAgICAgLy8gVHJ5IHRvIGNvbm5lY3QgdG8gdmVyaWZ5IGl0J3MgYWN0dWFsbHkgbGlzdGVuaW5nXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgY29uc3Qgc29ja2V0ID0gbmV0LmNyZWF0ZUNvbm5lY3Rpb24oeyBwYXRoOiBzb2NrZXRQYXRoIH0sICgpID0+IHtcbiAgICAgICAgICAgIHNvY2tldC5kZXN0cm95KCk7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc29ja2V0Lm9uKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICAgICAgc29ja2V0LnNldFRpbWVvdXQoMTAwMCk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gU29ja2V0IGV4aXN0cyBidXQgbm90IHJlYWR5IHlldFxuICAgICAgfVxuICAgIH1cbiAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgY2hlY2tJbnRlcnZhbCkpO1xuICB9XG5cbiAgdGhyb3cgbmV3IENvbm5lY3Rpb25FcnJvcihcbiAgICBgVGltZW91dCB3YWl0aW5nIGZvciBzZXJ2ZXIgc29ja2V0IGF0ICR7c29ja2V0UGF0aH0gYWZ0ZXIgJHt0aW1lb3V0TXN9bXNgXG4gICk7XG59XG5cbi8qKlxuICogRW1iZWRkZWQgc2VydmVyIGluc3RhbmNlXG4gKi9cbmludGVyZmFjZSBTZXJ2ZXJJbnN0YW5jZSB7XG4gIHByb2Nlc3M6IENoaWxkUHJvY2VzcztcbiAgc29ja2V0UGF0aDogc3RyaW5nO1xuICBkYlBhdGg6IHN0cmluZztcbn1cblxuLy8gVHJhY2sgcnVubmluZyBzZXJ2ZXIgaW5zdGFuY2VzXG5jb25zdCBydW5uaW5nU2VydmVyczogTWFwPHN0cmluZywgU2VydmVySW5zdGFuY2U+ID0gbmV3IE1hcCgpO1xuXG4vKipcbiAqIFN0YXJ0IGFuIGVtYmVkZGVkIFNvY2hEQiBzZXJ2ZXIgZm9yIHRoZSBnaXZlbiBkYXRhYmFzZSBwYXRoLlxuICogSWYgYSBzZXJ2ZXIgaXMgYWxyZWFkeSBydW5uaW5nIGZvciB0aGlzIHBhdGgsIHJldHVybiB0aGUgZXhpc3RpbmcgaW5zdGFuY2UuXG4gKlxuICogQHBhcmFtIGRiUGF0aCAtIFBhdGggdG8gdGhlIGRhdGFiYXNlIGRpcmVjdG9yeVxuICogQHJldHVybnMgVGhlIHNvY2tldCBwYXRoIGZvciBjb25uZWN0aW5nXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydEVtYmVkZGVkU2VydmVyKGRiUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgYWJzb2x1dGVQYXRoID0gcGF0aC5yZXNvbHZlKGRiUGF0aCk7XG4gIGNvbnN0IHNvY2tldFBhdGggPSBwYXRoLmpvaW4oYWJzb2x1dGVQYXRoLCAnc29jaGRiLnNvY2snKTtcblxuICAvLyBDaGVjayBpZiBzZXJ2ZXIgYWxyZWFkeSBydW5uaW5nIGZvciB0aGlzIHBhdGhcbiAgY29uc3QgZXhpc3RpbmcgPSBydW5uaW5nU2VydmVycy5nZXQoYWJzb2x1dGVQYXRoKTtcbiAgaWYgKGV4aXN0aW5nICYmIGV4aXN0aW5nLnByb2Nlc3MuZXhpdENvZGUgPT09IG51bGwpIHtcbiAgICAvLyBTZXJ2ZXIgc3RpbGwgcnVubmluZ1xuICAgIHJldHVybiBzb2NrZXRQYXRoO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgYW5vdGhlciBwcm9jZXNzIGFscmVhZHkgaGFzIGEgc2VydmVyIHJ1bm5pbmdcbiAgaWYgKGZzLmV4aXN0c1N5bmMoc29ja2V0UGF0aCkpIHtcbiAgICB0cnkge1xuICAgICAgLy8gVHJ5IHRvIGNvbm5lY3QgLSBpZiBzdWNjZXNzZnVsLCBzZXJ2ZXIgaXMgcnVubmluZ1xuICAgICAgYXdhaXQgd2FpdEZvclNvY2tldChzb2NrZXRQYXRoLCAxMDAwKTtcbiAgICAgIHJldHVybiBzb2NrZXRQYXRoO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gU29ja2V0IGV4aXN0cyBidXQgZGVhZCAtIGNsZWFuIGl0IHVwXG4gICAgICB0cnkge1xuICAgICAgICBmcy51bmxpbmtTeW5jKHNvY2tldFBhdGgpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIElnbm9yZVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIEVuc3VyZSBkYXRhYmFzZSBkaXJlY3RvcnkgZXhpc3RzXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNvbHV0ZVBhdGgpKSB7XG4gICAgZnMubWtkaXJTeW5jKGFic29sdXRlUGF0aCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH1cblxuICAvLyBGaW5kIGFuZCBzcGF3biBzZXJ2ZXJcbiAgY29uc3Qgc2VydmVyQmluYXJ5ID0gZmluZFNlcnZlckJpbmFyeSgpO1xuICBcbiAgY29uc3Qgc2VydmVyUHJvY2VzcyA9IHNwYXduKHNlcnZlckJpbmFyeSwgWyctLWRiJywgYWJzb2x1dGVQYXRoLCAnLS1zb2NrZXQnLCBzb2NrZXRQYXRoXSwge1xuICAgIHN0ZGlvOiBbJ2lnbm9yZScsICdwaXBlJywgJ3BpcGUnXSxcbiAgICBkZXRhY2hlZDogZmFsc2UsXG4gIH0pO1xuXG4gIC8vIENvbGxlY3Qgc3RkZXJyIGZvciBlcnJvciByZXBvcnRpbmdcbiAgbGV0IHN0ZGVyck91dHB1dCA9ICcnO1xuICBzZXJ2ZXJQcm9jZXNzLnN0ZGVycj8ub24oJ2RhdGEnLCAoZGF0YSkgPT4ge1xuICAgIHN0ZGVyck91dHB1dCArPSBkYXRhLnRvU3RyaW5nKCk7XG4gIH0pO1xuXG4gIC8vIEhhbmRsZSBwcm9jZXNzIGV4aXRcbiAgc2VydmVyUHJvY2Vzcy5vbignZXhpdCcsIChjb2RlLCBzaWduYWwpID0+IHtcbiAgICBydW5uaW5nU2VydmVycy5kZWxldGUoYWJzb2x1dGVQYXRoKTtcbiAgICBpZiAoY29kZSAhPT0gMCAmJiBjb2RlICE9PSBudWxsKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBTb2NoREIgc2VydmVyIGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfTogJHtzdGRlcnJPdXRwdXR9YCk7XG4gICAgfVxuICB9KTtcblxuICBzZXJ2ZXJQcm9jZXNzLm9uKCdlcnJvcicsIChlcnIpID0+IHtcbiAgICBydW5uaW5nU2VydmVycy5kZWxldGUoYWJzb2x1dGVQYXRoKTtcbiAgICBjb25zb2xlLmVycm9yKGBGYWlsZWQgdG8gc3RhcnQgU29jaERCIHNlcnZlcjogJHtlcnIubWVzc2FnZX1gKTtcbiAgfSk7XG5cbiAgLy8gU3RvcmUgaW5zdGFuY2VcbiAgcnVubmluZ1NlcnZlcnMuc2V0KGFic29sdXRlUGF0aCwge1xuICAgIHByb2Nlc3M6IHNlcnZlclByb2Nlc3MsXG4gICAgc29ja2V0UGF0aCxcbiAgICBkYlBhdGg6IGFic29sdXRlUGF0aCxcbiAgfSk7XG5cbiAgLy8gV2FpdCBmb3Igc2VydmVyIHRvIGJlIHJlYWR5XG4gIHRyeSB7XG4gICAgYXdhaXQgd2FpdEZvclNvY2tldChzb2NrZXRQYXRoLCAxMDAwMCk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIC8vIEtpbGwgdGhlIHByb2Nlc3MgaWYgaXQgZGlkbid0IHN0YXJ0IHByb3Blcmx5XG4gICAgc2VydmVyUHJvY2Vzcy5raWxsKCk7XG4gICAgcnVubmluZ1NlcnZlcnMuZGVsZXRlKGFic29sdXRlUGF0aCk7XG4gICAgdGhyb3cgbmV3IERhdGFiYXNlRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIHN0YXJ0IGVtYmVkZGVkIHNlcnZlcjogJHtzdGRlcnJPdXRwdXQgfHwgKGVyciBhcyBFcnJvcikubWVzc2FnZX1gXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBzb2NrZXRQYXRoO1xufVxuXG4vKipcbiAqIFN0b3AgdGhlIGVtYmVkZGVkIHNlcnZlciBmb3IgYSBzcGVjaWZpYyBkYXRhYmFzZSBwYXRoXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdG9wRW1iZWRkZWRTZXJ2ZXIoZGJQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYWJzb2x1dGVQYXRoID0gcGF0aC5yZXNvbHZlKGRiUGF0aCk7XG4gIGNvbnN0IGluc3RhbmNlID0gcnVubmluZ1NlcnZlcnMuZ2V0KGFic29sdXRlUGF0aCk7XG5cbiAgaWYgKCFpbnN0YW5jZSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFNlbmQgU0lHVEVSTSBhbmQgd2FpdCBmb3IgZ3JhY2VmdWwgc2h1dGRvd25cbiAgaW5zdGFuY2UucHJvY2Vzcy5raWxsKCdTSUdURVJNJyk7XG5cbiAgLy8gV2FpdCBmb3IgcHJvY2VzcyB0byBleGl0IChtYXggNSBzZWNvbmRzKVxuICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIC8vIEZvcmNlIGtpbGwgaWYgc3RpbGwgcnVubmluZ1xuICAgICAgaWYgKGluc3RhbmNlLnByb2Nlc3MuZXhpdENvZGUgPT09IG51bGwpIHtcbiAgICAgICAgaW5zdGFuY2UucHJvY2Vzcy5raWxsKCdTSUdLSUxMJyk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKCk7XG4gICAgfSwgNTAwMCk7XG5cbiAgICBpbnN0YW5jZS5wcm9jZXNzLm9uKCdleGl0JywgKCkgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBydW5uaW5nU2VydmVycy5kZWxldGUoYWJzb2x1dGVQYXRoKTtcblxuICAvLyBDbGVhbiB1cCBzb2NrZXQgZmlsZVxuICB0cnkge1xuICAgIGlmIChmcy5leGlzdHNTeW5jKGluc3RhbmNlLnNvY2tldFBhdGgpKSB7XG4gICAgICBmcy51bmxpbmtTeW5jKGluc3RhbmNlLnNvY2tldFBhdGgpO1xuICAgIH1cbiAgfSBjYXRjaCB7XG4gICAgLy8gSWdub3JlIGNsZWFudXAgZXJyb3JzXG4gIH1cbn1cblxuLyoqXG4gKiBTdG9wIGFsbCBydW5uaW5nIGVtYmVkZGVkIHNlcnZlcnNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0b3BBbGxFbWJlZGRlZFNlcnZlcnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHN0b3BQcm9taXNlczogUHJvbWlzZTx2b2lkPltdID0gW107XG4gIGZvciAoY29uc3QgW2RiUGF0aF0gb2YgcnVubmluZ1NlcnZlcnMpIHtcbiAgICBzdG9wUHJvbWlzZXMucHVzaChzdG9wRW1iZWRkZWRTZXJ2ZXIoZGJQYXRoKSk7XG4gIH1cbiAgYXdhaXQgUHJvbWlzZS5hbGwoc3RvcFByb21pc2VzKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBlbWJlZGRlZCBzZXJ2ZXIgaXMgcnVubmluZyBmb3IgYSBkYXRhYmFzZSBwYXRoXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NlcnZlclJ1bm5pbmcoZGJQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgYWJzb2x1dGVQYXRoID0gcGF0aC5yZXNvbHZlKGRiUGF0aCk7XG4gIGNvbnN0IGluc3RhbmNlID0gcnVubmluZ1NlcnZlcnMuZ2V0KGFic29sdXRlUGF0aCk7XG4gIHJldHVybiBpbnN0YW5jZSAhPT0gdW5kZWZpbmVkICYmIGluc3RhbmNlLnByb2Nlc3MuZXhpdENvZGUgPT09IG51bGw7XG59XG5cbi8vIENsZWFudXAgb24gcHJvY2VzcyBleGl0XG5wcm9jZXNzLm9uKCdleGl0JywgKCkgPT4ge1xuICBmb3IgKGNvbnN0IGluc3RhbmNlIG9mIHJ1bm5pbmdTZXJ2ZXJzLnZhbHVlcygpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGluc3RhbmNlLnByb2Nlc3Mua2lsbCgnU0lHS0lMTCcpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gSWdub3JlXG4gICAgfVxuICB9XG59KTtcblxucHJvY2Vzcy5vbignU0lHSU5UJywgYXN5bmMgKCkgPT4ge1xuICBhd2FpdCBzdG9wQWxsRW1iZWRkZWRTZXJ2ZXJzKCk7XG4gIHByb2Nlc3MuZXhpdCgwKTtcbn0pO1xuXG5wcm9jZXNzLm9uKCdTSUdURVJNJywgYXN5bmMgKCkgPT4ge1xuICBhd2FpdCBzdG9wQWxsRW1iZWRkZWRTZXJ2ZXJzKCk7XG4gIHByb2Nlc3MuZXhpdCgwKTtcbn0pO1xuIl19