(obj)
| 148 | * @returns {ParsedObject<T>} parsed object |
| 149 | */ |
| 150 | const parseObject = (obj) => { |
| 151 | /** @type {ParsedObjectStatic<T>} */ |
| 152 | const info = new Map(); |
| 153 | /** @type {ParsedObjectDynamic<T> | undefined} */ |
| 154 | let dynamicInfo; |
| 155 | /** |
| 156 | * Returns object parsed property entry. |
| 157 | * @param {keyof T} p path |
| 158 | * @returns {Partial<ObjectParsedPropertyEntry<T>>} object parsed property entry |
| 159 | */ |
| 160 | const getInfo = (p) => { |
| 161 | const entry = info.get(p); |
| 162 | if (entry !== undefined) return entry; |
| 163 | const newEntry = { |
| 164 | base: undefined, |
| 165 | byProperty: undefined, |
| 166 | byValues: undefined |
| 167 | }; |
| 168 | info.set(p, newEntry); |
| 169 | return newEntry; |
| 170 | }; |
| 171 | for (const key_ of Object.keys(obj)) { |
| 172 | const key = /** @type {keyof T} */ (key_); |
| 173 | if (typeof key === "string" && key.startsWith("by")) { |
| 174 | const byProperty = key; |
| 175 | const byObj = /** @type {ByObject} */ (obj[byProperty]); |
| 176 | if (typeof byObj === "object") { |
| 177 | for (const byValue of Object.keys(byObj)) { |
| 178 | const obj = byObj[/** @type {keyof (keyof T)} */ (byValue)]; |
| 179 | for (const key of Object.keys(obj)) { |
| 180 | const entry = getInfo(/** @type {keyof T} */ (key)); |
| 181 | if (entry.byProperty === undefined) { |
| 182 | entry.byProperty = /** @type {`by${string}`} */ (byProperty); |
| 183 | entry.byValues = new Map(); |
| 184 | } else if (entry.byProperty !== byProperty) { |
| 185 | throw new Error( |
| 186 | `${/** @type {string} */ (byProperty)} and ${entry.byProperty} for a single property is not supported` |
| 187 | ); |
| 188 | } |
| 189 | /** @type {ByValues} */ |
| 190 | (entry.byValues).set(byValue, obj[key]); |
| 191 | if (byValue === "default") { |
| 192 | for (const otherByValue of Object.keys(byObj)) { |
| 193 | if ( |
| 194 | !( |
| 195 | /** @type {ByValues} */ |
| 196 | (entry.byValues).has(otherByValue) |
| 197 | ) |
| 198 | ) { |
| 199 | /** @type {ByValues} */ |
| 200 | (entry.byValues).set(otherByValue, undefined); |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | } |
| 206 | } else if (typeof byObj === "function") { |
| 207 | if (dynamicInfo === undefined) { |
no test coverage detected