ai 3.0.5 → 3.0.7
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.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -10
- package/rsc/dist/index.d.ts +190 -0
- package/rsc/dist/index.mjs +18 -1
- package/rsc/dist/rsc-client.d.mts +1 -1
- package/rsc/dist/rsc-client.mjs +2 -2
- package/rsc/dist/rsc-client.mjs.map +1 -1
- package/rsc/dist/rsc-server.d.mts +11 -12
- package/rsc/dist/rsc-server.mjs +63 -20
- package/rsc/dist/rsc-server.mjs.map +1 -1
- package/rsc/dist/rsc-shared.d.mts +39 -8
- package/rsc/dist/rsc-shared.mjs +44 -35
- package/rsc/dist/rsc-shared.mjs.map +1 -1
- package/rsc/dist/index.d.mts +0 -6
- package/rsc/dist/index.mjs.map +0 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ai",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.7",
|
4
4
|
"license": "Apache-2.0",
|
5
5
|
"sideEffects": false,
|
6
6
|
"main": "./dist/index.js",
|
@@ -20,44 +20,37 @@
|
|
20
20
|
".": {
|
21
21
|
"types": "./dist/index.d.ts",
|
22
22
|
"import": "./dist/index.mjs",
|
23
|
-
"module": "./dist/index.mjs",
|
24
23
|
"require": "./dist/index.js"
|
25
24
|
},
|
26
25
|
"./rsc": {
|
27
|
-
"types": "./rsc/dist/index.d.
|
26
|
+
"types": "./rsc/dist/index.d.ts",
|
28
27
|
"react-server": "./rsc/dist/rsc-server.mjs",
|
29
|
-
"import": "./rsc/dist/rsc-client.mjs"
|
30
|
-
"module": "./rsc/dist/rsc-client.mjs"
|
28
|
+
"import": "./rsc/dist/rsc-client.mjs"
|
31
29
|
},
|
32
30
|
"./prompts": {
|
33
31
|
"types": "./prompts/dist/index.d.ts",
|
34
32
|
"import": "./prompts/dist/index.mjs",
|
35
|
-
"module": "./prompts/dist/index.mjs",
|
36
33
|
"require": "./prompts/dist/index.js"
|
37
34
|
},
|
38
35
|
"./react": {
|
39
36
|
"types": "./react/dist/index.d.ts",
|
40
37
|
"react-server": "./react/dist/index.server.mjs",
|
41
38
|
"import": "./react/dist/index.mjs",
|
42
|
-
"module": "./react/dist/index.mjs",
|
43
39
|
"require": "./react/dist/index.js"
|
44
40
|
},
|
45
41
|
"./svelte": {
|
46
42
|
"types": "./svelte/dist/index.d.ts",
|
47
43
|
"import": "./svelte/dist/index.mjs",
|
48
|
-
"module": "./svelte/dist/index.mjs",
|
49
44
|
"require": "./svelte/dist/index.js"
|
50
45
|
},
|
51
46
|
"./vue": {
|
52
47
|
"types": "./vue/dist/index.d.ts",
|
53
48
|
"import": "./vue/dist/index.mjs",
|
54
|
-
"module": "./vue/dist/index.mjs",
|
55
49
|
"require": "./vue/dist/index.js"
|
56
50
|
},
|
57
51
|
"./solid": {
|
58
52
|
"types": "./solid/dist/index.d.ts",
|
59
53
|
"import": "./solid/dist/index.mjs",
|
60
|
-
"module": "./solid/dist/index.mjs",
|
61
54
|
"require": "./solid/dist/index.js"
|
62
55
|
}
|
63
56
|
},
|
@@ -0,0 +1,190 @@
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
2
|
+
import { ReactNode } from 'react';
|
3
|
+
import OpenAI from 'openai';
|
4
|
+
import { z } from 'zod';
|
5
|
+
|
6
|
+
declare const STREAMABLE_VALUE_TYPE: unique symbol;
|
7
|
+
|
8
|
+
type AIAction<T = any, R = any> = (...args: T[]) => Promise<R>;
|
9
|
+
type AIActions<T = any, R = any> = Record<string, AIAction<T, R>>;
|
10
|
+
type AIProviderProps<AIState = any, UIState = any, Actions = any> = {
|
11
|
+
children: React.ReactNode;
|
12
|
+
initialAIState?: AIState;
|
13
|
+
initialUIState?: UIState;
|
14
|
+
/** $ActionTypes is only added for type inference and is never used at runtime **/
|
15
|
+
$ActionTypes?: Actions;
|
16
|
+
};
|
17
|
+
type AIProvider<AIState = any, UIState = any, Actions = any> = (props: AIProviderProps<AIState, UIState, Actions>) => Promise<React.ReactElement>;
|
18
|
+
type InferAIState<T, Fallback> = T extends AIProvider<infer AIState, any, any> ? AIState : Fallback;
|
19
|
+
type InferUIState<T, Fallback> = T extends AIProvider<any, infer UIState, any> ? UIState : Fallback;
|
20
|
+
type InferActions<T, Fallback> = T extends AIProvider<any, any, infer Actions> ? Actions : Fallback;
|
21
|
+
type OnSetAIState<S> = ({ key, state, done, }: {
|
22
|
+
key: string | number | symbol | undefined;
|
23
|
+
state: S;
|
24
|
+
done: boolean;
|
25
|
+
}) => void | Promise<void>;
|
26
|
+
type OnGetUIState<S> = AIAction<void, S | undefined>;
|
27
|
+
type ValueOrUpdater<T> = T | ((current: T) => T);
|
28
|
+
type MutableAIState<AIState> = {
|
29
|
+
get: () => AIState;
|
30
|
+
update: (newState: ValueOrUpdater<AIState>) => void;
|
31
|
+
done: ((newState: AIState) => void) | (() => void);
|
32
|
+
};
|
33
|
+
type StreamableValue<T = any, E = any> = {
|
34
|
+
type?: typeof STREAMABLE_VALUE_TYPE;
|
35
|
+
curr?: T;
|
36
|
+
error?: E;
|
37
|
+
next?: Promise<StreamableValue<T, E>>;
|
38
|
+
};
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Get the current AI state.
|
42
|
+
* If `key` is provided, it will return the value of the specified key in the
|
43
|
+
* AI state, if it's an object. If it's not an object, it will throw an error.
|
44
|
+
*
|
45
|
+
* @example const state = getAIState() // Get the entire AI state
|
46
|
+
* @example const field = getAIState('key') // Get the value of the key
|
47
|
+
*/
|
48
|
+
declare function getAIState<AI extends AIProvider = any>(): InferAIState<AI, any>;
|
49
|
+
declare function getAIState<AI extends AIProvider = any>(key: keyof InferAIState<AI, any>): InferAIState<AI, any>[typeof key];
|
50
|
+
/**
|
51
|
+
* Get the mutable AI state. Note that you must call `.close()` when finishing
|
52
|
+
* updating the AI state.
|
53
|
+
*
|
54
|
+
* @example
|
55
|
+
* ```tsx
|
56
|
+
* const state = getMutableAIState()
|
57
|
+
* state.update({ ...state.get(), key: 'value' })
|
58
|
+
* state.update((currentState) => ({ ...currentState, key: 'value' }))
|
59
|
+
* state.done()
|
60
|
+
* ```
|
61
|
+
*
|
62
|
+
* @example
|
63
|
+
* ```tsx
|
64
|
+
* const state = getMutableAIState()
|
65
|
+
* state.done({ ...state.get(), key: 'value' }) // Done with a new state
|
66
|
+
* ```
|
67
|
+
*/
|
68
|
+
declare function getMutableAIState<AI extends AIProvider = any>(): MutableAIState<InferAIState<AI, any>>;
|
69
|
+
declare function getMutableAIState<AI extends AIProvider = any>(key: keyof InferAIState<AI, any>): MutableAIState<InferAIState<AI, any>[typeof key]>;
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Create a piece of changable UI that can be streamed to the client.
|
73
|
+
* On the client side, it can be rendered as a normal React node.
|
74
|
+
*/
|
75
|
+
declare function createStreamableUI(initialValue?: React.ReactNode): {
|
76
|
+
value: react_jsx_runtime.JSX.Element;
|
77
|
+
update(value: React.ReactNode): void;
|
78
|
+
append(value: React.ReactNode): void;
|
79
|
+
error(error: any): void;
|
80
|
+
done(...args: any): void;
|
81
|
+
};
|
82
|
+
/**
|
83
|
+
* Create a wrapped, changable value that can be streamed to the client.
|
84
|
+
* On the client side, the value can be accessed via the readStreamableValue() API.
|
85
|
+
*/
|
86
|
+
declare function createStreamableValue<T = any, E = any>(initialValue?: T): {
|
87
|
+
value: StreamableValue<T, E>;
|
88
|
+
update(value: T): void;
|
89
|
+
error(error: any): void;
|
90
|
+
done(...args: any): void;
|
91
|
+
};
|
92
|
+
type Streamable = ReactNode | Promise<ReactNode>;
|
93
|
+
type Renderer<T> = (props: T) => Streamable | Generator<Streamable, Streamable, void> | AsyncGenerator<Streamable, Streamable, void>;
|
94
|
+
/**
|
95
|
+
* `render` is a helper function to create a streamable UI from some LLMs.
|
96
|
+
* Currently, it only supports OpenAI's GPT models with Function Calling and Assistants Tools.
|
97
|
+
*/
|
98
|
+
declare function render<TS extends {
|
99
|
+
[name: string]: z.Schema;
|
100
|
+
} = {}, FS extends {
|
101
|
+
[name: string]: z.Schema;
|
102
|
+
} = {}>(options: {
|
103
|
+
/**
|
104
|
+
* The model name to use. Must be OpenAI SDK compatible. Tools and Functions are only supported
|
105
|
+
* GPT models (3.5/4), OpenAI Assistants, Mistral small and large, and Fireworks firefunction-v1.
|
106
|
+
*
|
107
|
+
* @example "gpt-3.5-turbo"
|
108
|
+
*/
|
109
|
+
model: string;
|
110
|
+
/**
|
111
|
+
* The provider instance to use. Currently the only provider available is OpenAI.
|
112
|
+
* This needs to match the model name.
|
113
|
+
*/
|
114
|
+
provider: OpenAI;
|
115
|
+
messages: Parameters<typeof OpenAI.prototype.chat.completions.create>[0]['messages'];
|
116
|
+
text?: Renderer<{
|
117
|
+
content: string;
|
118
|
+
done: boolean;
|
119
|
+
}>;
|
120
|
+
tools?: {
|
121
|
+
[name in keyof TS]: {
|
122
|
+
description?: string;
|
123
|
+
parameters: TS[name];
|
124
|
+
render: Renderer<z.infer<TS[name]>>;
|
125
|
+
};
|
126
|
+
};
|
127
|
+
functions?: {
|
128
|
+
[name in keyof FS]: {
|
129
|
+
description?: string;
|
130
|
+
parameters: FS[name];
|
131
|
+
render: Renderer<z.infer<FS[name]>>;
|
132
|
+
};
|
133
|
+
};
|
134
|
+
initial?: ReactNode;
|
135
|
+
temperature?: number;
|
136
|
+
}): ReactNode;
|
137
|
+
|
138
|
+
declare function createAI<AIState = any, UIState = any, Actions extends AIActions = {}>({ actions, initialAIState, initialUIState, unstable_onSetAIState: onSetAIState, unstable_onGetUIState: onGetUIState, }: {
|
139
|
+
actions: Actions;
|
140
|
+
initialAIState?: AIState;
|
141
|
+
initialUIState?: UIState;
|
142
|
+
unstable_onSetAIState?: OnSetAIState<AIState>;
|
143
|
+
unstable_onGetUIState?: OnGetUIState<UIState>;
|
144
|
+
}): AIProvider<AIState, UIState, Actions>;
|
145
|
+
|
146
|
+
/**
|
147
|
+
* `readStreamableValue` takes a streamable value created via the `createStreamableValue().value` API,
|
148
|
+
* and returns an async iterator.
|
149
|
+
*
|
150
|
+
* ```js
|
151
|
+
* // Inside your AI action:
|
152
|
+
*
|
153
|
+
* async function action() {
|
154
|
+
* 'use server'
|
155
|
+
* const streamable = createStreamableValue();
|
156
|
+
*
|
157
|
+
* streamable.update(1);
|
158
|
+
* streamable.update(2);
|
159
|
+
* streamable.done(3);
|
160
|
+
* // ...
|
161
|
+
* return streamable.value;
|
162
|
+
* }
|
163
|
+
* ```
|
164
|
+
*
|
165
|
+
* And to read the value:
|
166
|
+
*
|
167
|
+
* ```js
|
168
|
+
* const streamableValue = await action()
|
169
|
+
* for await (const v of readStreamableValue(streamableValue)) {
|
170
|
+
* console.log(v)
|
171
|
+
* }
|
172
|
+
* ```
|
173
|
+
*
|
174
|
+
* This logs out 1, 2, 3 on console.
|
175
|
+
*/
|
176
|
+
declare function readStreamableValue<T = unknown>(streamableValue: StreamableValue<T>): AsyncIterable<T | undefined>;
|
177
|
+
|
178
|
+
declare function useUIState<AI extends AIProvider = any>(): [InferUIState<AI, any>, (v: InferUIState<AI, any> | ((v_: InferUIState<AI, any>) => InferUIState<AI, any>)) => void];
|
179
|
+
declare function useAIState<AI extends AIProvider = any>(): [
|
180
|
+
InferAIState<AI, any>,
|
181
|
+
(newState: ValueOrUpdater<InferAIState<AI, any>>) => void
|
182
|
+
];
|
183
|
+
declare function useAIState<AI extends AIProvider = any>(key: keyof InferAIState<AI, any>): [
|
184
|
+
InferAIState<AI, any>[typeof key],
|
185
|
+
(newState: ValueOrUpdater<InferAIState<AI, any>[typeof key]>) => void
|
186
|
+
];
|
187
|
+
declare function useActions<AI extends AIProvider = any>(): InferActions<AI, any>;
|
188
|
+
declare function useSyncUIState(): () => Promise<void>;
|
189
|
+
|
190
|
+
export { createAI, createStreamableUI, createStreamableValue, getAIState, getMutableAIState, readStreamableValue, render, useAIState, useActions, useSyncUIState, useUIState };
|
package/rsc/dist/index.mjs
CHANGED
@@ -1 +1,18 @@
|
|
1
|
-
|
1
|
+
"use strict";
|
2
|
+
var __defProp = Object.defineProperty;
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
8
|
+
for (let key of __getOwnPropNames(from))
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
11
|
+
}
|
12
|
+
return to;
|
13
|
+
};
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
15
|
+
|
16
|
+
// rsc/index.ts
|
17
|
+
var rsc_exports = {};
|
18
|
+
module.exports = __toCommonJS(rsc_exports);
|
@@ -1 +1 @@
|
|
1
|
-
export { useAIState, useActions,
|
1
|
+
export { readStreamableValue, useAIState, useActions, useSyncUIState, useUIState } from './rsc-shared.mjs';
|
package/rsc/dist/rsc-client.mjs
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
// rsc/rsc-client.ts
|
2
2
|
import {
|
3
|
-
|
3
|
+
readStreamableValue,
|
4
4
|
useUIState,
|
5
5
|
useAIState,
|
6
6
|
useActions,
|
7
7
|
useSyncUIState
|
8
8
|
} from "./rsc-shared.mjs";
|
9
9
|
export {
|
10
|
+
readStreamableValue,
|
10
11
|
useAIState,
|
11
12
|
useActions,
|
12
|
-
useStreamableValue,
|
13
13
|
useSyncUIState,
|
14
14
|
useUIState
|
15
15
|
};
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../rsc-client.ts"],"sourcesContent":["export {\n
|
1
|
+
{"version":3,"sources":["../rsc-client.ts"],"sourcesContent":["export {\n readStreamableValue,\n useUIState,\n useAIState,\n useActions,\n useSyncUIState,\n} from './rsc-shared.mjs';\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
|
@@ -2,7 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
3
3
|
import OpenAI from 'openai';
|
4
4
|
import { z } from 'zod';
|
5
|
-
|
5
|
+
|
6
|
+
declare const STREAMABLE_VALUE_TYPE: unique symbol;
|
6
7
|
|
7
8
|
type AIAction<T = any, R = any> = (...args: T[]) => Promise<R>;
|
8
9
|
type AIActions<T = any, R = any> = Record<string, AIAction<T, R>>;
|
@@ -27,6 +28,12 @@ type MutableAIState<AIState> = {
|
|
27
28
|
update: (newState: ValueOrUpdater<AIState>) => void;
|
28
29
|
done: ((newState: AIState) => void) | (() => void);
|
29
30
|
};
|
31
|
+
type StreamableValue<T = any, E = any> = {
|
32
|
+
type?: typeof STREAMABLE_VALUE_TYPE;
|
33
|
+
curr?: T;
|
34
|
+
error?: E;
|
35
|
+
next?: Promise<StreamableValue<T, E>>;
|
36
|
+
};
|
30
37
|
|
31
38
|
/**
|
32
39
|
* Get the current AI state.
|
@@ -72,18 +79,10 @@ declare function createStreamableUI(initialValue?: React.ReactNode): {
|
|
72
79
|
};
|
73
80
|
/**
|
74
81
|
* Create a wrapped, changable value that can be streamed to the client.
|
75
|
-
* On the client side, the value can be accessed via the
|
82
|
+
* On the client side, the value can be accessed via the readStreamableValue() API.
|
76
83
|
*/
|
77
|
-
declare function createStreamableValue<T = any>(initialValue?: T): {
|
78
|
-
value:
|
79
|
-
type: symbol;
|
80
|
-
curr: T | undefined;
|
81
|
-
next: Promise<any>;
|
82
|
-
} | {
|
83
|
-
curr: T | undefined;
|
84
|
-
next: Promise<any>;
|
85
|
-
type?: undefined;
|
86
|
-
};
|
84
|
+
declare function createStreamableValue<T = any, E = any>(initialValue?: T): {
|
85
|
+
value: StreamableValue<T, E>;
|
87
86
|
update(value: T): void;
|
88
87
|
error(error: any): void;
|
89
88
|
done(...args: any): void;
|
package/rsc/dist/rsc-server.mjs
CHANGED
@@ -745,7 +745,7 @@ function createFunctionCallTransformer(callbacks) {
|
|
745
745
|
type: "function",
|
746
746
|
func: {
|
747
747
|
name: tool.function.name,
|
748
|
-
arguments: tool.function.arguments
|
748
|
+
arguments: JSON.parse(tool.function.arguments)
|
749
749
|
}
|
750
750
|
});
|
751
751
|
}
|
@@ -842,6 +842,7 @@ function createFunctionCallTransformer(callbacks) {
|
|
842
842
|
|
843
843
|
// rsc/constants.ts
|
844
844
|
var STREAMABLE_VALUE_TYPE = Symbol.for("ui.streamable.value");
|
845
|
+
var DEV_DEFAULT_STREAMABLE_WARNING_TIME = 15 * 1e3;
|
845
846
|
|
846
847
|
// rsc/streamable.tsx
|
847
848
|
import { Fragment as Fragment2, jsxs as jsxs2 } from "react/jsx-runtime";
|
@@ -849,27 +850,39 @@ function createStreamableUI(initialValue) {
|
|
849
850
|
let currentValue = initialValue;
|
850
851
|
let closed = false;
|
851
852
|
let { row, resolve, reject } = createSuspensedChunk(initialValue);
|
852
|
-
function assertStream() {
|
853
|
+
function assertStream(method) {
|
853
854
|
if (closed) {
|
854
|
-
throw new Error("UI stream is already closed.");
|
855
|
+
throw new Error(method + ": UI stream is already closed.");
|
855
856
|
}
|
856
857
|
}
|
858
|
+
let warningTimeout;
|
859
|
+
function warnUnclosedStream() {
|
860
|
+
if (process.env.NODE_ENV === "development") {
|
861
|
+
if (warningTimeout) {
|
862
|
+
clearTimeout(warningTimeout);
|
863
|
+
}
|
864
|
+
warningTimeout = setTimeout(() => {
|
865
|
+
console.warn(
|
866
|
+
"The streamable UI has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`."
|
867
|
+
);
|
868
|
+
}, DEV_DEFAULT_STREAMABLE_WARNING_TIME);
|
869
|
+
}
|
870
|
+
}
|
871
|
+
warnUnclosedStream();
|
857
872
|
return {
|
858
873
|
value: row,
|
859
874
|
update(value) {
|
860
|
-
assertStream();
|
875
|
+
assertStream(".update()");
|
861
876
|
const resolvable = createResolvablePromise();
|
862
|
-
|
877
|
+
currentValue = value;
|
878
|
+
resolve({ value: currentValue, done: false, next: resolvable.promise });
|
863
879
|
resolve = resolvable.resolve;
|
864
880
|
reject = resolvable.reject;
|
865
|
-
|
881
|
+
warnUnclosedStream();
|
866
882
|
},
|
867
883
|
append(value) {
|
868
|
-
assertStream();
|
884
|
+
assertStream(".append()");
|
869
885
|
const resolvable = createResolvablePromise();
|
870
|
-
resolve({ value, done: false, next: resolvable.promise });
|
871
|
-
resolve = resolvable.resolve;
|
872
|
-
reject = resolvable.reject;
|
873
886
|
if (typeof currentValue === "string" && typeof value === "string") {
|
874
887
|
currentValue += value;
|
875
888
|
} else {
|
@@ -878,14 +891,24 @@ function createStreamableUI(initialValue) {
|
|
878
891
|
value
|
879
892
|
] });
|
880
893
|
}
|
894
|
+
resolve({ value: currentValue, done: false, next: resolvable.promise });
|
895
|
+
resolve = resolvable.resolve;
|
896
|
+
reject = resolvable.reject;
|
897
|
+
warnUnclosedStream();
|
881
898
|
},
|
882
899
|
error(error) {
|
883
|
-
assertStream();
|
900
|
+
assertStream(".error()");
|
901
|
+
if (warningTimeout) {
|
902
|
+
clearTimeout(warningTimeout);
|
903
|
+
}
|
884
904
|
closed = true;
|
885
905
|
reject(error);
|
886
906
|
},
|
887
907
|
done(...args) {
|
888
|
-
assertStream();
|
908
|
+
assertStream(".done()");
|
909
|
+
if (warningTimeout) {
|
910
|
+
clearTimeout(warningTimeout);
|
911
|
+
}
|
889
912
|
closed = true;
|
890
913
|
if (args.length) {
|
891
914
|
resolve({ value: args[0], done: true });
|
@@ -897,12 +920,26 @@ function createStreamableUI(initialValue) {
|
|
897
920
|
}
|
898
921
|
function createStreamableValue(initialValue) {
|
899
922
|
let closed = false;
|
900
|
-
let { promise, resolve
|
901
|
-
function assertStream() {
|
923
|
+
let { promise, resolve } = createResolvablePromise();
|
924
|
+
function assertStream(method) {
|
902
925
|
if (closed) {
|
903
|
-
throw new Error("Value stream is already closed.");
|
926
|
+
throw new Error(method + ": Value stream is already closed.");
|
927
|
+
}
|
928
|
+
}
|
929
|
+
let warningTimeout;
|
930
|
+
function warnUnclosedStream() {
|
931
|
+
if (process.env.NODE_ENV === "development") {
|
932
|
+
if (warningTimeout) {
|
933
|
+
clearTimeout(warningTimeout);
|
934
|
+
}
|
935
|
+
warningTimeout = setTimeout(() => {
|
936
|
+
console.warn(
|
937
|
+
"The streamable UI has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`."
|
938
|
+
);
|
939
|
+
}, DEV_DEFAULT_STREAMABLE_WARNING_TIME);
|
904
940
|
}
|
905
941
|
}
|
942
|
+
warnUnclosedStream();
|
906
943
|
function createWrapped(val, initial) {
|
907
944
|
if (initial) {
|
908
945
|
return {
|
@@ -919,21 +956,27 @@ function createStreamableValue(initialValue) {
|
|
919
956
|
return {
|
920
957
|
value: createWrapped(initialValue, true),
|
921
958
|
update(value) {
|
922
|
-
assertStream();
|
959
|
+
assertStream(".update()");
|
923
960
|
const resolvePrevious = resolve;
|
924
961
|
const resolvable = createResolvablePromise();
|
925
962
|
promise = resolvable.promise;
|
926
963
|
resolve = resolvable.resolve;
|
927
|
-
reject = resolvable.reject;
|
928
964
|
resolvePrevious(createWrapped(value));
|
965
|
+
warnUnclosedStream();
|
929
966
|
},
|
930
967
|
error(error) {
|
931
|
-
assertStream();
|
968
|
+
assertStream(".error()");
|
969
|
+
if (warningTimeout) {
|
970
|
+
clearTimeout(warningTimeout);
|
971
|
+
}
|
932
972
|
closed = true;
|
933
|
-
|
973
|
+
resolve({ error });
|
934
974
|
},
|
935
975
|
done(...args) {
|
936
|
-
assertStream();
|
976
|
+
assertStream(".done()");
|
977
|
+
if (warningTimeout) {
|
978
|
+
clearTimeout(warningTimeout);
|
979
|
+
}
|
937
980
|
closed = true;
|
938
981
|
if (args.length) {
|
939
982
|
resolve({ curr: args[0] });
|