@trojanbox-vcp-test/site-edit-engine 0.1.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 (174) hide show
  1. package/README.md +85 -0
  2. package/dist/execute-integration/execute-fixture-harness.d.ts +25 -0
  3. package/dist/execute-integration/execute-fixture-harness.js +37 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.js +2 -0
  6. package/dist/internal/ast/diagnostics/index.d.ts +5 -0
  7. package/dist/internal/ast/diagnostics/index.js +25 -0
  8. package/dist/internal/ast/history/index.d.ts +15 -0
  9. package/dist/internal/ast/history/index.js +62 -0
  10. package/dist/internal/ast/index.d.ts +8 -0
  11. package/dist/internal/ast/index.js +5 -0
  12. package/dist/internal/ast/locators/index.d.ts +1 -0
  13. package/dist/internal/ast/locators/index.js +1 -0
  14. package/dist/internal/ast/locators/resolve-locator.d.ts +16 -0
  15. package/dist/internal/ast/locators/resolve-locator.js +920 -0
  16. package/dist/internal/ast/parser/SourceParser.d.ts +30 -0
  17. package/dist/internal/ast/parser/SourceParser.js +49 -0
  18. package/dist/internal/ast/parser/index.d.ts +21 -0
  19. package/dist/internal/ast/parser/index.js +64 -0
  20. package/dist/internal/ast/primitives/conditional/conditional-primitives.d.ts +18 -0
  21. package/dist/internal/ast/primitives/conditional/conditional-primitives.js +237 -0
  22. package/dist/internal/ast/primitives/conditional/index.d.ts +1 -0
  23. package/dist/internal/ast/primitives/conditional/index.js +1 -0
  24. package/dist/internal/ast/primitives/imports/add-import.d.ts +18 -0
  25. package/dist/internal/ast/primitives/imports/add-import.js +111 -0
  26. package/dist/internal/ast/primitives/imports/index.d.ts +2 -0
  27. package/dist/internal/ast/primitives/imports/index.js +2 -0
  28. package/dist/internal/ast/primitives/imports/remove-import.d.ts +15 -0
  29. package/dist/internal/ast/primitives/imports/remove-import.js +72 -0
  30. package/dist/internal/ast/primitives/index.d.ts +10 -0
  31. package/dist/internal/ast/primitives/index.js +10 -0
  32. package/dist/internal/ast/primitives/jsx/index.d.ts +4 -0
  33. package/dist/internal/ast/primitives/jsx/index.js +4 -0
  34. package/dist/internal/ast/primitives/jsx/insert-child.d.ts +11 -0
  35. package/dist/internal/ast/primitives/jsx/insert-child.js +69 -0
  36. package/dist/internal/ast/primitives/jsx/move-node.d.ts +9 -0
  37. package/dist/internal/ast/primitives/jsx/move-node.js +76 -0
  38. package/dist/internal/ast/primitives/jsx/remove-node.d.ts +7 -0
  39. package/dist/internal/ast/primitives/jsx/remove-node.js +36 -0
  40. package/dist/internal/ast/primitives/jsx/update-text.d.ts +8 -0
  41. package/dist/internal/ast/primitives/jsx/update-text.js +81 -0
  42. package/dist/internal/ast/primitives/next/index.d.ts +1 -0
  43. package/dist/internal/ast/primitives/next/index.js +1 -0
  44. package/dist/internal/ast/primitives/next/next-primitives.d.ts +43 -0
  45. package/dist/internal/ast/primitives/next/next-primitives.js +211 -0
  46. package/dist/internal/ast/primitives/shared.d.ts +60 -0
  47. package/dist/internal/ast/primitives/shared.js +176 -0
  48. package/dist/internal/ast/primitives/style/class-expression.d.ts +23 -0
  49. package/dist/internal/ast/primitives/style/class-expression.js +174 -0
  50. package/dist/internal/ast/primitives/style/index.d.ts +1 -0
  51. package/dist/internal/ast/primitives/style/index.js +1 -0
  52. package/dist/internal/ast/primitives/style/style-primitives.d.ts +49 -0
  53. package/dist/internal/ast/primitives/style/style-primitives.js +555 -0
  54. package/dist/internal/ast/primitives/values/index.d.ts +1 -0
  55. package/dist/internal/ast/primitives/values/index.js +1 -0
  56. package/dist/internal/ast/primitives/values/value-primitives.d.ts +42 -0
  57. package/dist/internal/ast/primitives/values/value-primitives.js +158 -0
  58. package/dist/internal/ast/printer/SourcePrinter.d.ts +21 -0
  59. package/dist/internal/ast/printer/SourcePrinter.js +76 -0
  60. package/dist/internal/ast/printer/index.d.ts +6 -0
  61. package/dist/internal/ast/printer/index.js +126 -0
  62. package/dist/internal/ast/types.d.ts +190 -0
  63. package/dist/internal/ast/types.js +1 -0
  64. package/dist/internal/capability/capability-resolver.d.ts +16 -0
  65. package/dist/internal/capability/capability-resolver.js +127 -0
  66. package/dist/internal/classname-source.d.ts +24 -0
  67. package/dist/internal/classname-source.js +220 -0
  68. package/dist/internal/contracts/IEditEngineRuntime.d.ts +18 -0
  69. package/dist/internal/contracts/IEditEngineRuntime.js +1 -0
  70. package/dist/internal/domain/EditDiagnostic.d.ts +38 -0
  71. package/dist/internal/domain/EditDiagnostic.js +43 -0
  72. package/dist/internal/events/event-bus.d.ts +14 -0
  73. package/dist/internal/events/event-bus.js +21 -0
  74. package/dist/internal/graph/graph-builder.d.ts +12 -0
  75. package/dist/internal/graph/graph-builder.js +1371 -0
  76. package/dist/internal/graph/import-resolver.d.ts +31 -0
  77. package/dist/internal/graph/import-resolver.js +109 -0
  78. package/dist/internal/graph/project-graph-builder.d.ts +32 -0
  79. package/dist/internal/graph/project-graph-builder.js +133 -0
  80. package/dist/internal/graph/types.d.ts +114 -0
  81. package/dist/internal/graph/types.js +6 -0
  82. package/dist/internal/history/undo-redo.d.ts +28 -0
  83. package/dist/internal/history/undo-redo.js +42 -0
  84. package/dist/internal/index.d.ts +2 -0
  85. package/dist/internal/index.js +1 -0
  86. package/dist/internal/planner/planner.d.ts +104 -0
  87. package/dist/internal/planner/planner.js +2533 -0
  88. package/dist/internal/planner/types.d.ts +275 -0
  89. package/dist/internal/planner/types.js +6 -0
  90. package/dist/internal/protocol/boundary.d.ts +10 -0
  91. package/dist/internal/protocol/boundary.js +3 -0
  92. package/dist/internal/protocol/capability.d.ts +47 -0
  93. package/dist/internal/protocol/capability.js +8 -0
  94. package/dist/internal/protocol/error.d.ts +43 -0
  95. package/dist/internal/protocol/error.js +38 -0
  96. package/dist/internal/protocol/event.d.ts +39 -0
  97. package/dist/internal/protocol/event.js +3 -0
  98. package/dist/internal/protocol/identity.d.ts +26 -0
  99. package/dist/internal/protocol/identity.js +30 -0
  100. package/dist/internal/protocol/operation.d.ts +224 -0
  101. package/dist/internal/protocol/operation.js +8 -0
  102. package/dist/internal/protocol/render.d.ts +212 -0
  103. package/dist/internal/protocol/render.js +3 -0
  104. package/dist/internal/protocol.d.ts +9 -0
  105. package/dist/internal/protocol.js +2 -0
  106. package/dist/internal/provenance/binding-graph.d.ts +39 -0
  107. package/dist/internal/provenance/binding-graph.js +184 -0
  108. package/dist/internal/provenance/capability-policy.d.ts +15 -0
  109. package/dist/internal/provenance/capability-policy.js +96 -0
  110. package/dist/internal/provenance/data-source-classifier.d.ts +14 -0
  111. package/dist/internal/provenance/data-source-classifier.js +281 -0
  112. package/dist/internal/provenance/resolve-text-provenance.d.ts +45 -0
  113. package/dist/internal/provenance/resolve-text-provenance.js +3090 -0
  114. package/dist/internal/provenance/types.d.ts +89 -0
  115. package/dist/internal/provenance/types.js +1 -0
  116. package/dist/internal/render/component-semantic.d.ts +11 -0
  117. package/dist/internal/render/component-semantic.js +141 -0
  118. package/dist/internal/render/content-model.d.ts +3 -0
  119. package/dist/internal/render/content-model.js +89 -0
  120. package/dist/internal/render/media-model.d.ts +3 -0
  121. package/dist/internal/render/media-model.js +45 -0
  122. package/dist/internal/render/provenance-types.d.ts +33 -0
  123. package/dist/internal/render/provenance-types.js +1 -0
  124. package/dist/internal/render/render-projection.d.ts +24 -0
  125. package/dist/internal/render/render-projection.js +281 -0
  126. package/dist/internal/render/tailwind-style-model.d.ts +19 -0
  127. package/dist/internal/render/tailwind-style-model.js +1187 -0
  128. package/dist/internal/runtime/EditEngineRuntime.d.ts +25 -0
  129. package/dist/internal/runtime/EditEngineRuntime.js +89 -0
  130. package/dist/internal/runtime/EditEngineRuntimeSnapshot.d.ts +31 -0
  131. package/dist/internal/runtime/EditEngineRuntimeSnapshot.js +15 -0
  132. package/dist/internal/runtime/InternalEditEngine.d.ts +44 -0
  133. package/dist/internal/runtime/InternalEditEngine.js +1391 -0
  134. package/dist/internal/runtime.d.ts +3 -0
  135. package/dist/internal/runtime.js +1 -0
  136. package/dist/internal/topology/topology.d.ts +6 -0
  137. package/dist/internal/topology/topology.js +98 -0
  138. package/dist/internal/topology/types.d.ts +35 -0
  139. package/dist/internal/topology/types.js +5 -0
  140. package/dist/internal/types.d.ts +1 -0
  141. package/dist/internal/types.js +1 -0
  142. package/dist/internal/writeback/in-memory-fs.d.ts +7 -0
  143. package/dist/internal/writeback/in-memory-fs.js +44 -0
  144. package/dist/internal/writeback/types.d.ts +45 -0
  145. package/dist/internal/writeback/types.js +7 -0
  146. package/dist/internal/writeback/writeback-service.d.ts +7 -0
  147. package/dist/internal/writeback/writeback-service.js +568 -0
  148. package/dist/internal-adapter.d.ts +18 -0
  149. package/dist/internal-adapter.js +350 -0
  150. package/dist/next-app-router-fs.d.ts +2 -0
  151. package/dist/next-app-router-fs.js +64 -0
  152. package/dist/next-app-router.d.ts +11 -0
  153. package/dist/next-app-router.js +140 -0
  154. package/dist/preview-runtime.d.ts +394 -0
  155. package/dist/preview-runtime.js +102 -0
  156. package/dist/public-file-system.d.ts +7 -0
  157. package/dist/public-file-system.js +1 -0
  158. package/dist/runtime-sync.d.ts +95 -0
  159. package/dist/runtime-sync.js +321 -0
  160. package/dist/runtime.d.ts +340 -0
  161. package/dist/runtime.js +134 -0
  162. package/dist/site-edit-instrumentation.d.ts +19 -0
  163. package/dist/site-edit-instrumentation.js +322 -0
  164. package/dist/snapshot-file-system.d.ts +19 -0
  165. package/dist/snapshot-file-system.js +49 -0
  166. package/dist/source-watcher.d.ts +20 -0
  167. package/dist/source-watcher.js +150 -0
  168. package/dist/source-writeback-test-harness.d.ts +244 -0
  169. package/dist/source-writeback-test-harness.js +119 -0
  170. package/dist/types.d.ts +68 -0
  171. package/dist/types.js +1 -0
  172. package/dist/webpack-loader.cjs +592 -0
  173. package/dist/webpack-loader.d.ts +27 -0
  174. package/package.json +66 -0
@@ -0,0 +1,15 @@
1
+ export interface SourceRangeLike {
2
+ startLine: number;
3
+ startColumn: number;
4
+ endLine: number;
5
+ endColumn: number;
6
+ }
7
+ export interface PolicyNodeLike {
8
+ sourceRange: SourceRangeLike;
9
+ }
10
+ export interface CapabilityPolicyResult {
11
+ allowed: boolean;
12
+ reason?: string;
13
+ }
14
+ export declare function evaluateInsertChildPolicy(source: string, node: PolicyNodeLike): CapabilityPolicyResult;
15
+ export declare function evaluateCrossFileMovePolicy(source: string, node: PolicyNodeLike): CapabilityPolicyResult;
@@ -0,0 +1,96 @@
1
+ import * as parser from "@babel/parser";
2
+ import _traverse from "@babel/traverse";
3
+ import * as t from "@babel/types";
4
+ import { classifyExpressionDataSource, isApiSource, } from "./data-source-classifier.js";
5
+ const traverse = (typeof _traverse === "function" ? _traverse : _traverse.default);
6
+ export function evaluateInsertChildPolicy(source, node) {
7
+ const ast = parseSource(source);
8
+ if (!ast) {
9
+ return { allowed: true };
10
+ }
11
+ let blocked = false;
12
+ traverse(ast, {
13
+ CallExpression(path) {
14
+ if (!isNodeInsideRange(path.node, node.sourceRange) ||
15
+ !isMapCall(path.node)) {
16
+ return;
17
+ }
18
+ const calleePath = path.get("callee");
19
+ if (!calleePath.isMemberExpression()) {
20
+ return;
21
+ }
22
+ const objectPath = calleePath.get("object");
23
+ if (Array.isArray(objectPath) || !objectPath.isExpression()) {
24
+ return;
25
+ }
26
+ if (isApiSource(classifyExpressionDataSource(objectPath))) {
27
+ blocked = true;
28
+ path.stop();
29
+ }
30
+ },
31
+ });
32
+ return blocked
33
+ ? {
34
+ allowed: false,
35
+ reason: "Cannot add data-backed items to a dynamic API list",
36
+ }
37
+ : { allowed: true };
38
+ }
39
+ export function evaluateCrossFileMovePolicy(source, node) {
40
+ const ast = parseSource(source);
41
+ if (!ast) {
42
+ return { allowed: true };
43
+ }
44
+ let hasLocalDependency = false;
45
+ traverse(ast, {
46
+ JSXExpressionContainer(path) {
47
+ if (!isNodeInsideRange(path.node, node.sourceRange)) {
48
+ return;
49
+ }
50
+ if (!t.isJSXEmptyExpression(path.node.expression)) {
51
+ hasLocalDependency = true;
52
+ path.stop();
53
+ }
54
+ },
55
+ });
56
+ return hasLocalDependency
57
+ ? {
58
+ allowed: false,
59
+ reason: "Cannot move subtree across files because it depends on local binding expressions",
60
+ }
61
+ : { allowed: true };
62
+ }
63
+ function parseSource(source) {
64
+ try {
65
+ return parser.parse(source, {
66
+ sourceType: "module",
67
+ plugins: ["jsx", "typescript"],
68
+ });
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ function isMapCall(call) {
75
+ const callee = call.callee;
76
+ return (t.isMemberExpression(callee) &&
77
+ t.isIdentifier(callee.property) &&
78
+ callee.property.name === "map");
79
+ }
80
+ function isNodeInsideRange(node, range) {
81
+ const loc = node.loc;
82
+ if (!loc) {
83
+ return false;
84
+ }
85
+ return (comparePosition({ line: loc.start.line, column: loc.start.column }, { line: range.startLine, column: range.startColumn }) >= 0 &&
86
+ comparePosition({ line: loc.end.line, column: loc.end.column }, { line: range.endLine, column: range.endColumn }) <= 0);
87
+ }
88
+ function comparePosition(left, right) {
89
+ if (left.line !== right.line) {
90
+ return left.line < right.line ? -1 : 1;
91
+ }
92
+ if (left.column !== right.column) {
93
+ return left.column < right.column ? -1 : 1;
94
+ }
95
+ return 0;
96
+ }
@@ -0,0 +1,14 @@
1
+ import { type Binding, type NodePath } from "@babel/traverse";
2
+ import * as t from "@babel/types";
3
+ import type { ValuePathSegment } from "../ast/types.js";
4
+ export type DataSourceKind = "static-source" | "prop-source" | "repeat-item-source" | "api-source" | "external-adapter-source" | "derived-readonly" | "unknown-unsupported";
5
+ export interface DataSourceClassification {
6
+ kind: DataSourceKind;
7
+ readonly: boolean;
8
+ sourceId: string;
9
+ displayPath: string;
10
+ reason: string;
11
+ }
12
+ export declare function classifyExpressionDataSource(expressionPath: NodePath<t.Expression>, valuePath?: ValuePathSegment[]): DataSourceClassification | null;
13
+ export declare function classifyBindingDataSource(binding: Binding, valuePath?: ValuePathSegment[]): DataSourceClassification | null;
14
+ export declare function isApiSource(classification: DataSourceClassification | null): classification is DataSourceClassification;
@@ -0,0 +1,281 @@
1
+ import _traverse from "@babel/traverse";
2
+ import * as t from "@babel/types";
3
+ const traverse = (typeof _traverse === "function" ? _traverse : _traverse.default);
4
+ export function classifyExpressionDataSource(expressionPath, valuePath = []) {
5
+ if (expressionPath.isIdentifier()) {
6
+ const binding = expressionPath.scope.getBinding(expressionPath.node.name);
7
+ return binding ? classifyBindingDataSource(binding, valuePath) : null;
8
+ }
9
+ if (expressionPath.isMemberExpression()) {
10
+ const root = getMemberExpressionRoot(expressionPath.node);
11
+ if (!root) {
12
+ return null;
13
+ }
14
+ const binding = expressionPath.scope.getBinding(root);
15
+ return binding ? classifyBindingDataSource(binding, valuePath) : null;
16
+ }
17
+ if (expressionPath.isAwaitExpression() ||
18
+ isFetchLikeExpression(expressionPath.node)) {
19
+ return apiSource(getExpressionSourceId(expressionPath.node), valuePath, "awaited or fetched expression");
20
+ }
21
+ return null;
22
+ }
23
+ export function classifyBindingDataSource(binding, valuePath = []) {
24
+ const queryHook = classifyQueryHookDataBinding(binding, valuePath);
25
+ if (queryHook) {
26
+ return queryHook;
27
+ }
28
+ const hookState = classifyHookStateBinding(binding, valuePath);
29
+ if (hookState) {
30
+ return hookState;
31
+ }
32
+ const asyncResult = classifyAsyncResultBinding(binding, valuePath);
33
+ if (asyncResult) {
34
+ return asyncResult;
35
+ }
36
+ return null;
37
+ }
38
+ export function isApiSource(classification) {
39
+ return classification?.kind === "api-source";
40
+ }
41
+ function classifyQueryHookDataBinding(binding, valuePath) {
42
+ if (binding.path.isVariableDeclarator() &&
43
+ t.isObjectPattern(binding.path.node.id)) {
44
+ const prop = binding.path.node.id.properties.find((property) => t.isObjectProperty(property) &&
45
+ getObjectPropertyKey(property) === "data" &&
46
+ patternContainsBinding(property.value, binding.identifier.name));
47
+ const initPath = binding.path.get("init");
48
+ if (prop &&
49
+ initPath?.isCallExpression() &&
50
+ isQueryHookCall(initPath.node)) {
51
+ return apiSource(binding.identifier.name, valuePath, "query hook data binding");
52
+ }
53
+ }
54
+ const propertyPath = findObjectPropertyForBinding(binding);
55
+ if (!propertyPath) {
56
+ return null;
57
+ }
58
+ const propertyName = getObjectPropertyKey(propertyPath.node);
59
+ if (propertyName !== "data") {
60
+ return null;
61
+ }
62
+ const declaratorPath = propertyPath.findParent((parent) => parent.isVariableDeclarator());
63
+ if (!declaratorPath?.isVariableDeclarator()) {
64
+ return null;
65
+ }
66
+ const initPath = declaratorPath.get("init");
67
+ if (!initPath?.isCallExpression() || !isQueryHookCall(initPath.node)) {
68
+ return null;
69
+ }
70
+ return apiSource(binding.identifier.name, valuePath, "query hook data binding");
71
+ }
72
+ function classifyHookStateBinding(binding, valuePath) {
73
+ if (binding.path.isVariableDeclarator() &&
74
+ t.isArrayPattern(binding.path.node.id)) {
75
+ const initPath = binding.path.get("init");
76
+ if (!initPath?.isCallExpression() || !isUseStateCall(initPath.node)) {
77
+ return null;
78
+ }
79
+ const [state, setter] = binding.path.node.id.elements;
80
+ if (!t.isIdentifier(state) ||
81
+ state.name !== binding.identifier.name ||
82
+ !t.isIdentifier(setter)) {
83
+ return null;
84
+ }
85
+ return scopeWritesSetterFromApi(binding, setter.name)
86
+ ? apiSource(binding.identifier.name, valuePath, "state setter is updated by API data")
87
+ : null;
88
+ }
89
+ if (!binding.path.isIdentifier()) {
90
+ return null;
91
+ }
92
+ const arrayPattern = binding.path.parentPath;
93
+ if (!arrayPattern?.isArrayPattern()) {
94
+ return null;
95
+ }
96
+ const declaratorPath = arrayPattern.parentPath;
97
+ if (!declaratorPath?.isVariableDeclarator()) {
98
+ return null;
99
+ }
100
+ const initPath = declaratorPath.get("init");
101
+ if (!initPath?.isCallExpression() || !isUseStateCall(initPath.node)) {
102
+ return null;
103
+ }
104
+ const stateIndex = arrayPattern.node.elements.findIndex((element) => element === binding.path.node);
105
+ if (stateIndex !== 0) {
106
+ return null;
107
+ }
108
+ const setter = arrayPattern.node.elements[1];
109
+ if (!t.isIdentifier(setter)) {
110
+ return null;
111
+ }
112
+ return scopeWritesSetterFromApi(binding, setter.name)
113
+ ? apiSource(binding.identifier.name, valuePath, "state setter is updated by API data")
114
+ : null;
115
+ }
116
+ function classifyAsyncResultBinding(binding, valuePath) {
117
+ const declaratorPath = binding.path.isVariableDeclarator()
118
+ ? binding.path
119
+ : binding.path.findParent((parent) => parent.isVariableDeclarator());
120
+ if (!declaratorPath?.isVariableDeclarator()) {
121
+ return null;
122
+ }
123
+ const initPath = declaratorPath.get("init");
124
+ if (!initPath?.isExpression()) {
125
+ return null;
126
+ }
127
+ if (initPath.isAwaitExpression()) {
128
+ return apiSource(binding.identifier.name, valuePath, "awaited binding result");
129
+ }
130
+ if (isFetchLikeExpression(initPath.node)) {
131
+ return apiSource(binding.identifier.name, valuePath, "fetch-backed binding result");
132
+ }
133
+ return null;
134
+ }
135
+ function findObjectPropertyForBinding(binding) {
136
+ if (!binding.path.isIdentifier()) {
137
+ return null;
138
+ }
139
+ const parent = binding.path.parentPath;
140
+ if (parent?.isObjectProperty()) {
141
+ return parent;
142
+ }
143
+ if (parent?.isAssignmentPattern() && parent.parentPath?.isObjectProperty()) {
144
+ return parent.parentPath;
145
+ }
146
+ return null;
147
+ }
148
+ function patternContainsBinding(pattern, bindingName) {
149
+ if (t.isIdentifier(pattern)) {
150
+ return pattern.name === bindingName;
151
+ }
152
+ if (t.isAssignmentPattern(pattern)) {
153
+ return patternContainsBinding(pattern.left, bindingName);
154
+ }
155
+ if (t.isObjectPattern(pattern)) {
156
+ return pattern.properties.some((property) => t.isObjectProperty(property)
157
+ ? patternContainsBinding(property.value, bindingName)
158
+ : patternContainsBinding(property.argument, bindingName));
159
+ }
160
+ if (t.isArrayPattern(pattern)) {
161
+ return pattern.elements.some((element) => !!element &&
162
+ patternContainsBinding((t.isRestElement(element)
163
+ ? element.argument
164
+ : element), bindingName));
165
+ }
166
+ return false;
167
+ }
168
+ function scopeWritesSetterFromApi(binding, setterName) {
169
+ let hasFetch = false;
170
+ let writesSetter = false;
171
+ const scopeRoot = binding.scope.path;
172
+ scopeRoot.traverse({
173
+ CallExpression(path) {
174
+ if (isFetchLikeExpression(path.node)) {
175
+ hasFetch = true;
176
+ }
177
+ if (usesIdentifier(path.node.callee, setterName) ||
178
+ path.node.arguments.some((argument) => t.isIdentifier(argument) && argument.name === setterName)) {
179
+ writesSetter = true;
180
+ }
181
+ },
182
+ });
183
+ return hasFetch && writesSetter;
184
+ }
185
+ function isQueryHookCall(call) {
186
+ const calleeName = getCalleeName(call.callee);
187
+ return (calleeName === "useQuery" ||
188
+ calleeName === "useSWR" ||
189
+ calleeName === "useSuspenseQuery");
190
+ }
191
+ function isUseStateCall(call) {
192
+ return getCalleeName(call.callee) === "useState";
193
+ }
194
+ function isFetchLikeExpression(expression) {
195
+ return visitNode(expression, (node) => {
196
+ return t.isCallExpression(node) && getCalleeName(node.callee) === "fetch";
197
+ });
198
+ }
199
+ function getMemberExpressionRoot(expression) {
200
+ let current = expression;
201
+ while (t.isMemberExpression(current)) {
202
+ current = current.object;
203
+ }
204
+ return t.isIdentifier(current) ? current.name : null;
205
+ }
206
+ function getObjectPropertyKey(property) {
207
+ if (property.computed) {
208
+ return null;
209
+ }
210
+ if (t.isIdentifier(property.key)) {
211
+ return property.key.name;
212
+ }
213
+ if (t.isStringLiteral(property.key)) {
214
+ return property.key.value;
215
+ }
216
+ return null;
217
+ }
218
+ function getCalleeName(callee) {
219
+ if (t.isIdentifier(callee)) {
220
+ return callee.name;
221
+ }
222
+ if (t.isMemberExpression(callee) && t.isIdentifier(callee.property)) {
223
+ return callee.property.name;
224
+ }
225
+ return null;
226
+ }
227
+ function usesIdentifier(node, name) {
228
+ return visitNode(node, (candidate) => {
229
+ return t.isIdentifier(candidate) && candidate.name === name;
230
+ });
231
+ }
232
+ function visitNode(node, predicate) {
233
+ if (predicate(node)) {
234
+ return true;
235
+ }
236
+ const keys = t.VISITOR_KEYS[node.type];
237
+ if (!keys) {
238
+ return false;
239
+ }
240
+ for (const key of keys) {
241
+ const value = node[key];
242
+ if (Array.isArray(value)) {
243
+ for (const item of value) {
244
+ if (t.isNode(item) && visitNode(item, predicate)) {
245
+ return true;
246
+ }
247
+ }
248
+ continue;
249
+ }
250
+ if (t.isNode(value) && visitNode(value, predicate)) {
251
+ return true;
252
+ }
253
+ }
254
+ return false;
255
+ }
256
+ function getExpressionSourceId(expression) {
257
+ if (t.isIdentifier(expression)) {
258
+ return expression.name;
259
+ }
260
+ if (t.isCallExpression(expression)) {
261
+ return getCalleeName(expression.callee) ?? "api";
262
+ }
263
+ if (t.isAwaitExpression(expression)) {
264
+ return "awaited-api";
265
+ }
266
+ return "api";
267
+ }
268
+ function apiSource(sourceId, valuePath, reason) {
269
+ return {
270
+ kind: "api-source",
271
+ readonly: true,
272
+ sourceId,
273
+ displayPath: appendValuePath(sourceId, valuePath),
274
+ reason,
275
+ };
276
+ }
277
+ function appendValuePath(base, path) {
278
+ return path.reduce((expression, segment) => segment.kind === "property"
279
+ ? `${expression}.${segment.name}`
280
+ : `${expression}[${segment.index}]`, base);
281
+ }
@@ -0,0 +1,45 @@
1
+ import * as t from "@babel/types";
2
+ import type { ConditionalSourceCandidate, RenderSourceGraph, TextSegment } from "../graph/types.js";
3
+ import type { ExternalAdapterRegistration, ExternalSourceResolver, FunctionCallContract, ProvenanceResolution, ResolvedTextWriteTarget } from "./types.js";
4
+ interface ResolveParams {
5
+ file: string;
6
+ source: string;
7
+ segment: TextSegment;
8
+ readFile: (file: string) => Promise<string>;
9
+ exists: (file: string) => Promise<boolean>;
10
+ graph?: RenderSourceGraph;
11
+ externalSourceResolvers?: ExternalSourceResolver[];
12
+ externalAdapters?: ExternalAdapterRegistration[];
13
+ functionCallContracts?: FunctionCallContract[];
14
+ fileCache?: ProvenanceFileCache;
15
+ }
16
+ interface ResolveBaseParams {
17
+ file: string;
18
+ source: string;
19
+ readFile: (file: string) => Promise<string>;
20
+ exists: (file: string) => Promise<boolean>;
21
+ graph?: RenderSourceGraph;
22
+ externalSourceResolvers?: ExternalSourceResolver[];
23
+ externalAdapters?: ExternalAdapterRegistration[];
24
+ functionCallContracts?: FunctionCallContract[];
25
+ fileCache?: ProvenanceFileCache;
26
+ }
27
+ export type ResolveProvenanceParams = (ResolveBaseParams & {
28
+ target: {
29
+ kind: "text-segment";
30
+ segment: TextSegment;
31
+ };
32
+ }) | (ResolveBaseParams & {
33
+ target: {
34
+ kind: "conditional-branch";
35
+ candidate: ConditionalSourceCandidate;
36
+ };
37
+ });
38
+ interface LoadedFile {
39
+ source: string;
40
+ ast: t.File | null;
41
+ }
42
+ export type ProvenanceFileCache = Map<string, LoadedFile>;
43
+ export declare function resolveTextProvenance(params: ResolveParams): Promise<ResolvedTextWriteTarget | null>;
44
+ export declare function resolveProvenance(params: ResolveProvenanceParams): Promise<ProvenanceResolution>;
45
+ export {};