| 20 | * Tracks custom metadata associated with a `FieldNode`. |
| 21 | */ |
| 22 | export class FieldMetadataState { |
| 23 | /** A map of all `MetadataKey` that have been defined for this field. */ |
| 24 | private readonly metadata = new Map<MetadataKey<unknown, unknown, unknown>, unknown>(); |
| 25 | |
| 26 | constructor(private readonly node: FieldNode) {} |
| 27 | |
| 28 | /** |
| 29 | * Force eager creation of managed keys, |
| 30 | * as managed keys have a `create` function that needs to run during construction. |
| 31 | */ |
| 32 | runMetadataCreateLifecycle(): void { |
| 33 | if (!this.node.logicNode.logic.hasMetadataKeys()) { |
| 34 | return; |
| 35 | } |
| 36 | |
| 37 | untracked(() => |
| 38 | runInInjectionContext(this.node.structure.injector, () => { |
| 39 | for (const key of this.node.logicNode.logic.getMetadataKeys()) { |
| 40 | if (key.create) { |
| 41 | const logic = this.node.logicNode.logic.getMetadata(key); |
| 42 | const result = key.create!( |
| 43 | this.node, |
| 44 | computed(() => logic.compute(this.node.context)), |
| 45 | ); |
| 46 | this.metadata.set(key, result); |
| 47 | } |
| 48 | } |
| 49 | }), |
| 50 | ); |
| 51 | } |
| 52 | |
| 53 | /** Gets the value of an `MetadataKey` for the field. */ |
| 54 | get<T>(key: MetadataKey<T, unknown, unknown>): T | undefined { |
| 55 | // We create non-managed metadata lazily, the first time they are accessed. |
| 56 | if (this.has(key)) { |
| 57 | if (!this.metadata.has(key)) { |
| 58 | if (key.create) { |
| 59 | throw new RuntimeError( |
| 60 | RuntimeErrorCode.MANAGED_METADATA_LAZY_CREATION, |
| 61 | ngDevMode && 'Managed metadata cannot be created lazily', |
| 62 | ); |
| 63 | } |
| 64 | const logic = this.node.logicNode.logic.getMetadata(key); |
| 65 | this.metadata.set( |
| 66 | key, |
| 67 | computed(() => logic.compute(this.node.context)), |
| 68 | ); |
| 69 | } |
| 70 | } |
| 71 | return this.metadata.get(key) as T | undefined; |
| 72 | } |
| 73 | |
| 74 | /** Checks whether the current metadata state has the given metadata key. */ |
| 75 | has(key: MetadataKey<any, any, any>): boolean { |
| 76 | // Metadata keys get added to the map lazily, on first access, |
| 77 | // so we can't rely on checking presence in the metadata map. |
| 78 | // Instead we check if there is any logic for the given metadata key. |
| 79 | return this.node.logicNode.logic.hasMetadata(key); |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…