@base44-preview/vite-plugin 0.2.26-pr.43.e9195be → 0.2.27-pr.41.77be9cb
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/capabilities/inline-edit/controller.d.ts +3 -0
- package/dist/capabilities/inline-edit/controller.d.ts.map +1 -0
- package/dist/capabilities/inline-edit/controller.js +194 -0
- package/dist/capabilities/inline-edit/controller.js.map +1 -0
- package/dist/capabilities/inline-edit/dom-utils.d.ts +6 -0
- package/dist/capabilities/inline-edit/dom-utils.d.ts.map +1 -0
- package/dist/capabilities/inline-edit/dom-utils.js +49 -0
- package/dist/capabilities/inline-edit/dom-utils.js.map +1 -0
- package/dist/capabilities/inline-edit/index.d.ts +3 -0
- package/dist/capabilities/inline-edit/index.d.ts.map +1 -0
- package/dist/capabilities/inline-edit/index.js +2 -0
- package/dist/capabilities/inline-edit/index.js.map +1 -0
- package/dist/capabilities/inline-edit/types.d.ts +25 -0
- package/dist/capabilities/inline-edit/types.d.ts.map +1 -0
- package/dist/capabilities/inline-edit/types.js.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.d.ts +25 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.js +95 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.js.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.d.ts +4 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.js +4 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.js.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.d.ts +9 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.js +26 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.js.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.d.ts +17 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.js +76 -0
- package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.js.map +1 -0
- package/dist/injections/visual-edit-agent/constants.d.ts +10 -0
- package/dist/injections/visual-edit-agent/constants.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/constants.js +10 -0
- package/dist/injections/visual-edit-agent/constants.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/click-handlers.d.ts +10 -0
- package/dist/injections/visual-edit-agent/handlers/click-handlers.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/click-handlers.js +117 -0
- package/dist/injections/visual-edit-agent/handlers/click-handlers.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/hover-handlers.d.ts +14 -0
- package/dist/injections/visual-edit-agent/handlers/hover-handlers.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/hover-handlers.js +64 -0
- package/dist/injections/visual-edit-agent/handlers/hover-handlers.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.d.ts +14 -0
- package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.js +114 -0
- package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/message-handlers.d.ts +26 -0
- package/dist/injections/visual-edit-agent/handlers/message-handlers.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/message-handlers.js +148 -0
- package/dist/injections/visual-edit-agent/handlers/message-handlers.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.d.ts +7 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.js +54 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.d.ts +11 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.js +32 -0
- package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.js.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/messages/types.d.ts +105 -0
- package/dist/injections/visual-edit-agent/handlers/messages/types.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/handlers/messages/types.js +28 -0
- package/dist/injections/visual-edit-agent/handlers/messages/types.js.map +1 -0
- package/dist/injections/visual-edit-agent/index.d.ts +6 -0
- package/dist/injections/visual-edit-agent/index.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/index.js +109 -0
- package/dist/injections/visual-edit-agent/index.js.map +1 -0
- package/dist/injections/visual-edit-agent/state/agent-state.d.ts +17 -0
- package/dist/injections/visual-edit-agent/state/agent-state.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/state/agent-state.js +18 -0
- package/dist/injections/visual-edit-agent/state/agent-state.js.map +1 -0
- package/dist/injections/visual-edit-agent/ui/overlay.d.ts +26 -0
- package/dist/injections/visual-edit-agent/ui/overlay.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/ui/overlay.js +104 -0
- package/dist/injections/visual-edit-agent/ui/overlay.js.map +1 -0
- package/dist/injections/visual-edit-agent/utils/dom-utils.d.ts +14 -0
- package/dist/injections/visual-edit-agent/utils/dom-utils.d.ts.map +1 -0
- package/dist/injections/visual-edit-agent/utils/dom-utils.js +34 -0
- package/dist/injections/visual-edit-agent/utils/dom-utils.js.map +1 -0
- package/dist/injections/visual-edit-agent.d.ts +1 -1
- package/dist/injections/visual-edit-agent.d.ts.map +1 -1
- package/dist/injections/visual-edit-agent.js +1 -506
- package/dist/injections/visual-edit-agent.js.map +1 -1
- package/dist/jsx-processor.d.ts +1 -4
- package/dist/jsx-processor.d.ts.map +1 -1
- package/dist/jsx-processor.js +6 -33
- package/dist/jsx-processor.js.map +1 -1
- package/dist/jsx-utils.d.ts +0 -9
- package/dist/jsx-utils.d.ts.map +1 -1
- package/dist/jsx-utils.js +0 -86
- package/dist/jsx-utils.js.map +1 -1
- package/dist/processors/shared-utils.d.ts +0 -64
- package/dist/processors/shared-utils.d.ts.map +1 -1
- package/dist/processors/shared-utils.js +0 -468
- package/dist/processors/shared-utils.js.map +1 -1
- package/dist/processors/static-array-processor.d.ts +3 -2
- package/dist/processors/static-array-processor.d.ts.map +1 -1
- package/dist/processors/static-array-processor.js +3 -2
- package/dist/processors/static-array-processor.js.map +1 -1
- package/dist/statics/index.mjs +5 -1
- package/dist/statics/index.mjs.map +1 -1
- package/dist/visual-edit-plugin.d.ts +1 -0
- package/dist/visual-edit-plugin.d.ts.map +1 -1
- package/dist/visual-edit-plugin.js +178 -29
- package/dist/visual-edit-plugin.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities/inline-edit/controller.ts +245 -0
- package/src/capabilities/inline-edit/dom-utils.ts +48 -0
- package/src/capabilities/inline-edit/index.ts +2 -0
- package/src/capabilities/inline-edit/types.ts +30 -0
- package/src/injections/visual-edit-agent/README.md +222 -0
- package/src/injections/visual-edit-agent/capabilities/inline-editing/core.ts +120 -0
- package/src/injections/visual-edit-agent/capabilities/inline-editing/index.ts +10 -0
- package/src/injections/visual-edit-agent/capabilities/inline-editing/styles.ts +26 -0
- package/src/injections/visual-edit-agent/capabilities/inline-editing/validation.ts +87 -0
- package/src/injections/visual-edit-agent/constants.ts +9 -0
- package/src/injections/visual-edit-agent/handlers/click-handlers.ts +146 -0
- package/src/injections/visual-edit-agent/handlers/hover-handlers.ts +78 -0
- package/src/injections/visual-edit-agent/handlers/inline-edit-handlers.ts +146 -0
- package/src/injections/visual-edit-agent/handlers/message-handlers.ts +201 -0
- package/src/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.ts +65 -0
- package/src/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.ts +40 -0
- package/src/injections/visual-edit-agent/handlers/messages/types.ts +134 -0
- package/src/injections/visual-edit-agent/index.ts +121 -0
- package/src/injections/visual-edit-agent/state/agent-state.ts +31 -0
- package/src/injections/visual-edit-agent/ui/overlay.ts +126 -0
- package/src/injections/visual-edit-agent/utils/dom-utils.ts +39 -0
- package/src/injections/visual-edit-agent.ts +1 -625
- package/src/jsx-processor.ts +14 -41
- package/src/jsx-utils.ts +0 -116
- package/src/processors/shared-utils.ts +0 -596
- package/src/processors/static-array-processor.ts +3 -6
- package/src/visual-edit-plugin.ts +215 -34
- package/dist/consts.d.ts +0 -12
- package/dist/consts.d.ts.map +0 -1
- package/dist/consts.js +0 -12
- package/dist/consts.js.map +0 -1
- package/dist/processors/collection-id-processor.d.ts +0 -20
- package/dist/processors/collection-id-processor.d.ts.map +0 -1
- package/dist/processors/collection-id-processor.js +0 -182
- package/dist/processors/collection-id-processor.js.map +0 -1
- package/dist/processors/collection-item-field-processor.d.ts +0 -33
- package/dist/processors/collection-item-field-processor.d.ts.map +0 -1
- package/dist/processors/collection-item-field-processor.js +0 -275
- package/dist/processors/collection-item-field-processor.js.map +0 -1
- package/dist/processors/collection-item-id-processor.d.ts +0 -12
- package/dist/processors/collection-item-id-processor.d.ts.map +0 -1
- package/dist/processors/collection-item-id-processor.js +0 -50
- package/dist/processors/collection-item-id-processor.js.map +0 -1
- package/dist/processors/collection-reference-field-processor.d.ts +0 -31
- package/dist/processors/collection-reference-field-processor.d.ts.map +0 -1
- package/dist/processors/collection-reference-field-processor.js +0 -174
- package/dist/processors/collection-reference-field-processor.js.map +0 -1
- package/dist/processors/collection-tracing-utils.d.ts +0 -31
- package/dist/processors/collection-tracing-utils.d.ts.map +0 -1
- package/dist/processors/collection-tracing-utils.js +0 -326
- package/dist/processors/collection-tracing-utils.js.map +0 -1
- package/dist/types.d.ts +0 -5
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/src/consts.ts +0 -12
- package/src/processors/collection-id-processor.ts +0 -261
- package/src/processors/collection-item-field-processor.ts +0 -410
- package/src/processors/collection-item-id-processor.ts +0 -69
- package/src/processors/collection-reference-field-processor.ts +0 -225
- package/src/processors/collection-tracing-utils.ts +0 -436
- package/src/types.ts +0 -4
- /package/dist/{types.js → capabilities/inline-edit/types.js} +0 -0
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
import type { NodePath } from "@babel/traverse";
|
|
2
|
-
import type * as t from "@babel/types";
|
|
3
|
-
import {
|
|
4
|
-
DATA_COLLECTION_ITEM_FIELD,
|
|
5
|
-
DATA_COLLECTION_ITEM_ID,
|
|
6
|
-
EXCLUDED_FIELDS,
|
|
7
|
-
} from "../consts.js";
|
|
8
|
-
import { JSXUtils } from "../jsx-utils.js";
|
|
9
|
-
import {
|
|
10
|
-
JSXAttributeUtils,
|
|
11
|
-
ExpressionAnalysisUtils,
|
|
12
|
-
StaticValueUtils,
|
|
13
|
-
} from "./shared-utils.js";
|
|
14
|
-
|
|
15
|
-
export class DataItemFieldProcessor {
|
|
16
|
-
private attributeUtils: JSXAttributeUtils;
|
|
17
|
-
private expressionUtils: ExpressionAnalysisUtils;
|
|
18
|
-
private staticUtils: StaticValueUtils;
|
|
19
|
-
|
|
20
|
-
constructor(private types: typeof t) {
|
|
21
|
-
this.attributeUtils = new JSXAttributeUtils(types);
|
|
22
|
-
this.expressionUtils = new ExpressionAnalysisUtils(types);
|
|
23
|
-
this.staticUtils = new StaticValueUtils(types);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
process(path: NodePath<t.JSXOpeningElement>): void {
|
|
27
|
-
if (this.attributeUtils.hasAttribute(path, DATA_COLLECTION_ITEM_FIELD)) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const jsxElement = path.parentPath;
|
|
32
|
-
if (!jsxElement?.isJSXElement()) return;
|
|
33
|
-
|
|
34
|
-
const result = this.extractFieldFromChildren(jsxElement);
|
|
35
|
-
if (!result) return;
|
|
36
|
-
|
|
37
|
-
this.attributeUtils.addStringAttribute(
|
|
38
|
-
path,
|
|
39
|
-
DATA_COLLECTION_ITEM_FIELD,
|
|
40
|
-
result.fieldPath
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
this.tryAddItemId(path, result.rootIdentifier, result.fieldPath);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private extractFieldFromChildren(
|
|
47
|
-
jsxElement: NodePath<t.JSXElement>
|
|
48
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
49
|
-
const children = jsxElement.get("children");
|
|
50
|
-
|
|
51
|
-
for (const child of children) {
|
|
52
|
-
const result = this.extractFieldFromChild(child);
|
|
53
|
-
if (result) return result;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private extractFieldFromChild(
|
|
60
|
-
child: NodePath
|
|
61
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
62
|
-
if (child.isJSXExpressionContainer()) {
|
|
63
|
-
return this.extractFromExpressionContainer(child);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (child.isJSXElement()) {
|
|
67
|
-
return this.extractFromChildElement(child);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private extractFromExpressionContainer(
|
|
74
|
-
container: NodePath<t.JSXExpressionContainer>
|
|
75
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
76
|
-
const expression = container.get("expression");
|
|
77
|
-
|
|
78
|
-
if (expression.isJSXEmptyExpression()) return null;
|
|
79
|
-
|
|
80
|
-
const expr = expression as NodePath<t.Expression>;
|
|
81
|
-
|
|
82
|
-
if (expr.isMemberExpression() || expr.isOptionalMemberExpression()) {
|
|
83
|
-
return this.extractFromMemberExpression(expr);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (expr.isLogicalExpression() && expr.node.operator === "&&") {
|
|
87
|
-
const left = expr.get("left") as NodePath<t.Expression>;
|
|
88
|
-
if (
|
|
89
|
-
left.isMemberExpression() ||
|
|
90
|
-
left.isOptionalMemberExpression()
|
|
91
|
-
) {
|
|
92
|
-
return this.extractFromMemberExpression(left);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (expr.isCallExpression()) {
|
|
97
|
-
const callee = expr.get("callee");
|
|
98
|
-
if (callee.isMemberExpression()) {
|
|
99
|
-
const obj = callee.get("object") as NodePath<t.Expression>;
|
|
100
|
-
if (obj.isMemberExpression() || obj.isOptionalMemberExpression()) {
|
|
101
|
-
return this.extractFromMemberExpression(obj);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (expr.isIdentifier()) {
|
|
107
|
-
return this.extractFromSimpleIdentifier(expr);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private extractFromMemberExpression(
|
|
114
|
-
expr: NodePath<t.MemberExpression | t.OptionalMemberExpression>
|
|
115
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
116
|
-
const rootId = this.expressionUtils.extractRootIdentifier(
|
|
117
|
-
expr.node as t.Expression
|
|
118
|
-
);
|
|
119
|
-
if (!rootId) return null;
|
|
120
|
-
|
|
121
|
-
if (this.staticUtils.isDerivedFromStaticData(rootId.name, expr)) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const parts = this.expressionUtils.collectMemberExpressionPath(
|
|
126
|
-
expr.node as t.Expression
|
|
127
|
-
);
|
|
128
|
-
if (parts.length < 2) return null;
|
|
129
|
-
|
|
130
|
-
const fieldParts = parts.slice(1);
|
|
131
|
-
const fieldPath = fieldParts.join(".");
|
|
132
|
-
|
|
133
|
-
if (EXCLUDED_FIELDS.includes(fieldPath)) return null;
|
|
134
|
-
if (fieldParts.some((p) => EXCLUDED_FIELDS.includes(p))) return null;
|
|
135
|
-
|
|
136
|
-
return { fieldPath, rootIdentifier: rootId };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private extractFromSimpleIdentifier(
|
|
140
|
-
expr: NodePath<t.Identifier>
|
|
141
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
142
|
-
const name = expr.node.name;
|
|
143
|
-
if (EXCLUDED_FIELDS.includes(name)) return null;
|
|
144
|
-
if (this.staticUtils.isDerivedFromStaticData(name, expr)) return null;
|
|
145
|
-
|
|
146
|
-
return { fieldPath: name, rootIdentifier: expr.node };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private extractFromChildElement(
|
|
150
|
-
child: NodePath<t.JSXElement>
|
|
151
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
152
|
-
const elementName = JSXUtils.getElementName(child.node.openingElement);
|
|
153
|
-
if (!elementName) return null;
|
|
154
|
-
|
|
155
|
-
if (elementName === "Image" || elementName === "img") {
|
|
156
|
-
return this.extractFromImageElement(child);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const logicalParent = child.parentPath;
|
|
160
|
-
if (logicalParent?.isJSXExpressionContainer()) {
|
|
161
|
-
const logicalExpr = logicalParent.parentPath;
|
|
162
|
-
if (logicalExpr?.isLogicalExpression()) {
|
|
163
|
-
return this.extractFromConditionalImage(child);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private extractFromImageElement(
|
|
171
|
-
imageElement: NodePath<t.JSXElement>
|
|
172
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
173
|
-
const openingElement = imageElement.get("openingElement");
|
|
174
|
-
const attrs = openingElement.node.attributes;
|
|
175
|
-
|
|
176
|
-
for (const attr of attrs) {
|
|
177
|
-
if (
|
|
178
|
-
this.types.isJSXAttribute(attr) &&
|
|
179
|
-
this.types.isJSXIdentifier(attr.name) &&
|
|
180
|
-
attr.name.name === "src"
|
|
181
|
-
) {
|
|
182
|
-
if (
|
|
183
|
-
attr.value &&
|
|
184
|
-
this.types.isJSXExpressionContainer(attr.value) &&
|
|
185
|
-
this.types.isExpression(attr.value.expression) &&
|
|
186
|
-
!this.types.isJSXEmptyExpression(attr.value.expression)
|
|
187
|
-
) {
|
|
188
|
-
const expr = attr.value.expression;
|
|
189
|
-
if (
|
|
190
|
-
this.types.isMemberExpression(expr) ||
|
|
191
|
-
this.types.isOptionalMemberExpression(expr)
|
|
192
|
-
) {
|
|
193
|
-
const rootId = this.expressionUtils.extractRootIdentifier(expr);
|
|
194
|
-
if (!rootId) return null;
|
|
195
|
-
|
|
196
|
-
const parts = this.expressionUtils.collectMemberExpressionPath(expr);
|
|
197
|
-
if (parts.length < 2) return null;
|
|
198
|
-
|
|
199
|
-
const fieldPath = parts.slice(1).join(".");
|
|
200
|
-
if (EXCLUDED_FIELDS.includes(fieldPath)) return null;
|
|
201
|
-
|
|
202
|
-
return { fieldPath, rootIdentifier: rootId };
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
private extractFromConditionalImage(
|
|
212
|
-
child: NodePath<t.JSXElement>
|
|
213
|
-
): { fieldPath: string; rootIdentifier: t.Identifier } | null {
|
|
214
|
-
const elementName = JSXUtils.getElementName(child.node.openingElement);
|
|
215
|
-
if (elementName === "Image" || elementName === "img") {
|
|
216
|
-
return this.extractFromImageElement(child);
|
|
217
|
-
}
|
|
218
|
-
return null;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
private tryAddItemId(
|
|
222
|
-
path: NodePath<t.JSXOpeningElement>,
|
|
223
|
-
rootIdentifier: t.Identifier,
|
|
224
|
-
fieldPath: string
|
|
225
|
-
): void {
|
|
226
|
-
if (this.attributeUtils.hasAttribute(path, DATA_COLLECTION_ITEM_ID)) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const idField = this.resolveIdFieldName(path);
|
|
231
|
-
|
|
232
|
-
// Simple identifier: {name} from ({ name, price }) => ...
|
|
233
|
-
// rootIdentifier IS the field value (a string), not an object with ._id/.id.
|
|
234
|
-
// We need to find the id field from sibling destructured params instead.
|
|
235
|
-
if (rootIdentifier.name === fieldPath) {
|
|
236
|
-
this.tryAddItemIdFromDestructuredParams(path, idField);
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Member expression: {product.name} → product?.id or product?._id
|
|
241
|
-
const idExpr = this.types.optionalMemberExpression(
|
|
242
|
-
this.types.identifier(rootIdentifier.name),
|
|
243
|
-
this.types.identifier(idField),
|
|
244
|
-
false,
|
|
245
|
-
true
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
const binding = path.scope.getBinding(rootIdentifier.name);
|
|
249
|
-
if (!binding) {
|
|
250
|
-
this.tryAddItemIdFromParentComponent(path, rootIdentifier, idField);
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (
|
|
255
|
-
binding.path.isVariableDeclarator() ||
|
|
256
|
-
binding.kind === "param"
|
|
257
|
-
) {
|
|
258
|
-
this.attributeUtils.addExpressionAttribute(
|
|
259
|
-
path,
|
|
260
|
-
DATA_COLLECTION_ITEM_ID,
|
|
261
|
-
idExpr
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Walk up the JSX tree to find a key attribute that accesses .id or ._id,
|
|
268
|
-
* returning the actual field name used. Falls back to "_id".
|
|
269
|
-
*/
|
|
270
|
-
private resolveIdFieldName(
|
|
271
|
-
path: NodePath<t.JSXOpeningElement>
|
|
272
|
-
): string {
|
|
273
|
-
let current: NodePath | null = path.parentPath;
|
|
274
|
-
while (current) {
|
|
275
|
-
if (current.isJSXElement()) {
|
|
276
|
-
const opening = current.get("openingElement");
|
|
277
|
-
const field = this.extractIdFieldFromKey(opening);
|
|
278
|
-
if (field) return field;
|
|
279
|
-
}
|
|
280
|
-
current = current.parentPath;
|
|
281
|
-
}
|
|
282
|
-
return "_id";
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
private extractIdFieldFromKey(
|
|
286
|
-
path: NodePath<t.JSXOpeningElement>
|
|
287
|
-
): string | null {
|
|
288
|
-
for (const attr of path.node.attributes) {
|
|
289
|
-
if (
|
|
290
|
-
this.types.isJSXAttribute(attr) &&
|
|
291
|
-
this.types.isJSXIdentifier(attr.name) &&
|
|
292
|
-
attr.name.name === "key" &&
|
|
293
|
-
attr.value &&
|
|
294
|
-
this.types.isJSXExpressionContainer(attr.value)
|
|
295
|
-
) {
|
|
296
|
-
const expr = attr.value.expression;
|
|
297
|
-
if (
|
|
298
|
-
this.types.isMemberExpression(expr) &&
|
|
299
|
-
this.types.isIdentifier(expr.property)
|
|
300
|
-
) {
|
|
301
|
-
const name = expr.property.name;
|
|
302
|
-
if (name === "id" || name === "_id") return name;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return null;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* For simple identifiers from destructured component props like ({ name, price }),
|
|
311
|
-
* find or inject the id field in the ObjectPattern so we can reference it directly.
|
|
312
|
-
*/
|
|
313
|
-
private tryAddItemIdFromDestructuredParams(
|
|
314
|
-
path: NodePath<t.JSXOpeningElement>,
|
|
315
|
-
idField: string
|
|
316
|
-
): void {
|
|
317
|
-
const fn = path.getFunctionParent();
|
|
318
|
-
if (!fn) return;
|
|
319
|
-
|
|
320
|
-
const params = fn.get("params");
|
|
321
|
-
for (const param of Array.isArray(params) ? params : [params]) {
|
|
322
|
-
if (!param.isObjectPattern()) continue;
|
|
323
|
-
|
|
324
|
-
// Check if the id field is already destructured
|
|
325
|
-
for (const prop of param.get("properties")) {
|
|
326
|
-
if (
|
|
327
|
-
prop.isObjectProperty() &&
|
|
328
|
-
this.types.isIdentifier(prop.node.key) &&
|
|
329
|
-
(prop.node.key.name === "id" || prop.node.key.name === "_id") &&
|
|
330
|
-
this.types.isIdentifier(prop.node.value)
|
|
331
|
-
) {
|
|
332
|
-
this.attributeUtils.addExpressionAttribute(
|
|
333
|
-
path,
|
|
334
|
-
DATA_COLLECTION_ITEM_ID,
|
|
335
|
-
this.types.identifier(prop.node.value.name)
|
|
336
|
-
);
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// id field not destructured yet — inject it into the pattern
|
|
342
|
-
param.node.properties.push(
|
|
343
|
-
this.types.objectProperty(
|
|
344
|
-
this.types.identifier(idField),
|
|
345
|
-
this.types.identifier(idField),
|
|
346
|
-
false,
|
|
347
|
-
true
|
|
348
|
-
)
|
|
349
|
-
);
|
|
350
|
-
this.attributeUtils.addExpressionAttribute(
|
|
351
|
-
path,
|
|
352
|
-
DATA_COLLECTION_ITEM_ID,
|
|
353
|
-
this.types.identifier(idField)
|
|
354
|
-
);
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
private tryAddItemIdFromParentComponent(
|
|
360
|
-
path: NodePath<t.JSXOpeningElement>,
|
|
361
|
-
rootIdentifier: t.Identifier,
|
|
362
|
-
idField: string
|
|
363
|
-
): void {
|
|
364
|
-
let current: NodePath | null = path.parentPath;
|
|
365
|
-
while (current) {
|
|
366
|
-
if (current.isJSXElement()) {
|
|
367
|
-
const opening = current.get("openingElement");
|
|
368
|
-
const name = JSXUtils.getElementName(opening.node);
|
|
369
|
-
if (name && JSXUtils.isCustomComponent(name)) {
|
|
370
|
-
const keyAttr = this.findKeyWithId(opening);
|
|
371
|
-
if (keyAttr) {
|
|
372
|
-
const idExpr = this.types.optionalMemberExpression(
|
|
373
|
-
this.types.identifier(rootIdentifier.name),
|
|
374
|
-
this.types.identifier(idField),
|
|
375
|
-
false,
|
|
376
|
-
true
|
|
377
|
-
);
|
|
378
|
-
this.attributeUtils.addExpressionAttribute(
|
|
379
|
-
path,
|
|
380
|
-
DATA_COLLECTION_ITEM_ID,
|
|
381
|
-
idExpr
|
|
382
|
-
);
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
current = current.parentPath;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
private findKeyWithId(
|
|
392
|
-
path: NodePath<t.JSXOpeningElement>
|
|
393
|
-
): boolean {
|
|
394
|
-
for (const attr of path.node.attributes) {
|
|
395
|
-
if (
|
|
396
|
-
this.types.isJSXAttribute(attr) &&
|
|
397
|
-
this.types.isJSXIdentifier(attr.name) &&
|
|
398
|
-
attr.name.name === "key" &&
|
|
399
|
-
attr.value &&
|
|
400
|
-
this.types.isJSXExpressionContainer(attr.value)
|
|
401
|
-
) {
|
|
402
|
-
const expr = attr.value.expression;
|
|
403
|
-
if (this.types.isExpression(expr)) {
|
|
404
|
-
return this.expressionUtils.isIdAccess(expr);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
return false;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { NodePath } from "@babel/traverse";
|
|
2
|
-
import type * as t from "@babel/types";
|
|
3
|
-
import { DATA_COLLECTION_ITEM_ID } from "../consts.js";
|
|
4
|
-
import {
|
|
5
|
-
JSXAttributeUtils,
|
|
6
|
-
ExpressionAnalysisUtils,
|
|
7
|
-
} from "./shared-utils.js";
|
|
8
|
-
|
|
9
|
-
export class DataItemIdProcessor {
|
|
10
|
-
private attributeUtils: JSXAttributeUtils;
|
|
11
|
-
private expressionUtils: ExpressionAnalysisUtils;
|
|
12
|
-
|
|
13
|
-
constructor(private types: typeof t) {
|
|
14
|
-
this.attributeUtils = new JSXAttributeUtils(types);
|
|
15
|
-
this.expressionUtils = new ExpressionAnalysisUtils(types);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
process(path: NodePath<t.JSXOpeningElement>): void {
|
|
19
|
-
if (this.attributeUtils.hasAttribute(path, DATA_COLLECTION_ITEM_ID)) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const keyAttr = this.findKeyAttribute(path);
|
|
24
|
-
if (!keyAttr) return;
|
|
25
|
-
|
|
26
|
-
const expression = this.extractKeyExpression(keyAttr);
|
|
27
|
-
if (!expression) return;
|
|
28
|
-
|
|
29
|
-
if (!this.expressionUtils.isIdAccess(expression)) return;
|
|
30
|
-
|
|
31
|
-
const optionalExpr = this.types.isMemberExpression(expression)
|
|
32
|
-
? this.expressionUtils.createOptionalChainExpression(expression)
|
|
33
|
-
: expression;
|
|
34
|
-
|
|
35
|
-
this.attributeUtils.addExpressionAttribute(
|
|
36
|
-
path,
|
|
37
|
-
DATA_COLLECTION_ITEM_ID,
|
|
38
|
-
optionalExpr
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
private findKeyAttribute(
|
|
43
|
-
path: NodePath<t.JSXOpeningElement>
|
|
44
|
-
): t.JSXAttribute | null {
|
|
45
|
-
for (const attr of path.node.attributes) {
|
|
46
|
-
if (
|
|
47
|
-
this.types.isJSXAttribute(attr) &&
|
|
48
|
-
this.types.isJSXIdentifier(attr.name) &&
|
|
49
|
-
attr.name.name === "key"
|
|
50
|
-
) {
|
|
51
|
-
return attr;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private extractKeyExpression(
|
|
58
|
-
attr: t.JSXAttribute
|
|
59
|
-
): t.Expression | null {
|
|
60
|
-
if (!attr.value) return null;
|
|
61
|
-
|
|
62
|
-
if (this.types.isJSXExpressionContainer(attr.value)) {
|
|
63
|
-
const expr = attr.value.expression;
|
|
64
|
-
if (this.types.isExpression(expr)) return expr;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import type { NodePath } from "@babel/traverse";
|
|
2
|
-
import type * as t from "@babel/types";
|
|
3
|
-
import {
|
|
4
|
-
DATA_COLLECTION_FIELD_REFERENCE,
|
|
5
|
-
DATA_COLLECTION_REFERENCE,
|
|
6
|
-
} from "../consts.js";
|
|
7
|
-
import {
|
|
8
|
-
JSXAttributeUtils,
|
|
9
|
-
ExpressionAnalysisUtils,
|
|
10
|
-
TypeCheckUtils,
|
|
11
|
-
} from "./shared-utils.js";
|
|
12
|
-
|
|
13
|
-
export class ReferenceFieldProcessor {
|
|
14
|
-
private attributeUtils: JSXAttributeUtils;
|
|
15
|
-
private expressionUtils: ExpressionAnalysisUtils;
|
|
16
|
-
private typeCheckUtils: TypeCheckUtils;
|
|
17
|
-
|
|
18
|
-
constructor(private types: typeof t) {
|
|
19
|
-
this.attributeUtils = new JSXAttributeUtils(types);
|
|
20
|
-
this.expressionUtils = new ExpressionAnalysisUtils(types);
|
|
21
|
-
this.typeCheckUtils = new TypeCheckUtils(types);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
process(path: NodePath<t.JSXOpeningElement>): void {
|
|
25
|
-
if (
|
|
26
|
-
this.attributeUtils.hasAttribute(path, DATA_COLLECTION_FIELD_REFERENCE)
|
|
27
|
-
) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
this.isReturnedFromReferenceMap(path) ||
|
|
33
|
-
this.isInsideReferenceLogicalExpression(path) ||
|
|
34
|
-
this.isInReferencePropertyMapChain(path)
|
|
35
|
-
) {
|
|
36
|
-
this.attributeUtils.addStringAttribute(
|
|
37
|
-
path,
|
|
38
|
-
DATA_COLLECTION_FIELD_REFERENCE,
|
|
39
|
-
"true"
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Strategy A: Element is the direct return of a .map() callback
|
|
46
|
-
* whose array is a reference variable (initialized via type-check pattern).
|
|
47
|
-
*/
|
|
48
|
-
private isReturnedFromReferenceMap(
|
|
49
|
-
path: NodePath<t.JSXOpeningElement>
|
|
50
|
-
): boolean {
|
|
51
|
-
const jsxElement = path.parentPath;
|
|
52
|
-
if (!jsxElement?.isJSXElement()) return false;
|
|
53
|
-
|
|
54
|
-
const parent = jsxElement.parentPath;
|
|
55
|
-
if (!parent) return false;
|
|
56
|
-
|
|
57
|
-
const callbackFn = this.findEnclosingMapCallback(parent);
|
|
58
|
-
if (!callbackFn) return false;
|
|
59
|
-
|
|
60
|
-
const mapCall = callbackFn.parentPath;
|
|
61
|
-
if (!mapCall?.isCallExpression()) return false;
|
|
62
|
-
|
|
63
|
-
const callee = mapCall.get("callee");
|
|
64
|
-
if (!callee.isMemberExpression()) return false;
|
|
65
|
-
|
|
66
|
-
const arrayObj = callee.get("object") as NodePath<t.Expression>;
|
|
67
|
-
return this.isReferenceArray(arrayObj);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Strategy B: Element is inside a && expression where the left operand
|
|
72
|
-
* references a field name that appears in an ancestor's data-collection-reference.
|
|
73
|
-
*/
|
|
74
|
-
private isInsideReferenceLogicalExpression(
|
|
75
|
-
path: NodePath<t.JSXOpeningElement>
|
|
76
|
-
): boolean {
|
|
77
|
-
const jsxElement = path.parentPath;
|
|
78
|
-
if (!jsxElement?.isJSXElement()) return false;
|
|
79
|
-
|
|
80
|
-
const logicalParent = jsxElement.parentPath;
|
|
81
|
-
if (!logicalParent?.isLogicalExpression()) return false;
|
|
82
|
-
if (logicalParent.node.operator !== "&&") return false;
|
|
83
|
-
|
|
84
|
-
const left = logicalParent.node.left;
|
|
85
|
-
const fieldName = this.extractFieldNameFromExpression(left as t.Expression);
|
|
86
|
-
if (!fieldName) return false;
|
|
87
|
-
|
|
88
|
-
return this.isFieldInAncestorReference(path, fieldName);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Strategy C: Element is inside a .map() chain on a reference property.
|
|
93
|
-
* e.g. item.relatedProducts.map(...) or item.relatedProducts.filter(...).map(...)
|
|
94
|
-
*/
|
|
95
|
-
private isInReferencePropertyMapChain(
|
|
96
|
-
path: NodePath<t.JSXOpeningElement>
|
|
97
|
-
): boolean {
|
|
98
|
-
const jsxElement = path.parentPath;
|
|
99
|
-
if (!jsxElement?.isJSXElement()) return false;
|
|
100
|
-
|
|
101
|
-
let current: NodePath | null = jsxElement;
|
|
102
|
-
while (current) {
|
|
103
|
-
if (current.isCallExpression()) {
|
|
104
|
-
const callee = current.get("callee");
|
|
105
|
-
if (callee.isMemberExpression()) {
|
|
106
|
-
const fieldName = this.extractReferenceFieldFromMapChain(callee);
|
|
107
|
-
if (fieldName && this.isFieldInAncestorReference(path, fieldName)) {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
current = current.parentPath;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private findEnclosingMapCallback(
|
|
119
|
-
path: NodePath
|
|
120
|
-
): NodePath<t.Function> | null {
|
|
121
|
-
let current: NodePath | null = path;
|
|
122
|
-
while (current) {
|
|
123
|
-
if (current.isArrowFunctionExpression() || current.isFunctionExpression()) {
|
|
124
|
-
const parent = current.parentPath;
|
|
125
|
-
if (parent?.isCallExpression()) {
|
|
126
|
-
const callee = parent.get("callee");
|
|
127
|
-
if (callee.isMemberExpression()) {
|
|
128
|
-
const prop = callee.get("property") as NodePath;
|
|
129
|
-
if (
|
|
130
|
-
prop.isIdentifier() &&
|
|
131
|
-
(prop.node.name === "map" || prop.node.name === "flatMap")
|
|
132
|
-
) {
|
|
133
|
-
return current as NodePath<t.Function>;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
current = current.parentPath;
|
|
139
|
-
}
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private isReferenceArray(path: NodePath<t.Expression>): boolean {
|
|
144
|
-
if (!path.isIdentifier()) return false;
|
|
145
|
-
|
|
146
|
-
const binding = path.scope.getBinding(path.node.name);
|
|
147
|
-
if (!binding?.path.isVariableDeclarator()) return false;
|
|
148
|
-
|
|
149
|
-
const init = binding.path.get("init");
|
|
150
|
-
if (!init.isConditionalExpression()) return false;
|
|
151
|
-
|
|
152
|
-
const test = init.node.test;
|
|
153
|
-
return this.typeCheckUtils.isReferenceTypeCheck(test as t.Expression);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
private extractFieldNameFromExpression(
|
|
157
|
-
node: t.Expression
|
|
158
|
-
): string | null {
|
|
159
|
-
if (this.types.isMemberExpression(node)) {
|
|
160
|
-
const prop = node.property;
|
|
161
|
-
if (this.types.isIdentifier(prop)) return prop.name;
|
|
162
|
-
}
|
|
163
|
-
if (this.types.isOptionalMemberExpression(node)) {
|
|
164
|
-
const prop = node.property;
|
|
165
|
-
if (this.types.isIdentifier(prop)) return prop.name;
|
|
166
|
-
}
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private isFieldInAncestorReference(
|
|
171
|
-
path: NodePath,
|
|
172
|
-
fieldName: string
|
|
173
|
-
): boolean {
|
|
174
|
-
const ancestor = this.attributeUtils.findAncestorWithAttribute(
|
|
175
|
-
path,
|
|
176
|
-
DATA_COLLECTION_REFERENCE
|
|
177
|
-
);
|
|
178
|
-
if (!ancestor) return false;
|
|
179
|
-
|
|
180
|
-
const refValue = this.attributeUtils.getAttributeStringValue(
|
|
181
|
-
ancestor,
|
|
182
|
-
DATA_COLLECTION_REFERENCE
|
|
183
|
-
);
|
|
184
|
-
if (!refValue) return false;
|
|
185
|
-
|
|
186
|
-
const references = refValue.split(",").map((r) => r.trim());
|
|
187
|
-
return references.includes(fieldName);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
private extractReferenceFieldFromMapChain(
|
|
191
|
-
callee: NodePath<t.MemberExpression>
|
|
192
|
-
): string | null {
|
|
193
|
-
const prop = callee.get("property") as NodePath;
|
|
194
|
-
if (!prop.isIdentifier()) return null;
|
|
195
|
-
|
|
196
|
-
const methodName = prop.node.name;
|
|
197
|
-
const obj = callee.get("object") as NodePath<t.Expression>;
|
|
198
|
-
|
|
199
|
-
if (methodName === "map" || methodName === "flatMap") {
|
|
200
|
-
if (obj.isMemberExpression()) {
|
|
201
|
-
const fieldProp = obj.get("property") as NodePath;
|
|
202
|
-
if (fieldProp.isIdentifier()) return fieldProp.node.name;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (methodName === "map" || methodName === "flatMap") {
|
|
207
|
-
if (obj.isCallExpression()) {
|
|
208
|
-
const innerCallee = obj.get("callee");
|
|
209
|
-
if (innerCallee.isMemberExpression()) {
|
|
210
|
-
return this.extractReferenceFieldFromMapChain(innerCallee);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (
|
|
216
|
-
["filter", "sort", "slice"].includes(methodName) &&
|
|
217
|
-
obj.isMemberExpression()
|
|
218
|
-
) {
|
|
219
|
-
const fieldProp = obj.get("property") as NodePath;
|
|
220
|
-
if (fieldProp.isIdentifier()) return fieldProp.node.name;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
}
|