@json-layout/vocabulary 0.17.0 → 0.18.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": "@json-layout/vocabulary",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "Main JSON Layout vocabulary as JSON schemas and Typescript types. Also contains some small utility functions to validate and normalize annotations.",
5
5
  "type": "module",
6
6
  "exports": {
package/src/normalize.js CHANGED
@@ -16,25 +16,41 @@ import { getComponentValidate } from './validate.js'
16
16
 
17
17
  /**
18
18
  * @param {import('./types.js').SchemaFragment} schemaFragment
19
+ * @param {string} type
19
20
  * @returns {Children}
20
21
  */
21
- function getDefaultChildren (schemaFragment) {
22
- const { type } = getSchemaFragmentType(schemaFragment)
22
+ function getDefaultChildren (schemaFragment, type) {
23
23
  /** @type {Children} */
24
24
  const children = []
25
25
  if (type === 'object') {
26
- if (schemaFragment.properties) {
27
- for (const key of Object.keys(schemaFragment.properties)) {
28
- children.push({ key })
26
+ for (const key of Object.keys(schemaFragment)) {
27
+ if (key === 'properties') {
28
+ for (const key of Object.keys(schemaFragment.properties ?? {})) {
29
+ children.push({ key })
30
+ if (schemaFragment.dependencies?.[key] && !Array.isArray(schemaFragment.dependencies[key])) {
31
+ children.push({ key: `$deps-${key}` })
32
+ }
33
+ if (schemaFragment.dependentSchemas && schemaFragment.dependentSchemas[key]) {
34
+ children.push({ key: `$deps-${key}` })
35
+ }
36
+ }
29
37
  }
30
- }
31
- if (schemaFragment.allOf?.length) {
32
- for (let i = 0; i < schemaFragment.allOf.length; i++) {
33
- children.push({ key: `$allOf-${i}` })
38
+ if (key === 'allOf') {
39
+ if (schemaFragment.allOf?.length) {
40
+ for (let i = 0; i < schemaFragment.allOf.length; i++) {
41
+ children.push({ key: `$allOf-${i}` })
42
+ }
43
+ }
44
+ }
45
+ if (key === 'oneOf') {
46
+ children.push({ key: '$oneOf' })
47
+ }
48
+ if (key === 'then' && schemaFragment.if) {
49
+ children.push({ key: '$then' })
50
+ }
51
+ if (key === 'else' && schemaFragment.if) {
52
+ children.push({ key: '$else' })
34
53
  }
35
- }
36
- if (schemaFragment.oneOf) {
37
- children.push({ key: '$oneOf' })
38
54
  }
39
55
  }
40
56
  if (type === 'array' && Array.isArray(schemaFragment.items)) {
@@ -84,11 +100,11 @@ function getChildren (defaultChildren, partialChildren) {
84
100
  /**
85
101
  * @param {PartialCompObject} partial
86
102
  * @param {SchemaFragment} schemaFragment
103
+ * @param {string | undefined} type
87
104
  * @param {'oneOf'} [arrayChild]
88
105
  * @returns {import('./index.js').ComponentName}
89
106
  */
90
- function getDefaultComp (partial, schemaFragment, arrayChild) {
91
- const { type } = getSchemaFragmentType(schemaFragment)
107
+ function getDefaultComp (partial, schemaFragment, type, arrayChild) {
92
108
  const hasSimpleType = type && ['string', 'integer', 'number'].includes(type)
93
109
  if (arrayChild === 'oneOf') return 'one-of-select'
94
110
  if (hasSimpleType && schemaFragment.enum) return schemaFragment.enum.length > 20 ? 'autocomplete' : 'select'
@@ -232,6 +248,8 @@ export const getSchemaFragmentType = (schemaFragment) => {
232
248
  /**
233
249
  * @param {LayoutKeyword} layoutKeyword
234
250
  * @param {SchemaFragment} schemaFragment
251
+ * @param {string | undefined} type
252
+ * @param {boolean} nullable
235
253
  * @param {string} schemaPath
236
254
  * @param {Record<string, import('./types.js').ComponentInfo>} components
237
255
  * @param {(text: string) => string} markdown
@@ -239,11 +257,9 @@ export const getSchemaFragmentType = (schemaFragment) => {
239
257
  * @param {'oneOf'} [arrayChild]
240
258
  * @returns {BaseCompObject}
241
259
  */
242
- function getCompObject (layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
260
+ function getCompObject (layoutKeyword, schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild) {
243
261
  const key = schemaPath.slice(schemaPath.lastIndexOf('/') + 1)
244
262
 
245
- const { type, nullable } = getSchemaFragmentType(schemaFragment)
246
-
247
263
  if ('const' in schemaFragment) return { comp: 'none' }
248
264
  if (!type) return { comp: 'none' }
249
265
 
@@ -255,7 +271,7 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, components, m
255
271
 
256
272
  // chose the default component for a schema fragment
257
273
  if (!partial.comp) {
258
- partial.comp = getDefaultComp(partial, schemaFragment, arrayChild)
274
+ partial.comp = getDefaultComp(partial, schemaFragment, type, arrayChild)
259
275
  }
260
276
  const component = components[partial.comp]
261
277
  if (!component) {
@@ -267,7 +283,7 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, components, m
267
283
 
268
284
  if (component.composite) {
269
285
  if (!('title' in partial)) partial.title = schemaFragment.title ?? null
270
- partial.children = getChildren(getDefaultChildren(schemaFragment), partial.children)
286
+ partial.children = getChildren(getDefaultChildren(schemaFragment, type), partial.children)
271
287
  } else if (partial.comp === 'list') {
272
288
  if (!('title' in partial)) partial.title = schemaFragment.title ?? key
273
289
  partial.listEditMode = partial.listEditMode ?? (schemaFragment.items.type === 'object' ? 'inline-single' : 'inline')
@@ -414,6 +430,8 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, components, m
414
430
  /**
415
431
  * @param {LayoutKeyword} layoutKeyword
416
432
  * @param {SchemaFragment} schemaFragment
433
+ * @param {string | undefined} type
434
+ * @param {boolean} nullable
417
435
  * @param {string} schemaPath
418
436
  * @param {Record<string, import('./types.js').ComponentInfo>} components
419
437
  * @param {(text: string) => string} markdown
@@ -421,7 +439,7 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, components, m
421
439
  * @param {'oneOf'} [arrayChild]
422
440
  * @returns {NormalizedLayout}}
423
441
  */
424
- function getNormalizedLayout (layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
442
+ function getNormalizedLayout (layoutKeyword, schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild) {
425
443
  if (isPartialSwitch(layoutKeyword)) {
426
444
  /** @type {BaseCompObject[]} */
427
445
  const normalizedSwitchCases = []
@@ -431,12 +449,12 @@ function getNormalizedLayout (layoutKeyword, schemaFragment, schemaPath, compone
431
449
  }
432
450
  for (let i = 0; i < switchCases.length; i++) {
433
451
  const switchCase = switchCases[i]
434
- const compObjectResult = getCompObject(switchCase, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
452
+ const compObjectResult = getCompObject(switchCase, schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild)
435
453
  normalizedSwitchCases.push(compObjectResult)
436
454
  }
437
455
  return { switch: normalizedSwitchCases }
438
456
  } else {
439
- return getCompObject(layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
457
+ return getCompObject(layoutKeyword, schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild)
440
458
  }
441
459
  }
442
460
 
@@ -479,6 +497,8 @@ const defaultOptionsKeys = ['readOnly', 'summary', 'titleDepth', 'density', 'rem
479
497
 
480
498
  /**
481
499
  * @param {SchemaFragment} schemaFragment
500
+ * @param {string | undefined} type
501
+ * @param {boolean} nullable
482
502
  * @param {string} schemaPath
483
503
  * @param {Record<string, import('./types.js').ComponentInfo>} components
484
504
  * @param {(text: string) => string} markdown
@@ -486,7 +506,7 @@ const defaultOptionsKeys = ['readOnly', 'summary', 'titleDepth', 'density', 'rem
486
506
  * @param {'oneOf'} [arrayChild]
487
507
  * @returns {NormalizedLayout}
488
508
  */
489
- function normalizeValidLayoutFragment (schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
509
+ function normalizeValidLayoutFragment (schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild) {
490
510
  optionsKeys = optionsKeys ? optionsKeys.concat(defaultOptionsKeys) : defaultOptionsKeys
491
511
  let layoutKeyword
492
512
  if (arrayChild === 'oneOf') {
@@ -499,7 +519,7 @@ function normalizeValidLayoutFragment (schemaFragment, schemaPath, components, m
499
519
  error.cause = lighterValidationErrors(validateLayoutKeyword.errors)
500
520
  throw error
501
521
  }
502
- const normalizedLayout = getNormalizedLayout(layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
522
+ const normalizedLayout = getNormalizedLayout(layoutKeyword, schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild)
503
523
 
504
524
  if (!validateNormalizedLayout(normalizedLayout)) {
505
525
  const error = new Error('normalized layout validation errors at path')
@@ -516,20 +536,23 @@ function normalizeValidLayoutFragment (schemaFragment, schemaPath, components, m
516
536
  * @param {(text: string) => string} markdown
517
537
  * @param {string[]} [optionsKeys]
518
538
  * @param {'oneOf'} [arrayChild]
539
+ * @param {string | undefined} [knownType]
540
+ * @param {boolean} [knownNullable]
519
541
  * @returns {{layout: NormalizedLayout, errors: string[]}}
520
542
  */
521
- export function normalizeLayoutFragment (schemaFragment, schemaPath, components, markdown = (src) => src, optionsKeys, arrayChild) {
543
+ export function normalizeLayoutFragment (schemaFragment, schemaPath, components, markdown = (src) => src, optionsKeys, arrayChild, knownType, knownNullable) {
544
+ const { type, nullable } = knownType ? { type: knownType, nullable: knownNullable ?? false } : getSchemaFragmentType(schemaFragment)
522
545
  /** @type {string[]} */
523
546
  const errors = []
524
547
  try {
525
- const layout = normalizeValidLayoutFragment(schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
548
+ const layout = normalizeValidLayoutFragment(schemaFragment, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild)
526
549
  return { layout, errors }
527
550
  } catch (/** @type {any} */err) {
528
551
  try {
529
552
  errors.push(err.message)
530
553
  if (err.cause && Array.isArray(err.cause)) errors.push(...err.cause)
531
554
  errors.push('failed to normalize layout, use default component')
532
- const layout = normalizeValidLayoutFragment({ ...schemaFragment, layout: {} }, schemaPath, components, markdown, optionsKeys, arrayChild)
555
+ const layout = normalizeValidLayoutFragment({ ...schemaFragment, layout: {} }, type, nullable, schemaPath, components, markdown, optionsKeys, arrayChild)
533
556
  return { layout, errors }
534
557
  } catch (/** @type {any} */err) {
535
558
  errors.push(err.message)
package/src/types.ts CHANGED
@@ -19,6 +19,11 @@ export interface SchemaFragment {
19
19
  formatMinimum?: string
20
20
  formatMaximum?: string
21
21
  readOnly?: boolean
22
+ if?: any
23
+ then?: any
24
+ else?: any
25
+ dependencies?: Record<string, any>
26
+ dependentSchemas?: Record<string, any>
22
27
  }
23
28
 
24
29
  export interface ComponentInfo {
@@ -5,9 +5,11 @@
5
5
  * @param {(text: string) => string} markdown
6
6
  * @param {string[]} [optionsKeys]
7
7
  * @param {'oneOf'} [arrayChild]
8
+ * @param {string | undefined} [knownType]
9
+ * @param {boolean} [knownNullable]
8
10
  * @returns {{layout: NormalizedLayout, errors: string[]}}
9
11
  */
10
- export function normalizeLayoutFragment(schemaFragment: SchemaFragment, schemaPath: string, components: Record<string, import('./types.js').ComponentInfo>, markdown?: (text: string) => string, optionsKeys?: string[] | undefined, arrayChild?: "oneOf" | undefined): {
12
+ export function normalizeLayoutFragment(schemaFragment: SchemaFragment, schemaPath: string, components: Record<string, import('./types.js').ComponentInfo>, markdown?: (text: string) => string, optionsKeys?: string[] | undefined, arrayChild?: "oneOf" | undefined, knownType?: string | undefined, knownNullable?: boolean | undefined): {
11
13
  layout: NormalizedLayout;
12
14
  errors: string[];
13
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.js"],"names":[],"mappings":"AA+fA;;;;;;;;GAQG;AACH,wDARW,cAAc,cACd,MAAM,cACN,OAAO,MAAM,EAAE,OAAO,YAAY,EAAE,aAAa,CAAC,oBAC3C,MAAM,KAAK,MAAM;YAGb,gBAAgB;YAAU,MAAM,EAAE;EAsBvD;AApVM,sDAHI,cAAc,GACZ;IAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAC,CA+BzD;oBAhOY,OAAO,YAAY,EAAE,KAAK;uBAC1B,OAAO,YAAY,EAAE,QAAQ;6BAC7B,OAAO,YAAY,EAAE,cAAc;yBACnC,OAAO,YAAY,EAAE,UAAU;+BAC/B,OAAO,YAAY,EAAE,gBAAgB;4BACrC,OAAO,YAAY,EAAE,aAAa;8BAClC,OAAO,YAAY,EAAE,eAAe;gCACpC,OAAO,YAAY,EAAE,iBAAiB;6BACtC,OAAO,YAAY,EAAE,cAAc"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.js"],"names":[],"mappings":"AAmhBA;;;;;;;;;;GAUG;AACH,wDAVW,cAAc,cACd,MAAM,cACN,OAAO,MAAM,EAAE,OAAO,YAAY,EAAE,aAAa,CAAC,oBAC3C,MAAM,KAAK,MAAM,oFAGxB,MAAM,GAAG,SAAS;YAEP,gBAAgB;YAAU,MAAM,EAAE;EAuBvD;AA3VM,sDAHI,cAAc,GACZ;IAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAC,CA+BzD;oBAhPY,OAAO,YAAY,EAAE,KAAK;uBAC1B,OAAO,YAAY,EAAE,QAAQ;6BAC7B,OAAO,YAAY,EAAE,cAAc;yBACnC,OAAO,YAAY,EAAE,UAAU;+BAC/B,OAAO,YAAY,EAAE,gBAAgB;4BACrC,OAAO,YAAY,EAAE,aAAa;8BAClC,OAAO,YAAY,EAAE,eAAe;gCACpC,OAAO,YAAY,EAAE,iBAAiB;6BACtC,OAAO,YAAY,EAAE,cAAc"}
package/types/types.d.ts CHANGED
@@ -18,6 +18,11 @@ export interface SchemaFragment {
18
18
  formatMinimum?: string;
19
19
  formatMaximum?: string;
20
20
  readOnly?: boolean;
21
+ if?: any;
22
+ then?: any;
23
+ else?: any;
24
+ dependencies?: Record<string, any>;
25
+ dependentSchemas?: Record<string, any>;
21
26
  }
22
27
  export interface ComponentInfo {
23
28
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE9D,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,WAAW,CAAC,EAAE,aAAa,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;IACZ,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,MAAM,CAAC,EAAE,GAAG,CAAA;IACZ,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE9D,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,WAAW,CAAC,EAAE,aAAa,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;IACZ,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,EAAE,CAAC,EAAE,GAAG,CAAA;IACR,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,MAAM,CAAC,EAAE,GAAG,CAAA;IACZ,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB"}