@jumoo/processing 18.3.0 → 19.0.0-beta01
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.
|
@@ -39,7 +39,9 @@ let JumooProcessingErrorModal = class JumooProcessingErrorModal extends UmbModal
|
|
|
39
39
|
<div class="detail">${this.data?.error.action}</div>
|
|
40
40
|
</div>
|
|
41
41
|
<div class="more">
|
|
42
|
-
<div class="label"
|
|
42
|
+
<div class="label">
|
|
43
|
+
<umb-localize key="jumooProcError_step"></umb-localize>
|
|
44
|
+
</div>
|
|
43
45
|
<div class="detail">
|
|
44
46
|
${this.data?.error.step}
|
|
45
47
|
${when(this.data?.error.subStep, () => html `(${this.data?.error.subStep})`)}
|
|
@@ -9,10 +9,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _PipelineContext_instances, _PipelineContext_repository, _PipelineContext_hubContext, _PipelineContext_pipeline, _PipelineContext_state, _PipelineContext_options, _PipelineContext_results, _PipelineContext_message, _PipelineContext_backgroundState, _PipelineContext_conflict, _PipelineContext_clientId, _PipelineContext_hasConnectedBefore, _PipelineContext_onClientIdChanged, _PipelineContext_isInFlight, _PipelineContext_setConflict, _PipelineContext_trigger, _PipelineContext_close, _PipelineContext_finalized, _PipelineContext_valid, _PipelineContext_pending;
|
|
12
|
+
var _PipelineContext_instances, _PipelineContext_repository, _PipelineContext_hubContext, _PipelineContext_pipeline, _PipelineContext_state, _PipelineContext_options, _PipelineContext_results, _PipelineContext_message, _PipelineContext_backgroundState, _PipelineContext_conflict, _PipelineContext_clientId, _PipelineContext_hasConnectedBefore, _PipelineContext_onClientIdChanged, _PipelineContext_isInFlight, _PipelineContext_setConflict, _PipelineContext_retryAfterSignIn, _PipelineContext_waitForSignIn, _PipelineContext_trigger, _PipelineContext_close, _PipelineContext_finalized, _PipelineContext_valid, _PipelineContext_pending;
|
|
13
13
|
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
|
14
14
|
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
|
15
15
|
import { UmbBooleanState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
|
|
16
|
+
import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
|
|
17
|
+
import { UmbApiError } from '@umbraco-cms/backoffice/resources';
|
|
18
|
+
import { filter, firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
|
|
16
19
|
import { PipelineStatus, PipelineRepository, ProcessingSignalRContext, getPipelineConflict, } from '@jumoo/processing';
|
|
17
20
|
/**
|
|
18
21
|
* @description context for keeping pipeline status and progress as we do things.
|
|
@@ -65,8 +68,7 @@ export class PipelineContext extends UmbControllerBase {
|
|
|
65
68
|
__classPrivateFieldSet(this, _PipelineContext_repository, new PipelineRepository(this), "f");
|
|
66
69
|
this.provideContext(JUMOO_PROCESSING_CONTEXT, this);
|
|
67
70
|
__classPrivateFieldSet(this, _PipelineContext_hubContext, new ProcessingSignalRContext(this), "f");
|
|
68
|
-
|
|
69
|
-
__classPrivateFieldGet(this, _PipelineContext_hubContext, "f").startHub(token, ['message', 'state']);
|
|
71
|
+
__classPrivateFieldGet(this, _PipelineContext_hubContext, "f").startHub(['message', 'state']);
|
|
70
72
|
this.observe(__classPrivateFieldGet(this, _PipelineContext_hubContext, "f").messagesOf('message'), (message) => {
|
|
71
73
|
if (!message?.message)
|
|
72
74
|
return;
|
|
@@ -93,7 +95,7 @@ export class PipelineContext extends UmbControllerBase {
|
|
|
93
95
|
}
|
|
94
96
|
async createPipeline(processor, strategy, options) {
|
|
95
97
|
__classPrivateFieldGet(this, _PipelineContext_conflict, "f").setValue(undefined);
|
|
96
|
-
const { data, error } = await __classPrivateFieldGet(this, _PipelineContext_repository, "f").tryCreate(processor, strategy, options);
|
|
98
|
+
const { data, error } = await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_retryAfterSignIn).call(this, () => __classPrivateFieldGet(this, _PipelineContext_repository, "f").tryCreate(processor, strategy, options));
|
|
97
99
|
if (error) {
|
|
98
100
|
await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_setConflict).call(this, error);
|
|
99
101
|
return;
|
|
@@ -123,8 +125,10 @@ export class PipelineContext extends UmbControllerBase {
|
|
|
123
125
|
async process() {
|
|
124
126
|
if (!__classPrivateFieldGet(this, _PipelineContext_pipeline, "f").value)
|
|
125
127
|
return;
|
|
126
|
-
const
|
|
127
|
-
const { data: response, error } = await __classPrivateFieldGet(this,
|
|
128
|
+
const pipelineId = __classPrivateFieldGet(this, _PipelineContext_pipeline, "f").value;
|
|
129
|
+
const { data: response, error } = await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_retryAfterSignIn).call(this, () =>
|
|
130
|
+
// the connection id is read each time: the hub can reconnect while the user signs in.
|
|
131
|
+
__classPrivateFieldGet(this, _PipelineContext_repository, "f").tryProcess(pipelineId, __classPrivateFieldGet(this, _PipelineContext_hubContext, "f")?.getClientId() ?? null));
|
|
128
132
|
if (error) {
|
|
129
133
|
await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_setConflict).call(this, error);
|
|
130
134
|
return undefined;
|
|
@@ -143,7 +147,8 @@ export class PipelineContext extends UmbControllerBase {
|
|
|
143
147
|
async updateOptions(options) {
|
|
144
148
|
if (!__classPrivateFieldGet(this, _PipelineContext_pipeline, "f").value)
|
|
145
149
|
return;
|
|
146
|
-
const
|
|
150
|
+
const pipelineId = __classPrivateFieldGet(this, _PipelineContext_pipeline, "f").value;
|
|
151
|
+
const { data: response, error } = await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_retryAfterSignIn).call(this, () => __classPrivateFieldGet(this, _PipelineContext_repository, "f").tryUpdate(pipelineId, options));
|
|
147
152
|
if (error)
|
|
148
153
|
await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_setConflict).call(this, error);
|
|
149
154
|
if (response?.options) {
|
|
@@ -157,7 +162,8 @@ export class PipelineContext extends UmbControllerBase {
|
|
|
157
162
|
async saveOptions() {
|
|
158
163
|
if (!__classPrivateFieldGet(this, _PipelineContext_pipeline, "f").value)
|
|
159
164
|
return;
|
|
160
|
-
const
|
|
165
|
+
const pipelineId = __classPrivateFieldGet(this, _PipelineContext_pipeline, "f").value;
|
|
166
|
+
const { data: response, error } = await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_retryAfterSignIn).call(this, () => __classPrivateFieldGet(this, _PipelineContext_repository, "f").tryUpdate(pipelineId, __classPrivateFieldGet(this, _PipelineContext_options, "f").value));
|
|
161
167
|
if (error)
|
|
162
168
|
await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_setConflict).call(this, error);
|
|
163
169
|
if (response?.options) {
|
|
@@ -290,6 +296,48 @@ async function _PipelineContext_setConflict(error) {
|
|
|
290
296
|
if (holder)
|
|
291
297
|
__classPrivateFieldGet(this, _PipelineContext_conflict, "f").setValue({ ...conflict, holder });
|
|
292
298
|
return true;
|
|
299
|
+
}, _PipelineContext_retryAfterSignIn =
|
|
300
|
+
/**
|
|
301
|
+
* @description makes a create, update or process call, and makes it again if it hit a session
|
|
302
|
+
* timeout. From Umbraco 19 a 401 on a POST opens the login modal but, unlike a GET, the
|
|
303
|
+
* request is not retried - so a run would drop back to waiting mid-pipeline, or carry on with
|
|
304
|
+
* options that were never saved. The 401 comes from the auth middleware, before our
|
|
305
|
+
* controller runs, so once the user has signed back in it is safe to send the same call again.
|
|
306
|
+
* @param call the request, made again on each attempt.
|
|
307
|
+
* @returns the first result that isn't a 401.
|
|
308
|
+
*/
|
|
309
|
+
async function _PipelineContext_retryAfterSignIn(call) {
|
|
310
|
+
let result = await call();
|
|
311
|
+
while (result.error && (await __classPrivateFieldGet(this, _PipelineContext_instances, "m", _PipelineContext_waitForSignIn).call(this, result.error))) {
|
|
312
|
+
result = await call();
|
|
313
|
+
}
|
|
314
|
+
return result;
|
|
315
|
+
}, _PipelineContext_waitForSignIn =
|
|
316
|
+
/**
|
|
317
|
+
* @description waits for the user to sign back in after a session timeout.
|
|
318
|
+
* @param error the error from a request.
|
|
319
|
+
* @returns true once the user has signed back in after a 401, false for any other error.
|
|
320
|
+
*/
|
|
321
|
+
async function _PipelineContext_waitForSignIn(error) {
|
|
322
|
+
// the generated client doesn't throw, so this is usually the problem details themselves
|
|
323
|
+
// rather than an UmbApiError - check both, as getPipelineConflict does.
|
|
324
|
+
const status = UmbApiError.isUmbApiError(error)
|
|
325
|
+
? error.status
|
|
326
|
+
: error?.status;
|
|
327
|
+
if (status !== 401)
|
|
328
|
+
return false;
|
|
329
|
+
const authContext = await this.getContext(UMB_AUTH_CONTEXT);
|
|
330
|
+
if (!authContext)
|
|
331
|
+
return false;
|
|
332
|
+
// the 401 clears the session, but the request can land before that does - so wait for
|
|
333
|
+
// the session to be gone and then back, rather than taking a still-signed-in value.
|
|
334
|
+
let signedOut = false;
|
|
335
|
+
await firstValueFrom(authContext.isAuthorized.pipe(filter((isAuthorized) => {
|
|
336
|
+
if (!isAuthorized)
|
|
337
|
+
signedOut = true;
|
|
338
|
+
return isAuthorized && signedOut;
|
|
339
|
+
})));
|
|
340
|
+
return true;
|
|
293
341
|
};
|
|
294
342
|
export default PipelineContext;
|
|
295
343
|
export const JUMOO_PROCESSING_CONTEXT = new UmbContextToken('JumooPipelineContext');
|
|
@@ -9,6 +9,15 @@ export declare class ProcessingSignalRContext extends UmbControllerBase {
|
|
|
9
9
|
readonly message: import("rxjs").Observable<ProcessingHubMessage[]>;
|
|
10
10
|
readonly clientId: import("rxjs").Observable<string | null>;
|
|
11
11
|
readonly connectionState: import("rxjs").Observable<ProcessingConnectionState>;
|
|
12
|
+
/**
|
|
13
|
+
* @description connects to the processing hub. From Umbraco 19 the backoffice session is a
|
|
14
|
+
* cookie, so the connection sends that rather than a token.
|
|
15
|
+
*/
|
|
16
|
+
startHub(methods: string[]): void;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated there is no client-side token from Umbraco 19 - call `startHub(methods)`. The
|
|
19
|
+
* token is ignored. Will be removed in v21.
|
|
20
|
+
*/
|
|
12
21
|
startHub(token: string, methods: string[]): void;
|
|
13
22
|
hostConnected(): void;
|
|
14
23
|
hostDisconnected(): void;
|
|
@@ -28,8 +28,9 @@ export class ProcessingSignalRContext extends UmbControllerBase {
|
|
|
28
28
|
this.connectionState = __classPrivateFieldGet(this, _ProcessingSignalRContext_connectionState, "f").asObservable();
|
|
29
29
|
this.provideContext(JUMOO_PROCESSING_SIGNALR_CONTEXT, this);
|
|
30
30
|
}
|
|
31
|
-
startHub(
|
|
32
|
-
|
|
31
|
+
startHub(tokenOrMethods, methods) {
|
|
32
|
+
const hubMethods = Array.isArray(tokenOrMethods) ? tokenOrMethods : (methods ?? []);
|
|
33
|
+
__classPrivateFieldGet(this, _ProcessingSignalRContext_instances, "m", _ProcessingSignalRContext_setupConnection).call(this, JUMOO_PROCESSING_HUB_PATH, hubMethods);
|
|
33
34
|
}
|
|
34
35
|
hostConnected() {
|
|
35
36
|
super.hostConnected();
|
|
@@ -53,9 +54,11 @@ export class ProcessingSignalRContext extends UmbControllerBase {
|
|
|
53
54
|
return __classPrivateFieldGet(this, _ProcessingSignalRContext_connection, "f")?.connectionId ?? null;
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
|
-
_ProcessingSignalRContext_connection = new WeakMap(), _ProcessingSignalRContext_messages = new WeakMap(), _ProcessingSignalRContext_clientId = new WeakMap(), _ProcessingSignalRContext_connectionState = new WeakMap(), _ProcessingSignalRContext_instances = new WeakSet(), _ProcessingSignalRContext_setupConnection = function _ProcessingSignalRContext_setupConnection(url,
|
|
57
|
+
_ProcessingSignalRContext_connection = new WeakMap(), _ProcessingSignalRContext_messages = new WeakMap(), _ProcessingSignalRContext_clientId = new WeakMap(), _ProcessingSignalRContext_connectionState = new WeakMap(), _ProcessingSignalRContext_instances = new WeakSet(), _ProcessingSignalRContext_setupConnection = function _ProcessingSignalRContext_setupConnection(url, methods) {
|
|
58
|
+
// no accessTokenFactory: the backoffice auth cookie goes with the negotiate request and
|
|
59
|
+
// the websocket upgrade, which is how Umbraco's own server-event hub connects.
|
|
57
60
|
__classPrivateFieldSet(this, _ProcessingSignalRContext_connection, new signalR.HubConnectionBuilder()
|
|
58
|
-
.withUrl(url
|
|
61
|
+
.withUrl(url)
|
|
59
62
|
.withAutomaticReconnect([0, 2000, 10000, 30000])
|
|
60
63
|
.configureLogging(signalR.LogLevel.None)
|
|
61
64
|
.build(), "f");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jumoo/processing",
|
|
3
3
|
"licence": "custom",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "19.0.0-beta01",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Jumoo processing library",
|
|
7
7
|
"exports": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@eslint/js": "^10.0.1",
|
|
41
41
|
"@hey-api/openapi-ts": "^0.99.0",
|
|
42
42
|
"@microsoft/signalr": "^10.0.0",
|
|
43
|
-
"@umbraco-cms/backoffice": "
|
|
43
|
+
"@umbraco-cms/backoffice": "19.0.0-beta1",
|
|
44
44
|
"chalk": "^5.6.2",
|
|
45
45
|
"cross-env": "^10.1.0",
|
|
46
46
|
"eslint": "^10.13.0",
|