@stack-spot/portal-network 0.184.0 → 0.185.0
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/CHANGELOG.md +2419 -2412
- package/dist/api/account.js +1 -1
- package/dist/api/agent-tools.js +1 -1
- package/dist/api/agent.js +1 -1
- package/dist/api/ai.js +1 -1
- package/dist/api/apiManagement.js +1 -1
- package/dist/api/apiRuntime.js +1 -1
- package/dist/api/cloudAccount.js +1 -1
- package/dist/api/cloudPlatform.js +1 -1
- package/dist/api/cloudPlatformHorizon.js +1 -1
- package/dist/api/cloudRuntimes.js +1 -1
- package/dist/api/cloudServices.js +1 -1
- package/dist/api/codeShift.d.ts +63 -4
- package/dist/api/codeShift.d.ts.map +1 -1
- package/dist/api/codeShift.js +14 -1
- package/dist/api/codeShift.js.map +1 -1
- package/dist/api/content.js +1 -1
- package/dist/api/dataIntegration.js +1 -1
- package/dist/api/discover.js +1 -1
- package/dist/api/genAiInference.js +1 -1
- package/dist/api/insights.js +1 -1
- package/dist/api/notification.js +1 -1
- package/dist/api/secrets.js +1 -1
- package/dist/api/serviceCatalog.js +1 -1
- package/dist/api/workspace-ai.js +1 -1
- package/dist/api/workspace.js +1 -1
- package/dist/api/workspaceManager.js +1 -1
- package/dist/api/workspaceSearchEngine.js +1 -1
- package/dist/client/code-shift.d.ts +22 -0
- package/dist/client/code-shift.d.ts.map +1 -1
- package/dist/client/code-shift.js +28 -1
- package/dist/client/code-shift.js.map +1 -1
- package/package.json +6 -6
- package/scripts/generate-apis.ts +134 -134
- package/src/api/account.ts +8367 -8367
- package/src/api/agent-tools.ts +2169 -2169
- package/src/api/agent.ts +1083 -1083
- package/src/api/ai.ts +3388 -3388
- package/src/api/apiManagement.ts +570 -570
- package/src/api/apiRuntime.ts +2103 -2103
- package/src/api/cloudAccount.ts +1239 -1239
- package/src/api/cloudPlatform.ts +927 -927
- package/src/api/cloudPlatformHorizon.ts +2655 -2655
- package/src/api/cloudRuntimes.ts +2043 -2043
- package/src/api/cloudServices.ts +1445 -1445
- package/src/api/codeShift.ts +3567 -3481
- package/src/api/content.ts +9785 -9785
- package/src/api/dataIntegration.ts +1657 -1657
- package/src/api/discover.ts +435 -435
- package/src/api/eventBus.ts +171 -171
- package/src/api/genAiInference.ts +603 -603
- package/src/api/insights.ts +310 -310
- package/src/api/notification.ts +334 -334
- package/src/api/secrets.ts +342 -342
- package/src/api/serviceCatalog.ts +2908 -2908
- package/src/api/workflows.ts +1669 -1669
- package/src/api/workspace-ai.ts +677 -677
- package/src/api/workspace.ts +5889 -5889
- package/src/api/workspaceManager.ts +2951 -2951
- package/src/api/workspaceSearchEngine.ts +153 -153
- package/src/api-addresses.ts +120 -120
- package/src/apis-itau.json +225 -225
- package/src/apis.json +225 -225
- package/src/client/account.ts +902 -902
- package/src/client/agent-tools.ts +210 -210
- package/src/client/agent.ts +81 -81
- package/src/client/ai.ts +395 -395
- package/src/client/api-management.ts +40 -40
- package/src/client/cloud-account.ts +70 -70
- package/src/client/cloud-platform-horizon.ts +113 -113
- package/src/client/cloud-platform.ts +163 -163
- package/src/client/cloud-runtimes.ts +129 -129
- package/src/client/cloud-services.ts +94 -94
- package/src/client/code-shift.ts +364 -349
- package/src/client/content.ts +538 -538
- package/src/client/data-integration.ts +191 -191
- package/src/client/discover.ts +89 -89
- package/src/client/event-bus.ts +84 -84
- package/src/client/gen-ai-inference.ts +65 -65
- package/src/client/insights.ts +28 -28
- package/src/client/notification.ts +32 -32
- package/src/client/runtime-manager.ts +76 -76
- package/src/client/secrets.ts +60 -60
- package/src/client/types.ts +377 -377
- package/src/client/workflow.ts +83 -83
- package/src/client/workspace-ai.ts +191 -191
- package/src/client/workspace-manager.ts +564 -564
- package/src/client/workspace-search.ts +39 -39
- package/src/client/workspace.ts +480 -480
- package/src/error/DefaultAPIError.ts +151 -151
- package/src/error/FileUploadError.ts +18 -18
- package/src/error/IgnoredErrorCodes.ts +3 -3
- package/src/error/StackspotAPIError.ts +101 -101
- package/src/error/StreamCanceledError.ts +10 -10
- package/src/error/StreamError.ts +7 -7
- package/src/error/StreamJsonError.ts +10 -10
- package/src/error/dictionary/account.ts +58 -58
- package/src/error/dictionary/action-details.ts +20 -20
- package/src/error/dictionary/action.ts +211 -211
- package/src/error/dictionary/agent-tools.ts +75 -75
- package/src/error/dictionary/ai-inference.ts +28 -28
- package/src/error/dictionary/base.ts +22 -22
- package/src/error/dictionary/cloud-platform.ts +82 -82
- package/src/error/dictionary/cnt-fields.ts +14 -14
- package/src/error/dictionary/cnt.ts +103 -103
- package/src/error/dictionary/code-shift.ts +12 -12
- package/src/error/dictionary/rte.ts +24 -24
- package/src/error/dictionary/rtm.ts +10 -10
- package/src/error/dictionary/secrets.ts +14 -14
- package/src/error/dictionary/workspace-ai.ts +10 -10
- package/src/error/dictionary/workspace-details.ts +15 -15
- package/src/error/dictionary/workspace-fields.ts +10 -10
- package/src/error/dictionary/workspace.ts +209 -209
- package/src/error/types.ts +21 -21
- package/src/index.ts +43 -43
- package/src/network/AutoInfiniteQuery.ts +115 -115
- package/src/network/AutoMutation.ts +27 -27
- package/src/network/AutoOperation.ts +73 -73
- package/src/network/AutoQuery.ts +75 -75
- package/src/network/ManualInfiniteQuery.ts +95 -95
- package/src/network/ManualMutation.ts +40 -40
- package/src/network/ManualOperation.ts +52 -52
- package/src/network/ManualQuery.ts +82 -82
- package/src/network/NetworkClient.ts +167 -167
- package/src/network/ReactQueryNetworkClient.ts +312 -312
- package/src/network/react-query-client.ts +14 -14
- package/src/network/types.ts +294 -294
- package/src/types.ts +1 -1
- package/src/utils/StreamedArray.tsx +146 -146
- package/src/utils/StreamedJson.tsx +166 -166
- package/src/utils/remove-authorization-param.ts +6 -6
- package/src/utils/string.ts +19 -19
- package/src/utils/use-extended-list.ts +80 -80
- package/src/utils/use-streamed-array.ts +17 -17
- package/tsconfig.build.json +4 -4
- package/tsconfig.json +10 -10
|
@@ -1,146 +1,146 @@
|
|
|
1
|
-
import { CompletablePromise } from '@stack-spot/opa'
|
|
2
|
-
import { StreamCanceledError } from '../error/StreamCanceledError'
|
|
3
|
-
import { StreamError } from '../error/StreamError'
|
|
4
|
-
import { StreamJsonError } from '../error/StreamJsonError'
|
|
5
|
-
import { FetchEventStream } from '../network/types'
|
|
6
|
-
import { StreamingStatus } from '../types'
|
|
7
|
-
|
|
8
|
-
type OnChangeListener<T> = (value: T[]) => void
|
|
9
|
-
|
|
10
|
-
interface ConstructorParams {
|
|
11
|
-
/**
|
|
12
|
-
* The promises that result in the EventStreams to build the final array.
|
|
13
|
-
*/
|
|
14
|
-
eventsPromises: Promise<FetchEventStream>[],
|
|
15
|
-
/**
|
|
16
|
-
* A controller to abort the streaming.
|
|
17
|
-
*/
|
|
18
|
-
abortController?: AbortController,
|
|
19
|
-
/**
|
|
20
|
-
* A minimum number of milliseconds to wait before calling onChange listeners.
|
|
21
|
-
* @default 50
|
|
22
|
-
*/
|
|
23
|
-
minChangeIntervalMS?: number,
|
|
24
|
-
/***
|
|
25
|
-
* Aborts this stream when the signal is aborted.
|
|
26
|
-
*/
|
|
27
|
-
signal?: AbortSignal,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* An array represented by a stream where each event contains an item of the array as a JSON string. This can be watched as the stream runs.
|
|
32
|
-
*/
|
|
33
|
-
export class StreamedArray<T> {
|
|
34
|
-
private onChangeListeners: OnChangeListener<T>[] = []
|
|
35
|
-
private error: StreamError | undefined
|
|
36
|
-
private data: T[] = []
|
|
37
|
-
private fullPromise = new CompletablePromise<T[]>()
|
|
38
|
-
private abortController: AbortController | undefined
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param response the fetch response.
|
|
42
|
-
* @param minChangeIntervalMS a stream can be too fast. This sets a minimum interval between running the listeners. The default is 50ms.
|
|
43
|
-
*/
|
|
44
|
-
constructor({ eventsPromises, abortController, minChangeIntervalMS = 50, signal }: ConstructorParams) {
|
|
45
|
-
this.abortController = abortController ?? new AbortController()
|
|
46
|
-
eventsPromises.forEach(eventsPromise => this.run(eventsPromise, minChangeIntervalMS))
|
|
47
|
-
if (signal) {
|
|
48
|
-
signal.addEventListener('abort', () => this.cancel())
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private async run(eventsPromise: Promise<FetchEventStream>, minChangeIntervalMS: number) {
|
|
53
|
-
let lastChangeCall = 0
|
|
54
|
-
try {
|
|
55
|
-
const events = await eventsPromise
|
|
56
|
-
let flushed = true
|
|
57
|
-
for await (const event of events) {
|
|
58
|
-
if (this.error) return
|
|
59
|
-
if (event.data) {
|
|
60
|
-
this.data.push(JSON.parse(event.data))
|
|
61
|
-
if (new Date().getTime() - lastChangeCall >= minChangeIntervalMS) {
|
|
62
|
-
this.onChangeListeners.forEach(l => l(this.data))
|
|
63
|
-
lastChangeCall = new Date().getTime()
|
|
64
|
-
flushed = true
|
|
65
|
-
} else {
|
|
66
|
-
flushed = false
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (!flushed) this.onChangeListeners.forEach(l => l(this.data))
|
|
71
|
-
} catch (error: any) {
|
|
72
|
-
if (error instanceof DOMException && error.name === 'AbortError') this.fail(new StreamCanceledError())
|
|
73
|
-
if (error instanceof SyntaxError) this.fail(new StreamJsonError())
|
|
74
|
-
else if (error instanceof StreamError) this.fail(error)
|
|
75
|
-
else this.fail(new StreamError(error?.message || `${error}`))
|
|
76
|
-
}
|
|
77
|
-
if (!this.error) this.complete()
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private clear() {
|
|
81
|
-
this.onChangeListeners = []
|
|
82
|
-
this.abortController = undefined
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
private fail(error: any) {
|
|
86
|
-
this.error = error
|
|
87
|
-
this.fullPromise.reject(this.error)
|
|
88
|
-
this.clear()
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
private complete() {
|
|
92
|
-
this.fullPromise.resolve(this.data)
|
|
93
|
-
this.clear()
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Returns the full value of the array once the stream finishes.
|
|
98
|
-
*/
|
|
99
|
-
getValue(): Promise<T[]> {
|
|
100
|
-
return this.fullPromise.promise
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Returns the streamed array with every item streamed until now. This will be the complete array if the stream has finished.
|
|
105
|
-
*/
|
|
106
|
-
getPartialValue(): T[] {
|
|
107
|
-
return this.data
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Watches the array as it's streamed. This doesn't wait for the value to be complete.
|
|
112
|
-
*
|
|
113
|
-
* The listener is called whenever the value changes.
|
|
114
|
-
*
|
|
115
|
-
* @param listener the function to call with the new value.
|
|
116
|
-
* @returns a function that, when called, removes the listener.
|
|
117
|
-
*/
|
|
118
|
-
onChange(listener: (value: T[]) => void) {
|
|
119
|
-
if (this.fullPromise.resolved) {
|
|
120
|
-
listener(this.data)
|
|
121
|
-
return () => {}
|
|
122
|
-
}
|
|
123
|
-
this.onChangeListeners.push(listener)
|
|
124
|
-
return () => {
|
|
125
|
-
const index = this.onChangeListeners?.findIndex(l => l === listener)
|
|
126
|
-
if (index !== undefined && index >= 0) this.onChangeListeners?.splice(index, 1)
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
getStatus(): StreamingStatus {
|
|
131
|
-
if (this.error) return 'error'
|
|
132
|
-
if (this.fullPromise.resolved) return 'success'
|
|
133
|
-
return 'pending'
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
getError() {
|
|
137
|
-
return this.error
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* If this is a stream and it's not yet finished, calling this function cancels the stream.
|
|
142
|
-
*/
|
|
143
|
-
cancel() {
|
|
144
|
-
this.abortController?.abort(new StreamCanceledError())
|
|
145
|
-
}
|
|
146
|
-
}
|
|
1
|
+
import { CompletablePromise } from '@stack-spot/opa'
|
|
2
|
+
import { StreamCanceledError } from '../error/StreamCanceledError'
|
|
3
|
+
import { StreamError } from '../error/StreamError'
|
|
4
|
+
import { StreamJsonError } from '../error/StreamJsonError'
|
|
5
|
+
import { FetchEventStream } from '../network/types'
|
|
6
|
+
import { StreamingStatus } from '../types'
|
|
7
|
+
|
|
8
|
+
type OnChangeListener<T> = (value: T[]) => void
|
|
9
|
+
|
|
10
|
+
interface ConstructorParams {
|
|
11
|
+
/**
|
|
12
|
+
* The promises that result in the EventStreams to build the final array.
|
|
13
|
+
*/
|
|
14
|
+
eventsPromises: Promise<FetchEventStream>[],
|
|
15
|
+
/**
|
|
16
|
+
* A controller to abort the streaming.
|
|
17
|
+
*/
|
|
18
|
+
abortController?: AbortController,
|
|
19
|
+
/**
|
|
20
|
+
* A minimum number of milliseconds to wait before calling onChange listeners.
|
|
21
|
+
* @default 50
|
|
22
|
+
*/
|
|
23
|
+
minChangeIntervalMS?: number,
|
|
24
|
+
/***
|
|
25
|
+
* Aborts this stream when the signal is aborted.
|
|
26
|
+
*/
|
|
27
|
+
signal?: AbortSignal,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* An array represented by a stream where each event contains an item of the array as a JSON string. This can be watched as the stream runs.
|
|
32
|
+
*/
|
|
33
|
+
export class StreamedArray<T> {
|
|
34
|
+
private onChangeListeners: OnChangeListener<T>[] = []
|
|
35
|
+
private error: StreamError | undefined
|
|
36
|
+
private data: T[] = []
|
|
37
|
+
private fullPromise = new CompletablePromise<T[]>()
|
|
38
|
+
private abortController: AbortController | undefined
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param response the fetch response.
|
|
42
|
+
* @param minChangeIntervalMS a stream can be too fast. This sets a minimum interval between running the listeners. The default is 50ms.
|
|
43
|
+
*/
|
|
44
|
+
constructor({ eventsPromises, abortController, minChangeIntervalMS = 50, signal }: ConstructorParams) {
|
|
45
|
+
this.abortController = abortController ?? new AbortController()
|
|
46
|
+
eventsPromises.forEach(eventsPromise => this.run(eventsPromise, minChangeIntervalMS))
|
|
47
|
+
if (signal) {
|
|
48
|
+
signal.addEventListener('abort', () => this.cancel())
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private async run(eventsPromise: Promise<FetchEventStream>, minChangeIntervalMS: number) {
|
|
53
|
+
let lastChangeCall = 0
|
|
54
|
+
try {
|
|
55
|
+
const events = await eventsPromise
|
|
56
|
+
let flushed = true
|
|
57
|
+
for await (const event of events) {
|
|
58
|
+
if (this.error) return
|
|
59
|
+
if (event.data) {
|
|
60
|
+
this.data.push(JSON.parse(event.data))
|
|
61
|
+
if (new Date().getTime() - lastChangeCall >= minChangeIntervalMS) {
|
|
62
|
+
this.onChangeListeners.forEach(l => l(this.data))
|
|
63
|
+
lastChangeCall = new Date().getTime()
|
|
64
|
+
flushed = true
|
|
65
|
+
} else {
|
|
66
|
+
flushed = false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!flushed) this.onChangeListeners.forEach(l => l(this.data))
|
|
71
|
+
} catch (error: any) {
|
|
72
|
+
if (error instanceof DOMException && error.name === 'AbortError') this.fail(new StreamCanceledError())
|
|
73
|
+
if (error instanceof SyntaxError) this.fail(new StreamJsonError())
|
|
74
|
+
else if (error instanceof StreamError) this.fail(error)
|
|
75
|
+
else this.fail(new StreamError(error?.message || `${error}`))
|
|
76
|
+
}
|
|
77
|
+
if (!this.error) this.complete()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private clear() {
|
|
81
|
+
this.onChangeListeners = []
|
|
82
|
+
this.abortController = undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private fail(error: any) {
|
|
86
|
+
this.error = error
|
|
87
|
+
this.fullPromise.reject(this.error)
|
|
88
|
+
this.clear()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private complete() {
|
|
92
|
+
this.fullPromise.resolve(this.data)
|
|
93
|
+
this.clear()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Returns the full value of the array once the stream finishes.
|
|
98
|
+
*/
|
|
99
|
+
getValue(): Promise<T[]> {
|
|
100
|
+
return this.fullPromise.promise
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Returns the streamed array with every item streamed until now. This will be the complete array if the stream has finished.
|
|
105
|
+
*/
|
|
106
|
+
getPartialValue(): T[] {
|
|
107
|
+
return this.data
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Watches the array as it's streamed. This doesn't wait for the value to be complete.
|
|
112
|
+
*
|
|
113
|
+
* The listener is called whenever the value changes.
|
|
114
|
+
*
|
|
115
|
+
* @param listener the function to call with the new value.
|
|
116
|
+
* @returns a function that, when called, removes the listener.
|
|
117
|
+
*/
|
|
118
|
+
onChange(listener: (value: T[]) => void) {
|
|
119
|
+
if (this.fullPromise.resolved) {
|
|
120
|
+
listener(this.data)
|
|
121
|
+
return () => {}
|
|
122
|
+
}
|
|
123
|
+
this.onChangeListeners.push(listener)
|
|
124
|
+
return () => {
|
|
125
|
+
const index = this.onChangeListeners?.findIndex(l => l === listener)
|
|
126
|
+
if (index !== undefined && index >= 0) this.onChangeListeners?.splice(index, 1)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getStatus(): StreamingStatus {
|
|
131
|
+
if (this.error) return 'error'
|
|
132
|
+
if (this.fullPromise.resolved) return 'success'
|
|
133
|
+
return 'pending'
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getError() {
|
|
137
|
+
return this.error
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* If this is a stream and it's not yet finished, calling this function cancels the stream.
|
|
142
|
+
*/
|
|
143
|
+
cancel() {
|
|
144
|
+
this.abortController?.abort(new StreamCanceledError())
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
import { CompletablePromise } from '@stack-spot/opa'
|
|
2
|
-
import { StreamCanceledError } from '../error/StreamCanceledError'
|
|
3
|
-
import { StreamError } from '../error/StreamError'
|
|
4
|
-
import { StreamJsonError } from '../error/StreamJsonError'
|
|
5
|
-
import { FetchEventStream } from '../network/types'
|
|
6
|
-
import { StreamingStatus } from '../types'
|
|
7
|
-
|
|
8
|
-
type OnChangeListener<T> = (value: Partial<T>) => void
|
|
9
|
-
|
|
10
|
-
interface ConstructorParams<T> {
|
|
11
|
-
/**
|
|
12
|
-
* The promise that results in the EventStream to build the final json.
|
|
13
|
-
*/
|
|
14
|
-
eventsPromise: Promise<FetchEventStream>,
|
|
15
|
-
/**
|
|
16
|
-
* A controller to abort the streaming.
|
|
17
|
-
*/
|
|
18
|
-
abortController: AbortController,
|
|
19
|
-
/**
|
|
20
|
-
* A minimum number of milliseconds to wait before calling onChange listeners.
|
|
21
|
-
* @default 50
|
|
22
|
-
*/
|
|
23
|
-
minChangeIntervalMS?: number,
|
|
24
|
-
/**
|
|
25
|
-
* Optional. If set, this function will be called with every streaming event and must transform the current data object according to the
|
|
26
|
-
* message received.
|
|
27
|
-
*/
|
|
28
|
-
transform?: (event: Partial<T>, data: Partial<T>) => void | Promise<void>,
|
|
29
|
-
/**
|
|
30
|
-
* Optional. Keys to ignore when merging the result with the current event. Ignored keys are always replaced by the newest value instead
|
|
31
|
-
* of merged.
|
|
32
|
-
*/
|
|
33
|
-
ignoreKeys?: (keyof T)[],
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* An object represented by a JSON stream. This can be watched as the stream runs.
|
|
38
|
-
*/
|
|
39
|
-
export class StreamedJson<T> {
|
|
40
|
-
private onChangeListeners: OnChangeListener<T>[] = []
|
|
41
|
-
private error: StreamError | undefined
|
|
42
|
-
private data: Partial<T> = {}
|
|
43
|
-
private fullPromise = new CompletablePromise<T>()
|
|
44
|
-
private abortController: AbortController | undefined
|
|
45
|
-
private transform?: (event: Partial<T>, data: Partial<T>) => void | Promise<void>
|
|
46
|
-
private ignoreKeys?: (keyof T)[]
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param response the fetch response.
|
|
50
|
-
* @param minChangeIntervalMS a stream can be too fast. This sets a minimum interval between running the listeners. The default is 50ms.
|
|
51
|
-
*/
|
|
52
|
-
constructor({ eventsPromise, abortController, minChangeIntervalMS = 50, transform, ignoreKeys }: ConstructorParams<T>) {
|
|
53
|
-
this.abortController = abortController
|
|
54
|
-
this.transform = transform
|
|
55
|
-
this.ignoreKeys = ignoreKeys
|
|
56
|
-
this.run(eventsPromise, minChangeIntervalMS)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private async run(eventsPromise: Promise<FetchEventStream>, minChangeIntervalMS: number) {
|
|
60
|
-
let lastChangeCall = 0
|
|
61
|
-
try {
|
|
62
|
-
const events = await eventsPromise
|
|
63
|
-
let flushed = true
|
|
64
|
-
for await (const event of events) {
|
|
65
|
-
if (this.error) return
|
|
66
|
-
if (event.data) {
|
|
67
|
-
const json = JSON.parse(event.data)
|
|
68
|
-
await this.transform?.(json, this.data)
|
|
69
|
-
this.merge(json, this.data)
|
|
70
|
-
if (new Date().getTime() - lastChangeCall >= minChangeIntervalMS) {
|
|
71
|
-
this.onChangeListeners.forEach(l => l(this.data))
|
|
72
|
-
lastChangeCall = new Date().getTime()
|
|
73
|
-
flushed = true
|
|
74
|
-
} else {
|
|
75
|
-
flushed = false
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (!flushed) this.onChangeListeners.forEach(l => l(this.data))
|
|
80
|
-
} catch (error: any) {
|
|
81
|
-
if (error instanceof DOMException && error.name === 'AbortError') this.fail(new StreamCanceledError())
|
|
82
|
-
if (error instanceof SyntaxError) this.fail(new StreamJsonError())
|
|
83
|
-
else if (error instanceof StreamError) this.fail(error)
|
|
84
|
-
else this.fail(new StreamError(error?.message || `${error}`))
|
|
85
|
-
}
|
|
86
|
-
if (!this.error) this.complete()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private merge(source: Record<string, any>, target: Record<string, any>) {
|
|
90
|
-
Object.keys(source).forEach((k) => {
|
|
91
|
-
if (this.ignoreKeys?.includes(k as keyof T) || typeof source[k] !== typeof target[k]) target[k] = source[k]
|
|
92
|
-
else if (typeof source[k] === 'string') target[k] += source[k]
|
|
93
|
-
else if (Array.isArray(source[k])) target[k].push(...source[k])
|
|
94
|
-
else if (typeof source[k] === 'number') parseFloat(target[k] + source[k])
|
|
95
|
-
else if (source[k] && typeof source[k] === 'object') this.merge(source[k], target[k])
|
|
96
|
-
else if (source[k]) target[k] = source[k]
|
|
97
|
-
})
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private clear() {
|
|
101
|
-
this.onChangeListeners = []
|
|
102
|
-
this.abortController = undefined
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
private fail(error: any) {
|
|
106
|
-
this.error = error
|
|
107
|
-
this.fullPromise.reject(this.error)
|
|
108
|
-
this.clear()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private complete() {
|
|
112
|
-
this.fullPromise.resolve(this.data as T)
|
|
113
|
-
this.clear()
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Returns the full value of the object once the stream finishes.
|
|
118
|
-
*/
|
|
119
|
-
getValue(): Promise<T> {
|
|
120
|
-
return this.fullPromise.promise
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Returns the streamed object with everything already streamed. This will be the complete object if the stream has finished.
|
|
125
|
-
*/
|
|
126
|
-
getPartialValue(): Partial<T> {
|
|
127
|
-
return this.data
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Watches the object as it's streamed. This doesn't wait for the value to be complete.
|
|
132
|
-
*
|
|
133
|
-
* The listener is called whenever the value changes.
|
|
134
|
-
*
|
|
135
|
-
* @param listener the function to call with the new value.
|
|
136
|
-
* @returns a function that, when called, removes the listener.
|
|
137
|
-
*/
|
|
138
|
-
onChange(listener: (value: Partial<T>) => void) {
|
|
139
|
-
if (this.fullPromise.resolved) {
|
|
140
|
-
listener(this.data)
|
|
141
|
-
return () => {}
|
|
142
|
-
}
|
|
143
|
-
this.onChangeListeners.push(listener)
|
|
144
|
-
return () => {
|
|
145
|
-
const index = this.onChangeListeners?.findIndex(l => l === listener)
|
|
146
|
-
if (index !== undefined && index >= 0) this.onChangeListeners?.splice(index, 1)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
getStatus(): StreamingStatus {
|
|
151
|
-
if (this.error) return 'error'
|
|
152
|
-
if (this.fullPromise.resolved) return 'success'
|
|
153
|
-
return 'pending'
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
getError() {
|
|
157
|
-
return this.error
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* If this is a stream and it's not yet finished, calling this function cancels the stream.
|
|
162
|
-
*/
|
|
163
|
-
cancel() {
|
|
164
|
-
this.abortController?.abort(new StreamCanceledError())
|
|
165
|
-
}
|
|
166
|
-
}
|
|
1
|
+
import { CompletablePromise } from '@stack-spot/opa'
|
|
2
|
+
import { StreamCanceledError } from '../error/StreamCanceledError'
|
|
3
|
+
import { StreamError } from '../error/StreamError'
|
|
4
|
+
import { StreamJsonError } from '../error/StreamJsonError'
|
|
5
|
+
import { FetchEventStream } from '../network/types'
|
|
6
|
+
import { StreamingStatus } from '../types'
|
|
7
|
+
|
|
8
|
+
type OnChangeListener<T> = (value: Partial<T>) => void
|
|
9
|
+
|
|
10
|
+
interface ConstructorParams<T> {
|
|
11
|
+
/**
|
|
12
|
+
* The promise that results in the EventStream to build the final json.
|
|
13
|
+
*/
|
|
14
|
+
eventsPromise: Promise<FetchEventStream>,
|
|
15
|
+
/**
|
|
16
|
+
* A controller to abort the streaming.
|
|
17
|
+
*/
|
|
18
|
+
abortController: AbortController,
|
|
19
|
+
/**
|
|
20
|
+
* A minimum number of milliseconds to wait before calling onChange listeners.
|
|
21
|
+
* @default 50
|
|
22
|
+
*/
|
|
23
|
+
minChangeIntervalMS?: number,
|
|
24
|
+
/**
|
|
25
|
+
* Optional. If set, this function will be called with every streaming event and must transform the current data object according to the
|
|
26
|
+
* message received.
|
|
27
|
+
*/
|
|
28
|
+
transform?: (event: Partial<T>, data: Partial<T>) => void | Promise<void>,
|
|
29
|
+
/**
|
|
30
|
+
* Optional. Keys to ignore when merging the result with the current event. Ignored keys are always replaced by the newest value instead
|
|
31
|
+
* of merged.
|
|
32
|
+
*/
|
|
33
|
+
ignoreKeys?: (keyof T)[],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* An object represented by a JSON stream. This can be watched as the stream runs.
|
|
38
|
+
*/
|
|
39
|
+
export class StreamedJson<T> {
|
|
40
|
+
private onChangeListeners: OnChangeListener<T>[] = []
|
|
41
|
+
private error: StreamError | undefined
|
|
42
|
+
private data: Partial<T> = {}
|
|
43
|
+
private fullPromise = new CompletablePromise<T>()
|
|
44
|
+
private abortController: AbortController | undefined
|
|
45
|
+
private transform?: (event: Partial<T>, data: Partial<T>) => void | Promise<void>
|
|
46
|
+
private ignoreKeys?: (keyof T)[]
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param response the fetch response.
|
|
50
|
+
* @param minChangeIntervalMS a stream can be too fast. This sets a minimum interval between running the listeners. The default is 50ms.
|
|
51
|
+
*/
|
|
52
|
+
constructor({ eventsPromise, abortController, minChangeIntervalMS = 50, transform, ignoreKeys }: ConstructorParams<T>) {
|
|
53
|
+
this.abortController = abortController
|
|
54
|
+
this.transform = transform
|
|
55
|
+
this.ignoreKeys = ignoreKeys
|
|
56
|
+
this.run(eventsPromise, minChangeIntervalMS)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private async run(eventsPromise: Promise<FetchEventStream>, minChangeIntervalMS: number) {
|
|
60
|
+
let lastChangeCall = 0
|
|
61
|
+
try {
|
|
62
|
+
const events = await eventsPromise
|
|
63
|
+
let flushed = true
|
|
64
|
+
for await (const event of events) {
|
|
65
|
+
if (this.error) return
|
|
66
|
+
if (event.data) {
|
|
67
|
+
const json = JSON.parse(event.data)
|
|
68
|
+
await this.transform?.(json, this.data)
|
|
69
|
+
this.merge(json, this.data)
|
|
70
|
+
if (new Date().getTime() - lastChangeCall >= minChangeIntervalMS) {
|
|
71
|
+
this.onChangeListeners.forEach(l => l(this.data))
|
|
72
|
+
lastChangeCall = new Date().getTime()
|
|
73
|
+
flushed = true
|
|
74
|
+
} else {
|
|
75
|
+
flushed = false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!flushed) this.onChangeListeners.forEach(l => l(this.data))
|
|
80
|
+
} catch (error: any) {
|
|
81
|
+
if (error instanceof DOMException && error.name === 'AbortError') this.fail(new StreamCanceledError())
|
|
82
|
+
if (error instanceof SyntaxError) this.fail(new StreamJsonError())
|
|
83
|
+
else if (error instanceof StreamError) this.fail(error)
|
|
84
|
+
else this.fail(new StreamError(error?.message || `${error}`))
|
|
85
|
+
}
|
|
86
|
+
if (!this.error) this.complete()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private merge(source: Record<string, any>, target: Record<string, any>) {
|
|
90
|
+
Object.keys(source).forEach((k) => {
|
|
91
|
+
if (this.ignoreKeys?.includes(k as keyof T) || typeof source[k] !== typeof target[k]) target[k] = source[k]
|
|
92
|
+
else if (typeof source[k] === 'string') target[k] += source[k]
|
|
93
|
+
else if (Array.isArray(source[k])) target[k].push(...source[k])
|
|
94
|
+
else if (typeof source[k] === 'number') parseFloat(target[k] + source[k])
|
|
95
|
+
else if (source[k] && typeof source[k] === 'object') this.merge(source[k], target[k])
|
|
96
|
+
else if (source[k]) target[k] = source[k]
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private clear() {
|
|
101
|
+
this.onChangeListeners = []
|
|
102
|
+
this.abortController = undefined
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private fail(error: any) {
|
|
106
|
+
this.error = error
|
|
107
|
+
this.fullPromise.reject(this.error)
|
|
108
|
+
this.clear()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private complete() {
|
|
112
|
+
this.fullPromise.resolve(this.data as T)
|
|
113
|
+
this.clear()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Returns the full value of the object once the stream finishes.
|
|
118
|
+
*/
|
|
119
|
+
getValue(): Promise<T> {
|
|
120
|
+
return this.fullPromise.promise
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Returns the streamed object with everything already streamed. This will be the complete object if the stream has finished.
|
|
125
|
+
*/
|
|
126
|
+
getPartialValue(): Partial<T> {
|
|
127
|
+
return this.data
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Watches the object as it's streamed. This doesn't wait for the value to be complete.
|
|
132
|
+
*
|
|
133
|
+
* The listener is called whenever the value changes.
|
|
134
|
+
*
|
|
135
|
+
* @param listener the function to call with the new value.
|
|
136
|
+
* @returns a function that, when called, removes the listener.
|
|
137
|
+
*/
|
|
138
|
+
onChange(listener: (value: Partial<T>) => void) {
|
|
139
|
+
if (this.fullPromise.resolved) {
|
|
140
|
+
listener(this.data)
|
|
141
|
+
return () => {}
|
|
142
|
+
}
|
|
143
|
+
this.onChangeListeners.push(listener)
|
|
144
|
+
return () => {
|
|
145
|
+
const index = this.onChangeListeners?.findIndex(l => l === listener)
|
|
146
|
+
if (index !== undefined && index >= 0) this.onChangeListeners?.splice(index, 1)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
getStatus(): StreamingStatus {
|
|
151
|
+
if (this.error) return 'error'
|
|
152
|
+
if (this.fullPromise.resolved) return 'success'
|
|
153
|
+
return 'pending'
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getError() {
|
|
157
|
+
return this.error
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* If this is a stream and it's not yet finished, calling this function cancels the stream.
|
|
162
|
+
*/
|
|
163
|
+
cancel() {
|
|
164
|
+
this.abortController?.abort(new StreamCanceledError())
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FixVariables, OazapftsFunction } from '../client/types'
|
|
2
|
-
|
|
3
|
-
export function removeAuthorizationParam<T extends OazapftsFunction>(fn: T): FixVariables<T,
|
|
4
|
-
{ authorization: never, jwtToken: never, authorizationHeader: never }> {
|
|
5
|
-
return fn
|
|
6
|
-
}
|
|
1
|
+
import { FixVariables, OazapftsFunction } from '../client/types'
|
|
2
|
+
|
|
3
|
+
export function removeAuthorizationParam<T extends OazapftsFunction>(fn: T): FixVariables<T,
|
|
4
|
+
{ authorization: never, jwtToken: never, authorizationHeader: never }> {
|
|
5
|
+
return fn
|
|
6
|
+
}
|