@burdenoff/microfe-devportal 2026.626.1 → 2026.626.2

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.
Files changed (34) hide show
  1. package/dist/devportal/DevportalRoutes.js +38 -34
  2. package/dist/devportal/DevportalRoutes.js.map +1 -1
  3. package/dist/devportal/components/ConfirmDialog.js.map +1 -1
  4. package/dist/devportal/components/DataTable.js.map +1 -1
  5. package/dist/devportal/components/FormField.js.map +1 -1
  6. package/dist/devportal/components/GrantDelegationModal.js +2 -1
  7. package/dist/devportal/components/GrantDelegationModal.js.map +1 -1
  8. package/dist/devportal/components/LoadingState.js.map +1 -1
  9. package/dist/devportal/components/PageLayout.js.map +1 -1
  10. package/dist/devportal/components/SelectionCheckbox.js.map +1 -1
  11. package/dist/devportal/hooks/usePermission.js +2 -2
  12. package/dist/devportal/hooks/usePermission.js.map +1 -1
  13. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  14. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  15. package/dist/devportal/pages/CreateApplicationPage.js +185 -104
  16. package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
  17. package/dist/devportal/pages/CreateWebhookPage.js +6 -5
  18. package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
  19. package/dist/devportal/pages/DashboardPage.js.map +1 -1
  20. package/dist/devportal/pages/OAuthCallbackPage.js +64 -0
  21. package/dist/devportal/pages/OAuthCallbackPage.js.map +1 -0
  22. package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
  23. package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
  24. package/dist/devportal/pages/PublishPage.js +392 -187
  25. package/dist/devportal/pages/PublishPage.js.map +1 -1
  26. package/dist/devportal/pages/ResourcesPage.js.map +1 -1
  27. package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
  28. package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
  29. package/dist/devportal/pages/WebhooksPage.js +1 -1
  30. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  31. package/dist/devportal/types/index.js.map +1 -1
  32. package/dist/generated/global-operations.js +260 -174
  33. package/dist/generated/global-operations.js.map +1 -1
  34. package/package.json +1 -1
@@ -9,10 +9,10 @@ import "../components/index.js";
9
9
  import { DEVPORTAL_PERMISSIONS as d } from "../constants/permissions.js";
10
10
  import { useState as f } from "react";
11
11
  import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
12
- import { ArrowLeft as m, Box as h, Check as g, ChevronRight as _, GitFork as v, Info as y, Loader2 as b, Puzzle as x, Save as ee, X as S } from "lucide-react";
13
- import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
12
+ import { ArrowLeft as ee, Box as m, Check as h, ChevronRight as g, GitFork as _, Info as v, Loader2 as te, Puzzle as y, Save as b, X as x } from "lucide-react";
13
+ import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
14
14
  //#region src/devportal/pages/CreateApplicationPage.tsx
15
- var E = [
15
+ var T = [
16
16
  {
17
17
  id: "auth",
18
18
  label: "Authentication",
@@ -84,16 +84,16 @@ var E = [
84
84
  description: "Access control configuration"
85
85
  }
86
86
  ];
87
- function D() {
88
- return Object.fromEntries(E.map((e) => [e.id, "none"]));
87
+ function E() {
88
+ return Object.fromEntries(T.map((e) => [e.id, "none"]));
89
89
  }
90
- function O(e) {
90
+ function D(e) {
91
91
  return Object.entries(e).filter(([, e]) => e !== "none").map(([e, t]) => ({
92
92
  resource: e,
93
93
  level: t
94
94
  }));
95
95
  }
96
- var k = [
96
+ var O = [
97
97
  {
98
98
  value: "PUBLIC",
99
99
  label: "Public — visible to everyone"
@@ -106,34 +106,63 @@ var k = [
106
106
  value: "UNLISTED",
107
107
  label: "Unlisted — accessible via direct link"
108
108
  }
109
- ], A = ({ icon: e, title: n, description: r, bullets: i, selected: a, onClick: o }) => /* @__PURE__ */ T("button", {
109
+ ], k = [
110
+ {
111
+ value: "ai",
112
+ label: "AI & Automation"
113
+ },
114
+ {
115
+ value: "integration",
116
+ label: "Action in an App"
117
+ },
118
+ {
119
+ value: "data",
120
+ label: "Data & Transform"
121
+ },
122
+ {
123
+ value: "flow",
124
+ label: "Flow & Logic"
125
+ },
126
+ {
127
+ value: "core",
128
+ label: "Core"
129
+ },
130
+ {
131
+ value: "communication",
132
+ label: "Communication"
133
+ },
134
+ {
135
+ value: "trigger",
136
+ label: "Triggers"
137
+ }
138
+ ], A = ({ icon: e, title: n, description: r, bullets: i, selected: a, onClick: o }) => /* @__PURE__ */ w("button", {
110
139
  type: "button",
111
140
  onClick: o,
112
141
  className: t("relative flex flex-col gap-3 rounded-xl border-2 p-6 text-left transition-all hover:border-primary/50 hover:shadow-sm", a ? "border-primary bg-action-primary-bg/5 shadow-sm" : "border-border-subtle bg-bg-surface"),
113
142
  children: [
114
- a && /* @__PURE__ */ w("span", {
143
+ a && /* @__PURE__ */ C("span", {
115
144
  className: "absolute top-4 right-4 flex h-5 w-5 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text",
116
- children: /* @__PURE__ */ w(g, { size: 12 })
145
+ children: /* @__PURE__ */ C(h, { size: 12 })
117
146
  }),
118
- /* @__PURE__ */ w("div", {
147
+ /* @__PURE__ */ C("div", {
119
148
  className: "flex h-10 w-10 items-center justify-center rounded-lg bg-bg-sunken",
120
- children: /* @__PURE__ */ w(e, {
149
+ children: /* @__PURE__ */ C(e, {
121
150
  size: 22,
122
151
  className: "text-text-primary"
123
152
  })
124
153
  }),
125
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
154
+ /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
126
155
  className: "font-semibold text-text-primary",
127
156
  children: n
128
- }), /* @__PURE__ */ w("p", {
157
+ }), /* @__PURE__ */ C("p", {
129
158
  className: "mt-1 text-sm text-text-secondary",
130
159
  children: r
131
160
  })] }),
132
- /* @__PURE__ */ w("ul", {
161
+ /* @__PURE__ */ C("ul", {
133
162
  className: "mt-1 space-y-1",
134
- children: i.map((e) => /* @__PURE__ */ T("li", {
163
+ children: i.map((e) => /* @__PURE__ */ w("li", {
135
164
  className: "flex items-center gap-2 text-xs text-text-secondary",
136
- children: [/* @__PURE__ */ w(_, {
165
+ children: [/* @__PURE__ */ C(g, {
137
166
  size: 12,
138
167
  className: "flex-shrink-0 text-primary"
139
168
  }), e]
@@ -150,35 +179,35 @@ var k = [
150
179
  read: "Read",
151
180
  write: "Read & Write"
152
181
  };
153
- return /* @__PURE__ */ w("div", {
182
+ return /* @__PURE__ */ C("div", {
154
183
  className: "overflow-x-auto rounded-lg border border-border-subtle",
155
- children: /* @__PURE__ */ T("table", {
184
+ children: /* @__PURE__ */ w("table", {
156
185
  className: "w-full text-sm",
157
- children: [/* @__PURE__ */ w("thead", { children: /* @__PURE__ */ T("tr", {
186
+ children: [/* @__PURE__ */ C("thead", { children: /* @__PURE__ */ w("tr", {
158
187
  className: "border-b border-border-subtle bg-bg-sunken/50",
159
- children: [/* @__PURE__ */ w("th", {
188
+ children: [/* @__PURE__ */ C("th", {
160
189
  className: "px-4 py-3 text-left font-medium text-text-secondary w-1/2",
161
190
  children: "Resource"
162
- }), n.map((e) => /* @__PURE__ */ w("th", {
191
+ }), n.map((e) => /* @__PURE__ */ C("th", {
163
192
  className: "px-4 py-3 text-center font-medium text-text-secondary",
164
193
  children: r[e]
165
194
  }, e))]
166
- }) }), /* @__PURE__ */ w("tbody", {
195
+ }) }), /* @__PURE__ */ C("tbody", {
167
196
  className: "divide-y divide-border",
168
- children: E.map((r) => /* @__PURE__ */ T("tr", {
197
+ children: T.map((r) => /* @__PURE__ */ w("tr", {
169
198
  className: "hover:bg-bg-sunken/30 transition-colors",
170
- children: [/* @__PURE__ */ T("td", {
199
+ children: [/* @__PURE__ */ w("td", {
171
200
  className: "px-4 py-3",
172
- children: [/* @__PURE__ */ w("p", {
201
+ children: [/* @__PURE__ */ C("p", {
173
202
  className: "font-medium text-text-primary",
174
203
  children: r.label
175
- }), /* @__PURE__ */ w("p", {
204
+ }), /* @__PURE__ */ C("p", {
176
205
  className: "text-xs text-text-secondary",
177
206
  children: r.description
178
207
  })]
179
- }), n.map((n) => /* @__PURE__ */ w("td", {
208
+ }), n.map((n) => /* @__PURE__ */ C("td", {
180
209
  className: "px-4 py-3 text-center",
181
- children: /* @__PURE__ */ w("input", {
210
+ children: /* @__PURE__ */ C("input", {
182
211
  type: "radio",
183
212
  name: `permission-${r.id}`,
184
213
  value: n,
@@ -192,27 +221,31 @@ var k = [
192
221
  })
193
222
  });
194
223
  }, M = () => {
195
- let { navigate: t, basePath: g, activeOrgId: _ } = e(), { t: E } = p(), M = (e, t) => {
196
- let n = E(e);
224
+ let { navigate: t, basePath: h, activeOrgId: g } = e(), { t: T } = p(), M = (e, t) => {
225
+ let n = T(e);
197
226
  return n === e ? t : n;
198
- }, N = n(), [P, F] = f(null), [I, L] = f(D()), [R, z] = f({
227
+ }, N = n(), [P, F] = f(null), [I, L] = f(E()), [R, z] = f({
199
228
  name: "",
200
229
  slug: "",
201
230
  shortDescription: "",
202
231
  description: "",
232
+ category: "",
203
233
  visibility: "PRIVATE",
204
- developerOrganizationId: _ ?? "",
234
+ developerOrganizationId: g ?? "",
205
235
  websiteUrl: "",
206
236
  githubUrl: "",
207
237
  documentationUrl: "",
208
- supportUrl: ""
238
+ supportUrl: "",
239
+ oauthAuthUrl: "",
240
+ oauthTokenUrl: "",
241
+ oauthRevokeUrl: ""
209
242
  }), [B, V] = f({}), [H, { loading: U }] = r(), { data: W } = i({ fetchPolicy: "cache-and-network" }), G = [{
210
243
  value: "",
211
244
  label: "No organization (personal)"
212
245
  }, ...(W?.myDeveloperOrganizations ?? []).map((e) => ({
213
246
  value: e.id,
214
247
  label: e.name
215
- }))], K = (e) => t?.(`${g}${e}`), q = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), J = (e) => {
248
+ }))], K = (e) => t?.(`${h}${e}`), q = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), J = (e) => {
216
249
  let t = e.target.value;
217
250
  z((e) => ({
218
251
  ...e,
@@ -238,15 +271,16 @@ var k = [
238
271
  }, Z = () => {
239
272
  let e = {};
240
273
  return R.name.trim() ? R.name.length < 3 ? e.name = "Name must be at least 3 characters" : R.name.length > 100 && (e.name = "Name must be less than 100 characters") : e.name = "Name is required", R.slug.trim() ? /^[a-z0-9-]+$/.test(R.slug) || (e.slug = "Slug can only contain lowercase letters, numbers, and hyphens") : e.slug = "Slug is required", R.shortDescription.trim() ? R.shortDescription.length > 200 && (e.shortDescription = "Short description must be less than 200 characters") : e.shortDescription = "Short description is required", V(e), Object.keys(e).length === 0;
241
- }, Q = () => P === "node" ? "NODE" : P === "workflow" ? "WORKFLOW" : "API_INTEGRATION", te = async (e) => {
274
+ }, Q = () => P === "node" ? "NODE" : P === "workflow" ? "WORKFLOW" : "API_INTEGRATION", ne = async (e) => {
242
275
  if (e.preventDefault(), !Z() || !P) return;
243
- let t = P === "app" ? { permissions: O(I) } : null;
276
+ let t = P === "app" ? { permissions: D(I) } : null;
244
277
  try {
245
278
  let e = await H({ variables: { input: {
246
279
  name: R.name,
247
280
  slug: R.slug || void 0,
248
281
  shortDescription: R.shortDescription || void 0,
249
282
  description: R.description || void 0,
283
+ category: R.category || void 0,
250
284
  appType: Q(),
251
285
  visibility: R.visibility,
252
286
  developerOrganizationId: R.developerOrganizationId || void 0,
@@ -254,7 +288,12 @@ var k = [
254
288
  githubUrl: R.githubUrl || void 0,
255
289
  documentationUrl: R.documentationUrl || void 0,
256
290
  supportUrl: R.supportUrl || void 0,
257
- manifest: t ?? void 0
291
+ manifest: t ?? void 0,
292
+ ...P === "app" && {
293
+ oauthAuthUrl: R.oauthAuthUrl || void 0,
294
+ oauthTokenUrl: R.oauthTokenUrl || void 0,
295
+ oauthRevokeUrl: R.oauthRevokeUrl || void 0
296
+ }
258
297
  } } });
259
298
  e.data?.createApplication?.id && (N.emit("devportal.app.created", {
260
299
  appId: e.data.createApplication.id,
@@ -270,21 +309,21 @@ var k = [
270
309
  }));
271
310
  }
272
311
  };
273
- if (!P) return /* @__PURE__ */ w(u, {
312
+ if (!P) return /* @__PURE__ */ C(u, {
274
313
  permission: d.APP_CREATE,
275
- children: /* @__PURE__ */ w(a, {
314
+ children: /* @__PURE__ */ C(a, {
276
315
  title: "What do you want to build?",
277
316
  description: "Choose a builder type to get started",
278
317
  purpose: "Pick the kind of integration you are creating — a standard app, a Node package, or a workflow. Your choice sets up the right defaults (credentials, permissions, and where it can be installed) so you only fill in what that type actually needs.",
279
- backLink: `${g}/apps`,
318
+ backLink: `${h}/apps`,
280
319
  backLabel: "Back to Applications",
281
- children: /* @__PURE__ */ T("div", {
320
+ children: /* @__PURE__ */ w("div", {
282
321
  className: "max-w-3xl space-y-6",
283
- children: [/* @__PURE__ */ T("div", {
322
+ children: [/* @__PURE__ */ w("div", {
284
323
  className: "grid gap-4 sm:grid-cols-3",
285
324
  children: [
286
- /* @__PURE__ */ w(A, {
287
- icon: h,
325
+ /* @__PURE__ */ C(A, {
326
+ icon: m,
288
327
  title: "App",
289
328
  description: "Build integrations that connect your service to the platform using OAuth tokens.",
290
329
  bullets: [
@@ -296,8 +335,8 @@ var k = [
296
335
  selected: P === "app",
297
336
  onClick: () => F("app")
298
337
  }),
299
- /* @__PURE__ */ w(A, {
300
- icon: x,
338
+ /* @__PURE__ */ C(A, {
339
+ icon: y,
301
340
  title: "Node",
302
341
  description: "Build custom FluidGrids nodes that users can drag into their visual workflows.",
303
342
  bullets: [
@@ -309,8 +348,8 @@ var k = [
309
348
  selected: P === "node",
310
349
  onClick: () => F("node")
311
350
  }),
312
- /* @__PURE__ */ w(A, {
313
- icon: v,
351
+ /* @__PURE__ */ C(A, {
352
+ icon: _,
314
353
  title: "Workflow",
315
354
  description: "Build reusable automation workflows that users can import and customize.",
316
355
  bullets: [
@@ -323,48 +362,48 @@ var k = [
323
362
  onClick: () => F("workflow")
324
363
  })
325
364
  ]
326
- }), /* @__PURE__ */ T("div", {
365
+ }), /* @__PURE__ */ w("div", {
327
366
  className: "rounded-lg border border-border-subtle bg-bg-sunken/30 p-4 flex gap-3 text-sm text-text-secondary",
328
- children: [/* @__PURE__ */ w(y, {
367
+ children: [/* @__PURE__ */ C(v, {
329
368
  size: 16,
330
369
  className: "flex-shrink-0 mt-0.5"
331
- }), /* @__PURE__ */ w("p", { children: "Apps use OAuth to interact with platform data. Nodes and Workflows are packaged files you upload after creation." })]
370
+ }), /* @__PURE__ */ C("p", { children: "Apps use OAuth to interact with platform data. Nodes and Workflows are packaged files you upload after creation." })]
332
371
  })]
333
372
  })
334
373
  })
335
374
  });
336
- let $ = P === "app" ? "App" : P === "node" ? "Node" : "Workflow", ne = w(P === "app" ? h : P === "node" ? x : v, { size: 16 });
337
- return /* @__PURE__ */ w(u, {
375
+ let $ = P === "app" ? "App" : P === "node" ? "Node" : "Workflow", re = C(P === "app" ? m : P === "node" ? y : _, { size: 16 });
376
+ return /* @__PURE__ */ C(u, {
338
377
  permission: d.APP_CREATE,
339
- children: /* @__PURE__ */ w(a, {
378
+ children: /* @__PURE__ */ C(a, {
340
379
  title: `Create ${$}`,
341
380
  description: P === "app" ? "Register a new app integration with OAuth permissions" : P === "node" ? "Register a new FluidGrids node package" : "Register a new reusable automation workflow",
342
381
  purpose: "Give your integration a name, description, and the permissions it will request. Once created you will get credentials and can configure webhooks, then publish it to the marketplace when it is ready for users.",
343
- backLink: `${g}/apps`,
382
+ backLink: `${h}/apps`,
344
383
  backLabel: "Back to Applications",
345
- children: /* @__PURE__ */ T("form", {
346
- onSubmit: te,
384
+ children: /* @__PURE__ */ w("form", {
385
+ onSubmit: ne,
347
386
  className: "space-y-8 max-w-3xl",
348
387
  children: [
349
- /* @__PURE__ */ T("div", {
388
+ /* @__PURE__ */ w("div", {
350
389
  className: "flex items-center gap-3",
351
- children: [/* @__PURE__ */ T("button", {
390
+ children: [/* @__PURE__ */ w("button", {
352
391
  type: "button",
353
392
  onClick: () => F(null),
354
393
  className: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors",
355
- children: [/* @__PURE__ */ w(m, { size: 14 }), "Change type"]
356
- }), /* @__PURE__ */ T("span", {
394
+ children: [/* @__PURE__ */ C(ee, { size: 14 }), "Change type"]
395
+ }), /* @__PURE__ */ w("span", {
357
396
  className: "flex items-center gap-1.5 rounded-full border border-border-subtle bg-bg-sunken px-3 py-1 text-xs font-medium",
358
- children: [ne, $]
397
+ children: [re, $]
359
398
  })]
360
399
  }),
361
- /* @__PURE__ */ w(o, {
400
+ /* @__PURE__ */ C(o, {
362
401
  title: "Basic Information",
363
402
  description: "Core details about your application",
364
- children: /* @__PURE__ */ T("div", {
403
+ children: /* @__PURE__ */ w("div", {
365
404
  className: "space-y-4",
366
405
  children: [
367
- /* @__PURE__ */ w(s, {
406
+ /* @__PURE__ */ C(s, {
368
407
  label: "Name",
369
408
  value: R.name,
370
409
  onChange: J,
@@ -372,7 +411,7 @@ var k = [
372
411
  required: !0,
373
412
  error: B.name
374
413
  }),
375
- /* @__PURE__ */ w(s, {
414
+ /* @__PURE__ */ C(s, {
376
415
  label: "Slug",
377
416
  value: R.slug,
378
417
  onChange: (e) => Y("slug", e.target.value.toLowerCase()),
@@ -381,7 +420,7 @@ var k = [
381
420
  error: B.slug,
382
421
  hint: "URL-friendly identifier (auto-generated from name)"
383
422
  }),
384
- /* @__PURE__ */ w(l, {
423
+ /* @__PURE__ */ C(l, {
385
424
  label: "Short Description",
386
425
  value: R.shortDescription,
387
426
  onChange: (e) => Y("shortDescription", e.target.value),
@@ -391,7 +430,7 @@ var k = [
391
430
  hint: `${R.shortDescription.length}/200 characters`,
392
431
  rows: 2
393
432
  }),
394
- /* @__PURE__ */ w(l, {
433
+ /* @__PURE__ */ C(l, {
395
434
  label: "Full Description",
396
435
  value: R.description,
397
436
  onChange: (e) => Y("description", e.target.value),
@@ -402,52 +441,61 @@ var k = [
402
441
  ]
403
442
  })
404
443
  }),
405
- /* @__PURE__ */ w(o, {
444
+ /* @__PURE__ */ C(o, {
406
445
  title: "Publish Settings",
407
446
  description: "Control who can see this and which organization it belongs to",
408
- children: /* @__PURE__ */ T("div", {
447
+ children: /* @__PURE__ */ w("div", {
409
448
  className: "grid gap-4 sm:grid-cols-2",
410
- children: [/* @__PURE__ */ w(c, {
411
- label: "Visibility",
412
- value: R.visibility,
413
- onChange: (e) => Y("visibility", e.target.value),
414
- options: k
415
- }), /* @__PURE__ */ w(c, {
416
- label: "Developer Organization",
417
- value: R.developerOrganizationId,
418
- onChange: (e) => Y("developerOrganizationId", e.target.value),
419
- options: G
420
- })]
449
+ children: [
450
+ /* @__PURE__ */ C(c, {
451
+ label: "Category",
452
+ value: R.category,
453
+ onChange: (e) => Y("category", e.target.value),
454
+ options: k
455
+ }),
456
+ /* @__PURE__ */ C(c, {
457
+ label: "Visibility",
458
+ value: R.visibility,
459
+ onChange: (e) => Y("visibility", e.target.value),
460
+ options: O
461
+ }),
462
+ /* @__PURE__ */ C(c, {
463
+ label: "Developer Organization",
464
+ value: R.developerOrganizationId,
465
+ onChange: (e) => Y("developerOrganizationId", e.target.value),
466
+ options: G
467
+ })
468
+ ]
421
469
  })
422
470
  }),
423
- /* @__PURE__ */ w(o, {
471
+ /* @__PURE__ */ C(o, {
424
472
  title: "Links",
425
473
  description: "External resources",
426
- children: /* @__PURE__ */ T("div", {
474
+ children: /* @__PURE__ */ w("div", {
427
475
  className: "grid gap-4 sm:grid-cols-2",
428
476
  children: [
429
- /* @__PURE__ */ w(s, {
477
+ /* @__PURE__ */ C(s, {
430
478
  label: "Website URL",
431
479
  type: "url",
432
480
  value: R.websiteUrl,
433
481
  onChange: (e) => Y("websiteUrl", e.target.value),
434
482
  placeholder: "https://example.com"
435
483
  }),
436
- /* @__PURE__ */ w(s, {
484
+ /* @__PURE__ */ C(s, {
437
485
  label: "GitHub URL",
438
486
  type: "url",
439
487
  value: R.githubUrl,
440
488
  onChange: (e) => Y("githubUrl", e.target.value),
441
489
  placeholder: "https://github.com/org/repo"
442
490
  }),
443
- /* @__PURE__ */ w(s, {
491
+ /* @__PURE__ */ C(s, {
444
492
  label: "Documentation URL",
445
493
  type: "url",
446
494
  value: R.documentationUrl,
447
495
  onChange: (e) => Y("documentationUrl", e.target.value),
448
496
  placeholder: "https://docs.example.com"
449
497
  }),
450
- /* @__PURE__ */ w(s, {
498
+ /* @__PURE__ */ C(s, {
451
499
  label: "Support URL",
452
500
  type: "url",
453
501
  value: R.supportUrl,
@@ -457,50 +505,83 @@ var k = [
457
505
  ]
458
506
  })
459
507
  }),
460
- P === "app" && /* @__PURE__ */ T(o, {
508
+ P === "app" && /* @__PURE__ */ w(o, {
461
509
  title: "Permissions",
462
510
  description: "Choose what data your app can access. Users will see these permissions when authorizing your app — like GitHub Apps.",
463
- children: [/* @__PURE__ */ w(j, {
511
+ children: [/* @__PURE__ */ C(j, {
464
512
  permissions: I,
465
513
  onChange: X
466
- }), /* @__PURE__ */ T("div", {
514
+ }), /* @__PURE__ */ w("div", {
467
515
  className: "mt-3 flex gap-2 rounded-lg border border-border-subtle bg-bg-sunken/30 p-3 text-xs text-text-secondary",
468
- children: [/* @__PURE__ */ w(y, {
516
+ children: [/* @__PURE__ */ C(v, {
469
517
  size: 14,
470
518
  className: "flex-shrink-0 mt-0.5"
471
- }), /* @__PURE__ */ T("span", { children: [/* @__PURE__ */ w("strong", { children: "Read & Write" }), " implies Read. Select only what your app genuinely needs — fewer permissions build more user trust."] })]
519
+ }), /* @__PURE__ */ w("span", { children: [/* @__PURE__ */ C("strong", { children: "Read & Write" }), " implies Read. Select only what your app genuinely needs — fewer permissions build more user trust."] })]
472
520
  })]
473
521
  }),
474
- P !== "app" && /* @__PURE__ */ T("div", {
522
+ P === "app" && /* @__PURE__ */ C(o, {
523
+ title: "OAuth Endpoints",
524
+ description: "Configure the OAuth 2.0 endpoints your app uses to authenticate workspaces. Workspaces will be redirected through these URLs during installation.",
525
+ children: /* @__PURE__ */ w("div", {
526
+ className: "space-y-4",
527
+ children: [
528
+ /* @__PURE__ */ C(s, {
529
+ label: "Authorization URL",
530
+ type: "url",
531
+ value: R.oauthAuthUrl,
532
+ onChange: (e) => Y("oauthAuthUrl", e.target.value),
533
+ placeholder: "https://yourapp.com/oauth/authorize",
534
+ hint: "Where users are redirected to grant access"
535
+ }),
536
+ /* @__PURE__ */ C(s, {
537
+ label: "Token URL",
538
+ type: "url",
539
+ value: R.oauthTokenUrl,
540
+ onChange: (e) => Y("oauthTokenUrl", e.target.value),
541
+ placeholder: "https://yourapp.com/oauth/token",
542
+ hint: "Endpoint to exchange auth code for access token"
543
+ }),
544
+ /* @__PURE__ */ C(s, {
545
+ label: "Revoke URL",
546
+ type: "url",
547
+ value: R.oauthRevokeUrl,
548
+ onChange: (e) => Y("oauthRevokeUrl", e.target.value),
549
+ placeholder: "https://yourapp.com/oauth/revoke",
550
+ hint: "Endpoint to revoke tokens when app is uninstalled"
551
+ })
552
+ ]
553
+ })
554
+ }),
555
+ P !== "app" && /* @__PURE__ */ w("div", {
475
556
  className: "rounded-lg border border-border-subtle bg-bg-sunken/30 p-4 flex gap-3 text-sm text-text-secondary",
476
- children: [/* @__PURE__ */ w(y, {
557
+ children: [/* @__PURE__ */ C(v, {
477
558
  size: 16,
478
559
  className: "flex-shrink-0 mt-0.5"
479
- }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
560
+ }), /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
480
561
  className: "font-medium text-text-primary",
481
562
  children: "File uploads"
482
- }), /* @__PURE__ */ w("p", {
563
+ }), /* @__PURE__ */ C("p", {
483
564
  className: "mt-1",
484
565
  children: P === "node" ? "After creating your Node, go to the Versions tab to upload your ZIP bundle and manifest.json." : "After creating your Workflow, go to the Versions tab to upload your manifest and workflow JSON definition."
485
566
  })] })]
486
567
  }),
487
- /* @__PURE__ */ T("div", {
568
+ /* @__PURE__ */ w("div", {
488
569
  className: "flex items-center justify-end gap-3 border-t pt-6",
489
- children: [/* @__PURE__ */ T("button", {
570
+ children: [/* @__PURE__ */ w("button", {
490
571
  type: "button",
491
572
  onClick: () => K("/apps"),
492
573
  disabled: U,
493
574
  className: "inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50",
494
- children: [/* @__PURE__ */ w(S, { size: 16 }), M("devportal.cancel", "Cancel")]
495
- }), /* @__PURE__ */ w("button", {
575
+ children: [/* @__PURE__ */ C(x, { size: 16 }), M("devportal.cancel", "Cancel")]
576
+ }), /* @__PURE__ */ C("button", {
496
577
  type: "submit",
497
578
  disabled: U,
498
579
  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 transition-colors disabled:opacity-50",
499
- children: U ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(b, {
580
+ children: U ? /* @__PURE__ */ w(S, { children: [/* @__PURE__ */ C(te, {
500
581
  size: 16,
501
582
  className: "animate-spin"
502
- }), "Creating…"] }) : /* @__PURE__ */ T(C, { children: [
503
- /* @__PURE__ */ w(ee, { size: 16 }),
583
+ }), "Creating…"] }) : /* @__PURE__ */ w(S, { children: [
584
+ /* @__PURE__ */ C(b, { size: 16 }),
504
585
  "Create ",
505
586
  $
506
587
  ] })