@datenlotse/jsonjoy-builder 0.4.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -0
  3. package/dist/components/SchemaEditor/AddFieldButton.js +312 -0
  4. package/dist/components/SchemaEditor/JsonSchemaEditor.js +166 -0
  5. package/dist/components/SchemaEditor/JsonSchemaVisualizer.js +96 -0
  6. package/dist/components/SchemaEditor/SchemaField.js +104 -0
  7. package/dist/components/SchemaEditor/SchemaFieldList.js +84 -0
  8. package/dist/components/SchemaEditor/SchemaPropertyEditor.js +249 -0
  9. package/dist/components/SchemaEditor/SchemaTypeSelector.js +55 -0
  10. package/dist/components/SchemaEditor/SchemaVisualEditor.js +77 -0
  11. package/dist/components/SchemaEditor/TypeDropdown.js +72 -0
  12. package/dist/components/SchemaEditor/TypeEditor.js +71 -0
  13. package/dist/components/SchemaEditor/types/ArrayEditor.js +173 -0
  14. package/dist/components/SchemaEditor/types/BooleanEditor.js +107 -0
  15. package/dist/components/SchemaEditor/types/NumberEditor.js +583 -0
  16. package/dist/components/SchemaEditor/types/ObjectEditor.js +90 -0
  17. package/dist/components/SchemaEditor/types/StringEditor.js +542 -0
  18. package/dist/components/features/JsonValidator.js +239 -0
  19. package/dist/components/features/SchemaInferencer.js +107 -0
  20. package/dist/components/ui/badge.js +25 -0
  21. package/dist/components/ui/button.js +41 -0
  22. package/dist/components/ui/dialog.js +73 -0
  23. package/dist/components/ui/input.js +11 -0
  24. package/dist/components/ui/label.js +13 -0
  25. package/dist/components/ui/select.js +90 -0
  26. package/dist/components/ui/switch.js +14 -0
  27. package/dist/components/ui/tabs.js +24 -0
  28. package/dist/components/ui/tooltip.js +15 -0
  29. package/dist/hooks/use-monaco-theme.js +197 -0
  30. package/dist/hooks/use-translation.js +14 -0
  31. package/dist/i18n/locales/de.js +143 -0
  32. package/dist/i18n/locales/en.js +143 -0
  33. package/dist/i18n/locales/es.js +143 -0
  34. package/dist/i18n/locales/fr.js +143 -0
  35. package/dist/i18n/locales/ru.js +143 -0
  36. package/dist/i18n/locales/uk.js +143 -0
  37. package/dist/i18n/locales/zh.js +143 -0
  38. package/dist/i18n/translation-context.js +4 -0
  39. package/dist/i18n/translation-keys.js +0 -0
  40. package/dist/index.css +3830 -0
  41. package/dist/index.d.ts +995 -0
  42. package/dist/index.js +10 -0
  43. package/dist/lib/schema-inference.js +266 -0
  44. package/dist/lib/schemaCompile.js +113 -0
  45. package/dist/lib/schemaEditor.js +167 -0
  46. package/dist/lib/utils.js +40 -0
  47. package/dist/types/jsonSchema.js +98 -0
  48. package/dist/types/validation.js +215 -0
  49. package/dist/utils/jsonValidator.js +162 -0
  50. package/package.json +112 -0
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import JsonSchemaEditor from "./components/SchemaEditor/JsonSchemaEditor.js";
2
+ import JsonSchemaVisualizer from "./components/SchemaEditor/JsonSchemaVisualizer.js";
3
+ import SchemaVisualEditor from "./components/SchemaEditor/SchemaVisualEditor.js";
4
+ export * from "./components/features/JsonValidator.js";
5
+ export * from "./components/features/SchemaInferencer.js";
6
+ export * from "./i18n/locales/de.js";
7
+ export * from "./i18n/locales/en.js";
8
+ export * from "./i18n/translation-context.js";
9
+ export * from "./i18n/translation-keys.js";
10
+ export { JsonSchemaEditor, JsonSchemaVisualizer, SchemaVisualEditor };
@@ -0,0 +1,266 @@
1
+ import { asObjectSchema } from "../types/jsonSchema.js";
2
+ function mergeSchemas(schema1, schema2) {
3
+ const s1 = asObjectSchema(schema1);
4
+ const s2 = asObjectSchema(schema2);
5
+ if (JSON.stringify(s1) === JSON.stringify(s2)) return schema1;
6
+ if ("integer" === s1.type && "number" === s2.type) return {
7
+ type: "number"
8
+ };
9
+ if ("number" === s1.type && "integer" === s2.type) return {
10
+ type: "number"
11
+ };
12
+ const existingOneOf = Array.isArray(s1.oneOf) ? s1.oneOf : [
13
+ s1
14
+ ];
15
+ const newSchemaToAdd = s2;
16
+ if (!existingOneOf.some((s)=>JSON.stringify(s) === JSON.stringify(newSchemaToAdd))) {
17
+ const mergedOneOf = [
18
+ ...existingOneOf,
19
+ newSchemaToAdd
20
+ ];
21
+ const uniqueSchemas = [
22
+ ...new Map(mergedOneOf.map((s)=>[
23
+ JSON.stringify(s),
24
+ s
25
+ ])).values()
26
+ ];
27
+ if (1 === uniqueSchemas.length) return uniqueSchemas[0];
28
+ return {
29
+ oneOf: uniqueSchemas
30
+ };
31
+ }
32
+ return s1.oneOf ? s1 : {
33
+ oneOf: [
34
+ s1
35
+ ]
36
+ };
37
+ }
38
+ function inferObjectSchema(obj) {
39
+ const properties = {};
40
+ const required = [];
41
+ for (const [key, value] of Object.entries(obj)){
42
+ properties[key] = inferSchema(value);
43
+ if (null != value) required.push(key);
44
+ }
45
+ return {
46
+ type: "object",
47
+ properties,
48
+ required: required.length > 0 ? required.sort() : void 0
49
+ };
50
+ }
51
+ function detectEnumsInArrayItems(mergedProperties, originalArray, totalItems) {
52
+ if (totalItems < 10 || 0 === Object.keys(mergedProperties).length) return mergedProperties;
53
+ const valueMap = {};
54
+ for (const item of originalArray)for(const key in mergedProperties)if (Object.prototype.hasOwnProperty.call(item, key)) {
55
+ const value = item[key];
56
+ if ("string" == typeof value || "number" == typeof value) {
57
+ if (!valueMap[key]) valueMap[key] = new Set();
58
+ valueMap[key].add(value);
59
+ }
60
+ }
61
+ const updatedProperties = {
62
+ ...mergedProperties
63
+ };
64
+ for(const key in valueMap){
65
+ const distinctValues = Array.from(valueMap[key]);
66
+ if (distinctValues.length > 1 && distinctValues.length <= 10 && distinctValues.length < totalItems / 2) {
67
+ const currentSchema = asObjectSchema(updatedProperties[key]);
68
+ if ("string" === currentSchema.type || "number" === currentSchema.type || "integer" === currentSchema.type) updatedProperties[key] = {
69
+ type: currentSchema.type,
70
+ enum: distinctValues.sort()
71
+ };
72
+ }
73
+ }
74
+ return updatedProperties;
75
+ }
76
+ function detectSemanticFormatsInArrayItems(mergedProperties, originalArray) {
77
+ const updatedProperties = {
78
+ ...mergedProperties
79
+ };
80
+ for(const key in updatedProperties){
81
+ const currentSchema = asObjectSchema(updatedProperties[key]);
82
+ if (/coordinates?|coords?|latLon|lonLat|point/i.test(key) && "array" === currentSchema.type) {
83
+ const itemsSchema = asObjectSchema(currentSchema.items);
84
+ if (itemsSchema?.type === "number" || itemsSchema?.type === "integer") {
85
+ let isValidCoordArray = true;
86
+ let coordLength = null;
87
+ for (const item of originalArray)if (Object.prototype.hasOwnProperty.call(item, key) && Array.isArray(item[key])) {
88
+ const arr = item[key];
89
+ if (null === coordLength) coordLength = arr.length;
90
+ if (arr.length !== coordLength || 2 !== arr.length && 3 !== arr.length || !arr.every((v)=>"number" == typeof v)) {
91
+ isValidCoordArray = false;
92
+ break;
93
+ }
94
+ } else if (Object.prototype.hasOwnProperty.call(item, key)) {
95
+ isValidCoordArray = false;
96
+ break;
97
+ }
98
+ if (isValidCoordArray && null !== coordLength) updatedProperties[key] = {
99
+ type: "array",
100
+ items: {
101
+ type: "number"
102
+ },
103
+ minItems: coordLength,
104
+ maxItems: coordLength
105
+ };
106
+ }
107
+ }
108
+ if (/timestamp|createdAt|updatedAt|occurredAt/i.test(key) && "integer" === currentSchema.type) {
109
+ let isTimestampLike = true;
110
+ const now = Date.now();
111
+ const fiftyYearsAgo = now - 1576800000000;
112
+ for (const item of originalArray)if (Object.prototype.hasOwnProperty.call(item, key)) {
113
+ const val = item[key];
114
+ if ("number" != typeof val || !Number.isInteger(val) || val < fiftyYearsAgo) {
115
+ isTimestampLike = false;
116
+ break;
117
+ }
118
+ }
119
+ if (isTimestampLike) updatedProperties[key] = {
120
+ type: "integer",
121
+ format: "unix-timestamp",
122
+ description: "Unix timestamp (likely milliseconds)"
123
+ };
124
+ }
125
+ }
126
+ return updatedProperties;
127
+ }
128
+ function processArrayOfObjects(itemSchemas, originalArray) {
129
+ let mergedProperties = {};
130
+ const propertyCounts = {};
131
+ const totalItems = itemSchemas.length;
132
+ for (const schema of itemSchemas){
133
+ const objSchema = asObjectSchema(schema);
134
+ if (objSchema.properties) for (const [key, value] of Object.entries(objSchema.properties)){
135
+ propertyCounts[key] = (propertyCounts[key] || 0) + 1;
136
+ if (key in mergedProperties) mergedProperties[key] = mergeSchemas(mergedProperties[key], value);
137
+ else mergedProperties[key] = value;
138
+ }
139
+ }
140
+ const requiredProps = Object.entries(propertyCounts).filter(([_, count])=>count === totalItems).map(([key, _])=>key);
141
+ mergedProperties = detectEnumsInArrayItems(mergedProperties, originalArray, totalItems);
142
+ mergedProperties = detectSemanticFormatsInArrayItems(mergedProperties, originalArray);
143
+ return {
144
+ type: "object",
145
+ properties: mergedProperties,
146
+ required: requiredProps.length > 0 ? requiredProps.sort() : void 0
147
+ };
148
+ }
149
+ function inferArraySchema(obj) {
150
+ if (0 === obj.length) return {
151
+ type: "array",
152
+ items: {}
153
+ };
154
+ const itemSchemas = obj.map((item)=>inferSchema(item));
155
+ const firstItemSchema = asObjectSchema(itemSchemas[0]);
156
+ const allSameType = itemSchemas.every((schema)=>asObjectSchema(schema).type === firstItemSchema.type);
157
+ if (allSameType) {
158
+ if ("object" === firstItemSchema.type) {
159
+ const itemsSchema = processArrayOfObjects(itemSchemas, obj);
160
+ return {
161
+ type: "array",
162
+ items: itemsSchema,
163
+ minItems: 0
164
+ };
165
+ }
166
+ return {
167
+ type: "array",
168
+ items: itemSchemas[0],
169
+ minItems: 0
170
+ };
171
+ }
172
+ const uniqueSchemas = [
173
+ ...new Map(itemSchemas.map((s)=>[
174
+ JSON.stringify(s),
175
+ s
176
+ ])).values()
177
+ ];
178
+ if (1 === uniqueSchemas.length && "object" === asObjectSchema(uniqueSchemas[0]).type) return {
179
+ type: "array",
180
+ items: uniqueSchemas[0],
181
+ minItems: 0
182
+ };
183
+ return {
184
+ type: "array",
185
+ items: 1 === uniqueSchemas.length ? uniqueSchemas[0] : {
186
+ oneOf: uniqueSchemas
187
+ },
188
+ minItems: 0
189
+ };
190
+ }
191
+ function inferStringSchema(str) {
192
+ const formats = {
193
+ date: /^\d{4}-\d{2}-\d{2}$/,
194
+ "date-time": /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?$/,
195
+ email: /^[^@]+@[^@]+\.[^@]+$/,
196
+ uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
197
+ uri: /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/i
198
+ };
199
+ for (const [format, regex] of Object.entries(formats))if (regex.test(str)) return {
200
+ type: "string",
201
+ format
202
+ };
203
+ return {
204
+ type: "string"
205
+ };
206
+ }
207
+ function inferNumberSchema(num) {
208
+ return Number.isInteger(num) ? {
209
+ type: "integer"
210
+ } : {
211
+ type: "number"
212
+ };
213
+ }
214
+ function inferSchema(obj) {
215
+ if (null === obj) return {
216
+ type: "null"
217
+ };
218
+ const type = Array.isArray(obj) ? "array" : typeof obj;
219
+ switch(type){
220
+ case "object":
221
+ return inferObjectSchema(obj);
222
+ case "array":
223
+ return inferArraySchema(obj);
224
+ case "string":
225
+ return inferStringSchema(obj);
226
+ case "number":
227
+ return inferNumberSchema(obj);
228
+ case "boolean":
229
+ return {
230
+ type: "boolean"
231
+ };
232
+ default:
233
+ return {};
234
+ }
235
+ }
236
+ function createSchemaFromJson(jsonObject) {
237
+ const inferredSchema = inferSchema(jsonObject);
238
+ const rootSchema = asObjectSchema(inferredSchema);
239
+ const finalSchema = {
240
+ $schema: "https://json-schema.org/draft-07/schema",
241
+ title: "Generated Schema",
242
+ description: "Generated from JSON data"
243
+ };
244
+ if ("object" === rootSchema.type || rootSchema.properties) {
245
+ finalSchema.type = "object";
246
+ finalSchema.properties = rootSchema.properties;
247
+ if (rootSchema.required) finalSchema.required = rootSchema.required;
248
+ } else if ("array" === rootSchema.type || rootSchema.items) {
249
+ finalSchema.type = "array";
250
+ finalSchema.items = rootSchema.items;
251
+ if (void 0 !== rootSchema.minItems) finalSchema.minItems = rootSchema.minItems;
252
+ if (void 0 !== rootSchema.maxItems) finalSchema.maxItems = rootSchema.maxItems;
253
+ } else if (rootSchema.type) {
254
+ finalSchema.type = "object";
255
+ finalSchema.properties = {
256
+ value: rootSchema
257
+ };
258
+ finalSchema.required = [
259
+ "value"
260
+ ];
261
+ finalSchema.title = "Generated Schema (Primitive Root)";
262
+ finalSchema.description = "Input was a primitive value, wrapped in an object.";
263
+ } else finalSchema.type = "object";
264
+ return finalSchema;
265
+ }
266
+ export { createSchemaFromJson, inferSchema };
@@ -0,0 +1,113 @@
1
+ import { copySchema } from "./schemaEditor.js";
2
+ import { isBooleanSchema } from "../types/jsonSchema.js";
3
+ function compileDependentEnums(schema) {
4
+ if (isBooleanSchema(schema)) return schema;
5
+ const transformed = copySchema(schema);
6
+ return transformObject(transformed);
7
+ }
8
+ function transformObject(obj) {
9
+ if (!obj.properties) return obj;
10
+ const props = {
11
+ ...obj.properties
12
+ };
13
+ for (const key of Object.keys(props)){
14
+ const child = props[key];
15
+ if ("object" == typeof child && null !== child) props[key] = transformSchema(child);
16
+ }
17
+ const dependentProp = Object.entries(props).find(([, s])=>"object" == typeof s && null !== s && "$dependentEnum" in s && null != s.$dependentEnum);
18
+ if (!dependentProp) return {
19
+ ...obj,
20
+ properties: props
21
+ };
22
+ const [propName, propSchema] = dependentProp;
23
+ const dep = propSchema.$dependentEnum;
24
+ if (!dep) return {
25
+ ...obj,
26
+ properties: props
27
+ };
28
+ const controllingName = dep.property;
29
+ const valuesMap = dep.values;
30
+ const controllingValues = Object.keys(valuesMap);
31
+ const oneOfBranches = controllingValues.map((ctrlValue)=>{
32
+ const branchProps = {
33
+ ...props
34
+ };
35
+ const controllingSchema = branchProps[controllingName];
36
+ if ("object" == typeof controllingSchema && null !== controllingSchema) branchProps[controllingName] = {
37
+ ...controllingSchema,
38
+ const: ctrlValue
39
+ };
40
+ else branchProps[controllingName] = {
41
+ const: ctrlValue
42
+ };
43
+ const dependentSchema = branchProps[propName];
44
+ if ("object" == typeof dependentSchema && null !== dependentSchema) {
45
+ const { $dependentEnum: _d, ...rest } = dependentSchema;
46
+ branchProps[propName] = {
47
+ ...rest,
48
+ enum: valuesMap[ctrlValue] ?? []
49
+ };
50
+ }
51
+ return {
52
+ type: "object",
53
+ properties: branchProps,
54
+ required: obj.required,
55
+ $propertyOrder: obj.$propertyOrder
56
+ };
57
+ });
58
+ return {
59
+ ...obj.$schema && {
60
+ $schema: obj.$schema
61
+ },
62
+ ...obj.$id && {
63
+ $id: obj.$id
64
+ },
65
+ type: "object",
66
+ oneOf: oneOfBranches
67
+ };
68
+ }
69
+ function transformSchema(schema) {
70
+ if (isBooleanSchema(schema)) return schema;
71
+ const obj = schema;
72
+ if (obj.properties) return transformObject(obj);
73
+ if (obj.items && "object" == typeof obj.items) return {
74
+ ...obj,
75
+ items: transformSchema(obj.items)
76
+ };
77
+ if (obj.prefixItems && Array.isArray(obj.prefixItems)) return {
78
+ ...obj,
79
+ prefixItems: obj.prefixItems.map((s)=>transformSchema(s))
80
+ };
81
+ if (obj.additionalProperties && "object" == typeof obj.additionalProperties) return {
82
+ ...obj,
83
+ additionalProperties: transformSchema(obj.additionalProperties)
84
+ };
85
+ if (obj.oneOf && Array.isArray(obj.oneOf)) return {
86
+ ...obj,
87
+ oneOf: obj.oneOf.map(transformSchema)
88
+ };
89
+ if (obj.anyOf && Array.isArray(obj.anyOf)) return {
90
+ ...obj,
91
+ anyOf: obj.anyOf.map(transformSchema)
92
+ };
93
+ if (obj.allOf && Array.isArray(obj.allOf)) return {
94
+ ...obj,
95
+ allOf: obj.allOf.map(transformSchema)
96
+ };
97
+ if (obj.if && "object" == typeof obj.if) return {
98
+ ...obj,
99
+ if: transformSchema(obj.if),
100
+ then: obj.then ? transformSchema(obj.then) : void 0,
101
+ else: obj.else ? transformSchema(obj.else) : void 0
102
+ };
103
+ if (obj.$defs) {
104
+ const defs = {};
105
+ for (const k of Object.keys(obj.$defs))defs[k] = transformSchema(obj.$defs[k]);
106
+ return {
107
+ ...obj,
108
+ $defs: defs
109
+ };
110
+ }
111
+ return obj;
112
+ }
113
+ export { compileDependentEnums };
@@ -0,0 +1,167 @@
1
+ import { isBooleanSchema, isObjectSchema } from "../types/jsonSchema.js";
2
+ function copySchema(schema) {
3
+ if ("function" == typeof structuredClone) return structuredClone(schema);
4
+ return JSON.parse(JSON.stringify(schema));
5
+ }
6
+ function updateObjectProperty(schema, propertyName, propertySchema) {
7
+ if (!isObjectSchema(schema)) return schema;
8
+ const newSchema = copySchema(schema);
9
+ if (!newSchema.properties) newSchema.properties = {};
10
+ const isNewProperty = !(propertyName in newSchema.properties);
11
+ newSchema.properties[propertyName] = propertySchema;
12
+ if (newSchema.$propertyOrder) {
13
+ if (isNewProperty && !newSchema.$propertyOrder.includes(propertyName)) newSchema.$propertyOrder.push(propertyName);
14
+ } else newSchema.$propertyOrder = Object.keys(newSchema.properties);
15
+ return newSchema;
16
+ }
17
+ function removeObjectProperty(schema, propertyName) {
18
+ if (!isObjectSchema(schema) || !schema.properties) return schema;
19
+ const newSchema = copySchema(schema);
20
+ const { [propertyName]: _, ...remainingProps } = newSchema.properties;
21
+ newSchema.properties = remainingProps;
22
+ if (newSchema.required) newSchema.required = newSchema.required.filter((name)=>name !== propertyName);
23
+ if (newSchema.$propertyOrder) newSchema.$propertyOrder = newSchema.$propertyOrder.filter((name)=>name !== propertyName);
24
+ return newSchema;
25
+ }
26
+ function updatePropertyRequired(schema, propertyName, required) {
27
+ if (!isObjectSchema(schema)) return schema;
28
+ const newSchema = copySchema(schema);
29
+ if (!newSchema.required) newSchema.required = [];
30
+ if (required) {
31
+ if (!newSchema.required.includes(propertyName)) newSchema.required.push(propertyName);
32
+ } else newSchema.required = newSchema.required.filter((name)=>name !== propertyName);
33
+ return newSchema;
34
+ }
35
+ function updateArrayItems(schema, itemsSchema) {
36
+ if (isObjectSchema(schema) && "array" === schema.type) return {
37
+ ...schema,
38
+ items: itemsSchema
39
+ };
40
+ return schema;
41
+ }
42
+ function createFieldSchema(field) {
43
+ const { type, description, default: defaultValue, validation } = field;
44
+ if (isObjectSchema(validation)) {
45
+ const schema = {
46
+ type,
47
+ description,
48
+ ...validation
49
+ };
50
+ if (void 0 !== defaultValue) schema.default = defaultValue;
51
+ return schema;
52
+ }
53
+ const schema = validation || {
54
+ type
55
+ };
56
+ if (void 0 !== defaultValue) schema.default = defaultValue;
57
+ return schema;
58
+ }
59
+ function validateFieldName(name) {
60
+ if (!name || "" === name.trim()) return false;
61
+ const validNamePattern = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
62
+ return validNamePattern.test(name);
63
+ }
64
+ function getSchemaProperties(schema) {
65
+ if (!isObjectSchema(schema) || !schema.properties) return [];
66
+ const required = schema.required || [];
67
+ const propertyOrder = schema.$propertyOrder || Object.keys(schema.properties);
68
+ const orderedPropertyNames = propertyOrder.filter((name)=>name in schema.properties);
69
+ const allPropertyNames = Object.keys(schema.properties);
70
+ const missingProperties = allPropertyNames.filter((name)=>!orderedPropertyNames.includes(name));
71
+ const finalOrder = [
72
+ ...orderedPropertyNames,
73
+ ...missingProperties
74
+ ];
75
+ return finalOrder.map((name)=>({
76
+ name,
77
+ schema: schema.properties[name],
78
+ required: required.includes(name)
79
+ }));
80
+ }
81
+ function hasPathTo(graph, from, to) {
82
+ const visited = new Set();
83
+ let current = from;
84
+ while(current){
85
+ if (current === to) return true;
86
+ if (visited.has(current)) break;
87
+ visited.add(current);
88
+ current = graph.get(current);
89
+ }
90
+ return false;
91
+ }
92
+ function getEligibleEnumControllingProperties(parentSchema, propertyName) {
93
+ if (!parentSchema.properties) return [];
94
+ const graph = new Map();
95
+ for (const k of Object.keys(parentSchema.properties)){
96
+ const prop = parentSchema.properties[k];
97
+ if ("object" != typeof prop || null === prop) continue;
98
+ const dep = prop.$dependentEnum?.property;
99
+ if (dep) graph.set(k, dep);
100
+ }
101
+ const result = [];
102
+ const siblings = Object.keys(parentSchema.properties).filter((n)=>n !== propertyName);
103
+ for (const name of siblings){
104
+ if (hasPathTo(graph, name, propertyName)) continue;
105
+ const prop = parentSchema.properties[name];
106
+ if ("boolean" == typeof prop) continue;
107
+ if (!prop) continue;
108
+ let values;
109
+ if (Array.isArray(prop.enum) && prop.enum.length > 0) values = prop.enum;
110
+ else if (void 0 !== prop.const) values = [
111
+ prop.const
112
+ ];
113
+ if (void 0 !== values) result.push({
114
+ name,
115
+ values
116
+ });
117
+ }
118
+ return result;
119
+ }
120
+ function getArrayItemsSchema(schema) {
121
+ if (isBooleanSchema(schema)) return null;
122
+ if ("array" !== schema.type) return null;
123
+ return schema.items || null;
124
+ }
125
+ function renameObjectProperty(schema, oldName, newName) {
126
+ if (!isObjectSchema(schema) || !schema.properties) return schema;
127
+ const newSchema = copySchema(schema);
128
+ const newProperties = {};
129
+ const propertyOrder = newSchema.$propertyOrder || Object.keys(newSchema.properties);
130
+ for (const key of propertyOrder)if (key === oldName) newProperties[newName] = newSchema.properties[oldName];
131
+ else if (key in newSchema.properties) newProperties[key] = newSchema.properties[key];
132
+ for (const [key, value] of Object.entries(newSchema.properties))if (!(key in newProperties)) newProperties[key] = value;
133
+ newSchema.properties = newProperties;
134
+ if (newSchema.required) newSchema.required = newSchema.required.map((field)=>field === oldName ? newName : field);
135
+ if (newSchema.$propertyOrder) newSchema.$propertyOrder = newSchema.$propertyOrder.map((name)=>name === oldName ? newName : name);
136
+ return newSchema;
137
+ }
138
+ function reorderObjectProperty(schema, propertyName, direction) {
139
+ if (!isObjectSchema(schema) || !schema.properties) return schema;
140
+ const newSchema = copySchema(schema);
141
+ if (!newSchema.$propertyOrder) newSchema.$propertyOrder = Object.keys(newSchema.properties);
142
+ const propertyOrder = [
143
+ ...newSchema.$propertyOrder
144
+ ];
145
+ const currentIndex = propertyOrder.indexOf(propertyName);
146
+ if (-1 === currentIndex) return schema;
147
+ if ("up" === direction && 0 === currentIndex) return schema;
148
+ if ("down" === direction && currentIndex === propertyOrder.length - 1) return schema;
149
+ const targetIndex = "up" === direction ? currentIndex - 1 : currentIndex + 1;
150
+ [propertyOrder[currentIndex], propertyOrder[targetIndex]] = [
151
+ propertyOrder[targetIndex],
152
+ propertyOrder[currentIndex]
153
+ ];
154
+ const newProperties = {};
155
+ for (const name of propertyOrder)if (name in newSchema.properties) newProperties[name] = newSchema.properties[name];
156
+ for (const [key, value] of Object.entries(newSchema.properties))if (!(key in newProperties)) newProperties[key] = value;
157
+ newSchema.properties = newProperties;
158
+ newSchema.$propertyOrder = propertyOrder;
159
+ return newSchema;
160
+ }
161
+ function hasChildren(schema) {
162
+ if (!isObjectSchema(schema)) return false;
163
+ if ("object" === schema.type && schema.properties) return Object.keys(schema.properties).length > 0;
164
+ if ("array" === schema.type && schema.items && isObjectSchema(schema.items)) return "object" === schema.items.type && !!schema.items.properties;
165
+ return false;
166
+ }
167
+ export { copySchema, createFieldSchema, getArrayItemsSchema, getEligibleEnumControllingProperties, getSchemaProperties, hasChildren, removeObjectProperty, renameObjectProperty, reorderObjectProperty, updateArrayItems, updateObjectProperty, updatePropertyRequired, validateFieldName };
@@ -0,0 +1,40 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
6
+ const getTypeColor = (type)=>{
7
+ switch(type){
8
+ case "string":
9
+ return "text-blue-500 bg-blue-50";
10
+ case "number":
11
+ case "integer":
12
+ return "text-purple-500 bg-purple-50";
13
+ case "boolean":
14
+ return "text-green-500 bg-green-50";
15
+ case "object":
16
+ return "text-orange-500 bg-orange-50";
17
+ case "array":
18
+ return "text-pink-500 bg-pink-50";
19
+ case "null":
20
+ return "text-gray-500 bg-gray-50";
21
+ }
22
+ };
23
+ const getTypeLabel = (t, type)=>{
24
+ switch(type){
25
+ case "string":
26
+ return t.schemaTypeString;
27
+ case "number":
28
+ case "integer":
29
+ return t.schemaTypeNumber;
30
+ case "boolean":
31
+ return t.schemaTypeBoolean;
32
+ case "object":
33
+ return t.schemaTypeObject;
34
+ case "array":
35
+ return t.schemaTypeArray;
36
+ case "null":
37
+ return t.schemaTypeNull;
38
+ }
39
+ };
40
+ export { cn, getTypeColor, getTypeLabel };