@floegence/redevplugin-ui 3.0.13 → 3.0.15

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/errors.d.ts CHANGED
@@ -13,8 +13,9 @@ export declare class PluginPlatformRequestError extends Error {
13
13
  }
14
14
  export declare class PluginTransportError extends Error {
15
15
  readonly mutationOutcome?: PluginMutationOutcome;
16
+ readonly httpStatus?: number;
16
17
  readonly cause: unknown;
17
- constructor(message: string, cause: unknown, mutationOutcome?: PluginMutationOutcome);
18
+ constructor(message: string, cause: unknown, mutationOutcome?: PluginMutationOutcome, httpStatus?: number);
18
19
  }
19
20
  export declare class PluginBridgeError extends Error {
20
21
  readonly errorCode: string;
package/dist/errors.js CHANGED
@@ -13,12 +13,14 @@ export class PluginPlatformRequestError extends Error {
13
13
  }
14
14
  export class PluginTransportError extends Error {
15
15
  mutationOutcome;
16
+ httpStatus;
16
17
  cause;
17
- constructor(message, cause, mutationOutcome) {
18
+ constructor(message, cause, mutationOutcome, httpStatus) {
18
19
  super(message, { cause });
19
20
  this.name = "PluginTransportError";
20
21
  this.cause = cause;
21
22
  this.mutationOutcome = mutationOutcome;
23
+ this.httpStatus = httpStatus;
22
24
  }
23
25
  }
24
26
  export class PluginBridgeError extends Error {
package/dist/http.js CHANGED
@@ -60,19 +60,21 @@ async function readResponse(response, mutation) {
60
60
  raw = await response.json();
61
61
  }
62
62
  catch (cause) {
63
- throw new PluginTransportError(`Plugin platform endpoint returned invalid JSON with HTTP ${response.status}`, cause, mutation ? "unknown" : undefined);
63
+ throw new PluginTransportError(response.ok && response.status >= 200 && response.status < 300
64
+ ? `Plugin platform endpoint returned invalid JSON with HTTP ${response.status}`
65
+ : `Plugin platform endpoint rejected the request with HTTP ${response.status}`, cause, mutation ? "unknown" : undefined, response.status);
64
66
  }
65
67
  if (!isPlatformResponse(raw, mutation)) {
66
- throw new PluginTransportError(`Plugin platform endpoint returned an invalid envelope with HTTP ${response.status}`, new PluginPlatformRequestError("PLUGIN_CONTRACT_MISMATCH", "Invalid platform response envelope"), mutation ? "unknown" : undefined);
68
+ throw new PluginTransportError(`Plugin platform endpoint returned an invalid envelope with HTTP ${response.status}`, new PluginPlatformRequestError("PLUGIN_CONTRACT_MISMATCH", "Invalid platform response envelope"), mutation ? "unknown" : undefined, response.status);
67
69
  }
68
70
  if (raw.ok) {
69
71
  if (!response.ok || response.status !== 200) {
70
- throw new PluginTransportError(`Plugin platform endpoint returned a success envelope with HTTP ${response.status}`, new PluginPlatformRequestError("PLUGIN_CONTRACT_MISMATCH", "HTTP status does not match the platform response envelope"), mutation ? "unknown" : undefined);
72
+ throw new PluginTransportError(`Plugin platform endpoint returned a success envelope with HTTP ${response.status}`, new PluginPlatformRequestError("PLUGIN_CONTRACT_MISMATCH", "HTTP status does not match the platform response envelope"), mutation ? "unknown" : undefined, response.status);
71
73
  }
72
74
  return raw.data;
73
75
  }
74
76
  if (response.ok || response.status === 200) {
75
- throw new PluginTransportError(`Plugin platform endpoint returned an error envelope with HTTP ${response.status}`, new PluginPlatformRequestError("PLUGIN_CONTRACT_MISMATCH", "HTTP status does not match the platform response envelope"), mutation ? "unknown" : undefined);
77
+ throw new PluginTransportError(`Plugin platform endpoint returned an error envelope with HTTP ${response.status}`, new PluginPlatformRequestError("PLUGIN_CONTRACT_MISMATCH", "HTTP status does not match the platform response envelope"), mutation ? "unknown" : undefined, response.status);
76
78
  }
77
79
  {
78
80
  throw new PluginPlatformRequestError(raw.error.code, raw.error.message || `Plugin platform endpoint failed with HTTP ${response.status}`, raw.error.details, "mutation_outcome" in raw.error ? raw.error.mutation_outcome : undefined);
@@ -2089,6 +2089,8 @@ export interface components {
2089
2089
  };
2090
2090
  ListExecutionsRequest: {
2091
2091
  plugin_instance_id?: string;
2092
+ /** @enum {string} */
2093
+ operation_scope?: "release_install";
2092
2094
  cursor?: number;
2093
2095
  limit?: number;
2094
2096
  };
@@ -2356,7 +2358,8 @@ export interface components {
2356
2358
  failure_code?: string;
2357
2359
  /** @enum {string} */
2358
2360
  failure_stage?: "download" | "verify" | "install" | "enable";
2359
- };
2361
+ retryable?: boolean;
2362
+ } & unknown;
2360
2363
  PublicError: {
2361
2364
  code: string;
2362
2365
  message: string;
@@ -77,11 +77,15 @@ export type PluginSettingsPatchRequest = PluginSettingsPatchBase & ({
77
77
  export type PluginCapabilityContractPin = PlatformSchemas["HostCapabilityPinV1"];
78
78
  export type PluginExecution = PlatformSchemas["Execution"];
79
79
  export type PluginEvent = PlatformSchemas["Event"];
80
+ export type PluginReleaseInstallProgressEvent = PlatformSchemas["ReleaseInstallProgressEvent"];
80
81
  export type PluginStartReleaseInstallExecutionRequest = PlatformSchemas["StartReleaseInstallExecutionRequest"];
81
82
  export type PluginExecutionList = PlatformSchemas["ExecutionList"];
82
83
  export type PluginExecutionEventList = PlatformSchemas["ExecutionEventList"];
83
84
  export type PluginExecutionListOptions = PlatformSchemas["ListExecutionsRequest"];
85
+ export type PluginReleaseInstallExecutionListOptions = Omit<PluginExecutionListOptions, "operation_scope">;
84
86
  export type PluginExecutionEventListOptions = PlatformSchemas["ListExecutionEventsRequest"];
87
+ /** Reads the stable release-install progress projection from an execution event. */
88
+ export declare function decodePluginReleaseInstallProgressEvent(event: PluginEvent): PluginReleaseInstallProgressEvent | undefined;
85
89
  export type PluginIntentRecord = PlatformSchemas["PluginIntentRecord"];
86
90
  export type PluginIntentList = PlatformSchemas["PluginIntentList"];
87
91
  export type PluginIntentListOptions = PlatformSchemas["ListIntentsQueryRequest"];
@@ -144,6 +148,7 @@ export declare class PluginPlatformClient {
144
148
  getSettings(pluginInstanceId: string, scope: PluginResourceScopeKind, options?: PluginRequestOptions): Promise<PluginSettingsSnapshot>;
145
149
  patchSettings(pluginInstanceId: string, request: PluginSettingsPatchRequest, options?: PluginRequestOptions): Promise<PluginSettingsSnapshot>;
146
150
  listExecutions(options?: PluginExecutionListOptions, requestOptions?: PluginRequestOptions): Promise<PluginExecutionList>;
151
+ listReleaseInstallExecutions(options?: PluginReleaseInstallExecutionListOptions, requestOptions?: PluginRequestOptions): Promise<PluginExecutionList>;
147
152
  startReleaseInstallExecution(request: PluginStartReleaseInstallExecutionRequest, options?: PluginRequestOptions): Promise<PluginExecution>;
148
153
  getExecution(executionID: string, options?: PluginRequestOptions): Promise<PluginExecution>;
149
154
  cancelExecution(executionID: string, reason?: string, options?: PluginRequestOptions): Promise<PluginExecution>;
package/dist/platform.js CHANGED
@@ -20,6 +20,58 @@ function toPluginSurfaceHostBootstrap(value) {
20
20
  runtimeGenerationId: value.runtime_generation_id,
21
21
  };
22
22
  }
23
+ const releaseInstallStages = ["download", "verify", "install", "enable"];
24
+ const releaseInstallStatuses = ["pending", "running", "completed", "failed"];
25
+ const releaseInstallProgressKeys = [
26
+ "task_id",
27
+ "request_id",
28
+ "stage",
29
+ "status",
30
+ "completed",
31
+ "total",
32
+ "failure_code",
33
+ "failure_stage",
34
+ "retryable",
35
+ ];
36
+ /** Reads the stable release-install progress projection from an execution event. */
37
+ export function decodePluginReleaseInstallProgressEvent(event) {
38
+ const payload = event?.payload;
39
+ if (!isRecord(payload))
40
+ return undefined;
41
+ const value = payload.install_progress;
42
+ if (!isRecord(value) || !hasOnlyKeys(value, releaseInstallProgressKeys))
43
+ return undefined;
44
+ if (!isNonEmptyString(value.task_id) || !isNonEmptyString(value.request_id))
45
+ return undefined;
46
+ if (value.task_id !== event.execution_id)
47
+ return undefined;
48
+ if (!isOneOf(value.stage, releaseInstallStages) || !isOneOf(value.status, releaseInstallStatuses)) {
49
+ return undefined;
50
+ }
51
+ const hasCompleted = value.completed !== undefined;
52
+ const hasTotal = value.total !== undefined;
53
+ if (hasCompleted !== hasTotal)
54
+ return undefined;
55
+ if (hasCompleted &&
56
+ (!isSafeIntegerAtLeast(value.completed, 0) || !isSafeIntegerAtLeast(value.total, 1))) {
57
+ return undefined;
58
+ }
59
+ if (hasCompleted && Number(value.completed) > Number(value.total))
60
+ return undefined;
61
+ const failed = value.status === "failed";
62
+ if (failed) {
63
+ if (!isNonEmptyString(value.failure_code) ||
64
+ !isOneOf(value.failure_stage, releaseInstallStages) ||
65
+ value.failure_stage !== value.stage ||
66
+ typeof value.retryable !== "boolean") {
67
+ return undefined;
68
+ }
69
+ }
70
+ else if (value.failure_code !== undefined || value.failure_stage !== undefined || value.retryable !== undefined) {
71
+ return undefined;
72
+ }
73
+ return value;
74
+ }
23
75
  export class PluginPlatformClient {
24
76
  #fetch;
25
77
  #apiBaseURL;
@@ -161,6 +213,9 @@ export class PluginPlatformClient {
161
213
  listExecutions(options = {}, requestOptions = {}) {
162
214
  return this.#requestQuery("/_redevplugin/api/plugins/executions/query", options, requestOptions);
163
215
  }
216
+ listReleaseInstallExecutions(options = {}, requestOptions = {}) {
217
+ return this.listExecutions({ ...options, operation_scope: "release_install" }, requestOptions);
218
+ }
164
219
  startReleaseInstallExecution(request, options = {}) {
165
220
  return this.#requestMutation("POST", "/_redevplugin/api/plugins/executions/release-installs", request, options);
166
221
  }
@@ -412,6 +467,22 @@ function isPluginSessionScopeRevokeResult(value) {
412
467
  return false;
413
468
  return sessionScopeCountKeys.every((key) => Number.isSafeInteger(counts[key]) && Number(counts[key]) >= 0);
414
469
  }
470
+ function isRecord(value) {
471
+ return typeof value === "object" && value !== null && !Array.isArray(value);
472
+ }
473
+ function hasOnlyKeys(value, keys) {
474
+ const allowed = new Set(keys);
475
+ return Object.keys(value).every((key) => allowed.has(key));
476
+ }
477
+ function isNonEmptyString(value) {
478
+ return typeof value === "string" && value.length > 0;
479
+ }
480
+ function isOneOf(value, values) {
481
+ return typeof value === "string" && values.includes(value);
482
+ }
483
+ function isSafeIntegerAtLeast(value, minimum) {
484
+ return Number.isSafeInteger(value) && Number(value) >= minimum;
485
+ }
415
486
  function isExactRecord(value, keys) {
416
487
  if (typeof value !== "object" || value === null || Array.isArray(value))
417
488
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/redevplugin-ui",
3
- "version": "3.0.13",
3
+ "version": "3.0.15",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -40,7 +40,7 @@
40
40
  "dist"
41
41
  ],
42
42
  "dependencies": {
43
- "@floegence/redevplugin-contracts": "3.0.13"
43
+ "@floegence/redevplugin-contracts": "3.0.15"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public"