@cratis/scene.engine 4.5.0 → 4.6.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/dist/cjs/editing/inspect.js +9 -1
- package/dist/cjs/editing/inspect.js.map +1 -1
- package/dist/cjs/editing/validateValue.js +24 -0
- package/dist/cjs/editing/validateValue.js.map +1 -1
- package/dist/esm/editing/inspect.d.ts.map +1 -1
- package/dist/esm/editing/inspect.js +9 -1
- package/dist/esm/editing/inspect.js.map +1 -1
- package/dist/esm/editing/validateValue.d.ts.map +1 -1
- package/dist/esm/editing/validateValue.js +24 -0
- package/dist/esm/editing/validateValue.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/editing/inspect.ts +11 -1
- package/editing/validateValue.ts +29 -0
- package/package.json +3 -3
package/editing/inspect.ts
CHANGED
|
@@ -45,6 +45,16 @@ function toInspectedItems(raw: unknown, local: boolean): InspectedCollectionItem
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* The value a property takes when nothing configures it. A stored `null` is a real value for a `json` property
|
|
50
|
+
* (it is valid JSON, and clearing it to the default would hide it), so only that type keeps it; every other
|
|
51
|
+
* type falls back to its default for `null` and `undefined` alike.
|
|
52
|
+
*/
|
|
53
|
+
function effectiveValueOf(descriptor: PropertyDescriptor, currentValue: unknown): unknown {
|
|
54
|
+
if (currentValue === null && descriptor.valueType === PropertyValueType.Json) return null;
|
|
55
|
+
return currentValue ?? descriptor.default;
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
function inspectProperty(
|
|
49
59
|
descriptor: PropertyDescriptor,
|
|
50
60
|
record: NodeRecord,
|
|
@@ -61,7 +71,7 @@ function inspectProperty(
|
|
|
61
71
|
const inspected: InspectedProperty = {
|
|
62
72
|
descriptor,
|
|
63
73
|
currentValue,
|
|
64
|
-
effectiveValue: configured ? configured.value : (currentValue
|
|
74
|
+
effectiveValue: configured ? configured.value : effectiveValueOf(descriptor, currentValue),
|
|
65
75
|
source: (configured?.source ?? (currentValue === undefined ? ValueSource.Default : ValueSource.Local)) as ValueSource,
|
|
66
76
|
editable: false,
|
|
67
77
|
};
|
package/editing/validateValue.ts
CHANGED
|
@@ -65,11 +65,40 @@ export function validateValue(descriptor: PropertyDescriptor, value: unknown): s
|
|
|
65
65
|
case PropertyValueType.Collection:
|
|
66
66
|
return validateCollection(descriptor, value);
|
|
67
67
|
|
|
68
|
+
case PropertyValueType.Json:
|
|
69
|
+
return isJsonValue(value) ? undefined : 'expected a JSON value';
|
|
70
|
+
|
|
68
71
|
default:
|
|
69
72
|
return isRecord(value) || Array.isArray(value) ? undefined : 'expected a structured value';
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
/**
|
|
77
|
+
* The deepest nesting a JSON value may have. Authored configuration (chart datasets, option lists) is shallow;
|
|
78
|
+
* the limit turns a runaway or hostile structure into a validation message instead of a stack overflow.
|
|
79
|
+
*/
|
|
80
|
+
const maximumJsonDepth = 64;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Whether a value is JSON: `null`, a string, a boolean, a finite number, or an array or plain object of those.
|
|
84
|
+
* The value is only inspected, never serialized, so what an editor stores is exactly what was passed in.
|
|
85
|
+
*/
|
|
86
|
+
function isJsonValue(value: unknown, parents = new Set<object>()): boolean {
|
|
87
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean') return true;
|
|
88
|
+
if (typeof value === 'number') return Number.isFinite(value);
|
|
89
|
+
if (typeof value !== 'object' || parents.has(value) || parents.size >= maximumJsonDepth) return false;
|
|
90
|
+
|
|
91
|
+
const isArray = Array.isArray(value);
|
|
92
|
+
const prototype = Object.getPrototypeOf(value);
|
|
93
|
+
if (isArray ? prototype !== Array.prototype : prototype !== Object.prototype && prototype !== null) return false;
|
|
94
|
+
|
|
95
|
+
parents.add(value);
|
|
96
|
+
const values = isArray ? Array.from({ length: value.length }, (_, index) => (index in value ? value[index] : undefined)) : Object.values(value);
|
|
97
|
+
const valid = values.every(candidate => isJsonValue(candidate, parents));
|
|
98
|
+
parents.delete(value);
|
|
99
|
+
return valid;
|
|
100
|
+
}
|
|
101
|
+
|
|
73
102
|
function validateCollection(descriptor: PropertyDescriptor, value: unknown): string | undefined {
|
|
74
103
|
if (!Array.isArray(value)) return 'expected a list';
|
|
75
104
|
const constraints = descriptor.constraints ?? {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cratis/scene.engine",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "The Scene runtime: walks a Scene element tree and drives whichever renderer is plugged in. Does not know React, or any other rendering platform, exists.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cratis",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"up": "yarn g:up"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@cratis/scene.model": "4.
|
|
51
|
+
"@cratis/scene.model": "4.6.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@cratis/scene.model": "4.
|
|
54
|
+
"@cratis/scene.model": "4.6.0"
|
|
55
55
|
}
|
|
56
56
|
}
|