schema-markdown 1.1.1 → 1.1.5

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/README.md CHANGED
@@ -28,9 +28,10 @@ To schema-validate an object, first parse its *Schema Markdown* using the
28
28
  class:
29
29
 
30
30
  ``` javascript
31
- import * as smd from 'schema_markdown/index.js';
31
+ import {SchemaMarkdownParser} from 'schema-markdown/parser.js';
32
+ import {validateType} from 'schema-markdown/schema.js';
32
33
 
33
- const parser = new smd.SchemaMarkdownParser(`\
34
+ const parser = new SchemaMarkdownParser(`\
34
35
  # An aggregation function
35
36
  enum Aggregation
36
37
  Average
@@ -51,7 +52,7 @@ Then, validate an object using the
51
52
  function:
52
53
 
53
54
  ``` javascript
54
- const obj = smd.validateType(parser.types, 'Operation', {
55
+ const obj = validateType(parser.types, 'Operation', {
55
56
  'numbers': [1, 2, '3', 4]
56
57
  });
57
58
  console.assert(obj.numbers[2] === 3);
@@ -62,7 +63,7 @@ Validation fails if the object does not match the schema:
62
63
 
63
64
  ``` javascript
64
65
  try {
65
- smd.validateType(parser.types, 'Operation', {
66
+ validateType(parser.types, 'Operation', {
66
67
  'numbers': [1, 2, 'asdf', 4]
67
68
  });
68
69
  } catch ({message}) {
@@ -74,7 +75,7 @@ Validation also fails if a member contraint is violated:
74
75
 
75
76
  ``` javascript
76
77
  try {
77
- smd.validateType(parser.types, 'Operation', {
78
+ validateType(parser.types, 'Operation', {
78
79
  'numbers': []
79
80
  });
80
81
  } catch ({message}) {
package/lib/parser.js CHANGED
@@ -43,7 +43,7 @@ const RE_PART_TYPEDEF =
43
43
  const RE_TYPEDEF = new RegExp('^typedef\\s+' + RE_PART_TYPEDEF + '\\s*$');
44
44
  const RE_MEMBER = new RegExp('^\\s+(?<optional>optional\\s+)?' + RE_PART_TYPEDEF + '\\s*$');
45
45
  const RE_VALUE = new RegExp('^\\s+(?<id>' + RE_PART_ID + ')\\s*$');
46
- const RE_VALUE_QUOTED = new RegExp('^\\s+"(?<id>' + RE_PART_ID + '.*?)"\\s*$');
46
+ const RE_VALUE_QUOTED = /^\s+"(?<id>.*?)"\s*$/;
47
47
  const RE_URL = /^\s+(?<method>[A-Za-z]+|\*)(?:\s+(?<path>\/[^\s]*))?/;
48
48
 
49
49
 
@@ -321,38 +321,46 @@ export class SchemaMarkdownParser {
321
321
  }
322
322
 
323
323
  // Match syntax
324
- let [matchName, match] = ['comment', line.match(RE_COMMENT)];
324
+ let matchName = 'comment';
325
+ let match = line.match(RE_COMMENT);
325
326
  if (match === null) {
326
- [matchName, match] = ['group', line.match(RE_GROUP)];
327
+ matchName = 'group';
328
+ match = line.match(RE_GROUP);
327
329
  }
328
330
  if (match === null) {
329
- [matchName, match] = ['action', line.match(RE_ACTION)];
331
+ matchName = 'action';
332
+ match = line.match(RE_ACTION);
330
333
  }
331
334
  if (match === null) {
332
- [matchName, match] = ['definition', line.match(RE_DEFINITION)];
335
+ matchName = 'definition';
336
+ match = line.match(RE_DEFINITION);
333
337
  }
334
338
  if (match === null && action !== null) {
335
- [matchName, match] = ['section', line.match(RE_SECTION)];
339
+ matchName = 'section';
340
+ match = line.match(RE_SECTION);
336
341
  }
337
342
  if (match === null && action !== null) {
338
- [matchName, match] = ['section_plain', line.match(RE_SECTION_PLAIN)];
343
+ matchName = 'section_plain';
344
+ match = line.match(RE_SECTION_PLAIN);
339
345
  }
340
346
  if (match === null && userType !== null && 'enum' in userType) {
341
- const matchValue = line.match(RE_VALUE);
342
- if (matchValue !== null) {
343
- [matchName, match] = ['value', matchValue];
344
- } else {
345
- [matchName, match] = ['value', line.match(RE_VALUE_QUOTED)];
347
+ matchName = 'value';
348
+ match = line.match(RE_VALUE);
349
+ if (match === null) {
350
+ match = line.match(RE_VALUE_QUOTED);
346
351
  }
347
352
  }
348
353
  if (match === null && userType !== null && 'struct' in userType) {
349
- [matchName, match] = ['member', line.match(RE_MEMBER)];
354
+ matchName = 'member';
355
+ match = line.match(RE_MEMBER);
350
356
  }
351
357
  if (match === null && urls !== null) {
352
- [matchName, match] = ['urls', line.match(RE_URL)];
358
+ matchName = 'urls';
359
+ match = line.match(RE_URL);
353
360
  }
354
361
  if (match === null) {
355
- [matchName, match] = ['typedef', line.match(RE_TYPEDEF)];
362
+ matchName = 'typedef';
363
+ match = line.match(RE_TYPEDEF);
356
364
  }
357
365
  if (match === null) {
358
366
  matchName = null;
package/lib/schema.js CHANGED
@@ -235,12 +235,12 @@ function validateTypeHelper(types, type, value, memberFqn) {
235
235
  for (let ixArrayValue = 0; ixArrayValue < valueNew.length; ixArrayValue++) {
236
236
  const memberFqnValue = memberFqn !== null ? `${memberFqn}.${ixArrayValue}` : `${ixArrayValue}`;
237
237
  let arrayValue = valueNew[ixArrayValue];
238
- if (arrayValue === null || (arrayValueNullable && arrayValue === 'null')) {
238
+ if (arrayValueNullable && (arrayValue === null || arrayValue === 'null')) {
239
239
  arrayValue = null;
240
240
  } else {
241
241
  arrayValue = validateTypeHelper(types, arrayType, arrayValue, memberFqnValue);
242
+ validateAttr(arrayType, arrayAttr, arrayValue, memberFqnValue);
242
243
  }
243
- validateAttr(arrayType, arrayAttr, arrayValue, memberFqnValue);
244
244
  valueCopy.push(arrayValue);
245
245
  }
246
246
 
@@ -269,20 +269,20 @@ function validateTypeHelper(types, type, value, memberFqn) {
269
269
  const memberFqnKey = memberFqn !== null ? `${memberFqn}.${dictKey}` : `${dictKey}`;
270
270
 
271
271
  // Validate the key
272
- if (dictKey === null || (dictKeyNullable && dictKey === 'null')) {
272
+ if (dictKeyNullable && (dictKey === null || dictKey === 'null')) {
273
273
  dictKey = null;
274
274
  } else {
275
275
  dictKey = validateTypeHelper(types, dictKeyType, dictKey, memberFqn);
276
+ validateAttr(dictKeyType, dictKeyAttr, dictKey, memberFqn);
276
277
  }
277
- validateAttr(dictKeyType, dictKeyAttr, dictKey, memberFqn);
278
278
 
279
279
  // Validate the value
280
- if (dictValue === null || (dictValueNullable && dictValue === 'null')) {
280
+ if (dictValueNullable && (dictValue === null || dictValue === 'null')) {
281
281
  dictValue = null;
282
282
  } else {
283
283
  dictValue = validateTypeHelper(types, dictType, dictValue, memberFqnKey);
284
+ validateAttr(dictType, dictAttr, dictValue, memberFqnKey);
284
285
  }
285
- validateAttr(dictType, dictAttr, dictValue, memberFqnKey);
286
286
 
287
287
  // Copy the key/value
288
288
  if (valueCopy instanceof Map) {
@@ -311,12 +311,12 @@ function validateTypeHelper(types, type, value, memberFqn) {
311
311
 
312
312
  // Validate the value
313
313
  const valueNullable = typedefAttr !== null && 'nullable' in typedefAttr && typedefAttr.nullable;
314
- if (value === null || (valueNullable && value === 'null')) {
314
+ if (valueNullable && (value === null || value === 'null')) {
315
315
  valueNew = null;
316
316
  } else {
317
317
  valueNew = validateTypeHelper(types, typedef.type, value, memberFqn);
318
+ validateAttr(type, typedefAttr, valueNew, memberFqn);
318
319
  }
319
- validateAttr(type, typedefAttr, valueNew, memberFqn);
320
320
 
321
321
  // enum?
322
322
  } else if ('enum' in userType) {
@@ -351,7 +351,8 @@ function validateTypeHelper(types, type, value, memberFqn) {
351
351
  for (const member of getStructMembers(types, struct)) {
352
352
  const memberName = member.name;
353
353
  const memberFqnMember = memberFqn !== null ? `${memberFqn}.${memberName}` : `${memberName}`;
354
- const memberOptional = 'optional' in member ? member.optional : false;
354
+ const memberOptional = 'optional' in member && member.optional;
355
+ const memberNullable = 'attr' in member && 'nullable' in member.attr && member.attr.nullable;
355
356
 
356
357
  // Missing non-optional member?
357
358
  if (!(valueNew instanceof Map ? valueNew.has(memberName) : memberName in valueNew)) {
@@ -361,10 +362,12 @@ function validateTypeHelper(types, type, value, memberFqn) {
361
362
  } else {
362
363
  // Validate the member value
363
364
  let memberValue = valueNew instanceof Map ? valueNew.get(memberName) : valueNew[memberName];
364
- if (memberValue !== null) {
365
+ if (memberNullable && (memberValue === null || memberValue === 'null')) {
366
+ memberValue = null;
367
+ } else {
365
368
  memberValue = validateTypeHelper(types, member.type, memberValue, memberFqnMember);
369
+ validateAttr(member.type, 'attr' in member ? member.attr : null, memberValue, memberFqnMember);
366
370
  }
367
- validateAttr(member.type, 'attr' in member ? member.attr : null, memberValue, memberFqnMember);
368
371
 
369
372
  // Copy the validated member
370
373
  if (valueCopy instanceof Map) {
@@ -405,12 +408,7 @@ function throwMemberError(type, value, memberFqn, attr = null) {
405
408
 
406
409
 
407
410
  function validateAttr(type, attr, value, memberFqn) {
408
- if (value === null) {
409
- const valueNullable = attr !== null && 'nullable' in attr && attr.nullable;
410
- if (!valueNullable) {
411
- throwMemberError(type, value, memberFqn);
412
- }
413
- } else if (attr !== null) {
411
+ if (attr !== null) {
414
412
  const length = Array.isArray(value) || typeof value === 'string' ? value.length
415
413
  : (typeof value === 'object' ? Object.keys(value).length : null);
416
414
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "schema-markdown",
4
- "version": "1.1.1",
4
+ "version": "1.1.5",
5
5
  "description": "Human-friendly schema definition language and schema validator",
6
6
  "keywords": [
7
7
  "schema",
@@ -26,8 +26,8 @@
26
26
  "devDependencies": {
27
27
  "ava": "^4.0.0-rc.1",
28
28
  "c8": "~7.10",
29
- "eslint": "~8.3",
29
+ "eslint": "~8.4",
30
30
  "jsdoc": "~3.6",
31
- "jsdom": "~18.1"
31
+ "jsdom": "~19.0"
32
32
  }
33
33
  }