funifier-mcp 0.3.20 → 0.3.21
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/.cursor/rules/funifier.mdc +1 -0
- package/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +11 -0
- package/datasource-funifier-docs/.coverage.json +13 -5
- package/datasource-funifier-docs/knowledge/guides/server-utils.md +718 -0
- package/datasource-funifier-docs/knowledge/index.md +1 -0
- package/dist/mcp/bundle.js +1 -1
- package/package.json +1 -1
- package/skills/funifier/SKILL.md +1 -0
- package/skills/funifier/references/help.md +0 -6
- package/skills/funifier/references/server-utils.md +94 -0
- package/datasource-funifier-docs/.search-index.json +0 -59689
- package/datasource-funifier-docs/.skills-map.json +0 -150
|
@@ -106,6 +106,7 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
|
|
|
106
106
|
| Java Managers | `guides/java-managers.md` | Referência de managers Java | Métodos disponíveis em cada manager (PlayerManager, ActionManager, etc.) para uso em triggers, schedulers e public endpoints |
|
|
107
107
|
| Java Entities | `guides/java-entities.md` | Referência de entidades Java | Campos e tipos dos objetos (Player, Achievement, ActionLog, etc.) e mapeamento para coleções MongoDB |
|
|
108
108
|
| Java Libraries | `guides/java-libraries.md` | Bibliotecas e utilitários Java | JsonUtil, Guid, DateUtil, Unirest, EmailBuilder, Jongo — métodos e exemplos de uso |
|
|
109
|
+
| Server-side Utils | `guides/server-utils.md` | Classes utilitárias do pacote `com.funifier.engine.util` | CpfUtil, AesCrypt, BCrypt, PgpCrypt, OtpAuthUtil, DiffUtil, ExpressionUtils, MustacheUtils, StringUtil, FormatterUtil, ParserUtil, HttpUtil, UrlUtil, ExcelUtil, PaginationUtil, FileUtil — use quando precisar validar CPF, criptografar campo, renderizar template, comparar objetos, gerar Excel ou fazer HTTP em código server-side |
|
|
109
110
|
| Permission Audit | `guides/permission-audit.md` | Auditoria de permissões de API | Cross-check código↔Funifier: manifest de chamadas → missing scopes, excess tokens, danger findings; gramática de scope (SecurityFilter), keyword `database`, auth context, remediação |
|
|
110
111
|
|
|
111
112
|
---
|
package/dist/mcp/bundle.js
CHANGED
|
@@ -62,7 +62,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
62
62
|
`),s=o===-1?-1:a.indexOf(`
|
|
63
63
|
`,o+1),c=s===-1?"":a.slice(s+1);String(i.stack).endsWith(c)||(i.stack+=`
|
|
64
64
|
`+a)}}catch{}}throw i}}_request(t,r){typeof t=="string"?(r=r||{},r.url=t):r=t||{},r=Eo(this.defaults,r);let{transitional:i,paramsSerializer:n,headers:a}=r;i!==void 0&&Vp.assertOptions(i,{silentJSONParsing:or.transitional(or.boolean),forcedJSONParsing:or.transitional(or.boolean),clarifyTimeoutError:or.transitional(or.boolean),legacyInterceptorReqResOrdering:or.transitional(or.boolean),advertiseZstdAcceptEncoding:or.transitional(or.boolean),validateStatusUndefinedResolves:or.transitional(or.boolean)},!1),n!=null&&(D.isFunction(n)?r.paramsSerializer={serialize:n}:Vp.assertOptions(n,{encode:or.function,serialize:or.function},!0)),r.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?r.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:r.allowAbsoluteUrls=!0),Vp.assertOptions(r,{baseUrl:or.spelling("baseURL"),withXsrfToken:or.spelling("withXSRFToken")},!0),r.method=(r.method||this.defaults.method||"get").toLowerCase();let o=a&&D.merge(a.common,a[r.method]);a&&D.forEach(["delete","get","head","post","put","patch","query","common"],g=>{delete a[g]}),r.headers=St.concat(o,a);let s=[],c=!0;this.interceptors.request.forEach(function(b){if(typeof b.runWhen=="function"&&b.runWhen(r)===!1)return;c=c&&b.synchronous;let _=r.transitional||ef;_&&_.legacyInterceptorReqResOrdering?s.unshift(b.fulfilled,b.rejected):s.push(b.fulfilled,b.rejected)});let u=[];this.interceptors.response.forEach(function(b){u.push(b.fulfilled,b.rejected)});let l,d=0,f;if(!c){let g=[T4.bind(this),void 0];for(g.unshift(...s),g.push(...u),f=g.length,l=Promise.resolve(r);d<f;)l=l.then(g[d++],g[d++]);return l}f=s.length;let h=r;for(;d<f;){let g=s[d++],b=s[d++];try{h=g(h)}catch(_){b.call(this,_);break}}try{l=T4.call(this,h)}catch(g){return Promise.reject(g)}for(d=0,f=u.length;d<f;)l=l.then(u[d++],u[d++]);return l}getUri(t){t=Eo(this.defaults,t);let r=Pv(t.baseURL,t.url,t.allowAbsoluteUrls,t);return Ev(r,t.params,t.paramsSerializer)}};D.forEach(["delete","get","head","options"],function(t){zi.prototype[t]=function(r,i){return this.request(Eo(i||{},{method:t,url:r,data:i&&D.hasOwnProp(i,"data")?i.data:void 0}))}});D.forEach(["post","put","patch","query"],function(t){function r(i){return function(a,o,s){return this.request(Eo(s||{},{method:t,headers:i?{"Content-Type":"multipart/form-data"}:{},url:a,data:o}))}}zi.prototype[t]=r(),t!=="query"&&(zi.prototype[t+"Form"]=r(!0))});var yv=class e{constructor(t){if(typeof t!="function")throw new TypeError("executor must be a function.");let r;this.promise=new Promise(function(a){r=a});let i=this;this.promise.then(n=>{if(!i._listeners)return;let a=i._listeners.length;for(;a-- >0;)i._listeners[a](n);i._listeners=null}),this.promise.then=n=>{let a,o=new Promise(s=>{i.subscribe(s),a=s}).then(n);return o.cancel=function(){i.unsubscribe(a)},o},t(function(a,o,s){i.reason||(i.reason=new qi(a,o,s),r(i.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;let r=this._listeners.indexOf(t);r!==-1&&this._listeners.splice(r,1)}toAbortSignal(){let t=new AbortController,r=i=>{t.abort(i)};return this.subscribe(r),t.signal.unsubscribe=()=>this.unsubscribe(r),t.signal}static source(){let t;return{token:new e(function(n){t=n}),cancel:t}}};function qee(e){return function(r){return e.apply(null,r)}}function Uee(e){return D.isObject(e)&&e.isAxiosError===!0}var _v={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(_v).forEach(([e,t])=>{_v[t]=e});function dO(e){let t=new zi(e),r=A4(zi.prototype.request,t);return D.extend(r,zi.prototype,t,{allOwnKeys:!0}),D.extend(r,t,null,{allOwnKeys:!0}),r.create=function(n){return dO(Eo(e,n))},r}var kt=dO(Eu);kt.Axios=zi;kt.CanceledError=qi;kt.CancelToken=yv;kt.isCancel=Y4;kt.VERSION=wu;kt.toFormData=Qp;kt.AxiosError=R;kt.Cancel=kt.CanceledError;kt.all=function(t){return Promise.all(t)};kt.spread=qee;kt.isAxiosError=Uee;kt.mergeConfig=Eo;kt.AxiosHeaders=St;kt.formToJSON=e=>W4(D.isHTMLForm(e)?new FormData(e):e);kt.getAdapter=lO.getAdapter;kt.HttpStatusCode=_v;kt.default=kt;pO.exports=kt});var rf=x(zs=>{"use strict";Object.defineProperty(zs,"__esModule",{value:!0});zs.Endpoints=zs.API=void 0;zs.API={RANGE_HEADER:"items=0-1000",BASE_PATH:"/v3",REQUEST_TIMEOUT_MS:3e4,MAX_RETRIES:2,RETRY_BASE_DELAY_MS:300,DEFAULT_AGGREGATE_LIMIT:1e3};zs.Endpoints={TRIGGER:"/trigger",SCHEDULER:"/scheduler",SCHEDULER_FETCH:"/database/scheduler",WIDGET:"/widget",CUSTOM_PAGE:"/database/studio_page",AGGREGATE:"/database/prepared_aggregate",AGGREGATE_BY_ID:e=>`/prepared/aggregate/${e}`,AGGREGATE_PARAMS:e=>`/find/${e}/params`,AGGREGATE_FIND:e=>`/find/${e}`,AGGREGATE_ANALYZE:e=>`/prepared/aggregate/${e}/analyze`,PUBLIC_ENDPOINT:"/database/public_endpoint",PUBLIC_ENDPOINT_UPDATE:"/public",PUBLIC_ENDPOINT_BY_ID:e=>`/public/${e}`,CHALLENGE_AGGREGATE:"/database/challenge_rule_prepared",AUTH_MODULE:"/database/auth_module",AUTH_MODULE_UPDATE:"/auth/module",WEBSOCKET:"/database/websocket",WEBSOCKET_UPDATE:"/websocket",AI_KNOWLEDGE:"/system/ai/knowledge",SCHEDULER_LOG:"/scheduler/log",TRIGGER_LOG:"/database/trigger_log/aggregate",CRON_VALIDATE:"/util/cron/evaluate",ACCOUNT_INFO:"/account/info",COLLECTIONS:"/database/collections",GAMIFICATION:e=>`/gamification/${e}`,AUDIT:"/audit",ACTION:"/action",CHALLENGE:"/challenge",CHALLENGE_FETCH:"/database/challenge",POINT:"/point",LEVEL:"/level",LEVEL_CONFIG:"/database/level_config",LEVEL_POSITION:"/level/position",LEADERBOARD:"/leaderboard",LEADERBOARD_LEADERS:e=>`/leaderboard/${e}/leader/aggregate`,LEADERBOARD_RESET:"/leaderboard/reset",QUIZ:"/quiz",QUIZ_LIST:"/database/quiz",QUIZ_QUESTION:"/question",QUIZ_QUESTION_BY_QUIZ:e=>`/quiz/${e}/question`,QUIZ_START:"/quiz/start",QUIZ_FINISH:"/quiz/finish",QUESTION_LOG_BULK:"/question/log/bulk",VIRTUAL_GOOD_CATALOG:"/virtualgoods/catalog",VIRTUAL_GOOD_ITEM:"/virtualgoods/item",VIRTUAL_GOOD_PURCHASE:"/virtualgoods/purchase",FOLDER:"/folder",FOLDER_BY_ID:e=>`/folder/${e}`,FOLDER_INSIDE:"/folder/inside",FOLDER_PROGRESS:"/folder/progress",FOLDER_BREADCRUMB:"/folder/breadcrumb",FOLDER_MOVE:e=>`/folder/${e}/move`,FOLDER_CONTENT:"/folder/content",FOLDER_CONTENT_BY_ID:e=>`/folder/content/${e}`,FOLDER_CONTENT_DATA:e=>`/folder/content/${e}/data`,FOLDER_CONTENT_AGGREGATE:"/folder/content/aggregate",FOLDER_CONTENT_MOVE:e=>`/folder/content/${e}/move`,FOLDER_LOG:"/folder/log",FOLDER_LOG_BY_ID:e=>`/folder/log/${e}`,FOLDER_CONTENT_TYPE:"/database/folder_content_type",ROLE:"/system/role",ROLE_BY_ID:e=>`/system/role/${e}`,ROLE_AGGREGATE:"/system/role/aggregate",ROLE_ASSIGN:"/system/role/assign",ROLE_ASSIGN_AGGREGATE:"/system/role/assign/aggregate",ROLE_BULK:"/system/role/bulk",INDEX:e=>`/database/${e}/index`,INDEX_BY_NAME:(e,t)=>`/database/${e}/index/${encodeURIComponent(t)}`}});var nf=x(Pu=>{"use strict";Object.defineProperty(Pu,"__esModule",{value:!0});Pu.logger=void 0;Pu.log=Ou;var Tv={debug:0,info:1,warn:2,error:3};function Lee(){let e=(process.env.FUNIFIER_LOG_LEVEL??"info").toLowerCase();return e in Tv?e:"info"}function Ou(e,t,r={}){if(Tv[e]<Tv[Lee()])return;let i={ts:new Date().toISOString(),level:e,msg:t,...r};try{process.stderr.write(`${JSON.stringify(i)}
|
|
65
|
-
`)}catch{}}Pu.logger={debug:(e,t)=>Ou("debug",e,t),info:(e,t)=>Ou("info",e,t),warn:(e,t)=>Ou("warn",e,t),error:(e,t)=>Ou("error",e,t)}});var vO=x(Ea=>{"use strict";var Bee=Ea&&Ea.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ea,"__esModule",{value:!0});Ea.shouldRetryRequest=hO;Ea.retryDelayMs=gO;Ea.serializeToFunifierQuery=xO;Ea.createAPIClient=Hee;var Vee=Bee(fO()),N=rf(),mO=nf();function X(e){if(e?.response?.data){let t=e.response.data;return typeof t=="string"?t:t.errorMessage?t.errorMessage:t.message?t.message:JSON.stringify(t)}return e?.message?e.message:String(e)}function pe(e){mO.logger.error("funifier api request failed",{status:e?.response?.status,method:(e?.config?.method??"").toUpperCase()||void 0,url:e?.config?.url,error:X(e)})}function hO(e,t){if(t>=N.API.MAX_RETRIES||!((e?.config?.method??"").toLowerCase()==="get"))return!1;let i=e?.response?.status;return!e?.response||e?.code==="ECONNABORTED"||typeof i=="number"&&i>=500}function gO(e){return N.API.RETRY_BASE_DELAY_MS*2**(e-1)}function Gee(e){e.interceptors.response.use(void 0,async t=>{let r=t?.config,i=r?.__retryCount??0;if(!r||!hO(t,i))return Promise.reject(t);let n=i+1;return r.__retryCount=n,mO.logger.warn("retrying funifier GET after transient failure",{url:r.url,attempt:n,status:t?.response?.status}),await new Promise(a=>setTimeout(a,gO(n))),e(r)})}function xO(e){return Object.entries(e).map(([t,r])=>{if(r!==null&&typeof r=="object")throw Array.isArray(r)?new Error(`Array value for field "${t}" not supported in action=query. Use action=aggregate with [{"$match": {"${t}": {"$in": <array>}}}] instead.`):new Error(`Operator in field "${t}" not supported in action=query. Use action=aggregate with [{"$match": <filter>}] instead.`);return typeof r=="string"?`${t}:"${r}"`:`${t}:${r}`}).join(",")}function Hee(e){if(!e.apiKey||!e.secretKey||!e.serverUrl)throw new Error("Funifier config is required: apiKey, secretKey, and serverUrl must be provided");let t=Vee.default.create({baseURL:`${e.serverUrl}${N.API.BASE_PATH}`,timeout:N.API.REQUEST_TIMEOUT_MS,headers:{"Content-Type":"application/json",Authorization:`Basic ${Buffer.from(`${e.apiKey}:${e.secretKey}`).toString("base64")}`,Range:N.API.RANGE_HEADER}});return Gee(t),{listTriggers:async()=>{try{return(await t.get(N.Endpoints.TRIGGER)).data}catch(r){return pe(r),[]}},saveTrigger:async r=>{try{return(await t.post(N.Endpoints.TRIGGER,r)).data}catch(i){throw new Error("Failed to update trigger: "+X(i))}},deleteTrigger:async r=>{try{return(await t.delete(`${N.Endpoints.TRIGGER}/${r}`)).data}catch(i){throw new Error("Failed to delete trigger: "+X(i))}},getTriggerLogs:async r=>{try{let i=[{$match:{_id:r}}];return(await t.post(N.Endpoints.TRIGGER_LOG,i)).data}catch(i){return pe(i),[]}},listSchedulers:async()=>{try{return(await t.get(N.Endpoints.SCHEDULER_FETCH)).data}catch(r){return pe(r),[]}},saveScheduler:async r=>{try{return(await t.post(N.Endpoints.SCHEDULER,r)).data}catch(i){throw new Error("Failed to save scheduler: "+X(i))}},deleteScheduler:async r=>{try{return(await t.delete(`${N.Endpoints.SCHEDULER}/${r}`)).data}catch(i){throw new Error("Failed to delete scheduler: "+X(i))}},executeScheduler:async r=>{try{return(await t.get(`${N.Endpoints.SCHEDULER}/execute/${r}`)).data}catch(i){throw pe(i),new Error("Failed to execute scheduler: "+X(i))}},getSchedulerLogs:async r=>{try{return(await t.get(N.Endpoints.SCHEDULER_LOG,{params:{orderby:"time",reverse:!0,max_results:10,item:r}})).data}catch(i){return pe(i),[]}},listAggregates:async()=>{try{return(await t.get(N.Endpoints.AGGREGATE)).data}catch(r){return pe(r),[]}},saveAggregate:async r=>{try{return(await t.put(N.Endpoints.AGGREGATE,r)).data}catch(i){throw new Error("Failed to save aggregate: "+X(i))}},deleteAggregate:async r=>{try{return(await t.delete(N.Endpoints.AGGREGATE_BY_ID(r))).data}catch(i){throw new Error("Failed to delete aggregate: "+X(i))}},executeAggregate:async(r,i)=>{try{return(await t.post(N.Endpoints.AGGREGATE_FIND(r),i)).data}catch(n){throw pe(n),new Error("Failed to execute aggregate: "+X(n))}},analyzeAggregate:async(r,i)=>{try{return(await t.post(N.Endpoints.AGGREGATE_ANALYZE(r),i)).data}catch(n){throw pe(n),new Error("Failed to analyze aggregate: "+X(n))}},getAggregateParams:async r=>{try{return(await t.get(N.Endpoints.AGGREGATE_PARAMS(r))).data}catch(i){throw pe(i),new Error("Failed to get aggregate params: "+X(i))}},listWebsockets:async()=>{try{return(await t.get(N.Endpoints.WEBSOCKET)).data}catch(r){return pe(r),[]}},saveWebsocket:async(r,i)=>{try{let n={...r,isNew:i};return(await t.post(N.Endpoints.WEBSOCKET_UPDATE,n)).data}catch(n){throw new Error("Failed to save websocket: "+X(n))}},deleteWebsocket:async r=>{try{return await t.delete(`${N.Endpoints.WEBSOCKET_UPDATE}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete websocket: "+X(i))}},listWidgets:async()=>{try{return(await t.get(N.Endpoints.WIDGET)).data}catch(r){return pe(r),[]}},getWidgetById:async r=>{try{return(await t.get(`${N.Endpoints.WIDGET}/${r}`)).data}catch(i){pe(i);return}},saveWidget:async r=>{try{return(await t.post(N.Endpoints.WIDGET,r)).data}catch(i){throw new Error("Failed to save widget: "+X(i))}},deleteWidget:async r=>{try{return(await t.delete(`${N.Endpoints.WIDGET}/${r}`)).data}catch(i){throw new Error("Failed to delete widget: "+X(i))}},listCustomPages:async()=>{try{return(await t.get(N.Endpoints.CUSTOM_PAGE)).data}catch(r){return pe(r),[]}},saveCustomPage:async r=>{try{return(await t.put(N.Endpoints.CUSTOM_PAGE,r)).data}catch(i){throw new Error("Failed to save custom page: "+X(i))}},deleteCustomPage:async r=>{try{return(await t.delete(`${N.Endpoints.CUSTOM_PAGE}?q=_id:'${r}'`)).data}catch(i){throw new Error("Failed to delete custom page: "+X(i))}},listPublicEndpoints:async()=>{try{return(await t.get(N.Endpoints.PUBLIC_ENDPOINT)).data}catch(r){return pe(r),[]}},savePublicEndpoint:async r=>{try{return(await t.post(N.Endpoints.PUBLIC_ENDPOINT_UPDATE,r)).data}catch(i){throw new Error("Failed to save public endpoint: "+X(i))}},deletePublicEndpoint:async r=>{try{return(await t.delete(N.Endpoints.PUBLIC_ENDPOINT_BY_ID(r))).data}catch(i){throw new Error("Failed to delete public endpoint: "+X(i))}},executePublicEndpoint:async(r,i,n,a)=>{try{let o=`/pub/${r}/${i}`;return(a.toUpperCase()==="GET"?await t.get(o):await t.post(o,n)).data}catch(o){if(pe(o),o.response?.data)return o.response.data;throw new Error("Failed to execute public endpoint: "+X(o))}},listChallengeAggregates:async()=>{try{return(await t.get(N.Endpoints.CHALLENGE_AGGREGATE)).data}catch(r){return pe(r),[]}},saveChallengeAggregate:async r=>{try{return(await t.put(N.Endpoints.CHALLENGE_AGGREGATE,r)).data}catch(i){throw new Error("Failed to execute aggregate: "+X(i))}},deleteChallengeAggregate:async r=>{try{return(await t.delete(`${N.Endpoints.CHALLENGE_AGGREGATE}?q=_id:'${r}'`)).data}catch(i){throw new Error("Failed to delete challenge aggregate: "+X(i))}},listAuthModules:async()=>{try{return(await t.get(N.Endpoints.AUTH_MODULE)).data}catch(r){return pe(r),[]}},saveAuthModule:async(r,i)=>{try{let n={...r,isNew:i};return(await t.post(N.Endpoints.AUTH_MODULE_UPDATE,n)).data}catch(n){throw new Error("Failed to save auth module: "+X(n))}},deleteAuthModule:async r=>{try{return await t.delete(`${N.Endpoints.AUTH_MODULE_UPDATE}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete auth module: "+X(i))}},listAiKnowledge:async()=>{try{return(await t.post(`${N.Endpoints.AI_KNOWLEDGE}/aggregate`,[])).data}catch(r){return pe(r),[]}},saveAiKnowledge:async r=>{try{return(await t.post(N.Endpoints.AI_KNOWLEDGE,r)).data}catch(i){throw new Error("Failed to save AI knowledge: "+X(i))}},deleteAiKnowledge:async r=>{try{return(await t.delete(`${N.Endpoints.AI_KNOWLEDGE}/${r}`)).data}catch(i){throw new Error("Failed to delete AI knowledge: "+X(i))}},getStudioPageFolders:async()=>{try{let i=(await t.get(`${N.Endpoints.CUSTOM_PAGE}_folder`)).data;return Array.isArray(i)?i:i&&typeof i=="object"?[i]:[]}catch(r){return pe(r),[]}},listFolders:async()=>{try{return(await t.get("/database/folder")).data}catch(r){return pe(r),[]}},saveFolder:async r=>{try{return(await t.post(N.Endpoints.FOLDER,r)).data}catch(i){throw new Error("Failed to save folder: "+X(i))}},deleteFolder:async r=>{try{return(await t.delete(N.Endpoints.FOLDER_BY_ID(r))).data}catch(i){throw new Error("Failed to delete folder: "+X(i))}},listFolderContents:async()=>{try{return(await t.get("/database/folder_content")).data}catch(r){return pe(r),[]}},saveFolderContent:async r=>{try{return(await t.post(N.Endpoints.FOLDER_CONTENT,r)).data}catch(i){throw new Error("Failed to save folder content: "+X(i))}},deleteFolderContent:async r=>{try{return(await t.delete(N.Endpoints.FOLDER_CONTENT_BY_ID(r))).data}catch(i){throw new Error("Failed to delete folder content: "+X(i))}},listFolderContentTypes:async()=>{try{return(await t.get(N.Endpoints.FOLDER_CONTENT_TYPE)).data}catch(r){return pe(r),[]}},saveFolderContentType:async r=>{try{return(await t.put(N.Endpoints.FOLDER_CONTENT_TYPE,r)).data}catch(i){throw new Error("Failed to save folder content type: "+X(i))}},listFolderLogs:async()=>{try{return(await t.get("/database/folder_log")).data}catch(r){return pe(r),[]}},saveFolderLog:async r=>{try{return(await t.post(N.Endpoints.FOLDER_LOG,r)).data}catch(i){throw new Error("Failed to save folder log: "+X(i))}},deleteFolderLog:async r=>{try{return(await t.delete(N.Endpoints.FOLDER_LOG_BY_ID(r))).data}catch(i){throw new Error("Failed to delete folder log: "+X(i))}},folderInside:async r=>{try{return(await t.post(N.Endpoints.FOLDER_INSIDE,{folder:r})).data}catch(i){throw new Error("Failed to get folder inside: "+X(i))}},folderProgress:async(r,i)=>{try{return(await t.post(N.Endpoints.FOLDER_PROGRESS,{folder:r,player:i})).data}catch(n){throw new Error("Failed to get folder progress: "+X(n))}},folderBreadcrumb:async r=>{try{return(await t.post(N.Endpoints.FOLDER_BREADCRUMB,{folder:r})).data}catch(i){throw new Error("Failed to get folder breadcrumb: "+X(i))}},evaluateCron:async r=>{try{return(await t.post(N.Endpoints.CRON_VALIDATE,{expression:r,language:"en"})).data}catch(i){throw pe(i),new Error("Failed to evaluate cron expression: "+X(i))}},getCollections:async()=>{try{return(await t.get(N.Endpoints.COLLECTIONS)).data}catch(r){return pe(r),[]}},queryCollection:async(r,i={},n={})=>{let a={};Object.keys(i).length>0&&(a.q=xO(i));try{n.sort&&(a.sort=JSON.stringify(n.sort));let o=n.skip??0,s=n.limit??10;return(await t.get(`/database/${r}`,{params:a,headers:{Range:`items=${o}-${s}`}})).data}catch(o){return pe(o),[]}},aggregateCollection:async(r,i)=>{try{return(await t.post(`/database/${r}/aggregate`,i)).data}catch(n){throw pe(n),new Error(`Failed to aggregate on ${r}: ${n}`)}},insertDocument:async(r,i)=>{try{return(await t.post(`/database/${r}`,i)).data}catch(n){throw pe(n),new Error(`Failed to insert document into ${r}: ${n}`)}},updateDocument:async(r,i)=>{try{return(await t.put(`/database/${r}`,i)).data}catch(n){throw pe(n),new Error(`Failed to update document in ${r}: ${n}`)}},deleteDocument:async(r,i)=>{try{return(await t.delete(`/database/${r}?q=${i}`)).data}catch(n){throw pe(n),new Error(`Failed to delete document from ${r}: ${n}`)}},bulkInsert:async(r,i)=>{try{return(await t.post(`/database/${r}/bulk`,i)).data}catch(n){throw pe(n),new Error(`Failed to bulk insert into ${r}: ${n}`)}},listIndexes:async r=>{try{return(await t.get(N.Endpoints.INDEX(r))).data}catch(i){return pe(i),[]}},createIndex:async(r,i)=>{try{return(await t.post(N.Endpoints.INDEX(r),i)).data}catch(n){throw new Error(`Failed to create index on '${r}': ${X(n)}`)}},dropIndex:async(r,i)=>{try{return(await t.delete(N.Endpoints.INDEX_BY_NAME(r,i))).data}catch(n){throw new Error(`Failed to drop index '${i}' on '${r}': ${X(n)}`)}},listActions:async()=>{try{return(await t.get(N.Endpoints.ACTION)).data}catch(r){return pe(r),[]}},saveAction:async r=>{try{return(await t.post(N.Endpoints.ACTION,r)).data}catch(i){throw new Error("Failed to save action: "+X(i))}},deleteAction:async r=>{try{return(await t.delete(`${N.Endpoints.ACTION}/${r}`)).data}catch(i){throw new Error("Failed to delete action: "+X(i))}},listAudits:async()=>{try{return(await t.post("/database/audit/aggregate",[])).data}catch(r){return pe(r),[]}},saveAudit:async r=>{try{return(await t.post(N.Endpoints.AUDIT,r)).data}catch(i){throw new Error("Failed to save audit: "+X(i))}},deleteAudit:async r=>{try{return(await t.delete(`${N.Endpoints.AUDIT}/${r}`)).data}catch(i){throw new Error("Failed to delete audit: "+X(i))}},listChallenges:async()=>{try{return(await t.get(N.Endpoints.CHALLENGE_FETCH)).data}catch(r){return pe(r),[]}},saveChallenge:async r=>{try{return(await t.post(N.Endpoints.CHALLENGE,r)).data}catch(i){throw new Error("Failed to save challenge: "+X(i))}},deleteChallenge:async r=>{try{return(await t.delete(`${N.Endpoints.CHALLENGE}/${r}`)).data}catch(i){throw new Error("Failed to delete challenge: "+X(i))}},listPoints:async()=>{try{return(await t.get(N.Endpoints.POINT)).data}catch(r){return pe(r),[]}},savePoint:async r=>{try{return(await t.post(N.Endpoints.POINT,r)).data}catch(i){throw new Error("Failed to save point: "+X(i))}},deletePoint:async r=>{try{return(await t.delete(`${N.Endpoints.POINT}/${r}`)).data}catch(i){throw new Error("Failed to delete point: "+X(i))}},listLevels:async()=>{try{return(await t.get(N.Endpoints.LEVEL)).data}catch(r){return pe(r),[]}},saveLevel:async r=>{try{return(await t.post(N.Endpoints.LEVEL,r)).data}catch(i){throw new Error("Failed to save level: "+X(i))}},deleteLevel:async r=>{try{return(await t.delete(`${N.Endpoints.LEVEL}/${r}`)).data}catch(i){throw new Error("Failed to delete level: "+X(i))}},saveLevelConfig:async r=>{try{return(await t.put(N.Endpoints.LEVEL_CONFIG,r)).data}catch(i){throw new Error("Failed to save level config: "+X(i))}},listLeaderboards:async()=>{try{return(await t.get(N.Endpoints.LEADERBOARD)).data}catch(r){return pe(r),[]}},saveLeaderboard:async r=>{try{return(await t.post(N.Endpoints.LEADERBOARD,r)).data}catch(i){throw new Error("Failed to save leaderboard: "+X(i))}},deleteLeaderboard:async r=>{try{return(await t.delete(`${N.Endpoints.LEADERBOARD}/${r}`)).data}catch(i){throw new Error("Failed to delete leaderboard: "+X(i))}},getLeaderboardResults:async r=>{try{return(await t.post(N.Endpoints.LEADERBOARD_LEADERS(r),[])).data}catch(i){return pe(i),[]}},listQuizzes:async()=>{try{return(await t.get(N.Endpoints.QUIZ_LIST)).data}catch(r){return pe(r),[]}},saveQuiz:async r=>{try{return(await t.post(N.Endpoints.QUIZ,r)).data}catch(i){throw new Error("Failed to save quiz: "+X(i))}},deleteQuiz:async r=>{try{return(await t.delete(`${N.Endpoints.QUIZ}/${r}`)).data}catch(i){throw new Error("Failed to delete quiz: "+X(i))}},listQuizQuestions:async r=>{try{return(await t.get(N.Endpoints.QUIZ_QUESTION_BY_QUIZ(r))).data}catch(i){return pe(i),[]}},saveQuestion:async r=>{try{return(await t.post(N.Endpoints.QUIZ_QUESTION,r)).data}catch(i){throw new Error("Failed to save question: "+X(i))}},listVirtualGoodCatalogs:async()=>{try{return(await t.get(N.Endpoints.VIRTUAL_GOOD_CATALOG)).data}catch(r){return pe(r),[]}},saveVirtualGoodCatalog:async r=>{try{return(await t.post(N.Endpoints.VIRTUAL_GOOD_CATALOG,r)).data}catch(i){throw new Error("Failed to save virtual good catalog: "+X(i))}},listVirtualGoodItems:async()=>{try{return(await t.get(N.Endpoints.VIRTUAL_GOOD_ITEM)).data}catch(r){return pe(r),[]}},saveVirtualGoodItem:async r=>{try{return(await t.post(N.Endpoints.VIRTUAL_GOOD_ITEM,r)).data}catch(i){throw new Error("Failed to save virtual good item: "+X(i))}},deleteVirtualGoodCatalog:async r=>{try{return await t.delete(`${N.Endpoints.VIRTUAL_GOOD_CATALOG}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete virtual good catalog: "+X(i))}},deleteVirtualGoodItem:async r=>{try{return await t.delete(`${N.Endpoints.VIRTUAL_GOOD_ITEM}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete virtual good item: "+X(i))}},getGamification:async r=>{try{return(await t.get(N.Endpoints.GAMIFICATION(r))).data}catch(i){if(i.response?.data)return i.response.data;throw pe(i),i}},listRoles:async()=>{try{return(await t.post(N.Endpoints.ROLE_AGGREGATE,[])).data}catch(r){return pe(r),[]}},listRolesStrict:async()=>{try{return(await t.post(N.Endpoints.ROLE_AGGREGATE,[])).data}catch(r){throw new Error("Failed to list roles: "+X(r))}},getRoleById:async r=>{try{return(await t.get(N.Endpoints.ROLE_BY_ID(r))).data}catch(i){pe(i);return}},saveRole:async r=>{try{return(await t.post(N.Endpoints.ROLE,r)).data}catch(i){throw new Error("Failed to save role: "+X(i))}},deleteRole:async r=>{try{return(await t.delete(N.Endpoints.ROLE_BY_ID(r))).data}catch(i){throw new Error("Failed to delete role: "+X(i))}},assignRole:async r=>{try{return(await t.post(N.Endpoints.ROLE_ASSIGN,r)).data}catch(i){throw new Error("Failed to assign role: "+X(i))}},unassignRole:async r=>{try{return(await t.delete(N.Endpoints.ROLE_ASSIGN,{data:r})).data}catch(i){throw new Error("Failed to unassign role: "+X(i))}},listRoleAssignments:async r=>{try{let i={};return r&&(i.item=r),(await t.get(N.Endpoints.ROLE_ASSIGN,{params:i})).data}catch(i){return pe(i),[]}},listRoleAssignmentsStrict:async r=>{try{let i={};return r&&(i.item=r),(await t.get(N.Endpoints.ROLE_ASSIGN,{params:i})).data}catch(i){throw new Error("Failed to list role assignments: "+X(i))}}}}});var _O=x(ju=>{"use strict";var yO=ju&&ju.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(ju,"__esModule",{value:!0});ju.resolveConfig=Jee;var bO=yO(require("fs")),Kee=yO(require("path"));function Jee(e){let t=e||Kee.default.join(process.cwd(),"funifier.json");if(bO.default.existsSync(t)){let a=bO.default.readFileSync(t,"utf-8"),o=JSON.parse(a);if(o.apiKey&&o.secretKey&&o.serverUrl)return{apiKey:o.apiKey,secretKey:o.secretKey,serverUrl:o.serverUrl};throw new Error(`funifier.json at ${t} is missing required fields (apiKey, secretKey, serverUrl)`)}let r=process.env.FUNIFIER_API_KEY,i=process.env.FUNIFIER_SECRET_KEY,n=process.env.FUNIFIER_SERVER_URL;if(r&&i&&n)return{apiKey:r,secretKey:i,serverUrl:n};throw new Error("Funifier config not found. Provide funifier.json in the working directory or set FUNIFIER_API_KEY, FUNIFIER_SECRET_KEY, and FUNIFIER_SERVER_URL environment variables.")}});var SO=x(wO=>{"use strict";Object.defineProperty(wO,"__esModule",{value:!0})});var $O=x(DO=>{"use strict";Object.defineProperty(DO,"__esModule",{value:!0})});var OO=x(EO=>{"use strict";Object.defineProperty(EO,"__esModule",{value:!0})});var jO=x(PO=>{"use strict";Object.defineProperty(PO,"__esModule",{value:!0})});var IO=x(TO=>{"use strict";Object.defineProperty(TO,"__esModule",{value:!0})});var CO=x(kO=>{"use strict";Object.defineProperty(kO,"__esModule",{value:!0})});var AO=x(RO=>{"use strict";Object.defineProperty(RO,"__esModule",{value:!0})});var MO=x(NO=>{"use strict";Object.defineProperty(NO,"__esModule",{value:!0})});var ZO=x(FO=>{"use strict";Object.defineProperty(FO,"__esModule",{value:!0})});var qO=x(zO=>{"use strict";Object.defineProperty(zO,"__esModule",{value:!0})});var LO=x(UO=>{"use strict";Object.defineProperty(UO,"__esModule",{value:!0})});var VO=x(BO=>{"use strict";Object.defineProperty(BO,"__esModule",{value:!0})});var HO=x(GO=>{"use strict";Object.defineProperty(GO,"__esModule",{value:!0})});var JO=x(KO=>{"use strict";Object.defineProperty(KO,"__esModule",{value:!0})});var YO=x(WO=>{"use strict";Object.defineProperty(WO,"__esModule",{value:!0})});var QO=x(XO=>{"use strict";Object.defineProperty(XO,"__esModule",{value:!0})});var tP=x(eP=>{"use strict";Object.defineProperty(eP,"__esModule",{value:!0})});var nP=x(rP=>{"use strict";Object.defineProperty(rP,"__esModule",{value:!0})});var aP=x(iP=>{"use strict";Object.defineProperty(iP,"__esModule",{value:!0})});var sP=x(oP=>{"use strict";Object.defineProperty(oP,"__esModule",{value:!0})});var uP=x(cP=>{"use strict";Object.defineProperty(cP,"__esModule",{value:!0})});var dP=x(lP=>{"use strict";Object.defineProperty(lP,"__esModule",{value:!0})});var fP=x(pP=>{"use strict";Object.defineProperty(pP,"__esModule",{value:!0})});var mP=x(He=>{"use strict";var Wee=He&&He.__createBinding||(Object.create?function(e,t,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(t,r);(!n||("get"in n?!t.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,n)}:function(e,t,r,i){i===void 0&&(i=r),e[i]=t[r]}),lt=He&&He.__exportStar||function(e,t){for(var r in e)r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r)&&Wee(t,e,r)};Object.defineProperty(He,"__esModule",{value:!0});lt(SO(),He);lt($O(),He);lt(OO(),He);lt(jO(),He);lt(IO(),He);lt(CO(),He);lt(AO(),He);lt(MO(),He);lt(ZO(),He);lt(qO(),He);lt(LO(),He);lt(VO(),He);lt(HO(),He);lt(JO(),He);lt(YO(),He);lt(QO(),He);lt(tP(),He);lt(nP(),He);lt(aP(),He);lt(sP(),He);lt(uP(),He);lt(dP(),He);lt(fP(),He)});var gP=x(pr=>{"use strict";var Yee=pr&&pr.__createBinding||(Object.create?function(e,t,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(t,r);(!n||("get"in n?!t.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,n)}:function(e,t,r,i){i===void 0&&(i=r),e[i]=t[r]}),Xee=pr&&pr.__exportStar||function(e,t){for(var r in e)r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r)&&Yee(t,e,r)};Object.defineProperty(pr,"__esModule",{value:!0});pr.Endpoints=pr.API=pr.resolveConfig=pr.createAPIClient=void 0;var Qee=vO();Object.defineProperty(pr,"createAPIClient",{enumerable:!0,get:function(){return Qee.createAPIClient}});var ete=_O();Object.defineProperty(pr,"resolveConfig",{enumerable:!0,get:function(){return ete.resolveConfig}});var hP=rf();Object.defineProperty(pr,"API",{enumerable:!0,get:function(){return hP.API}});Object.defineProperty(pr,"Endpoints",{enumerable:!0,get:function(){return hP.Endpoints}});Xee(mP(),pr)});var vP=x(af=>{"use strict";Object.defineProperty(af,"__esModule",{value:!0});af.ApiHolder=void 0;var xP=gP(),Iv=class{constructor(){this.client=null,this.currentConfig=null,this.connectionName=null}tryAutoConnect(){try{let t=(0,xP.resolveConfig)();return this.connect(t),!0}catch{return!1}}connect(t,r){this.client=(0,xP.createAPIClient)(t),this.currentConfig=t,this.connectionName=r||t.serverUrl}getClient(){return this.client}requireClient(){if(!this.client)throw new Error("Not connected to any Funifier instance. Use the funifier_connect tool first with your apiKey, secretKey, and serverUrl.");return this.client}getConnectionInfo(){return{connected:this.client!==null,serverUrl:this.currentConfig?.serverUrl||null,name:this.connectionName}}disconnect(){this.client=null,this.currentConfig=null,this.connectionName=null}};af.ApiHolder=Iv});var kv=x((Cde,tte)=>{tte.exports={name:"funifier-mcp",version:"0.3.20",description:"Funifier AI toolkit \u2014 MCP server, API client, and Claude Code skills for the Funifier gamification platform",main:"dist/index.js",types:"dist/index.d.ts",bin:{"funifier-mcp":"dist/mcp/index.js"},files:["dist","skills","doc","datasource-funifier-docs","AGENTS.md",".github/copilot-instructions.md",".cursor/rules/funifier.mdc","README.md","CHANGELOG.md","LICENSE"],repository:{type:"git",url:"git+https://github.com/funifierinc/funifier-mcp.git"},bugs:{url:"https://github.com/funifierinc/funifier-mcp/issues"},homepage:"https://github.com/funifierinc/funifier-mcp#readme",author:"Funifier",publishConfig:{access:"public"},scripts:{build:"tsc",bundle:"npm run build && esbuild dist/mcp/index.js --bundle --outfile=dist/mcp/bundle.js --format=cjs --platform=node --minify",dev:"tsc --watch",prepublishOnly:"npm run build:skills && npm run bundle",test:"vitest run","test:watch":"vitest watch","build:skills":"tsx scripts/build-skills.ts","build:skills:force":"tsx scripts/build-skills.ts --force","search:docs":"tsx scripts/search-docs.ts","validate:skills":"tsx scripts/validate-skills.ts","enrich:skills":"tsx scripts/enrich-skills.ts","generate:skills":"tsx scripts/generate-skills.ts","dev:init":"npm run build && node scripts/dev-init.js"},keywords:["funifier","gamification","mcp","model-context-protocol","claude","ai","api-client"],license:"MIT",dependencies:{"@inquirer/prompts":"^7.10.1","@modelcontextprotocol/sdk":"^1.0.0",axios:"^1.6.0",zod:"^3.25.76"},devDependencies:{"@anthropic-ai/sdk":"^0.96.0","@types/node":"^25.5.0",esbuild:"^0.20.0",tsx:"^4.21.0",typescript:"^5.3.0",vitest:"^1.0.0"},engines:{node:">=18"}}});var Rv=x(Oa=>{"use strict";Object.defineProperty(Oa,"__esModule",{value:!0});Oa.isMajorUpdate=_P;Oa.setUpdateNotice=wP;Oa.consumeUpdateNotice=rte;Oa.formatUpdateNotice=SP;Oa.checkForUpdate=nte;Oa.isOutdated=yP;function of(e){return e.replace(/[^0-9.]/g,"").split(".").map(Number)}function yP(e,t){let[r,i,n]=of(e),[a,o,s]=of(t);return a!==r?a>r:o!==i?o>i:s>n}function _P(e,t){let[r,i]=of(e),[n,a]=of(t);return n!==r?!0:r===0&&a!==i}var Cv=null;function wP(e){Cv=e}function rte(){let e=Cv;return Cv=null,e}var bP="https://github.com/funifierinc/funifier-mcp/blob/main/CHANGELOG.md";function SP(e,t){let r=_P(e,t),i=r?`\u2B06 funifier-mcp: nova vers\xE3o com MUDAN\xC7AS INCOMPAT\xCDVEIS dispon\xEDvel (${e} \u2192 ${t}).`:`\u2B06 funifier-mcp: nova vers\xE3o dispon\xEDvel (${e} \u2192 ${t}).`,n=r?`[assistant instruction] Before continuing, tell the user \u2014 in one or two short sentences, in the language they are using \u2014 that funifier-mcp ${t} is available and likely contains BREAKING CHANGES, so they should review the changelog (${bP}) before updating with \`npx funifier-mcp@latest init\`. Relay only these facts, do not speculate about what changed, then continue with their task.`:"[assistant instruction] Before continuing, tell the user \u2014 in one short sentence, in the language they are using \u2014 that a newer version of funifier-mcp is available and that they should run `npx funifier-mcp@latest init` to update (changelog: "+bP+"). One line only, do not speculate about what changed, then continue with their task.";return[i,"",n].join(`
|
|
65
|
+
`)}catch{}}Pu.logger={debug:(e,t)=>Ou("debug",e,t),info:(e,t)=>Ou("info",e,t),warn:(e,t)=>Ou("warn",e,t),error:(e,t)=>Ou("error",e,t)}});var vO=x(Ea=>{"use strict";var Bee=Ea&&Ea.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ea,"__esModule",{value:!0});Ea.shouldRetryRequest=hO;Ea.retryDelayMs=gO;Ea.serializeToFunifierQuery=xO;Ea.createAPIClient=Hee;var Vee=Bee(fO()),N=rf(),mO=nf();function X(e){if(e?.response?.data){let t=e.response.data;return typeof t=="string"?t:t.errorMessage?t.errorMessage:t.message?t.message:JSON.stringify(t)}return e?.message?e.message:String(e)}function pe(e){mO.logger.error("funifier api request failed",{status:e?.response?.status,method:(e?.config?.method??"").toUpperCase()||void 0,url:e?.config?.url,error:X(e)})}function hO(e,t){if(t>=N.API.MAX_RETRIES||!((e?.config?.method??"").toLowerCase()==="get"))return!1;let i=e?.response?.status;return!e?.response||e?.code==="ECONNABORTED"||typeof i=="number"&&i>=500}function gO(e){return N.API.RETRY_BASE_DELAY_MS*2**(e-1)}function Gee(e){e.interceptors.response.use(void 0,async t=>{let r=t?.config,i=r?.__retryCount??0;if(!r||!hO(t,i))return Promise.reject(t);let n=i+1;return r.__retryCount=n,mO.logger.warn("retrying funifier GET after transient failure",{url:r.url,attempt:n,status:t?.response?.status}),await new Promise(a=>setTimeout(a,gO(n))),e(r)})}function xO(e){return Object.entries(e).map(([t,r])=>{if(r!==null&&typeof r=="object")throw Array.isArray(r)?new Error(`Array value for field "${t}" not supported in action=query. Use action=aggregate with [{"$match": {"${t}": {"$in": <array>}}}] instead.`):new Error(`Operator in field "${t}" not supported in action=query. Use action=aggregate with [{"$match": <filter>}] instead.`);return typeof r=="string"?`${t}:"${r}"`:`${t}:${r}`}).join(",")}function Hee(e){if(!e.apiKey||!e.secretKey||!e.serverUrl)throw new Error("Funifier config is required: apiKey, secretKey, and serverUrl must be provided");let t=Vee.default.create({baseURL:`${e.serverUrl}${N.API.BASE_PATH}`,timeout:N.API.REQUEST_TIMEOUT_MS,headers:{"Content-Type":"application/json",Authorization:`Basic ${Buffer.from(`${e.apiKey}:${e.secretKey}`).toString("base64")}`,Range:N.API.RANGE_HEADER}});return Gee(t),{listTriggers:async()=>{try{return(await t.get(N.Endpoints.TRIGGER)).data}catch(r){return pe(r),[]}},saveTrigger:async r=>{try{return(await t.post(N.Endpoints.TRIGGER,r)).data}catch(i){throw new Error("Failed to update trigger: "+X(i))}},deleteTrigger:async r=>{try{return(await t.delete(`${N.Endpoints.TRIGGER}/${r}`)).data}catch(i){throw new Error("Failed to delete trigger: "+X(i))}},getTriggerLogs:async r=>{try{let i=[{$match:{_id:r}}];return(await t.post(N.Endpoints.TRIGGER_LOG,i)).data}catch(i){return pe(i),[]}},listSchedulers:async()=>{try{return(await t.get(N.Endpoints.SCHEDULER_FETCH)).data}catch(r){return pe(r),[]}},saveScheduler:async r=>{try{return(await t.post(N.Endpoints.SCHEDULER,r)).data}catch(i){throw new Error("Failed to save scheduler: "+X(i))}},deleteScheduler:async r=>{try{return(await t.delete(`${N.Endpoints.SCHEDULER}/${r}`)).data}catch(i){throw new Error("Failed to delete scheduler: "+X(i))}},executeScheduler:async r=>{try{return(await t.get(`${N.Endpoints.SCHEDULER}/execute/${r}`)).data}catch(i){throw pe(i),new Error("Failed to execute scheduler: "+X(i))}},getSchedulerLogs:async r=>{try{return(await t.get(N.Endpoints.SCHEDULER_LOG,{params:{orderby:"time",reverse:!0,max_results:10,item:r}})).data}catch(i){return pe(i),[]}},listAggregates:async()=>{try{return(await t.get(N.Endpoints.AGGREGATE)).data}catch(r){return pe(r),[]}},saveAggregate:async r=>{try{return(await t.put(N.Endpoints.AGGREGATE,r)).data}catch(i){throw new Error("Failed to save aggregate: "+X(i))}},deleteAggregate:async r=>{try{return(await t.delete(N.Endpoints.AGGREGATE_BY_ID(r))).data}catch(i){throw new Error("Failed to delete aggregate: "+X(i))}},executeAggregate:async(r,i)=>{try{return(await t.post(N.Endpoints.AGGREGATE_FIND(r),i)).data}catch(n){throw pe(n),new Error("Failed to execute aggregate: "+X(n))}},analyzeAggregate:async(r,i)=>{try{return(await t.post(N.Endpoints.AGGREGATE_ANALYZE(r),i)).data}catch(n){throw pe(n),new Error("Failed to analyze aggregate: "+X(n))}},getAggregateParams:async r=>{try{return(await t.get(N.Endpoints.AGGREGATE_PARAMS(r))).data}catch(i){throw pe(i),new Error("Failed to get aggregate params: "+X(i))}},listWebsockets:async()=>{try{return(await t.get(N.Endpoints.WEBSOCKET)).data}catch(r){return pe(r),[]}},saveWebsocket:async(r,i)=>{try{let n={...r,isNew:i};return(await t.post(N.Endpoints.WEBSOCKET_UPDATE,n)).data}catch(n){throw new Error("Failed to save websocket: "+X(n))}},deleteWebsocket:async r=>{try{return await t.delete(`${N.Endpoints.WEBSOCKET_UPDATE}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete websocket: "+X(i))}},listWidgets:async()=>{try{return(await t.get(N.Endpoints.WIDGET)).data}catch(r){return pe(r),[]}},getWidgetById:async r=>{try{return(await t.get(`${N.Endpoints.WIDGET}/${r}`)).data}catch(i){pe(i);return}},saveWidget:async r=>{try{return(await t.post(N.Endpoints.WIDGET,r)).data}catch(i){throw new Error("Failed to save widget: "+X(i))}},deleteWidget:async r=>{try{return(await t.delete(`${N.Endpoints.WIDGET}/${r}`)).data}catch(i){throw new Error("Failed to delete widget: "+X(i))}},listCustomPages:async()=>{try{return(await t.get(N.Endpoints.CUSTOM_PAGE)).data}catch(r){return pe(r),[]}},saveCustomPage:async r=>{try{return(await t.put(N.Endpoints.CUSTOM_PAGE,r)).data}catch(i){throw new Error("Failed to save custom page: "+X(i))}},deleteCustomPage:async r=>{try{return(await t.delete(`${N.Endpoints.CUSTOM_PAGE}?q=_id:'${r}'`)).data}catch(i){throw new Error("Failed to delete custom page: "+X(i))}},listPublicEndpoints:async()=>{try{return(await t.get(N.Endpoints.PUBLIC_ENDPOINT)).data}catch(r){return pe(r),[]}},savePublicEndpoint:async r=>{try{return(await t.post(N.Endpoints.PUBLIC_ENDPOINT_UPDATE,r)).data}catch(i){throw new Error("Failed to save public endpoint: "+X(i))}},deletePublicEndpoint:async r=>{try{return(await t.delete(N.Endpoints.PUBLIC_ENDPOINT_BY_ID(r))).data}catch(i){throw new Error("Failed to delete public endpoint: "+X(i))}},executePublicEndpoint:async(r,i,n,a)=>{try{let o=`/pub/${r}/${i}`;return(a.toUpperCase()==="GET"?await t.get(o):await t.post(o,n)).data}catch(o){if(pe(o),o.response?.data)return o.response.data;throw new Error("Failed to execute public endpoint: "+X(o))}},listChallengeAggregates:async()=>{try{return(await t.get(N.Endpoints.CHALLENGE_AGGREGATE)).data}catch(r){return pe(r),[]}},saveChallengeAggregate:async r=>{try{return(await t.put(N.Endpoints.CHALLENGE_AGGREGATE,r)).data}catch(i){throw new Error("Failed to execute aggregate: "+X(i))}},deleteChallengeAggregate:async r=>{try{return(await t.delete(`${N.Endpoints.CHALLENGE_AGGREGATE}?q=_id:'${r}'`)).data}catch(i){throw new Error("Failed to delete challenge aggregate: "+X(i))}},listAuthModules:async()=>{try{return(await t.get(N.Endpoints.AUTH_MODULE)).data}catch(r){return pe(r),[]}},saveAuthModule:async(r,i)=>{try{let n={...r,isNew:i};return(await t.post(N.Endpoints.AUTH_MODULE_UPDATE,n)).data}catch(n){throw new Error("Failed to save auth module: "+X(n))}},deleteAuthModule:async r=>{try{return await t.delete(`${N.Endpoints.AUTH_MODULE_UPDATE}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete auth module: "+X(i))}},listAiKnowledge:async()=>{try{return(await t.post(`${N.Endpoints.AI_KNOWLEDGE}/aggregate`,[])).data}catch(r){return pe(r),[]}},saveAiKnowledge:async r=>{try{return(await t.post(N.Endpoints.AI_KNOWLEDGE,r)).data}catch(i){throw new Error("Failed to save AI knowledge: "+X(i))}},deleteAiKnowledge:async r=>{try{return(await t.delete(`${N.Endpoints.AI_KNOWLEDGE}/${r}`)).data}catch(i){throw new Error("Failed to delete AI knowledge: "+X(i))}},getStudioPageFolders:async()=>{try{let i=(await t.get(`${N.Endpoints.CUSTOM_PAGE}_folder`)).data;return Array.isArray(i)?i:i&&typeof i=="object"?[i]:[]}catch(r){return pe(r),[]}},listFolders:async()=>{try{return(await t.get("/database/folder")).data}catch(r){return pe(r),[]}},saveFolder:async r=>{try{return(await t.post(N.Endpoints.FOLDER,r)).data}catch(i){throw new Error("Failed to save folder: "+X(i))}},deleteFolder:async r=>{try{return(await t.delete(N.Endpoints.FOLDER_BY_ID(r))).data}catch(i){throw new Error("Failed to delete folder: "+X(i))}},listFolderContents:async()=>{try{return(await t.get("/database/folder_content")).data}catch(r){return pe(r),[]}},saveFolderContent:async r=>{try{return(await t.post(N.Endpoints.FOLDER_CONTENT,r)).data}catch(i){throw new Error("Failed to save folder content: "+X(i))}},deleteFolderContent:async r=>{try{return(await t.delete(N.Endpoints.FOLDER_CONTENT_BY_ID(r))).data}catch(i){throw new Error("Failed to delete folder content: "+X(i))}},listFolderContentTypes:async()=>{try{return(await t.get(N.Endpoints.FOLDER_CONTENT_TYPE)).data}catch(r){return pe(r),[]}},saveFolderContentType:async r=>{try{return(await t.put(N.Endpoints.FOLDER_CONTENT_TYPE,r)).data}catch(i){throw new Error("Failed to save folder content type: "+X(i))}},listFolderLogs:async()=>{try{return(await t.get("/database/folder_log")).data}catch(r){return pe(r),[]}},saveFolderLog:async r=>{try{return(await t.post(N.Endpoints.FOLDER_LOG,r)).data}catch(i){throw new Error("Failed to save folder log: "+X(i))}},deleteFolderLog:async r=>{try{return(await t.delete(N.Endpoints.FOLDER_LOG_BY_ID(r))).data}catch(i){throw new Error("Failed to delete folder log: "+X(i))}},folderInside:async r=>{try{return(await t.post(N.Endpoints.FOLDER_INSIDE,{folder:r})).data}catch(i){throw new Error("Failed to get folder inside: "+X(i))}},folderProgress:async(r,i)=>{try{return(await t.post(N.Endpoints.FOLDER_PROGRESS,{folder:r,player:i})).data}catch(n){throw new Error("Failed to get folder progress: "+X(n))}},folderBreadcrumb:async r=>{try{return(await t.post(N.Endpoints.FOLDER_BREADCRUMB,{folder:r})).data}catch(i){throw new Error("Failed to get folder breadcrumb: "+X(i))}},evaluateCron:async r=>{try{return(await t.post(N.Endpoints.CRON_VALIDATE,{expression:r,language:"en"})).data}catch(i){throw pe(i),new Error("Failed to evaluate cron expression: "+X(i))}},getCollections:async()=>{try{return(await t.get(N.Endpoints.COLLECTIONS)).data}catch(r){return pe(r),[]}},queryCollection:async(r,i={},n={})=>{let a={};Object.keys(i).length>0&&(a.q=xO(i));try{n.sort&&(a.sort=JSON.stringify(n.sort));let o=n.skip??0,s=n.limit??10;return(await t.get(`/database/${r}`,{params:a,headers:{Range:`items=${o}-${s}`}})).data}catch(o){return pe(o),[]}},aggregateCollection:async(r,i)=>{try{return(await t.post(`/database/${r}/aggregate`,i)).data}catch(n){throw pe(n),new Error(`Failed to aggregate on ${r}: ${n}`)}},insertDocument:async(r,i)=>{try{return(await t.post(`/database/${r}`,i)).data}catch(n){throw pe(n),new Error(`Failed to insert document into ${r}: ${n}`)}},updateDocument:async(r,i)=>{try{return(await t.put(`/database/${r}`,i)).data}catch(n){throw pe(n),new Error(`Failed to update document in ${r}: ${n}`)}},deleteDocument:async(r,i)=>{try{return(await t.delete(`/database/${r}?q=${i}`)).data}catch(n){throw pe(n),new Error(`Failed to delete document from ${r}: ${n}`)}},bulkInsert:async(r,i)=>{try{return(await t.post(`/database/${r}/bulk`,i)).data}catch(n){throw pe(n),new Error(`Failed to bulk insert into ${r}: ${n}`)}},listIndexes:async r=>{try{return(await t.get(N.Endpoints.INDEX(r))).data}catch(i){return pe(i),[]}},createIndex:async(r,i)=>{try{return(await t.post(N.Endpoints.INDEX(r),i)).data}catch(n){throw new Error(`Failed to create index on '${r}': ${X(n)}`)}},dropIndex:async(r,i)=>{try{return(await t.delete(N.Endpoints.INDEX_BY_NAME(r,i))).data}catch(n){throw new Error(`Failed to drop index '${i}' on '${r}': ${X(n)}`)}},listActions:async()=>{try{return(await t.get(N.Endpoints.ACTION)).data}catch(r){return pe(r),[]}},saveAction:async r=>{try{return(await t.post(N.Endpoints.ACTION,r)).data}catch(i){throw new Error("Failed to save action: "+X(i))}},deleteAction:async r=>{try{return(await t.delete(`${N.Endpoints.ACTION}/${r}`)).data}catch(i){throw new Error("Failed to delete action: "+X(i))}},listAudits:async()=>{try{return(await t.post("/database/audit/aggregate",[])).data}catch(r){return pe(r),[]}},saveAudit:async r=>{try{return(await t.post(N.Endpoints.AUDIT,r)).data}catch(i){throw new Error("Failed to save audit: "+X(i))}},deleteAudit:async r=>{try{return(await t.delete(`${N.Endpoints.AUDIT}/${r}`)).data}catch(i){throw new Error("Failed to delete audit: "+X(i))}},listChallenges:async()=>{try{return(await t.get(N.Endpoints.CHALLENGE_FETCH)).data}catch(r){return pe(r),[]}},saveChallenge:async r=>{try{return(await t.post(N.Endpoints.CHALLENGE,r)).data}catch(i){throw new Error("Failed to save challenge: "+X(i))}},deleteChallenge:async r=>{try{return(await t.delete(`${N.Endpoints.CHALLENGE}/${r}`)).data}catch(i){throw new Error("Failed to delete challenge: "+X(i))}},listPoints:async()=>{try{return(await t.get(N.Endpoints.POINT)).data}catch(r){return pe(r),[]}},savePoint:async r=>{try{return(await t.post(N.Endpoints.POINT,r)).data}catch(i){throw new Error("Failed to save point: "+X(i))}},deletePoint:async r=>{try{return(await t.delete(`${N.Endpoints.POINT}/${r}`)).data}catch(i){throw new Error("Failed to delete point: "+X(i))}},listLevels:async()=>{try{return(await t.get(N.Endpoints.LEVEL)).data}catch(r){return pe(r),[]}},saveLevel:async r=>{try{return(await t.post(N.Endpoints.LEVEL,r)).data}catch(i){throw new Error("Failed to save level: "+X(i))}},deleteLevel:async r=>{try{return(await t.delete(`${N.Endpoints.LEVEL}/${r}`)).data}catch(i){throw new Error("Failed to delete level: "+X(i))}},saveLevelConfig:async r=>{try{return(await t.put(N.Endpoints.LEVEL_CONFIG,r)).data}catch(i){throw new Error("Failed to save level config: "+X(i))}},listLeaderboards:async()=>{try{return(await t.get(N.Endpoints.LEADERBOARD)).data}catch(r){return pe(r),[]}},saveLeaderboard:async r=>{try{return(await t.post(N.Endpoints.LEADERBOARD,r)).data}catch(i){throw new Error("Failed to save leaderboard: "+X(i))}},deleteLeaderboard:async r=>{try{return(await t.delete(`${N.Endpoints.LEADERBOARD}/${r}`)).data}catch(i){throw new Error("Failed to delete leaderboard: "+X(i))}},getLeaderboardResults:async r=>{try{return(await t.post(N.Endpoints.LEADERBOARD_LEADERS(r),[])).data}catch(i){return pe(i),[]}},listQuizzes:async()=>{try{return(await t.get(N.Endpoints.QUIZ_LIST)).data}catch(r){return pe(r),[]}},saveQuiz:async r=>{try{return(await t.post(N.Endpoints.QUIZ,r)).data}catch(i){throw new Error("Failed to save quiz: "+X(i))}},deleteQuiz:async r=>{try{return(await t.delete(`${N.Endpoints.QUIZ}/${r}`)).data}catch(i){throw new Error("Failed to delete quiz: "+X(i))}},listQuizQuestions:async r=>{try{return(await t.get(N.Endpoints.QUIZ_QUESTION_BY_QUIZ(r))).data}catch(i){return pe(i),[]}},saveQuestion:async r=>{try{return(await t.post(N.Endpoints.QUIZ_QUESTION,r)).data}catch(i){throw new Error("Failed to save question: "+X(i))}},listVirtualGoodCatalogs:async()=>{try{return(await t.get(N.Endpoints.VIRTUAL_GOOD_CATALOG)).data}catch(r){return pe(r),[]}},saveVirtualGoodCatalog:async r=>{try{return(await t.post(N.Endpoints.VIRTUAL_GOOD_CATALOG,r)).data}catch(i){throw new Error("Failed to save virtual good catalog: "+X(i))}},listVirtualGoodItems:async()=>{try{return(await t.get(N.Endpoints.VIRTUAL_GOOD_ITEM)).data}catch(r){return pe(r),[]}},saveVirtualGoodItem:async r=>{try{return(await t.post(N.Endpoints.VIRTUAL_GOOD_ITEM,r)).data}catch(i){throw new Error("Failed to save virtual good item: "+X(i))}},deleteVirtualGoodCatalog:async r=>{try{return await t.delete(`${N.Endpoints.VIRTUAL_GOOD_CATALOG}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete virtual good catalog: "+X(i))}},deleteVirtualGoodItem:async r=>{try{return await t.delete(`${N.Endpoints.VIRTUAL_GOOD_ITEM}/${r}`),{success:!0}}catch(i){throw new Error("Failed to delete virtual good item: "+X(i))}},getGamification:async r=>{try{return(await t.get(N.Endpoints.GAMIFICATION(r))).data}catch(i){if(i.response?.data)return i.response.data;throw pe(i),i}},listRoles:async()=>{try{return(await t.post(N.Endpoints.ROLE_AGGREGATE,[])).data}catch(r){return pe(r),[]}},listRolesStrict:async()=>{try{return(await t.post(N.Endpoints.ROLE_AGGREGATE,[])).data}catch(r){throw new Error("Failed to list roles: "+X(r))}},getRoleById:async r=>{try{return(await t.get(N.Endpoints.ROLE_BY_ID(r))).data}catch(i){pe(i);return}},saveRole:async r=>{try{return(await t.post(N.Endpoints.ROLE,r)).data}catch(i){throw new Error("Failed to save role: "+X(i))}},deleteRole:async r=>{try{return(await t.delete(N.Endpoints.ROLE_BY_ID(r))).data}catch(i){throw new Error("Failed to delete role: "+X(i))}},assignRole:async r=>{try{return(await t.post(N.Endpoints.ROLE_ASSIGN,r)).data}catch(i){throw new Error("Failed to assign role: "+X(i))}},unassignRole:async r=>{try{return(await t.delete(N.Endpoints.ROLE_ASSIGN,{data:r})).data}catch(i){throw new Error("Failed to unassign role: "+X(i))}},listRoleAssignments:async r=>{try{let i={};return r&&(i.item=r),(await t.get(N.Endpoints.ROLE_ASSIGN,{params:i})).data}catch(i){return pe(i),[]}},listRoleAssignmentsStrict:async r=>{try{let i={};return r&&(i.item=r),(await t.get(N.Endpoints.ROLE_ASSIGN,{params:i})).data}catch(i){throw new Error("Failed to list role assignments: "+X(i))}}}}});var _O=x(ju=>{"use strict";var yO=ju&&ju.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(ju,"__esModule",{value:!0});ju.resolveConfig=Jee;var bO=yO(require("fs")),Kee=yO(require("path"));function Jee(e){let t=e||Kee.default.join(process.cwd(),"funifier.json");if(bO.default.existsSync(t)){let a=bO.default.readFileSync(t,"utf-8"),o=JSON.parse(a);if(o.apiKey&&o.secretKey&&o.serverUrl)return{apiKey:o.apiKey,secretKey:o.secretKey,serverUrl:o.serverUrl};throw new Error(`funifier.json at ${t} is missing required fields (apiKey, secretKey, serverUrl)`)}let r=process.env.FUNIFIER_API_KEY,i=process.env.FUNIFIER_SECRET_KEY,n=process.env.FUNIFIER_SERVER_URL;if(r&&i&&n)return{apiKey:r,secretKey:i,serverUrl:n};throw new Error("Funifier config not found. Provide funifier.json in the working directory or set FUNIFIER_API_KEY, FUNIFIER_SECRET_KEY, and FUNIFIER_SERVER_URL environment variables.")}});var SO=x(wO=>{"use strict";Object.defineProperty(wO,"__esModule",{value:!0})});var $O=x(DO=>{"use strict";Object.defineProperty(DO,"__esModule",{value:!0})});var OO=x(EO=>{"use strict";Object.defineProperty(EO,"__esModule",{value:!0})});var jO=x(PO=>{"use strict";Object.defineProperty(PO,"__esModule",{value:!0})});var IO=x(TO=>{"use strict";Object.defineProperty(TO,"__esModule",{value:!0})});var CO=x(kO=>{"use strict";Object.defineProperty(kO,"__esModule",{value:!0})});var AO=x(RO=>{"use strict";Object.defineProperty(RO,"__esModule",{value:!0})});var MO=x(NO=>{"use strict";Object.defineProperty(NO,"__esModule",{value:!0})});var ZO=x(FO=>{"use strict";Object.defineProperty(FO,"__esModule",{value:!0})});var qO=x(zO=>{"use strict";Object.defineProperty(zO,"__esModule",{value:!0})});var LO=x(UO=>{"use strict";Object.defineProperty(UO,"__esModule",{value:!0})});var VO=x(BO=>{"use strict";Object.defineProperty(BO,"__esModule",{value:!0})});var HO=x(GO=>{"use strict";Object.defineProperty(GO,"__esModule",{value:!0})});var JO=x(KO=>{"use strict";Object.defineProperty(KO,"__esModule",{value:!0})});var YO=x(WO=>{"use strict";Object.defineProperty(WO,"__esModule",{value:!0})});var QO=x(XO=>{"use strict";Object.defineProperty(XO,"__esModule",{value:!0})});var tP=x(eP=>{"use strict";Object.defineProperty(eP,"__esModule",{value:!0})});var nP=x(rP=>{"use strict";Object.defineProperty(rP,"__esModule",{value:!0})});var aP=x(iP=>{"use strict";Object.defineProperty(iP,"__esModule",{value:!0})});var sP=x(oP=>{"use strict";Object.defineProperty(oP,"__esModule",{value:!0})});var uP=x(cP=>{"use strict";Object.defineProperty(cP,"__esModule",{value:!0})});var dP=x(lP=>{"use strict";Object.defineProperty(lP,"__esModule",{value:!0})});var fP=x(pP=>{"use strict";Object.defineProperty(pP,"__esModule",{value:!0})});var mP=x(He=>{"use strict";var Wee=He&&He.__createBinding||(Object.create?function(e,t,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(t,r);(!n||("get"in n?!t.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,n)}:function(e,t,r,i){i===void 0&&(i=r),e[i]=t[r]}),lt=He&&He.__exportStar||function(e,t){for(var r in e)r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r)&&Wee(t,e,r)};Object.defineProperty(He,"__esModule",{value:!0});lt(SO(),He);lt($O(),He);lt(OO(),He);lt(jO(),He);lt(IO(),He);lt(CO(),He);lt(AO(),He);lt(MO(),He);lt(ZO(),He);lt(qO(),He);lt(LO(),He);lt(VO(),He);lt(HO(),He);lt(JO(),He);lt(YO(),He);lt(QO(),He);lt(tP(),He);lt(nP(),He);lt(aP(),He);lt(sP(),He);lt(uP(),He);lt(dP(),He);lt(fP(),He)});var gP=x(pr=>{"use strict";var Yee=pr&&pr.__createBinding||(Object.create?function(e,t,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(t,r);(!n||("get"in n?!t.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,n)}:function(e,t,r,i){i===void 0&&(i=r),e[i]=t[r]}),Xee=pr&&pr.__exportStar||function(e,t){for(var r in e)r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r)&&Yee(t,e,r)};Object.defineProperty(pr,"__esModule",{value:!0});pr.Endpoints=pr.API=pr.resolveConfig=pr.createAPIClient=void 0;var Qee=vO();Object.defineProperty(pr,"createAPIClient",{enumerable:!0,get:function(){return Qee.createAPIClient}});var ete=_O();Object.defineProperty(pr,"resolveConfig",{enumerable:!0,get:function(){return ete.resolveConfig}});var hP=rf();Object.defineProperty(pr,"API",{enumerable:!0,get:function(){return hP.API}});Object.defineProperty(pr,"Endpoints",{enumerable:!0,get:function(){return hP.Endpoints}});Xee(mP(),pr)});var vP=x(af=>{"use strict";Object.defineProperty(af,"__esModule",{value:!0});af.ApiHolder=void 0;var xP=gP(),Iv=class{constructor(){this.client=null,this.currentConfig=null,this.connectionName=null}tryAutoConnect(){try{let t=(0,xP.resolveConfig)();return this.connect(t),!0}catch{return!1}}connect(t,r){this.client=(0,xP.createAPIClient)(t),this.currentConfig=t,this.connectionName=r||t.serverUrl}getClient(){return this.client}requireClient(){if(!this.client)throw new Error("Not connected to any Funifier instance. Use the funifier_connect tool first with your apiKey, secretKey, and serverUrl.");return this.client}getConnectionInfo(){return{connected:this.client!==null,serverUrl:this.currentConfig?.serverUrl||null,name:this.connectionName}}disconnect(){this.client=null,this.currentConfig=null,this.connectionName=null}};af.ApiHolder=Iv});var kv=x((Cde,tte)=>{tte.exports={name:"funifier-mcp",version:"0.3.21",description:"Funifier AI toolkit \u2014 MCP server, API client, and Claude Code skills for the Funifier gamification platform",main:"dist/index.js",types:"dist/index.d.ts",bin:{"funifier-mcp":"dist/mcp/index.js"},files:["dist","skills","doc","datasource-funifier-docs","AGENTS.md",".github/copilot-instructions.md",".cursor/rules/funifier.mdc","README.md","CHANGELOG.md","LICENSE"],repository:{type:"git",url:"git+https://github.com/funifierinc/funifier-mcp.git"},bugs:{url:"https://github.com/funifierinc/funifier-mcp/issues"},homepage:"https://github.com/funifierinc/funifier-mcp#readme",author:"Funifier",publishConfig:{access:"public"},scripts:{build:"tsc",bundle:"npm run build && esbuild dist/mcp/index.js --bundle --outfile=dist/mcp/bundle.js --format=cjs --platform=node --minify",dev:"tsc --watch",prepublishOnly:"npm run build:skills && npm run bundle",test:"vitest run","test:watch":"vitest watch","build:skills":"tsx scripts/build-skills.ts","build:skills:force":"tsx scripts/build-skills.ts --force","search:docs":"tsx scripts/search-docs.ts","validate:skills":"tsx scripts/validate-skills.ts","enrich:skills":"tsx scripts/enrich-skills.ts","generate:skills":"tsx scripts/generate-skills.ts","dev:init":"npm run build && node scripts/dev-init.js"},keywords:["funifier","gamification","mcp","model-context-protocol","claude","ai","api-client"],license:"MIT",dependencies:{"@inquirer/prompts":"^7.10.1","@modelcontextprotocol/sdk":"^1.0.0",axios:"^1.6.0",zod:"^3.25.76"},devDependencies:{"@anthropic-ai/sdk":"^0.96.0","@types/node":"^25.5.0",esbuild:"^0.20.0",tsx:"^4.21.0",typescript:"^5.3.0",vitest:"^1.0.0"},engines:{node:">=18"}}});var Rv=x(Oa=>{"use strict";Object.defineProperty(Oa,"__esModule",{value:!0});Oa.isMajorUpdate=_P;Oa.setUpdateNotice=wP;Oa.consumeUpdateNotice=rte;Oa.formatUpdateNotice=SP;Oa.checkForUpdate=nte;Oa.isOutdated=yP;function of(e){return e.replace(/[^0-9.]/g,"").split(".").map(Number)}function yP(e,t){let[r,i,n]=of(e),[a,o,s]=of(t);return a!==r?a>r:o!==i?o>i:s>n}function _P(e,t){let[r,i]=of(e),[n,a]=of(t);return n!==r?!0:r===0&&a!==i}var Cv=null;function wP(e){Cv=e}function rte(){let e=Cv;return Cv=null,e}var bP="https://github.com/funifierinc/funifier-mcp/blob/main/CHANGELOG.md";function SP(e,t){let r=_P(e,t),i=r?`\u2B06 funifier-mcp: nova vers\xE3o com MUDAN\xC7AS INCOMPAT\xCDVEIS dispon\xEDvel (${e} \u2192 ${t}).`:`\u2B06 funifier-mcp: nova vers\xE3o dispon\xEDvel (${e} \u2192 ${t}).`,n=r?`[assistant instruction] Before continuing, tell the user \u2014 in one or two short sentences, in the language they are using \u2014 that funifier-mcp ${t} is available and likely contains BREAKING CHANGES, so they should review the changelog (${bP}) before updating with \`npx funifier-mcp@latest init\`. Relay only these facts, do not speculate about what changed, then continue with their task.`:"[assistant instruction] Before continuing, tell the user \u2014 in one short sentence, in the language they are using \u2014 that a newer version of funifier-mcp is available and that they should run `npx funifier-mcp@latest init` to update (changelog: "+bP+"). One line only, do not speculate about what changed, then continue with their task.";return[i,"",n].join(`
|
|
66
66
|
`)}async function nte(){let{version:e}=kv(),t;try{let i=await fetch("https://registry.npmjs.org/funifier-mcp/latest",{signal:AbortSignal.timeout(3e3)});if(!i.ok)return;t=(await i.json()).version}catch{return}if(!yP(e,t))return;let r=SP(e,t);wP(r),console.error(r)}});var DP=x(Av=>{"use strict";Object.defineProperty(Av,"__esModule",{value:!0});Av.registerConnectTool=ite;var sf=Zt();function ite(e,t){e.registerTool("funifier_connect",{title:"Connect to Funifier",description:"Connect to a Funifier gamification instance. Required before using other tools if no funifier.json or env vars are configured. Can also be used to switch between different instances during a session.",inputSchema:{apiKey:sf.z.string().describe("The Funifier API key"),secretKey:sf.z.string().describe("The Funifier secret key"),serverUrl:sf.z.string().describe("The Funifier server URL (e.g., 'https://example.funifier.com')"),name:sf.z.string().optional().describe("Optional friendly name for this connection (e.g., 'production', 'staging')")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},async({apiKey:r,secretKey:i,serverUrl:n,name:a})=>{try{t.connect({apiKey:r,secretKey:i,serverUrl:n},a);let s=await t.requireClient().getCollections();return{content:[{type:"text",text:`Connected to Funifier: ${a||n}
|
|
67
67
|
Server: ${n}
|
|
68
68
|
Collections available: ${s.length}
|
package/package.json
CHANGED
package/skills/funifier/SKILL.md
CHANGED
|
@@ -70,6 +70,7 @@ Then read a result with `funifier_read_doc path=<path>`.
|
|
|
70
70
|
| Upload files to Funifier — images and documents for player avatars, challenge resources, and visual assets; use when adding media to the platform, not for CSV data import (use funifier-import-csv) or static frontend hosting (use funifier-implement-frontend) | `references/upload-file.md` |
|
|
71
71
|
| Create, list, and drop MongoDB single-field indexes on Funifier collections via the REST API. Composite (multi-field) indexes are NOT supported by this endpoint — see Limitation section. | `references/manage-indexes.md` |
|
|
72
72
|
| Cross-check a project's Funifier API calls against the live security document — scan code for usage, build an evidence-backed manifest, run the deterministic audit engine, and report missing scopes, excess tokens, and static danger findings; use when debugging 401s, auditing minimum privilege, or verifying permissions before deploying; audit is read-only and never changes any configuration | `references/audit-permissions.md` |
|
|
73
|
+
| Use the server-side utility classes from com.funifier.engine.util in Groovy triggers, schedulers, and public endpoints — validates CPF, encrypts fields with AES/BCrypt/PGP, renders Mustache templates, evaluates inline expressions, computes object diffs/changelogs, converts JSON, generates Excel, makes HTTP calls, and handles files and pagination | `references/server-utils.md` |
|
|
73
74
|
|
|
74
75
|
## Documented Modules
|
|
75
76
|
|
|
@@ -79,9 +79,3 @@ Baseado na tabela acima, instrua o usuário a usar a skill específica.
|
|
|
79
79
|
### 4. Se não encontrar skill específica
|
|
80
80
|
|
|
81
81
|
Consulte `funifier_read_doc path=index` e leia o módulo relevante diretamente.
|
|
82
|
-
|
|
83
|
-
## Verified References
|
|
84
|
-
|
|
85
|
-
| Claim | Status | Evidence |
|
|
86
|
-
|-------|--------|----------|
|
|
87
|
-
| Achievement is the core entity class representing all gamification rewards in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/achievement/Achievement.java:Achievement |
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# funifier-server-utils
|
|
2
|
+
|
|
3
|
+
Use the server-side utility classes from com.funifier.engine.util in Groovy triggers, schedulers, and public endpoints — validates CPF, encrypts fields with AES/BCrypt/PGP, renders Mustache templates, evaluates inline expressions, computes object diffs/changelogs, converts JSON, generates Excel, makes HTTP calls, and handles files and pagination
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Formato do payload (obrigatório)
|
|
8
|
+
|
|
9
|
+
Funifier armazena código como **strings JSON escapadas**. Ao montar o payload do `funifier_save`:
|
|
10
|
+
|
|
11
|
+
- **Quebra de linha** → `\n` (nunca newline literal dentro da string)
|
|
12
|
+
- **Aspas duplas** dentro do código → `\"`
|
|
13
|
+
- **Backslash** → `\\` (regex `\b` vira `\\b`; dentro de Groovy com string-building pode exigir `\\\\b`)
|
|
14
|
+
- **Tab** → `\t` (se usar)
|
|
15
|
+
- **Pipelines de aggregate** vão como **string JSON** (não objeto aninhado) — serialize o array inteiro
|
|
16
|
+
|
|
17
|
+
A regra prática: monte o objeto em JavaScript normalmente e passe por `JSON.stringify` — o MCP faz isso automaticamente quando você entrega o payload como JSON. **Nunca** cole código multilinha cru no meio do JSON.
|
|
18
|
+
|
|
19
|
+
### Exemplo 1 — custom-page (html + angularjs script)
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"title": "Ciclos",
|
|
24
|
+
"slug": "studio/custom/ciclos",
|
|
25
|
+
"html": "<div class=\"row\">\n <div class=\"col-md-12\">\n <h2>Ciclos</h2>\n </div>\n</div>\n",
|
|
26
|
+
"script": "$scope.all = [];\n$scope.loading = false;\n\n$scope.list = function () {\n $scope.loading = true;\n};\n$scope.list();\n"
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Exemplo 2 — aggregate preparado (pipeline JSON + script Groovy)
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"_id": "extrato",
|
|
35
|
+
"title": "Extrato de Pontos",
|
|
36
|
+
"collection": "extrato",
|
|
37
|
+
"aggregate": "[\n {\n \"$match\": { \"player\": \"$param:player\" }\n },\n {\n \"$sort\": { \"time\": -1 }\n }\n]",
|
|
38
|
+
"script": "void prepare(aggregations, params) {\n if (context.get(\"player\") != null) {\n params.put(\"player\", context.get(\"player\"));\n } else {\n params.put(\"player\", \"NAO_EXISTE\");\n }\n}\n"
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Note que `aggregate` é uma **string** contendo JSON serializado (com `\n` e `\"` escapados), **não** um array nativo. Mesma regra vale para `script` em triggers/schedulers/aggregates e `html`/`script` em custom-pages.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Before starting — find relevant docs
|
|
47
|
+
|
|
48
|
+
Use the `funifier_search_docs` MCP tool to load only what you need:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
funifier_search_docs "cpf cnpj validar validate cpf-util aes encrypt decrypt criptografar criptografia bcrypt hash senha password pgp pgpcrypt rsa asymmetric totp otp 2fa qrcode google-authenticator mustache template render handlebars expression inline formula avaliar diff changelog auditoria comparar compare json serialize deserialize jsonutil excel xlsx spreadsheet planilha relatorio currency moeda formatar format http get post requisicao external url read-url pagination paginar paginacao paginate file stream arquivo util helper utility server-side groovy"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then read the most relevant results with `funifier_read_doc path=<path>`.
|
|
55
|
+
|
|
56
|
+
## Primary docs for this skill
|
|
57
|
+
|
|
58
|
+
If search returns insufficient results, read these directly:
|
|
59
|
+
|
|
60
|
+
- `funifier_read_doc path=guides/server-utils`
|
|
61
|
+
- `funifier_read_doc path=guides/triggers-guide`
|
|
62
|
+
- `funifier_read_doc path=guides/java-managers`
|
|
63
|
+
|
|
64
|
+
## Steps
|
|
65
|
+
|
|
66
|
+
### 1. Understand the requirement
|
|
67
|
+
|
|
68
|
+
Ask the user what they want to create or accomplish. Gather:
|
|
69
|
+
- The name/title
|
|
70
|
+
- The purpose and behavior
|
|
71
|
+
- Any specific configuration or constraints
|
|
72
|
+
|
|
73
|
+
### 2. Search for relevant documentation
|
|
74
|
+
|
|
75
|
+
Run the lexical search (command shown above) and read the returned files.
|
|
76
|
+
|
|
77
|
+
### 3. Check existing resources (if MCP available)
|
|
78
|
+
|
|
79
|
+
Use `funifier_list` with the relevant type and a `search` parameter to see
|
|
80
|
+
if a similar resource already exists. Never list all resources without a search term.
|
|
81
|
+
|
|
82
|
+
### 4. Design and confirm
|
|
83
|
+
|
|
84
|
+
Based on the docs, outline the configuration to the user and confirm before saving.
|
|
85
|
+
|
|
86
|
+
### 5. Create or update
|
|
87
|
+
|
|
88
|
+
Use `funifier_save` with the appropriate type and a JSON payload to create or
|
|
89
|
+
update the resource. If MCP is unavailable, show the complete JSON for manual use.
|
|
90
|
+
|
|
91
|
+
### 6. Validate
|
|
92
|
+
|
|
93
|
+
Use `funifier_logs` (for triggers/schedulers) or `funifier_get` to confirm
|
|
94
|
+
the resource was saved correctly and executed without errors.
|