aboutsummaryrefslogtreecommitdiff
path: root/src/fields/util.ts
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-08-08 12:27:40 -0400
committerbobzel <zzzman@gmail.com>2024-08-08 12:27:40 -0400
commit4574b7f03ccc85c4bebdbfd9475788456086704f (patch)
treed23d30343541b9af029ef418492d629d3cc710d7 /src/fields/util.ts
parente1db06d59d580aa640212a0d3a6aeecb9122bdf0 (diff)
many changes to add typing in place of 'any's etc
Diffstat (limited to 'src/fields/util.ts')
-rw-r--r--src/fields/util.ts132
1 files changed, 77 insertions, 55 deletions
diff --git a/src/fields/util.ts b/src/fields/util.ts
index a6499c3e3..69ece82a2 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -7,7 +7,7 @@ import { UndoManager } from '../client/util/UndoManager';
import { Doc, DocListCast, FieldType, FieldResult, HierarchyMapping, ReverseHierarchyMap, StrListCast, aclLevel, updateCachedAcls } from './Doc';
import { AclAdmin, AclAugment, AclEdit, AclPrivate, DirectLinks, DocAcl, DocData, DocLayout, FieldKeys, ForceServerWrite, Height, Initializing, SelfProxy, UpdatingFromServer, Width } from './DocSymbols';
import { FieldChanged, Id, Parent, ToValue } from './FieldSymbols';
-import { List } from './List';
+import { List, ListImpl } from './List';
import { ObjectField } from './ObjectField';
import { PrefetchProxy, ProxyField } from './Proxy';
import { RefField } from './RefField';
@@ -44,15 +44,23 @@ export function TraceMobx() {
tracing && trace();
}
-export const _propSetterCB = new Map<string, ((target: any, value: any) => void) | undefined>();
+export const _propSetterCB = new Map<string, ((target: Doc, value: FieldType) => void) | undefined>();
-const _setterImpl = action((target: any, prop: string | symbol | number, valueIn: any, receiver: any): boolean => {
+const _setterImpl = action((target: Doc | ListImpl<FieldType>, prop: string | symbol | number, valueIn: unknown, receiver: Doc | ListImpl<FieldType>): boolean => {
+ if (target instanceof ListImpl) {
+ if (typeof prop !== 'symbol' && +prop == prop) {
+ target[SelfProxy].splice(+prop, 1, valueIn as FieldType);
+ } else {
+ target[prop] = valueIn as FieldType;
+ }
+ return true;
+ }
if (SerializationHelper.IsSerializing() || typeof prop === 'symbol') {
- target[prop] = valueIn;
+ target[prop] = valueIn as FieldResult;
return true;
}
- let value = valueIn?.[SelfProxy] ?? valueIn; // convert any Doc type values to Proxy's
+ let value = (valueIn as Doc | ListImpl<FieldType>)?.[SelfProxy] ?? valueIn; // convert any Doc type values to Proxy's
const curValue = target.__fieldTuples[prop];
if (curValue === value || (curValue instanceof ProxyField && value instanceof RefField && curValue.fieldId === value[Id])) {
@@ -60,7 +68,7 @@ const _setterImpl = action((target: any, prop: string | symbol | number, valueIn
// curValue should get filled in with value if it isn't already filled in, in case we fetched the referenced field some other way
return true;
}
- if (value instanceof RefField) {
+ if (value instanceof Doc) {
value = new ProxyField(value);
}
@@ -77,7 +85,7 @@ const _setterImpl = action((target: any, prop: string | symbol | number, valueIn
delete curValue[FieldChanged];
}
- if (typeof prop === 'string' && _propSetterCB.has(prop)) _propSetterCB.get(prop)!(target[SelfProxy], value);
+ if (typeof prop === 'string' && _propSetterCB.has(prop)) _propSetterCB.get(prop)!(target[SelfProxy], value as FieldType);
// eslint-disable-next-line no-use-before-define
const effectiveAcl = GetEffectiveAcl(target);
@@ -108,16 +116,17 @@ const _setterImpl = action((target: any, prop: string | symbol | number, valueIn
(target as Doc|ObjectField)[FieldChanged]?.(undefined, { $unset: { ['fields.' + prop]: '' } });
else (target as Doc|ObjectField)[FieldChanged]?.(undefined, { $set: { ['fields.' + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) :value}});
if (prop === 'author' || prop.toString().startsWith('acl_')) updateCachedAcls(target);
- } else {
+ } else if (receiver instanceof Doc) {
DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue);
}
!receiver[Initializing] &&
+ receiver instanceof Doc &&
!StrListCast(receiver.undoIgnoreFields).includes(prop.toString()) &&
(!receiver[UpdatingFromServer] || receiver[ForceServerWrite]) &&
UndoManager.AddEvent(
{
redo: () => {
- receiver[prop] = value;
+ receiver[prop] = value as FieldType;
},
undo: () => {
const wasUpdate = receiver[UpdatingFromServer];
@@ -137,7 +146,7 @@ const _setterImpl = action((target: any, prop: string | symbol | number, valueIn
return true;
});
-let _setter: (target: any, prop: string | symbol | number, value: any, receiver: any) => boolean = _setterImpl;
+let _setter: (target: Doc | ListImpl<FieldType>, prop: string | symbol | number, value: FieldType | undefined, receiver: Doc | ListImpl<FieldType>) => boolean = _setterImpl;
export function makeReadOnly() {
_setter = _readOnlySetter;
@@ -156,18 +165,18 @@ export function denormalizeEmail(email: string) {
// return acl from cache or cache the acl and return.
// eslint-disable-next-line no-use-before-define
-const getEffectiveAclCache = computedFn((target: any, user?: string) => getEffectiveAcl(target, user), true);
+const getEffectiveAclCache = computedFn((target: Doc | ListImpl<FieldType>, user?: string) => getEffectiveAcl(target, user), true);
/**
* Calculates the effective access right to a document for the current user.
*/
-export function GetEffectiveAcl(target: any, user?: string): symbol {
+export function GetEffectiveAcl(target: Doc | ListImpl<FieldType>, user?: string): symbol {
if (!target) return AclPrivate;
if (target[UpdatingFromServer] || ClientUtils.CurrentUserEmail() === 'guest') return AclAdmin;
return getEffectiveAclCache(target, user); // all changes received from the server must be processed as Admin. return this directly so that the acls aren't cached (UpdatingFromServer is not observable)
}
-export function GetPropAcl(target: any, prop: string | symbol | number) {
+export function GetPropAcl(target: Doc | ListImpl<FieldType>, prop: string | symbol | number) {
if (typeof prop === 'symbol' || target[UpdatingFromServer]) return AclAdmin; // requesting the UpdatingFromServer prop or AclSym must always go through to keep the local DB consistent
if (prop && DocServer.IsPlaygroundField(prop.toString())) return AclEdit; // playground props are always editable
return GetEffectiveAcl(target);
@@ -182,7 +191,8 @@ export function GetCachedGroupByName(name: string) {
export function SetCachedGroups(groups: string[]) {
runInAction(() => cachedGroups.push(...groups));
}
-function getEffectiveAcl(target: any, user?: string): symbol {
+function getEffectiveAcl(target: Doc | ListImpl<FieldType>, user?: string): symbol {
+ if (target instanceof ListImpl) return AclAdmin;
const targetAcls = target[DocAcl];
if (targetAcls?.acl_Me === AclAdmin || GetCachedGroupByName('Admin')) return AclAdmin;
@@ -287,14 +297,14 @@ export function inheritParentAcls(parent: Doc, child: Doc, layoutOnly: boolean)
* @param prop
* @param propSetter
*/
-export function SetPropSetterCb(prop: string, propSetter: ((target: any, value: any) => void) | undefined) {
+export function SetPropSetterCb(prop: string, propSetter: ((target: Doc, value: FieldType) => void) | undefined) {
_propSetterCB.set(prop, propSetter);
}
//
// target should be either a Doc or ListImpl. receiver should be a Proxy<Doc> Or List.
//
-export function setter(target: any, inProp: string | symbol | number, value: any, receiver: any): boolean {
+export function setter(target: ListImpl<FieldType> | Doc, inProp: string | symbol | number, value: unknown, receiver: Doc | ListImpl<FieldType>): boolean {
if (!inProp) {
console.log('WARNING: trying to set an empty property. This should be fixed. ');
return false;
@@ -303,12 +313,12 @@ export function setter(target: any, inProp: string | symbol | number, value: any
const effectiveAcl = inProp === 'constructor' || typeof inProp === 'symbol' ? AclAdmin : GetPropAcl(target, prop);
if (effectiveAcl !== AclEdit && effectiveAcl !== AclAugment && effectiveAcl !== AclAdmin) return true;
// if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't
- if (typeof prop === 'string' && prop.startsWith('acl_') && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value))) return true;
+ if (typeof prop === 'string' && prop.startsWith('acl_') && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value as SharingPermissions))) return true;
if (typeof prop === 'string' && prop !== '__id' && prop !== '__fieldTuples' && prop.startsWith('_')) {
if (!prop.startsWith('__')) prop = prop.substring(1);
- if (target.__LAYOUT__) {
- target.__LAYOUT__[prop] = value;
+ if (target.__LAYOUT__ instanceof Doc) {
+ target.__LAYOUT__[prop] = value as FieldResult;
return true;
}
}
@@ -317,10 +327,10 @@ export function setter(target: any, inProp: string | symbol | number, value: any
return !!ScriptCast(target.__fieldTuples[prop])?.setterscript?.run({ self: target[SelfProxy], this: target[SelfProxy], value }).success;
}
}
- return _setter(target, prop, value, receiver);
+ return _setter(target, prop, value as FieldType, receiver);
}
-function getFieldImpl(target: any, prop: string | number, proxy: any, ignoreProto: boolean = false): any {
+function getFieldImpl(target: ListImpl<FieldType> | Doc, prop: string | number, proxy: ListImpl<FieldType> | Doc, ignoreProto: boolean = false): FieldType {
const field = target.__fieldTuples[prop];
const value = field?.[ToValue]?.(proxy); // converts ComputedFields to values, or unpacks ProxyFields into Proxys
if (value) return value.value;
@@ -332,7 +342,7 @@ function getFieldImpl(target: any, prop: string | number, proxy: any, ignoreProt
}
return field;
}
-export function getter(target: any, prop: string | symbol, proxy: any): any {
+export function getter(target: Doc | ListImpl<FieldType>, prop: string | symbol, proxy: ListImpl<FieldType> | Doc): unknown {
// prettier-ignore
switch (prop) {
case 'then' : return undefined;
@@ -352,19 +362,23 @@ export function getter(target: any, prop: string | symbol, proxy: any): any {
}
const layoutProp = prop.startsWith('_') ? prop.substring(1) : undefined;
- if (layoutProp && target.__LAYOUT__) return target.__LAYOUT__[layoutProp];
+ if (layoutProp && target.__LAYOUT__) return (target.__LAYOUT__ as Doc)[layoutProp];
return getFieldImpl(target, layoutProp ?? prop, proxy);
}
-export function getField(target: any, prop: string | number, ignoreProto: boolean = false): any {
- return getFieldImpl(target, prop, target[SelfProxy], ignoreProto);
+export function getField(target: ListImpl<FieldType> | Doc, prop: string | number, ignoreProto: boolean = false): unknown {
+ return getFieldImpl(target, prop, target[SelfProxy] as Doc, ignoreProto);
}
-export function deleteProperty(target: any, prop: string | number | symbol) {
+export function deleteProperty(target: Doc | ListImpl<FieldType>, prop: string | number | symbol) {
if (typeof prop === 'symbol') {
delete target[prop];
} else {
- target[SelfProxy][prop] = undefined;
+ if (target instanceof Doc) {
+ target[SelfProxy][prop] = undefined;
+ } else if (+prop == prop) {
+ target[SelfProxy].splice(+prop, 1);
+ }
}
return true;
}
@@ -378,39 +392,42 @@ export function deleteProperty(target: any, prop: string | number | symbol) {
// were replaced. Based on this specification, an Undo event is setup that will save enough information about the ObjectField to be
// able to undo and redo the partial change.
//
-export function containedFieldChangedHandler(container: List<FieldType> | Doc, prop: string | number, liveContainedField: ObjectField) {
+export function containedFieldChangedHandler(container: ListImpl<FieldType> | Doc, prop: string | number, liveContainedField: ObjectField) {
let lastValue: FieldResult = liveContainedField instanceof ObjectField ? ObjectField.MakeCopy(liveContainedField) : liveContainedField;
- return (diff?: { op: '$addToSet' | '$remFromSet' | '$set'; items: FieldType[] | undefined; length: number | undefined; hint?: any } /* , dummyServerOp?: any */) => {
+ return (diff?: { op: '$addToSet' | '$remFromSet' | '$set'; items: (FieldType & { value?: FieldType })[] | undefined; length: number | undefined; hint?: unknown } /* , dummyServerOp?: any */) => {
const serializeItems = () => ({ __type: 'list', fields: diff?.items?.map((item: FieldType) => SerializationHelper.Serialize(item)) });
// prettier-ignore
const serverOp = diff?.op === '$addToSet'
? { $addToSet: { ['fields.' + prop]: serializeItems() }, length: diff.length }
: diff?.op === '$remFromSet'
? { $remFromSet: { ['fields.' + prop]: serializeItems(), hint: diff.hint}, length: diff.length }
- : { $set: { ['fields.' + prop]: liveContainedField ? SerializationHelper.Serialize(liveContainedField) : undefined } };
+ : { $set: { ['fields.' + prop]: liveContainedField ? SerializationHelper.Serialize(liveContainedField) as FieldType : undefined } };
if (!(container instanceof Doc) || !container[UpdatingFromServer]) {
- const prevValue = ObjectField.MakeCopy(lastValue as List<any>);
+ const cont = container as { [key: string | number]: FieldType };
+ const prevValue = ObjectField.MakeCopy(lastValue as List<FieldType>);
lastValue = ObjectField.MakeCopy(liveContainedField);
const newValue = ObjectField.MakeCopy(liveContainedField);
if (diff?.op === '$addToSet') {
UndoManager.AddEvent(
{
redo: () => {
+ const contList = cont[prop] as List<FieldType>;
// console.log('redo $add: ' + prop, diff.items); // bcz: uncomment to log undo
- (container as any)[prop as any]?.push(...((diff.items || [])?.map((item: any) => item.value ?? item) ?? []));
- lastValue = ObjectField.MakeCopy((container as any)[prop as any]);
+ contList?.push(...((diff.items || [])?.map(item => item.value ?? item) ?? []));
+ lastValue = ObjectField.MakeCopy(contList);
},
undo: action(() => {
+ const contList = cont[prop] as List<FieldType>;
// console.log('undo $add: ' + prop, diff.items); // bcz: uncomment to log undo
- diff.items?.forEach((item: any) => {
+ diff.items?.forEach(item => {
const ind =
item instanceof SchemaHeaderField //
- ? (container as any)[prop as any]?.findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading)
- : (container as any)[prop as any]?.indexOf(item.value ?? item);
- ind !== undefined && ind !== -1 && (container as any)[prop as any]?.splice(ind, 1);
+ ? contList?.findIndex(ele => ele instanceof SchemaHeaderField && ele.heading === item.heading)
+ : contList?.indexOf(item.value ?? item);
+ ind !== undefined && ind !== -1 && (cont[prop] as List<FieldType>)?.splice(ind, 1);
});
- lastValue = ObjectField.MakeCopy((container as any)[prop as any]);
+ lastValue = ObjectField.MakeCopy(contList);
}),
prop: 'add ' + (diff.items?.length ?? 0) + ' items to list',
},
@@ -420,48 +437,53 @@ export function containedFieldChangedHandler(container: List<FieldType> | Doc, p
UndoManager.AddEvent(
{
redo: action(() => {
+ const contList = cont[prop] as List<FieldType>;
// console.log('redo $rem: ' + prop, diff.items); // bcz: uncomment to log undo
- diff.items?.forEach((item: any) => {
+ diff.items?.forEach(item => {
const ind =
item instanceof SchemaHeaderField //
- ? (container as any)[prop as any]?.findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading)
- : (container as any)[prop as any]?.indexOf(item.value ?? item);
- ind !== undefined && ind !== -1 && (container as any)[prop as any]?.splice(ind, 1);
+ ? contList?.findIndex(ele => ele instanceof SchemaHeaderField && ele.heading === item.heading)
+ : contList?.indexOf(item.value ?? item);
+ ind !== undefined && ind !== -1 && contList?.splice(ind, 1);
});
- lastValue = ObjectField.MakeCopy((container as any)[prop as any]);
+ lastValue = ObjectField.MakeCopy(contList);
}),
undo: () => {
+ const contList = cont[prop] as List<FieldType>;
+ const prevList = prevValue as List<FieldType>;
// console.log('undo $rem: ' + prop, diff.items); // bcz: uncomment to log undo
- diff.items?.forEach((item: any) => {
+ diff.items?.forEach(item => {
if (item instanceof SchemaHeaderField) {
- const ind = (prevValue as List<any>).findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading);
- ind !== -1 && (container as any)[prop as any].findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading) === -1 && (container as any)[prop as any].splice(ind, 0, item);
+ const ind = prevList.findIndex(ele => ele instanceof SchemaHeaderField && ele.heading === item.heading);
+ ind !== -1 && contList.findIndex(ele => ele instanceof SchemaHeaderField && ele.heading === item.heading) === -1 && contList.splice(ind, 0, item);
} else {
- const ind = (prevValue as List<any>).indexOf(item.value ?? item);
- ind !== -1 && (container as any)[prop as any].indexOf(item.value ?? item) === -1 && (container as any)[prop as any].splice(ind, 0, item);
+ const ind = prevList.indexOf(item.value ?? item);
+ ind !== -1 && contList.indexOf(item.value ?? item) === -1 && (cont[prop] as List<FieldType>).splice(ind, 0, item);
}
});
- lastValue = ObjectField.MakeCopy((container as any)[prop as any]);
+ lastValue = ObjectField.MakeCopy(contList);
},
- prop: 'remove ' + (diff.items?.length ?? 0) + ' items from list(' + ((container as any)?.title ?? '') + ':' + prop + ')',
+ prop: 'remove ' + (diff.items?.length ?? 0) + ' items from list(' + (cont?.title ?? '') + ':' + prop + ')',
},
diff?.items
);
} else {
const setFieldVal = (val: FieldType | undefined) => {
- container instanceof Doc ? (container[prop as string] = val) : (container[prop as number] = val as FieldType);
+ container instanceof Doc ? (container[prop] = val) : (container[prop as number] = val as FieldType);
};
UndoManager.AddEvent(
{
redo: () => {
// console.log('redo list: ' + prop, fieldVal()); // bcz: uncomment to log undo
- setFieldVal(newValue instanceof ObjectField ? ObjectField.MakeCopy(newValue) : undefined);
- lastValue = ObjectField.MakeCopy((container as any)[prop as any]);
+ setFieldVal(ObjectField.MakeCopy(newValue));
+ const containerProp = cont[prop];
+ lastValue = containerProp instanceof ObjectField && ObjectField.MakeCopy(containerProp);
},
undo: () => {
// console.log('undo list: ' + prop, fieldVal()); // bcz: uncomment to log undo
- setFieldVal(prevValue instanceof ObjectField ? ObjectField.MakeCopy(prevValue) : undefined);
- lastValue = ObjectField.MakeCopy((container as any)[prop as any]);
+ setFieldVal(ObjectField.MakeCopy(prevValue));
+ const containerProp = cont[prop];
+ lastValue = containerProp instanceof ObjectField && ObjectField.MakeCopy(containerProp);
},
prop: 'set list field',
},