@blinkdotnew/dev-sdk 2.2.0 → 2.2.2
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 +291 -9
- package/dist/index.d.ts +291 -9
- package/dist/index.js +455 -143
- package/dist/index.mjs +453 -144
- 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;
|
|
@@ -1155,6 +1264,15 @@ function getSessionStorage() {
|
|
|
1155
1264
|
return null;
|
|
1156
1265
|
}
|
|
1157
1266
|
}
|
|
1267
|
+
function isSafari() {
|
|
1268
|
+
if (!hasWindow()) return false;
|
|
1269
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
1270
|
+
const hasSafariUA = /safari/i.test(ua) && !/chrome|chromium|android/i.test(ua);
|
|
1271
|
+
const isSafariVendor = typeof navigator !== "undefined" && /apple computer|apple/i.test(navigator.vendor || "");
|
|
1272
|
+
const isIOSSafari = /safari/i.test(ua) && /iphone|ipad|ipod/i.test(ua);
|
|
1273
|
+
const hasSafariProperties = typeof window !== "undefined" && "safari" in window && !("chrome" in window);
|
|
1274
|
+
return hasSafariUA || isSafariVendor || isIOSSafari || hasSafariProperties;
|
|
1275
|
+
}
|
|
1158
1276
|
|
|
1159
1277
|
// src/auth.ts
|
|
1160
1278
|
var BlinkAuth = class {
|
|
@@ -1178,15 +1296,15 @@ var BlinkAuth = class {
|
|
|
1178
1296
|
mode: "managed",
|
|
1179
1297
|
// Default mode
|
|
1180
1298
|
authUrl: "https://dev.blink.new",
|
|
1181
|
-
coreUrl: "https://core.blink.new",
|
|
1299
|
+
coreUrl: "https://core.dev.blink.new",
|
|
1182
1300
|
detectSessionInUrl: true,
|
|
1183
1301
|
// Default to true for web compatibility
|
|
1184
1302
|
...config.auth
|
|
1185
1303
|
};
|
|
1186
|
-
this.authUrl = "https://dev.blink.new";
|
|
1187
|
-
this.coreUrl = this.authConfig.coreUrl || "https://core.blink.new";
|
|
1304
|
+
this.authUrl = this.authConfig.authUrl || "https://dev.blink.new";
|
|
1305
|
+
this.coreUrl = this.authConfig.coreUrl || "https://core.dev.blink.new";
|
|
1188
1306
|
const hostname = getLocationHostname();
|
|
1189
|
-
if (hostname && this.authUrl === "https://blink.new" && (hostname === "localhost" || hostname === "127.0.0.1")) {
|
|
1307
|
+
if (hostname && this.authUrl === "https://dev.blink.new" && (hostname === "localhost" || hostname === "127.0.0.1")) {
|
|
1190
1308
|
console.warn("\u26A0\uFE0F Using default authUrl in development. Set auth.authUrl to your app origin for headless auth endpoints to work.");
|
|
1191
1309
|
}
|
|
1192
1310
|
if (config.authRequired !== void 0 && !config.auth?.mode) {
|
|
@@ -1238,7 +1356,7 @@ var BlinkAuth = class {
|
|
|
1238
1356
|
setupParentWindowListener() {
|
|
1239
1357
|
if (!isWeb || !this.isIframe || !hasWindow()) return;
|
|
1240
1358
|
window.addEventListener("message", (event) => {
|
|
1241
|
-
if (event.origin !== "https://blink.new" && event.origin !== "http://localhost:3000" && event.origin !== "http://localhost:3001") {
|
|
1359
|
+
if (event.origin !== "https://dev.blink.new" && event.origin !== "https://blink.new" && event.origin !== "http://localhost:3000" && event.origin !== "http://localhost:3001") {
|
|
1242
1360
|
return;
|
|
1243
1361
|
}
|
|
1244
1362
|
if (event.data?.type === "BLINK_AUTH_TOKENS") {
|
|
@@ -1901,7 +2019,7 @@ var BlinkAuth = class {
|
|
|
1901
2019
|
if (!hasWindow()) {
|
|
1902
2020
|
throw new BlinkAuthError("NETWORK_ERROR" /* NETWORK_ERROR */, "signInWithProvider requires a browser environment");
|
|
1903
2021
|
}
|
|
1904
|
-
const shouldPreferRedirect = isWeb && this.isIframe || typeof window !== "undefined" && window.crossOriginIsolated === true;
|
|
2022
|
+
const shouldPreferRedirect = isWeb && this.isIframe || typeof window !== "undefined" && window.crossOriginIsolated === true || isWeb && isSafari();
|
|
1905
2023
|
const state = this.generateState();
|
|
1906
2024
|
try {
|
|
1907
2025
|
const sessionStorage = getSessionStorage();
|
|
@@ -2937,6 +3055,11 @@ var BlinkAuth = class {
|
|
|
2937
3055
|
};
|
|
2938
3056
|
|
|
2939
3057
|
// src/database.ts
|
|
3058
|
+
function assertServerOnly(methodName) {
|
|
3059
|
+
if (typeof window !== "undefined") {
|
|
3060
|
+
throw new Error(`${methodName} is server-only. Use Blink CRUD methods (blink.db.<table>.*) instead.`);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
2940
3063
|
function camelToSnake3(str) {
|
|
2941
3064
|
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
2942
3065
|
}
|
|
@@ -3155,6 +3278,7 @@ var BlinkTable = class {
|
|
|
3155
3278
|
* Raw SQL query on this table (for advanced use cases)
|
|
3156
3279
|
*/
|
|
3157
3280
|
async sql(query, params) {
|
|
3281
|
+
assertServerOnly("blink.db.<table>.sql");
|
|
3158
3282
|
const response = await this.httpClient.dbSql(query, params);
|
|
3159
3283
|
return response.data;
|
|
3160
3284
|
}
|
|
@@ -3203,6 +3327,7 @@ var BlinkDatabase = class {
|
|
|
3203
3327
|
* Execute raw SQL query
|
|
3204
3328
|
*/
|
|
3205
3329
|
async sql(query, params) {
|
|
3330
|
+
assertServerOnly("blink.db.sql");
|
|
3206
3331
|
const response = await this.httpClient.dbSql(query, params);
|
|
3207
3332
|
return response.data;
|
|
3208
3333
|
}
|
|
@@ -3210,6 +3335,7 @@ var BlinkDatabase = class {
|
|
|
3210
3335
|
* Execute batch SQL operations
|
|
3211
3336
|
*/
|
|
3212
3337
|
async batch(statements, mode = "write") {
|
|
3338
|
+
assertServerOnly("blink.db.batch");
|
|
3213
3339
|
const response = await this.httpClient.dbBatch(statements, mode);
|
|
3214
3340
|
return response.data;
|
|
3215
3341
|
}
|
|
@@ -3272,7 +3398,6 @@ var BlinkStorageImpl = class {
|
|
|
3272
3398
|
correctedPath,
|
|
3273
3399
|
// Use corrected path with proper extension
|
|
3274
3400
|
{
|
|
3275
|
-
upsert: options.upsert,
|
|
3276
3401
|
onProgress: options.onProgress,
|
|
3277
3402
|
contentType: detectedContentType
|
|
3278
3403
|
// Pass detected content type
|
|
@@ -3292,7 +3417,7 @@ var BlinkStorageImpl = class {
|
|
|
3292
3417
|
if (error instanceof Error && "status" in error) {
|
|
3293
3418
|
const status = error.status;
|
|
3294
3419
|
if (status === 409) {
|
|
3295
|
-
throw new BlinkStorageError("File already exists.
|
|
3420
|
+
throw new BlinkStorageError("File already exists.", 409);
|
|
3296
3421
|
}
|
|
3297
3422
|
if (status === 400) {
|
|
3298
3423
|
throw new BlinkStorageError("Invalid request parameters", 400);
|
|
@@ -3337,7 +3462,6 @@ var BlinkStorageImpl = class {
|
|
|
3337
3462
|
detectedContentType
|
|
3338
3463
|
};
|
|
3339
3464
|
} catch (error) {
|
|
3340
|
-
console.warn("File type detection failed, using original path:", error);
|
|
3341
3465
|
return {
|
|
3342
3466
|
correctedPath: originalPath,
|
|
3343
3467
|
detectedContentType: "application/octet-stream"
|
|
@@ -3727,13 +3851,7 @@ var BlinkAIImpl = class {
|
|
|
3727
3851
|
options.prompt || "",
|
|
3728
3852
|
requestBody
|
|
3729
3853
|
);
|
|
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
|
-
}
|
|
3854
|
+
return response.data;
|
|
3737
3855
|
} catch (error) {
|
|
3738
3856
|
if (error instanceof BlinkAIError) {
|
|
3739
3857
|
throw error;
|
|
@@ -3802,9 +3920,14 @@ var BlinkAIImpl = class {
|
|
|
3802
3920
|
);
|
|
3803
3921
|
return {
|
|
3804
3922
|
text: result.text || "",
|
|
3805
|
-
finishReason: "stop",
|
|
3923
|
+
finishReason: result.finishReason || "stop",
|
|
3806
3924
|
usage: result.usage,
|
|
3807
|
-
|
|
3925
|
+
toolCalls: result.toolCalls,
|
|
3926
|
+
toolResults: result.toolResults,
|
|
3927
|
+
sources: result.sources,
|
|
3928
|
+
files: result.files,
|
|
3929
|
+
reasoningDetails: result.reasoning,
|
|
3930
|
+
response: result.response
|
|
3808
3931
|
};
|
|
3809
3932
|
} catch (error) {
|
|
3810
3933
|
if (error instanceof BlinkAIError) {
|
|
@@ -3883,13 +4006,7 @@ var BlinkAIImpl = class {
|
|
|
3883
4006
|
signal: options.signal
|
|
3884
4007
|
}
|
|
3885
4008
|
);
|
|
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
|
-
}
|
|
4009
|
+
return response.data;
|
|
3893
4010
|
} catch (error) {
|
|
3894
4011
|
if (error instanceof BlinkAIError) {
|
|
3895
4012
|
throw error;
|
|
@@ -3951,8 +4068,7 @@ var BlinkAIImpl = class {
|
|
|
3951
4068
|
return {
|
|
3952
4069
|
object: result.object || {},
|
|
3953
4070
|
finishReason: "stop",
|
|
3954
|
-
usage: result.usage
|
|
3955
|
-
...result
|
|
4071
|
+
usage: result.usage
|
|
3956
4072
|
};
|
|
3957
4073
|
} catch (error) {
|
|
3958
4074
|
if (error instanceof BlinkAIError) {
|
|
@@ -4213,6 +4329,131 @@ var BlinkAIImpl = class {
|
|
|
4213
4329
|
);
|
|
4214
4330
|
}
|
|
4215
4331
|
}
|
|
4332
|
+
/**
|
|
4333
|
+
* Generates videos from text prompts or images using AI video generation models.
|
|
4334
|
+
*
|
|
4335
|
+
* @param options - Object containing:
|
|
4336
|
+
* - `prompt`: Text description of the video to generate (required)
|
|
4337
|
+
* - `model`: Video model to use (optional). Available models:
|
|
4338
|
+
* **Text-to-Video Models:**
|
|
4339
|
+
* - `"fal-ai/veo3.1"` - Google Veo 3.1 (best quality)
|
|
4340
|
+
* - `"fal-ai/veo3.1/fast"` (default) - Veo 3.1 fast mode (faster, cheaper)
|
|
4341
|
+
* - `"fal-ai/sora-2/text-to-video/pro"` - OpenAI Sora 2
|
|
4342
|
+
* - `"fal-ai/kling-video/v2.6/pro/text-to-video"` - Kling 2.6
|
|
4343
|
+
* **Image-to-Video Models:**
|
|
4344
|
+
* - `"fal-ai/veo3.1/image-to-video"` - Veo 3.1 I2V
|
|
4345
|
+
* - `"fal-ai/veo3.1/fast/image-to-video"` - Veo 3.1 fast I2V
|
|
4346
|
+
* - `"fal-ai/sora-2/image-to-video/pro"` - Sora 2 I2V
|
|
4347
|
+
* - `"fal-ai/kling-video/v2.6/pro/image-to-video"` - Kling 2.6 I2V
|
|
4348
|
+
* - `image_url`: Source image URL for image-to-video (required for I2V models)
|
|
4349
|
+
* - `duration`: Video duration ("4s", "5s", "6s", "8s", "10s", "12s")
|
|
4350
|
+
* - `aspect_ratio`: Aspect ratio ("16:9", "9:16", "1:1")
|
|
4351
|
+
* - `resolution`: Resolution ("720p", "1080p") - Veo/Sora only
|
|
4352
|
+
* - `negative_prompt`: What to avoid in generation - Veo/Kling only
|
|
4353
|
+
* - `generate_audio`: Generate audio with video (default: true)
|
|
4354
|
+
* - `seed`: For reproducibility - Veo only
|
|
4355
|
+
* - `cfg_scale`: Guidance scale (0-1) - Kling only
|
|
4356
|
+
* - Plus optional signal parameter
|
|
4357
|
+
*
|
|
4358
|
+
* @example
|
|
4359
|
+
* ```ts
|
|
4360
|
+
* // Basic text-to-video generation (uses default fast model)
|
|
4361
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4362
|
+
* prompt: "A serene sunset over the ocean with gentle waves"
|
|
4363
|
+
* });
|
|
4364
|
+
* console.log("Video URL:", result.video.url);
|
|
4365
|
+
*
|
|
4366
|
+
* // High quality with Veo 3.1
|
|
4367
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4368
|
+
* prompt: "A cinematic shot of a futuristic city at night",
|
|
4369
|
+
* model: "fal-ai/veo3.1",
|
|
4370
|
+
* resolution: "1080p",
|
|
4371
|
+
* aspect_ratio: "16:9"
|
|
4372
|
+
* });
|
|
4373
|
+
*
|
|
4374
|
+
* // Image-to-video animation
|
|
4375
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4376
|
+
* prompt: "Animate this image with gentle camera movement",
|
|
4377
|
+
* model: "fal-ai/veo3.1/fast/image-to-video",
|
|
4378
|
+
* image_url: "https://example.com/my-image.jpg",
|
|
4379
|
+
* duration: "5s"
|
|
4380
|
+
* });
|
|
4381
|
+
*
|
|
4382
|
+
* // Using Sora 2 for creative videos
|
|
4383
|
+
* const { result } = await blink.ai.generateVideo({
|
|
4384
|
+
* prompt: "A magical forest with glowing fireflies",
|
|
4385
|
+
* model: "fal-ai/sora-2/text-to-video/pro",
|
|
4386
|
+
* duration: "8s"
|
|
4387
|
+
* });
|
|
4388
|
+
*
|
|
4389
|
+
* // Using Kling for detailed videos
|
|
4390
|
+
* const { result, usage } = await blink.ai.generateVideo({
|
|
4391
|
+
* prompt: "A professional cooking tutorial scene",
|
|
4392
|
+
* model: "fal-ai/kling-video/v2.6/pro/text-to-video",
|
|
4393
|
+
* negative_prompt: "blur, distort, low quality",
|
|
4394
|
+
* cfg_scale: 0.7
|
|
4395
|
+
* });
|
|
4396
|
+
* console.log("Credits charged:", usage?.creditsCharged);
|
|
4397
|
+
* ```
|
|
4398
|
+
*
|
|
4399
|
+
* @returns Promise<VideoGenerationResponse> - Object containing:
|
|
4400
|
+
* - `result.video.url`: URL to the generated video
|
|
4401
|
+
* - `result.video.content_type`: MIME type (video/mp4)
|
|
4402
|
+
* - `result.video.file_name`: Generated filename
|
|
4403
|
+
* - `result.video.file_size`: File size in bytes
|
|
4404
|
+
* - `metadata`: Generation metadata (projectId, timestamp, model)
|
|
4405
|
+
* - `usage`: Credits charged and cost information
|
|
4406
|
+
*/
|
|
4407
|
+
async generateVideo(options) {
|
|
4408
|
+
try {
|
|
4409
|
+
if (!options.prompt) {
|
|
4410
|
+
throw new BlinkAIError("Prompt is required");
|
|
4411
|
+
}
|
|
4412
|
+
const i2vModels = [
|
|
4413
|
+
"fal-ai/veo3.1/image-to-video",
|
|
4414
|
+
"fal-ai/veo3.1/fast/image-to-video",
|
|
4415
|
+
"fal-ai/sora-2/image-to-video/pro",
|
|
4416
|
+
"fal-ai/kling-video/v2.6/pro/image-to-video"
|
|
4417
|
+
];
|
|
4418
|
+
if (options.model && i2vModels.includes(options.model) && !options.image_url) {
|
|
4419
|
+
throw new BlinkAIError("image_url is required for image-to-video models");
|
|
4420
|
+
}
|
|
4421
|
+
if (options.image_url) {
|
|
4422
|
+
const validation = this.validateImageUrl(options.image_url);
|
|
4423
|
+
if (!validation.isValid) {
|
|
4424
|
+
throw new BlinkAIError(`Invalid image_url: ${validation.error}`);
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
const response = await this.httpClient.aiVideo(
|
|
4428
|
+
options.prompt,
|
|
4429
|
+
{
|
|
4430
|
+
model: options.model,
|
|
4431
|
+
image_url: options.image_url,
|
|
4432
|
+
duration: options.duration,
|
|
4433
|
+
aspect_ratio: options.aspect_ratio,
|
|
4434
|
+
resolution: options.resolution,
|
|
4435
|
+
negative_prompt: options.negative_prompt,
|
|
4436
|
+
generate_audio: options.generate_audio,
|
|
4437
|
+
seed: options.seed,
|
|
4438
|
+
cfg_scale: options.cfg_scale,
|
|
4439
|
+
signal: options.signal
|
|
4440
|
+
}
|
|
4441
|
+
);
|
|
4442
|
+
if (!response.data?.result?.video?.url) {
|
|
4443
|
+
throw new BlinkAIError("Invalid response format: missing video URL");
|
|
4444
|
+
}
|
|
4445
|
+
return response.data;
|
|
4446
|
+
} catch (error) {
|
|
4447
|
+
if (error instanceof BlinkAIError) {
|
|
4448
|
+
throw error;
|
|
4449
|
+
}
|
|
4450
|
+
throw new BlinkAIError(
|
|
4451
|
+
`Video generation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
4452
|
+
void 0,
|
|
4453
|
+
{ originalError: error }
|
|
4454
|
+
);
|
|
4455
|
+
}
|
|
4456
|
+
}
|
|
4216
4457
|
/**
|
|
4217
4458
|
* Converts text to speech using AI voice synthesis models.
|
|
4218
4459
|
*
|
|
@@ -5271,7 +5512,6 @@ var BlinkAnalyticsImpl = class {
|
|
|
5271
5512
|
} catch (error) {
|
|
5272
5513
|
this.queue = [...events, ...this.queue];
|
|
5273
5514
|
this.persistQueue();
|
|
5274
|
-
console.error("Failed to send analytics events:", error);
|
|
5275
5515
|
}
|
|
5276
5516
|
if (this.queue.length > 0) {
|
|
5277
5517
|
this.timer = setTimeout(() => this.flush(), BATCH_TIMEOUT);
|
|
@@ -5462,6 +5702,64 @@ var BlinkAnalyticsImpl = class {
|
|
|
5462
5702
|
}
|
|
5463
5703
|
};
|
|
5464
5704
|
|
|
5705
|
+
// src/connectors.ts
|
|
5706
|
+
var BlinkConnectorsImpl = class {
|
|
5707
|
+
constructor(httpClient) {
|
|
5708
|
+
this.httpClient = httpClient;
|
|
5709
|
+
}
|
|
5710
|
+
async status(provider, options) {
|
|
5711
|
+
const response = await this.httpClient.connectorStatus(provider);
|
|
5712
|
+
return response.data;
|
|
5713
|
+
}
|
|
5714
|
+
async execute(provider, request) {
|
|
5715
|
+
const response = await this.httpClient.connectorExecute(provider, request);
|
|
5716
|
+
return response.data;
|
|
5717
|
+
}
|
|
5718
|
+
async saveApiKey(provider, request) {
|
|
5719
|
+
const response = await this.httpClient.connectorSaveApiKey(provider, request);
|
|
5720
|
+
return response.data;
|
|
5721
|
+
}
|
|
5722
|
+
};
|
|
5723
|
+
|
|
5724
|
+
// src/functions.ts
|
|
5725
|
+
var BlinkFunctionsImpl = class {
|
|
5726
|
+
httpClient;
|
|
5727
|
+
projectId;
|
|
5728
|
+
constructor(httpClient, projectId, _getToken) {
|
|
5729
|
+
this.httpClient = httpClient;
|
|
5730
|
+
this.projectId = projectId;
|
|
5731
|
+
}
|
|
5732
|
+
/**
|
|
5733
|
+
* Get the project suffix from the full project ID.
|
|
5734
|
+
* Project IDs are formatted as: prj_xxxxx
|
|
5735
|
+
* The suffix is the last 8 characters used in function URLs.
|
|
5736
|
+
*/
|
|
5737
|
+
getProjectSuffix() {
|
|
5738
|
+
return this.projectId.slice(-8);
|
|
5739
|
+
}
|
|
5740
|
+
/**
|
|
5741
|
+
* Build the full function URL
|
|
5742
|
+
*/
|
|
5743
|
+
buildFunctionUrl(functionSlug, searchParams) {
|
|
5744
|
+
const suffix = this.getProjectSuffix();
|
|
5745
|
+
const baseUrl = `https://${suffix}--${functionSlug}.functions.blink.new`;
|
|
5746
|
+
if (!searchParams || Object.keys(searchParams).length === 0) {
|
|
5747
|
+
return baseUrl;
|
|
5748
|
+
}
|
|
5749
|
+
const url = new URL(baseUrl);
|
|
5750
|
+
Object.entries(searchParams).forEach(([key, value]) => {
|
|
5751
|
+
url.searchParams.set(key, value);
|
|
5752
|
+
});
|
|
5753
|
+
return url.toString();
|
|
5754
|
+
}
|
|
5755
|
+
async invoke(functionSlug, options = {}) {
|
|
5756
|
+
const { method = "POST", body, headers = {}, searchParams } = options;
|
|
5757
|
+
const url = this.buildFunctionUrl(functionSlug, searchParams);
|
|
5758
|
+
const res = await this.httpClient.request(url, { method, body, headers });
|
|
5759
|
+
return { data: res.data, status: res.status, headers: res.headers };
|
|
5760
|
+
}
|
|
5761
|
+
};
|
|
5762
|
+
|
|
5465
5763
|
// src/client.ts
|
|
5466
5764
|
var BlinkClientImpl = class {
|
|
5467
5765
|
auth;
|
|
@@ -5472,8 +5770,13 @@ var BlinkClientImpl = class {
|
|
|
5472
5770
|
realtime;
|
|
5473
5771
|
notifications;
|
|
5474
5772
|
analytics;
|
|
5773
|
+
connectors;
|
|
5774
|
+
functions;
|
|
5475
5775
|
httpClient;
|
|
5476
5776
|
constructor(config) {
|
|
5777
|
+
if ((config.secretKey || config.serviceToken) && isBrowser) {
|
|
5778
|
+
throw new Error("secretKey/serviceToken is server-only. Do not provide it in browser/React Native clients.");
|
|
5779
|
+
}
|
|
5477
5780
|
this.auth = new BlinkAuth(config);
|
|
5478
5781
|
this.httpClient = new HttpClient(
|
|
5479
5782
|
config,
|
|
@@ -5487,6 +5790,12 @@ var BlinkClientImpl = class {
|
|
|
5487
5790
|
this.realtime = new BlinkRealtimeImpl(this.httpClient, config.projectId);
|
|
5488
5791
|
this.notifications = new BlinkNotificationsImpl(this.httpClient);
|
|
5489
5792
|
this.analytics = new BlinkAnalyticsImpl(this.httpClient, config.projectId);
|
|
5793
|
+
this.connectors = new BlinkConnectorsImpl(this.httpClient);
|
|
5794
|
+
this.functions = new BlinkFunctionsImpl(
|
|
5795
|
+
this.httpClient,
|
|
5796
|
+
config.projectId,
|
|
5797
|
+
() => this.auth.getValidToken()
|
|
5798
|
+
);
|
|
5490
5799
|
this.auth.onAuthStateChanged((state) => {
|
|
5491
5800
|
if (state.isAuthenticated && state.user) {
|
|
5492
5801
|
this.analytics.setUserId(state.user.id);
|
|
@@ -5505,6 +5814,6 @@ function createClient(config) {
|
|
|
5505
5814
|
return new BlinkClientImpl(config);
|
|
5506
5815
|
}
|
|
5507
5816
|
|
|
5508
|
-
export { AsyncStorageAdapter, BlinkAIImpl, BlinkAnalyticsImpl, BlinkDataImpl, BlinkDatabase, BlinkRealtimeChannel, BlinkRealtimeImpl, BlinkStorageImpl, BlinkTable, NoOpStorageAdapter, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isNode, isReactNative, isWeb, platform };
|
|
5817
|
+
export { AsyncStorageAdapter, BlinkAIImpl, BlinkAnalyticsImpl, BlinkConnectorsImpl, BlinkDataImpl, BlinkDatabase, BlinkRealtimeChannel, BlinkRealtimeImpl, BlinkStorageImpl, BlinkTable, NoOpStorageAdapter, WebStorageAdapter, createClient, getDefaultStorageAdapter, isBrowser, isDeno, isNode, isReactNative, isServer, isWeb, platform };
|
|
5509
5818
|
//# sourceMappingURL=index.mjs.map
|
|
5510
5819
|
//# sourceMappingURL=index.mjs.map
|