@ram_28/kf-ai-sdk 2.0.20-beta.0 → 2.0.20-beta.2
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/{FileField-BWrSHNRq.js → FileField-CZjS2uLh.js} +3 -3
- package/dist/{FileField-eDeuzln8.cjs → FileField-DU4UWo_t.cjs} +1 -1
- package/dist/bdo/core/Item.d.ts +0 -4
- package/dist/bdo/core/Item.d.ts.map +1 -1
- package/dist/bdo/fields/ReferenceField.d.ts +1 -1
- package/dist/bdo/fields/ReferenceField.d.ts.map +1 -1
- package/dist/bdo/fields/SelectField.d.ts +1 -1
- package/dist/bdo/fields/SelectField.d.ts.map +1 -1
- package/dist/bdo/fields/UserField.d.ts +1 -1
- package/dist/bdo/fields/UserField.d.ts.map +1 -1
- package/dist/bdo.cjs +1 -1
- package/dist/bdo.mjs +298 -286
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts +2 -3
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.mjs +226 -243
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.mjs +1 -1
- package/package.json +1 -1
- package/sdk/bdo/core/Item.ts +1 -11
- package/sdk/bdo/expressions/evaluator.ts +51 -9
- package/sdk/bdo/fields/ReferenceField.ts +1 -1
- package/sdk/bdo/fields/SelectField.ts +1 -1
- package/sdk/bdo/fields/UserField.ts +1 -1
- package/sdk/components/hooks/useBDOForm/createItemProxy.ts +18 -63
package/dist/workflow.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var ne=Object.defineProperty;var ie=(o,t,e)=>t in o?ne(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var V=(o,t,e)=>ie(o,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./client-D5k4SYuw.cjs"),A=require("./FileField-eDeuzln8.cjs"),h=require("react"),k=require("./shared-nnmlRVs7.cjs"),oe=require("@tanstack/react-query"),z=require("./attachment-constants-B5jlqoKI.cjs"),G=require("./useTable-CeRklbdT.cjs"),ce=require("./metadata-DWXQPDav.cjs");class W{constructor(t){V(this,"bp_id");this.bp_id=t}async start(){const t=await fetch(`${y.getApiBaseUrl()}/api/app/process/${this.bp_id}/start`,{method:"POST",headers:y.getDefaultHeaders()});if(!t.ok)throw new Error(`Failed to start process: ${t.statusText}`);return(await t.json()).Data}async progress(t){const e=await fetch(`${y.getApiBaseUrl()}/api/app/process/${this.bp_id}/${t}/progress`,{method:"GET",headers:y.getDefaultHeaders()});if(!e.ok)throw new Error(`Failed to get process progress: ${e.statusText}`);return(await e.json()).Data}activity(t){const e=`/api/app/process/${this.bp_id}/${t}`;return{async inProgressList(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/inprogress/list`,{method:"POST",headers:y.getDefaultHeaders(),body:a?JSON.stringify(a):void 0});if(!r.ok)throw new Error(`Failed to list in-progress activities: ${r.statusText}`);return r.json()},async completedList(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/completed/list`,{method:"POST",headers:y.getDefaultHeaders(),body:a?JSON.stringify(a):void 0});if(!r.ok)throw new Error(`Failed to list completed activities: ${r.statusText}`);return r.json()},async inProgressCount(a){var w,s;const r={Type:"Metric",GroupBy:[],Metric:[{Field:"_id",Type:"Count"}],...(a==null?void 0:a.Filter)&&{Filter:a.Filter}},i=await fetch(`${y.getApiBaseUrl()}${e}/inprogress/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get in-progress count: ${i.statusText}`);return{Count:((s=(w=(await i.json()).Data)==null?void 0:w[0])==null?void 0:s.count__id)??0}},async completedCount(a){var w,s;const r={Type:"Metric",GroupBy:[],Metric:[{Field:"_id",Type:"Count"}],...(a==null?void 0:a.Filter)&&{Filter:a.Filter}},i=await fetch(`${y.getApiBaseUrl()}${e}/completed/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get completed count: ${i.statusText}`);return{Count:((s=(w=(await i.json()).Data)==null?void 0:w[0])==null?void 0:s.count__id)??0}},async inProgressMetric(a){const r={Type:"Metric",...a},i=await fetch(`${y.getApiBaseUrl()}${e}/inprogress/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get in-progress metrics: ${i.statusText}`);return i.json()},async completedMetric(a){const r={Type:"Metric",...a},i=await fetch(`${y.getApiBaseUrl()}${e}/completed/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get completed metrics: ${i.statusText}`);return i.json()},async read(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/${a}/read`,{method:"GET",headers:y.getDefaultHeaders()});if(!r.ok)throw new Error(`Failed to read activity: ${r.statusText}`);return(await r.json()).Data},async update(a,r){const i=await fetch(`${y.getApiBaseUrl()}${e}/${a}/update`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to update activity: ${i.statusText}`);return i.json()},async draftStart(a,r){const i=await fetch(`${y.getApiBaseUrl()}${e}/${a}/draft`,{method:"PATCH",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to start draft: ${i.statusText}`);return i.json()},async draftEnd(a,r){const i=await fetch(`${y.getApiBaseUrl()}${e}/${a}/draft`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to end draft: ${i.statusText}`);return i.json()},async complete(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/${a}/done`,{method:"POST",headers:y.getDefaultHeaders()});if(!r.ok)throw new Error(`Failed to complete activity: ${r.statusText}`);return r.json()},async progress(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/${a}/progress`,{method:"GET",headers:y.getDefaultHeaders()});if(!r.ok)throw new Error(`Failed to get activity progress: ${r.statusText}`);return r.json()}}}}class X{constructor(t,e,a,r){V(this,"_id");V(this,"_data");V(this,"_ops");V(this,"_fields");V(this,"_accessorCache",new Map);this._ops=t,this._id=e,this._data={...a},this._fields=r}toJSON(){return{...this._data}}validate(){const t=[];for(const[e,a]of Object.entries(this._fields)){const r=this._data[e],i=a.validate(r);i.valid||t.push(...i.errors)}return{valid:t.length===0,errors:t}}async update(t){return this._ops.update(this._id,t)}async save(t){return this._ops.draftEnd(this._id,t)}async complete(){return this._ops.complete(this._id)}async progress(){return this._ops.progress(this._id)}_getAccessor(t){if(this._accessorCache.has(t))return this._accessorCache.get(t);const e=this._fields[t],a=(e==null?void 0:e.meta)??{_id:t,Name:t,Type:"String"},r=(e==null?void 0:e.readOnly)??!1,i=()=>e?e.validate(this._data[t]):{valid:!0,errors:[]};let n;return r?n={label:(e==null?void 0:e.label)??t,required:(e==null?void 0:e.required)??!1,readOnly:!0,defaultValue:e==null?void 0:e.defaultValue,meta:a,get:()=>this._data[t],validate:i}:n={label:(e==null?void 0:e.label)??t,required:(e==null?void 0:e.required)??!1,readOnly:!1,defaultValue:e==null?void 0:e.defaultValue,meta:a,get:()=>this._data[t],set:f=>{this._data[t]=f},validate:i},this._accessorCache.set(t,n),n}}function le(o,t,e,a){const r=new X(o,t,e,a);return new Proxy(r,{get(i,n,f){return n==="validate"||n==="toJSON"||n==="update"||n==="save"||n==="complete"||n==="progress"||n==="_ops"||n==="_data"||n==="_fields"||n==="_accessorCache"||n==="_getAccessor"||typeof n=="symbol"?Reflect.get(i,n,f):n==="_id"?i._id:i._getAccessor(n)},has(i,n){return typeof n=="symbol"?!1:n==="validate"||n==="toJSON"||n==="update"||n==="save"||n==="complete"||n==="progress"||n==="_id"?!0:n in i._fields},ownKeys(i){return[...Object.keys(i._fields),"_id","validate","toJSON","update","save","complete","progress"]},getOwnPropertyDescriptor(i,n){if(typeof n!="symbol")return{configurable:!0,enumerable:n!=="validate"&&n!=="toJSON"&&n!=="update"&&n!=="save"&&n!=="complete"&&n!=="progress"}}})}class ue{constructor(){V(this,"_fieldsCache",null)}_ops(){return new W(this.meta.businessProcessId).activity(this.meta.activityId)}_discoverFields(){if(this._fieldsCache)return this._fieldsCache;const t={};for(const e of Object.keys(this)){const a=this[e];a instanceof A.BaseField&&(t[e]=a)}return this._fieldsCache=t,t}async getInProgressList(t){return this._ops().inProgressList(t)}async getCompletedList(t){return this._ops().completedList(t)}async inProgressCount(t){return(await this._ops().inProgressCount(t)).Count}async completedCount(t){return(await this._ops().completedCount(t)).Count}async inProgressMetric(t){return this._ops().inProgressMetric(t)}async completedMetric(t){return this._ops().completedMetric(t)}async getInstance(t){const e=this._ops(),a=await e.read(t),r=this._discoverFields();return le(e,t,a,r)}_getFields(){return this._discoverFields()}_getOps(){return this._ops()}}function K(o,t){var r;const e={_id:o,...t},a=t.Type;if(a==="String"&&((r=t.Constraint)!=null&&r.Enum))return new A.SelectField(e);switch(a){case"String":return new A.StringField(e);case"Number":return new A.NumberField(e);case"Boolean":return new A.BooleanField(e);case"Date":return new A.DateField(e);case"DateTime":return new A.DateTimeField(e);case"Text":return new A.TextField(e);case"Reference":return new A.ReferenceField(e);case"User":return new A.UserField(e);case"File":return new A.FileField(e);default:return new A.StringField(e)}}function Y(o){const t={};for(const[e,a]of Object.entries(o))t[e]=K(e,a);return t}function de(o,t,e){var i;const a=t==null?void 0:t.BDOBlob;if(!(a!=null&&a.Activity))return null;const r=o==null?void 0:o.Id;for(const n of a.Activity)if(n.Id!==r&&(i=n.Input)!=null&&i[e])return n.Input[e];return null}function ye(o){return async(t,e,a)=>{const r={},i="_getFields"in o?o._getFields():o,n=(a==null?void 0:a.names)??Object.keys(i);for(const f of n){const w=i[f];if(!w||w.readOnly)continue;let s=t[f];typeof s=="string"&&w.meta.Type==="Number"&&(s=s===""?void 0:Number(s));const l=w.validate(s);if(!l.valid&&l.errors.length>0){r[f]={type:"validate",message:l.errors[0]||`${f} is invalid`};continue}const v=k.validateConstraints(w,s);!v.valid&&v.errors.length>0&&(r[f]={type:"constraint",message:v.errors[0]})}return Object.keys(r).length===0?{values:t,errors:{}}:{values:{},errors:r}}}function fe(o,t,e){const a=o._getFields(),r=new Map,i=`/api/app/process/${o.meta.businessProcessId}/${o.meta.activityId}`,n=y.createResourceClient(i);function f(){if(!e)throw new Error("Cannot perform attachment operation: no activity instance ID");return e}return new Proxy({},{get(w,s){if(typeof s=="symbol")return;if(s==="_id")return e;if(s==="toJSON")return()=>t.getValues();if(s==="validate")return()=>t.trigger();if(r.has(s))return r.get(s);const l=a[s],v=(l==null?void 0:l.meta)??{_id:s,Name:s,Type:"String"},E=(l==null?void 0:l.readOnly)??!1,I=()=>l?l.validate(t.getValues(s)):{valid:!0,errors:[]},q=$=>{const d=t.getValues(s);return d??$};if(!E){const $=()=>{const c=t.getValues(s);return v.Type==="File"?c??[]:c},d={label:(l==null?void 0:l.label)??s,required:(l==null?void 0:l.required)??!1,readOnly:!1,defaultValue:l==null?void 0:l.defaultValue,meta:v,get:$,getOrDefault:q,set:c=>{t.setValue(s,c,{shouldDirty:!0,shouldTouch:!0,shouldValidate:!1})},validate:I};return(v.Type==="Image"||v.Type==="File")&&(v.Type==="Image"?(d.upload=async c=>{z.validateFileExtension(c.name,"Image");const m=f(),[g]=await n.getUploadUrl(m,s,[{FileName:c.name,Size:c.size,FileExtension:z.extractFileExtension(c.name)}]);await fetch(g.UploadUrl.URL,{method:"PUT",headers:{"Content-Type":g.ContentType},body:c});const F={_id:g._id,_name:g._name,FileName:g.FileName,FileExtension:g.FileExtension,Size:g.Size,ContentType:g.ContentType};return t.setValue(s,F,{shouldDirty:!0}),F},d.deleteAttachment=async()=>{const c=t.getValues(s),m=f();if(!(c!=null&&c._id))throw new Error(`${s} has no image to delete`);await n.deleteAttachment(m,s,c._id),t.setValue(s,null,{shouldDirty:!0})},d.getDownloadUrl=async c=>{const m=t.getValues(s),g=f();if(!(m!=null&&m._id))throw new Error(`${s} has no image`);return n.getDownloadUrl(g,s,m._id,c)}):(d.upload=async c=>{for(const O of c)z.validateFileExtension(O.name,"File");const m=f(),g=c.map(O=>({FileName:O.name,Size:O.size,FileExtension:z.extractFileExtension(O.name)})),F=await n.getUploadUrl(m,s,g),R=await Promise.all(c.map(async(O,P)=>(await fetch(F[P].UploadUrl.URL,{method:"PUT",headers:{"Content-Type":F[P].ContentType},body:O}),{_id:F[P]._id,_name:F[P]._name,FileName:F[P].FileName,FileExtension:F[P].FileExtension,Size:F[P].Size,ContentType:F[P].ContentType}))),u=t.getValues(s)??[];return t.setValue(s,[...u,...R],{shouldDirty:!0}),R},d.deleteAttachment=async c=>{const m=t.getValues(s)??[],g=f();await n.deleteAttachment(g,s,c),t.setValue(s,m.filter(F=>F._id!==c),{shouldDirty:!0})},d.getDownloadUrl=async(c,m)=>{const g=f();return n.getDownloadUrl(g,s,c,m)},d.getDownloadUrls=async c=>{const m=f();return n.getDownloadUrls(m,s,c)})),r.set(s,d),d}const B=()=>{const $=t.getValues(s);return v.Type==="File"?$??[]:$},D={label:(l==null?void 0:l.label)??s,required:(l==null?void 0:l.required)??!1,readOnly:!0,defaultValue:l==null?void 0:l.defaultValue,meta:v,get:B,getOrDefault:q,validate:I};return(v.Type==="Image"||v.Type==="File")&&(v.Type==="Image"?D.getDownloadUrl=async $=>{const d=t.getValues(s),c=f();if(!(d!=null&&d._id))throw new Error(`${s} has no image to download`);return n.getDownloadUrl(c,s,d._id,$)}:(D.getDownloadUrl=async($,d)=>{const c=f();return n.getDownloadUrl(c,s,$,d)},D.getDownloadUrls=async $=>{const d=f();return n.getDownloadUrls(d,s,$)})),r.set(s,D),D},has(w,s){return typeof s=="symbol"?!1:s==="_id"||s==="toJSON"||s==="validate"?!0:s in a},ownKeys(w){return[...Object.keys(a),"_id","toJSON","validate"]},getOwnPropertyDescriptor(w,s){if(typeof s!="symbol")return{configurable:!0,enumerable:s!=="toJSON"&&s!=="validate"}}})}function ge(o,t){const{activity_instance_id:e,defaultValues:a={},mode:r="onBlur",enabled:i=!0}=t,[n,f]=h.useState(!1),[w,s]=h.useState(null),[l,v]=h.useState(!1),[E,I]=h.useState({}),q=h.useRef(!1),B=h.useRef(null),{data:D,isLoading:$}=oe.useQuery({queryKey:["bp-metadata",o.meta.businessProcessId],queryFn:()=>ce.getBdoSchema(o.meta.businessProcessId),staleTime:30*60*1e3}),d=h.useMemo(()=>{const _=D==null?void 0:D.BDOBlob;return _!=null&&_.Activity?_.Activity.find(b=>b.Id===o.meta.activityId)??null:null},[D,o.meta.activityId]),c=$,m=h.useMemo(()=>d!=null&&d.Input?Y(d.Input):o._getFields(),[d,o]),g=h.useMemo(()=>({...E,...m}),[E,m]),F=h.useMemo(()=>Object.keys(g).filter(_=>g[_].readOnly),[g]),R=h.useMemo(()=>ye(m),[m]),u=k.useForm({mode:r,defaultValues:a,resolver:R}),O=h.useMemo(()=>o._getOps(),[o]),P=h.useMemo(()=>fe(o,u,e),[o,u,e]);h.useEffect(()=>{if(!i||c)return;let _=!0;return(async()=>{f(!0),s(null);try{const T=await O.read(e);if(!_)return;if(T&&typeof T=="object"){const U=k.coerceRecordForForm(m,T),p={...a,...U};(B.current===null||T!==B.current)&&(u.reset(p),B.current=T);const M=new Set(["_id","BPInstanceId","Status","AssignedTo","CompletedAt","_created_at","_modified_at","_created_by","_modified_by","_v","_m_v"]),x={};for(const C of Object.keys(T))if(!m[C]&&!M.has(C)){const S=de(d,D,C);S&&(x[C]=K(C,{...S,ReadOnly:!0}))}Object.keys(x).length>0&&I(x)}}catch(T){if(!_)return;console.error("Failed to read activity data:",T),s(G.toError(T))}finally{_&&f(!1)}})(),()=>{_=!1}},[i,c,O,e]);const Q=h.useCallback((_,b)=>O.update(e,{[_]:b}),[O,e]),J=h.useMemo(()=>k.createSyncField({apiFn:Q,allFields:g,readonlyFieldNames:F,rhf:u,isComputingRef:q}),[Q,g,F,u]),L=r==="onChange"||r==="all",H=r==="onBlur"||r==="onTouched"||r==="all",Z=h.useMemo(()=>k.createEnhancedRegister({rhf:u,allFields:g,syncField:J,syncOnBlur:H,syncOnChange:L}),[u,g,J,H,L]),ee=h.useMemo(()=>k.createEnhancedControl({control:u.control,syncField:J,syncOnBlur:H,syncOnChange:L}),[u.control,J,H,L]),te=h.useCallback((_,b)=>u.handleSubmit(async(T,U)=>{v(!0);try{const p={},M=new Set(F),x=u.formState.dirtyFields,C=u.getValues();for(const S of Object.keys(C)){if(M.has(S)||!x[S])continue;const N=C[S]!==void 0?C[S]:T[S],j=g[S];p[S]=j?k.coerceFieldValue(j,N):N}Object.keys(p).length>0&&await O.update(e,p),await(_==null?void 0:_(T,U))}catch(p){b==null||b(G.toError(p),U)}finally{v(!1)}},(T,U)=>{b==null||b(T,U)}),[u,O,F,g,e]),se=h.useCallback((_,b)=>u.handleSubmit(async(T,U)=>{v(!0);try{const p={},M=new Set(F),x=u.formState.dirtyFields,C=u.getValues();for(const S of Object.keys(C)){if(M.has(S)||!x[S])continue;const N=C[S]!==void 0?C[S]:T[S],j=g[S];p[S]=j?k.coerceFieldValue(j,N):N}Object.keys(p).length>0&&await O.update(e,p),await O.complete(e),await(_==null?void 0:_(T,U))}catch(p){b==null||b(G.toError(p),U)}finally{v(!1)}},(T,U)=>{b==null||b(T,U)}),[u,O,F,g,e]),ae=h.useCallback(()=>{u.clearErrors()},[u]),re=!!w;return{item:P,activity:o,register:Z,handleSubmit:te,handleComplete:se,watch:u.watch,setValue:u.setValue,getValues:u.getValues,reset:u.reset,trigger:u.trigger,control:ee,errors:u.formState.errors,isValid:u.formState.isValid,isDirty:u.formState.isDirty,isSubmitting:u.formState.isSubmitting||l,isSubmitSuccessful:u.formState.isSubmitSuccessful,isLoading:n||c,isMetadataLoading:c,loadError:w,hasError:re,bpMetadata:D??null,clearErrors:ae}}function he(o){const{activity:t,status:e,...a}=o,{businessProcessId:r,activityId:i}=t.meta,n=h.useMemo(()=>t._getOps(),[t]),f=h.useMemo(()=>e==="inprogress"?s=>n.inProgressList(s):s=>n.completedList(s),[n,e]),w=h.useMemo(()=>e==="inprogress"?s=>n.inProgressCount(s):s=>n.completedCount(s),[n,e]);return G.useTable({queryKey:["activity-table",r,i,e],listFn:f,countFn:w,...a})}const me={InProgress:"inprogress",Completed:"completed"};exports.Activity=ue;exports.ActivityInstance=X;exports.ActivityTableStatus=me;exports.Workflow=W;exports.buildFieldsFromInput=Y;exports.createFieldFromMeta=K;exports.useActivityForm=ge;exports.useActivityTable=he;
|
|
1
|
+
"use strict";var ne=Object.defineProperty;var ie=(o,t,e)=>t in o?ne(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var V=(o,t,e)=>ie(o,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./client-D5k4SYuw.cjs"),A=require("./FileField-DU4UWo_t.cjs"),h=require("react"),k=require("./shared-nnmlRVs7.cjs"),oe=require("@tanstack/react-query"),z=require("./attachment-constants-B5jlqoKI.cjs"),G=require("./useTable-CeRklbdT.cjs"),ce=require("./metadata-DWXQPDav.cjs");class W{constructor(t){V(this,"bp_id");this.bp_id=t}async start(){const t=await fetch(`${y.getApiBaseUrl()}/api/app/process/${this.bp_id}/start`,{method:"POST",headers:y.getDefaultHeaders()});if(!t.ok)throw new Error(`Failed to start process: ${t.statusText}`);return(await t.json()).Data}async progress(t){const e=await fetch(`${y.getApiBaseUrl()}/api/app/process/${this.bp_id}/${t}/progress`,{method:"GET",headers:y.getDefaultHeaders()});if(!e.ok)throw new Error(`Failed to get process progress: ${e.statusText}`);return(await e.json()).Data}activity(t){const e=`/api/app/process/${this.bp_id}/${t}`;return{async inProgressList(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/inprogress/list`,{method:"POST",headers:y.getDefaultHeaders(),body:a?JSON.stringify(a):void 0});if(!r.ok)throw new Error(`Failed to list in-progress activities: ${r.statusText}`);return r.json()},async completedList(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/completed/list`,{method:"POST",headers:y.getDefaultHeaders(),body:a?JSON.stringify(a):void 0});if(!r.ok)throw new Error(`Failed to list completed activities: ${r.statusText}`);return r.json()},async inProgressCount(a){var w,s;const r={Type:"Metric",GroupBy:[],Metric:[{Field:"_id",Type:"Count"}],...(a==null?void 0:a.Filter)&&{Filter:a.Filter}},i=await fetch(`${y.getApiBaseUrl()}${e}/inprogress/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get in-progress count: ${i.statusText}`);return{Count:((s=(w=(await i.json()).Data)==null?void 0:w[0])==null?void 0:s.count__id)??0}},async completedCount(a){var w,s;const r={Type:"Metric",GroupBy:[],Metric:[{Field:"_id",Type:"Count"}],...(a==null?void 0:a.Filter)&&{Filter:a.Filter}},i=await fetch(`${y.getApiBaseUrl()}${e}/completed/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get completed count: ${i.statusText}`);return{Count:((s=(w=(await i.json()).Data)==null?void 0:w[0])==null?void 0:s.count__id)??0}},async inProgressMetric(a){const r={Type:"Metric",...a},i=await fetch(`${y.getApiBaseUrl()}${e}/inprogress/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get in-progress metrics: ${i.statusText}`);return i.json()},async completedMetric(a){const r={Type:"Metric",...a},i=await fetch(`${y.getApiBaseUrl()}${e}/completed/metric`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to get completed metrics: ${i.statusText}`);return i.json()},async read(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/${a}/read`,{method:"GET",headers:y.getDefaultHeaders()});if(!r.ok)throw new Error(`Failed to read activity: ${r.statusText}`);return(await r.json()).Data},async update(a,r){const i=await fetch(`${y.getApiBaseUrl()}${e}/${a}/update`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to update activity: ${i.statusText}`);return i.json()},async draftStart(a,r){const i=await fetch(`${y.getApiBaseUrl()}${e}/${a}/draft`,{method:"PATCH",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to start draft: ${i.statusText}`);return i.json()},async draftEnd(a,r){const i=await fetch(`${y.getApiBaseUrl()}${e}/${a}/draft`,{method:"POST",headers:y.getDefaultHeaders(),body:JSON.stringify(r)});if(!i.ok)throw new Error(`Failed to end draft: ${i.statusText}`);return i.json()},async complete(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/${a}/done`,{method:"POST",headers:y.getDefaultHeaders()});if(!r.ok)throw new Error(`Failed to complete activity: ${r.statusText}`);return r.json()},async progress(a){const r=await fetch(`${y.getApiBaseUrl()}${e}/${a}/progress`,{method:"GET",headers:y.getDefaultHeaders()});if(!r.ok)throw new Error(`Failed to get activity progress: ${r.statusText}`);return r.json()}}}}class X{constructor(t,e,a,r){V(this,"_id");V(this,"_data");V(this,"_ops");V(this,"_fields");V(this,"_accessorCache",new Map);this._ops=t,this._id=e,this._data={...a},this._fields=r}toJSON(){return{...this._data}}validate(){const t=[];for(const[e,a]of Object.entries(this._fields)){const r=this._data[e],i=a.validate(r);i.valid||t.push(...i.errors)}return{valid:t.length===0,errors:t}}async update(t){return this._ops.update(this._id,t)}async save(t){return this._ops.draftEnd(this._id,t)}async complete(){return this._ops.complete(this._id)}async progress(){return this._ops.progress(this._id)}_getAccessor(t){if(this._accessorCache.has(t))return this._accessorCache.get(t);const e=this._fields[t],a=(e==null?void 0:e.meta)??{_id:t,Name:t,Type:"String"},r=(e==null?void 0:e.readOnly)??!1,i=()=>e?e.validate(this._data[t]):{valid:!0,errors:[]};let n;return r?n={label:(e==null?void 0:e.label)??t,required:(e==null?void 0:e.required)??!1,readOnly:!0,defaultValue:e==null?void 0:e.defaultValue,meta:a,get:()=>this._data[t],validate:i}:n={label:(e==null?void 0:e.label)??t,required:(e==null?void 0:e.required)??!1,readOnly:!1,defaultValue:e==null?void 0:e.defaultValue,meta:a,get:()=>this._data[t],set:f=>{this._data[t]=f},validate:i},this._accessorCache.set(t,n),n}}function le(o,t,e,a){const r=new X(o,t,e,a);return new Proxy(r,{get(i,n,f){return n==="validate"||n==="toJSON"||n==="update"||n==="save"||n==="complete"||n==="progress"||n==="_ops"||n==="_data"||n==="_fields"||n==="_accessorCache"||n==="_getAccessor"||typeof n=="symbol"?Reflect.get(i,n,f):n==="_id"?i._id:i._getAccessor(n)},has(i,n){return typeof n=="symbol"?!1:n==="validate"||n==="toJSON"||n==="update"||n==="save"||n==="complete"||n==="progress"||n==="_id"?!0:n in i._fields},ownKeys(i){return[...Object.keys(i._fields),"_id","validate","toJSON","update","save","complete","progress"]},getOwnPropertyDescriptor(i,n){if(typeof n!="symbol")return{configurable:!0,enumerable:n!=="validate"&&n!=="toJSON"&&n!=="update"&&n!=="save"&&n!=="complete"&&n!=="progress"}}})}class ue{constructor(){V(this,"_fieldsCache",null)}_ops(){return new W(this.meta.businessProcessId).activity(this.meta.activityId)}_discoverFields(){if(this._fieldsCache)return this._fieldsCache;const t={};for(const e of Object.keys(this)){const a=this[e];a instanceof A.BaseField&&(t[e]=a)}return this._fieldsCache=t,t}async getInProgressList(t){return this._ops().inProgressList(t)}async getCompletedList(t){return this._ops().completedList(t)}async inProgressCount(t){return(await this._ops().inProgressCount(t)).Count}async completedCount(t){return(await this._ops().completedCount(t)).Count}async inProgressMetric(t){return this._ops().inProgressMetric(t)}async completedMetric(t){return this._ops().completedMetric(t)}async getInstance(t){const e=this._ops(),a=await e.read(t),r=this._discoverFields();return le(e,t,a,r)}_getFields(){return this._discoverFields()}_getOps(){return this._ops()}}function K(o,t){var r;const e={_id:o,...t},a=t.Type;if(a==="String"&&((r=t.Constraint)!=null&&r.Enum))return new A.SelectField(e);switch(a){case"String":return new A.StringField(e);case"Number":return new A.NumberField(e);case"Boolean":return new A.BooleanField(e);case"Date":return new A.DateField(e);case"DateTime":return new A.DateTimeField(e);case"Text":return new A.TextField(e);case"Reference":return new A.ReferenceField(e);case"User":return new A.UserField(e);case"File":return new A.FileField(e);default:return new A.StringField(e)}}function Y(o){const t={};for(const[e,a]of Object.entries(o))t[e]=K(e,a);return t}function de(o,t,e){var i;const a=t==null?void 0:t.BDOBlob;if(!(a!=null&&a.Activity))return null;const r=o==null?void 0:o.Id;for(const n of a.Activity)if(n.Id!==r&&(i=n.Input)!=null&&i[e])return n.Input[e];return null}function ye(o){return async(t,e,a)=>{const r={},i="_getFields"in o?o._getFields():o,n=(a==null?void 0:a.names)??Object.keys(i);for(const f of n){const w=i[f];if(!w||w.readOnly)continue;let s=t[f];typeof s=="string"&&w.meta.Type==="Number"&&(s=s===""?void 0:Number(s));const l=w.validate(s);if(!l.valid&&l.errors.length>0){r[f]={type:"validate",message:l.errors[0]||`${f} is invalid`};continue}const v=k.validateConstraints(w,s);!v.valid&&v.errors.length>0&&(r[f]={type:"constraint",message:v.errors[0]})}return Object.keys(r).length===0?{values:t,errors:{}}:{values:{},errors:r}}}function fe(o,t,e){const a=o._getFields(),r=new Map,i=`/api/app/process/${o.meta.businessProcessId}/${o.meta.activityId}`,n=y.createResourceClient(i);function f(){if(!e)throw new Error("Cannot perform attachment operation: no activity instance ID");return e}return new Proxy({},{get(w,s){if(typeof s=="symbol")return;if(s==="_id")return e;if(s==="toJSON")return()=>t.getValues();if(s==="validate")return()=>t.trigger();if(r.has(s))return r.get(s);const l=a[s],v=(l==null?void 0:l.meta)??{_id:s,Name:s,Type:"String"},E=(l==null?void 0:l.readOnly)??!1,I=()=>l?l.validate(t.getValues(s)):{valid:!0,errors:[]},q=$=>{const d=t.getValues(s);return d??$};if(!E){const $=()=>{const c=t.getValues(s);return v.Type==="File"?c??[]:c},d={label:(l==null?void 0:l.label)??s,required:(l==null?void 0:l.required)??!1,readOnly:!1,defaultValue:l==null?void 0:l.defaultValue,meta:v,get:$,getOrDefault:q,set:c=>{t.setValue(s,c,{shouldDirty:!0,shouldTouch:!0,shouldValidate:!1})},validate:I};return(v.Type==="Image"||v.Type==="File")&&(v.Type==="Image"?(d.upload=async c=>{z.validateFileExtension(c.name,"Image");const m=f(),[g]=await n.getUploadUrl(m,s,[{FileName:c.name,Size:c.size,FileExtension:z.extractFileExtension(c.name)}]);await fetch(g.UploadUrl.URL,{method:"PUT",headers:{"Content-Type":g.ContentType},body:c});const F={_id:g._id,_name:g._name,FileName:g.FileName,FileExtension:g.FileExtension,Size:g.Size,ContentType:g.ContentType};return t.setValue(s,F,{shouldDirty:!0}),F},d.deleteAttachment=async()=>{const c=t.getValues(s),m=f();if(!(c!=null&&c._id))throw new Error(`${s} has no image to delete`);await n.deleteAttachment(m,s,c._id),t.setValue(s,null,{shouldDirty:!0})},d.getDownloadUrl=async c=>{const m=t.getValues(s),g=f();if(!(m!=null&&m._id))throw new Error(`${s} has no image`);return n.getDownloadUrl(g,s,m._id,c)}):(d.upload=async c=>{for(const O of c)z.validateFileExtension(O.name,"File");const m=f(),g=c.map(O=>({FileName:O.name,Size:O.size,FileExtension:z.extractFileExtension(O.name)})),F=await n.getUploadUrl(m,s,g),R=await Promise.all(c.map(async(O,P)=>(await fetch(F[P].UploadUrl.URL,{method:"PUT",headers:{"Content-Type":F[P].ContentType},body:O}),{_id:F[P]._id,_name:F[P]._name,FileName:F[P].FileName,FileExtension:F[P].FileExtension,Size:F[P].Size,ContentType:F[P].ContentType}))),u=t.getValues(s)??[];return t.setValue(s,[...u,...R],{shouldDirty:!0}),R},d.deleteAttachment=async c=>{const m=t.getValues(s)??[],g=f();await n.deleteAttachment(g,s,c),t.setValue(s,m.filter(F=>F._id!==c),{shouldDirty:!0})},d.getDownloadUrl=async(c,m)=>{const g=f();return n.getDownloadUrl(g,s,c,m)},d.getDownloadUrls=async c=>{const m=f();return n.getDownloadUrls(m,s,c)})),r.set(s,d),d}const B=()=>{const $=t.getValues(s);return v.Type==="File"?$??[]:$},D={label:(l==null?void 0:l.label)??s,required:(l==null?void 0:l.required)??!1,readOnly:!0,defaultValue:l==null?void 0:l.defaultValue,meta:v,get:B,getOrDefault:q,validate:I};return(v.Type==="Image"||v.Type==="File")&&(v.Type==="Image"?D.getDownloadUrl=async $=>{const d=t.getValues(s),c=f();if(!(d!=null&&d._id))throw new Error(`${s} has no image to download`);return n.getDownloadUrl(c,s,d._id,$)}:(D.getDownloadUrl=async($,d)=>{const c=f();return n.getDownloadUrl(c,s,$,d)},D.getDownloadUrls=async $=>{const d=f();return n.getDownloadUrls(d,s,$)})),r.set(s,D),D},has(w,s){return typeof s=="symbol"?!1:s==="_id"||s==="toJSON"||s==="validate"?!0:s in a},ownKeys(w){return[...Object.keys(a),"_id","toJSON","validate"]},getOwnPropertyDescriptor(w,s){if(typeof s!="symbol")return{configurable:!0,enumerable:s!=="toJSON"&&s!=="validate"}}})}function ge(o,t){const{activity_instance_id:e,defaultValues:a={},mode:r="onBlur",enabled:i=!0}=t,[n,f]=h.useState(!1),[w,s]=h.useState(null),[l,v]=h.useState(!1),[E,I]=h.useState({}),q=h.useRef(!1),B=h.useRef(null),{data:D,isLoading:$}=oe.useQuery({queryKey:["bp-metadata",o.meta.businessProcessId],queryFn:()=>ce.getBdoSchema(o.meta.businessProcessId),staleTime:30*60*1e3}),d=h.useMemo(()=>{const _=D==null?void 0:D.BDOBlob;return _!=null&&_.Activity?_.Activity.find(b=>b.Id===o.meta.activityId)??null:null},[D,o.meta.activityId]),c=$,m=h.useMemo(()=>d!=null&&d.Input?Y(d.Input):o._getFields(),[d,o]),g=h.useMemo(()=>({...E,...m}),[E,m]),F=h.useMemo(()=>Object.keys(g).filter(_=>g[_].readOnly),[g]),R=h.useMemo(()=>ye(m),[m]),u=k.useForm({mode:r,defaultValues:a,resolver:R}),O=h.useMemo(()=>o._getOps(),[o]),P=h.useMemo(()=>fe(o,u,e),[o,u,e]);h.useEffect(()=>{if(!i||c)return;let _=!0;return(async()=>{f(!0),s(null);try{const T=await O.read(e);if(!_)return;if(T&&typeof T=="object"){const U=k.coerceRecordForForm(m,T),p={...a,...U};(B.current===null||T!==B.current)&&(u.reset(p),B.current=T);const M=new Set(["_id","BPInstanceId","Status","AssignedTo","CompletedAt","_created_at","_modified_at","_created_by","_modified_by","_v","_m_v"]),x={};for(const C of Object.keys(T))if(!m[C]&&!M.has(C)){const S=de(d,D,C);S&&(x[C]=K(C,{...S,ReadOnly:!0}))}Object.keys(x).length>0&&I(x)}}catch(T){if(!_)return;console.error("Failed to read activity data:",T),s(G.toError(T))}finally{_&&f(!1)}})(),()=>{_=!1}},[i,c,O,e]);const Q=h.useCallback((_,b)=>O.update(e,{[_]:b}),[O,e]),J=h.useMemo(()=>k.createSyncField({apiFn:Q,allFields:g,readonlyFieldNames:F,rhf:u,isComputingRef:q}),[Q,g,F,u]),L=r==="onChange"||r==="all",H=r==="onBlur"||r==="onTouched"||r==="all",Z=h.useMemo(()=>k.createEnhancedRegister({rhf:u,allFields:g,syncField:J,syncOnBlur:H,syncOnChange:L}),[u,g,J,H,L]),ee=h.useMemo(()=>k.createEnhancedControl({control:u.control,syncField:J,syncOnBlur:H,syncOnChange:L}),[u.control,J,H,L]),te=h.useCallback((_,b)=>u.handleSubmit(async(T,U)=>{v(!0);try{const p={},M=new Set(F),x=u.formState.dirtyFields,C=u.getValues();for(const S of Object.keys(C)){if(M.has(S)||!x[S])continue;const N=C[S]!==void 0?C[S]:T[S],j=g[S];p[S]=j?k.coerceFieldValue(j,N):N}Object.keys(p).length>0&&await O.update(e,p),await(_==null?void 0:_(T,U))}catch(p){b==null||b(G.toError(p),U)}finally{v(!1)}},(T,U)=>{b==null||b(T,U)}),[u,O,F,g,e]),se=h.useCallback((_,b)=>u.handleSubmit(async(T,U)=>{v(!0);try{const p={},M=new Set(F),x=u.formState.dirtyFields,C=u.getValues();for(const S of Object.keys(C)){if(M.has(S)||!x[S])continue;const N=C[S]!==void 0?C[S]:T[S],j=g[S];p[S]=j?k.coerceFieldValue(j,N):N}Object.keys(p).length>0&&await O.update(e,p),await O.complete(e),await(_==null?void 0:_(T,U))}catch(p){b==null||b(G.toError(p),U)}finally{v(!1)}},(T,U)=>{b==null||b(T,U)}),[u,O,F,g,e]),ae=h.useCallback(()=>{u.clearErrors()},[u]),re=!!w;return{item:P,activity:o,register:Z,handleSubmit:te,handleComplete:se,watch:u.watch,setValue:u.setValue,getValues:u.getValues,reset:u.reset,trigger:u.trigger,control:ee,errors:u.formState.errors,isValid:u.formState.isValid,isDirty:u.formState.isDirty,isSubmitting:u.formState.isSubmitting||l,isSubmitSuccessful:u.formState.isSubmitSuccessful,isLoading:n||c,isMetadataLoading:c,loadError:w,hasError:re,bpMetadata:D??null,clearErrors:ae}}function he(o){const{activity:t,status:e,...a}=o,{businessProcessId:r,activityId:i}=t.meta,n=h.useMemo(()=>t._getOps(),[t]),f=h.useMemo(()=>e==="inprogress"?s=>n.inProgressList(s):s=>n.completedList(s),[n,e]),w=h.useMemo(()=>e==="inprogress"?s=>n.inProgressCount(s):s=>n.completedCount(s),[n,e]);return G.useTable({queryKey:["activity-table",r,i,e],listFn:f,countFn:w,...a})}const me={InProgress:"inprogress",Completed:"completed"};exports.Activity=ue;exports.ActivityInstance=X;exports.ActivityTableStatus=me;exports.Workflow=W;exports.buildFieldsFromInput=Y;exports.createFieldFromMeta=K;exports.useActivityForm=ge;exports.useActivityTable=he;
|
package/dist/workflow.mjs
CHANGED
|
@@ -2,7 +2,7 @@ var oe = Object.defineProperty;
|
|
|
2
2
|
var ce = (o, t, e) => t in o ? oe(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
3
3
|
var N = (o, t, e) => ce(o, typeof t != "symbol" ? t + "" : t, e);
|
|
4
4
|
import { c as S, g as $, d as le } from "./client-_ayziI1d.js";
|
|
5
|
-
import { B as ue, c as de, S as Q, F as ye, U as fe, R as he, T as ge, D as me, b as _e, a as we, N as Fe } from "./FileField-
|
|
5
|
+
import { B as ue, c as de, S as Q, F as ye, U as fe, R as he, T as ge, D as me, b as _e, a as we, N as Fe } from "./FileField-CZjS2uLh.js";
|
|
6
6
|
import { useState as z, useRef as W, useMemo as P, useEffect as Te, useCallback as G } from "react";
|
|
7
7
|
import { v as ve, u as Oe, b as be, d as Se, e as $e, f as X, a as Ce } from "./shared-5a7UkED1.js";
|
|
8
8
|
import { useQuery as pe } from "@tanstack/react-query";
|
package/package.json
CHANGED
package/sdk/bdo/core/Item.ts
CHANGED
|
@@ -196,18 +196,8 @@ export class Item<T extends Record<string, unknown>> {
|
|
|
196
196
|
}) as Item<T>;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
/**
|
|
200
|
-
* Require instanceId or throw.
|
|
201
|
-
* TODO: Support create flow via draftInteraction to get temp _id
|
|
202
|
-
*/
|
|
203
199
|
private _requireInstanceId(): string {
|
|
204
|
-
|
|
205
|
-
if (!id) {
|
|
206
|
-
throw new Error(
|
|
207
|
-
"Cannot perform attachment operation: item has no _id. Save the item first.",
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
return id;
|
|
200
|
+
return (this._data._id as string | undefined) || "draft";
|
|
211
201
|
}
|
|
212
202
|
|
|
213
203
|
/**
|
|
@@ -105,6 +105,40 @@ function evaluateSystemIdentifier(
|
|
|
105
105
|
return systemValue;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/**
|
|
109
|
+
* ISO date regex: matches YYYY-MM-DD with optional time component
|
|
110
|
+
*/
|
|
111
|
+
const _DATE_RE = /^\d{4}-\d{2}-\d{2}([ T]\d{2}:\d{2}(:\d{2})?)?$/;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Convert a date-like value to a comparable timestamp (ms since epoch).
|
|
115
|
+
* Returns NaN if the value is not a valid date.
|
|
116
|
+
*/
|
|
117
|
+
function _toTimestamp(value: unknown): number {
|
|
118
|
+
if (value instanceof Date) return value.getTime();
|
|
119
|
+
if (typeof value === "string" && _DATE_RE.test(value)) {
|
|
120
|
+
// Append "T00:00:00" for date-only strings to ensure consistent parsing
|
|
121
|
+
const normalized = value.includes("T") || value.includes(" ")
|
|
122
|
+
? value.replace(" ", "T")
|
|
123
|
+
: value + "T00:00:00";
|
|
124
|
+
return new Date(normalized).getTime();
|
|
125
|
+
}
|
|
126
|
+
return NaN;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Compare two values for ordering operators (<, <=, >, >=).
|
|
131
|
+
* Uses date comparison for date-like values, numeric comparison otherwise.
|
|
132
|
+
*/
|
|
133
|
+
function _compareValues(left: unknown, right: unknown): { l: number; r: number } {
|
|
134
|
+
const lt = _toTimestamp(left);
|
|
135
|
+
const rt = _toTimestamp(right);
|
|
136
|
+
// If both are valid dates, compare as timestamps
|
|
137
|
+
if (!isNaN(lt) && !isNaN(rt)) return { l: lt, r: rt };
|
|
138
|
+
// Otherwise fall back to numeric comparison
|
|
139
|
+
return { l: Number(left), r: Number(right) };
|
|
140
|
+
}
|
|
141
|
+
|
|
108
142
|
/**
|
|
109
143
|
* Evaluate a BinaryExpression node
|
|
110
144
|
*
|
|
@@ -131,15 +165,23 @@ function evaluateBinaryExpression(
|
|
|
131
165
|
case "!=":
|
|
132
166
|
return left != right;
|
|
133
167
|
|
|
134
|
-
//
|
|
135
|
-
case "<":
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
case "
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
168
|
+
// Ordering comparison — date-aware
|
|
169
|
+
case "<": {
|
|
170
|
+
const { l, r } = _compareValues(left, right);
|
|
171
|
+
return l < r;
|
|
172
|
+
}
|
|
173
|
+
case "<=": {
|
|
174
|
+
const { l, r } = _compareValues(left, right);
|
|
175
|
+
return l <= r;
|
|
176
|
+
}
|
|
177
|
+
case ">": {
|
|
178
|
+
const { l, r } = _compareValues(left, right);
|
|
179
|
+
return l > r;
|
|
180
|
+
}
|
|
181
|
+
case ">=": {
|
|
182
|
+
const { l, r } = _compareValues(left, right);
|
|
183
|
+
return l >= r;
|
|
184
|
+
}
|
|
143
185
|
|
|
144
186
|
// Arithmetic operators
|
|
145
187
|
case "+":
|
|
@@ -71,7 +71,7 @@ export class ReferenceField<TRef = unknown> extends BaseField<
|
|
|
71
71
|
* Fetch referenced records from the backend via the fetchField API.
|
|
72
72
|
* Requires the field to be bound to a parent BDO.
|
|
73
73
|
*/
|
|
74
|
-
async fetchOptions(instanceId: string): Promise<TRef[]> {
|
|
74
|
+
async fetchOptions(instanceId: string = "draft"): Promise<TRef[]> {
|
|
75
75
|
if (!this._parentBoId) {
|
|
76
76
|
throw new Error(
|
|
77
77
|
`Field ${this.id} not bound to a BDO. Cannot fetch options.`
|
|
@@ -57,7 +57,7 @@ export class SelectField<T extends string | number = string> extends BaseField<T
|
|
|
57
57
|
/**
|
|
58
58
|
* Fetch dynamic options from the backend, returned as typed SelectOption[]
|
|
59
59
|
*/
|
|
60
|
-
async fetchOptions(instanceId: string): Promise<SelectOptionType<T>[]> {
|
|
60
|
+
async fetchOptions(instanceId: string = "draft"): Promise<SelectOptionType<T>[]> {
|
|
61
61
|
if (!this._parentBoId) {
|
|
62
62
|
throw new Error(
|
|
63
63
|
`Field ${this.id} not bound to a BDO. Cannot fetch options.`
|
|
@@ -32,7 +32,7 @@ export class UserField extends BaseField<UserFieldType> {
|
|
|
32
32
|
* Fetch user records from the backend via the fetchField API.
|
|
33
33
|
* Requires the field to be bound to a parent BDO.
|
|
34
34
|
*/
|
|
35
|
-
async fetchOptions(instanceId: string): Promise<UserFieldType[]> {
|
|
35
|
+
async fetchOptions(instanceId: string = "draft"): Promise<UserFieldType[]> {
|
|
36
36
|
if (!this._parentBoId) {
|
|
37
37
|
throw new Error(
|
|
38
38
|
`Field ${this.id} not bound to a BDO. Cannot fetch options.`,
|
|
@@ -21,9 +21,8 @@ import type {
|
|
|
21
21
|
* Key principle: Item has NO state. It's a view over RHF's state.
|
|
22
22
|
* Editable fields get set(), readonly fields do not.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* On form submit, if a draft _id exists, update() is used instead of create().
|
|
24
|
+
* In create mode (no _id), uses "draft" as the instanceId for attachment
|
|
25
|
+
* uploads and fetch operations — no draftInteraction() call needed.
|
|
27
26
|
*
|
|
28
27
|
* @param bdo - The BDO instance for field metadata
|
|
29
28
|
* @param form - The RHF useForm return object
|
|
@@ -36,34 +35,9 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
36
35
|
const fields = bdo.getFields();
|
|
37
36
|
const accessorCache = new Map<string, EditableFormFieldAccessorType<unknown> | ReadonlyFormFieldAccessorType<unknown>>();
|
|
38
37
|
|
|
39
|
-
// Draft tracking for create mode — shared across all attachment fields in this form
|
|
40
38
|
const boIdShared = bdo.getBoId();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Ensures a record _id exists for attachment uploads.
|
|
46
|
-
* In edit mode, returns the existing _id.
|
|
47
|
-
* In create mode, creates a draft record via draftInteraction() to get an _id.
|
|
48
|
-
* The draft _id is shared across all attachment fields and only created once.
|
|
49
|
-
*/
|
|
50
|
-
async function ensureDraft(): Promise<string> {
|
|
51
|
-
// If form already has an _id (edit mode or previous draft), use it
|
|
52
|
-
const existing = form.getValues("_id" as Path<FieldValues>) as string | undefined;
|
|
53
|
-
if (existing) return existing;
|
|
54
|
-
if (draftId) return draftId;
|
|
55
|
-
if (!draftPromise) {
|
|
56
|
-
draftPromise = api(boIdShared).draftInteraction({}).then((d: any) => {
|
|
57
|
-
draftId = d._id;
|
|
58
|
-
form.setValue("_id" as Path<FieldValues>, draftId as any, { shouldDirty: false });
|
|
59
|
-
return draftId!;
|
|
60
|
-
}).catch((err: Error) => {
|
|
61
|
-
draftPromise = null;
|
|
62
|
-
throw err;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return draftPromise;
|
|
66
|
-
}
|
|
39
|
+
const getInstanceId = (): string =>
|
|
40
|
+
(form.getValues("_id" as Path<FieldValues>) as string) || "draft";
|
|
67
41
|
|
|
68
42
|
return new Proxy({} as FormItemType<ExtractEditableType<B>, ExtractReadonlyType<B>>, {
|
|
69
43
|
get(_, prop: string | symbol) {
|
|
@@ -87,11 +61,6 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
87
61
|
return () => form.trigger();
|
|
88
62
|
}
|
|
89
63
|
|
|
90
|
-
// Internal: check if a draft was created (used by handleSubmit)
|
|
91
|
-
if (prop === "_hasDraft") {
|
|
92
|
-
return () => !!draftId;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
64
|
// Return cached accessor if available
|
|
96
65
|
if (accessorCache.has(prop)) {
|
|
97
66
|
return accessorCache.get(prop);
|
|
@@ -179,21 +148,15 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
179
148
|
validate,
|
|
180
149
|
};
|
|
181
150
|
|
|
182
|
-
// Enrich Image/File field accessors with attachment methods
|
|
151
|
+
// Enrich Image/File field accessors with attachment methods
|
|
183
152
|
if (fieldMeta.Type === "Image" || fieldMeta.Type === "File") {
|
|
184
153
|
const boId = boIdShared;
|
|
185
|
-
const requireInstanceId = (): string => {
|
|
186
|
-
const id = form.getValues("_id" as Path<FieldValues>) as string | undefined;
|
|
187
|
-
if (!id) throw new Error("Save the record before attachment operations");
|
|
188
|
-
return id;
|
|
189
|
-
};
|
|
190
154
|
|
|
191
155
|
if (fieldMeta.Type === "Image") {
|
|
192
|
-
// Image: single file upload
|
|
156
|
+
// Image: single file upload
|
|
193
157
|
(accessor as any).upload = async (file: File): Promise<FileType> => {
|
|
194
158
|
validateFileExtension(file.name, "Image");
|
|
195
|
-
const id =
|
|
196
|
-
|
|
159
|
+
const id = getInstanceId();
|
|
197
160
|
const [uploadInfo] = await api(boId).getUploadUrl(id, prop, [
|
|
198
161
|
{ FileName: file.name, Size: file.size, FileExtension: extractFileExtension(file.name) },
|
|
199
162
|
]);
|
|
@@ -216,7 +179,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
216
179
|
|
|
217
180
|
(accessor as any).deleteAttachment = async (): Promise<void> => {
|
|
218
181
|
const val = form.getValues(prop as Path<FieldValues>) as any;
|
|
219
|
-
const instanceId =
|
|
182
|
+
const instanceId = getInstanceId();
|
|
220
183
|
if (!(val?._id)) throw new Error(`${prop} has no image to delete`);
|
|
221
184
|
await api(boId).deleteAttachment(instanceId, prop, val._id);
|
|
222
185
|
form.setValue(prop as Path<FieldValues>, null as any, { shouldDirty: true });
|
|
@@ -224,16 +187,15 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
224
187
|
|
|
225
188
|
(accessor as any).getDownloadUrl = async (viewType?: AttachmentViewType): Promise<FileDownloadResponseType> => {
|
|
226
189
|
const val = form.getValues(prop as Path<FieldValues>) as any;
|
|
227
|
-
const instanceId =
|
|
190
|
+
const instanceId = getInstanceId();
|
|
228
191
|
if (!(val?._id)) throw new Error(`${prop} has no image`);
|
|
229
192
|
return api(boId).getDownloadUrl(instanceId, prop, val._id, viewType);
|
|
230
193
|
};
|
|
231
194
|
} else {
|
|
232
|
-
// File field — multi-file
|
|
195
|
+
// File field — multi-file
|
|
233
196
|
(accessor as any).upload = async (files: File[]): Promise<FileType[]> => {
|
|
234
197
|
for (const file of files) validateFileExtension(file.name, "File");
|
|
235
|
-
const id =
|
|
236
|
-
|
|
198
|
+
const id = getInstanceId();
|
|
237
199
|
const requests = files.map((file) => ({
|
|
238
200
|
FileName: file.name,
|
|
239
201
|
Size: file.size,
|
|
@@ -264,7 +226,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
264
226
|
|
|
265
227
|
(accessor as any).deleteAttachment = async (attachmentId: string): Promise<void> => {
|
|
266
228
|
const current = (form.getValues(prop as Path<FieldValues>) as any[]) ?? [];
|
|
267
|
-
const instanceId =
|
|
229
|
+
const instanceId = getInstanceId();
|
|
268
230
|
await api(boId).deleteAttachment(instanceId, prop, attachmentId);
|
|
269
231
|
form.setValue(
|
|
270
232
|
prop as Path<FieldValues>,
|
|
@@ -277,13 +239,13 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
277
239
|
attachmentId: string,
|
|
278
240
|
viewType?: AttachmentViewType,
|
|
279
241
|
): Promise<FileDownloadResponseType> => {
|
|
280
|
-
const instanceId =
|
|
242
|
+
const instanceId = getInstanceId();
|
|
281
243
|
return api(boId).getDownloadUrl(instanceId, prop, attachmentId, viewType);
|
|
282
244
|
};
|
|
283
245
|
(accessor as any).getDownloadUrls = async (
|
|
284
246
|
viewType?: AttachmentViewType,
|
|
285
247
|
): Promise<FileDownloadResponseType[]> => {
|
|
286
|
-
const instanceId =
|
|
248
|
+
const instanceId = getInstanceId();
|
|
287
249
|
return api(boId).getDownloadUrls(instanceId, prop, viewType);
|
|
288
250
|
};
|
|
289
251
|
}
|
|
@@ -314,16 +276,11 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
314
276
|
// Enrich readonly Image/File field accessors with download methods
|
|
315
277
|
if (fieldMeta.Type === "Image" || fieldMeta.Type === "File") {
|
|
316
278
|
const boId = boIdShared;
|
|
317
|
-
const requireInstanceId = (): string => {
|
|
318
|
-
const id = form.getValues("_id" as Path<FieldValues>) as string | undefined;
|
|
319
|
-
if (!id) throw new Error("Cannot perform attachment operation: item has no _id. Save the item first.");
|
|
320
|
-
return id;
|
|
321
|
-
};
|
|
322
279
|
|
|
323
280
|
if (fieldMeta.Type === "Image") {
|
|
324
281
|
(accessor as any).getDownloadUrl = async (viewType?: AttachmentViewType): Promise<FileDownloadResponseType> => {
|
|
325
282
|
const val = form.getValues(prop as Path<FieldValues>) as any;
|
|
326
|
-
const instanceId =
|
|
283
|
+
const instanceId = getInstanceId();
|
|
327
284
|
if (!(val?._id)) throw new Error(`${prop} has no image to download`);
|
|
328
285
|
return api(boId).getDownloadUrl(instanceId, prop, val._id, viewType);
|
|
329
286
|
};
|
|
@@ -332,13 +289,13 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
332
289
|
attachmentId: string,
|
|
333
290
|
viewType?: AttachmentViewType,
|
|
334
291
|
): Promise<FileDownloadResponseType> => {
|
|
335
|
-
const instanceId =
|
|
292
|
+
const instanceId = getInstanceId();
|
|
336
293
|
return api(boId).getDownloadUrl(instanceId, prop, attachmentId, viewType);
|
|
337
294
|
};
|
|
338
295
|
(accessor as any).getDownloadUrls = async (
|
|
339
296
|
viewType?: AttachmentViewType,
|
|
340
297
|
): Promise<FileDownloadResponseType[]> => {
|
|
341
|
-
const instanceId =
|
|
298
|
+
const instanceId = getInstanceId();
|
|
342
299
|
return api(boId).getDownloadUrls(instanceId, prop, viewType);
|
|
343
300
|
};
|
|
344
301
|
}
|
|
@@ -352,8 +309,6 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
352
309
|
if (typeof prop === "symbol") return false;
|
|
353
310
|
if (prop === "_id" || prop === "toJSON" || prop === "validate")
|
|
354
311
|
return true;
|
|
355
|
-
if (prop === "_hasDraft")
|
|
356
|
-
return true;
|
|
357
312
|
return prop in fields;
|
|
358
313
|
},
|
|
359
314
|
|
|
@@ -365,7 +320,7 @@ export function createItemProxy<B extends BaseBdo<any, any, any>>(
|
|
|
365
320
|
if (typeof prop === "symbol") return undefined;
|
|
366
321
|
return {
|
|
367
322
|
configurable: true,
|
|
368
|
-
enumerable: prop !== "toJSON" && prop !== "validate"
|
|
323
|
+
enumerable: prop !== "toJSON" && prop !== "validate",
|
|
369
324
|
};
|
|
370
325
|
},
|
|
371
326
|
});
|