@floegence/redevplugin-ui 3.0.12 → 3.0.14

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.
@@ -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/dist/surface.js CHANGED
@@ -1902,29 +1902,6 @@ export function createOpaquePluginBootstrapHTML(options = {}) {
1902
1902
  ' close();',
1903
1903
  ' return;',
1904
1904
  '}',
1905
- 'const __rpVerifyDynamicImportBlocked = () => new Promise((resolve, reject) => {',
1906
- ' const specifier = "data:text/javascript,export default 1";',
1907
- ' let settled = false;',
1908
- ' let timeout;',
1909
- ' const cleanup = () => { __rpRemoveEventListener("securitypolicyviolation", onViolation, true); if (timeout !== undefined) __rpClearTimeout(timeout); };',
1910
- ' const finishBlocked = () => { if (settled) return; settled = true; cleanup(); resolve(true); };',
1911
- ' const finishEscaped = () => {',
1912
- ' if (settled) { __rpReportFailure(new TypeError("Dynamic import escaped the ReDevPlugin worker sandbox")); return; }',
1913
- ' settled = true; cleanup(); resolve(false);',
1914
- ' };',
1915
- ' const onViolation = (event) => {',
1916
- ' const directive = String(event && (event.effectiveDirective || event.violatedDirective) || "");',
1917
- ' const blockedURI = String(event && event.blockedURI || "");',
1918
- ' if ((directive === "script-src" || directive === "script-src-elem") && (blockedURI === "data" || blockedURI.startsWith("data:"))) finishBlocked();',
1919
- ' };',
1920
- ' __rpAddEventListener("securitypolicyviolation", onViolation, true);',
1921
- ' timeout = __rpSetTimeout(() => { if (settled) return; settled = true; cleanup(); reject(new TypeError("Dynamic import sandbox verification timed out")); }, 1000);',
1922
- ' try {',
1923
- ' import(specifier).then(finishEscaped, finishBlocked);',
1924
- ' } catch {',
1925
- ' finishBlocked();',
1926
- ' }',
1927
- '});',
1928
1905
  'let __rpClaimed = false;',
1929
1906
  'const __rpBridge = Object.freeze({ claim() { if (__rpClaimed) return undefined; __rpClaimed = true; return Object.freeze({ surfaceHandle: __rpSurfaceHandle, port: __rpPort }); } });',
1930
1907
  'Object.defineProperty(globalThis, ' + JSON.stringify(workerGlobalKey) + ', { configurable: false, enumerable: false, writable: false, value: __rpBridge });',
@@ -1944,7 +1921,6 @@ export function createOpaquePluginBootstrapHTML(options = {}) {
1944
1921
  'addEventListener("unhandledrejection", (event) => __rpReportFailure(event.reason || "plugin worker rejected"), { capture: true });',
1945
1922
  'void (async () => {',
1946
1923
  ' try {',
1947
- ' if (!await __rpVerifyDynamicImportBlocked()) throw new TypeError("Dynamic import escaped the ReDevPlugin worker sandbox");',
1948
1924
  ' __redevpluginPluginMain();',
1949
1925
  ' setTimeout(() => { if (!__rpFailed) __rpControlPost({ type: "redevplugin.worker.ready" }); }, 0);',
1950
1926
  ' } catch (error) {',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/redevplugin-ui",
3
- "version": "3.0.12",
3
+ "version": "3.0.14",
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.12"
43
+ "@floegence/redevplugin-contracts": "3.0.14"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public"