@floegence/redevplugin-ui 0.5.1 → 0.6.5

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/http.js CHANGED
@@ -14,6 +14,24 @@ export function assertMutationDispatchable(signal, operation) {
14
14
  return;
15
15
  throw new PluginTransportError(`Plugin platform request was aborted before dispatch for ${operation}`, signal.reason, "not_committed");
16
16
  }
17
+ export async function dispatchQueryRequest(fetch, input, init, operation) {
18
+ if (init.signal?.aborted) {
19
+ throw new PluginTransportError(`Plugin platform query was aborted before dispatch for ${operation}`, init.signal.reason);
20
+ }
21
+ let pending;
22
+ try {
23
+ pending = fetch(input, init);
24
+ }
25
+ catch (cause) {
26
+ throw new PluginTransportError(`Plugin platform query failed before dispatch for ${operation}`, cause);
27
+ }
28
+ try {
29
+ return await pending;
30
+ }
31
+ catch (cause) {
32
+ throw new PluginTransportError(`Plugin platform query failed after dispatch for ${operation}`, cause);
33
+ }
34
+ }
17
35
  export async function dispatchMutationRequest(fetch, input, init, operation) {
18
36
  assertMutationDispatchable(init.signal, operation);
19
37
  let pending;
@@ -88,7 +106,8 @@ function isPlatformResponse(value, mutation) {
88
106
  Array.from(value.error.message).length > 4096 ||
89
107
  !isPlatformErrorDetails(value.error.code, value.error.details))
90
108
  return false;
91
- return !mutation || value.error.mutation_outcome === "not_committed" || value.error.mutation_outcome === "unknown";
109
+ return !mutation || value.error.mutation_outcome === "committed" ||
110
+ value.error.mutation_outcome === "not_committed" || value.error.mutation_outcome === "unknown";
92
111
  }
93
112
  const packageValidationErrorCodes = [
94
113
  "PLUGIN_MANIFEST_INVALID",
@@ -111,6 +130,9 @@ function isPluginPlatformErrorCode(value) {
111
130
  return typeof value === "string" && pluginPlatformErrorCodes.includes(value);
112
131
  }
113
132
  function isPlatformErrorDetails(code, value) {
133
+ if (code === "PLUGIN_SESSION_TEARDOWN_INCOMPLETE") {
134
+ return hasExactKeys(value, ["session_scope"]) && isIncompleteSessionScopeResult(value.session_scope);
135
+ }
114
136
  if (code === "PLUGIN_MANAGEMENT_REVISION_MISMATCH") {
115
137
  return hasExactKeys(value, ["plugin_instance_id", "expected_management_revision", "actual_management_revision"]) &&
116
138
  typeof value.plugin_instance_id === "string" && value.plugin_instance_id.length > 0 &&
@@ -176,6 +198,20 @@ function isPlatformErrorDetails(code, value) {
176
198
  }
177
199
  return hasExactKeys(value, []);
178
200
  }
201
+ const sessionScopeCountKeys = [
202
+ "surfaces", "asset_tickets", "asset_sessions", "plugin_gateway_tokens", "confirmation_tokens",
203
+ "stream_tickets", "handle_grants", "confirmations", "operations", "streams", "runtime_executions",
204
+ "active_network_requests", "sockets", "network_streams", "storage_hostcalls",
205
+ ];
206
+ function isIncompleteSessionScopeResult(value) {
207
+ if (!hasExactKeys(value, ["state", "fenced", "complete", "counts"]) ||
208
+ value.state !== "incomplete" || value.fenced !== true || value.complete !== false)
209
+ return false;
210
+ const counts = value.counts;
211
+ if (!hasExactKeys(counts, sessionScopeCountKeys))
212
+ return false;
213
+ return sessionScopeCountKeys.every((key) => Number.isSafeInteger(counts[key]) && Number(counts[key]) >= 0);
214
+ }
179
215
  function hasRequiredKeys(value, keys) {
180
216
  return keys.every((key) => Object.hasOwn(value, key));
181
217
  }
@@ -17,19 +17,23 @@ export class PluginLocalImportClient {
17
17
  if (!canonicalPluginInstanceId) {
18
18
  throw new TypeError("pluginInstanceId is required");
19
19
  }
20
- return this.#requestMutation(`/_redevplugin/api/plugins/local-imports?plugin_instance_id=${encodeURIComponent(canonicalPluginInstanceId)}`, packageBlob, options);
20
+ return this.#requestMutation("POST", `/_redevplugin/api/plugins/${encodeURIComponent(canonicalPluginInstanceId)}/local-import`, packageBlob, options);
21
21
  }
22
22
  async updateLocalPackage(pluginInstanceId, expectedManagementRevision, packageBlob, options = {}) {
23
23
  const canonicalPluginInstanceId = pluginInstanceId.trim();
24
24
  if (!canonicalPluginInstanceId) {
25
25
  throw new TypeError("pluginInstanceId is required");
26
26
  }
27
+ if (!Number.isSafeInteger(expectedManagementRevision) || expectedManagementRevision <= 0) {
28
+ throw new TypeError("expectedManagementRevision must be a positive safe integer");
29
+ }
27
30
  let plugin;
28
31
  try {
29
- plugin = await this.#requestMutation(`/_redevplugin/api/plugins/${encodeURIComponent(canonicalPluginInstanceId)}/local-import?expected_management_revision=${encodeURIComponent(String(expectedManagementRevision))}`, packageBlob, options);
32
+ plugin = await this.#requestMutation("PUT", `/_redevplugin/api/plugins/${encodeURIComponent(canonicalPluginInstanceId)}/local-import`, packageBlob, options, { "X-ReDevPlugin-Expected-Management-Revision": String(expectedManagementRevision) });
30
33
  }
31
34
  catch (error) {
32
- if (pluginMutationOutcome(error) !== "not_committed") {
35
+ const outcome = pluginMutationOutcome(error);
36
+ if (outcome === "committed" || outcome === "unknown") {
33
37
  const lifecycleErrors = [];
34
38
  try {
35
39
  await disposePluginSurfaceScope(this.#surfaceScope, canonicalPluginInstanceId);
@@ -37,11 +41,13 @@ export class PluginLocalImportClient {
37
41
  catch (caught) {
38
42
  lifecycleErrors.push(caught);
39
43
  }
40
- try {
41
- this.#onMutationOutcomeUnknown?.(canonicalPluginInstanceId);
42
- }
43
- catch (caught) {
44
- lifecycleErrors.push(caught);
44
+ if (outcome === "unknown") {
45
+ try {
46
+ this.#onMutationOutcomeUnknown?.(canonicalPluginInstanceId);
47
+ }
48
+ catch (caught) {
49
+ lifecycleErrors.push(caught);
50
+ }
45
51
  }
46
52
  if (lifecycleErrors.length > 0) {
47
53
  throw new PluginMutationLifecycleError("Local plugin update and surface teardown failed", error, lifecycleErrors);
@@ -52,11 +58,10 @@ export class PluginLocalImportClient {
52
58
  await disposePluginSurfaceScope(this.#surfaceScope, canonicalPluginInstanceId);
53
59
  return plugin;
54
60
  }
55
- async #requestMutation(path, body, options) {
61
+ async #requestMutation(method, path, body, options, metadataHeaders = {}) {
56
62
  if (!(body instanceof Blob)) {
57
63
  throw new TypeError("package upload must be a Blob");
58
64
  }
59
- const method = path.includes("/local-import?") ? "PUT" : "POST";
60
65
  const operation = `${method} ${path}`;
61
66
  assertMutationDispatchable(options.signal, operation);
62
67
  options.onProgress?.(0, body.size);
@@ -65,6 +70,7 @@ export class PluginLocalImportClient {
65
70
  headers: {
66
71
  "Accept": "application/json",
67
72
  "Content-Type": "application/vnd.redevplugin.package+zip",
73
+ ...metadataHeaders,
68
74
  },
69
75
  body,
70
76
  credentials: "same-origin",