qstd 0.3.42 → 0.3.44
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/block/drawer.d.ts.map +1 -1
- package/dist/client/index.cjs +71 -5
- package/dist/client/index.js +71 -5
- package/dist/react/index.cjs +5 -0
- package/dist/react/index.js +5 -0
- package/dist/server/index.cjs +71 -5
- package/dist/server/index.js +71 -5
- package/dist/shared/api/domain.d.ts +19 -1
- package/dist/shared/api/domain.d.ts.map +1 -1
- package/dist/shared/api/fns.d.ts +43 -0
- package/dist/shared/api/fns.d.ts.map +1 -1
- package/dist/shared/api/index.d.ts +22 -1
- package/dist/shared/api/index.d.ts.map +1 -1
- package/dist/shared/api/types.d.ts +43 -3
- package/dist/shared/api/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/block/drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,QAAA,MAAM,SAAS,KAAoB,CAAC;AACpC,QAAA,MAAM,SAAS,KAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/block/drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,QAAA,MAAM,SAAS,KAAoB,CAAC;AACpC,QAAA,MAAM,SAAS,KAAuB,CAAC;AA4WvC,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,2CAMxD;AAID,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,2CAYrE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,uDAkDrE"}
|
package/dist/client/index.cjs
CHANGED
|
@@ -638,6 +638,7 @@ __export(api_exports, {
|
|
|
638
638
|
RestError: () => RestError,
|
|
639
639
|
configure: () => configure,
|
|
640
640
|
get: () => get,
|
|
641
|
+
parseSSE: () => parseSSE,
|
|
641
642
|
patch: () => patch,
|
|
642
643
|
post: () => post,
|
|
643
644
|
put: () => put,
|
|
@@ -719,11 +720,80 @@ var prepareBody = (body, input) => {
|
|
|
719
720
|
}
|
|
720
721
|
return body;
|
|
721
722
|
};
|
|
723
|
+
async function* parseSSE(stream) {
|
|
724
|
+
const reader = stream.getReader();
|
|
725
|
+
const decoder = new TextDecoder();
|
|
726
|
+
let buffer = "";
|
|
727
|
+
let eventType;
|
|
728
|
+
let eventId;
|
|
729
|
+
let dataLines = [];
|
|
730
|
+
const parseJsonData = (rawData) => {
|
|
731
|
+
try {
|
|
732
|
+
return JSON.parse(rawData);
|
|
733
|
+
} catch {
|
|
734
|
+
const preview = rawData.length > 100 ? rawData.slice(0, 100) + "..." : rawData;
|
|
735
|
+
throw new Error(
|
|
736
|
+
`[api] SSE data must be valid JSON. This parser expects your server to send JSON-formatted data in each SSE event. If you're sending plain strings or another format, you'll need to update your server to send JSON instead (e.g., {"message":"Hello"} instead of just "Hello").
|
|
737
|
+
|
|
738
|
+
Received: ${preview}`
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
try {
|
|
743
|
+
while (true) {
|
|
744
|
+
const { done, value } = await reader.read();
|
|
745
|
+
if (done) break;
|
|
746
|
+
buffer += decoder.decode(value, { stream: true });
|
|
747
|
+
const lines = buffer.split("\n");
|
|
748
|
+
buffer = lines.pop() || "";
|
|
749
|
+
for (const line of lines) {
|
|
750
|
+
if (line === "" || line === "\r") {
|
|
751
|
+
if (dataLines.length > 0) {
|
|
752
|
+
const rawData = dataLines.join("\n");
|
|
753
|
+
yield {
|
|
754
|
+
data: parseJsonData(rawData),
|
|
755
|
+
...eventType && { event: eventType },
|
|
756
|
+
...eventId && { id: eventId }
|
|
757
|
+
};
|
|
758
|
+
dataLines = [];
|
|
759
|
+
eventType = void 0;
|
|
760
|
+
eventId = void 0;
|
|
761
|
+
}
|
|
762
|
+
} else if (line.startsWith("data:")) {
|
|
763
|
+
const value2 = line.slice(5);
|
|
764
|
+
dataLines.push(value2.startsWith(" ") ? value2.slice(1) : value2);
|
|
765
|
+
} else if (line.startsWith("event:")) {
|
|
766
|
+
const value2 = line.slice(6);
|
|
767
|
+
eventType = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
768
|
+
} else if (line.startsWith("id:")) {
|
|
769
|
+
const value2 = line.slice(3);
|
|
770
|
+
eventId = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (dataLines.length > 0) {
|
|
775
|
+
const rawData = dataLines.join("\n");
|
|
776
|
+
yield {
|
|
777
|
+
data: parseJsonData(rawData),
|
|
778
|
+
...eventType && { event: eventType },
|
|
779
|
+
...eventId && { id: eventId }
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
} finally {
|
|
783
|
+
reader.releaseLock();
|
|
784
|
+
}
|
|
785
|
+
}
|
|
722
786
|
var parseResponse = async (response, output, onProgress) => {
|
|
723
787
|
const out = output ?? "json";
|
|
724
788
|
if (out === "stream") {
|
|
725
789
|
return response.body;
|
|
726
790
|
}
|
|
791
|
+
if (out === "sse") {
|
|
792
|
+
if (!response.body) {
|
|
793
|
+
throw new Error("[api] SSE output requires a response body");
|
|
794
|
+
}
|
|
795
|
+
return parseSSE(response.body);
|
|
796
|
+
}
|
|
727
797
|
if (onProgress && response.body) {
|
|
728
798
|
const total = Number(response.headers.get("Content-Length")) || 0;
|
|
729
799
|
let loaded = 0;
|
|
@@ -808,11 +878,7 @@ var request = async (method, path, options, defaultInput) => {
|
|
|
808
878
|
return opts?.onSuccess ? opts.onSuccess(data) : data;
|
|
809
879
|
};
|
|
810
880
|
function get(path, opts) {
|
|
811
|
-
return request(
|
|
812
|
-
"GET",
|
|
813
|
-
path,
|
|
814
|
-
opts
|
|
815
|
-
);
|
|
881
|
+
return request("GET", path, opts);
|
|
816
882
|
}
|
|
817
883
|
function post(path, body, opts) {
|
|
818
884
|
return request(
|
package/dist/client/index.js
CHANGED
|
@@ -631,6 +631,7 @@ __export(api_exports, {
|
|
|
631
631
|
RestError: () => RestError,
|
|
632
632
|
configure: () => configure,
|
|
633
633
|
get: () => get,
|
|
634
|
+
parseSSE: () => parseSSE,
|
|
634
635
|
patch: () => patch,
|
|
635
636
|
post: () => post,
|
|
636
637
|
put: () => put,
|
|
@@ -712,11 +713,80 @@ var prepareBody = (body, input) => {
|
|
|
712
713
|
}
|
|
713
714
|
return body;
|
|
714
715
|
};
|
|
716
|
+
async function* parseSSE(stream) {
|
|
717
|
+
const reader = stream.getReader();
|
|
718
|
+
const decoder = new TextDecoder();
|
|
719
|
+
let buffer = "";
|
|
720
|
+
let eventType;
|
|
721
|
+
let eventId;
|
|
722
|
+
let dataLines = [];
|
|
723
|
+
const parseJsonData = (rawData) => {
|
|
724
|
+
try {
|
|
725
|
+
return JSON.parse(rawData);
|
|
726
|
+
} catch {
|
|
727
|
+
const preview = rawData.length > 100 ? rawData.slice(0, 100) + "..." : rawData;
|
|
728
|
+
throw new Error(
|
|
729
|
+
`[api] SSE data must be valid JSON. This parser expects your server to send JSON-formatted data in each SSE event. If you're sending plain strings or another format, you'll need to update your server to send JSON instead (e.g., {"message":"Hello"} instead of just "Hello").
|
|
730
|
+
|
|
731
|
+
Received: ${preview}`
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
try {
|
|
736
|
+
while (true) {
|
|
737
|
+
const { done, value } = await reader.read();
|
|
738
|
+
if (done) break;
|
|
739
|
+
buffer += decoder.decode(value, { stream: true });
|
|
740
|
+
const lines = buffer.split("\n");
|
|
741
|
+
buffer = lines.pop() || "";
|
|
742
|
+
for (const line of lines) {
|
|
743
|
+
if (line === "" || line === "\r") {
|
|
744
|
+
if (dataLines.length > 0) {
|
|
745
|
+
const rawData = dataLines.join("\n");
|
|
746
|
+
yield {
|
|
747
|
+
data: parseJsonData(rawData),
|
|
748
|
+
...eventType && { event: eventType },
|
|
749
|
+
...eventId && { id: eventId }
|
|
750
|
+
};
|
|
751
|
+
dataLines = [];
|
|
752
|
+
eventType = void 0;
|
|
753
|
+
eventId = void 0;
|
|
754
|
+
}
|
|
755
|
+
} else if (line.startsWith("data:")) {
|
|
756
|
+
const value2 = line.slice(5);
|
|
757
|
+
dataLines.push(value2.startsWith(" ") ? value2.slice(1) : value2);
|
|
758
|
+
} else if (line.startsWith("event:")) {
|
|
759
|
+
const value2 = line.slice(6);
|
|
760
|
+
eventType = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
761
|
+
} else if (line.startsWith("id:")) {
|
|
762
|
+
const value2 = line.slice(3);
|
|
763
|
+
eventId = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (dataLines.length > 0) {
|
|
768
|
+
const rawData = dataLines.join("\n");
|
|
769
|
+
yield {
|
|
770
|
+
data: parseJsonData(rawData),
|
|
771
|
+
...eventType && { event: eventType },
|
|
772
|
+
...eventId && { id: eventId }
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
} finally {
|
|
776
|
+
reader.releaseLock();
|
|
777
|
+
}
|
|
778
|
+
}
|
|
715
779
|
var parseResponse = async (response, output, onProgress) => {
|
|
716
780
|
const out = output ?? "json";
|
|
717
781
|
if (out === "stream") {
|
|
718
782
|
return response.body;
|
|
719
783
|
}
|
|
784
|
+
if (out === "sse") {
|
|
785
|
+
if (!response.body) {
|
|
786
|
+
throw new Error("[api] SSE output requires a response body");
|
|
787
|
+
}
|
|
788
|
+
return parseSSE(response.body);
|
|
789
|
+
}
|
|
720
790
|
if (onProgress && response.body) {
|
|
721
791
|
const total = Number(response.headers.get("Content-Length")) || 0;
|
|
722
792
|
let loaded = 0;
|
|
@@ -801,11 +871,7 @@ var request = async (method, path, options, defaultInput) => {
|
|
|
801
871
|
return opts?.onSuccess ? opts.onSuccess(data) : data;
|
|
802
872
|
};
|
|
803
873
|
function get(path, opts) {
|
|
804
|
-
return request(
|
|
805
|
-
"GET",
|
|
806
|
-
path,
|
|
807
|
-
opts
|
|
808
|
-
);
|
|
874
|
+
return request("GET", path, opts);
|
|
809
875
|
}
|
|
810
876
|
function post(path, body, opts) {
|
|
811
877
|
return request(
|
package/dist/react/index.cjs
CHANGED
|
@@ -2616,6 +2616,10 @@ function DrawerComponent(props) {
|
|
|
2616
2616
|
const dragControls = framerMotion.useDragControls();
|
|
2617
2617
|
const { open, setOpen } = useDrawer();
|
|
2618
2618
|
const { onClose, onExitComplete, ...rest } = props;
|
|
2619
|
+
const [mounted, setMounted] = React13__namespace.default.useState(false);
|
|
2620
|
+
React13__namespace.default.useEffect(() => {
|
|
2621
|
+
setMounted(true);
|
|
2622
|
+
}, []);
|
|
2619
2623
|
const y = framerMotion.useMotionValue(0);
|
|
2620
2624
|
const openDrawer = () => {
|
|
2621
2625
|
y.stop();
|
|
@@ -2697,6 +2701,7 @@ function DrawerComponent(props) {
|
|
|
2697
2701
|
console.log("[close] clicked backdrop");
|
|
2698
2702
|
closeFnRef.current?.();
|
|
2699
2703
|
};
|
|
2704
|
+
if (!mounted) return null;
|
|
2700
2705
|
return reactDom.createPortal(
|
|
2701
2706
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, mode: "wait", onExitComplete, children: open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2702
2707
|
Backdrop,
|
package/dist/react/index.js
CHANGED
|
@@ -2593,6 +2593,10 @@ function DrawerComponent(props) {
|
|
|
2593
2593
|
const dragControls = useDragControls();
|
|
2594
2594
|
const { open, setOpen } = useDrawer();
|
|
2595
2595
|
const { onClose, onExitComplete, ...rest } = props;
|
|
2596
|
+
const [mounted, setMounted] = React13__default.useState(false);
|
|
2597
|
+
React13__default.useEffect(() => {
|
|
2598
|
+
setMounted(true);
|
|
2599
|
+
}, []);
|
|
2596
2600
|
const y = useMotionValue(0);
|
|
2597
2601
|
const openDrawer = () => {
|
|
2598
2602
|
y.stop();
|
|
@@ -2674,6 +2678,7 @@ function DrawerComponent(props) {
|
|
|
2674
2678
|
console.log("[close] clicked backdrop");
|
|
2675
2679
|
closeFnRef.current?.();
|
|
2676
2680
|
};
|
|
2681
|
+
if (!mounted) return null;
|
|
2677
2682
|
return createPortal(
|
|
2678
2683
|
/* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", onExitComplete, children: open && /* @__PURE__ */ jsx(
|
|
2679
2684
|
Backdrop,
|
package/dist/server/index.cjs
CHANGED
|
@@ -643,6 +643,7 @@ __export(api_exports, {
|
|
|
643
643
|
RestError: () => RestError,
|
|
644
644
|
configure: () => configure,
|
|
645
645
|
get: () => get,
|
|
646
|
+
parseSSE: () => parseSSE,
|
|
646
647
|
patch: () => patch,
|
|
647
648
|
post: () => post,
|
|
648
649
|
put: () => put,
|
|
@@ -724,11 +725,80 @@ var prepareBody = (body, input) => {
|
|
|
724
725
|
}
|
|
725
726
|
return body;
|
|
726
727
|
};
|
|
728
|
+
async function* parseSSE(stream) {
|
|
729
|
+
const reader = stream.getReader();
|
|
730
|
+
const decoder = new TextDecoder();
|
|
731
|
+
let buffer = "";
|
|
732
|
+
let eventType;
|
|
733
|
+
let eventId;
|
|
734
|
+
let dataLines = [];
|
|
735
|
+
const parseJsonData = (rawData) => {
|
|
736
|
+
try {
|
|
737
|
+
return JSON.parse(rawData);
|
|
738
|
+
} catch {
|
|
739
|
+
const preview = rawData.length > 100 ? rawData.slice(0, 100) + "..." : rawData;
|
|
740
|
+
throw new Error(
|
|
741
|
+
`[api] SSE data must be valid JSON. This parser expects your server to send JSON-formatted data in each SSE event. If you're sending plain strings or another format, you'll need to update your server to send JSON instead (e.g., {"message":"Hello"} instead of just "Hello").
|
|
742
|
+
|
|
743
|
+
Received: ${preview}`
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
try {
|
|
748
|
+
while (true) {
|
|
749
|
+
const { done, value } = await reader.read();
|
|
750
|
+
if (done) break;
|
|
751
|
+
buffer += decoder.decode(value, { stream: true });
|
|
752
|
+
const lines = buffer.split("\n");
|
|
753
|
+
buffer = lines.pop() || "";
|
|
754
|
+
for (const line of lines) {
|
|
755
|
+
if (line === "" || line === "\r") {
|
|
756
|
+
if (dataLines.length > 0) {
|
|
757
|
+
const rawData = dataLines.join("\n");
|
|
758
|
+
yield {
|
|
759
|
+
data: parseJsonData(rawData),
|
|
760
|
+
...eventType && { event: eventType },
|
|
761
|
+
...eventId && { id: eventId }
|
|
762
|
+
};
|
|
763
|
+
dataLines = [];
|
|
764
|
+
eventType = void 0;
|
|
765
|
+
eventId = void 0;
|
|
766
|
+
}
|
|
767
|
+
} else if (line.startsWith("data:")) {
|
|
768
|
+
const value2 = line.slice(5);
|
|
769
|
+
dataLines.push(value2.startsWith(" ") ? value2.slice(1) : value2);
|
|
770
|
+
} else if (line.startsWith("event:")) {
|
|
771
|
+
const value2 = line.slice(6);
|
|
772
|
+
eventType = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
773
|
+
} else if (line.startsWith("id:")) {
|
|
774
|
+
const value2 = line.slice(3);
|
|
775
|
+
eventId = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
if (dataLines.length > 0) {
|
|
780
|
+
const rawData = dataLines.join("\n");
|
|
781
|
+
yield {
|
|
782
|
+
data: parseJsonData(rawData),
|
|
783
|
+
...eventType && { event: eventType },
|
|
784
|
+
...eventId && { id: eventId }
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
} finally {
|
|
788
|
+
reader.releaseLock();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
727
791
|
var parseResponse = async (response2, output, onProgress) => {
|
|
728
792
|
const out = output ?? "json";
|
|
729
793
|
if (out === "stream") {
|
|
730
794
|
return response2.body;
|
|
731
795
|
}
|
|
796
|
+
if (out === "sse") {
|
|
797
|
+
if (!response2.body) {
|
|
798
|
+
throw new Error("[api] SSE output requires a response body");
|
|
799
|
+
}
|
|
800
|
+
return parseSSE(response2.body);
|
|
801
|
+
}
|
|
732
802
|
if (onProgress && response2.body) {
|
|
733
803
|
const total = Number(response2.headers.get("Content-Length")) || 0;
|
|
734
804
|
let loaded = 0;
|
|
@@ -813,11 +883,7 @@ var request = async (method, path, options, defaultInput) => {
|
|
|
813
883
|
return opts?.onSuccess ? opts.onSuccess(data) : data;
|
|
814
884
|
};
|
|
815
885
|
function get(path, opts) {
|
|
816
|
-
return request(
|
|
817
|
-
"GET",
|
|
818
|
-
path,
|
|
819
|
-
opts
|
|
820
|
-
);
|
|
886
|
+
return request("GET", path, opts);
|
|
821
887
|
}
|
|
822
888
|
function post(path, body, opts) {
|
|
823
889
|
return request(
|
package/dist/server/index.js
CHANGED
|
@@ -640,6 +640,7 @@ __export(api_exports, {
|
|
|
640
640
|
RestError: () => RestError,
|
|
641
641
|
configure: () => configure,
|
|
642
642
|
get: () => get,
|
|
643
|
+
parseSSE: () => parseSSE,
|
|
643
644
|
patch: () => patch,
|
|
644
645
|
post: () => post,
|
|
645
646
|
put: () => put,
|
|
@@ -721,11 +722,80 @@ var prepareBody = (body, input) => {
|
|
|
721
722
|
}
|
|
722
723
|
return body;
|
|
723
724
|
};
|
|
725
|
+
async function* parseSSE(stream) {
|
|
726
|
+
const reader = stream.getReader();
|
|
727
|
+
const decoder = new TextDecoder();
|
|
728
|
+
let buffer = "";
|
|
729
|
+
let eventType;
|
|
730
|
+
let eventId;
|
|
731
|
+
let dataLines = [];
|
|
732
|
+
const parseJsonData = (rawData) => {
|
|
733
|
+
try {
|
|
734
|
+
return JSON.parse(rawData);
|
|
735
|
+
} catch {
|
|
736
|
+
const preview = rawData.length > 100 ? rawData.slice(0, 100) + "..." : rawData;
|
|
737
|
+
throw new Error(
|
|
738
|
+
`[api] SSE data must be valid JSON. This parser expects your server to send JSON-formatted data in each SSE event. If you're sending plain strings or another format, you'll need to update your server to send JSON instead (e.g., {"message":"Hello"} instead of just "Hello").
|
|
739
|
+
|
|
740
|
+
Received: ${preview}`
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
try {
|
|
745
|
+
while (true) {
|
|
746
|
+
const { done, value } = await reader.read();
|
|
747
|
+
if (done) break;
|
|
748
|
+
buffer += decoder.decode(value, { stream: true });
|
|
749
|
+
const lines = buffer.split("\n");
|
|
750
|
+
buffer = lines.pop() || "";
|
|
751
|
+
for (const line of lines) {
|
|
752
|
+
if (line === "" || line === "\r") {
|
|
753
|
+
if (dataLines.length > 0) {
|
|
754
|
+
const rawData = dataLines.join("\n");
|
|
755
|
+
yield {
|
|
756
|
+
data: parseJsonData(rawData),
|
|
757
|
+
...eventType && { event: eventType },
|
|
758
|
+
...eventId && { id: eventId }
|
|
759
|
+
};
|
|
760
|
+
dataLines = [];
|
|
761
|
+
eventType = void 0;
|
|
762
|
+
eventId = void 0;
|
|
763
|
+
}
|
|
764
|
+
} else if (line.startsWith("data:")) {
|
|
765
|
+
const value2 = line.slice(5);
|
|
766
|
+
dataLines.push(value2.startsWith(" ") ? value2.slice(1) : value2);
|
|
767
|
+
} else if (line.startsWith("event:")) {
|
|
768
|
+
const value2 = line.slice(6);
|
|
769
|
+
eventType = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
770
|
+
} else if (line.startsWith("id:")) {
|
|
771
|
+
const value2 = line.slice(3);
|
|
772
|
+
eventId = value2.startsWith(" ") ? value2.slice(1) : value2;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
if (dataLines.length > 0) {
|
|
777
|
+
const rawData = dataLines.join("\n");
|
|
778
|
+
yield {
|
|
779
|
+
data: parseJsonData(rawData),
|
|
780
|
+
...eventType && { event: eventType },
|
|
781
|
+
...eventId && { id: eventId }
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
} finally {
|
|
785
|
+
reader.releaseLock();
|
|
786
|
+
}
|
|
787
|
+
}
|
|
724
788
|
var parseResponse = async (response2, output, onProgress) => {
|
|
725
789
|
const out = output ?? "json";
|
|
726
790
|
if (out === "stream") {
|
|
727
791
|
return response2.body;
|
|
728
792
|
}
|
|
793
|
+
if (out === "sse") {
|
|
794
|
+
if (!response2.body) {
|
|
795
|
+
throw new Error("[api] SSE output requires a response body");
|
|
796
|
+
}
|
|
797
|
+
return parseSSE(response2.body);
|
|
798
|
+
}
|
|
729
799
|
if (onProgress && response2.body) {
|
|
730
800
|
const total = Number(response2.headers.get("Content-Length")) || 0;
|
|
731
801
|
let loaded = 0;
|
|
@@ -810,11 +880,7 @@ var request = async (method, path, options, defaultInput) => {
|
|
|
810
880
|
return opts?.onSuccess ? opts.onSuccess(data) : data;
|
|
811
881
|
};
|
|
812
882
|
function get(path, opts) {
|
|
813
|
-
return request(
|
|
814
|
-
"GET",
|
|
815
|
-
path,
|
|
816
|
-
opts
|
|
817
|
-
);
|
|
883
|
+
return request("GET", path, opts);
|
|
818
884
|
}
|
|
819
885
|
function post(path, body, opts) {
|
|
820
886
|
return request(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BodylessOptions, Config, DataForOutput, JsonRes, Options, Output, ReqFrom, ResFrom } from "./types";
|
|
1
|
+
import type { BodylessOptions, Config, DataForOutput, JsonRes, Options, Output, ReqFrom, ResFrom, SSEEvent } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* Configure the API client with base URL and default headers.
|
|
4
4
|
*
|
|
@@ -57,10 +57,19 @@ export declare const configure: (c: Config) => void;
|
|
|
57
57
|
*
|
|
58
58
|
* // Download as blob
|
|
59
59
|
* const image = await Api.get("/avatar.png", { output: "blob" });
|
|
60
|
+
*
|
|
61
|
+
* // SSE streaming
|
|
62
|
+
* const events = await Api.get<{ Res: Event }>("/events", { output: "sse" });
|
|
63
|
+
* for await (const { data } of events) { ... }
|
|
60
64
|
* ```
|
|
61
65
|
*
|
|
62
66
|
* @throws {RestError} When the response is not ok and no `onError` handler is provided.
|
|
63
67
|
*/
|
|
68
|
+
export declare function get<TTypes = unknown>(path: string, opts: Omit<Options<JsonRes<ResFrom<TTypes>>, never, "sse">, "onSuccess" | "onError"> & {
|
|
69
|
+
output: "sse";
|
|
70
|
+
onSuccess?: undefined;
|
|
71
|
+
onError?: undefined;
|
|
72
|
+
}): Promise<AsyncGenerator<SSEEvent<JsonRes<ResFrom<TTypes>>>, void, unknown>>;
|
|
64
73
|
export declare function get<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, opts: Options<JsonRes<ResFrom<TTypes>>, Return, O> & {
|
|
65
74
|
onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
|
|
66
75
|
}): Promise<Return>;
|
|
@@ -94,10 +103,19 @@ export declare function get<TTypes = unknown, O extends Output | undefined = und
|
|
|
94
103
|
*
|
|
95
104
|
* // External URL (never includes configured default headers like auth)
|
|
96
105
|
* await Api.post(presignedUrl, formData);
|
|
106
|
+
*
|
|
107
|
+
* // SSE streaming (output type inferred from { output: "sse" })
|
|
108
|
+
* const events = await Api.post<{ Res: ChatChunk }>("/chat", body, { output: "sse" });
|
|
109
|
+
* for await (const { data } of events) { ... }
|
|
97
110
|
* ```
|
|
98
111
|
*
|
|
99
112
|
* @throws {RestError} When the response is not ok and no `onError` handler is provided.
|
|
100
113
|
*/
|
|
114
|
+
export declare function post<TTypes = unknown>(path: string, body: ReqFrom<TTypes>, opts: Omit<BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, never, "sse">, "onSuccess" | "onError"> & {
|
|
115
|
+
output: "sse";
|
|
116
|
+
onSuccess?: undefined;
|
|
117
|
+
onError?: undefined;
|
|
118
|
+
}): Promise<AsyncGenerator<SSEEvent<JsonRes<ResFrom<TTypes>>>, void, unknown>>;
|
|
101
119
|
export declare function post<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, body: ReqFrom<TTypes>, opts: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
|
|
102
120
|
onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
|
|
103
121
|
}): Promise<Return>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/shared/api/domain.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EAEf,MAAM,EACN,aAAa,EAGb,OAAO,EAEP,OAAO,EACP,MAAM,EACN,OAAO,EACP,OAAO,
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/shared/api/domain.ts"],"names":[],"mappings":"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"}
|
package/dist/shared/api/fns.d.ts
CHANGED
|
@@ -136,5 +136,48 @@ export declare const prepareBody: (body: unknown, input: _t.Input | undefined) =
|
|
|
136
136
|
* );
|
|
137
137
|
* ```
|
|
138
138
|
*/
|
|
139
|
+
/**
|
|
140
|
+
* Parse a ReadableStream as Server-Sent Events (SSE).
|
|
141
|
+
*
|
|
142
|
+
* SSE is a W3C standard wire format for server-to-client streaming. This parser
|
|
143
|
+
* handles the protocol details:
|
|
144
|
+
* - Buffers incomplete lines across chunks (network packets don't align with events)
|
|
145
|
+
* - Parses `data:`, `event:`, `id:` fields per the spec
|
|
146
|
+
* - Yields complete events when an empty line is encountered
|
|
147
|
+
*
|
|
148
|
+
* The generator yields `SSEEvent<T>` objects containing the parsed data and optional
|
|
149
|
+
* event type and ID fields. It completes naturally when the stream ends.
|
|
150
|
+
*
|
|
151
|
+
* Note: Application-level signals like `[DONE]` (OpenAI) are NOT handled here.
|
|
152
|
+
* Those are application semantics, not protocol. The consumer should check for
|
|
153
|
+
* them in the yielded events.
|
|
154
|
+
*
|
|
155
|
+
* ## ⚠️ Important: JSON is required
|
|
156
|
+
*
|
|
157
|
+
* This parser **always** JSON-parses the `data:` payload. Your server must send
|
|
158
|
+
* valid JSON in each SSE event. If it sends plain strings, XML, or any non-JSON
|
|
159
|
+
* format, parsing will fail with a descriptive error.
|
|
160
|
+
*
|
|
161
|
+
* **Why JSON-only?** This matches regular HTTP behavior — when you type
|
|
162
|
+
* `Res: SomeInterface`, you're declaring a JSON contract. SSE follows the same
|
|
163
|
+
* convention: typed data = JSON data.
|
|
164
|
+
*
|
|
165
|
+
* @throws {Error} When a `data:` payload is not valid JSON. The error message
|
|
166
|
+
* includes the raw data that failed to parse for debugging.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* // ✅ Works - server sends JSON
|
|
171
|
+
* // Server: data: {"type":"delta","content":"Hello"}
|
|
172
|
+
* for await (const { data } of parseSSE<ChatChunk>(stream)) {
|
|
173
|
+
* console.log(data.type); // "delta"
|
|
174
|
+
* }
|
|
175
|
+
*
|
|
176
|
+
* // ❌ Throws - server sends plain string
|
|
177
|
+
* // Server: data: Hello world
|
|
178
|
+
* // Error: "SSE data must be valid JSON. Received: Hello world"
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export declare function parseSSE<T = unknown>(stream: ReadableStream<Uint8Array>): AsyncGenerator<_t.SSEEvent<T>, void, unknown>;
|
|
139
182
|
export declare const parseResponse: <Res, O extends _t.Output | undefined = undefined>(response: Response, output?: O, onProgress?: (progress: _t.Progress) => void) => Promise<_t.DataForOutput<Res, O>>;
|
|
140
183
|
//# sourceMappingURL=fns.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fns.d.ts","sourceRoot":"","sources":["../../../src/shared/api/fns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAwB9B;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,YAA4B,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,EACZ,OAAO;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAA;CAAE,KAC7C,MA+BF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,cAAc,GAAU,OAAO;IAC1C,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC;IAC3B,aAAa,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAC9D,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf,KAAG,OAAO,CAAC,EAAE,CAAC,aAAa,GAAG,SAAS,CA6BvC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,OAAO,EACb,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,KAC1B,QAAQ,GAAG,SAuBb,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,aAAa,GACxB,GAAG,EACH,CAAC,SAAS,EAAE,CAAC,MAAM,GAAG,SAAS,GAAG,SAAS,EAE3C,UAAU,QAAQ,EAClB,SAAS,CAAC,EACV,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,IAAI,KAC3C,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"fns.d.ts","sourceRoot":"","sources":["../../../src/shared/api/fns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAwB9B;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,YAA4B,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,EACZ,OAAO;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAA;CAAE,KAC7C,MA+BF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,cAAc,GAAU,OAAO;IAC1C,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC;IAC3B,aAAa,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAC9D,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf,KAAG,OAAO,CAAC,EAAE,CAAC,aAAa,GAAG,SAAS,CA6BvC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,OAAO,EACb,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,KAC1B,QAAQ,GAAG,SAuBb,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAuB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACzC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GACjC,cAAc,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAoF/C;AAED,eAAO,MAAM,aAAa,GACxB,GAAG,EACH,CAAC,SAAS,EAAE,CAAC,MAAM,GAAG,SAAS,GAAG,SAAS,EAE3C,UAAU,QAAQ,EAClB,SAAS,CAAC,EACV,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,IAAI,KAC3C,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,CAyDlC,CAAC"}
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* - default / `"json"` → `response.text()` then `JSON.parse(...)`
|
|
12
12
|
* - `"blob"` → `response.blob()`
|
|
13
13
|
* - `"arrayBuffer"` → `response.arrayBuffer()`
|
|
14
|
-
* - `"stream"` → `response.body`
|
|
14
|
+
* - `"stream"` → `response.body` (raw ReadableStream)
|
|
15
|
+
* - `"sse"` → `AsyncGenerator<SSEEvent<Res>>` (Server-Sent Events, JSON only)
|
|
15
16
|
*
|
|
16
17
|
* The return type is derived from `output`. If you try to use a non-JSON response
|
|
17
18
|
* type (like `Blob`) without setting `output`, TypeScript will surface a helpful
|
|
@@ -22,6 +23,15 @@
|
|
|
22
23
|
* - FormData → multipart (browser sets Content-Type with boundary)
|
|
23
24
|
* - Blob → uses blob.type for Content-Type
|
|
24
25
|
*
|
|
26
|
+
* ### SSE streaming (output: "sse")
|
|
27
|
+
*
|
|
28
|
+
* For Server-Sent Events streaming, use `output: "sse"`. This returns an async
|
|
29
|
+
* generator that yields parsed events.
|
|
30
|
+
*
|
|
31
|
+
* **⚠️ SSE requires JSON data.** Your server must send valid JSON in each
|
|
32
|
+
* `data:` line. Plain strings or other formats will throw an error with a
|
|
33
|
+
* helpful message explaining what went wrong.
|
|
34
|
+
*
|
|
25
35
|
* @example
|
|
26
36
|
* ```ts
|
|
27
37
|
* // Configure once at app startup
|
|
@@ -48,9 +58,20 @@
|
|
|
48
58
|
*
|
|
49
59
|
* // External URL (never includes configured default headers like auth)
|
|
50
60
|
* await Api.post(s3PresignedUrl, formData);
|
|
61
|
+
*
|
|
62
|
+
* // SSE streaming (server must send JSON in each data: line)
|
|
63
|
+
* // Server sends: data: {"type":"delta","content":"Hello"}
|
|
64
|
+
* type ChatChunk = { type: "delta" | "done"; content?: string };
|
|
65
|
+
* const events = Api.post<{ Res: ChatChunk }>("/chat", body, { output: "sse" });
|
|
66
|
+
* for await (const { data } of events) {
|
|
67
|
+
* if (data.type === "delta") {
|
|
68
|
+
* content += data.content;
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
51
71
|
* ```
|
|
52
72
|
*/
|
|
53
73
|
export { RestError } from "./types";
|
|
74
|
+
export { parseSSE } from "./fns";
|
|
54
75
|
export type * from "./types";
|
|
55
76
|
export * from "./domain";
|
|
56
77
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/api/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,mBAAmB,SAAS,CAAC;AAC7B,cAAc,UAAU,CAAC"}
|
|
@@ -16,7 +16,44 @@ export type Config = {
|
|
|
16
16
|
};
|
|
17
17
|
export type Params = Record<string, string | number | boolean | undefined | null>;
|
|
18
18
|
export type Input = "json" | "form" | "text";
|
|
19
|
-
export type Output = "json" | "text" | "blob" | "stream" | "arrayBuffer";
|
|
19
|
+
export type Output = "json" | "text" | "blob" | "stream" | "arrayBuffer" | "sse";
|
|
20
|
+
/**
|
|
21
|
+
* A parsed Server-Sent Event.
|
|
22
|
+
*
|
|
23
|
+
* SSE is a W3C standard format for server-to-client streaming:
|
|
24
|
+
* - `data` is the event payload (always JSON-parsed)
|
|
25
|
+
* - `event` is the optional event type (from `event:` field)
|
|
26
|
+
* - `id` is the optional event ID (from `id:` field)
|
|
27
|
+
*
|
|
28
|
+
* ## ⚠️ Important: JSON is required
|
|
29
|
+
*
|
|
30
|
+
* The `data` field is **always** parsed as JSON. The `Res` type parameter
|
|
31
|
+
* defines the expected JSON shape. If your server sends non-JSON data
|
|
32
|
+
* (plain strings, XML, etc.), this will throw a parse error.
|
|
33
|
+
*
|
|
34
|
+
* **Your server must send valid JSON in each `data:` line.**
|
|
35
|
+
*
|
|
36
|
+
* This matches the behavior of regular HTTP JSON responses — if you type
|
|
37
|
+
* `Res: SomeInterface`, you're declaring a JSON contract.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* // ✅ Server sends: data: {"type":"delta","content":"Hello"}
|
|
42
|
+
* type ChatChunk = { type: "delta" | "done"; content?: string };
|
|
43
|
+
* const events = Api.post<{ Res: ChatChunk }>("/chat", body, { output: "sse" });
|
|
44
|
+
* for await (const { data } of events) {
|
|
45
|
+
* console.log(data.type); // "delta"
|
|
46
|
+
* }
|
|
47
|
+
*
|
|
48
|
+
* // ❌ Server sends: data: Hello world (plain string, NOT JSON)
|
|
49
|
+
* // This will throw: "SSE data must be valid JSON"
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export type SSEEvent<T = unknown> = {
|
|
53
|
+
data: T;
|
|
54
|
+
event?: string;
|
|
55
|
+
id?: string;
|
|
56
|
+
};
|
|
20
57
|
/**
|
|
21
58
|
* Named generic type-args for API calls.
|
|
22
59
|
*
|
|
@@ -50,19 +87,20 @@ export type ResFrom<T> = IsTypeArgs<T> extends true ? "Res" extends keyof T ? T
|
|
|
50
87
|
*
|
|
51
88
|
* - `output: "json"` (or omitted) → `Res`
|
|
52
89
|
* - `output: "blob"` → `Blob`
|
|
90
|
+
* - `output: "sse"` → `AsyncGenerator<SSEEvent<Res>>`
|
|
53
91
|
* - etc.
|
|
54
92
|
*
|
|
55
93
|
* This makes `output` the single source of truth for non-JSON response shapes,
|
|
56
94
|
* while `Res` describes the JSON-decoded shape when `output` is omitted/`"json"`.
|
|
57
95
|
*/
|
|
58
|
-
export type DataForOutput<Res, O extends Output | undefined> = O extends "text" ? string : O extends "blob" ? Blob : O extends "stream" ? ReadableStream<Uint8Array> | null : O extends "arrayBuffer" ? ArrayBuffer : Res;
|
|
96
|
+
export type DataForOutput<Res, O extends Output | undefined> = O extends "text" ? string : O extends "blob" ? Blob : O extends "stream" ? ReadableStream<Uint8Array> | null : O extends "arrayBuffer" ? ArrayBuffer : O extends "sse" ? AsyncGenerator<SSEEvent<Res>, void, unknown> : Res;
|
|
59
97
|
/**
|
|
60
98
|
* Types that cannot be produced by JSON parsing and therefore require an explicit `output`.
|
|
61
99
|
*
|
|
62
100
|
* (We intentionally do NOT include `string` here because JSON can legitimately parse to a
|
|
63
101
|
* string, e.g. `"hello"`.)
|
|
64
102
|
*/
|
|
65
|
-
export type NonJsonDecoded = Blob | ArrayBuffer | ReadableStream<Uint8Array>;
|
|
103
|
+
export type NonJsonDecoded = Blob | ArrayBuffer | ReadableStream<Uint8Array> | AsyncGenerator<unknown>;
|
|
66
104
|
/**
|
|
67
105
|
* A helpful compile-time error shape when a non-JSON decoded type is requested without
|
|
68
106
|
* specifying the matching `output` option.
|
|
@@ -82,6 +120,7 @@ export type Options<Res, Return = Res, O extends Output | undefined = undefined>
|
|
|
82
120
|
params?: Params;
|
|
83
121
|
output?: O;
|
|
84
122
|
signal?: AbortSignal;
|
|
123
|
+
/** Progress callback for blob/arrayBuffer downloads (not applicable to SSE). */
|
|
85
124
|
onProgress?: (progress: Progress) => void;
|
|
86
125
|
onSuccess?: (data: DataForOutput<Res, O>) => Return;
|
|
87
126
|
onError?: (error: RestError) => Return;
|
|
@@ -93,6 +132,7 @@ export type BodyOptions<Req = unknown, Res = unknown, Return = Res, O extends Ou
|
|
|
93
132
|
params?: Params;
|
|
94
133
|
output?: O;
|
|
95
134
|
signal?: AbortSignal;
|
|
135
|
+
/** Progress callback for blob/arrayBuffer downloads (not applicable to SSE). */
|
|
96
136
|
onProgress?: (progress: Progress) => void;
|
|
97
137
|
onSuccess?: (data: DataForOutput<Res, O>) => Return;
|
|
98
138
|
onError?: (error: RestError) => Return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/api/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAMjE,qBAAa,SAAU,SAAQ,KAAK;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;gBAED,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAMpD;AAMD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AACzE,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,aAAa,KACpB,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5C,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC;CACzC,CAAC;AAMF,MAAM,MAAM,MAAM,GAAG,MAAM,CACzB,MAAM,EACN,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAC7C,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAC7C,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/api/types.ts"],"names":[],"mappings":"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"}
|