@blinkdotnew/dev-sdk 2.1.2 → 2.1.4
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/dist/index.d.mts +296 -9
- package/dist/index.d.ts +296 -9
- package/dist/index.js +509 -141
- package/dist/index.mjs +507 -142
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -7,6 +7,33 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
+
// ../core/src/platform.ts
|
|
11
|
+
function detectPlatform() {
|
|
12
|
+
if (typeof Deno !== "undefined") {
|
|
13
|
+
return "deno";
|
|
14
|
+
}
|
|
15
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
16
|
+
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
17
|
+
return "react-native";
|
|
18
|
+
}
|
|
19
|
+
return "node";
|
|
20
|
+
}
|
|
21
|
+
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
22
|
+
return "react-native";
|
|
23
|
+
}
|
|
24
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
25
|
+
return "web";
|
|
26
|
+
}
|
|
27
|
+
return "node";
|
|
28
|
+
}
|
|
29
|
+
var platform = detectPlatform();
|
|
30
|
+
var isWeb = platform === "web";
|
|
31
|
+
var isReactNative = platform === "react-native";
|
|
32
|
+
var isNode = platform === "node";
|
|
33
|
+
var isDeno = platform === "deno";
|
|
34
|
+
var isBrowser = isWeb || isReactNative;
|
|
35
|
+
var isServer = isNode || isDeno;
|
|
36
|
+
|
|
10
37
|
// ../core/src/storage-adapter.ts
|
|
11
38
|
var WebStorageAdapter = class {
|
|
12
39
|
getItem(key) {
|
|
@@ -92,6 +119,9 @@ var NoOpStorageAdapter = class {
|
|
|
92
119
|
}
|
|
93
120
|
};
|
|
94
121
|
function getDefaultStorageAdapter() {
|
|
122
|
+
if (isDeno) {
|
|
123
|
+
return new NoOpStorageAdapter();
|
|
124
|
+
}
|
|
95
125
|
if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
|
|
96
126
|
try {
|
|
97
127
|
localStorage.setItem("__test__", "test");
|
|
@@ -103,28 +133,6 @@ function getDefaultStorageAdapter() {
|
|
|
103
133
|
return new NoOpStorageAdapter();
|
|
104
134
|
}
|
|
105
135
|
|
|
106
|
-
// ../core/src/platform.ts
|
|
107
|
-
function detectPlatform() {
|
|
108
|
-
if (typeof process !== "undefined" && process.versions?.node) {
|
|
109
|
-
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
110
|
-
return "react-native";
|
|
111
|
-
}
|
|
112
|
-
return "node";
|
|
113
|
-
}
|
|
114
|
-
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
115
|
-
return "react-native";
|
|
116
|
-
}
|
|
117
|
-
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
118
|
-
return "web";
|
|
119
|
-
}
|
|
120
|
-
return "node";
|
|
121
|
-
}
|
|
122
|
-
var platform = detectPlatform();
|
|
123
|
-
var isWeb = platform === "web";
|
|
124
|
-
var isReactNative = platform === "react-native";
|
|
125
|
-
var isNode = platform === "node";
|
|
126
|
-
var isBrowser = isWeb || isReactNative;
|
|
127
|
-
|
|
128
136
|
// ../core/src/types.ts
|
|
129
137
|
var BlinkError = class extends Error {
|
|
130
138
|
constructor(message, code, status, details) {
|
|
@@ -388,17 +396,44 @@ function convertKeysToCamelCase(obj) {
|
|
|
388
396
|
return converted;
|
|
389
397
|
}
|
|
390
398
|
var HttpClient = class {
|
|
391
|
-
authUrl;
|
|
392
|
-
coreUrl;
|
|
399
|
+
authUrl = "https://blink.new";
|
|
400
|
+
coreUrl = "https://core.blink.new";
|
|
393
401
|
projectId;
|
|
402
|
+
publishableKey;
|
|
403
|
+
secretKey;
|
|
404
|
+
// Permanent, non-expiring key (like Stripe's sk_live_...)
|
|
394
405
|
getToken;
|
|
395
406
|
getValidToken;
|
|
396
407
|
constructor(config, getToken, getValidToken) {
|
|
397
408
|
this.projectId = config.projectId;
|
|
409
|
+
this.publishableKey = config.publishableKey;
|
|
410
|
+
this.secretKey = config.secretKey || config.serviceToken;
|
|
398
411
|
this.getToken = getToken;
|
|
399
412
|
this.getValidToken = getValidToken;
|
|
400
|
-
|
|
401
|
-
|
|
413
|
+
}
|
|
414
|
+
shouldAttachPublishableKey(path, method) {
|
|
415
|
+
if (method !== "GET" && method !== "POST") return false;
|
|
416
|
+
if (path.includes("/api/analytics/")) return true;
|
|
417
|
+
if (path.includes("/api/storage/")) return true;
|
|
418
|
+
if (path.includes("/api/db/") && path.includes("/rest/v1/")) return method === "GET";
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
shouldSkipSecretKey(url) {
|
|
422
|
+
try {
|
|
423
|
+
const parsed = new URL(url);
|
|
424
|
+
return parsed.hostname.endsWith(".functions.blink.new");
|
|
425
|
+
} catch {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
getAuthorizationHeader(url, token) {
|
|
430
|
+
if (this.secretKey && !this.shouldSkipSecretKey(url)) {
|
|
431
|
+
return `Bearer ${this.secretKey}`;
|
|
432
|
+
}
|
|
433
|
+
if (token) {
|
|
434
|
+
return `Bearer ${token}`;
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
402
437
|
}
|
|
403
438
|
/**
|
|
404
439
|
* Make an authenticated request to the Blink API
|
|
@@ -406,19 +441,23 @@ var HttpClient = class {
|
|
|
406
441
|
async request(path, options = {}) {
|
|
407
442
|
const url = this.buildUrl(path, options.searchParams);
|
|
408
443
|
const token = this.getValidToken ? await this.getValidToken() : this.getToken();
|
|
444
|
+
const method = options.method || "GET";
|
|
409
445
|
const headers = {
|
|
410
446
|
"Content-Type": "application/json",
|
|
411
447
|
...options.headers
|
|
412
448
|
};
|
|
413
|
-
|
|
414
|
-
|
|
449
|
+
const auth = this.getAuthorizationHeader(url, token);
|
|
450
|
+
if (auth) {
|
|
451
|
+
headers.Authorization = auth;
|
|
452
|
+
} else if (this.publishableKey && !headers["x-blink-publishable-key"] && this.shouldAttachPublishableKey(path, method)) {
|
|
453
|
+
headers["x-blink-publishable-key"] = this.publishableKey;
|
|
415
454
|
}
|
|
416
455
|
const requestInit = {
|
|
417
|
-
method
|
|
456
|
+
method,
|
|
418
457
|
headers,
|
|
419
458
|
signal: options.signal
|
|
420
459
|
};
|
|
421
|
-
if (options.body &&
|
|
460
|
+
if (options.body && method !== "GET") {
|
|
422
461
|
requestInit.body = typeof options.body === "string" ? options.body : JSON.stringify(options.body);
|
|
423
462
|
}
|
|
424
463
|
try {
|
|
@@ -572,12 +611,12 @@ var HttpClient = class {
|
|
|
572
611
|
throw new BlinkValidationError("Unsupported file type");
|
|
573
612
|
}
|
|
574
613
|
formData.append("path", filePath);
|
|
575
|
-
if (options.upsert !== void 0) {
|
|
576
|
-
formData.append("options", JSON.stringify({ upsert: options.upsert }));
|
|
577
|
-
}
|
|
578
614
|
const headers = {};
|
|
579
|
-
|
|
580
|
-
|
|
615
|
+
const auth = this.getAuthorizationHeader(url, token);
|
|
616
|
+
if (auth) {
|
|
617
|
+
headers.Authorization = auth;
|
|
618
|
+
} else if (this.publishableKey && path.includes("/api/storage/") && !headers["x-blink-publishable-key"]) {
|
|
619
|
+
headers["x-blink-publishable-key"] = this.publishableKey;
|
|
581
620
|
}
|
|
582
621
|
try {
|
|
583
622
|
if (typeof XMLHttpRequest !== "undefined" && options.onProgress) {
|
|
@@ -678,7 +717,7 @@ var HttpClient = class {
|
|
|
678
717
|
});
|
|
679
718
|
}
|
|
680
719
|
/**
|
|
681
|
-
* Stream AI text generation
|
|
720
|
+
* Stream AI text generation - uses Vercel AI SDK's pipeUIMessageStreamToResponse (Data Stream Protocol)
|
|
682
721
|
*/
|
|
683
722
|
async streamAiText(prompt, options = {}, onChunk) {
|
|
684
723
|
const url = this.buildUrl(`/api/ai/${this.projectId}/text`);
|
|
@@ -686,9 +725,8 @@ var HttpClient = class {
|
|
|
686
725
|
const headers = {
|
|
687
726
|
"Content-Type": "application/json"
|
|
688
727
|
};
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
728
|
+
const auth = this.getAuthorizationHeader(url, token);
|
|
729
|
+
if (auth) headers.Authorization = auth;
|
|
692
730
|
const body = {
|
|
693
731
|
prompt,
|
|
694
732
|
stream: true,
|
|
@@ -708,7 +746,7 @@ var HttpClient = class {
|
|
|
708
746
|
if (!response.body) {
|
|
709
747
|
throw new BlinkNetworkError("No response body for streaming");
|
|
710
748
|
}
|
|
711
|
-
return this.
|
|
749
|
+
return this.parseDataStreamProtocol(response.body, onChunk);
|
|
712
750
|
} catch (error) {
|
|
713
751
|
if (error instanceof BlinkError) {
|
|
714
752
|
throw error;
|
|
@@ -733,7 +771,7 @@ var HttpClient = class {
|
|
|
733
771
|
});
|
|
734
772
|
}
|
|
735
773
|
/**
|
|
736
|
-
* Stream AI object generation
|
|
774
|
+
* Stream AI object generation - uses Vercel AI SDK's pipeTextStreamToResponse
|
|
737
775
|
*/
|
|
738
776
|
async streamAiObject(prompt, options = {}, onPartial) {
|
|
739
777
|
const url = this.buildUrl(`/api/ai/${this.projectId}/object`);
|
|
@@ -741,9 +779,8 @@ var HttpClient = class {
|
|
|
741
779
|
const headers = {
|
|
742
780
|
"Content-Type": "application/json"
|
|
743
781
|
};
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
782
|
+
const auth = this.getAuthorizationHeader(url, token);
|
|
783
|
+
if (auth) headers.Authorization = auth;
|
|
747
784
|
const body = {
|
|
748
785
|
prompt,
|
|
749
786
|
stream: true,
|
|
@@ -763,7 +800,35 @@ var HttpClient = class {
|
|
|
763
800
|
if (!response.body) {
|
|
764
801
|
throw new BlinkNetworkError("No response body for streaming");
|
|
765
802
|
}
|
|
766
|
-
|
|
803
|
+
const reader = response.body.getReader();
|
|
804
|
+
const decoder = new TextDecoder();
|
|
805
|
+
let buffer = "";
|
|
806
|
+
let latestObject = {};
|
|
807
|
+
try {
|
|
808
|
+
while (true) {
|
|
809
|
+
const { done, value } = await reader.read();
|
|
810
|
+
if (done) break;
|
|
811
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
812
|
+
buffer += chunk;
|
|
813
|
+
try {
|
|
814
|
+
const parsed = JSON.parse(buffer);
|
|
815
|
+
latestObject = parsed;
|
|
816
|
+
if (onPartial) {
|
|
817
|
+
onPartial(parsed);
|
|
818
|
+
}
|
|
819
|
+
} catch {
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
if (buffer) {
|
|
823
|
+
try {
|
|
824
|
+
latestObject = JSON.parse(buffer);
|
|
825
|
+
} catch {
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
return { object: latestObject };
|
|
829
|
+
} finally {
|
|
830
|
+
reader.releaseLock();
|
|
831
|
+
}
|
|
767
832
|
} catch (error) {
|
|
768
833
|
if (error instanceof BlinkError) {
|
|
769
834
|
throw error;
|
|
@@ -820,6 +885,17 @@ var HttpClient = class {
|
|
|
820
885
|
signal
|
|
821
886
|
});
|
|
822
887
|
}
|
|
888
|
+
async aiVideo(prompt, options = {}) {
|
|
889
|
+
const { signal, ...body } = options;
|
|
890
|
+
return this.request(`/api/ai/${this.projectId}/video`, {
|
|
891
|
+
method: "POST",
|
|
892
|
+
body: {
|
|
893
|
+
prompt,
|
|
894
|
+
...body
|
|
895
|
+
},
|
|
896
|
+
signal
|
|
897
|
+
});
|
|
898
|
+
}
|
|
823
899
|
/**
|
|
824
900
|
* Data-specific requests
|
|
825
901
|
*/
|
|
@@ -861,6 +937,38 @@ var HttpClient = class {
|
|
|
861
937
|
async dataSearch(projectId, request) {
|
|
862
938
|
return this.post(`/api/data/${projectId}/search`, request);
|
|
863
939
|
}
|
|
940
|
+
/**
|
|
941
|
+
* Connector requests
|
|
942
|
+
*/
|
|
943
|
+
formatProviderForPath(provider) {
|
|
944
|
+
return provider.replace("_", "-");
|
|
945
|
+
}
|
|
946
|
+
async connectorStatus(provider) {
|
|
947
|
+
return this.request(`/api/connectors/${this.formatProviderForPath(provider)}/${this.projectId}/status`, {
|
|
948
|
+
method: "GET"
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
async connectorExecute(provider, request) {
|
|
952
|
+
const path = request.method.startsWith("/") ? request.method : `/${request.method}`;
|
|
953
|
+
const url = `/api/connectors/${this.formatProviderForPath(provider)}/${this.projectId}${path}`;
|
|
954
|
+
const method = (request.http_method || "GET").toUpperCase();
|
|
955
|
+
if (method === "GET") {
|
|
956
|
+
return this.request(url, {
|
|
957
|
+
method: "GET",
|
|
958
|
+
searchParams: request.params
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
return this.request(url, {
|
|
962
|
+
method,
|
|
963
|
+
body: request.params || {}
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
async connectorSaveApiKey(provider, request) {
|
|
967
|
+
return this.request(`/api/connectors/${this.formatProviderForPath(provider)}/${this.projectId}/api-key`, {
|
|
968
|
+
method: "POST",
|
|
969
|
+
body: request
|
|
970
|
+
});
|
|
971
|
+
}
|
|
864
972
|
/**
|
|
865
973
|
* Realtime-specific requests
|
|
866
974
|
*/
|
|
@@ -926,93 +1034,94 @@ var HttpClient = class {
|
|
|
926
1034
|
}
|
|
927
1035
|
}
|
|
928
1036
|
/**
|
|
929
|
-
* Parse Vercel AI SDK
|
|
930
|
-
*
|
|
1037
|
+
* Parse Vercel AI SDK v5 Data Stream Protocol (Server-Sent Events)
|
|
1038
|
+
* Supports all event types from the UI Message Stream protocol
|
|
931
1039
|
*/
|
|
932
|
-
async
|
|
1040
|
+
async parseDataStreamProtocol(body, onChunk) {
|
|
933
1041
|
const reader = body.getReader();
|
|
934
1042
|
const decoder = new TextDecoder();
|
|
1043
|
+
const finalResult = {
|
|
1044
|
+
text: "",
|
|
1045
|
+
toolCalls: [],
|
|
1046
|
+
toolResults: [],
|
|
1047
|
+
sources: [],
|
|
1048
|
+
files: [],
|
|
1049
|
+
reasoning: []
|
|
1050
|
+
};
|
|
935
1051
|
let buffer = "";
|
|
936
|
-
let finalResult = {};
|
|
937
1052
|
try {
|
|
938
1053
|
while (true) {
|
|
939
1054
|
const { done, value } = await reader.read();
|
|
940
1055
|
if (done) break;
|
|
941
1056
|
buffer += decoder.decode(value, { stream: true });
|
|
942
|
-
const lines = buffer.split(
|
|
1057
|
+
const lines = buffer.split("\n");
|
|
943
1058
|
buffer = lines.pop() || "";
|
|
944
1059
|
for (const line of lines) {
|
|
945
1060
|
if (!line.trim()) continue;
|
|
1061
|
+
if (line === "[DONE]") {
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
if (!line.startsWith("data: ")) continue;
|
|
946
1065
|
try {
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
} else if (line.startsWith("2:")) {
|
|
957
|
-
const data = JSON.parse(line.slice(2));
|
|
958
|
-
if (Array.isArray(data) && data.length > 0) {
|
|
959
|
-
const item = data[0];
|
|
960
|
-
if (typeof item === "string") {
|
|
961
|
-
finalResult.status = item;
|
|
962
|
-
} else if (typeof item === "object") {
|
|
963
|
-
if (onPartial) {
|
|
964
|
-
onPartial(item);
|
|
965
|
-
}
|
|
966
|
-
finalResult.object = item;
|
|
1066
|
+
const jsonStr = line.slice(6);
|
|
1067
|
+
const part = JSON.parse(jsonStr);
|
|
1068
|
+
switch (part.type) {
|
|
1069
|
+
case "text-start":
|
|
1070
|
+
break;
|
|
1071
|
+
case "text-delta":
|
|
1072
|
+
if (part.delta) {
|
|
1073
|
+
finalResult.text += part.delta;
|
|
1074
|
+
if (onChunk) onChunk(part.delta);
|
|
967
1075
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
if (metadata.usage) {
|
|
972
|
-
finalResult.usage = metadata.usage;
|
|
973
|
-
}
|
|
974
|
-
if (metadata.finishReason) {
|
|
975
|
-
finalResult.finishReason = metadata.finishReason;
|
|
976
|
-
}
|
|
977
|
-
} else if (line.startsWith("e:")) {
|
|
978
|
-
const errorData = JSON.parse(line.slice(2));
|
|
979
|
-
finalResult.error = errorData;
|
|
980
|
-
}
|
|
981
|
-
} catch (error) {
|
|
982
|
-
console.warn("Failed to parse stream line:", line, error);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
if (buffer.trim()) {
|
|
987
|
-
try {
|
|
988
|
-
if (buffer.startsWith("0:")) {
|
|
989
|
-
const textChunk = JSON.parse(buffer.slice(2));
|
|
990
|
-
if (onChunk) {
|
|
991
|
-
onChunk(textChunk);
|
|
992
|
-
}
|
|
993
|
-
finalResult.text = (finalResult.text || "") + textChunk;
|
|
994
|
-
} else if (buffer.startsWith("2:")) {
|
|
995
|
-
const data = JSON.parse(buffer.slice(2));
|
|
996
|
-
if (Array.isArray(data) && data.length > 0) {
|
|
997
|
-
const item = data[0];
|
|
998
|
-
if (typeof item === "object") {
|
|
999
|
-
if (onPartial) {
|
|
1000
|
-
onPartial(item);
|
|
1076
|
+
if (part.textDelta) {
|
|
1077
|
+
finalResult.text += part.textDelta;
|
|
1078
|
+
if (onChunk) onChunk(part.textDelta);
|
|
1001
1079
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1080
|
+
break;
|
|
1081
|
+
case "text-end":
|
|
1082
|
+
break;
|
|
1083
|
+
case "tool-call":
|
|
1084
|
+
finalResult.toolCalls.push({
|
|
1085
|
+
toolCallId: part.toolCallId,
|
|
1086
|
+
toolName: part.toolName,
|
|
1087
|
+
args: part.args
|
|
1088
|
+
});
|
|
1089
|
+
break;
|
|
1090
|
+
case "tool-result":
|
|
1091
|
+
finalResult.toolResults.push({
|
|
1092
|
+
toolCallId: part.toolCallId,
|
|
1093
|
+
toolName: part.toolName,
|
|
1094
|
+
result: part.result
|
|
1095
|
+
});
|
|
1096
|
+
break;
|
|
1097
|
+
case "source-url":
|
|
1098
|
+
finalResult.sources.push({
|
|
1099
|
+
id: part.id,
|
|
1100
|
+
url: part.url,
|
|
1101
|
+
title: part.title
|
|
1102
|
+
});
|
|
1103
|
+
break;
|
|
1104
|
+
case "file":
|
|
1105
|
+
finalResult.files.push(part.file);
|
|
1106
|
+
break;
|
|
1107
|
+
case "reasoning":
|
|
1108
|
+
finalResult.reasoning.push(part.content);
|
|
1109
|
+
break;
|
|
1110
|
+
case "finish":
|
|
1111
|
+
finalResult.finishReason = part.finishReason;
|
|
1112
|
+
finalResult.usage = part.usage;
|
|
1113
|
+
if (part.response) finalResult.response = part.response;
|
|
1114
|
+
break;
|
|
1115
|
+
case "error":
|
|
1116
|
+
finalResult.error = part.error;
|
|
1117
|
+
throw new Error(part.error);
|
|
1118
|
+
case "data":
|
|
1119
|
+
if (!finalResult.customData) finalResult.customData = [];
|
|
1120
|
+
finalResult.customData.push(part.value);
|
|
1121
|
+
break;
|
|
1012
1122
|
}
|
|
1123
|
+
} catch (e) {
|
|
1013
1124
|
}
|
|
1014
|
-
} catch (error) {
|
|
1015
|
-
console.warn("Failed to parse final buffer:", buffer, error);
|
|
1016
1125
|
}
|
|
1017
1126
|
}
|
|
1018
1127
|
return finalResult;
|
|
@@ -1180,13 +1289,13 @@ var BlinkAuth = class {
|
|
|
1180
1289
|
mode: "managed",
|
|
1181
1290
|
// Default mode
|
|
1182
1291
|
authUrl: "https://blink.new",
|
|
1183
|
-
coreUrl: "https://
|
|
1292
|
+
coreUrl: "https://core.blink.new",
|
|
1184
1293
|
detectSessionInUrl: true,
|
|
1185
1294
|
// Default to true for web compatibility
|
|
1186
1295
|
...config.auth
|
|
1187
1296
|
};
|
|
1188
1297
|
this.authUrl = this.authConfig.authUrl || "https://blink.new";
|
|
1189
|
-
this.coreUrl = this.authConfig.coreUrl || "https://
|
|
1298
|
+
this.coreUrl = this.authConfig.coreUrl || "https://core.blink.new";
|
|
1190
1299
|
const hostname = getLocationHostname();
|
|
1191
1300
|
if (hostname && this.authUrl === "https://blink.new" && (hostname === "localhost" || hostname === "127.0.0.1")) {
|
|
1192
1301
|
console.warn("\u26A0\uFE0F Using default authUrl in development. Set auth.authUrl to your app origin for headless auth endpoints to work.");
|
|
@@ -1857,6 +1966,67 @@ var BlinkAuth = class {
|
|
|
1857
1966
|
throw pollError;
|
|
1858
1967
|
}
|
|
1859
1968
|
}
|
|
1969
|
+
/**
|
|
1970
|
+
* OAuth flow via parent window (for iframe context)
|
|
1971
|
+
* Delegates OAuth to parent window since OAuth providers block flows inside iframes
|
|
1972
|
+
*/
|
|
1973
|
+
signInWithProviderViaParent(provider, options) {
|
|
1974
|
+
return new Promise((resolve, reject) => {
|
|
1975
|
+
const state = this.generateState();
|
|
1976
|
+
const redirectUrl = options?.redirectUrl || getLocationOrigin() || "";
|
|
1977
|
+
let timeoutId;
|
|
1978
|
+
let cleanedUp = false;
|
|
1979
|
+
const cleanup = () => {
|
|
1980
|
+
if (cleanedUp) return;
|
|
1981
|
+
cleanedUp = true;
|
|
1982
|
+
clearTimeout(timeoutId);
|
|
1983
|
+
window.removeEventListener("message", messageListener);
|
|
1984
|
+
};
|
|
1985
|
+
const messageListener = (event) => {
|
|
1986
|
+
const { type, access_token, refresh_token, expires_in, refresh_expires_in, issued_at, projectId, error } = event.data || {};
|
|
1987
|
+
if (type === "BLINK_AUTH_TOKENS") {
|
|
1988
|
+
if (projectId && projectId !== this.config.projectId) {
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
console.log("\u{1F4E5} Received auth tokens from parent window");
|
|
1992
|
+
this.setTokens({
|
|
1993
|
+
access_token,
|
|
1994
|
+
refresh_token,
|
|
1995
|
+
token_type: "Bearer",
|
|
1996
|
+
expires_in: expires_in || 3600,
|
|
1997
|
+
refresh_expires_in,
|
|
1998
|
+
issued_at: issued_at || Math.floor(Date.now() / 1e3)
|
|
1999
|
+
}, true).then(() => {
|
|
2000
|
+
cleanup();
|
|
2001
|
+
resolve(this.authState.user);
|
|
2002
|
+
}).catch((err) => {
|
|
2003
|
+
cleanup();
|
|
2004
|
+
reject(err);
|
|
2005
|
+
});
|
|
2006
|
+
} else if (type === "BLINK_AUTH_ERROR") {
|
|
2007
|
+
cleanup();
|
|
2008
|
+
reject(new BlinkAuthError(
|
|
2009
|
+
"POPUP_CANCELED" /* POPUP_CANCELED */,
|
|
2010
|
+
error || "Authentication failed"
|
|
2011
|
+
));
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
window.addEventListener("message", messageListener);
|
|
2015
|
+
timeoutId = setTimeout(() => {
|
|
2016
|
+
cleanup();
|
|
2017
|
+
reject(new BlinkAuthError("AUTH_TIMEOUT" /* AUTH_TIMEOUT */, "Authentication timed out"));
|
|
2018
|
+
}, 3e5);
|
|
2019
|
+
console.log("\u{1F4E4} Sending OAuth request to parent window");
|
|
2020
|
+
window.parent.postMessage({
|
|
2021
|
+
type: "BLINK_AUTH_OAUTH_REQUEST",
|
|
2022
|
+
provider,
|
|
2023
|
+
projectId: this.config.projectId,
|
|
2024
|
+
redirectUrl,
|
|
2025
|
+
state,
|
|
2026
|
+
authUrl: this.authUrl
|
|
2027
|
+
}, "*");
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
1860
2030
|
/**
|
|
1861
2031
|
* Generic provider sign-in method (headless mode)
|
|
1862
2032
|
*
|
|
@@ -1903,7 +2073,10 @@ var BlinkAuth = class {
|
|
|
1903
2073
|
if (!hasWindow()) {
|
|
1904
2074
|
throw new BlinkAuthError("NETWORK_ERROR" /* NETWORK_ERROR */, "signInWithProvider requires a browser environment");
|
|
1905
2075
|
}
|
|
1906
|
-
|
|
2076
|
+
if (isWeb && this.isIframe && hasWindow() && window.parent !== window) {
|
|
2077
|
+
console.log("\u{1F5BC}\uFE0F In iframe, delegating OAuth to parent window");
|
|
2078
|
+
return this.signInWithProviderViaParent(provider, options);
|
|
2079
|
+
}
|
|
1907
2080
|
const state = this.generateState();
|
|
1908
2081
|
try {
|
|
1909
2082
|
const sessionStorage = getSessionStorage();
|
|
@@ -1923,6 +2096,7 @@ var BlinkAuth = class {
|
|
|
1923
2096
|
url.searchParams.set("opener_origin", getLocationOrigin() || "");
|
|
1924
2097
|
return url;
|
|
1925
2098
|
};
|
|
2099
|
+
const shouldPreferRedirect = typeof window !== "undefined" && window.crossOriginIsolated === true;
|
|
1926
2100
|
if (shouldPreferRedirect) {
|
|
1927
2101
|
window.location.href = buildAuthUrl("redirect").toString();
|
|
1928
2102
|
return new Promise(() => {
|
|
@@ -2939,6 +3113,11 @@ var BlinkAuth = class {
|
|
|
2939
3113
|
};
|
|
2940
3114
|
|
|
2941
3115
|
// src/database.ts
|
|
3116
|
+
function assertServerOnly(methodName) {
|
|
3117
|
+
if (typeof window !== "undefined") {
|
|
3118
|
+
throw new Error(`${methodName} is server-only. Use Blink CRUD methods (blink.db.<table>.*) instead.`);
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
2942
3121
|
function camelToSnake3(str) {
|
|
2943
3122
|
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
2944
3123
|
}
|
|
@@ -3157,6 +3336,7 @@ var BlinkTable = class {
|
|
|
3157
3336
|
* Raw SQL query on this table (for advanced use cases)
|
|
3158
3337
|
*/
|
|
3159
3338
|
async sql(query, params) {
|
|
3339
|
+
assertServerOnly("blink.db.<table>.sql");
|
|
3160
3340
|
const response = await this.httpClient.dbSql(query, params);
|
|
3161
3341
|
return response.data;
|
|
3162
3342
|
}
|
|
@@ -3205,6 +3385,7 @@ var BlinkDatabase = class {
|
|
|
3205
3385
|
* Execute raw SQL query
|
|
3206
3386
|
*/
|
|
3207
3387
|
async sql(query, params) {
|
|
3388
|
+
assertServerOnly("blink.db.sql");
|
|
3208
3389
|
const response = await this.httpClient.dbSql(query, params);
|
|
3209
3390
|
return response.data;
|
|
3210
3391
|
}
|
|
@@ -3212,6 +3393,7 @@ var BlinkDatabase = class {
|
|
|
3212
3393
|
* Execute batch SQL operations
|
|
3213
3394
|
*/
|
|
3214
3395
|
async batch(statements, mode = "write") {
|
|
3396
|
+
assertServerOnly("blink.db.batch");
|
|
3215
3397
|
const response = await this.httpClient.dbBatch(statements, mode);
|
|
3216
3398
|
return response.data;
|
|
3217
3399
|
}
|
|
@@ -3274,7 +3456,6 @@ var BlinkStorageImpl = class {
|
|
|
3274
3456
|
correctedPath,
|
|
3275
3457
|
// Use corrected path with proper extension
|
|
3276
3458
|
{
|
|
3277
|
-
upsert: options.upsert,
|
|
3278
3459
|
onProgress: options.onProgress,
|
|
3279
3460
|
contentType: detectedContentType
|
|
3280
3461
|
// Pass detected content type
|
|
@@ -3294,7 +3475,7 @@ var BlinkStorageImpl = class {
|
|
|
3294
3475
|
if (error instanceof Error && "status" in error) {
|
|
3295
3476
|
const status = error.status;
|
|
3296
3477
|
if (status === 409) {
|
|
3297
|
-
throw new BlinkStorageError("File already exists.
|
|
3478
|
+
throw new BlinkStorageError("File already exists.", 409);
|
|
3298
3479
|
}
|
|
3299
3480
|
if (status === 400) {
|
|
3300
3481
|
throw new BlinkStorageError("Invalid request parameters", 400);
|
|
@@ -3339,7 +3520,6 @@ var BlinkStorageImpl = class {
|
|
|
3339
3520
|
detectedContentType
|
|
3340
3521
|
};
|
|
3341
3522
|
} catch (error) {
|
|
3342
|
-
console.warn("File type detection failed, using original path:", error);
|
|
3343
3523
|
return {
|
|
3344
3524
|
correctedPath: originalPath,
|
|
3345
3525
|
detectedContentType: "application/octet-stream"
|
|
@@ -3729,13 +3909,7 @@ var BlinkAIImpl = class {
|
|
|
3729
3909
|
options.prompt || "",
|
|
3730
3910
|
requestBody
|
|
3731
3911
|
);
|
|
3732
|
-
|
|
3733
|
-
return response.data.result;
|
|
3734
|
-
} else if (response.data?.text) {
|
|
3735
|
-
return response.data;
|
|
3736
|
-
} else {
|
|
3737
|
-
throw new BlinkAIError("Invalid response format: missing text");
|
|
3738
|
-
}
|
|
3912
|
+
return response.data;
|
|
3739
3913
|
} catch (error) {
|
|
3740
3914
|
if (error instanceof BlinkAIError) {
|
|
3741
3915
|
throw error;
|
|
@@ -3804,9 +3978,14 @@ var BlinkAIImpl = class {
|
|
|
3804
3978
|
);
|
|
3805
3979
|
return {
|
|
3806
3980
|
text: result.text || "",
|
|
3807
|
-
finishReason: "stop",
|
|
3981
|
+
finishReason: result.finishReason || "stop",
|
|
3808
3982
|
usage: result.usage,
|
|
3809
|
-
|
|
3983
|
+
toolCalls: result.toolCalls,
|
|
3984
|
+
toolResults: result.toolResults,
|
|
3985
|
+
sources: result.sources,
|
|
3986
|
+
files: result.files,
|
|
3987
|
+
reasoningDetails: result.reasoning,
|
|
3988
|
+
response: result.response
|
|
3810
3989
|
};
|
|
3811
3990
|
} catch (error) {
|
|
3812
3991
|
if (error instanceof BlinkAIError) {
|
|
@@ -3885,13 +4064,7 @@ var BlinkAIImpl = class {
|
|
|
3885
4064
|
signal: options.signal
|
|
3886
4065
|
}
|
|
3887
4066
|
);
|
|
3888
|
-
|
|
3889
|
-
return response.data.result;
|
|
3890
|
-
} else if (response.data?.object) {
|
|
3891
|
-
return response.data;
|
|
3892
|
-
} else {
|
|
3893
|
-
throw new BlinkAIError("Invalid response format: missing object");
|
|
3894
|
-
}
|
|
4067
|
+
return response.data;
|
|
3895
4068
|
} catch (error) {
|
|
3896
4069
|
if (error instanceof BlinkAIError) {
|
|
3897
4070
|
throw error;
|
|
@@ -3953,8 +4126,7 @@ var BlinkAIImpl = class {
|
|
|
3953
4126
|
return {
|
|
3954
4127
|
object: result.object || {},
|
|
3955
4128
|
finishReason: "stop",
|
|
3956
|
-
usage: result.usage
|
|
3957
|
-
...result
|
|
4129
|
+
usage: result.usage
|
|
3958
4130
|
};
|
|
3959
4131
|
} catch (error) {
|
|
3960
4132
|
if (error instanceof BlinkAIError) {
|
|
@@ -4215,6 +4387,131 @@ var BlinkAIImpl = class {
|
|
|
4215
4387
|
);
|
|
4216
4388
|
}
|
|
4217
4389
|
}
|
|
4390
|
+
/**
|
|
4391
|
+
* Generates videos from text prompts or images using AI video generation models.
|
|
4392
|
+
*
|
|
4393
|
+
* @param options - Object containing:
|
|
4394
|
+
* - `prompt`: Text description of the video to generate (required)
|
|
4395
|
+
* - `model`: Video model to use (optional). Available models:
|
|
4396
|
+
* **Text-to-Video Models:**
|
|
4397
|
+
* - `"fal-ai/veo3.1"` - Google Veo 3.1 (best quality)
|
|
4398
|
+
* - `"fal-ai/veo3.1/fast"` (default) - Veo 3.1 fast mode (faster, cheaper)
|
|
4399
|
+
* - `"fal-ai/sora-2/text-to-video/pro"` - OpenAI Sora 2
|
|
4400
|
+
* - `"fal-ai/kling-video/v2.6/pro/text-to-video"` - Kling 2.6
|
|
4401
|
+
* **Image-to-Video Models:**
|
|
4402
|
+
* - `"fal-ai/veo3.1/image-to-video"` - Veo 3.1 I2V
|
|
4403
|
+
* - `"fal-ai/veo3.1/fast/image-to-video"` - Veo 3.1 fast I2V
|
|
4404
|
+
* - `"fal-ai/sora-2/image-to-video/pro"` - Sora 2 I2V
|
|
4405
|
+
* - `"fal-ai/kling-video/v2.6/pro/image-to-video"` - Kling 2.6 I2V
|
|
4406
|
+
* - `image_url`: Source image URL for image-to-video (required for I2V models)
|
|
4407
|
+
* - `duration`: Video duration ("4s", "5s", "6s", "8s", "10s", "12s")
|
|
4408
|
+
* - `aspect_ratio`: Aspect ratio ("16:9", "9:16", "1:1")
|
|
4409
|
+
* - `resolution`: Resolution ("720p", "1080p") - Veo/Sora only
|
|
4410
|
+
* - `negative_prompt`: What to avoid in generation - Veo/Kling only
|
|
4411
|
+
* - `generate_audio`: Generate audio with video (default: true)
|
|
4412
|
+
* - `seed`: For reproducibility - Veo only
|
|
4413
|
+
* - `cfg_scale`: Guidance scale (0-1) - Kling only
|
|
4414
|
+
* - Plus optional signal parameter
|
|
4415
|
+
*
|
|
4416
|
+
* @example
|
|
4417
|
+
* ```ts
|
|
4418
|
+
* // Basic text-to-video generation (uses default fast model)
|
|
4419
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4420
|
+
* prompt: "A serene sunset over the ocean with gentle waves"
|
|
4421
|
+
* });
|
|
4422
|
+
* console.log("Video URL:", result.video.url);
|
|
4423
|
+
*
|
|
4424
|
+
* // High quality with Veo 3.1
|
|
4425
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4426
|
+
* prompt: "A cinematic shot of a futuristic city at night",
|
|
4427
|
+
* model: "fal-ai/veo3.1",
|
|
4428
|
+
* resolution: "1080p",
|
|
4429
|
+
* aspect_ratio: "16:9"
|
|
4430
|
+
* });
|
|
4431
|
+
*
|
|
4432
|
+
* // Image-to-video animation
|
|
4433
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4434
|
+
* prompt: "Animate this image with gentle camera movement",
|
|
4435
|
+
* model: "fal-ai/veo3.1/fast/image-to-video",
|
|
4436
|
+
* image_url: "https://example.com/my-image.jpg",
|
|
4437
|
+
* duration: "5s"
|
|
4438
|
+
* });
|
|
4439
|
+
*
|
|
4440
|
+
* // Using Sora 2 for creative videos
|
|
4441
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4442
|
+
* prompt: "A magical forest with glowing fireflies",
|
|
4443
|
+
* model: "fal-ai/sora-2/text-to-video/pro",
|
|
4444
|
+
* duration: "8s"
|
|
4445
|
+
* });
|
|
4446
|
+
*
|
|
4447
|
+
* // Using Kling for detailed videos
|
|
4448
|
+
* const { result, usage } = await blink.ai.generateVideo({
|
|
4449
|
+
* prompt: "A professional cooking tutorial scene",
|
|
4450
|
+
* model: "fal-ai/kling-video/v2.6/pro/text-to-video",
|
|
4451
|
+
* negative_prompt: "blur, distort, low quality",
|
|
4452
|
+
* cfg_scale: 0.7
|
|
4453
|
+
* });
|
|
4454
|
+
* console.log("Credits charged:", usage?.creditsCharged);
|
|
4455
|
+
* ```
|
|
4456
|
+
*
|
|
4457
|
+
* @returns Promise<VideoGenerationResponse> - Object containing:
|
|
4458
|
+
* - `result.video.url`: URL to the generated video
|
|
4459
|
+
* - `result.video.content_type`: MIME type (video/mp4)
|
|
4460
|
+
* - `result.video.file_name`: Generated filename
|
|
4461
|
+
* - `result.video.file_size`: File size in bytes
|
|
4462
|
+
* - `metadata`: Generation metadata (projectId, timestamp, model)
|
|
4463
|
+
* - `usage`: Credits charged and cost information
|
|
4464
|
+
*/
|
|
4465
|
+
async generateVideo(options) {
|
|
4466
|
+
try {
|
|
4467
|
+
if (!options.prompt) {
|
|
4468
|
+
throw new BlinkAIError("Prompt is required");
|
|
4469
|
+
}
|
|
4470
|
+
const i2vModels = [
|
|
4471
|
+
"fal-ai/veo3.1/image-to-video",
|
|
4472
|
+
"fal-ai/veo3.1/fast/image-to-video",
|
|
4473
|
+
"fal-ai/sora-2/image-to-video/pro",
|
|
4474
|
+
"fal-ai/kling-video/v2.6/pro/image-to-video"
|
|
4475
|
+
];
|
|
4476
|
+
if (options.model && i2vModels.includes(options.model) && !options.image_url) {
|
|
4477
|
+
throw new BlinkAIError("image_url is required for image-to-video models");
|
|
4478
|
+
}
|
|
4479
|
+
if (options.image_url) {
|
|
4480
|
+
const validation = this.validateImageUrl(options.image_url);
|
|
4481
|
+
if (!validation.isValid) {
|
|
4482
|
+
throw new BlinkAIError(`Invalid image_url: ${validation.error}`);
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
const response = await this.httpClient.aiVideo(
|
|
4486
|
+
options.prompt,
|
|
4487
|
+
{
|
|
4488
|
+
model: options.model,
|
|
4489
|
+
image_url: options.image_url,
|
|
4490
|
+
duration: options.duration,
|
|
4491
|
+
aspect_ratio: options.aspect_ratio,
|
|
4492
|
+
resolution: options.resolution,
|
|
4493
|
+
negative_prompt: options.negative_prompt,
|
|
4494
|
+
generate_audio: options.generate_audio,
|
|
4495
|
+
seed: options.seed,
|
|
4496
|
+
cfg_scale: options.cfg_scale,
|
|
4497
|
+
signal: options.signal
|
|
4498
|
+
}
|
|
4499
|
+
);
|
|
4500
|
+
if (!response.data?.result?.video?.url) {
|
|
4501
|
+
throw new BlinkAIError("Invalid response format: missing video URL");
|
|
4502
|
+
}
|
|
4503
|
+
return response.data;
|
|
4504
|
+
} catch (error) {
|
|
4505
|
+
if (error instanceof BlinkAIError) {
|
|
4506
|
+
throw error;
|
|
4507
|
+
}
|
|
4508
|
+
throw new BlinkAIError(
|
|
4509
|
+
`Video generation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
4510
|
+
void 0,
|
|
4511
|
+
{ originalError: error }
|
|
4512
|
+
);
|
|
4513
|
+
}
|
|
4514
|
+
}
|
|
4218
4515
|
/**
|
|
4219
4516
|
* Converts text to speech using AI voice synthesis models.
|
|
4220
4517
|
*
|
|
@@ -4804,7 +5101,7 @@ var BlinkRealtimeChannel = class {
|
|
|
4804
5101
|
return new Promise((resolve, reject) => {
|
|
4805
5102
|
try {
|
|
4806
5103
|
const httpClient = this.httpClient;
|
|
4807
|
-
const coreUrl = httpClient.coreUrl || "https://
|
|
5104
|
+
const coreUrl = httpClient.coreUrl || "https://core.blink.new";
|
|
4808
5105
|
const baseUrl = coreUrl.replace("https://", "wss://").replace("http://", "ws://");
|
|
4809
5106
|
const wsUrl = `${baseUrl}?project_id=${this.projectId}`;
|
|
4810
5107
|
console.log(`\u{1F517} Attempting WebSocket connection to: ${wsUrl}`);
|
|
@@ -5273,7 +5570,6 @@ var BlinkAnalyticsImpl = class {
|
|
|
5273
5570
|
} catch (error) {
|
|
5274
5571
|
this.queue = [...events, ...this.queue];
|
|
5275
5572
|
this.persistQueue();
|
|
5276
|
-
console.error("Failed to send analytics events:", error);
|
|
5277
5573
|
}
|
|
5278
5574
|
if (this.queue.length > 0) {
|
|
5279
5575
|
this.timer = setTimeout(() => this.flush(), BATCH_TIMEOUT);
|
|
@@ -5464,6 +5760,64 @@ var BlinkAnalyticsImpl = class {
|
|
|
5464
5760
|
}
|
|
5465
5761
|
};
|
|
5466
5762
|
|
|
5763
|
+
// src/connectors.ts
|
|
5764
|
+
var BlinkConnectorsImpl = class {
|
|
5765
|
+
constructor(httpClient) {
|
|
5766
|
+
this.httpClient = httpClient;
|
|
5767
|
+
}
|
|
5768
|
+
async status(provider, options) {
|
|
5769
|
+
const response = await this.httpClient.connectorStatus(provider);
|
|
5770
|
+
return response.data;
|
|
5771
|
+
}
|
|
5772
|
+
async execute(provider, request) {
|
|
5773
|
+
const response = await this.httpClient.connectorExecute(provider, request);
|
|
5774
|
+
return response.data;
|
|
5775
|
+
}
|
|
5776
|
+
async saveApiKey(provider, request) {
|
|
5777
|
+
const response = await this.httpClient.connectorSaveApiKey(provider, request);
|
|
5778
|
+
return response.data;
|
|
5779
|
+
}
|
|
5780
|
+
};
|
|
5781
|
+
|
|
5782
|
+
// src/functions.ts
|
|
5783
|
+
var BlinkFunctionsImpl = class {
|
|
5784
|
+
httpClient;
|
|
5785
|
+
projectId;
|
|
5786
|
+
constructor(httpClient, projectId, _getToken) {
|
|
5787
|
+
this.httpClient = httpClient;
|
|
5788
|
+
this.projectId = projectId;
|
|
5789
|
+
}
|
|
5790
|
+
/**
|
|
5791
|
+
* Get the project suffix from the full project ID.
|
|
5792
|
+
* Project IDs are formatted as: prj_xxxxx
|
|
5793
|
+
* The suffix is the last 8 characters used in function URLs.
|
|
5794
|
+
*/
|
|
5795
|
+
getProjectSuffix() {
|
|
5796
|
+
return this.projectId.slice(-8);
|
|
5797
|
+
}
|
|
5798
|
+
/**
|
|
5799
|
+
* Build the full function URL
|
|
5800
|
+
*/
|
|
5801
|
+
buildFunctionUrl(functionSlug, searchParams) {
|
|
5802
|
+
const suffix = this.getProjectSuffix();
|
|
5803
|
+
const baseUrl = `https://${suffix}--${functionSlug}.functions.blink.new`;
|
|
5804
|
+
if (!searchParams || Object.keys(searchParams).length === 0) {
|
|
5805
|
+
return baseUrl;
|
|
5806
|
+
}
|
|
5807
|
+
const url = new URL(baseUrl);
|
|
5808
|
+
Object.entries(searchParams).forEach(([key, value]) => {
|
|
5809
|
+
url.searchParams.set(key, value);
|
|
5810
|
+
});
|
|
5811
|
+
return url.toString();
|
|
5812
|
+
}
|
|
5813
|
+
async invoke(functionSlug, options = {}) {
|
|
5814
|
+
const { method = "POST", body, headers = {}, searchParams } = options;
|
|
5815
|
+
const url = this.buildFunctionUrl(functionSlug, searchParams);
|
|
5816
|
+
const res = await this.httpClient.request(url, { method, body, headers });
|
|
5817
|
+
return { data: res.data, status: res.status, headers: res.headers };
|
|
5818
|
+
}
|
|
5819
|
+
};
|
|
5820
|
+
|
|
5467
5821
|
// src/client.ts
|
|
5468
5822
|
var BlinkClientImpl = class {
|
|
5469
5823
|
auth;
|
|
@@ -5474,8 +5828,13 @@ var BlinkClientImpl = class {
|
|
|
5474
5828
|
realtime;
|
|
5475
5829
|
notifications;
|
|
5476
5830
|
analytics;
|
|
5831
|
+
connectors;
|
|
5832
|
+
functions;
|
|
5477
5833
|
httpClient;
|
|
5478
5834
|
constructor(config) {
|
|
5835
|
+
if ((config.secretKey || config.serviceToken) && isBrowser) {
|
|
5836
|
+
throw new Error("secretKey/serviceToken is server-only. Do not provide it in browser/React Native clients.");
|
|
5837
|
+
}
|
|
5479
5838
|
this.auth = new BlinkAuth(config);
|
|
5480
5839
|
this.httpClient = new HttpClient(
|
|
5481
5840
|
config,
|
|
@@ -5489,6 +5848,12 @@ var BlinkClientImpl = class {
|
|
|
5489
5848
|
this.realtime = new BlinkRealtimeImpl(this.httpClient, config.projectId);
|
|
5490
5849
|
this.notifications = new BlinkNotificationsImpl(this.httpClient);
|
|
5491
5850
|
this.analytics = new BlinkAnalyticsImpl(this.httpClient, config.projectId);
|
|
5851
|
+
this.connectors = new BlinkConnectorsImpl(this.httpClient);
|
|
5852
|
+
this.functions = new BlinkFunctionsImpl(
|
|
5853
|
+
this.httpClient,
|
|
5854
|
+
config.projectId,
|
|
5855
|
+
() => this.auth.getValidToken()
|
|
5856
|
+
);
|
|
5492
5857
|
this.auth.onAuthStateChanged((state) => {
|
|
5493
5858
|
if (state.isAuthenticated && state.user) {
|
|
5494
5859
|
this.analytics.setUserId(state.user.id);
|
|
@@ -5510,6 +5875,7 @@ function createClient(config) {
|
|
|
5510
5875
|
exports.AsyncStorageAdapter = AsyncStorageAdapter;
|
|
5511
5876
|
exports.BlinkAIImpl = BlinkAIImpl;
|
|
5512
5877
|
exports.BlinkAnalyticsImpl = BlinkAnalyticsImpl;
|
|
5878
|
+
exports.BlinkConnectorsImpl = BlinkConnectorsImpl;
|
|
5513
5879
|
exports.BlinkDataImpl = BlinkDataImpl;
|
|
5514
5880
|
exports.BlinkDatabase = BlinkDatabase;
|
|
5515
5881
|
exports.BlinkRealtimeChannel = BlinkRealtimeChannel;
|
|
@@ -5521,8 +5887,10 @@ exports.WebStorageAdapter = WebStorageAdapter;
|
|
|
5521
5887
|
exports.createClient = createClient;
|
|
5522
5888
|
exports.getDefaultStorageAdapter = getDefaultStorageAdapter;
|
|
5523
5889
|
exports.isBrowser = isBrowser;
|
|
5890
|
+
exports.isDeno = isDeno;
|
|
5524
5891
|
exports.isNode = isNode;
|
|
5525
5892
|
exports.isReactNative = isReactNative;
|
|
5893
|
+
exports.isServer = isServer;
|
|
5526
5894
|
exports.isWeb = isWeb;
|
|
5527
5895
|
exports.platform = platform;
|
|
5528
5896
|
//# sourceMappingURL=index.js.map
|