@stoker-platform/node-client 0.4.1 → 0.5.1
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 +1 -1
- package/dist/bundle.js +2 -2
- package/package.json +3 -3
package/dist/bundle.cjs
CHANGED
|
@@ -11,4 +11,4 @@ ${i}`)}})()]),r.length>0)throw new Error(r.join(", "))},tr=async(n,e,t,s,r,i,o,a
|
|
|
11
11
|
<a href="${m}">${m}</a>`)}catch{throw await u(r,c),new Error(c)}}}return h.uid},sr=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 Ge(i,r).catch(()=>{throw new Error("PERMISSION_DENIED")}),a=o.Collection_Path;if(a.push(o.id),a.push(t.collection),!ze(n,a))throw new Error("PERMISSION_DENIED")}else if(n.length>1)throw new Error("PERMISSION_DENIED")},Vn=n=>n!==null&&typeof n=="object"&&!Array.isArray(n),Zc=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{Vn(r)&&Object.keys(r).length===2&&typeof r.seconds=="number"&&typeof r.nanoseconds=="number"?t[s]=new H.Timestamp(r.seconds,r.nanoseconds):Vn(r)&&e(r)})};e(n)},rr=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{Vn(r)&&Object.keys(r).length===2&&typeof r._seconds=="number"&&typeof r._nanoseconds=="number"?t[s]=new H.Timestamp(r._seconds,r._nanoseconds):Vn(r)&&e(r)})};e(n)},Gn=n=>{if(typeof n=="object")for(const e in n)Object.prototype.hasOwnProperty.call(n,e)&&(n[e]==="_DELETE_FIELD"?n[e]=H.FieldValue.delete():Gn(n[e]))},zc=(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{}},ri=async(n,e,t,s,r,i,o)=>{if(!X(t)||!t.enforceHierarchy)return;const{fields:a}=e,l=H.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 f=Te(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 d=await r.get(f.doc(u));if(!d.exists)throw new Error(`VALIDATION_ERROR: Record ${u} not found in collection ${t.collection}`);const m=d.data(),O=W(a,t.enforceHierarchy.field),y=t.enforceHierarchy;if(!m[y.recordLinkField]||!s[O.name]||!Object.keys(s[O.name]).every(w=>Object.keys(m[y.recordLinkField]).includes(w)))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`]},ps=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`]=t)},qc=(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}},ir=async(n,e,t,s,r,i,o,a,l,c,u,h)=>{const{fields:f}=i,d=H.getFirestore(),m=new Map,O=new Map,y=new Map;for(const w of f)X(w)&&["OneToOne","OneToMany"].includes(w.type)&&w.enforceHierarchy&&s[w.name]&&(n==="Create"||n==="Update"&&!ze(h?.[w.name],s[w.name]))&&await ri(e,i,w,s,a,l);for(const w of f)if(X(w)&&w.twoWay){const b=o.collections[w.collection],N=W(b.fields,w.twoWay),p=ut(b,[N]);if(s[w.name]){const T=Object.entries(s[w.name]);for(const C of T){const[v,Z]=C;if(n==="Create"||!h?.[w.name]?.[v]){let x;const g=y.get(w.collection)?.[v];if(g)x=g;else{if(l.size++,l&&l.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 two way updates, unique field checks, entity restrictions (in permissions when dealing with user collections) or relation hierarchy checks.");const _=Te(d,Z.Collection_Path,e),A=await a.get(_.doc(v));if(!A.exists){yn(w,r,v);continue}const E=A.data();O.set(w.collection,{...O.get(w.collection)||{},[v]:E}),x=pe({...E,...kn(s)})}const k={...x[N.name],[t]:{Collection_Path:s.Collection_Path,...zc(i,s,N)}};x[N.name]=k,x[`${N.name}_Array`]||=[],x[`${N.name}_Array`].push(t),p.size===1&&(x[`${N.name}_Single`]=k),y.set(w.collection,{...y.get(w.collection)||{},[v]:x})}}}if(n==="Update"){const T=Object.entries(h?.[w.name]||{});for(const C of T){const[v,Z]=C;if(!s[w.name]?.[v]){let x;const g=y.get(w.collection)?.[v];if(g)x=g;else{if(l.size++,l&&l.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 two way updates, unique field checks, entity restrictions (in permissions when dealing with user collections) or relation hierarchy checks.");const k=Te(d,Z.Collection_Path,e),_=await a.get(k.doc(v));if(!_.exists){m.set(w.name,[...m.get(w.name)||[],v]);continue}const A=_.data();O.set(w.collection,{...O.get(w.collection)||{},[v]:A}),x=pe({...A,...kn(s)})}x[N.name][t]&&delete x[N.name][t],Array.isArray(x[`${N.name}_Array`])&&(x[`${N.name}_Array`]=x[`${N.name}_Array`].filter(k=>k!==t)),p.size===1&&delete x[`${N.name}_Single`],y.set(w.collection,{...y.get(w.collection)||{},[v]:x})}}}}for(const[w,b]of y.entries()){const N=o.collections[w],p=Je(w,o);for(const[T,C]of Object.entries(b)){const{addedFields:v,removedFields:Z}=qc(n,T,w,i,s,h);if(c&&u){for(const x of v){const g=W(N.fields,x.twoWay);if(!cr(N,g,u)){yn(x,r,T);continue}}for(const x of Z){const g=W(N.fields,x.twoWay),k=ut(N,[g]);if(!cr(N,g,u)){ps(x,r,h?.[x.name]?.[T],T,k.size===1);continue}}if(!it("Update",N,o,c,u,O.get(w)?.[T])){for(const x of v)yn(x,r,T);for(const x of Z){const g=W(N.fields,x.twoWay),k=ut(N,[g]);ps(x,r,h?.[x.name]?.[T],T,k.size===1)}}if(!it("Update",N,o,c,u,C)){for(const x of v)yn(x,r,T);for(const x of Z){const g=W(N.fields,x.twoWay),k=ut(N,[g]);ps(x,r,h?.[x.name]?.[T],T,k.size===1)}}}try{await sn("update",C,N,p,["update",C,{},void 0,C],o)}catch(x){throw new Error(`VALIDATION_ERROR: Two way relation update would invalidate record ${T} in ${w}: ${x.message}`)}for(const x of v){const g=W(N.fields,x.twoWay);["OneToOne","OneToMany"].includes(g.type)&&X(g)&&g.enforceHierarchy&&await ri(e,N,g,C,a,l,!0)}}}return m},Mo=(n,e,t)=>{n==="create"&&ht.forEach(s=>{if(!ze(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)&&!ze(e[s],t[s]))throw new Error(`Updating system fields in hooks is not allowed: ${s}`)}))},or=(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]=H.FieldValue.serverTimestamp();else{if(!s)throw new Error("Original record is required for update");if(!s[i])t[o]=H.FieldValue.serverTimestamp();else if(t[o]&&t[o]?.valueOf()!==s[o]?.valueOf())throw new Error("Soft delete timestamp cannot be changed")}},ys=async(n,e,t,s,r)=>{if(!Se("Read",r.collections?.[e.labels.collection]))return!1;try{await Ge([e.labels.collection],t,{user:s,providedTransaction:n})}catch{return!1}return!0},Bc=10,Hc=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))},Po=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 f=i?.collections?.[a],d=[];if(l.individualEntities){const m=l.individualEntities,O=f?.individualEntities||[],y=i?m.filter(w=>!O.includes(w)):m;for(const w 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).");d.push(async()=>{if(!await ys(n,u,w,t,s))throw new Error("PERMISSION_DENIED")})}}if(l.parentEntities){const m=c.entityRestrictions?.restrictions?.find(p=>p.type==="Parent"&&p.roles.some(T=>T.role===e.Role));if(!m)throw new Error("PERMISSION_DENIED");const O=W(u.fields,m.collectionField),y=r.collections[O.collection],w=l.parentEntities,b=f?.parentEntities||[],N=i?w.filter(p=>!b.includes(p)):w;for(const p of N){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).");d.push(async()=>{if(!await ys(n,y,p,t,s))throw new Error("PERMISSION_DENIED")})}}if(l.parentPropertyEntities){const m=c.entityRestrictions?.restrictions?.find(N=>N.type==="Parent_Property"&&N.roles.some(p=>p.role===e.Role));if(!m)throw new Error("PERMISSION_DENIED");const O=W(u.fields,m.collectionField),y=r.collections[O.collection],w=l.parentPropertyEntities,b=f?.parentPropertyEntities||{};for(const[N,p]of Object.entries(w)){const T=b[N]||[],C=i?p.filter(v=>!T.includes(v)):p;for(const v 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).");d.push(async()=>{if(!await ys(n,y,v,t,s))throw new Error("PERMISSION_DENIED")})}}}await Hc(d,Bc)}}},Gc=async(n,e,t,s,r,i,o)=>{const a=Ye(),l=Vt();let c=await je();if(n.length===0)throw new Error("EMPTY_PATH");const u=n.at(-1),h=Object.keys(c.collections).includes(u),f=l.disabledCollections?.includes(u);if(!h||f)throw new Error("COLLECTION_NOT_FOUND");const d=c.collections[u],{labels:m,fields:O,enableWriteLog:y,softDelete:w}=d,b=Je(m.collection,c),N=await ie(l.appName),p=H.getFirestore(),T=yt.getAuth(),v=(s?await T.getUser(s):void 0)?.customClaims?.role;let Z;s&&await sr(n,d);const x=Te(p,n,a),g=o||x.doc().id;i=i||{},i.collection=m.collection,e.id=g,rr(e),Gn(e);const k=Us("create",n,e,c,N,"Online",s||"System",H.Timestamp.now(),H.FieldValue.serverTimestamp()),_=pe(k);w&&(k[w.archivedField]=!1),Le(e),y&&await pt("create","started",k,a,n,g,d),await le("preOperation",l,b,["create",k,g,i]),await le("preWrite",l,b,["create",k,g,i]),bn(d,k,c),Sn(d,k),await ca(k,d,b,v),Le(k);try{if(d.auth&&t&&!t.password)throw new Error("Password is required");await $o("create",a,g,k,d,c),await sn("create",k,d,b,["create",k,i],c)}catch(P){throw new Error(`VALIDATION_ERROR: ${P.message}`)}Le(k),e.id=g,w&&(k[w.archivedField]=!1),bn(d,k,c),Sn(d,k);try{Mo("create",k,_),or("create",d,k),await sn("create",k,d,b,["create",k,i],c)}catch(P){throw new Error(`VALIDATION_ERROR: ${P.message}`)}if(s){const P=v;if(!P)throw new Error("USER_ERROR");if(!(b.custom?.serverAccess?.create!==void 0?await ie(b.custom.serverAccess.create,[P,k]):!0))throw new Error("PERMISSION_DENIED");for(const K of d.fields){if(!(K.name in k))continue;const S=Ie(K,b);if(S?.custom?.serverAccess?.create!==void 0&&!await ie(S.custom.serverAccess.create,[P,k]))throw new Error("PERMISSION_DENIED")}}t&&(t.permissions||={},t.permissions.Role||=k.Role,t.permissions.Enabled||=k.Enabled);const I=async(P,j)=>{const[K,S,q,B]=await Promise.all([P.get(p.collection("system_deployment").doc("latest_deploy")),P.get(p.collection("system_deployment").doc("maintenance_mode")),s?P.get(p.collection("tenants").doc(a).collection("system_user_permissions").doc(s)):Promise.resolve(Promise.resolve({})),je()]);if(j&&(j.size+=3),!K.exists)throw new Error("VERSION_ERROR");const oe=K.data();if(oe.force&&k.Last_Write_At.valueOf()<oe.time.valueOf())throw new Error("VERSION_ERROR");if(!S.exists)throw new Error("MAINTENANCE_MODE");if(S.data().active)throw new Error("MAINTENANCE_MODE");if(c=B,s){if(!q?.exists)throw new Error("PERMISSION_DENIED");if(Z=q.data(),!Z.Role)throw new Error("USER_ERROR");if(!Z.Enabled)throw new Error("PERMISSION_DENIED")}const me=O.filter(ae=>"unique"in ae&&ae.unique).map(async ae=>{if(!s||!ae.access||ae.access.includes(Z.Role)){if(!e[ae.name])return;const Pe=Ie(ae,b);if(!(s&&Pe?.custom?.serverAccess?.read!==void 0?await ie(Pe.custom.serverAccess.read,[Z?.Role,k]):!0))throw new Error("PERMISSION_DENIED");const Yn=e[ae.name].toString().toLowerCase().replace(/\s/g,"---").replaceAll("/","|||");if(Qs(Yn)){if(j&&j.size++,j&&j.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 P.get(p.collection("tenants").doc(a).collection("system_unique").doc(m.collection).collection(`Unique-${m.collection}-${ae.name}`).doc(Yn)))?.exists)throw new Error(`VALIDATION_ERROR: ${ae.name} "${k[ae.name]}" already exists`)}else throw new Error(`VALIDATION_ERROR: ${ae.name} "${k[ae.name]}" is invalid`)}});await Promise.all(me),ur(k,g,d,c,s,Z,t?.permissions),t?.permissions&&s&&Z&&await Po(P,t.permissions,s,Z,c),ur(k,g,d,c,s,Z,t?.permissions)};if(d.auth&&t){await p.runTransaction(async j=>{await I(j)},{maxAttempts:10});const P=await nr(a,g,l,m.collection,k,t.permissions,t.password);k.User_ID=P}try{const P={size:1};await p.runTransaction(async j=>{await I(j,P),r?.noTwoWay||await ir("Create",a,g,k,k,d,c,j,P,s,Z);const K=Vs(c);Js("create",j,n,g,k,c,d,r,K,H.FieldValue.arrayUnion,H.FieldValue.arrayRemove,H.FieldValue.delete,S=>p.collection("tenants").doc(a).collection("system_fields").doc(m.collection).collection(`${m.collection}-${S.name}`).doc(g),(S,q)=>p.collection("tenants").doc(a).collection("system_unique").doc(m.collection).collection(`Unique-${m.collection}-${S.name}`).doc(q),S=>p.collection("tenants").doc(a).collection("system_fields").doc(m.collection).collection(`${m.collection}-${S}`).doc(g),(S,q)=>Te(p,S,a).doc(q),(S,q,B)=>p.collection("tenants").doc(a).collection("system_fields").doc(S.collection).collection(`${S.collection}-${q}`).doc(B),(S,q,B)=>p.collection("tenants").doc(a).collection("system_fields").doc(S.collection).collection(`${S.collection}-${q.replaceAll(" ","-")}`).doc(B),void 0,void 0,P),j.set(x.doc(g),k)},{maxAttempts:10})}catch(P){const K=await le("postWriteError",l,b,["create",k,g,i,P]);if(y&&(await new Promise(S=>{setTimeout(S,250)}),await pt("create",K?.resolved?"success":"failed",k,a,n,g,d,K?.resolved?void 0:P)),!K?.resolved)throw d.auth&&t&&await Ut(k),P}const R=["create",k,g,i],M=[...R];return await le("postWrite",l,b,R),await le("postOperation",l,b,M),{id:g,...k}},Qt=async(n,e,t,s)=>{const r=Ye(),i=yt.getAuth(),o=H.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}`)},Lo=async(n,e,t,s,r,i,o,a,l,c,u)=>{const h=yt.getAuth(),f=H.getFirestore(),d=a?.customClaims||{},m="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 nr(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 Qt(o.User_ID,a,c,m),new Error(m)}if(i.Role&&i.Role!==o.Role)try{await h.setCustomUserClaims(o.User_ID,{...d,role:i.Role}),await h.revokeRefreshTokens(o.User_ID)}catch{throw await Qt(o.User_ID,a,c,m),new Error(m)}try{await f.collection("tenants").doc(e).collection("system_user_permissions").doc(o.User_ID).set({...l||c,Collection:d.collection,Doc_ID:d.doc,Role:i.Role,Enabled:i.Enabled??o.Enabled??!1})}catch{throw await Qt(o.User_ID,a,c,m),new Error(m)}if(o.Email!==i.Email){const w=s.auth.enableMultiFactorAuth;if(w===!0||typeof w=="object"&&w.includes(i.Role)){let b=await h.generateEmailVerificationLink(i.Email).catch(()=>{throw new Error("Error generating email verification link")});if(b.includes("apiKey=&")){const N=JSON.parse(process.env.STOKER_FB_WEB_APP_CONFIG);b=b.replace("apiKey=&",`apiKey=${N.apiKey}&`)}if(b){const N=`https://${h.app.options.projectId}.firebaseapp.com/__/auth/action${b}`,p=await ie(s.appName),T=s?.mail?.emailVerification&&s.mail.emailVerification(N,p);try{await tr(i.Email,T?.subject||"Please verify your email address",void 0,T?.html||`Please verify your email address by clicking the link:
|
|
12
12
|
</br>
|
|
13
13
|
</br>
|
|
14
|
-
<a href="${N}">${N}</a>`)}catch{throw await Qt(o.User_ID,a,c,m),new Error(m)}}}}}else if(n==="delete")try{await Ut(o)}catch(y){throw new Error(y.message)}if(O)return O},Yc=async(n,e,t)=>{const s=Ye(),r=H.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})},ii=async(n,e)=>{const t=Ye(),s=H.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()},Vo=async(n,e,t,s,r,i,o)=>{const a=Ye(),l=Vt();let c=await je(!0);if(n.length===0)throw new Error("EMPTY_PATH");const u=n.at(-1),h=Object.keys(c.collections).includes(u),f=l.disabledCollections?.includes(u);if(!h||f)throw new Error("COLLECTION_NOT_FOUND");const d=c.collections[u],{labels:m,fields:O,enableWriteLog:y}=d,w=Je(m.collection,c),b=await ie(l.appName),N=yt.getAuth(),p=H.getFirestore();let T;r&&await sr(n,d);const C=Te(p,n,a);o=o||{},o.collection=m.collection;let v=await Ge(n,e,{user: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,q])=>[S,{...q,fields:q.fields.filter(B=>B.type!=="Computed")}]))},s&&!s.operation)throw new Error("VALIDATION_ERROR: User operation is required");if(s&&!d.auth)throw new Error("VALIDATION_ERROR: User operations are only permitted for auth collections");if(s?.operation==="delete"&&s.permissions)throw new Error("VALIDATION_ERROR: Permissions are not allowed for delete operations");const Z=d.auth&&s?.operation==="create",x=d.auth&&s?.operation==="delete",g=d.auth&&!Z&&!x&&(s?.operation==="update"||t.Role||t.Enabled!==void 0||t.Name||t.Email||t.Photo_URL),k=S=>S.User_ID&&(d.auth&&!Z&&!x&&s?.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,rr(t),Gn(t);const _=Us("update",n,t,c,b,"Online",r||"System",H.Timestamp.now(),H.FieldValue.serverTimestamp()),A=pe(_);for(const S of O)!X(S)&&Ne(_[S.name])&&S.nullable&&(_[S.name]=null);Le(_),Le(v),y&&await pt("update","started",_,a,n,e,d,void 0,v);const E=["update",_,e,o,void 0,pe(v)];await le("preOperation",l,w,E);const I=["update",_,e,o,void 0,pe(v)];await le("preWrite",l,w,I),bn(d,_,c),Sn(d,_),Le(_);try{if(Z&&!s.password)throw new Error("Password is required");const S={...v,..._};await $o("update",a,e,S,d,c),nt(S),await sn("update",S,d,w,["update",_,o,void 0,pe(v)],c)}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}Le(_),delete t.id,bn(d,_,c),Sn(d,_);for(const S of O)!X(S)&&Ne(_[S.name])&&S.nullable&&(_[S.name]=null);try{const S={...v,..._};nt(S),or("update",d,_,v),Mo("update",_,A),await sn("update",S,d,w,["update",_,o,void 0,v],c)}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}let R;s&&(s.permissions||={});const M=async(S,q,B)=>{const[oe,Qe,Wt,me,ae]=await Promise.all([S.get(p.collection("system_deployment").doc("latest_deploy")),S.get(p.collection("system_deployment").doc("maintenance_mode")),Ge(n,e,{user:r,providedTransaction:S,noComputedFields:!0}),r?S.get(p.collection("tenants").doc(a).collection("system_user_permissions").doc(r)):Promise.resolve(Promise.resolve({})),je()]);if(B&&(B.size+=3),!oe.exists)throw new Error("VERSION_ERROR");const Pe=oe.data();if(Pe.force&&_.Last_Write_At.valueOf()<Pe.time.valueOf())throw new Error("VERSION_ERROR");if(!Qe.exists)throw new Error("MAINTENANCE_MODE");if(Qe.data().active)throw new Error("MAINTENANCE_MODE");if(!Wt)throw new Error("NOT_FOUND");if(v=Wt,c=ae,r){if(!me?.exists)throw new Error("PERMISSION_DENIED");if(T=me.data(),!T.Role)throw new Error("USER_ERROR");if(!T.Enabled)throw new Error("PERMISSION_DENIED")}if(B&&(B.size+=Ks(a,n,e,c,T).length),Z&&v.User_ID||x&&!v.User_ID)throw new Error("USER_ERROR");if(k(v)){const de=await S.get(p.collection("tenants").doc(a).collection("system_user_permissions").doc(v.User_ID));if(B&&B.size++,!de?.exists)throw new Error("PERMISSION_DENIED");if(R=de.data(),s?.permissions){if(s.permissions.Role||=_.Role||v.Role,s.permissions.Enabled??=_.Enabled??v.Enabled,Ne(s.permissions.Role))throw new Error("VALIDATION_ERROR: Role field is required");if(Ne(s.permissions.Enabled))throw new Error("VALIDATION_ERROR: Enabled field is required")}}const ar=O.filter(de=>"unique"in de&&de.unique).map(async de=>{if(!r||!de.access||de.access.includes(T.Role)){if(_[de.name]===void 0||Ne(_[de.name]))return;const jt=Ie(de,w),lr={...v,..._};if(!(r&&jt?.custom?.serverAccess?.read!==void 0?await ie(jt.custom.serverAccess.read,[T?.Role,lr]):!0))throw new Error("PERMISSION_DENIED");const Zt=_[de.name].toString().toLowerCase().replace(/\s/g,"---").replaceAll("/","|||");if(Qs(Zt)){if(B&&B.size++,B&&B.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 Qn=await S.get(p.collection("tenants").doc(a).collection("system_unique").doc(m.collection).collection(`Unique-${m.collection}-${de.name}`).doc(Zt));if(Qn.exists&&Qn.data().id!==e)throw new Error(`VALIDATION_ERROR: ${de.name} "${_[de.name]}" already exists`)}else throw new Error(`VALIDATION_ERROR: ${de.name} "${_[de.name]}" is invalid`)}});if(await Promise.all(ar),r&&T?.Role){const de=T.Role,jt={...v,..._};if(!(w.custom?.serverAccess?.update!==void 0?await ie(w.custom.serverAccess.update,[de,jt,v]):!0))throw new Error("PERMISSION_DENIED");for(const Jn of d.fields){const Zt=Ie(Jn,w);if(Object.prototype.hasOwnProperty.call(_,Jn.name)&&Zt?.custom?.serverAccess?.update!==void 0&&!await ie(Zt.custom.serverAccess.update,[de,jt,v]))throw new Error("PERMISSION_DENIED")}}dr(_,v,e,d,c,r,T,s?.operation?s.operation:g?"update":void 0,s?.permissions,R),s?.permissions&&r&&T&&await Po(S,s.permissions,r,T,c,R,B),dr(_,v,e,d,c,r,T,s?.operation?s.operation:g?"update":void 0,s?.permissions,R),q&&(Z||k(v)||x)&&await Yc(S,e,v.User_ID)};(Z||g||x)&&await p.runTransaction(async S=>{await M(S,!0)},{maxAttempts:10});try{let S;if(Z||k(v)||x){if(k(v)){S=await N.getUser(v.User_ID);const oe=S.customClaims;if(!(oe&&oe.role&&oe.collection&&oe.doc))throw new Error("USER_ERROR")}const q={...v,..._};nt(q);const B=await Lo(s?.operation||"update",a,e,l,m.collection,q,v,S,s?.permissions,R,s?.password);Z&&(_.User_ID=B),x&&(_.User_ID=H.FieldValue.delete())}try{const q={size:1};await p.runTransaction(async B=>{const oe={...v,..._};await M(B,!1,q);let Qe;i?.noTwoWay||(Qe=await ir("Update",a,e,oe,_,d,c,B,q,r,T,v));const Wt=Vs(c);Js("update",B,n,e,_,c,d,i,Wt,H.FieldValue.arrayUnion,H.FieldValue.arrayRemove,H.FieldValue.delete,me=>p.collection("tenants").doc(a).collection("system_fields").doc(m.collection).collection(`${m.collection}-${me.name}`).doc(e),(me,ae)=>p.collection("tenants").doc(a).collection("system_unique").doc(m.collection).collection(`Unique-${m.collection}-${me.name}`).doc(ae),me=>p.collection("tenants").doc(a).collection("system_fields").doc(m.collection).collection(`${m.collection}-${me}`).doc(e),(me,ae)=>Te(p,me,a).doc(ae),(me,ae,Pe)=>p.collection("tenants").doc(a).collection("system_fields").doc(me.collection).collection(`${me.collection}-${ae}`).doc(Pe),(me,ae,Pe)=>p.collection("tenants").doc(a).collection("system_fields").doc(me.collection).collection(`${me.collection}-${ae.replaceAll(" ","-")}`).doc(Pe),v,Qe,q),B.update(C.doc(e),_)},{maxAttempts:10})}catch(q){const B=["update",_,e,o,q,void 0,void 0,pe(v)],oe=await le("postWriteError",l,w,B);if(y&&(await new Promise(Qe=>{setTimeout(Qe,250)}),await pt("update",oe?.resolved?"success":"failed",_,a,n,e,d,oe?.resolved?void 0:q,v)),!oe?.resolved)throw Z&&await Ut(v),k(v)&&await Qt(v.User_ID,S,R,"USER_ERROR"),x&&await p.collection(m.collection).doc(e).update({User_ID:H.FieldValue.delete()}),q}(Z||k(v)||x)&&await ni(ii,[e,v.User_ID]).catch(()=>{throw new Error("USER_ERROR")})}catch(S){throw(Z||k(v)||x)&&await ni(ii,[e,v.User_ID]).catch(()=>{throw new Error("USER_ERROR")}),S}const $=["update",_,e,o,void 0,pe(v)],P=[...$];await le("postWrite",l,w,$),await le("postOperation",l,w,P);const j={...v,..._};return nt(j),{id:e,...j}},Jc=async(n,e,t,s,r)=>{const i=Ye(),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:f,auth:d,enableWriteLog:m,softDelete:O}=h,y=Je(f.collection,a),w=await ie(o.appName);if(O&&!d&&!s?.force)return await Vo(n,e,{[O.archivedField]:!0,[O.timestampField]:H.FieldValue.serverTimestamp()},void 0,t);const b=H.getFirestore();let N;t&&await sr(n,h);const p=Te(b,n,i);r=r||{},r.collection=f.collection;const T=await Ge(n,e,{user:t});let C=Us("delete",n,T,a,w,"Online",t||"System",H.Timestamp.now(),H.FieldValue.serverTimestamp());const v=kn(C);Le(C),m&&await pt("delete","started",C,i,n,e,h),await le("preOperation",o,y,["delete",C,e,r]),await le("preWrite",o,y,["delete",C,e,r]),Le(C);const g=async E=>{const[I,R,M,$]=await Promise.all([E.get(b.collection("system_deployment").doc("maintenance_mode")),Ge([f.collection],e,{user:t,providedTransaction:E}),t?E.get(b.collection("tenants").doc(i).collection("system_user_permissions").doc(t)):Promise.resolve(Promise.resolve({})),je()]);if(!I.exists)throw new Error("MAINTENANCE_MODE");if(I.data().active)throw new Error("MAINTENANCE_MODE");if(!R)throw new Error("NOT_FOUND");if(C={...R,...v},a=$,t){if(!M?.exists)throw new Error("PERMISSION_DENIED");if(N=M.data(),!N.Role)throw new Error("USER_ERROR");if(!N.Enabled)throw new Error("PERMISSION_DENIED");Xo(C,e,h,a,t,N)}if(t&&N?.Role){const j=N.Role;if(!(y.custom?.serverAccess?.delete!==void 0?await ie(y.custom.serverAccess.delete,[j,C]):!0))throw new Error("PERMISSION_DENIED")}};h.auth&&(await b.runTransaction(async E=>{await g(E)},{maxAttempts:10}),C.User_ID&&await Ut(C));try{await b.runTransaction(async E=>{await g(E);const I=Vs(a);Js("delete",E,n,e,C,a,h,s,I,H.FieldValue.arrayUnion,H.FieldValue.arrayRemove,H.FieldValue.delete,R=>b.collection("tenants").doc(i).collection("system_fields").doc(f.collection).collection(`${f.collection}-${R.name}`).doc(e),(R,M)=>b.collection("tenants").doc(i).collection("system_unique").doc(f.collection).collection(`Unique-${f.collection}-${R.name}`).doc(M),R=>b.collection("tenants").doc(i).collection("system_fields").doc(f.collection).collection(`${f.collection}-${R}`).doc(e),(R,M)=>Te(b,R,i).doc(M),(R,M,$)=>b.collection("tenants").doc(i).collection("system_fields").doc(R.collection).collection(`${R.collection}-${M}`).doc($),(R,M,$)=>b.collection("tenants").doc(i).collection("system_fields").doc(R.collection).collection(`${R.collection}-${M.replaceAll(" ","-")}`).doc($)),E.delete(p.doc(e))},{maxAttempts:10})}catch(E){const R=await le("postWriteError",o,y,["delete",C,e,r,E]);if(m&&(await new Promise(M=>{setTimeout(M,250)}),await pt("delete",R?.resolved?"success":"failed",C,i,n,e,h,R?.resolved?void 0:E)),!R?.resolved)throw h.auth&&C.User_ID&&await b.collection(f.collection).doc(e).update({User_ID:H.FieldValue.delete()}),E}const k=["delete",C,e,r],_=[...k];return await le("postWrite",o,y,k),await le("postOperation",o,y,_),{id:e,...C}},Qc=async(n,e)=>{const t=H.getFirestore(),s=xo(),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)},Kc=n=>n!==null&&typeof n=="object",Xc=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{r instanceof H.Timestamp?t[s]={_seconds:r.seconds,_nanoseconds:r.nanoseconds}:Kc(r)&&e(r)})};e(n)},eu=async n=>await yt.getAuth().getUser(n),tu=n=>{const e=Do();return V.fromJSDate(n).setZone(e)},Uo=n=>{const e=Do();return V.fromJSDate(n.toDate()).setZone(e)},nu=(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()},su=(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()},ru=n=>"seconds"in n&&"nanoseconds"in n?Uo(new H.Timestamp(n.seconds,n.nanoseconds)).toFormat("MMMM d, yyyy '@' h:mm a"):"";exports.addRecord=Gc;exports.addUser=nr;exports.convertDateToTimezone=tu;exports.convertTimestampToTimezone=Uo;exports.deleteRecord=Jc;exports.deleteUser=Ut;exports.deserializeDeleteSentinels=Gn;exports.deserializeTimestamps=rr;exports.deserializeTimestampsWithoutUnderscores=Zc;exports.displayDate=ru;exports.fetchCurrentSchema=je;exports.fetchLastSchema=jc;exports.getCachedConfigValue=ia;exports.getCollectionRefs=Io;exports.getCustomizationFiles=bo;exports.getDocumentRefs=Ks;exports.getFirestorePathRef=Te;exports.getInputSchema=Vc;exports.getOne=Ge;exports.getSome=er;exports.getUser=eu;exports.getZodSchema=Ei;exports.initializeFirebase=Bo;exports.initializeStoker=Wc;exports.isDeleteSentinel=Ne;exports.keepTimezone=nu;exports.removeTimezone=su;exports.runChildProcess=qo;exports.sendMail=tr;exports.sendMessage=Qc;exports.serializeTimestamps=Xc;exports.tryPromise=ie;exports.updateRecord=Vo;exports.updateUser=Lo;exports.validateRelations=ir;exports.validateSoftDelete=or;exports.writeLog=pt;
|
|
14
|
+
<a href="${N}">${N}</a>`)}catch{throw await Qt(o.User_ID,a,c,m),new Error(m)}}}}}else if(n==="delete")try{await Ut(o)}catch(y){throw new Error(y.message)}if(O)return O},Yc=async(n,e,t)=>{const s=Ye(),r=H.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})},ii=async(n,e)=>{const t=Ye(),s=H.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()},Vo=async(n,e,t,s,r,i,o)=>{const a=Ye(),l=Vt();let c=await je(!0);if(n.length===0)throw new Error("EMPTY_PATH");const u=n.at(-1),h=Object.keys(c.collections).includes(u),f=l.disabledCollections?.includes(u);if(!h||f)throw new Error("COLLECTION_NOT_FOUND");const d=c.collections[u],{labels:m,fields:O,enableWriteLog:y}=d,w=Je(m.collection,c),b=await ie(l.appName),N=yt.getAuth(),p=H.getFirestore();let T;r&&await sr(n,d);const C=Te(p,n,a);o=o||{},o.collection=m.collection;let v=await Ge(n,e,{user: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,q])=>[S,{...q,fields:q.fields.filter(B=>B.type!=="Computed")}]))},s&&!s.operation)throw new Error("VALIDATION_ERROR: User operation is required");if(s&&!d.auth)throw new Error("VALIDATION_ERROR: User operations are only permitted for auth collections");if(s?.operation==="delete"&&s.permissions)throw new Error("VALIDATION_ERROR: Permissions are not allowed for delete operations");const Z=d.auth&&s?.operation==="create",x=d.auth&&s?.operation==="delete",g=d.auth&&!Z&&!x&&(s?.operation==="update"||t.Role||t.Enabled!==void 0||t.Name||t.Email||t.Photo_URL),k=S=>S.User_ID&&(d.auth&&!Z&&!x&&s?.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,rr(t),Gn(t);const _=Us("update",n,t,c,b,"Online",r||"System",H.Timestamp.now(),H.FieldValue.serverTimestamp()),A=pe(_);for(const S of O)!X(S)&&Ne(_[S.name])&&S.nullable&&(_[S.name]=null);Le(_),Le(v),y&&await pt("update","started",_,a,n,e,d,void 0,v);const E=["update",_,e,o,void 0,pe(v)];await le("preOperation",l,w,E);const I=["update",_,e,o,void 0,pe(v)];await le("preWrite",l,w,I),bn(d,_,c),Sn(d,_),Le(_);try{if(Z&&!s.password)throw new Error("Password is required");const S={...v,..._};await $o("update",a,e,S,d,c),nt(S),await sn("update",S,d,w,["update",_,o,void 0,pe(v)],c)}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}Le(_),delete t.id,bn(d,_,c),Sn(d,_);for(const S of O)!X(S)&&Ne(_[S.name])&&S.nullable&&(_[S.name]=null);try{const S={...v,..._};nt(S),or("update",d,_,v),Mo("update",_,A),await sn("update",S,d,w,["update",_,o,void 0,v],c)}catch(S){throw new Error(`VALIDATION_ERROR: ${S.message}`)}let R;s&&(s.permissions||={});const M=async(S,q,B)=>{const[oe,Qe,Wt,me,ae]=await Promise.all([S.get(p.collection("system_deployment").doc("latest_deploy")),S.get(p.collection("system_deployment").doc("maintenance_mode")),Ge(n,e,{user:r,providedTransaction:S,noComputedFields:!0}),r?S.get(p.collection("tenants").doc(a).collection("system_user_permissions").doc(r)):Promise.resolve(Promise.resolve({})),je()]);if(B&&(B.size+=3),!oe.exists)throw new Error("VERSION_ERROR");const Pe=oe.data();if(Pe.force&&_.Last_Write_At.valueOf()<Pe.time.valueOf())throw new Error("VERSION_ERROR");if(!Qe.exists)throw new Error("MAINTENANCE_MODE");if(Qe.data().active)throw new Error("MAINTENANCE_MODE");if(!Wt)throw new Error("NOT_FOUND");if(v=Wt,c=ae,r){if(!me?.exists)throw new Error("PERMISSION_DENIED");if(T=me.data(),!T.Role)throw new Error("USER_ERROR");if(!T.Enabled)throw new Error("PERMISSION_DENIED")}if(B&&(B.size+=Ks(a,n,e,c,T).length),Z&&v.User_ID||x&&!v.User_ID)throw new Error("USER_ERROR");if(k(v)){const de=await S.get(p.collection("tenants").doc(a).collection("system_user_permissions").doc(v.User_ID));if(B&&B.size++,!de?.exists)throw new Error("PERMISSION_DENIED");if(R=de.data(),s?.permissions){if(s.permissions.Role||=_.Role||v.Role,s.permissions.Enabled??=_.Enabled??v.Enabled,Ne(s.permissions.Role))throw new Error("VALIDATION_ERROR: Role field is required");if(Ne(s.permissions.Enabled))throw new Error("VALIDATION_ERROR: Enabled field is required")}}const ar=O.filter(de=>"unique"in de&&de.unique).map(async de=>{if(!r||!de.access||de.access.includes(T.Role)){if(_[de.name]===void 0||Ne(_[de.name]))return;const jt=Ie(de,w),lr={...v,..._};if(!(r&&jt?.custom?.serverAccess?.read!==void 0?await ie(jt.custom.serverAccess.read,[T?.Role,lr]):!0))throw new Error("PERMISSION_DENIED");const Zt=_[de.name].toString().toLowerCase().replace(/\s/g,"---").replaceAll("/","|||");if(Qs(Zt)){if(B&&B.size++,B&&B.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 Qn=await S.get(p.collection("tenants").doc(a).collection("system_unique").doc(m.collection).collection(`Unique-${m.collection}-${de.name}`).doc(Zt));if(Qn.exists&&Qn.data().id!==e)throw new Error(`VALIDATION_ERROR: ${de.name} "${_[de.name]}" already exists`)}else throw new Error(`VALIDATION_ERROR: ${de.name} "${_[de.name]}" is invalid`)}});if(await Promise.all(ar),r&&T?.Role){const de=T.Role,jt={...v,..._};if(!(w.custom?.serverAccess?.update!==void 0?await ie(w.custom.serverAccess.update,[de,jt,v]):!0))throw new Error("PERMISSION_DENIED");for(const Jn of d.fields){const Zt=Ie(Jn,w);if(Object.prototype.hasOwnProperty.call(_,Jn.name)&&Zt?.custom?.serverAccess?.update!==void 0&&!await ie(Zt.custom.serverAccess.update,[de,jt,v]))throw new Error("PERMISSION_DENIED")}}dr(_,v,e,d,c,r,T,s?.operation?s.operation:g?"update":void 0,s?.permissions,R),s?.permissions&&r&&T&&await Po(S,s.permissions,r,T,c,R,B),dr(_,v,e,d,c,r,T,s?.operation?s.operation:g?"update":void 0,s?.permissions,R),q&&(Z||k(v)||x)&&await Yc(S,e,v.User_ID)};(Z||g||x)&&await p.runTransaction(async S=>{await M(S,!0)},{maxAttempts:10});try{let S;if(Z||k(v)||x){if(k(v)){S=await N.getUser(v.User_ID);const oe=S.customClaims;if(!(oe&&oe.role&&oe.collection&&oe.doc))throw new Error("USER_ERROR")}const q={...v,..._};nt(q);const B=await Lo(s?.operation||"update",a,e,l,m.collection,q,v,S,s?.permissions,R,s?.password);Z&&(_.User_ID=B),x&&(_.User_ID=H.FieldValue.delete())}try{const q={size:1};await p.runTransaction(async B=>{const oe={...v,..._};await M(B,!1,q);let Qe;i?.noTwoWay||(Qe=await ir("Update",a,e,oe,_,d,c,B,q,r,T,v));const Wt=Vs(c);Js("update",B,n,e,_,c,d,i,Wt,H.FieldValue.arrayUnion,H.FieldValue.arrayRemove,H.FieldValue.delete,me=>p.collection("tenants").doc(a).collection("system_fields").doc(m.collection).collection(`${m.collection}-${me.name}`).doc(e),(me,ae)=>p.collection("tenants").doc(a).collection("system_unique").doc(m.collection).collection(`Unique-${m.collection}-${me.name}`).doc(ae),me=>p.collection("tenants").doc(a).collection("system_fields").doc(m.collection).collection(`${m.collection}-${me}`).doc(e),(me,ae)=>Te(p,me,a).doc(ae),(me,ae,Pe)=>p.collection("tenants").doc(a).collection("system_fields").doc(me.collection).collection(`${me.collection}-${ae}`).doc(Pe),(me,ae,Pe)=>p.collection("tenants").doc(a).collection("system_fields").doc(me.collection).collection(`${me.collection}-${ae.replaceAll(" ","-")}`).doc(Pe),v,Qe,q),B.update(C.doc(e),_)},{maxAttempts:10})}catch(q){const B=["update",_,e,o,q,void 0,void 0,pe(v)],oe=await le("postWriteError",l,w,B);if(y&&(await new Promise(Qe=>{setTimeout(Qe,250)}),await pt("update",oe?.resolved?"success":"failed",_,a,n,e,d,oe?.resolved?void 0:q,v)),!oe?.resolved)throw Z&&await Ut(v),k(v)&&await Qt(v.User_ID,S,R,"USER_ERROR"),x&&await p.collection("tenants").doc(a).collection(m.collection).doc(e).update({User_ID:H.FieldValue.delete()}),q}(Z||k(v)||x)&&await ni(ii,[e,v.User_ID]).catch(()=>{throw new Error("USER_ERROR")})}catch(S){throw(Z||k(v)||x)&&await ni(ii,[e,v.User_ID]).catch(()=>{throw new Error("USER_ERROR")}),S}const $=["update",_,e,o,void 0,pe(v)],P=[...$];await le("postWrite",l,w,$),await le("postOperation",l,w,P);const j={...v,..._};return nt(j),{id:e,...j}},Jc=async(n,e,t,s,r)=>{const i=Ye(),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:f,auth:d,enableWriteLog:m,softDelete:O}=h,y=Je(f.collection,a),w=await ie(o.appName);if(O&&!d&&!s?.force)return await Vo(n,e,{[O.archivedField]:!0,[O.timestampField]:H.FieldValue.serverTimestamp()},void 0,t);const b=H.getFirestore();let N;t&&await sr(n,h);const p=Te(b,n,i);r=r||{},r.collection=f.collection;const T=await Ge(n,e,{user:t});let C=Us("delete",n,T,a,w,"Online",t||"System",H.Timestamp.now(),H.FieldValue.serverTimestamp());const v=kn(C);Le(C),m&&await pt("delete","started",C,i,n,e,h),await le("preOperation",o,y,["delete",C,e,r]),await le("preWrite",o,y,["delete",C,e,r]),Le(C);const g=async E=>{const[I,R,M,$]=await Promise.all([E.get(b.collection("system_deployment").doc("maintenance_mode")),Ge([f.collection],e,{user:t,providedTransaction:E}),t?E.get(b.collection("tenants").doc(i).collection("system_user_permissions").doc(t)):Promise.resolve(Promise.resolve({})),je()]);if(!I.exists)throw new Error("MAINTENANCE_MODE");if(I.data().active)throw new Error("MAINTENANCE_MODE");if(!R)throw new Error("NOT_FOUND");if(C={...R,...v},a=$,t){if(!M?.exists)throw new Error("PERMISSION_DENIED");if(N=M.data(),!N.Role)throw new Error("USER_ERROR");if(!N.Enabled)throw new Error("PERMISSION_DENIED");Xo(C,e,h,a,t,N)}if(t&&N?.Role){const j=N.Role;if(!(y.custom?.serverAccess?.delete!==void 0?await ie(y.custom.serverAccess.delete,[j,C]):!0))throw new Error("PERMISSION_DENIED")}};h.auth&&(await b.runTransaction(async E=>{await g(E)},{maxAttempts:10}),C.User_ID&&await Ut(C));try{await b.runTransaction(async E=>{await g(E);const I=Vs(a);Js("delete",E,n,e,C,a,h,s,I,H.FieldValue.arrayUnion,H.FieldValue.arrayRemove,H.FieldValue.delete,R=>b.collection("tenants").doc(i).collection("system_fields").doc(f.collection).collection(`${f.collection}-${R.name}`).doc(e),(R,M)=>b.collection("tenants").doc(i).collection("system_unique").doc(f.collection).collection(`Unique-${f.collection}-${R.name}`).doc(M),R=>b.collection("tenants").doc(i).collection("system_fields").doc(f.collection).collection(`${f.collection}-${R}`).doc(e),(R,M)=>Te(b,R,i).doc(M),(R,M,$)=>b.collection("tenants").doc(i).collection("system_fields").doc(R.collection).collection(`${R.collection}-${M}`).doc($),(R,M,$)=>b.collection("tenants").doc(i).collection("system_fields").doc(R.collection).collection(`${R.collection}-${M.replaceAll(" ","-")}`).doc($)),E.delete(p.doc(e))},{maxAttempts:10})}catch(E){const R=await le("postWriteError",o,y,["delete",C,e,r,E]);if(m&&(await new Promise(M=>{setTimeout(M,250)}),await pt("delete",R?.resolved?"success":"failed",C,i,n,e,h,R?.resolved?void 0:E)),!R?.resolved)throw h.auth&&C.User_ID&&await b.collection("tenants").doc(i).collection(f.collection).doc(e).update({User_ID:H.FieldValue.delete()}),E}const k=["delete",C,e,r],_=[...k];return await le("postWrite",o,y,k),await le("postOperation",o,y,_),{id:e,...C}},Qc=async(n,e)=>{const t=H.getFirestore(),s=xo(),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)},Kc=n=>n!==null&&typeof n=="object",Xc=n=>{const e=t=>{Object.entries(t).forEach(([s,r])=>{r instanceof H.Timestamp?t[s]={_seconds:r.seconds,_nanoseconds:r.nanoseconds}:Kc(r)&&e(r)})};e(n)},eu=async n=>await yt.getAuth().getUser(n),tu=n=>{const e=Do();return V.fromJSDate(n).setZone(e)},Uo=n=>{const e=Do();return V.fromJSDate(n.toDate()).setZone(e)},nu=(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()},su=(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()},ru=n=>"seconds"in n&&"nanoseconds"in n?Uo(new H.Timestamp(n.seconds,n.nanoseconds)).toFormat("MMMM d, yyyy '@' h:mm a"):"";exports.addRecord=Gc;exports.addUser=nr;exports.convertDateToTimezone=tu;exports.convertTimestampToTimezone=Uo;exports.deleteRecord=Jc;exports.deleteUser=Ut;exports.deserializeDeleteSentinels=Gn;exports.deserializeTimestamps=rr;exports.deserializeTimestampsWithoutUnderscores=Zc;exports.displayDate=ru;exports.fetchCurrentSchema=je;exports.fetchLastSchema=jc;exports.getCachedConfigValue=ia;exports.getCollectionRefs=Io;exports.getCustomizationFiles=bo;exports.getDocumentRefs=Ks;exports.getFirestorePathRef=Te;exports.getInputSchema=Vc;exports.getOne=Ge;exports.getSome=er;exports.getUser=eu;exports.getZodSchema=Ei;exports.initializeFirebase=Bo;exports.initializeStoker=Wc;exports.isDeleteSentinel=Ne;exports.keepTimezone=nu;exports.removeTimezone=su;exports.runChildProcess=qo;exports.sendMail=tr;exports.sendMessage=Qc;exports.serializeTimestamps=Xc;exports.tryPromise=ie;exports.updateRecord=Vo;exports.updateUser=Lo;exports.validateRelations=ir;exports.validateSoftDelete=or;exports.writeLog=pt;
|
package/dist/bundle.js
CHANGED
|
@@ -11067,7 +11067,7 @@ ${i}`);
|
|
|
11067
11067
|
if (y && (await new Promise((Qe) => {
|
|
11068
11068
|
setTimeout(Qe, 250);
|
|
11069
11069
|
}), await Mt("update", re?.resolved ? "success" : "failed", _, a, n, e, d, re?.resolved ? void 0 : q, v)), !re?.resolved)
|
|
11070
|
-
throw Z && await un(v), k(v) && await Qt(v.User_ID, S, R, "USER_ERROR"), x && await p.collection(m.collection).doc(e).update({ User_ID: me.delete() }), q;
|
|
11070
|
+
throw Z && await un(v), k(v) && await Qt(v.User_ID, S, R, "USER_ERROR"), x && await p.collection("tenants").doc(a).collection(m.collection).doc(e).update({ User_ID: me.delete() }), q;
|
|
11071
11071
|
}
|
|
11072
11072
|
(Z || k(v) || x) && await Jr(Xr, [e, v.User_ID]).catch(() => {
|
|
11073
11073
|
throw new Error("USER_ERROR");
|
|
@@ -11143,7 +11143,7 @@ ${i}`);
|
|
|
11143
11143
|
if (m && (await new Promise((F) => {
|
|
11144
11144
|
setTimeout(F, 250);
|
|
11145
11145
|
}), await Mt("delete", R?.resolved ? "success" : "failed", C, i, n, e, h, R?.resolved ? void 0 : E)), !R?.resolved)
|
|
11146
|
-
throw h.auth && C.User_ID && await b.collection(f.collection).doc(e).update({ User_ID: me.delete() }), E;
|
|
11146
|
+
throw h.auth && C.User_ID && await b.collection("tenants").doc(i).collection(f.collection).doc(e).update({ User_ID: me.delete() }), E;
|
|
11147
11147
|
}
|
|
11148
11148
|
const k = ["delete", C, e, r], _ = [...k];
|
|
11149
11149
|
return await ae("postWrite", o, y, k), await ae("postOperation", o, y, _), { id: e, ...C };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stoker-platform/node-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"files": [
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@google-cloud/storage": "^7.18.0",
|
|
26
|
-
"@stoker-platform/types": "0.
|
|
27
|
-
"@stoker-platform/utils": "0.
|
|
26
|
+
"@stoker-platform/types": "0.5.1",
|
|
27
|
+
"@stoker-platform/utils": "0.5.1",
|
|
28
28
|
"@types/luxon": "^3.7.1",
|
|
29
29
|
"firebase-admin": "^13.6.0",
|
|
30
30
|
"lodash": "^4.17.21",
|