@burdenoff/microfe-devportal 2026.629.10 → 2026.701.1

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.
@@ -14,205 +14,220 @@ import { useDevportalPermission as c } from "../hooks/usePermission.js";
14
14
  import "../hooks/index.js";
15
15
  import ce from "../../node_modules/date-fns/format.js";
16
16
  import { usePackageUpload as le } from "../hooks/usePackageUpload.js";
17
- import { useCallback as ue, useEffect as de, useMemo as l, useRef as fe, useState as u } from "react";
18
- import { useI18n as pe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
19
- import { AlertCircle as d, Archive as me, CheckCircle as f, Clock as he, Loader2 as p, Package as ge, Plus as m, Upload as _e } from "lucide-react";
20
- import { useParams as ve } from "react-router-dom";
21
- import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
17
+ import { useCallback as l, useEffect as ue, useMemo as u, useRef as d, useState as f } from "react";
18
+ import { useI18n as de } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
19
+ import { AlertCircle as p, Archive as fe, CheckCircle as m, Clock as pe, Loader2 as h, Package as me, Plus as he, Upload as ge } from "lucide-react";
20
+ import { useParams as _e } from "react-router-dom";
21
+ import { Fragment as ve, jsx as g, jsxs as _ } from "react/jsx-runtime";
22
22
  //#region src/devportal/pages/ApplicationVersionsPage.tsx
23
- var v = () => {
24
- let { t: v } = pe(), y = (e, t) => {
25
- let n = v(e);
23
+ var ye = () => {
24
+ let { t: ye } = de(), v = (e, t) => {
25
+ let n = ye(e);
26
26
  return n === e ? t : n;
27
- }, { allowed: b } = c(s.APP_VERSION_CREATE), { allowed: x } = c(s.APP_VERSION_PUBLISH), { allowed: S } = c(s.APP_VERSION_DEPRECATE), { appId: C } = ve(), { workspacesGatewayUrl: ye, authToken: be, workspaceId: xe, getWorkspaceToken: Se } = e(), { upload: w, uploading: T, progress: Ce, error: E } = le(ye, be, xe, Se), D = fe(null), [O, k] = u(!1), [A, j] = u({
27
+ }, { allowed: y } = c(s.APP_VERSION_CREATE), { allowed: b } = c(s.APP_VERSION_PUBLISH), { allowed: x } = c(s.APP_VERSION_DEPRECATE), { appId: S } = _e(), { workspacesGatewayUrl: be, authToken: xe, workspaceId: Se, getWorkspaceToken: Ce } = e(), { upload: C, uploading: w, progress: we, error: T } = le(be, xe, Se, Ce), E = d(null), D = d(null), [O, k] = f(null), [A, j] = f(!1), [M, N] = f({
28
28
  version: "",
29
29
  releaseNotes: "",
30
30
  changelog: "",
31
31
  packageUrl: "",
32
32
  packageSize: "",
33
- manifestJson: ""
34
- }), [M, N] = u(null), [P, F] = u(null), [I, L] = u(/* @__PURE__ */ new Set()), [R, z] = u(null), { data: B } = ee({
35
- variables: { id: C ?? "" },
36
- skip: !C,
33
+ manifestJson: "",
34
+ requiredScopes: ""
35
+ }), [P, F] = f(null), [I, L] = f(null), [R, z] = f(/* @__PURE__ */ new Set()), Te = l((e) => {
36
+ let t = e.target.files?.[0];
37
+ if (!t) return;
38
+ let n = new FileReader();
39
+ n.onload = (e) => {
40
+ let n = e.target?.result;
41
+ typeof n == "string" && (N((e) => ({
42
+ ...e,
43
+ manifestJson: n
44
+ })), k(t.name));
45
+ }, n.readAsText(t), e.target.value = "";
46
+ }, []), [B, V] = f(null), { data: H } = ee({
47
+ variables: { id: S ?? "" },
48
+ skip: !S,
37
49
  fetchPolicy: "cache-first"
38
- }), V = B?.application?.appType === "WORKFLOW";
39
- de(() => {
40
- let e = B?.application?.name;
41
- if (!C || !e) return;
50
+ }), U = H?.application?.appType === "WORKFLOW", W = H?.application?.appType === "NODE", G = !U && !W;
51
+ ue(() => {
52
+ let e = H?.application?.name;
53
+ if (!S || !e) return;
42
54
  let t = window.__breadcrumbRegistry;
43
- return t?.register(C, e), () => t?.unregister(C);
44
- }, [C, B?.application?.name]);
45
- let { data: H, loading: we, error: U } = te({
46
- variables: { applicationId: C },
47
- skip: !C,
55
+ return t?.register(S, e), () => t?.unregister(S);
56
+ }, [S, H?.application?.name]);
57
+ let { data: K, loading: Ee, error: De } = te({
58
+ variables: { applicationId: S },
59
+ skip: !S,
48
60
  fetchPolicy: "cache-and-network"
49
- }), [Te, { loading: Ee }] = n({ refetchQueries: ["GetApplicationVersions"] }), [W] = ne({ refetchQueries: ["GetApplicationVersions"] }), [G] = r({ refetchQueries: ["GetApplicationVersions"] }), K = l(() => H?.application?.versions?.edges?.map((e) => e.node) ?? [], [H?.application?.versions]), q = l(() => K.filter((e) => I.has(e.id)), [K, I]), J = l(() => q.filter((e) => e.status?.toUpperCase() === "DRAFT"), [q]), Y = l(() => q.filter((e) => e.status?.toUpperCase() === "PUBLISHED" && !e.isLatest), [q]), X = K.length > 0 && K.every((e) => I.has(e.id)), Z = K.some((e) => I.has(e.id)) && !X, De = async () => {
50
- if (!C || !A.version.trim()) return;
51
- N(null);
61
+ }), [Oe, { loading: ke }] = n({ refetchQueries: ["GetApplicationVersions"] }), [Ae] = ne({ refetchQueries: ["GetApplicationVersions"] }), [je] = r({ refetchQueries: ["GetApplicationVersions"] }), q = u(() => K?.application?.versions?.edges?.map((e) => e.node) ?? [], [K?.application?.versions]), J = u(() => q.filter((e) => R.has(e.id)), [q, R]), Y = u(() => J.filter((e) => e.status?.toUpperCase() === "DRAFT"), [J]), X = u(() => J.filter((e) => e.status?.toUpperCase() === "PUBLISHED" && !e.isLatest), [J]), Z = q.length > 0 && q.every((e) => R.has(e.id)), Q = q.some((e) => R.has(e.id)) && !Z, Me = async () => {
62
+ if (!S || !M.version.trim()) return;
63
+ F(null);
52
64
  let e;
53
- if (V) {
54
- if (!A.manifestJson.trim()) {
55
- N("Workflow Definition (JSON) is required — paste the {nodes, edges} object.");
65
+ if (U) {
66
+ if (!M.manifestJson.trim()) {
67
+ F("Workflow Definition (JSON) is required — paste the {nodes, edges} object.");
56
68
  return;
57
69
  }
58
70
  try {
59
- e = JSON.parse(A.manifestJson);
71
+ e = JSON.parse(M.manifestJson);
60
72
  } catch {
61
- N("Invalid JSON in Workflow Definition — please check your input.");
73
+ F("Invalid JSON in Workflow Definition — please check your input.");
62
74
  return;
63
75
  }
64
- } else if (A.manifestJson.trim()) try {
65
- e = JSON.parse(A.manifestJson);
76
+ } else if (M.manifestJson.trim()) try {
77
+ e = JSON.parse(M.manifestJson);
66
78
  } catch {
67
- N("Invalid JSON in manifest — please check your input.");
79
+ F("Invalid JSON in manifest — please check your input.");
68
80
  return;
69
81
  }
82
+ let t = G && M.requiredScopes.trim() ? M.requiredScopes.split(",").map((e) => e.trim()).filter(Boolean) : void 0;
70
83
  try {
71
- await Te({ variables: {
72
- applicationId: C,
84
+ await Oe({ variables: {
85
+ applicationId: S,
73
86
  input: {
74
- version: A.version,
75
- releaseNotes: A.releaseNotes || void 0,
76
- changelog: A.changelog || void 0,
77
- packageUrl: A.packageUrl || void 0,
78
- packageSize: A.packageSize || void 0,
79
- manifest: e
87
+ version: M.version,
88
+ releaseNotes: M.releaseNotes || void 0,
89
+ changelog: M.changelog || void 0,
90
+ packageUrl: M.packageUrl || void 0,
91
+ packageSize: M.packageSize || void 0,
92
+ manifest: e,
93
+ requiredScopes: t
80
94
  }
81
- } }), k(!1), j({
95
+ } }), j(!1), k(null), N({
82
96
  version: "",
83
97
  releaseNotes: "",
84
98
  changelog: "",
85
99
  packageUrl: "",
86
100
  packageSize: "",
87
- manifestJson: ""
88
- }), F(y("devportal.versionCreatedSuccess", "Version created successfully"));
101
+ manifestJson: "",
102
+ requiredScopes: ""
103
+ }), L(v("devportal.versionCreatedSuccess", "Version created successfully"));
89
104
  } catch (e) {
90
- N(e instanceof Error ? e.message : y("devportal.versionCreateFailed", "Failed to create version"));
105
+ F(e instanceof Error ? e.message : v("devportal.versionCreateFailed", "Failed to create version"));
91
106
  }
92
- }, Oe = ue(async (e) => {
107
+ }, Ne = l(async (e) => {
93
108
  let t = e.target.files?.[0];
94
109
  if (t) {
95
110
  e.target.value = "";
96
111
  try {
97
- let e = await w(t);
98
- j((n) => ({
112
+ let e = await C(t);
113
+ N((n) => ({
99
114
  ...n,
100
115
  packageUrl: e.downloadUrl,
101
116
  packageSize: String(t.size)
102
117
  }));
103
118
  } catch {}
104
119
  }
105
- }, [w]), ke = async (e) => {
106
- N(null), F(null);
120
+ }, [C]), Pe = async (e) => {
121
+ F(null), L(null);
107
122
  try {
108
- await W({ variables: { id: e } }), F(y("devportal.versionPublishedSuccess", "Version published successfully"));
123
+ await Ae({ variables: { id: e } }), L(v("devportal.versionPublishedSuccess", "Version published successfully"));
109
124
  } catch (e) {
110
- N(e instanceof Error ? e.message : y("devportal.versionPublishFailed", "Failed to publish version"));
125
+ F(e instanceof Error ? e.message : v("devportal.versionPublishFailed", "Failed to publish version"));
111
126
  }
112
- }, Ae = async (e) => {
113
- N(null), F(null);
127
+ }, Fe = async (e) => {
128
+ F(null), L(null);
114
129
  try {
115
- await G({ variables: { id: e } }), F(y("devportal.versionDeprecatedSuccess", "Version deprecated successfully"));
130
+ await je({ variables: { id: e } }), L(v("devportal.versionDeprecatedSuccess", "Version deprecated successfully"));
116
131
  } catch (e) {
117
- N(e instanceof Error ? e.message : y("devportal.versionDeprecateFailed", "Failed to deprecate version"));
132
+ F(e instanceof Error ? e.message : v("devportal.versionDeprecateFailed", "Failed to deprecate version"));
118
133
  }
119
- }, je = (e) => {
134
+ }, Ie = (e) => {
120
135
  let t = e.status?.toUpperCase();
121
- return t === "PUBLISHED" && e.isLatest ? /* @__PURE__ */ g(f, {
136
+ return t === "PUBLISHED" && e.isLatest ? /* @__PURE__ */ g(m, {
122
137
  size: 16,
123
138
  className: "text-status-success-text"
124
- }) : t === "DRAFT" ? /* @__PURE__ */ g(he, {
139
+ }) : t === "DRAFT" ? /* @__PURE__ */ g(pe, {
125
140
  size: 16,
126
141
  className: "text-status-warning-text"
127
- }) : t === "DEPRECATED" ? /* @__PURE__ */ g(me, {
142
+ }) : t === "DEPRECATED" ? /* @__PURE__ */ g(fe, {
128
143
  size: 16,
129
144
  className: "text-text-secondary"
130
- }) : /* @__PURE__ */ g(ge, {
145
+ }) : /* @__PURE__ */ g(me, {
131
146
  size: 16,
132
147
  className: "text-accent-blue"
133
148
  });
134
- }, Me = (e, t) => {
135
- L((n) => {
149
+ }, Le = (e, t) => {
150
+ z((n) => {
136
151
  let r = new Set(n);
137
152
  return t ? r.add(e) : r.delete(e), r;
138
153
  });
139
- }, Q = (e) => {
140
- L((t) => {
154
+ }, Re = (e) => {
155
+ z((t) => {
141
156
  let n = new Set(t);
142
- return K.forEach((t) => {
157
+ return q.forEach((t) => {
143
158
  e ? n.add(t.id) : n.delete(t.id);
144
159
  }), n;
145
160
  });
146
- }, $ = () => L(/* @__PURE__ */ new Set());
147
- return we && !H ? /* @__PURE__ */ g(i, {
148
- title: y("devportal.versionManagement", "Version Management"),
149
- description: y("devportal.versionManagementDescription", "Manage your application versions"),
150
- backLink: `/apps/${C}`,
151
- backLabel: y("devportal.backToApplication", "Back to Application"),
161
+ }, $ = () => z(/* @__PURE__ */ new Set());
162
+ return Ee && !K ? /* @__PURE__ */ g(i, {
163
+ title: v("devportal.versionManagement", "Version Management"),
164
+ description: v("devportal.versionManagementDescription", "Manage your application versions"),
165
+ backLink: `/apps/${S}`,
166
+ backLabel: v("devportal.backToApplication", "Back to Application"),
152
167
  children: /* @__PURE__ */ g("div", {
153
168
  className: "flex items-center justify-center py-16",
154
- children: /* @__PURE__ */ g(p, { className: "h-8 w-8 animate-spin text-text-secondary" })
169
+ children: /* @__PURE__ */ g(h, { className: "h-8 w-8 animate-spin text-text-secondary" })
155
170
  })
156
- }) : U && !H ? /* @__PURE__ */ g(i, {
157
- title: y("devportal.versionManagement", "Version Management"),
158
- description: y("devportal.versionManagementDescription", "Manage your application versions"),
159
- backLink: `/apps/${C}`,
160
- backLabel: y("devportal.backToApplication", "Back to Application"),
171
+ }) : De && !K ? /* @__PURE__ */ g(i, {
172
+ title: v("devportal.versionManagement", "Version Management"),
173
+ description: v("devportal.versionManagementDescription", "Manage your application versions"),
174
+ backLink: `/apps/${S}`,
175
+ backLabel: v("devportal.backToApplication", "Back to Application"),
161
176
  children: /* @__PURE__ */ g(t, {
162
- icon: /* @__PURE__ */ g(d, {
177
+ icon: /* @__PURE__ */ g(p, {
163
178
  size: 32,
164
179
  className: "text-status-error-text"
165
180
  }),
166
- title: y("devportal.failedToLoadVersions", "Failed to load versions"),
167
- description: U.message || y("devportal.versionsLoadError", "An error occurred while loading versions")
181
+ title: v("devportal.failedToLoadVersions", "Failed to load versions"),
182
+ description: De.message || v("devportal.versionsLoadError", "An error occurred while loading versions")
168
183
  })
169
184
  }) : /* @__PURE__ */ g(se, {
170
185
  permission: s.APP_READ,
171
186
  children: /* @__PURE__ */ _(i, {
172
- title: y("devportal.versionManagement", "Version Management"),
173
- description: y("devportal.versionManagementDescription", "Manage your application versions"),
174
- purpose: V ? y("devportal.versionManagementPurposeWorkflow", "Versions track releases of your workflow. Create a version for each significant change, add release notes, and publish it. The actual workflow definition is configured in the Store Listing tab.") : y("devportal.versionManagementPurpose", "Versions are the releases of your app that users install. Cut a new version when you ship changes, upload its package, and publish it — the one marked Latest is what new installs receive, so promote carefully."),
175
- backLink: `/apps/${C}`,
176
- backLabel: y("devportal.backToApplication", "Back to Application"),
187
+ title: v("devportal.versionManagement", "Version Management"),
188
+ description: v("devportal.versionManagementDescription", "Manage your application versions"),
189
+ purpose: U ? v("devportal.versionManagementPurposeWorkflow", "Versions track releases of your workflow. Create a version for each significant change and paste the workflow definition JSON. No zip is needed — the manifest is the workflow.") : W ? v("devportal.versionManagementPurposeNode", "Versions are the releases of your node that users install. Upload a new zip whenever the node implementation changes, and update the manifest if the node's inputs, outputs, or operations change. Bump the version for any change users will see.") : v("devportal.versionManagementPurposeIntegration", "Versions track permission and webhook changes for your integration. No zip or manifest is needed — create a new version whenever you add or change required scopes so users can review and accept the updated permissions."),
190
+ backLink: `/apps/${S}`,
191
+ backLabel: v("devportal.backToApplication", "Back to Application"),
177
192
  actions: /* @__PURE__ */ _("button", {
178
- onClick: () => k(!0),
179
- disabled: !b,
180
- "aria-disabled": !b,
193
+ onClick: () => j(!0),
194
+ disabled: !y,
195
+ "aria-disabled": !y,
181
196
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
182
- children: [/* @__PURE__ */ g(m, { size: 16 }), y("devportal.newVersion", "New Version")]
197
+ children: [/* @__PURE__ */ g(he, { size: 16 }), v("devportal.newVersion", "New Version")]
183
198
  }),
184
199
  children: [
185
- M && /* @__PURE__ */ _("div", {
200
+ P && /* @__PURE__ */ _("div", {
186
201
  className: "rounded-lg border border-border-subtle bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text",
187
202
  children: [
188
- /* @__PURE__ */ g(d, {
203
+ /* @__PURE__ */ g(p, {
189
204
  size: 16,
190
205
  className: "flex-shrink-0"
191
206
  }),
192
- M,
207
+ P,
193
208
  /* @__PURE__ */ g("button", {
194
- onClick: () => N(null),
209
+ onClick: () => F(null),
195
210
  className: "ml-auto text-status-error-text hover:text-status-error-text",
196
- children: y("devportal.dismiss", "Dismiss")
211
+ children: v("devportal.dismiss", "Dismiss")
197
212
  })
198
213
  ]
199
214
  }),
200
- P && /* @__PURE__ */ _("div", {
215
+ I && /* @__PURE__ */ _("div", {
201
216
  className: "rounded-lg border border-border-subtle bg-status-success-bg-subtle p-3 flex items-center gap-2 text-sm text-status-success-text",
202
217
  children: [
203
- /* @__PURE__ */ g(f, {
218
+ /* @__PURE__ */ g(m, {
204
219
  size: 16,
205
220
  className: "flex-shrink-0"
206
221
  }),
207
- P,
222
+ I,
208
223
  /* @__PURE__ */ g("button", {
209
- onClick: () => F(null),
224
+ onClick: () => L(null),
210
225
  className: "ml-auto text-status-success-text hover:text-status-success-text",
211
- children: y("devportal.dismiss", "Dismiss")
226
+ children: v("devportal.dismiss", "Dismiss")
212
227
  })
213
228
  ]
214
229
  }),
215
- K.length > 0 && /* @__PURE__ */ g("div", {
230
+ q.length > 0 && /* @__PURE__ */ g("div", {
216
231
  className: "rounded-card border border-border-seam bg-bg-surface p-4",
217
232
  children: /* @__PURE__ */ _("div", {
218
233
  className: "flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",
@@ -221,104 +236,104 @@ var v = () => {
221
236
  children: [/* @__PURE__ */ _("div", {
222
237
  className: "flex items-center gap-2",
223
238
  children: [/* @__PURE__ */ g(a, {
224
- checked: X,
225
- indeterminate: Z,
226
- onChange: Q,
239
+ checked: Z,
240
+ indeterminate: Q,
241
+ onChange: Re,
227
242
  ariaLabel: "Select all visible versions"
228
243
  }), /* @__PURE__ */ g("span", {
229
244
  className: "text-sm font-medium",
230
- children: y("devportal.selectAllVisible", "Select all visible")
245
+ children: v("devportal.selectAllVisible", "Select all visible")
231
246
  })]
232
- }), I.size > 0 && /* @__PURE__ */ g("button", {
247
+ }), R.size > 0 && /* @__PURE__ */ g("button", {
233
248
  onClick: $,
234
249
  className: "text-sm text-text-secondary hover:text-text-primary",
235
- children: y("devportal.clearSelection", "Clear selection")
250
+ children: v("devportal.clearSelection", "Clear selection")
236
251
  })]
237
252
  }), /* @__PURE__ */ _("div", {
238
253
  className: "flex flex-wrap items-center gap-2",
239
254
  children: [
240
255
  /* @__PURE__ */ _("span", {
241
256
  className: "rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary",
242
- children: [I.size, " selected"]
257
+ children: [R.size, " selected"]
243
258
  }),
244
259
  /* @__PURE__ */ _("button", {
245
- onClick: () => z("publish"),
246
- disabled: J.length === 0 || !x,
247
- "aria-disabled": !x,
260
+ onClick: () => V("publish"),
261
+ disabled: Y.length === 0 || !b,
262
+ "aria-disabled": !b,
248
263
  className: "rounded-md border border-status-success-bg px-3 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle disabled:cursor-not-allowed disabled:opacity-50",
249
- children: [y("devportal.publishSelected", "Publish Selected"), J.length > 0 ? ` (${J.length})` : ""]
264
+ children: [v("devportal.publishSelected", "Publish Selected"), Y.length > 0 ? ` (${Y.length})` : ""]
250
265
  }),
251
266
  /* @__PURE__ */ _("button", {
252
- onClick: () => z("deprecate"),
253
- disabled: Y.length === 0 || !S,
254
- "aria-disabled": !S,
267
+ onClick: () => V("deprecate"),
268
+ disabled: X.length === 0 || !x,
269
+ "aria-disabled": !x,
255
270
  className: "rounded-md border border-status-warning-bg px-3 py-2 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg-subtle disabled:cursor-not-allowed disabled:opacity-50",
256
- children: [y("devportal.deprecateSelected", "Deprecate Selected"), Y.length > 0 ? ` (${Y.length})` : ""]
271
+ children: [v("devportal.deprecateSelected", "Deprecate Selected"), X.length > 0 ? ` (${X.length})` : ""]
257
272
  })
258
273
  ]
259
274
  })]
260
275
  })
261
276
  }),
262
- K.length > 0 ? /* @__PURE__ */ g(ie, {
263
- data: K,
277
+ q.length > 0 ? /* @__PURE__ */ g(ie, {
278
+ data: q,
264
279
  keyField: "id",
265
280
  columns: [
266
281
  {
267
282
  key: "select",
268
283
  header: /* @__PURE__ */ g(a, {
269
- checked: X,
270
- indeterminate: Z,
271
- onChange: Q,
284
+ checked: Z,
285
+ indeterminate: Q,
286
+ onChange: Re,
272
287
  ariaLabel: "Select all visible versions"
273
288
  }),
274
289
  className: "w-12",
275
290
  render: (e) => /* @__PURE__ */ g("div", {
276
291
  onClick: (e) => e.stopPropagation(),
277
292
  children: /* @__PURE__ */ g(a, {
278
- checked: I.has(e.id),
279
- onChange: (t) => Me(e.id, t),
293
+ checked: R.has(e.id),
294
+ onChange: (t) => Le(e.id, t),
280
295
  ariaLabel: `Select version ${e.version}`
281
296
  })
282
297
  })
283
298
  },
284
299
  {
285
300
  key: "version",
286
- header: y("devportal.version", "Version"),
301
+ header: v("devportal.version", "Version"),
287
302
  render: (e) => /* @__PURE__ */ _("div", {
288
303
  className: "flex items-center gap-2",
289
304
  children: [
290
- je(e),
305
+ Ie(e),
291
306
  /* @__PURE__ */ g("span", {
292
307
  className: "font-mono font-medium",
293
308
  children: e.version
294
309
  }),
295
310
  e.isLatest && /* @__PURE__ */ g("span", {
296
311
  className: "rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text",
297
- children: y("devportal.latest", "Latest")
312
+ children: v("devportal.latest", "Latest")
298
313
  }),
299
314
  !e.isStable && /* @__PURE__ */ g("span", {
300
315
  className: "rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs text-status-warning-text",
301
- children: y("devportal.beta", "Beta")
316
+ children: v("devportal.beta", "Beta")
302
317
  })
303
318
  ]
304
319
  })
305
320
  },
306
321
  {
307
322
  key: "releaseNotes",
308
- header: y("devportal.releaseNotes", "Release Notes"),
323
+ header: v("devportal.releaseNotes", "Release Notes"),
309
324
  render: (e) => /* @__PURE__ */ g("p", {
310
325
  className: "max-w-md truncate text-sm text-text-secondary",
311
- children: e.releaseNotes || y("devportal.noReleaseNotes", "No release notes")
326
+ children: e.releaseNotes || v("devportal.noReleaseNotes", "No release notes")
312
327
  })
313
328
  },
314
329
  {
315
330
  key: "status",
316
- header: y("devportal.status", "Status"),
331
+ header: v("devportal.status", "Status"),
317
332
  render: (e) => /* @__PURE__ */ g(re, { status: e.status })
318
333
  },
319
334
  {
320
335
  key: "publishedAt",
321
- header: y("devportal.published", "Published"),
336
+ header: v("devportal.published", "Published"),
322
337
  render: (e) => e.publishedAt ? ce(new Date(e.publishedAt), "MMM d, yyyy") : "-"
323
338
  },
324
339
  {
@@ -329,51 +344,51 @@ var v = () => {
329
344
  className: "flex gap-2",
330
345
  children: [e.status?.toUpperCase() === "DRAFT" && /* @__PURE__ */ g("button", {
331
346
  className: "text-xs text-primary hover:underline disabled:opacity-50",
332
- disabled: !x,
333
- "aria-disabled": !x,
334
- onClick: () => ke(e.id),
335
- children: y("devportal.publish", "Publish")
347
+ disabled: !b,
348
+ "aria-disabled": !b,
349
+ onClick: () => Pe(e.id),
350
+ children: v("devportal.publish", "Publish")
336
351
  }), e.status?.toUpperCase() === "PUBLISHED" && !e.isLatest && /* @__PURE__ */ g("button", {
337
352
  className: "text-xs text-status-warning-text hover:underline disabled:opacity-50",
338
- disabled: !S,
339
- "aria-disabled": !S,
340
- onClick: () => Ae(e.id),
341
- children: y("devportal.deprecate", "Deprecate")
353
+ disabled: !x,
354
+ "aria-disabled": !x,
355
+ onClick: () => Fe(e.id),
356
+ children: v("devportal.deprecate", "Deprecate")
342
357
  })]
343
358
  })
344
359
  }
345
360
  ]
346
361
  }) : /* @__PURE__ */ g(t, {
347
362
  illustration: "empty-data",
348
- title: y("devportal.noVersionsYet", "No versions yet"),
349
- description: y("devportal.noVersionsYetDescription", "Create your first version to start distributing your app"),
363
+ title: v("devportal.noVersionsYet", "No versions yet"),
364
+ description: v("devportal.noVersionsYetDescription", "Create your first version to start distributing your app"),
350
365
  action: /* @__PURE__ */ _("button", {
351
- onClick: () => k(!0),
366
+ onClick: () => j(!0),
352
367
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
353
- children: [/* @__PURE__ */ g(m, { size: 16 }), y("devportal.createVersion", "Create Version")]
368
+ children: [/* @__PURE__ */ g(he, { size: 16 }), v("devportal.createVersion", "Create Version")]
354
369
  })
355
370
  }),
356
- O && /* @__PURE__ */ g(o, {
357
- open: O,
358
- onOpenChange: k,
359
- onConfirm: De,
360
- title: y("devportal.createNewVersion", "Create New Version"),
361
- confirmLabel: Ee ? y("devportal.creating", "Creating...") : y("devportal.createVersion", "Create Version"),
371
+ A && /* @__PURE__ */ g(o, {
372
+ open: A,
373
+ onOpenChange: j,
374
+ onConfirm: Me,
375
+ title: v("devportal.createNewVersion", "Create New Version"),
376
+ confirmLabel: ke ? v("devportal.creating", "Creating...") : v("devportal.createVersion", "Create Version"),
362
377
  children: /* @__PURE__ */ _("div", {
363
378
  className: "space-y-4",
364
379
  children: [
365
380
  /* @__PURE__ */ g(ae, {
366
- label: y("devportal.versionNumber", "Version Number"),
367
- value: A.version,
368
- onChange: (e) => j({
369
- ...A,
381
+ label: v("devportal.versionNumber", "Version Number"),
382
+ value: M.version,
383
+ onChange: (e) => N({
384
+ ...M,
370
385
  version: e.target.value
371
386
  }),
372
387
  placeholder: "e.g., 2.2.0",
373
- hint: y("devportal.versionHint", "Use semantic versioning (major.minor.patch)"),
388
+ hint: v("devportal.versionHint", "Use semantic versioning (major.minor.patch)"),
374
389
  required: !0
375
390
  }),
376
- V && /* @__PURE__ */ _("div", {
391
+ U && /* @__PURE__ */ _("div", {
377
392
  className: "space-y-1",
378
393
  children: [
379
394
  /* @__PURE__ */ _("label", {
@@ -391,9 +406,9 @@ var v = () => {
391
406
  rows: 10,
392
407
  required: !0,
393
408
  placeholder: "{\n \"nodes\": [],\n \"edges\": []\n}",
394
- value: A.manifestJson,
395
- onChange: (e) => j({
396
- ...A,
409
+ value: M.manifestJson,
410
+ onChange: (e) => N({
411
+ ...M,
397
412
  manifestJson: e.target.value
398
413
  }),
399
414
  className: "w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]"
@@ -408,123 +423,201 @@ var v = () => {
408
423
  })
409
424
  ]
410
425
  }),
411
- !V && /* @__PURE__ */ _("div", {
426
+ W && /* @__PURE__ */ _("div", {
412
427
  className: "space-y-1",
413
428
  children: [
414
- /* @__PURE__ */ g("label", {
429
+ /* @__PURE__ */ _("label", {
415
430
  className: "text-sm font-medium",
416
- children: "Package (.zip)"
431
+ children: [
432
+ "Package (.zip)",
433
+ " ",
434
+ /* @__PURE__ */ g("span", {
435
+ className: "text-status-error-text",
436
+ children: "*"
437
+ })
438
+ ]
417
439
  }),
418
440
  /* @__PURE__ */ _("div", {
419
441
  className: "flex gap-2 items-center",
420
442
  children: [
421
443
  /* @__PURE__ */ g("input", {
422
- ref: D,
444
+ ref: E,
423
445
  type: "file",
424
446
  accept: ".zip",
425
447
  className: "hidden",
426
- onChange: Oe
448
+ onChange: Ne
427
449
  }),
428
450
  /* @__PURE__ */ g("button", {
429
451
  type: "button",
430
- disabled: T,
431
- onClick: () => D.current?.click(),
452
+ disabled: w,
453
+ onClick: () => E.current?.click(),
432
454
  className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50",
433
- children: T ? /* @__PURE__ */ _(h, { children: [
434
- /* @__PURE__ */ g(p, {
455
+ children: w ? /* @__PURE__ */ _(ve, { children: [
456
+ /* @__PURE__ */ g(h, {
435
457
  size: 14,
436
458
  className: "animate-spin"
437
459
  }),
438
460
  " ",
439
461
  "Uploading… ",
440
- Ce,
462
+ we,
441
463
  "%"
442
- ] }) : /* @__PURE__ */ _(h, { children: [
443
- /* @__PURE__ */ g(_e, { size: 14 }),
464
+ ] }) : /* @__PURE__ */ _(ve, { children: [
465
+ /* @__PURE__ */ g(ge, { size: 14 }),
444
466
  " ",
445
- A.packageUrl ? "Replace zip" : "Upload zip"
467
+ M.packageUrl ? "Replace zip" : "Upload zip"
446
468
  ] })
447
469
  }),
448
- A.packageUrl && !T && /* @__PURE__ */ g("span", {
470
+ M.packageUrl && !w && /* @__PURE__ */ g("span", {
449
471
  className: "text-xs text-status-success-text",
450
472
  children: "✓ Uploaded"
451
473
  })
452
474
  ]
453
475
  }),
454
- E && /* @__PURE__ */ g("p", {
476
+ T && /* @__PURE__ */ g("p", {
455
477
  className: "text-xs text-status-error-text",
456
- children: E
478
+ children: T
479
+ }),
480
+ /* @__PURE__ */ g("p", {
481
+ className: "text-xs text-text-tertiary",
482
+ children: "The zip is the node executable. Upload it before publishing — users install exactly this artifact."
483
+ })
484
+ ]
485
+ }),
486
+ W && /* @__PURE__ */ _("div", {
487
+ className: "space-y-2",
488
+ children: [
489
+ /* @__PURE__ */ _("div", {
490
+ className: "flex items-center justify-between gap-2 flex-wrap",
491
+ children: [/* @__PURE__ */ _("label", {
492
+ className: "text-sm font-medium",
493
+ children: [
494
+ "manifest.json",
495
+ " ",
496
+ /* @__PURE__ */ g("span", {
497
+ className: "text-xs font-normal text-text-secondary",
498
+ children: "(optional)"
499
+ })
500
+ ]
501
+ }), /* @__PURE__ */ _("div", {
502
+ className: "flex items-center gap-2",
503
+ children: [
504
+ O && /* @__PURE__ */ _("span", {
505
+ className: "text-xs text-status-success-text",
506
+ children: ["✓ ", O]
507
+ }),
508
+ /* @__PURE__ */ g("input", {
509
+ ref: D,
510
+ type: "file",
511
+ accept: ".json,application/json",
512
+ className: "hidden",
513
+ onChange: Te
514
+ }),
515
+ /* @__PURE__ */ _("button", {
516
+ type: "button",
517
+ onClick: () => D.current?.click(),
518
+ className: "inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors",
519
+ children: [/* @__PURE__ */ g(ge, { size: 12 }), "Upload manifest.json"]
520
+ })
521
+ ]
522
+ })]
523
+ }),
524
+ /* @__PURE__ */ g("textarea", {
525
+ rows: 5,
526
+ placeholder: "{\n \"manifestVersion\": \"1.0\",\n \"itemType\": \"node\",\n \"identity\": { \"version\": \"1.0.0\", \"displayName\": \"My Node\" }\n}",
527
+ value: M.manifestJson,
528
+ onChange: (e) => {
529
+ k(null), N({
530
+ ...M,
531
+ manifestJson: e.target.value
532
+ });
533
+ },
534
+ className: "w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]"
535
+ }),
536
+ /* @__PURE__ */ _("p", {
537
+ className: "text-xs text-text-tertiary",
538
+ children: [
539
+ "Upload or paste your ",
540
+ /* @__PURE__ */ g("code", { children: "manifest.json" }),
541
+ " — update it whenever inputs, outputs, or operations change. The platform does not extract it from the zip automatically."
542
+ ]
457
543
  })
458
544
  ]
459
545
  }),
460
- !V && /* @__PURE__ */ _("div", {
546
+ G && /* @__PURE__ */ _("div", {
461
547
  className: "space-y-1",
462
- children: [/* @__PURE__ */ _("label", {
463
- className: "text-sm font-medium",
464
- children: [
465
- "manifest.json",
466
- " ",
467
- /* @__PURE__ */ g("span", {
468
- className: "text-xs font-normal text-text-secondary",
469
- children: "(optional — paste if not bundled inside the zip)"
470
- })
471
- ]
472
- }), /* @__PURE__ */ g("textarea", {
473
- rows: 5,
474
- placeholder: "{\n \"manifestVersion\": \"1.0\",\n \"itemType\": \"node\",\n \"identity\": { \"version\": \"1.0.0\", \"displayName\": \"My Node\" }\n}",
475
- value: A.manifestJson,
476
- onChange: (e) => j({
477
- ...A,
478
- manifestJson: e.target.value
548
+ children: [
549
+ /* @__PURE__ */ _("label", {
550
+ className: "text-sm font-medium",
551
+ children: [
552
+ "Required scopes",
553
+ " ",
554
+ /* @__PURE__ */ g("span", {
555
+ className: "text-xs font-normal text-text-secondary",
556
+ children: "(optional)"
557
+ })
558
+ ]
479
559
  }),
480
- className: "w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]"
481
- })]
560
+ /* @__PURE__ */ g("input", {
561
+ type: "text",
562
+ value: M.requiredScopes,
563
+ onChange: (e) => N({
564
+ ...M,
565
+ requiredScopes: e.target.value
566
+ }),
567
+ placeholder: "e.g. read:contacts, write:messages",
568
+ className: "w-full rounded-md border bg-transparent px-3 py-2 text-sm placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]"
569
+ }),
570
+ /* @__PURE__ */ g("p", {
571
+ className: "text-xs text-text-tertiary",
572
+ children: "Comma-separated. List every permission this version needs — users will be prompted to accept any new or changed scopes on update."
573
+ })
574
+ ]
482
575
  }),
483
576
  /* @__PURE__ */ g(oe, {
484
- label: y("devportal.releaseNotes", "Release Notes"),
485
- value: A.releaseNotes,
486
- onChange: (e) => j({
487
- ...A,
577
+ label: v("devportal.releaseNotes", "Release Notes"),
578
+ value: M.releaseNotes,
579
+ onChange: (e) => N({
580
+ ...M,
488
581
  releaseNotes: e.target.value
489
582
  }),
490
- placeholder: y("devportal.releaseNotesPlaceholder", "What changed in this release?"),
583
+ placeholder: v("devportal.releaseNotesPlaceholder", "What changed in this release?"),
491
584
  rows: 2
492
585
  })
493
586
  ]
494
587
  })
495
588
  }),
496
589
  /* @__PURE__ */ g(o, {
497
- open: R === "publish",
590
+ open: B === "publish",
498
591
  onOpenChange: (e) => {
499
- e || z(null);
592
+ e || V(null);
500
593
  },
501
594
  onConfirm: async () => {
502
- if (J.length === 0) return;
503
- N(null);
504
- let e = await Promise.allSettled(J.map((e) => W({ variables: { id: e.id } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
505
- F(`Published ${t} version${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), $(), z(null);
595
+ if (Y.length === 0) return;
596
+ F(null);
597
+ let e = await Promise.allSettled(Y.map((e) => Ae({ variables: { id: e.id } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
598
+ L(`Published ${t} version${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), $(), V(null);
506
599
  },
507
- title: y("devportal.publishSelectedVersions", "Publish selected versions"),
508
- description: `${y("devportal.publish", "Publish")} ${J.length} selected version${J.length === 1 ? "" : "s"}?`,
509
- confirmLabel: y("devportal.publish", "Publish"),
510
- cancelLabel: y("devportal.cancel", "Cancel"),
600
+ title: v("devportal.publishSelectedVersions", "Publish selected versions"),
601
+ description: `${v("devportal.publish", "Publish")} ${Y.length} selected version${Y.length === 1 ? "" : "s"}?`,
602
+ confirmLabel: v("devportal.publish", "Publish"),
603
+ cancelLabel: v("devportal.cancel", "Cancel"),
511
604
  variant: "success"
512
605
  }),
513
606
  /* @__PURE__ */ g(o, {
514
- open: R === "deprecate",
607
+ open: B === "deprecate",
515
608
  onOpenChange: (e) => {
516
- e || z(null);
609
+ e || V(null);
517
610
  },
518
611
  onConfirm: async () => {
519
- if (Y.length === 0) return;
520
- N(null);
521
- let e = await Promise.allSettled(Y.map((e) => G({ variables: { id: e.id } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
522
- F(`Deprecated ${t} version${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), $(), z(null);
612
+ if (X.length === 0) return;
613
+ F(null);
614
+ let e = await Promise.allSettled(X.map((e) => je({ variables: { id: e.id } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
615
+ L(`Deprecated ${t} version${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), $(), V(null);
523
616
  },
524
- title: y("devportal.deprecateSelectedVersions", "Deprecate selected versions"),
525
- description: `${y("devportal.deprecate", "Deprecate")} ${Y.length} selected version${Y.length === 1 ? "" : "s"}? ${y("devportal.deprecateVersionsWarning", "Deprecated versions remain visible but should no longer be promoted.")}`,
526
- confirmLabel: y("devportal.deprecate", "Deprecate"),
527
- cancelLabel: y("devportal.cancel", "Cancel"),
617
+ title: v("devportal.deprecateSelectedVersions", "Deprecate selected versions"),
618
+ description: `${v("devportal.deprecate", "Deprecate")} ${X.length} selected version${X.length === 1 ? "" : "s"}? ${v("devportal.deprecateVersionsWarning", "Deprecated versions remain visible but should no longer be promoted.")}`,
619
+ confirmLabel: v("devportal.deprecate", "Deprecate"),
620
+ cancelLabel: v("devportal.cancel", "Cancel"),
528
621
  variant: "warning"
529
622
  })
530
623
  ]
@@ -532,6 +625,6 @@ var v = () => {
532
625
  });
533
626
  };
534
627
  //#endregion
535
- export { v as ApplicationVersionsPage };
628
+ export { ye as ApplicationVersionsPage };
536
629
 
537
630
  //# sourceMappingURL=ApplicationVersionsPage.js.map