unleash-server 7.6.1 → 7.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.d.ts.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.js +29 -17
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.js.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.test.js +99 -0
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.test.js.map +1 -1
- package/dist/lib/features/feature-search/feature.search.e2e.test.js +1 -1
- package/dist/lib/features/feature-search/feature.search.e2e.test.js.map +1 -1
- package/dist/lib/openapi/spec/feature-search-query-parameters.d.ts +1 -1
- package/dist/lib/openapi/spec/feature-search-query-parameters.d.ts.map +1 -1
- package/dist/lib/openapi/spec/feature-search-query-parameters.js.map +1 -1
- package/dist/lib/routes/logout.d.ts +0 -1
- package/dist/lib/routes/logout.d.ts.map +1 -1
- package/dist/lib/routes/logout.js +1 -5
- package/dist/lib/routes/logout.js.map +1 -1
- package/dist/lib/routes/logout.test.js +4 -4
- package/dist/lib/routes/logout.test.js.map +1 -1
- package/dist/lib/services/user-service.d.ts.map +1 -1
- package/dist/lib/services/user-service.js +0 -4
- package/dist/lib/services/user-service.js.map +1 -1
- package/dist/lib/types/experimental.d.ts +1 -1
- package/dist/lib/types/experimental.d.ts.map +1 -1
- package/dist/lib/types/experimental.js +2 -4
- package/dist/lib/types/experimental.js.map +1 -1
- package/dist/server-dev.js +1 -1
- package/dist/server-dev.js.map +1 -1
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/{AdvancedPlayground-CJ7eG--B.js → AdvancedPlayground-BTPrG6RW.js} +1 -1
- package/frontend/build/static/{BackendConnections-C9C9tzVe.js → BackendConnections-CRh8Vxoe.js} +1 -1
- package/frontend/build/static/{CreateProject-C2o4HAPI.js → CreateProject-DEMalH1j.js} +1 -1
- package/frontend/build/static/{EnterpriseEdge-wEksSFXY.js → EnterpriseEdge-Cp-pGMa0.js} +1 -1
- package/frontend/build/static/{FeatureMetricsChart-Dg3LuBck.js → FeatureMetricsChart-DQOE71LA.js} +2 -2
- package/frontend/build/static/FeatureStaleDialog-B6BfnDiQ.js +689 -0
- package/frontend/build/static/{FeatureViewLazyExport-0rEqFrgo.js → FeatureViewLazyExport-BkNTNFqK.js} +3 -3
- package/frontend/build/static/{FlagMetricsChart-DbKM-kaT.js → FlagMetricsChart-zYDF9bet.js} +1 -1
- package/frontend/build/static/FrontendNetworkTrafficUsage-CbxdFXH7.js +1 -0
- package/frontend/build/static/GridLayoutWrapper-Cq6Bzm36.js +3 -0
- package/frontend/build/static/{ImpactMetricsPage-BDLs7Gss.js → ImpactMetricsPage-CFYXYXPb.js} +1 -1
- package/frontend/build/static/LazyAdminExport-ByTh4iFa.js +38 -0
- package/frontend/build/static/{LazyProjectExport-B5ifELrF.js → LazyProjectExport-K12Xy3w9.js} +19 -701
- package/frontend/build/static/{LifecycleChartComponent-CJWEy-Ub.js → LifecycleChartComponent-DHvlFNd2.js} +1 -1
- package/frontend/build/static/LineChartComponent-BlhKm3cw.js +1 -0
- package/frontend/build/static/{MarkCompletedDialogue-C86IfCH-.js → MarkCompletedDialogue-apmlFjVY.js} +1 -1
- package/frontend/build/static/{NetworkOverview-Cjz8v1WC.js → NetworkOverview-BiLOuQ4c.js} +1 -1
- package/frontend/build/static/{NetworkPrometheusAPIWarning-qXY7ao0F.js → NetworkPrometheusAPIWarning-CYo3j2Tj.js} +1 -1
- package/frontend/build/static/{NetworkTraffic-BBEsgALR.js → NetworkTraffic-DONL5oIx.js} +1 -1
- package/frontend/build/static/{NetworkTrafficUsage-a6syIscc.js → NetworkTrafficUsage-DjQiYq0S.js} +1 -1
- package/frontend/build/static/{PercentageDonut-CC9h07JZ.js → PercentageDonut-CA9hYg3v.js} +1 -1
- package/frontend/build/static/{ReactJSONEditor-B-T6_DlA.js → ReactJSONEditor-9cJL1vJY.js} +1 -1
- package/frontend/build/static/{RoleCell-4trKLU2Y.js → RoleCell-ZzU5Oqy8.js} +1 -1
- package/frontend/build/static/Safeguard-DY1N4aPz.js +1 -0
- package/frontend/build/static/{aggregateFeatureMetrics-CAg4DbsF.js → aggregateFeatureMetrics-D6bHft_C.js} +1 -1
- package/frontend/build/static/{formatTickValue-BxmGFWwJ.js → formatTickValue-BcLsqREh.js} +1 -1
- package/frontend/build/static/{index-Cikp5fMR.js → index-CoLhlfXP.js} +131 -135
- package/frontend/build/static/{networkTrafficUsageHighlightPlugin-mvUd1fv5.js → networkTrafficUsageHighlightPlugin-CqEM-cK_.js} +1 -1
- package/frontend/build/static/{useApiTokens-BHKIbW5c.js → useApiTokens-ClWvohC9.js} +1 -1
- package/frontend/package.json +2 -2
- package/package.json +3 -3
- package/frontend/build/static/FeatureStaleDialog-DmUpnOZe.js +0 -7
- package/frontend/build/static/FrontendNetworkTrafficUsage-DkvZ1uov.js +0 -1
- package/frontend/build/static/GridLayoutWrapper-Dwn6EwoE.js +0 -3
- package/frontend/build/static/LazyAdminExport-CE3juyvl.js +0 -38
- package/frontend/build/static/LineChartComponent-tPwau2Yw.js +0 -1
- package/frontend/build/static/Safeguard-DArPoSLG.js +0 -1
|
@@ -0,0 +1,689 @@
|
|
|
1
|
+
import{E as Z,j as n,F as ee,A as ve,l as Se,C as ne,m as Fe,n as Ne,bf as Le,kp as $e,o as Ye,b as L,T as y,s as h,u as je,b7 as ze,r as x,b6 as te,b8 as ae,ba as Be,c0 as $,aN as _e,by as He,hQ as Ge,bA as qe,f as P,bB as We,b9 as se,bq as Me,ao as Ue,kq as Ve,bG as Je,kr as Qe,b5 as M,ks as Xe,jB as Ze,jr as en,i as E,h as T,kt as nn,cp as Ce,aQ as tn,aR as an,aO as sn,aU as Ae,be as de,bc as ke,ku as on,kv as rn,kw as ln,jp as cn,kx as dn,B as _,an as un,cq as pn,fV as hn,hh as gn,K as Y,ia as mn,cN as Ie,ai as Re,ky as I,kz as fn,kA as bn,kB as xn,kC as yn,kD as vn,kE as Sn,kF as jn,kG as _n,kH as Un,kI as Cn,kJ as An,kK as kn,kL as In,kM as Rn,kN as En,fA as V,cL as J,it as z,cy as Tn,ie as wn,aM as N,d as Pn,x as Dn,hL as On,w as Kn,d3 as Fn,i_ as Q,aB as Nn,c8 as Ln}from"./index-CoLhlfXP.js";var oe={},$n=ee;Object.defineProperty(oe,"__esModule",{value:!0});var Ee=oe.default=void 0,Yn=$n(Z()),zn=n,Bn=(0,Yn.default)((0,zn.jsx)("path",{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z"}),"IndeterminateCheckBox");Ee=oe.default=Bn;const Hn=$e(),ja=({options:e,selectedOptions:t,indeterminateOptions:a,tagType:s,existingTags:o,disabled:r=!1,onChange:l})=>{const i=n.jsx(Ye,{fontSize:"small"}),d=u=>u.inputValue?u.inputValue:u.title,m=({key:u,...g},c,{selected:f})=>{const j=(a==null?void 0:a.some(v=>v.title===c.title))??!1;return n.jsxs("li",{...g,children:[n.jsx(ne,{condition:!!c.inputValue,show:n.jsx(Le,{sx:{mr:v=>v.spacing(.5)}}),elseShow:n.jsx(Fe,{icon:i,checkedIcon:n.jsx(Ne,{fontSize:"small"}),indeterminateIcon:n.jsx(Ee,{fontSize:"small"}),sx:{mr:v=>v.spacing(.5)},checked:f&&!j,indeterminate:j})}),c.title]},u)},b=(u,g)=>{const c=g.inputValue.trim(),f=Hn(u,{...g,inputValue:c}),j=u.some(v=>c===v.title);return c.length>=2&&!j&&f.push({inputValue:c,title:`Create new value "${c}"`}),f};return n.jsx(ve,{multiple:!0,id:"checkboxes-tag",sx:{marginTop:u=>u.spacing(2),width:500},disableCloseOnSelect:!0,options:e,value:t,isOptionEqualToValue:(u,g)=>g.inputValue&&g.inputValue!==""?u.title===g.inputValue:u.title===g.title,getOptionLabel:d,renderOption:m,filterOptions:b,ListboxProps:{style:{maxHeight:200,overflow:"auto"}},onChange:l,renderInput:u=>n.jsx(Se,{...u,label:"Select values",placeholder:"Select values"}),disabled:r})},Gn=h("li")({flexDirection:"column"}),_a=({options:e,value:t,disabled:a=!1,onChange:s})=>{const o=L();return n.jsx(ve,{disablePortal:!0,disabled:a,id:"tag-type-select",sx:{marginTop:r=>r.spacing(2),width:500},options:e,disableClearable:!0,value:t,getOptionLabel:r=>r.name,renderOption:({key:r,...l},i)=>n.jsxs(Gn,{...l,style:{alignItems:"flex-start",gap:o.spacing(.5)},children:[n.jsx(y,{variant:"body1",children:i.name}),n.jsx(y,{variant:"caption",children:i.description})]},r),renderInput:r=>n.jsx(Se,{...r,label:"Tag type",value:t}),onChange:s,ListboxProps:{style:{maxHeight:200,overflow:"auto"}}})},Ua=()=>{const{makeRequest:e,createRequest:t,errors:a,loading:s}=je({propagateErrors:!0});return{createTag:async l=>{const d=t("api/admin/tags",{method:"POST",body:JSON.stringify(l)});return e(d.caller,d.id)},bulkUpdateTags:async(l,i)=>{const d=`api/admin/projects/${i}/tags`,m=t(d,{method:"PUT",body:JSON.stringify(l)});return e(m.caller,m.id)},errors:a,loading:s}},Ca=(e,t={})=>{const a=async()=>{const m=te(`api/admin/tags/${e}`);return(await fetch(m,{method:"GET"}).then(ae("Tags"))).json()},s=`api/admin/tags/${e}`,{data:o,error:r}=ze(!!e,{tags:[]},s,a,t),[l,i]=x.useState(!r&&!o),d=()=>{Be(s)};return x.useEffect(()=>{i(!r&&!o)},[o,r]),{tags:(o==null?void 0:o.tags)||[],error:r,loading:l,refetch:d}},qn=(e,t)=>{var l,i;const{project:a,refetch:s}=$(e),o={name:"flexibleRollout",constraints:[],parameters:{rollout:"100",stickiness:a.defaultStickiness||"default",groupId:""}},r=(i=(l=a.environments)==null?void 0:l.find(d=>d.environment===t))==null?void 0:i.defaultStrategy;return{defaultStrategyFallback:o,strategy:r,refetch:s}},Aa=()=>{const e=_e("projectId"),t=He("environmentId"),{refetch:a}=$(e),{defaultStrategyFallback:s,strategy:o,refetch:r}=qn(e,t),[l,i]=x.useState(o||s),{updateDefaultStrategy:d,loading:m}=Ge(),{strategyDefinition:b}=qe(l.name),{setToastData:u,setToastApiError:g}=P(),c=We(),{uiConfig:f}=se(),{unleashUrl:j}=f,v=Me(),{trackEvent:R}=Ue(),k=Ve(l.constraints);if(!b)return null;const C=Wn(l),p=async()=>{const D=`/projects/${e}/settings/default-strategy`;try{await d(e,t,C),R("default_strategy",{props:{action:"edit",hasTitle:!!C.title}}),a(),u({text:"Default Strategy updated",type:"success"}),await r(),v(D)}catch(ce){g(T(ce))}};return n.jsx(Je,{modal:!0,disablePadding:!0,description:Vn,documentationLink:Jn,documentationLinkLabel:Qn,formatApiCode:()=>Mn(e,t,C,b,j),children:n.jsxs(Qe,{strategy:l,setStrategy:i,strategyDefinition:b,errors:c,groupIdTooltip:"Defaults to the feature flag name if not set.",onSubmit:p,children:[n.jsx(M,{permission:[Ze,en],projectId:e,environmentId:t,variant:"contained",color:"primary",type:"submit",disabled:m||!k||c.hasFormErrors(),"data-testid":Xe,children:"Save strategy"}),n.jsx(E,{type:"button",onClick:()=>v(`/projects/${e}/settings/default-strategy`),children:"Cancel"})]})})},Wn=e=>({name:e.name,title:e.title,constraints:e.constraints??[],parameters:Object.fromEntries(Object.entries(e.parameters??{}).filter(([,t])=>t!==void 0).map(([t,a])=>[t,String(a)])),variants:e.variants??[],segments:e.segments??[],disabled:e.disabled??!1}),Mn=(e,t,a,s,o)=>{if(!o)return"";const r={...a,parameters:nn(a.parameters??{},s)},l=`${o}/api/admin/projects/${e}/environments/${t}/default-strategy`,i=JSON.stringify(r,void 0,2);return`curl --location --request POST '${l}' \\
|
|
2
|
+
--header 'Authorization: INSERT_API_KEY' \\
|
|
3
|
+
--header 'Content-Type: application/json' \\
|
|
4
|
+
--data-raw '${i}'`},Vn=`
|
|
5
|
+
An activation strategy will only run when a feature flag is enabled and provides a way to control who will get access to the feature.
|
|
6
|
+
If any of a feature flag's activation strategies returns true, the user will get access.
|
|
7
|
+
`,Jn="https://docs.getunleash.io/concepts/projects#project-default-strategy",Qn="Default strategy documentation",ka=e=>{const{data:t,error:a,mutate:s}=Ce(te(`api/admin/environments/project/${e}`),Xn),o=x.useMemo(()=>t||[],[t]),r=x.useCallback(async()=>{await s()},[s]);return{environments:o,refetchEnvironments:r,loading:!a&&!t,error:a}},Xn=async e=>(await fetch(e).then(ae("Environments")).then(a=>a.json())).environments.sort((a,s)=>a.sortOrder-s.sortOrder),Zn=e=>{const{setToastData:t,setToastApiError:a}=P(),{addChange:s}=tn(),{refetch:o}=an(e),[r,l]=x.useState(!1),[i,d]=x.useState({isOpen:!1}),m=x.useCallback((g,c,f,j)=>{d({featureName:g,environment:c,enabled:f,shouldActivateDisabledStrategies:j,isOpen:!0})},[]),b=x.useCallback(()=>{d(g=>({...g,isOpen:!1}))},[]),u=x.useCallback(async()=>{try{l(!0),await s(e,i.environment,{feature:i.featureName,action:"updateEnabled",payload:{enabled:!!i.enabled,shouldActivateDisabledStrategies:!!i.shouldActivateDisabledStrategies}}),o(),d(g=>({...g,isOpen:!1})),t({type:"success",text:"Changes added to draft"})}catch(g){a(T(g)),d(c=>({...c,isOpen:!1}))}finally{l(!1)}},[s]);return{pending:r,onChangeRequestToggle:m,onChangeRequestToggleClose:b,onChangeRequestToggleConfirm:u,changeRequestDialogDetails:i}},et=({enabled:e,featureName:t,environment:a})=>n.jsxs(y,{"data-testid":"update-enabled-message",children:[n.jsx("strong",{children:e?"Enable":"Disable"})," feature flag"," ",n.jsx("strong",{children:t})," in ",n.jsx("strong",{children:a})]}),nt=h("ul")(({theme:e})=>({margin:e.spacing(1),paddingLeft:e.spacing(2)})),tt=({isOpen:e,onAddDefaultStrategy:t,onActivateDisabledStrategies:a,onClose:s,environment:o,featureId:r})=>{var b,u,g;const l=_e("projectId"),{feature:i}=sn(l,r),d=(g=(u=(b=i.environments)==null?void 0:b.find(({name:c})=>c===o))==null?void 0:u.strategies)==null?void 0:g.filter(({disabled:c})=>c).length,m=d?d===1?"1 disabled strategy":`${d} disabled strategies`:"disabled strategies";return n.jsxs(Ae,{open:e,secondaryButtonText:"Cancel",permissionButton:n.jsxs(n.Fragment,{children:[n.jsx(M,{type:"button",variant:"outlined",permission:de,projectId:l,environmentId:o,onClick:t,children:"Add default strategy"}),n.jsx(M,{type:"button",variant:"outlined",permission:de,projectId:l,environmentId:o,onClick:a,children:"Enable all strategies"})]}),onClose:s,title:`Enable feature flag in ${o}`,fullWidth:!0,children:[n.jsx(y,{sx:{mb:c=>c.spacing(3)},children:"A feature flag cannot be enabled without an enabled strategy."}),n.jsx(y,{children:"To enable this feature flag you can choose to:"}),n.jsxs(nt,{children:[n.jsx("li",{children:n.jsx(y,{children:n.jsx("strong",{children:"Add the default strategy"})})}),n.jsx("li",{children:n.jsxs(y,{children:[n.jsx("strong",{children:"Enable all the disabled strategies"})," ","(this feature flag has ",m,")"]})})]})]})},at=e=>{const t=a=>{a<e.length&&e[a](()=>t(a+1))};t(0)},Ia=e=>{const{toggleFeatureEnvironmentOn:t,toggleFeatureEnvironmentOff:a}=ke(),{setToastData:s,setToastApiError:o}=P(),[r,l]=x.useState({open:!1,label:"",loading:!1,onClose:()=>{},onClick:()=>{}}),[i,d]=x.useState({isOpen:!1,environment:"",featureId:"",onClose:()=>{},onActivateDisabledStrategies:()=>{},onAddDefaultStrategy:()=>{}}),{pending:m,onChangeRequestToggle:b,onChangeRequestToggleClose:u,onChangeRequestToggleConfirm:g,changeRequestDialogDetails:c}=Zn(e),[f,j]=x.useState(),v=x.useCallback(async(C,p)=>{let D=!1;return at([U=>{if(p.isChangeRequestEnabled||!ln(p.environmentType||""))return U();l({open:!0,label:`${C?"Enable":"Disable"} Environment`,loading:!1,onClose:()=>{var S;l(A=>({...A,open:!1})),(S=p.onRollback)==null||S.call(p)},onClick:()=>{l(S=>({...S,open:!1,loading:!0})),U()}})},U=>{if(C===!1||!p.hasStrategies||p.hasEnabledStrategies||p.hasReleasePlans)return U();d({isOpen:!0,environment:p.environmentName,featureId:p.featureId,onClose:()=>{var S;d(A=>({...A,isOpen:!1})),(S=p.onRollback)==null||S.call(p)},onActivateDisabledStrategies:()=>{d(S=>({...S,isOpen:!1})),D=!0,U()},onAddDefaultStrategy:()=>{d(S=>({...S,isOpen:!1})),U()}})},U=>{if(!p.isChangeRequestEnabled)return U();j(()=>{var S;j(void 0),(S=p.onRollback)==null||S.call(p)}),b(p.featureId,p.environmentName,C,D)},async U=>{var S,A;if(C!==!1)return U();try{await a(p.projectId,p.featureId,p.environmentName),s({type:"success",text:`Disabled in ${p.environmentName}`}),(S=p.onSuccess)==null||S.call(p)}catch(G){o(T(G)),(A=p.onRollback)==null||A.call(p)}},async U=>{var S,A;if(C!==!0)return U();try{await t(p.projectId,p.featureId,p.environmentName,D),s({type:"success",text:`Enabled in ${p.environmentName}`}),(S=p.onSuccess)==null||S.call(p)}catch(G){o(T(G)),(A=p.onRollback)==null||A.call(p)}}])},[l]),R=i.featureId.length!==0,k=n.jsxs(n.Fragment,{children:[n.jsx(on,{...r}),n.jsx(ne,{condition:R,show:n.jsx(tt,{...i})}),n.jsx(rn,{isOpen:c.isOpen,onClose:()=>{f==null||f(),u()},environment:c==null?void 0:c.environment,disabled:m,onConfirm:()=>{f==null||f(),g()},messageComponent:n.jsx(et,{enabled:c==null?void 0:c.enabled,featureName:c==null?void 0:c.featureName,environment:c.environment})})]});return{onToggle:v,modals:k}},st=e=>{const[t,a]=x.useState(e),s=x.useCallback(()=>a(e),[e]);return x.useEffect(()=>{a(e)},[e]),[t,a,s]},ot=h(_)(()=>({mx:"auto",...un})),Ra=({projectId:e,featureId:t,environmentName:a,value:s,onToggle:o})=>{const[r,l,i]=st(s),d=()=>{l(!r),requestAnimationFrame(()=>{o(!r,i)})},m=`${t}-${a}`;return n.jsx(n.Fragment,{children:n.jsx(ot,{"data-testid":`TOGGLE-${m}`,children:n.jsx(cn,{tooltip:r?`Disable flag in ${a}`:`Enable flag in ${a}`,checked:s,environmentId:a,projectId:e,permission:dn,inputProps:{"aria-label":a},onClick:d,"data-testid":"permission-switch",disabled:s!==r})},m)})};var ie={},it=ee;Object.defineProperty(ie,"__esModule",{value:!0});var rt=ie.default=void 0,lt=it(Z()),ct=n,dt=(0,lt.default)((0,ct.jsx)("path",{d:"M16 11h-1V3c0-1.1-.9-2-2-2h-2c-1.1 0-2 .9-2 2v8H8c-2.76 0-5 2.24-5 5v7h18v-7c0-2.76-2.24-5-5-5zm3 10h-2v-3c0-.55-.45-1-1-1s-1 .45-1 1v3h-2v-3c0-.55-.45-1-1-1s-1 .45-1 1v3H9v-3c0-.55-.45-1-1-1s-1 .45-1 1v3H5v-5c0-1.65 1.35-3 3-3h8c1.65 0 3 1.35 3 3v5z"}),"CleaningServices");rt=ie.default=dt;const ut="flag-reminders:v1",pt=50,ht=7,Ea=({days:e=ht,maxReminders:t=pt}={})=>{const[a,s]=pn(ut,{});return{shouldShowReminder:l=>{const i=a[l];return!i||gn(new Date,new Date(i))},snoozeReminder:(l,i=e)=>{const d=hn(new Date,i).getTime();s(m=>{const b={...m,[l]:d},u=Object.entries(b);if(u.length>t){u.sort((c,f)=>c[1]-f[1]);const g=u.slice(u.length-t);return Object.fromEntries(g)}return b})}}},gt=(e,t={})=>{const a=te(`api/admin/projects/${e}/api-tokens`),{data:s,error:o,mutate:r}=Ce(a,mt,t),l=x.useMemo(()=>s??[],[s]),i=x.useCallback(()=>{r().catch(console.warn)},[r]);return{tokens:l,error:o,loading:!o&&!s,refetch:i}},mt=async e=>(await(await fetch(e).then(ae("Project Api tokens"))).json()).tokens,ft=()=>{const{makeRequest:e,createRequest:t,errors:a,loading:s}=je({propagateErrors:!0});return{deleteToken:async(l,i)=>{const d=`api/admin/projects/${i}/api-tokens/${l}`,m=t(d,{method:"DELETE"});return e(m.caller,m.id)},createToken:async(l,i)=>{const d=`api/admin/projects/${i}/api-tokens`,m=t(d,{method:"POST",body:JSON.stringify(l)});return e(m.caller,m.id)},errors:a,loading:s}},bt=e=>{if(!e)return null;const[t,a]=e.split(":",2);if(!a)return null;const[s,o,...r]=a.split(".");return t&&s&&o&&r.length===0?{project:t,environment:s,secret:o}:null},w=h("div")(({theme:e})=>({fontWeight:e.typography.fontWeightBold,marginBottom:e.spacing(1),fontSize:e.typography.body1.fontSize})),B=h("div")(({theme:e})=>({display:"flex",alignItems:"center",justifyContent:"space-between",marginTop:e.spacing(2)})),xt=h("div")(({theme:e})=>({display:"flex",gap:e.spacing(1)})),yt=h("div")(({theme:e})=>({background:e.palette.background.application,borderRadius:e.shape.borderRadius,width:e.spacing(7),height:e.spacing(1)})),vt=h("div")(({theme:e})=>({background:e.palette.background.sidebar,borderRadius:e.shape.borderRadius,width:e.spacing(7),height:e.spacing(1)})),H=({active:e,steps:t})=>n.jsx(xt,{children:Array.from({length:t},(a,s)=>s===e?n.jsx(vt,{},s):n.jsx(yt,{},s))}),St=({environments:e,onSelect:t,currentEnvironment:a})=>{const s=Math.max(...e.map(o=>o.length));return n.jsx(mn,{tooltip:{header:""},description:"Select the environment where the API key will be created",options:e.map(o=>({label:o,value:o})),onChange:o=>{t(o)},button:{label:a,icon:n.jsx(Ie,{}),labelWidth:`${s+5}ch`},search:{label:"Filter project mode options",placeholder:"Select project mode"}})},jt=h("div")(({theme:e})=>({backgroundColor:e.palette.background.elevation1,borderRadius:e.shape.borderRadius,padding:e.spacing(3),display:"flex",flexDirection:"column",alignItems:"center"})),q=h("div")(({theme:e})=>({backgroundColor:e.palette.background.paper,borderRadius:e.shape.borderRadius,padding:e.spacing(2),flex:1,color:e.palette.text.secondary,fontSize:e.typography.body2.fontSize})),_t=h(_)(({theme:e})=>({display:"flex",gap:e.spacing(2),alignItems:"flex-start",marginTop:e.spacing(8),flexWrap:"wrap"})),W=h("p")(({theme:e})=>({color:e.palette.text.secondary,fontSize:e.typography.body2.fontSize,marginBottom:e.spacing(2)})),Ut=h("div")(({theme:e})=>({padding:e.spacing(5,8,3,8),display:"flex",flexDirection:"column",gap:e.spacing(3)})),Ct=({project:e,environment:t,secret:a})=>{const s=L(),o=Re(s.breakpoints.up("lg"));return n.jsx(I.ArcherContainer,{strokeColor:s.palette.secondary.border,endMarker:!1,lineStyle:"curve",children:n.jsxs(jt,{children:[n.jsxs(_,{sx:{wordBreak:"break-all"},children:[n.jsx(I.ArcherElement,{id:"project",children:n.jsx("span",{children:e})}),":",n.jsx(I.ArcherElement,{id:"environment",children:n.jsx("span",{children:t})}),".",n.jsx(I.ArcherElement,{id:"secret",children:n.jsx("span",{children:a})})]}),o?n.jsxs(_t,{children:[n.jsx(I.ArcherElement,{id:"project-description",relations:[{targetId:"project",targetAnchor:"bottom",sourceAnchor:"top"}],children:n.jsx(q,{children:"The project this API key can retrieve feature flags from"})}),n.jsx(I.ArcherElement,{id:"environment-description",relations:[{targetId:"environment",targetAnchor:"bottom",sourceAnchor:"top"}],children:n.jsx(q,{children:"The environment this API key can retrieve feature flag configuration from"})}),n.jsx(I.ArcherElement,{id:"secret-description",relations:[{targetId:"secret",targetAnchor:"right",sourceAnchor:"top"}],children:n.jsx(q,{children:"The API key secret"})})]}):null]})})},At=({environments:e,environment:t,project:a,sdkType:s,onEnvSelect:o,onApiKey:r})=>{const{trackEvent:l}=Ue(),{tokens:i,refetch:d}=gt(a),{createToken:m,loading:b}=ft(),u=i.find(v=>v.environment===t&&v.type===s);x.useEffect(()=>{r((u==null?void 0:u.secret)||null)},[u]);const g=bt(u==null?void 0:u.secret),{setToastApiError:c}=P(),f=async()=>{try{await m({environment:t,type:s,projects:[a],tokenName:`api-key-${a}-${t}`},a),d(),j()}catch(v){c(T(v))}},j=()=>{l("onboarding",{props:{eventType:"api-key-generated"}})};return n.jsxs(Ut,{children:[n.jsx(y,{variant:"h2",children:"Connect an SDK to Unleash"}),n.jsxs(B,{children:[n.jsx(H,{active:1,steps:3}),n.jsx(Y,{color:"secondary",children:"2/3 - Generate API Key"})]}),n.jsxs(_,{sx:{mt:2},children:[n.jsx(w,{children:"Environment"}),n.jsx(W,{children:"The environment the SDK connects to to retrieve configuration."}),e.length>0?n.jsx(St,{environments:e,currentEnvironment:t,onSelect:o}):null]}),n.jsxs(_,{sx:{mt:3},children:[n.jsx(w,{children:"API Key"}),g?n.jsxs(W,{children:["Here is your generated API key. We will use it to connect to the ",n.jsx("b",{children:g.project})," project in the ",n.jsx("b",{children:g.environment})," environment."]}):n.jsx(W,{children:"You currently have no active API keys for this project/environment combination. Generate an API key to proceed with connecting your SDK."}),g?n.jsx(Ct,{project:g.project,environment:g.environment,secret:g.secret}):n.jsx(E,{variant:"contained",disabled:b,onClick:f,children:"Generate API Key"})]})]})},Te=[{name:"Node.js",icon:fn},{name:"Go",icon:bn},{name:"Ruby",icon:xn},{name:"PHP",icon:yn},{name:"Rust",icon:vn},{name:".NET",icon:Sn},{name:"Java",icon:jn},{name:"Python",icon:_n}],we=[{name:"JavaScript",icon:Un},{name:"React",icon:Cn},{name:"Vue",icon:An},{name:"Svelte",icon:kn},{name:"Swift",icon:In},{name:"Android",icon:Rn},{name:"Flutter",icon:En}],kt=[...Te,...we],It=h("div")(({theme:e})=>({padding:e.spacing(5,8,8,8),display:"flex",flexDirection:"column",gap:e.spacing(3)})),ue=h("div")(({theme:e})=>({marginTop:e.spacing(4),marginBottom:e.spacing(2),fontSize:e.typography.body1.fontSize})),pe=h("div")(({theme:e})=>({backgroundColor:e.palette.background.elevation1,borderRadius:e.shape.borderRadius,padding:e.spacing(6),display:"flex",columnGap:e.spacing(2),rowGap:e.spacing(5),alignItems:"center",justifyContent:"flex-start",flexWrap:"wrap"})),he=h("div")(({theme:e})=>({fontSize:e.typography.body2.fontSize,backgroundColor:e.palette.background.default,borderRadius:e.shape.borderRadius,padding:e.spacing(2,3),width:"170px",position:"relative"})),ge=h("div")(()=>({display:"flex",justifyContent:"space-between"})),me=h(z)(({theme:e})=>({position:"absolute",width:e.spacing(4),height:e.spacing(4),top:e.spacing(-2.75),left:e.spacing(2),boxShadow:e.shadows[2]})),Rt=({onSelect:e})=>n.jsxs(It,{children:[n.jsx(y,{variant:"h2",children:"Connect an SDK to Unleash"}),n.jsxs(B,{children:[n.jsx(H,{active:0,steps:3}),n.jsx(Y,{color:"secondary",children:"1/3 - Choose SDK"})]}),n.jsxs(_,{sx:{mt:2},children:[n.jsx(w,{children:"Select SDK"}),n.jsx(ue,{children:"Server side SDKs"}),n.jsx(pe,{children:Te.map(t=>n.jsxs(he,{children:[n.jsx(me,{src:V(t.icon)}),n.jsxs(ge,{children:[n.jsx("b",{children:t.name})," ",n.jsx(J,{onClick:()=>e({name:t.name,type:"client"}),component:"button",children:"Select"})]})]},t.name))}),n.jsx(ue,{children:"Client side SDKs"}),n.jsx(pe,{children:we.map(t=>n.jsxs(he,{children:[n.jsx(me,{src:V(t.icon)}),n.jsxs(ge,{children:[n.jsx("b",{children:t.name})," ",n.jsx(J,{onClick:()=>e({name:t.name,type:"frontend"}),component:"button",children:"Select"})]})]},t.name))})]})]}),Pe=h("div")(({theme:e})=>({backgroundColor:e.palette.background.sidebar,padding:e.spacing(12,6,6,6),flex:0,minWidth:"400px"})),O=h("p")(({theme:e})=>({color:e.palette.primary.contrastText,fontSize:e.typography.caption.fontSize,marginBottom:e.spacing(2)})),re=({theme:e})=>({color:e.palette.primary.contrastText,fontSize:e.typography.body2.fontSize,marginTop:e.spacing(.5)}),Et=h(wn)(re),Tt=h(Ie)(re),De=h(Tn)(re),K=h("div")(({theme:e})=>({display:"flex",gap:e.spacing(1.5),alignItems:"flex-start",marginTop:e.spacing(3)})),F=h("div")(({theme:e})=>({color:e.palette.primary.contrastText,fontSize:e.typography.body2.fontSize,fontWeight:e.typography.fontWeightBold,marginBottom:e.spacing(2)})),wt=()=>n.jsxs(Pe,{children:[n.jsxs(K,{children:[n.jsx(Et,{}),n.jsxs(_,{children:[n.jsx(F,{children:"Flags live in projects"}),n.jsx(O,{children:"Projects are containers for feature flags. Each flag belongs to the project where you create it."})]})]}),n.jsxs(K,{children:[n.jsx(Tt,{}),n.jsxs(_,{children:[n.jsx(F,{children:"Flags have configuration in environments"}),n.jsx(O,{children:"You can have multiple environments, and each feature flag has a different configuration per environment."})]})]}),n.jsxs(K,{children:[n.jsx(De,{}),n.jsxs(_,{children:[n.jsx(F,{children:"SDKs connect to Unleash to retrieve configuration"}),n.jsx(O,{children:"When you connect an SDK to Unleash, it uses the API key to identify which feature flags and configuration to retrieve from each environment."})]})]})]}),Pt=()=>n.jsx(Pe,{children:n.jsxs(K,{children:[n.jsx(De,{}),n.jsxs(_,{children:[n.jsx(F,{children:"SDKs and Unleash"}),n.jsx(O,{children:"SDKs serve to bind your application to Unleash. The SDK can connect to Unleash via HTTP and retrieve feature flag configuration that is then cached in your application. Making sure none of your application data ever leaves your servers."})]})]})}),Ta=h(z,{shouldForwardProp:e=>e!=="active"})(({theme:e,active:t})=>({transition:"background-color 0.5s ease",color:e.palette.common.white,backgroundColor:t?e.palette.primary.main:e.palette.divider,"@keyframes pulse":{"0%":{boxShadow:`0 0 0 0px ${N(e.palette.primary.main,.7)}`},"100%":{boxShadow:`0 0 0 20px ${N(e.palette.primary.main,0)}`}},animation:t?"pulse 2s infinite":""})),Dt=h(z,{shouldForwardProp:e=>e!=="active"})(({theme:e,active:t})=>({transition:"background-color 0.5s ease",color:e.palette.primary.main,backgroundColor:t?e.palette.background.default:e.palette.divider,"@keyframes pulse":{"0%":{boxShadow:`0 0 0 0px ${N(e.palette.background.default,.7)}`},"100%":{boxShadow:`0 0 0 20px ${N(e.palette.background.default,0)}`}},animation:t?"pulse 2s infinite":""}));var le={},Ot=ee;Object.defineProperty(le,"__esModule",{value:!0});var Oe=le.default=void 0,Kt=Ot(Z()),Ft=n,Nt=(0,Kt.default)((0,Ft.jsx)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM7 13.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm5 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm5 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"}),"Pending");Oe=le.default=Nt;const Lt=h("div")(({theme:e})=>({backgroundColor:e.palette.background.sidebar,padding:e.spacing(6,9,6,9),minWidth:"400px",display:"flex",flexDirection:"column",color:e.palette.primary.contrastText})),$t=h(y)(({theme:e})=>({display:"flex",alignItems:"center",justifyContent:"center",fontWeight:e.typography.fontWeightBold})),Yt=h("div")(({theme:e})=>({display:"flex",flexDirection:"row",padding:e.spacing(4,0,12,0),justifyContent:"space-between",fontSize:e.spacing(1)})),fe=h("div")(({theme:e})=>({display:"flex",gap:e.spacing(1),flexDirection:"column"})),be=h("div")(({theme:e})=>({alignItems:"center",justifyContent:"center",display:"flex",gap:e.spacing(2),flexDirection:"column",fontSize:e.fontSizes.smallBody})),zt=h(Pn)(({theme:e})=>({color:e.palette.primary.main,backgroundColor:e.palette.background.paper,borderRadius:"50%",padding:e.spacing(1),width:"80px",height:"80px"})),Bt=({projectId:e,sdk:t,environment:a})=>{const s=L(),{project:o}=$(e,{refreshInterval:1e3}),r=o.onboardingStatus.status==="onboarded";return n.jsxs(Lt,{children:[n.jsx($t,{children:"Connection information"}),n.jsxs(Yt,{children:[n.jsxs(fe,{children:[n.jsx(y,{fontWeight:"bold",variant:"body2",children:"Environment"}),n.jsx(y,{variant:"body2",children:a})]}),n.jsxs(fe,{children:[n.jsx(y,{fontWeight:"bold",variant:"body2",children:"SDK"}),n.jsx(y,{variant:"body2",children:t})]})]}),r?n.jsxs(be,{children:[n.jsx(y,{fontWeight:"bold",variant:"body2",children:"Connection status"}),n.jsx(y,{sx:{mb:s.spacing(4)},variant:"body2",children:"Connected"}),n.jsx(zt,{}),n.jsx(y,{sx:{mb:s.spacing(4)},variant:"body2",children:"We received metrics from your application!"})]}):n.jsxs(be,{children:[n.jsx(y,{fontWeight:"bold",variant:"body2",children:"Connection status"}),n.jsx(y,{sx:{mb:s.spacing(4)},variant:"body2",children:"Waiting for SDK data..."}),n.jsx(Dt,{sx:{width:80,height:80},active:!0,children:n.jsx(Oe,{fontSize:"large"})})]})]})},Ht=`1\\. Install the SDK
|
|
8
|
+
|
|
9
|
+
\`\`\`gradle
|
|
10
|
+
implementation("io.getunleash:unleash-android:1")
|
|
11
|
+
\`\`\`
|
|
12
|
+
|
|
13
|
+
2\\. Enable required [permissions](https://developer.android.com/guide/topics/manifest/uses-permission-element)
|
|
14
|
+
|
|
15
|
+
\`\`\`xml
|
|
16
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
17
|
+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
2\\. Initialize Unleash in your application
|
|
21
|
+
|
|
22
|
+
\`\`\`kotlin
|
|
23
|
+
class MyApplication: Application() {
|
|
24
|
+
val unleash: Unleash by lazy {
|
|
25
|
+
val instance = DefaultUnleash(
|
|
26
|
+
androidContext = this,
|
|
27
|
+
unleashConfig = UnleashConfig.newBuilder(appName = "unleash-onboarding-android")
|
|
28
|
+
.proxyUrl("<YOUR_API_URL>")
|
|
29
|
+
.clientKey("<YOUR_API_TOKEN>")
|
|
30
|
+
.build()
|
|
31
|
+
)
|
|
32
|
+
instance.start()
|
|
33
|
+
instance
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override fun onTerminate() {
|
|
37
|
+
super.onTerminate()
|
|
38
|
+
unleash.close()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
\`\`\`
|
|
42
|
+
|
|
43
|
+
3\\. Check flag status
|
|
44
|
+
|
|
45
|
+
\`\`\`kotlin
|
|
46
|
+
class MainActivity : ComponentActivity() {
|
|
47
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
48
|
+
super.onCreate(savedInstanceState)
|
|
49
|
+
val unleashInstance = (application as MyApplication).unleash
|
|
50
|
+
|
|
51
|
+
setContent {
|
|
52
|
+
var flagStatus by remember { mutableStateOf("loading") }
|
|
53
|
+
LaunchedEffect(Unit) {
|
|
54
|
+
while (isActive) {
|
|
55
|
+
val isFlagEnabled = unleashInstance.isEnabled("<YOUR_FLAG>")
|
|
56
|
+
flagStatus = if (isFlagEnabled) "enabled" else "disabled"
|
|
57
|
+
delay(3000L)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
Text(text = "Flag is $flagStatus!")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
\`\`\`
|
|
67
|
+
ℹ️ **Info:** The Android SDK takes at least 60 seconds to post metrics to Unleash.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
---
|
|
71
|
+
- [SDK repository with documentation and example](https://github.com/Unleash/unleash-android)
|
|
72
|
+
- [Android SDK basic example](hhttps://github.com/Unleash/unleash-sdk-examples/tree/main/Android)
|
|
73
|
+
`,Gt=`1\\. Install the SDK
|
|
74
|
+
\`\`\`sh
|
|
75
|
+
go get github.com/Unleash/unleash-client-go/v4
|
|
76
|
+
\`\`\`
|
|
77
|
+
|
|
78
|
+
2\\. Run Unleash
|
|
79
|
+
\`\`\`go
|
|
80
|
+
package main
|
|
81
|
+
|
|
82
|
+
import (
|
|
83
|
+
"github.com/Unleash/unleash-client-go/v4"
|
|
84
|
+
"net/http"
|
|
85
|
+
"time"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
func init() {
|
|
89
|
+
unleash.Initialize(
|
|
90
|
+
unleash.WithListener(&unleash.DebugListener{}),
|
|
91
|
+
unleash.WithAppName("unleash-onboarding-golang"),
|
|
92
|
+
unleash.WithUrl("<YOUR_API_URL>"),
|
|
93
|
+
unleash.WithCustomHeaders(http.Header{"Authorization": {"<YOUR_API_TOKEN>"}}), // in production use environment variable
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
func main() {
|
|
98
|
+
for {
|
|
99
|
+
unleash.IsEnabled("<YOUR_FLAG>")
|
|
100
|
+
time.Sleep(time.Second)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
\`\`\`
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
\`\`\`go
|
|
107
|
+
func init() {
|
|
108
|
+
unleash.Initialize(
|
|
109
|
+
unleash.WithListener(&unleash.DebugListener{}),
|
|
110
|
+
unleash.WithAppName("unleash-onboarding-golang"),
|
|
111
|
+
unleash.WithUrl("<YOUR_API_URL>"),
|
|
112
|
+
unleash.WithCustomHeaders(http.Header{
|
|
113
|
+
"Authorization": {os.Getenv("UNLEASH_API_KEY")},
|
|
114
|
+
})
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
\`\`\`
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-go)
|
|
121
|
+
- [Go SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Go)
|
|
122
|
+
`,qt=`1\\. Install the SDK
|
|
123
|
+
\`\`\`sh
|
|
124
|
+
npm install unleash-proxy-client
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
2\\. Run Unleash
|
|
128
|
+
\`\`\`js
|
|
129
|
+
const { UnleashClient } = require('unleash-proxy-client');
|
|
130
|
+
|
|
131
|
+
const unleash = new UnleashClient({
|
|
132
|
+
url: '<YOUR_API_URL>',
|
|
133
|
+
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
|
134
|
+
appName: 'unleash-onboarding-javascript',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
unleash.start();
|
|
138
|
+
|
|
139
|
+
setInterval(() => {
|
|
140
|
+
console.log('Is enabled', unleash.isEnabled('<YOUR_FLAG>'));
|
|
141
|
+
}, 1000);
|
|
142
|
+
\`\`\`
|
|
143
|
+
---
|
|
144
|
+
\`\`\`js
|
|
145
|
+
const unleash = new UnleashClient({
|
|
146
|
+
url: '<YOUR_API_URL>',
|
|
147
|
+
clientKey: process.env.UNLEASH_API_TOKEN,
|
|
148
|
+
appName: 'unleash-onboarding-javascript',
|
|
149
|
+
});
|
|
150
|
+
unleash.start();
|
|
151
|
+
\`\`\`
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-proxy-client-js)
|
|
155
|
+
- [JavaScript SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/JavaScript)
|
|
156
|
+
`,Wt=`1\\. Install the SDK
|
|
157
|
+
\`\`\`sh
|
|
158
|
+
npm install unleash-client
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
2\\. Run Unleash
|
|
162
|
+
\`\`\`js
|
|
163
|
+
const { initialize } = require('unleash-client');
|
|
164
|
+
|
|
165
|
+
const unleash = initialize({
|
|
166
|
+
url: '<YOUR_API_URL>',
|
|
167
|
+
appName: 'unleash-onboarding-node',
|
|
168
|
+
customHeaders: {
|
|
169
|
+
Authorization: '<YOUR_API_TOKEN>' // in production use environment variable
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
setInterval(() => {
|
|
174
|
+
console.log('Is enabled', unleash.isEnabled('<YOUR_FLAG>'));
|
|
175
|
+
}, 1000);
|
|
176
|
+
\`\`\`
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
\`\`\`js
|
|
180
|
+
const { initialize } = require('unleash-client');
|
|
181
|
+
|
|
182
|
+
const unleash = initialize({
|
|
183
|
+
url: '<YOUR_API_URL>',
|
|
184
|
+
appName: 'unleash-onboarding-node',
|
|
185
|
+
customHeaders: { Authorization: process.env.UNLEASH_API_KEY },
|
|
186
|
+
});
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-node)
|
|
191
|
+
- [Node.js SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Node.js)
|
|
192
|
+
- [Node.js SDK tutorial](https://dev.to/reeshee/how-to-implement-feature-flags-in-nodejs-using-unleash-3907)
|
|
193
|
+
`,Mt=`1\\. Install the SDK
|
|
194
|
+
\`\`\`sh
|
|
195
|
+
pip install UnleashClient
|
|
196
|
+
\`\`\`
|
|
197
|
+
|
|
198
|
+
2\\. Run Unleash
|
|
199
|
+
\`\`\`python
|
|
200
|
+
from UnleashClient import UnleashClient
|
|
201
|
+
import asyncio
|
|
202
|
+
|
|
203
|
+
client = UnleashClient(
|
|
204
|
+
url="<YOUR_API_URL>",
|
|
205
|
+
app_name="unleash-onboarding-python",
|
|
206
|
+
custom_headers={'Authorization': '<YOUR_API_TOKEN>'}) # in production use environment variable
|
|
207
|
+
|
|
208
|
+
client.initialize_client()
|
|
209
|
+
|
|
210
|
+
while True:
|
|
211
|
+
print(client.is_enabled("<YOUR_FLAG>"))
|
|
212
|
+
asyncio.run(asyncio.sleep(1))
|
|
213
|
+
\`\`\`
|
|
214
|
+
---
|
|
215
|
+
\`\`\`python
|
|
216
|
+
from UnleashClient import UnleashClient
|
|
217
|
+
import asyncio
|
|
218
|
+
import os
|
|
219
|
+
|
|
220
|
+
client = UnleashClient(
|
|
221
|
+
url="<YOUR_API_URL>",
|
|
222
|
+
app_name="unleash-onboarding-python",
|
|
223
|
+
custom_headers={'Authorization': os.getenv('UNLEASH_API_TOKEN')}
|
|
224
|
+
\`\`\`
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-python)
|
|
228
|
+
- [Python SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Python)
|
|
229
|
+
- [How to Implement Feature Flags in Python](https://docs.getunleash.io/feature-flag-tutorials/python)
|
|
230
|
+
`,Vt=`1\\. Install the SDK
|
|
231
|
+
\`\`\`sh
|
|
232
|
+
gem install unleash
|
|
233
|
+
\`\`\`
|
|
234
|
+
|
|
235
|
+
2\\. Run Unleash
|
|
236
|
+
\`\`\`rb
|
|
237
|
+
require 'unleash'
|
|
238
|
+
|
|
239
|
+
@unleash = Unleash::Client.new(
|
|
240
|
+
url: "<YOUR_API_URL>",
|
|
241
|
+
custom_http_headers: { 'Authorization': "<YOUR_API_TOKEN>" }, # in production use environment variable
|
|
242
|
+
app_name: 'unleash-onboarding-ruby',
|
|
243
|
+
instance_id: 'unleash-onboarding-ruby',
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
while true
|
|
247
|
+
if @unleash.is_enabled?("<YOUR_FLAG>")
|
|
248
|
+
puts "Flag is enabled"
|
|
249
|
+
else
|
|
250
|
+
puts "Flag is not enabled"
|
|
251
|
+
end
|
|
252
|
+
sleep 3
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
\`\`\`
|
|
256
|
+
---
|
|
257
|
+
\`\`\`rb
|
|
258
|
+
@unleash = Unleash::Client.new(
|
|
259
|
+
url: "<YOUR_API_URL>",
|
|
260
|
+
custom_http_headers: { 'Authorization': ENV['UNLEASH_API_TOKEN'] },
|
|
261
|
+
app_name: 'unleash-onboarding-ruby',
|
|
262
|
+
instance_id: 'unleash-onboarding-ruby',
|
|
263
|
+
)
|
|
264
|
+
\`\`\`
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-ruby)
|
|
268
|
+
- [Ruby example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Ruby)
|
|
269
|
+
- [How to Implement Feature Flags in Ruby](https://docs.getunleash.io/feature-flag-tutorials/ruby)
|
|
270
|
+
`,Jt=`1\\. Install the SDK
|
|
271
|
+
\`\`\`sh
|
|
272
|
+
npm install @unleash/proxy-client-svelte
|
|
273
|
+
\`\`\`
|
|
274
|
+
|
|
275
|
+
2\\. Initialize Unleash
|
|
276
|
+
\`\`\`svelte
|
|
277
|
+
<script>
|
|
278
|
+
import { FlagProvider } from '@unleash/proxy-client-svelte';
|
|
279
|
+
|
|
280
|
+
const config = {
|
|
281
|
+
url: '<YOUR_API_URL>',
|
|
282
|
+
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
|
283
|
+
appName: 'unleash-onboarding-svelte',
|
|
284
|
+
};
|
|
285
|
+
<\/script>
|
|
286
|
+
|
|
287
|
+
<div class="app">
|
|
288
|
+
<FlagProvider {config}>
|
|
289
|
+
<main>
|
|
290
|
+
<slot />
|
|
291
|
+
</main>
|
|
292
|
+
</FlagProvider>
|
|
293
|
+
</div>
|
|
294
|
+
\`\`\`
|
|
295
|
+
|
|
296
|
+
3\\. Check feature flag status
|
|
297
|
+
\`\`\`svelte
|
|
298
|
+
<script lang="ts">
|
|
299
|
+
import { useFlag } from '@unleash/proxy-client-svelte';
|
|
300
|
+
const enabled = useFlag('<YOUR_FLAG>');
|
|
301
|
+
<\/script>
|
|
302
|
+
|
|
303
|
+
<section>
|
|
304
|
+
<p>
|
|
305
|
+
{$enabled ? 'Feature is enabled!' : 'Feature is disabled!'}
|
|
306
|
+
</p>
|
|
307
|
+
</section>
|
|
308
|
+
\`\`\`
|
|
309
|
+
---
|
|
310
|
+
\`\`\`svelte
|
|
311
|
+
const config = {
|
|
312
|
+
url: '<YOUR_API_URL>',
|
|
313
|
+
clientKey: import.meta.env.VITE_UNLEASH_API_TOKEN,
|
|
314
|
+
appName: 'unleash-onboarding-svelte',
|
|
315
|
+
};
|
|
316
|
+
\`\`\`
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
- [SDK repository with documentation](https://github.com/Unleash/proxy-client-svelte)
|
|
320
|
+
- [Svelte example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Svelte)
|
|
321
|
+
- [How to Implement Feature Flags in SvelteKit](https://docs.getunleash.io/feature-flag-tutorials/sveltekit)
|
|
322
|
+
`,Qt=`1\\. Install the SDK
|
|
323
|
+
\`\`\`sh
|
|
324
|
+
npm install @unleash/proxy-client-vue
|
|
325
|
+
\`\`\`
|
|
326
|
+
|
|
327
|
+
2\\. Initialize Unleash
|
|
328
|
+
\`\`\`vue
|
|
329
|
+
<script setup lang="ts">
|
|
330
|
+
import { FlagProvider } from '@unleash/proxy-client-vue'
|
|
331
|
+
|
|
332
|
+
const config = {
|
|
333
|
+
url: '<YOUR_API_URL>',
|
|
334
|
+
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
|
335
|
+
appName: 'unleash-onboarding-vue',
|
|
336
|
+
}
|
|
337
|
+
<\/script>
|
|
338
|
+
|
|
339
|
+
<template>
|
|
340
|
+
<FlagProvider :config="config">
|
|
341
|
+
<!-- <YourComponent /> -->
|
|
342
|
+
</FlagProvider>
|
|
343
|
+
</template>
|
|
344
|
+
\`\`\`
|
|
345
|
+
|
|
346
|
+
3\\. Check feature flag status
|
|
347
|
+
\`\`\`vue
|
|
348
|
+
<script setup lang="ts">
|
|
349
|
+
import { useFlag } from '@unleash/proxy-client-vue'
|
|
350
|
+
const enabled = useFlag('<YOUR_FLAG>')
|
|
351
|
+
<\/script>
|
|
352
|
+
|
|
353
|
+
<template>
|
|
354
|
+
<div>
|
|
355
|
+
{{ enabled ? 'Feature is enabled!' : 'Feature is disabled!' }}
|
|
356
|
+
</div>
|
|
357
|
+
</template>
|
|
358
|
+
\`\`\`
|
|
359
|
+
---
|
|
360
|
+
\`\`\`svelte
|
|
361
|
+
const config = {
|
|
362
|
+
url: '<YOUR_API_URL>',
|
|
363
|
+
clientKey: import.meta.env.VITE_UNLEASH_API_TOKEN,
|
|
364
|
+
appName: 'unleash-onboarding-vue',
|
|
365
|
+
}
|
|
366
|
+
\`\`\`
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
- [SDK repository with documentation](https://github.com/Unleash/proxy-client-vue)
|
|
370
|
+
- [Vue example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Vue)
|
|
371
|
+
`,Xt=`1\\. Install the SDK
|
|
372
|
+
\`\`\`sh
|
|
373
|
+
flutter pub add unleash_proxy_client_flutter
|
|
374
|
+
\`\`\`
|
|
375
|
+
|
|
376
|
+
2\\. Run Unleash
|
|
377
|
+
\`\`\`dart
|
|
378
|
+
import 'package:unleash_proxy_client_flutter/unleash_proxy_client_flutter.dart';
|
|
379
|
+
import 'dart:async';
|
|
380
|
+
|
|
381
|
+
final unleash = UnleashClient(
|
|
382
|
+
url: Uri.parse('<YOUR_API_URL>'),
|
|
383
|
+
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
|
384
|
+
appName: 'unleash-onboarding-flutter');
|
|
385
|
+
|
|
386
|
+
unleash.start();
|
|
387
|
+
|
|
388
|
+
Timer.periodic(Duration(seconds: 1), (Timer timer) {
|
|
389
|
+
final flagStatus = unleash.isEnabled('<YOUR_FLAG>');
|
|
390
|
+
print('Flag is \${unleash.isEnabled("<YOUR_FLAG>") ? "enabled" : "disabled"}');
|
|
391
|
+
});
|
|
392
|
+
\`\`\`
|
|
393
|
+
---
|
|
394
|
+
\`\`\`dart
|
|
395
|
+
import 'package:unleash_proxy_client_flutter/unleash_proxy_client_flutter.dart';
|
|
396
|
+
import 'dart:async';
|
|
397
|
+
import 'dart:io';
|
|
398
|
+
|
|
399
|
+
final unleash = UnleashClient(
|
|
400
|
+
url: Uri.parse('<YOUR_API_URL>'),
|
|
401
|
+
clientKey: Platform.environment['UNLEASH_CLIENT_KEY']!,
|
|
402
|
+
appName: 'unleash-onboarding-flutter');
|
|
403
|
+
|
|
404
|
+
unleash.start();
|
|
405
|
+
\`\`\`
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash_proxy_client_flutter)
|
|
409
|
+
- [Flutter example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Flutter)
|
|
410
|
+
- [A/B Testing in Flutter using Unleash and Mixpanel](https://docs.getunleash.io/feature-flag-tutorials/flutter/a-b-testing)
|
|
411
|
+
`,Zt=`1\\. Install the SDK
|
|
412
|
+
\`\`\`xml
|
|
413
|
+
<dependency>
|
|
414
|
+
<groupId>io.getunleash</groupId>
|
|
415
|
+
<artifactId>unleash-client-java</artifactId>
|
|
416
|
+
<version>LATEST</version>
|
|
417
|
+
</dependency>
|
|
418
|
+
\`\`\`
|
|
419
|
+
|
|
420
|
+
2\\. Run Unleash
|
|
421
|
+
\`\`\`java
|
|
422
|
+
UnleashConfig config = UnleashConfig.builder()
|
|
423
|
+
.appName("unleash-onboarding-java")
|
|
424
|
+
.instanceId("unleash-onboarding-instance")
|
|
425
|
+
.unleashAPI("<YOUR_API_URL>")
|
|
426
|
+
.apiKey("<YOUR_API_TOKEN>") // in production use environment variable
|
|
427
|
+
.build();
|
|
428
|
+
|
|
429
|
+
Unleash unleash = new DefaultUnleash(config);
|
|
430
|
+
|
|
431
|
+
while (true) {
|
|
432
|
+
boolean featureEnabled = unleash.isEnabled("<YOUR_FLAG>");
|
|
433
|
+
System.out.println("Feature enabled: " + featureEnabled);
|
|
434
|
+
Thread.sleep(1000);
|
|
435
|
+
}
|
|
436
|
+
\`\`\`
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
\`\`\`java
|
|
440
|
+
UnleashConfig config = UnleashConfig.builder()
|
|
441
|
+
.appName("unleash-onboarding-java")
|
|
442
|
+
.instanceId("unleash-onboarding-instance")
|
|
443
|
+
.unleashAPI("<YOUR_API_URL>")
|
|
444
|
+
.apiKey(System.getenv("UNLEASH_API_KEY"))
|
|
445
|
+
.build();
|
|
446
|
+
\`\`\`
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-java)
|
|
450
|
+
- [Java SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Java)
|
|
451
|
+
- [How to Implement Feature Flags in Java](https://docs.getunleash.io/feature-flag-tutorials/java)
|
|
452
|
+
`,ea=`1\\. Install the SDK
|
|
453
|
+
\`\`\`sh
|
|
454
|
+
dotnet add package unleash.client
|
|
455
|
+
// If you do not have a json library in your project:
|
|
456
|
+
dotnet add package Newtonsoft.Json
|
|
457
|
+
\`\`\`
|
|
458
|
+
|
|
459
|
+
2\\. Initialize Unleash
|
|
460
|
+
\`\`\`csharp
|
|
461
|
+
using Unleash;
|
|
462
|
+
using Unleash.ClientFactory;
|
|
463
|
+
|
|
464
|
+
public class Program
|
|
465
|
+
{
|
|
466
|
+
public static async Task Main()
|
|
467
|
+
{
|
|
468
|
+
var settings = new UnleashSettings()
|
|
469
|
+
{
|
|
470
|
+
AppName = "unleash-onboarding-dotnet",
|
|
471
|
+
UnleashApi = new Uri("<YOUR_API_URL>"),
|
|
472
|
+
CustomHttpHeaders = new Dictionary<string, string>()
|
|
473
|
+
{
|
|
474
|
+
{"Authorization","<YOUR_API_TOKEN>"} // in production use environment variable
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
var unleash = new DefaultUnleash(settings);
|
|
479
|
+
|
|
480
|
+
while (true) {
|
|
481
|
+
Console.WriteLine($"Flag is enabled: {unleash.IsEnabled("<YOUR_FLAG>")}");
|
|
482
|
+
await Task.Delay(1000);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
\`\`\`
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
\`\`\`csharp
|
|
491
|
+
var settings = new UnleashSettings()
|
|
492
|
+
{
|
|
493
|
+
AppName = "unleash-onboarding-dotnet",
|
|
494
|
+
UnleashApi = new Uri("<YOUR_API_URL>"),
|
|
495
|
+
CustomHttpHeaders = new Dictionary<string, string>()
|
|
496
|
+
{
|
|
497
|
+
{"Authorization",Environment.GetEnvironmentVariable("UNLEASH_API_KEY")}
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
\`\`\`
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-dotnet)
|
|
504
|
+
- [.NET/C# SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Csharp)
|
|
505
|
+
`,na=`1\\. Install the SDK
|
|
506
|
+
\`\`\`sh
|
|
507
|
+
composer require unleash/client
|
|
508
|
+
\`\`\`
|
|
509
|
+
|
|
510
|
+
2\\. Initialize Unleash
|
|
511
|
+
\`\`\`php
|
|
512
|
+
<?php
|
|
513
|
+
|
|
514
|
+
use Unleash\\\\Client\\\\UnleashBuilder;
|
|
515
|
+
|
|
516
|
+
require 'vendor/autoload.php';
|
|
517
|
+
|
|
518
|
+
$unleash = UnleashBuilder::create()
|
|
519
|
+
->withAppName('unleash-onboarding-php')
|
|
520
|
+
->withAppUrl('<YOUR_API_URL>')
|
|
521
|
+
->withHeader('Authorization', '<YOUR_API_TOKEN>') // in production use environment variable
|
|
522
|
+
->withInstanceId('unleash-onboarding-instance')
|
|
523
|
+
->build();
|
|
524
|
+
|
|
525
|
+
while (true) {
|
|
526
|
+
echo 'Feature flag is: ' . $unleash->isEnabled('<YOUR_FLAG>') . PHP_EOL;
|
|
527
|
+
sleep(1);
|
|
528
|
+
}
|
|
529
|
+
\`\`\`
|
|
530
|
+
---
|
|
531
|
+
\`\`\`php
|
|
532
|
+
$unleash = UnleashBuilder::create()
|
|
533
|
+
->withAppName('unleash-onboarding-php')
|
|
534
|
+
->withAppUrl('<YOUR_API_URL>')
|
|
535
|
+
->withHeader('Authorization', getenv('UNLEASH_API_TOKEN'))
|
|
536
|
+
->withInstanceId('unleash-onboarding-instance')
|
|
537
|
+
->build();
|
|
538
|
+
\`\`\`
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-php)
|
|
542
|
+
- [PHP SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/PHP)
|
|
543
|
+
`,ta=`1\\. Install the SDK
|
|
544
|
+
\`\`\`sh
|
|
545
|
+
npm install @unleash/proxy-client-react unleash-proxy-client
|
|
546
|
+
\`\`\`
|
|
547
|
+
|
|
548
|
+
2\\. Initialize Unleash
|
|
549
|
+
\`\`\`jsx
|
|
550
|
+
import { createRoot } from 'react-dom/client';
|
|
551
|
+
import { FlagProvider } from '@unleash/proxy-client-react';
|
|
552
|
+
|
|
553
|
+
const config = {
|
|
554
|
+
url: '<YOUR_API_URL>',
|
|
555
|
+
clientKey: '<YOUR_API_TOKEN>', // in production use environment variable
|
|
556
|
+
appName: 'unleash-onboarding-react',
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
const root = createRoot(document.getElementById('root'));
|
|
560
|
+
|
|
561
|
+
root.render(
|
|
562
|
+
<React.StrictMode>
|
|
563
|
+
<FlagProvider config={config}>
|
|
564
|
+
<App />
|
|
565
|
+
</FlagProvider>
|
|
566
|
+
</React.StrictMode>
|
|
567
|
+
);
|
|
568
|
+
\`\`\`
|
|
569
|
+
|
|
570
|
+
3\\. Check feature flag status
|
|
571
|
+
\`\`\`jsx
|
|
572
|
+
import { useFlag } from '@unleash/proxy-client-react';
|
|
573
|
+
|
|
574
|
+
const TestComponent = () => {
|
|
575
|
+
const enabled = useFlag('<YOUR_FLAG>');
|
|
576
|
+
|
|
577
|
+
return enabled ? 'Flag is enabled' : 'Flag is disabled'
|
|
578
|
+
};
|
|
579
|
+
\`\`\`
|
|
580
|
+
---
|
|
581
|
+
\`\`\`jsx
|
|
582
|
+
const config = {
|
|
583
|
+
url: '<YOUR_API_URL>',
|
|
584
|
+
clientKey: process.env.UNLEASH_API_TOKEN,
|
|
585
|
+
appName: 'unleash-onboarding-react',
|
|
586
|
+
};
|
|
587
|
+
\`\`\`
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
- [SDK repository with documentation](https://github.com/Unleash/proxy-client-react)
|
|
591
|
+
- [React SDK example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/React)
|
|
592
|
+
- [https://docs.getunleash.io/feature-flag-tutorials/react](https://docs.getunleash.io/feature-flag-tutorials/react)
|
|
593
|
+
|
|
594
|
+
`,aa=`1\\. Install the SDK
|
|
595
|
+
\`\`\`sh
|
|
596
|
+
cargo add unleash-api-client --features async-std,reqwest,surf
|
|
597
|
+
cargo add serde --features derive
|
|
598
|
+
cargo add serde reqwest --features json
|
|
599
|
+
cargo add serde tokio --features full
|
|
600
|
+
cargo add serde anyhow cfg cfg-if enum-map@~2.0.0 surf
|
|
601
|
+
\`\`\`
|
|
602
|
+
|
|
603
|
+
2\\. Run Unleash
|
|
604
|
+
\`\`\`rust
|
|
605
|
+
use enum_map::Enum;
|
|
606
|
+
use serde::{Deserialize, Serialize};
|
|
607
|
+
use std::error::Error;
|
|
608
|
+
use std::time::Duration;
|
|
609
|
+
use tokio::time::sleep;
|
|
610
|
+
use unleash_api_client::client::ClientBuilder;
|
|
611
|
+
use unleash_api_client::Client;
|
|
612
|
+
|
|
613
|
+
#[derive(Debug, Deserialize, Serialize, Enum, Clone)]
|
|
614
|
+
enum Flags {
|
|
615
|
+
#[serde(rename = "<YOUR_FLAG>")]
|
|
616
|
+
TestFlag,
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
#[tokio::main]
|
|
620
|
+
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|
621
|
+
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
|
|
622
|
+
.into_client(
|
|
623
|
+
"<YOUR_API_URL>",
|
|
624
|
+
"unleash-onboarding-rust",
|
|
625
|
+
"unleash-onboarding-instance",
|
|
626
|
+
Some("<YOUR_API_TOKEN>".to_owned()), // in production use environment variable
|
|
627
|
+
)?;
|
|
628
|
+
client.register().await?;
|
|
629
|
+
|
|
630
|
+
let (_, _) = tokio::join!(client.poll_for_updates(), async {
|
|
631
|
+
sleep(Duration::from_millis(1000)).await;
|
|
632
|
+
|
|
633
|
+
let is_enabled = client.is_enabled(Flags::TestFlag, None, true);
|
|
634
|
+
println!("\\nIs flag enabled: {}\\n", is_enabled);
|
|
635
|
+
|
|
636
|
+
sleep(Duration::from_millis(5000)).await;
|
|
637
|
+
|
|
638
|
+
client.stop_poll().await;
|
|
639
|
+
Ok::<(), Box<dyn Error + Send + Sync>>(())
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
Ok(())
|
|
643
|
+
}
|
|
644
|
+
\`\`\`
|
|
645
|
+
---
|
|
646
|
+
\`\`\`rust
|
|
647
|
+
let api_token = env::var("UNLEASH_API_TOKEN").expect("UNLEASH_API_TOKEN environment variable not set");
|
|
648
|
+
|
|
649
|
+
let client: Client<Flags, reqwest::Client> = ClientBuilder::default()
|
|
650
|
+
.into_client(
|
|
651
|
+
"<YOUR_API_URL>",
|
|
652
|
+
"unleash-onboarding-rust",
|
|
653
|
+
"unleash-onboarding-instance",
|
|
654
|
+
Some(api_token.to_owned()),
|
|
655
|
+
)?;
|
|
656
|
+
client.register().await?;
|
|
657
|
+
\`\`\`
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
- [SDK repository with documentation](https://github.com/Unleash/unleash-client-rust)
|
|
661
|
+
- [Rust example with CodeSandbox](https://github.com/Unleash/unleash-sdk-examples/tree/main/Rust)
|
|
662
|
+
- [How to Implement Feature Flags in Rust](https://docs.getunleash.io/feature-flag-tutorials/rust)
|
|
663
|
+
`,sa=`1\\. Install the SDK
|
|
664
|
+
\`\`\`sh
|
|
665
|
+
// Instructions to add the Swift SDK can be found at the provided URL:
|
|
666
|
+
https://github.com/Unleash/unleash-proxy-client-swift.git
|
|
667
|
+
\`\`\`
|
|
668
|
+
|
|
669
|
+
2\\. Run Unleash
|
|
670
|
+
\`\`\`swift
|
|
671
|
+
import Foundation
|
|
672
|
+
import UnleashProxyClientSwift
|
|
673
|
+
|
|
674
|
+
var unleash = UnleashProxyClientSwift.UnleashClient(
|
|
675
|
+
unleashUrl: "<YOUR_API_URL>",
|
|
676
|
+
clientKey: "<YOUR_API_TOKEN>", // in production use environment variable
|
|
677
|
+
appName: "unleash-onboarding-swift",
|
|
678
|
+
context: [:])
|
|
679
|
+
|
|
680
|
+
unleash.start()
|
|
681
|
+
|
|
682
|
+
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
|
|
683
|
+
print("Is enabled", unleash.isEnabled(name: "<YOUR_FLAG>"))
|
|
684
|
+
}
|
|
685
|
+
\`\`\`
|
|
686
|
+
ℹ️ **Info:** The Swift SDK takes at least 60 seconds to post metrics to Unleash.
|
|
687
|
+
`,Ke={Android:Ht,Go:Gt,JavaScript:qt,"Node.js":Wt,Python:Mt,Ruby:Vt,Svelte:Jt,Vue:Qt,Flutter:Xt,Java:Zt,".NET":ea,PHP:na,React:ta,Rust:aa,Swift:sa},oa=h("pre")(({theme:e})=>({backgroundColor:e.palette.background.elevation1,padding:e.spacing(2),borderRadius:e.shape.borderRadius,overflow:"auto",fontSize:e.typography.body2.fontSize,wordBreak:"break-all",whiteSpace:"pre-wrap",position:"relative",maxHeight:e.spacing(34)})),ia=h(Kn)(({theme:e})=>({position:"absolute",top:e.spacing(1),right:e.spacing(1)})),ra=({title:e,code:t})=>{const a=o=>()=>{Fn(o),s({type:"success",text:"Copied to clipboard"})},{setToastData:s}=P();return n.jsxs(oa,{children:[t,n.jsx(ia,{title:e,arrow:!0,children:n.jsx(Dn,{onClick:a(t),size:"small",children:n.jsx(On,{})})})]})},X=({inline:e=!1,children:t})=>!e&&typeof(t==null?void 0:t[0])=="string"?n.jsx(ra,{code:t[0],title:"Copy code"}):n.jsx("code",{children:t}),la=h("div")(({theme:e})=>({padding:e.spacing(5,8,2,8),display:"flex",flexDirection:"column",gap:e.spacing(3)})),ca=h("div")(({theme:e})=>({display:"inline-flex",gap:e.spacing(3),padding:e.spacing(1,2),border:`1px solid ${e.palette.divider}`,borderRadius:e.shape.borderRadius,marginBottom:e.spacing(3)})),da=({sdk:e,apiKey:t,feature:a,onSdkChange:s})=>{var c;const{uiConfig:o}=se(),r=(c=kt.find(f=>f.name===e.name))==null?void 0:c.icon,l=`${o.unleashUrl}/api/`,i=`${o.unleashUrl}/api/frontend/`,d=e.type==="client"?l:i,m=(Ke[e.name]||"").replace("<YOUR_API_TOKEN>",t).replace("<YOUR_API_URL>",d).replaceAll("<YOUR_FLAG>",a),[b,u,g]=m.split(`---
|
|
688
|
+
`);return n.jsxs(la,{children:[n.jsx(y,{variant:"h2",children:"Connect an SDK to Unleash"}),n.jsxs(B,{children:[n.jsx(H,{active:2,steps:3}),n.jsx(Y,{color:"secondary",children:"3/3 - Test connection"})]}),n.jsxs(_,{sx:{mt:2},children:[n.jsxs(ca,{children:[r?n.jsx(z,{variant:"circular",src:V(r),alt:e.name}):null,n.jsx(J,{onClick:s,component:"button",children:"Change SDK"})]}),n.jsx(w,{children:"Setup the SDK"}),n.jsx(Q,{components:{code:X},children:b})]})]})},ua=h("div")(({theme:e})=>({padding:e.spacing(5,8,2,8),display:"flex",flexDirection:"column",gap:e.spacing(3),fontSize:e.typography.body2.fontSize})),pa=({sdk:e})=>{const{uiConfig:t}=se(),a=`${t.unleashUrl}/api/`,s=`${t.unleashUrl}/api/frontend/`,o=e.type==="client"?a:s,r=(Ke[e.name]||"").replaceAll("<YOUR_API_URL>",o),[l,i,d]=r.split(`---
|
|
689
|
+
`);return n.jsxs(ua,{children:[n.jsx(y,{variant:"h2",children:"Connect an SDK to Unleash"}),n.jsxs(B,{children:[n.jsx(H,{active:2,steps:3}),n.jsx(Y,{color:"secondary",children:"3/3 - Test connection"})]}),i!=null&&i.trim()?n.jsxs(_,{sx:{mt:2},children:[n.jsx(w,{children:"Production settings"}),n.jsx(y,{variant:"body2",children:"You have successfully connected your SDK. In the previous code example, the settings were optimized for development. We recommend the following setup for production."}),n.jsx(Q,{components:{code:X},children:i})]}):null,d!=null&&d.trim()?n.jsxs(_,{children:[n.jsx(w,{children:"Additional resources"}),n.jsx(y,{variant:"body2",children:"Now that we’ve validated the connection, you might want to look into more advanced use cases and examples:"}),n.jsx(Q,{components:{code:X},children:d})]}):null]})},ha=({sdk:e,apiKey:t,feature:a,onSdkChange:s})=>n.jsx(x.Suspense,{fallback:n.jsx(Nn,{}),children:a?n.jsx(da,{sdk:e,apiKey:t,feature:a,onSdkChange:s}):n.jsx(pa,{sdk:e})}),ga=h("main")(({theme:e})=>({backgroundColor:e.palette.background.paper,display:"flex",flexDirection:"column",flex:1})),ma=h(Ln)(({theme:e})=>({"& .MuiDialog-paper":{borderRadius:e.shape.borderRadiusLarge,maxWidth:e.spacing(170),width:"100%",backgroundColor:"transparent"},padding:0,"& .MuiPaper-root > section":{overflowX:"hidden"}})),xe=h("div")(({theme:e})=>({borderTop:`1px solid ${e.palette.divider}}`,display:"flex",justifyContent:"flex-end",gap:e.spacing(4),alignItems:"center",padding:e.spacing(3,8,3,8)})),ye=h("div")(({theme:e})=>({display:"flex",justifyContent:"flex-end",gap:e.spacing(4),alignItems:"center",padding:e.spacing(3,8,3,8)})),fa=({onClose:e,onFinish:t,environments:a,project:s,feature:o})=>{const r=L(),l=Re(r.breakpoints.up("lg")),[i,d]=x.useState(null),[m,b]=x.useState(null),[u,g]=x.useState(null),[c,f]=x.useState("select-sdk"),{project:j}=$(s,{refreshInterval:1e3}),v=c==="select-sdk",R=c==="generate-api-key"&&i&&m,k=c==="test-connection"&&i&&m&&u,C=j.onboardingStatus.status==="onboarded";return x.useEffect(()=>{a.length>0&&b(a[0])},[JSON.stringify(a)]),n.jsx(ma,{open:!0,onClose:e,children:n.jsxs(_,{sx:{display:"flex"},children:[n.jsxs(ga,{children:[v?n.jsx(Rt,{onSelect:p=>{d(p),f("generate-api-key")}}):null,R?n.jsx(At,{environments:a,environment:m,project:s,sdkType:i.type,onEnvSelect:b,onApiKey:g}):null,k?n.jsx(ha,{apiKey:u,sdk:i,feature:o,onSdkChange:()=>{f("select-sdk")}}):null,c==="generate-api-key"?n.jsx(xe,{children:n.jsxs(ye,{children:[n.jsx(E,{variant:"text",color:"inherit",onClick:()=>{f("select-sdk")},children:"Back"}),n.jsx(E,{variant:"contained",disabled:!u,onClick:()=>{f("test-connection")},children:"Next"})]})}):null,k?n.jsx(xe,{children:n.jsxs(ye,{children:[C?null:n.jsx(E,{variant:"text",color:"inherit",onClick:()=>{f("generate-api-key")},children:"Back"}),n.jsx(E,{variant:"contained",onClick:()=>{t(i.name)},children:"Complete"})]})}):null]}),l&&v?n.jsx(Pt,{}):null,l&&R?n.jsx(wt,{}):null,l&&k?n.jsx(Bt,{projectId:s,sdk:i.name,environment:m}):null]})})},wa=({open:e,...t})=>e?n.jsx(fa,{...t}):null,Pa=({isStale:e,isOpen:t,projectId:a,featureId:s,onClose:o})=>{const{setToastData:r,setToastApiError:l}=P(),{patchFeatureToggle:i}=ke(),d=n.jsx(y,{children:"Setting a flag to stale marks it for cleanup"}),m=n.jsx(y,{children:"Setting a flag to active marks it as in active use"}),b=e?"active":"stale",u=async g=>{g.stopPropagation();try{await i(a,s,[{op:"replace",path:"/stale",value:!e}]),o()}catch(c){l(T(c))}r(e?{type:"success",text:"The flag is no longer marked as stale"}:{type:"success",text:"The flag has been marked as stale"})};return n.jsx(Ae,{open:t,secondaryButtonText:"Cancel",primaryButtonText:`Flip to ${b}`,title:`Set feature state to ${b}`,onClick:u,onClose:o,children:n.jsx(ne,{condition:e,show:m,elseShow:d})})};export{wa as C,Aa as E,Ra as F,Ta as P,_a as T,Ca as a,ja as b,qn as c,ka as d,Ia as e,Ea as f,rt as g,Pa as h,kt as i,Oe as j,ft as k,gt as l,Ua as u};
|