-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy pathbuilder-data.ts
More file actions
158 lines (126 loc) · 3.66 KB
/
Copy pathbuilder-data.ts
File metadata and controls
158 lines (126 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import { REFERENCE } from '@/executor/constants'
export interface JSONProperty {
id: string
name: string
type: string
value: unknown
collapsed?: boolean
}
/**
* Converts builder data (structured JSON properties) into a plain JSON object.
*/
export function convertBuilderDataToJson(builderData: JSONProperty[]): Record<string, unknown> {
if (!Array.isArray(builderData)) {
return {}
}
const result: Record<string, unknown> = {}
for (const prop of builderData) {
if (!prop.name || !prop.name.trim()) {
continue
}
const value = convertPropertyValue(prop)
result[prop.name] = value
}
return result
}
/**
* Converts builder data into a JSON string with variable references unquoted.
*/
export function convertBuilderDataToJsonString(builderData: JSONProperty[]): string {
if (!Array.isArray(builderData) || builderData.length === 0) {
return '{\n \n}'
}
const result: Record<string, unknown> = {}
for (const prop of builderData) {
if (!prop.name || !prop.name.trim()) {
continue
}
result[prop.name] = prop.value
}
let jsonString = JSON.stringify(result, null, 2)
jsonString = jsonString.replace(/"(<[^>]+>)"/g, '$1')
return jsonString
}
export function convertPropertyValue(prop: JSONProperty): unknown {
switch (prop.type) {
case 'object':
return convertObjectValue(prop.value)
case 'array':
return convertArrayValue(prop.value)
case 'number':
return convertNumberValue(prop.value)
case 'boolean':
return convertBooleanValue(prop.value)
case 'files':
return prop.value
default:
return prop.value
}
}
function convertObjectValue(value: unknown): unknown {
if (Array.isArray(value)) {
return convertBuilderDataToJson(value as JSONProperty[])
}
if (typeof value === 'string' && !isVariableReference(value)) {
return tryParseJson(value, value)
}
return value
}
function convertArrayValue(value: unknown): unknown {
if (Array.isArray(value)) {
return value.map((item: unknown) => convertArrayItem(item))
}
if (typeof value === 'string' && !isVariableReference(value)) {
const parsed = tryParseJson(value, value)
return Array.isArray(parsed) ? parsed : value
}
return value
}
function convertArrayItem(item: unknown): unknown {
if (typeof item !== 'object' || item === null || !('type' in item)) {
return item
}
const record = item as Record<string, unknown>
if (typeof record.type !== 'string') {
return item
}
const typed = record as { type: string; value: unknown }
if (typed.type === 'object' && Array.isArray(typed.value)) {
return convertBuilderDataToJson(typed.value as JSONProperty[])
}
if (typed.type === 'array' && Array.isArray(typed.value)) {
return (typed.value as unknown[]).map((subItem: unknown) =>
typeof subItem === 'object' && subItem !== null && 'value' in subItem
? (subItem as { value: unknown }).value
: subItem
)
}
return typed.value
}
function convertNumberValue(value: unknown): unknown {
if (isVariableReference(value)) {
return value
}
const numValue = Number(value)
return Number.isNaN(numValue) ? value : numValue
}
function convertBooleanValue(value: unknown): unknown {
if (isVariableReference(value)) {
return value
}
return value === 'true' || value === true
}
function tryParseJson(jsonString: string, fallback: unknown): unknown {
try {
return JSON.parse(jsonString)
} catch {
return fallback
}
}
function isVariableReference(value: unknown): boolean {
return (
typeof value === 'string' &&
value.trim().startsWith(REFERENCE.START) &&
value.trim().includes(REFERENCE.END)
)
}