Socket
Socket
Sign inDemoInstall

@json-layout/core

Package Overview
Dependencies
Maintainers
0
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@json-layout/core - npm Package Compare versions

Comparing version 0.24.1 to 0.25.0

2

package.json
{
"name": "@json-layout/core",
"version": "0.24.1",
"version": "0.25.0",
"description": "Compilation and state management utilities for JSON Layout.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -63,3 +63,3 @@ // compileStatic is meant to produce a serializable result

/** @type {import('ajv').Options} */
const ajvOpts = { allErrors: true, strict: false }
const ajvOpts = { allErrors: true, strict: false, verbose: true }
if (partialOptions.ajvOptions) Object.assign(ajvOpts, partialOptions.ajvOptions)

@@ -130,2 +130,4 @@ if (partialOptions.code) ajvOpts.code = { source: true, esm: true, lines: true }

const skeletonTrees = {}
/** @type {Record<string, import('./types.js').SkeletonNode>} */
const skeletonNodes = {}

@@ -142,2 +144,3 @@ // makeSkeletonTree also mutates the schema (adding some error messages)

skeletonTrees,
skeletonNodes,
validatePointers,

@@ -193,2 +196,3 @@ validationErrors,

skeletonTrees,
skeletonNodes,
validates,

@@ -195,0 +199,0 @@ validationErrors,

@@ -84,2 +84,3 @@ // import Debug from 'debug'

skeletonTrees: clone(compiledLayout.skeletonTrees),
skeletonNodes: clone(compiledLayout.skeletonNodes),
normalizedLayouts: clone(compiledLayout.normalizedLayouts),

@@ -86,0 +87,0 @@ validates: {},

@@ -12,2 +12,3 @@ // import Debug from 'debug'

* @param {Record<string, import('./types.js').SkeletonTree>} skeletonTrees
* @param {Record<string, import('./types.js').SkeletonNode>} skeletonNodes
* @param {string[]} validates

@@ -18,4 +19,3 @@ * @param {Record<string, string[]>} validationErrors

* @param {string | number} key
* @param {string} currentPointer
* @param {string | null} parentPointer
* @param {string} pointer
* @param {boolean} required

@@ -33,2 +33,3 @@ * @param {string} [condition]

skeletonTrees,
skeletonNodes,
validates,

@@ -39,4 +40,3 @@ validationErrors,

key,
currentPointer,
parentPointer,
pointer,
required,

@@ -49,11 +49,13 @@ condition,

let schema = rawSchema
let pointer = currentPointer
let refPointer = pointer
let refFragment
rawSchema.__pointer = pointer
if (schema.$ref) {
[refFragment, schemaId, pointer] = getJSONRef(sourceSchemaId, schema.$ref)
schema = {...rawSchema, ...refFragment}
[refFragment, schemaId, refPointer] = getJSONRef(sourceSchemaId, schema.$ref)
refFragment.__pointer = refPointer
schema = { ...rawSchema, ...refFragment }
delete schema.$ref
}
schema = partialResolveRefs(schema, schemaId, getJSONRef)
const { type, nullable } = knownType ? { type: knownType, nullable: false } : getSchemaFragmentType(schema)
const resolvedSchema = partialResolveRefs(schema, schemaId, getJSONRef)
const { type, nullable } = knownType ? { type: knownType, nullable: false } : getSchemaFragmentType(resolvedSchema)

@@ -64,3 +66,3 @@ // improve on ajv error messages based on ajv-errors (https://ajv.js.org/packages/ajv-errors.html)

const normalizationResult = normalizeLayoutFragment(
/** @type {import('@json-layout/vocabulary').SchemaFragment} */(schema),
/** @type {import('@json-layout/vocabulary').SchemaFragment} */(resolvedSchema),
pointer,

@@ -141,3 +143,3 @@ options.components,

pointer,
parentPointer,
refPointer,
pure,

@@ -163,25 +165,63 @@ propertyKeys: [],

const dependent = schema.dependentRequired && Object.values(schema.dependentRequired).some(dependentProperties => dependentProperties.includes(propertyKey))
node.children.push(makeSkeletonNode(
schema.properties[propertyKey],
schemaId,
options,
getJSONRef,
skeletonTrees,
validates,
validationErrors,
normalizedLayouts,
expressions,
propertyKey,
`${pointer}/properties/${propertyKey}`,
pointer,
schema.required?.includes(propertyKey),
undefined,
dependent
))
const childPointer = `${refPointer}/properties/${propertyKey}`
if (!skeletonNodes[childPointer]) {
// @ts-ignore
skeletonNodes[childPointer] = 'recursing'
skeletonNodes[childPointer] = makeSkeletonNode(
schema.properties[propertyKey],
schemaId,
options,
getJSONRef,
skeletonTrees,
skeletonNodes,
validates,
validationErrors,
normalizedLayouts,
expressions,
propertyKey,
childPointer,
schema.required?.includes(propertyKey),
undefined,
dependent
)
}
node.children.push(childPointer)
if (schema.dependentSchemas?.[propertyKey] || (schema.dependencies?.[propertyKey] && !Array.isArray(schema.dependencies[propertyKey]))) {
const dependentSchema = schema.dependentSchemas?.[propertyKey] ?? schema.dependencies[propertyKey]
const dependentPointer = schema.dependentSchemas?.[propertyKey] ? `${pointer}/dependentSchemas/${propertyKey}` : `${pointer}/dependencies/${propertyKey}`
node.children.push(makeSkeletonNode(
dependentSchema,
const dependentPointer = schema.dependentSchemas?.[propertyKey] ? `${refPointer}/dependentSchemas/${propertyKey}` : `${refPointer}/dependencies/${propertyKey}`
if (!skeletonNodes[dependentPointer]) {
// @ts-ignore
skeletonNodes[dependentPointer] = 'recursing'
skeletonNodes[dependentPointer] = makeSkeletonNode(
dependentSchema,
schemaId,
options,
getJSONRef,
skeletonTrees,
skeletonNodes,
validates,
validationErrors,
normalizedLayouts,
expressions,
`$deps-${propertyKey}`,
dependentPointer,
false,
`data["${propertyKey}"] !== undefined`,
undefined,
'object'
)
}
node.children.push(dependentPointer)
}
}
}
if (schema.allOf) {
for (let i = 0; i < schema.allOf.length; i++) {
const childPointer = `${refPointer}/allOf/${i}`
if (!skeletonNodes[childPointer]) {
// @ts-ignore
skeletonNodes[childPointer] = 'recursing'
skeletonNodes[childPointer] = makeSkeletonNode(
schema.allOf[i],
schemaId,

@@ -191,2 +231,3 @@ options,

skeletonTrees,
skeletonNodes,
validates,

@@ -196,39 +237,16 @@ validationErrors,

expressions,
`$deps-${propertyKey}`,
dependentPointer,
pointer,
`$allOf-${i}`,
childPointer,
false,
`data["${propertyKey}"] !== undefined`,
undefined,
undefined,
'object'
))
)
}
node.propertyKeys = node.propertyKeys.concat(skeletonNodes[childPointer].propertyKeys)
node.roPropertyKeys = node.roPropertyKeys.concat(skeletonNodes[childPointer].roPropertyKeys)
node.children = node.children ?? []
node.children.push(childPointer)
}
}
if (schema.allOf) {
node.children = node.children ?? []
for (let i = 0; i < schema.allOf.length; i++) {
const allOfNode = makeSkeletonNode(
schema.allOf[i],
schemaId,
options,
getJSONRef,
skeletonTrees,
validates,
validationErrors,
normalizedLayouts,
expressions,
`$allOf-${i}`,
`${pointer}/allOf/${i}`,
pointer,
false,
undefined,
undefined,
'object'
)
node.propertyKeys = node.propertyKeys.concat(allOfNode.propertyKeys)
node.roPropertyKeys = node.roPropertyKeys.concat(allOfNode.roPropertyKeys)
node.children.push(allOfNode)
}
}
if (schema.oneOf) {

@@ -269,2 +287,3 @@ const oneOfPointer = `${pointer}/oneOf`

skeletonTrees,
skeletonNodes,
validates,

@@ -280,14 +299,17 @@ validationErrors,

}
if (!skeletonNodes[oneOfPointer]) {
skeletonNodes[oneOfPointer] = {
key: '$oneOf',
pointer: oneOfPointer,
refPointer: oneOfPointer,
childrenTrees,
pure: skeletonNodes[skeletonTrees[childrenTrees[0]]?.root].pure,
propertyKeys: [],
roPropertyKeys: []
}
}
node.children = node.children ?? []
node.children.push({
key: '$oneOf',
pointer: `${pointer}/oneOf`,
parentPointer: pointer,
childrenTrees,
pure: skeletonTrees[childrenTrees[0]]?.root.pure,
propertyKeys: [],
roPropertyKeys: []
})
node.children.push(oneOfPointer)
schema.errorMessage.oneOf = options.messages.errorOneOf
rawSchema.errorMessage.oneOf = options.messages.errorOneOf
}

@@ -297,42 +319,54 @@ if (schema.if) {

if (schema.then) {
const childPointer = `${refPointer}/then`
if (!skeletonNodes[childPointer]) {
// @ts-ignore
skeletonNodes[childPointer] = 'recursing'
skeletonNodes[childPointer] = makeSkeletonNode(
schema.then,
schemaId,
options,
getJSONRef,
skeletonTrees,
skeletonNodes,
validates,
validationErrors,
normalizedLayouts,
expressions,
'$then',
childPointer,
false,
`validates["${pointer}/if"](data)`,
undefined,
'object'
)
}
node.children = node.children ?? []
node.children.push(makeSkeletonNode(
schema.then,
schemaId,
options,
getJSONRef,
skeletonTrees,
validates,
validationErrors,
normalizedLayouts,
expressions,
'$then',
`${pointer}/then`,
pointer,
false,
`validates["${pointer}/if"](data)`,
undefined,
'object'
))
node.children.push(childPointer)
}
if (schema.else) {
const childPointer = `${refPointer}/else`
if (!skeletonNodes[childPointer]) {
// @ts-ignore
skeletonNodes[childPointer] = 'recursing'
skeletonNodes[childPointer] = makeSkeletonNode(
schema.else,
schemaId,
options,
getJSONRef,
skeletonTrees,
skeletonNodes,
validates,
validationErrors,
normalizedLayouts,
expressions,
'$else',
childPointer,
false,
`!validates["${pointer}/if"](data)`,
undefined,
'object'
)
}
node.children = node.children ?? []
node.children.push(makeSkeletonNode(
schema.else,
schemaId,
options,
getJSONRef,
skeletonTrees,
validates,
validationErrors,
normalizedLayouts,
expressions,
'$else',
`${pointer}/else`,
pointer,
false,
`!validates["${pointer}/if"](data)`,
undefined,
'object'
))
node.children.push(childPointer)
}

@@ -343,7 +377,7 @@ }

if (schema?.required?.includes(propertyKey)) {
schema.errorMessage.required = schema.errorMessage.required ?? {}
schema.errorMessage.required[propertyKey] = options.messages.errorRequired
rawSchema.errorMessage.required = rawSchema.errorMessage.required ?? {}
rawSchema.errorMessage.required[propertyKey] = options.messages.errorRequired
}
if (schema.dependentRequired && Object.keys(schema.dependentRequired).includes(propertyKey)) {
schema.errorMessage.dependentRequired = options.messages.errorRequired
rawSchema.errorMessage.dependentRequired = options.messages.errorRequired
}

@@ -355,19 +389,28 @@ }

if (Array.isArray(schema.items)) {
node.children = schema.items.map((/** @type {any} */ itemSchema, /** @type {number} */ i) => {
return makeSkeletonNode(
itemSchema,
schemaId,
options,
getJSONRef,
skeletonTrees,
validates,
validationErrors,
normalizedLayouts,
expressions,
i,
`${pointer}/items/${i}`,
pointer,
true
)
})
node.children = node.children ?? []
for (let i = 0; i < schema.items.length; i++) {
/** @type {any} */
const itemSchema = schema.items[i]
const childPointer = `${refPointer}/items/${i}`
if (!skeletonNodes[childPointer]) {
// @ts-ignore
skeletonNodes[childPointer] = 'recursing'
skeletonNodes[childPointer] = makeSkeletonNode(
itemSchema,
schemaId,
options,
getJSONRef,
skeletonTrees,
skeletonNodes,
validates,
validationErrors,
normalizedLayouts,
expressions,
i,
childPointer,
true
)
}
node.children.push(childPointer)
}
} else {

@@ -384,2 +427,3 @@ const childTreePointer = `${pointer}/items`

skeletonTrees,
skeletonNodes,
validates,

@@ -397,7 +441,8 @@ validationErrors,

for (const child of node.children || []) {
for (const childPointer of node.children || []) {
const child = skeletonNodes[childPointer]
if (!child.pure) node.pure = false
}
for (const childTree of node.childrenTrees || []) {
if (!skeletonTrees[childTree]?.root?.pure) node.pure = false
if (!skeletonNodes[skeletonTrees[childTree]?.root]?.pure) node.pure = false
}

@@ -404,0 +449,0 @@

@@ -12,2 +12,3 @@ // import Debug from 'debug'

* @param {Record<string, import('./types.js').SkeletonTree>} skeletonTrees
* @param {Record<string, import('./types.js').SkeletonNode>} skeletonNodes
* @param {string[]} validates

@@ -27,2 +28,3 @@ * @param {Record<string, string[]>} validationErrors

skeletonTrees,
skeletonNodes,
validates,

@@ -35,19 +37,23 @@ validationErrors,

) {
const root = makeSkeletonNode(
schema,
schemaId,
options,
getJSONRef,
skeletonTrees,
validates,
validationErrors,
normalizedLayouts,
expressions,
'',
pointer,
null,
true
)
validates.push(root.pointer)
return { title, root }
if (!skeletonNodes[pointer]) {
// @ts-ignore
skeletonNodes[pointer] = 'recursing'
skeletonNodes[pointer] = makeSkeletonNode(
schema,
schemaId,
options,
getJSONRef,
skeletonTrees,
skeletonNodes,
validates,
validationErrors,
normalizedLayouts,
expressions,
'',
pointer,
true
)
validates.push(pointer)
}
return { title, root: pointer }
}

@@ -44,4 +44,5 @@ import type ajvModule from 'ajv/dist/2019.js'

schema?: SchemaObject
mainTree: string,
mainTree: string
skeletonTrees: Record<string, SkeletonTree>
skeletonNodes: Record<string, SkeletonNode>
validates: Record<string, ValidateFunction>

@@ -61,3 +62,3 @@ validationErrors: Record<string, string[]>

title: string
root: SkeletonNode
root: string
}

@@ -70,3 +71,3 @@

pointer: string
parentPointer: string | null
refPointer: string
pure: boolean

@@ -76,3 +77,3 @@ propertyKeys: string[]

condition?: Expression
children?: SkeletonNode[] // optional children in the case of arrays and object nodes
children?: string[] // optional children in the case of arrays and object nodes
childrenTrees?: string[] // other trees that can be instantiated with separate validation (for example in the case of new array items of oneOfs, etc)

@@ -79,0 +80,0 @@ required?: boolean

@@ -141,2 +141,3 @@ import { isSwitchStruct, childIsCompObject, isCompositeLayout, isFocusableLayout, isItemsLayout, isGetItemsExpression, isGetItemsFetch } from '@json-layout/vocabulary'

/**
* should match if an error belongs to this exact node
* @param {import('ajv').ErrorObject} error

@@ -151,3 +152,3 @@ * @param {import('../index.js').SkeletonNode} skeleton

if (parentDataPath === originalError.instancePath && originalError.params?.missingProperty === skeleton.key) return true
if (originalError.instancePath === dataPath && originalError.schemaPath === skeleton.pointer) return true
if (originalError.instancePath === dataPath && (originalError.schemaPath === skeleton.pointer || originalError.schemaPath === skeleton.refPointer)) return true
return false

@@ -157,2 +158,3 @@ }

/**
* should match if an error belongs to a child of the current node but the child was not displayed
* @param {import('ajv').ErrorObject} error

@@ -165,7 +167,11 @@ * @param {import('../index.js').SkeletonNode} skeleton

const matchChildError = (error, skeleton, dataPath, parentDataPath) => {
const originalError = error.params?.errors?.[0] ?? error
if (!(
error.schemaPath === skeleton.pointer ||
error.schemaPath.startsWith(skeleton.pointer + '/')
originalError.schemaPath === skeleton.pointer ||
originalError.schemaPath.startsWith(skeleton.pointer + '/')
) && !(
originalError.schemaPath === skeleton.refPointer ||
originalError.schemaPath.startsWith(skeleton.refPointer + '/')
)) return false
if (error.instancePath.startsWith(dataPath)) return true
if (originalError.instancePath.startsWith(dataPath)) return true
return false

@@ -310,3 +316,5 @@ }

) continue
const childSkeleton = skeleton.children?.find(c => c.key === childLayout.key) ?? skeleton
let childSkeleton = skeleton
const childSkeletonKey = skeleton.children?.find(c => compiledLayout.skeletonNodes[c].key === childLayout.key)
if (childSkeletonKey !== undefined) childSkeleton = compiledLayout.skeletonNodes[childSkeletonKey]
if (childSkeleton.condition) {

@@ -345,12 +353,15 @@ if (!evalExpression(compiledLayout.expressions, childSkeleton.condition, objectData, parentOptions, display, layout, compiledLayout.validates, context.rootData, parentContext)) {

/** @type {number} */
const activeChildTreeIndex = fullKey in context.activatedItems ? context.activatedItems[fullKey] : skeleton.childrenTrees?.findIndex((childTree) => compiledLayout.validates[compiledLayout.skeletonTrees[childTree].root.pointer](data))
const activeChildTreeIndex = fullKey in context.activatedItems ? context.activatedItems[fullKey] : skeleton.childrenTrees?.findIndex((childTree) => compiledLayout.validates[compiledLayout.skeletonTrees[childTree].root](data))
if (activeChildTreeIndex !== -1) {
context.errors = context.errors?.filter(error => {
const originalError = error.params?.errors?.[0] ?? error
// console.log(originalError.schemaPath, skeleton.pointer, skeleton.refPointer)
// if an item was selected, remove the oneOf error
if (originalError.schemaPath === skeleton.pointer && originalError.keyword === 'oneOf') return false
if ((originalError.schemaPath === skeleton.pointer || originalError.schemaPath === skeleton.refPointer) && originalError.keyword === 'oneOf') return false
// also remove the errors from other children of the oneOf
if (originalError.schemaPath.startsWith(skeleton.pointer) && !originalError.schemaPath.startsWith(skeleton.pointer + '/' + activeChildTreeIndex)) return false
if (originalError.schemaPath.startsWith(skeleton.refPointer) && !originalError.schemaPath.startsWith(skeleton.refPointer + '/' + activeChildTreeIndex)) return false
return true
})
// console.log(context.errors?.map(error => error.params?.errors?.[0] ?? error))
const activeChildKey = `${fullKey}/${activeChildTreeIndex}`

@@ -369,3 +380,3 @@ if (context.autofocusTarget === fullKey) context.autofocusTarget = activeChildKey

dataPath,
activeChildTree.root,
compiledLayout.skeletonNodes[activeChildTree.root],
null,

@@ -384,3 +395,3 @@ display,

const arrayData = /** @type {unknown[]} */(data ?? [])
const childSkeleton = /** @type {import('../index.js').SkeletonNode} */(skeleton?.childrenTrees?.[0] && compiledLayout.skeletonTrees[skeleton?.childrenTrees?.[0]]?.root)
const childSkeleton = /** @type {import('../index.js').SkeletonNode} */(skeleton?.childrenTrees?.[0] && compiledLayout.skeletonNodes[compiledLayout.skeletonTrees[skeleton?.childrenTrees?.[0]]?.root])
const listItemOptions = layout.listEditMode === 'inline' ? options : produceReadonlyArrayItemOptions(options)

@@ -387,0 +398,0 @@ children = []

@@ -48,3 +48,3 @@ import { produce } from 'immer'

) {
const validate = compiledLayout.validates[skeleton.root.pointer]
const validate = compiledLayout.validates[skeleton.root]
const valid = validate(data)

@@ -56,2 +56,12 @@ if (validate.errors) {

context.errors = validate.errors
if (context.errors.length) {
for (const error of context.errors) {
const originalError = error.params?.errors?.[0] ?? error
// work around this issue https://github.com/ajv-validator/ajv/issues/512
if (originalError?.parentSchema.__pointer) {
originalError.schemaPath = originalError?.parentSchema.__pointer
if (originalError.keyword === 'oneOf') originalError.schemaPath += '/oneOf'
}
}
}
if ([true, 'error'].includes(options.removeAdditional)) {

@@ -70,3 +80,3 @@ context.additionalPropertiesErrors = validate.errors.filter(error => error.keyword === 'additionalProperties' || error.keyword === 'unevaluatedProperties')

null,
skeleton.root,
compiledLayout.skeletonNodes[skeleton.root],
null,

@@ -73,0 +83,0 @@ display,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc