yaml icon indicating copy to clipboard operation
yaml copied to clipboard

Resolve aliases when using `getIn`

Open remcohaszing opened this issue 2 years ago • 3 comments

Is your feature request related to a problem? Please describe.

I have a situation where I have a list of paths from a YAML document. I need to map these paths to the location in the document source code. This can be done using the following code:

import { parseDocument } from 'yaml';

const yaml = `
foo: &anchor
  bar: 1
fooz:
  baz: *anchor
`;

const doc = parseDocument(yaml, {});
console.dir(doc.getIn(['foo', 'bar'], true));
console.dir(doc.getIn(['fooz', 'baz'], true));
console.dir(doc.getIn(['fooz', 'baz', 'bar'], true));

Unfortunately the last statement doesn’t work, because getIn doesn’t resolve aliases.

Describe the solution you'd like

I would love for getIn to be able to resolve aliases.

Describe alternatives you've considered

Possibly new methods can be introduced: resolve(key, keepScalar?) and resolveIn(path, keepScalar?). This would avoid breaking changes in get and getIn respectively.

It’s possible to do this manually, but I think it’s a useful feature for this library to support out of the box.

Additional context

We use this together with the jsonschema package. Apart from this issue, it’s working amazing!

remcohaszing avatar May 02 '22 15:05 remcohaszing

I like this idea. I'd really rather not add any new methods specifically for it, though.

I'm rather tempted to say that going from doc.getIn(['fooz', 'baz', 'bar'], true) returning undefined to indicate not finding the value, to it returning the Scalar { value: 1 } should not count as a breaking change: Really it's just an improvement in the search method.

Or is there a potential real-world use where this might break something?

eemeli avatar May 02 '22 19:05 eemeli

I think whether or not this is a breaking change really depends on how you look at it. For me this wouldn’t break anything, nor can I think of any potential real-world use cases that could break, but it is a change of behaviour.

Another alternative would be to accept an options object:

interface GetOptions {
  keepScalar?: boolean;
  resolveAnchors?: boolean;
}

doc.getIn(path: Iterable<unknown>, options?: boolean | GetOptions)

Passing true would be equivalent to { keepScalar: true }


I think it also makes sense to resolve the alias node itself if that would be the result. So given the example above, the following two lines would be equivalent:

console.dir(doc.getIn(['foo'], true));
console.dir(doc.getIn(['fooz', 'baz'], true));

remcohaszing avatar May 03 '22 08:05 remcohaszing

I’ll gladly provide a pull request if we reach concensus about the options format. :)

remcohaszing avatar May 25 '22 11:05 remcohaszing