@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,10 @@
1
+ export { updateText } from "./jsx/index.js";
2
+ export { removeNode } from "./jsx/index.js";
3
+ export { insertChild } from "./jsx/index.js";
4
+ export { moveNode } from "./jsx/index.js";
5
+ export { addImport, } from "./imports/index.js";
6
+ export { removeImport, } from "./imports/index.js";
7
+ export { updateValue, insertArrayElement, removeArrayElement, moveArrayElement, insertObjectProperty, removeObjectProperty, } from "./values/index.js";
8
+ export { replaceConditionalExpression, setConditionalBranchContent, } from "./conditional/index.js";
9
+ export { addDirective, removeDirective, updateDirective, updateNamedExport, updateMetadataField, updateGenerateMetadata, } from "./next/index.js";
10
+ export { setJsxAttribute, removeJsxAttribute, updateClassName, addTailwindClass, removeTailwindClass, updateStyleProperty, updateStyleProperties, updateCssModuleClassReference, } from "./style/index.js";
@@ -0,0 +1,4 @@
1
+ export { updateText, type UpdateTextParams } from "./update-text.js";
2
+ export { removeNode, type RemoveNodeParams } from "./remove-node.js";
3
+ export { insertChild, type InsertChildParams } from "./insert-child.js";
4
+ export { moveNode, type MoveNodeParams } from "./move-node.js";
@@ -0,0 +1,4 @@
1
+ export { updateText } from "./update-text.js";
2
+ export { removeNode } from "./remove-node.js";
3
+ export { insertChild } from "./insert-child.js";
4
+ export { moveNode } from "./move-node.js";
@@ -0,0 +1,11 @@
1
+ import type { AstPrimitiveResult, JsxNodeLocator, Placement } from "../../types.js";
2
+ export interface InsertChildParams {
3
+ source: string;
4
+ locator: JsxNodeLocator;
5
+ node: {
6
+ jsx: string;
7
+ };
8
+ placement: Placement;
9
+ anchorLocator?: JsxNodeLocator;
10
+ }
11
+ export declare function insertChild(params: InsertChildParams): AstPrimitiveResult;
@@ -0,0 +1,69 @@
1
+ import { cloneNode, } from "@babel/types";
2
+ import { primitiveFailure } from "../../diagnostics/index.js";
3
+ import { resolveLocatorPath } from "../../locators/index.js";
4
+ import { parseJsxNodeSource, parseMutationSource, printMutationWithOperation, } from "../shared.js";
5
+ export function insertChild(params) {
6
+ const { source, locator, node, placement, anchorLocator } = params;
7
+ const parsed = parseMutationSource(source, "jsx-node");
8
+ /* node:coverage ignore start */
9
+ if (!parsed.ok) {
10
+ return parsed.result;
11
+ }
12
+ /* node:coverage ignore stop */
13
+ const parentMatch = resolveLocatorPath(parsed.ast, locator);
14
+ if (!parentMatch.ok) {
15
+ return { ok: false, source, diagnostic: parentMatch.diagnostic };
16
+ }
17
+ const parentNode = parentMatch.match.path.node;
18
+ if (!parentMatch.match.path.isJSXElement() &&
19
+ !parentMatch.match.path.isJSXFragment()) {
20
+ return primitiveFailure(source, "unsupported-syntax", "insert-child target must be a JSXElement or JSXFragment", "jsx-node");
21
+ }
22
+ if (parentMatch.match.path.isJSXElement()) {
23
+ if (!parentNode.closingElement || parentNode.openingElement.selfClosing) {
24
+ return primitiveFailure(source, "self-closing-element", "Cannot insert child into self-closing element", "jsx-node");
25
+ }
26
+ }
27
+ const parsedNode = parseJsxNodeSource(source, node.jsx);
28
+ if (!parsedNode.ok) {
29
+ return parsedNode.result;
30
+ }
31
+ const nextChild = cloneNode(parsedNode.node, true);
32
+ const children = parentNode.children;
33
+ if (placement === "append") {
34
+ children.push(nextChild);
35
+ return printMutationWithOperation(parsed.ast, source, {
36
+ kind: "insert-child",
37
+ target: "jsx-node",
38
+ inverse: "remove-child",
39
+ });
40
+ }
41
+ if (placement === "prepend") {
42
+ children.unshift(nextChild);
43
+ return printMutationWithOperation(parsed.ast, source, {
44
+ kind: "insert-child",
45
+ target: "jsx-node",
46
+ inverse: "remove-child",
47
+ });
48
+ }
49
+ if (!anchorLocator) {
50
+ return primitiveFailure(source, "locator-miss", `Placement '${placement}' requires anchorLocator`, "jsx-node");
51
+ }
52
+ const anchorMatch = resolveLocatorPath(parsed.ast, anchorLocator);
53
+ if (!anchorMatch.ok)
54
+ return { ok: false, source, diagnostic: anchorMatch.diagnostic };
55
+ if (anchorMatch.match.path.parentPath !== parentMatch.match.path ||
56
+ anchorMatch.match.path.listKey !== "children") {
57
+ return primitiveFailure(source, "invalid-parent-child-relation", "Anchor node is not a direct child of the target parent", "jsx-node");
58
+ }
59
+ const anchorIndex = children.findIndex((child) => child === anchorMatch.match.path.node);
60
+ if (anchorIndex === -1) {
61
+ return primitiveFailure(source, "locator-miss", "Anchor node no longer exists in target parent", "jsx-node");
62
+ }
63
+ children.splice(placement === "before" ? anchorIndex : anchorIndex + 1, 0, nextChild);
64
+ return printMutationWithOperation(parsed.ast, source, {
65
+ kind: "insert-child",
66
+ target: "jsx-node",
67
+ inverse: "remove-child",
68
+ });
69
+ }
@@ -0,0 +1,9 @@
1
+ import type { AstPrimitiveResult, JsxNodeLocator, Placement } from "../../types.js";
2
+ export interface MoveNodeParams {
3
+ source: string;
4
+ locator: JsxNodeLocator;
5
+ targetParentLocator: JsxNodeLocator;
6
+ placement: Placement;
7
+ anchorLocator?: JsxNodeLocator;
8
+ }
9
+ export declare function moveNode(params: MoveNodeParams): AstPrimitiveResult;
@@ -0,0 +1,76 @@
1
+ import { cloneNode, nullLiteral } from "@babel/types";
2
+ import { primitiveFailure } from "../../diagnostics/index.js";
3
+ import { resolveLocatorPath } from "../../locators/index.js";
4
+ import { parseMutationSource, printMutation } from "../shared.js";
5
+ export function moveNode(params) {
6
+ const { source, locator, targetParentLocator, placement, anchorLocator } = params;
7
+ const parsed = parseMutationSource(source, "jsx-node");
8
+ if (!parsed.ok) {
9
+ return parsed.result;
10
+ }
11
+ const sourceMatch = resolveLocatorPath(parsed.ast, locator);
12
+ if (!sourceMatch.ok) {
13
+ return { ok: false, source, diagnostic: sourceMatch.diagnostic };
14
+ }
15
+ const targetParentMatch = resolveLocatorPath(parsed.ast, targetParentLocator);
16
+ if (!targetParentMatch.ok) {
17
+ return { ok: false, source, diagnostic: targetParentMatch.diagnostic };
18
+ }
19
+ if (!targetParentMatch.match.path.isJSXElement()) {
20
+ return primitiveFailure(source, "unsupported-syntax", "move-node target parent must be a JSXElement", "jsx-node");
21
+ }
22
+ const targetParent = targetParentMatch.match.path.node;
23
+ if (!targetParent.closingElement || targetParent.openingElement.selfClosing) {
24
+ return primitiveFailure(source, "self-closing-element", "Cannot move child into self-closing element", "jsx-node");
25
+ }
26
+ let anchorNode = null;
27
+ if (!anchorLocator) {
28
+ if (placement === "before" || placement === "after") {
29
+ return primitiveFailure(source, "locator-miss", `Placement '${placement}' requires anchorLocator`, "jsx-node");
30
+ }
31
+ }
32
+ else {
33
+ const anchorMatch = resolveLocatorPath(parsed.ast, anchorLocator);
34
+ if (!anchorMatch.ok) {
35
+ return { ok: false, source, diagnostic: anchorMatch.diagnostic };
36
+ }
37
+ if (anchorMatch.match.path.parentPath !== targetParentMatch.match.path ||
38
+ anchorMatch.match.path.listKey !== "children") {
39
+ return primitiveFailure(source, "invalid-parent-child-relation", "Anchor node is not a direct child of the target parent", "jsx-node");
40
+ }
41
+ anchorNode = anchorMatch.match.path.node;
42
+ }
43
+ const movingNode = cloneNode(sourceMatch.match.path.node, true);
44
+ removeMovedJsxNodePath(sourceMatch.match.path);
45
+ const children = targetParent.children;
46
+ if (placement === "append") {
47
+ children.push(movingNode);
48
+ return printMutation(parsed.ast, source);
49
+ }
50
+ if (placement === "prepend") {
51
+ children.unshift(movingNode);
52
+ return printMutation(parsed.ast, source);
53
+ }
54
+ const anchorIndex = children.findIndex((child) => child === anchorNode);
55
+ if (anchorIndex === -1) {
56
+ return primitiveFailure(source, "locator-miss", "Anchor node no longer exists in target parent", "jsx-node");
57
+ }
58
+ children.splice(placement === "before" ? anchorIndex : anchorIndex + 1, 0, movingNode);
59
+ return printMutation(parsed.ast, source);
60
+ }
61
+ function removeMovedJsxNodePath(path) {
62
+ if (path.parentPath?.isConditionalExpression() &&
63
+ (path.key === "consequent" || path.key === "alternate")) {
64
+ path.replaceWith(nullLiteral());
65
+ return;
66
+ }
67
+ if (path.parentPath?.isArrowFunctionExpression() && path.key === "body") {
68
+ path.replaceWith(nullLiteral());
69
+ return;
70
+ }
71
+ if (path.parentPath?.isReturnStatement() && path.key === "argument") {
72
+ path.replaceWith(nullLiteral());
73
+ return;
74
+ }
75
+ path.remove();
76
+ }
@@ -0,0 +1,7 @@
1
+ import type { AstPrimitiveResult, JsxNodeLocator } from "../../types.js";
2
+ export interface RemoveNodeParams {
3
+ source: string;
4
+ locator: JsxNodeLocator;
5
+ removeWhitespace?: boolean;
6
+ }
7
+ export declare function removeNode(params: RemoveNodeParams): AstPrimitiveResult;
@@ -0,0 +1,36 @@
1
+ import { nullLiteral } from "@babel/types";
2
+ import { resolveLocatorPath } from "../../locators/index.js";
3
+ import { parseMutationSource, printMutationWithOperation } from "../shared.js";
4
+ export function removeNode(params) {
5
+ const { source, locator } = params;
6
+ const parsed = parseMutationSource(source, "jsx-node");
7
+ if (!parsed.ok) {
8
+ return parsed.result;
9
+ }
10
+ const match = resolveLocatorPath(parsed.ast, locator);
11
+ if (!match.ok) {
12
+ return { ok: false, source, diagnostic: match.diagnostic };
13
+ }
14
+ removeJsxNodePathSafely(match.match.path);
15
+ return printMutationWithOperation(parsed.ast, source, {
16
+ kind: "remove-node",
17
+ target: "jsx-node",
18
+ inverse: "insert-child",
19
+ });
20
+ }
21
+ function removeJsxNodePathSafely(path) {
22
+ if (path.parentPath?.isConditionalExpression() &&
23
+ (path.key === "consequent" || path.key === "alternate")) {
24
+ path.replaceWith(nullLiteral());
25
+ return;
26
+ }
27
+ if (path.parentPath?.isArrowFunctionExpression() && path.key === "body") {
28
+ path.replaceWith(nullLiteral());
29
+ return;
30
+ }
31
+ if (path.parentPath?.isReturnStatement() && path.key === "argument") {
32
+ path.replaceWith(nullLiteral());
33
+ return;
34
+ }
35
+ path.remove();
36
+ }
@@ -0,0 +1,8 @@
1
+ import type { AstPrimitiveResult, JsxNodeLocator } from "../../types.js";
2
+ export interface UpdateTextParams {
3
+ source: string;
4
+ locator: JsxNodeLocator;
5
+ segmentIndex: number;
6
+ newText: string;
7
+ }
8
+ export declare function updateText(params: UpdateTextParams): AstPrimitiveResult;
@@ -0,0 +1,81 @@
1
+ import { primitiveFailure } from "../../diagnostics/index.js";
2
+ import { resolveLocatorPath } from "../../locators/index.js";
3
+ import { parseMutationSource, printMutationWithOperation } from "../shared.js";
4
+ export function updateText(params) {
5
+ const { source, locator, segmentIndex, newText } = params;
6
+ const parsed = parseMutationSource(source, "jsx-node");
7
+ if (!parsed.ok) {
8
+ return parsed.result;
9
+ }
10
+ const match = resolveLocatorPath(parsed.ast, locator);
11
+ if (!match.ok) {
12
+ return { ok: false, source, diagnostic: match.diagnostic };
13
+ }
14
+ const segments = collectTextSegments(match.match.path);
15
+ const segment = segments[segmentIndex];
16
+ if (!segment) {
17
+ return primitiveFailure(source, "locator-miss", `Text segment ${segmentIndex} not found`, "jsx-node");
18
+ }
19
+ switch (segment.kind) {
20
+ case "jsx-text":
21
+ segment.path.node.value = newText;
22
+ break;
23
+ case "string-literal":
24
+ segment.path.node.value = newText;
25
+ break;
26
+ case "template-literal": {
27
+ const quasiIndex = segment.quasiIndex;
28
+ segment.path.node.quasis[quasiIndex].value.raw = newText;
29
+ segment.path.node.quasis[quasiIndex].value.cooked = newText;
30
+ break;
31
+ }
32
+ }
33
+ return printMutationWithOperation(parsed.ast, source, {
34
+ kind: "update-text",
35
+ target: "jsx-node",
36
+ inverse: "restore-text",
37
+ });
38
+ }
39
+ function collectTextSegments(path) {
40
+ const segments = [];
41
+ path.traverse({
42
+ JSXText(textPath) {
43
+ if (textPath.node.value.trim().length > 0) {
44
+ segments.push({ kind: "jsx-text", path: textPath });
45
+ }
46
+ },
47
+ JSXExpressionContainer(containerPath) {
48
+ const segs = resolveExpressionTextSegments(containerPath.get("expression"));
49
+ if (segs.length > 0) {
50
+ segments.push(...segs);
51
+ }
52
+ },
53
+ });
54
+ return segments;
55
+ }
56
+ function resolveExpressionTextSegments(expression) {
57
+ if (expression.isStringLiteral()) {
58
+ return [{ kind: "string-literal", path: expression }];
59
+ }
60
+ if (expression.isTemplateLiteral()) {
61
+ const segments = [];
62
+ const quasis = expression.node.quasis;
63
+ for (let i = 0; i < quasis.length; i++) {
64
+ const quasi = quasis[i];
65
+ if (quasi.value.raw.trim().length > 0) {
66
+ segments.push({
67
+ kind: "template-literal",
68
+ path: expression,
69
+ quasiIndex: i,
70
+ });
71
+ }
72
+ }
73
+ if (segments.length > 0) {
74
+ return segments;
75
+ }
76
+ }
77
+ if (!expression.isCallExpression()) {
78
+ return [];
79
+ }
80
+ return [];
81
+ }
@@ -0,0 +1 @@
1
+ export { addDirective, removeDirective, updateDirective, updateNamedExport, updateMetadataField, updateGenerateMetadata, type AddDirectiveParams, type RemoveDirectiveParams, type UpdateDirectiveParams, type UpdateNamedExportParams, type UpdateMetadataFieldParams, type UpdateGenerateMetadataParams, } from "./next-primitives.js";
@@ -0,0 +1 @@
1
+ export { addDirective, removeDirective, updateDirective, updateNamedExport, updateMetadataField, updateGenerateMetadata, } from "./next-primitives.js";
@@ -0,0 +1,43 @@
1
+ import type { AstPrimitiveResult, DirectiveLocator, ExportLocator, PrimitiveValue, ValuePathSegment } from "../../types.js";
2
+ export interface AddDirectiveParams {
3
+ source: string;
4
+ value: string;
5
+ }
6
+ export interface RemoveDirectiveParams {
7
+ source: string;
8
+ locator: DirectiveLocator;
9
+ }
10
+ export interface UpdateDirectiveParams {
11
+ source: string;
12
+ locator: DirectiveLocator;
13
+ nextValue: string;
14
+ }
15
+ export interface UpdateNamedExportParams {
16
+ source: string;
17
+ locator: Extract<ExportLocator, {
18
+ exportKind: "named";
19
+ }>;
20
+ next: PrimitiveValue;
21
+ }
22
+ export interface UpdateMetadataFieldParams {
23
+ source: string;
24
+ locator: Extract<ExportLocator, {
25
+ exportKind: "metadata";
26
+ }>;
27
+ path: ValuePathSegment[];
28
+ next: PrimitiveValue;
29
+ }
30
+ export interface UpdateGenerateMetadataParams {
31
+ source: string;
32
+ locator: Extract<ExportLocator, {
33
+ exportKind: "generate-metadata";
34
+ }>;
35
+ path: ValuePathSegment[];
36
+ next: PrimitiveValue;
37
+ }
38
+ export declare function addDirective(params: AddDirectiveParams): AstPrimitiveResult;
39
+ export declare function removeDirective(params: RemoveDirectiveParams): AstPrimitiveResult;
40
+ export declare function updateDirective(params: UpdateDirectiveParams): AstPrimitiveResult;
41
+ export declare function updateNamedExport(params: UpdateNamedExportParams): AstPrimitiveResult;
42
+ export declare function updateMetadataField(params: UpdateMetadataFieldParams): AstPrimitiveResult;
43
+ export declare function updateGenerateMetadata(params: UpdateGenerateMetadataParams): AstPrimitiveResult;
@@ -0,0 +1,211 @@
1
+ import { directive, directiveLiteral } from "@babel/types";
2
+ import { primitiveFailure } from "../../diagnostics/index.js";
3
+ import { resolveLocatorPath } from "../../locators/index.js";
4
+ import { parseMutationSource, printMutationWithOperation, valueToExpression, } from "../shared.js";
5
+ export function addDirective(params) {
6
+ const { source, value } = params;
7
+ const parsed = parseMutationSource(source, "directive");
8
+ if (!parsed.ok) {
9
+ return parsed.result;
10
+ }
11
+ const conflict = conflictingDirective(value);
12
+ if (conflict &&
13
+ parsed.ast.program.directives.some((item) => item.value.value === conflict)) {
14
+ return primitiveFailure(source, "directive-conflict", `Directive '${value}' conflicts with '${conflict}'`, "directive");
15
+ }
16
+ if (!parsed.ast.program.directives.some((item) => item.value.value === value)) {
17
+ parsed.ast.program.directives.unshift(directive(directiveLiteral(value)));
18
+ }
19
+ return printMutationWithOperation(parsed.ast, source, {
20
+ kind: "add-directive",
21
+ target: "directive",
22
+ inverse: "remove-directive",
23
+ });
24
+ }
25
+ export function removeDirective(params) {
26
+ const { source, locator } = params;
27
+ const parsed = parseMutationSource(source, "directive");
28
+ if (!parsed.ok) {
29
+ return parsed.result;
30
+ }
31
+ const resolved = resolveLocatorPath(parsed.ast, locator);
32
+ if (!resolved.ok) {
33
+ return { ok: false, source, diagnostic: resolved.diagnostic };
34
+ }
35
+ resolved.match.path.remove();
36
+ return printMutationWithOperation(parsed.ast, source, {
37
+ kind: "remove-directive",
38
+ target: "directive",
39
+ inverse: "add-directive",
40
+ });
41
+ }
42
+ export function updateDirective(params) {
43
+ const { source, locator, nextValue } = params;
44
+ const parsed = parseMutationSource(source, "directive");
45
+ if (!parsed.ok) {
46
+ return parsed.result;
47
+ }
48
+ const conflict = conflictingDirective(nextValue);
49
+ if (conflict &&
50
+ parsed.ast.program.directives.some((item) => item.value.value === conflict && item.value.value !== locator.value)) {
51
+ return primitiveFailure(source, "directive-conflict", `Directive '${nextValue}' conflicts with '${conflict}'`, "directive");
52
+ }
53
+ const resolved = resolveLocatorPath(parsed.ast, locator);
54
+ if (!resolved.ok) {
55
+ return { ok: false, source, diagnostic: resolved.diagnostic };
56
+ }
57
+ resolved.match.path.node.value.value = nextValue;
58
+ return printMutationWithOperation(parsed.ast, source, {
59
+ kind: "update-directive",
60
+ target: "directive",
61
+ inverse: "restore-directive",
62
+ });
63
+ }
64
+ export function updateNamedExport(params) {
65
+ const { source, locator, next } = params;
66
+ const parsed = parseMutationSource(source, "export");
67
+ if (!parsed.ok) {
68
+ return parsed.result;
69
+ }
70
+ const resolved = resolveLocatorPath(parsed.ast, locator);
71
+ if (!resolved.ok) {
72
+ return { ok: false, source, diagnostic: resolved.diagnostic };
73
+ }
74
+ resolved.match.path.replaceWith(valueToExpression(next));
75
+ return printMutationWithOperation(parsed.ast, source, {
76
+ kind: "update-named-export",
77
+ target: "export",
78
+ inverse: "restore-named-export",
79
+ });
80
+ }
81
+ export function updateMetadataField(params) {
82
+ const { source, locator, path, next } = params;
83
+ const parsed = parseMutationSource(source, "export");
84
+ if (!parsed.ok) {
85
+ return parsed.result;
86
+ }
87
+ const resolved = resolveLocatorPath(parsed.ast, locator);
88
+ if (!resolved.ok) {
89
+ return { ok: false, source, diagnostic: resolved.diagnostic };
90
+ }
91
+ if (!resolved.match.path.isObjectExpression()) {
92
+ return primitiveFailure(source, "metadata-shape-unsupported", "metadata export must be a static object literal", "export");
93
+ }
94
+ const target = resolveMetadataObjectPath(resolved.match.path, path, source);
95
+ if (!target.ok) {
96
+ return target.result;
97
+ }
98
+ target.path.replaceWith(valueToExpression(next));
99
+ return printMutationWithOperation(parsed.ast, source, {
100
+ kind: "update-metadata-field",
101
+ target: "export",
102
+ inverse: "restore-metadata-field",
103
+ });
104
+ }
105
+ export function updateGenerateMetadata(params) {
106
+ const { source, locator, path, next } = params;
107
+ const parsed = parseMutationSource(source, "export");
108
+ if (!parsed.ok) {
109
+ return parsed.result;
110
+ }
111
+ const resolved = resolveLocatorPath(parsed.ast, locator);
112
+ if (!resolved.ok) {
113
+ return { ok: false, source, diagnostic: resolved.diagnostic };
114
+ }
115
+ const node = resolved.match.path.node;
116
+ const isFunctionDecl = resolved.match.path.isFunctionDeclaration();
117
+ const isArrowFunction = resolved.match.path.isArrowFunctionExpression();
118
+ if (!isFunctionDecl && !isArrowFunction) {
119
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must be a function", "export");
120
+ }
121
+ let returnArgument;
122
+ if (isFunctionDecl && node.body) {
123
+ const bodyStatements = resolved.match.path
124
+ .get("body")
125
+ .get("body");
126
+ if (bodyStatements.length !== 1 || !bodyStatements[0].isReturnStatement()) {
127
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must directly return an object literal", "export");
128
+ }
129
+ const argument = bodyStatements[0].get("argument");
130
+ if (!argument.node) {
131
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must directly return an object literal", "export");
132
+ }
133
+ returnArgument = argument;
134
+ }
135
+ else if (isArrowFunction) {
136
+ const body = node.body;
137
+ if (body.type === "BlockStatement") {
138
+ const bodyStatements = resolved.match.path.get("body");
139
+ const statements = bodyStatements.get("body");
140
+ if (statements.length !== 1 || !statements[0].isReturnStatement()) {
141
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must directly return an object literal", "export");
142
+ }
143
+ const argument = statements[0].get("argument");
144
+ if (!argument.node) {
145
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must directly return an object literal", "export");
146
+ }
147
+ returnArgument = argument;
148
+ }
149
+ else {
150
+ returnArgument = resolved.match.path.get("body");
151
+ }
152
+ }
153
+ else {
154
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must directly return an object literal", "export");
155
+ }
156
+ if (!returnArgument.node || !returnArgument.isObjectExpression()) {
157
+ return primitiveFailure(source, "metadata-shape-unsupported", "generateMetadata must directly return an object literal", "export");
158
+ }
159
+ const target = resolveMetadataObjectPath(returnArgument, path, source);
160
+ if (!target.ok) {
161
+ return target.result;
162
+ }
163
+ target.path.replaceWith(valueToExpression(next));
164
+ return printMutationWithOperation(parsed.ast, source, {
165
+ kind: "update-generate-metadata",
166
+ target: "export",
167
+ inverse: "restore-generate-metadata",
168
+ });
169
+ }
170
+ function resolveMetadataObjectPath(objectPath, segments, source) {
171
+ let current = objectPath;
172
+ for (const segment of segments) {
173
+ if (segment.kind !== "property" || !current.isObjectExpression()) {
174
+ return {
175
+ ok: false,
176
+ result: primitiveFailure(source, "metadata-shape-unsupported", "metadata path must stay within object properties", "export"),
177
+ };
178
+ }
179
+ if (current.node.properties.some((item) => item.type !== "ObjectProperty")) {
180
+ return {
181
+ ok: false,
182
+ result: primitiveFailure(source, "metadata-shape-unsupported", "metadata object cannot contain spread properties", "export"),
183
+ };
184
+ }
185
+ const property = current
186
+ .get("properties")
187
+ .find((item) => item.isObjectProperty() &&
188
+ (item.node.key.type === "Identifier"
189
+ ? item.node.key.name
190
+ : item.node.key.type === "StringLiteral"
191
+ ? item.node.key.value
192
+ : null) === segment.name);
193
+ if (!property || !property.isObjectProperty()) {
194
+ return {
195
+ ok: false,
196
+ result: primitiveFailure(source, "property-not-found", `Property '${segment.name}' not found`, "export"),
197
+ };
198
+ }
199
+ current = property.get("value");
200
+ }
201
+ return { ok: true, path: current };
202
+ }
203
+ function conflictingDirective(value) {
204
+ if (value === "use client") {
205
+ return "use server";
206
+ }
207
+ if (value === "use server") {
208
+ return "use client";
209
+ }
210
+ return null;
211
+ }
@@ -0,0 +1,60 @@
1
+ import type * as t from "@babel/types";
2
+ import type { AstDiagnostic, AstPrimitiveResult, JsxAttributeLocator, JsxNodeLocator, PrimitiveValue } from "../types.js";
3
+ import { type InternalLocatorMatch } from "../locators/index.js";
4
+ export interface OperationBuilderParams {
5
+ kind: string;
6
+ target: string;
7
+ inverse: string;
8
+ }
9
+ export declare function buildOperationDescription(beforeSource: string, afterSource: string, params: OperationBuilderParams): AstPrimitiveResult & {
10
+ ok: true;
11
+ };
12
+ export declare function printMutationWithOperation(ast: t.File, beforeSource: string, params: OperationBuilderParams): AstPrimitiveResult;
13
+ export type ParsedMutationResult = {
14
+ ok: true;
15
+ ast: t.File;
16
+ } | {
17
+ ok: false;
18
+ result: AstPrimitiveResult;
19
+ };
20
+ export declare function parseMutationSource(source: string, locatorKind?: InternalLocatorMatch["locatorKind"]): ParsedMutationResult;
21
+ export declare function printMutation(ast: t.File, source: string): AstPrimitiveResult;
22
+ export declare function resolveRequiredJsxNode(ast: t.File, locator: JsxNodeLocator, source: string): {
23
+ ok: true;
24
+ match: InternalLocatorMatch;
25
+ } | {
26
+ ok: false;
27
+ result: AstPrimitiveResult;
28
+ };
29
+ export declare function resolveRequiredJsxElement(ast: t.File, locator: JsxNodeLocator, source: string): {
30
+ ok: true;
31
+ match: InternalLocatorMatch;
32
+ } | {
33
+ ok: false;
34
+ result: AstPrimitiveResult;
35
+ };
36
+ export declare function resolveRequiredJsxAttribute(ast: t.File, locator: JsxAttributeLocator, source: string): {
37
+ ok: true;
38
+ match: InternalLocatorMatch;
39
+ } | {
40
+ ok: false;
41
+ result: AstPrimitiveResult;
42
+ };
43
+ export declare function resolveOptionalJsxAttribute(ast: t.File, locator: JsxAttributeLocator): {
44
+ ok: true;
45
+ match: InternalLocatorMatch | null;
46
+ } | {
47
+ ok: false;
48
+ diagnostic: AstDiagnostic;
49
+ };
50
+ export declare function valueToExpression(value: PrimitiveValue): t.Expression;
51
+ export declare function valueToJsxAttributeValue(value: PrimitiveValue): t.StringLiteral | t.JSXExpressionContainer;
52
+ export declare function createJsxAttribute(name: string, value: PrimitiveValue): t.JSXAttribute;
53
+ export declare function parseJsxNodeSource(source: string, jsx: string): {
54
+ ok: true;
55
+ node: t.JSXElement | t.JSXFragment;
56
+ } | {
57
+ ok: false;
58
+ result: AstPrimitiveResult;
59
+ };
60
+ export declare function objectPropertyKey(name: string): t.Identifier | t.StringLiteral;