@leverege/imaginarium-ui 1.2.2 → 1.3.0

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 (110) hide show
  1. package/lib/ImaginariumApp-D7jCl_VH.js +514 -0
  2. package/lib/ImaginariumApp-D7jCl_VH.js.map +1 -0
  3. package/lib/ImaginariumApp-DeLr4nad.cjs +2 -0
  4. package/lib/ImaginariumApp-DeLr4nad.cjs.map +1 -0
  5. package/lib/MarkdownPageDoc-BZF02iL5.cjs +2 -0
  6. package/lib/MarkdownPageDoc-BZF02iL5.cjs.map +1 -0
  7. package/lib/MarkdownPageDoc-DR1FmNpF.js +157 -0
  8. package/lib/MarkdownPageDoc-DR1FmNpF.js.map +1 -0
  9. package/lib/{PluginSetup-NL8jYfpN.js → PluginSetup-CTRJO5hU.js} +164 -118
  10. package/lib/PluginSetup-CTRJO5hU.js.map +1 -0
  11. package/lib/PluginSetup-CuLezaDw.cjs +45 -0
  12. package/lib/PluginSetup-CuLezaDw.cjs.map +1 -0
  13. package/lib/{PluginSetup-Co-WnS3V.js → PluginSetup-DNKri9P1.js} +2 -2
  14. package/lib/{PluginSetup-Co-WnS3V.js.map → PluginSetup-DNKri9P1.js.map} +1 -1
  15. package/lib/{PluginSetup-BQk4FFh9.js → PluginSetup-DaNNHmql.js} +782 -671
  16. package/lib/PluginSetup-DaNNHmql.js.map +1 -0
  17. package/lib/{PluginSetup-CQPpS_Js.cjs → PluginSetup-De9E1hRC.cjs} +2 -2
  18. package/lib/{PluginSetup-CQPpS_Js.cjs.map → PluginSetup-De9E1hRC.cjs.map} +1 -1
  19. package/lib/PluginSetup-o9elzgOQ.cjs +112 -0
  20. package/lib/PluginSetup-o9elzgOQ.cjs.map +1 -0
  21. package/lib/PluginTypes-BmYA5_B9.cjs +2 -0
  22. package/lib/PluginTypes-BmYA5_B9.cjs.map +1 -0
  23. package/lib/PluginTypes-mZ4TjxPV.js +9 -0
  24. package/lib/PluginTypes-mZ4TjxPV.js.map +1 -0
  25. package/lib/docs/DocsPanel.d.ts +15 -0
  26. package/lib/docs/DocsPanel.d.ts.map +1 -0
  27. package/lib/docs/MarkdownPageDoc.d.ts +8 -0
  28. package/lib/docs/MarkdownPageDoc.d.ts.map +1 -0
  29. package/lib/docs/PageDoc.d.ts +9 -0
  30. package/lib/docs/PageDoc.d.ts.map +1 -0
  31. package/lib/docs/PageDocsContext.d.ts +12 -0
  32. package/lib/docs/PageDocsContext.d.ts.map +1 -0
  33. package/lib/docs/index.d.ts +5 -0
  34. package/lib/docs/index.d.ts.map +1 -0
  35. package/lib/docs/mdComponents.d.ts +21 -0
  36. package/lib/docs/mdComponents.d.ts.map +1 -0
  37. package/lib/imp/release/ImpPageDoc.d.ts +3 -0
  38. package/lib/imp/release/ImpPageDoc.d.ts.map +1 -0
  39. package/lib/imp/release/PluginSetup.d.ts.map +1 -1
  40. package/lib/index.cjs +1 -1
  41. package/lib/index.cjs.map +1 -1
  42. package/lib/index.d.ts +4 -1
  43. package/lib/index.d.ts.map +1 -1
  44. package/lib/index.js +75 -72
  45. package/lib/mdComponents-BiOJ7Epf.cjs +16 -0
  46. package/lib/mdComponents-BiOJ7Epf.cjs.map +1 -0
  47. package/lib/mdComponents-kPa8Rxqz.js +6792 -0
  48. package/lib/mdComponents-kPa8Rxqz.js.map +1 -0
  49. package/lib/plugins/PluginTypes.d.ts +1 -0
  50. package/lib/plugins/PluginTypes.d.ts.map +1 -1
  51. package/lib/plugins/registry.d.ts +3 -1
  52. package/lib/plugins/registry.d.ts.map +1 -1
  53. package/lib/plugins/types.d.ts +5 -0
  54. package/lib/plugins/types.d.ts.map +1 -1
  55. package/lib/plugins.cjs +1 -1
  56. package/lib/plugins.js +2 -2
  57. package/lib/registry-Bq42i86Q.cjs +2 -0
  58. package/lib/registry-Bq42i86Q.cjs.map +1 -0
  59. package/lib/registry-CMZCG8pH.js +44 -0
  60. package/lib/registry-CMZCG8pH.js.map +1 -0
  61. package/lib/release.cjs +1 -1
  62. package/lib/release.js +1 -1
  63. package/lib/secret.cjs +1 -1
  64. package/lib/secret.js +1 -1
  65. package/lib/shell/Shell.d.ts.map +1 -1
  66. package/lib/shell.cjs +1 -1
  67. package/lib/shell.js +1 -1
  68. package/lib/system/PluginSetup.d.ts.map +1 -1
  69. package/lib/system/SystemPageDoc.d.ts +3 -0
  70. package/lib/system/SystemPageDoc.d.ts.map +1 -0
  71. package/lib/system.cjs +1 -1
  72. package/lib/system.js +2 -2
  73. package/package.json +3 -2
  74. package/src/docs/DocsPanel.tsx +80 -0
  75. package/src/docs/MarkdownPageDoc.tsx +35 -0
  76. package/src/docs/PageDoc.ts +12 -0
  77. package/src/docs/PageDocsContext.tsx +37 -0
  78. package/src/docs/index.ts +4 -0
  79. package/src/docs/mdComponents.tsx +75 -0
  80. package/src/imp/release/ImpPageDoc.ts +113 -0
  81. package/src/imp/release/PluginSetup.ts +3 -0
  82. package/src/index.ts +4 -0
  83. package/src/plugins/PluginTypes.ts +1 -0
  84. package/src/plugins/registry.ts +13 -2
  85. package/src/plugins/types.ts +6 -0
  86. package/src/shell/Shell.tsx +48 -14
  87. package/src/system/PluginSetup.ts +4 -0
  88. package/src/system/SystemPageDoc.ts +49 -0
  89. package/lib/ImaginariumApp-Bp1toCAd.js +0 -437
  90. package/lib/ImaginariumApp-Bp1toCAd.js.map +0 -1
  91. package/lib/ImaginariumApp-DpQNMjG_.cjs +0 -2
  92. package/lib/ImaginariumApp-DpQNMjG_.cjs.map +0 -1
  93. package/lib/PluginSetup-3m6kjRze.cjs +0 -2
  94. package/lib/PluginSetup-3m6kjRze.cjs.map +0 -1
  95. package/lib/PluginSetup-BQk4FFh9.js.map +0 -1
  96. package/lib/PluginSetup-DoIf-dYR.cjs +0 -5
  97. package/lib/PluginSetup-DoIf-dYR.cjs.map +0 -1
  98. package/lib/PluginSetup-NL8jYfpN.js.map +0 -1
  99. package/lib/PluginTypes-C4a2lmPj.cjs +0 -2
  100. package/lib/PluginTypes-C4a2lmPj.cjs.map +0 -1
  101. package/lib/PluginTypes-DsLT43Y8.js +0 -8
  102. package/lib/PluginTypes-DsLT43Y8.js.map +0 -1
  103. package/lib/SystemConfigsContext-D0hXRSH-.js +0 -128
  104. package/lib/SystemConfigsContext-D0hXRSH-.js.map +0 -1
  105. package/lib/SystemConfigsContext-yOuS10VO.cjs +0 -2
  106. package/lib/SystemConfigsContext-yOuS10VO.cjs.map +0 -1
  107. package/lib/registry-8kQ494RA.js +0 -36
  108. package/lib/registry-8kQ494RA.js.map +0 -1
  109. package/lib/registry-CHzOVHAg.cjs +0 -2
  110. package/lib/registry-CHzOVHAg.cjs.map +0 -1
@@ -0,0 +1,45 @@
1
+ "use strict";const j=require("@leverege/plugin"),A=require("./PluginTypes-BmYA5_B9.cjs"),T=require("./MarkdownPageDoc-BZF02iL5.cjs"),e=require("react/jsx-runtime"),N=require("react"),v=require("@tanstack/react-query"),u=require("lucide-react"),n=require("./Card-CHVaz_7u.cjs"),a=require("./Label-BhnvyUcc.cjs");function O({value:i,onChange:c,placeholder:y,id:o,className:m}){const[l,f]=N.useState(""),h=()=>{const s=l.trim();s&&(i.includes(s)||c([...i,s]),f(""))},d=s=>c(i.filter(r=>r!==s)),x=s=>{s.key==="Enter"||s.key===","?(s.preventDefault(),h()):s.key==="Backspace"&&l===""&&i.length>0&&d(i[i.length-1])};return e.jsxs("div",{className:n.cn("flex flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-2 py-1.5 text-sm focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",m),children:[i.map(s=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-sm bg-secondary px-2 py-0.5 text-secondary-foreground",children:[s,e.jsx("button",{type:"button",onClick:()=>d(s),"aria-label":`Remove tag ${s}`,className:"text-muted-foreground hover:text-foreground",children:e.jsx(u.X,{className:"h-3 w-3"})})]},s)),e.jsx("input",{id:o,value:l,onChange:s=>f(s.target.value),onKeyDown:x,onBlur:h,placeholder:i.length===0?y??"Add a tag…":"",className:"flex-1 min-w-32 bg-transparent outline-none placeholder:text-muted-foreground"})]})}const L={displayName:"",apiKey:"",secret:"",projectId:"",systemId:"",baseUrl:"",audience:"",type:"",tags:[],metadata:""};function E({title:i="Imagine Systems",subtitle:c="Manage Imagine API configurations for different systems",dialogDescription:y="Configure your Imagine API credentials."}={}){const{toast:o}=n.useToast(),{fetchJson:m}=n.useImaginariumApi(),l=v.useQueryClient(),[f,h]=N.useState(!1),[d,x]=N.useState(null),[s,r]=N.useState(L),{filtered:D,isLoading:F,apiPath:b,queryKey:S}=T.useSystemConfigs(),C=v.useMutation({mutationFn:t=>m(b,{method:"POST",body:JSON.stringify(t)}),onSuccess:()=>{l.invalidateQueries({queryKey:S}),o({title:"Success",description:"System Configuration created successfully"}),P()},onError:t=>{o({title:"Error",description:t.message,variant:"destructive"})}}),w=v.useMutation({mutationFn:({id:t,data:p})=>m(`${b}/${t}`,{method:"PATCH",body:JSON.stringify(p)}),onSuccess:()=>{l.invalidateQueries({queryKey:S}),o({title:"Success",description:"System Configuration updated successfully"}),P()},onError:t=>{o({title:"Error",description:t.message,variant:"destructive"})}}),U=v.useMutation({mutationFn:t=>m(`${b}/${t}`,{method:"DELETE"}),onSuccess:()=>{l.invalidateQueries({queryKey:S}),o({title:"Success",description:"System Configuration deleted successfully"})},onError:t=>{o({title:"Error",description:t.message,variant:"destructive"})}}),k=()=>{x(null),r(L),h(!0)},q=t=>{x(t),r({displayName:t.displayName,apiKey:t.apiKey,secret:"",projectId:t.projectId,systemId:t.systemId,baseUrl:t.baseUrl,audience:t.audience??"",type:t.type??"",tags:t.tags??[],metadata:t.metadata?JSON.stringify(t.metadata,null,2):""}),h(!0)},P=()=>{h(!1),x(null)},M=()=>{const{metadata:t,type:p,tags:K,...Q}=s;return{...Q,type:p.trim()||null,tags:K,metadata:t.trim()?JSON.parse(t):null}},B=()=>{let t;try{t=M()}catch{o({title:"Invalid metadata",description:"Metadata must be valid JSON",variant:"destructive"});return}d?(s.secret.trim()||delete t.secret,w.mutate({id:d.id,data:t})):C.mutate(t)},R=t=>{window.confirm("Are you sure you want to delete this system configuration?")&&U.mutate(t)},J=!!(s.displayName.trim()&&s.apiKey.trim()&&(d||s.secret.trim())&&s.projectId.trim()&&s.systemId.trim()&&s.baseUrl.trim());return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-semibold",children:i}),e.jsx("p",{className:"text-sm text-muted-foreground",children:c})]}),e.jsxs(n.Button,{onClick:k,children:[e.jsx(u.Plus,{className:"w-4 h-4 mr-2"}),"Add System"]})]}),F?e.jsx("div",{className:"text-center text-muted-foreground",children:"Loading system configurations..."}):D.length>0?e.jsx("div",{className:"grid gap-4",children:D.map(t=>e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(n.CardTitle,{children:t.displayName}),e.jsxs(n.CardDescription,{children:["Project: ",t.projectId," | System: ",t.systemId]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(n.Button,{variant:"ghost",size:"icon",onClick:()=>q(t),children:e.jsx(u.Pencil,{className:"w-4 h-4"})}),e.jsx(n.Button,{variant:"ghost",size:"icon",onClick:()=>R(t.id),children:e.jsx(u.Trash2,{className:"w-4 h-4"})})]})]})}),e.jsx(n.CardContent,{className:"space-y-2",children:e.jsxs("div",{className:"grid grid-cols-2 gap-4 text-sm",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Base URL:"}),e.jsx("div",{className:"font-mono text-xs mt-1",children:t.baseUrl})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"API Key:"}),e.jsx("div",{className:"font-mono text-xs mt-1",children:t.apiKey})]}),t.audience&&e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Audience:"}),e.jsx("div",{className:"font-mono text-xs mt-1",children:t.audience})]}),t.type&&e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Type:"}),e.jsx("div",{className:"font-mono text-xs mt-1",children:t.type})]}),t.tags&&t.tags.length>0&&e.jsxs("div",{className:"col-span-2",children:[e.jsx("span",{className:"text-muted-foreground",children:"Tags:"}),e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:t.tags.map(p=>e.jsx("span",{className:"inline-flex items-center rounded-sm bg-secondary px-2 py-0.5 text-xs text-secondary-foreground",children:p},p))})]}),t.metadata&&e.jsxs("div",{className:"col-span-2",children:[e.jsx("span",{className:"text-muted-foreground",children:"Metadata:"}),e.jsx("pre",{className:"font-mono text-xs mt-1 whitespace-pre-wrap",children:JSON.stringify(t.metadata,null,2)})]})]})})]},t.id))}):e.jsx(n.Card,{children:e.jsxs(n.CardContent,{className:"py-12 text-center",children:[e.jsx("p",{className:"text-muted-foreground mb-4",children:"No systems yet"}),e.jsxs(n.Button,{onClick:k,children:[e.jsx(u.Plus,{className:"w-4 h-4 mr-2"}),"Add Your First System"]})]})}),e.jsx(a.Dialog,{open:f,onOpenChange:h,children:e.jsxs(a.DialogContent,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsxs(a.DialogHeader,{children:[e.jsx(a.DialogTitle,{children:d?"Edit System":"New System"}),e.jsx(a.DialogDescription,{children:y})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"display-name",children:"Display Name"}),e.jsx(a.Input,{id:"display-name",value:s.displayName,onChange:t=>r({...s,displayName:t.target.value}),placeholder:"Production - Customer Name"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"base-url",children:"Base URL"}),e.jsx(a.Input,{id:"base-url",type:"url",value:s.baseUrl,onChange:t=>r({...s,baseUrl:t.target.value}),placeholder:"https://prd-customer-imagine-api.leverege.com",className:"font-mono"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"project-id",children:"Project ID"}),e.jsx(a.Input,{id:"project-id",value:s.projectId,onChange:t=>r({...s,projectId:t.target.value}),placeholder:"proj123",className:"font-mono"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"system-id",children:"System ID"}),e.jsx(a.Input,{id:"system-id",value:s.systemId,onChange:t=>r({...s,systemId:t.target.value}),placeholder:"sys456",className:"font-mono"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"api-key",children:"API Key"}),e.jsx(a.Input,{id:"api-key",value:s.apiKey,onChange:t=>r({...s,apiKey:t.target.value}),placeholder:"Enter API key (JWT issuer)",className:"font-mono"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"This will be used as the JWT issuer (iss claim)"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"secret",children:"API Secret"}),e.jsx(a.Input,{id:"secret",type:"password",value:s.secret,onChange:t=>r({...s,secret:t.target.value}),placeholder:d?"Leave blank to keep current secret":"Enter API secret",className:"font-mono"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["The Imagine API secret. It will be encrypted before storage.",d&&" Leave blank to keep the existing secret."]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"audience",children:"Audience (Optional)"}),e.jsx(a.Input,{id:"audience",value:s.audience,onChange:t=>r({...s,audience:t.target.value}),placeholder:"Auto-extracted from base URL if not provided",className:"font-mono"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"type",children:"Type (Optional)"}),e.jsx(a.Input,{id:"type",value:s.type,onChange:t=>r({...s,type:t.target.value}),placeholder:"imagine",className:"font-mono"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"tags",children:"Tags (Optional)"}),e.jsx(O,{id:"tags",value:s.tags,onChange:t=>r({...s,tags:t}),placeholder:"Press Enter to add"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Press Enter or comma to add. Backspace removes the last tag when the input is empty."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a.Label,{htmlFor:"metadata",children:"Metadata (Optional)"}),e.jsx("textarea",{id:"metadata",value:s.metadata,onChange:t=>r({...s,metadata:t.target.value}),placeholder:'{ "region": "us-central1" }',rows:5,className:"flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm font-mono ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"JSON object stored alongside the config. Leave empty to clear."})]})]}),e.jsxs(a.DialogFooter,{children:[e.jsxs(n.Button,{variant:"outline",onClick:P,children:[e.jsx(u.X,{className:"w-4 h-4 mr-2"}),"Cancel"]}),e.jsxs(n.Button,{onClick:B,disabled:!J||C.isPending||w.isPending,children:[e.jsx(u.Save,{className:"w-4 h-4 mr-2"}),C.isPending||w.isPending?"Saving...":"Save System"]})]})]})})]})}const I={id:"imaginarium.ImagineSystemPage",path:"/system-config",element:E},g={id:"imaginarium.ImagineSystemNavItem",path:"/system-config",label:"Imagine Systems",sort:100,icon:u.Settings,section:"Settings",sectionSort:900},W=T.MarkdownPageDoc.create({path:"/system-config",markdown:`# Imagine Systems
2
+
3
+ Each entry connects this app to an Imagine cluster. The required fields are display name, base URL, project ID, system ID, API key, and secret.
4
+
5
+ ## Display Name
6
+
7
+ A human-readable label for this system entry. Used throughout the app to identify the cluster.
8
+
9
+ ## Base URL
10
+
11
+ The root address of the cluster's API, for example \`https://prd-customer-imagine-api.leverege.com\`. Do not include a trailing slash or any path segment.
12
+
13
+ If you are unsure of the URL, open the Architect UI for the cluster, open your browser's Network tab, and look at any outbound API request. The base URL is everything before the path.
14
+
15
+ ## Project ID and System ID
16
+
17
+ Both are found in Architect under the project and system settings. They identify which project and system within the cluster this entry targets.
18
+
19
+ ## API Key and Secret
20
+
21
+ The API key is used as the JWT issuer (the \`iss\` claim). The secret is the signing key. Together they authenticate requests from this app to the cluster. The secret is encrypted before storage and is not shown after saving.
22
+
23
+ ### Permissions
24
+
25
+ The key should only have the permissions the app actually needs. Start from minimum and add only what is missing.
26
+
27
+ ### New keys default to admin
28
+
29
+ When you create a new API key in Architect, it is granted admin permissions by default. Remove the admin role before saving and leave only the specific permissions the app requires.
30
+
31
+ ## Audience (Optional)
32
+
33
+ The JWT audience (\`aud\` claim). If left blank, the app derives it automatically from the base URL.
34
+
35
+ ## Tags (Optional)
36
+
37
+ Tags added here appear as filter options in the cluster filter throughout the app. Use them to group or label systems, for example by environment, region, or customer, so users can narrow down which clusters are visible.
38
+
39
+ Tags can also be read by custom plugins to drive conditional behavior.
40
+
41
+ ## Metadata (Optional)
42
+
43
+ A free-form JSON object stored alongside the system config. The app does not use it directly, but custom plugins can read it to drive logic specific to a cluster, for example storing a feature flag, a display preference, or an external reference ID.
44
+ `}),$=I.id,H=g.id,V={install(i){const c=j.Config.get("ImagineSystemConfig","path",I.path),y=j.Config.get("ImagineSystemConfig","navLabel",g.label),o=j.Config.get("ImagineSystemConfig","navSort",g.sort),m=j.Config.get("ImagineSystemConfig","navIcon",g.icon),l=m===null?void 0:m;i.addPlugin(A.PageType,{...I,path:c}),i.addPlugin(A.NavItemType,{...g,path:c,label:y,sort:o,icon:l}),T.PageDoc.register(i,{...W,path:c})}};exports.ImagineSystemNavItem=g;exports.ImagineSystemNavItemId=H;exports.ImagineSystemPage=I;exports.ImagineSystemPageId=$;exports.ImagineSystemView=E;exports.SystemSetup=V;exports.TagInput=O;
45
+ //# sourceMappingURL=PluginSetup-CuLezaDw.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginSetup-CuLezaDw.cjs","sources":["../src/components/ui/TagInput.tsx","../src/system/ImagineSystemView.tsx","../src/system/ImagineSystemPage.tsx","../src/system/ImagineSystemNavItem.ts","../src/system/SystemPageDoc.ts","../src/system/PluginSetup.ts"],"sourcesContent":["import { useState, type KeyboardEvent } from 'react'\nimport { X } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nexport interface TagInputProps {\n value : string[]\n onChange : ( next: string[] ) => void\n placeholder? : string\n id? : string\n className? : string\n}\n\nexport function TagInput( { value, onChange, placeholder, id, className }: TagInputProps ) {\n const [ draft, setDraft ] = useState( '' )\n\n const commit = () => {\n const t = draft.trim()\n if ( !t ) { return }\n if ( !value.includes( t ) ) { onChange( [ ...value, t ] ) }\n setDraft( '' )\n }\n\n const remove = ( tag: string ) => onChange( value.filter( ( t ) => t !== tag ) )\n\n const handleKeyDown = ( e: KeyboardEvent<HTMLInputElement> ) => {\n if ( e.key === 'Enter' || e.key === ',' ) {\n e.preventDefault()\n commit()\n } else if ( e.key === 'Backspace' && draft === '' && value.length > 0 ) {\n remove( value[value.length - 1] )\n }\n }\n\n return (\n <div\n className={cn(\n 'flex flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-2 py-1.5 text-sm focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',\n className,\n )}\n >\n {value.map( ( tag ) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-sm bg-secondary px-2 py-0.5 text-secondary-foreground\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => remove( tag )}\n aria-label={`Remove tag ${tag}`}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n ) )}\n <input\n id={id}\n value={draft}\n onChange={( e ) => setDraft( e.target.value )}\n onKeyDown={handleKeyDown}\n onBlur={commit}\n placeholder={value.length === 0 ? ( placeholder ?? 'Add a tag…' ) : ''}\n className=\"flex-1 min-w-32 bg-transparent outline-none placeholder:text-muted-foreground\"\n />\n </div>\n )\n}\n","import { useState } from 'react'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { Plus, Pencil, Trash2, Save, X } from 'lucide-react'\n\nimport { Button } from '../components/ui/Button'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '../components/ui/Card'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '../components/ui/Dialog'\nimport { Input } from '../components/ui/Input'\nimport { Label } from '../components/ui/Label'\nimport { TagInput } from '../components/ui/TagInput'\nimport { useToast } from '../hooks/useToast'\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport { useSystemConfigs } from './SystemConfigsContext'\nimport type { ImagineSystemConfig } from './types'\n\ninterface ConfigFormData {\n displayName: string\n apiKey: string\n secret: string\n projectId: string\n systemId: string\n baseUrl: string\n audience: string\n type: string\n tags: string[]\n metadata: string\n}\n\nconst EMPTY_FORM: ConfigFormData = {\n displayName: '',\n apiKey: '',\n secret: '',\n projectId: '',\n systemId: '',\n baseUrl: '',\n audience: '',\n type: '',\n tags: [],\n metadata: '',\n}\n\nexport interface ImagineSystemViewProps {\n title?: string\n subtitle?: string\n dialogDescription?: string\n}\n\nexport default function ImagineSystemView( {\n title = 'Imagine Systems',\n subtitle = 'Manage Imagine API configurations for different systems',\n dialogDescription = 'Configure your Imagine API credentials.',\n}: ImagineSystemViewProps = {} ) {\n const { toast } = useToast()\n const { fetchJson } = useImaginariumApi()\n const queryClient = useQueryClient()\n const [ isDialogOpen, setIsDialogOpen ] = useState( false )\n const [ editingConfig, setEditingConfig ] = useState<ImagineSystemConfig | null>( null )\n const [ formData, setFormData ] = useState<ConfigFormData>( EMPTY_FORM )\n\n const { filtered: filteredConfigs, isLoading, apiPath, queryKey } = useSystemConfigs()\n\n const createMutation = useMutation( {\n mutationFn: ( data: Record<string, unknown> ) =>\n fetchJson( apiPath, { method: 'POST', body: JSON.stringify( data ) } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'System Configuration created successfully' } )\n closeDialog()\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const updateMutation = useMutation( {\n mutationFn: ( { id, data }: { id: string; data: Record<string, unknown> } ) =>\n fetchJson( `${apiPath}/${id}`, { method: 'PATCH', body: JSON.stringify( data ) } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'System Configuration updated successfully' } )\n closeDialog()\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const deleteMutation = useMutation( {\n mutationFn: ( id: string ) => fetchJson( `${apiPath}/${id}`, { method: 'DELETE' } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'System Configuration deleted successfully' } )\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const openCreateDialog = () => {\n setEditingConfig( null )\n setFormData( EMPTY_FORM )\n setIsDialogOpen( true )\n }\n\n const openEditDialog = ( config: ImagineSystemConfig ) => {\n setEditingConfig( config )\n setFormData( {\n displayName: config.displayName,\n apiKey: config.apiKey,\n secret: '',\n projectId: config.projectId,\n systemId: config.systemId,\n baseUrl: config.baseUrl,\n audience: config.audience ?? '',\n type: config.type ?? '',\n tags: config.tags ?? [],\n metadata: config.metadata ? JSON.stringify( config.metadata, null, 2 ) : '',\n } )\n setIsDialogOpen( true )\n }\n\n const closeDialog = () => {\n setIsDialogOpen( false )\n setEditingConfig( null )\n }\n\n const buildPayload = (): Record<string, unknown> => {\n const { metadata, type, tags, ...rest } = formData\n return {\n ...rest,\n type: type.trim() || null,\n tags,\n metadata: metadata.trim() ? JSON.parse( metadata ) : null,\n }\n }\n\n const handleSubmit = () => {\n let payload: Record<string, unknown>\n try {\n payload = buildPayload()\n } catch {\n toast( {\n title: 'Invalid metadata',\n description: 'Metadata must be valid JSON',\n variant: 'destructive',\n } )\n return\n }\n if ( editingConfig ) {\n if ( !formData.secret.trim() ) { delete payload.secret }\n updateMutation.mutate( { id: editingConfig.id, data: payload } )\n } else {\n createMutation.mutate( payload )\n }\n }\n\n const handleDelete = ( id: string ) => {\n if ( window.confirm( 'Are you sure you want to delete this system configuration?' ) ) {\n deleteMutation.mutate( id )\n }\n }\n\n const isFormValid = Boolean(\n formData.displayName.trim()\n && formData.apiKey.trim()\n && ( editingConfig || formData.secret.trim() )\n && formData.projectId.trim()\n && formData.systemId.trim()\n && formData.baseUrl.trim(),\n )\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h2 className=\"text-2xl font-semibold\">{title}</h2>\n <p className=\"text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <Button onClick={openCreateDialog}>\n <Plus className=\"w-4 h-4 mr-2\" />\n Add System\n </Button>\n </div>\n\n {isLoading ? (\n <div className=\"text-center text-muted-foreground\">Loading system configurations...</div>\n ) : filteredConfigs.length > 0 ? (\n <div className=\"grid gap-4\">\n {filteredConfigs.map( ( config ) => (\n <Card key={config.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <div>\n <CardTitle>{config.displayName}</CardTitle>\n <CardDescription>\n Project: {config.projectId} | System: {config.systemId}\n </CardDescription>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => openEditDialog( config )}>\n <Pencil className=\"w-4 h-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => handleDelete( config.id )}>\n <Trash2 className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">Base URL:</span>\n <div className=\"font-mono text-xs mt-1\">{config.baseUrl}</div>\n </div>\n <div>\n <span className=\"text-muted-foreground\">API Key:</span>\n <div className=\"font-mono text-xs mt-1\">{config.apiKey}</div>\n </div>\n {config.audience && (\n <div>\n <span className=\"text-muted-foreground\">Audience:</span>\n <div className=\"font-mono text-xs mt-1\">{config.audience}</div>\n </div>\n )}\n {config.type && (\n <div>\n <span className=\"text-muted-foreground\">Type:</span>\n <div className=\"font-mono text-xs mt-1\">{config.type}</div>\n </div>\n )}\n {config.tags && config.tags.length > 0 && (\n <div className=\"col-span-2\">\n <span className=\"text-muted-foreground\">Tags:</span>\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {config.tags.map( ( t ) => (\n <span\n key={t}\n className=\"inline-flex items-center rounded-sm bg-secondary px-2 py-0.5 text-xs text-secondary-foreground\"\n >\n {t}\n </span>\n ) )}\n </div>\n </div>\n )}\n {config.metadata && (\n <div className=\"col-span-2\">\n <span className=\"text-muted-foreground\">Metadata:</span>\n <pre className=\"font-mono text-xs mt-1 whitespace-pre-wrap\">\n {JSON.stringify( config.metadata, null, 2 )}\n </pre>\n </div>\n )}\n </div>\n </CardContent>\n </Card>\n ) )}\n </div>\n ) : (\n <Card>\n <CardContent className=\"py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">No systems yet</p>\n <Button onClick={openCreateDialog}>\n <Plus className=\"w-4 h-4 mr-2\" />\n Add Your First System\n </Button>\n </CardContent>\n </Card>\n )}\n\n <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>\n <DialogContent className=\"max-w-2xl max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>\n {editingConfig ? 'Edit System' : 'New System'}\n </DialogTitle>\n <DialogDescription>{dialogDescription}</DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"display-name\">Display Name</Label>\n <Input\n id=\"display-name\"\n value={formData.displayName}\n onChange={( e ) => setFormData( { ...formData, displayName: e.target.value } )}\n placeholder=\"Production - Customer Name\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"base-url\">Base URL</Label>\n <Input\n id=\"base-url\"\n type=\"url\"\n value={formData.baseUrl}\n onChange={( e ) => setFormData( { ...formData, baseUrl: e.target.value } )}\n placeholder=\"https://prd-customer-imagine-api.leverege.com\"\n className=\"font-mono\"\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"project-id\">Project ID</Label>\n <Input\n id=\"project-id\"\n value={formData.projectId}\n onChange={( e ) => setFormData( { ...formData, projectId: e.target.value } )}\n placeholder=\"proj123\"\n className=\"font-mono\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"system-id\">System ID</Label>\n <Input\n id=\"system-id\"\n value={formData.systemId}\n onChange={( e ) => setFormData( { ...formData, systemId: e.target.value } )}\n placeholder=\"sys456\"\n className=\"font-mono\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"api-key\">API Key</Label>\n <Input\n id=\"api-key\"\n value={formData.apiKey}\n onChange={( e ) => setFormData( { ...formData, apiKey: e.target.value } )}\n placeholder=\"Enter API key (JWT issuer)\"\n className=\"font-mono\"\n />\n <p className=\"text-xs text-muted-foreground\">\n This will be used as the JWT issuer (iss claim)\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret\">API Secret</Label>\n <Input\n id=\"secret\"\n type=\"password\"\n value={formData.secret}\n onChange={( e ) => setFormData( { ...formData, secret: e.target.value } )}\n placeholder={editingConfig ? 'Leave blank to keep current secret' : 'Enter API secret'}\n className=\"font-mono\"\n />\n <p className=\"text-xs text-muted-foreground\">\n The Imagine API secret. It will be encrypted before storage.\n {editingConfig && ' Leave blank to keep the existing secret.'}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"audience\">Audience (Optional)</Label>\n <Input\n id=\"audience\"\n value={formData.audience}\n onChange={( e ) => setFormData( { ...formData, audience: e.target.value } )}\n placeholder=\"Auto-extracted from base URL if not provided\"\n className=\"font-mono\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"type\">Type (Optional)</Label>\n <Input\n id=\"type\"\n value={formData.type}\n onChange={( e ) => setFormData( { ...formData, type: e.target.value } )}\n placeholder=\"imagine\"\n className=\"font-mono\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"tags\">Tags (Optional)</Label>\n <TagInput\n id=\"tags\"\n value={formData.tags}\n onChange={( tags ) => setFormData( { ...formData, tags } )}\n placeholder=\"Press Enter to add\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Press Enter or comma to add. Backspace removes the last tag when the input is empty.\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"metadata\">Metadata (Optional)</Label>\n <textarea\n id=\"metadata\"\n value={formData.metadata}\n onChange={( e ) => setFormData( { ...formData, metadata: e.target.value } )}\n placeholder='{ \"region\": \"us-central1\" }'\n rows={5}\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm font-mono ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\n />\n <p className=\"text-xs text-muted-foreground\">\n JSON object stored alongside the config. Leave empty to clear.\n </p>\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={closeDialog}>\n <X className=\"w-4 h-4 mr-2\" />\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n disabled={!isFormValid || createMutation.isPending || updateMutation.isPending}\n >\n <Save className=\"w-4 h-4 mr-2\" />\n {createMutation.isPending || updateMutation.isPending ? 'Saving...' : 'Save System'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n )\n}\n","import ImagineSystemView from './ImagineSystemView'\n\nexport default {\n id : 'imaginarium.ImagineSystemPage',\n path : '/system-config',\n element : ImagineSystemView,\n}\n","import { Settings } from 'lucide-react'\n\nexport default {\n id : 'imaginarium.ImagineSystemNavItem',\n path : '/system-config',\n label : 'Imagine Systems',\n sort : 100,\n icon : Settings,\n section : 'Settings',\n sectionSort : 900,\n}\n","import { MarkdownPageDoc } from '../docs/MarkdownPageDoc'\n\nexport default MarkdownPageDoc.create( {\n path: '/system-config',\n markdown: `# Imagine Systems\n\nEach entry connects this app to an Imagine cluster. The required fields are display name, base URL, project ID, system ID, API key, and secret.\n\n## Display Name\n\nA human-readable label for this system entry. Used throughout the app to identify the cluster.\n\n## Base URL\n\nThe root address of the cluster's API, for example \\`https://prd-customer-imagine-api.leverege.com\\`. Do not include a trailing slash or any path segment.\n\nIf you are unsure of the URL, open the Architect UI for the cluster, open your browser's Network tab, and look at any outbound API request. The base URL is everything before the path.\n\n## Project ID and System ID\n\nBoth are found in Architect under the project and system settings. They identify which project and system within the cluster this entry targets.\n\n## API Key and Secret\n\nThe API key is used as the JWT issuer (the \\`iss\\` claim). The secret is the signing key. Together they authenticate requests from this app to the cluster. The secret is encrypted before storage and is not shown after saving.\n\n### Permissions\n\nThe key should only have the permissions the app actually needs. Start from minimum and add only what is missing.\n\n### New keys default to admin\n\nWhen you create a new API key in Architect, it is granted admin permissions by default. Remove the admin role before saving and leave only the specific permissions the app requires.\n\n## Audience (Optional)\n\nThe JWT audience (\\`aud\\` claim). If left blank, the app derives it automatically from the base URL.\n\n## Tags (Optional)\n\nTags added here appear as filter options in the cluster filter throughout the app. Use them to group or label systems, for example by environment, region, or customer, so users can narrow down which clusters are visible.\n\nTags can also be read by custom plugins to drive conditional behavior.\n\n## Metadata (Optional)\n\nA free-form JSON object stored alongside the system config. The app does not use it directly, but custom plugins can read it to drive logic specific to a cluster, for example storing a feature flag, a display preference, or an external reference ID.\n`,\n} )\n","import { Config } from '@leverege/plugin'\n\nimport { NavItemType, PageType } from '../plugins/PluginTypes'\nimport { PageDoc } from '../docs/PageDoc'\nimport SystemPageDoc from './SystemPageDoc'\nimport ImagineSystemPage from './ImagineSystemPage'\nimport ImagineSystemNavItem from './ImagineSystemNavItem'\n\nexport const ImagineSystemPageId = ImagineSystemPage.id\nexport const ImagineSystemNavItemId = ImagineSystemNavItem.id\n\ninterface RegistryLike {\n addPlugin( type: string, plugin: unknown ): unknown\n}\n\n/**\n * Self-installs the ImagineSystem CRUD page + nav item, layering in any values\n * set under the `'ImagineSystemConfig'` Config resource on top of the static\n * defaults declared in `ImagineSystemPage` and `ImagineSystemNavItem`.\n *\n * Recognized config keys:\n * - `path` route path for the page (default `/system-config`)\n * - `apiPath` API path the view hits (default `/configs`; consumed by the view)\n * - `navLabel` nav button label (default `'Imagine Systems'`)\n * - `navSort` nav ordering (default `100`)\n * - `navIcon` lucide-react icon component (default `Settings`); set to\n * `null` to render no icon\n */\nexport const SystemSetup = {\n install( plg: RegistryLike ) {\n const path = Config.get<string>(\n 'ImagineSystemConfig', 'path', ImagineSystemPage.path,\n )\n const label = Config.get<string>(\n 'ImagineSystemConfig', 'navLabel', ImagineSystemNavItem.label,\n )\n const sort = Config.get<number>(\n 'ImagineSystemConfig', 'navSort', ImagineSystemNavItem.sort,\n )\n const iconSetting = Config.get<typeof ImagineSystemNavItem.icon | null>(\n 'ImagineSystemConfig', 'navIcon', ImagineSystemNavItem.icon,\n )\n const icon = iconSetting === null ? undefined : iconSetting\n\n plg.addPlugin( PageType, {\n ...ImagineSystemPage,\n path,\n } )\n plg.addPlugin( NavItemType, {\n ...ImagineSystemNavItem,\n path,\n label,\n sort,\n icon,\n } )\n\n PageDoc.register( plg, { ...SystemPageDoc, path } )\n },\n}\n\nexport default SystemSetup\n"],"names":["TagInput","value","onChange","placeholder","id","className","draft","setDraft","useState","commit","t","remove","tag","handleKeyDown","e","jsxs","cn","jsx","X","EMPTY_FORM","ImagineSystemView","title","subtitle","dialogDescription","toast","useToast","fetchJson","useImaginariumApi","queryClient","useQueryClient","isDialogOpen","setIsDialogOpen","editingConfig","setEditingConfig","formData","setFormData","filteredConfigs","isLoading","apiPath","queryKey","useSystemConfigs","createMutation","useMutation","data","closeDialog","error","updateMutation","deleteMutation","openCreateDialog","openEditDialog","config","buildPayload","metadata","type","tags","rest","handleSubmit","payload","handleDelete","isFormValid","Button","Plus","Card","CardHeader","CardTitle","CardDescription","Pencil","Trash2","CardContent","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Label","Input","DialogFooter","Save","ImagineSystemPage","ImagineSystemNavItem","Settings","SystemPageDoc","MarkdownPageDoc","ImagineSystemPageId","ImagineSystemNavItemId","SystemSetup","plg","path","Config","label","sort","iconSetting","icon","PageType","NavItemType","PageDoc"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { P as j, N as q } from "./PluginTypes-DsLT43Y8.js";
1
+ import { P as j, N as q } from "./PluginTypes-mZ4TjxPV.js";
2
2
  import { jsxs as i, jsx as t } from "react/jsx-runtime";
3
3
  import { useState as y } from "react";
4
4
  import { useQueryClient as R, useQuery as _, useMutation as N } from "@tanstack/react-query";
@@ -187,4 +187,4 @@ export {
187
187
  ve as b,
188
188
  ae as c
189
189
  };
190
- //# sourceMappingURL=PluginSetup-Co-WnS3V.js.map
190
+ //# sourceMappingURL=PluginSetup-DNKri9P1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PluginSetup-Co-WnS3V.js","sources":["../src/secret/SecretView.tsx","../src/secret/SecretPage.tsx","../src/secret/SecretNavItem.ts","../src/secret/PluginSetup.ts"],"sourcesContent":["import { useState } from 'react'\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { Plus, Pencil, Trash2, Save, X, KeyRound } from 'lucide-react'\nimport { Config } from '@leverege/plugin'\n\nimport { Button } from '../components/ui/Button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/Card'\nimport {\n Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,\n} from '../components/ui/Dialog'\nimport { Input } from '../components/ui/Input'\nimport { Label } from '../components/ui/Label'\nimport { useToast } from '../hooks/useToast'\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport type { Secret, SecretListResponse } from './types'\n\ninterface SecretFormData {\n name: string\n secret: string\n description: string\n}\n\nconst EMPTY_FORM: SecretFormData = { name: '', secret: '', description: '' }\n\nexport interface SecretViewProps {\n title?: string\n subtitle?: string\n}\n\nexport default function SecretView( {\n title = 'Secrets',\n subtitle = 'Manage encrypted secrets used by server-side services',\n}: SecretViewProps = {} ) {\n const apiPath = Config.get<string>( 'Secret', 'apiPath', '/secrets' )\n const { toast } = useToast()\n const { fetchJson } = useImaginariumApi()\n const queryClient = useQueryClient()\n const [ isOpen, setIsOpen ] = useState( false )\n const [ editing, setEditing ] = useState<Secret | null>( null )\n const [ form, setForm ] = useState<SecretFormData>( EMPTY_FORM )\n\n const queryKey = [ 'imaginarium', 'secrets', apiPath ] as const\n\n const { data: secrets, isLoading } = useQuery<Secret[]>( {\n queryKey,\n queryFn: async () => {\n const res = await fetchJson<SecretListResponse | Secret[]>( apiPath )\n return Array.isArray( res ) ? res : ( res?.items ?? [] )\n },\n } )\n\n const createMutation = useMutation( {\n mutationFn: ( data: Record<string, unknown> ) =>\n fetchJson( apiPath, { method: 'POST', body: JSON.stringify( data ) } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'Secret created' } )\n close()\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const updateMutation = useMutation( {\n mutationFn: ( { id, data }: { id: string; data: Record<string, unknown> } ) =>\n fetchJson( `${apiPath}/${id}`, { method: 'PATCH', body: JSON.stringify( data ) } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'Secret updated' } )\n close()\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const deleteMutation = useMutation( {\n mutationFn: ( id: string ) => fetchJson( `${apiPath}/${id}`, { method: 'DELETE' } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'Secret deleted' } )\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const openCreate = () => { setEditing( null ); setForm( EMPTY_FORM ); setIsOpen( true ) }\n const openEdit = ( s: Secret ) => {\n setEditing( s )\n setForm( { name: s.name, secret: '', description: s.description ?? '' } )\n setIsOpen( true )\n }\n const close = () => { setIsOpen( false ); setEditing( null ) }\n\n const buildPayload = (): Record<string, unknown> => {\n const payload: Record<string, unknown> = {\n name: form.name.trim(),\n description: form.description.trim() || null,\n }\n // Include secret only if user provided one; on edit, blank means \"keep existing\".\n if ( form.secret.trim() ) { payload.secret = form.secret }\n return payload\n }\n\n const handleSubmit = () => {\n const payload = buildPayload()\n if ( editing ) {\n updateMutation.mutate( { id: editing.id, data: payload } )\n } else {\n if ( !payload.secret ) {\n toast( { title: 'Missing secret', description: 'Secret value is required.', variant: 'destructive' } )\n return\n }\n createMutation.mutate( payload )\n }\n }\n\n const handleDelete = ( id: string ) => {\n if ( window.confirm( 'Delete this secret?' ) ) { deleteMutation.mutate( id ) }\n }\n\n const isValid = Boolean( form.name.trim() && ( editing || form.secret.trim() ) )\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h2 className=\"text-2xl font-semibold\">{title}</h2>\n <p className=\"text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <Button onClick={openCreate}>\n <Plus className=\"w-4 h-4 mr-2\" />\n Add Secret\n </Button>\n </div>\n\n {isLoading ? (\n <div className=\"text-center text-muted-foreground\">Loading…</div>\n ) : secrets && secrets.length > 0 ? (\n <div className=\"grid gap-4\">\n {secrets.map( ( s ) => (\n <Card key={s.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <KeyRound className=\"w-4 h-4 text-muted-foreground\" />\n <CardTitle>{s.name}</CardTitle>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => openEdit( s )}>\n <Pencil className=\"w-4 h-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => handleDelete( s.id )}>\n <Trash2 className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n {s.description ? (\n <CardDescription className=\"ml-6\">{s.description}</CardDescription>\n ) : null}\n </CardHeader>\n </Card>\n ) )}\n </div>\n ) : (\n <Card>\n <CardContent className=\"py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">No secrets yet</p>\n <Button onClick={openCreate}>\n <Plus className=\"w-4 h-4 mr-2\" />\n Add Your First Secret\n </Button>\n </CardContent>\n </Card>\n )}\n\n <Dialog open={isOpen} onOpenChange={setIsOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{editing ? `Edit ${editing.name}` : 'New Secret'}</DialogTitle>\n <DialogDescription>\n Secret values are encrypted at rest and never returned by the API.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret-name\">Name</Label>\n <Input\n id=\"secret-name\"\n value={form.name}\n onChange={( e ) => setForm( { ...form, name: e.target.value } )}\n placeholder=\"SUPER_SECRET_API_KEY\"\n className=\"font-mono\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret-value\">Secret Value</Label>\n <Input\n id=\"secret-value\"\n type=\"password\"\n value={form.secret}\n onChange={( e ) => setForm( { ...form, secret: e.target.value } )}\n placeholder={editing ? 'Leave blank to keep current value' : 'Enter secret value'}\n className=\"font-mono\"\n />\n <p className=\"text-xs text-muted-foreground\">\n {editing\n ? 'Leave blank to keep the existing value.'\n : 'Stored encrypted; not retrievable via the API.'}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret-description\">Description (Optional)</Label>\n <Input\n id=\"secret-description\"\n value={form.description}\n onChange={( e ) => setForm( { ...form, description: e.target.value } )}\n placeholder=\"What this secret is used for\"\n />\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={close}>\n <X className=\"w-4 h-4 mr-2\" />\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n disabled={!isValid || createMutation.isPending || updateMutation.isPending}\n >\n <Save className=\"w-4 h-4 mr-2\" />\n {createMutation.isPending || updateMutation.isPending ? 'Saving…' : 'Save Secret'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n )\n}\n","import SecretView from './SecretView'\n\nexport default {\n id : 'imaginarium.ui.SecretsPage',\n path : '/secrets',\n element : SecretView,\n}\n","import { KeyRound } from 'lucide-react'\n\nexport default {\n id : 'imaginarium.ui.SecretsNavItem',\n path : '/secrets',\n label : 'Secrets',\n icon : KeyRound,\n sort : 200,\n section : 'Settings',\n sectionSort : 900,\n}\n","import { PageType, NavItemType } from '../plugins/PluginTypes'\n\nimport SecretPage from './SecretPage'\nimport SecretNavItem from './SecretNavItem'\n\nexport const SecretSetup = {\n install( plg: { addPlugin: ( type: string, p: unknown ) => void } ) {\n plg.addPlugin( PageType, SecretPage )\n plg.addPlugin( NavItemType, SecretNavItem )\n },\n}\n\nexport default SecretSetup\n"],"names":["EMPTY_FORM","SecretView","title","subtitle","apiPath","Config","toast","useToast","fetchJson","useImaginariumApi","queryClient","useQueryClient","isOpen","setIsOpen","useState","editing","setEditing","form","setForm","queryKey","secrets","isLoading","useQuery","res","createMutation","useMutation","data","close","error","updateMutation","id","deleteMutation","openCreate","openEdit","s","buildPayload","payload","handleSubmit","handleDelete","isValid","jsxs","jsx","Button","Plus","Card","CardHeader","KeyRound","CardTitle","Pencil","Trash2","CardDescription","CardContent","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Label","Input","DialogFooter","X","Save","SecretPage","SecretNavItem","SecretSetup","plg","PageType","NavItemType"],"mappings":"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"}
1
+ {"version":3,"file":"PluginSetup-DNKri9P1.js","sources":["../src/secret/SecretView.tsx","../src/secret/SecretPage.tsx","../src/secret/SecretNavItem.ts","../src/secret/PluginSetup.ts"],"sourcesContent":["import { useState } from 'react'\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { Plus, Pencil, Trash2, Save, X, KeyRound } from 'lucide-react'\nimport { Config } from '@leverege/plugin'\n\nimport { Button } from '../components/ui/Button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/Card'\nimport {\n Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,\n} from '../components/ui/Dialog'\nimport { Input } from '../components/ui/Input'\nimport { Label } from '../components/ui/Label'\nimport { useToast } from '../hooks/useToast'\nimport { useImaginariumApi } from '../api/ImaginariumApiContext'\nimport type { Secret, SecretListResponse } from './types'\n\ninterface SecretFormData {\n name: string\n secret: string\n description: string\n}\n\nconst EMPTY_FORM: SecretFormData = { name: '', secret: '', description: '' }\n\nexport interface SecretViewProps {\n title?: string\n subtitle?: string\n}\n\nexport default function SecretView( {\n title = 'Secrets',\n subtitle = 'Manage encrypted secrets used by server-side services',\n}: SecretViewProps = {} ) {\n const apiPath = Config.get<string>( 'Secret', 'apiPath', '/secrets' )\n const { toast } = useToast()\n const { fetchJson } = useImaginariumApi()\n const queryClient = useQueryClient()\n const [ isOpen, setIsOpen ] = useState( false )\n const [ editing, setEditing ] = useState<Secret | null>( null )\n const [ form, setForm ] = useState<SecretFormData>( EMPTY_FORM )\n\n const queryKey = [ 'imaginarium', 'secrets', apiPath ] as const\n\n const { data: secrets, isLoading } = useQuery<Secret[]>( {\n queryKey,\n queryFn: async () => {\n const res = await fetchJson<SecretListResponse | Secret[]>( apiPath )\n return Array.isArray( res ) ? res : ( res?.items ?? [] )\n },\n } )\n\n const createMutation = useMutation( {\n mutationFn: ( data: Record<string, unknown> ) =>\n fetchJson( apiPath, { method: 'POST', body: JSON.stringify( data ) } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'Secret created' } )\n close()\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const updateMutation = useMutation( {\n mutationFn: ( { id, data }: { id: string; data: Record<string, unknown> } ) =>\n fetchJson( `${apiPath}/${id}`, { method: 'PATCH', body: JSON.stringify( data ) } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'Secret updated' } )\n close()\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const deleteMutation = useMutation( {\n mutationFn: ( id: string ) => fetchJson( `${apiPath}/${id}`, { method: 'DELETE' } ),\n onSuccess: () => {\n queryClient.invalidateQueries( { queryKey } )\n toast( { title: 'Success', description: 'Secret deleted' } )\n },\n onError: ( error: Error ) => {\n toast( { title: 'Error', description: error.message, variant: 'destructive' } )\n },\n } )\n\n const openCreate = () => { setEditing( null ); setForm( EMPTY_FORM ); setIsOpen( true ) }\n const openEdit = ( s: Secret ) => {\n setEditing( s )\n setForm( { name: s.name, secret: '', description: s.description ?? '' } )\n setIsOpen( true )\n }\n const close = () => { setIsOpen( false ); setEditing( null ) }\n\n const buildPayload = (): Record<string, unknown> => {\n const payload: Record<string, unknown> = {\n name: form.name.trim(),\n description: form.description.trim() || null,\n }\n // Include secret only if user provided one; on edit, blank means \"keep existing\".\n if ( form.secret.trim() ) { payload.secret = form.secret }\n return payload\n }\n\n const handleSubmit = () => {\n const payload = buildPayload()\n if ( editing ) {\n updateMutation.mutate( { id: editing.id, data: payload } )\n } else {\n if ( !payload.secret ) {\n toast( { title: 'Missing secret', description: 'Secret value is required.', variant: 'destructive' } )\n return\n }\n createMutation.mutate( payload )\n }\n }\n\n const handleDelete = ( id: string ) => {\n if ( window.confirm( 'Delete this secret?' ) ) { deleteMutation.mutate( id ) }\n }\n\n const isValid = Boolean( form.name.trim() && ( editing || form.secret.trim() ) )\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h2 className=\"text-2xl font-semibold\">{title}</h2>\n <p className=\"text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <Button onClick={openCreate}>\n <Plus className=\"w-4 h-4 mr-2\" />\n Add Secret\n </Button>\n </div>\n\n {isLoading ? (\n <div className=\"text-center text-muted-foreground\">Loading…</div>\n ) : secrets && secrets.length > 0 ? (\n <div className=\"grid gap-4\">\n {secrets.map( ( s ) => (\n <Card key={s.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <KeyRound className=\"w-4 h-4 text-muted-foreground\" />\n <CardTitle>{s.name}</CardTitle>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => openEdit( s )}>\n <Pencil className=\"w-4 h-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" onClick={() => handleDelete( s.id )}>\n <Trash2 className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n {s.description ? (\n <CardDescription className=\"ml-6\">{s.description}</CardDescription>\n ) : null}\n </CardHeader>\n </Card>\n ) )}\n </div>\n ) : (\n <Card>\n <CardContent className=\"py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">No secrets yet</p>\n <Button onClick={openCreate}>\n <Plus className=\"w-4 h-4 mr-2\" />\n Add Your First Secret\n </Button>\n </CardContent>\n </Card>\n )}\n\n <Dialog open={isOpen} onOpenChange={setIsOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{editing ? `Edit ${editing.name}` : 'New Secret'}</DialogTitle>\n <DialogDescription>\n Secret values are encrypted at rest and never returned by the API.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret-name\">Name</Label>\n <Input\n id=\"secret-name\"\n value={form.name}\n onChange={( e ) => setForm( { ...form, name: e.target.value } )}\n placeholder=\"SUPER_SECRET_API_KEY\"\n className=\"font-mono\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret-value\">Secret Value</Label>\n <Input\n id=\"secret-value\"\n type=\"password\"\n value={form.secret}\n onChange={( e ) => setForm( { ...form, secret: e.target.value } )}\n placeholder={editing ? 'Leave blank to keep current value' : 'Enter secret value'}\n className=\"font-mono\"\n />\n <p className=\"text-xs text-muted-foreground\">\n {editing\n ? 'Leave blank to keep the existing value.'\n : 'Stored encrypted; not retrievable via the API.'}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"secret-description\">Description (Optional)</Label>\n <Input\n id=\"secret-description\"\n value={form.description}\n onChange={( e ) => setForm( { ...form, description: e.target.value } )}\n placeholder=\"What this secret is used for\"\n />\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={close}>\n <X className=\"w-4 h-4 mr-2\" />\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n disabled={!isValid || createMutation.isPending || updateMutation.isPending}\n >\n <Save className=\"w-4 h-4 mr-2\" />\n {createMutation.isPending || updateMutation.isPending ? 'Saving…' : 'Save Secret'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n )\n}\n","import SecretView from './SecretView'\n\nexport default {\n id : 'imaginarium.ui.SecretsPage',\n path : '/secrets',\n element : SecretView,\n}\n","import { KeyRound } from 'lucide-react'\n\nexport default {\n id : 'imaginarium.ui.SecretsNavItem',\n path : '/secrets',\n label : 'Secrets',\n icon : KeyRound,\n sort : 200,\n section : 'Settings',\n sectionSort : 900,\n}\n","import { PageType, NavItemType } from '../plugins/PluginTypes'\n\nimport SecretPage from './SecretPage'\nimport SecretNavItem from './SecretNavItem'\n\nexport const SecretSetup = {\n install( plg: { addPlugin: ( type: string, p: unknown ) => void } ) {\n plg.addPlugin( PageType, SecretPage )\n plg.addPlugin( NavItemType, SecretNavItem )\n },\n}\n\nexport default SecretSetup\n"],"names":["EMPTY_FORM","SecretView","title","subtitle","apiPath","Config","toast","useToast","fetchJson","useImaginariumApi","queryClient","useQueryClient","isOpen","setIsOpen","useState","editing","setEditing","form","setForm","queryKey","secrets","isLoading","useQuery","res","createMutation","useMutation","data","close","error","updateMutation","id","deleteMutation","openCreate","openEdit","s","buildPayload","payload","handleSubmit","handleDelete","isValid","jsxs","jsx","Button","Plus","Card","CardHeader","KeyRound","CardTitle","Pencil","Trash2","CardDescription","CardContent","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Label","Input","DialogFooter","X","Save","SecretPage","SecretNavItem","SecretSetup","plg","PageType","NavItemType"],"mappings":";;;;;;;;AAsBA,MAAMA,IAA6B,EAAE,MAAM,IAAI,QAAQ,IAAI,aAAa,GAAA;AAOxE,SAAwBC,GAAY;AAAA,EAClC,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AACb,IAAqB,IAAK;AACxB,QAAMC,IAAUC,EAAO,IAAa,UAAU,WAAW,UAAW,GAC9D,EAAE,OAAAC,EAAA,IAAUC,EAAA,GACZ,EAAE,WAAAC,EAAA,IAAcC,EAAA,GAChBC,IAAcC,EAAA,GACd,CAAEC,GAAQC,CAAU,IAAIC,EAAU,EAAM,GACxC,CAAEC,GAASC,CAAW,IAAIF,EAAyB,IAAK,GACxD,CAAEG,GAAMC,CAAQ,IAAIJ,EAA0Bd,CAAW,GAEzDmB,IAAW,CAAE,eAAe,WAAWf,CAAQ,GAE/C,EAAE,MAAMgB,GAAS,WAAAC,EAAA,IAAcC,EAAoB;AAAA,IACvD,UAAAH;AAAA,IACA,SAAS,YAAY;AACnB,YAAMI,IAAM,MAAMf,EAA0CJ,CAAQ;AACpE,aAAO,MAAM,QAASmB,CAAI,IAAIA,KAAQA,KAAA,gBAAAA,EAAK,UAAS,CAAA;AAAA,IACtD;AAAA,EAAA,CACA,GAEIC,IAAiBC,EAAa;AAAA,IAClC,YAAY,CAAEC,MACZlB,EAAWJ,GAAS,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAWsB,CAAK,GAAI;AAAA,IACvE,WAAW,MAAM;AACf,MAAAhB,EAAY,kBAAmB,EAAE,UAAAS,GAAW,GAC5Cb,EAAO,EAAE,OAAO,WAAW,aAAa,kBAAmB,GAC3DqB,EAAA;AAAA,IACF;AAAA,IACA,SAAS,CAAEC,MAAkB;AAC3B,MAAAtB,EAAO,EAAE,OAAO,SAAS,aAAasB,EAAM,SAAS,SAAS,eAAgB;AAAA,IAChF;AAAA,EAAA,CACA,GAEIC,IAAiBJ,EAAa;AAAA,IAClC,YAAY,CAAE,EAAE,IAAAK,GAAI,MAAAJ,QAClBlB,EAAW,GAAGJ,CAAO,IAAI0B,CAAE,IAAI,EAAE,QAAQ,SAAS,MAAM,KAAK,UAAWJ,CAAK,GAAI;AAAA,IACnF,WAAW,MAAM;AACf,MAAAhB,EAAY,kBAAmB,EAAE,UAAAS,GAAW,GAC5Cb,EAAO,EAAE,OAAO,WAAW,aAAa,kBAAmB,GAC3DqB,EAAA;AAAA,IACF;AAAA,IACA,SAAS,CAAEC,MAAkB;AAC3B,MAAAtB,EAAO,EAAE,OAAO,SAAS,aAAasB,EAAM,SAAS,SAAS,eAAgB;AAAA,IAChF;AAAA,EAAA,CACA,GAEIG,IAAiBN,EAAa;AAAA,IAClC,YAAY,CAAEK,MAAgBtB,EAAW,GAAGJ,CAAO,IAAI0B,CAAE,IAAI,EAAE,QAAQ,SAAA,CAAW;AAAA,IAClF,WAAW,MAAM;AACf,MAAApB,EAAY,kBAAmB,EAAE,UAAAS,GAAW,GAC5Cb,EAAO,EAAE,OAAO,WAAW,aAAa,kBAAmB;AAAA,IAC7D;AAAA,IACA,SAAS,CAAEsB,MAAkB;AAC3B,MAAAtB,EAAO,EAAE,OAAO,SAAS,aAAasB,EAAM,SAAS,SAAS,eAAgB;AAAA,IAChF;AAAA,EAAA,CACA,GAEII,IAAa,MAAM;AAAE,IAAAhB,EAAY,IAAK,GAAGE,EAASlB,CAAW,GAAGa,EAAW,EAAK;AAAA,EAAE,GAClFoB,IAAW,CAAEC,MAAe;AAChC,IAAAlB,EAAYkB,CAAE,GACdhB,EAAS,EAAE,MAAMgB,EAAE,MAAM,QAAQ,IAAI,aAAaA,EAAE,eAAe,GAAA,CAAK,GACxErB,EAAW,EAAK;AAAA,EAClB,GACMc,IAAQ,MAAM;AAAE,IAAAd,EAAW,EAAM,GAAGG,EAAY,IAAK;AAAA,EAAE,GAEvDmB,IAAe,MAA+B;AAClD,UAAMC,IAAmC;AAAA,MACvC,MAAMnB,EAAK,KAAK,KAAA;AAAA,MAChB,aAAaA,EAAK,YAAY,UAAU;AAAA,IAAA;AAG1C,WAAKA,EAAK,OAAO,WAAWmB,EAAQ,SAASnB,EAAK,SAC3CmB;AAAA,EACT,GAEMC,IAAe,MAAM;AACzB,UAAMD,IAAUD,EAAA;AAChB,QAAKpB;AACH,MAAAc,EAAe,OAAQ,EAAE,IAAId,EAAQ,IAAI,MAAMqB,GAAU;AAAA,SACpD;AACL,UAAK,CAACA,EAAQ,QAAS;AACrB,QAAA9B,EAAO,EAAE,OAAO,kBAAkB,aAAa,6BAA6B,SAAS,eAAgB;AACrG;AAAA,MACF;AACA,MAAAkB,EAAe,OAAQY,CAAQ;AAAA,IACjC;AAAA,EACF,GAEME,IAAe,CAAER,MAAgB;AACrC,IAAK,OAAO,QAAS,qBAAsB,KAAMC,EAAe,OAAQD,CAAG;AAAA,EAC7E,GAEMS,IAAU,GAAStB,EAAK,KAAK,WAAYF,KAAWE,EAAK,OAAO,KAAA;AAEtE,SACE,gBAAAuB,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,QAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,0BAA0B,UAAAvC,GAAM;AAAA,QAC9C,gBAAAuC,EAAC,KAAA,EAAE,WAAU,iCAAiC,UAAAtC,EAAA,CAAS;AAAA,MAAA,GACzD;AAAA,MACA,gBAAAqC,EAACE,GAAA,EAAO,SAASV,GACf,UAAA;AAAA,QAAA,gBAAAS,EAACE,GAAA,EAAK,WAAU,eAAA,CAAe;AAAA,QAAE;AAAA,MAAA,EAAA,CAEnC;AAAA,IAAA,GACF;AAAA,IAECtB,sBACE,OAAA,EAAI,WAAU,qCAAoC,UAAA,WAAA,CAAQ,IACzDD,KAAWA,EAAQ,SAAS,sBAC7B,OAAA,EAAI,WAAU,cACZ,UAAAA,EAAQ,IAAK,CAAEc,MACd,gBAAAO,EAACG,GAAA,EACC,UAAA,gBAAAJ,EAACK,GAAA,EACC,UAAA;AAAA,MAAA,gBAAAL,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAC,EAACK,GAAA,EAAS,WAAU,gCAAA,CAAgC;AAAA,UACpD,gBAAAL,EAACM,GAAA,EAAW,UAAAb,EAAE,KAAA,CAAK;AAAA,QAAA,GACrB;AAAA,QACA,gBAAAM,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,UAAA,gBAAAC,EAACC,GAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,SAAS,MAAMT,EAAUC,CAAE,GAC7D,UAAA,gBAAAO,EAACO,GAAA,EAAO,WAAU,WAAU,GAC9B;AAAA,4BACCN,GAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,SAAS,MAAMJ,EAAcJ,EAAE,EAAG,GACpE,UAAA,gBAAAO,EAACQ,GAAA,EAAO,WAAU,WAAU,EAAA,CAC9B;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MACCf,EAAE,cACD,gBAAAO,EAACS,GAAA,EAAgB,WAAU,QAAQ,UAAAhB,EAAE,aAAY,IAC/C;AAAA,IAAA,EAAA,CACN,EAAA,GAnBSA,EAAE,EAoBb,CACA,EAAA,CACJ,IAEA,gBAAAO,EAACG,GAAA,EACC,UAAA,gBAAAJ,EAACW,GAAA,EAAY,WAAU,qBACrB,UAAA;AAAA,MAAA,gBAAAV,EAAC,KAAA,EAAE,WAAU,8BAA6B,UAAA,kBAAc;AAAA,MACxD,gBAAAD,EAACE,GAAA,EAAO,SAASV,GACf,UAAA;AAAA,QAAA,gBAAAS,EAACE,GAAA,EAAK,WAAU,eAAA,CAAe;AAAA,QAAE;AAAA,MAAA,EAAA,CAEnC;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,sBAGDS,GAAA,EAAO,MAAMxC,GAAQ,cAAcC,GAClC,4BAACwC,IAAA,EACC,UAAA;AAAA,MAAA,gBAAAb,EAACc,IAAA,EACC,UAAA;AAAA,QAAA,gBAAAb,EAACc,MAAa,UAAAxC,IAAU,QAAQA,EAAQ,IAAI,KAAK,cAAa;AAAA,QAC9D,gBAAA0B,EAACe,MAAkB,UAAA,qEAAA,CAEnB;AAAA,MAAA,GACF;AAAA,MAEA,gBAAAhB,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAC,EAACgB,GAAA,EAAM,SAAQ,eAAc,UAAA,QAAI;AAAA,UACjC,gBAAAhB;AAAA,YAACiB;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,OAAOzC,EAAK;AAAA,cACZ,UAAU,CAAE,MAAOC,EAAS,EAAE,GAAGD,GAAM,MAAM,EAAE,OAAO,OAAQ;AAAA,cAC9D,aAAY;AAAA,cACZ,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACZ,GACF;AAAA,QAEA,gBAAAuB,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAC,EAACgB,GAAA,EAAM,SAAQ,gBAAe,UAAA,gBAAY;AAAA,UAC1C,gBAAAhB;AAAA,YAACiB;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,MAAK;AAAA,cACL,OAAOzC,EAAK;AAAA,cACZ,UAAU,CAAE,MAAOC,EAAS,EAAE,GAAGD,GAAM,QAAQ,EAAE,OAAO,OAAQ;AAAA,cAChE,aAAaF,IAAU,sCAAsC;AAAA,cAC7D,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,4BAEX,KAAA,EAAE,WAAU,iCACV,UAAAA,IACG,4CACA,iDAAA,CACN;AAAA,QAAA,GACF;AAAA,QAEA,gBAAAyB,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAC,EAACgB,GAAA,EAAM,SAAQ,sBAAqB,UAAA,0BAAsB;AAAA,UAC1D,gBAAAhB;AAAA,YAACiB;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,OAAOzC,EAAK;AAAA,cACZ,UAAU,CAAE,MAAOC,EAAS,EAAE,GAAGD,GAAM,aAAa,EAAE,OAAO,OAAQ;AAAA,cACrE,aAAY;AAAA,YAAA;AAAA,UAAA;AAAA,QACd,EAAA,CACF;AAAA,MAAA,GACF;AAAA,wBAEC0C,IAAA,EACC,UAAA;AAAA,QAAA,gBAAAnB,EAACE,GAAA,EAAO,SAAQ,WAAU,SAASf,GACjC,UAAA;AAAA,UAAA,gBAAAc,EAACmB,GAAA,EAAE,WAAU,eAAA,CAAe;AAAA,UAAE;AAAA,QAAA,GAEhC;AAAA,QACA,gBAAApB;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,SAASL;AAAA,YACT,UAAU,CAACE,KAAWf,EAAe,aAAaK,EAAe;AAAA,YAEjE,UAAA;AAAA,cAAA,gBAAAY,EAACoB,GAAA,EAAK,WAAU,eAAA,CAAe;AAAA,cAC9BrC,EAAe,aAAaK,EAAe,YAAY,YAAY;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACtE,EAAA,CACF;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AClPA,MAAAiC,KAAe;AAAA,EACb,IAAK;AAAA,EACL,MAAO;AAAA,EACP,SAAU7D;AACZ,GCJA8D,KAAe;AAAA,EACb,IAAK;AAAA,EACL,MAAO;AAAA,EACP,OAAQ;AAAA,EACR,MAAOjB;AAAA,EACP,MAAO;AAAA,EACP,SAAU;AAAA,EACV,aAAc;AAChB,GCLakB,KAAc;AAAA,EACzB,QAASC,GAA2D;AAClE,IAAAA,EAAI,UAAWC,GAAUJ,EAAW,GACpCG,EAAI,UAAWE,GAAaJ,EAAc;AAAA,EAC5C;AACF;"}