| 527 | * @returns {{ problem?: LocalProblem, object?: ObjectConfiguration, property?: Property, value?: EXPECTED_OBJECT | EXPECTED_ANY[] }} problem or object with property and value |
| 528 | */ |
| 529 | const getObjectAndProperty = (config, schemaPath, index = 0) => { |
| 530 | if (!schemaPath) return { value: config }; |
| 531 | const parts = schemaPath.split("."); |
| 532 | const property = /** @type {string} */ (parts.pop()); |
| 533 | let current = config; |
| 534 | let i = 0; |
| 535 | for (const part of parts) { |
| 536 | const isArray = part.endsWith("[]"); |
| 537 | const name = isArray ? part.slice(0, -2) : part; |
| 538 | if (isUnsafeKey(name)) { |
| 539 | return { |
| 540 | problem: { |
| 541 | type: "prototype-pollution-in-path", |
| 542 | path: parts.slice(0, i).join(".") |
| 543 | } |
| 544 | }; |
| 545 | } |
| 546 | let value = current[name]; |
| 547 | if (isArray) { |
| 548 | if (value === undefined) { |
| 549 | value = {}; |
| 550 | current[name] = [...Array.from({ length: index }), value]; |
| 551 | cliAddedItems.set(current[name], index + 1); |
| 552 | } else if (!Array.isArray(value)) { |
| 553 | return { |
| 554 | problem: { |
| 555 | type: "unexpected-non-array-in-path", |
| 556 | path: parts.slice(0, i).join(".") |
| 557 | } |
| 558 | }; |
| 559 | } else { |
| 560 | let addedItems = cliAddedItems.get(value) || 0; |
| 561 | while (addedItems <= index) { |
| 562 | value.push(undefined); |
| 563 | addedItems++; |
| 564 | } |
| 565 | cliAddedItems.set(value, addedItems); |
| 566 | const x = value.length - addedItems + index; |
| 567 | if (value[x] === undefined) { |
| 568 | value[x] = {}; |
| 569 | } else if (value[x] === null || typeof value[x] !== "object") { |
| 570 | return { |
| 571 | problem: { |
| 572 | type: "unexpected-non-object-in-path", |
| 573 | path: parts.slice(0, i).join(".") |
| 574 | } |
| 575 | }; |
| 576 | } |
| 577 | value = value[x]; |
| 578 | } |
| 579 | } else if (value === undefined) { |
| 580 | value = current[name] = {}; |
| 581 | } else if (value === null || typeof value !== "object") { |
| 582 | return { |
| 583 | problem: { |
| 584 | type: "unexpected-non-object-in-path", |
| 585 | path: parts.slice(0, i).join(".") |
| 586 | } |