ec.fdk 0.9.4 → 0.9.5

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/README.md CHANGED
@@ -221,6 +221,7 @@ ec.fdk <command> [options]
221
221
  | `login` | Login via browser (OIDC). Use `--password` for email/password prompt. | — |
222
222
  | `logout` | Logout and remove stored token | — |
223
223
  | `whoami` | Show current logged-in user | — |
224
+ | `install-skill` | Install Claude Code skill | — (optional `--dir <path>`) |
224
225
  | `resourceList` | List any resource type | `--resource`, `-f` for query params |
225
226
  | `resourceGet` | Get a single resource | `--resource`, `-f` for identifying params |
226
227
  | `resourceEdit` | Edit a single resource | `--resource`, `-f` for identifying params, `--data` |
@@ -263,6 +264,7 @@ ec.fdk <command> [options]
263
264
  | `--sort <field>` | Sort field for list |
264
265
  | `-f, --filter <k=v>` | Filter for list (repeatable) |
265
266
  | `--password` | Use email/password login instead of browser OIDC |
267
+ | `--dir <path>` | Target directory for `install-skill` (default: `~/.claude`) |
266
268
  | `--raw` | Include `_links` and `_embedded` in output |
267
269
  | `--md` | Output entries as readable markdown table |
268
270
  | `-v, --version` | Show version |
@@ -303,6 +305,12 @@ ec.fdk logout -e stage
303
305
  # Show current user
304
306
  ec.fdk whoami -e stage
305
307
 
308
+ # Install Claude Code skill (to ~/.claude/skills/ec-fdk/)
309
+ ec.fdk install-skill
310
+
311
+ # Install to custom directory
312
+ ec.fdk install-skill --dir ~/entrecode/.claude
313
+
306
314
  # List datamanagers
307
315
  ec.fdk dmList -e stage
308
316
 
package/dist/cli.cjs CHANGED
@@ -1,18 +1,19 @@
1
1
  #!/usr/bin/env node
2
- "use strict";const fe=require("node:util"),ge=require("node:module"),E=require("node:fs"),Q=require("node:path"),me=require("node:os"),he=require("node:readline"),P=require("node:crypto"),pe=require("node:http"),ye=require("node:child_process");async function u(t,e={},n={}){const{token:r,rawRes:o}=e;r&&(n.headers={...n.headers||{},Authorization:`Bearer ${r}`});const a=await fetch(t,n);if(!a.ok){if(a.headers.get("content-type")?.includes("application/json")){const s=await a.json(),c=`${s.title}
2
+ "use strict";var he=Object.create;var H=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,we=Object.prototype.hasOwnProperty;var De=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ye(t))!we.call(e,o)&&o!==n&&H(e,o,{get:()=>t[o],enumerable:!(r=pe(t,o))||r.enumerable});return e};var U=(e,t,n)=>(n=e!=null?he(ke(e)):{},De(t||!e||!e.__esModule?H(n,"default",{value:e,enumerable:!0}):n,e));const Te=require("node:util"),be=require("node:module"),E=require("node:fs"),ee=require("node:path"),$e=require("node:os"),Ee=require("node:readline"),B=require("node:crypto"),ve=require("node:http"),Ie=require("node:child_process");async function l(e,t={},n={}){const{token:r,rawRes:o}=t;r&&(n.headers={...n.headers||{},Authorization:`Bearer ${r}`});const a=await fetch(e,n);if(!a.ok){if(a.headers.get("content-type")?.includes("application/json")){const s=await a.json(),c=`${s.title}
3
3
  ${s.detail}
4
- ${s.verbose}`;throw new Error(c)}throw new Error(`unexpected fetch error: ${a.statusText}`)}if(o)return a;if(a.status===204)return;const i=await a.text();return i?JSON.parse(i):void 0}const q={datamanager:{live:"https://datamanager.entrecode.de/",stage:"https://datamanager.cachena.entrecode.de/"},accounts:{live:"https://accounts.entrecode.de/",stage:"https://accounts.cachena.entrecode.de/"},appserver:{live:"https://appserver.entrecode.de/",stage:"https://appserver.cachena.entrecode.de/"},"dm-history":{live:"https://dm-history.entrecode.de/",stage:"https://dm-history.cachena.entrecode.de/"}};function g(t,e="stage",n="datamanager"){const r=q[n];if(!r)throw new Error(`subdomain "${n}" not found. Try one of ${Object.keys(q).join(", ")}`);const o=r[e];if(!o)throw new Error(`env "${e}" not found. Try one of ${Object.keys(r[e]).join(", ")}`);return o+t}function h(t,e=!0){return Object.entries(t).sort((n,r)=>n[0].localeCompare(r[0])).map(([n,r])=>`${n}=${r}`).join("&")}function d(t){Object.entries(t).forEach(([e,n])=>{if(n===void 0)throw new Error(`expected ${e} to be set!`)})}const Z={stage:"https://accounts.cachena.entrecode.de/",live:"https://accounts.entrecode.de/"};async function ke(t){let{env:e,dmShortID:n,email:r,password:o}=t;d({env:e,dmShortID:n,email:r,password:o});const a=g(`api/${n}/_auth/login?clientID=rest`,e);return await u(a,{},{method:"POST",body:JSON.stringify({email:r,password:o}),headers:{"Content-Type":"application/json"}})}async function we(t){let{env:e,email:n,password:r}=t;d({env:e,email:n,password:r});const o=`${Z[e]}auth/login?clientID=rest`;return await u(o,{},{method:"POST",body:JSON.stringify({email:n,password:r}),headers:{"Content-Type":"application/json"}})}async function De(t){let{dmShortID:e,env:n,token:r}=t;d({dmShortID:e,env:n,token:r});const o=g(`api/${e}/_auth/logout?clientID=rest&token=${r}`,n);return await u(o,{rawRes:!0},{method:"POST"})}async function Te(t){let{env:e,token:n}=t;d({env:e,token:n});const r=`${Z[e]}auth/logout?clientID=rest`;return await u(r,{rawRes:!0,token:n},{method:"POST"})}function be({dmShortID:t}){return d({dmShortID:t}),t}function $e({env:t}){return d({env:t}),t}let Ee=["created","creator","id","modified","private","_created","_creator","_embedded","_entryTitle","_id","_links","_modelTitle","_modelTitleField","_modified"];function ee(t){let e={};for(let n in t)Ee.includes(n)||(e[n]=t[n]);return e}function ve(t){return JSON.parse(JSON.stringify(t))}async function Ae(t){let{env:e,dmShortID:n}=t;d({env:e,dmShortID:n});const r=g(`api/${n}`,e);return u(r,t)}async function te(t){let{env:e,dmShortID:n,model:r,options:o={}}=t;d({env:e,dmShortID:n,model:r}),o={size:50,page:1,_list:!0,...o};const a=h(o),i=g(`api/${n}/${r}?${a}`,e),{count:s,total:c,_embedded:f}=await u(i,t);let m=f?f[`${n}:${r}`]:[];return m=Array.isArray(m)?m:[m],{count:s,total:c,items:m}}function Ie({env:t,dmShortID:e,model:n,entryID:r,token:o}){d({env:t,dmShortID:e,model:n,entryID:r});const a=h({_id:r}),i=g(`api/${e}/${n}?${a}`,t);return u(i,{token:o})}async function Se({env:t,dmShortID:e,model:n,value:r,token:o}){d({env:t,dmShortID:e,model:n,value:r});const a=g(`api/${e}/${n}`,t);return await u(a,{token:o},{method:"POST",body:JSON.stringify(r),headers:{"Content-Type":"application/json"}})}async function ne({env:t,dmShortID:e,model:n,entryID:r,value:o,token:a,safePut:i=!1}){d({env:t,dmShortID:e,model:n,entryID:r,value:o});const s={"Content-Type":"application/json"};if(i){if(!("_modified"in o))throw new Error("expected _modified to be set!");s["If-Unmodified-Since"]=new Date(o._modified).toUTCString()}const c=g(`api/${e}/${n}?_id=${r}`,t);return o=ve(o),o=ee(o),await u(c,{token:a},{method:"PUT",headers:s,body:JSON.stringify(o)})}function re({env:t,dmShortID:e,model:n,entryID:r,token:o}){d({env:t,dmShortID:e,model:n,entryID:r});const a=g(`api/${e}/${n}?_id=${r}`,t);return u(a,{token:o,rawRes:!0},{method:"DELETE",headers:{"Content-Type":"application/json"}})}async function _e(t,e){let{env:n,dmShortID:r,model:o,options:a={}}=t;d({env:n,dmShortID:r,model:o}),t.options={size:50,page:1,_list:!0,...a};let i=0,s,c=[];for(;s===void 0||i<s;){const f=await te(t);for(let m of f.items)c.push(await e(m));i+=f.items.length,s=f.total,t.options.page++}return c}async function qe({env:t,dmShortID:e,model:n,withMetadata:r}){d({env:t,dmShortID:e,model:n});const o=g(`api/schema/${e}/${n}`,t),a=await u(o),i=a?.allOf?.[1];if(typeof i.properties!="object")throw new Error(`getSchema: ${o} returned unexpected format: ${JSON.stringify(a)}`);const{properties:s}=i,c=ee(s);for(let f in c){let m=c[f];if(m.required=i.required.includes(f),c[f]?.oneOf&&delete c[f]?.oneOf,m.title?.includes("<")&&m.title?.includes(">")){const k=m.title.split("<")[1].slice(0,-1),w=m.title.split("<")[0];m.type=w,k.includes(":")?m.resource=k.split(":")[1]:m.resource=k}else["asset","entry","assets","entries"].includes(m.title)?(m.type=m.title,m.resource=null):m.type=m.title;delete c[f].title}if(r){const f=s._modelTitle.title,m=s._modelTitleField.title;return{properties:c,meta:{modelTitleField:m,modelTitle:f}}}return c}function oe(t){return Object.entries(t).map(([e,n])=>typeof n!="object"?{[e]:String(n)}:{...n.sort&&{sort:Array.isArray(n)?n.join(","):n},...n.search&&{[e+"~"]:n.search},...n.notNull&&{[e+"!"]:""},...n.null&&{[e]:""},...n.any&&{[e]:n.any.join(",")},...n.from&&{[e+"From"]:n.from},...n.to&&{[e+"To"]:n.to}}).reduce((e,n)=>({...e,...n}),{})}const Oe=oe;function B(t){return t._links.collection.href.split("/").slice(-2)[0]}function ae(t){const e=t._links.collection.href.split("api/")[0];return Object.keys(q.datamanager).find(r=>q.datamanager[r]===e)}const se=t=>{const e=B(t),n=ae(t),r=t._modelTitle,o=t.id;return{dmShortID:e,env:n,model:r,entryID:o}},Ce=t=>re(se(t)),Ue=(t,e)=>ne({...se(t),value:e});function Me(t,e){const n=B(e);return e._embedded[`${n}:${e._modelTitle}/${t}/asset`]}async function Le({env:t,dmShortID:e,assetGroup:n,assetID:r,token:o}){d({env:t,dmShortID:e,assetGroup:n,assetID:r});const a=h({assetID:r}),i=g(`a/${e}/${n}?${a}`,t),{_embedded:s}=await u(i,{token:o});return s?s["ec:dm-asset"]:void 0}async function Re(t){let{env:e,dmShortID:n,assetGroup:r,token:o,options:a={}}=t;d({env:e,dmShortID:n,assetGroup:r}),a={size:50,page:1,_list:!0,...a};const i=h(a),s=g(`a/${n}/${r}?${i}`,e),{count:c,total:f,_embedded:m}=await u(s,{token:o});let k=m?m["ec:dm-asset"]:[];return k=Array.isArray(k)?k:[k],{count:c,total:f,items:k}}async function Pe({env:t,dmShortID:e,assetGroup:n,token:r,file:o,name:a,options:i}){d({env:t,dmShortID:e,assetGroup:n,file:o});const s=g(`a/${e}/${n}`,t),c=new FormData;return c.append("file",o,a),i&&Object.keys(i).forEach(m=>{c.append(m,i[m])}),(await u(s,{token:r},{method:"POST",body:c}))._embedded["ec:dm-asset"]}async function Be({env:t,dmShortID:e,assetGroup:n,files:r,options:o}){d({env:t,dmShortID:e,assetGroup:n,files:r});const a=g(`a/${e}/${n}`,t),i=new FormData;r.forEach(c=>{i.append("file",c)}),o&&Object.keys(o).forEach(c=>{i.append(c,o[c])});const s=await u(a,{},{method:"POST",body:i});return Array.isArray(s._embedded["ec:dm-asset"])?s._embedded["ec:dm-asset"]:[s._embedded["ec:dm-asset"]]}async function Ge({env:t,dmShortID:e,assetGroup:n,assetID:r,token:o}){d({env:t,dmShortID:e,assetGroup:n,assetID:r});const a=g(`a/${e}/${n}/${r}`,t);await u(a,{token:o,rawRes:!0},{method:"DELETE"})}function Ne(t,e,n=!1){let r,o;return(n?t?.thumbnails:t?.fileVariants)?.forEach(i=>{const{resolution:{width:s,height:c}}=i,f=Math.abs(Math.max(s,c)-e);(!o||f<o)&&(o=f,r=i)}),r?.url??t?.file?.url??null}function xe(t="stage",e,n,r,o=!1){const a=Math.max(r.file.resolution.width,r.file.resolution.height),i=n.filter(c=>c<a),s=`https://datamanager${t==="stage"?".cachena":""}.entrecode.de`;return o?i.map(c=>{const f=r.thumbnails.find(w=>c===w.dimension),m=`${s}/t/${e}/${r.assetID}/${c}`,k=f?f.url:m;return{size:c,url:k,generated:f}}):i.map(c=>{const f=r.fileVariants.find(w=>c===Math.max(w.resolution.width,w.resolution.height)),m=`${s}/f/${e}/${r.assetID}/${c}`,k=f?f.url:m;return{size:c,url:k,generated:f}})}const p={"Content-Type":"application/json"};async function je(t){let{env:e,dmID:n,token:r}=t;d({env:e,dmID:n});const o=g(`?dataManagerID=${n}`,e);return u(o,{token:r})}async function Je(t){let{env:e,options:n={}}=t;d({env:e}),n={size:25,page:1,_list:!0,...n};const r=h(n),o=g(`?${r}`,e),{count:a,total:i,_embedded:s}=await u(o,t);let c=s?s["ec:datamanager"]:[];return c=Array.isArray(c)?c:[c],{count:a,total:i,items:c}}async function Fe(t){let{env:e,dmID:n,options:r={}}=t;d({env:e,dmID:n}),r={size:25,dataManagerID:n,page:1,_list:!0,...r};const o=h(r),a=g(`model?${o}`,e),{count:i,total:s,_embedded:c}=await u(a,t);let f=c?c["ec:model"]:[];return f=Array.isArray(f)?f:[f],{count:i,total:s,items:f}}async function He(t){let{env:e,resource:n,options:r={},subdomain:o="datamanager"}=t;d({env:e,subdomain:o,resource:n}),r={size:25,page:1,_list:!0,...r};const a=h(r),i=g(`${n}?${a}`,e,o),{count:s,total:c,_embedded:f}=await u(i,t);let m=f?f[Object.keys(f)[0]]:[];return m=Array.isArray(m)?m:[m],{count:s,total:c,items:m}}async function ze(t){let{env:e,resource:n,options:r={},subdomain:o="datamanager"}=t;d({env:e,subdomain:o,resource:n});const a=h(r),i=g(`${n}?${a}`,e,o);return u(i,t)}async function Ke(t){let{env:e,resource:n,options:r={},subdomain:o="datamanager",value:a}=t;d({env:e,subdomain:o,resource:n,value:a});const i=h(r),s=g(`${n}?${i}`,e,o);return u(s,t,{method:"PUT",body:JSON.stringify(a),headers:p})}async function Ve(t){let{env:e,resource:n,options:r={},subdomain:o="datamanager"}=t;d({env:e,subdomain:o,resource:n});const a=h(r),i=g(`${n}?${a}`,e,o);return u(i,{...t,rawRes:!0},{method:"DELETE",headers:p})}async function Ye(t,e={}){let{env:n,route:r,options:o={},subdomain:a="datamanager"}=t;d({env:n,subdomain:a,route:r}),o={...o};const i=h(o),s=g(`${r}?${i}`,n,a);return u(s,t,e)}async function We(t){let{env:e,token:n,value:r}=t;d({env:e,value:r});const o=g("",e);return u(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function Xe(t){let{env:e,token:n,dmID:r,value:o}=t;d({env:e,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`?${a}`,e);return u(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function Qe(t){let{env:e,token:n,dmID:r}=t;d({env:e,dmID:r});const o=h({dataManagerID:r}),a=g(`?${o}`,e);return u(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function Ze(t){let{env:e,token:n,dmID:r,value:o}=t;d({env:e,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`model?${a}`,e);return u(i,{token:n},{method:"POST",body:JSON.stringify(o),headers:p})}async function et(t){let{env:e,token:n,dmID:r,modelID:o,value:a}=t;d({env:e,dmID:r,modelID:o,value:a});const i=h({dataManagerID:r,modelID:o}),s=g(`model?${i}`,e);return u(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function tt(t){let{env:e,token:n,dmID:r,modelID:o}=t;d({env:e,dmID:r,modelID:o});const a=h({dataManagerID:r,modelID:o}),i=g(`model?${a}`,e);return u(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function nt(t){let{env:e,token:n,value:r}=t;d({env:e,value:r});const o=g("template",e);return u(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function rt(t){let{env:e,token:n,dmID:r,value:o}=t;d({env:e,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`assetgroup?${a}`,e);return u(i,{token:n},{method:"POST",body:JSON.stringify(o),headers:p})}async function ot(t){let{env:e,token:n,dmID:r,assetGroupID:o,value:a}=t;d({env:e,dmID:r,assetGroupID:o,value:a});const i=h({dataManagerID:r,assetGroupID:o}),s=g(`assetgroup?${i}`,e);return u(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function at(t){let{env:e,token:n,dmShortID:r,assetGroup:o,assetID:a,value:i}=t;d({env:e,dmShortID:r,assetGroup:o,assetID:a,value:i});const s=g(`a/${r}/${o}/${a}`,e);return u(s,{token:n},{method:"PUT",body:JSON.stringify(i),headers:p})}async function st(t){let{env:e,token:n,dmID:r,clientID:o,value:a}=t;d({env:e,dmID:r,clientID:o,value:a});const i=h({dataManagerID:r,clientID:o}),s=g(`client?${i}`,e);return u(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function it(t){let{env:e,token:n,dmID:r,value:o}=t;d({env:e,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`role?${a}`,e);return u(i,{token:n},{method:"POST",body:JSON.stringify(o),headers:p})}async function ct(t){let{env:e,token:n,dmID:r,roleID:o,value:a}=t;d({env:e,dmID:r,roleID:o,value:a});const i=h({dataManagerID:r,roleID:o}),s=g(`role?${i}`,e);return u(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function dt(t){let{env:e,token:n,dmID:r,roleID:o}=t;d({env:e,dmID:r,roleID:o});const a=h({dataManagerID:r,roleID:o}),i=g(`role?${a}`,e);return u(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function ut(t){let{env:e,token:n,dmID:r,accountID:o,value:a}=t;d({env:e,dmID:r,accountID:o,value:a});const i=h({dataManagerID:r,accountID:o}),s=g(`account?${i}`,e);return u(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function lt(t){let{env:e,token:n,dmID:r,accountID:o}=t;d({env:e,dmID:r,accountID:o});const a=h({dataManagerID:r,accountID:o}),i=g(`account?${a}`,e);return u(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function ft(t){let{env:e,token:n,options:r={}}=t;d({env:e});const o=h(r),a=g(`stats?${o}`,e);return u(a,{token:n})}async function gt(t){let{env:e,token:n,options:r={}}=t;d({env:e});const o=h(r),a=g(`entries?${o}`,e,"dm-history");return u(a,{token:n})}async function mt(t){let{env:e,token:n,value:r}=t;d({env:e,value:r});const o=g("client",e,"accounts");return u(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function ht(t){let{env:e,token:n,clientID:r,value:o}=t;d({env:e,clientID:r,value:o});const a=h({clientID:r}),i=g(`client?${a}`,e,"accounts");return u(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function pt(t){let{env:e,token:n,clientID:r}=t;d({env:e,clientID:r});const o=h({clientID:r}),a=g(`client?${o}`,e,"accounts");return u(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function yt(t){let{env:e,token:n,value:r}=t;d({env:e,value:r});const o=g("group",e,"accounts");return u(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function kt(t){let{env:e,token:n,groupID:r,value:o}=t;d({env:e,groupID:r,value:o});const a=h({groupID:r}),i=g(`group?${a}`,e,"accounts");return u(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function wt(t){let{env:e,token:n,groupID:r}=t;d({env:e,groupID:r});const o=h({groupID:r}),a=g(`group?${o}`,e,"accounts");return u(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function Dt(t){let{env:e,token:n,value:r}=t;d({env:e,value:r});const o=g("invite",e,"accounts"),a=await u(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p});return a?._embedded?.["ec:invite"]??a}async function Tt(t){let{env:e,token:n,inviteID:r,value:o}=t;d({env:e,inviteID:r,value:o});const a=h({invite:r}),i=g(`invite?${a}`,e,"accounts");return u(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function bt(t){let{env:e,token:n,inviteID:r}=t;d({env:e,inviteID:r});const o=h({invite:r}),a=g(`invite?${o}`,e,"accounts");return u(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function $t(t){let{env:e,token:n,accountID:r,value:o}=t;d({env:e,accountID:r,value:o});const a=h({accountID:r}),i=g(`account?${a}`,e,"accounts");return u(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function Et(t){let{env:e,token:n,accountID:r}=t;d({env:e,accountID:r});const o=h({accountID:r}),a=g(`account/tokens?${o}`,e,"accounts");let s=(await u(a,{token:n}))?._embedded?.["ec:account/token"]??[];return Array.isArray(s)?s:[s]}async function vt(t){let{env:e,token:n,accountID:r}=t;d({env:e,accountID:r});const o=h({accountID:r}),a=g(`account/tokens?${o}`,e,"accounts");return u(a,{token:n},{method:"POST",headers:p})}async function At(t){let{env:e,token:n,accountID:r,accessTokenID:o}=t;d({env:e,accountID:r,accessTokenID:o});const a=h({accessTokenID:o,accountID:r}),i=g(`account/tokens?${a}`,e,"accounts");return u(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}const It=Object.freeze(Object.defineProperty({__proto__:null,assetList:Re,createAccountClient:mt,createAsset:Pe,createAssetGroup:rt,createAssets:Be,createDatamanager:We,createEntry:Se,createGroup:yt,createInvite:Dt,createModel:Ze,createRole:it,createTemplate:nt,createToken:vt,deleteAccountClient:pt,deleteAsset:Ge,deleteDatamanager:Qe,deleteDmAccount:lt,deleteEntry:re,deleteEntryObject:Ce,deleteGroup:wt,deleteInvite:bt,deleteModel:tt,deleteRole:dt,deleteToken:At,dmList:Je,editAccount:$t,editAccountClient:ht,editAsset:at,editAssetGroup:ot,editDatamanager:Xe,editDmAccount:ut,editDmClient:st,editEntry:ne,editEntryObject:Ue,editGroup:kt,editInvite:Tt,editModel:et,editRole:ct,entryList:te,fileVariant:Ne,filterOptions:Oe,getAsset:Le,getDatamanager:je,getEcAuthKey:$e,getEntry:Ie,getEntryAsset:Me,getEntryEnv:ae,getEntryShortID:B,getFileVariants:xe,getHistory:gt,getPublicAuthKey:be,getSchema:qe,getStats:ft,listTokens:Et,loginEc:we,loginPublic:ke,logoutEc:Te,logoutPublic:De,mapEntries:_e,modelList:Fe,publicApi:Ae,raw:Ye,resourceDelete:Ve,resourceEdit:Ke,resourceGet:ze,resourceList:He,sdkOptions:oe},Symbol.toStringTag,{value:"Module"})),{entryList:F,mapEntries:St,getEntry:_t,getAsset:qt,assetList:H,createAsset:Ot,createAssets:Ct,deleteAsset:Ut,createEntry:Mt,editEntry:z,deleteEntry:Lt,getSchema:Rt,loginPublic:Pt,loginEc:Bt,logoutEc:Gt,logoutPublic:Nt,getEcAuthKey:b,getPublicAuthKey:A,dmList:xt,modelList:jt,publicApi:Jt,getDatamanager:Ft,resourceList:Ht,resourceGet:zt,resourceEdit:Kt,resourceDelete:Vt,raw:Yt,createDatamanager:Wt,editDatamanager:Xt,deleteDatamanager:Qt,createModel:Zt,editModel:en,deleteModel:tn,createTemplate:nn,createAssetGroup:rn,editAssetGroup:on,editAsset:an,editDmClient:sn,createRole:cn,editRole:dn,deleteRole:un,editDmAccount:ln,deleteDmAccount:fn,getStats:gn,getHistory:mn,createAccountClient:hn,editAccountClient:pn,deleteAccountClient:yn,createGroup:kn,editGroup:wn,deleteGroup:Dn,createInvite:Tn,editInvite:bn,deleteInvite:$n,editAccount:En,listTokens:vn,createToken:An,deleteToken:In}=It;function K(t){if(!t||typeof t!="object")return t;const{_links:e,_embedded:n,...r}=t;return r}function Sn(t){return!t||typeof t!="object"?t:Array.isArray(t.items)?{...t,items:t.items.map(K)}:K(t)}class G{constructor(e={}){if(!e.storageAdapter){let n=new Map;e.storageAdapter={get:r=>n.get(r),set:(r,o)=>n.set(r,o),remove:r=>n.delete(r)}}this.config=e}set(e){return new G({...this.config,...e})}async entries(e={}){const n=await this.getBestToken();return F({...this.config,options:e,token:n})}async entryList(e){const n=await this.getBestToken();return F({...this.config,options:e,token:n}).then(r=>this.maybeClean(r))}async mapEntries(e,n={}){const r=await this.getBestToken();return St({...this.config,options:n,token:r},e)}async getEntry(e){const n=await this.getBestToken();return _t({...this.config,entryID:e,token:n}).then(r=>this.maybeClean(r))}async editEntrySafe(e,n){const r=await this.getBestToken();return z({...this.config,entryID:e,token:r,value:n,safePut:!0}).then(o=>this.maybeClean(o))}async getSchema(){return Rt(this.config)}async assets(e){const n=await this.getBestToken();return H({...this.config,options:e,token:n})}async assetList(e){const n=await this.getBestToken();return H({...this.config,options:e,token:n})}async createAsset(e){const{file:n,name:r,options:o}=e,a=await this.getBestToken();return Ot({...this.config,file:n,name:r,options:o,token:a})}async createAssets(e){const{files:n,options:r}=e,o=await this.getBestToken();return Ct({...this.config,files:n,options:r,token:o})}async deleteAsset(e){const n=await this.getBestToken();return Ut({...this.config,token:n,assetID:e})}async getAsset(e){const n=await this.getBestToken();return qt({...this.config,assetID:e,token:n})}async createEntry(e){const n=await this.getBestToken();return Mt({...this.config,token:n,value:e}).then(r=>this.maybeClean(r))}async editEntry(e,n){const r=await this.getBestToken();return z({...this.config,entryID:e,token:r,value:n}).then(o=>this.maybeClean(o))}async deleteEntry(e){const n=await this.getBestToken();return Lt({...this.config,token:n,entryID:e})}async resourceList(e){const n=await this.getBestToken();return Ht({...this.config,options:e,token:n})}async resourceGet(e){const n=await this.getBestToken();return zt({...this.config,options:e,token:n})}async resourceEdit(e,n){const r=await this.getBestToken();return Kt({...this.config,options:e,token:r,value:n})}async resourceDelete(e){const n=await this.getBestToken();return Vt({...this.config,options:e,token:n})}async raw(e,n){const r=await this.getBestToken();return Yt({...this.config,options:e,token:r},n)}async createDatamanager(e){const n=await this.getBestToken();return Wt({...this.config,token:n,value:e})}async editDatamanager(e,n){const r=await this.getBestToken();return Xt({...this.config,token:r,dmID:e,value:n})}async deleteDatamanager(e){const n=await this.getBestToken();return Qt({...this.config,token:n,dmID:e})}async createModel(e){const n=await this.getBestToken();return Zt({...this.config,token:n,value:e})}async editModel(e,n){const r=await this.getBestToken();return en({...this.config,token:r,modelID:e,value:n})}async deleteModel(e){const n=await this.getBestToken();return tn({...this.config,token:n,modelID:e})}async createTemplate(e){const n=await this.getBestToken();return nn({...this.config,token:n,value:e})}async createAssetGroup(e){const n=await this.getBestToken();return rn({...this.config,token:n,value:e})}async editAssetGroup(e,n){const r=await this.getBestToken();return on({...this.config,token:r,assetGroupID:e,value:n})}async editAsset(e,n){const r=await this.getBestToken();return an({...this.config,token:r,assetID:e,value:n})}async editDmClient(e,n){const r=await this.getBestToken();return sn({...this.config,token:r,clientID:e,value:n})}async createRole(e){const n=await this.getBestToken();return cn({...this.config,token:n,value:e})}async editRole(e,n){const r=await this.getBestToken();return dn({...this.config,token:r,roleID:e,value:n})}async deleteRole(e){const n=await this.getBestToken();return un({...this.config,token:n,roleID:e})}async editDmAccount(e,n){const r=await this.getBestToken();return ln({...this.config,token:r,accountID:e,value:n})}async deleteDmAccount(e){const n=await this.getBestToken();return fn({...this.config,token:n,accountID:e})}async getStats(e={}){const n=await this.getBestToken();return gn({...this.config,token:n,options:e})}async getHistory(e={}){const n=await this.getBestToken();return mn({...this.config,token:n,options:e})}async createAccountClient(e){const n=await this.getBestToken();return hn({...this.config,token:n,value:e})}async editAccountClient(e,n){const r=await this.getBestToken();return pn({...this.config,token:r,clientID:e,value:n})}async deleteAccountClient(e){const n=await this.getBestToken();return yn({...this.config,token:n,clientID:e})}async createGroup(e){const n=await this.getBestToken();return kn({...this.config,token:n,value:e})}async editGroup(e,n){const r=await this.getBestToken();return wn({...this.config,token:r,groupID:e,value:n})}async deleteGroup(e){const n=await this.getBestToken();return Dn({...this.config,token:n,groupID:e})}async createInvite(e){const n=await this.getBestToken();return Tn({...this.config,token:n,value:e})}async editInvite(e,n){const r=await this.getBestToken();return bn({...this.config,token:r,inviteID:e,value:n})}async deleteInvite(e){const n=await this.getBestToken();return $n({...this.config,token:n,inviteID:e})}async editAccount(e,n){const r=await this.getBestToken();return En({...this.config,token:r,accountID:e,value:n})}async listTokens(e){const n=await this.getBestToken();return vn({...this.config,token:n,accountID:e})}async createToken(e){const n=await this.getBestToken();return An({...this.config,token:n,accountID:e})}async deleteToken(e,n){const r=await this.getBestToken();return In({...this.config,token:r,accountID:e,accessTokenID:n})}storageAdapter(e){return this.set({storageAdapter:e})}removeToken(e){if(!this.config.storageAdapter)throw new Error("cannot removeToken: no storageAdapter defined!");const{remove:n}=this.config.storageAdapter;n(e)}getToken(e){if(!this.config.storageAdapter)throw new Error("cannot getAuth: no storageAdapter defined!");const{get:n}=this.config.storageAdapter;return n(e)}getPublicToken(){return this.config.token||this.getToken(A(this.config))}getEcToken(){return this.config.token||this.getToken(b(this.config))}setToken(e,n){if(!this.config.storageAdapter)throw new Error("cannot setEcToken: no storageAdapter defined!");return this.config.storageAdapter.set(e,n)}setEcToken(e){this.setToken(b(this.config),e)}removeEcToken(){this.removeToken(b(this.config))}setPublicToken(e){this.setToken(A(this.config),e)}loginEc(e){return Bt({...this.config,...e}).then(n=>this.setToken(b(this.config),n.token))}loginPublic(e){return Pt({...this.config,...e}).then(n=>this.setToken(A(this.config),n.token))}logoutPublic(){const e=this.getPublicToken();return Nt({...this.config,token:e}).then(()=>this.removeToken(A(this.config)))}logoutEc(){const e=this.getEcToken();return Gt({...this.config,token:e}).then(()=>this.removeToken(b(this.config)))}hasPublicToken(){return!!this.getPublicToken()}hasEcToken(){return!!this.getEcToken()}hasAnyToken(){return!!this.getEcToken()||!!this.getPublicToken()}getBestToken(){try{return this.getEcToken()||this.getPublicToken()}catch{return}}clean(e=!0){return this.set({_clean:e})}maybeClean(e){return this.config._clean?Sn(e):e}model(e){return this.set({model:e})}token(e){return this.set({token:e})}dmShortID(e){return this.set({dmShortID:e})}dm(e){return this.dmShortID(e)}dmID(e){return this.set({dmID:e})}assetGroup(e){return this.set({assetGroup:e})}assetgroup(e){return this.assetGroup(e)}subdomain(e){return this.set({subdomain:e})}resource(e){return this.set({resource:e})}route(e){return this.set({route:e})}publicApi(){return Jt(this.config)}async getDatamanager(e){const n=await this.getBestToken();return Ft({...this.config,dmID:e,token:n})}async dmList(e={}){const n=await this.getBestToken();return xt({...this.config,options:e,token:n})}async modelList(e={}){const n=await this.getBestToken();return jt({...this.config,options:e,token:n})}}const M=Q.join(me.homedir(),".ec-fdk"),L=Q.join(M,"auth.json");function U(){try{return E.existsSync(L)?JSON.parse(E.readFileSync(L,"utf-8")):{}}catch{return{}}}function V(t){E.existsSync(M)||E.mkdirSync(M,{recursive:!0,mode:448}),E.writeFileSync(L,JSON.stringify(t,null,2),{mode:384})}const $={get(t){return U()[t]},set(t,e){const n=U();n[t]=e,V(n)},remove(t){const e=U();delete e[t],V(e)}};function _n(t){const e=he.createInterface({input:process.stdin,output:process.stderr});return new Promise(n=>{e.question(t,r=>{e.close(),n(r)})})}function qn(t){return new Promise(e=>{process.stderr.write(t);const n=process.stdin;n.setRawMode(!0),n.resume(),n.setEncoding("utf-8");let r="";const o=a=>{for(const i of a){if(i===""&&(process.stderr.write(`
4
+ ${s.verbose}`;throw new Error(c)}throw new Error(`unexpected fetch error: ${a.statusText}`)}if(o)return a;if(a.status===204)return;const i=await a.text();return i?JSON.parse(i):void 0}const q={datamanager:{live:"https://datamanager.entrecode.de/",stage:"https://datamanager.cachena.entrecode.de/"},accounts:{live:"https://accounts.entrecode.de/",stage:"https://accounts.cachena.entrecode.de/"},appserver:{live:"https://appserver.entrecode.de/",stage:"https://appserver.cachena.entrecode.de/"},"dm-history":{live:"https://dm-history.entrecode.de/",stage:"https://dm-history.cachena.entrecode.de/"}};function g(e,t="stage",n="datamanager"){const r=q[n];if(!r)throw new Error(`subdomain "${n}" not found. Try one of ${Object.keys(q).join(", ")}`);const o=r[t];if(!o)throw new Error(`env "${t}" not found. Try one of ${Object.keys(r[t]).join(", ")}`);return o+e}function h(e,t=!0){return Object.entries(e).sort((n,r)=>n[0].localeCompare(r[0])).map(([n,r])=>`${n}=${r}`).join("&")}function d(e){Object.entries(e).forEach(([t,n])=>{if(n===void 0)throw new Error(`expected ${t} to be set!`)})}const te={stage:"https://accounts.cachena.entrecode.de/",live:"https://accounts.entrecode.de/"};async function Ae(e){let{env:t,dmShortID:n,email:r,password:o}=e;d({env:t,dmShortID:n,email:r,password:o});const a=g(`api/${n}/_auth/login?clientID=rest`,t);return await l(a,{},{method:"POST",body:JSON.stringify({email:r,password:o}),headers:{"Content-Type":"application/json"}})}async function Se(e){let{env:t,email:n,password:r}=e;d({env:t,email:n,password:r});const o=`${te[t]}auth/login?clientID=rest`;return await l(o,{},{method:"POST",body:JSON.stringify({email:n,password:r}),headers:{"Content-Type":"application/json"}})}async function _e(e){let{dmShortID:t,env:n,token:r}=e;d({dmShortID:t,env:n,token:r});const o=g(`api/${t}/_auth/logout?clientID=rest&token=${r}`,n);return await l(o,{rawRes:!0},{method:"POST"})}async function qe(e){let{env:t,token:n}=e;d({env:t,token:n});const r=`${te[t]}auth/logout?clientID=rest`;return await l(r,{rawRes:!0,token:n},{method:"POST"})}function Oe({dmShortID:e}){return d({dmShortID:e}),e}function Ce({env:e}){return d({env:e}),e}let Ue=["created","creator","id","modified","private","_created","_creator","_embedded","_entryTitle","_id","_links","_modelTitle","_modelTitleField","_modified"];function ne(e){let t={};for(let n in e)Ue.includes(n)||(t[n]=e[n]);return t}function Le(e){return JSON.parse(JSON.stringify(e))}async function Me(e){let{env:t,dmShortID:n}=e;d({env:t,dmShortID:n});const r=g(`api/${n}`,t);return l(r,e)}async function re(e){let{env:t,dmShortID:n,model:r,options:o={}}=e;d({env:t,dmShortID:n,model:r}),o={size:50,page:1,_list:!0,...o};const a=h(o),i=g(`api/${n}/${r}?${a}`,t),{count:s,total:c,_embedded:u}=await l(i,e);let m=u?u[`${n}:${r}`]:[];return m=Array.isArray(m)?m:[m],{count:s,total:c,items:m}}function Re({env:e,dmShortID:t,model:n,entryID:r,token:o}){d({env:e,dmShortID:t,model:n,entryID:r});const a=h({_id:r}),i=g(`api/${t}/${n}?${a}`,e);return l(i,{token:o})}async function Pe({env:e,dmShortID:t,model:n,value:r,token:o}){d({env:e,dmShortID:t,model:n,value:r});const a=g(`api/${t}/${n}`,e);return await l(a,{token:o},{method:"POST",body:JSON.stringify(r),headers:{"Content-Type":"application/json"}})}async function oe({env:e,dmShortID:t,model:n,entryID:r,value:o,token:a,safePut:i=!1}){d({env:e,dmShortID:t,model:n,entryID:r,value:o});const s={"Content-Type":"application/json"};if(i){if(!("_modified"in o))throw new Error("expected _modified to be set!");s["If-Unmodified-Since"]=new Date(o._modified).toUTCString()}const c=g(`api/${t}/${n}?_id=${r}`,e);return o=Le(o),o=ne(o),await l(c,{token:a},{method:"PUT",headers:s,body:JSON.stringify(o)})}function ae({env:e,dmShortID:t,model:n,entryID:r,token:o}){d({env:e,dmShortID:t,model:n,entryID:r});const a=g(`api/${t}/${n}?_id=${r}`,e);return l(a,{token:o,rawRes:!0},{method:"DELETE",headers:{"Content-Type":"application/json"}})}async function Be(e,t){let{env:n,dmShortID:r,model:o,options:a={}}=e;d({env:n,dmShortID:r,model:o}),e.options={size:50,page:1,_list:!0,...a};let i=0,s,c=[];for(;s===void 0||i<s;){const u=await re(e);for(let m of u.items)c.push(await t(m));i+=u.items.length,s=u.total,e.options.page++}return c}async function Ge({env:e,dmShortID:t,model:n,withMetadata:r}){d({env:e,dmShortID:t,model:n});const o=g(`api/schema/${t}/${n}`,e),a=await l(o),i=a?.allOf?.[1];if(typeof i.properties!="object")throw new Error(`getSchema: ${o} returned unexpected format: ${JSON.stringify(a)}`);const{properties:s}=i,c=ne(s);for(let u in c){let m=c[u];if(m.required=i.required.includes(u),c[u]?.oneOf&&delete c[u]?.oneOf,m.title?.includes("<")&&m.title?.includes(">")){const y=m.title.split("<")[1].slice(0,-1),w=m.title.split("<")[0];m.type=w,y.includes(":")?m.resource=y.split(":")[1]:m.resource=y}else["asset","entry","assets","entries"].includes(m.title)?(m.type=m.title,m.resource=null):m.type=m.title;delete c[u].title}if(r){const u=s._modelTitle.title,m=s._modelTitleField.title;return{properties:c,meta:{modelTitleField:m,modelTitle:u}}}return c}function se(e){return Object.entries(e).map(([t,n])=>typeof n!="object"?{[t]:String(n)}:{...n.sort&&{sort:Array.isArray(n)?n.join(","):n},...n.search&&{[t+"~"]:n.search},...n.notNull&&{[t+"!"]:""},...n.null&&{[t]:""},...n.any&&{[t]:n.any.join(",")},...n.from&&{[t+"From"]:n.from},...n.to&&{[t+"To"]:n.to}}).reduce((t,n)=>({...t,...n}),{})}const Ne=se;function G(e){return e._links.collection.href.split("/").slice(-2)[0]}function ie(e){const t=e._links.collection.href.split("api/")[0];return Object.keys(q.datamanager).find(r=>q.datamanager[r]===t)}const ce=e=>{const t=G(e),n=ie(e),r=e._modelTitle,o=e.id;return{dmShortID:t,env:n,model:r,entryID:o}},xe=e=>ae(ce(e)),je=(e,t)=>oe({...ce(e),value:t});function Je(e,t){const n=G(t);return t._embedded[`${n}:${t._modelTitle}/${e}/asset`]}async function Fe({env:e,dmShortID:t,assetGroup:n,assetID:r,token:o}){d({env:e,dmShortID:t,assetGroup:n,assetID:r});const a=h({assetID:r}),i=g(`a/${t}/${n}?${a}`,e),{_embedded:s}=await l(i,{token:o});return s?s["ec:dm-asset"]:void 0}async function He(e){let{env:t,dmShortID:n,assetGroup:r,token:o,options:a={}}=e;d({env:t,dmShortID:n,assetGroup:r}),a={size:50,page:1,_list:!0,...a};const i=h(a),s=g(`a/${n}/${r}?${i}`,t),{count:c,total:u,_embedded:m}=await l(s,{token:o});let y=m?m["ec:dm-asset"]:[];return y=Array.isArray(y)?y:[y],{count:c,total:u,items:y}}async function ze({env:e,dmShortID:t,assetGroup:n,token:r,file:o,name:a,options:i}){d({env:e,dmShortID:t,assetGroup:n,file:o});const s=g(`a/${t}/${n}`,e),c=new FormData;return c.append("file",o,a),i&&Object.keys(i).forEach(m=>{c.append(m,i[m])}),(await l(s,{token:r},{method:"POST",body:c}))._embedded["ec:dm-asset"]}async function Ke({env:e,dmShortID:t,assetGroup:n,files:r,options:o}){d({env:e,dmShortID:t,assetGroup:n,files:r});const a=g(`a/${t}/${n}`,e),i=new FormData;r.forEach(c=>{i.append("file",c)}),o&&Object.keys(o).forEach(c=>{i.append(c,o[c])});const s=await l(a,{},{method:"POST",body:i});return Array.isArray(s._embedded["ec:dm-asset"])?s._embedded["ec:dm-asset"]:[s._embedded["ec:dm-asset"]]}async function Ve({env:e,dmShortID:t,assetGroup:n,assetID:r,token:o}){d({env:e,dmShortID:t,assetGroup:n,assetID:r});const a=g(`a/${t}/${n}/${r}`,e);await l(a,{token:o,rawRes:!0},{method:"DELETE"})}function Ye(e,t,n=!1){let r,o;return(n?e?.thumbnails:e?.fileVariants)?.forEach(i=>{const{resolution:{width:s,height:c}}=i,u=Math.abs(Math.max(s,c)-t);(!o||u<o)&&(o=u,r=i)}),r?.url??e?.file?.url??null}function We(e="stage",t,n,r,o=!1){const a=Math.max(r.file.resolution.width,r.file.resolution.height),i=n.filter(c=>c<a),s=`https://datamanager${e==="stage"?".cachena":""}.entrecode.de`;return o?i.map(c=>{const u=r.thumbnails.find(w=>c===w.dimension),m=`${s}/t/${t}/${r.assetID}/${c}`,y=u?u.url:m;return{size:c,url:y,generated:u}}):i.map(c=>{const u=r.fileVariants.find(w=>c===Math.max(w.resolution.width,w.resolution.height)),m=`${s}/f/${t}/${r.assetID}/${c}`,y=u?u.url:m;return{size:c,url:y,generated:u}})}const p={"Content-Type":"application/json"};async function Xe(e){let{env:t,dmID:n,token:r}=e;d({env:t,dmID:n});const o=g(`?dataManagerID=${n}`,t);return l(o,{token:r})}async function Qe(e){let{env:t,options:n={}}=e;d({env:t}),n={size:25,page:1,_list:!0,...n};const r=h(n),o=g(`?${r}`,t),{count:a,total:i,_embedded:s}=await l(o,e);let c=s?s["ec:datamanager"]:[];return c=Array.isArray(c)?c:[c],{count:a,total:i,items:c}}async function Ze(e){let{env:t,dmID:n,options:r={}}=e;d({env:t,dmID:n}),r={size:25,dataManagerID:n,page:1,_list:!0,...r};const o=h(r),a=g(`model?${o}`,t),{count:i,total:s,_embedded:c}=await l(a,e);let u=c?c["ec:model"]:[];return u=Array.isArray(u)?u:[u],{count:i,total:s,items:u}}async function et(e){let{env:t,resource:n,options:r={},subdomain:o="datamanager"}=e;d({env:t,subdomain:o,resource:n}),r={size:25,page:1,_list:!0,...r};const a=h(r),i=g(`${n}?${a}`,t,o),{count:s,total:c,_embedded:u}=await l(i,e);let m=u?u[Object.keys(u)[0]]:[];return m=Array.isArray(m)?m:[m],{count:s,total:c,items:m}}async function tt(e){let{env:t,resource:n,options:r={},subdomain:o="datamanager"}=e;d({env:t,subdomain:o,resource:n});const a=h(r),i=g(`${n}?${a}`,t,o);return l(i,e)}async function nt(e){let{env:t,resource:n,options:r={},subdomain:o="datamanager",value:a}=e;d({env:t,subdomain:o,resource:n,value:a});const i=h(r),s=g(`${n}?${i}`,t,o);return l(s,e,{method:"PUT",body:JSON.stringify(a),headers:p})}async function rt(e){let{env:t,resource:n,options:r={},subdomain:o="datamanager"}=e;d({env:t,subdomain:o,resource:n});const a=h(r),i=g(`${n}?${a}`,t,o);return l(i,{...e,rawRes:!0},{method:"DELETE",headers:p})}async function ot(e,t={}){let{env:n,route:r,options:o={},subdomain:a="datamanager"}=e;d({env:n,subdomain:a,route:r}),o={...o};const i=h(o),s=g(`${r}?${i}`,n,a);return l(s,e,t)}async function at(e){let{env:t,token:n,value:r}=e;d({env:t,value:r});const o=g("",t);return l(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function st(e){let{env:t,token:n,dmID:r,value:o}=e;d({env:t,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`?${a}`,t);return l(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function it(e){let{env:t,token:n,dmID:r}=e;d({env:t,dmID:r});const o=h({dataManagerID:r}),a=g(`?${o}`,t);return l(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function ct(e){let{env:t,token:n,dmID:r,value:o}=e;d({env:t,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`model?${a}`,t);return l(i,{token:n},{method:"POST",body:JSON.stringify(o),headers:p})}async function dt(e){let{env:t,token:n,dmID:r,modelID:o,value:a}=e;d({env:t,dmID:r,modelID:o,value:a});const i=h({dataManagerID:r,modelID:o}),s=g(`model?${i}`,t);return l(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function ut(e){let{env:t,token:n,dmID:r,modelID:o}=e;d({env:t,dmID:r,modelID:o});const a=h({dataManagerID:r,modelID:o}),i=g(`model?${a}`,t);return l(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function lt(e){let{env:t,token:n,value:r}=e;d({env:t,value:r});const o=g("template",t);return l(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function ft(e){let{env:t,token:n,dmID:r,value:o}=e;d({env:t,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`assetgroup?${a}`,t);return l(i,{token:n},{method:"POST",body:JSON.stringify(o),headers:p})}async function gt(e){let{env:t,token:n,dmID:r,assetGroupID:o,value:a}=e;d({env:t,dmID:r,assetGroupID:o,value:a});const i=h({dataManagerID:r,assetGroupID:o}),s=g(`assetgroup?${i}`,t);return l(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function mt(e){let{env:t,token:n,dmShortID:r,assetGroup:o,assetID:a,value:i}=e;d({env:t,dmShortID:r,assetGroup:o,assetID:a,value:i});const s=g(`a/${r}/${o}/${a}`,t);return l(s,{token:n},{method:"PUT",body:JSON.stringify(i),headers:p})}async function ht(e){let{env:t,token:n,dmID:r,clientID:o,value:a}=e;d({env:t,dmID:r,clientID:o,value:a});const i=h({dataManagerID:r,clientID:o}),s=g(`client?${i}`,t);return l(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function pt(e){let{env:t,token:n,dmID:r,value:o}=e;d({env:t,dmID:r,value:o});const a=h({dataManagerID:r}),i=g(`role?${a}`,t);return l(i,{token:n},{method:"POST",body:JSON.stringify(o),headers:p})}async function yt(e){let{env:t,token:n,dmID:r,roleID:o,value:a}=e;d({env:t,dmID:r,roleID:o,value:a});const i=h({dataManagerID:r,roleID:o}),s=g(`role?${i}`,t);return l(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function kt(e){let{env:t,token:n,dmID:r,roleID:o}=e;d({env:t,dmID:r,roleID:o});const a=h({dataManagerID:r,roleID:o}),i=g(`role?${a}`,t);return l(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function wt(e){let{env:t,token:n,dmID:r,accountID:o,value:a}=e;d({env:t,dmID:r,accountID:o,value:a});const i=h({dataManagerID:r,accountID:o}),s=g(`account?${i}`,t);return l(s,{token:n},{method:"PUT",body:JSON.stringify(a),headers:p})}async function Dt(e){let{env:t,token:n,dmID:r,accountID:o}=e;d({env:t,dmID:r,accountID:o});const a=h({dataManagerID:r,accountID:o}),i=g(`account?${a}`,t);return l(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function Tt(e){let{env:t,token:n,options:r={}}=e;d({env:t});const o=h(r),a=g(`stats?${o}`,t);return l(a,{token:n})}async function bt(e){let{env:t,token:n,options:r={}}=e;d({env:t});const o=h(r),a=g(`entries?${o}`,t,"dm-history");return l(a,{token:n})}async function $t(e){let{env:t,token:n,value:r}=e;d({env:t,value:r});const o=g("client",t,"accounts");return l(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function Et(e){let{env:t,token:n,clientID:r,value:o}=e;d({env:t,clientID:r,value:o});const a=h({clientID:r}),i=g(`client?${a}`,t,"accounts");return l(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function vt(e){let{env:t,token:n,clientID:r}=e;d({env:t,clientID:r});const o=h({clientID:r}),a=g(`client?${o}`,t,"accounts");return l(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function It(e){let{env:t,token:n,value:r}=e;d({env:t,value:r});const o=g("group",t,"accounts");return l(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p})}async function At(e){let{env:t,token:n,groupID:r,value:o}=e;d({env:t,groupID:r,value:o});const a=h({groupID:r}),i=g(`group?${a}`,t,"accounts");return l(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function St(e){let{env:t,token:n,groupID:r}=e;d({env:t,groupID:r});const o=h({groupID:r}),a=g(`group?${o}`,t,"accounts");return l(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function _t(e){let{env:t,token:n,value:r}=e;d({env:t,value:r});const o=g("invite",t,"accounts"),a=await l(o,{token:n},{method:"POST",body:JSON.stringify(r),headers:p});return a?._embedded?.["ec:invite"]??a}async function qt(e){let{env:t,token:n,inviteID:r,value:o}=e;d({env:t,inviteID:r,value:o});const a=h({invite:r}),i=g(`invite?${a}`,t,"accounts");return l(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function Ot(e){let{env:t,token:n,inviteID:r}=e;d({env:t,inviteID:r});const o=h({invite:r}),a=g(`invite?${o}`,t,"accounts");return l(a,{token:n,rawRes:!0},{method:"DELETE",headers:p})}async function Ct(e){let{env:t,token:n,accountID:r,value:o}=e;d({env:t,accountID:r,value:o});const a=h({accountID:r}),i=g(`account?${a}`,t,"accounts");return l(i,{token:n},{method:"PUT",body:JSON.stringify(o),headers:p})}async function Ut(e){let{env:t,token:n,accountID:r}=e;d({env:t,accountID:r});const o=h({accountID:r}),a=g(`account/tokens?${o}`,t,"accounts");let s=(await l(a,{token:n}))?._embedded?.["ec:account/token"]??[];return Array.isArray(s)?s:[s]}async function Lt(e){let{env:t,token:n,accountID:r}=e;d({env:t,accountID:r});const o=h({accountID:r}),a=g(`account/tokens?${o}`,t,"accounts");return l(a,{token:n},{method:"POST",headers:p})}async function Mt(e){let{env:t,token:n,accountID:r,accessTokenID:o}=e;d({env:t,accountID:r,accessTokenID:o});const a=h({accessTokenID:o,accountID:r}),i=g(`account/tokens?${a}`,t,"accounts");return l(i,{token:n,rawRes:!0},{method:"DELETE",headers:p})}const Rt=Object.freeze(Object.defineProperty({__proto__:null,assetList:He,createAccountClient:$t,createAsset:ze,createAssetGroup:ft,createAssets:Ke,createDatamanager:at,createEntry:Pe,createGroup:It,createInvite:_t,createModel:ct,createRole:pt,createTemplate:lt,createToken:Lt,deleteAccountClient:vt,deleteAsset:Ve,deleteDatamanager:it,deleteDmAccount:Dt,deleteEntry:ae,deleteEntryObject:xe,deleteGroup:St,deleteInvite:Ot,deleteModel:ut,deleteRole:kt,deleteToken:Mt,dmList:Qe,editAccount:Ct,editAccountClient:Et,editAsset:mt,editAssetGroup:gt,editDatamanager:st,editDmAccount:wt,editDmClient:ht,editEntry:oe,editEntryObject:je,editGroup:At,editInvite:qt,editModel:dt,editRole:yt,entryList:re,fileVariant:Ye,filterOptions:Ne,getAsset:Fe,getDatamanager:Xe,getEcAuthKey:Ce,getEntry:Re,getEntryAsset:Je,getEntryEnv:ie,getEntryShortID:G,getFileVariants:We,getHistory:bt,getPublicAuthKey:Oe,getSchema:Ge,getStats:Tt,listTokens:Ut,loginEc:Se,loginPublic:Ae,logoutEc:qe,logoutPublic:_e,mapEntries:Be,modelList:Ze,publicApi:Me,raw:ot,resourceDelete:rt,resourceEdit:nt,resourceGet:tt,resourceList:et,sdkOptions:se},Symbol.toStringTag,{value:"Module"})),{entryList:z,mapEntries:Pt,getEntry:Bt,getAsset:Gt,assetList:K,createAsset:Nt,createAssets:xt,deleteAsset:jt,createEntry:Jt,editEntry:V,deleteEntry:Ft,getSchema:Ht,loginPublic:zt,loginEc:Kt,logoutEc:Vt,logoutPublic:Yt,getEcAuthKey:b,getPublicAuthKey:I,dmList:Wt,modelList:Xt,publicApi:Qt,getDatamanager:Zt,resourceList:en,resourceGet:tn,resourceEdit:nn,resourceDelete:rn,raw:on,createDatamanager:an,editDatamanager:sn,deleteDatamanager:cn,createModel:dn,editModel:un,deleteModel:ln,createTemplate:fn,createAssetGroup:gn,editAssetGroup:mn,editAsset:hn,editDmClient:pn,createRole:yn,editRole:kn,deleteRole:wn,editDmAccount:Dn,deleteDmAccount:Tn,getStats:bn,getHistory:$n,createAccountClient:En,editAccountClient:vn,deleteAccountClient:In,createGroup:An,editGroup:Sn,deleteGroup:_n,createInvite:qn,editInvite:On,deleteInvite:Cn,editAccount:Un,listTokens:Ln,createToken:Mn,deleteToken:Rn}=Rt;function Y(e){if(!e||typeof e!="object")return e;const{_links:t,_embedded:n,...r}=e;return r}function Pn(e){return!e||typeof e!="object"?e:Array.isArray(e.items)?{...e,items:e.items.map(Y)}:Y(e)}class N{constructor(t={}){if(!t.storageAdapter){let n=new Map;t.storageAdapter={get:r=>n.get(r),set:(r,o)=>n.set(r,o),remove:r=>n.delete(r)}}this.config=t}set(t){return new N({...this.config,...t})}async entries(t={}){const n=await this.getBestToken();return z({...this.config,options:t,token:n})}async entryList(t){const n=await this.getBestToken();return z({...this.config,options:t,token:n}).then(r=>this.maybeClean(r))}async mapEntries(t,n={}){const r=await this.getBestToken();return Pt({...this.config,options:n,token:r},t)}async getEntry(t){const n=await this.getBestToken();return Bt({...this.config,entryID:t,token:n}).then(r=>this.maybeClean(r))}async editEntrySafe(t,n){const r=await this.getBestToken();return V({...this.config,entryID:t,token:r,value:n,safePut:!0}).then(o=>this.maybeClean(o))}async getSchema(){return Ht(this.config)}async assets(t){const n=await this.getBestToken();return K({...this.config,options:t,token:n})}async assetList(t){const n=await this.getBestToken();return K({...this.config,options:t,token:n})}async createAsset(t){const{file:n,name:r,options:o}=t,a=await this.getBestToken();return Nt({...this.config,file:n,name:r,options:o,token:a})}async createAssets(t){const{files:n,options:r}=t,o=await this.getBestToken();return xt({...this.config,files:n,options:r,token:o})}async deleteAsset(t){const n=await this.getBestToken();return jt({...this.config,token:n,assetID:t})}async getAsset(t){const n=await this.getBestToken();return Gt({...this.config,assetID:t,token:n})}async createEntry(t){const n=await this.getBestToken();return Jt({...this.config,token:n,value:t}).then(r=>this.maybeClean(r))}async editEntry(t,n){const r=await this.getBestToken();return V({...this.config,entryID:t,token:r,value:n}).then(o=>this.maybeClean(o))}async deleteEntry(t){const n=await this.getBestToken();return Ft({...this.config,token:n,entryID:t})}async resourceList(t){const n=await this.getBestToken();return en({...this.config,options:t,token:n})}async resourceGet(t){const n=await this.getBestToken();return tn({...this.config,options:t,token:n})}async resourceEdit(t,n){const r=await this.getBestToken();return nn({...this.config,options:t,token:r,value:n})}async resourceDelete(t){const n=await this.getBestToken();return rn({...this.config,options:t,token:n})}async raw(t,n){const r=await this.getBestToken();return on({...this.config,options:t,token:r},n)}async createDatamanager(t){const n=await this.getBestToken();return an({...this.config,token:n,value:t})}async editDatamanager(t,n){const r=await this.getBestToken();return sn({...this.config,token:r,dmID:t,value:n})}async deleteDatamanager(t){const n=await this.getBestToken();return cn({...this.config,token:n,dmID:t})}async createModel(t){const n=await this.getBestToken();return dn({...this.config,token:n,value:t})}async editModel(t,n){const r=await this.getBestToken();return un({...this.config,token:r,modelID:t,value:n})}async deleteModel(t){const n=await this.getBestToken();return ln({...this.config,token:n,modelID:t})}async createTemplate(t){const n=await this.getBestToken();return fn({...this.config,token:n,value:t})}async createAssetGroup(t){const n=await this.getBestToken();return gn({...this.config,token:n,value:t})}async editAssetGroup(t,n){const r=await this.getBestToken();return mn({...this.config,token:r,assetGroupID:t,value:n})}async editAsset(t,n){const r=await this.getBestToken();return hn({...this.config,token:r,assetID:t,value:n})}async editDmClient(t,n){const r=await this.getBestToken();return pn({...this.config,token:r,clientID:t,value:n})}async createRole(t){const n=await this.getBestToken();return yn({...this.config,token:n,value:t})}async editRole(t,n){const r=await this.getBestToken();return kn({...this.config,token:r,roleID:t,value:n})}async deleteRole(t){const n=await this.getBestToken();return wn({...this.config,token:n,roleID:t})}async editDmAccount(t,n){const r=await this.getBestToken();return Dn({...this.config,token:r,accountID:t,value:n})}async deleteDmAccount(t){const n=await this.getBestToken();return Tn({...this.config,token:n,accountID:t})}async getStats(t={}){const n=await this.getBestToken();return bn({...this.config,token:n,options:t})}async getHistory(t={}){const n=await this.getBestToken();return $n({...this.config,token:n,options:t})}async createAccountClient(t){const n=await this.getBestToken();return En({...this.config,token:n,value:t})}async editAccountClient(t,n){const r=await this.getBestToken();return vn({...this.config,token:r,clientID:t,value:n})}async deleteAccountClient(t){const n=await this.getBestToken();return In({...this.config,token:n,clientID:t})}async createGroup(t){const n=await this.getBestToken();return An({...this.config,token:n,value:t})}async editGroup(t,n){const r=await this.getBestToken();return Sn({...this.config,token:r,groupID:t,value:n})}async deleteGroup(t){const n=await this.getBestToken();return _n({...this.config,token:n,groupID:t})}async createInvite(t){const n=await this.getBestToken();return qn({...this.config,token:n,value:t})}async editInvite(t,n){const r=await this.getBestToken();return On({...this.config,token:r,inviteID:t,value:n})}async deleteInvite(t){const n=await this.getBestToken();return Cn({...this.config,token:n,inviteID:t})}async editAccount(t,n){const r=await this.getBestToken();return Un({...this.config,token:r,accountID:t,value:n})}async listTokens(t){const n=await this.getBestToken();return Ln({...this.config,token:n,accountID:t})}async createToken(t){const n=await this.getBestToken();return Mn({...this.config,token:n,accountID:t})}async deleteToken(t,n){const r=await this.getBestToken();return Rn({...this.config,token:r,accountID:t,accessTokenID:n})}storageAdapter(t){return this.set({storageAdapter:t})}removeToken(t){if(!this.config.storageAdapter)throw new Error("cannot removeToken: no storageAdapter defined!");const{remove:n}=this.config.storageAdapter;n(t)}getToken(t){if(!this.config.storageAdapter)throw new Error("cannot getAuth: no storageAdapter defined!");const{get:n}=this.config.storageAdapter;return n(t)}getPublicToken(){return this.config.token||this.getToken(I(this.config))}getEcToken(){return this.config.token||this.getToken(b(this.config))}setToken(t,n){if(!this.config.storageAdapter)throw new Error("cannot setEcToken: no storageAdapter defined!");return this.config.storageAdapter.set(t,n)}setEcToken(t){this.setToken(b(this.config),t)}removeEcToken(){this.removeToken(b(this.config))}setPublicToken(t){this.setToken(I(this.config),t)}loginEc(t){return Kt({...this.config,...t}).then(n=>this.setToken(b(this.config),n.token))}loginPublic(t){return zt({...this.config,...t}).then(n=>this.setToken(I(this.config),n.token))}logoutPublic(){const t=this.getPublicToken();return Yt({...this.config,token:t}).then(()=>this.removeToken(I(this.config)))}logoutEc(){const t=this.getEcToken();return Vt({...this.config,token:t}).then(()=>this.removeToken(b(this.config)))}hasPublicToken(){return!!this.getPublicToken()}hasEcToken(){return!!this.getEcToken()}hasAnyToken(){return!!this.getEcToken()||!!this.getPublicToken()}getBestToken(){try{return this.getEcToken()||this.getPublicToken()}catch{return}}clean(t=!0){return this.set({_clean:t})}maybeClean(t){return this.config._clean?Pn(t):t}model(t){return this.set({model:t})}token(t){return this.set({token:t})}dmShortID(t){return this.set({dmShortID:t})}dm(t){return this.dmShortID(t)}dmID(t){return this.set({dmID:t})}assetGroup(t){return this.set({assetGroup:t})}assetgroup(t){return this.assetGroup(t)}subdomain(t){return this.set({subdomain:t})}resource(t){return this.set({resource:t})}route(t){return this.set({route:t})}publicApi(){return Qt(this.config)}async getDatamanager(t){const n=await this.getBestToken();return Zt({...this.config,dmID:t,token:n})}async dmList(t={}){const n=await this.getBestToken();return Wt({...this.config,options:t,token:n})}async modelList(t={}){const n=await this.getBestToken();return Xt({...this.config,options:t,token:n})}}const M=ee.join($e.homedir(),".ec-fdk"),R=ee.join(M,"auth.json");function L(){try{return E.existsSync(R)?JSON.parse(E.readFileSync(R,"utf-8")):{}}catch{return{}}}function W(e){E.existsSync(M)||E.mkdirSync(M,{recursive:!0,mode:448}),E.writeFileSync(R,JSON.stringify(e,null,2),{mode:384})}const $={get(e){return L()[e]},set(e,t){const n=L();n[e]=t,W(n)},remove(e){const t=L();delete t[e],W(t)}};function Bn(e){const t=Ee.createInterface({input:process.stdin,output:process.stderr});return new Promise(n=>{t.question(e,r=>{t.close(),n(r)})})}function Gn(e){return new Promise(t=>{process.stderr.write(e);const n=process.stdin;n.setRawMode(!0),n.resume(),n.setEncoding("utf-8");let r="";const o=a=>{for(const i of a){if(i===""&&(process.stderr.write(`
5
5
  `),process.exit(130)),i==="\r"||i===`
6
6
  `){n.setRawMode(!1),n.pause(),n.removeListener("data",o),process.stderr.write(`
7
- `),e(r);return}if(i===""||i==="\b"){r.length>0&&(r=r.slice(0,-1),process.stderr.write("\b \b"));continue}r+=i,process.stderr.write("*")}};n.on("data",o)})}const ie={stage:{authEndpoint:"https://login.cachena.entrecode.de/oidc/auth",tokenEndpoint:"https://login.cachena.entrecode.de/oidc/token"},live:{authEndpoint:"https://login.entrecode.de/oidc/auth",tokenEndpoint:"https://login.entrecode.de/oidc/token"}},R="ec-fdk-cli",Y="http://localhost:19836/callback",On=12e4;function N(t){return t.toString("base64url")}function Cn(){return N(P.randomBytes(32))}function Un(t){return N(P.createHash("sha256").update(t).digest())}function Mn(t){const e=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";ye.exec(`${e} ${JSON.stringify(t)}`)}const Ln=`<!DOCTYPE html><html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0">
8
- <div style="text-align:center"><h1>Login successful</h1><p>You can close this tab.</p></div></body></html>`,I=t=>`<!DOCTYPE html><html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0">
9
- <div style="text-align:center"><h1>Login failed</h1><p>${t}</p></div></body></html>`;async function Rn(t,e){const{tokenEndpoint:n}=ie[t],r=await fetch(n,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",client_id:R,refresh_token:e})});if(!r.ok){const a=await r.text();throw new Error(`Token refresh failed: ${r.status} ${a}`)}const o=await r.json();if(!o.access_token)throw new Error("No access_token in refresh response");return{access_token:o.access_token,refresh_token:o.refresh_token}}function Pn(t){const{authEndpoint:e,tokenEndpoint:n}=ie[t],r=Cn(),o=Un(r),a=N(P.randomBytes(16));return new Promise((i,s)=>{const c=pe.createServer(async(k,w)=>{if(!k.url?.startsWith("/callback")){w.writeHead(404),w.end();return}const T=new URL(k.url,"http://localhost").searchParams,x=T.get("code"),ue=T.get("state"),C=T.get("error");if(C){w.writeHead(200,{"Content-Type":"text/html"}),w.end(I(T.get("error_description")||C)),m(),s(new Error(T.get("error_description")||C));return}if(ue!==a){w.writeHead(200,{"Content-Type":"text/html"}),w.end(I("State mismatch")),m(),s(new Error("State mismatch — possible CSRF attack"));return}if(!x){w.writeHead(200,{"Content-Type":"text/html"}),w.end(I("No authorization code received")),m(),s(new Error("No authorization code received"));return}try{const D=await fetch(n,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:R,redirect_uri:Y,code:x,code_verifier:r})});if(!D.ok){const le=await D.text();throw new Error(`Token exchange failed: ${D.status} ${le}`)}const j=await D.json(),J=j.access_token;if(!J)throw new Error("No access_token in token response");w.writeHead(200,{"Content-Type":"text/html"}),w.end(Ln),m(),i({access_token:J,refresh_token:j.refresh_token})}catch(D){w.writeHead(200,{"Content-Type":"text/html"}),w.end(I(D.message)),m(),s(D)}}),f=setTimeout(()=>{m(),s(new Error("Login timed out after 2 minutes"))},On);function m(){clearTimeout(f),c.close()}c.listen(19836,()=>{const k=`${e}?`+new URLSearchParams({client_id:R,redirect_uri:Y,response_type:"code",scope:"openid offline_access",state:a,code_challenge:o,code_challenge_method:"S256"}).toString();process.stderr.write(`Opening browser for login...
10
- `),Mn(k)}),c.on("error",k=>{m(),s(new Error(`Could not start local server: ${k.message}`))})})}const Bn=ge.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:document.currentScript&&document.currentScript.src||new URL("cli.cjs",document.baseURI).href),{version:Gn}=Bn("../package.json"),Nn=`ec.fdk <command> [options]
7
+ `),t(r);return}if(i===""||i==="\b"){r.length>0&&(r=r.slice(0,-1),process.stderr.write("\b \b"));continue}r+=i,process.stderr.write("*")}};n.on("data",o)})}const de={stage:{authEndpoint:"https://login.cachena.entrecode.de/oidc/auth",tokenEndpoint:"https://login.cachena.entrecode.de/oidc/token"},live:{authEndpoint:"https://login.entrecode.de/oidc/auth",tokenEndpoint:"https://login.entrecode.de/oidc/token"}},P="ec-fdk-cli",X="http://localhost:19836/callback",Nn=12e4;function x(e){return e.toString("base64url")}function xn(){return x(B.randomBytes(32))}function jn(e){return x(B.createHash("sha256").update(e).digest())}function Jn(e){const t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";Ie.exec(`${t} ${JSON.stringify(e)}`)}const Fn=`<!DOCTYPE html><html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0">
8
+ <div style="text-align:center"><h1>Login successful</h1><p>You can close this tab.</p></div></body></html>`,A=e=>`<!DOCTYPE html><html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0">
9
+ <div style="text-align:center"><h1>Login failed</h1><p>${e}</p></div></body></html>`;async function Hn(e,t){const{tokenEndpoint:n}=de[e],r=await fetch(n,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",client_id:P,refresh_token:t})});if(!r.ok){const a=await r.text();throw new Error(`Token refresh failed: ${r.status} ${a}`)}const o=await r.json();if(!o.access_token)throw new Error("No access_token in refresh response");return{access_token:o.access_token,refresh_token:o.refresh_token}}function zn(e){const{authEndpoint:t,tokenEndpoint:n}=de[e],r=xn(),o=jn(r),a=x(B.randomBytes(16));return new Promise((i,s)=>{const c=ve.createServer(async(y,w)=>{if(!y.url?.startsWith("/callback")){w.writeHead(404),w.end();return}const T=new URL(y.url,"http://localhost").searchParams,j=T.get("code"),ge=T.get("state"),C=T.get("error");if(C){w.writeHead(200,{"Content-Type":"text/html"}),w.end(A(T.get("error_description")||C)),m(),s(new Error(T.get("error_description")||C));return}if(ge!==a){w.writeHead(200,{"Content-Type":"text/html"}),w.end(A("State mismatch")),m(),s(new Error("State mismatch — possible CSRF attack"));return}if(!j){w.writeHead(200,{"Content-Type":"text/html"}),w.end(A("No authorization code received")),m(),s(new Error("No authorization code received"));return}try{const D=await fetch(n,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:P,redirect_uri:X,code:j,code_verifier:r})});if(!D.ok){const me=await D.text();throw new Error(`Token exchange failed: ${D.status} ${me}`)}const J=await D.json(),F=J.access_token;if(!F)throw new Error("No access_token in token response");w.writeHead(200,{"Content-Type":"text/html"}),w.end(Fn),m(),i({access_token:F,refresh_token:J.refresh_token})}catch(D){w.writeHead(200,{"Content-Type":"text/html"}),w.end(A(D.message)),m(),s(D)}}),u=setTimeout(()=>{m(),s(new Error("Login timed out after 2 minutes"))},Nn);function m(){clearTimeout(u),c.close()}c.listen(19836,()=>{const y=`${t}?`+new URLSearchParams({client_id:P,redirect_uri:X,response_type:"code",scope:"openid offline_access",state:a,code_challenge:o,code_challenge_method:"S256"}).toString();process.stderr.write(`Opening browser for login...
10
+ `),Jn(y)}),c.on("error",y=>{m(),s(new Error(`Could not start local server: ${y.message}`))})})}const ue=be.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:document.currentScript&&document.currentScript.src||new URL("cli.cjs",document.baseURI).href),{version:Kn}=ue("../package.json"),Vn=`ec.fdk <command> [options]
11
11
 
12
12
  Commands:
13
13
  login Login via browser (OIDC). Use --password for email/password prompt.
14
14
  logout Logout and remove stored token
15
15
  whoami Show current logged-in user
16
+ install-skill Install Claude Code skill (default: ~/.claude/skills, or --dir <path>)
16
17
 
17
18
  Entry commands (require --dm, --model):
18
19
  entryList List entries
@@ -107,34 +108,35 @@ Options:
107
108
  --md Output entries as readable markdown
108
109
  -v, --version Show version
109
110
  --password Use email/password login instead of browser
110
- -h, --help Show help`;function S(t){return Object.fromEntries(t.map(e=>{const n=e.indexOf("=");return n===-1&&l(`Invalid filter: "${e}" (expected key=value)`),[e.slice(0,n),e.slice(n+1)]}))}function l(t){process.stderr.write(`Error: ${t}
111
- `),process.exit(2)}function xn(){return new Promise(t=>{let e="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",n=>e+=n),process.stdin.on("end",()=>t(e))})}async function y(t){if(t)try{return JSON.parse(t)}catch{l("--data must be valid JSON")}if(!process.stdin.isTTY){const e=await xn();e.trim()||l("No data provided via stdin");try{return JSON.parse(e)}catch{l("Stdin must be valid JSON")}}l("Provide --data or pipe JSON via stdin")}function v(t){if(!t||typeof t!="object")return t;const{_links:e,_embedded:n,...r}=t;return r}function _(t){return!t||typeof t!="object"?t:Array.isArray(t.items)?{...t,items:t.items.map(v)}:v(t)}const W=40;function X(t){return t.length>W?t.slice(0,W-2)+"..":t}function ce(t){return t==null?"":X(typeof t=="object"?JSON.stringify(t):String(t))}function de(t){return Object.keys(t).filter(e=>!e.startsWith("_"))}function O(t,e){return"| "+t.map((n,r)=>n.padEnd(e[r])).join(" | ")+" |"}function jn(t){const e=de(t),n=e.map(f=>ce(t[f])),r=Math.max(5,...e.map(f=>f.length)),o=Math.max(5,...n.map(f=>f.length)),a=[r,o],i=O(["Field","Value"],a),s="| "+a.map(f=>"-".repeat(f)).join(" | ")+" |",c=e.map((f,m)=>O([f,n[m]],a));return`${i}
111
+ -h, --help Show help`;function S(e){return Object.fromEntries(e.map(t=>{const n=t.indexOf("=");return n===-1&&f(`Invalid filter: "${t}" (expected key=value)`),[t.slice(0,n),t.slice(n+1)]}))}function f(e){process.stderr.write(`Error: ${e}
112
+ `),process.exit(2)}function Yn(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>e(t))})}async function k(e){if(e)try{return JSON.parse(e)}catch{f("--data must be valid JSON")}if(!process.stdin.isTTY){const t=await Yn();t.trim()||f("No data provided via stdin");try{return JSON.parse(t)}catch{f("Stdin must be valid JSON")}}f("Provide --data or pipe JSON via stdin")}function v(e){if(!e||typeof e!="object")return e;const{_links:t,_embedded:n,...r}=e;return r}function _(e){return!e||typeof e!="object"?e:Array.isArray(e.items)?{...e,items:e.items.map(v)}:v(e)}const Q=40;function Z(e){return e.length>Q?e.slice(0,Q-2)+"..":e}function le(e){return e==null?"":Z(typeof e=="object"?JSON.stringify(e):String(e))}function fe(e){return Object.keys(e).filter(t=>!t.startsWith("_"))}function O(e,t){return"| "+e.map((n,r)=>n.padEnd(t[r])).join(" | ")+" |"}function Wn(e){const t=fe(e),n=t.map(u=>le(e[u])),r=Math.max(5,...t.map(u=>u.length)),o=Math.max(5,...n.map(u=>u.length)),a=[r,o],i=O(["Field","Value"],a),s="| "+a.map(u=>"-".repeat(u)).join(" | ")+" |",c=t.map((u,m)=>O([u,n[m]],a));return`${i}
112
113
  ${s}
113
114
  ${c.join(`
114
- `)}`}function Jn(t){if(!t.items.length)return"No entries found.";const e=de(t.items[0]),n=t.items.map(s=>e.map(c=>ce(s[c]))),r=e.map((s,c)=>Math.max(s.length,...n.map(f=>f[c].length))),o=O(e,r),a="| "+r.map(s=>"-".repeat(s)).join(" | ")+" |",i=n.map(s=>O(s,r));return`${o}
115
+ `)}`}function Xn(e){if(!e.items.length)return"No entries found.";const t=fe(e.items[0]),n=e.items.map(s=>t.map(c=>le(s[c]))),r=t.map((s,c)=>Math.max(s.length,...n.map(u=>u[c].length))),o=O(t,r),a="| "+r.map(s=>"-".repeat(s)).join(" | ")+" |",i=n.map(s=>O(s,r));return`${o}
115
116
  ${a}
116
117
  ${i.join(`
117
118
  `)}
118
119
 
119
- ${t.items.length} of ${t.total} entries`}async function Fn(){const{values:t,positionals:e}=fe.parseArgs({allowPositionals:!0,options:{env:{type:"string",short:"e",default:"stage"},dm:{type:"string",short:"d"},model:{type:"string",short:"m"},id:{type:"string",short:"i"},data:{type:"string"},size:{type:"string",short:"s"},page:{type:"string",short:"p"},sort:{type:"string"},filter:{type:"string",short:"f",multiple:!0,default:[]},rid:{type:"string"},"account-id":{type:"string"},assetgroup:{type:"string"},resource:{type:"string"},subdomain:{type:"string"},raw:{type:"boolean",default:!1},md:{type:"boolean",default:!1},password:{type:"boolean",default:!1},version:{type:"boolean",short:"v"},help:{type:"boolean",short:"h"}}});t.version&&(console.log(Gn),process.exit(0)),(t.help||e.length===0)&&(console.log(Nn),process.exit(0));const n=e[0],r=t.env;r!=="stage"&&r!=="live"&&l('--env must be "stage" or "live"');const o=new G({env:r,storageAdapter:$});if(n!=="login"&&n!=="logout"){const a=o.getEcToken(),i=$.get(`${r}_refresh`);if(a&&i)try{const s=JSON.parse(Buffer.from(a.split(".")[1],"base64url").toString());if(s.exp&&s.exp*1e3<Date.now()){const c=await Rn(r,i);o.setEcToken(c.access_token),c.refresh_token&&$.set(`${r}_refresh`,c.refresh_token)}}catch{}}if(n==="login"){try{if(t.password){const a=await _n("Email: "),i=await qn("Password: ");await o.loginEc({email:a,password:i})}else{const a=await Pn(r);o.setEcToken(a.access_token),a.refresh_token&&$.set(`${r}_refresh`,a.refresh_token)}process.stderr.write(`Logged in to ${r} successfully.
120
+ ${e.items.length} of ${e.total} entries`}async function Qn(){const{values:e,positionals:t}=Te.parseArgs({allowPositionals:!0,options:{env:{type:"string",short:"e",default:"stage"},dm:{type:"string",short:"d"},model:{type:"string",short:"m"},id:{type:"string",short:"i"},data:{type:"string"},size:{type:"string",short:"s"},page:{type:"string",short:"p"},sort:{type:"string"},filter:{type:"string",short:"f",multiple:!0,default:[]},rid:{type:"string"},"account-id":{type:"string"},assetgroup:{type:"string"},resource:{type:"string"},subdomain:{type:"string"},raw:{type:"boolean",default:!1},md:{type:"boolean",default:!1},password:{type:"boolean",default:!1},dir:{type:"string"},version:{type:"boolean",short:"v"},help:{type:"boolean",short:"h"}}});e.version&&(console.log(Kn),process.exit(0)),(e.help||t.length===0)&&(console.log(Vn),process.exit(0));const n=t[0],r=e.env;r!=="stage"&&r!=="live"&&f('--env must be "stage" or "live"');const o=new N({env:r,storageAdapter:$});if(n!=="login"&&n!=="logout"){const a=o.getEcToken(),i=$.get(`${r}_refresh`);if(a&&i)try{const s=JSON.parse(Buffer.from(a.split(".")[1],"base64url").toString());if(s.exp&&s.exp*1e3<Date.now()){const c=await Hn(r,i);o.setEcToken(c.access_token),c.refresh_token&&$.set(`${r}_refresh`,c.refresh_token)}}catch{}}if(n==="login"){try{if(e.password){const a=await Bn("Email: "),i=await Gn("Password: ");await o.loginEc({email:a,password:i})}else{const a=await zn(r);o.setEcToken(a.access_token),a.refresh_token&&$.set(`${r}_refresh`,a.refresh_token)}process.stderr.write(`Logged in to ${r} successfully.
120
121
  `)}catch(a){process.stderr.write(`Login failed: ${a.message}
121
122
  `),process.exit(1)}return}if(n==="whoami"){const a=o.getEcToken();a||(process.stderr.write(`Not logged in to ${r}.
122
123
  `),process.exit(1));try{const i=JSON.parse(Buffer.from(a.split(".")[1],"base64url").toString()),s={env:r};i.email&&(s.email=i.email),i.sub&&(s.accountID=i.sub),i.iss&&(s.issuer=i.iss),i.exp&&(s.expires=new Date(i.exp*1e3).toISOString()),process.stdout.write(JSON.stringify(s,null,2)+`
123
- `)}catch{l("Could not decode token")}return}if(n==="logout"){try{o.hasEcToken()&&await o.logoutEc()}catch{}o.removeEcToken(),$.remove(`${r}_refresh`),process.stderr.write(`Logged out of ${r}.
124
- `);return}try{let a;const i=()=>{const s={...S(t.filter)};return t.size&&(s.size=Number(t.size)),t.page&&(s.page=Number(t.page)),t.sort&&(s.sort=[t.sort]),s};switch(n){case"dmList":{a=await o.dmList(i()),t.raw||(a=_(a));break}case"modelList":{t.id||l("--id (datamanager UUID) is required for modelList"),a=await o.dmID(t.id).modelList(i()),t.raw||(a=_(a));break}case"getDatamanager":{t.id||l("--id (datamanager UUID) is required for getDatamanager"),a=await o.getDatamanager(t.id),t.raw||(a=_(a));break}case"resourceList":{t.resource||l("--resource is required for resourceList");let s=o.resource(t.resource);t.subdomain&&(s=s.subdomain(t.subdomain)),a=await s.resourceList(i()),t.raw||(a=_(a));break}case"resourceGet":{t.resource||l("--resource is required for resourceGet");let s=o.resource(t.resource);t.subdomain&&(s=s.subdomain(t.subdomain)),a=await s.resourceGet(S(t.filter)),t.raw||(a=v(a));break}case"resourceEdit":{t.resource||l("--resource is required for resourceEdit");let s=o.resource(t.resource);t.subdomain&&(s=s.subdomain(t.subdomain));const c=await y(t.data);if(a=await s.resourceEdit(S(t.filter),c),!a){process.stderr.write(`Resource updated.
125
- `);return}t.raw||(a=v(a));break}case"resourceDelete":{t.resource||l("--resource is required for resourceDelete");let s=o.resource(t.resource);t.subdomain&&(s=s.subdomain(t.subdomain)),await s.resourceDelete(S(t.filter)),process.stderr.write(`Resource deleted.
126
- `);return}case"getStats":{a=await o.getStats(i());break}case"getHistory":{a=await o.getHistory(i());break}case"entryList":case"getEntry":case"createEntry":case"editEntry":case"deleteEntry":case"getSchema":{t.dm||l("--dm is required"),t.model||l("--model is required");const s=o.dm(t.dm).model(t.model).clean(!t.raw);switch(n){case"entryList":{a=await s.entryList(i());break}case"getEntry":{t.id||l("--id is required for getEntry"),a=await s.getEntry(t.id);break}case"createEntry":{const c=await y(t.data);a=await s.createEntry(c);break}case"editEntry":{t.id||l("--id is required for editEntry");const c=await y(t.data);a=await s.editEntry(t.id,c);break}case"deleteEntry":{t.id||l("--id is required for deleteEntry"),await s.deleteEntry(t.id),process.stderr.write(`Entry deleted.
127
- `);return}case"getSchema":{a=await s.getSchema();break}}break}case"createDatamanager":{const s=await y(t.data);a=await o.createDatamanager(s);break}case"editDatamanager":{t.id||l("--id (datamanager UUID) is required for editDatamanager");const s=await y(t.data);a=await o.editDatamanager(t.id,s);break}case"deleteDatamanager":{t.id||l("--id (datamanager UUID) is required for deleteDatamanager"),await o.deleteDatamanager(t.id),process.stderr.write(`Datamanager deleted.
128
- `);return}case"createModel":{t.id||l("--id (datamanager UUID) is required for createModel");const s=await y(t.data);a=await o.dmID(t.id).createModel(s);break}case"editModel":{t.id||l("--id (datamanager UUID) is required for editModel"),t.rid||l("--rid (model ID) is required for editModel");const s=await y(t.data);a=await o.dmID(t.id).editModel(t.rid,s);break}case"deleteModel":{t.id||l("--id (datamanager UUID) is required for deleteModel"),t.rid||l("--rid (model ID) is required for deleteModel"),await o.dmID(t.id).deleteModel(t.rid),process.stderr.write(`Model deleted.
129
- `);return}case"createTemplate":{const s=await y(t.data);a=await o.createTemplate(s);break}case"createAssetGroup":{t.id||l("--id (datamanager UUID) is required for createAssetGroup");const s=await y(t.data);a=await o.dmID(t.id).createAssetGroup(s);break}case"editAssetGroup":{t.id||l("--id (datamanager UUID) is required for editAssetGroup"),t.rid||l("--rid (asset group ID) is required for editAssetGroup");const s=await y(t.data);a=await o.dmID(t.id).editAssetGroup(t.rid,s);break}case"editAsset":{t.dm||l("--dm (short ID) is required for editAsset"),t.assetgroup||l("--assetgroup is required for editAsset"),t.rid||l("--rid (asset ID) is required for editAsset");const s=await y(t.data);a=await o.dm(t.dm).assetGroup(t.assetgroup).editAsset(t.rid,s);break}case"editDmClient":{t.id||l("--id (datamanager UUID) is required for editDmClient"),t.rid||l("--rid (client ID) is required for editDmClient");const s=await y(t.data);a=await o.dmID(t.id).editDmClient(t.rid,s);break}case"createRole":{t.id||l("--id (datamanager UUID) is required for createRole");const s=await y(t.data);a=await o.dmID(t.id).createRole(s);break}case"editRole":{t.id||l("--id (datamanager UUID) is required for editRole"),t.rid||l("--rid (role ID) is required for editRole");const s=await y(t.data);a=await o.dmID(t.id).editRole(t.rid,s);break}case"deleteRole":{t.id||l("--id (datamanager UUID) is required for deleteRole"),t.rid||l("--rid (role ID) is required for deleteRole"),await o.dmID(t.id).deleteRole(t.rid),process.stderr.write(`Role deleted.
130
- `);return}case"editDmAccount":{t.id||l("--id (datamanager UUID) is required for editDmAccount"),t["account-id"]||l("--account-id is required for editDmAccount");const s=await y(t.data);a=await o.dmID(t.id).editDmAccount(t["account-id"],s);break}case"deleteDmAccount":{t.id||l("--id (datamanager UUID) is required for deleteDmAccount"),t["account-id"]||l("--account-id is required for deleteDmAccount"),await o.dmID(t.id).deleteDmAccount(t["account-id"]),process.stderr.write(`DM account deleted.
131
- `);return}case"createAccountClient":{const s=await y(t.data);a=await o.createAccountClient(s);break}case"editAccountClient":{t.rid||l("--rid (client ID) is required for editAccountClient");const s=await y(t.data);a=await o.editAccountClient(t.rid,s);break}case"deleteAccountClient":{t.rid||l("--rid (client ID) is required for deleteAccountClient"),await o.deleteAccountClient(t.rid),process.stderr.write(`Account client deleted.
132
- `);return}case"createGroup":{const s=await y(t.data);a=await o.createGroup(s);break}case"editGroup":{t.rid||l("--rid (group ID) is required for editGroup");const s=await y(t.data);a=await o.editGroup(t.rid,s);break}case"deleteGroup":{t.rid||l("--rid (group ID) is required for deleteGroup"),await o.deleteGroup(t.rid),process.stderr.write(`Group deleted.
133
- `);return}case"createInvite":{const s=await y(t.data);a=await o.createInvite(s);break}case"editInvite":{t.rid||l("--rid (invite ID) is required for editInvite");const s=await y(t.data);a=await o.editInvite(t.rid,s);break}case"deleteInvite":{t.rid||l("--rid (invite ID) is required for deleteInvite"),await o.deleteInvite(t.rid),process.stderr.write(`Invite deleted.
134
- `);return}case"editAccount":{t["account-id"]||l("--account-id is required for editAccount");const s=await y(t.data);if(a=await o.editAccount(t["account-id"],s),!a){process.stderr.write(`Account updated.
135
- `);return}break}case"listTokens":{t["account-id"]||l("--account-id is required for listTokens");const s=await o.listTokens(t["account-id"]);a=t.raw?s:s.map(v);break}case"createToken":{t["account-id"]||l("--account-id is required for createToken"),a=await o.createToken(t["account-id"]);break}case"deleteToken":{t["account-id"]||l("--account-id is required for deleteToken"),t.rid||l("--rid (access token ID) is required for deleteToken"),await o.deleteToken(t["account-id"],t.rid),process.stderr.write(`Token deleted.
136
- `);return}default:l(`Unknown command: ${n}`)}t.md&&a&&typeof a=="object"?Array.isArray(a.items)?process.stdout.write(Jn(a)+`
137
- `):process.stdout.write(jn(a)+`
124
+ `)}catch{f("Could not decode token")}return}if(n==="install-skill"){const{mkdirSync:a,copyFileSync:i}=await import("node:fs"),{join:s,resolve:c}=await import("node:path"),{homedir:u}=await import("node:os"),m=e.dir?c(e.dir):s(u(),".claude"),y=s(m,"skills","ec-fdk"),w=ue.resolve("../skill/SKILL.md");a(y,{recursive:!0}),i(w,s(y,"SKILL.md")),process.stderr.write(`Installed skill to ${y}/SKILL.md
125
+ `);return}if(n==="logout"){try{o.hasEcToken()&&await o.logoutEc()}catch{}o.removeEcToken(),$.remove(`${r}_refresh`),process.stderr.write(`Logged out of ${r}.
126
+ `);return}try{let a;const i=()=>{const s={...S(e.filter)};return e.size&&(s.size=Number(e.size)),e.page&&(s.page=Number(e.page)),e.sort&&(s.sort=[e.sort]),s};switch(n){case"dmList":{a=await o.dmList(i()),e.raw||(a=_(a));break}case"modelList":{e.id||f("--id (datamanager UUID) is required for modelList"),a=await o.dmID(e.id).modelList(i()),e.raw||(a=_(a));break}case"getDatamanager":{e.id||f("--id (datamanager UUID) is required for getDatamanager"),a=await o.getDatamanager(e.id),e.raw||(a=_(a));break}case"resourceList":{e.resource||f("--resource is required for resourceList");let s=o.resource(e.resource);e.subdomain&&(s=s.subdomain(e.subdomain)),a=await s.resourceList(i()),e.raw||(a=_(a));break}case"resourceGet":{e.resource||f("--resource is required for resourceGet");let s=o.resource(e.resource);e.subdomain&&(s=s.subdomain(e.subdomain)),a=await s.resourceGet(S(e.filter)),e.raw||(a=v(a));break}case"resourceEdit":{e.resource||f("--resource is required for resourceEdit");let s=o.resource(e.resource);e.subdomain&&(s=s.subdomain(e.subdomain));const c=await k(e.data);if(a=await s.resourceEdit(S(e.filter),c),!a){process.stderr.write(`Resource updated.
127
+ `);return}e.raw||(a=v(a));break}case"resourceDelete":{e.resource||f("--resource is required for resourceDelete");let s=o.resource(e.resource);e.subdomain&&(s=s.subdomain(e.subdomain)),await s.resourceDelete(S(e.filter)),process.stderr.write(`Resource deleted.
128
+ `);return}case"getStats":{a=await o.getStats(i());break}case"getHistory":{a=await o.getHistory(i());break}case"entryList":case"getEntry":case"createEntry":case"editEntry":case"deleteEntry":case"getSchema":{e.dm||f("--dm is required"),e.model||f("--model is required");const s=o.dm(e.dm).model(e.model).clean(!e.raw);switch(n){case"entryList":{a=await s.entryList(i());break}case"getEntry":{e.id||f("--id is required for getEntry"),a=await s.getEntry(e.id);break}case"createEntry":{const c=await k(e.data);a=await s.createEntry(c);break}case"editEntry":{e.id||f("--id is required for editEntry");const c=await k(e.data);a=await s.editEntry(e.id,c);break}case"deleteEntry":{e.id||f("--id is required for deleteEntry"),await s.deleteEntry(e.id),process.stderr.write(`Entry deleted.
129
+ `);return}case"getSchema":{a=await s.getSchema();break}}break}case"createDatamanager":{const s=await k(e.data);a=await o.createDatamanager(s);break}case"editDatamanager":{e.id||f("--id (datamanager UUID) is required for editDatamanager");const s=await k(e.data);a=await o.editDatamanager(e.id,s);break}case"deleteDatamanager":{e.id||f("--id (datamanager UUID) is required for deleteDatamanager"),await o.deleteDatamanager(e.id),process.stderr.write(`Datamanager deleted.
130
+ `);return}case"createModel":{e.id||f("--id (datamanager UUID) is required for createModel");const s=await k(e.data);a=await o.dmID(e.id).createModel(s);break}case"editModel":{e.id||f("--id (datamanager UUID) is required for editModel"),e.rid||f("--rid (model ID) is required for editModel");const s=await k(e.data);a=await o.dmID(e.id).editModel(e.rid,s);break}case"deleteModel":{e.id||f("--id (datamanager UUID) is required for deleteModel"),e.rid||f("--rid (model ID) is required for deleteModel"),await o.dmID(e.id).deleteModel(e.rid),process.stderr.write(`Model deleted.
131
+ `);return}case"createTemplate":{const s=await k(e.data);a=await o.createTemplate(s);break}case"createAssetGroup":{e.id||f("--id (datamanager UUID) is required for createAssetGroup");const s=await k(e.data);a=await o.dmID(e.id).createAssetGroup(s);break}case"editAssetGroup":{e.id||f("--id (datamanager UUID) is required for editAssetGroup"),e.rid||f("--rid (asset group ID) is required for editAssetGroup");const s=await k(e.data);a=await o.dmID(e.id).editAssetGroup(e.rid,s);break}case"editAsset":{e.dm||f("--dm (short ID) is required for editAsset"),e.assetgroup||f("--assetgroup is required for editAsset"),e.rid||f("--rid (asset ID) is required for editAsset");const s=await k(e.data);a=await o.dm(e.dm).assetGroup(e.assetgroup).editAsset(e.rid,s);break}case"editDmClient":{e.id||f("--id (datamanager UUID) is required for editDmClient"),e.rid||f("--rid (client ID) is required for editDmClient");const s=await k(e.data);a=await o.dmID(e.id).editDmClient(e.rid,s);break}case"createRole":{e.id||f("--id (datamanager UUID) is required for createRole");const s=await k(e.data);a=await o.dmID(e.id).createRole(s);break}case"editRole":{e.id||f("--id (datamanager UUID) is required for editRole"),e.rid||f("--rid (role ID) is required for editRole");const s=await k(e.data);a=await o.dmID(e.id).editRole(e.rid,s);break}case"deleteRole":{e.id||f("--id (datamanager UUID) is required for deleteRole"),e.rid||f("--rid (role ID) is required for deleteRole"),await o.dmID(e.id).deleteRole(e.rid),process.stderr.write(`Role deleted.
132
+ `);return}case"editDmAccount":{e.id||f("--id (datamanager UUID) is required for editDmAccount"),e["account-id"]||f("--account-id is required for editDmAccount");const s=await k(e.data);a=await o.dmID(e.id).editDmAccount(e["account-id"],s);break}case"deleteDmAccount":{e.id||f("--id (datamanager UUID) is required for deleteDmAccount"),e["account-id"]||f("--account-id is required for deleteDmAccount"),await o.dmID(e.id).deleteDmAccount(e["account-id"]),process.stderr.write(`DM account deleted.
133
+ `);return}case"createAccountClient":{const s=await k(e.data);a=await o.createAccountClient(s);break}case"editAccountClient":{e.rid||f("--rid (client ID) is required for editAccountClient");const s=await k(e.data);a=await o.editAccountClient(e.rid,s);break}case"deleteAccountClient":{e.rid||f("--rid (client ID) is required for deleteAccountClient"),await o.deleteAccountClient(e.rid),process.stderr.write(`Account client deleted.
134
+ `);return}case"createGroup":{const s=await k(e.data);a=await o.createGroup(s);break}case"editGroup":{e.rid||f("--rid (group ID) is required for editGroup");const s=await k(e.data);a=await o.editGroup(e.rid,s);break}case"deleteGroup":{e.rid||f("--rid (group ID) is required for deleteGroup"),await o.deleteGroup(e.rid),process.stderr.write(`Group deleted.
135
+ `);return}case"createInvite":{const s=await k(e.data);a=await o.createInvite(s);break}case"editInvite":{e.rid||f("--rid (invite ID) is required for editInvite");const s=await k(e.data);a=await o.editInvite(e.rid,s);break}case"deleteInvite":{e.rid||f("--rid (invite ID) is required for deleteInvite"),await o.deleteInvite(e.rid),process.stderr.write(`Invite deleted.
136
+ `);return}case"editAccount":{e["account-id"]||f("--account-id is required for editAccount");const s=await k(e.data);if(a=await o.editAccount(e["account-id"],s),!a){process.stderr.write(`Account updated.
137
+ `);return}break}case"listTokens":{e["account-id"]||f("--account-id is required for listTokens");const s=await o.listTokens(e["account-id"]);a=e.raw?s:s.map(v);break}case"createToken":{e["account-id"]||f("--account-id is required for createToken"),a=await o.createToken(e["account-id"]);break}case"deleteToken":{e["account-id"]||f("--account-id is required for deleteToken"),e.rid||f("--rid (access token ID) is required for deleteToken"),await o.deleteToken(e["account-id"],e.rid),process.stderr.write(`Token deleted.
138
+ `);return}default:f(`Unknown command: ${n}`)}e.md&&a&&typeof a=="object"?Array.isArray(a.items)?process.stdout.write(Xn(a)+`
139
+ `):process.stdout.write(Wn(a)+`
138
140
  `):process.stdout.write(JSON.stringify(a,null,2)+`
139
141
  `)}catch(a){process.stderr.write(`${a.message}
140
- `),process.exit(1)}}Fn();
142
+ `),process.exit(1)}}Qn();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ec.fdk",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "ec frontend sdk",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {
package/skill/SKILL.md ADDED
@@ -0,0 +1,290 @@
1
+ ---
2
+ name: ec-fdk
3
+ description: Use when interacting with entrecode APIs, managing datamanagers, models, entries, assets, roles, accounts, or any ec.fdk CLI operations. Use when user mentions ec.fdk, entrecode, datamanager, shortID, or wants to open ec.editor4 URLs.
4
+ ---
5
+
6
+ # ec.fdk CLI
7
+
8
+ Use the `ec.fdk` CLI + `jq` for all entrecode API interactions. Always pipe output through `jq` to minimize tokens in context.
9
+
10
+ ## Entry Commands (require `--dm`, `--model`)
11
+
12
+ ```sh
13
+ # List entries
14
+ ec.fdk entryList -d <shortID> -m <model> | jq '.items'
15
+
16
+ # List entries sorted by newest first
17
+ ec.fdk entryList -d <shortID> -m <model> --sort=-_created -s 1
18
+
19
+ # List entries with filters
20
+ ec.fdk entryList -d <shortID> -m <model> -f name~=chocolate -f createdFrom=2024-01-01
21
+
22
+ # Get a single entry
23
+ ec.fdk getEntry -d <shortID> -m <model> -i <entryID>
24
+
25
+ # Get model schema (returns field names as top-level keys)
26
+ ec.fdk getSchema -d <shortID> -m <model> | jq 'keys'
27
+
28
+ # Create an entry
29
+ ec.fdk createEntry -d <shortID> -m <model> --data '{"name":"new","value":10}'
30
+
31
+ # Create via stdin pipe
32
+ echo '{"name":"piped"}' | ec.fdk createEntry -d <shortID> -m <model>
33
+
34
+ # Edit an entry
35
+ ec.fdk editEntry -d <shortID> -m <model> -i <entryID> --data '{"name":"updated"}'
36
+
37
+ # Delete an entry
38
+ ec.fdk deleteEntry -d <shortID> -m <model> -i <entryID>
39
+ ```
40
+
41
+ ## Datamanager Commands
42
+
43
+ ```sh
44
+ # Find a datamanager's shortID
45
+ ec.fdk dmList -f title=HO | jq '.items[0].shortID'
46
+
47
+ # Find a datamanager's UUID
48
+ ec.fdk dmList -f title=HO | jq '.items[0].dataManagerID'
49
+
50
+ # Get a single datamanager
51
+ ec.fdk getDatamanager --id <dataManagerID>
52
+
53
+ # Create a datamanager
54
+ ec.fdk createDatamanager --data '{"title":"My DM","config":{}}'
55
+
56
+ # editDatamanager is a full PUT — pass the complete resource, not just changed fields.
57
+ ec.fdk getDatamanager --id <dataManagerID> \
58
+ | jq '.title = "New Title"' \
59
+ | ec.fdk editDatamanager --id <dataManagerID>
60
+
61
+ # Delete a datamanager
62
+ ec.fdk deleteDatamanager --id <dataManagerID>
63
+
64
+ # Datamanager stats
65
+ ec.fdk getStats
66
+ ```
67
+
68
+ ## Model Commands (`--id` = DM UUID)
69
+
70
+ ```sh
71
+ # List models of a datamanager
72
+ ec.fdk modelList --id <dataManagerID> | jq '[.items[].title]'
73
+
74
+ # Search models by name
75
+ ec.fdk modelList --id <dataManagerID> -f title~=muffin | jq '[.items[].title]'
76
+
77
+ # Create a model
78
+ ec.fdk createModel --id <dataManagerID> --data '{"title":"article","locales":[],"fields":[]}'
79
+
80
+ # Edit a model
81
+ ec.fdk editModel --id <dataManagerID> --rid <modelID> --data '{"title":"renamed","locales":[],"fields":[]}'
82
+
83
+ # Delete a model
84
+ ec.fdk deleteModel --id <dataManagerID> --rid <modelID>
85
+ ```
86
+
87
+ ## Generic Resource Commands
88
+
89
+ For any resource type not covered by specific commands, use `resource*`:
90
+
91
+ ```sh
92
+ # List any resource type
93
+ ec.fdk resourceList --resource template -s 5
94
+ ec.fdk resourceList --resource client --subdomain accounts
95
+
96
+ # Get / edit / delete (use -f to identify the resource)
97
+ ec.fdk resourceGet --resource model -f dataManagerID=<dataManagerID> -f modelID=<modelID>
98
+ ec.fdk resourceGet --resource group --subdomain accounts -f groupID=<groupID>
99
+ ec.fdk resourceEdit --resource invite --subdomain accounts -f invite=<inviteID> --data '{"email":"user@example.com","permissions":["dm-read"],"groups":[]}'
100
+ ec.fdk resourceDelete --resource role -f dataManagerID=<dataManagerID> -f roleID=<roleID>
101
+ ```
102
+
103
+ ### `resourceList` Resource Types
104
+
105
+ | `--resource` | `--subdomain` | Typical filters |
106
+ | --- | --- | --- |
107
+ | `model` | — | `-f dataManagerID=<dataManagerID>` |
108
+ | `assetgroup` | — | `-f dataManagerID=<dataManagerID>` |
109
+ | `client` | — | `-f dataManagerID=<dataManagerID>` |
110
+ | `role` | — | `-f dataManagerID=<dataManagerID>` |
111
+ | `account` | — | `-f dataManagerID=<dataManagerID>` |
112
+ | `template` | — | — |
113
+ | `tag` | — | `-f dataManagerID=<dataManagerID>` |
114
+ | `account` | `accounts` | — |
115
+ | `client` | `accounts` | — |
116
+ | `group` | `accounts` | — |
117
+ | `invite` | `accounts` | — |
118
+ | `account/tokens` | `accounts` | `-f accountID=<accountID>` |
119
+
120
+ ## Other Admin Commands
121
+
122
+ ```sh
123
+ # Login via browser OIDC (stores token in ~/.ec-fdk/auth.json)
124
+ ec.fdk login -e stage
125
+
126
+ # Login via email/password prompt
127
+ ec.fdk login -e stage --password
128
+
129
+ # Logout (removes stored token)
130
+ ec.fdk logout -e stage
131
+
132
+ # Show current user
133
+ ec.fdk whoami -e stage
134
+
135
+ # dm-history (requires shortID filter)
136
+ ec.fdk getHistory -f shortID=<shortID> -s 10
137
+
138
+ # Template
139
+ ec.fdk createTemplate --data '{"name":"My Template","collection":{"id":"<collectionID>","name":"my-collection","order":[],"requests":[]}}'
140
+
141
+ # Asset group
142
+ ec.fdk createAssetGroup --id <dataManagerID> --data '{"assetGroupID":"photos"}'
143
+ ec.fdk editAssetGroup --id <dataManagerID> --rid <assetGroup> --data '{"public":true}'
144
+
145
+ # Asset metadata
146
+ ec.fdk editAsset --dm <shortID> --assetgroup <assetGroup> --rid <assetID> --data '{"title":"sunset"}'
147
+
148
+ # DM client
149
+ ec.fdk editDmClient --id <dataManagerID> --rid <clientID> --data '{"callbackURL":"https://example.com/cb"}'
150
+
151
+ # Role
152
+ ec.fdk createRole --id <dataManagerID> --data '{"name":"editor"}'
153
+ ec.fdk editRole --id <dataManagerID> --rid <roleID> --data '{"name":"admin"}'
154
+ ec.fdk deleteRole --id <dataManagerID> --rid <roleID>
155
+
156
+ # DM account
157
+ ec.fdk editDmAccount --id <dataManagerID> --account-id <accountID> --data '{"email":"user@example.com"}'
158
+ ec.fdk deleteDmAccount --id <dataManagerID> --account-id <accountID>
159
+
160
+ # Account client (editAccountClient is a full PUT — clientID is required in the body)
161
+ ec.fdk createAccountClient --data '{"clientID":"my-client","callbackURL":"https://example.com/cb"}'
162
+ ec.fdk deleteAccountClient --rid <clientID>
163
+
164
+ # Group
165
+ ec.fdk createGroup --data '{"name":"devs"}'
166
+ ec.fdk editGroup --rid <groupID> --data '{"name":"developers"}'
167
+ ec.fdk deleteGroup --rid <groupID>
168
+
169
+ # Invite (editInvite is a full PUT — pass the complete resource)
170
+ ec.fdk createInvite --data '{"email":"user@example.com"}'
171
+ ec.fdk editInvite --rid <inviteID> --data '{"email":"user@example.com","permissions":["dm-read"],"groups":[]}'
172
+ ec.fdk deleteInvite --rid <inviteID>
173
+
174
+ # Account
175
+ ec.fdk editAccount --account-id <accountID> --data '{"email":"user@example.com"}'
176
+
177
+ # Tokens
178
+ ec.fdk listTokens --account-id <accountID>
179
+ ec.fdk createToken --account-id <accountID>
180
+ ec.fdk deleteToken --account-id <accountID> --rid <tokenID>
181
+ ```
182
+
183
+ ## Quick Reference
184
+
185
+ | Command | Required flags |
186
+ | --- | --- |
187
+ | **Entry** (require `--dm`, `--model`) | |
188
+ | `entryList` | `--dm`, `--model` |
189
+ | `getEntry` | `--dm`, `--model`, `--id` |
190
+ | `createEntry` | `--dm`, `--model`, `--data` |
191
+ | `editEntry` | `--dm`, `--model`, `--id`, `--data` |
192
+ | `deleteEntry` | `--dm`, `--model`, `--id` |
193
+ | `getSchema` | `--dm`, `--model` |
194
+ | **Datamanager** (`--id` = DM UUID) | |
195
+ | `dmList` | — |
196
+ | `getDatamanager` | `--id` |
197
+ | `createDatamanager` | `--data` |
198
+ | `editDatamanager` | `--id`, `--data` (full PUT) |
199
+ | `deleteDatamanager` | `--id` |
200
+ | `getStats` | — |
201
+ | **Model** (`--id` = DM UUID) | |
202
+ | `modelList` | `--id` |
203
+ | `createModel` | `--id`, `--data` |
204
+ | `editModel` | `--id`, `--rid`, `--data` |
205
+ | `deleteModel` | `--id`, `--rid` |
206
+ | **Generic resource** | |
207
+ | `resourceList` | `--resource` |
208
+ | `resourceGet` | `--resource`, `-f` filters |
209
+ | `resourceEdit` | `--resource`, `-f` filters, `--data` |
210
+ | `resourceDelete` | `--resource`, `-f` filters |
211
+ | **Auth** | |
212
+ | `login` | — (add `--password` for email/password prompt) |
213
+ | `logout` | — |
214
+ | `whoami` | — |
215
+ | `install-skill` | — (optional `--dir <path>`) |
216
+
217
+ ## Options
218
+
219
+ | Option | Description |
220
+ | --- | --- |
221
+ | `-e, --env` | `stage` (default) or `live` |
222
+ | `-d, --dm` | DataManager short ID |
223
+ | `-m, --model` | Model name |
224
+ | `-i, --id` | Entry ID or DataManager UUID (context-dependent) |
225
+ | `--rid` | Resource ID (model, role, client, asset group, invite, token, etc.) |
226
+ | `--account-id` | Account ID |
227
+ | `--assetgroup` | Asset group name (for `editAsset`) |
228
+ | `--resource` | Resource name (for `resource*` commands) |
229
+ | `--subdomain` | Subdomain override (for `resource*` commands, default: `datamanager`) |
230
+ | `--data` | JSON data (via flag or stdin pipe) |
231
+ | `-s, --size` | Page size |
232
+ | `-p, --page` | Page number |
233
+ | `--sort` | Sort field (system fields: `_created`, `_modified`) |
234
+ | `-f, --filter` | Repeatable filter (`key=value`) |
235
+ | `--password` | Use email/password login instead of browser OIDC |
236
+ | `--dir` | Target directory for `install-skill` (default: `~/.claude`) |
237
+ | `--raw` | Include `_links` and `_embedded` |
238
+ | `--md` | Output as markdown table |
239
+
240
+ ## Filter Suffixes
241
+
242
+ Filters map to entrecode filter query params:
243
+
244
+ - `~` — search (contains): `-f name~=chocolate`
245
+ - `From` — greater than / after: `-f createdFrom=2024-01-01`
246
+ - `To` — less than / before: `-f createdTo=2025-01-01`
247
+ - (none) — exact match: `-f title=HO`
248
+
249
+ ## Common Mistakes
250
+
251
+ - **Using `--id` for entry commands** — entry commands need `--dm` (shortID) + `--model`, not `--id` for the DM
252
+ - **Partial PUT on editDatamanager/editAccountClient/editInvite** — these are full PUT operations, pass the complete resource
253
+ - **Forgetting `jq`** — always pipe through `jq` to keep output concise
254
+ - **Wrong ID type** — `--dm` takes shortID, `--id` takes UUID for datamanager commands
255
+
256
+ ## ec.editor4 URLs
257
+
258
+ Base URLs:
259
+ - Stage: `https://e4.cachena.entrecode.de`
260
+ - Live: `https://e4.entrecode.de`
261
+
262
+ When the user asks to "open" a resource, output the full editor URL. Use `open <url>` via Bash to open it in the browser. Default to stage unless the user specifies live.
263
+
264
+ | Resource | URL pattern |
265
+ |---|---|
266
+ | Datamanager | `/d/{shortID}` |
267
+ | Model list | `/d/{shortID}/model` |
268
+ | Model entries | `/d/{shortID}/model/{model}/entry` |
269
+ | Model settings | `/d/{shortID}/model/{model}/settings` |
270
+ | Create entry | `/d/{shortID}/model/{model}/entry/create` |
271
+ | Entry | `/d/{shortID}/model/{model}/entry/{entryID}` |
272
+ | Entry history | `/d/{shortID}/model/{model}/entry/{entryID}/history` |
273
+ | Asset groups | `/d/{shortID}/assetgroup` |
274
+ | Asset group | `/d/{shortID}/assetgroup/{assetgroup}` |
275
+ | Asset | `/d/{shortID}/assetgroup/{assetgroup}/asset/{assetID}` |
276
+ | Roles | `/d/{shortID}/roles` |
277
+ | Role | `/d/{shortID}/roles/{roleID}` |
278
+ | Clients | `/d/{shortID}/clients` |
279
+ | DM Accounts | `/d/{shortID}/accounts` |
280
+ | DM Graph | `/d/{shortID}/graph` |
281
+ | DM Settings | `/d/{shortID}/settings` |
282
+ | Accounts | `/accounts` |
283
+ | Account | `/accounts/{accountID}` |
284
+ | Apps | `/apps` |
285
+
286
+ ## Notes
287
+
288
+ - Status/error messages go to stderr, data goes to stdout — piping always works cleanly
289
+ - `editDatamanager`, `editAccountClient`, and `editInvite` are full PUT operations — pass the complete resource
290
+ - `--data` accepts JSON via flag or stdin pipe (e.g. `echo '{}' | ec.fdk createEntry ...`)