Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 148x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 148x 148x 148x 12x 12x 12x 1x 1x 12x 11x 11x 12x 14x 14x 14x 17x 14x 17x 3x 3x 3x 3x 3x 3x 3x 12x 11x 308x 304x 157x 308x 151x 151x 308x 39x 56x 56x 308x 308x 27x 27x 17x 17x 308x 68x 2x 2x 68x 2x 2x 2x 2x 2x 308x 308x 258x 258x 258x 11x 11x 11x 11x 11x 11x 11x 11x 148x 148x 148x 148x 148x 148x 148x 158x 158x 158x 158x 158x 148x 148x 161x 161x 161x 161x 151x 161x 155x 155x 148x 148x | import { produce } from 'immer';
import { FlowDefinition } from '../store/flow-definition';
import { normalizeUuid } from '../store/identity';
export interface FlowDependency {
type: string;
name: string;
uuid?: string;
key?: string;
missing?: boolean;
}
const dependencyIdentity = (dependency: FlowDependency): string | null => {
const identity = dependency.uuid || dependency.key;
return identity ? `${dependency.type}:${identity}` : null;
};
/**
* Returns a definition whose embedded reference names have been replaced by
* the canonical dependency names supplied by the server. References with a
* UUID are safe to recognize anywhere in the definition because flow-owned
* UUIDs don't appear in its dependency list. Field references use keys and
* only occur under a `field` property; scoping keyed matching there avoids
* confusing a field key with a result name or another keyed structure.
*/
export const resolveDependencyNames = (
definition: FlowDefinition,
dependencies: FlowDependency[] = []
): FlowDefinition => {
if (!definition || dependencies.length === 0) {
return definition;
}
const namesByUuid = new Map<string, string>();
const fieldNamesByKey = new Map<string, string>();
for (const dependency of dependencies) {
if (dependency.uuid && dependency.name != null) {
// normalized on both set and lookup so a reference embedded in the
// definition in a non-canonical form still matches, the same way the
// store's asset cache resolves it
namesByUuid.set(normalizeUuid(dependency.uuid), dependency.name);
} else if (
dependency.type === 'field' &&
dependency.key &&
dependency.name != null
) {
fieldNamesByKey.set(dependency.key, dependency.name);
}
}
return produce(definition, (draft: any) => {
const visit = (value: any, propertyName?: string) => {
if (!value || typeof value !== 'object') {
return;
}
if (Array.isArray(value)) {
// keep the owning property name so `field` scoping still applies to
// references nested in an array
value.forEach((item) => visit(item, propertyName));
return;
}
if (typeof value.uuid === 'string' && 'name' in value) {
const canonical = namesByUuid.get(normalizeUuid(value.uuid));
if (canonical != null) {
value.name = canonical;
}
} else if (
propertyName === 'field' &&
typeof value.key === 'string' &&
'name' in value
) {
const canonical = fieldNamesByKey.get(value.key);
if (canonical != null) {
value.name = canonical;
}
}
for (const [key, child] of Object.entries(value)) {
visit(child, key);
}
};
visit(draft);
});
};
/**
* Replaces every matching dependency whose canonical name has changed. Assets
* the loaded flow isn't interested in are ignored.
*/
export const replaceDependencies = (
dependencies: FlowDependency[] = [],
changed: FlowDependency[]
): FlowDependency[] | null => {
const changedByIdentity = new Map<string, FlowDependency>();
for (const dependency of changed) {
const identity = dependencyIdentity(dependency);
if (identity) {
changedByIdentity.set(identity, dependency);
}
}
let replaced = false;
const updated = dependencies.map((dependency) => {
const identity = dependencyIdentity(dependency);
const replacement = identity ? changedByIdentity.get(identity) : null;
if (!replacement || replacement.name === dependency.name) {
return dependency;
}
replaced = true;
return { ...dependency, name: replacement.name };
});
return replaced ? updated : null;
};
|