diff --git a/readme.md b/readme.md index 2fa5737..622325b 100644 --- a/readme.md +++ b/readme.md @@ -64,9 +64,7 @@ Type: `object` [JSON Schema](https://json-schema.org) to validate your config data. -Under the hood, the JSON Schema validator [ajv](https://ajv.js.org/json-schema.html) is used to validate your config. We use [JSON Schema draft-2020-12](https://json-schema.org/draft/2020-12/release-notes) and support all validation keywords and formats. - -You should define your schema as an object where each key is the name of your data's property and each value is a JSON schema used to validate that property. See more [here](https://json-schema.org/understanding-json-schema/reference/object.html#properties). +This will be the [`properties`](https://json-schema.org/understanding-json-schema/reference/object.html#properties) object of the JSON schema. That is, define `schema` as an object where each key is the name of your data's property and each value is a JSON schema used to validate that property. Example: @@ -100,6 +98,53 @@ config.set('foo', '1'); **Note:** The `default` value will be overwritten by the `defaults` option if set. +#### rootSchema + +Type: `object` + +Top-level properties for the schema, excluding `properties` field. + +Example: + +```js +import Conf from 'conf'; + +const store = new Conf({ + projectName: 'foo', + schema: { /* … */ }, + rootSchema: { + additionalProperties: false + } +}); +``` + +#### ajvOptions + +Type: `object` + +[Options passed to AJV](https://ajv.js.org/options.html). + +Under the hood, the JSON Schema validator [ajv](https://ajv.js.org/json-schema.html) is used to validate your config. We use [JSON Schema draft-2020-12](https://json-schema.org/draft/2020-12/release-notes) and support all validation keywords and formats. + +**Note:** By default, `allErrors` and `useDefaults` are both set to `true`, but can be overridden. + +Example: + +```js +import Conf from 'conf'; + +const store = new Conf({ + projectName: 'foo', + schema: { /* … */ }, + rootSchema: { + additionalProperties: false + }, + ajvOptions: { + removeAdditional: true + } +}); +``` + #### migrations Type: `object` diff --git a/source/index.ts b/source/index.ts index cc54804..c00bb28 100644 --- a/source/index.ts +++ b/source/index.ts @@ -89,25 +89,27 @@ export default class Conf = Record> = { @@ -13,9 +14,7 @@ export type Options> = { /** [JSON Schema](https://json-schema.org) to validate your config data. - Under the hood, the JSON Schema validator [ajv](https://github.com/epoberezkin/ajv) is used to validate your config. We use [JSON Schema draft-07](https://json-schema.org/latest/json-schema-validation.html) and support all [validation keywords](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md) and [formats](https://github.com/epoberezkin/ajv#formats). - - You should define your schema as an object where each key is the name of your data's property and each value is a JSON schema used to validate that property. See more [here](https://json-schema.org/understanding-json-schema/reference/object.html#properties). + This will be the [`properties`](https://json-schema.org/understanding-json-schema/reference/object.html#properties) object of the JSON schema. That is, define `schema` as an object where each key is the name of your data's property and each value is a JSON schema used to validate that property. @example ``` @@ -50,6 +49,49 @@ export type Options> = { */ schema?: Schema; + /** + Top-level properties for the schema, excluding `properties` field. + + @example + ``` + import Conf from 'conf'; + + const store = new Conf({ + projectName: 'foo', + schema: {}, + rootSchema: { + additionalProperties: false + } + }); + ``` + */ + rootSchema?: Omit; + + /** + [Options passed to AJV](https://ajv.js.org/options.html). + + Under the hood, the JSON Schema validator [ajv](https://ajv.js.org/json-schema.html) is used to validate your config. We use [JSON Schema draft-2020-12](https://json-schema.org/draft/2020-12/release-notes) and support all validation keywords and formats. + + **Note:** By default, `allErrors` and `useDefaults` are both set to `true`, but can be overridden. + + @example + ``` + import Conf from 'conf'; + + const store = new Conf({ + projectName: 'foo', + schema: {}, + rootSchema: { + additionalProperties: false + }, + ajvOptions: { + removeAdditional: true + } + }); + ``` + */ + ajvOptions?: AjvOptions; + /** Name of the config file (without extension). @@ -259,3 +301,5 @@ export type OnDidChangeCallback = (newValue?: T, oldValue?: T) => void; export type OnDidAnyChangeCallback = (newValue?: Readonly, oldValue?: Readonly) => void; export type Unsubscribe = () => void; + +export type {CurrentOptions as AjvOptions} from 'ajv/dist/core.js'; diff --git a/test/index.ts b/test/index.ts index 22a3a8a..008f847 100644 --- a/test/index.ts +++ b/test/index.ts @@ -787,6 +787,32 @@ test('schema - validate Conf default', t => { }, {message: 'Config schema violation: `foo` must be string'}); }); +test('schema - validate rootSchema', t => { + t.throws(() => { + const config = new Conf({ + cwd: temporaryDirectory(), + rootSchema: { + additionalProperties: false, + }, + }); + config.set('foo', 'bar'); + }, {message: 'Config schema violation: `` must NOT have additional properties'}); +}); + +test('AJV - validate AJV options', t => { + const config = new Conf({ + cwd: temporaryDirectory(), + ajvOptions: { + removeAdditional: true, + }, + rootSchema: { + additionalProperties: false, + }, + }); + config.set('foo', 'bar'); + t.is(config.get('foo'), undefined); +}); + test('.get() - without dot notation', t => { t.is(t.context.configWithoutDotNotation.get('foo'), undefined); t.is(t.context.configWithoutDotNotation.get('foo', '🐴'), '🐴');