@harperfast/harper 5.0.0-beta.6 → 5.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/harper.js +1 -1
- package/bin/run.js +2 -2
- package/components/Application.ts +6 -3
- package/components/componentLoader.ts +19 -11
- package/components/operations.js +13 -13
- package/components/operationsValidation.js +3 -3
- package/config/configUtils.js +20 -4
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +3 -2
- package/dist/bin/harper.d.ts +1 -1
- package/dist/bin/harper.js +1 -1
- package/dist/bin/run.js +2 -2
- package/dist/bin/run.js.map +1 -1
- package/dist/components/Application.js +7 -2
- package/dist/components/Application.js.map +1 -1
- package/dist/components/componentLoader.js +19 -9
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/operations.js +13 -13
- package/dist/components/operations.js.map +1 -1
- package/dist/components/operationsValidation.js +3 -3
- package/dist/components/operationsValidation.js.map +1 -1
- package/dist/config/configUtils.d.ts +6 -0
- package/dist/config/configUtils.js +23 -3
- package/dist/config/configUtils.js.map +1 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +3 -2
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js.map +1 -1
- package/dist/resources/Resource.d.ts +2 -0
- package/dist/resources/Resource.js +11 -4
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/RocksTransactionLogStore.d.ts +1 -0
- package/dist/resources/RocksTransactionLogStore.js +8 -1
- package/dist/resources/RocksTransactionLogStore.js.map +1 -1
- package/dist/resources/analytics/write.js +6 -0
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/databases.js +3 -2
- package/dist/resources/databases.js.map +1 -1
- package/dist/security/jsLoader.js +114 -40
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/server/REST.js +17 -10
- package/dist/server/REST.js.map +1 -1
- package/dist/server/http.js +1 -1
- package/dist/server/http.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +1 -1
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/utility/hdbTerms.d.ts +1 -0
- package/dist/utility/hdbTerms.js +1 -0
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/logging/harper_logger.js +24 -1
- package/dist/utility/logging/harper_logger.js.map +1 -1
- package/dist/utility/logging/readLog.js +2 -2
- package/dist/utility/logging/readLog.js.map +1 -1
- package/dist/utility/npmUtilities.js +2 -2
- package/dist/utility/npmUtilities.js.map +1 -1
- package/dist/validation/configValidator.js +18 -8
- package/dist/validation/configValidator.js.map +1 -1
- package/dist/validation/readLogValidator.js +2 -2
- package/dist/validation/readLogValidator.js.map +1 -1
- package/package.json +3 -3
- package/resources/Resource.ts +17 -6
- package/resources/RocksTransactionLogStore.ts +8 -1
- package/resources/analytics/write.ts +6 -0
- package/resources/databases.ts +3 -2
- package/security/jsLoader.ts +127 -46
- package/server/REST.ts +20 -11
- package/server/http.ts +2 -2
- package/server/itc/serverHandlers.js +1 -1
- package/static/defaultConfig.yaml +1 -1
- package/studio/web/assets/{index-BckVDix4.js → index-ClD_q6ya.js} +5 -5
- package/studio/web/assets/{index-BckVDix4.js.map → index-ClD_q6ya.js.map} +1 -1
- package/studio/web/assets/{index.lazy-iG1_8dzm.js → index.lazy-CXzU1gVu.js} +2 -2
- package/studio/web/assets/{index.lazy-iG1_8dzm.js.map → index.lazy-CXzU1gVu.js.map} +1 -1
- package/studio/web/assets/{profile-CzjslUXv.js → profile-DCNVg5yY.js} +2 -2
- package/studio/web/assets/{profile-CzjslUXv.js.map → profile-DCNVg5yY.js.map} +1 -1
- package/studio/web/assets/{status-BP4TQJDR.js → status-CoGlcjSB.js} +2 -2
- package/studio/web/assets/{status-BP4TQJDR.js.map → status-CoGlcjSB.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/utility/hdbTerms.ts +1 -0
- package/utility/logging/harper_logger.js +22 -1
- package/utility/logging/readLog.js +2 -2
- package/utility/npmUtilities.js +2 -2
- package/validation/configValidator.js +16 -8
- package/validation/readLogValidator.js +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/swagger-ui-react-CW6i-J2I.js","assets/vendor-misc-BBL3Mh21.js","assets/rolldown-runtime-FhOqtrmT.js","assets/vendor-markdown-c5U0YRyN.js","assets/vendor-html-C0BzV7Np.js","assets/vendor-core-BY_ZlgBF.js","assets/vendor-react-DrZSc0Lm.js","assets/vendor-datadog-B4t4E5qd.js","assets/vendor-monaco-CLBN4H7U.js","assets/vendor-charts-BUlf-q3q.js","assets/vendor-react-BlDLhtZc.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{d as t,f as n,i as r,o as i,p as a,r as o}from"./cn-BnE9QzQD.js";import"./vendor-core-BY_ZlgBF.js";import{$i as s,Pi as c,Qi as l,Qn as u,Vi as d,Yi as f,Zi as p,qi as m,vr as h}from"./vendor-react-DrZSc0Lm.js";import"./vendor-misc-BBL3Mh21.js";import{t as g}from"./button-DWsEHYDp.js";import{i as _}from"./vendor-datadog-B4t4E5qd.js";import{A as v,M as y,a as b,b as x,i as S,j as C,n as w,o as T,r as E,v as D,y as O}from"./index-
|
|
2
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{d as t,f as n,i as r,o as i,p as a,r as o}from"./cn-BnE9QzQD.js";import"./vendor-core-BY_ZlgBF.js";import{$i as s,Pi as c,Qi as l,Qn as u,Vi as d,Yi as f,Zi as p,qi as m,vr as h}from"./vendor-react-DrZSc0Lm.js";import"./vendor-misc-BBL3Mh21.js";import{t as g}from"./button-DWsEHYDp.js";import{i as _}from"./vendor-datadog-B4t4E5qd.js";import{A as v,M as y,a as b,b as x,i as S,j as C,n as w,o as T,r as E,v as D,y as O}from"./index-ClD_q6ya.js";var k=[{fn:{requestSnippetGenerator_fetch:e=>{let t=new URL(e.get(`url`)),n=!1,r=e.get(`headers`);r&&r.size&&r.map((e,t)=>{n||=/^content-type$/i.test(t)&&/^multipart\/form-data$/i.test(e)});let i=e.get(`body`),a=e.get(`method`);if(i){if(n&&[`POST`,`PUT`,`PATCH`].includes(a))return`throw new Error("Currently unsupported content-type: /^multipart\\/form-data$/i");`;typeof i!=`string`&&(i=JSON.stringify(i,null,` `))}else !i&&a===`POST`&&(i=``);let o="`"+(i||``).replace(/\\n/g,`
|
|
3
3
|
`).replace(/`/g,"\\`")+"`";return`const response = await fetch("${t.toString()}", {
|
|
4
4
|
\tmethod: "${e.get(`method`)}",${r&&r.size?`
|
|
5
5
|
\theaders: {
|
|
@@ -12,4 +12,4 @@ const data = await response.json();
|
|
|
12
12
|
console.log(data);
|
|
13
13
|
`}}}],A={generators:{fetch:{title:`Fetch`,syntax:`javascript`}}};async function j({instanceClient:e,...t}){let{data:n}=await e.post(`/`,{operation:`set_configuration`,...t});return n}var M=e(s(),1),N=l();function P({onRestartedSuccessfully:e}={}){let s=v(),c=p(),[l,d]=(0,M.useState)(!1);return{onConfigUpdate:(0,M.useCallback)(async l=>{d(!0);let f=!1,p={duration:6e4,action:{label:`Cancel`,onClick:()=>{f=!0}}},m=u.loading(`Restarting`,{...p,description:(0,N.jsx)(D,{animated:!0,width:`0%`})}),h=s.entityType===`cluster`?await x(s.entityId):null,g=s.entityType===`cluster`?h?.instances||[]:[{id:s.entityId,status:`RUNNING`}],_=!!h&&o.checkForFabricConnect(h.id),v=s.entityType===`cluster`?g.filter(e=>e.status===`RUNNING`).map(e=>t({id:e.id,forceFabricConnect:_,operationsUrl:r(e)})).reverse():[s.instanceClient],y=0;if(v.length)for(let e=0;e<v.length;e++){let t=v[e];if(!f){u.loading(`Updating Instance ${e+1} of ${v.length}`,{...p,id:m,description:(0,N.jsx)(D,{animated:!0,width:(e===0?0:e/v.length*100)+`%`})});try{await i({instanceClient:t}),await j({...l,instanceClient:t}),await T({operation:`restart_service`,replicated:!1,instanceClient:t}),y+=1}catch{e+1!==v.length&&(u.loading(`Failed Restarting Instance ${e+1} of ${v.length}`,{...p,id:m,description:`We will carry on momentarily.`}),await n(3e3))}}}if(d(!1),c.invalidateQueries({queryKey:[s.entityId,`get_configuration`]}),f)u.error(`Cancelled`,{id:m,description:`The config update was partially cancelled.`,duration:1e4,action:{label:`Dismiss`,onClick:()=>u.dismiss()}});else if(g.length===y)e?.(),u.success(`Success`,{id:m,description:`Your configuration has been updated successfully!`,duration:1e4,action:{label:`Dismiss`,onClick:()=>u.dismiss()}});else{let e=a(g.length,`instance`,`instances`),t=a(y,`"RUNNING" instance was`,`"RUNNING" instances were`);u.error(`Error`,{id:m,description:`Failed to fully update cluster.
|
|
14
14
|
`+([g.length===0&&`No instances were found within the cluster to restart.`,y===0&&`No instances were in a "RUNNING" state of ${e}.`,g.length!==y&&`Only ${t} restarted of ${e}.`].filter(C).shift()||``),duration:1e4,action:{label:`Dismiss`,onClick:()=>u.dismiss()}})}},[s,e,c]),isPending:l}}function F({entityId:e,instanceClient:t}){return m({queryKey:[e,`OpenAPI`],queryFn:async()=>{let{data:e}=await t.get(`/api/openapi/rest`);return e}})}var I=(0,M.lazy)(()=>_(()=>import(`./swagger-ui-react-CW6i-J2I.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])));function L(){let{instanceId:e,clusterId:t}=d({strict:!1}),n=v(),{data:r,isLoading:i}=f(E(n)),{data:a,isLoading:o}=f(w(n)),s=b(),{data:c,isLoading:l,error:u}=f(F(n));c?.servers?.length&&(c.servers[0].url=s);let p=r?.http,m=``,_=p?.cors===!1,x=p?.corsAccessList?.length!==void 0&&!p.corsAccessList.includes(`*`)&&!p.corsAccessList.includes(`null`)&&!p.corsAccessList.includes(window.location.origin);_?m=`This ${t&&!e?`cluster`:`instance`} has CORS disabled currently, so you won't be able to execute API requests from the browser.`:x&&(m=`This ${t&&!e?`cluster`:`instance`} has CORS enabled, but ${window.location.origin} is not allowed, so you won't be able to execute API requests from the browser.`);let{onConfigUpdate:C,isPending:T}=P(),D=(0,M.useCallback)(()=>{C({..._?{http_cors:!0}:{},...x?{http_corsAccessList:[...p?.corsAccessList??[],window.location.origin]}:{}})},[_,p?.corsAccessList,x,C]);if(i||o||l)return(0,N.jsx)(O,{centered:!0,text:`Looking up your instance configuration, one moment.`});if(u){let e;return e=a?.version&&!S(`4.7.0-beta.7`,a?.version)?`API Docs are only available starting in version '4.7.0-beta.7' of Harper, please update your version ${a.version}!`:`We weren't able to look up your docs. Please check the Network tab of your developer tools to see why the docs were not accessible to Studio.`,(0,N.jsx)(y,{title:`API Docs Unavailable`,error:{message:e},showReturnToHome:!1})}return(0,N.jsxs)(N.Fragment,{children:[m&&(0,N.jsx)(y,{title:`CORS Disabled: HTTP API Not Accessible`,className:`mt-0 mx-4 m-0 border-yellow text-yellow`,error:{message:m},showReturnToHome:!1,children:(0,N.jsxs)(g,{disabled:T,variant:`warning`,className:`rounded-full`,onClick:D,children:[(0,N.jsx)(h,{}),T?`Enabling CORS...`:`Enable CORS for ${window.location.origin}`]})}),(0,N.jsx)(M.Suspense,{fallback:(0,N.jsx)(O,{centered:!0,text:`Loading API documentation...`}),children:(0,N.jsx)(I,{spec:c,persistAuthorization:!0,withCredentials:!0,requestSnippetsEnabled:!0,defaultModelRendering:`model`,requestSnippets:A,plugins:k,tryItOutEnabled:!0})})]})}var R=c(`/apis`)({component:L});export{R as route};
|
|
15
|
-
//# sourceMappingURL=index.lazy-
|
|
15
|
+
//# sourceMappingURL=index.lazy-CXzU1gVu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/features/instance/apis/plugins.ts","../../src/features/instance/apis/requestSnippets.ts","../../src/integrations/api/instance/status/setConfiguration.ts","../../src/hooks/useRollingConfigUpdate.tsx","../../src/integrations/api/instance/status/getOpenAPI.ts","../../src/features/instance/apis/APIDocs.tsx","../../src/features/instance/apis/index.lazy.tsx"],"sourcesContent":["export const SnippedGeneratorNodeJsPlugin = {\n\tfn: {\n\t\trequestSnippetGenerator_fetch: (request: { get: (key: string) => unknown }) => {\n\t\t\tconst url = new URL(request.get('url') as string);\n\t\t\tlet isMultipartFormDataRequest = false;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst headers = request.get('headers') as any;\n\t\t\tif (headers && headers.size) {\n\t\t\t\theaders.map((val: string, key: string) => {\n\t\t\t\t\tisMultipartFormDataRequest = isMultipartFormDataRequest\n\t\t\t\t\t\t|| /^content-type$/i.test(key) && /^multipart\\/form-data$/i.test(val);\n\t\t\t\t});\n\t\t\t}\n\t\t\tlet reqBody = request.get('body') as string | object;\n\t\t\tconst reqMethod = request.get('method') as string;\n\t\t\tif (reqBody) {\n\t\t\t\tif (isMultipartFormDataRequest && ['POST', 'PUT', 'PATCH'].includes(reqMethod)) {\n\t\t\t\t\treturn 'throw new Error(\"Currently unsupported content-type: /^multipart\\\\/form-data$/i\");';\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof reqBody !== 'string') {\n\t\t\t\t\t\treqBody = JSON.stringify(reqBody, null, '\\t');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (!reqBody && reqMethod === 'POST') {\n\t\t\t\treqBody = '';\n\t\t\t}\n\n\t\t\tconst stringBody = '`' + (reqBody || '')\n\t\t\t\t.replace(/\\\\n/g, '\\n')\n\t\t\t\t.replace(/`/g, '\\\\`')\n\t\t\t\t+ '`';\n\n\t\t\treturn `const response = await fetch(\"${url.toString()}\", {\n\\tmethod: \"${request.get('method')}\",${\n\t\t\t\theaders && headers.size\n\t\t\t\t\t? `\n\\theaders: {\n\\t\\t${headers.map((val: string, key: string) => `\"${key}\": \"${val}\"`).valueSeq().join(',\\n\\t\\t')}\n\\t},`\n\t\t\t\t\t: ''\n\t\t\t}${\n\t\t\t\treqBody\n\t\t\t\t\t? `\n\\tbody: ${stringBody},`\n\t\t\t\t\t: ''\n\t\t\t}\n});\nconst data = await response.json();\nconsole.log(data);\n`;\n\t\t},\n\t},\n};\n\nexport const plugins = [\n\tSnippedGeneratorNodeJsPlugin,\n];\n","export const requestSnippets = {\n\tgenerators: {\n\t\tfetch: {\n\t\t\ttitle: 'Fetch',\n\t\t\tsyntax: 'javascript',\n\t\t},\n\t},\n};\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\n\ninterface SetConfigurationParams extends InstanceClientConfig {\n\t[key: string]: unknown;\n}\n\nexport async function setConfiguration({\n\tinstanceClient,\n\t...changes\n}: SetConfigurationParams): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'set_configuration',\n\t\t...changes,\n\t});\n\treturn data;\n}\n","import { ProgressBar } from '@/components/ProgressBar';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfo } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { Instance } from '@/integrations/api/api.patch';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { restartInstance } from '@/integrations/api/instance/status/restartInstance';\nimport { setConfiguration } from '@/integrations/api/instance/status/setConfiguration';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { pluralize } from '@/lib/pluralize';\nimport { sleep } from '@/lib/sleep';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\ninterface RollingConfigUpdateParams {\n\tonRestartedSuccessfully?: () => void;\n}\n\ninterface RollingConfigUpdateResponse {\n\tonConfigUpdate: (params: Record<string, unknown>) => void;\n\tisPending: boolean;\n}\n\nexport function useRollingConfigUpdate(\n\t{ onRestartedSuccessfully }: RollingConfigUpdateParams = {},\n): RollingConfigUpdateResponse {\n\tconst operationsParams = useInstanceClientIdParams();\n\tconst queryClient = useQueryClient();\n\tconst [isPending, setIsPending] = useState(false);\n\tconst onConfigUpdate = useCallback(async (params: Record<string, unknown>) => {\n\t\tsetIsPending(true);\n\n\t\tlet canceled = false;\n\t\tconst toastConfig = {\n\t\t\tduration: 60_000,\n\t\t\taction: {\n\t\t\t\tlabel: 'Cancel',\n\t\t\t\tonClick: () => {\n\t\t\t\t\tcanceled = true;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tconst toastId = toast.loading('Restarting', {\n\t\t\t...toastConfig,\n\t\t\tdescription: (\n\t\t\t\t<ProgressBar\n\t\t\t\t\tanimated={true}\n\t\t\t\t\twidth=\"0%\"\n\t\t\t\t/>\n\t\t\t),\n\t\t});\n\n\t\tconst cluster = operationsParams.entityType === 'cluster'\n\t\t\t? await getClusterInfo(operationsParams.entityId)\n\t\t\t: null;\n\t\tconst allInstances = operationsParams.entityType === 'cluster'\n\t\t\t? cluster?.instances || []\n\t\t\t: [{ id: operationsParams.entityId, status: 'RUNNING' } as Instance];\n\t\tconst clusterUsesFabricConnect = !!cluster && authStore.checkForFabricConnect(cluster.id);\n\t\tconst instanceClients = operationsParams.entityType === 'cluster'\n\t\t\t? allInstances\n\t\t\t\t.filter(instance => instance.status === 'RUNNING')\n\t\t\t\t.map(instance =>\n\t\t\t\t\tgetInstanceClient({\n\t\t\t\t\t\tid: instance.id,\n\t\t\t\t\t\tforceFabricConnect: clusterUsesFabricConnect,\n\t\t\t\t\t\toperationsUrl: getOperationsUrlForInstance(instance),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.reverse()\n\t\t\t: [operationsParams.instanceClient];\n\t\tlet instancesRestarted = 0;\n\n\t\tif (instanceClients.length) {\n\t\t\tfor (let i = 0; i < instanceClients.length; i++) {\n\t\t\t\tconst instanceClient = instanceClients[i];\n\t\t\t\tif (!canceled) {\n\t\t\t\t\ttoast.loading(`Updating Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\tdescription: (\n\t\t\t\t\t\t\t<ProgressBar\n\t\t\t\t\t\t\t\tanimated={true}\n\t\t\t\t\t\t\t\twidth={(i === 0 ? 0 : (i / instanceClients.length * 100)) + '%'}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Make sure the instance is responding.\n\t\t\t\t\t\tawait getInstanceUserInfo({\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait setConfiguration({\n\t\t\t\t\t\t\t...params,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// Then restart it.\n\t\t\t\t\t\tawait restartInstance({\n\t\t\t\t\t\t\toperation: 'restart_service',\n\t\t\t\t\t\t\treplicated: false,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinstancesRestarted += 1;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tif (i + 1 !== instanceClients.length) {\n\t\t\t\t\t\t\t// If it fails to restart, or wasn't available, warn for a bit then move on.\n\t\t\t\t\t\t\ttoast.loading(`Failed Restarting Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\t\t\tdescription: 'We will carry on momentarily.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait sleep(3000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsetIsPending(false);\n\t\tvoid queryClient.invalidateQueries({ queryKey: [operationsParams.entityId, 'get_configuration'] });\n\n\t\tif (canceled) {\n\t\t\ttoast.error('Cancelled', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `The config update was partially cancelled.`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else if (allInstances.length === instancesRestarted) {\n\t\t\tonRestartedSuccessfully?.();\n\t\t\ttoast.success('Success', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Your configuration has been updated successfully!`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tconst allTheInstances = pluralize(allInstances.length, 'instance', 'instances');\n\t\t\tconst someRunningInstancesWere = pluralize(\n\t\t\t\tinstancesRestarted,\n\t\t\t\t'\"RUNNING\" instance was',\n\t\t\t\t'\"RUNNING\" instances were',\n\t\t\t);\n\t\t\ttoast.error('Error', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Failed to fully update cluster.\\n`\n\t\t\t\t\t+ ([\n\t\t\t\t\t\tallInstances.length === 0 && 'No instances were found within the cluster to restart.',\n\t\t\t\t\t\tinstancesRestarted === 0 && `No instances were in a \"RUNNING\" state of ${allTheInstances}.`,\n\t\t\t\t\t\tallInstances.length !== instancesRestarted\n\t\t\t\t\t\t&& `Only ${someRunningInstancesWere} restarted of ${allTheInstances}.`,\n\t\t\t\t\t].filter(excludeFalsy).shift() || ''),\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}, [operationsParams, onRestartedSuccessfully, queryClient]);\n\n\treturn {\n\t\tonConfigUpdate,\n\t\tisPending,\n\t};\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport function getOpenAPIQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'OpenAPI'] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.get('/api/openapi/rest');\n\t\t\treturn data;\n\t\t},\n\t});\n}\n","import { ErrorComponent } from '@/components/ErrorComponent';\nimport { Loading } from '@/components/Loading';\nimport { Button } from '@/components/ui/button';\nimport { useEntityRestURL } from '@/config/useEntityRestURL';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { plugins } from '@/features/instance/apis/plugins';\nimport { requestSnippets } from '@/features/instance/apis/requestSnippets';\nimport { useRollingConfigUpdate } from '@/hooks/useRollingConfigUpdate';\nimport { getConfigurationQueryOptions } from '@/integrations/api/instance/status/getConfiguration';\nimport { getOpenAPIQueryOptions } from '@/integrations/api/instance/status/getOpenAPI';\nimport { getRegistrationInfoQueryOptions } from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { wasAReleasedBeforeB } from '@/lib/string/wasAReleasedBeforeB';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { Plus } from 'lucide-react';\nimport { lazy, Suspense, useCallback } from 'react';\n\nconst SwaggerUI = lazy(() => import('swagger-ui-react'));\nimport 'swagger-ui-react/swagger-ui.css';\nimport './swagger.css';\n\nexport function APIDocs() {\n\tconst { instanceId, clusterId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst operationsParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: configurationInfo,\n\t\tisLoading: isLoadingConfiguration,\n\t} = useQuery(getConfigurationQueryOptions(operationsParams));\n\tconst { data: registrationInfo, isLoading: isLoadingRegistration } = useQuery(\n\t\tgetRegistrationInfoQueryOptions(operationsParams),\n\t);\n\tconst baseURL = useEntityRestURL();\n\tconst {\n\t\tdata: spec,\n\t\tisLoading: isLoadingDocs,\n\t\terror,\n\t} = useQuery(getOpenAPIQueryOptions(operationsParams));\n\tif (spec?.servers?.length) {\n\t\tspec.servers[0].url = baseURL;\n\t}\n\tconst http = configurationInfo?.http;\n\n\tlet apiInaccessibleWarning: string = '';\n\n\tconst corsDisabled = http?.cors === false;\n\tconst missingFromCORSList = http?.corsAccessList?.length !== undefined\n\t\t&& !http.corsAccessList.includes('*')\n\t\t&& !http.corsAccessList.includes('null')\n\t\t&& !http.corsAccessList.includes(window.location.origin);\n\tif (corsDisabled) {\n\t\tapiInaccessibleWarning = `This ${\n\t\t\tclusterId && !instanceId ? 'cluster' : 'instance'\n\t\t} has CORS disabled currently, so you won't be able to execute API requests from the browser.`;\n\t} else if (missingFromCORSList) {\n\t\tapiInaccessibleWarning = `This ${\n\t\t\tclusterId && !instanceId ? 'cluster' : 'instance'\n\t\t} has CORS enabled, but ${window.location.origin} is not allowed, so you won't be able to execute API requests from the browser.`;\n\t}\n\n\tconst { onConfigUpdate, isPending: isSettingConfiguration } = useRollingConfigUpdate();\n\tconst enableCORS = useCallback(() => {\n\t\tonConfigUpdate({\n\t\t\t...(corsDisabled\n\t\t\t\t? {\n\t\t\t\t\t'http_cors': true,\n\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(missingFromCORSList\n\t\t\t\t? {\n\t\t\t\t\t'http_corsAccessList': [\n\t\t\t\t\t\t...(http?.corsAccessList ?? []),\n\t\t\t\t\t\twindow.location.origin,\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t\t: {}),\n\t\t});\n\t}, [corsDisabled, http?.corsAccessList, missingFromCORSList, onConfigUpdate]);\n\n\tif (isLoadingConfiguration || isLoadingRegistration || isLoadingDocs) {\n\t\treturn <Loading centered={true} text=\"Looking up your instance configuration, one moment.\" />;\n\t}\n\n\tif (error) {\n\t\tlet message: string;\n\t\tif (registrationInfo?.version && !wasAReleasedBeforeB('4.7.0-beta.7', registrationInfo?.version)) {\n\t\t\tmessage =\n\t\t\t\t`API Docs are only available starting in version '4.7.0-beta.7' of Harper, please update your version ${registrationInfo.version}!`;\n\t\t} else {\n\t\t\tmessage =\n\t\t\t\t`We weren't able to look up your docs. Please check the Network tab of your developer tools to see why the docs were not accessible to Studio.`;\n\t\t}\n\n\t\treturn (\n\t\t\t<ErrorComponent\n\t\t\t\ttitle=\"API Docs Unavailable\"\n\t\t\t\terror={{ message }}\n\t\t\t\tshowReturnToHome={false}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{apiInaccessibleWarning && (\n\t\t\t\t<ErrorComponent\n\t\t\t\t\ttitle=\"CORS Disabled: HTTP API Not Accessible\"\n\t\t\t\t\tclassName=\"mt-0 mx-4 m-0 border-yellow text-yellow\"\n\t\t\t\t\terror={{ message: apiInaccessibleWarning }}\n\t\t\t\t\tshowReturnToHome={false}\n\t\t\t\t>\n\t\t\t\t\t<Button disabled={isSettingConfiguration} variant=\"warning\" className=\"rounded-full\" onClick={enableCORS}>\n\t\t\t\t\t\t<Plus />\n\t\t\t\t\t\t{isSettingConfiguration ? 'Enabling CORS...' : `Enable CORS for ${window.location.origin}`}\n\t\t\t\t\t</Button>\n\t\t\t\t</ErrorComponent>\n\t\t\t)}\n\t\t\t<Suspense fallback={<Loading centered={true} text=\"Loading API documentation...\" />}>\n\t\t\t\t<SwaggerUI\n\t\t\t\t\tspec={spec}\n\t\t\t\t\tpersistAuthorization={true}\n\t\t\t\t\twithCredentials={true}\n\t\t\t\t\trequestSnippetsEnabled={true}\n\t\t\t\t\tdefaultModelRendering=\"model\"\n\t\t\t\t\trequestSnippets={requestSnippets}\n\t\t\t\t\tplugins={plugins}\n\t\t\t\t\ttryItOutEnabled={true}\n\t\t\t\t/>\n\t\t\t</Suspense>\n\t\t</>\n\t);\n}\n","import { APIDocs } from '@/features/instance/apis/APIDocs';\nimport { createLazyRoute } from '@tanstack/react-router';\n\nexport const route = createLazyRoute('/apis')({\n\tcomponent: APIDocs,\n});\n"],"file":"index.lazy-iG1_8dzm.js"}
|
|
1
|
+
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/features/instance/apis/plugins.ts","../../src/features/instance/apis/requestSnippets.ts","../../src/integrations/api/instance/status/setConfiguration.ts","../../src/hooks/useRollingConfigUpdate.tsx","../../src/integrations/api/instance/status/getOpenAPI.ts","../../src/features/instance/apis/APIDocs.tsx","../../src/features/instance/apis/index.lazy.tsx"],"sourcesContent":["export const SnippedGeneratorNodeJsPlugin = {\n\tfn: {\n\t\trequestSnippetGenerator_fetch: (request: { get: (key: string) => unknown }) => {\n\t\t\tconst url = new URL(request.get('url') as string);\n\t\t\tlet isMultipartFormDataRequest = false;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst headers = request.get('headers') as any;\n\t\t\tif (headers && headers.size) {\n\t\t\t\theaders.map((val: string, key: string) => {\n\t\t\t\t\tisMultipartFormDataRequest = isMultipartFormDataRequest\n\t\t\t\t\t\t|| /^content-type$/i.test(key) && /^multipart\\/form-data$/i.test(val);\n\t\t\t\t});\n\t\t\t}\n\t\t\tlet reqBody = request.get('body') as string | object;\n\t\t\tconst reqMethod = request.get('method') as string;\n\t\t\tif (reqBody) {\n\t\t\t\tif (isMultipartFormDataRequest && ['POST', 'PUT', 'PATCH'].includes(reqMethod)) {\n\t\t\t\t\treturn 'throw new Error(\"Currently unsupported content-type: /^multipart\\\\/form-data$/i\");';\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof reqBody !== 'string') {\n\t\t\t\t\t\treqBody = JSON.stringify(reqBody, null, '\\t');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (!reqBody && reqMethod === 'POST') {\n\t\t\t\treqBody = '';\n\t\t\t}\n\n\t\t\tconst stringBody = '`' + (reqBody || '')\n\t\t\t\t.replace(/\\\\n/g, '\\n')\n\t\t\t\t.replace(/`/g, '\\\\`')\n\t\t\t\t+ '`';\n\n\t\t\treturn `const response = await fetch(\"${url.toString()}\", {\n\\tmethod: \"${request.get('method')}\",${\n\t\t\t\theaders && headers.size\n\t\t\t\t\t? `\n\\theaders: {\n\\t\\t${headers.map((val: string, key: string) => `\"${key}\": \"${val}\"`).valueSeq().join(',\\n\\t\\t')}\n\\t},`\n\t\t\t\t\t: ''\n\t\t\t}${\n\t\t\t\treqBody\n\t\t\t\t\t? `\n\\tbody: ${stringBody},`\n\t\t\t\t\t: ''\n\t\t\t}\n});\nconst data = await response.json();\nconsole.log(data);\n`;\n\t\t},\n\t},\n};\n\nexport const plugins = [\n\tSnippedGeneratorNodeJsPlugin,\n];\n","export const requestSnippets = {\n\tgenerators: {\n\t\tfetch: {\n\t\t\ttitle: 'Fetch',\n\t\t\tsyntax: 'javascript',\n\t\t},\n\t},\n};\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\n\ninterface SetConfigurationParams extends InstanceClientConfig {\n\t[key: string]: unknown;\n}\n\nexport async function setConfiguration({\n\tinstanceClient,\n\t...changes\n}: SetConfigurationParams): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'set_configuration',\n\t\t...changes,\n\t});\n\treturn data;\n}\n","import { ProgressBar } from '@/components/ProgressBar';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfo } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { Instance } from '@/integrations/api/api.patch';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { restartInstance } from '@/integrations/api/instance/status/restartInstance';\nimport { setConfiguration } from '@/integrations/api/instance/status/setConfiguration';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { pluralize } from '@/lib/pluralize';\nimport { sleep } from '@/lib/sleep';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\ninterface RollingConfigUpdateParams {\n\tonRestartedSuccessfully?: () => void;\n}\n\ninterface RollingConfigUpdateResponse {\n\tonConfigUpdate: (params: Record<string, unknown>) => void;\n\tisPending: boolean;\n}\n\nexport function useRollingConfigUpdate(\n\t{ onRestartedSuccessfully }: RollingConfigUpdateParams = {},\n): RollingConfigUpdateResponse {\n\tconst operationsParams = useInstanceClientIdParams();\n\tconst queryClient = useQueryClient();\n\tconst [isPending, setIsPending] = useState(false);\n\tconst onConfigUpdate = useCallback(async (params: Record<string, unknown>) => {\n\t\tsetIsPending(true);\n\n\t\tlet canceled = false;\n\t\tconst toastConfig = {\n\t\t\tduration: 60_000,\n\t\t\taction: {\n\t\t\t\tlabel: 'Cancel',\n\t\t\t\tonClick: () => {\n\t\t\t\t\tcanceled = true;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tconst toastId = toast.loading('Restarting', {\n\t\t\t...toastConfig,\n\t\t\tdescription: (\n\t\t\t\t<ProgressBar\n\t\t\t\t\tanimated={true}\n\t\t\t\t\twidth=\"0%\"\n\t\t\t\t/>\n\t\t\t),\n\t\t});\n\n\t\tconst cluster = operationsParams.entityType === 'cluster'\n\t\t\t? await getClusterInfo(operationsParams.entityId)\n\t\t\t: null;\n\t\tconst allInstances = operationsParams.entityType === 'cluster'\n\t\t\t? cluster?.instances || []\n\t\t\t: [{ id: operationsParams.entityId, status: 'RUNNING' } as Instance];\n\t\tconst clusterUsesFabricConnect = !!cluster && authStore.checkForFabricConnect(cluster.id);\n\t\tconst instanceClients = operationsParams.entityType === 'cluster'\n\t\t\t? allInstances\n\t\t\t\t.filter(instance => instance.status === 'RUNNING')\n\t\t\t\t.map(instance =>\n\t\t\t\t\tgetInstanceClient({\n\t\t\t\t\t\tid: instance.id,\n\t\t\t\t\t\tforceFabricConnect: clusterUsesFabricConnect,\n\t\t\t\t\t\toperationsUrl: getOperationsUrlForInstance(instance),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.reverse()\n\t\t\t: [operationsParams.instanceClient];\n\t\tlet instancesRestarted = 0;\n\n\t\tif (instanceClients.length) {\n\t\t\tfor (let i = 0; i < instanceClients.length; i++) {\n\t\t\t\tconst instanceClient = instanceClients[i];\n\t\t\t\tif (!canceled) {\n\t\t\t\t\ttoast.loading(`Updating Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\tdescription: (\n\t\t\t\t\t\t\t<ProgressBar\n\t\t\t\t\t\t\t\tanimated={true}\n\t\t\t\t\t\t\t\twidth={(i === 0 ? 0 : (i / instanceClients.length * 100)) + '%'}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Make sure the instance is responding.\n\t\t\t\t\t\tawait getInstanceUserInfo({\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait setConfiguration({\n\t\t\t\t\t\t\t...params,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// Then restart it.\n\t\t\t\t\t\tawait restartInstance({\n\t\t\t\t\t\t\toperation: 'restart_service',\n\t\t\t\t\t\t\treplicated: false,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinstancesRestarted += 1;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tif (i + 1 !== instanceClients.length) {\n\t\t\t\t\t\t\t// If it fails to restart, or wasn't available, warn for a bit then move on.\n\t\t\t\t\t\t\ttoast.loading(`Failed Restarting Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\t\t\tdescription: 'We will carry on momentarily.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait sleep(3000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsetIsPending(false);\n\t\tvoid queryClient.invalidateQueries({ queryKey: [operationsParams.entityId, 'get_configuration'] });\n\n\t\tif (canceled) {\n\t\t\ttoast.error('Cancelled', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `The config update was partially cancelled.`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else if (allInstances.length === instancesRestarted) {\n\t\t\tonRestartedSuccessfully?.();\n\t\t\ttoast.success('Success', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Your configuration has been updated successfully!`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tconst allTheInstances = pluralize(allInstances.length, 'instance', 'instances');\n\t\t\tconst someRunningInstancesWere = pluralize(\n\t\t\t\tinstancesRestarted,\n\t\t\t\t'\"RUNNING\" instance was',\n\t\t\t\t'\"RUNNING\" instances were',\n\t\t\t);\n\t\t\ttoast.error('Error', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Failed to fully update cluster.\\n`\n\t\t\t\t\t+ ([\n\t\t\t\t\t\tallInstances.length === 0 && 'No instances were found within the cluster to restart.',\n\t\t\t\t\t\tinstancesRestarted === 0 && `No instances were in a \"RUNNING\" state of ${allTheInstances}.`,\n\t\t\t\t\t\tallInstances.length !== instancesRestarted\n\t\t\t\t\t\t&& `Only ${someRunningInstancesWere} restarted of ${allTheInstances}.`,\n\t\t\t\t\t].filter(excludeFalsy).shift() || ''),\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}, [operationsParams, onRestartedSuccessfully, queryClient]);\n\n\treturn {\n\t\tonConfigUpdate,\n\t\tisPending,\n\t};\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport function getOpenAPIQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'OpenAPI'] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.get('/api/openapi/rest');\n\t\t\treturn data;\n\t\t},\n\t});\n}\n","import { ErrorComponent } from '@/components/ErrorComponent';\nimport { Loading } from '@/components/Loading';\nimport { Button } from '@/components/ui/button';\nimport { useEntityRestURL } from '@/config/useEntityRestURL';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { plugins } from '@/features/instance/apis/plugins';\nimport { requestSnippets } from '@/features/instance/apis/requestSnippets';\nimport { useRollingConfigUpdate } from '@/hooks/useRollingConfigUpdate';\nimport { getConfigurationQueryOptions } from '@/integrations/api/instance/status/getConfiguration';\nimport { getOpenAPIQueryOptions } from '@/integrations/api/instance/status/getOpenAPI';\nimport { getRegistrationInfoQueryOptions } from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { wasAReleasedBeforeB } from '@/lib/string/wasAReleasedBeforeB';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { Plus } from 'lucide-react';\nimport { lazy, Suspense, useCallback } from 'react';\n\nconst SwaggerUI = lazy(() => import('swagger-ui-react'));\nimport 'swagger-ui-react/swagger-ui.css';\nimport './swagger.css';\n\nexport function APIDocs() {\n\tconst { instanceId, clusterId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst operationsParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: configurationInfo,\n\t\tisLoading: isLoadingConfiguration,\n\t} = useQuery(getConfigurationQueryOptions(operationsParams));\n\tconst { data: registrationInfo, isLoading: isLoadingRegistration } = useQuery(\n\t\tgetRegistrationInfoQueryOptions(operationsParams),\n\t);\n\tconst baseURL = useEntityRestURL();\n\tconst {\n\t\tdata: spec,\n\t\tisLoading: isLoadingDocs,\n\t\terror,\n\t} = useQuery(getOpenAPIQueryOptions(operationsParams));\n\tif (spec?.servers?.length) {\n\t\tspec.servers[0].url = baseURL;\n\t}\n\tconst http = configurationInfo?.http;\n\n\tlet apiInaccessibleWarning: string = '';\n\n\tconst corsDisabled = http?.cors === false;\n\tconst missingFromCORSList = http?.corsAccessList?.length !== undefined\n\t\t&& !http.corsAccessList.includes('*')\n\t\t&& !http.corsAccessList.includes('null')\n\t\t&& !http.corsAccessList.includes(window.location.origin);\n\tif (corsDisabled) {\n\t\tapiInaccessibleWarning = `This ${\n\t\t\tclusterId && !instanceId ? 'cluster' : 'instance'\n\t\t} has CORS disabled currently, so you won't be able to execute API requests from the browser.`;\n\t} else if (missingFromCORSList) {\n\t\tapiInaccessibleWarning = `This ${\n\t\t\tclusterId && !instanceId ? 'cluster' : 'instance'\n\t\t} has CORS enabled, but ${window.location.origin} is not allowed, so you won't be able to execute API requests from the browser.`;\n\t}\n\n\tconst { onConfigUpdate, isPending: isSettingConfiguration } = useRollingConfigUpdate();\n\tconst enableCORS = useCallback(() => {\n\t\tonConfigUpdate({\n\t\t\t...(corsDisabled\n\t\t\t\t? {\n\t\t\t\t\t'http_cors': true,\n\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(missingFromCORSList\n\t\t\t\t? {\n\t\t\t\t\t'http_corsAccessList': [\n\t\t\t\t\t\t...(http?.corsAccessList ?? []),\n\t\t\t\t\t\twindow.location.origin,\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t\t: {}),\n\t\t});\n\t}, [corsDisabled, http?.corsAccessList, missingFromCORSList, onConfigUpdate]);\n\n\tif (isLoadingConfiguration || isLoadingRegistration || isLoadingDocs) {\n\t\treturn <Loading centered={true} text=\"Looking up your instance configuration, one moment.\" />;\n\t}\n\n\tif (error) {\n\t\tlet message: string;\n\t\tif (registrationInfo?.version && !wasAReleasedBeforeB('4.7.0-beta.7', registrationInfo?.version)) {\n\t\t\tmessage =\n\t\t\t\t`API Docs are only available starting in version '4.7.0-beta.7' of Harper, please update your version ${registrationInfo.version}!`;\n\t\t} else {\n\t\t\tmessage =\n\t\t\t\t`We weren't able to look up your docs. Please check the Network tab of your developer tools to see why the docs were not accessible to Studio.`;\n\t\t}\n\n\t\treturn (\n\t\t\t<ErrorComponent\n\t\t\t\ttitle=\"API Docs Unavailable\"\n\t\t\t\terror={{ message }}\n\t\t\t\tshowReturnToHome={false}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{apiInaccessibleWarning && (\n\t\t\t\t<ErrorComponent\n\t\t\t\t\ttitle=\"CORS Disabled: HTTP API Not Accessible\"\n\t\t\t\t\tclassName=\"mt-0 mx-4 m-0 border-yellow text-yellow\"\n\t\t\t\t\terror={{ message: apiInaccessibleWarning }}\n\t\t\t\t\tshowReturnToHome={false}\n\t\t\t\t>\n\t\t\t\t\t<Button disabled={isSettingConfiguration} variant=\"warning\" className=\"rounded-full\" onClick={enableCORS}>\n\t\t\t\t\t\t<Plus />\n\t\t\t\t\t\t{isSettingConfiguration ? 'Enabling CORS...' : `Enable CORS for ${window.location.origin}`}\n\t\t\t\t\t</Button>\n\t\t\t\t</ErrorComponent>\n\t\t\t)}\n\t\t\t<Suspense fallback={<Loading centered={true} text=\"Loading API documentation...\" />}>\n\t\t\t\t<SwaggerUI\n\t\t\t\t\tspec={spec}\n\t\t\t\t\tpersistAuthorization={true}\n\t\t\t\t\twithCredentials={true}\n\t\t\t\t\trequestSnippetsEnabled={true}\n\t\t\t\t\tdefaultModelRendering=\"model\"\n\t\t\t\t\trequestSnippets={requestSnippets}\n\t\t\t\t\tplugins={plugins}\n\t\t\t\t\ttryItOutEnabled={true}\n\t\t\t\t/>\n\t\t\t</Suspense>\n\t\t</>\n\t);\n}\n","import { APIDocs } from '@/features/instance/apis/APIDocs';\nimport { createLazyRoute } from '@tanstack/react-router';\n\nexport const route = createLazyRoute('/apis')({\n\tcomponent: APIDocs,\n});\n"],"file":"index.lazy-CXzU1gVu.js"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{m as t,n,r}from"./cn-BnE9QzQD.js";import{Kt as i,Wt as a}from"./vendor-core-BY_ZlgBF.js";import{$i as o,An as s,Fn as c,Ki as l,Qi as u,Qn as d,Ui as f,fr as p,zi as m}from"./vendor-react-DrZSc0Lm.js";import"./vendor-misc-BBL3Mh21.js";import{n as h,t as g}from"./button-DWsEHYDp.js";import{C as _,D as v,E as y,O as b,S as x,T as S,k as C,x as w}from"./index-
|
|
2
|
-
//# sourceMappingURL=profile-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{m as t,n,r}from"./cn-BnE9QzQD.js";import{Kt as i,Wt as a}from"./vendor-core-BY_ZlgBF.js";import{$i as o,An as s,Fn as c,Ki as l,Qi as u,Qn as d,Ui as f,fr as p,zi as m}from"./vendor-react-DrZSc0Lm.js";import"./vendor-misc-BBL3Mh21.js";import{n as h,t as g}from"./button-DWsEHYDp.js";import{C as _,D as v,E as y,O as b,S as x,T as S,k as C,x as w}from"./index-ClD_q6ya.js";async function T(e){let{id:n,newPassword:r,confirmNewPassword:i,...a}=e,o={...a};r&&r===i&&(o.password=r);let{data:s}=await t.patch(`/User/${n}`,o);return s}function E(){return l({mutationFn:e=>T(e)})}var D=a({id:i(),firstname:i({error:`Please enter your first name.`}).min(2,{error:`First name is required.`}).max(50,{error:`First name must be less than 50 characters.`}),lastname:i({error:`Please enter your last name.`}).min(2,{error:`Last name is required.`}).max(50,{error:`Last name must be less than 50 characters.`}),newPassword:i({error:`Please enter your new password.`}).min(8,{error:`Password must be 8 characters or more.`}).or(i().max(0)),confirmNewPassword:i().optional()}).refine(e=>e.newPassword===e.confirmNewPassword,{error:`Passwords do not match`,path:[`confirmNewPassword`]}),O=e(o(),1),k=u();function A(){let e=f(),t=m(),{user:i}=h(),a=c({resolver:s(D),defaultValues:{confirmNewPassword:``,firstname:i?.firstname||``,id:i?.id||``,lastname:i?.lastname||``,newPassword:``}}),{control:o,handleSubmit:l,reset:u,formState:{defaultValues:T,isDirty:A,isValid:j}}=a,{mutate:M,isPending:N}=E(),P=(0,O.useCallback)(async i=>{i&&M(i,{onSuccess:a=>{u({...T,...a}),r.updateUserForEntity(n,a),i.newPassword?(d.success(`Profile updated successfully!`,{description:`Please sign in with your new password.`}),C(),t({to:`/sign-in`}),e.invalidate()):d.success(`Profile updated successfully!`)}})},[T,t,u,e,M]);return(0,k.jsxs)(`div`,{className:`mt-20 px-4 pt-4 md:px-12`,children:[(0,k.jsx)(`h2`,{className:`text-2xl font-light`,children:`Profile`}),(0,k.jsx)(b,{...a,children:(0,k.jsxs)(`form`,{id:`profile-edit-form`,name:`profile-edit-form`,onSubmit:l(P),className:`grid gap-4 my-4`,children:[(0,k.jsx)(y,{control:o,name:`firstname`,render:({field:e})=>(0,k.jsxs)(S,{children:[(0,k.jsx)(_,{className:`pb-1`,children:`First Name`}),(0,k.jsx)(v,{children:(0,k.jsx)(w,{type:`text`,className:`bg-purple-400 border-purple-400 dark:bg-black dark:border-black`,autoCapitalize:`words`,...e})}),(0,k.jsx)(x,{})]})}),(0,k.jsx)(y,{control:o,name:`lastname`,render:({field:e})=>(0,k.jsxs)(S,{children:[(0,k.jsx)(_,{className:`pb-1`,children:`Last Name`}),(0,k.jsx)(v,{children:(0,k.jsx)(w,{type:`text`,className:`bg-purple-400 border-purple-400 dark:bg-black dark:border-black`,autoCapitalize:`words`,...e})}),(0,k.jsx)(x,{})]})}),(0,k.jsx)(_,{className:`pb-1`,children:`Email`}),(0,k.jsx)(v,{children:(0,k.jsx)(w,{type:`email`,enterKeyHint:`next`,autoComplete:`email`,autoCapitalize:`none`,value:i?.email||``,disabled:!0,readOnly:!0})}),(0,k.jsx)(y,{control:o,name:`newPassword`,render:({field:e})=>(0,k.jsxs)(S,{children:[(0,k.jsx)(_,{className:`pb-1`,children:`New Password`}),(0,k.jsx)(v,{children:(0,k.jsx)(w,{type:`password`,placeholder:`Optional`,className:`bg-purple-400 border-purple-400 dark:bg-black dark:border-black`,autoComplete:`new-password`,autoCapitalize:`none`,...e})}),(0,k.jsx)(x,{})]})}),(0,k.jsx)(y,{control:o,name:`confirmNewPassword`,render:({field:e})=>(0,k.jsxs)(S,{children:[(0,k.jsx)(_,{className:`pb-1`,children:`Confirm New Password`}),(0,k.jsx)(v,{children:(0,k.jsx)(w,{type:`password`,className:`bg-purple-400 border-purple-400 dark:bg-black dark:border-black`,autoComplete:`new-password`,autoCapitalize:`none`,...e})}),(0,k.jsx)(x,{})]})}),(0,k.jsx)(`div`,{className:`flex justify-between w-full`,children:(0,k.jsxs)(g,{type:`submit`,variant:`submit`,className:`rounded-full`,disabled:N||!A||!j,children:[(0,k.jsx)(p,{}),` Update Profile`]})})]})})]})}export{A as ProfileIndex};
|
|
2
|
+
//# sourceMappingURL=profile-DCNVg5yY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-CzjslUXv.js","names":[],"sources":["../../src/features/profile/mutations/updateUserMutation.ts","../../src/features/profile/mutations/updateUserSchema.ts","../../src/features/profile/index.tsx"],"sourcesContent":["import { apiClient } from '@/config/apiClient';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { User } from '@/integrations/api/api.patch';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nasync function onUpdateUser(formData: z.infer<typeof UpdateUserSchema>) {\n\tconst { id, newPassword, confirmNewPassword, ...otherFields } = formData;\n\tconst userData: Partial<SchemaUser & { password: string }> = {\n\t\t...otherFields,\n\t};\n\tif (newPassword && newPassword === confirmNewPassword) {\n\t\tuserData.password = newPassword;\n\t}\n\tconst { data } = await apiClient.patch(`/User/${id}` as '/User/{id}', userData);\n\treturn data as Partial<User>;\n}\n\nexport function useUpdateUserMutation() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof UpdateUserSchema>) => onUpdateUser(formData),\n\t});\n}\n","import { z } from 'zod';\n\nexport const UpdateUserSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tfirstname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your first name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'First name is required.' })\n\t\t\t.max(50, { error: 'First name must be less than 50 characters.' }),\n\t\tlastname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your last name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'Last name is required.' })\n\t\t\t.max(50, { error: 'Last name must be less than 50 characters.' }),\n\t\tnewPassword: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your new password.',\n\t\t\t})\n\t\t\t.min(8, { error: 'Password must be 8 characters or more.' })\n\t\t\t.or(z.string().max(0)),\n\t\tconfirmNewPassword: z\n\t\t\t.string()\n\t\t\t.optional(),\n\t})\n\t.refine((data) => data.newPassword === data.confirmNewPassword, {\n\t\terror: 'Passwords do not match',\n\t\tpath: ['confirmNewPassword'],\n\t});\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { logoutOnSuccess } from '@/features/auth/handlers/logoutOnSuccess';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useUpdateUserMutation } from '@/features/profile/mutations/updateUserMutation';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useNavigate, useRouter } from '@tanstack/react-router';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function ProfileIndex() {\n\tconst router = useRouter();\n\tconst navigate = useNavigate();\n\tconst { user } = useCloudAuth();\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(UpdateUserSchema),\n\t\tdefaultValues: {\n\t\t\tconfirmNewPassword: '',\n\t\t\tfirstname: user?.firstname || '',\n\t\t\tid: user?.id || '',\n\t\t\tlastname: user?.lastname || '',\n\t\t\tnewPassword: '',\n\t\t},\n\t});\n\tconst { control, handleSubmit, reset, formState: { defaultValues, isDirty, isValid } } = methods;\n\tconst { mutate: updateUser, isPending: isUpdatePending } = useUpdateUserMutation();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof UpdateUserSchema>) => {\n\t\t\tif (formData) {\n\t\t\t\tupdateUser(formData, {\n\t\t\t\t\tonSuccess: (data) => {\n\t\t\t\t\t\treset({\n\t\t\t\t\t\t\t...defaultValues,\n\t\t\t\t\t\t\t...data,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tauthStore.updateUserForEntity(OverallAppSignIn, data);\n\t\t\t\t\t\tif (formData.newPassword) {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!', {\n\t\t\t\t\t\t\t\tdescription: 'Please sign in with your new password.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tlogoutOnSuccess();\n\t\t\t\t\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t\t\t\t\t\tvoid router.invalidate();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!');\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[defaultValues, navigate, reset, router, updateUser],\n\t);\n\n\treturn (\n\t\t<div className=\"mt-20 px-4 pt-4 md:px-12\">\n\t\t\t<h2 className=\"text-2xl font-light\">Profile</h2>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"profile-edit-form\"\n\t\t\t\t\tname=\"profile-edit-form\"\n\t\t\t\t\tonSubmit={handleSubmit(onSubmitClick)}\n\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"firstname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">First Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"lastname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Last Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormLabel className=\"pb-1\">Email</FormLabel>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\tvalue={user?.email || ''}\n\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"newPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"Optional\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"confirmNewPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tdisabled={isUpdatePending || !isDirty || !isValid}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save /> Update Profile\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"profile-DCNVg5yY.js","names":[],"sources":["../../src/features/profile/mutations/updateUserMutation.ts","../../src/features/profile/mutations/updateUserSchema.ts","../../src/features/profile/index.tsx"],"sourcesContent":["import { apiClient } from '@/config/apiClient';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { User } from '@/integrations/api/api.patch';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nasync function onUpdateUser(formData: z.infer<typeof UpdateUserSchema>) {\n\tconst { id, newPassword, confirmNewPassword, ...otherFields } = formData;\n\tconst userData: Partial<SchemaUser & { password: string }> = {\n\t\t...otherFields,\n\t};\n\tif (newPassword && newPassword === confirmNewPassword) {\n\t\tuserData.password = newPassword;\n\t}\n\tconst { data } = await apiClient.patch(`/User/${id}` as '/User/{id}', userData);\n\treturn data as Partial<User>;\n}\n\nexport function useUpdateUserMutation() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof UpdateUserSchema>) => onUpdateUser(formData),\n\t});\n}\n","import { z } from 'zod';\n\nexport const UpdateUserSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tfirstname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your first name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'First name is required.' })\n\t\t\t.max(50, { error: 'First name must be less than 50 characters.' }),\n\t\tlastname: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your last name.',\n\t\t\t})\n\t\t\t.min(2, { error: 'Last name is required.' })\n\t\t\t.max(50, { error: 'Last name must be less than 50 characters.' }),\n\t\tnewPassword: z\n\t\t\t.string({\n\t\t\t\terror: 'Please enter your new password.',\n\t\t\t})\n\t\t\t.min(8, { error: 'Password must be 8 characters or more.' })\n\t\t\t.or(z.string().max(0)),\n\t\tconfirmNewPassword: z\n\t\t\t.string()\n\t\t\t.optional(),\n\t})\n\t.refine((data) => data.newPassword === data.confirmNewPassword, {\n\t\terror: 'Passwords do not match',\n\t\tpath: ['confirmNewPassword'],\n\t});\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { logoutOnSuccess } from '@/features/auth/handlers/logoutOnSuccess';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useUpdateUserMutation } from '@/features/profile/mutations/updateUserMutation';\nimport { UpdateUserSchema } from '@/features/profile/mutations/updateUserSchema';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useNavigate, useRouter } from '@tanstack/react-router';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function ProfileIndex() {\n\tconst router = useRouter();\n\tconst navigate = useNavigate();\n\tconst { user } = useCloudAuth();\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(UpdateUserSchema),\n\t\tdefaultValues: {\n\t\t\tconfirmNewPassword: '',\n\t\t\tfirstname: user?.firstname || '',\n\t\t\tid: user?.id || '',\n\t\t\tlastname: user?.lastname || '',\n\t\t\tnewPassword: '',\n\t\t},\n\t});\n\tconst { control, handleSubmit, reset, formState: { defaultValues, isDirty, isValid } } = methods;\n\tconst { mutate: updateUser, isPending: isUpdatePending } = useUpdateUserMutation();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof UpdateUserSchema>) => {\n\t\t\tif (formData) {\n\t\t\t\tupdateUser(formData, {\n\t\t\t\t\tonSuccess: (data) => {\n\t\t\t\t\t\treset({\n\t\t\t\t\t\t\t...defaultValues,\n\t\t\t\t\t\t\t...data,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tauthStore.updateUserForEntity(OverallAppSignIn, data);\n\t\t\t\t\t\tif (formData.newPassword) {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!', {\n\t\t\t\t\t\t\t\tdescription: 'Please sign in with your new password.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tlogoutOnSuccess();\n\t\t\t\t\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t\t\t\t\t\tvoid router.invalidate();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoast.success('Profile updated successfully!');\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[defaultValues, navigate, reset, router, updateUser],\n\t);\n\n\treturn (\n\t\t<div className=\"mt-20 px-4 pt-4 md:px-12\">\n\t\t\t<h2 className=\"text-2xl font-light\">Profile</h2>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"profile-edit-form\"\n\t\t\t\t\tname=\"profile-edit-form\"\n\t\t\t\t\tonSubmit={handleSubmit(onSubmitClick)}\n\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"firstname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">First Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"lastname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Last Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormLabel className=\"pb-1\">Email</FormLabel>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\tvalue={user?.email || ''}\n\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"newPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tplaceholder=\"Optional\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"confirmNewPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tdisabled={isUpdatePending || !isDirty || !isValid}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save /> Update Profile\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{t}from"./cn-BnE9QzQD.js";import"./vendor-core-BY_ZlgBF.js";import{$i as n,Ji as r,Qi as i,Yi as a,a as o,i as s,n as c,o as l,qi as u,r as d,s as f,t as p}from"./vendor-react-DrZSc0Lm.js";import"./vendor-misc-BBL3Mh21.js";import{A as m,_ as h,c as g,d as _,f as v,g as y,h as b,j as x,l as S,m as C,p as w,s as T,u as E,w as D}from"./index-
|
|
2
|
-
//# sourceMappingURL=status-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{t}from"./cn-BnE9QzQD.js";import"./vendor-core-BY_ZlgBF.js";import{$i as n,Ji as r,Qi as i,Yi as a,a as o,i as s,n as c,o as l,qi as u,r as d,s as f,t as p}from"./vendor-react-DrZSc0Lm.js";import"./vendor-misc-BBL3Mh21.js";import{A as m,_ as h,c as g,d as _,f as v,g as y,h as b,j as x,l as S,m as C,p as w,s as T,u as E,w as D}from"./index-ClD_q6ya.js";var O=new Date(2025,0).getTime(),k=1440*60*1e3;function A(e){let t=[];for(let n in e){let r=e[n];t.push(...M(n,r,0))}return t}function j(e){return!!e.title}function M(e,t,n,r){if(t&&Array.isArray(t)){let r=t;return[r.length>1&&{title:e,depth:n},...t.map((t,i)=>M(r.length>1?String(i+1):e,t,n+1,e)).flat(1)].filter(x)}if(N(t)){let r=t;return[{title:e,depth:n},...Object.keys(t).map(t=>M(String(t),r[t],n+1,e)).flat(1)]}return(e===`__updatedtime__`||e===`__createdtime__`)&&(e=e.replace(/_/g,``).replace(`time`,``)),typeof t==`number`?t>O&&t<Date.now()+k?t=T(Date.now()-t,t):r===`memory`?t=g(t):!e.startsWith(`raw`)&&e.toLowerCase().includes(`load`)&&(t=Math.round(t*10)/10+`%`):typeof t==`boolean`&&(t=t?`Yes`:`No`),[{name:e,value:String(t),depth:n}]}function N(e){return!!e&&typeof e==`object`}var P=e(n(),1),F=i();function I({data:e}){return(0,F.jsx)(`div`,{className:`max-w-96 grid mb-12`,children:(0,P.useMemo)(()=>A(e),[e]).map((e,n)=>j(e)?(0,F.jsx)(`div`,{className:t(`font-semibold text-xl`,n!==0&&`mt-4`),style:{paddingLeft:e.depth*12+`px`},children:e.title},n):(0,F.jsxs)(`div`,{style:{paddingLeft:e.depth*12+`px`},children:[(0,F.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.name,`:`]}),e.value]},n))})}function L({metricConfig:e,startTime:t,endTime:n,instanceParams:r}){return u({queryKey:[`get_analytics`,e.name,e.path,t,n],queryFn:async()=>{let i={operation:`get_analytics`,metric:e.name,start_time:t,end_time:n};e.path&&(i.conditions=[{attribute:`path`,value:e.path}]);let{data:a}=await r.instanceClient.post(`/`,i);return a}})}var R={"persistence-purple":`#403B8A`,"b-tree-green":`#55C58F`,"cyber-grape":`#7A3A87`,"quantum-purple":`#312556`,"cloud-white":`#F5F5F5`,"acid-magenta":`#C63368`,"edge-gray":`#383D40`};function z(e,t,n,r){let i;return i=typeof t==`string`?e[t]??0:t(e),r?E(i,n,r):i}function B({metricConfig:e,startTime:t,endTime:n,instanceParams:r}){let{data:i}=a(L({instanceParams:r,metricConfig:e,startTime:t,endTime:n})),u=(0,P.useMemo)(()=>i?.reduce((e,t)=>{let n={metric:``,node:``,id:0,period:0,count:0,mean:0};for(let e in t)t[e]!==null&&(n[e]=t[e]);return e.push(n),e},[]),[i]),[m,h]=(0,P.useState)(e.units),g=(0,P.useMemo)(()=>{let t={},{dataKey:n,aggregator:r,units:i}=e,a=i;if(u&&u.length>0){a=S(i,Math.max(...u.map(e=>z(e,n,i)))),h(a);for(let e of u){let o=Math.floor(e.id/e.period)*e.period,s=z(e,n,i,a);t[o]?e.node in t[o]?t[o][e.node]=r(t[o][e.node],s):t[o][e.node]=s:t[o]={[e.node]:s}}return Object.keys(t).map(e=>{let n=Number.parseInt(e),r=t[e];return{id:n,...Object.keys(t[e]).reduce((e,t)=>(e[t]=r[t].toFixed(2),e),{})}})}},[u,e]),_=(0,P.useMemo)(()=>Array.from(new Set(u?.map(e=>e.node))),[u]),v=e=>new Date(e).toLocaleDateString(void 0,{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,hour12:!1});return g&&g.length>0?(0,F.jsx)(f,{width:`100%`,height:600,className:`mt-8`,children:(0,F.jsxs)(p,{width:600,height:300,data:g,children:[_.map((t,n)=>{let r=e.name;e.path&&(r+=`.`+e.path);let i=r+`.`+t;return(0,F.jsx)(s,{name:t,dataKey:t,stroke:Object.values(R)[n]},i)}),(0,F.jsx)(d,{dataKey:e=>v(e.id)}),(0,F.jsx)(c,{unit:` ${m}`,width:100}),(0,F.jsx)(l,{}),(0,F.jsx)(o,{})]})}):(0,F.jsx)(`div`,{className:`mt-8 h-[600px]`,children:(0,F.jsxs)(`p`,{children:[`No `,e.name,` data for this time period`]})})}var V=typeof window<`u`?P.useLayoutEffect:P.useEffect;function H(e,t){let n=(0,P.useRef)(e);V(()=>{n.current=e},[e]),(0,P.useEffect)(()=>{if(t===null)return;let e=setInterval(()=>{n.current()},t);return()=>{clearInterval(e)}},[t])}var U=[{id:`db-read`,name:`db-read`,dataKey:`count`,aggregator:G,units:`reads`},{id:`db-read-bytes`,label:`db-read-bytes`,name:`db-read`,dataKey:W,aggregator:G,units:`bytes`},{id:`db-write`,name:`db-write`,dataKey:`count`,aggregator:G,units:`writes`},{id:`db-write-bytes`,label:`db-write-bytes`,name:`db-write`,dataKey:W,aggregator:G,units:`bytes`},{id:`db-message`,name:`db-message`,dataKey:`count`,aggregator:G,units:`messages`},{id:`db-message-bytes`,label:`db-message-bytes`,name:`db-message`,dataKey:W,aggregator:G,units:`bytes`},{id:`cpu-usage-user`,name:`cpu-usage`,path:`user`,dataKey:W,aggregator:G,units:`secs`},{id:`cpu-usage-harper`,name:`cpu-usage`,path:`harper`,dataKey:W,aggregator:G,units:`secs`}];function W(e){return e.mean&&e.count?e.mean*e.count:0}function G(e,t){return e+t}var K=[{label:`10 mins`,value:10*6e4},{label:`hour`,value:60*6e4,default:!0},{label:`6 hours`,value:360*6e4},{label:`day`,value:1440*6e4}],q=[{label:`15 secs`,value:15e3},{label:`30 secs`,value:3e4},{label:`minute`,value:6e4,default:!0},{label:`5 mins`,value:5*6e4},{label:`15 mins`,value:15*6e4}];function J({instanceParams:e}){let[t,n]=(0,P.useState)(U[0]),[r,i]=(0,P.useState)(q.find(e=>e.default)),[a,o]=(0,P.useState)(Date.now),[s,c]=(0,P.useState)(K.find(e=>e.default));H(()=>{o(Date.now)},r.value);let l=(0,P.useMemo)(()=>a-s.value,[a,s]);return(0,F.jsxs)(`div`,{children:[(0,F.jsx)(`div`,{className:`flex justify-between`,children:(0,F.jsxs)(`div`,{className:`justify-items-end grid grid-cols-1 lg:grid-cols-3 gap-4`,children:[(0,F.jsxs)(`div`,{className:`flex flex-nowrap items-center`,children:[(0,F.jsx)(D,{className:`ml-8 mr-2`,children:`Metric:`}),(0,F.jsxs)(_,{defaultValue:t.id,onValueChange:e=>{n(U.find(t=>t.id===e)||U[0])},children:[(0,F.jsx)(b,{className:`inline-flex align-middle w-auto h-auto`,children:(0,F.jsx)(y,{})}),(0,F.jsx)(v,{children:(0,F.jsx)(w,{children:U.map(e=>{let t=e.label??e.name;return e.path&&(t+=` (${e.path})`),(0,F.jsx)(C,{value:e.id,children:t},e.id)})})})]})]}),(0,F.jsxs)(`div`,{className:`flex flex-nowrap items-center`,children:[(0,F.jsx)(D,{className:`ml-8 mr-2`,children:`Show last`}),(0,F.jsxs)(_,{defaultValue:s.value.toString(),onValueChange:e=>{c(K.find(t=>t.value===Number(e)))},children:[(0,F.jsx)(b,{className:`inline-flex align-middle w-auto h-auto`,children:(0,F.jsx)(y,{})}),(0,F.jsx)(v,{children:(0,F.jsx)(w,{children:K.map(e=>(0,F.jsx)(C,{value:e.value.toString(),children:e.label},e.value))})})]})]}),(0,F.jsxs)(`div`,{className:`flex flex-nowrap items-center`,children:[(0,F.jsx)(D,{className:`ml-8 mr-2`,children:`Update every`}),(0,F.jsxs)(_,{defaultValue:r.value.toString(),onValueChange:e=>{i(q.find(t=>t.value===Number(e)))},children:[(0,F.jsx)(b,{className:`inline-flex align-middle w-auto h-auto`,children:(0,F.jsx)(y,{})}),(0,F.jsx)(v,{children:(0,F.jsx)(w,{children:q.map(e=>(0,F.jsx)(C,{value:e.value.toString(),children:e.label},e.value))})})]})]})]})}),(0,F.jsx)(B,{metricConfig:t,startTime:l,endTime:a,instanceParams:e})]})}function Y({entityId:e,instanceClient:t}){return u({queryKey:[e,`system_information`],queryFn:async()=>{let{data:e}=await t.post(`/`,{operation:`system_information`,attributes:[`network`,`disk`,`cpu`,`memory`,`system`]});return e}})}function X({instanceParams:e}){let{data:t}=r(Y(e));return(0,F.jsx)(P.Suspense,{fallback:(0,F.jsx)(h,{}),children:(0,F.jsx)(I,{data:t})})}function Z(){let e=m();return(0,F.jsxs)(`div`,{className:`px-4 py-2 flex flex-col`,children:[(0,F.jsx)(`div`,{className:`mb-12`,children:(0,F.jsx)(J,{instanceParams:e})}),(0,F.jsx)(X,{instanceParams:e})]})}export{Z as StatusIndex};
|
|
2
|
+
//# sourceMappingURL=status-CoGlcjSB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-BP4TQJDR.js","names":[],"sources":["../../src/features/instance/status/crawlData.ts","../../src/features/instance/status/Status.tsx","../../src/features/instance/status/CloudStatus.tsx","../../src/integrations/api/instance/status/getAnalytics.ts","../../src/lib/colorPalette.ts","../../src/features/instance/status/components/monitoring/MetricVisualization.tsx","../../src/hooks/useIsomorphicLayoutEffect.ts","../../src/hooks/useInterval.ts","../../src/features/instance/status/components/Monitoring.tsx","../../src/integrations/api/instance/status/getSystemInformation.ts","../../src/features/instance/status/LocalStatus.tsx","../../src/features/instance/status/index.tsx"],"sourcesContent":["import { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { humanFileSize } from '@/lib/humanFileSize';\nimport { translateSecondsToAgo } from '@/lib/translateSecondsToAgo';\n\nconst startOf2025 = new Date(2025, 0).getTime();\nconst oneDayInMs = 24 * 60 * 60 * 1000;\n\ninterface TitleItem {\n\ttitle: string;\n\tdepth: number;\n}\n\ninterface NameValuePairItem {\n\tname: string;\n\tvalue: string;\n\tdepth: number;\n}\n\ntype ItemForDisplay = TitleItem | NameValuePairItem;\n\nexport function crawlData(data: Record<string, unknown>): ItemForDisplay[] {\n\tconst sections: ItemForDisplay[] = [];\n\tfor (const key in data) {\n\t\tconst value = data[key];\n\t\tsections.push(...parseValue(key, value, 0));\n\t}\n\treturn sections;\n}\n\nexport function hasTitle(item: ItemForDisplay): item is TitleItem {\n\treturn !!(item as TitleItem).title;\n}\n\nfunction parseValue(name: string, value: unknown, depth: number, parentName?: string): ItemForDisplay[] {\n\tif (value && Array.isArray(value)) {\n\t\tconst array = value;\n\t\treturn [\n\t\t\tarray.length > 1 && { title: name, depth },\n\t\t\t...value.map((item, index) =>\n\t\t\t\tparseValue(\n\t\t\t\t\tarray.length > 1 ? String(index + 1) : name,\n\t\t\t\t\titem,\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tname,\n\t\t\t\t)\n\t\t\t).flat(1),\n\t\t].filter(excludeFalsy);\n\t}\n\tif (isObject(value)) {\n\t\tconst obj = value;\n\t\treturn [\n\t\t\t{ title: name, depth },\n\t\t\t...Object.keys(value).map(subKey =>\n\t\t\t\tparseValue(\n\t\t\t\t\tString(subKey),\n\t\t\t\t\tobj[subKey],\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tname,\n\t\t\t\t)\n\t\t\t).flat(1),\n\t\t];\n\t}\n\tif (name === '__updatedtime__' || name === '__createdtime__') {\n\t\tname = name.replace(/_/g, '').replace('time', '');\n\t}\n\tif (typeof value === 'number') {\n\t\tif (value > startOf2025 && value < Date.now() + oneDayInMs) {\n\t\t\tconst elapsed = Date.now() - value;\n\t\t\tvalue = translateSecondsToAgo(elapsed, value);\n\t\t} else if (parentName === 'memory') {\n\t\t\tvalue = humanFileSize(value);\n\t\t} else if (!name.startsWith('raw') && name.toLowerCase().includes('load')) {\n\t\t\tvalue = Math.round(value * 10) / 10 + '%';\n\t\t}\n\t} else if (typeof value === 'boolean') {\n\t\tvalue = value ? 'Yes' : 'No';\n\t}\n\treturn [\n\t\t{ name, value: String(value), depth },\n\t];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn !!value && typeof value === 'object';\n}\n","import { crawlData, hasTitle } from '@/features/instance/status/crawlData';\nimport { cn } from '@/lib/cn';\nimport { useMemo } from 'react';\n\nexport function Status({ data }: { data: Record<string, unknown> }) {\n\tconst items = useMemo(() => crawlData(data), [data]);\n\treturn (\n\t\t<div className=\"max-w-96 grid mb-12\">\n\t\t\t{items.map((item, index) =>\n\t\t\t\thasTitle(item)\n\t\t\t\t\t? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\tclassName={cn('font-semibold text-xl', index !== 0 && 'mt-4')}\n\t\t\t\t\t\t\tstyle={{ paddingLeft: item.depth * 12 + 'px' }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<div key={index} style={{ paddingLeft: item.depth * 12 + 'px' }}>\n\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">{item.name}:</span>\n\t\t\t\t\t\t\t{item.value}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport { Status } from '@/features/instance/status/Status';\nimport { getStatusQueryOptions } from '@/integrations/api/instance/status/getStatus';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Suspense } from 'react';\n\ninterface CloudStatusParams {\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nexport function CloudStatus({ instanceParams }: CloudStatusParams) {\n\tconst { data } = useSuspenseQuery(getStatusQueryOptions(instanceParams));\n\n\treturn (\n\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t<Status data={data} />\n\t\t</Suspense>\n\t);\n}\n","import type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport type { Units } from '@/lib/units';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport type MetricDataKey = string | ((metric: Metric) => number);\nexport type MetricUnits = Units | 'reads' | 'writes' | 'messages';\nexport interface MetricConfig {\n\tid: string;\n\tname: string;\n\tlabel?: string;\n\tdataKey: MetricDataKey;\n\taggregator: (accumulator: number, current: number) => number;\n\tunits: MetricUnits;\n\tpath?: string;\n}\n\ninterface GetAnalyticsParams {\n\tmetricConfig: MetricConfig;\n\tstartTime: number;\n\tendTime: number;\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\ninterface GetAnalyticsRequest {\n\toperation: 'get_analytics';\n\tmetric: string;\n\tstart_time: number;\n\tend_time: number;\n\tconditions?: {\n\t\tattribute: string;\n\t\tvalue: string | number | boolean;\n\t\tcomparator?: string;\n\t}[];\n}\n\nexport interface Metric {\n\tid: number;\n\tmetric: string;\n\tcount: number;\n\tmean: number;\n\tperiod: number;\n\tnode: string;\n\t[key: string]: string | number | boolean | null;\n}\n\ntype GetAnalyticsResponse = Metric[];\n\nexport function getAnalyticsQueryOptions({ metricConfig, startTime, endTime, instanceParams }: GetAnalyticsParams) {\n\treturn queryOptions({\n\t\tqueryKey: ['get_analytics', metricConfig.name, metricConfig.path, startTime, endTime] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst req: GetAnalyticsRequest = {\n\t\t\t\toperation: 'get_analytics',\n\t\t\t\tmetric: metricConfig.name,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t};\n\t\t\tif (metricConfig.path) {\n\t\t\t\treq.conditions = [{ attribute: 'path', value: metricConfig.path }];\n\t\t\t}\n\t\t\tconst { data } = await instanceParams.instanceClient.post<GetAnalyticsResponse>('/', req);\n\t\t\treturn data;\n\t\t},\n\t});\n}\n","export const harperPalette = {\n\t'persistence-purple': '#403B8A',\n\t'b-tree-green': '#55C58F',\n\t'cyber-grape': '#7A3A87',\n\t'quantum-purple': '#312556',\n\t'cloud-white': '#F5F5F5',\n\t'acid-magenta': '#C63368',\n\t'edge-gray': '#383D40',\n};\n","import type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport {\n\tgetAnalyticsQueryOptions,\n\ttype Metric,\n\ttype MetricConfig,\n\ttype MetricDataKey,\n\ttype MetricUnits,\n} from '@/integrations/api/instance/status/getAnalytics.ts';\nimport { harperPalette } from '@/lib/colorPalette.ts';\nimport { determineUnits, scaleValueToUnits } from '@/lib/units';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMemo, useState } from 'react';\nimport { Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';\n\ntype MetricValue = string | number | boolean;\ntype NullableMetricValue = MetricValue | null;\ntype NullableMetric = { [key: string]: NullableMetricValue };\ntype NodeMetric = { [node: string]: number };\ntype CoalescedMetrics = { [id: string]: NodeMetric };\ntype FormattedMetric = { [node: string]: string };\n\ninterface MetricVisualizationParams {\n\tmetricConfig: MetricConfig;\n\tstartTime: number;\n\tendTime: number;\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nfunction resolveMetricDataKey(\n\tmetric: Metric,\n\tdataKey: MetricDataKey,\n\tbaseUnits: MetricUnits,\n\tconversionUnits?: string,\n) {\n\tlet baseValue;\n\tif (typeof dataKey === 'string') {\n\t\tbaseValue = metric[dataKey] as number ?? 0;\n\t} else {\n\t\tbaseValue = dataKey(metric);\n\t}\n\n\tif (conversionUnits) {\n\t\treturn scaleValueToUnits(baseValue, baseUnits, conversionUnits);\n\t}\n\n\treturn baseValue;\n}\n\nexport function MetricVisualization({ metricConfig, startTime, endTime, instanceParams }: MetricVisualizationParams) {\n\tconst { data } = useQuery(getAnalyticsQueryOptions({ instanceParams, metricConfig, startTime, endTime }));\n\tconst metrics = useMemo(() => {\n\t\treturn data?.reduce((ms: Metric[], m: NullableMetric) => {\n\t\t\tconst newMetric: Metric = { metric: '', node: '', id: 0, period: 0, count: 0, mean: 0 };\n\t\t\tfor (const k in m) {\n\t\t\t\tif (m[k] !== null) {\n\t\t\t\t\tnewMetric[k] = m[k];\n\t\t\t\t}\n\t\t\t}\n\t\t\tms.push(newMetric);\n\t\t\treturn ms;\n\t\t}, []);\n\t}, [data]);\n\n\tconst [yAxisUnits, setYAxisUnits] = useState<string>(metricConfig.units);\n\n\tconst nodeMetrics = useMemo(() => {\n\t\tconst coalescedMetrics: CoalescedMetrics = {};\n\t\tconst { dataKey, aggregator, units } = metricConfig;\n\t\tlet conversionUnits = units as string;\n\n\t\tif (metrics && metrics.length > 0) {\n\t\t\tconst maxDataValue = Math.max(...metrics.map((m) => resolveMetricDataKey(m, dataKey, units)));\n\t\t\tconversionUnits = determineUnits(units, maxDataValue);\n\t\t\t// We set the y-axis based on the max of the metrics, and we were careful to avoid a circular dependency.\n\t\t\t// So ignoring the set-state-in-render is safe, in this case.\n\t\t\t// eslint-disable-next-line react-hooks/set-state-in-render\n\t\t\tsetYAxisUnits(conversionUnits);\n\n\t\t\tfor (const metric of metrics) {\n\t\t\t\tconst coalescedTime = Math.floor(metric.id / metric.period) * metric.period;\n\t\t\t\tconst resolvedMetric = resolveMetricDataKey(metric, dataKey, units, conversionUnits);\n\n\t\t\t\tif (coalescedMetrics[coalescedTime]) {\n\t\t\t\t\tif (metric.node in coalescedMetrics[coalescedTime]) {\n\t\t\t\t\t\tcoalescedMetrics[coalescedTime][metric.node] = aggregator(\n\t\t\t\t\t\t\tcoalescedMetrics[coalescedTime][metric.node],\n\t\t\t\t\t\t\tresolvedMetric,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcoalescedMetrics[coalescedTime][metric.node] = resolvedMetric;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcoalescedMetrics[coalescedTime] = { [metric.node]: resolvedMetric };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Object.keys(coalescedMetrics).map((id: string) => {\n\t\t\t\tconst numericalId = Number.parseInt(id);\n\t\t\t\tconst coalescedMetric = coalescedMetrics[id];\n\t\t\t\tconst formattedMetrics = Object.keys(coalescedMetrics[id]).reduce((metric, node) => {\n\t\t\t\t\tmetric[node] = coalescedMetric[node].toFixed(2);\n\t\t\t\t\treturn metric;\n\t\t\t\t}, {} as FormattedMetric);\n\t\t\t\treturn { id: numericalId, ...formattedMetrics };\n\t\t\t});\n\t\t}\n\t}, [metrics, metricConfig]);\n\n\tconst nodes = useMemo(() => {\n\t\treturn Array.from(new Set<string>(metrics?.map((m) => m.node)));\n\t}, [metrics]);\n\n\tconst formatTime = (ts: number) => {\n\t\tconst date = new Date(ts);\n\t\treturn date.toLocaleDateString(undefined, {\n\t\t\tmonth: '2-digit',\n\t\t\tday: '2-digit',\n\t\t\thour: '2-digit',\n\t\t\tminute: '2-digit',\n\t\t\thour12: false,\n\t\t});\n\t};\n\n\tif (nodeMetrics && nodeMetrics.length > 0) {\n\t\treturn (\n\t\t\t<ResponsiveContainer width=\"100%\" height={600} className=\"mt-8\">\n\t\t\t\t<LineChart width={600} height={300} data={nodeMetrics}>\n\t\t\t\t\t{nodes.map((node, i) => {\n\t\t\t\t\t\tlet metricDifferentiator = metricConfig.name;\n\t\t\t\t\t\tif (metricConfig.path) {\n\t\t\t\t\t\t\tmetricDifferentiator += '.' + metricConfig.path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst key = metricDifferentiator + '.' + node;\n\t\t\t\t\t\treturn <Line key={key} name={node} dataKey={node} stroke={Object.values(harperPalette)[i]} />;\n\t\t\t\t\t})}\n\t\t\t\t\t<XAxis dataKey={(item) => formatTime(item.id)} />\n\t\t\t\t\t<YAxis unit={` ${yAxisUnits}`} width={100} />\n\t\t\t\t\t<Legend />\n\t\t\t\t\t<Tooltip />\n\t\t\t\t</LineChart>\n\t\t\t</ResponsiveContainer>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"mt-8 h-[600px]\">\n\t\t\t<p>No {metricConfig.name} data for this time period</p>\n\t\t</div>\n\t);\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nexport const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n","import { useIsomorphicLayoutEffect } from '@/hooks/useIsomorphicLayoutEffect';\nimport { useEffect, useRef } from 'react';\n\nexport function useInterval(callback: () => void, delay: number | null) {\n\tconst savedCallback = useRef(callback);\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tsavedCallback.current = callback;\n\t}, [callback]);\n\n\tuseEffect(() => {\n\t\tif (delay === null) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst id = setInterval(() => {\n\t\t\tsavedCallback.current();\n\t\t}, delay);\n\n\t\treturn () => {\n\t\t\tclearInterval(id);\n\t\t};\n\t}, [delay]);\n}\n","import { Label } from '@/components/ui/label.tsx';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select.tsx';\nimport type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport { MetricVisualization } from '@/features/instance/status/components/monitoring/MetricVisualization.tsx';\nimport { useInterval } from '@/hooks/useInterval.ts';\nimport type { Metric, MetricConfig } from '@/integrations/api/instance/status/getAnalytics.ts';\nimport { useMemo, useState } from 'react';\n\nconst metrics: MetricConfig[] = [\n\t{\n\t\tid: 'db-read',\n\t\tname: 'db-read',\n\t\tdataKey: 'count',\n\t\taggregator: aggregateSum,\n\t\tunits: 'reads',\n\t},\n\t{\n\t\tid: 'db-read-bytes',\n\t\tlabel: 'db-read-bytes',\n\t\tname: 'db-read',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'bytes',\n\t},\n\t{\n\t\tid: 'db-write',\n\t\tname: 'db-write',\n\t\tdataKey: 'count',\n\t\taggregator: aggregateSum,\n\t\tunits: 'writes',\n\t},\n\t{\n\t\tid: 'db-write-bytes',\n\t\tlabel: 'db-write-bytes',\n\t\tname: 'db-write',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'bytes',\n\t},\n\t{\n\t\tid: 'db-message',\n\t\tname: 'db-message',\n\t\tdataKey: 'count',\n\t\taggregator: aggregateSum,\n\t\tunits: 'messages',\n\t},\n\t{\n\t\tid: 'db-message-bytes',\n\t\tlabel: 'db-message-bytes',\n\t\tname: 'db-message',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'bytes',\n\t},\n\t{\n\t\tid: 'cpu-usage-user',\n\t\tname: 'cpu-usage',\n\t\tpath: 'user',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'secs',\n\t},\n\t{\n\t\tid: 'cpu-usage-harper',\n\t\tname: 'cpu-usage',\n\t\tpath: 'harper',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'secs',\n\t},\n];\n\nfunction metricSum(metric: Metric) {\n\tif (metric.mean && metric.count) {\n\t\treturn metric.mean * metric.count;\n\t}\n\treturn 0;\n}\n\nfunction aggregateSum(accumulator: number, current: number) {\n\treturn accumulator + current;\n}\n\ninterface TimeSelectOption {\n\tlabel: string;\n\tvalue: number;\n\tdefault?: boolean;\n}\ntype TimeSelectOptions = TimeSelectOption[];\n\nconst windowOptions: TimeSelectOptions = [\n\t{ label: '10 mins', value: 10 * 60_000 },\n\t{ label: 'hour', value: 60 * 60_000, default: true },\n\t{ label: '6 hours', value: 6 * 60 * 60_000 },\n\t{ label: 'day', value: 24 * 60 * 60_000 },\n];\n\nconst intervalOptions: TimeSelectOptions = [\n\t{ label: '15 secs', value: 15_000 },\n\t{ label: '30 secs', value: 30_000 },\n\t{ label: 'minute', value: 60_000, default: true },\n\t{ label: '5 mins', value: 5 * 60_000 },\n\t{ label: '15 mins', value: 15 * 60_000 },\n];\n\ninterface MonitoringParams {\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nexport function Monitoring({ instanceParams }: MonitoringParams) {\n\tconst [selectedMetric, setSelectedMetric] = useState(metrics[0]);\n\n\tconst [updateInterval, setUpdateInterval] = useState(intervalOptions.find((o) => o.default)!);\n\tconst [endTime, setEndTime] = useState(Date.now);\n\n\tconst [timeWindow, setTimeWindow] = useState(windowOptions.find((o) => o.default)!);\n\n\tuseInterval(() => {\n\t\tsetEndTime(Date.now);\n\t}, updateInterval.value);\n\n\tconst startTime = useMemo(() => endTime - timeWindow.value, [endTime, timeWindow]);\n\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"flex justify-between\">\n\t\t\t\t<div className=\"justify-items-end grid grid-cols-1 lg:grid-cols-3 gap-4\">\n\t\t\t\t\t<div className=\"flex flex-nowrap items-center\">\n\t\t\t\t\t\t<Label className=\"ml-8 mr-2\">Metric:</Label>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tdefaultValue={selectedMetric.id}\n\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\tsetSelectedMetric(metrics.find((m) => m.id === value) || metrics[0]);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"inline-flex align-middle w-auto h-auto\">\n\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{metrics.map((m) => {\n\t\t\t\t\t\t\t\t\t\tlet itemLabel = m.label ?? m.name;\n\t\t\t\t\t\t\t\t\t\tif (m.path) {\n\t\t\t\t\t\t\t\t\t\t\titemLabel += ` (${m.path})`;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn <SelectItem key={m.id} value={m.id}>{itemLabel}</SelectItem>;\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-nowrap items-center\">\n\t\t\t\t\t\t<Label className=\"ml-8 mr-2\">Show last</Label>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tdefaultValue={timeWindow.value.toString()}\n\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\tsetTimeWindow(windowOptions.find((o) => o.value === Number(value))!);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"inline-flex align-middle w-auto h-auto\">\n\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{windowOptions.map((o) => {\n\t\t\t\t\t\t\t\t\t\treturn <SelectItem key={o.value} value={o.value.toString()}>{o.label}</SelectItem>;\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-nowrap items-center\">\n\t\t\t\t\t\t<Label className=\"ml-8 mr-2\">Update every</Label>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tdefaultValue={updateInterval.value.toString()}\n\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\tsetUpdateInterval(intervalOptions.find((o) => o.value === Number(value))!);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"inline-flex align-middle w-auto h-auto\">\n\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{intervalOptions.map((o) => {\n\t\t\t\t\t\t\t\t\t\treturn <SelectItem key={o.value} value={o.value.toString()}>{o.label}</SelectItem>;\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<MetricVisualization\n\t\t\t\tmetricConfig={selectedMetric}\n\t\t\t\tstartTime={startTime}\n\t\t\t\tendTime={endTime}\n\t\t\t\tinstanceParams={instanceParams}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface SystemInformationResponse {\n\tsystem: {\n\t\tplatform: 'darwin' | 'linux' | string;\n\t\tdistro: 'macOS' | 'Debian GNU/Linux' | string;\n\t\trelease: string;\n\t\tcodename: string;\n\t\tkernel: string;\n\t\tarch: 'arm64' | 'x64' | string;\n\t\thostname: string;\n\t\tfqdn: string;\n\t\tnode_version: string;\n\t\tnpm_version: string;\n\t};\n\tcpu: {\n\t\tmanufacturer: 'Apple' | 'AMD' | string;\n\t\tbrand: 'M4' | string;\n\t\tvendor: 'Apple' | 'AMD' | string;\n\t\tspeed: number;\n\t\tspeedMin: number;\n\t\tspeedMax: number;\n\t\tcores: number;\n\t\tphysicalCores: number;\n\t\tperformanceCores: number;\n\t\tefficiencyCores: number;\n\t\tprocessors: number;\n\t\tflags: string;\n\t\tvirtualization: boolean;\n\t\tcpu_speed: {\n\t\t\tmin: number;\n\t\t\tmax: number;\n\t\t\tavg: number;\n\t\t\tcores: number[];\n\t\t};\n\t\tcurrent_load: {\n\t\t\tavgLoad: number;\n\t\t\tcurrentLoad: number;\n\t\t\tcurrentLoadUser: number;\n\t\t\tcurrentLoadSystem: number;\n\t\t\tcurrentLoadNice: number;\n\t\t\tcurrentLoadIdle: number;\n\t\t\tcurrentLoadIrq: number;\n\t\t\tcurrentLoadSteal: number;\n\t\t\tcurrentLoadGuest: number;\n\t\t\trawCurrentLoad: number;\n\t\t\trawCurrentLoadUser: number;\n\t\t\trawCurrentLoadSystem: number;\n\t\t\trawCurrentLoadNice: number;\n\t\t\trawCurrentLoadIdle: number;\n\t\t\trawCurrentLoadIrq: number;\n\t\t\trawCurrentLoadSteal: number;\n\t\t\trawCurrentLoadGuest: number;\n\t\t\tcpus: Array<{\n\t\t\t\tload: number;\n\t\t\t\tloadUser: number;\n\t\t\t\tloadSystem: number;\n\t\t\t\tloadNice: number;\n\t\t\t\tloadIdle: number;\n\t\t\t\tloadIrq: number;\n\t\t\t\tloadSteal: number;\n\t\t\t\tloadGuest: number;\n\t\t\t\trawLoadSteal: number;\n\t\t\t\trawLoadGuest: number;\n\t\t\t}>;\n\t\t};\n\t};\n\tmemory: {\n\t\ttotal: number;\n\t\tfree: number;\n\t\tused: number;\n\t\tactive: number;\n\t\tavailable: number;\n\t\treclaimable: number;\n\t\tswaptotal: number;\n\t\tswapused: number;\n\t\tswapfree: number;\n\t\twriteback: unknown;\n\t\tdirty: unknown;\n\t\trss: number;\n\t\theapTotal: number;\n\t\theapUsed: number;\n\t\texternal: number;\n\t\tarrayBuffers: number;\n\t};\n\tdisk: Record<string, unknown>;\n\tnetwork: {\n\t\tdefault_interface: unknown;\n\t\tlatency: Record<string, unknown>;\n\t\tinterfaces: Array<Record<string, unknown>>;\n\t\tstats: Array<Record<string, unknown>>;\n\t\tconnections: Array<Record<string, unknown>>;\n\t};\n\n\t[key: string]: unknown;\n}\n\nexport function getSystemInformationQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'system_information'] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.post<SystemInformationResponse>('/', {\n\t\t\t\toperation: 'system_information',\n\t\t\t\tattributes: ['network', 'disk', 'cpu', 'memory', 'system'],\n\t\t\t});\n\t\t\treturn data;\n\t\t},\n\t});\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { Status } from '@/features/instance/status/Status';\nimport { getSystemInformationQueryOptions } from '@/integrations/api/instance/status/getSystemInformation';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Suspense } from 'react';\n\ninterface LocalStatusParams {\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nexport function LocalStatus({ instanceParams }: LocalStatusParams) {\n\tconst { data } = useSuspenseQuery(getSystemInformationQueryOptions(instanceParams));\n\n\treturn (\n\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t<Status data={data} />\n\t\t</Suspense>\n\t);\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient.tsx';\nimport { CloudStatus } from '@/features/instance/status/CloudStatus';\nimport { Monitoring } from '@/features/instance/status/components/Monitoring.tsx';\nimport { LocalStatus } from '@/features/instance/status/LocalStatus';\n\nexport function StatusIndex() {\n\tconst instanceParams = useInstanceClientIdParams();\n\n\treturn (\n\t\t<div className=\"px-4 py-2 flex flex-col\">\n\t\t\t<div className=\"mb-12\">\n\t\t\t\t<Monitoring instanceParams={instanceParams} />\n\t\t\t</div>\n\t\t\t{isLocalStudio\n\t\t\t\t? <LocalStatus instanceParams={instanceParams} />\n\t\t\t\t: <CloudStatus instanceParams={instanceParams} />}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"status-CoGlcjSB.js","names":[],"sources":["../../src/features/instance/status/crawlData.ts","../../src/features/instance/status/Status.tsx","../../src/features/instance/status/CloudStatus.tsx","../../src/integrations/api/instance/status/getAnalytics.ts","../../src/lib/colorPalette.ts","../../src/features/instance/status/components/monitoring/MetricVisualization.tsx","../../src/hooks/useIsomorphicLayoutEffect.ts","../../src/hooks/useInterval.ts","../../src/features/instance/status/components/Monitoring.tsx","../../src/integrations/api/instance/status/getSystemInformation.ts","../../src/features/instance/status/LocalStatus.tsx","../../src/features/instance/status/index.tsx"],"sourcesContent":["import { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { humanFileSize } from '@/lib/humanFileSize';\nimport { translateSecondsToAgo } from '@/lib/translateSecondsToAgo';\n\nconst startOf2025 = new Date(2025, 0).getTime();\nconst oneDayInMs = 24 * 60 * 60 * 1000;\n\ninterface TitleItem {\n\ttitle: string;\n\tdepth: number;\n}\n\ninterface NameValuePairItem {\n\tname: string;\n\tvalue: string;\n\tdepth: number;\n}\n\ntype ItemForDisplay = TitleItem | NameValuePairItem;\n\nexport function crawlData(data: Record<string, unknown>): ItemForDisplay[] {\n\tconst sections: ItemForDisplay[] = [];\n\tfor (const key in data) {\n\t\tconst value = data[key];\n\t\tsections.push(...parseValue(key, value, 0));\n\t}\n\treturn sections;\n}\n\nexport function hasTitle(item: ItemForDisplay): item is TitleItem {\n\treturn !!(item as TitleItem).title;\n}\n\nfunction parseValue(name: string, value: unknown, depth: number, parentName?: string): ItemForDisplay[] {\n\tif (value && Array.isArray(value)) {\n\t\tconst array = value;\n\t\treturn [\n\t\t\tarray.length > 1 && { title: name, depth },\n\t\t\t...value.map((item, index) =>\n\t\t\t\tparseValue(\n\t\t\t\t\tarray.length > 1 ? String(index + 1) : name,\n\t\t\t\t\titem,\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tname,\n\t\t\t\t)\n\t\t\t).flat(1),\n\t\t].filter(excludeFalsy);\n\t}\n\tif (isObject(value)) {\n\t\tconst obj = value;\n\t\treturn [\n\t\t\t{ title: name, depth },\n\t\t\t...Object.keys(value).map(subKey =>\n\t\t\t\tparseValue(\n\t\t\t\t\tString(subKey),\n\t\t\t\t\tobj[subKey],\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tname,\n\t\t\t\t)\n\t\t\t).flat(1),\n\t\t];\n\t}\n\tif (name === '__updatedtime__' || name === '__createdtime__') {\n\t\tname = name.replace(/_/g, '').replace('time', '');\n\t}\n\tif (typeof value === 'number') {\n\t\tif (value > startOf2025 && value < Date.now() + oneDayInMs) {\n\t\t\tconst elapsed = Date.now() - value;\n\t\t\tvalue = translateSecondsToAgo(elapsed, value);\n\t\t} else if (parentName === 'memory') {\n\t\t\tvalue = humanFileSize(value);\n\t\t} else if (!name.startsWith('raw') && name.toLowerCase().includes('load')) {\n\t\t\tvalue = Math.round(value * 10) / 10 + '%';\n\t\t}\n\t} else if (typeof value === 'boolean') {\n\t\tvalue = value ? 'Yes' : 'No';\n\t}\n\treturn [\n\t\t{ name, value: String(value), depth },\n\t];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn !!value && typeof value === 'object';\n}\n","import { crawlData, hasTitle } from '@/features/instance/status/crawlData';\nimport { cn } from '@/lib/cn';\nimport { useMemo } from 'react';\n\nexport function Status({ data }: { data: Record<string, unknown> }) {\n\tconst items = useMemo(() => crawlData(data), [data]);\n\treturn (\n\t\t<div className=\"max-w-96 grid mb-12\">\n\t\t\t{items.map((item, index) =>\n\t\t\t\thasTitle(item)\n\t\t\t\t\t? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\tclassName={cn('font-semibold text-xl', index !== 0 && 'mt-4')}\n\t\t\t\t\t\t\tstyle={{ paddingLeft: item.depth * 12 + 'px' }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<div key={index} style={{ paddingLeft: item.depth * 12 + 'px' }}>\n\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">{item.name}:</span>\n\t\t\t\t\t\t\t{item.value}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport { Status } from '@/features/instance/status/Status';\nimport { getStatusQueryOptions } from '@/integrations/api/instance/status/getStatus';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Suspense } from 'react';\n\ninterface CloudStatusParams {\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nexport function CloudStatus({ instanceParams }: CloudStatusParams) {\n\tconst { data } = useSuspenseQuery(getStatusQueryOptions(instanceParams));\n\n\treturn (\n\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t<Status data={data} />\n\t\t</Suspense>\n\t);\n}\n","import type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport type { Units } from '@/lib/units';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport type MetricDataKey = string | ((metric: Metric) => number);\nexport type MetricUnits = Units | 'reads' | 'writes' | 'messages';\nexport interface MetricConfig {\n\tid: string;\n\tname: string;\n\tlabel?: string;\n\tdataKey: MetricDataKey;\n\taggregator: (accumulator: number, current: number) => number;\n\tunits: MetricUnits;\n\tpath?: string;\n}\n\ninterface GetAnalyticsParams {\n\tmetricConfig: MetricConfig;\n\tstartTime: number;\n\tendTime: number;\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\ninterface GetAnalyticsRequest {\n\toperation: 'get_analytics';\n\tmetric: string;\n\tstart_time: number;\n\tend_time: number;\n\tconditions?: {\n\t\tattribute: string;\n\t\tvalue: string | number | boolean;\n\t\tcomparator?: string;\n\t}[];\n}\n\nexport interface Metric {\n\tid: number;\n\tmetric: string;\n\tcount: number;\n\tmean: number;\n\tperiod: number;\n\tnode: string;\n\t[key: string]: string | number | boolean | null;\n}\n\ntype GetAnalyticsResponse = Metric[];\n\nexport function getAnalyticsQueryOptions({ metricConfig, startTime, endTime, instanceParams }: GetAnalyticsParams) {\n\treturn queryOptions({\n\t\tqueryKey: ['get_analytics', metricConfig.name, metricConfig.path, startTime, endTime] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst req: GetAnalyticsRequest = {\n\t\t\t\toperation: 'get_analytics',\n\t\t\t\tmetric: metricConfig.name,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t};\n\t\t\tif (metricConfig.path) {\n\t\t\t\treq.conditions = [{ attribute: 'path', value: metricConfig.path }];\n\t\t\t}\n\t\t\tconst { data } = await instanceParams.instanceClient.post<GetAnalyticsResponse>('/', req);\n\t\t\treturn data;\n\t\t},\n\t});\n}\n","export const harperPalette = {\n\t'persistence-purple': '#403B8A',\n\t'b-tree-green': '#55C58F',\n\t'cyber-grape': '#7A3A87',\n\t'quantum-purple': '#312556',\n\t'cloud-white': '#F5F5F5',\n\t'acid-magenta': '#C63368',\n\t'edge-gray': '#383D40',\n};\n","import type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport {\n\tgetAnalyticsQueryOptions,\n\ttype Metric,\n\ttype MetricConfig,\n\ttype MetricDataKey,\n\ttype MetricUnits,\n} from '@/integrations/api/instance/status/getAnalytics.ts';\nimport { harperPalette } from '@/lib/colorPalette.ts';\nimport { determineUnits, scaleValueToUnits } from '@/lib/units';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMemo, useState } from 'react';\nimport { Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';\n\ntype MetricValue = string | number | boolean;\ntype NullableMetricValue = MetricValue | null;\ntype NullableMetric = { [key: string]: NullableMetricValue };\ntype NodeMetric = { [node: string]: number };\ntype CoalescedMetrics = { [id: string]: NodeMetric };\ntype FormattedMetric = { [node: string]: string };\n\ninterface MetricVisualizationParams {\n\tmetricConfig: MetricConfig;\n\tstartTime: number;\n\tendTime: number;\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nfunction resolveMetricDataKey(\n\tmetric: Metric,\n\tdataKey: MetricDataKey,\n\tbaseUnits: MetricUnits,\n\tconversionUnits?: string,\n) {\n\tlet baseValue;\n\tif (typeof dataKey === 'string') {\n\t\tbaseValue = metric[dataKey] as number ?? 0;\n\t} else {\n\t\tbaseValue = dataKey(metric);\n\t}\n\n\tif (conversionUnits) {\n\t\treturn scaleValueToUnits(baseValue, baseUnits, conversionUnits);\n\t}\n\n\treturn baseValue;\n}\n\nexport function MetricVisualization({ metricConfig, startTime, endTime, instanceParams }: MetricVisualizationParams) {\n\tconst { data } = useQuery(getAnalyticsQueryOptions({ instanceParams, metricConfig, startTime, endTime }));\n\tconst metrics = useMemo(() => {\n\t\treturn data?.reduce((ms: Metric[], m: NullableMetric) => {\n\t\t\tconst newMetric: Metric = { metric: '', node: '', id: 0, period: 0, count: 0, mean: 0 };\n\t\t\tfor (const k in m) {\n\t\t\t\tif (m[k] !== null) {\n\t\t\t\t\tnewMetric[k] = m[k];\n\t\t\t\t}\n\t\t\t}\n\t\t\tms.push(newMetric);\n\t\t\treturn ms;\n\t\t}, []);\n\t}, [data]);\n\n\tconst [yAxisUnits, setYAxisUnits] = useState<string>(metricConfig.units);\n\n\tconst nodeMetrics = useMemo(() => {\n\t\tconst coalescedMetrics: CoalescedMetrics = {};\n\t\tconst { dataKey, aggregator, units } = metricConfig;\n\t\tlet conversionUnits = units as string;\n\n\t\tif (metrics && metrics.length > 0) {\n\t\t\tconst maxDataValue = Math.max(...metrics.map((m) => resolveMetricDataKey(m, dataKey, units)));\n\t\t\tconversionUnits = determineUnits(units, maxDataValue);\n\t\t\t// We set the y-axis based on the max of the metrics, and we were careful to avoid a circular dependency.\n\t\t\t// So ignoring the set-state-in-render is safe, in this case.\n\t\t\t// eslint-disable-next-line react-hooks/set-state-in-render\n\t\t\tsetYAxisUnits(conversionUnits);\n\n\t\t\tfor (const metric of metrics) {\n\t\t\t\tconst coalescedTime = Math.floor(metric.id / metric.period) * metric.period;\n\t\t\t\tconst resolvedMetric = resolveMetricDataKey(metric, dataKey, units, conversionUnits);\n\n\t\t\t\tif (coalescedMetrics[coalescedTime]) {\n\t\t\t\t\tif (metric.node in coalescedMetrics[coalescedTime]) {\n\t\t\t\t\t\tcoalescedMetrics[coalescedTime][metric.node] = aggregator(\n\t\t\t\t\t\t\tcoalescedMetrics[coalescedTime][metric.node],\n\t\t\t\t\t\t\tresolvedMetric,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcoalescedMetrics[coalescedTime][metric.node] = resolvedMetric;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcoalescedMetrics[coalescedTime] = { [metric.node]: resolvedMetric };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Object.keys(coalescedMetrics).map((id: string) => {\n\t\t\t\tconst numericalId = Number.parseInt(id);\n\t\t\t\tconst coalescedMetric = coalescedMetrics[id];\n\t\t\t\tconst formattedMetrics = Object.keys(coalescedMetrics[id]).reduce((metric, node) => {\n\t\t\t\t\tmetric[node] = coalescedMetric[node].toFixed(2);\n\t\t\t\t\treturn metric;\n\t\t\t\t}, {} as FormattedMetric);\n\t\t\t\treturn { id: numericalId, ...formattedMetrics };\n\t\t\t});\n\t\t}\n\t}, [metrics, metricConfig]);\n\n\tconst nodes = useMemo(() => {\n\t\treturn Array.from(new Set<string>(metrics?.map((m) => m.node)));\n\t}, [metrics]);\n\n\tconst formatTime = (ts: number) => {\n\t\tconst date = new Date(ts);\n\t\treturn date.toLocaleDateString(undefined, {\n\t\t\tmonth: '2-digit',\n\t\t\tday: '2-digit',\n\t\t\thour: '2-digit',\n\t\t\tminute: '2-digit',\n\t\t\thour12: false,\n\t\t});\n\t};\n\n\tif (nodeMetrics && nodeMetrics.length > 0) {\n\t\treturn (\n\t\t\t<ResponsiveContainer width=\"100%\" height={600} className=\"mt-8\">\n\t\t\t\t<LineChart width={600} height={300} data={nodeMetrics}>\n\t\t\t\t\t{nodes.map((node, i) => {\n\t\t\t\t\t\tlet metricDifferentiator = metricConfig.name;\n\t\t\t\t\t\tif (metricConfig.path) {\n\t\t\t\t\t\t\tmetricDifferentiator += '.' + metricConfig.path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst key = metricDifferentiator + '.' + node;\n\t\t\t\t\t\treturn <Line key={key} name={node} dataKey={node} stroke={Object.values(harperPalette)[i]} />;\n\t\t\t\t\t})}\n\t\t\t\t\t<XAxis dataKey={(item) => formatTime(item.id)} />\n\t\t\t\t\t<YAxis unit={` ${yAxisUnits}`} width={100} />\n\t\t\t\t\t<Legend />\n\t\t\t\t\t<Tooltip />\n\t\t\t\t</LineChart>\n\t\t\t</ResponsiveContainer>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"mt-8 h-[600px]\">\n\t\t\t<p>No {metricConfig.name} data for this time period</p>\n\t\t</div>\n\t);\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nexport const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n","import { useIsomorphicLayoutEffect } from '@/hooks/useIsomorphicLayoutEffect';\nimport { useEffect, useRef } from 'react';\n\nexport function useInterval(callback: () => void, delay: number | null) {\n\tconst savedCallback = useRef(callback);\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tsavedCallback.current = callback;\n\t}, [callback]);\n\n\tuseEffect(() => {\n\t\tif (delay === null) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst id = setInterval(() => {\n\t\t\tsavedCallback.current();\n\t\t}, delay);\n\n\t\treturn () => {\n\t\t\tclearInterval(id);\n\t\t};\n\t}, [delay]);\n}\n","import { Label } from '@/components/ui/label.tsx';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select.tsx';\nimport type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport { MetricVisualization } from '@/features/instance/status/components/monitoring/MetricVisualization.tsx';\nimport { useInterval } from '@/hooks/useInterval.ts';\nimport type { Metric, MetricConfig } from '@/integrations/api/instance/status/getAnalytics.ts';\nimport { useMemo, useState } from 'react';\n\nconst metrics: MetricConfig[] = [\n\t{\n\t\tid: 'db-read',\n\t\tname: 'db-read',\n\t\tdataKey: 'count',\n\t\taggregator: aggregateSum,\n\t\tunits: 'reads',\n\t},\n\t{\n\t\tid: 'db-read-bytes',\n\t\tlabel: 'db-read-bytes',\n\t\tname: 'db-read',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'bytes',\n\t},\n\t{\n\t\tid: 'db-write',\n\t\tname: 'db-write',\n\t\tdataKey: 'count',\n\t\taggregator: aggregateSum,\n\t\tunits: 'writes',\n\t},\n\t{\n\t\tid: 'db-write-bytes',\n\t\tlabel: 'db-write-bytes',\n\t\tname: 'db-write',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'bytes',\n\t},\n\t{\n\t\tid: 'db-message',\n\t\tname: 'db-message',\n\t\tdataKey: 'count',\n\t\taggregator: aggregateSum,\n\t\tunits: 'messages',\n\t},\n\t{\n\t\tid: 'db-message-bytes',\n\t\tlabel: 'db-message-bytes',\n\t\tname: 'db-message',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'bytes',\n\t},\n\t{\n\t\tid: 'cpu-usage-user',\n\t\tname: 'cpu-usage',\n\t\tpath: 'user',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'secs',\n\t},\n\t{\n\t\tid: 'cpu-usage-harper',\n\t\tname: 'cpu-usage',\n\t\tpath: 'harper',\n\t\tdataKey: metricSum,\n\t\taggregator: aggregateSum,\n\t\tunits: 'secs',\n\t},\n];\n\nfunction metricSum(metric: Metric) {\n\tif (metric.mean && metric.count) {\n\t\treturn metric.mean * metric.count;\n\t}\n\treturn 0;\n}\n\nfunction aggregateSum(accumulator: number, current: number) {\n\treturn accumulator + current;\n}\n\ninterface TimeSelectOption {\n\tlabel: string;\n\tvalue: number;\n\tdefault?: boolean;\n}\ntype TimeSelectOptions = TimeSelectOption[];\n\nconst windowOptions: TimeSelectOptions = [\n\t{ label: '10 mins', value: 10 * 60_000 },\n\t{ label: 'hour', value: 60 * 60_000, default: true },\n\t{ label: '6 hours', value: 6 * 60 * 60_000 },\n\t{ label: 'day', value: 24 * 60 * 60_000 },\n];\n\nconst intervalOptions: TimeSelectOptions = [\n\t{ label: '15 secs', value: 15_000 },\n\t{ label: '30 secs', value: 30_000 },\n\t{ label: 'minute', value: 60_000, default: true },\n\t{ label: '5 mins', value: 5 * 60_000 },\n\t{ label: '15 mins', value: 15 * 60_000 },\n];\n\ninterface MonitoringParams {\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nexport function Monitoring({ instanceParams }: MonitoringParams) {\n\tconst [selectedMetric, setSelectedMetric] = useState(metrics[0]);\n\n\tconst [updateInterval, setUpdateInterval] = useState(intervalOptions.find((o) => o.default)!);\n\tconst [endTime, setEndTime] = useState(Date.now);\n\n\tconst [timeWindow, setTimeWindow] = useState(windowOptions.find((o) => o.default)!);\n\n\tuseInterval(() => {\n\t\tsetEndTime(Date.now);\n\t}, updateInterval.value);\n\n\tconst startTime = useMemo(() => endTime - timeWindow.value, [endTime, timeWindow]);\n\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"flex justify-between\">\n\t\t\t\t<div className=\"justify-items-end grid grid-cols-1 lg:grid-cols-3 gap-4\">\n\t\t\t\t\t<div className=\"flex flex-nowrap items-center\">\n\t\t\t\t\t\t<Label className=\"ml-8 mr-2\">Metric:</Label>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tdefaultValue={selectedMetric.id}\n\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\tsetSelectedMetric(metrics.find((m) => m.id === value) || metrics[0]);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"inline-flex align-middle w-auto h-auto\">\n\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{metrics.map((m) => {\n\t\t\t\t\t\t\t\t\t\tlet itemLabel = m.label ?? m.name;\n\t\t\t\t\t\t\t\t\t\tif (m.path) {\n\t\t\t\t\t\t\t\t\t\t\titemLabel += ` (${m.path})`;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn <SelectItem key={m.id} value={m.id}>{itemLabel}</SelectItem>;\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-nowrap items-center\">\n\t\t\t\t\t\t<Label className=\"ml-8 mr-2\">Show last</Label>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tdefaultValue={timeWindow.value.toString()}\n\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\tsetTimeWindow(windowOptions.find((o) => o.value === Number(value))!);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"inline-flex align-middle w-auto h-auto\">\n\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{windowOptions.map((o) => {\n\t\t\t\t\t\t\t\t\t\treturn <SelectItem key={o.value} value={o.value.toString()}>{o.label}</SelectItem>;\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-nowrap items-center\">\n\t\t\t\t\t\t<Label className=\"ml-8 mr-2\">Update every</Label>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tdefaultValue={updateInterval.value.toString()}\n\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\tsetUpdateInterval(intervalOptions.find((o) => o.value === Number(value))!);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"inline-flex align-middle w-auto h-auto\">\n\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{intervalOptions.map((o) => {\n\t\t\t\t\t\t\t\t\t\treturn <SelectItem key={o.value} value={o.value.toString()}>{o.label}</SelectItem>;\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<MetricVisualization\n\t\t\t\tmetricConfig={selectedMetric}\n\t\t\t\tstartTime={startTime}\n\t\t\t\tendTime={endTime}\n\t\t\t\tinstanceParams={instanceParams}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface SystemInformationResponse {\n\tsystem: {\n\t\tplatform: 'darwin' | 'linux' | string;\n\t\tdistro: 'macOS' | 'Debian GNU/Linux' | string;\n\t\trelease: string;\n\t\tcodename: string;\n\t\tkernel: string;\n\t\tarch: 'arm64' | 'x64' | string;\n\t\thostname: string;\n\t\tfqdn: string;\n\t\tnode_version: string;\n\t\tnpm_version: string;\n\t};\n\tcpu: {\n\t\tmanufacturer: 'Apple' | 'AMD' | string;\n\t\tbrand: 'M4' | string;\n\t\tvendor: 'Apple' | 'AMD' | string;\n\t\tspeed: number;\n\t\tspeedMin: number;\n\t\tspeedMax: number;\n\t\tcores: number;\n\t\tphysicalCores: number;\n\t\tperformanceCores: number;\n\t\tefficiencyCores: number;\n\t\tprocessors: number;\n\t\tflags: string;\n\t\tvirtualization: boolean;\n\t\tcpu_speed: {\n\t\t\tmin: number;\n\t\t\tmax: number;\n\t\t\tavg: number;\n\t\t\tcores: number[];\n\t\t};\n\t\tcurrent_load: {\n\t\t\tavgLoad: number;\n\t\t\tcurrentLoad: number;\n\t\t\tcurrentLoadUser: number;\n\t\t\tcurrentLoadSystem: number;\n\t\t\tcurrentLoadNice: number;\n\t\t\tcurrentLoadIdle: number;\n\t\t\tcurrentLoadIrq: number;\n\t\t\tcurrentLoadSteal: number;\n\t\t\tcurrentLoadGuest: number;\n\t\t\trawCurrentLoad: number;\n\t\t\trawCurrentLoadUser: number;\n\t\t\trawCurrentLoadSystem: number;\n\t\t\trawCurrentLoadNice: number;\n\t\t\trawCurrentLoadIdle: number;\n\t\t\trawCurrentLoadIrq: number;\n\t\t\trawCurrentLoadSteal: number;\n\t\t\trawCurrentLoadGuest: number;\n\t\t\tcpus: Array<{\n\t\t\t\tload: number;\n\t\t\t\tloadUser: number;\n\t\t\t\tloadSystem: number;\n\t\t\t\tloadNice: number;\n\t\t\t\tloadIdle: number;\n\t\t\t\tloadIrq: number;\n\t\t\t\tloadSteal: number;\n\t\t\t\tloadGuest: number;\n\t\t\t\trawLoadSteal: number;\n\t\t\t\trawLoadGuest: number;\n\t\t\t}>;\n\t\t};\n\t};\n\tmemory: {\n\t\ttotal: number;\n\t\tfree: number;\n\t\tused: number;\n\t\tactive: number;\n\t\tavailable: number;\n\t\treclaimable: number;\n\t\tswaptotal: number;\n\t\tswapused: number;\n\t\tswapfree: number;\n\t\twriteback: unknown;\n\t\tdirty: unknown;\n\t\trss: number;\n\t\theapTotal: number;\n\t\theapUsed: number;\n\t\texternal: number;\n\t\tarrayBuffers: number;\n\t};\n\tdisk: Record<string, unknown>;\n\tnetwork: {\n\t\tdefault_interface: unknown;\n\t\tlatency: Record<string, unknown>;\n\t\tinterfaces: Array<Record<string, unknown>>;\n\t\tstats: Array<Record<string, unknown>>;\n\t\tconnections: Array<Record<string, unknown>>;\n\t};\n\n\t[key: string]: unknown;\n}\n\nexport function getSystemInformationQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'system_information'] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.post<SystemInformationResponse>('/', {\n\t\t\t\toperation: 'system_information',\n\t\t\t\tattributes: ['network', 'disk', 'cpu', 'memory', 'system'],\n\t\t\t});\n\t\t\treturn data;\n\t\t},\n\t});\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { Status } from '@/features/instance/status/Status';\nimport { getSystemInformationQueryOptions } from '@/integrations/api/instance/status/getSystemInformation';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Suspense } from 'react';\n\ninterface LocalStatusParams {\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\nexport function LocalStatus({ instanceParams }: LocalStatusParams) {\n\tconst { data } = useSuspenseQuery(getSystemInformationQueryOptions(instanceParams));\n\n\treturn (\n\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t<Status data={data} />\n\t\t</Suspense>\n\t);\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient.tsx';\nimport { CloudStatus } from '@/features/instance/status/CloudStatus';\nimport { Monitoring } from '@/features/instance/status/components/Monitoring.tsx';\nimport { LocalStatus } from '@/features/instance/status/LocalStatus';\n\nexport function StatusIndex() {\n\tconst instanceParams = useInstanceClientIdParams();\n\n\treturn (\n\t\t<div className=\"px-4 py-2 flex flex-col\">\n\t\t\t<div className=\"mb-12\">\n\t\t\t\t<Monitoring instanceParams={instanceParams} />\n\t\t\t</div>\n\t\t\t{isLocalStudio\n\t\t\t\t? <LocalStatus instanceParams={instanceParams} />\n\t\t\t\t: <CloudStatus instanceParams={instanceParams} />}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
package/studio/web/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<link rel="icon" type="dynamic-favicon" href="/favicon_purple.png" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>Harper Fabric</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-ClD_q6ya.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-FhOqtrmT.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendor-datadog-B4t4E5qd.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/vendor-html-C0BzV7Np.js">
|
package/utility/hdbTerms.ts
CHANGED
|
@@ -426,6 +426,7 @@ export const LEGACY_CONFIG_PARAMS = {
|
|
|
426
426
|
export const CONFIG_PARAMS = {
|
|
427
427
|
ANALYTICS_AGGREGATEPERIOD: 'analytics_aggregatePeriod',
|
|
428
428
|
ANALYTICS_REPLICATE: 'analytics_replicate',
|
|
429
|
+
ANALYTICS_STORAGEINTERVAL: 'analytics_storageInterval',
|
|
429
430
|
AUTHENTICATION_AUTHORIZELOCAL: 'authentication_authorizeLocal',
|
|
430
431
|
AUTHENTICATION_CACHETTL: 'authentication_cacheTTL',
|
|
431
432
|
AUTHENTICATION_COOKIE_DOMAINS: 'authentication_cookie_domains',
|
|
@@ -98,6 +98,14 @@ function updateConditional(logger) {
|
|
|
98
98
|
conditional.debug = LOG_LEVEL_HIERARCHY.debug >= logger.level ? logger.debug.bind(logger) : undefined;
|
|
99
99
|
conditional.trace = LOG_LEVEL_HIERARCHY.trace >= logger.level ? logger.trace.bind(logger) : undefined;
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve a config path value against rootPath if it is relative.
|
|
103
|
+
*/
|
|
104
|
+
function resolveLogPath(configPath, rootPath) {
|
|
105
|
+
if (!configPath || !rootPath) return configPath;
|
|
106
|
+
if (pathModule.isAbsolute(configPath)) return configPath;
|
|
107
|
+
return pathModule.resolve(rootPath, configPath);
|
|
108
|
+
}
|
|
101
109
|
async function updateLogSettings() {
|
|
102
110
|
if (!rootConfig) {
|
|
103
111
|
// set up the initial watcher
|
|
@@ -109,6 +117,14 @@ async function updateLogSettings() {
|
|
|
109
117
|
}
|
|
110
118
|
let rootConfigObject = rootConfig.config;
|
|
111
119
|
const logOptions = rootConfigObject.logging ?? {};
|
|
120
|
+
// Resolve relative paths against rootPath from the same config
|
|
121
|
+
const rootPath = rootConfigObject.rootPath;
|
|
122
|
+
if (logOptions.root) {
|
|
123
|
+
logOptions.root = resolveLogPath(logOptions.root, rootPath);
|
|
124
|
+
}
|
|
125
|
+
if (logOptions.rotation?.path) {
|
|
126
|
+
logOptions.rotation.path = resolveLogPath(logOptions.rotation.path, rootPath);
|
|
127
|
+
}
|
|
112
128
|
updateLogger(mainLogger, logOptions);
|
|
113
129
|
logFilePath = mainLogger.path;
|
|
114
130
|
logConsole = logOptions.console ?? false;
|
|
@@ -805,13 +821,18 @@ function getLogConfig(hdbConfigPath) {
|
|
|
805
821
|
};
|
|
806
822
|
}
|
|
807
823
|
const configDoc = YAML.parseDocument(fs.readFileSync(hdbConfigPath, 'utf8'));
|
|
824
|
+
const rootPath = configDoc.getIn(['rootPath']);
|
|
808
825
|
const level = configDoc.getIn(['logging', 'level']);
|
|
809
|
-
const configLogPath = configDoc.getIn(['logging', 'root']);
|
|
826
|
+
const configLogPath = resolveLogPath(configDoc.getIn(['logging', 'root']), rootPath);
|
|
810
827
|
const toFile = configDoc.getIn(['logging', 'file']);
|
|
811
828
|
const toStream = configDoc.getIn(['logging', 'stdStreams']);
|
|
812
829
|
const logConsole = configDoc.getIn(['logging', 'console']);
|
|
813
830
|
const colorMode = configDoc.getIn(['logging', 'colors']) ?? true; // default to true
|
|
814
831
|
const rotation = configDoc.getIn(['logging', 'rotation'])?.toJSON();
|
|
832
|
+
// Resolve rotation path if relative
|
|
833
|
+
if (rotation?.path) {
|
|
834
|
+
rotation.path = resolveLogPath(rotation.path, rootPath);
|
|
835
|
+
}
|
|
815
836
|
|
|
816
837
|
return {
|
|
817
838
|
level,
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const hdbTerms = require('../hdbTerms.ts');
|
|
4
4
|
const hdbLogger = require('./harper_logger.js');
|
|
5
|
-
const envMangr = require('../environment/environmentManager.js');
|
|
6
5
|
const validator = require('../../validation/readLogValidator.js');
|
|
7
6
|
const path = require('path');
|
|
8
7
|
const fs = require('fs-extra');
|
|
9
8
|
const { once } = require('events');
|
|
9
|
+
const { getConfigPath } = require('../../config/configUtils.js');
|
|
10
10
|
const { handleHDBError, hdbErrors } = require('../errors/hdbError.js');
|
|
11
11
|
const { PACKAGE_ROOT } = require('../../utility/packageUtils.js');
|
|
12
12
|
const { server } = require('../../server/Server.ts');
|
|
@@ -39,7 +39,7 @@ async function readLog(request) {
|
|
|
39
39
|
// start pulling logs from the other nodes now so it can be done in parallel
|
|
40
40
|
let whenReplicatedResponse = server.replication.replicateOperation(request);
|
|
41
41
|
|
|
42
|
-
const logPath =
|
|
42
|
+
const logPath = getConfigPath(hdbTerms.HDB_SETTINGS_NAMES.LOG_PATH_KEY);
|
|
43
43
|
const logName = request.log_name === undefined ? hdbTerms.LOG_NAMES.HDB : request.log_name;
|
|
44
44
|
const readLogPath =
|
|
45
45
|
logName === hdbTerms.LOG_NAMES.INSTALL
|
package/utility/npmUtilities.js
CHANGED
|
@@ -14,7 +14,7 @@ module.exports = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
const { CONFIG_PARAMS } = require('./hdbTerms.ts');
|
|
17
|
-
const {
|
|
17
|
+
const { getConfigPath } = require('../config/configUtils.js');
|
|
18
18
|
const { nonInteractiveSpawn } = require('../components/Application.ts');
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -34,7 +34,7 @@ async function installModules(req) {
|
|
|
34
34
|
|
|
35
35
|
let { projects, dryRun } = req;
|
|
36
36
|
|
|
37
|
-
const componentsRootDirPath =
|
|
37
|
+
const componentsRootDirPath = getConfigPath(CONFIG_PARAMS.COMPONENTSROOT);
|
|
38
38
|
|
|
39
39
|
const responseObject = {};
|
|
40
40
|
|
|
@@ -226,9 +226,17 @@ function doesPathExist(pathToCheck) {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
function validatePath(value, helpers) {
|
|
229
|
-
Joi.assert(value, string.pattern(/^[
|
|
229
|
+
Joi.assert(value, string.pattern(/^[\\/~]$|([\\/~a-zA-Z_0-9:-]+)+$/, 'directory path'));
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
let resolvedValue;
|
|
232
|
+
if (value.startsWith('~/')) {
|
|
233
|
+
resolvedValue = path.join(os.homedir(), value.slice(1));
|
|
234
|
+
} else if (path.isAbsolute(value)) {
|
|
235
|
+
resolvedValue = value;
|
|
236
|
+
} else {
|
|
237
|
+
resolvedValue = path.join(hdbRoot, value);
|
|
238
|
+
}
|
|
239
|
+
const doesExistMsg = doesPathExist(resolvedValue);
|
|
232
240
|
if (doesExistMsg) {
|
|
233
241
|
return helpers.message(doesExistMsg);
|
|
234
242
|
}
|
|
@@ -302,17 +310,17 @@ function setDefaultRoot(parent, helpers) {
|
|
|
302
310
|
|
|
303
311
|
switch (configParam) {
|
|
304
312
|
case 'componentsRoot':
|
|
305
|
-
return
|
|
313
|
+
return DEFAULT_COMPONENTS_FOLDER;
|
|
306
314
|
case 'logging.root':
|
|
307
|
-
return
|
|
315
|
+
return DEFAULT_LOG_FOLDER;
|
|
308
316
|
case 'storage.path':
|
|
309
317
|
const legacyStoragePath = path.join(hdbRoot, hdbTerms.LEGACY_DATABASES_DIR_NAME);
|
|
310
|
-
if (fs.existsSync(legacyStoragePath)) return
|
|
311
|
-
return
|
|
318
|
+
if (fs.existsSync(legacyStoragePath)) return hdbTerms.LEGACY_DATABASES_DIR_NAME;
|
|
319
|
+
return hdbTerms.DATABASES_DIR_NAME;
|
|
312
320
|
case 'logging.rotation.path':
|
|
313
|
-
return
|
|
321
|
+
return DEFAULT_LOG_FOLDER;
|
|
314
322
|
case 'operationsApi.network.domainSocket':
|
|
315
|
-
return configParam == null ? null :
|
|
323
|
+
return configParam == null ? null : 'operations-server';
|
|
316
324
|
default:
|
|
317
325
|
throw new Error(`Error setting default root for config parameter: ${configParam}. Unrecognized config parameter`);
|
|
318
326
|
}
|