@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,80 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SochDB Bulk CLI Wrapper
5
+ * Automatically locates and runs the platform-specific binary.
6
+ */
7
+
8
+ const os = require('os');
9
+ const path = require('path');
10
+ const { spawn } = require('child_process');
11
+ const fs = require('fs');
12
+
13
+ function getPlatformBinary() {
14
+ const platform = os.platform();
15
+ const arch = os.arch();
16
+
17
+ let target = '';
18
+ let ext = '';
19
+
20
+ if (platform === 'darwin') {
21
+ target = arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin';
22
+ } else if (platform === 'linux') {
23
+ target = arch === 'arm64' ? 'aarch64-unknown-linux-gnu' : 'x86_64-unknown-linux-gnu';
24
+ } else if (platform === 'win32') {
25
+ target = 'x86_64-pc-windows-msvc';
26
+ ext = '.exe';
27
+ } else {
28
+ throw new Error(`Unsupported platform: ${platform} ${arch}`);
29
+ }
30
+
31
+ // Look for bundled binary
32
+ const binName = `sochdb-bulk${ext}`;
33
+ const bundledPath = path.resolve(__dirname, '..', '_bin', target, binName);
34
+
35
+ if (fs.existsSync(bundledPath)) {
36
+ return bundledPath;
37
+ }
38
+
39
+ // Fallback: Check environment variable
40
+ if (process.env.SOCHDB_BULK_PATH) {
41
+ return process.env.SOCHDB_BULK_PATH;
42
+ }
43
+
44
+ throw new Error(`
45
+ sochdb-bulk binary not found!
46
+ Searched at: ${bundledPath}
47
+
48
+ To fix:
49
+ 1. Reinstall the package: npm install --force @sushanth/sochdb
50
+ 2. Or set SOCHDB_BULK_PATH environment variable
51
+ `);
52
+ }
53
+
54
+ try {
55
+ const binPath = getPlatformBinary();
56
+
57
+ const child = spawn(binPath, process.argv.slice(2), {
58
+ stdio: 'inherit'
59
+ });
60
+
61
+ child.on('exit', (code) => {
62
+ process.exit(code || 0);
63
+ });
64
+
65
+ child.on('error', (err) => {
66
+ console.error(`Failed to start sochdb-bulk: ${err.message}`);
67
+ process.exit(1);
68
+ });
69
+
70
+ const signals = ['SIGINT', 'SIGTERM'];
71
+ signals.forEach(signal => {
72
+ process.on(signal, () => {
73
+ child.kill(signal);
74
+ });
75
+ });
76
+
77
+ } catch (err) {
78
+ console.error(`[sochdb-js] Error: ${err.message}`);
79
+ process.exit(1);
80
+ }
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SochDB gRPC Server CLI Wrapper
5
+ * Automatically locates and runs the platform-specific binary.
6
+ */
7
+
8
+ const os = require('os');
9
+ const path = require('path');
10
+ const { spawn } = require('child_process');
11
+ const fs = require('fs');
12
+
13
+ function getPlatformBinary() {
14
+ const platform = os.platform();
15
+ const arch = os.arch();
16
+
17
+ let target = '';
18
+ let ext = '';
19
+
20
+ if (platform === 'darwin') {
21
+ target = arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin';
22
+ } else if (platform === 'linux') {
23
+ target = arch === 'arm64' ? 'aarch64-unknown-linux-gnu' : 'x86_64-unknown-linux-gnu';
24
+ } else if (platform === 'win32') {
25
+ target = 'x86_64-pc-windows-msvc';
26
+ ext = '.exe';
27
+ } else {
28
+ throw new Error(`Unsupported platform: ${platform} ${arch}`);
29
+ }
30
+
31
+ // Look for bundled binary
32
+ const binName = `sochdb-grpc-server${ext}`;
33
+ const bundledPath = path.resolve(__dirname, '..', '_bin', target, binName);
34
+
35
+ if (fs.existsSync(bundledPath)) {
36
+ return bundledPath;
37
+ }
38
+
39
+ // Fallback: Check environment variable
40
+ if (process.env.SOCHDB_GRPC_SERVER_PATH) {
41
+ return process.env.SOCHDB_GRPC_SERVER_PATH;
42
+ }
43
+
44
+ throw new Error(`
45
+ sochdb-grpc-server binary not found!
46
+ Searched at: ${bundledPath}
47
+
48
+ To fix:
49
+ 1. Reinstall the package: npm install --force @sushanth/sochdb
50
+ 2. Or set SOCHDB_GRPC_SERVER_PATH environment variable
51
+ `);
52
+ }
53
+
54
+ try {
55
+ const binPath = getPlatformBinary();
56
+
57
+ const child = spawn(binPath, process.argv.slice(2), {
58
+ stdio: 'inherit'
59
+ });
60
+
61
+ child.on('exit', (code) => {
62
+ process.exit(code || 0);
63
+ });
64
+
65
+ child.on('error', (err) => {
66
+ console.error(`Failed to start sochdb-grpc-server: ${err.message}`);
67
+ process.exit(1);
68
+ });
69
+
70
+ const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
71
+ signals.forEach(signal => {
72
+ process.on(signal, () => {
73
+ child.kill(signal);
74
+ });
75
+ });
76
+
77
+ } catch (err) {
78
+ console.error(`[sochdb-js] Error: ${err.message}`);
79
+ process.exit(1);
80
+ }
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SochDB Server CLI Wrapper
5
+ * Automatically locates and runs the platform-specific binary.
6
+ */
7
+
8
+ const os = require('os');
9
+ const path = require('path');
10
+ const { spawn } = require('child_process');
11
+ const fs = require('fs');
12
+
13
+ function getPlatformBinary() {
14
+ const platform = os.platform();
15
+ const arch = os.arch();
16
+
17
+ let target = '';
18
+ let ext = '';
19
+
20
+ if (platform === 'darwin') {
21
+ target = arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin';
22
+ } else if (platform === 'linux') {
23
+ target = arch === 'arm64' ? 'aarch64-unknown-linux-gnu' : 'x86_64-unknown-linux-gnu';
24
+ } else if (platform === 'win32') {
25
+ target = 'x86_64-pc-windows-msvc';
26
+ ext = '.exe';
27
+ } else {
28
+ throw new Error(`Unsupported platform: ${platform} ${arch}`);
29
+ }
30
+
31
+ // Look for bundled binary
32
+ const binName = `sochdb-server${ext}`;
33
+ const bundledPath = path.resolve(__dirname, '..', '_bin', target, binName);
34
+
35
+ if (fs.existsSync(bundledPath)) {
36
+ return bundledPath;
37
+ }
38
+
39
+ // Fallback: Check environment variable
40
+ if (process.env.SOCHDB_SERVER_PATH) {
41
+ return process.env.SOCHDB_SERVER_PATH;
42
+ }
43
+
44
+ throw new Error(`
45
+ sochdb-server binary not found!
46
+ Searched at: ${bundledPath}
47
+
48
+ To fix:
49
+ 1. Reinstall the package: npm install --force @sushanth/sochdb
50
+ 2. Or set SOCHDB_SERVER_PATH environment variable
51
+ `);
52
+ }
53
+
54
+ try {
55
+ const binPath = getPlatformBinary();
56
+
57
+ // Spawn with inherited stdio
58
+ const child = spawn(binPath, process.argv.slice(2), {
59
+ stdio: 'inherit'
60
+ });
61
+
62
+ child.on('exit', (code) => {
63
+ process.exit(code || 0);
64
+ });
65
+
66
+ child.on('error', (err) => {
67
+ console.error(`Failed to start sochdb-server: ${err.message}`);
68
+ process.exit(1);
69
+ });
70
+
71
+ // Handle signals
72
+ const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
73
+ signals.forEach(signal => {
74
+ process.on(signal, () => {
75
+ if (child.kill(signal)) {
76
+ // Wait specifically for child exit
77
+ }
78
+ });
79
+ });
80
+
81
+ } catch (err) {
82
+ console.error(`[sochdb-js] Error: ${err.message}`);
83
+ process.exit(1);
84
+ }
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ /**
3
+ * SochDB Analytics - Anonymous usage tracking with PostHog
4
+ *
5
+ * This module provides anonymous, privacy-respecting analytics to help
6
+ * improve SochDB. All tracking can be disabled by setting:
7
+ *
8
+ * SOCHDB_DISABLE_ANALYTICS=true
9
+ *
10
+ * No personally identifiable information (PII) is collected. Only aggregate
11
+ * usage patterns are tracked to understand:
12
+ * - Which features are most used
13
+ * - Performance characteristics
14
+ * - Error patterns for debugging
15
+ *
16
+ * Copyright 2025 Sushanth (https://github.com/sushanthpy)
17
+ * Licensed under the Apache License, Version 2.0
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.isAnalyticsDisabled = isAnalyticsDisabled;
21
+ exports.capture = capture;
22
+ exports.captureError = captureError;
23
+ exports.shutdown = shutdown;
24
+ exports.trackDatabaseOpen = trackDatabaseOpen;
25
+ const crypto_1 = require("crypto");
26
+ const os_1 = require("os");
27
+ // PostHog configuration
28
+ const POSTHOG_API_KEY = "phc_zf0hm6ZmPUJj1pM07Kigqvphh1ClhKX1NahRU4G0bfu";
29
+ const POSTHOG_HOST = "https://us.i.posthog.com";
30
+ // Lazy-loaded PostHog client
31
+ let posthogClient = null;
32
+ let posthogInitialized = false;
33
+ /**
34
+ * Check if analytics is disabled via environment variable.
35
+ *
36
+ * Analytics is disabled when SOCHDB_DISABLE_ANALYTICS is set to 'true', '1', 'yes', or 'on'.
37
+ *
38
+ * @returns true if analytics is disabled
39
+ */
40
+ function isAnalyticsDisabled() {
41
+ const disableVar = (process.env.SOCHDB_DISABLE_ANALYTICS || "").toLowerCase();
42
+ return ["true", "1", "yes", "on"].includes(disableVar);
43
+ }
44
+ /**
45
+ * Generate a stable anonymous ID for this machine.
46
+ *
47
+ * Uses a hash of machine-specific but non-identifying information.
48
+ * The same machine will always get the same ID, but the ID cannot
49
+ * be reversed to identify the machine.
50
+ */
51
+ function getAnonymousId() {
52
+ try {
53
+ const machineInfo = [
54
+ (0, os_1.hostname)(),
55
+ (0, os_1.platform)(),
56
+ (0, os_1.arch)(),
57
+ process.getuid?.() ?? "windows",
58
+ ].join("|");
59
+ return (0, crypto_1.createHash)("sha256").update(machineInfo).digest("hex").slice(0, 16);
60
+ }
61
+ catch {
62
+ return "anonymous";
63
+ }
64
+ }
65
+ /**
66
+ * Lazily initialize PostHog client.
67
+ */
68
+ async function getPosthogClient() {
69
+ if (isAnalyticsDisabled()) {
70
+ return null;
71
+ }
72
+ if (posthogInitialized) {
73
+ return posthogClient;
74
+ }
75
+ posthogInitialized = true;
76
+ try {
77
+ // Use require to avoid TypeScript checking the optional module
78
+ // This allows the SDK to work without posthog-node installed
79
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
80
+ const posthogModule = require("posthog-node");
81
+ const { PostHog } = posthogModule;
82
+ posthogClient = new PostHog(POSTHOG_API_KEY, {
83
+ host: POSTHOG_HOST,
84
+ });
85
+ return posthogClient;
86
+ }
87
+ catch {
88
+ // posthog-node not installed or error - analytics disabled
89
+ return null;
90
+ }
91
+ }
92
+ /**
93
+ * Get the SDK version.
94
+ */
95
+ function getSdkVersion() {
96
+ try {
97
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
98
+ const pkg = require("../package.json");
99
+ return pkg.version || "unknown";
100
+ }
101
+ catch {
102
+ return "unknown";
103
+ }
104
+ }
105
+ /**
106
+ * Capture an analytics event.
107
+ *
108
+ * This function is a no-op if:
109
+ * - SOCHDB_DISABLE_ANALYTICS=true
110
+ * - posthog-node package is not installed
111
+ * - Any error occurs (fails silently)
112
+ *
113
+ * @param event - Event name (e.g., "database_opened", "vector_search")
114
+ * @param properties - Optional event properties
115
+ * @param distinctId - Optional distinct ID (defaults to anonymous machine ID)
116
+ */
117
+ async function capture(event, properties, distinctId) {
118
+ if (isAnalyticsDisabled()) {
119
+ return;
120
+ }
121
+ try {
122
+ const client = await getPosthogClient();
123
+ if (!client) {
124
+ return;
125
+ }
126
+ // Build properties with SDK context
127
+ const eventProperties = {
128
+ sdk: "nodejs",
129
+ sdk_version: getSdkVersion(),
130
+ node_version: process.version,
131
+ os: (0, os_1.platform)(),
132
+ arch: (0, os_1.arch)(),
133
+ ...properties,
134
+ };
135
+ client.capture({
136
+ distinctId: distinctId || getAnonymousId(),
137
+ event,
138
+ properties: eventProperties,
139
+ });
140
+ // Flush to ensure event is sent immediately
141
+ await client.flush();
142
+ }
143
+ catch {
144
+ // Never let analytics break user code
145
+ }
146
+ }
147
+ /**
148
+ * Capture an error event for debugging.
149
+ *
150
+ * Only sends static information - no dynamic error messages.
151
+ *
152
+ * @param errorType - Static error category (e.g., "connection_error", "query_error", "timeout_error")
153
+ * @param location - Static code location (e.g., "database.open", "query.execute", "transaction.commit")
154
+ * @param properties - Optional additional static properties only
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * captureError('connection_error', 'database.open');
159
+ * captureError('query_error', 'sql.execute', { query_type: 'SELECT' });
160
+ * ```
161
+ */
162
+ async function captureError(errorType, location, properties) {
163
+ await capture("error", {
164
+ error_type: errorType,
165
+ location,
166
+ ...properties,
167
+ });
168
+ }
169
+ /**
170
+ * Flush any pending events and shutdown the client.
171
+ */
172
+ async function shutdown() {
173
+ if (isAnalyticsDisabled()) {
174
+ return;
175
+ }
176
+ try {
177
+ if (posthogClient) {
178
+ await posthogClient.shutdown();
179
+ }
180
+ }
181
+ catch {
182
+ // Ignore shutdown errors
183
+ }
184
+ }
185
+ // Convenience functions for common events
186
+ /**
187
+ * Track database open event.
188
+ */
189
+ async function trackDatabaseOpen(dbPath, mode = "embedded") {
190
+ await capture("database_opened", {
191
+ mode,
192
+ has_custom_path: dbPath !== ":memory:",
193
+ });
194
+ }
195
+ // Vector search and batch insert tracking removed - only database_opened is tracked
196
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbHl0aWNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FuYWx5dGljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7O0FBb0JILGtEQUtDO0FBbUZELDBCQW9DQztBQWlCRCxvQ0FVQztBQUtELDRCQVlDO0FBT0QsOENBUUM7QUF6TUQsbUNBQW9DO0FBQ3BDLDJCQUF1RDtBQUV2RCx3QkFBd0I7QUFDeEIsTUFBTSxlQUFlLEdBQUcsaURBQWlELENBQUM7QUFDMUUsTUFBTSxZQUFZLEdBQUcsMEJBQTBCLENBQUM7QUFFaEQsNkJBQTZCO0FBQzdCLElBQUksYUFBYSxHQUFRLElBQUksQ0FBQztBQUM5QixJQUFJLGtCQUFrQixHQUFHLEtBQUssQ0FBQztBQUUvQjs7Ozs7O0dBTUc7QUFDSCxTQUFnQixtQkFBbUI7SUFDakMsTUFBTSxVQUFVLEdBQUcsQ0FDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsSUFBSSxFQUFFLENBQzNDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDaEIsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUN6RCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxjQUFjO0lBQ3JCLElBQUksQ0FBQztRQUNILE1BQU0sV0FBVyxHQUFHO1lBQ2xCLElBQUEsYUFBUSxHQUFFO1lBQ1YsSUFBQSxhQUFRLEdBQUU7WUFDVixJQUFBLFNBQUksR0FBRTtZQUNOLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLFNBQVM7U0FDaEMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFWixPQUFPLElBQUEsbUJBQVUsRUFBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsZ0JBQWdCO0lBQzdCLElBQUksbUJBQW1CLEVBQUUsRUFBRSxDQUFDO1FBQzFCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELElBQUksa0JBQWtCLEVBQUUsQ0FBQztRQUN2QixPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO0lBRUQsa0JBQWtCLEdBQUcsSUFBSSxDQUFDO0lBRTFCLElBQUksQ0FBQztRQUNILCtEQUErRDtRQUMvRCw2REFBNkQ7UUFDN0QsOERBQThEO1FBQzlELE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUM5QyxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsYUFBYSxDQUFDO1FBQ2xDLGFBQWEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxlQUFlLEVBQUU7WUFDM0MsSUFBSSxFQUFFLFlBQVk7U0FDbkIsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLDJEQUEyRDtRQUMzRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGFBQWE7SUFDcEIsSUFBSSxDQUFDO1FBQ0gsOERBQThEO1FBQzlELE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3ZDLE9BQU8sR0FBRyxDQUFDLE9BQU8sSUFBSSxTQUFTLENBQUM7SUFDbEMsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDO0FBTUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSSxLQUFLLFVBQVUsT0FBTyxDQUMzQixLQUFhLEVBQ2IsVUFBNEIsRUFDNUIsVUFBbUI7SUFFbkIsSUFBSSxtQkFBbUIsRUFBRSxFQUFFLENBQUM7UUFDMUIsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLGdCQUFnQixFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osT0FBTztRQUNULENBQUM7UUFFRCxvQ0FBb0M7UUFDcEMsTUFBTSxlQUFlLEdBQW9CO1lBQ3ZDLEdBQUcsRUFBRSxRQUFRO1lBQ2IsV0FBVyxFQUFFLGFBQWEsRUFBRTtZQUM1QixZQUFZLEVBQUUsT0FBTyxDQUFDLE9BQU87WUFDN0IsRUFBRSxFQUFFLElBQUEsYUFBUSxHQUFFO1lBQ2QsSUFBSSxFQUFFLElBQUEsU0FBSSxHQUFFO1lBQ1osR0FBRyxVQUFVO1NBQ2QsQ0FBQztRQUVGLE1BQU0sQ0FBQyxPQUFPLENBQUM7WUFDYixVQUFVLEVBQUUsVUFBVSxJQUFJLGNBQWMsRUFBRTtZQUMxQyxLQUFLO1lBQ0wsVUFBVSxFQUFFLGVBQWU7U0FDNUIsQ0FBQyxDQUFDO1FBRUgsNENBQTRDO1FBQzVDLE1BQU0sTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxzQ0FBc0M7SUFDeEMsQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNJLEtBQUssVUFBVSxZQUFZLENBQ2hDLFNBQWlCLEVBQ2pCLFFBQWdCLEVBQ2hCLFVBQTRCO0lBRTVCLE1BQU0sT0FBTyxDQUFDLE9BQU8sRUFBRTtRQUNyQixVQUFVLEVBQUUsU0FBUztRQUNyQixRQUFRO1FBQ1IsR0FBRyxVQUFVO0tBQ2QsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOztHQUVHO0FBQ0ksS0FBSyxVQUFVLFFBQVE7SUFDNUIsSUFBSSxtQkFBbUIsRUFBRSxFQUFFLENBQUM7UUFDMUIsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLENBQUM7UUFDSCxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ2xCLE1BQU0sYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2pDLENBQUM7SUFDSCxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AseUJBQXlCO0lBQzNCLENBQUM7QUFDSCxDQUFDO0FBRUQsMENBQTBDO0FBRTFDOztHQUVHO0FBQ0ksS0FBSyxVQUFVLGlCQUFpQixDQUNyQyxNQUFjLEVBQ2QsT0FBZSxVQUFVO0lBRXpCLE1BQU0sT0FBTyxDQUFDLGlCQUFpQixFQUFFO1FBQy9CLElBQUk7UUFDSixlQUFlLEVBQUUsTUFBTSxLQUFLLFVBQVU7S0FDdkMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELG9GQUFvRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU29jaERCIEFuYWx5dGljcyAtIEFub255bW91cyB1c2FnZSB0cmFja2luZyB3aXRoIFBvc3RIb2dcbiAqXG4gKiBUaGlzIG1vZHVsZSBwcm92aWRlcyBhbm9ueW1vdXMsIHByaXZhY3ktcmVzcGVjdGluZyBhbmFseXRpY3MgdG8gaGVscFxuICogaW1wcm92ZSBTb2NoREIuIEFsbCB0cmFja2luZyBjYW4gYmUgZGlzYWJsZWQgYnkgc2V0dGluZzpcbiAqXG4gKiAgICAgU09DSERCX0RJU0FCTEVfQU5BTFlUSUNTPXRydWVcbiAqXG4gKiBObyBwZXJzb25hbGx5IGlkZW50aWZpYWJsZSBpbmZvcm1hdGlvbiAoUElJKSBpcyBjb2xsZWN0ZWQuIE9ubHkgYWdncmVnYXRlXG4gKiB1c2FnZSBwYXR0ZXJucyBhcmUgdHJhY2tlZCB0byB1bmRlcnN0YW5kOlxuICogLSBXaGljaCBmZWF0dXJlcyBhcmUgbW9zdCB1c2VkXG4gKiAtIFBlcmZvcm1hbmNlIGNoYXJhY3RlcmlzdGljc1xuICogLSBFcnJvciBwYXR0ZXJucyBmb3IgZGVidWdnaW5nXG4gKlxuICogQ29weXJpZ2h0IDIwMjUgU3VzaGFudGggKGh0dHBzOi8vZ2l0aHViLmNvbS9zdXNoYW50aHB5KVxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMFxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tIFwiY3J5cHRvXCI7XG5pbXBvcnQgeyBob3N0bmFtZSwgcGxhdGZvcm0sIGFyY2gsIHJlbGVhc2UgfSBmcm9tIFwib3NcIjtcblxuLy8gUG9zdEhvZyBjb25maWd1cmF0aW9uXG5jb25zdCBQT1NUSE9HX0FQSV9LRVkgPSBcInBoY196ZjBobTZabVBVSmoxcE0wN0tpZ3F2cGhoMUNsaEtYMU5haFJVNEcwYmZ1XCI7XG5jb25zdCBQT1NUSE9HX0hPU1QgPSBcImh0dHBzOi8vdXMuaS5wb3N0aG9nLmNvbVwiO1xuXG4vLyBMYXp5LWxvYWRlZCBQb3N0SG9nIGNsaWVudFxubGV0IHBvc3Rob2dDbGllbnQ6IGFueSA9IG51bGw7XG5sZXQgcG9zdGhvZ0luaXRpYWxpemVkID0gZmFsc2U7XG5cbi8qKlxuICogQ2hlY2sgaWYgYW5hbHl0aWNzIGlzIGRpc2FibGVkIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZS5cbiAqIFxuICogQW5hbHl0aWNzIGlzIGRpc2FibGVkIHdoZW4gU09DSERCX0RJU0FCTEVfQU5BTFlUSUNTIGlzIHNldCB0byAndHJ1ZScsICcxJywgJ3llcycsIG9yICdvbicuXG4gKiBcbiAqIEByZXR1cm5zIHRydWUgaWYgYW5hbHl0aWNzIGlzIGRpc2FibGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0FuYWx5dGljc0Rpc2FibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCBkaXNhYmxlVmFyID0gKFxuICAgIHByb2Nlc3MuZW52LlNPQ0hEQl9ESVNBQkxFX0FOQUxZVElDUyB8fCBcIlwiXG4gICkudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIFtcInRydWVcIiwgXCIxXCIsIFwieWVzXCIsIFwib25cIl0uaW5jbHVkZXMoZGlzYWJsZVZhcik7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgYSBzdGFibGUgYW5vbnltb3VzIElEIGZvciB0aGlzIG1hY2hpbmUuXG4gKlxuICogVXNlcyBhIGhhc2ggb2YgbWFjaGluZS1zcGVjaWZpYyBidXQgbm9uLWlkZW50aWZ5aW5nIGluZm9ybWF0aW9uLlxuICogVGhlIHNhbWUgbWFjaGluZSB3aWxsIGFsd2F5cyBnZXQgdGhlIHNhbWUgSUQsIGJ1dCB0aGUgSUQgY2Fubm90XG4gKiBiZSByZXZlcnNlZCB0byBpZGVudGlmeSB0aGUgbWFjaGluZS5cbiAqL1xuZnVuY3Rpb24gZ2V0QW5vbnltb3VzSWQoKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtYWNoaW5lSW5mbyA9IFtcbiAgICAgIGhvc3RuYW1lKCksXG4gICAgICBwbGF0Zm9ybSgpLFxuICAgICAgYXJjaCgpLFxuICAgICAgcHJvY2Vzcy5nZXR1aWQ/LigpID8/IFwid2luZG93c1wiLFxuICAgIF0uam9pbihcInxcIik7XG5cbiAgICByZXR1cm4gY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUobWFjaGluZUluZm8pLmRpZ2VzdChcImhleFwiKS5zbGljZSgwLCAxNik7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBcImFub255bW91c1wiO1xuICB9XG59XG5cbi8qKlxuICogTGF6aWx5IGluaXRpYWxpemUgUG9zdEhvZyBjbGllbnQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldFBvc3Rob2dDbGllbnQoKTogUHJvbWlzZTxhbnk+IHtcbiAgaWYgKGlzQW5hbHl0aWNzRGlzYWJsZWQoKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgaWYgKHBvc3Rob2dJbml0aWFsaXplZCkge1xuICAgIHJldHVybiBwb3N0aG9nQ2xpZW50O1xuICB9XG5cbiAgcG9zdGhvZ0luaXRpYWxpemVkID0gdHJ1ZTtcblxuICB0cnkge1xuICAgIC8vIFVzZSByZXF1aXJlIHRvIGF2b2lkIFR5cGVTY3JpcHQgY2hlY2tpbmcgdGhlIG9wdGlvbmFsIG1vZHVsZVxuICAgIC8vIFRoaXMgYWxsb3dzIHRoZSBTREsgdG8gd29yayB3aXRob3V0IHBvc3Rob2ctbm9kZSBpbnN0YWxsZWRcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIGNvbnN0IHBvc3Rob2dNb2R1bGUgPSByZXF1aXJlKFwicG9zdGhvZy1ub2RlXCIpO1xuICAgIGNvbnN0IHsgUG9zdEhvZyB9ID0gcG9zdGhvZ01vZHVsZTtcbiAgICBwb3N0aG9nQ2xpZW50ID0gbmV3IFBvc3RIb2coUE9TVEhPR19BUElfS0VZLCB7XG4gICAgICBob3N0OiBQT1NUSE9HX0hPU1QsXG4gICAgfSk7XG4gICAgcmV0dXJuIHBvc3Rob2dDbGllbnQ7XG4gIH0gY2F0Y2gge1xuICAgIC8vIHBvc3Rob2ctbm9kZSBub3QgaW5zdGFsbGVkIG9yIGVycm9yIC0gYW5hbHl0aWNzIGRpc2FibGVkXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXQgdGhlIFNESyB2ZXJzaW9uLlxuICovXG5mdW5jdGlvbiBnZXRTZGtWZXJzaW9uKCk6IHN0cmluZyB7XG4gIHRyeSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgICBjb25zdCBwa2cgPSByZXF1aXJlKFwiLi4vcGFja2FnZS5qc29uXCIpO1xuICAgIHJldHVybiBwa2cudmVyc2lvbiB8fCBcInVua25vd25cIjtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIFwidW5rbm93blwiO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRQcm9wZXJ0aWVzIHtcbiAgW2tleTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG51bGwgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQ2FwdHVyZSBhbiBhbmFseXRpY3MgZXZlbnQuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBhIG5vLW9wIGlmOlxuICogLSBTT0NIREJfRElTQUJMRV9BTkFMWVRJQ1M9dHJ1ZVxuICogLSBwb3N0aG9nLW5vZGUgcGFja2FnZSBpcyBub3QgaW5zdGFsbGVkXG4gKiAtIEFueSBlcnJvciBvY2N1cnMgKGZhaWxzIHNpbGVudGx5KVxuICpcbiAqIEBwYXJhbSBldmVudCAtIEV2ZW50IG5hbWUgKGUuZy4sIFwiZGF0YWJhc2Vfb3BlbmVkXCIsIFwidmVjdG9yX3NlYXJjaFwiKVxuICogQHBhcmFtIHByb3BlcnRpZXMgLSBPcHRpb25hbCBldmVudCBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0gZGlzdGluY3RJZCAtIE9wdGlvbmFsIGRpc3RpbmN0IElEIChkZWZhdWx0cyB0byBhbm9ueW1vdXMgbWFjaGluZSBJRClcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNhcHR1cmUoXG4gIGV2ZW50OiBzdHJpbmcsXG4gIHByb3BlcnRpZXM/OiBFdmVudFByb3BlcnRpZXMsXG4gIGRpc3RpbmN0SWQ/OiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoaXNBbmFseXRpY3NEaXNhYmxlZCgpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBnZXRQb3N0aG9nQ2xpZW50KCk7XG4gICAgaWYgKCFjbGllbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBCdWlsZCBwcm9wZXJ0aWVzIHdpdGggU0RLIGNvbnRleHRcbiAgICBjb25zdCBldmVudFByb3BlcnRpZXM6IEV2ZW50UHJvcGVydGllcyA9IHtcbiAgICAgIHNkazogXCJub2RlanNcIixcbiAgICAgIHNka192ZXJzaW9uOiBnZXRTZGtWZXJzaW9uKCksXG4gICAgICBub2RlX3ZlcnNpb246IHByb2Nlc3MudmVyc2lvbixcbiAgICAgIG9zOiBwbGF0Zm9ybSgpLFxuICAgICAgYXJjaDogYXJjaCgpLFxuICAgICAgLi4ucHJvcGVydGllcyxcbiAgICB9O1xuXG4gICAgY2xpZW50LmNhcHR1cmUoe1xuICAgICAgZGlzdGluY3RJZDogZGlzdGluY3RJZCB8fCBnZXRBbm9ueW1vdXNJZCgpLFxuICAgICAgZXZlbnQsXG4gICAgICBwcm9wZXJ0aWVzOiBldmVudFByb3BlcnRpZXMsXG4gICAgfSk7XG4gICAgXG4gICAgLy8gRmx1c2ggdG8gZW5zdXJlIGV2ZW50IGlzIHNlbnQgaW1tZWRpYXRlbHlcbiAgICBhd2FpdCBjbGllbnQuZmx1c2goKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gTmV2ZXIgbGV0IGFuYWx5dGljcyBicmVhayB1c2VyIGNvZGVcbiAgfVxufVxuXG4vKipcbiAqIENhcHR1cmUgYW4gZXJyb3IgZXZlbnQgZm9yIGRlYnVnZ2luZy5cbiAqXG4gKiBPbmx5IHNlbmRzIHN0YXRpYyBpbmZvcm1hdGlvbiAtIG5vIGR5bmFtaWMgZXJyb3IgbWVzc2FnZXMuXG4gKlxuICogQHBhcmFtIGVycm9yVHlwZSAtIFN0YXRpYyBlcnJvciBjYXRlZ29yeSAoZS5nLiwgXCJjb25uZWN0aW9uX2Vycm9yXCIsIFwicXVlcnlfZXJyb3JcIiwgXCJ0aW1lb3V0X2Vycm9yXCIpXG4gKiBAcGFyYW0gbG9jYXRpb24gLSBTdGF0aWMgY29kZSBsb2NhdGlvbiAoZS5nLiwgXCJkYXRhYmFzZS5vcGVuXCIsIFwicXVlcnkuZXhlY3V0ZVwiLCBcInRyYW5zYWN0aW9uLmNvbW1pdFwiKVxuICogQHBhcmFtIHByb3BlcnRpZXMgLSBPcHRpb25hbCBhZGRpdGlvbmFsIHN0YXRpYyBwcm9wZXJ0aWVzIG9ubHlcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY2FwdHVyZUVycm9yKCdjb25uZWN0aW9uX2Vycm9yJywgJ2RhdGFiYXNlLm9wZW4nKTtcbiAqIGNhcHR1cmVFcnJvcigncXVlcnlfZXJyb3InLCAnc3FsLmV4ZWN1dGUnLCB7IHF1ZXJ5X3R5cGU6ICdTRUxFQ1QnIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjYXB0dXJlRXJyb3IoXG4gIGVycm9yVHlwZTogc3RyaW5nLFxuICBsb2NhdGlvbjogc3RyaW5nLFxuICBwcm9wZXJ0aWVzPzogRXZlbnRQcm9wZXJ0aWVzXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgY2FwdHVyZShcImVycm9yXCIsIHtcbiAgICBlcnJvcl90eXBlOiBlcnJvclR5cGUsXG4gICAgbG9jYXRpb24sXG4gICAgLi4ucHJvcGVydGllcyxcbiAgfSk7XG59XG5cbi8qKlxuICogRmx1c2ggYW55IHBlbmRpbmcgZXZlbnRzIGFuZCBzaHV0ZG93biB0aGUgY2xpZW50LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2h1dGRvd24oKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChpc0FuYWx5dGljc0Rpc2FibGVkKCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB0cnkge1xuICAgIGlmIChwb3N0aG9nQ2xpZW50KSB7XG4gICAgICBhd2FpdCBwb3N0aG9nQ2xpZW50LnNodXRkb3duKCk7XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBJZ25vcmUgc2h1dGRvd24gZXJyb3JzXG4gIH1cbn1cblxuLy8gQ29udmVuaWVuY2UgZnVuY3Rpb25zIGZvciBjb21tb24gZXZlbnRzXG5cbi8qKlxuICogVHJhY2sgZGF0YWJhc2Ugb3BlbiBldmVudC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRyYWNrRGF0YWJhc2VPcGVuKFxuICBkYlBhdGg6IHN0cmluZyxcbiAgbW9kZTogc3RyaW5nID0gXCJlbWJlZGRlZFwiXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgY2FwdHVyZShcImRhdGFiYXNlX29wZW5lZFwiLCB7XG4gICAgbW9kZSxcbiAgICBoYXNfY3VzdG9tX3BhdGg6IGRiUGF0aCAhPT0gXCI6bWVtb3J5OlwiLFxuICB9KTtcbn1cblxuLy8gVmVjdG9yIHNlYXJjaCBhbmQgYmF0Y2ggaW5zZXJ0IHRyYWNraW5nIHJlbW92ZWQgLSBvbmx5IGRhdGFiYXNlX29wZW5lZCBpcyB0cmFja2VkXG4iXX0=