@versionzero/schema 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versionzero/schema",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "A composable schema library that supports asynchronous processing",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -51,6 +51,8 @@ export function registerCoreLibrary(libraryFn) {
51
51
  /** @import { SchemaData } from './types.js' */
52
52
  /** @import { ValueProcessorDefinition, ValueProcessorSpec, ValueProcessorBuilder, ValueProcessorFunction, ValueProcessorArgs, ValueProcessorParameter, KeywordValueProcessorSpec } from './value-processor/value-processor.js' */
53
53
 
54
+ /** @typedef {{name:string, namespace?:string, schema:Schema}} RegisteredSchemaInfo */
55
+
54
56
  /**
55
57
  * The SchemaResolver uses its internal registries of named schemas and value processor keywords to
56
58
  * convert Schemas containing unresolved references into resolved Schemas that are fully self-contained.
@@ -58,7 +60,7 @@ export function registerCoreLibrary(libraryFn) {
58
60
  export class SchemaResolver
59
61
  {
60
62
  /**
61
- * @type {Map<string,Schema>}
63
+ * @type {Map<string,RegisteredSchemaInfo>}
62
64
  */
63
65
  #schemaMap = new Map();
64
66
  /**
@@ -85,7 +87,7 @@ export class SchemaResolver
85
87
  throw new ResolverError(`Registry can only store Schema instances`);
86
88
  }
87
89
  const registryName = toKebabCase(name);
88
- this.#schemaMap.set(registryName, schema);
90
+ this.#schemaMap.set(registryName, {name: registryName, schema});
89
91
  return this;
90
92
  }
91
93
 
@@ -96,11 +98,11 @@ export class SchemaResolver
96
98
  */
97
99
  getSchema(name) {
98
100
  const registryName = toKebabCase(name);
99
- const schema = this.#schemaMap.get(registryName);
100
- if (!schema) {
101
+ const schemaInfo = this.#schemaMap.get(registryName);
102
+ if (!schemaInfo) {
101
103
  throw new ResolverError(`Unable to resolve "${name}"`);
102
104
  }
103
- return schema;
105
+ return schemaInfo.schema;
104
106
  }
105
107
 
106
108
  /**
@@ -113,6 +115,14 @@ export class SchemaResolver
113
115
  return this.#schemaMap.has(registryName);
114
116
  }
115
117
 
118
+ /**
119
+ * return all registered schemas
120
+ * @returns {RegisteredSchemaInfo[]}
121
+ */
122
+ listRegisteredSchemas() {
123
+ return [...this.#schemaMap.values()];
124
+ }
125
+
116
126
  /**
117
127
  * Register a value processor definition
118
128
  * @param {ValueProcessorDefinition} definition
@@ -121,20 +131,24 @@ export class SchemaResolver
121
131
  registerValueProcessorDefinition(definition) {
122
132
  const {keyword, process, description, build} = definition;
123
133
 
124
- if (!keyword) {
134
+ if (!keyword || typeof keyword !== 'string') {
125
135
  throw new ResolverError('Missing keyword in processor definition');
126
136
  }
127
137
 
128
138
  if (process && build) {
129
- throw new ResolverError(`Processor definition for '${keyword}' cannot define both process and build functions`);
139
+ throw new ResolverError(`Processor definition for '$${keyword}' cannot define both process and build functions`);
130
140
  }
131
141
 
132
142
  if (!process && !build) {
133
- throw new ResolverError(`Processor definition for '${keyword}' must have define a process or build function`);
143
+ throw new ResolverError(`Processor definition for '$${keyword}' must have define a process or build function`);
134
144
  }
135
145
 
136
146
  if (description && typeof description !== 'string') {
137
- throw new ResolverError(`Processor definition description for '${keyword}' must be a string`);
147
+ throw new ResolverError(`Processor definition description for '$${keyword}' must be a string`);
148
+ }
149
+
150
+ if (this.#constantKeywordProcessors[`${keyword}`]) {
151
+ throw new ResolverError(`Processor keyword conflict with builtin literal '$${keyword}'`)
138
152
  }
139
153
 
140
154
  this.#processorMap.set(keyword, definition);
@@ -176,6 +190,24 @@ export class SchemaResolver
176
190
  });
177
191
  }
178
192
 
193
+ /**
194
+ * List all registered value processors (and reserved builtins)
195
+ *
196
+ * @returns {ValueProcessorDefinition[]}
197
+ */
198
+ listValueProcessorDefinitions() {
199
+
200
+ return [
201
+ ...Object.entries(this.#constantKeywordProcessors).map(([k,v]) => ({
202
+ keyword: k,
203
+ build: (() => v),
204
+ spec: `$${k}`,
205
+ reserved: true
206
+ })),
207
+ ...this.#processorMap.values()
208
+ ];
209
+ }
210
+
179
211
 
180
212
  /**
181
213
  * Load a library of schemas and/or value processors.
@@ -209,13 +241,11 @@ export class SchemaResolver
209
241
 
210
242
  }
211
243
 
212
-
213
-
214
- _constantKeywords = {
215
- $null: NULL_EXECUTOR,
216
- $undefined: UNDEFINED_EXECUTOR,
217
- $true: TRUE_EXECUTOR,
218
- $false: FALSE_EXECUTOR
244
+ #constantKeywordProcessors = {
245
+ 'null': new ComposedValueProcessor(NULL_EXECUTOR, '$null'),
246
+ 'undefined': new ComposedValueProcessor(UNDEFINED_EXECUTOR, '$undefined'),
247
+ 'true': new ComposedValueProcessor(TRUE_EXECUTOR, '$true'),
248
+ 'false': new ComposedValueProcessor(FALSE_EXECUTOR, '$false')
219
249
  }
220
250
 
221
251
  /**
@@ -230,8 +260,8 @@ export class SchemaResolver
230
260
  }
231
261
  const [keyword, rawArgs] = extractKeywordValueProcessorSpec(spec);
232
262
 
233
- if (this._constantKeywords[spec]) {
234
- return new ComposedValueProcessor(this._constantKeywords[spec], spec);
263
+ if (this.#constantKeywordProcessors[keyword]) {
264
+ return this.#constantKeywordProcessors[keyword];
235
265
  }
236
266
 
237
267
  if (keyword === 'literal') {
@@ -44,11 +44,13 @@ import { SchemaLocation } from '../schema-location.js';
44
44
  /**
45
45
  * @typedef {object} ValueProcessorDefinition
46
46
  * @property {string} keyword
47
+ * @property {string} [namespace]
47
48
  * @property {ValueProcessorFunction} [process]
48
49
  * @property {ValueProcessorParameter[]} [parameters]
49
50
  * @property {string} [description]
50
51
  * @property {ValueProcessorBuilder} [build]
51
52
  * @property {ValueProcessorDescriber} [describe]
53
+ * @property {boolean} [reserved]
52
54
  */
53
55
 
54
56
 
@@ -9,6 +9,7 @@ export function registerCoreLibrary(libraryFn: (resolver: SchemaResolver, option
9
9
  /** @typedef {{name:string, [key:string]:any}} SchemaResolverLibraryOptions */
10
10
  /** @import { SchemaData } from './types.js' */
11
11
  /** @import { ValueProcessorDefinition, ValueProcessorSpec, ValueProcessorBuilder, ValueProcessorFunction, ValueProcessorArgs, ValueProcessorParameter, KeywordValueProcessorSpec } from './value-processor/value-processor.js' */
12
+ /** @typedef {{name:string, namespace?:string, schema:Schema}} RegisteredSchemaInfo */
12
13
  /**
13
14
  * The SchemaResolver uses its internal registries of named schemas and value processor keywords to
14
15
  * convert Schemas containing unresolved references into resolved Schemas that are fully self-contained.
@@ -33,6 +34,11 @@ export class SchemaResolver {
33
34
  * @returns {boolean}
34
35
  */
35
36
  hasSchema(name: string): boolean;
37
+ /**
38
+ * return all registered schemas
39
+ * @returns {RegisteredSchemaInfo[]}
40
+ */
41
+ listRegisteredSchemas(): RegisteredSchemaInfo[];
36
42
  /**
37
43
  * Register a value processor definition
38
44
  * @param {ValueProcessorDefinition} definition
@@ -54,6 +60,12 @@ export class SchemaResolver {
54
60
  * @returns {SchemaResolver}
55
61
  */
56
62
  registerValueProcessorBuilder(keyword: string, build: ValueProcessorBuilder): SchemaResolver;
63
+ /**
64
+ * List all registered value processors (and reserved builtins)
65
+ *
66
+ * @returns {ValueProcessorDefinition[]}
67
+ */
68
+ listValueProcessorDefinitions(): ValueProcessorDefinition[];
57
69
  /**
58
70
  * Load a library of schemas and/or value processors.
59
71
  *
@@ -68,12 +80,6 @@ export class SchemaResolver {
68
80
  * @returns {Promise<void>}
69
81
  */
70
82
  use(libraryFunction: (resolver: SchemaResolver, options: object) => Promise<void> | void, options?: object): Promise<void>;
71
- _constantKeywords: {
72
- $null: ConstantExecutor;
73
- $undefined: ConstantExecutor;
74
- $true: ConstantExecutor;
75
- $false: ConstantExecutor;
76
- };
77
83
  /**
78
84
  * @param {SchemaCompiler} compiler
79
85
  * @param {KeywordValueProcessorSpec} spec
@@ -131,11 +137,15 @@ export type SchemaResolverLibraryOptions = {
131
137
  name: string;
132
138
  [key: string]: any;
133
139
  };
140
+ export type RegisteredSchemaInfo = {
141
+ name: string;
142
+ namespace?: string;
143
+ schema: Schema;
144
+ };
134
145
  import { Schema } from './schema.js';
135
146
  import type { ValueProcessorDefinition } from './value-processor/value-processor.js';
136
147
  import type { ValueProcessorFunction } from './value-processor/value-processor.js';
137
148
  import type { ValueProcessorBuilder } from './value-processor/value-processor.js';
138
- import { ConstantExecutor } from './executor/executor.js';
139
149
  import { SchemaCompiler } from './schema-compiler.js';
140
150
  import type { KeywordValueProcessorSpec } from './value-processor/value-processor.js';
141
151
  import { ValueProcessor } from './value-processor/value-processor.js';
@@ -31,11 +31,13 @@
31
31
  /**
32
32
  * @typedef {object} ValueProcessorDefinition
33
33
  * @property {string} keyword
34
+ * @property {string} [namespace]
34
35
  * @property {ValueProcessorFunction} [process]
35
36
  * @property {ValueProcessorParameter[]} [parameters]
36
37
  * @property {string} [description]
37
38
  * @property {ValueProcessorBuilder} [build]
38
39
  * @property {ValueProcessorDescriber} [describe]
40
+ * @property {boolean} [reserved]
39
41
  */
40
42
  /**
41
43
  * @augments {Executor<any>}
@@ -82,11 +84,13 @@ export type ValueProcessorDescriber = (args: {
82
84
  } | ValueProcessor[] | undefined) => string | undefined;
83
85
  export type ValueProcessorDefinition = {
84
86
  keyword: string;
87
+ namespace?: string | undefined;
85
88
  process?: ValueProcessorFunction | undefined;
86
89
  parameters?: ValueProcessorParameter[] | undefined;
87
90
  description?: string | undefined;
88
91
  build?: ValueProcessorBuilder | undefined;
89
92
  describe?: ValueProcessorDescriber | undefined;
93
+ reserved?: boolean | undefined;
90
94
  };
91
95
  import { Executor } from '../executor/executor.js';
92
96
  import { SchemaLocation } from '../schema-location.js';