Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate nested properties (Array & Object) #18

Open
A-312 opened this issue Apr 11, 2020 · 3 comments
Open

Validate nested properties (Array & Object) #18

A-312 opened this issue Apr 11, 2020 · 3 comments
Labels
enhancement New feature or request

Comments

@A-312
Copy link
Owner

A-312 commented Apr 11, 2020

Follow this standard for Object should be a good thing.

'+ Support array nested properties

@A-312 A-312 changed the title Validate nested properties (Array or Object) Validate nested properties (Array & Object) Apr 11, 2020
@A-312 A-312 added the enhancement New feature or request label Apr 11, 2020
@michaelrommel
Copy link

Dear A-312,

I saw that you are struggling with the same issues as myself and the lack of progress in node-convict.

My issue was that I wanted to use a config file with a non-fixed number of subkeys underneath acmeProviders. I tried both variants Arrays and Objects, but am struggling and wondered, whether you have a good strategy for that usecase:

{
  "pidfilename": "cra-api.pid",
  "pidpath": "/run/",
  "topic": {
    "listentopic": "new-order",
    "informtopic": "update-order"
  },
  "acmeProviders": [
    { "name": "providerA",
      "url": "https://server1/dir",
      "nameservers": ["192.168.1.1"],
      "pdnsapi": "http://192.168.1.1",
      "accountKey": "/conf/.creds_acme_providerA"
    },
    { "name": "providerB",
      "url": "letsencrypt.staging",
      "nameservers": ["192.168.2.2"],
      "pdnsapi": "http://192.168.2.2",
      "accountKey": "/conf/.creds_acme_providerB"
    },
    { "name": "providerC",
      "url": "https://server3.foo.bar.org/dir",
      "nameservers": ["192.168.3.3"],
      "pdnsapi": "http://192.168.3.3",
      "accountKey": "/conf/.creds_acme_providerC"
    }
  ]
}

This together with customFormats like this:

import acme from 'acme-client';
convict.addFormats({
  acmeUrl: {
    validate: function (x) {
      if (x === 'letsencrypt.staging' ||
          x === 'letsencrypt.production') {
        return true;
      }
      if (!validator.isURL(x, { require_tld: false })) {
        throw new Error('must be an URL');
      }
    },
    coerce: function (x) {
      switch (x) {
        case 'letsencrypt.staging':
          return acme.directory.letsencrypt.staging;
        case 'letsencrypt.production':
          return acme.directory.letsencrypt.production;
        default:
          return x.toString();
      }
    }
  },
  acmeProviderArray: {
    validate: function (x, schema) {
      if (!Array.isArray(x)) {
        throw new Error('must be an array');
      }
      for (const p of x) {
        convict(schema.children).load(p).validate();
      }
    },
    coerce: function (x, schema) {
      for (const p of x) {
        convict(schema.children).load(p).toString();
      }
    }
  }, ...

is actually working for validating the whole structure.

But what is missing is, that when the config file is loaded (before a call to .validate()) the coerce functions are basically skipped because in the code the custom converters call is skipped for arrays because of

 if (typeof v === 'string') {

So that means that my custom replacement of the string letsencrypt.staging with the value from the acme module is not working. It only works for validation or in the .toString() context.

Do you have some idea or want to implement coercion also for arrays and such?

Thanks,

Michael.

@A-312
Copy link
Owner Author

A-312 commented Aug 9, 2021

@michaelrommel
Copy link

Hi,
yeah, I tried something along these lines. As I said, the coerce method is not working properly, validate is working fine. I solved my use case now in another way, by not coercing, but by deriving another value which was previously set to null to a derived string, when I load the config file. So it is not encapsulated inside the schema and the addFormat code but in another place.
Thanks for your suggestion, though!
Have a good year!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants