@json-layout/core
Advanced tools
Comparing version 0.18.0 to 0.19.0
{ | ||
"name": "@json-layout/core", | ||
"version": "0.18.0", | ||
"version": "0.19.0", | ||
"description": "Compilation and state management utilities for JSON Layout.", | ||
@@ -62,3 +62,3 @@ "type": "module", | ||
"dependencies": { | ||
"@json-layout/vocabulary": "^0.17.0", | ||
"@json-layout/vocabulary": "^0.18.0", | ||
"@types/markdown-it": "^13.0.1", | ||
@@ -73,4 +73,3 @@ "ajv": "^8.12.0", | ||
"markdown-it": "^13.0.2", | ||
"mitt": "^3.0.1", | ||
"recast": "^0.23.4" | ||
"mitt": "^3.0.1" | ||
}, | ||
@@ -77,0 +76,0 @@ "devDependencies": { |
@@ -145,4 +145,4 @@ // compileStatic is meant to produce a serializable result | ||
const expressionsParams = expression.pure | ||
? ['data', 'options', 'context', 'display', 'layout'] | ||
: ['data', 'options', 'context', 'display', 'layout', 'rootData', 'parent'] | ||
? ['data', 'options', 'context', 'display', 'layout', 'validates'] | ||
: ['data', 'options', 'context', 'display', 'layout', 'validates', 'rootData', 'parent'] | ||
/* if (expression.type === 'expr-eval') { | ||
@@ -149,0 +149,0 @@ expressions.push(exprEvalParser.parse(expression.expr).toJSFunction(expressionsParams.join(','))) |
@@ -5,3 +5,2 @@ // import Debug from 'debug' | ||
import { parseModule, generateCode, builders } from 'magicast' | ||
import { parse, print } from 'recast' | ||
import clone from '../utils/clone.js' | ||
@@ -63,6 +62,9 @@ import { isSwitchStruct } from '@json-layout/vocabulary' | ||
for (const expression of compiledLayout.expressions) { | ||
const id = `expression${i++}` | ||
code += expression.toString().replace('function anonymous', `function ${id}`) | ||
/* Previous code based on recast/esprima, suffered syntax limitations | ||
const fn = parse(expression.toString()).program.body[0] | ||
fn.id = `expression${i++}` | ||
code += `\n${print(fn)}\n` | ||
expressionsNodes.push(builders.raw(fn.id)) | ||
fn.id = id | ||
code += `\n${print(fn)}\n` */ | ||
expressionsNodes.push(builders.raw(id)) | ||
} | ||
@@ -69,0 +71,0 @@ |
@@ -16,2 +16,5 @@ // import Debug from 'debug' | ||
* @param {boolean} required | ||
* @param {string} [condition] | ||
* @param {boolean} [dependent] | ||
* @param {string} [knownType] | ||
* @returns {import('./types.js').SkeletonNode} | ||
@@ -29,5 +32,8 @@ */ | ||
parentPointer, | ||
required | ||
required, | ||
condition, | ||
dependent, | ||
knownType | ||
) { | ||
const { type, nullable } = getSchemaFragmentType(schema) | ||
const { type, nullable } = knownType ? { type: knownType, nullable: false } : getSchemaFragmentType(schema) | ||
@@ -42,3 +48,6 @@ // improve on ajv error messages based on ajv-errors (https://ajv.js.org/packages/ajv-errors.html) | ||
options.markdown, | ||
options.optionsKeys | ||
options.optionsKeys, | ||
undefined, | ||
type, | ||
nullable | ||
) | ||
@@ -60,3 +69,3 @@ normalizedLayouts[pointer] = normalizationResult.layout | ||
let pure = true | ||
let pure = !dependent | ||
/** | ||
@@ -111,2 +120,9 @@ * @param {import('@json-layout/vocabulary').Expression[]} expressions | ||
const node = { key: key ?? '', pointer, parentPointer, pure, propertyKeys: [], roPropertyKeys: [] } | ||
if (condition) { | ||
if (isSwitchStruct(normalizedLayout)) throw new Error('Switch struct not allowed in conditional schema') | ||
node.condition = { type: 'js-eval', expr: condition, pure: true } | ||
pushExpression(expressions, node.condition) | ||
} | ||
if (type === 'object') { | ||
@@ -118,2 +134,3 @@ if (schema.properties) { | ||
if (schema.properties[propertyKey].readOnly) node.roPropertyKeys.push(propertyKey) | ||
const dependent = schema.dependentRequired && Object.values(schema.dependentRequired).some(dependentProperties => dependentProperties.includes(propertyKey)) | ||
node.children.push(makeSkeletonNode( | ||
@@ -129,3 +146,5 @@ schema.properties[propertyKey], | ||
pointer, | ||
schema.required?.includes(propertyKey) | ||
schema.required?.includes(propertyKey), | ||
undefined, | ||
dependent | ||
)) | ||
@@ -136,2 +155,25 @@ if (schema?.required?.includes(propertyKey)) { | ||
} | ||
if (schema.dependentRequired && Object.keys(schema.dependentRequired).includes(propertyKey)) { | ||
schema.errorMessage.dependentRequired = options.messages.errorRequired | ||
} | ||
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, | ||
options, | ||
validates, | ||
validationErrors, | ||
normalizedLayouts, | ||
expressions, | ||
`$deps-${propertyKey}`, | ||
dependentPointer, | ||
pointer, | ||
false, | ||
`"${propertyKey}" in data`, | ||
undefined, | ||
'object' | ||
)) | ||
} | ||
} | ||
@@ -152,3 +194,6 @@ } | ||
pointer, | ||
false | ||
false, | ||
undefined, | ||
undefined, | ||
'object' | ||
) | ||
@@ -169,3 +214,5 @@ node.propertyKeys = node.propertyKeys.concat(allOfNode.propertyKeys) | ||
options.optionsKeys, | ||
'oneOf' | ||
'oneOf', | ||
type, | ||
nullable | ||
) | ||
@@ -208,2 +255,41 @@ normalizedLayouts[oneOfPointer] = normalizationResult.layout | ||
} | ||
if (schema.if) { | ||
validates.push(`${pointer}/if`) | ||
if (schema.then) { | ||
node.children = node.children ?? [] | ||
node.children.push(makeSkeletonNode( | ||
schema.then, | ||
options, | ||
validates, | ||
validationErrors, | ||
normalizedLayouts, | ||
expressions, | ||
'$then', | ||
`${pointer}/then`, | ||
pointer, | ||
false, | ||
`validates["${pointer}/if"](data)`, | ||
undefined, | ||
'object' | ||
)) | ||
} | ||
if (schema.else) { | ||
node.children = node.children ?? [] | ||
node.children.push(makeSkeletonNode( | ||
schema.else, | ||
options, | ||
validates, | ||
validationErrors, | ||
normalizedLayouts, | ||
expressions, | ||
'$else', | ||
`${pointer}/else`, | ||
pointer, | ||
false, | ||
`!validates["${pointer}/if"](data)`, | ||
undefined, | ||
'object' | ||
)) | ||
} | ||
} | ||
} | ||
@@ -210,0 +296,0 @@ |
import type ajvModule from 'ajv/dist/2019.js' | ||
import type MarkdownIt from 'markdown-it' | ||
import { type ComponentInfo, type BaseCompObject, type NormalizedLayout, type StateNodeOptionsBase } from '@json-layout/vocabulary' | ||
import { type ComponentInfo, type BaseCompObject, type NormalizedLayout, type StateNodeOptionsBase, type Expression } from '@json-layout/vocabulary' | ||
import { type ValidateFunction, type SchemaObject, type ErrorObject } from 'ajv/dist/2019.js' | ||
@@ -19,2 +19,3 @@ import { type Display } from '../state/utils/display.js' | ||
layout: BaseCompObject, | ||
validates: Record<string, ValidateFunction>, | ||
rootData?: unknown, | ||
@@ -71,4 +72,5 @@ parent?: ParentContextExpression | null | ||
roPropertyKeys: string[] | ||
condition?: Expression | ||
children?: SkeletonNode[] // optional children in the case of arrays and object nodes | ||
childrenTrees?: SkeletonTree[] // other trees that can be instantiated with separate validation (for example in the case of new array items of oneOfs, etc) | ||
} |
@@ -374,3 +374,2 @@ // eslint-disable-next-line import/no-named-default | ||
/** | ||
* @private | ||
* @param {StateNode} node | ||
@@ -382,3 +381,3 @@ * @param {import('@json-layout/vocabulary').Expression} expression | ||
evalNodeExpression (node, expression, data) { | ||
return evalExpression(this.compiledLayout.expressions, expression, data, node.options, new Display(node.width), node.layout, this._data, this.getParentContextExpression(node)) | ||
return evalExpression(this.compiledLayout.expressions, expression, data, node.options, new Display(node.width), node.layout, this.compiledLayout.validates, this._data, this.getParentContextExpression(node)) | ||
} | ||
@@ -385,0 +384,0 @@ |
@@ -173,2 +173,3 @@ import { isSwitchStruct, childIsCompObject, isCompositeLayout, isFocusableLayout } from '@json-layout/vocabulary' | ||
* @param {import('@json-layout/vocabulary').BaseCompObject} layout | ||
* @param {Record<string, import('ajv').ValidateFunction>} validates | ||
* @param {unknown} rootData | ||
@@ -178,8 +179,8 @@ * @param {import('../compile/types.js').ParentContextExpression | null} parentContext | ||
*/ | ||
export function evalExpression (expressions, expression, data, options, display, layout, rootData, parentContext) { | ||
export function evalExpression (expressions, expression, data, options, display, layout, validates, rootData, parentContext) { | ||
if (expression.ref === undefined) throw new Error('expression was not compiled : ' + JSON.stringify(expression)) | ||
const compiledExpression = expressions[expression.ref] | ||
return expression.pure | ||
? compiledExpression(data, options, options.context, display, layout) | ||
: compiledExpression(data, options, options.context, display, layout, rootData, parentContext) | ||
? compiledExpression(data, options, options.context, display, layout, validates) | ||
: compiledExpression(data, options, options.context, display, layout, validates, rootData, parentContext) | ||
} | ||
@@ -200,3 +201,3 @@ | ||
for (const compObject of normalizedLayout.switch) { | ||
if (!compObject.if || !!evalExpression(compiledLayout.expressions, compObject.if, data, options, display, compObject, rootData, parentContext)) { | ||
if (!compObject.if || !!evalExpression(compiledLayout.expressions, compObject.if, data, options, display, compObject, compiledLayout.validates, rootData, parentContext)) { | ||
return compObject | ||
@@ -207,3 +208,3 @@ } | ||
if (normalizedLayout.if) { | ||
if (evalExpression(compiledLayout.expressions, normalizedLayout.if, data, options, display, normalizedLayout, rootData, parentContext)) { | ||
if (evalExpression(compiledLayout.expressions, normalizedLayout.if, data, options, display, normalizedLayout, compiledLayout.validates, rootData, parentContext)) { | ||
return normalizedLayout | ||
@@ -276,3 +277,3 @@ } | ||
parentOptions, | ||
evalExpression(compiledLayout.expressions, layout.getOptions, data, parentOptions, display, layout, context.rootData, parentContext) | ||
evalExpression(compiledLayout.expressions, layout.getOptions, data, parentOptions, display, layout, compiledLayout.validates, context.rootData, parentContext) | ||
) | ||
@@ -300,2 +301,7 @@ : parentOptions | ||
const childSkeleton = skeleton.children?.find(c => c.key === childLayout.key) ?? skeleton | ||
if (childSkeleton.condition) { | ||
if (!evalExpression(compiledLayout.expressions, childSkeleton.condition, objectData, parentOptions, display, layout, compiledLayout.validates, context.rootData, parentContext)) { | ||
continue | ||
} | ||
} | ||
const isSameData = typeof childLayout.key === 'string' && childLayout.key.startsWith('$') | ||
@@ -436,3 +442,3 @@ const childFullKey = `${fullKey}/${childLayout.key}` | ||
if (!context.rehydrate) { | ||
nodeData = evalExpression(compiledLayout.expressions, layout.getConstData, nodeData, options, display, layout, context.rootData, parentContext) | ||
nodeData = evalExpression(compiledLayout.expressions, layout.getConstData, nodeData, options, display, layout, compiledLayout.validates, context.rootData, parentContext) | ||
} | ||
@@ -442,3 +448,3 @@ } else { | ||
if (!context.rehydrate) { | ||
nodeData = evalExpression(compiledLayout.expressions, layout.getDefaultData, nodeData, options, display, layout, context.rootData, parentContext) | ||
nodeData = evalExpression(compiledLayout.expressions, layout.getDefaultData, nodeData, options, display, layout, compiledLayout.validates, context.rootData, parentContext) | ||
} | ||
@@ -463,3 +469,3 @@ } else { | ||
if (layout.getProps) { | ||
props = evalExpression(compiledLayout.expressions, layout.getProps, nodeData, options, display, layout, context.rootData, parentContext) | ||
props = evalExpression(compiledLayout.expressions, layout.getProps, nodeData, options, display, layout, compiledLayout.validates, context.rootData, parentContext) | ||
} | ||
@@ -466,0 +472,0 @@ |
@@ -12,5 +12,8 @@ /** | ||
* @param {boolean} required | ||
* @param {string} [condition] | ||
* @param {boolean} [dependent] | ||
* @param {string} [knownType] | ||
* @returns {import('./types.js').SkeletonNode} | ||
*/ | ||
export function makeSkeletonNode(schema: any, options: import('./index.js').CompileOptions, validates: string[], validationErrors: Record<string, string[]>, normalizedLayouts: Record<string, import('@json-layout/vocabulary').NormalizedLayout>, expressions: import('@json-layout/vocabulary').Expression[], key: string | number, pointer: string, parentPointer: string | null, required: boolean): import('./types.js').SkeletonNode; | ||
export function makeSkeletonNode(schema: any, options: import('./index.js').CompileOptions, validates: string[], validationErrors: Record<string, string[]>, normalizedLayouts: Record<string, import('@json-layout/vocabulary').NormalizedLayout>, expressions: import('@json-layout/vocabulary').Expression[], key: string | number, pointer: string, parentPointer: string | null, required: boolean, condition?: string | undefined, dependent?: boolean | undefined, knownType?: string | undefined): import('./types.js').SkeletonNode; | ||
//# sourceMappingURL=skeleton-node.d.ts.map |
import type ajvModule from 'ajv/dist/2019.js'; | ||
import type MarkdownIt from 'markdown-it'; | ||
import { type ComponentInfo, type BaseCompObject, type NormalizedLayout, type StateNodeOptionsBase } from '@json-layout/vocabulary'; | ||
import { type ComponentInfo, type BaseCompObject, type NormalizedLayout, type StateNodeOptionsBase, type Expression } from '@json-layout/vocabulary'; | ||
import { type ValidateFunction, type SchemaObject } from 'ajv/dist/2019.js'; | ||
@@ -11,3 +11,3 @@ import { type Display } from '../state/utils/display.js'; | ||
} | ||
export type CompiledExpression = (data: any, options: StateNodeOptionsBase, context: object, display: Display, layout: BaseCompObject, rootData?: unknown, parent?: ParentContextExpression | null) => any; | ||
export type CompiledExpression = (data: any, options: StateNodeOptionsBase, context: object, display: Display, layout: BaseCompObject, validates: Record<string, ValidateFunction>, rootData?: unknown, parent?: ParentContextExpression | null) => any; | ||
export interface CompileOptions { | ||
@@ -52,2 +52,3 @@ ajv: ajvModule.default; | ||
roPropertyKeys: string[]; | ||
condition?: Expression; | ||
children?: SkeletonNode[]; | ||
@@ -54,0 +55,0 @@ childrenTrees?: SkeletonTree[]; |
@@ -185,3 +185,2 @@ export { Display } from "./utils/display.js"; | ||
/** | ||
* @private | ||
* @param {StateNode} node | ||
@@ -192,3 +191,3 @@ * @param {import('@json-layout/vocabulary').Expression} expression | ||
*/ | ||
private evalNodeExpression; | ||
evalNodeExpression(node: StateNode, expression: import('@json-layout/vocabulary').Expression, data: any): any; | ||
/** | ||
@@ -195,0 +194,0 @@ * @private |
@@ -8,2 +8,3 @@ /** | ||
* @param {import('@json-layout/vocabulary').BaseCompObject} layout | ||
* @param {Record<string, import('ajv').ValidateFunction>} validates | ||
* @param {unknown} rootData | ||
@@ -13,3 +14,3 @@ * @param {import('../compile/types.js').ParentContextExpression | null} parentContext | ||
*/ | ||
export function evalExpression(expressions: import('../index.js').CompiledExpression[], expression: import('@json-layout/vocabulary').Expression, data: any, options: import('./types.js').StateNodeOptions, display: import('./utils/display.js').Display, layout: import('@json-layout/vocabulary').BaseCompObject, rootData: unknown, parentContext: import('../compile/types.js').ParentContextExpression | null): any; | ||
export function evalExpression(expressions: import('../index.js').CompiledExpression[], expression: import('@json-layout/vocabulary').Expression, data: any, options: import('./types.js').StateNodeOptions, display: import('./utils/display.js').Display, layout: import('@json-layout/vocabulary').BaseCompObject, validates: Record<string, import('ajv').ValidateFunction>, rootData: unknown, parentContext: import('../compile/types.js').ParentContextExpression | null): any; | ||
/** | ||
@@ -16,0 +17,0 @@ * |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
140850
11
3178
+ Added@json-layout/vocabulary@0.18.0(transitive)
- Removedrecast@^0.23.4
- Removed@json-layout/vocabulary@0.17.0(transitive)
- Removedast-types@0.16.1(transitive)
- Removedesprima@4.0.1(transitive)
- Removedrecast@0.23.9(transitive)
- Removedsource-map@0.6.1(transitive)
- Removedtiny-invariant@1.3.3(transitive)
- Removedtslib@2.7.0(transitive)