@nice2dev/ui-forms 1.4.4 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/studio.cjs CHANGED
@@ -1,10 +1,26 @@
1
- "use strict";var Se=Object.defineProperty;var je=(e,t,n)=>t in e?Se(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var H=(e,t,n)=>je(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Z="\uFEFF",Q={bom:!1,eol:`
2
- `,indent:" ",finalNewline:!0,colonSpace:!0};function P(e){const t=e.charCodeAt(0)===65279,n=e.includes(`\r
1
+ "use strict";var qe=Object.defineProperty;var Ve=(e,t,n)=>t in e?qe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var se=(e,t,n)=>Ve(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const M=()=>({version:1,sections:[],folders:[],placement:{}}),ze=(e,t)=>`${e}:${t}`,W=".studio.json",We=/^([^/]+?)\.(manifest|entities|views|workflows|permissions|rbac|seeds|datasources|scripts)\.json$/i,ae=e=>!e.includes("/")&&e.toLowerCase().endsWith(W);function Be(e){const t=e.find(n=>ae(n.path));if(t)return t.path;for(const n of e){const s=We.exec(n.path);if(s)return`${s[1]}${W}`}return`module${W}`}const N=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),b=e=>typeof e=="string"&&e?e:void 0;function He(e){if(!e)return M();let t;try{t=JSON.parse(e.replace(/^\uFEFF/,""))}catch{return M()}if(!N(t))return M();const n=(Array.isArray(t.sections)?t.sections:[]).filter(N).map(r=>({id:b(r.id),label:b(r.label)??b(r.id)})).filter(r=>!!r.id&&!!r.label),s=(Array.isArray(t.folders)?t.folders:[]).filter(N).map(r=>({id:b(r.id),label:b(r.label)??b(r.id),group:b(r.group),...b(r.parent)?{parent:b(r.parent)}:{},...b(r.section)?{section:b(r.section)}:{}})).filter(r=>!!r.id&&!!r.label&&!!r.group),i={};if(N(t.placement))for(const[r,a]of Object.entries(t.placement)){if(!N(a))continue;const l={};b(a.section)&&(l.section=b(a.section)),b(a.folder)&&(l.folder=b(a.folder)),typeof a.order=="number"&&Number.isFinite(a.order)&&(l.order=a.order),(l.section||l.folder||l.order!==void 0)&&(i[r]=l)}return{version:1,sections:n,folders:s,placement:i}}const Xe=e=>e.sections.length===0&&e.folders.length===0&&Object.keys(e.placement).length===0;function Ze(e,t){const n=JSON.stringify(e,null,2)+`
2
+ `;return t!=null&&t.includes(`\r
3
+ `)?n.replace(/\n/g,`\r
4
+ `):n}const Ge=e=>e.toLowerCase().normalize("NFKD").replace(/[̀-ͯ]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"item";function ce(e,t){const n=Ge(e);let s=n;for(let i=2;t.has(s);i++)s=`${n}-${i}`;return s}function Ye(e,t){const n=ce(t,new Set(e.sections.map(s=>s.id)));return{layout:{...e,sections:[...e.sections,{id:n,label:t}]},id:n}}function Qe(e,t){const n=ce(t.label,new Set(e.folders.map(i=>i.id))),s={id:n,label:t.label,group:t.group};return t.parent&&(s.parent=t.parent),t.section&&(s.section=t.section),{layout:{...e,folders:[...e.folders,s]},id:n}}function et(e,t,n){return t.kind==="section"?{...e,sections:e.sections.map(s=>s.id===t.id?{...s,label:n}:s)}:{...e,folders:e.folders.map(s=>s.id===t.id?{...s,label:n}:s)}}function tt(e,t){const n={};if(t.kind==="folder"){const s=e.folders.find(i=>i.id===t.id);for(const[i,r]of Object.entries(e.placement))n[i]=r.folder===t.id?{...r,folder:s==null?void 0:s.parent}:r,n[i].folder||delete n[i].folder;return{...e,folders:e.folders.filter(i=>i.id!==t.id).map(i=>i.parent===t.id?{...i,parent:s==null?void 0:s.parent}:i).map(i=>{if(!i.parent){const{parent:r,...a}=i;return a}return i}),placement:B(n)}}for(const[s,i]of Object.entries(e.placement))if(i.section===t.id){const{section:r,...a}=i;n[s]=a}else n[s]=i;return{...e,sections:e.sections.filter(s=>s.id!==t.id),folders:e.folders.map(s=>{if(s.section===t.id){const{section:i,...r}=s;return r}return s}),placement:B(n)}}function B(e){const t={};for(const[n,s]of Object.entries(e))(s.section||s.folder||s.order!==void 0)&&(t[n]=s);return t}function nt(e,t,n){var r;const s=(r=e.placement[t])==null?void 0:r.order,i={};if(n.folder){i.folder=n.folder;const a=e.folders.find(l=>l.id===n.folder);a!=null&&a.section&&(i.section=a.section)}else n.section&&(i.section=n.section);return s!==void 0&&(i.order=s),{...e,placement:B({...e.placement,[t]:i})}}function st(e,t,n){if(t===n||!e.placement[t])return e;const s={...e.placement,[n]:e.placement[t]};return delete s[t],{...e,placement:s}}const le="\uFEFF",de={bom:!1,eol:`
5
+ `,indent:" ",finalNewline:!0,colonSpace:!0};function q(e){const t=e.charCodeAt(0)===65279,n=e.includes(`\r
3
6
  `)?`\r
4
7
  `:`
5
- `;let i=Q.indent;const r=e.split(/\r?\n/);for(let c=1;c<r.length;c++){const d=/^([ \t]+)\S/.exec(r[c]);if(d){i=d[1];break}}const a=/"\s*:(\s?)/.exec(e);return{bom:t,eol:n,indent:i,finalNewline:/\n$/.test(e),colonSpace:a?a[1]!=="":!0}}function K(e){const t=P(e);return{value:JSON.parse(t.bom?e.slice(1):e),format:t}}function w(e,t){const n={...Q,...t},i=O(e,n,"");return(n.bom?Z:"")+i+(n.finalNewline?n.eol:"")}function ee(e,t){if(t===void 0)return e;let n=t.includes(`\r
8
+ `;let s=de.indent;const i=e.split(/\r?\n/);for(let a=1;a<i.length;a++){const l=/^([ \t]+)\S/.exec(i[a]);if(l){s=l[1];break}}const r=/"\s*:(\s?)/.exec(e);return{bom:t,eol:n,indent:s,finalNewline:/\n$/.test(e),colonSpace:r?r[1]!=="":!0}}function A(e){const t=q(e);return{value:JSON.parse(t.bom?e.slice(1):e),format:t}}function S(e,t){const n={...de,...t},s=E(e,n,"");return(n.bom?le:"")+s+(n.finalNewline?n.eol:"")}function fe(e,t){if(t===void 0)return e;let n=t.includes(`\r
6
9
  `)?e.replace(/\r?\n/g,`\r
7
- `):e;return t.charCodeAt(0)===65279&&n.charCodeAt(0)!==65279&&(n=Z+n),n}function x(e,t){if(e===t)return!0;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return!1;if(Array.isArray(e)){const a=t;return e.length===a.length&&e.every((c,d)=>x(c,a[d]))}const n=e,i=t,r=Object.keys(n);return r.length!==Object.keys(i).length?!1:r.every(a=>Object.prototype.hasOwnProperty.call(i,a)&&x(n[a],i[a]))}function q(e,t,n){return te(e,t,n).text}function te(e,t,n){const i=P(e),r=s=>({text:w(t,i),exact:!1,reason:s});let a;try{a=new Ke(e).parseDocument()}catch(s){return r(s instanceof Error?s.message:String(s))}if(C(a))return r("duplicate keys");const c=[],d={text:e,format:i,edits:c,options:n,compact:!e.trimEnd().includes(`
8
- `)};z(d,a,t,"",!1);const u=Oe(e,c);try{const s=JSON.parse(i.bom?u.slice(1):u);if(!x(s,t))return r("patch did not read back")}catch{return r("patch was not valid JSON")}return{text:u,exact:!0}}class Ke{constructor(t){H(this,"pos",0);this.text=t}parseDocument(){this.text.charCodeAt(0)===65279&&(this.pos=1);const t=this.value();if(this.ws(),this.pos<this.text.length)throw new Error(`Unexpected text at ${this.pos}`);return t}ws(){for(;this.pos<this.text.length&&/\s/.test(this.text[this.pos]);)this.pos++}value(){this.ws();const t=this.text[this.pos];if(t==="{")return this.object();if(t==="[")return this.array();const n=this.pos;if(t==='"')return{kind:"scalar",start:n,end:this.stringEnd(),value:JSON.parse(this.slice(n))};const i=/^(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/.exec(this.text.slice(n,n+64));if(!i)throw new Error(`Unexpected token at ${n}`);return this.pos=n+i[0].length,{kind:"scalar",start:n,end:this.pos,value:JSON.parse(i[0])}}slice(t){return this.text.slice(t,this.pos)}stringEnd(){for(this.pos++;this.pos<this.text.length;){const t=this.text[this.pos];if(t==="\\"){this.pos+=2;continue}if(this.pos++,t==='"')return this.pos}throw new Error("Unterminated string")}object(){const t=this.pos++,n=[];if(this.ws(),this.text[this.pos]==="}")return{kind:"object",start:t,end:++this.pos,members:n};for(;;){this.ws();const i=this.pos;if(this.text[this.pos]!=='"')throw new Error(`Expected a key at ${this.pos}`);const r=JSON.parse(this.text.slice(i,this.stringEnd()));if(this.ws(),this.text[this.pos]!==":")throw new Error(`Expected ':' at ${this.pos}`);this.pos++,n.push({key:r,start:i,value:this.value()}),this.ws();const a=this.text[this.pos++];if(a==="}")return{kind:"object",start:t,end:this.pos,members:n};if(a!==",")throw new Error(`Expected ',' or '}' at ${this.pos-1}`)}}array(){const t=this.pos++,n=[];if(this.ws(),this.text[this.pos]==="]")return{kind:"array",start:t,end:++this.pos,items:n};for(;;){n.push(this.value()),this.ws();const i=this.text[this.pos++];if(i==="]")return{kind:"array",start:t,end:this.pos,items:n};if(i!==",")throw new Error(`Expected ',' or ']' at ${this.pos-1}`)}}}function C(e){if(e.kind==="object"){const t=new Set;for(const n of e.members){if(t.has(n.key)||C(n.value))return!0;t.add(n.key)}}else if(e.kind==="array")return e.items.some(C);return!1}function M(e){if(e.kind==="scalar")return e.value;if(e.kind==="array")return e.items.map(M);const t={};for(const n of e.members)t[n.key]=M(n.value);return t}function O(e,t,n){if(e===null||typeof e!="object")return e===void 0?"null":JSON.stringify(e);const i=n+t.indent,r=t.colonSpace?": ":":";if(Array.isArray(e))return e.length===0?"[]":`[${t.eol}${e.map(c=>i+O(c,t,i)).join(`,${t.eol}`)}${t.eol}${n}]`;const a=Object.entries(e).filter(([,c])=>c!==void 0);return a.length===0?"{}":`{${t.eol}${a.map(([c,d])=>`${i}${JSON.stringify(c)}${r}${O(d,t,i)}`).join(`,${t.eol}`)}${t.eol}${n}}`}function A(e,t,n=!1){if(e===null||typeof e!="object")return e===void 0?"null":JSON.stringify(e);const i=t.colonSpace?": ":":",r=n?",":", ";if(Array.isArray(e))return`[${e.map(d=>A(d,t,n)).join(r)}]`;const a=Object.entries(e).filter(([,d])=>d!==void 0),c=n?"":" ";return a.length===0?"{}":`{${c}${a.map(([d,u])=>`${JSON.stringify(d)}${i}${A(u,t,n)}`).join(r)}${c}}`}const ne=e=>e.compact?",":", ";function Oe(e,t){let n=e;for(const i of[...t].sort((r,a)=>a.start-r.start))n=n.slice(0,i.start)+i.text+n.slice(i.end);return n}function F(e,t){var i;const n=e.lastIndexOf(`
9
- `,t-1)+1;return((i=/^[ \t]*/.exec(e.slice(n,t)))==null?void 0:i[0])??""}function se(e,t){return!e.slice(t.start,t.end).includes(`
10
- `)}function _(e,t,n){return e.compact?!0:t.kind==="scalar"||(t.kind==="object"?t.members.length===0:t.items.length===0)?n:se(e.text,t)}function N(e,t,n,i){const r=_(e,t,i);e.edits.push({start:t.start,end:t.end,text:r?A(n,e.format,e.compact):O(n,e.format,F(e.text,t.start))})}const ie=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function z(e,t,n,i,r){if(t.kind==="scalar"){if(t.value===n)return;N(e,t,n,r);return}x(M(t),n)||(t.kind==="object"&&ie(n)?Ae(e,t,n,i,r):t.kind==="array"&&Array.isArray(n)?Ne(e,t,n,i,r):N(e,t,n,r))}function re(e,t,n){return n!==void 0?F(e.text,n):F(e.text,t.start)+e.format.indent}function Ae(e,t,n,i,r){var l;const a=_(e,t,r),c=t.members.filter(f=>Object.prototype.hasOwnProperty.call(n,f.key)&&n[f.key]!==void 0),d=Object.keys(n).filter(f=>n[f]!==void 0&&!t.members.some(h=>h.key===f));if(c.length===0&&t.members.length>0){N(e,t,n,r);return}for(const f of c)z(e,f.value,n[f.key],`${i}/${Fe(f.key)}`,a);if(oe(e,t.members.map(f=>({start:f.start,end:f.value.end})),t.members.map(f=>c.includes(f))),d.length===0)return;const u=e.format.colonSpace?": ":":";if(a){const f=d.map(h=>`${JSON.stringify(h)}${u}${A(n[h],e.format,e.compact)}`);ce(e,t,c.length>0?c[c.length-1].value.end:void 0,f);return}const s=re(e,t,(l=t.members[0])==null?void 0:l.start),o=d.map(f=>`${s}${JSON.stringify(f)}${u}${O(n[f],e.format,s)}`);ae(e,t,c.length>0?c[c.length-1].value.end:void 0,o)}const Ee=["name","id","code","key","slug","state","Id"];function xe(e,t,n,i){var u,s;const r=[...n,...i];if(r.length===0||!r.every(ie))return;const a=(o,l)=>{const f=o.map(h=>h[l]);return f.every(h=>typeof h=="string"||typeof h=="number")&&new Set(f).size===f.length},c=(s=(u=e.options)==null?void 0:u.arrayKey)==null?void 0:s.call(u,t);return(c?[c]:Ee).find(o=>a(n,o)&&a(i,o))}function Ne(e,t,n,i,r){var g;const a=_(e,t,r),c=t.items.map(M),d=xe(e,i,c,n),u=p=>p[d],s=d!==void 0?c.map(p=>{const m=u(p);return n.findIndex(b=>u(b)===m)}):Me(c,n);{const p=new Set(s.filter(m=>m>=0));for(let m=0;m<s.length;m++){if(s[m]>=0)continue;let b=-1;for(let y=m-1;y>=0;y--)if(s[y]>=0){b=s[y];break}let $=n.length;for(let y=m+1;y<s.length;y++)if(s[y]>=0){$=s[y];break}for(let y=b+1;y<$;y++)if(!p.has(y)){s[m]=y,p.add(y);break}}}const o=s.filter(p=>p>=0);if(o.some((p,m)=>m>0&&p<o[m-1])){N(e,t,n,r);return}if(o.length===0&&t.items.length>0){N(e,t,n,r);return}t.items.forEach((p,m)=>{s[m]>=0&&z(e,p,n[s[m]],`${i}/${s[m]}`,a)}),oe(e,t.items.map(p=>({start:p.start,end:p.end})),s.map(p=>p>=0));const l=t.items.length>0&&t.items.every(p=>p.kind!=="scalar"&&se(e.text,p)),f=re(e,t,(g=t.items[0])==null?void 0:g.start),h=new Map;n.forEach((p,m)=>{if(s.includes(m))return;let b;for(let S=t.items.length-1;S>=0;S--)if(s[S]>=0&&s[S]<m){b=S;break}const $=a?A(p,e.format,e.compact):l?`${f}${A(p,e.format)}`:`${f}${O(p,e.format,f)}`,y=h.get(b)??[];y.push($),h.set(b,y)});for(const[p,m]of h){const b=p===void 0?void 0:t.items[p].end;if(p===void 0&&o.length>0){const $=t.items[s.findIndex(S=>S>=0)],y=a?ne(e):`,${e.format.eol}`;e.edits.push({start:$.start,end:$.start,text:a?m.join(y)+y:m.join(y).trimStart()+y+f});continue}a?ce(e,t,b,m):ae(e,t,b,m)}}const Ie=4e6;function Me(e,t){const n=e.length,i=t.length;if(n*i>Ie)return e.map((o,l)=>l<i?l:-1);const r=e.map(o=>JSON.stringify(o)),a=t.map(o=>JSON.stringify(o)),c=Array.from({length:n+1},()=>new Uint32Array(i+1));for(let o=n-1;o>=0;o--)for(let l=i-1;l>=0;l--)c[o][l]=r[o]===a[l]?c[o+1][l+1]+1:Math.max(c[o+1][l],c[o][l+1]);const d=new Array(n).fill(-1);let u=0,s=0;for(;u<n&&s<i;)r[u]===a[s]?d[u++]=s++:c[u+1][s]>=c[u][s+1]?u++:s++;return d}function oe(e,t,n){for(let i=0;i<t.length;i++){if(n[i])continue;let r=i;for(;r+1<t.length&&!n[r+1];)r++;r+1<t.length?e.edits.push({start:t[i].start,end:t[r+1].start,text:""}):i>0?e.edits.push({start:t[i-1].end,end:t[r].end,text:""}):e.edits.push({start:t[i].start,end:t[r].end,text:""}),i=r}}function ae(e,t,n,i){const r=e.format.eol;if(n!==void 0){e.edits.push({start:n,end:n,text:`,${r}${i.join(`,${r}`)}`});return}const a=t.end-1;if((t.kind==="object"?t.members.length:t.items.length)===0)e.edits.push({start:t.start+1,end:a,text:`${r}${i.join(`,${r}`)}${r}${F(e.text,t.start)}`});else{const d=t.kind==="object"?t.members[0].start:t.items[0].start;e.edits.push({start:d,end:d,text:`${i.join(`,${r}`).trimStart()}`})}}function ce(e,t,n,i){const r=ne(e);if(n!==void 0){e.edits.push({start:n,end:n,text:`${r}${i.join(r)}`});return}const a=t.kind==="object"&&!e.compact?" ":"";e.edits.push({start:t.start+1,end:t.end-1,text:`${a}${i.join(r)}${a}`})}function Fe(e){return e.replace(/~/g,"~0").replace(/\//g,"~1")}const j=e=>e.slice(e.lastIndexOf("/")+1),Te=e=>e.charCodeAt(0)===65279?e.slice(1):e;function V(e){return{id:e.id,label:e.label,labelKey:e.labelKey,icon:e.icon,match:e.match,editor:e.editor,decode(t,n){return e.select(K(t[0].text).value,n)},encode(t,n,i){const r=n[0].text,a=K(r).value,c=e.assign(a,t,i);return{files:[{path:n[0].path,text:q(r,c,{arrayKey:e.arrayKey})}]}}}}const T=V({id:"json",label:"JSON",labelKey:"devStudio.kind.json",icon:"code",match:e=>e.toLowerCase().endsWith(".json"),editor:"json",select:e=>e,assign:(e,t)=>t}),J={id:"text",label:"Text",labelKey:"devStudio.kind.text",icon:"file",match:()=>!0,editor:"text",decode:e=>e[0].text,encode:(e,t)=>({files:[{path:t[0].path,text:ee(e,t[0].text)}]})};function le(e,t){return e.find(n=>n.match(t))??(T.match(t)?T:J)}function Je(e,t,n){for(const i of[T,J])if(i.match(e.path))try{const r=i.decode([e],n);return{key:`${i.id}:${e.path}`,kind:i,paths:[e.path],label:j(e.path),model:r,error:t}}catch{}return{key:`text:${e.path}`,kind:J,paths:[e.path],label:j(e.path),model:e.text,error:t}}function De(e,t,n,i){var d,u;const r=e.encode(t,n,i),a=new Map(n.map(s=>[s.path,s.text])),c=((d=r.files.find(s=>a.get(s.path)!==s.text))==null?void 0:d.path)??((u=r.deleted)==null?void 0:u.find(s=>a.has(s)));if(c!==void 0)throw new Error(`${j(c)} would not be stored as it is`)}function Pe(e,t,n){const i=new Map;for(const a of t){const c=le(e,a.path),d=c.group?c.group(a.path):a.path,u=`${c.id}:${d}`,s=i.get(u)??{kind:c,group:d,files:[]};s.files.push(a),i.set(u,s)}const r=[];for(const[a,{kind:c,group:d,files:u}]of i){const s=u.map(l=>l.path).sort(),o=j(c.group?d:s[0]);try{const l=c.decode(u,n);De(c,l,u,n),r.push({key:a,kind:c,paths:s,label:o,model:l})}catch(l){const f=l instanceof Error?l.message:String(l);for(const h of u)r.push(Je(h,f,n))}}return r.sort((a,c)=>a.label.localeCompare(c.label))}function Ve(e,t,n,i){const r=n.filter(u=>e.paths.includes(u.path)),a=e.kind.encode(t,r,i),c=new Map(n.map(u=>[u.path,u])),d=[];for(const u of a.files){const s=c.get(u.path);s&&s.text===u.text||d.push({type:"write",path:u.path,text:u.text,baseVersion:s==null?void 0:s.version})}for(const u of a.deleted??[]){const s=c.get(u);s&&d.push({type:"delete",path:u,baseVersion:s.version})}return d}function de(e,t){try{return JSON.parse(Te(e))}catch{return t}}const k=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),v=(...e)=>t=>{const n=t.toLowerCase();return e.some(i=>n.endsWith(i.toLowerCase()))};function I(e){return V({id:e.id,label:e.label,labelKey:e.labelKey,icon:e.icon,editor:e.editor,match:e.match,select:t=>{if(Array.isArray(t))return t;const n=k(t)?t[e.property]:void 0;return Array.isArray(n)?n:[]},assign:(t,n)=>Array.isArray(t)?n:k(t)&&!(e.property in t)&&n.length===0?t:{...k(t)?t:{},[e.property]:n},arrayKey:e.itemKey?()=>e.itemKey:void 0})}function B(e){const t=I(e);return{...t,decode:(n,i)=>t.decode(n,i).map((r,a)=>e.toItem(r,a)),encode:(n,i,r)=>t.encode(n.map(a=>e.fromItem(a)),i,r)}}function G(e){return V({...e,select:t=>k(t)?t:{},assign:(t,n)=>n})}const Le=/^(.*)\.([a-z]{2,3}(?:-[A-Za-z]{2,4})?)\.i18n\.json$/i,Ce=e=>{const t=Le.exec(e);return t?{group:t[1],locale:t[2]}:null},R=e=>k(e)&&Object.values(e).every(t=>typeof t=="string");function fe(e){if(k(e)){for(const t of["translations","keys"])if(t in e){if(R(e[t]))return e[t];throw new Error(`"${t}" is not a flat map of texts`)}if(R(e))return e}throw new Error("no translations in this file")}function U(e,t){return k(e)?k(e.translations)?{...e,translations:t}:k(e.keys)?{...e,keys:t}:R(e)?t:{...e,translations:t}:{translations:t}}function ue(e={}){const t=e.parse??Ce,n=e.pathFor??((i,r)=>`${i}.${r}.i18n.json`);return{id:e.id??"i18n",label:e.label??"Translations",labelKey:e.labelKey??"devStudio.kind.i18n",icon:"globe",editor:"i18n",match:i=>t(i)!==null,group:i=>{var r;return((r=t(i))==null?void 0:r.group)??i},decode(i){const r={};for(const a of i){const c=t(a.path);c&&(r[c.locale]={...fe(K(a.text).value)})}return r},encode(i,r){const a=new Map;let c="";for(const o of r){const l=t(o.path);l&&(a.set(l.locale,o),c=l.group)}const d=a.get("en")??r[0],u=[];for(const[o,l]of Object.entries(i)){const f=a.get(o);if(f){const g=K(f.text).value;u.push({path:f.path,text:q(f.text,U(g,l))});continue}const h=n(c||j((d==null?void 0:d.path)??"module"),o);if(d){const g=K(d.text).value,p=k(g)&&"locale"in g?{...g,locale:o}:g;u.push({path:h,text:w(U(p,l),P(d.text))})}else u.push({path:h,text:w({locale:o,translations:l})})}const s=[...a.entries()].filter(([o])=>!(o in i)).map(([,o])=>o.path);return{files:u,deleted:s}}}}const E=e=>JSON.parse(JSON.stringify(e));function Re(e){const t=e.revisions!==!1;let n=0;const i=e.workspaces.map(s=>({meta:{id:s.id,label:s.label,description:s.description,icon:s.icon,readOnly:s.readOnly},packages:new Map((s.packages??[]).map(o=>[o.id,{...o,workspaceId:s.id}])),modules:new Map(s.modules.map(o=>[o.id,{...o,files:new Map(Object.entries(o.files).map(([l,f])=>[l,{text:f,version:++n}])),revisions:[]}]))}));let r=(e.templates??[]).map(s=>E(s));const a=s=>{const o=i.find(l=>l.meta.id===s);if(!o)throw new Error(`Unknown workspace "${s}"`);return o},c=s=>{const o=a(s.workspaceId).modules.get(s.id);if(!o)throw new Error(`Unknown module "${s.id}"`);return o},d=(s,o)=>({workspaceId:s,id:o.id,packageId:o.packageId,label:o.label??o.id,description:o.description,icon:o.icon,version:o.version,readOnly:o.readOnly||a(s).meta.readOnly,files:[...o.files.keys()].sort()}),u=(s,o)=>({path:s,text:o.text,version:String(o.version)});return{async listWorkspaces(){return i.map(s=>({...s.meta}))},async listModules(s){return[...a(s).modules.values()].map(l=>d(s,l))},async listPackages(s){const o=a(s),l=[...o.packages.values()],f=[...new Set([...o.modules.values()].map(h=>h.packageId).filter(Boolean))].filter(h=>!o.packages.has(h)).map(h=>({id:h,workspaceId:s,label:h,derived:!0}));return[...l,...f]},async readModule(s){return[...c(s).files.entries()].map(([l,f])=>u(l,f))},async writeModule(s,o){const l=c(s);if(l.readOnly||a(s.workspaceId).meta.readOnly)throw new Error(`Module "${s.id}" is read-only`);const f=o.filter(p=>p.baseVersion!==void 0).filter(p=>{const m=l.files.get(p.path);return m?String(m.version)!==p.baseVersion:!1}).map(p=>{var m;return{path:p.path,currentVersion:String((m=l.files.get(p.path))==null?void 0:m.version)}});if(f.length>0)return{ok:!1,conflicts:f};let h;if(t){const p={};for(const[m,b]of l.files)p[m]=b.text;h=`r${++n}`,l.revisions.unshift({id:h,timestamp:Date.now(),label:h,summary:o.map(m=>`${m.type} ${m.path}`).join(", "),files:p})}const g={};for(const p of o)if(p.type==="delete")l.files.delete(p.path);else{const m=++n;l.files.set(p.path,{text:p.text,version:m}),g[p.path]=String(m)}return{ok:!0,versions:g,revision:h}},async createModule(s){const o=a(s.workspaceId);if(o.meta.readOnly)throw new Error(`Workspace "${s.workspaceId}" is read-only`);if(o.modules.has(s.id))throw new Error(`Module "${s.id}" already exists`);const l={id:s.id,packageId:s.packageId,files:new Map(s.files.map(f=>[f.path,{text:f.text,version:++n}])),revisions:[]};return o.modules.set(s.id,l),d(s.workspaceId,l)},async deleteModule(s){const o=a(s.workspaceId);if(o.meta.readOnly)throw new Error(`Workspace "${s.workspaceId}" is read-only`);o.modules.delete(s.id)},async savePackage(s){return a(s.workspaceId).packages.set(s.id,{...s,derived:!1}),{...s,derived:!1}},async deletePackage(s){a(s.workspaceId).packages.delete(s.id)},async listTemplates(){return r.map(s=>E(s))},async saveTemplate(s,o){const l=(o==null?void 0:o.previousId)??s.id,f=E(s),h=r.findIndex(g=>g.id===l);return r=h>=0?r.map((g,p)=>p===h?f:g):[...r,f],E(f)},async deleteTemplate(s){r=r.filter(o=>o.id!==s)},async listRevisions(s,o){return c(s).revisions.filter(l=>!o||o in l.files).map(({files:l,...f})=>({...f,...o?{path:o}:{}}))},async readRevision(s,o,l){const f=c(s).revisions.find(h=>h.id===o);if(!f)throw new Error(`Unknown revision "${o}"`);return l?f.files[l]??"":JSON.stringify(f.files,null,2)},async rollback(s,o,l){const f=c(s),h=f.revisions.find(p=>p.id===o);if(!h)throw new Error(`Unknown revision "${o}"`);const g=l?{[l]:h.files[l]}:h.files;if(!l)for(const p of[...f.files.keys()])p in g||f.files.delete(p);for(const[p,m]of Object.entries(g))m!==void 0&&f.files.set(p,{text:m,version:++n})},snapshot(){return{workspaces:i.map(s=>({...s.meta,packages:[...s.packages.values()].map(({workspaceId:o,...l})=>l),modules:[...s.modules.values()].map(o=>({id:o.id,packageId:o.packageId,label:o.label,description:o.description,icon:o.icon,version:o.version,readOnly:o.readOnly,files:Object.fromEntries([...o.files.entries()].map(([l,f])=>[l,f.text]))}))})),templates:r.map(s=>E(s)),revisions:t}}}}function Ue(e){return e}function D(e,t){if(!t||e===void 0||e===null)return!0;if(t.enum&&!t.enum.includes(e))return!1;switch(t.type){case"string":return typeof e=="string";case"number":return typeof e=="number";case"integer":return Number.isInteger(e);case"boolean":return typeof e=="boolean";case"array":return Array.isArray(e)&&(!t.items||e.every(n=>D(n,t.items)));case"object":{if(typeof e!="object"||Array.isArray(e))return!1;const n=t.properties;return!n||Object.entries(e).every(([i,r])=>i in n&&D(r,n[i]))}default:return!0}}function We(e,t){var c;const n=(e.fields??[]).map(d=>d.name),i=(c=e.schema)==null?void 0:c.properties;if(!e.schema||!i)return{section:e,keys:n};const r=Object.entries(i).filter(([d,u])=>!(d in t)||D(t[d],u)),a=r.map(([d])=>d);return{section:{...e,schema:{...e.schema,properties:Object.fromEntries(r),...e.schema.required?{required:e.schema.required.filter(d=>a.includes(d))}:{}}},keys:[...a,...n]}}function qe(e){var n;const t=new Set;for(const i of e){for(const r of Object.keys(((n=i.schema)==null?void 0:n.properties)??{}))t.add(r);for(const r of i.fields??[])t.add(r.name)}return t}function _e(e){return e.map(t=>{const n=t;return{name:String(n.tableName||n.name||"Entity"),columns:(Array.isArray(n.fields)?n.fields:[]).map(i=>({name:String(i.name??""),dataType:String(i.dataType??i.type??"string"),isPrimaryKey:!!i.isPrimaryKey,isForeignKey:!!(i.isForeignKey??i.foreignKey)}))}})}function ze(e){const t=e.manifest??{},n=String(t.displayName||t.packageName||"Module"),i=(e.views??[]).map(a=>({id:`view:${a.id}`,label:a.name,type:"view"})),r=(e.entities??[]).map(a=>{const c=String(a.name??"Entity");return{id:`entity:${c}`,label:c,type:"entity"}});return{roles:[{id:"admin",label:"Admin"},{id:"user",label:"User"}],actions:[{id:"view",label:"View"},{id:"create",label:"Create"},{id:"edit",label:"Edit"},{id:"delete",label:"Delete"}],resources:[{id:"module",label:n,type:"module",children:[...i.length?[{id:"views",label:"Views",type:"group",children:i}]:[],...r.length?[{id:"entities",label:"Entities",type:"group",children:r}]:[]]}],grants:{}}}const L=G({id:"manifest",label:"Manifest",labelKey:"devStudio.kind.manifest",icon:"file",editor:"manifest",match:v(".manifest.json")}),pe=I({id:"entities",label:"Entities",labelKey:"devStudio.kind.entities",icon:"database",editor:"entities",match:v(".entities.json"),property:"entities",itemKey:"name"}),me=ue();function he(e,t){const n=e,i=typeof e=="object"&&e!==null&&typeof n.id=="string";return{key:i?n.id:`#${t}`,label:i&&n.name||(i?n.id:`#${t+1}`),...i?{definition:n}:{rawReason:"no id"},source:e}}const ye=B({id:"views",label:"Views",labelKey:"devStudio.kind.views",icon:"grid",editor:"views",match:v(".views.json"),property:"views",itemKey:"id",toItem:(e,t)=>he(e,t),fromItem:e=>e.definition??e.source}),ge=B({id:"workflows",label:"Workflows",labelKey:"devStudio.kind.workflows",icon:"git-branch",editor:"workflows",match:v(".workflows.json"),property:"workflows",itemKey:"id",toItem:(e,t)=>he(e,t),fromItem:e=>e.definition??e.source}),be=I({id:"dataSources",label:"Data sources",labelKey:"devStudio.kind.dataSources",icon:"database",editor:"dataSources",match:v(".datasources.json"),property:"dataSources",itemKey:"key"}),we=G({id:"rbac",label:"Access",labelKey:"devStudio.kind.rbac",icon:"shield",editor:"rbac",match:v(".rbac.json")}),ke=I({id:"hooks",label:"Lifecycle hooks",labelKey:"devStudio.kind.hooks",icon:"zap",editor:"hooks",match:v(".hooks.json"),property:"bindings",itemKey:"id"}),ve=[L,pe,me,ye,ge,be,we,ke];function W(e){return e.normalize("NFKD").replace(/[̀-ͯ]/g,"").replace(/ł/g,"l").replace(/Ł/g,"L").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"module"}const X=e=>{const t=e.find(n=>L.match(n.path));return t?de(t.text,void 0):void 0};function $e(e){const t=e.find(n=>L.match(n.path));return t?j(t.path).replace(/\.manifest\.json$/i,""):"module"}const Y=e=>Array.isArray(e.fields)?e.fields:[],Be={id:"native",kinds:ve,locales:["en","pl","de","fr","es","uk"],requiredLocales:["en"],moduleId:e=>{const t=X(e),n=(t==null?void 0:t.id)??(t==null?void 0:t.packageName);return typeof n=="string"?n:void 0},validateModule:({files:e})=>{const t=X(e);return t?["id","name","version"].filter(n=>typeof t[n]!="string"||!t[n]).map(n=>({severity:"error",code:"manifest.required",message:`The manifest needs "${n}".`,messageKey:"devStudio.issue.manifestRequired",params:{field:n},pointer:`/${n}`})):[{severity:"error",code:"manifest.missing",message:"The module has no manifest.",messageKey:"devStudio.issue.manifestMissing"}]},newFile:(e,{files:t})=>{const n=$e(t),r={entities:["entities.json",{entities:[]}],views:["views.json",{views:[]}],workflows:["workflows.json",{workflows:[]}],dataSources:["datasources.json",{dataSources:[]}],rbac:["rbac.json",{roles:[],actions:[],resources:[],grants:{}}],hooks:["hooks.json",{bindings:[]}]}[e];return r?{path:`${n}.${r[0]}`,text:w(r[1])}:void 0},generateModule:async(e,{existingIds:t})=>{let n=W(e.name);for(let r=2;t.has(n);r++)n=`${W(e.name)}-${r}`;const i=[{path:`${n}.manifest.json`,text:w({id:n,name:e.name,version:"1.0.0",...e.description?{description:e.description}:{},...e.icon?{icon:e.icon}:{},...e.packageId?{category:e.packageId}:{}})},{path:`${n}.entities.json`,text:w({entities:e.entities})}];for(const r of e.locales){const a={"module.displayName":e.name};for(const c of e.entities){const d=String(c.name??"");a[`entity.${d}.displayName`]=d;for(const u of Y(c))a[`field.${d}.${String(u.name)}.label`]=String(u.name)}i.push({path:`${n}.${r}.i18n.json`,text:w({locale:r,translations:a})})}if(e.views){const r=e.entities.map(a=>{const c=String(a.name??"Item");return{id:`${c}List`,name:`${c} list`,kind:"grid",version:2,columns:12,dataSources:[{key:"rows",type:"entity",entity:c,autoLoad:!0}],rows:[{id:"r1",cells:[{id:"grid",controlType:"dataGrid",colSpan:12,props:{columns:Y(a).map(d=>({field:String(d.name),header:String(d.name)}))},bindings:{data:{source:"rows",field:""}}}]}]}});i.push({path:`${n}.views.json`,text:w({views:r})})}if(e.permissions){const r={roles:[{id:"viewer",label:"Viewer"},{id:"editor",label:"Editor"},{id:"admin",label:"Admin"}],actions:[{id:"view",label:"View"},{id:"edit",label:"Edit"},{id:"delete",label:"Delete"}],resources:e.entities.map(a=>({id:`entity:${String(a.name)}`,label:String(a.name),type:"entity"})),grants:{}};i.push({path:`${n}.rbac.json`,text:w(r)})}return{id:n,packageId:e.packageId,files:i}}};exports.arrayFileKind=I;exports.buildDocuments=Pe;exports.createMemoryStudioProvider=Re;exports.defineManifestSection=Ue;exports.deriveDefaultRbac=ze;exports.detectJsonTextFormat=P;exports.encodeDocument=Ve;exports.endsWithAny=v;exports.entitiesToSchemas=_e;exports.fileName=j;exports.fitManifestSection=We;exports.i18nFileKind=ue;exports.itemsFileKind=B;exports.jsonFallbackKind=T;exports.jsonFileKind=V;exports.jsonValueFitsSchema=D;exports.jsonValuesEqual=x;exports.keepTextFormat=ee;exports.manifestSectionKeys=qe;exports.modulePrefix=$e;exports.nativeDataSourcesKind=be;exports.nativeEntitiesKind=pe;exports.nativeFileKinds=ve;exports.nativeHooksKind=ke;exports.nativeI18nKind=me;exports.nativeManifestKind=L;exports.nativeRbacKind=we;exports.nativeStudioPreset=Be;exports.nativeViewsKind=ye;exports.nativeWorkflowsKind=ge;exports.objectFileKind=G;exports.parseJsonText=K;exports.patchJsonText=q;exports.patchJsonTextDetailed=te;exports.readTranslations=fe;exports.resolveFileKind=le;exports.safeJson=de;exports.slugifyModuleId=W;exports.stringifyJsonText=w;exports.textFallbackKind=J;exports.writeTranslations=U;
10
+ `):e;return t.charCodeAt(0)===65279&&n.charCodeAt(0)!==65279&&(n=le+n),n}function F(e,t){if(e===t)return!0;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return!1;if(Array.isArray(e)){const r=t;return e.length===r.length&&e.every((a,l)=>F(a,r[l]))}const n=e,s=t,i=Object.keys(n);return i.length!==Object.keys(s).length?!1:i.every(r=>Object.prototype.hasOwnProperty.call(s,r)&&F(n[r],s[r]))}function Y(e,t,n){return ue(e,t,n).text}function ue(e,t,n){const s=q(e),i=o=>({text:S(t,s),exact:!1,reason:o});let r;try{r=new it(e).parseDocument()}catch(o){return i(o instanceof Error?o.message:String(o))}if(H(r))return i("duplicate keys");const a=[],l={text:e,format:s,edits:a,options:n,compact:!e.trimEnd().includes(`
11
+ `)};ee(l,r,t,"",!1);const f=rt(e,a);try{const o=JSON.parse(s.bom?f.slice(1):f);if(!F(o,t))return i("patch did not read back")}catch{return i("patch was not valid JSON")}return{text:f,exact:!0}}class it{constructor(t){se(this,"pos",0);this.text=t}parseDocument(){this.text.charCodeAt(0)===65279&&(this.pos=1);const t=this.value();if(this.ws(),this.pos<this.text.length)throw new Error(`Unexpected text at ${this.pos}`);return t}ws(){for(;this.pos<this.text.length&&/\s/.test(this.text[this.pos]);)this.pos++}value(){this.ws();const t=this.text[this.pos];if(t==="{")return this.object();if(t==="[")return this.array();const n=this.pos;if(t==='"')return{kind:"scalar",start:n,end:this.stringEnd(),value:JSON.parse(this.slice(n))};const s=/^(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/.exec(this.text.slice(n,n+64));if(!s)throw new Error(`Unexpected token at ${n}`);return this.pos=n+s[0].length,{kind:"scalar",start:n,end:this.pos,value:JSON.parse(s[0])}}slice(t){return this.text.slice(t,this.pos)}stringEnd(){for(this.pos++;this.pos<this.text.length;){const t=this.text[this.pos];if(t==="\\"){this.pos+=2;continue}if(this.pos++,t==='"')return this.pos}throw new Error("Unterminated string")}object(){const t=this.pos++,n=[];if(this.ws(),this.text[this.pos]==="}")return{kind:"object",start:t,end:++this.pos,members:n};for(;;){this.ws();const s=this.pos;if(this.text[this.pos]!=='"')throw new Error(`Expected a key at ${this.pos}`);const i=JSON.parse(this.text.slice(s,this.stringEnd()));if(this.ws(),this.text[this.pos]!==":")throw new Error(`Expected ':' at ${this.pos}`);this.pos++,n.push({key:i,start:s,value:this.value()}),this.ws();const r=this.text[this.pos++];if(r==="}")return{kind:"object",start:t,end:this.pos,members:n};if(r!==",")throw new Error(`Expected ',' or '}' at ${this.pos-1}`)}}array(){const t=this.pos++,n=[];if(this.ws(),this.text[this.pos]==="]")return{kind:"array",start:t,end:++this.pos,items:n};for(;;){n.push(this.value()),this.ws();const s=this.text[this.pos++];if(s==="]")return{kind:"array",start:t,end:this.pos,items:n};if(s!==",")throw new Error(`Expected ',' or ']' at ${this.pos-1}`)}}}function H(e){if(e.kind==="object"){const t=new Set;for(const n of e.members){if(t.has(n.key)||H(n.value))return!0;t.add(n.key)}}else if(e.kind==="array")return e.items.some(H);return!1}function P(e){if(e.kind==="scalar")return e.value;if(e.kind==="array")return e.items.map(P);const t={};for(const n of e.members)t[n.key]=P(n.value);return t}function E(e,t,n){if(e===null||typeof e!="object")return e===void 0?"null":JSON.stringify(e);const s=n+t.indent,i=t.colonSpace?": ":":";if(Array.isArray(e))return e.length===0?"[]":`[${t.eol}${e.map(a=>s+E(a,t,s)).join(`,${t.eol}`)}${t.eol}${n}]`;const r=Object.entries(e).filter(([,a])=>a!==void 0);return r.length===0?"{}":`{${t.eol}${r.map(([a,l])=>`${s}${JSON.stringify(a)}${i}${E(l,t,s)}`).join(`,${t.eol}`)}${t.eol}${n}}`}function I(e,t,n=!1){if(e===null||typeof e!="object")return e===void 0?"null":JSON.stringify(e);const s=t.colonSpace?": ":":",i=n?",":", ";if(Array.isArray(e))return`[${e.map(l=>I(l,t,n)).join(i)}]`;const r=Object.entries(e).filter(([,l])=>l!==void 0),a=n?"":" ";return r.length===0?"{}":`{${a}${r.map(([l,f])=>`${JSON.stringify(l)}${s}${I(f,t,n)}`).join(i)}${a}}`}const pe=e=>e.compact?",":", ";function rt(e,t){let n=e;for(const s of[...t].sort((i,r)=>r.start-i.start))n=n.slice(0,s.start)+s.text+n.slice(s.end);return n}function J(e,t){var s;const n=e.lastIndexOf(`
12
+ `,t-1)+1;return((s=/^[ \t]*/.exec(e.slice(n,t)))==null?void 0:s[0])??""}function me(e,t){return!e.slice(t.start,t.end).includes(`
13
+ `)}function Q(e,t,n){return e.compact?!0:t.kind==="scalar"||(t.kind==="object"?t.members.length===0:t.items.length===0)?n:me(e.text,t)}function x(e,t,n,s){const i=Q(e,t,s);e.edits.push({start:t.start,end:t.end,text:i?I(n,e.format,e.compact):E(n,e.format,J(e.text,t.start))})}const ye=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function ee(e,t,n,s,i){if(t.kind==="scalar"){if(t.value===n)return;x(e,t,n,i);return}F(P(t),n)||(t.kind==="object"&&ye(n)?ot(e,t,n,s,i):t.kind==="array"&&Array.isArray(n)?lt(e,t,n,s,i):x(e,t,n,i))}function he(e,t,n){return n!==void 0?J(e.text,n):J(e.text,t.start)+e.format.indent}function ot(e,t,n,s,i){var d;const r=Q(e,t,i),a=t.members.filter(u=>Object.prototype.hasOwnProperty.call(n,u.key)&&n[u.key]!==void 0),l=Object.keys(n).filter(u=>n[u]!==void 0&&!t.members.some(y=>y.key===u));if(a.length===0&&t.members.length>0){x(e,t,n,i);return}for(const u of a)ee(e,u.value,n[u.key],`${s}/${ut(u.key)}`,r);if(ge(e,t.members.map(u=>({start:u.start,end:u.value.end})),t.members.map(u=>a.includes(u))),l.length===0)return;const f=e.format.colonSpace?": ":":";if(r){const u=l.map(y=>`${JSON.stringify(y)}${f}${I(n[y],e.format,e.compact)}`);ke(e,t,a.length>0?a[a.length-1].value.end:void 0,u);return}const o=he(e,t,(d=t.members[0])==null?void 0:d.start),c=l.map(u=>`${o}${JSON.stringify(u)}${f}${E(n[u],e.format,o)}`);be(e,t,a.length>0?a[a.length-1].value.end:void 0,c)}const at=["name","id","code","key","slug","state","Id"];function ct(e,t,n,s){var f,o;const i=[...n,...s];if(i.length===0||!i.every(ye))return;const r=(c,d)=>{const u=c.map(y=>y[d]);return u.every(y=>typeof y=="string"||typeof y=="number")&&new Set(u).size===u.length},a=(o=(f=e.options)==null?void 0:f.arrayKey)==null?void 0:o.call(f,t);return(a?[a]:at).find(c=>r(n,c)&&r(s,c))}function lt(e,t,n,s,i){var g;const r=Q(e,t,i),a=t.items.map(P),l=ct(e,s,a,n),f=p=>p[l],o=l!==void 0?a.map(p=>{const m=f(p);return n.findIndex(k=>f(k)===m)}):ft(a,n);{const p=new Set(o.filter(m=>m>=0));for(let m=0;m<o.length;m++){if(o[m]>=0)continue;let k=-1;for(let h=m-1;h>=0;h--)if(o[h]>=0){k=o[h];break}let j=n.length;for(let h=m+1;h<o.length;h++)if(o[h]>=0){j=o[h];break}for(let h=k+1;h<j;h++)if(!p.has(h)){o[m]=h,p.add(h);break}}}const c=o.filter(p=>p>=0);if(c.some((p,m)=>m>0&&p<c[m-1])){x(e,t,n,i);return}if(c.length===0&&t.items.length>0){x(e,t,n,i);return}t.items.forEach((p,m)=>{o[m]>=0&&ee(e,p,n[o[m]],`${s}/${o[m]}`,r)}),ge(e,t.items.map(p=>({start:p.start,end:p.end})),o.map(p=>p>=0));const d=t.items.length>0&&t.items.every(p=>p.kind!=="scalar"&&me(e.text,p)),u=he(e,t,(g=t.items[0])==null?void 0:g.start),y=new Map;n.forEach((p,m)=>{if(o.includes(m))return;let k;for(let K=t.items.length-1;K>=0;K--)if(o[K]>=0&&o[K]<m){k=K;break}const j=r?I(p,e.format,e.compact):d?`${u}${I(p,e.format)}`:`${u}${E(p,e.format,u)}`,h=y.get(k)??[];h.push(j),y.set(k,h)});for(const[p,m]of y){const k=p===void 0?void 0:t.items[p].end;if(p===void 0&&c.length>0){const j=t.items[o.findIndex(K=>K>=0)],h=r?pe(e):`,${e.format.eol}`;e.edits.push({start:j.start,end:j.start,text:r?m.join(h)+h:m.join(h).trimStart()+h+u});continue}r?ke(e,t,k,m):be(e,t,k,m)}}const dt=4e6;function ft(e,t){const n=e.length,s=t.length;if(n*s>dt)return e.map((c,d)=>d<s?d:-1);const i=e.map(c=>JSON.stringify(c)),r=t.map(c=>JSON.stringify(c)),a=Array.from({length:n+1},()=>new Uint32Array(s+1));for(let c=n-1;c>=0;c--)for(let d=s-1;d>=0;d--)a[c][d]=i[c]===r[d]?a[c+1][d+1]+1:Math.max(a[c+1][d],a[c][d+1]);const l=new Array(n).fill(-1);let f=0,o=0;for(;f<n&&o<s;)i[f]===r[o]?l[f++]=o++:a[f+1][o]>=a[f][o+1]?f++:o++;return l}function ge(e,t,n){for(let s=0;s<t.length;s++){if(n[s])continue;let i=s;for(;i+1<t.length&&!n[i+1];)i++;i+1<t.length?e.edits.push({start:t[s].start,end:t[i+1].start,text:""}):s>0?e.edits.push({start:t[s-1].end,end:t[i].end,text:""}):e.edits.push({start:t[s].start,end:t[i].end,text:""}),s=i}}function be(e,t,n,s){const i=e.format.eol;if(n!==void 0){e.edits.push({start:n,end:n,text:`,${i}${s.join(`,${i}`)}`});return}const r=t.end-1;if((t.kind==="object"?t.members.length:t.items.length)===0)e.edits.push({start:t.start+1,end:r,text:`${i}${s.join(`,${i}`)}${i}${J(e.text,t.start)}`});else{const l=t.kind==="object"?t.members[0].start:t.items[0].start;e.edits.push({start:l,end:l,text:`${s.join(`,${i}`).trimStart()}`})}}function ke(e,t,n,s){const i=pe(e);if(n!==void 0){e.edits.push({start:n,end:n,text:`${i}${s.join(i)}`});return}const r=t.kind==="object"&&!e.compact?" ":"";e.edits.push({start:t.start+1,end:t.end-1,text:`${r}${s.join(i)}${r}`})}function ut(e){return e.replace(/~/g,"~0").replace(/\//g,"~1")}const O=e=>e.slice(e.lastIndexOf("/")+1),pt=e=>e.charCodeAt(0)===65279?e.slice(1):e;function L(e){return{id:e.id,label:e.label,labelKey:e.labelKey,icon:e.icon,match:e.match,editor:e.editor,decode(t,n){return e.select(A(t[0].text).value,n)},encode(t,n,s){const i=n[0].text,r=A(i).value,a=e.assign(r,t,s);return{files:[{path:n[0].path,text:Y(i,a,{arrayKey:e.arrayKey})}]}}}}const D=L({id:"json",label:"JSON",labelKey:"devStudio.kind.json",icon:"code",match:e=>e.toLowerCase().endsWith(".json"),editor:"json",select:e=>e,assign:(e,t)=>t}),_={id:"text",label:"Text",labelKey:"devStudio.kind.text",icon:"file",match:()=>!0,editor:"text",decode:e=>e[0].text,encode:(e,t)=>({files:[{path:t[0].path,text:fe(e,t[0].text)}]})};function Se(e,t){return e.find(n=>n.match(t))??(D.match(t)?D:_)}function mt(e,t,n){for(const s of[D,_])if(s.match(e.path))try{const i=s.decode([e],n);return{key:`${s.id}:${e.path}`,kind:s,paths:[e.path],label:O(e.path),model:i,error:t}}catch{}return{key:`text:${e.path}`,kind:_,paths:[e.path],label:O(e.path),model:e.text,error:t}}function yt(e,t,n,s){var l,f;const i=e.encode(t,n,s),r=new Map(n.map(o=>[o.path,o.text])),a=((l=i.files.find(o=>r.get(o.path)!==o.text))==null?void 0:l.path)??((f=i.deleted)==null?void 0:f.find(o=>r.has(o)));if(a!==void 0)throw new Error(`${O(a)} would not be stored as it is`)}function ht(e,t,n){const s=new Map;for(const r of t){const a=Se(e,r.path),l=a.group?a.group(r.path):r.path,f=`${a.id}:${l}`,o=s.get(f)??{kind:a,group:l,files:[]};o.files.push(r),s.set(f,o)}const i=[];for(const[r,{kind:a,group:l,files:f}]of s){const o=f.map(d=>d.path).sort(),c=O(a.group?l:o[0]);try{const d=a.decode(f,n);yt(a,d,f,n),i.push({key:r,kind:a,paths:o,label:c,model:d})}catch(d){const u=d instanceof Error?d.message:String(d);for(const y of f)i.push(mt(y,u,n))}}return i.sort((r,a)=>r.label.localeCompare(a.label))}function gt(e,t,n,s){const i=n.filter(f=>e.paths.includes(f.path)),r=e.kind.encode(t,i,s),a=new Map(n.map(f=>[f.path,f])),l=[];for(const f of r.files){const o=a.get(f.path);o&&o.text===f.text||l.push({type:"write",path:f.path,text:f.text,baseVersion:o==null?void 0:o.version})}for(const f of r.deleted??[]){const o=a.get(f);o&&l.push({type:"delete",path:f,baseVersion:o.version})}return l}function ve(e,t){try{return JSON.parse(pt(e))}catch{return t}}const v=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),w=(...e)=>t=>{const n=t.toLowerCase();return e.some(s=>n.endsWith(s.toLowerCase()))};function C(e){return L({id:e.id,label:e.label,labelKey:e.labelKey,icon:e.icon,editor:e.editor,match:e.match,select:t=>{if(Array.isArray(t))return t;const n=v(t)?t[e.property]:void 0;return Array.isArray(n)?n:[]},assign:(t,n)=>Array.isArray(t)?n:v(t)&&!(e.property in t)&&n.length===0?t:{...v(t)?t:{},[e.property]:n},arrayKey:e.itemKey?()=>e.itemKey:void 0})}function te(e){const t=C(e);return{...t,decode:(n,s)=>t.decode(n,s).map((i,r)=>e.toItem(i,r)),encode:(n,s,i)=>t.encode(n.map(r=>e.fromItem(r)),s,i)}}function ne(e){return L({...e,select:t=>v(t)?t:{},assign:(t,n)=>n})}const bt=/^(.*)\.([a-z]{2,3}(?:-[A-Za-z]{2,4})?)\.i18n\.json$/i,kt=e=>{const t=bt.exec(e);return t?{group:t[1],locale:t[2]}:null},X=e=>v(e)&&Object.values(e).every(t=>typeof t=="string");function we(e){if(v(e)){for(const t of["translations","keys"])if(t in e){if(X(e[t]))return e[t];throw new Error(`"${t}" is not a flat map of texts`)}if(X(e))return e}throw new Error("no translations in this file")}function Z(e,t){return v(e)?v(e.translations)?{...e,translations:t}:v(e.keys)?{...e,keys:t}:X(e)?t:{...e,translations:t}:{translations:t}}function $e(e={}){const t=e.parse??kt,n=e.pathFor??((s,i)=>`${s}.${i}.i18n.json`);return{id:e.id??"i18n",label:e.label??"Translations",labelKey:e.labelKey??"devStudio.kind.i18n",icon:"globe",editor:"i18n",match:s=>t(s)!==null,group:s=>{var i;return((i=t(s))==null?void 0:i.group)??s},decode(s){const i={};for(const r of s){const a=t(r.path);a&&(i[a.locale]={...we(A(r.text).value)})}return i},encode(s,i){const r=new Map;let a="";for(const c of i){const d=t(c.path);d&&(r.set(d.locale,c),a=d.group)}const l=r.get("en")??i[0],f=[];for(const[c,d]of Object.entries(s)){const u=r.get(c);if(u){const g=A(u.text).value;f.push({path:u.path,text:Y(u.text,Z(g,d))});continue}const y=n(a||O((l==null?void 0:l.path)??"module"),c);if(l){const g=A(l.text).value,p=v(g)&&"locale"in g?{...g,locale:c}:g;f.push({path:y,text:S(Z(p,d),q(l.text))})}else f.push({path:y,text:S({locale:c,translations:d})})}const o=[...r.entries()].filter(([c])=>!(c in s)).map(([,c])=>c.path);return{files:f,deleted:o}}}}const $=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),je=["frontend","backend","noCode","sql"],St=["preInstall","postInstall","preUninstall","postUninstall"];function Ke(e){switch(e){case"frontend":return["typescript","javascript"];case"backend":return["csharp","javascript"];case"sql":return["sql"];case"noCode":return[]}}const vt=new Set(["read","filter","map","aggregate","set","if","forEach","write","callScript","return"]),Oe=e=>Array.isArray(e)&&e.every(t=>$(t)&&typeof t.id=="string"&&vt.has(String(t.type)));function R(e){if(je.includes(e.kind))return e.kind;if(e.source===void 0&&Oe(e.steps))return"noCode";const t=typeof e.language=="string"?e.language.toLowerCase():"";return t.endsWith("sql")||e.source===void 0&&typeof e.sql=="string"?"sql":/^(csharp|c#|cs\b)/.test(t)?"backend":"frontend"}const Ae=["id","displayName","description","language","category","trigger","returnType","source","sourcePath"],wt=e=>Array.isArray(e)&&e.every(t=>$(t)&&typeof t.name=="string");function Ee(e,t){const n=`#${t+1}`;if(!$(e)||typeof e.name!="string"||!e.name){const l=$(e)&&typeof e.displayName=="string"?e.displayName:n;return{key:`#${t}`,label:l,rawReason:"no name",source:e}}const s=e.name,i=typeof e.displayName=="string"&&e.displayName?e.displayName:s,r=l=>({key:s,label:i,rawReason:l,source:e}),a={name:s,kind:R(e)};for(const l of Ae){const f=e[l];if(f!==void 0){if(typeof f!="string")return r(`"${l}" is not text`);a[l]=f}}if(e.parameters!==void 0){if(!wt(e.parameters))return r('"parameters" is not a list of named parameters');a.parameters=e.parameters}if(a.kind==="noCode"){if(e.steps!==void 0&&!Oe(e.steps))return r('"steps" are not no-code steps');a.steps=e.steps??[]}return{key:s,label:i,definition:a,source:e}}function Ie(e){const t=e.definition;if(!t)return e.source;const n=$(e.source)?e.source:{},s={...n,name:t.name};for(const i of Ae)t[i]===void 0?delete s[i]:s[i]=t[i];return t.parameters===void 0?delete s.parameters:s.parameters=t.parameters,t.kind==="noCode"?s.steps=t.steps??[]:R(n)==="noCode"&&delete s.steps,delete s.kind,("kind"in n||R(s)!==t.kind)&&(s.kind=t.kind),s}function z(e){const t=new Set;return e.map((n,s)=>{const i=Ee(n,s);return t.has(i.key)&&(i.key=`${i.key}#${s}`),t.add(i.key),i})}function ie(e,t){if(!$(e)||!Object.values(e).every(n=>Array.isArray(n)&&n.every(s=>typeof s=="string")))throw new Error(`"${t}" is not lists of SQL statements per phase`);return e}function Ne(e){const t=e.property??"scripts",n=e.phasesProperty??"phases",s=t===n,i=r=>r.scripts.map(Ie);return L({id:e.id??"scripts",label:e.label??"Scripts",labelKey:e.labelKey??"devStudio.kind.scripts",icon:e.icon??"code",editor:"scriptList",match:e.match,select:r=>{if(Array.isArray(r))return{scripts:z(r),...s?{holds:"scripts"}:{}};if(!$(r)||r[t]===void 0&&r[n]===void 0)throw new Error(`no "${t}" in this file`);const a=r[t];if(s)return Array.isArray(a)?{scripts:z(a),holds:"scripts"}:{scripts:[],phases:ie(a,t),holds:"phases"};if(a!==void 0&&!Array.isArray(a))throw new Error(`"${t}" is not a list`);const l=r[n];return{scripts:z(a??[]),...l!==void 0?{phases:ie(l,n)}:{}}},assign:(r,a)=>{if(a.holds==="phases"&&a.scripts.length>0)throw new Error("This file holds database scripts only; add scripts to another file.");if(Array.isArray(r)&&a.phases===void 0)return i(a);const l=$(r)?r:{};if(s)return{...l,[t]:a.holds==="phases"?a.phases??{}:i(a)};const f={...l};return(t in l||a.scripts.length>0)&&(f[t]=i(a)),a.phases===void 0?delete f[n]:f[n]=a.phases,f},arrayKey:r=>r===`/${t}`?"name":void 0})}function Te(e){const n=e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").split(/[^A-Za-z0-9]+/).filter(Boolean).map((s,i)=>i===0?s[0].toLowerCase()+s.slice(1):s[0].toUpperCase()+s.slice(1)).join("");return/^[A-Za-z_]/.test(n)?n:`script${n}`}function $t(e){const t=Te(e.name),n=e.language??Ke(e.kind)[0],s={name:t,kind:e.kind,...e.name!==t?{displayName:e.name}:{},...n?{language:n}:{},...e.category?{category:e.category}:{},...e.trigger?{trigger:e.trigger}:{},parameters:[]},i=t[0].toUpperCase()+t.slice(1);switch(e.kind){case"noCode":return{...s,steps:[]};case"sql":return{...s,source:`-- ${e.name}
14
+ SELECT 1;
15
+ `};case"backend":return{...s,returnType:"object",source:n==="csharp"?`public static object ${i}(IDictionary<string, object> args)
16
+ {
17
+ return null;
18
+ }
19
+ `:`function ${t}(args) {
20
+ return null;
21
+ }
22
+ `};case"frontend":return{...s,returnType:"void",source:n==="typescript"?`export function ${t}(): void {
23
+ }
24
+ `:`export function ${t}() {
25
+ }
26
+ `}}}const T=e=>JSON.parse(JSON.stringify(e));function jt(e){const t=e.revisions!==!1;let n=0;const s=e.workspaces.map(o=>({meta:{id:o.id,label:o.label,description:o.description,icon:o.icon,readOnly:o.readOnly},packages:new Map((o.packages??[]).map(c=>[c.id,{...c,workspaceId:o.id}])),modules:new Map(o.modules.map(c=>[c.id,{...c,files:new Map(Object.entries(c.files).map(([d,u])=>[d,{text:u,version:++n}])),revisions:[]}]))}));let i=(e.templates??[]).map(o=>T(o));const r=o=>{const c=s.find(d=>d.meta.id===o);if(!c)throw new Error(`Unknown workspace "${o}"`);return c},a=o=>{const c=r(o.workspaceId).modules.get(o.id);if(!c)throw new Error(`Unknown module "${o.id}"`);return c},l=(o,c)=>({workspaceId:o,id:c.id,packageId:c.packageId,label:c.label??c.id,description:c.description,icon:c.icon,version:c.version,readOnly:c.readOnly||r(o).meta.readOnly,files:[...c.files.keys()].sort()}),f=(o,c)=>({path:o,text:c.text,version:String(c.version)});return{async listWorkspaces(){return s.map(o=>({...o.meta}))},async listModules(o){return[...r(o).modules.values()].map(d=>l(o,d))},async listPackages(o){const c=r(o),d=[...c.packages.values()],u=[...new Set([...c.modules.values()].map(y=>y.packageId).filter(Boolean))].filter(y=>!c.packages.has(y)).map(y=>({id:y,workspaceId:o,label:y,derived:!0}));return[...d,...u]},async readModule(o){return[...a(o).files.entries()].map(([d,u])=>f(d,u))},async writeModule(o,c){const d=a(o);if(d.readOnly||r(o.workspaceId).meta.readOnly)throw new Error(`Module "${o.id}" is read-only`);const u=c.filter(p=>p.baseVersion!==void 0).filter(p=>{const m=d.files.get(p.path);return m?String(m.version)!==p.baseVersion:!1}).map(p=>{var m;return{path:p.path,currentVersion:String((m=d.files.get(p.path))==null?void 0:m.version)}});if(u.length>0)return{ok:!1,conflicts:u};let y;if(t){const p={};for(const[m,k]of d.files)p[m]=k.text;y=`r${++n}`,d.revisions.unshift({id:y,timestamp:Date.now(),label:y,summary:c.map(m=>`${m.type} ${m.path}`).join(", "),files:p})}const g={};for(const p of c)if(p.type==="delete")d.files.delete(p.path);else{const m=++n;d.files.set(p.path,{text:p.text,version:m}),g[p.path]=String(m)}return{ok:!0,versions:g,revision:y}},async createModule(o){const c=r(o.workspaceId);if(c.meta.readOnly)throw new Error(`Workspace "${o.workspaceId}" is read-only`);if(c.modules.has(o.id))throw new Error(`Module "${o.id}" already exists`);const d={id:o.id,packageId:o.packageId,files:new Map(o.files.map(u=>[u.path,{text:u.text,version:++n}])),revisions:[]};return c.modules.set(o.id,d),l(o.workspaceId,d)},async deleteModule(o){const c=r(o.workspaceId);if(c.meta.readOnly)throw new Error(`Workspace "${o.workspaceId}" is read-only`);c.modules.delete(o.id)},async savePackage(o){return r(o.workspaceId).packages.set(o.id,{...o,derived:!1}),{...o,derived:!1}},async deletePackage(o){r(o.workspaceId).packages.delete(o.id)},async listTemplates(){return i.map(o=>T(o))},async saveTemplate(o,c){const d=(c==null?void 0:c.previousId)??o.id,u=T(o),y=i.findIndex(g=>g.id===d);return i=y>=0?i.map((g,p)=>p===y?u:g):[...i,u],T(u)},async deleteTemplate(o){i=i.filter(c=>c.id!==o)},async listRevisions(o,c){return a(o).revisions.filter(d=>!c||c in d.files).map(({files:d,...u})=>({...u,...c?{path:c}:{}}))},async readRevision(o,c,d){const u=a(o).revisions.find(y=>y.id===c);if(!u)throw new Error(`Unknown revision "${c}"`);return d?u.files[d]??"":JSON.stringify(u.files,null,2)},async rollback(o,c,d){const u=a(o),y=u.revisions.find(p=>p.id===c);if(!y)throw new Error(`Unknown revision "${c}"`);const g=d?{[d]:y.files[d]}:y.files;if(!d)for(const p of[...u.files.keys()])p in g||u.files.delete(p);for(const[p,m]of Object.entries(g))m!==void 0&&u.files.set(p,{text:m,version:++n})},snapshot(){return{workspaces:s.map(o=>({...o.meta,packages:[...o.packages.values()].map(({workspaceId:c,...d})=>d),modules:[...o.modules.values()].map(c=>({id:c.id,packageId:c.packageId,label:c.label,description:c.description,icon:c.icon,version:c.version,readOnly:c.readOnly,files:Object.fromEntries([...c.files.entries()].map(([d,u])=>[d,u.text]))}))})),templates:i.map(o=>T(o)),revisions:t}}}}function Kt(e){return e}function U(e,t){if(!t||e===void 0||e===null)return!0;if(t.enum&&!t.enum.includes(e))return!1;switch(t.type){case"string":return typeof e=="string";case"number":return typeof e=="number";case"integer":return Number.isInteger(e);case"boolean":return typeof e=="boolean";case"array":return Array.isArray(e)&&(!t.items||e.every(n=>U(n,t.items)));case"object":{if(typeof e!="object"||Array.isArray(e))return!1;const n=t.properties;return!n||Object.entries(e).every(([s,i])=>s in n&&U(i,n[s]))}default:return!0}}function Ot(e,t){var a;const n=(e.fields??[]).map(l=>l.name),s=(a=e.schema)==null?void 0:a.properties;if(!e.schema||!s)return{section:e,keys:n};const i=Object.entries(s).filter(([l,f])=>!(l in t)||U(t[l],f)),r=i.map(([l])=>l);return{section:{...e,schema:{...e.schema,properties:Object.fromEntries(i),...e.schema.required?{required:e.schema.required.filter(l=>r.includes(l))}:{}}},keys:[...r,...n]}}function At(e){var n;const t=new Set;for(const s of e){for(const i of Object.keys(((n=s.schema)==null?void 0:n.properties)??{}))t.add(i);for(const i of s.fields??[])t.add(i.name)}return t}function Et(e){return e.map(t=>{const n=t;return{name:String(n.tableName||n.name||"Entity"),columns:(Array.isArray(n.fields)?n.fields:[]).map(s=>({name:String(s.name??""),dataType:String(s.dataType??s.type??"string"),isPrimaryKey:!!s.isPrimaryKey,isForeignKey:!!(s.isForeignKey??s.foreignKey)}))}})}function It(e){const t=e.manifest??{},n=String(t.displayName||t.packageName||"Module"),s=(e.views??[]).map(r=>({id:`view:${r.id}`,label:r.name,type:"view"})),i=(e.entities??[]).map(r=>{const a=String(r.name??"Entity");return{id:`entity:${a}`,label:a,type:"entity"}});return{roles:[{id:"admin",label:"Admin"},{id:"user",label:"User"}],actions:[{id:"view",label:"View"},{id:"create",label:"Create"},{id:"edit",label:"Edit"},{id:"delete",label:"Delete"}],resources:[{id:"module",label:n,type:"module",children:[...s.length?[{id:"views",label:"Views",type:"group",children:s}]:[],...i.length?[{id:"entities",label:"Entities",type:"group",children:i}]:[]]}],grants:{}}}const V=ne({id:"manifest",label:"Manifest",labelKey:"devStudio.kind.manifest",icon:"file",editor:"manifest",match:w(".manifest.json")}),Fe=C({id:"entities",label:"Entities",labelKey:"devStudio.kind.entities",icon:"database",editor:"entities",match:w(".entities.json"),property:"entities",itemKey:"name"}),xe=$e();function Le(e,t){const n=e,s=typeof e=="object"&&e!==null&&typeof n.id=="string";return{key:s?n.id:`#${t}`,label:s&&n.name||(s?n.id:`#${t+1}`),...s?{definition:n}:{rawReason:"no id"},source:e}}const Ce=te({id:"views",label:"Views",labelKey:"devStudio.kind.views",icon:"grid",editor:"views",match:w(".views.json"),property:"views",itemKey:"id",toItem:(e,t)=>Le(e,t),fromItem:e=>e.definition??e.source}),Me=te({id:"workflows",label:"Workflows",labelKey:"devStudio.kind.workflows",icon:"git-branch",editor:"workflows",match:w(".workflows.json"),property:"workflows",itemKey:"id",toItem:(e,t)=>Le(e,t),fromItem:e=>e.definition??e.source}),Pe=C({id:"dataSources",label:"Data sources",labelKey:"devStudio.kind.dataSources",icon:"database",editor:"dataSources",match:w(".datasources.json"),property:"dataSources",itemKey:"key"}),Je=ne({id:"rbac",label:"Access",labelKey:"devStudio.kind.rbac",icon:"shield",editor:"rbac",match:w(".rbac.json")}),De=C({id:"hooks",label:"Lifecycle hooks",labelKey:"devStudio.kind.hooks",icon:"zap",editor:"hooks",match:w(".hooks.json"),property:"bindings",itemKey:"id"}),_e=Ne({match:w(".scripts.json")}),Re=[V,Fe,xe,Ce,Me,Pe,Je,De,_e];function G(e){return e.normalize("NFKD").replace(/[̀-ͯ]/g,"").replace(/ł/g,"l").replace(/Ł/g,"L").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"module"}const re=e=>{const t=e.find(n=>V.match(n.path));return t?ve(t.text,void 0):void 0};function Ue(e){const t=e.find(n=>V.match(n.path));return t?O(t.path).replace(/\.manifest\.json$/i,""):"module"}const oe=e=>Array.isArray(e.fields)?e.fields:[],Nt={id:"native",kinds:Re,locales:["en","pl","de","fr","es","uk"],requiredLocales:["en"],moduleId:e=>{const t=re(e),n=(t==null?void 0:t.id)??(t==null?void 0:t.packageName);return typeof n=="string"?n:void 0},validateModule:({files:e})=>{const t=re(e);return t?["id","name","version"].filter(n=>typeof t[n]!="string"||!t[n]).map(n=>({severity:"error",code:"manifest.required",message:`The manifest needs "${n}".`,messageKey:"devStudio.issue.manifestRequired",params:{field:n},pointer:`/${n}`})):[{severity:"error",code:"manifest.missing",message:"The module has no manifest.",messageKey:"devStudio.issue.manifestMissing"}]},newFile:(e,{files:t})=>{const n=Ue(t),i={entities:["entities.json",{entities:[]}],views:["views.json",{views:[]}],workflows:["workflows.json",{workflows:[]}],dataSources:["datasources.json",{dataSources:[]}],rbac:["rbac.json",{roles:[],actions:[],resources:[],grants:{}}],hooks:["hooks.json",{bindings:[]}],scripts:["scripts.json",{scripts:[]}]}[e];return i?{path:`${n}.${i[0]}`,text:S(i[1])}:void 0},generateModule:async(e,{existingIds:t})=>{let n=G(e.name);for(let i=2;t.has(n);i++)n=`${G(e.name)}-${i}`;const s=[{path:`${n}.manifest.json`,text:S({id:n,name:e.name,version:"1.0.0",...e.description?{description:e.description}:{},...e.icon?{icon:e.icon}:{},...e.packageId?{category:e.packageId}:{}})},{path:`${n}.entities.json`,text:S({entities:e.entities})}];for(const i of e.locales){const r={"module.displayName":e.name};for(const a of e.entities){const l=String(a.name??"");r[`entity.${l}.displayName`]=l;for(const f of oe(a))r[`field.${l}.${String(f.name)}.label`]=String(f.name)}s.push({path:`${n}.${i}.i18n.json`,text:S({locale:i,translations:r})})}if(e.views){const i=e.entities.map(r=>{const a=String(r.name??"Item");return{id:`${a}List`,name:`${a} list`,kind:"grid",version:2,columns:12,dataSources:[{key:"rows",type:"entity",entity:a,autoLoad:!0}],rows:[{id:"r1",cells:[{id:"grid",controlType:"dataGrid",colSpan:12,props:{columns:oe(r).map(l=>({field:String(l.name),header:String(l.name)}))},bindings:{data:{source:"rows",field:""}}}]}]}});s.push({path:`${n}.views.json`,text:S({views:i})})}if(e.permissions){const i={roles:[{id:"viewer",label:"Viewer"},{id:"editor",label:"Editor"},{id:"admin",label:"Admin"}],actions:[{id:"view",label:"View"},{id:"edit",label:"Edit"},{id:"delete",label:"Delete"}],resources:e.entities.map(r=>({id:`entity:${String(r.name)}`,label:String(r.name),type:"entity"})),grants:{}};s.push({path:`${n}.rbac.json`,text:S(i)})}return{id:n,packageId:e.packageId,files:s}}};exports.NICE_STUDIO_SCRIPT_KINDS=je;exports.NICE_STUDIO_SCRIPT_PHASES=St;exports.addStudioFolder=Qe;exports.addStudioSection=Ye;exports.arrayFileKind=C;exports.buildDocuments=ht;exports.createMemoryStudioProvider=jt;exports.defineManifestSection=Kt;exports.deriveDefaultRbac=It;exports.detectJsonTextFormat=q;exports.emptyStudioLayout=M;exports.encodeDocument=gt;exports.endsWithAny=w;exports.entitiesToSchemas=Et;exports.fileName=O;exports.fitManifestSection=Ot;exports.fromStudioScriptItem=Ie;exports.i18nFileKind=$e;exports.inferStudioScriptKind=R;exports.isEmptyStudioLayout=Xe;exports.isStudioLayoutPath=ae;exports.itemsFileKind=te;exports.jsonFallbackKind=D;exports.jsonFileKind=L;exports.jsonValueFitsSchema=U;exports.jsonValuesEqual=F;exports.keepTextFormat=fe;exports.manifestSectionKeys=At;exports.modulePrefix=Ue;exports.nativeDataSourcesKind=Pe;exports.nativeEntitiesKind=Fe;exports.nativeFileKinds=Re;exports.nativeHooksKind=De;exports.nativeI18nKind=xe;exports.nativeManifestKind=V;exports.nativeRbacKind=Je;exports.nativeScriptsKind=_e;exports.nativeStudioPreset=Nt;exports.nativeViewsKind=Ce;exports.nativeWorkflowsKind=Me;exports.newStudioScript=$t;exports.objectFileKind=ne;exports.parseJsonText=A;exports.parseStudioLayout=He;exports.patchJsonText=Y;exports.patchJsonTextDetailed=ue;exports.placeStudioEntry=nt;exports.readTranslations=we;exports.removeStudioLayoutNode=tt;exports.renameStudioEntryRef=st;exports.renameStudioLayoutNode=et;exports.resolveFileKind=Se;exports.safeJson=ve;exports.scriptsFileKind=Ne;exports.serializeStudioLayout=Ze;exports.slugifyModuleId=G;exports.stringifyJsonText=S;exports.studioEntryRef=ze;exports.studioLayoutPath=Be;exports.studioScriptIdentifier=Te;exports.studioScriptLanguages=Ke;exports.textFallbackKind=_;exports.toStudioScriptItem=Ee;exports.writeTranslations=Z;
package/dist/studio.d.ts CHANGED
@@ -3,10 +3,23 @@ import { NiceDataSourceDef } from '@nice2dev/ui';
3
3
  import { NiceDataSourceSchemaTable } from '@nice2dev/ui';
4
4
  import { NiceFormItem } from '@nice2dev/ui';
5
5
  import { NiceHookBinding } from '@nice2dev/ui';
6
+ import { NiceNoCodeStep } from '@nice2dev/ui';
6
7
  import { NiceRbacModel } from '@nice2dev/ui';
7
8
  import { NiceViewDefinition } from '@nice2dev/ui';
8
9
  import { NiceWorkflowDefinition } from '@nice2dev/ui';
9
10
 
11
+ /** The layout with a new folder in `group` (inside `parent` / `section`); returns its id too. */
12
+ export declare function addStudioFolder(layout: NiceStudioLayout, folder: Omit<NiceStudioLayoutFolder, 'id'>): {
13
+ layout: NiceStudioLayout;
14
+ id: string;
15
+ };
16
+
17
+ /** The layout with a new section; returns the layout and the section's id. */
18
+ export declare function addStudioSection(layout: NiceStudioLayout, label: string): {
19
+ layout: NiceStudioLayout;
20
+ id: string;
21
+ };
22
+
10
23
  /** A file holding one array, either bare or under `property`; the rest of the file is kept. */
11
24
  export declare function arrayFileKind<T>(o: NiceArrayFileKindOptions): NiceStudioFileKind<T[]>;
12
25
 
@@ -29,17 +42,20 @@ export declare function defineManifestSection<TSchema extends JsonSchema>(sectio
29
42
 
30
43
  /** A starter access model: admin / user × view / create / edit / delete over the module's views and entities. */
31
44
  export declare function deriveDefaultRbac(module: {
32
- manifest?: Row;
45
+ manifest?: Row_2;
33
46
  views?: ReadonlyArray<{
34
47
  id: string;
35
48
  name: string;
36
49
  }>;
37
- entities?: readonly Row[];
50
+ entities?: readonly Row_2[];
38
51
  }): NiceRbacModel;
39
52
 
40
53
  /** Reads how `text` is written: BOM, line breaks, indentation, final newline, colon spacing. */
41
54
  export declare function detectJsonTextFormat(text: string): NiceJsonTextFormat;
42
55
 
56
+ /** An empty layout: no sections, no folders — the flat tree. */
57
+ export declare const emptyStudioLayout: () => NiceStudioLayout;
58
+
43
59
  /**
44
60
  * The file changes that store a document's new model: only files whose text differs from what
45
61
  * was read, plus files the encoder adds or removes.
@@ -50,7 +66,7 @@ export declare function encodeDocument(doc: NiceStudioDocument, model: unknown,
50
66
  export declare const endsWithAny: (...suffixes: string[]) => (path: string) => boolean;
51
67
 
52
68
  /** The module's entities as the tables NiceDataSourceBuilder queries. */
53
- export declare function entitiesToSchemas(entities: readonly Row[]): NiceDataSourceSchemaTable[];
69
+ export declare function entitiesToSchemas(entities: readonly Row_2[]): NiceDataSourceSchemaTable[];
54
70
 
55
71
  /** The file name of a path. */
56
72
  export declare const fileName: (path: string) => string;
@@ -131,12 +147,27 @@ declare interface FormFieldValidation {
131
147
  message?: string;
132
148
  }
133
149
 
150
+ /** A list item back as the stored script: its definition merged onto the entry as stored. */
151
+ export declare function fromStudioScriptItem(item: NiceStudioItem<NiceStudioScriptDef>): unknown;
152
+
134
153
  /**
135
154
  * Translations split into one file per language, edited as one document. A new language gets a
136
155
  * file shaped and formatted like its siblings; a language removed in the editor loses its file.
137
156
  */
138
157
  export declare function i18nFileKind(o?: NiceI18nFileKindOptions): NiceStudioFileKind<NiceStudioTranslations>;
139
158
 
159
+ /**
160
+ * The kind of a stored script: its `kind`, else from what it holds — no-code steps, a SQL language
161
+ * or `sql` text, a C# language (server) — else browser code.
162
+ */
163
+ export declare function inferStudioScriptKind(raw: Row): NiceStudioScriptKind;
164
+
165
+ /** Whether a layout holds nothing (its file can go). */
166
+ export declare const isEmptyStudioLayout: (layout: NiceStudioLayout) => boolean;
167
+
168
+ /** Whether a path is a module's layout file. */
169
+ export declare const isStudioLayoutPath: (path: string) => boolean;
170
+
140
171
  /**
141
172
  * A file holding a list of entries edited one at a time (views, workflows). Entries the editor
142
173
  * does not understand stay raw and round-trip as they are.
@@ -198,7 +229,7 @@ export declare function modulePrefix(files: readonly NiceStudioFile[]): string;
198
229
 
199
230
  export declare const nativeDataSourcesKind: NiceStudioFileKind<NiceDataSourceDef[]>;
200
231
 
201
- export declare const nativeEntitiesKind: NiceStudioFileKind<Row_2[]>;
232
+ export declare const nativeEntitiesKind: NiceStudioFileKind<Row_3[]>;
202
233
 
203
234
  /** The file kinds of the native format, in matching order. */
204
235
  export declare const nativeFileKinds: NiceStudioFileKind[];
@@ -207,17 +238,29 @@ export declare const nativeHooksKind: NiceStudioFileKind<NiceHookBinding[]>;
207
238
 
208
239
  export declare const nativeI18nKind: NiceStudioFileKind<NiceStudioTranslations>;
209
240
 
210
- export declare const nativeManifestKind: NiceStudioFileKind<Row_2>;
241
+ export declare const nativeManifestKind: NiceStudioFileKind<Row_3>;
211
242
 
212
243
  export declare const nativeRbacKind: NiceStudioFileKind<NiceRbacModel>;
213
244
 
214
- /** The studio's own format: manifest, entities, translations, views, workflows, data sources, access, hooks. */
245
+ /** `{id}.scripts.json`: `{ scripts: [...], phases: { postInstall: [...] } }` (1.4.6). */
246
+ export declare const nativeScriptsKind: NiceStudioFileKind<NiceStudioScripts>;
247
+
248
+ /** The studio's own format: manifest, entities, translations, views, workflows, data sources, access, hooks, scripts. */
215
249
  export declare const nativeStudioPreset: NiceStudioPreset;
216
250
 
217
251
  export declare const nativeViewsKind: NiceStudioFileKind<NiceStudioItem<NiceViewDefinition>[]>;
218
252
 
219
253
  export declare const nativeWorkflowsKind: NiceStudioFileKind<NiceStudioItem<NiceWorkflowDefinition>[]>;
220
254
 
255
+ /** A new script of a kind, with a starting body in its language. */
256
+ export declare function newStudioScript(spec: NiceStudioNewScript): NiceStudioScriptDef;
257
+
258
+ /** The script kinds, in the order "Add script" offers them. */
259
+ export declare const NICE_STUDIO_SCRIPT_KINDS: readonly NiceStudioScriptKind[];
260
+
261
+ /** Install phases offered for database scripts when the preset names none. */
262
+ export declare const NICE_STUDIO_SCRIPT_PHASES: readonly string[];
263
+
221
264
  /** Options of {@link arrayFileKind}. */
222
265
  export declare interface NiceArrayFileKindOptions {
223
266
  id: string;
@@ -381,6 +424,27 @@ export declare interface NiceObjectFileKindOptions {
381
424
  match(path: string): boolean;
382
425
  }
383
426
 
427
+ /** Options of {@link scriptsFileKind}. */
428
+ export declare interface NiceScriptsFileKindOptions {
429
+ id?: string;
430
+ label?: string;
431
+ labelKey?: string;
432
+ icon?: string;
433
+ match(path: string): boolean;
434
+ /** The property holding the scripts list. Default `scripts`; the file may also be the bare list. */
435
+ property?: string;
436
+ /**
437
+ * The property holding the database scripts per phase. Default `phases`. The same as `property`:
438
+ * that property holds either — a list of scripts or an object of phases (OmniVerk).
439
+ */
440
+ phasesProperty?: string;
441
+ }
442
+
443
+ /** The studio's own editors. */
444
+ export declare type NiceStudioBuiltinEditorId = 'manifest' | 'entities' | 'i18n' | 'views' | 'workflows' | 'permissions' | 'rbac' | 'dataSources' | 'seeds' | 'hooks' | 'script'
445
+ /** A list of named scripts and database scripts per phase ({@link NiceStudioScripts}, 1.4.6). */
446
+ | 'scriptList' | 'json' | 'text';
447
+
384
448
  /** What a file kind's decode and encode know about the module. */
385
449
  export declare interface NiceStudioCodecContext {
386
450
  moduleId: string;
@@ -402,8 +466,11 @@ export declare interface NiceStudioDocument<M = unknown> {
402
466
  error?: string;
403
467
  }
404
468
 
405
- /** The built-in editors a file kind can open in. */
406
- export declare type NiceStudioEditorId = 'manifest' | 'entities' | 'i18n' | 'views' | 'workflows' | 'permissions' | 'rbac' | 'dataSources' | 'seeds' | 'hooks' | 'script' | 'json' | 'text';
469
+ /**
470
+ * The editors a file kind can open in: a built-in one, or the id of an editor the host registers
471
+ * (1.4.5 — the union was closed; an unknown id opens as raw JSON / text until one is registered).
472
+ */
473
+ export declare type NiceStudioEditorId = NiceStudioBuiltinEditorId | (string & {});
407
474
 
408
475
  /** New and removed files of an encoded document. */
409
476
  export declare interface NiceStudioEncoded {
@@ -463,6 +530,11 @@ export declare interface NiceStudioFileKind<M = unknown> {
463
530
  /** The document a file belongs to (files with the same group open together). Default: the path. */
464
531
  group?(path: string): string;
465
532
  editor: NiceStudioEditorId;
533
+ /**
534
+ * The tree group its documents are listed under (1.4.5): one of the preset's `groups`, or a
535
+ * built-in group id. Default: the built-in group of its editor (none for raw JSON / text).
536
+ */
537
+ treeGroup?: string;
466
538
  /** The files of one document → the editor's model. Throwing opens the files as raw JSON / text. */
467
539
  decode(files: readonly NiceStudioFile[], ctx: NiceStudioCodecContext): M;
468
540
  /** The model → the document's files (only their text; unchanged files may be returned as they were). */
@@ -479,6 +551,20 @@ export declare interface NiceStudioGeneratedModule {
479
551
  }>;
480
552
  }
481
553
 
554
+ /**
555
+ * A group of the tree a preset adds (1.4.5): its documents — of the kinds whose `treeGroup` names
556
+ * it — are listed one per row under it, like scripts.
557
+ */
558
+ export declare interface NiceStudioGroupDef {
559
+ id: string;
560
+ label: string;
561
+ labelKey?: string;
562
+ /** NiceIcon name. */
563
+ icon?: string;
564
+ /** Where it goes among the groups (the built-in ones are 10, 20, … 100). Default: after them. */
565
+ order?: number;
566
+ }
567
+
482
568
  /** A problem found in a module. */
483
569
  export declare interface NiceStudioIssue {
484
570
  severity: 'error' | 'warning' | 'info';
@@ -512,6 +598,40 @@ export declare interface NiceStudioItem<D> {
512
598
  rawReason?: string;
513
599
  }
514
600
 
601
+ /** The layout of a module — the content of its `{prefix}.studio.json`. */
602
+ export declare interface NiceStudioLayout {
603
+ version: 1;
604
+ sections: NiceStudioLayoutSection[];
605
+ folders: NiceStudioLayoutFolder[];
606
+ /** By entry ref, `group:key` — `entities:Customer`, `views:customer-list`. */
607
+ placement: Record<string, NiceStudioLayoutPlacement>;
608
+ }
609
+
610
+ /** A folder inside one group of a module (entities, views…), optionally nested and in a section. */
611
+ export declare interface NiceStudioLayoutFolder {
612
+ id: string;
613
+ label: string;
614
+ /** The group it belongs to: `entities`, `views`, `workflows`, a preset's own group… */
615
+ group: string;
616
+ /** The folder it sits in. */
617
+ parent?: string;
618
+ /** The section it sits in (absent: the module's own groups). */
619
+ section?: string;
620
+ }
621
+
622
+ /** Where one entry sits: a section, a folder, an order among its siblings. */
623
+ export declare interface NiceStudioLayoutPlacement {
624
+ section?: string;
625
+ folder?: string;
626
+ order?: number;
627
+ }
628
+
629
+ /** A section of a module: a band of the tree that holds groups (Sales, Warehouse…). */
630
+ export declare interface NiceStudioLayoutSection {
631
+ id: string;
632
+ label: string;
633
+ }
634
+
515
635
  /** What validators and generators get. */
516
636
  export declare interface NiceStudioModuleContext {
517
637
  key: NiceStudioModuleKey;
@@ -569,6 +689,16 @@ export declare interface NiceStudioModuleSpec {
569
689
  permissions?: boolean;
570
690
  }
571
691
 
692
+ /** What "Add script" asks for. */
693
+ export declare interface NiceStudioNewScript {
694
+ kind: NiceStudioScriptKind;
695
+ /** The display name; the script's `name` is made from it. */
696
+ name: string;
697
+ language?: string;
698
+ category?: string;
699
+ trigger?: string;
700
+ }
701
+
572
702
  /** A group of modules in a workspace (a category, a product line). */
573
703
  export declare interface NiceStudioPackage {
574
704
  id: string;
@@ -579,6 +709,11 @@ export declare interface NiceStudioPackage {
579
709
  /** Computed from the modules (e.g. their `category`) rather than stored: it cannot be edited. */
580
710
  derived?: boolean;
581
711
  readOnly?: boolean;
712
+ /**
713
+ * The package it sits in (1.4.5): packages nest in the tree. An id with `/` (`Finance/Banking`, an
714
+ * OmniVerk category path) nests under the part before its last `/` without it.
715
+ */
716
+ parentId?: string;
582
717
  }
583
718
 
584
719
  /** The model of the `permissions` editor: permission codes and the groups (roles) granting them. */
@@ -604,6 +739,8 @@ export declare interface NiceStudioPreset {
604
739
  id: string;
605
740
  /** Tried in order; a path no kind matches opens as raw JSON (`*.json`) or text. */
606
741
  kinds: NiceStudioFileKind[];
742
+ /** Groups of the tree the preset adds to the built-in ones (1.4.5). */
743
+ groups?: NiceStudioGroupDef[];
607
744
  /** The manifest's sections, each a form over part of the manifest. */
608
745
  manifestSections?: NiceManifestSection[];
609
746
  entities?: NiceStudioEntityOptions;
@@ -627,6 +764,8 @@ export declare interface NiceStudioPreset {
627
764
  path: string;
628
765
  text: string;
629
766
  } | undefined;
767
+ /** Kinds, categories, triggers and phases of the module's scripts (1.4.6). */
768
+ scripts?: NiceStudioScriptOptions;
630
769
  /** Lifecycle triggers offered by a `hooks` document. */
631
770
  hooks?: {
632
771
  triggers: Array<{
@@ -698,6 +837,73 @@ export declare interface NiceStudioRevision {
698
837
  path?: string;
699
838
  }
700
839
 
840
+ /** A named script of a module (1.4.6). Fields the studio does not edit stay in the stored entry. */
841
+ export declare interface NiceStudioScriptDef {
842
+ id?: string;
843
+ /** The name other scripts and the app call it by (unique in the module). */
844
+ name: string;
845
+ displayName?: string;
846
+ description?: string;
847
+ kind: NiceStudioScriptKind;
848
+ /** `typescript`, `javascript`, `csharp`, `sql`… (none for a no-code script). */
849
+ language?: string;
850
+ /** Free grouping: `formatting`, `validation`, `integration`… */
851
+ category?: string;
852
+ /** What runs it: an event, a schedule, a button (one of the preset's `scripts.triggers`). */
853
+ trigger?: string;
854
+ parameters?: NiceStudioScriptParameter[];
855
+ returnType?: string;
856
+ /** The code (frontend, backend, SQL). */
857
+ source?: string;
858
+ /** A file of the module holding the code instead of `source`. */
859
+ sourcePath?: string;
860
+ /** The steps of a no-code script. */
861
+ steps?: NiceNoCodeStep[];
862
+ }
863
+
864
+ /**
865
+ * What a script is (1.4.6): code run in the browser (`frontend`), code run on the server
866
+ * (`backend`), no-code steps (`noCode`, run by `runNoCodeScript`) or a SQL query or procedure.
867
+ */
868
+ export declare type NiceStudioScriptKind = 'frontend' | 'backend' | 'noCode' | 'sql';
869
+
870
+ /** How a preset's scripts look (1.4.6). */
871
+ export declare interface NiceStudioScriptOptions {
872
+ /** The kinds "Add script" offers. Default: all four. */
873
+ kinds?: NiceStudioScriptKind[];
874
+ /** Categories offered (the module's own are offered too). */
875
+ categories?: string[];
876
+ /** What can run a script. */
877
+ triggers?: Array<{
878
+ id: string;
879
+ label: string;
880
+ description?: string;
881
+ }>;
882
+ /** Install phases offered for database scripts. Default: preInstall, postInstall, preUninstall, postUninstall. */
883
+ phases?: string[];
884
+ }
885
+
886
+ /** A parameter of a script. */
887
+ export declare interface NiceStudioScriptParameter {
888
+ name: string;
889
+ /** Its type as the script's language writes it (`string`, `Date | string`, `decimal`). */
890
+ type?: string;
891
+ description?: string;
892
+ default?: unknown;
893
+ }
894
+
895
+ /** The model of the `scriptList` editor (1.4.6): named scripts and database scripts per phase. */
896
+ export declare interface NiceStudioScripts {
897
+ scripts: Array<NiceStudioItem<NiceStudioScriptDef>>;
898
+ /** SQL statements per install phase: `{ postInstall: ['CREATE INDEX …'] }`. */
899
+ phases?: Record<string, string[]>;
900
+ /**
901
+ * What the file can hold when one property keeps either (OmniVerk's `scripts` is a list of
902
+ * scripts or an object of phases): only named scripts, or only phases. Absent: both.
903
+ */
904
+ holds?: 'scripts' | 'phases';
905
+ }
906
+
701
907
  /** The model of the `seeds` editor: rows per entity, plus demo rows. */
702
908
  export declare interface NiceStudioSeeds {
703
909
  seeds: Record<string, Array<Record<string, unknown>>>;
@@ -767,6 +973,12 @@ export declare function parseJsonText(text: string): {
767
973
  format: NiceJsonTextFormat;
768
974
  };
769
975
 
976
+ /**
977
+ * A layout from its file's text — what it can read of it: unknown fields and broken entries are
978
+ * dropped, a text that does not parse gives the empty layout.
979
+ */
980
+ export declare function parseStudioLayout(text: string | undefined): NiceStudioLayout;
981
+
770
982
  /**
771
983
  * `previous` with its content replaced by `next`, changing as few bytes as possible. Falls back
772
984
  * to {@link stringifyJsonText} in the file's own format when the text cannot be patched (invalid
@@ -777,9 +989,36 @@ export declare function patchJsonText(previous: string, next: unknown, options?:
777
989
  /** {@link patchJsonText}, also telling whether the patch was exact. */
778
990
  export declare function patchJsonTextDetailed(previous: string, next: unknown, options?: NiceJsonPatchOptions): NiceJsonPatchResult;
779
991
 
992
+ /**
993
+ * The layout with an entry put somewhere: into a folder (its section follows the folder's), into a
994
+ * section (out of any folder), or back to its group (`{}`).
995
+ */
996
+ export declare function placeStudioEntry(layout: NiceStudioLayout, ref: string, target: {
997
+ folder?: string;
998
+ section?: string;
999
+ }): NiceStudioLayout;
1000
+
780
1001
  /** The translations inside a file: `translations`, `keys`, or the whole file when it is a flat map. */
781
1002
  export declare function readTranslations(root: unknown): Record<string, string>;
782
1003
 
1004
+ /**
1005
+ * The layout without a section or folder. What it held moves up: a folder's entries and folders go
1006
+ * to its parent (or the group), a section's folders and entries back to the module's own groups.
1007
+ */
1008
+ export declare function removeStudioLayoutNode(layout: NiceStudioLayout, node: {
1009
+ kind: 'section' | 'folder';
1010
+ id: string;
1011
+ }): NiceStudioLayout;
1012
+
1013
+ /** The layout after an entry was renamed — its placement follows it (`entities:Old` → `entities:New`). */
1014
+ export declare function renameStudioEntryRef(layout: NiceStudioLayout, from: string, to: string): NiceStudioLayout;
1015
+
1016
+ /** The layout with a section or folder renamed. */
1017
+ export declare function renameStudioLayoutNode(layout: NiceStudioLayout, node: {
1018
+ kind: 'section' | 'folder';
1019
+ id: string;
1020
+ }, label: string): NiceStudioLayout;
1021
+
783
1022
  /** The kind a path opens with: the first that matches, else JSON or text. */
784
1023
  export declare function resolveFileKind(kinds: readonly NiceStudioFileKind[], path: string): NiceStudioFileKind;
785
1024
 
@@ -787,18 +1026,48 @@ declare type Row = Record<string, unknown>;
787
1026
 
788
1027
  declare type Row_2 = Record<string, unknown>;
789
1028
 
1029
+ declare type Row_3 = Record<string, unknown>;
1030
+
790
1031
  /** Parses JSON without a BOM and returns `fallback` when the text is not JSON. */
791
1032
  export declare function safeJson<T = unknown>(text: string, fallback: T): T;
792
1033
 
1034
+ /**
1035
+ * A file of named scripts and database scripts per phase (the `scriptList` editor). Scripts the
1036
+ * form does not understand stay raw and round-trip as they are; a file whose phases are not lists
1037
+ * of SQL text opens as raw JSON.
1038
+ */
1039
+ export declare function scriptsFileKind(o: NiceScriptsFileKindOptions): NiceStudioFileKind<NiceStudioScripts>;
1040
+
1041
+ /** A layout's file text: two-space JSON with a final newline, in the line ending of `previous`. */
1042
+ export declare function serializeStudioLayout(layout: NiceStudioLayout, previous?: string): string;
1043
+
793
1044
  /** A file-name-safe id out of a display name: "Bike rental" → `bike-rental`. */
794
1045
  export declare function slugifyModuleId(name: string): string;
795
1046
 
796
1047
  /** Writes `value` in a given format (defaults: two spaces, LF, final newline, no BOM). */
797
1048
  export declare function stringifyJsonText(value: unknown, format?: Partial<NiceJsonTextFormat>): string;
798
1049
 
1050
+ /** The ref of an entry in a layout: `group:key`. */
1051
+ export declare const studioEntryRef: (group: string, key: string) => string;
1052
+
1053
+ /**
1054
+ * The path of a module's layout file: the one it has, else `{prefix}.studio.json` after the prefix
1055
+ * of its files, else `module.studio.json`.
1056
+ */
1057
+ export declare function studioLayoutPath(files: readonly NiceStudioFile[]): string;
1058
+
1059
+ /** `"Send invoice"` → `sendInvoice`: a name usable as a function's. */
1060
+ export declare function studioScriptIdentifier(name: string): string;
1061
+
1062
+ /** The languages of a kind, the first being the default (none for no-code). */
1063
+ export declare function studioScriptLanguages(kind: NiceStudioScriptKind): string[];
1064
+
799
1065
  /** Any other file, edited as text. */
800
1066
  export declare const textFallbackKind: NiceStudioFileKind<string>;
801
1067
 
1068
+ /** A stored script as a list item: with a definition when the form can keep every field it edits. */
1069
+ export declare function toStudioScriptItem(raw: unknown, index: number): NiceStudioItem<NiceStudioScriptDef>;
1070
+
802
1071
  /** The file with its translations replaced, in the same place they were. */
803
1072
  export declare function writeTranslations(root: unknown, entries: Record<string, string>): unknown;
804
1073