libmodulor 0.21.0 → 0.22.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 +13 -0
- package/README.md +1 -1
- package/dist/esm/apps/Helper/src/lib/project.js +7 -7
- package/dist/esm/apps/Helper/src/ucds/CreateProjectUCD.d.ts +1 -0
- package/dist/esm/apps/Helper/src/ucds/CreateProjectUCD.js +20 -13
- package/dist/esm/dt/DataType.d.ts +2 -1
- package/dist/esm/dt/DataTypes.js +1 -0
- package/dist/esm/dt/final/TTransportType.d.ts +8 -0
- package/dist/esm/dt/final/TTransportType.js +16 -0
- package/dist/esm/dt/index.d.ts +1 -0
- package/dist/esm/dt/index.js +1 -0
- package/dist/esm/error/funcs.d.ts +2 -0
- package/dist/esm/error/funcs.js +19 -0
- package/dist/esm/error/index.d.ts +1 -0
- package/dist/esm/error/index.js +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/std/HTTPAPICallExecutor.d.ts +16 -7
- package/dist/esm/std/HTTPAPICaller.d.ts +8 -1
- package/dist/esm/std/LLMManager.d.ts +20 -3
- package/dist/esm/std/impl/FakeClockManager.d.ts +6 -0
- package/dist/esm/std/impl/FakeClockManager.js +19 -0
- package/dist/esm/std/impl/FakeHTTPAPICallExecutor.js +19 -18
- package/dist/esm/std/impl/FakeLLMManager.d.ts +4 -0
- package/dist/esm/std/impl/FakeLLMManager.js +40 -0
- package/dist/esm/std/impl/MistralAILLMManager.js +12 -0
- package/dist/esm/std/impl/OllamaLLMManager.d.ts +7 -2
- package/dist/esm/std/impl/OllamaLLMManager.js +32 -5
- package/dist/esm/std/impl/OpenAILLMManager.js +9 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.d.ts +7 -3
- package/dist/esm/std/impl/SimpleHTTPAPICaller.js +66 -15
- package/dist/esm/target/lib/cli/CommandExecutor.js +9 -1
- package/dist/esm/target/lib/react/UCPanel.d.ts +4 -2
- package/dist/esm/target/lib/react/UCPanel.js +2 -2
- package/dist/esm/target/lib/server/ServerRequestHandler.d.ts +3 -2
- package/dist/esm/target/lib/server/ServerRequestHandler.js +2 -2
- package/dist/esm/target/lib/server-express/funcs.js +52 -1
- package/dist/esm/target/lib/server-hono/funcs.js +65 -2
- package/dist/esm/testing/workers/UCExecutor.js +39 -1
- package/dist/esm/uc/ext.d.ts +7 -1
- package/dist/esm/uc/impl/HTTPUCTransporter.d.ts +2 -2
- package/dist/esm/uc/impl/HTTPUCTransporter.js +3 -1
- package/dist/esm/uc/impl/SimpleUCManager.d.ts +3 -3
- package/dist/esm/uc/impl/SimpleUCManager.js +23 -4
- package/dist/esm/uc/lifecycle/client/SendClientMain.d.ts +1 -1
- package/dist/esm/uc/lifecycle/client/SendClientMain.js +5 -2
- package/dist/esm/uc/main.d.ts +8 -1
- package/dist/esm/uc/manager.d.ts +11 -2
- package/dist/esm/uc/output.d.ts +1 -0
- package/dist/esm/uc/output.js +10 -1
- package/dist/esm/uc/transporter.d.ts +7 -1
- package/dist/esm/utils/async/types.d.ts +2 -0
- package/dist/esm/utils/async/types.js +1 -0
- package/dist/esm/utils/http/NDJSONStreamManager.d.ts +12 -0
- package/dist/esm/utils/http/NDJSONStreamManager.js +42 -0
- package/dist/esm/utils/http/SSEStreamManager.d.ts +12 -0
- package/dist/esm/utils/http/SSEStreamManager.js +57 -0
- package/dist/esm/utils/http/nd-json.d.ts +1 -0
- package/dist/esm/utils/http/nd-json.js +2 -0
- package/dist/esm/utils/http/sse.d.ts +14 -0
- package/dist/esm/utils/http/sse.js +24 -0
- package/dist/esm/utils/http/status.d.ts +4 -0
- package/dist/esm/utils/http/status.js +9 -0
- package/dist/esm/utils/index.d.ts +6 -0
- package/dist/esm/utils/index.js +4 -0
- package/dist/esm/utils/streams/types.d.ts +17 -0
- package/dist/esm/utils/streams/types.js +1 -0
- package/package.json +15 -15
- package/pnpm-workspace.yaml +1 -0
|
@@ -24,7 +24,7 @@ let OllamaLLMManager = class OllamaLLMManager {
|
|
|
24
24
|
oll_base_url: this.settingsManager.get()('oll_base_url'),
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
async send(req) {
|
|
27
|
+
async send(req, opts) {
|
|
28
28
|
const firstMessage = req.messages[0];
|
|
29
29
|
if (!firstMessage) {
|
|
30
30
|
throw new IllegalArgumentError('Please provide at least one message');
|
|
@@ -32,20 +32,47 @@ let OllamaLLMManager = class OllamaLLMManager {
|
|
|
32
32
|
return await this.httpAPICaller.exec({
|
|
33
33
|
errBuilder: async (error) => error.error,
|
|
34
34
|
method: 'POST',
|
|
35
|
-
outputBuilder: async (res) => (
|
|
36
|
-
choices: [{ message: { content: res.response } }],
|
|
37
|
-
}),
|
|
35
|
+
outputBuilder: async (res) => this.toRes(req.stream, res),
|
|
38
36
|
req: {
|
|
39
37
|
builder: async () => ({
|
|
40
38
|
model: req.model,
|
|
41
39
|
prompt: firstMessage.content,
|
|
42
|
-
stream: false,
|
|
40
|
+
stream: req.stream ?? false,
|
|
43
41
|
}),
|
|
44
42
|
envelope: 'json',
|
|
45
43
|
},
|
|
44
|
+
stream: {
|
|
45
|
+
onData: (res) => {
|
|
46
|
+
opts?.stream?.onData?.(res);
|
|
47
|
+
// Beware : this won't work if/when we accept multiple choices in the request
|
|
48
|
+
if (res.choices[0]?.finish_reason) {
|
|
49
|
+
opts?.stream?.onDone();
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
},
|
|
46
53
|
urlBuilder: async () => `${this.s().oll_base_url}/api/generate`,
|
|
47
54
|
});
|
|
48
55
|
}
|
|
56
|
+
toRes(stream, res) {
|
|
57
|
+
if (stream) {
|
|
58
|
+
return {
|
|
59
|
+
choices: [
|
|
60
|
+
{
|
|
61
|
+
delta: { content: res.response },
|
|
62
|
+
finish_reason: res.done ? 'stop' : null,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
choices: [
|
|
69
|
+
{
|
|
70
|
+
finish_reason: res.done ? 'stop' : null,
|
|
71
|
+
message: { content: res.response },
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
49
76
|
};
|
|
50
77
|
OllamaLLMManager = __decorate([
|
|
51
78
|
injectable(),
|
|
@@ -38,6 +38,15 @@ let OpenAILLMManager = class OpenAILLMManager {
|
|
|
38
38
|
builder: async () => req,
|
|
39
39
|
envelope: 'json',
|
|
40
40
|
},
|
|
41
|
+
stream: {
|
|
42
|
+
onData: (res) => {
|
|
43
|
+
opts?.stream?.onData?.(res);
|
|
44
|
+
// Beware : this won't work if/when we accept multiple choices in the request
|
|
45
|
+
if (res.choices[0]?.finish_reason) {
|
|
46
|
+
opts?.stream?.onDone();
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
},
|
|
41
50
|
urlBuilder: async () => `${OpenAILLMManager_1.BASE_URL}/chat/completions`,
|
|
42
51
|
});
|
|
43
52
|
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import { HTTPRequestBuilder } from '../../utils/index.js';
|
|
1
|
+
import { HTTPRequestBuilder, NDJSONStreamManager, SSEStreamManager } from '../../utils/index.js';
|
|
2
2
|
import type { BufferManager } from '../BufferManager.js';
|
|
3
3
|
import type { HTTPAPICallExecutor, HTTPAPICallExecutorAgentBuilder } from '../HTTPAPICallExecutor.js';
|
|
4
4
|
import type { HTTPAPICaller, HTTPAPICallerInput } from '../HTTPAPICaller.js';
|
|
5
5
|
import type { Logger } from '../Logger.js';
|
|
6
6
|
import type { XMLManager } from '../XMLManager.js';
|
|
7
|
+
export declare const ERR_STREAM_UNAVAILABLE = "The internal HTTP impl (fetch ?) does not implement streaming (React Native ?)";
|
|
7
8
|
export declare class SimpleHTTPAPICaller implements HTTPAPICaller {
|
|
8
9
|
private bufferManager;
|
|
9
10
|
private httpAPICallExecutor;
|
|
10
11
|
private httpAPICallExecutorAgentBuilder;
|
|
11
12
|
private httpRequestBuilder;
|
|
12
13
|
private logger;
|
|
14
|
+
private ndJSONStreamManager;
|
|
15
|
+
private sseStreamManager;
|
|
13
16
|
private xmlManager;
|
|
14
|
-
constructor(bufferManager: BufferManager, httpAPICallExecutor: HTTPAPICallExecutor, httpAPICallExecutorAgentBuilder: HTTPAPICallExecutorAgentBuilder, httpRequestBuilder: HTTPRequestBuilder, logger: Logger, xmlManager: XMLManager);
|
|
15
|
-
exec<AH extends object | undefined, Req extends object, ResBad, ResGood, O>({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType, errBuilder, method, opts, outputBuilder, req, urlBuilder, unknownErrorMessage, }: HTTPAPICallerInput<AH, Req, ResBad, ResGood, O>): Promise<O>;
|
|
17
|
+
constructor(bufferManager: BufferManager, httpAPICallExecutor: HTTPAPICallExecutor, httpAPICallExecutorAgentBuilder: HTTPAPICallExecutorAgentBuilder, httpRequestBuilder: HTTPRequestBuilder, logger: Logger, ndJSONStreamManager: NDJSONStreamManager, sseStreamManager: SSEStreamManager, xmlManager: XMLManager);
|
|
18
|
+
exec<AH extends object | undefined, Req extends object, ResBad, ResGood, O>({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType, errBuilder, method, opts, outputBuilder, registerAbort, req, stream, urlBuilder, unknownErrorMessage, }: HTTPAPICallerInput<AH, Req, ResBad, ResGood, O>): Promise<O>;
|
|
16
19
|
private computeHeaders;
|
|
17
20
|
private processResBad;
|
|
18
21
|
private processResGood;
|
|
22
|
+
private throwError;
|
|
19
23
|
}
|
|
@@ -12,23 +12,28 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
12
12
|
};
|
|
13
13
|
import { inject, injectable } from 'inversify';
|
|
14
14
|
import { CustomError, IllegalArgumentError } from '../../error/index.js';
|
|
15
|
-
import { HTTPRequestBuilder } from '../../utils/index.js';
|
|
15
|
+
import { HTTPRequestBuilder, isClientError, NDJSONStreamManager, SSEStreamManager, } from '../../utils/index.js';
|
|
16
|
+
export const ERR_STREAM_UNAVAILABLE = 'The internal HTTP impl (fetch ?) does not implement streaming (React Native ?)';
|
|
16
17
|
let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
17
18
|
bufferManager;
|
|
18
19
|
httpAPICallExecutor;
|
|
19
20
|
httpAPICallExecutorAgentBuilder;
|
|
20
21
|
httpRequestBuilder;
|
|
21
22
|
logger;
|
|
23
|
+
ndJSONStreamManager;
|
|
24
|
+
sseStreamManager;
|
|
22
25
|
xmlManager;
|
|
23
|
-
constructor(bufferManager, httpAPICallExecutor, httpAPICallExecutorAgentBuilder, httpRequestBuilder, logger, xmlManager) {
|
|
26
|
+
constructor(bufferManager, httpAPICallExecutor, httpAPICallExecutorAgentBuilder, httpRequestBuilder, logger, ndJSONStreamManager, sseStreamManager, xmlManager) {
|
|
24
27
|
this.bufferManager = bufferManager;
|
|
25
28
|
this.httpAPICallExecutor = httpAPICallExecutor;
|
|
26
29
|
this.httpAPICallExecutorAgentBuilder = httpAPICallExecutorAgentBuilder;
|
|
27
30
|
this.httpRequestBuilder = httpRequestBuilder;
|
|
28
31
|
this.logger = logger;
|
|
32
|
+
this.ndJSONStreamManager = ndJSONStreamManager;
|
|
33
|
+
this.sseStreamManager = sseStreamManager;
|
|
29
34
|
this.xmlManager = xmlManager;
|
|
30
35
|
}
|
|
31
|
-
async exec({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType = 'application/json', errBuilder, method, opts, outputBuilder, req, urlBuilder, unknownErrorMessage = CustomError.ERROR_UNKNOWN, }) {
|
|
36
|
+
async exec({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType = 'application/json', errBuilder, method, opts, outputBuilder, registerAbort, req, stream, urlBuilder, unknownErrorMessage = CustomError.ERROR_UNKNOWN, }) {
|
|
32
37
|
const baseURL = await urlBuilder();
|
|
33
38
|
const data = (await req?.builder?.()) || {};
|
|
34
39
|
const { body, url } = await this.httpRequestBuilder.exec({
|
|
@@ -46,11 +51,16 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
46
51
|
const agent = this.httpAPICallExecutorAgentBuilder.exec({
|
|
47
52
|
url: new URL(url),
|
|
48
53
|
});
|
|
54
|
+
const abortController = new AbortController();
|
|
55
|
+
registerAbort?.(() => {
|
|
56
|
+
abortController.abort();
|
|
57
|
+
});
|
|
49
58
|
const response = await this.httpAPICallExecutor.fn()(url, {
|
|
50
59
|
agent,
|
|
51
60
|
body,
|
|
52
61
|
headers: reqHeaders,
|
|
53
62
|
method,
|
|
63
|
+
signal: abortController.signal,
|
|
54
64
|
});
|
|
55
65
|
const { headers, status } = response;
|
|
56
66
|
this.logger.trace('HTTPAPICaller', {
|
|
@@ -66,24 +76,24 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
66
76
|
}
|
|
67
77
|
// Using .startsWith instead of === because the value can look like this 'application/json; charset=utf-8'
|
|
68
78
|
const responseContentType = headers.get('Content-Type');
|
|
69
|
-
const isJSON = responseContentType?.startsWith('application/json');
|
|
70
79
|
const isFormURLEncoded = responseContentType?.startsWith('application/x-www-form-urlencoded');
|
|
80
|
+
const isJSON = responseContentType?.startsWith('application/json');
|
|
81
|
+
const isNDJSON = responseContentType?.startsWith('application/x-ndjson');
|
|
82
|
+
const isSSE = responseContentType?.startsWith('text/event-stream');
|
|
71
83
|
const isXML = responseContentType?.startsWith('text/xml');
|
|
72
84
|
this.logger.trace('HTTPAPICaller', {
|
|
73
85
|
isFormURLEncoded,
|
|
74
86
|
isJSON,
|
|
87
|
+
isNDJSON,
|
|
88
|
+
isSSE,
|
|
75
89
|
isXML,
|
|
76
90
|
});
|
|
77
91
|
const { ok, redirected } = response;
|
|
78
92
|
if (ok || redirected) {
|
|
79
|
-
return this.processResGood({ opts, outputBuilder }, isFormURLEncoded, isJSON, isXML, response);
|
|
80
|
-
}
|
|
81
|
-
const errMsg = await this.processResBad({ errBuilder, opts }, isJSON, isXML, response);
|
|
82
|
-
const message = errMsg ?? unknownErrorMessage;
|
|
83
|
-
if (status < 500) {
|
|
84
|
-
throw new IllegalArgumentError(message);
|
|
93
|
+
return this.processResGood({ opts, outputBuilder, stream }, isFormURLEncoded, isJSON, isNDJSON, isSSE, isXML, response);
|
|
85
94
|
}
|
|
86
|
-
|
|
95
|
+
const message = await this.processResBad({ errBuilder, opts }, isJSON, isXML, response);
|
|
96
|
+
this.throwError(message ?? unknownErrorMessage, status);
|
|
87
97
|
}
|
|
88
98
|
async computeHeaders({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType = 'application/json', req, }) {
|
|
89
99
|
const headers = {};
|
|
@@ -163,9 +173,41 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
163
173
|
return JSON.stringify(error);
|
|
164
174
|
}
|
|
165
175
|
}
|
|
166
|
-
async processResGood({ opts, outputBuilder, }, isFormURLEncoded, isJSON, isXML, response) {
|
|
176
|
+
async processResGood({ opts, outputBuilder, stream, }, isFormURLEncoded, isJSON, isNDJSON, isSSE, isXML, response) {
|
|
167
177
|
let payload;
|
|
168
|
-
if (
|
|
178
|
+
if (isNDJSON && stream) {
|
|
179
|
+
if (!response.body) {
|
|
180
|
+
throw new Error(ERR_STREAM_UNAVAILABLE);
|
|
181
|
+
}
|
|
182
|
+
await this.ndJSONStreamManager.exec({
|
|
183
|
+
onData: async (data) => {
|
|
184
|
+
if (outputBuilder) {
|
|
185
|
+
stream.onData(await outputBuilder(data));
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
stream.onData(data);
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
reader: response.body.getReader(),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else if (isSSE && stream) {
|
|
195
|
+
if (!response.body) {
|
|
196
|
+
throw new Error(ERR_STREAM_UNAVAILABLE);
|
|
197
|
+
}
|
|
198
|
+
await this.sseStreamManager.exec({
|
|
199
|
+
onData: async (data) => {
|
|
200
|
+
if (outputBuilder) {
|
|
201
|
+
stream.onData(await outputBuilder(data));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
stream.onData(data);
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
reader: response.body.getReader(),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
else if (isJSON) {
|
|
169
211
|
payload = await response.json();
|
|
170
212
|
}
|
|
171
213
|
else {
|
|
@@ -196,6 +238,12 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
196
238
|
}
|
|
197
239
|
return payload;
|
|
198
240
|
}
|
|
241
|
+
throwError(message, status) {
|
|
242
|
+
if (isClientError(status)) {
|
|
243
|
+
throw new IllegalArgumentError(message);
|
|
244
|
+
}
|
|
245
|
+
throw new Error(message);
|
|
246
|
+
}
|
|
199
247
|
};
|
|
200
248
|
SimpleHTTPAPICaller = __decorate([
|
|
201
249
|
injectable(),
|
|
@@ -204,7 +252,10 @@ SimpleHTTPAPICaller = __decorate([
|
|
|
204
252
|
__param(2, inject('HTTPAPICallExecutorAgentBuilder')),
|
|
205
253
|
__param(3, inject(HTTPRequestBuilder)),
|
|
206
254
|
__param(4, inject('Logger')),
|
|
207
|
-
__param(5, inject(
|
|
208
|
-
|
|
255
|
+
__param(5, inject(NDJSONStreamManager)),
|
|
256
|
+
__param(6, inject(SSEStreamManager)),
|
|
257
|
+
__param(7, inject('XMLManager')),
|
|
258
|
+
__metadata("design:paramtypes", [Object, Object, Object, HTTPRequestBuilder, Object, NDJSONStreamManager,
|
|
259
|
+
SSEStreamManager, Object])
|
|
209
260
|
], SimpleHTTPAPICaller);
|
|
210
261
|
export { SimpleHTTPAPICaller };
|
|
@@ -41,7 +41,15 @@ let CommandExecutor = class CommandExecutor {
|
|
|
41
41
|
if (!confirmed) {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
const ucor = await this.ucManager.execClient(uc
|
|
44
|
+
const ucor = await this.ucManager.execClient(uc, {
|
|
45
|
+
stream: {
|
|
46
|
+
onClose: async () => { },
|
|
47
|
+
onData: async (ucor) => {
|
|
48
|
+
print(JSON.stringify(ucor.output()));
|
|
49
|
+
},
|
|
50
|
+
onDone: async () => { },
|
|
51
|
+
},
|
|
52
|
+
});
|
|
45
53
|
const output = ucor.output();
|
|
46
54
|
if (output) {
|
|
47
55
|
print(JSON.stringify(output));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ReactElement } from 'react';
|
|
2
2
|
import type { UIntDuration } from '../../../dt/index.js';
|
|
3
|
-
import { type UCInput, type UCOPIBase } from '../../../uc/index.js';
|
|
3
|
+
import { type UCInput, type UCOPIBase, type UCOutputReader } from '../../../uc/index.js';
|
|
4
|
+
import { type StreamConfig } from '../../../utils/index.js';
|
|
4
5
|
import type { RenderUCForm } from './form.js';
|
|
5
6
|
import type { RenderUCAutoExecLoader } from './loader.js';
|
|
6
7
|
import type { UCPanelCtx, UCPanelOnDone, UCPanelOnError, UCPanelOnInit, UCPanelOnStartSubmitting } from './panel.js';
|
|
@@ -15,6 +16,7 @@ type Props<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | u
|
|
|
15
16
|
renderExecTouchable: RenderUCExecTouchable<I, OPI0, OPI1>;
|
|
16
17
|
renderForm: RenderUCForm<I, OPI0, OPI1>;
|
|
17
18
|
sleepInMs?: UIntDuration;
|
|
19
|
+
stream?: StreamConfig<UCOutputReader<I, OPI0, OPI1>> | undefined;
|
|
18
20
|
};
|
|
19
|
-
export declare function UCPanel<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ autoExec, clearAfterExec, onDone, onError, onInit, onStartSubmitting, renderAutoExecLoader, renderForm, renderExecTouchable, sleepInMs, uc, }: Props<I, OPI0, OPI1>): ReactElement;
|
|
21
|
+
export declare function UCPanel<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ autoExec, clearAfterExec, onDone, onError, onInit, onStartSubmitting, renderAutoExecLoader, renderForm, renderExecTouchable, sleepInMs, stream, uc, }: Props<I, OPI0, OPI1>): ReactElement;
|
|
20
22
|
export {};
|
|
@@ -5,12 +5,12 @@ import { sleep } from '../../../utils/index.js';
|
|
|
5
5
|
import { useDIContext } from './DIContextProvider.js';
|
|
6
6
|
import { UCContainer } from './UCContainer.js';
|
|
7
7
|
import { useAction } from './useAction.js';
|
|
8
|
-
export function UCPanel({ autoExec = false, clearAfterExec = true, onDone, onError, onInit, onStartSubmitting, renderAutoExecLoader, renderForm, renderExecTouchable, sleepInMs, uc, }) {
|
|
8
|
+
export function UCPanel({ autoExec = false, clearAfterExec = true, onDone, onError, onInit, onStartSubmitting, renderAutoExecLoader, renderForm, renderExecTouchable, sleepInMs, stream, uc, }) {
|
|
9
9
|
const { container } = useDIContext();
|
|
10
10
|
const [ucManager] = useState(container.get('UCManager'));
|
|
11
11
|
const { exec, execState } = useAction({
|
|
12
12
|
action: async () => {
|
|
13
|
-
const ucor = await ucManager.execClient(uc);
|
|
13
|
+
const ucor = await ucManager.execClient(uc, { stream });
|
|
14
14
|
await onDone?.(ucor);
|
|
15
15
|
clear();
|
|
16
16
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AppManifest } from '../../../app/index.js';
|
|
2
2
|
import type { HTTPMethod, HTTPStatusNumber, URL, URLPath } from '../../../dt/index.js';
|
|
3
3
|
import type { SettingsManager, Worker } from '../../../std/index.js';
|
|
4
|
-
import { UCBuilder, type UCDef, type UCInput, type UCManager, type UCOPIBase, type UCOutput } from '../../../uc/index.js';
|
|
4
|
+
import { UCBuilder, type UCDef, type UCInput, type UCManager, type UCManagerExecServerOpts, type UCOPIBase, type UCOutput } from '../../../uc/index.js';
|
|
5
5
|
import type { HTTPDataEnvelope, HTTPReqData } from '../../../utils/index.js';
|
|
6
6
|
import { AuthCookieCreator, type Output as AuthCookieCreatorOutput } from './AuthCookieCreator.js';
|
|
7
7
|
import { AuthenticationChecker } from './AuthenticationChecker.js';
|
|
@@ -29,6 +29,7 @@ export interface ServerRequestHandlerRes {
|
|
|
29
29
|
interface Input<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
|
|
30
30
|
appManifest: AppManifest;
|
|
31
31
|
envelope: HTTPDataEnvelope;
|
|
32
|
+
execOpts?: UCManagerExecServerOpts<OPI0, OPI1> | undefined;
|
|
32
33
|
req: ServerRequestHandlerReq;
|
|
33
34
|
res: ServerRequestHandlerRes;
|
|
34
35
|
ucd: UCDef<I, OPI0, OPI1>;
|
|
@@ -61,7 +62,7 @@ export declare class ServerRequestHandler implements Worker<Input, Promise<Outpu
|
|
|
61
62
|
private static X_FORWARDED_PROTO_HEADER_NAME;
|
|
62
63
|
constructor(authCookieCreator: AuthCookieCreator, authenticationChecker: AuthenticationChecker, customerFacingErrorBuilder: CustomerFacingErrorBuilder, publicApiKeyChecker: PublicApiKeyChecker, requestChecker: RequestChecker, requestLogger: RequestLogger, settingsManager: SettingsManager<S>, ucBuilder: UCBuilder);
|
|
63
64
|
s(): S;
|
|
64
|
-
exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ appManifest, envelope, req, res, ucd, ucManager, }: Input<I, OPI0, OPI1>): Promise<Output<OPI0, OPI1>>;
|
|
65
|
+
exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ appManifest, envelope, execOpts, req, res, ucd, ucManager, }: Input<I, OPI0, OPI1>): Promise<Output<OPI0, OPI1>>;
|
|
65
66
|
private fill;
|
|
66
67
|
private applySideEffects;
|
|
67
68
|
private applyClearAuthSideEffect;
|
|
@@ -47,7 +47,7 @@ let ServerRequestHandler = class ServerRequestHandler {
|
|
|
47
47
|
server_public_api_key_header_name: this.settingsManager.get()('server_public_api_key_header_name'),
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
async exec({ appManifest, envelope, req, res, ucd, ucManager, }) {
|
|
50
|
+
async exec({ appManifest, envelope, execOpts, req, res, ucd, ucManager, }) {
|
|
51
51
|
try {
|
|
52
52
|
const { bodyRaw, cookie, header, method, secure, url } = req;
|
|
53
53
|
this.requestLogger.exec({
|
|
@@ -79,7 +79,7 @@ let ServerRequestHandler = class ServerRequestHandler {
|
|
|
79
79
|
uc.auth = auth;
|
|
80
80
|
}
|
|
81
81
|
await this.fill(req, envelope, uc);
|
|
82
|
-
const output = await ucManager.execServer(uc);
|
|
82
|
+
const output = await ucManager.execServer(uc, execOpts);
|
|
83
83
|
const { status } = await this.applySideEffects(res, ucd, output);
|
|
84
84
|
if (status !== undefined) {
|
|
85
85
|
return {
|
|
@@ -1,12 +1,48 @@
|
|
|
1
1
|
import cookieParser from 'cookie-parser';
|
|
2
2
|
import express, {} from 'express';
|
|
3
3
|
import fileUpload from 'express-fileupload';
|
|
4
|
+
import { fmtSingleDataMsg, fmtSSEError, isError, SSE_HEADERS, } from '../../../utils/index.js';
|
|
4
5
|
export function buildHandler(appManifest, ucd, contract, serverRequestHandler, ucManager) {
|
|
5
6
|
const { envelope } = contract;
|
|
6
7
|
const handler = async (req, res) => {
|
|
8
|
+
const transportType = ucd.ext?.http?.transportType ?? 'standard';
|
|
9
|
+
let execOpts;
|
|
10
|
+
switch (transportType) {
|
|
11
|
+
case 'standard':
|
|
12
|
+
// Nothing to do
|
|
13
|
+
break;
|
|
14
|
+
case 'stream': {
|
|
15
|
+
execOpts = {
|
|
16
|
+
stream: {
|
|
17
|
+
onClose: async () => { },
|
|
18
|
+
onData: async (output) => {
|
|
19
|
+
if (!output) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
res.write(fmtSingleDataMsg(output));
|
|
23
|
+
},
|
|
24
|
+
onDone: async () => {
|
|
25
|
+
res.end();
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
for (const [k, v] of SSE_HEADERS) {
|
|
30
|
+
res.setHeader(k, v);
|
|
31
|
+
}
|
|
32
|
+
res.flushHeaders();
|
|
33
|
+
res.on('close', async () => {
|
|
34
|
+
res.end();
|
|
35
|
+
await execOpts?.stream?.onClose();
|
|
36
|
+
});
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
default:
|
|
40
|
+
((_) => { })(transportType);
|
|
41
|
+
}
|
|
7
42
|
const { body, status } = await serverRequestHandler.exec({
|
|
8
43
|
appManifest,
|
|
9
44
|
envelope,
|
|
45
|
+
execOpts,
|
|
10
46
|
req: toReq(req),
|
|
11
47
|
res: toRes(res),
|
|
12
48
|
ucd,
|
|
@@ -16,7 +52,22 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
|
|
|
16
52
|
res.status(status).send();
|
|
17
53
|
return;
|
|
18
54
|
}
|
|
19
|
-
|
|
55
|
+
switch (transportType) {
|
|
56
|
+
case 'standard':
|
|
57
|
+
res.status(status).send(body);
|
|
58
|
+
return;
|
|
59
|
+
case 'stream': {
|
|
60
|
+
if (isError(status)) {
|
|
61
|
+
res.write(fmtSSEError({
|
|
62
|
+
message: body.message,
|
|
63
|
+
status,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
default:
|
|
69
|
+
((_) => { })(transportType);
|
|
70
|
+
}
|
|
20
71
|
};
|
|
21
72
|
return handler;
|
|
22
73
|
}
|
|
@@ -3,14 +3,60 @@ import { deleteCookie, getCookie, setCookie } from 'hono/cookie';
|
|
|
3
3
|
import { logger } from 'hono/logger';
|
|
4
4
|
import { secureHeaders } from 'hono/secure-headers';
|
|
5
5
|
import { NotFoundError } from '../../../error/index.js';
|
|
6
|
-
import { fromFormData } from '../../../utils/index.js';
|
|
6
|
+
import { fmtSingleDataMsg, fmtSSEError, fromFormData, isError, SSE_HEADERS, } from '../../../utils/index.js';
|
|
7
7
|
export function buildHandler(appManifest, ucd, contract, serverRequestHandler, ucManager, beforeExec) {
|
|
8
8
|
const { envelope } = contract;
|
|
9
9
|
const handler = async (c) => {
|
|
10
10
|
await beforeExec?.(c);
|
|
11
|
+
const transportType = ucd.ext?.http?.transportType ?? 'standard';
|
|
12
|
+
let execOpts;
|
|
13
|
+
let stream;
|
|
14
|
+
let controller;
|
|
15
|
+
switch (transportType) {
|
|
16
|
+
case 'standard':
|
|
17
|
+
// Nothing to do
|
|
18
|
+
break;
|
|
19
|
+
case 'stream': {
|
|
20
|
+
stream = new ReadableStream({
|
|
21
|
+
start: (ctrl) => {
|
|
22
|
+
controller = ctrl;
|
|
23
|
+
let closed = false;
|
|
24
|
+
const close = () => {
|
|
25
|
+
if (closed) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
ctrl.close();
|
|
29
|
+
closed = true;
|
|
30
|
+
};
|
|
31
|
+
execOpts = {
|
|
32
|
+
stream: {
|
|
33
|
+
onClose: async () => { },
|
|
34
|
+
onData: async (output) => {
|
|
35
|
+
if (!output || closed) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
ctrl.enqueue(fmtSingleDataMsg(output));
|
|
39
|
+
},
|
|
40
|
+
onDone: async () => {
|
|
41
|
+
close();
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
c.req.raw.signal.addEventListener('abort', async () => {
|
|
46
|
+
close();
|
|
47
|
+
await execOpts?.stream?.onClose();
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
default:
|
|
54
|
+
((_) => { })(transportType);
|
|
55
|
+
}
|
|
11
56
|
const { body, status } = await serverRequestHandler.exec({
|
|
12
57
|
appManifest,
|
|
13
58
|
envelope,
|
|
59
|
+
execOpts,
|
|
14
60
|
req: toReq(c),
|
|
15
61
|
res: toRes(c),
|
|
16
62
|
ucd,
|
|
@@ -19,6 +65,23 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
|
|
|
19
65
|
if (!body) {
|
|
20
66
|
return c.newResponse(null, status);
|
|
21
67
|
}
|
|
68
|
+
switch (transportType) {
|
|
69
|
+
case 'standard':
|
|
70
|
+
return c.json(body, status);
|
|
71
|
+
case 'stream': {
|
|
72
|
+
if (isError(status)) {
|
|
73
|
+
controller?.enqueue(fmtSSEError({
|
|
74
|
+
message: body.message,
|
|
75
|
+
status,
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
return new Response(stream, {
|
|
79
|
+
headers: SSE_HEADERS,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
default:
|
|
83
|
+
((_) => { })(transportType);
|
|
84
|
+
}
|
|
22
85
|
return c.json(body, status);
|
|
23
86
|
};
|
|
24
87
|
return handler;
|
|
@@ -50,7 +113,7 @@ export function toReq(c) {
|
|
|
50
113
|
return {
|
|
51
114
|
bodyFromFormData: async () => fromFormData(await c.req.formData()),
|
|
52
115
|
bodyFromJSON: () => c.req.json(),
|
|
53
|
-
bodyFromQueryParams: async () => c.req.
|
|
116
|
+
bodyFromQueryParams: async () => c.req.query(),
|
|
54
117
|
bodyRaw: c.req.raw,
|
|
55
118
|
cookie: async (name) => getCookie(c, name),
|
|
56
119
|
header: async (name) => c.req.header(name),
|
|
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
13
13
|
var UCExecutor_1;
|
|
14
14
|
import { inject, injectable } from 'inversify';
|
|
15
15
|
import { rInput, UCBuilder, } from '../../uc/index.js';
|
|
16
|
+
const ERR_CLIENT_EXPECTED_UCOR = (name) => `${name} client is expected to return an ucor`;
|
|
16
17
|
const ERR_CLIENT_EXPECTED_OUTPUT = (name) => `${name} client is expected to return an output but returned nothing`;
|
|
17
18
|
const ERR_CLIENT_UNEXPECTED_OUTPUT = (name) => `${name} client is expected to return nothing but returned an output`;
|
|
18
19
|
let UCExecutor = class UCExecutor {
|
|
@@ -70,7 +71,44 @@ let UCExecutor = class UCExecutor {
|
|
|
70
71
|
out.io.i = input;
|
|
71
72
|
out.hash = this.cryptoManager.hash(UCExecutor_1.HASH_ALG, [name, JSON.stringify(args), JSON.stringify(input)].join(UCExecutor_1.HASH_SEP), UCExecutor_1.HASH_BTT_ENCODING);
|
|
72
73
|
try {
|
|
73
|
-
|
|
74
|
+
let ucor;
|
|
75
|
+
const transportType = ucd.ext?.http?.transportType ?? 'standard';
|
|
76
|
+
switch (transportType) {
|
|
77
|
+
case 'standard':
|
|
78
|
+
ucor = await this.ucManager.execClient(uc);
|
|
79
|
+
break;
|
|
80
|
+
case 'stream': {
|
|
81
|
+
try {
|
|
82
|
+
let abort;
|
|
83
|
+
await this.ucManager.execClient(uc, {
|
|
84
|
+
registerAbort: (func) => {
|
|
85
|
+
abort = func;
|
|
86
|
+
},
|
|
87
|
+
stream: {
|
|
88
|
+
onClose: async () => { },
|
|
89
|
+
onData: async (ucor2) => {
|
|
90
|
+
if (!ucor) {
|
|
91
|
+
ucor = ucor2;
|
|
92
|
+
abort();
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
onDone: async () => { },
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (err.name !== 'AbortError') {
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
default:
|
|
107
|
+
((_) => { })(transportType);
|
|
108
|
+
}
|
|
109
|
+
if (!ucor) {
|
|
110
|
+
throw new Error(ERR_CLIENT_EXPECTED_UCOR(name));
|
|
111
|
+
}
|
|
74
112
|
const output = ucor.output();
|
|
75
113
|
if (uc.hasOutputParts() && !output) {
|
|
76
114
|
throw new Error(ERR_CLIENT_EXPECTED_OUTPUT(name));
|
package/dist/esm/uc/ext.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HTTPMethod, URLPath } from '../dt/index.js';
|
|
1
|
+
import type { HTTPMethod, TransportType, URLPath } from '../dt/index.js';
|
|
2
2
|
import type { UCOPIBase } from './opi.js';
|
|
3
3
|
import type { UCOutput } from './output.js';
|
|
4
4
|
import type { UCMountingPoint } from './utils/ucMountingPoint.js';
|
|
@@ -41,5 +41,11 @@ export interface UCExt<OPI0 extends UCOPIBase | undefined = undefined, OPI1 exte
|
|
|
41
41
|
* @returns
|
|
42
42
|
*/
|
|
43
43
|
transform?: (output: UCOutput<OPI0, OPI1>) => object;
|
|
44
|
+
/**
|
|
45
|
+
* The way the output is transported
|
|
46
|
+
*
|
|
47
|
+
* By default, it's `standard`.
|
|
48
|
+
*/
|
|
49
|
+
transportType?: TransportType;
|
|
44
50
|
};
|
|
45
51
|
}
|
|
@@ -3,7 +3,7 @@ import type { ServerClientManager, ServerClientManagerSettings } from '../../tar
|
|
|
3
3
|
import type { UCInput } from '../input.js';
|
|
4
4
|
import type { UCOPIBase } from '../opi.js';
|
|
5
5
|
import type { UCOutputOrNothing } from '../output.js';
|
|
6
|
-
import type { UCTransporter } from '../transporter.js';
|
|
6
|
+
import type { UCTransporter, UCTransporterOpts } from '../transporter.js';
|
|
7
7
|
import type { UC } from '../UC.js';
|
|
8
8
|
type S = Pick<ServerClientManagerSettings, 'server_cookies_name_auth' | 'server_public_api_key_header_name'>;
|
|
9
9
|
export declare class HTTPUCTransporter implements Configurable<S>, UCTransporter {
|
|
@@ -12,6 +12,6 @@ export declare class HTTPUCTransporter implements Configurable<S>, UCTransporter
|
|
|
12
12
|
private settingsManager;
|
|
13
13
|
constructor(httpAPICaller: HTTPAPICaller, serverClientManager: ServerClientManager, settingsManager: SettingsManager<S>);
|
|
14
14
|
s(): S;
|
|
15
|
-
send<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<UCOutputOrNothing<OPI0, OPI1>>;
|
|
15
|
+
send<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, opts: UCTransporterOpts<OPI0, OPI1>): Promise<UCOutputOrNothing<OPI0, OPI1>>;
|
|
16
16
|
}
|
|
17
17
|
export {};
|
|
@@ -29,7 +29,7 @@ let HTTPUCTransporter = class HTTPUCTransporter {
|
|
|
29
29
|
server_public_api_key_header_name: this.settingsManager.get()('server_public_api_key_header_name'),
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
async send(uc) {
|
|
32
|
+
async send(uc, opts) {
|
|
33
33
|
const { auth, def: { sec }, } = uc;
|
|
34
34
|
const baseURL = await this.serverClientManager.baseURL({ auth });
|
|
35
35
|
const { contentType, envelope, method, path } = ucHTTPContract(uc);
|
|
@@ -96,10 +96,12 @@ let HTTPUCTransporter = class HTTPUCTransporter {
|
|
|
96
96
|
contentType,
|
|
97
97
|
errBuilder: async (error) => error.message,
|
|
98
98
|
method,
|
|
99
|
+
registerAbort: opts.registerAbort,
|
|
99
100
|
req: {
|
|
100
101
|
builder: async () => rInput(uc, { ignoreUndefined: true }),
|
|
101
102
|
envelope,
|
|
102
103
|
},
|
|
104
|
+
stream: opts.stream,
|
|
103
105
|
urlBuilder: async () => `${baseURL}${path}`,
|
|
104
106
|
});
|
|
105
107
|
// In case of 204, we get an empty object.
|
|
@@ -7,7 +7,7 @@ import { UCOutputReader } from '../helpers/UCOutputReader.js';
|
|
|
7
7
|
import type { UCInit } from '../init.js';
|
|
8
8
|
import type { UCInput } from '../input.js';
|
|
9
9
|
import type { UCMain } from '../main.js';
|
|
10
|
-
import type { UCManager, UCManagerPersistOpts } from '../manager.js';
|
|
10
|
+
import type { UCManager, UCManagerExecClientOpts, UCManagerExecServerOpts, UCManagerPersistOpts } from '../manager.js';
|
|
11
11
|
import type { UCOPIBase } from '../opi.js';
|
|
12
12
|
import type { UCOutputOrNothing } from '../output.js';
|
|
13
13
|
import type { UC } from '../UC.js';
|
|
@@ -29,8 +29,8 @@ export declare class SimpleUCManager implements UCManager {
|
|
|
29
29
|
constructor(ucClientConfirmManager: UCClientConfirmManager, clockManager: ClockManager, cryptoManager: CryptoManager, logger: Logger, ucDataStore: UCDataStore, ucExecChecker: UCExecChecker, ucInputFilesProcessor: UCInputFilesProcessor, ucInputValidator: UCInputValidator, ucInitProvider: Provider<UCInit>, ucMainProvider: Provider<UCMain>);
|
|
30
30
|
commitTx(): Promise<void>;
|
|
31
31
|
confirmClient<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<boolean>;
|
|
32
|
-
execClient<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<UCOutputReader<I, OPI0, OPI1>>;
|
|
33
|
-
execServer<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<UCOutputOrNothing<OPI0, OPI1>>;
|
|
32
|
+
execClient<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, opts?: UCManagerExecClientOpts<I, OPI0, OPI1>): Promise<UCOutputReader<I, OPI0, OPI1>>;
|
|
33
|
+
execServer<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, opts?: UCManagerExecServerOpts<OPI0, OPI1>): Promise<UCOutputOrNothing<OPI0, OPI1>>;
|
|
34
34
|
initServer<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<void>;
|
|
35
35
|
startTx(): Promise<void>;
|
|
36
36
|
persist<I extends UCInput | undefined = undefined, D extends UCData | null = null, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, data?: D, opts?: UCManagerPersistOpts): Promise<UCDataStoreRecord<I, D>>;
|