@stoker-platform/node-client 0.5.44 → 0.5.45

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/bundle.cjs CHANGED
@@ -11,4 +11,4 @@ ${i}`)}})()]),r.length>0)throw new Error(r.join(", "))},nr=async(n,e,t,s,r,i,o,a
11
11
  <a href="${p}">${p}</a>`)}catch{throw await u(r,c),new Error(c)}}}return h.uid},rr=async(n,e)=>{const{labels:t,parentCollection:s}=e;if(s){const r=n.at(-2);if(!r)throw new Error("PERMISSION_DENIED");const i=[...n].slice(0,-2),o=await Qe(i,r).catch(()=>{throw new Error("PERMISSION_DENIED")}),a=o.Collection_Path;if(a.push(o.id),a.push(t.collection),!He(n,a))throw new Error("PERMISSION_DENIED")}else if(n.length>1)throw new Error("PERMISSION_DENIED")},Un=n=>n!==null&&typeof n=="object"&&!Array.isArray(n),qc=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{Un(r)&&Object.keys(r).length===2&&typeof r.seconds=="number"&&typeof r.nanoseconds=="number"?t[s]=new B.Timestamp(r.seconds,r.nanoseconds):Un(r)&&e(r)})};e(n)},ir=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{Un(r)&&Object.keys(r).length===2&&typeof r._seconds=="number"&&typeof r._nanoseconds=="number"?t[s]=new B.Timestamp(r._seconds,r._nanoseconds):Un(r)&&e(r)})};e(n)},Yn=n=>{if(typeof n=="object")for(const e in n)Object.prototype.hasOwnProperty.call(n,e)&&(n[e]==="_DELETE_FIELD"?n[e]=B.FieldValue.delete():Yn(n[e]))},Bc=(n,e,t)=>{if(X(t)&&t.includeFields){const s={};return t.includeFields.forEach(r=>{if(e[r]!==void 0){s[r]=e[r];const i=W(n.fields,r);gt(n,[i]).size===1&&(s[`${r}_Lowercase`]=e[`${r}_Lowercase`])}}),s}return{}},ii=async(n,e,t,s,r,i,o)=>{if(!X(t)||!t.enforceHierarchy)return;const{fields:a}=e,l=B.getFirestore(),c=Object.entries(s[t.name]);if(!c.length)throw new Error(`VALIDATION_ERROR: relation ${t.name} is required`);const[u,h]=c[0];if(!h)throw new Error(`VALIDATION_ERROR: Relation ${t.name} is required`);const d=Se(l,h.Collection_Path,n);if(i.size++,!o&&i.size>500)throw new Error("VALIDATION ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks, entity restrictions (in permissions when dealing with user collections) or relation hierarchy checks.");const f=await r.get(d.doc(u));if(!f.exists)throw new Error(`VALIDATION_ERROR: Record ${u} not found in collection ${t.collection}`);const p=f.data(),O=W(a,t.enforceHierarchy.field),y=t.enforceHierarchy;if(!p[y.recordLinkField]||!s[O.name]||!Object.keys(s[O.name]).every(g=>Object.keys(p[y.recordLinkField]).includes(g)))throw new Error("VALIDATION_ERROR: Invalid relation hierarchy")},yn=async(n,e,t)=>{delete e[n.name][t],e[`${n.name}_Array`]=e[`${n.name}_Array`]?.filter(s=>s!==t),delete e[`${n.name}_Single`]},ms=async(n,e,t,s,r)=>{e[n.name]||={},e[n.name][s]=t,e[`${n.name}_Array`]||=[],e[`${n.name}_Array`].push(s),r&&(e[`${n.name}_Single`]={id:s,...t})},Hc=(n,e,t,s,r,i)=>{const o=[],a=[];for(const l of s.fields)X(l)&&l.twoWay&&l.collection===t&&((n==="Create"||!i?.[l.name]?.[e])&&r[l.name]?.[e]&&o.push(l),n==="Update"&&i?.[l.name]?.[e]&&!r[l.name]?.[e]&&a.push(l));return{addedFields:o,removedFields:a}},or=async(n,e,t,s,r,i,o,a,l,c,u,h)=>{const{fields:d}=i,f=B.getFirestore(),p=new Map,O=new Map,y=new Map;for(const g of d)X(g)&&["OneToOne","OneToMany"].includes(g.type)&&g.enforceHierarchy&&s[g.name]&&(n==="Create"||n==="Update"&&!He(h?.[g.name],s[g.name]))&&await ii(e,i,g,s,a,l);for(const g of d)if(X(g)&&g.twoWay){const N=o.collections[g.collection],b=W(N.fields,g.twoWay),x=ut(N,[b]);if(s[g.name]){const E=Object.entries(s[g.name]);for(const C of E){const[_,z]=C;if(n==="Create"||!h?.[g.name]?.[_]){let k;const m=y.get(g.collection)?.[_];if(m)k=m;else{l.size++,l&&l.size>500&&console.error(new Error(`VALIDATION_ERROR: ${l.size} operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of two way updates, unique field checks, entity restrictions (in permissions when dealing with user collections) or relation hierarchy checks.`));const v=Se(f,z.Collection_Path,e),H=await a.get(v.doc(_));if(!H.exists){yn(g,r,_);continue}const w=H.data();O.set(g.collection,{...O.get(g.collection)||{},[_]:w}),k=he({...w,...bn(s)})}const $={...k[b.name],[t]:{Collection_Path:s.Collection_Path,...Bc(i,s,b)}};k[b.name]=$,k[`${b.name}_Array`]||=[],k[`${b.name}_Array`].push(t),x.size===1&&(k[`${b.name}_Single`]={id:t,...$}),y.set(g.collection,{...y.get(g.collection)||{},[_]:k})}}}if(n==="Update"){const E=Object.entries(h?.[g.name]||{});for(const C of E){const[_,z]=C;if(!s[g.name]?.[_]){let k;const m=y.get(g.collection)?.[_];if(m)k=m;else{l.size++,l&&l.size>500&&console.error(new Error(`VALIDATION_ERROR: ${l.size} operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of two way updates, unique field checks, entity restrictions (in permissions when dealing with user collections) or relation hierarchy checks.`));const $=Se(f,z.Collection_Path,e),v=await a.get($.doc(_));if(!v.exists){p.set(g.name,[...p.get(g.name)||[],_]);continue}const H=v.data();O.set(g.collection,{...O.get(g.collection)||{},[_]:H}),k=he({...H,...bn(s)})}k[b.name][t]&&delete k[b.name][t],Array.isArray(k[`${b.name}_Array`])&&(k[`${b.name}_Array`]=k[`${b.name}_Array`].filter($=>$!==t)),x.size===1&&delete k[`${b.name}_Single`],y.set(g.collection,{...y.get(g.collection)||{},[_]:k})}}}}for(const[g,N]of y.entries()){const b=o.collections[g],x=Ze(g,o);for(const[E,C]of Object.entries(N)){const{addedFields:_,removedFields:z}=Hc(n,E,g,i,s,h);if(c&&u){for(const k of _){const m=W(b.fields,k.twoWay);if(!cr(b,m,u)){yn(k,r,E);continue}}for(const k of z){const m=W(b.fields,k.twoWay),$=ut(b,[m]);if(!cr(b,m,u)){ms(k,r,h?.[k.name]?.[E],E,$.size===1);continue}}if(!it("Update",b,o,c,u,O.get(g)?.[E])){for(const k of _)yn(k,r,E);for(const k of z){const m=W(b.fields,k.twoWay),$=ut(b,[m]);ms(k,r,h?.[k.name]?.[E],E,$.size===1)}}if(!it("Update",b,o,c,u,C)){for(const k of _)yn(k,r,E);for(const k of z){const m=W(b.fields,k.twoWay),$=ut(b,[m]);ms(k,r,h?.[k.name]?.[E],E,$.size===1)}}}try{await nn("update",C,b,x,["update",C,{},void 0,C],o)}catch(k){throw new Error(`VALIDATION_ERROR: Two way relation update would invalidate record ${E} in ${g}: ${k.message}`)}for(const k of _){const m=W(b.fields,k.twoWay);["OneToOne","OneToMany"].includes(m.type)&&X(m)&&m.enforceHierarchy&&await ii(e,b,m,C,a,l,!0)}}}return p},$o=(n,e,t)=>{n==="create"&&ht.forEach(s=>{if(!He(e[s],t[s]))throw new Error(`Updating system fields in hooks is not allowed: ${s}`)}),n==="update"&&(["id","Collection_Path","Created_At","Saved_At","Created_By"].forEach(s=>{if(s in e)throw new Error(`Cannot update system field: ${s}`)}),ht.forEach(s=>{if(!["id","Collection_Path","Created_At","Saved_At","Created_By"].includes(s)&&!He(e[s],t[s]))throw new Error(`Updating system fields in hooks is not allowed: ${s}`)}))},ar=(n,e,t,s)=>{const{softDelete:r}=e;if(!r)return;const i=r?.archivedField,o=r?.timestampField;if(t[i]===!0)if(n==="create")t[o]=B.FieldValue.serverTimestamp();else{if(!s)throw new Error("Original record is required for update");if(!s[i])t[o]=B.FieldValue.serverTimestamp();else if(t[o]&&t[o]?.valueOf()!==s[o]?.valueOf())throw new Error("Soft delete timestamp cannot be changed")}},ps=async(n,e,t,s,r)=>{if(!be("Read",r.collections?.[e.labels.collection]))return!1;try{await Qe([e.labels.collection],t,{userId:s,providedTransaction:n})}catch{return!1}return!0},Gc=10,Yc=async(n,e)=>{if(n.length===0)return;const t=Math.min(e,n.length);let s=0;const r=async()=>{for(;s<n.length;){const i=s;s+=1,await n[i]()}};await Promise.all(Array.from({length:t},r))},Mo=async(n,e,t,s,r,i,o)=>{for(const[a,l]of Object.entries(e?.collections||{})){if(!r.collections[a])throw new Error("PERMISSION_DENIED");const c=r.collections[a].access,u=r.collections[a];if(s.collections?.[a]?.restrictEntities||s?.collections?.[a]?.recordOwner?.active||s?.collections?.[a]?.recordUser?.active||s?.collections?.[a]?.recordProperty?.active){const d=i?.collections?.[a],f=[];if(l.individualEntities){const p=l.individualEntities,O=d?.individualEntities||[],y=i?p.filter(g=>!O.includes(g)):p;for(const g of y){if(o&&o.size++,o&&o.size>500)throw new Error("VALIDATION_ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks or entity restrictions (in permissions when dealing with user collections).");f.push(async()=>{if(!await ps(n,u,g,t,s))throw new Error("PERMISSION_DENIED")})}}if(l.parentEntities){const p=c.entityRestrictions?.restrictions?.find(x=>x.type==="Parent"&&x.roles.some(E=>E.role===e.Role));if(!p)throw new Error("PERMISSION_DENIED");const O=W(u.fields,p.collectionField),y=r.collections[O.collection],g=l.parentEntities,N=d?.parentEntities||[],b=i?g.filter(x=>!N.includes(x)):g;for(const x of b){if(o&&o.size++,o&&o.size>500)throw new Error("VALIDATION_ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks or entity restrictions (in permissions when dealing with user collections).");f.push(async()=>{if(!await ps(n,y,x,t,s))throw new Error("PERMISSION_DENIED")})}}if(l.parentPropertyEntities){const p=c.entityRestrictions?.restrictions?.find(b=>b.type==="Parent_Property"&&b.roles.some(x=>x.role===e.Role));if(!p)throw new Error("PERMISSION_DENIED");const O=W(u.fields,p.collectionField),y=r.collections[O.collection],g=l.parentPropertyEntities,N=d?.parentPropertyEntities||{};for(const[b,x]of Object.entries(g)){const E=N[b]||[],C=i?x.filter(_=>!E.includes(_)):x;for(const _ of C){if(o&&o.size++,o&&o.size>500)throw new Error("VALIDATION_ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks or entity restrictions (in permissions when dealing with user collections).");f.push(async()=>{if(!await ps(n,y,_,t,s))throw new Error("PERMISSION_DENIED")})}}}await Yc(f,Gc)}}},Jc=async(n,e,t)=>{const s=t?.userId,r=t?.user;let i=t?.context;const o=ze(),a=vt();if(t?.providedTransaction&&s)throw new Error("PERMISSION_DENIED");if(t?.providedSchema&&s)throw new Error("PERMISSION_DENIED");let l=t?.providedSchema||await je();if(n.length===0)throw new Error("EMPTY_PATH");const c=n.at(-1),u=Object.keys(l.collections).includes(c),h=a.disabledCollections?.includes(c);if(!u||h)throw new Error("COLLECTION_NOT_FOUND");const d=l.collections[c],{labels:f,fields:p,enableWriteLog:O,softDelete:y}=d,g=Ze(f.collection,l),N=await oe(a.appName),b=B.getFirestore(),x=yt.getAuth(),C=(s?await x.getUser(s):void 0)?.customClaims?.role;let _;s&&await rr(n,d);const z=Se(b,n,o),k=t?.id||z.doc().id;i=i||{},i.collection=f.collection,e.id=k,ir(e),Yn(e);const m=Vs("create",n,e,l,N,"Online",s||"System",B.Timestamp.now(),B.FieldValue.serverTimestamp());t?.createdAt&&(m.Created_At=t.createdAt),t?.createdBy&&(m.Created_By=t.createdBy);const $=he(m);y&&(m[y.archivedField]=!1),Le(e),O&&!t?.providedTransaction&&await pt("create","started",m,o,n,k,d),await ae("preOperation",a,g,["create",m,k,i]),await ae("preWrite",a,g,["create",m,k,i]),Tn(d,m,l),Sn(d,m),await oa(m,d,g,C),Le(m);try{if(d.auth&&r&&!r.password)throw new Error("Password is required");t?.providedTransaction||(await Fo("create",o,k,m,d,l),await nn("create",m,d,g,["create",m,i],l))}catch(R){throw new Error(`VALIDATION_ERROR: ${R.message}`)}Le(m),e.id=k,y&&(m[y.archivedField]=!1),Tn(d,m,l),Sn(d,m);try{$o("create",m,$),ar("create",d,m),await nn("create",m,d,g,["create",m,i],l)}catch(R){throw new Error(`VALIDATION_ERROR: ${R.message}`)}if(s){const R=C;if(!R)throw new Error("USER_ERROR");if(!(g.custom?.serverAccess?.create!==void 0?await oe(g.custom.serverAccess.create,[R,m]):!0))throw new Error("PERMISSION_DENIED");for(const q of d.fields){if(!(q.name in m))continue;const P=Ae(q,g);if(P?.custom?.serverAccess?.create!==void 0&&!await oe(P.custom.serverAccess.create,[R,m]))throw new Error("PERMISSION_DENIED")}}r&&(r.permissions||={},r.permissions.Role||=m.Role,r.permissions.Enabled||=m.Enabled);const w=async(R,A)=>{const[q,P,S,L]=await Promise.all([t?.providedTransaction?Promise.resolve({}):R.get(b.collection("system_deployment").doc("latest_deploy")),t?.providedTransaction?Promise.resolve({}):R.get(b.collection("system_deployment").doc("maintenance_mode")),s?R.get(b.collection("tenants").doc(o).collection("system_user_permissions").doc(s)):Promise.resolve({}),t?.providedSchema?Promise.resolve(t.providedSchema):je()]);if(A&&(A.size+=3),!t?.providedTransaction){if(!q.exists)throw new Error("VERSION_ERROR");const Z=q.data();if(Z.force&&m.Last_Write_At.valueOf()<Z.time.valueOf())throw new Error("VERSION_ERROR");if(!P.exists)throw new Error("MAINTENANCE_MODE");if(P.data().active)throw new Error("MAINTENANCE_MODE")}if(l=L,s){if(!S?.exists)throw new Error("PERMISSION_DENIED");if(_=S.data(),!_.Role)throw new Error("USER_ERROR");if(!_.Enabled)throw new Error("PERMISSION_DENIED")}if(!t?.providedTransaction){const K=p.filter(te=>"unique"in te&&te.unique).map(async te=>{if(!s||!te.access||te.access.includes(_.Role)){if(!e[te.name])return;const qe=Ae(te,g);if(!(s&&qe?.custom?.serverAccess?.read!==void 0?await oe(qe.custom.serverAccess.read,[_?.Role,m]):!0))throw new Error("PERMISSION_DENIED");const Re=e[te.name].toString().toLowerCase().replace(/\s/g,"---").replaceAll("/","|||");if(Js(Re)){if(A&&A.size++,A&&A.size>500)throw new Error("VALIDATION_ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks.");if((await R.get(b.collection("tenants").doc(o).collection("system_unique").doc(f.collection).collection(`Unique-${f.collection}-${te.name}`).doc(Re)))?.exists)throw new Error(`VALIDATION_ERROR: ${te.name} "${m[te.name]}" already exists`)}else throw new Error(`VALIDATION_ERROR: ${te.name} "${m[te.name]}" is invalid`)}});await Promise.all(K)}ur(m,k,d,l,s,_,r?.permissions),r?.permissions&&s&&_&&await Mo(R,r.permissions,s,_,l),ur(m,k,d,l,s,_,r?.permissions)};if(d.auth&&r){await b.runTransaction(async A=>{await w(A)},{maxAttempts:10});const R=await sr(o,k,a,f.collection,m,r.permissions,r.password);m.User_ID=R}const I=async R=>{try{const A={size:1};await w(R,A),t?.noTwoWay||await or("Create",o,k,m,m,d,l,R,A,s,_);const q=Ls(l);Ys("create",R,n,k,m,l,d,t,q,B.FieldValue.arrayUnion,B.FieldValue.arrayRemove,B.FieldValue.delete,P=>b.collection("tenants").doc(o).collection("system_fields").doc(f.collection).collection(`${f.collection}-${P.name}`).doc(k),(P,S)=>b.collection("tenants").doc(o).collection("system_unique").doc(f.collection).collection(`Unique-${f.collection}-${P.name}`).doc(S),P=>b.collection("tenants").doc(o).collection("system_fields").doc(f.collection).collection(`${f.collection}-${P}`).doc(k),(P,S)=>Se(b,P,o).doc(S),(P,S,L)=>b.collection("tenants").doc(o).collection("system_fields").doc(P.collection).collection(`${P.collection}-${S}`).doc(L),(P,S,L)=>b.collection("tenants").doc(o).collection("system_fields").doc(P.collection).collection(`${P.collection}-${S.replaceAll(" ","-")}`).doc(L),void 0,void 0,A),R.set(z.doc(k),m)}catch(A){if(t?.providedTransaction)throw A;{const P=await ae("postWriteError",a,g,["create",m,k,i,A]);if(O&&(await new Promise(S=>{setTimeout(S,250)}),await pt("create",P?.resolved?"success":"failed",m,o,n,k,d,P?.resolved?void 0:A)),!P?.resolved)throw d.auth&&r&&await Ut(m),A}}};if(t?.providedTransaction?await I(t.providedTransaction):await b.runTransaction(async R=>{await I(R)},{maxAttempts:10}),!t?.providedTransaction){const R=["create",m,k,i],A=[...R];await ae("postWrite",a,g,R),await ae("postOperation",a,g,A)}return{id:k,...m}},Jt=async(n,e,t,s)=>{const r=ze(),i=yt.getAuth(),o=B.getFirestore(),a=e.customClaims||{};let l=!1;try{await i.updateUser(n,{email:e.email,disabled:e.disabled,displayName:e.displayName,photoURL:e.photoURL,emailVerified:!!e.emailVerified})}catch{l=!0}try{await i.setCustomUserClaims(n,{...a})}catch{l=!0}try{await o.collection("tenants").doc(r).collection("system_user_permissions").doc(n).update({...t,Collection:a.collection,Doc_ID:a.doc,Role:a.role,Enabled:!e.disabled})}catch{l=!0}if(l)throw new Error(`ROLLBACK_FAILED: ${s}`)},Po=async(n,e,t,s,r,i,o,a,l,c,u)=>{const h=yt.getAuth(),d=B.getFirestore(),f=a?.customClaims||{},p="USER_ERROR";let O="";if(n==="create"){if(!u)throw new Error("VALIDATION_ERROR: Password is required");if(!l)throw new Error("VALIDATION_ERROR: Permissions are required");try{O=await sr(e,t,s,r,i,l,u)}catch(y){throw new Error(y.message)}}else if(n==="update"){if(!c||!a)throw new Error("USER_ERROR");const y={};if(o.Name!==i.Name&&(y.displayName=i.Name),o.Email!==i.Email&&(y.email=i.Email,y.emailVerified=!1),o.Photo_URL!==i.Photo_URL&&(y.photoURL=i.Photo_URL?i.Photo_URL:void 0),o.Enabled!==i.Enabled&&(y.disabled=!i.Enabled),u&&(y.password=u),Object.keys(y).length)try{await h.updateUser(o.User_ID,y),y.disabled===!0&&await h.revokeRefreshTokens(o.User_ID)}catch{throw await Jt(o.User_ID,a,c,p),new Error(p)}if(i.Role&&i.Role!==o.Role)try{await h.setCustomUserClaims(o.User_ID,{...f,role:i.Role}),await h.revokeRefreshTokens(o.User_ID)}catch{throw await Jt(o.User_ID,a,c,p),new Error(p)}try{await d.collection("tenants").doc(e).collection("system_user_permissions").doc(o.User_ID).set({...l||c,Collection:f.collection,Doc_ID:f.doc,Role:i.Role,Enabled:i.Enabled??o.Enabled??!1})}catch{throw await Jt(o.User_ID,a,c,p),new Error(p)}if(o.Email!==i.Email){const g=s.auth.enableMultiFactorAuth;if(g===!0||typeof g=="object"&&g.includes(i.Role)){let N=await h.generateEmailVerificationLink(i.Email).catch(()=>{throw new Error("Error generating email verification link")});if(N.includes("apiKey=&")){const b=JSON.parse(process.env.STOKER_FB_WEB_APP_CONFIG);N=N.replace("apiKey=&",`apiKey=${b.apiKey}&`)}if(N){const b=`https://${h.app.options.projectId}.firebaseapp.com/__/auth/action${N}`,x=await oe(s.appName),E=s?.mail?.emailVerification&&s.mail.emailVerification(b,x);try{await nr(i.Email,E?.subject||"Please verify your email address",void 0,E?.html||`Please verify your email address by clicking the link:
12
12
  </br>
13
13
  </br>
14
- <a href="${b}">${b}</a>`)}catch{throw await Jt(o.User_ID,a,c,p),new Error(p)}}}}}else if(n==="delete")try{await Ut(o)}catch(y){throw new Error(y.message)}if(O)return O},Qc=async(n,e,t)=>{const s=ze(),r=B.getFirestore(),i=[e];t&&t.trim()!==""&&i.push(t),i.sort();const o=[];for(const a of i){const l=r.collection("tenants").doc(s).collection("system_locks").doc(a);if((await n.get(l)).exists)throw new Error("DOCUMENT_LOCKED");o.push(l)}for(const a of o)n.set(a,{locked:!0})},oi=async(n,e)=>{const t=ze(),s=B.getFirestore(),r=[n];e&&e.trim()!==""&&r.push(e),r.sort();const i=s.batch();for(const o of r){const a=s.collection("tenants").doc(t).collection("system_locks").doc(o);i.delete(a)}await i.commit()},Lo=async(n,e,t,s)=>{const r=s?.userId,i=s?.user;let o=s?.context;const a=ze(),l=vt();if(s?.providedTransaction&&r)throw new Error("PERMISSION_DENIED");if(s?.providedSchema&&r)throw new Error("PERMISSION_DENIED");if(s?.providedTransaction&&!s?.originalRecord)throw new Error("PERMISSION_DENIED");let c=s?.providedSchema||await je(!0);if(n.length===0)throw new Error("EMPTY_PATH");const u=n.at(-1),h=Object.keys(c.collections).includes(u),d=l.disabledCollections?.includes(u);if(!h||d)throw new Error("COLLECTION_NOT_FOUND");const f=c.collections[u],{labels:p,fields:O,enableWriteLog:y}=f,g=Ze(p.collection,c),N=await oe(l.appName),b=yt.getAuth(),x=B.getFirestore();let E;r&&await rr(n,f);const C=Se(x,n,a);o=o||{},o.collection=p.collection;let _=s?.originalRecord||await Qe(n,e,{userId:r,noComputedFields:!0,noEmbeddingFields:!0});for(const S of O)S.type==="Computed"&&delete t[S.name];if(c={...c,collections:Object.fromEntries(Object.entries(c.collections).map(([S,L])=>[S,{...L,fields:L.fields.filter(Z=>Z.type!=="Computed")}]))},i&&!i.operation)throw new Error("VALIDATION_ERROR: User operation is required");if(i&&!f.auth)throw new Error("VALIDATION_ERROR: User operations are only permitted for auth collections");if(i?.operation==="delete"&&i.permissions)throw new Error("VALIDATION_ERROR: Permissions are not allowed for delete operations");const z=f.auth&&i?.operation==="create",k=f.auth&&i?.operation==="delete",m=f.auth&&!z&&!k&&(i?.operation==="update"||t.Role||t.Enabled!==void 0||t.Name||t.Email||t.Photo_URL),$=S=>S.User_ID&&(f.auth&&!z&&!k&&i?.operation==="update"||t.Role&&t.Role!==S.Role||t.Enabled!==void 0&&t.Enabled!==S.Enabled||t.Name&&t.Name!==S.Name||t.Email&&t.Email!==S.Email||t.Photo_URL&&t.Photo_URL!==S.Photo_URL);delete t.id,ir(t),Yn(t);const v=Vs("update",n,t,c,N,"Online",r||"System",B.Timestamp.now(),B.FieldValue.serverTimestamp()),H=he(v);for(const S of O)!X(S)&&xe(v[S.name])&&S.nullable&&(v[S.name]=null);Le(v),Le(_),y&&!s?.providedTransaction&&await pt("update","started",v,a,n,e,f,void 0,_);const w=["update",v,e,o,void 0,he(_)];await ae("preOperation",l,g,w);const I=["update",v,e,o,void 0,he(_)];await ae("preWrite",l,g,I),Tn(f,v,c),Sn(f,v),Le(v);try{if(z&&!i.password)throw new Error("Password is required");if(!s?.providedTransaction){const S={..._,...v};await Fo("update",a,e,S,f,c),nt(S),await nn("update",S,f,g,["update",v,o,void 0,he(_)],c)}}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}Le(v),delete t.id,Tn(f,v,c),Sn(f,v);for(const S of O)!X(S)&&xe(v[S.name])&&S.nullable&&(v[S.name]=null);try{const S={..._,...v};nt(S),ar("update",f,v,_),$o("update",v,H),await nn("update",S,f,g,["update",v,o,void 0,_],c)}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}let T;i&&(i.permissions||={});const R=async(S,L,Z)=>{const[K,te,qe,fe,Re]=await Promise.all([s?.providedTransaction?Promise.resolve({}):S.get(x.collection("system_deployment").doc("latest_deploy")),s?.providedTransaction?Promise.resolve({}):S.get(x.collection("system_deployment").doc("maintenance_mode")),s?.providedTransaction?Promise.resolve(_):Qe(n,e,{userId:r,providedTransaction:S,noComputedFields:!0}),r?S.get(x.collection("tenants").doc(a).collection("system_user_permissions").doc(r)):Promise.resolve({}),s?.providedSchema?Promise.resolve(s.providedSchema):je()]);if(Z&&(Z.size+=3),!s?.providedTransaction){if(!K.exists)throw new Error("VERSION_ERROR");const ge=K.data();if(ge.force&&v.Last_Write_At.valueOf()<ge.time.valueOf())throw new Error("VERSION_ERROR");if(!te.exists)throw new Error("MAINTENANCE_MODE");if(te.data().active)throw new Error("MAINTENANCE_MODE")}if(!qe)throw new Error("NOT_FOUND");if(_=qe,c=Re,r){if(!fe?.exists)throw new Error("PERMISSION_DENIED");if(E=fe.data(),!E.Role)throw new Error("USER_ERROR");if(!E.Enabled)throw new Error("PERMISSION_DENIED")}if(Z&&(Z.size+=Xs(a,n,e,c,E).length),z&&_.User_ID||k&&!_.User_ID)throw new Error("USER_ERROR");if($(_)){const ge=await S.get(x.collection("tenants").doc(a).collection("system_user_permissions").doc(_.User_ID));if(Z&&Z.size++,!ge?.exists)throw new Error("PERMISSION_DENIED");if(T=ge.data(),i?.permissions){if(i.permissions.Role||=v.Role||_.Role,i.permissions.Enabled??=v.Enabled??_.Enabled,xe(i.permissions.Role))throw new Error("VALIDATION_ERROR: Role field is required");if(xe(i.permissions.Enabled))throw new Error("VALIDATION_ERROR: Enabled field is required")}}if(!s?.providedTransaction){const Wt=O.filter(we=>"unique"in we&&we.unique).map(async we=>{if(!r||!we.access||we.access.includes(E.Role)){if(v[we.name]===void 0||xe(v[we.name]))return;const jt=Ae(we,g),cn={..._,...v};if(!(r&&jt?.custom?.serverAccess?.read!==void 0?await oe(jt.custom.serverAccess.read,[E?.Role,cn]):!0))throw new Error("PERMISSION_DENIED");const Jn=v[we.name].toString().toLowerCase().replace(/\s/g,"---").replaceAll("/","|||");if(Js(Jn)){if(Z&&Z.size++,Z&&Z.size>500)throw new Error("VALIDATION_ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks.");const lr=await S.get(x.collection("tenants").doc(a).collection("system_unique").doc(p.collection).collection(`Unique-${p.collection}-${we.name}`).doc(Jn));if(lr.exists&&lr.data().id!==e)throw new Error(`VALIDATION_ERROR: ${we.name} "${v[we.name]}" already exists`)}else throw new Error(`VALIDATION_ERROR: ${we.name} "${v[we.name]}" is invalid`)}});await Promise.all(Wt)}if(r&&E?.Role){const ge=E.Role,Wt={..._,...v};if(!(g.custom?.serverAccess?.update!==void 0?await oe(g.custom.serverAccess.update,[ge,Wt,_]):!0))throw new Error("PERMISSION_DENIED");for(const jt of f.fields){const cn=Ae(jt,g);if(Object.prototype.hasOwnProperty.call(v,jt.name)&&cn?.custom?.serverAccess?.update!==void 0&&!await oe(cn.custom.serverAccess.update,[ge,Wt,_]))throw new Error("PERMISSION_DENIED")}}dr(v,_,e,f,c,r,E,i?.operation?i.operation:m?"update":void 0,i?.permissions,T),i?.permissions&&r&&E&&await Mo(S,i.permissions,r,E,c,T,Z),dr(v,_,e,f,c,r,E,i?.operation?i.operation:m?"update":void 0,i?.permissions,T),L&&(z||$(_)||k)&&await Qc(S,e,_.User_ID)};(z||m||k)&&await x.runTransaction(async S=>{await R(S,!0)},{maxAttempts:10});const A=async(S,L)=>{if(!_)throw new Error("NOT_FOUND");try{const Z={size:1},K={..._,...v};await R(S,!1,Z);let te;!s?.noTwoWay&&!s?.providedTransaction&&(te=await or("Update",a,e,K,v,f,c,S,Z,r,E,_));const qe=Ls(c);Ys("update",S,n,e,v,c,f,s,qe,B.FieldValue.arrayUnion,B.FieldValue.arrayRemove,B.FieldValue.delete,fe=>x.collection("tenants").doc(a).collection("system_fields").doc(p.collection).collection(`${p.collection}-${fe.name}`).doc(e),(fe,Re)=>x.collection("tenants").doc(a).collection("system_unique").doc(p.collection).collection(`Unique-${p.collection}-${fe.name}`).doc(Re),fe=>x.collection("tenants").doc(a).collection("system_fields").doc(p.collection).collection(`${p.collection}-${fe}`).doc(e),(fe,Re)=>Se(x,fe,a).doc(Re),(fe,Re,ge)=>x.collection("tenants").doc(a).collection("system_fields").doc(fe.collection).collection(`${fe.collection}-${Re}`).doc(ge),(fe,Re,ge)=>x.collection("tenants").doc(a).collection("system_fields").doc(fe.collection).collection(`${fe.collection}-${Re.replaceAll(" ","-")}`).doc(ge),_,te,Z),S.update(C.doc(e),v)}catch(Z){if(s?.providedTransaction)throw Z;{const K=["update",v,e,o,Z,void 0,void 0,void 0,he(_)],te=await ae("postWriteError",l,g,K);if(y&&(await new Promise(qe=>{setTimeout(qe,250)}),await pt("update",te?.resolved?"success":"failed",v,a,n,e,f,te?.resolved?void 0:Z,_)),!te?.resolved)throw z&&await Ut(_),$(_)&&await Jt(_.User_ID,L,T,"USER_ERROR"),k&&await x.collection("tenants").doc(a).collection(p.collection).doc(e).update({User_ID:B.FieldValue.delete()}),Z}}(z||$(_)||k)&&await ni(oi,[e,_.User_ID]).catch(()=>{throw new Error("USER_ERROR")})};try{let S;if(z||$(_)||k){if($(_)){S=await b.getUser(_.User_ID);const K=S.customClaims;if(!(K&&K.role&&K.collection&&K.doc))throw new Error("USER_ERROR")}const L={..._,...v};nt(L);const Z=await Po(i?.operation||"update",a,e,l,p.collection,L,_,S,i?.permissions,T,i?.password);z&&(v.User_ID=Z),k&&(v.User_ID=B.FieldValue.delete())}s?.providedTransaction?await A(s.providedTransaction,S):await x.runTransaction(async L=>{await A(L,S)},{maxAttempts:10})}catch(S){throw(z||$(_)||k)&&await ni(oi,[e,_.User_ID]).catch(()=>{throw new Error("USER_ERROR")}),S}if(!s?.providedTransaction){const S=["update",v,e,o,void 0,he(_)],L=[...S];await ae("postWrite",l,g,S),await ae("postOperation",l,g,L)}const q={..._,...v};return nt(q),{id:e,...q}},Kc=async(n,e,t)=>{const s=t?.userId;let r=t?.context;const i=ze(),o=vt();let a=await je();if(n.length===0)throw new Error("EMPTY_PATH");const l=n.at(-1),c=Object.keys(a.collections).includes(l),u=o.disabledCollections?.includes(l);if(!c||u)throw new Error("COLLECTION_NOT_FOUND");const h=a.collections[l],{labels:d,auth:f,enableWriteLog:p,softDelete:O}=h,y=Ze(d.collection,a),g=await oe(o.appName);if(O&&!f&&!t?.force)return await Lo(n,e,{[O.archivedField]:!0,[O.timestampField]:B.FieldValue.serverTimestamp()},{userId:s});const N=B.getFirestore();let b;s&&await rr(n,h);const x=Se(N,n,i);r=r||{},r.collection=d.collection;const E=await Qe(n,e,{userId:s});let C=Vs("delete",n,E,a,g,"Online",s||"System",B.Timestamp.now(),B.FieldValue.serverTimestamp());const _=bn(C);Le(C),p&&await pt("delete","started",C,i,n,e,h),await ae("preOperation",o,y,["delete",C,e,r]),await ae("preWrite",o,y,["delete",C,e,r]),Le(C);const m=async w=>{const[I,T,R,A]=await Promise.all([w.get(N.collection("system_deployment").doc("maintenance_mode")),Qe([d.collection],e,{userId:s,providedTransaction:w}),s?w.get(N.collection("tenants").doc(i).collection("system_user_permissions").doc(s)):Promise.resolve({}),je()]);if(!I.exists)throw new Error("MAINTENANCE_MODE");if(I.data().active)throw new Error("MAINTENANCE_MODE");if(!T)throw new Error("NOT_FOUND");if(C={...T,..._},a=A,s){if(!R?.exists)throw new Error("PERMISSION_DENIED");if(b=R.data(),!b.Role)throw new Error("USER_ERROR");if(!b.Enabled)throw new Error("PERMISSION_DENIED");Jo(C,e,h,a,s,b)}if(s&&b?.Role){const P=b.Role;if(!(y.custom?.serverAccess?.delete!==void 0?await oe(y.custom.serverAccess.delete,[P,C]):!0))throw new Error("PERMISSION_DENIED")}};h.auth&&(await N.runTransaction(async w=>{await m(w)},{maxAttempts:10}),C.User_ID&&await Ut(C));try{await N.runTransaction(async w=>{await m(w);const I=Ls(a);Ys("delete",w,n,e,C,a,h,t,I,B.FieldValue.arrayUnion,B.FieldValue.arrayRemove,B.FieldValue.delete,T=>N.collection("tenants").doc(i).collection("system_fields").doc(d.collection).collection(`${d.collection}-${T.name}`).doc(e),(T,R)=>N.collection("tenants").doc(i).collection("system_unique").doc(d.collection).collection(`Unique-${d.collection}-${T.name}`).doc(R),T=>N.collection("tenants").doc(i).collection("system_fields").doc(d.collection).collection(`${d.collection}-${T}`).doc(e),(T,R)=>Se(N,T,i).doc(R),(T,R,A)=>N.collection("tenants").doc(i).collection("system_fields").doc(T.collection).collection(`${T.collection}-${R}`).doc(A),(T,R,A)=>N.collection("tenants").doc(i).collection("system_fields").doc(T.collection).collection(`${T.collection}-${R.replaceAll(" ","-")}`).doc(A)),w.delete(x.doc(e))},{maxAttempts:10})}catch(w){const T=await ae("postWriteError",o,y,["delete",C,e,r,w]);if(p&&(await new Promise(R=>{setTimeout(R,250)}),await pt("delete",T?.resolved?"success":"failed",C,i,n,e,h,T?.resolved?void 0:w)),!T?.resolved)throw h.auth&&C.User_ID&&await N.collection("tenants").doc(i).collection(d.collection).doc(e).update({User_ID:B.FieldValue.delete()}),w}const $=["delete",C,e,r],v=[...$];return await ae("postWrite",o,y,$),await ae("postOperation",o,y,v),{id:e,...C}},Xc=async(n,e)=>{const t=B.getFirestore(),s=Qs(),r=process.env.ADMIN_SMS;if(s==="development")if(r)n=r;else throw new Error("Admin phone not set");const i={to:n,body:e};await t.collection("system_messages").add(i)},eu=n=>n!==null&&typeof n=="object",tu=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{r instanceof B.Timestamp?t[s]={_seconds:r.seconds,_nanoseconds:r.nanoseconds}:eu(r)&&e(r)})};e(n)},nu=async n=>await yt.getAuth().getUser(n),su=n=>{const e=Ks();return V.fromJSDate(n).setZone(e)},Vo=n=>{const e=Ks();return V.fromJSDate(n.toDate()).setZone(e)},ru=(n,e)=>{const s=V.fromJSDate(n,{zone:e}).offset,i=V.fromJSDate(n).offset,o=s-i;return V.fromJSDate(n).plus({minutes:o}).toJSDate()},iu=(n,e)=>{const s=V.fromJSDate(n,{zone:e}).offset,i=V.fromJSDate(n).offset,o=s-i;return V.fromJSDate(n).minus({minutes:o}).toJSDate()},ou=n=>"seconds"in n&&"nanoseconds"in n?Vo(new B.Timestamp(n.seconds,n.nanoseconds)).toFormat("MMMM d, yyyy '@' h:mm a"):"";exports.addRecord=Jc;exports.addUser=sr;exports.convertDateToTimezone=su;exports.convertTimestampToTimezone=Vo;exports.deleteRecord=Kc;exports.deleteUser=Ut;exports.deserializeDeleteSentinels=Yn;exports.deserializeTimestamps=ir;exports.deserializeTimestampsWithoutUnderscores=qc;exports.displayDate=ou;exports.fetchCurrentSchema=je;exports.fetchLastSchema=Zc;exports.getCachedConfigValue=na;exports.getCollectionRefs=No;exports.getCustomizationFile=Ze;exports.getCustomizationFiles=So;exports.getDocumentRefs=Xs;exports.getFirestorePathRef=Se;exports.getGlobalConfigModule=vt;exports.getInputSchema=Mc;exports.getMaintenanceInfo=Wc;exports.getMode=Qs;exports.getOne=Qe;exports.getSome=tr;exports.getTenant=ze;exports.getTimezone=Ks;exports.getUser=nu;exports.getVersionInfo=Uc;exports.getZodSchema=Oi;exports.initializeFirebase=zc;exports.initializeStoker=Lc;exports.isDeleteSentinel=xe;exports.keepTimezone=ru;exports.removeTimezone=iu;exports.runChildProcess=jc;exports.sendMail=nr;exports.sendMessage=Xc;exports.serializeTimestamps=tu;exports.setTenant=Vc;exports.tryPromise=oe;exports.updateRecord=Lo;exports.updateUser=Po;exports.validateRelations=or;exports.validateSoftDelete=ar;exports.writeLog=pt;
14
+ <a href="${b}">${b}</a>`)}catch{throw await Jt(o.User_ID,a,c,p),new Error(p)}}}}}else if(n==="delete")try{await Ut(o)}catch(y){throw new Error(y.message)}if(O)return O},Qc=async(n,e,t)=>{const s=ze(),r=B.getFirestore(),i=[e];t&&t.trim()!==""&&i.push(t),i.sort();const o=[];for(const a of i){const l=r.collection("tenants").doc(s).collection("system_locks").doc(a);if((await n.get(l)).exists)throw new Error("DOCUMENT_LOCKED");o.push(l)}for(const a of o)n.set(a,{locked:!0})},oi=async(n,e)=>{const t=ze(),s=B.getFirestore(),r=[n];e&&e.trim()!==""&&r.push(e),r.sort();const i=s.batch();for(const o of r){const a=s.collection("tenants").doc(t).collection("system_locks").doc(o);i.delete(a)}await i.commit()},Lo=async(n,e,t,s)=>{const r=s?.userId,i=s?.user;let o=s?.context;const a=ze(),l=vt();if(s?.providedTransaction&&r)throw new Error("PERMISSION_DENIED");if(s?.providedSchema&&r)throw new Error("PERMISSION_DENIED");if(s?.providedTransaction&&!s?.originalRecord)throw new Error("PERMISSION_DENIED");let c=s?.providedSchema||await je(!0);if(n.length===0)throw new Error("EMPTY_PATH");const u=n.at(-1),h=Object.keys(c.collections).includes(u),d=l.disabledCollections?.includes(u);if(!h||d)throw new Error("COLLECTION_NOT_FOUND");const f=c.collections[u],{labels:p,fields:O,enableWriteLog:y}=f,g=Ze(p.collection,c),N=await oe(l.appName),b=yt.getAuth(),x=B.getFirestore();let E;r&&await rr(n,f);const C=Se(x,n,a);o=o||{},o.collection=p.collection;let _=s?.originalRecord||await Qe(n,e,{userId:r,noComputedFields:!0,noEmbeddingFields:!0});for(const S of O)S.type==="Computed"&&delete t[S.name];if(c={...c,collections:Object.fromEntries(Object.entries(c.collections).map(([S,L])=>[S,{...L,fields:L.fields.filter(Z=>Z.type!=="Computed")}]))},i&&!i.operation)throw new Error("VALIDATION_ERROR: User operation is required");if(i&&!f.auth)throw new Error("VALIDATION_ERROR: User operations are only permitted for auth collections");if(i?.operation==="delete"&&i.permissions)throw new Error("VALIDATION_ERROR: Permissions are not allowed for delete operations");const z=f.auth&&i?.operation==="create",k=f.auth&&i?.operation==="delete",m=f.auth&&!z&&!k&&(i?.operation==="update"||t.Role||t.Enabled!==void 0||t.Name||t.Email||t.Photo_URL),$=S=>S.User_ID&&(f.auth&&!z&&!k&&i?.operation==="update"||t.Role&&t.Role!==S.Role||t.Enabled!==void 0&&t.Enabled!==S.Enabled||t.Name&&t.Name!==S.Name||t.Email&&t.Email!==S.Email||t.Photo_URL&&t.Photo_URL!==S.Photo_URL);delete t.id,ir(t),Yn(t);const v=Vs("update",n,t,c,N,"Online",r||"System",B.Timestamp.now(),B.FieldValue.serverTimestamp()),H=he(v);for(const S of O)!X(S)&&xe(v[S.name])&&S.nullable&&(v[S.name]=null);Le(v),Le(_),y&&!s?.providedTransaction&&await pt("update","started",v,a,n,e,f,void 0,_);const w=["update",v,e,o,void 0,he(_)];await ae("preOperation",l,g,w);const I=["update",v,e,o,void 0,he(_)];await ae("preWrite",l,g,I),Tn(f,v,c),Sn(f,v),Le(v);try{if(z&&!i.password)throw new Error("Password is required");if(!s?.providedTransaction){const S={..._,...v};await Fo("update",a,e,S,f,c),nt(S),await nn("update",S,f,g,["update",v,o,void 0,he(_)],c)}}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}Le(v),delete t.id,Tn(f,v,c),Sn(f,v);for(const S of O)!X(S)&&xe(v[S.name])&&S.nullable&&(v[S.name]=null);try{const S={..._,...v};nt(S),ar("update",f,v,_),$o("update",v,H),await nn("update",S,f,g,["update",v,o,void 0,_],c)}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}let T;i&&(i.permissions||={});const R=async(S,L,Z)=>{const[K,te,qe,fe,Re]=await Promise.all([s?.providedTransaction?Promise.resolve({}):S.get(x.collection("system_deployment").doc("latest_deploy")),s?.providedTransaction?Promise.resolve({}):S.get(x.collection("system_deployment").doc("maintenance_mode")),s?.providedTransaction?Promise.resolve(_):Qe(n,e,{userId:r,providedTransaction:S,noComputedFields:!0}),r?S.get(x.collection("tenants").doc(a).collection("system_user_permissions").doc(r)):Promise.resolve({}),s?.providedSchema?Promise.resolve(s.providedSchema):je()]);if(Z&&(Z.size+=3),!s?.providedTransaction){if(!K.exists)throw new Error("VERSION_ERROR");const ge=K.data();if(ge.force&&v.Last_Write_At.valueOf()<ge.time.valueOf())throw new Error("VERSION_ERROR");if(!te.exists)throw new Error("MAINTENANCE_MODE");if(te.data().active)throw new Error("MAINTENANCE_MODE")}if(!qe)throw new Error("NOT_FOUND");if(_=qe,c=Re,r){if(!fe?.exists)throw new Error("PERMISSION_DENIED");if(E=fe.data(),!E.Role)throw new Error("USER_ERROR");if(!E.Enabled)throw new Error("PERMISSION_DENIED")}if(Z&&(Z.size+=Xs(a,n,e,c,E).length),z&&_.User_ID||k&&!_.User_ID)throw new Error("USER_ERROR");if($(_)){const ge=await S.get(x.collection("tenants").doc(a).collection("system_user_permissions").doc(_.User_ID));if(Z&&Z.size++,!ge?.exists)throw new Error("PERMISSION_DENIED");if(T=ge.data(),i?.permissions){if(i.permissions.Role||=v.Role||_.Role,i.permissions.Enabled??=v.Enabled??_.Enabled,xe(i.permissions.Role))throw new Error("VALIDATION_ERROR: Role field is required");if(xe(i.permissions.Enabled))throw new Error("VALIDATION_ERROR: Enabled field is required")}}if(!s?.providedTransaction){const Wt=O.filter(we=>"unique"in we&&we.unique).map(async we=>{if(!r||!we.access||we.access.includes(E.Role)){if(v[we.name]===void 0||xe(v[we.name]))return;const jt=Ae(we,g),cn={..._,...v};if(!(r&&jt?.custom?.serverAccess?.read!==void 0?await oe(jt.custom.serverAccess.read,[E?.Role,cn]):!0))throw new Error("PERMISSION_DENIED");const Jn=v[we.name].toString().toLowerCase().replace(/\s/g,"---").replaceAll("/","|||");if(Js(Jn)){if(Z&&Z.size++,Z&&Z.size>500)throw new Error("VALIDATION_ERROR: The number of operations in the Firestore transaction has exceeded the limit of 500. This is likely due to a large number of unique field checks.");const lr=await S.get(x.collection("tenants").doc(a).collection("system_unique").doc(p.collection).collection(`Unique-${p.collection}-${we.name}`).doc(Jn));if(lr.exists&&lr.data().id!==e)throw new Error(`VALIDATION_ERROR: ${we.name} "${v[we.name]}" already exists`)}else throw new Error(`VALIDATION_ERROR: ${we.name} "${v[we.name]}" is invalid`)}});await Promise.all(Wt)}if(r&&E?.Role){const ge=E.Role,Wt={..._,...v};if(!(g.custom?.serverAccess?.update!==void 0?await oe(g.custom.serverAccess.update,[ge,Wt,_]):!0))throw new Error("PERMISSION_DENIED");for(const jt of f.fields){const cn=Ae(jt,g);if(Object.prototype.hasOwnProperty.call(v,jt.name)&&cn?.custom?.serverAccess?.update!==void 0&&!await oe(cn.custom.serverAccess.update,[ge,Wt,_]))throw new Error("PERMISSION_DENIED")}}dr(v,_,e,f,c,r,E,i?.operation?i.operation:m?"update":void 0,i?.permissions,T),i?.permissions&&r&&E&&await Mo(S,i.permissions,r,E,c,T,Z),dr(v,_,e,f,c,r,E,i?.operation?i.operation:m?"update":void 0,i?.permissions,T),L&&(z||$(_)||k)&&await Qc(S,e,_.User_ID)};(z||m||k)&&await x.runTransaction(async S=>{await R(S,!0)},{maxAttempts:10});const A=async(S,L)=>{if(!_)throw new Error("NOT_FOUND");try{const Z={size:1},K={..._,...v};await R(S,!1,Z);let te;!s?.noTwoWay&&!s?.providedTransaction&&(te=await or("Update",a,e,K,v,f,c,S,Z,r,E,_));const qe=Ls(c);Ys("update",S,n,e,v,c,f,s,qe,B.FieldValue.arrayUnion,B.FieldValue.arrayRemove,B.FieldValue.delete,fe=>x.collection("tenants").doc(a).collection("system_fields").doc(p.collection).collection(`${p.collection}-${fe.name}`).doc(e),(fe,Re)=>x.collection("tenants").doc(a).collection("system_unique").doc(p.collection).collection(`Unique-${p.collection}-${fe.name}`).doc(Re),fe=>x.collection("tenants").doc(a).collection("system_fields").doc(p.collection).collection(`${p.collection}-${fe}`).doc(e),(fe,Re)=>Se(x,fe,a).doc(Re),(fe,Re,ge)=>x.collection("tenants").doc(a).collection("system_fields").doc(fe.collection).collection(`${fe.collection}-${Re}`).doc(ge),(fe,Re,ge)=>x.collection("tenants").doc(a).collection("system_fields").doc(fe.collection).collection(`${fe.collection}-${Re.replaceAll(" ","-")}`).doc(ge),_,te,Z),S.update(C.doc(e),v)}catch(Z){if(s?.providedTransaction)throw Z;{const K=["update",v,e,o,Z,void 0,void 0,void 0,he(_)],te=await ae("postWriteError",l,g,K);if(y&&(await new Promise(qe=>{setTimeout(qe,250)}),await pt("update",te?.resolved?"success":"failed",v,a,n,e,f,te?.resolved?void 0:Z,_)),!te?.resolved)throw z&&await Ut(_),$(_)&&await Jt(_.User_ID,L,T,"USER_ERROR"),k&&await x.collection("tenants").doc(a).collection(p.collection).doc(e).update({User_ID:B.FieldValue.delete()}),Z}}(z||$(_)||k)&&await ni(oi,[e,_.User_ID]).catch(()=>{throw new Error("USER_ERROR")})};try{let S;if(z||$(_)||k){if($(_)){S=await b.getUser(_.User_ID);const K=S.customClaims;if(!(K&&K.role&&K.collection&&K.doc))throw new Error("USER_ERROR")}const L={..._,...v};nt(L);const Z=await Po(i?.operation||"update",a,e,l,p.collection,L,_,S,i?.permissions,T,i?.password);z&&(v.User_ID=Z),k&&(v.User_ID=B.FieldValue.delete())}s?.providedTransaction?await A(s.providedTransaction,S):await x.runTransaction(async L=>{await A(L,S)},{maxAttempts:10})}catch(S){throw(z||$(_)||k)&&await ni(oi,[e,_.User_ID]).catch(()=>{throw new Error("USER_ERROR")}),S}if(!s?.providedTransaction){const S=["update",v,e,o,void 0,he(_)],L=[...S];await ae("postWrite",l,g,S),await ae("postOperation",l,g,L)}const q={..._,...v};return nt(q),{id:e,...q}},Kc=async(n,e,t)=>{const s=t?.userId;let r=t?.context;const i=ze(),o=vt();let a=await je();if(n.length===0)throw new Error("EMPTY_PATH");const l=n.at(-1),c=Object.keys(a.collections).includes(l),u=o.disabledCollections?.includes(l);if(!c||u)throw new Error("COLLECTION_NOT_FOUND");const h=a.collections[l],{labels:d,auth:f,enableWriteLog:p,softDelete:O}=h,y=Ze(d.collection,a),g=await oe(o.appName);if(O&&!f&&!t?.force)return await Lo(n,e,{[O.archivedField]:!0,[O.timestampField]:B.FieldValue.serverTimestamp()},{userId:s});const N=B.getFirestore();let b;s&&await rr(n,h);const x=Se(N,n,i);r=r||{},r.collection=d.collection;const E=await Qe(n,e,{userId:s});let C=Vs("delete",n,E,a,g,"Online",s||"System",B.Timestamp.now(),B.FieldValue.serverTimestamp());const _=bn(C);Le(C),p&&await pt("delete","started",C,i,n,e,h),await ae("preOperation",o,y,["delete",C,e,r]),await ae("preWrite",o,y,["delete",C,e,r]),Le(C);const m=async w=>{const[I,T,R,A]=await Promise.all([w.get(N.collection("system_deployment").doc("maintenance_mode")),Qe(n,e,{userId:s,providedTransaction:w}),s?w.get(N.collection("tenants").doc(i).collection("system_user_permissions").doc(s)):Promise.resolve({}),je()]);if(!I.exists)throw new Error("MAINTENANCE_MODE");if(I.data().active)throw new Error("MAINTENANCE_MODE");if(!T)throw new Error("NOT_FOUND");if(C={...T,..._},a=A,s){if(!R?.exists)throw new Error("PERMISSION_DENIED");if(b=R.data(),!b.Role)throw new Error("USER_ERROR");if(!b.Enabled)throw new Error("PERMISSION_DENIED");Jo(C,e,h,a,s,b)}if(s&&b?.Role){const P=b.Role;if(!(y.custom?.serverAccess?.delete!==void 0?await oe(y.custom.serverAccess.delete,[P,C]):!0))throw new Error("PERMISSION_DENIED")}};h.auth&&(await N.runTransaction(async w=>{await m(w)},{maxAttempts:10}),C.User_ID&&await Ut(C));try{await N.runTransaction(async w=>{await m(w);const I=Ls(a);Ys("delete",w,n,e,C,a,h,t,I,B.FieldValue.arrayUnion,B.FieldValue.arrayRemove,B.FieldValue.delete,T=>N.collection("tenants").doc(i).collection("system_fields").doc(d.collection).collection(`${d.collection}-${T.name}`).doc(e),(T,R)=>N.collection("tenants").doc(i).collection("system_unique").doc(d.collection).collection(`Unique-${d.collection}-${T.name}`).doc(R),T=>N.collection("tenants").doc(i).collection("system_fields").doc(d.collection).collection(`${d.collection}-${T}`).doc(e),(T,R)=>Se(N,T,i).doc(R),(T,R,A)=>N.collection("tenants").doc(i).collection("system_fields").doc(T.collection).collection(`${T.collection}-${R}`).doc(A),(T,R,A)=>N.collection("tenants").doc(i).collection("system_fields").doc(T.collection).collection(`${T.collection}-${R.replaceAll(" ","-")}`).doc(A)),w.delete(x.doc(e))},{maxAttempts:10})}catch(w){const T=await ae("postWriteError",o,y,["delete",C,e,r,w]);if(p&&(await new Promise(R=>{setTimeout(R,250)}),await pt("delete",T?.resolved?"success":"failed",C,i,n,e,h,T?.resolved?void 0:w)),!T?.resolved)throw h.auth&&C.User_ID&&await N.collection("tenants").doc(i).collection(d.collection).doc(e).update({User_ID:B.FieldValue.delete()}),w}const $=["delete",C,e,r],v=[...$];return await ae("postWrite",o,y,$),await ae("postOperation",o,y,v),{id:e,...C}},Xc=async(n,e)=>{const t=B.getFirestore(),s=Qs(),r=process.env.ADMIN_SMS;if(s==="development")if(r)n=r;else throw new Error("Admin phone not set");const i={to:n,body:e};await t.collection("system_messages").add(i)},eu=n=>n!==null&&typeof n=="object",tu=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{r instanceof B.Timestamp?t[s]={_seconds:r.seconds,_nanoseconds:r.nanoseconds}:eu(r)&&e(r)})};e(n)},nu=async n=>await yt.getAuth().getUser(n),su=n=>{const e=Ks();return V.fromJSDate(n).setZone(e)},Vo=n=>{const e=Ks();return V.fromJSDate(n.toDate()).setZone(e)},ru=(n,e)=>{const s=V.fromJSDate(n,{zone:e}).offset,i=V.fromJSDate(n).offset,o=s-i;return V.fromJSDate(n).plus({minutes:o}).toJSDate()},iu=(n,e)=>{const s=V.fromJSDate(n,{zone:e}).offset,i=V.fromJSDate(n).offset,o=s-i;return V.fromJSDate(n).minus({minutes:o}).toJSDate()},ou=n=>"seconds"in n&&"nanoseconds"in n?Vo(new B.Timestamp(n.seconds,n.nanoseconds)).toFormat("MMMM d, yyyy '@' h:mm a"):"";exports.addRecord=Jc;exports.addUser=sr;exports.convertDateToTimezone=su;exports.convertTimestampToTimezone=Vo;exports.deleteRecord=Kc;exports.deleteUser=Ut;exports.deserializeDeleteSentinels=Yn;exports.deserializeTimestamps=ir;exports.deserializeTimestampsWithoutUnderscores=qc;exports.displayDate=ou;exports.fetchCurrentSchema=je;exports.fetchLastSchema=Zc;exports.getCachedConfigValue=na;exports.getCollectionRefs=No;exports.getCustomizationFile=Ze;exports.getCustomizationFiles=So;exports.getDocumentRefs=Xs;exports.getFirestorePathRef=Se;exports.getGlobalConfigModule=vt;exports.getInputSchema=Mc;exports.getMaintenanceInfo=Wc;exports.getMode=Qs;exports.getOne=Qe;exports.getSome=tr;exports.getTenant=ze;exports.getTimezone=Ks;exports.getUser=nu;exports.getVersionInfo=Uc;exports.getZodSchema=Oi;exports.initializeFirebase=zc;exports.initializeStoker=Lc;exports.isDeleteSentinel=xe;exports.keepTimezone=ru;exports.removeTimezone=iu;exports.runChildProcess=jc;exports.sendMail=nr;exports.sendMessage=Xc;exports.serializeTimestamps=tu;exports.setTenant=Vc;exports.tryPromise=oe;exports.updateRecord=Lo;exports.updateUser=Po;exports.validateRelations=or;exports.validateSoftDelete=ar;exports.writeLog=pt;
package/dist/bundle.js CHANGED
@@ -11179,7 +11179,7 @@ ${i}`);
11179
11179
  const m = async (w) => {
11180
11180
  const [I, S, R, A] = await Promise.all([
11181
11181
  w.get(N.collection("system_deployment").doc("maintenance_mode")),
11182
- at([d.collection], e, { userId: s, providedTransaction: w }),
11182
+ at(n, e, { userId: s, providedTransaction: w }),
11183
11183
  s ? w.get(N.collection("tenants").doc(i).collection("system_user_permissions").doc(s)) : Promise.resolve({}),
11184
11184
  Ye()
11185
11185
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/node-client",
3
- "version": "0.5.44",
3
+ "version": "0.5.45",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "files": [