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