@querypanel/node-sdk 1.0.36 → 1.0.38
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 +20 -1
- package/dist/index.cjs +85 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +85 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -525,7 +525,6 @@ function sanitize2(value) {
|
|
|
525
525
|
}
|
|
526
526
|
|
|
527
527
|
// src/core/client.ts
|
|
528
|
-
import { createSign } from "crypto";
|
|
529
528
|
var ApiClient = class {
|
|
530
529
|
baseUrl;
|
|
531
530
|
privateKey;
|
|
@@ -533,6 +532,7 @@ var ApiClient = class {
|
|
|
533
532
|
defaultTenantId;
|
|
534
533
|
additionalHeaders;
|
|
535
534
|
fetchImpl;
|
|
535
|
+
cryptoKey = null;
|
|
536
536
|
constructor(baseUrl, privateKey, organizationId, options) {
|
|
537
537
|
if (!baseUrl) {
|
|
538
538
|
throw new Error("Base URL is required");
|
|
@@ -648,6 +648,66 @@ var ApiClient = class {
|
|
|
648
648
|
}
|
|
649
649
|
return headers;
|
|
650
650
|
}
|
|
651
|
+
/**
|
|
652
|
+
* Base64URL encode a string (works in both Node.js 18+ and Deno)
|
|
653
|
+
*/
|
|
654
|
+
base64UrlEncode(str) {
|
|
655
|
+
const bytes = new TextEncoder().encode(str);
|
|
656
|
+
let binary = "";
|
|
657
|
+
const chunkSize = 8192;
|
|
658
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
659
|
+
const chunk = bytes.slice(i, i + chunkSize);
|
|
660
|
+
binary += String.fromCharCode(...chunk);
|
|
661
|
+
}
|
|
662
|
+
const base64 = btoa(binary);
|
|
663
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Base64URL encode from Uint8Array (for binary data like signatures)
|
|
667
|
+
*/
|
|
668
|
+
base64UrlEncodeBytes(bytes) {
|
|
669
|
+
let binary = "";
|
|
670
|
+
const chunkSize = 8192;
|
|
671
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
672
|
+
const chunk = bytes.slice(i, i + chunkSize);
|
|
673
|
+
binary += String.fromCharCode(...chunk);
|
|
674
|
+
}
|
|
675
|
+
const base64 = btoa(binary);
|
|
676
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Import the private key into Web Crypto API format (cached after first import)
|
|
680
|
+
*/
|
|
681
|
+
async getCryptoKey() {
|
|
682
|
+
if (this.cryptoKey) {
|
|
683
|
+
return this.cryptoKey;
|
|
684
|
+
}
|
|
685
|
+
this.cryptoKey = await crypto.subtle.importKey(
|
|
686
|
+
"pkcs8",
|
|
687
|
+
this.privateKeyToArrayBuffer(this.privateKey),
|
|
688
|
+
{
|
|
689
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
690
|
+
hash: "SHA-256"
|
|
691
|
+
},
|
|
692
|
+
false,
|
|
693
|
+
["sign"]
|
|
694
|
+
);
|
|
695
|
+
return this.cryptoKey;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Convert PEM private key to ArrayBuffer for Web Crypto API
|
|
699
|
+
*/
|
|
700
|
+
privateKeyToArrayBuffer(pem) {
|
|
701
|
+
const pemHeader = "-----BEGIN PRIVATE KEY-----";
|
|
702
|
+
const pemFooter = "-----END PRIVATE KEY-----";
|
|
703
|
+
const pemContents = pem.replace(pemHeader, "").replace(pemFooter, "").replace(/\s/g, "");
|
|
704
|
+
const binaryString = atob(pemContents);
|
|
705
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
706
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
707
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
708
|
+
}
|
|
709
|
+
return bytes.buffer;
|
|
710
|
+
}
|
|
651
711
|
async generateJWT(tenantId, userId, scopes) {
|
|
652
712
|
const header = {
|
|
653
713
|
alg: "RS256",
|
|
@@ -659,19 +719,20 @@ var ApiClient = class {
|
|
|
659
719
|
};
|
|
660
720
|
if (userId) payload.userId = userId;
|
|
661
721
|
if (scopes?.length) payload.scopes = scopes;
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
const base64 = Buffer.from(json).toString("base64");
|
|
665
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
666
|
-
};
|
|
667
|
-
const encodedHeader = encodeJson(header);
|
|
668
|
-
const encodedPayload = encodeJson(payload);
|
|
722
|
+
const encodedHeader = this.base64UrlEncode(JSON.stringify(header));
|
|
723
|
+
const encodedPayload = this.base64UrlEncode(JSON.stringify(payload));
|
|
669
724
|
const data = `${encodedHeader}.${encodedPayload}`;
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
725
|
+
const key = await this.getCryptoKey();
|
|
726
|
+
const dataBytes = new TextEncoder().encode(data);
|
|
727
|
+
const signature = await crypto.subtle.sign(
|
|
728
|
+
{
|
|
729
|
+
name: "RSASSA-PKCS1-v1_5"
|
|
730
|
+
},
|
|
731
|
+
key,
|
|
732
|
+
dataBytes
|
|
733
|
+
);
|
|
734
|
+
const signatureBytes = new Uint8Array(signature);
|
|
735
|
+
const encodedSignature = this.base64UrlEncodeBytes(signatureBytes);
|
|
675
736
|
return `${data}.${encodedSignature}`;
|
|
676
737
|
}
|
|
677
738
|
};
|
|
@@ -756,13 +817,19 @@ var QueryEngine = class {
|
|
|
756
817
|
return sql;
|
|
757
818
|
}
|
|
758
819
|
const tenantField = metadata.tenantFieldName;
|
|
759
|
-
const paramKey = tenantField;
|
|
760
|
-
params[paramKey] = tenantId;
|
|
761
820
|
const normalizedSql = sql.toLowerCase();
|
|
762
821
|
if (normalizedSql.includes(tenantField.toLowerCase())) {
|
|
763
822
|
return sql;
|
|
764
823
|
}
|
|
765
|
-
|
|
824
|
+
let tenantPredicate;
|
|
825
|
+
if (metadata.dialect === "clickhouse") {
|
|
826
|
+
const paramKey = tenantField;
|
|
827
|
+
params[paramKey] = tenantId;
|
|
828
|
+
tenantPredicate = `${tenantField} = {${tenantField}:${metadata.tenantFieldType ?? "String"}}`;
|
|
829
|
+
} else {
|
|
830
|
+
const escapedId = tenantId.replace(/'/g, "''");
|
|
831
|
+
tenantPredicate = `${tenantField} = '${escapedId}'`;
|
|
832
|
+
}
|
|
766
833
|
if (/\bwhere\b/i.test(sql)) {
|
|
767
834
|
return sql.replace(
|
|
768
835
|
/\bwhere\b/i,
|
|
@@ -996,7 +1063,6 @@ function resolveTenantId2(client, tenantId) {
|
|
|
996
1063
|
}
|
|
997
1064
|
|
|
998
1065
|
// src/routes/ingest.ts
|
|
999
|
-
import { randomUUID } from "crypto";
|
|
1000
1066
|
async function syncSchema(client, queryEngine, databaseName, options, signal) {
|
|
1001
1067
|
const tenantId = resolveTenantId3(client, options.tenantId);
|
|
1002
1068
|
const adapter = queryEngine.getDatabase(databaseName);
|
|
@@ -1008,7 +1074,7 @@ async function syncSchema(client, queryEngine, databaseName, options, signal) {
|
|
|
1008
1074
|
if (options.forceReindex) {
|
|
1009
1075
|
payload.force_reindex = true;
|
|
1010
1076
|
}
|
|
1011
|
-
const sessionId = randomUUID();
|
|
1077
|
+
const sessionId = crypto.randomUUID();
|
|
1012
1078
|
const response = await client.post(
|
|
1013
1079
|
"/ingest",
|
|
1014
1080
|
payload,
|
|
@@ -1057,10 +1123,9 @@ function buildSchemaRequest(databaseName, adapter, introspection, metadata) {
|
|
|
1057
1123
|
}
|
|
1058
1124
|
|
|
1059
1125
|
// src/routes/query.ts
|
|
1060
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
1061
1126
|
async function ask(client, queryEngine, question, options, signal) {
|
|
1062
1127
|
const tenantId = resolveTenantId4(client, options.tenantId);
|
|
1063
|
-
const sessionId =
|
|
1128
|
+
const sessionId = crypto.randomUUID();
|
|
1064
1129
|
const maxRetry = options.maxRetry ?? 0;
|
|
1065
1130
|
let attempt = 0;
|
|
1066
1131
|
let lastError = options.lastError;
|