sela-core 1.0.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 (144) hide show
  1. package/README.md +93 -0
  2. package/bin/sela.js +3 -0
  3. package/dist/cli/ErrorHandler.d.ts +10 -0
  4. package/dist/cli/ErrorHandler.d.ts.map +1 -0
  5. package/dist/cli/ErrorHandler.js +70 -0
  6. package/dist/cli/commands/bulk.d.ts +3 -0
  7. package/dist/cli/commands/bulk.d.ts.map +1 -0
  8. package/dist/cli/commands/bulk.js +140 -0
  9. package/dist/cli/commands/find.d.ts +3 -0
  10. package/dist/cli/commands/find.d.ts.map +1 -0
  11. package/dist/cli/commands/find.js +51 -0
  12. package/dist/cli/commands/init.d.ts +3 -0
  13. package/dist/cli/commands/init.d.ts.map +1 -0
  14. package/dist/cli/commands/init.js +133 -0
  15. package/dist/cli/commands/list.d.ts +3 -0
  16. package/dist/cli/commands/list.d.ts.map +1 -0
  17. package/dist/cli/commands/list.js +56 -0
  18. package/dist/cli/commands/refactor.d.ts +3 -0
  19. package/dist/cli/commands/refactor.d.ts.map +1 -0
  20. package/dist/cli/commands/refactor.js +30 -0
  21. package/dist/cli/commands/status.d.ts +3 -0
  22. package/dist/cli/commands/status.d.ts.map +1 -0
  23. package/dist/cli/commands/status.js +51 -0
  24. package/dist/cli/commands/sync.d.ts +3 -0
  25. package/dist/cli/commands/sync.d.ts.map +1 -0
  26. package/dist/cli/commands/sync.js +123 -0
  27. package/dist/cli/index.d.ts +2 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +42 -0
  30. package/dist/cli/ui/DnaTable.d.ts +3 -0
  31. package/dist/cli/ui/DnaTable.d.ts.map +1 -0
  32. package/dist/cli/ui/DnaTable.js +70 -0
  33. package/dist/cli/ui/LocatorPicker.d.ts +8 -0
  34. package/dist/cli/ui/LocatorPicker.d.ts.map +1 -0
  35. package/dist/cli/ui/LocatorPicker.js +33 -0
  36. package/dist/cli/ui/ProgressReporter.d.ts +11 -0
  37. package/dist/cli/ui/ProgressReporter.d.ts.map +1 -0
  38. package/dist/cli/ui/ProgressReporter.js +33 -0
  39. package/dist/cli/ui/RefactorWizard.d.ts +26 -0
  40. package/dist/cli/ui/RefactorWizard.d.ts.map +1 -0
  41. package/dist/cli/ui/RefactorWizard.js +269 -0
  42. package/dist/config/ConfigLoader.d.ts +15 -0
  43. package/dist/config/ConfigLoader.d.ts.map +1 -0
  44. package/dist/config/ConfigLoader.js +174 -0
  45. package/dist/config/SelaConfig.d.ts +67 -0
  46. package/dist/config/SelaConfig.d.ts.map +1 -0
  47. package/dist/config/SelaConfig.js +57 -0
  48. package/dist/config/defineConfig.d.ts +3 -0
  49. package/dist/config/defineConfig.d.ts.map +1 -0
  50. package/dist/config/defineConfig.js +9 -0
  51. package/dist/engine/FixwrightEngine.d.ts +24 -0
  52. package/dist/engine/FixwrightEngine.d.ts.map +1 -0
  53. package/dist/engine/FixwrightEngine.js +403 -0
  54. package/dist/engine/HealingRegistry.d.ts +40 -0
  55. package/dist/engine/HealingRegistry.d.ts.map +1 -0
  56. package/dist/engine/HealingRegistry.js +98 -0
  57. package/dist/engine/singleton.d.ts +3 -0
  58. package/dist/engine/singleton.d.ts.map +1 -0
  59. package/dist/engine/singleton.js +5 -0
  60. package/dist/fixtures/expectProxy.d.ts +12 -0
  61. package/dist/fixtures/expectProxy.d.ts.map +1 -0
  62. package/dist/fixtures/expectProxy.js +228 -0
  63. package/dist/fixtures/index.d.ts +6 -0
  64. package/dist/fixtures/index.d.ts.map +1 -0
  65. package/dist/fixtures/index.js +688 -0
  66. package/dist/fixtures/moduleExpect.d.ts +2 -0
  67. package/dist/fixtures/moduleExpect.d.ts.map +1 -0
  68. package/dist/fixtures/moduleExpect.js +46 -0
  69. package/dist/index.d.ts +7 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +28 -0
  72. package/dist/services/ASTSourceUpdater.d.ts +79 -0
  73. package/dist/services/ASTSourceUpdater.d.ts.map +1 -0
  74. package/dist/services/ASTSourceUpdater.js +3177 -0
  75. package/dist/services/ArgumentTypeAnalyzer.d.ts +26 -0
  76. package/dist/services/ArgumentTypeAnalyzer.d.ts.map +1 -0
  77. package/dist/services/ArgumentTypeAnalyzer.js +92 -0
  78. package/dist/services/BlastRadiusAnalyzer.d.ts +15 -0
  79. package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -0
  80. package/dist/services/BlastRadiusAnalyzer.js +103 -0
  81. package/dist/services/ChainValidator.d.ts +76 -0
  82. package/dist/services/ChainValidator.d.ts.map +1 -0
  83. package/dist/services/ChainValidator.js +569 -0
  84. package/dist/services/CrossFileHealer.d.ts +6 -0
  85. package/dist/services/CrossFileHealer.d.ts.map +1 -0
  86. package/dist/services/CrossFileHealer.js +134 -0
  87. package/dist/services/DefinitionTracer.d.ts +41 -0
  88. package/dist/services/DefinitionTracer.d.ts.map +1 -0
  89. package/dist/services/DefinitionTracer.js +350 -0
  90. package/dist/services/DnaEditorService.d.ts +31 -0
  91. package/dist/services/DnaEditorService.d.ts.map +1 -0
  92. package/dist/services/DnaEditorService.js +198 -0
  93. package/dist/services/DnaIndexService.d.ts +24 -0
  94. package/dist/services/DnaIndexService.d.ts.map +1 -0
  95. package/dist/services/DnaIndexService.js +131 -0
  96. package/dist/services/HealingAdvisory.d.ts +22 -0
  97. package/dist/services/HealingAdvisory.d.ts.map +1 -0
  98. package/dist/services/HealingAdvisory.js +42 -0
  99. package/dist/services/HealthReportService.d.ts +10 -0
  100. package/dist/services/HealthReportService.d.ts.map +1 -0
  101. package/dist/services/HealthReportService.js +84 -0
  102. package/dist/services/InitializerUpdater.d.ts +16 -0
  103. package/dist/services/InitializerUpdater.d.ts.map +1 -0
  104. package/dist/services/InitializerUpdater.js +37 -0
  105. package/dist/services/IntentAuditor.d.ts +39 -0
  106. package/dist/services/IntentAuditor.d.ts.map +1 -0
  107. package/dist/services/IntentAuditor.js +302 -0
  108. package/dist/services/LLMService.d.ts +100 -0
  109. package/dist/services/LLMService.d.ts.map +1 -0
  110. package/dist/services/LLMService.js +439 -0
  111. package/dist/services/SafetyGuard.d.ts +65 -0
  112. package/dist/services/SafetyGuard.d.ts.map +1 -0
  113. package/dist/services/SafetyGuard.js +524 -0
  114. package/dist/services/SnapshotService.d.ts +11 -0
  115. package/dist/services/SnapshotService.d.ts.map +1 -0
  116. package/dist/services/SnapshotService.js +349 -0
  117. package/dist/services/SourceLinkService.d.ts +26 -0
  118. package/dist/services/SourceLinkService.d.ts.map +1 -0
  119. package/dist/services/SourceLinkService.js +156 -0
  120. package/dist/services/SourceUpdater.d.ts +45 -0
  121. package/dist/services/SourceUpdater.d.ts.map +1 -0
  122. package/dist/services/SourceUpdater.js +1021 -0
  123. package/dist/services/TemplateDiffService.d.ts +25 -0
  124. package/dist/services/TemplateDiffService.d.ts.map +1 -0
  125. package/dist/services/TemplateDiffService.js +331 -0
  126. package/dist/services/types.d.ts +59 -0
  127. package/dist/services/types.d.ts.map +1 -0
  128. package/dist/services/types.js +2 -0
  129. package/dist/storage/SnapshotManager.d.ts +5 -0
  130. package/dist/storage/SnapshotManager.d.ts.map +1 -0
  131. package/dist/storage/SnapshotManager.js +31 -0
  132. package/dist/types/index.d.ts +95 -0
  133. package/dist/types/index.d.ts.map +1 -0
  134. package/dist/types/index.js +7 -0
  135. package/dist/utils/DOMUtils.d.ts +33 -0
  136. package/dist/utils/DOMUtils.d.ts.map +1 -0
  137. package/dist/utils/DOMUtils.js +179 -0
  138. package/dist/utils/StackUtils.d.ts +11 -0
  139. package/dist/utils/StackUtils.d.ts.map +1 -0
  140. package/dist/utils/StackUtils.js +120 -0
  141. package/dist/vendor/enquirer.d.ts +33 -0
  142. package/dist/vendor/enquirer.d.ts.map +1 -0
  143. package/dist/vendor/enquirer.js +11 -0
  144. package/package.json +67 -0
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ // src/fixtures/expectProxy.ts — full replacement
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.createHealingExpect = createHealingExpect;
5
+ const test_1 = require("@playwright/test");
6
+ const HealingRegistry_1 = require("../engine/HealingRegistry");
7
+ const ELEMENT_NOT_FOUND_PATTERNS = [
8
+ /element.*not found/i,
9
+ /locator.*resolved to.*\d+ element/i,
10
+ /waiting for.*locator/i,
11
+ /timeout.*exceeded/i,
12
+ ];
13
+ function isElementNotFoundError(err) {
14
+ if (!(err instanceof Error))
15
+ return false;
16
+ return ELEMENT_NOT_FOUND_PATTERNS.some((p) => p.test(err.message));
17
+ }
18
+ /**
19
+ * Returns true only for genuine Playwright Locator instances —
20
+ * not FrameLocator proxies or Fixwright proxy objects.
21
+ *
22
+ * A real Locator has _frame internally.
23
+ * A FrameLocator has _frameSelector instead.
24
+ * We must NOT intercept frame-scoped locators because we cannot
25
+ * safely rebuild them from a bare selector string on page.locator().
26
+ */
27
+ function isRealLocator(value) {
28
+ if (value === null || value === undefined)
29
+ return false;
30
+ if (typeof value !== "object")
31
+ return false;
32
+ const hasFrame = value._frame !== undefined ||
33
+ value._impl?._frame !== undefined;
34
+ const isFrameLocator = value._frameSelector !== undefined ||
35
+ value._impl?._frameSelector !== undefined;
36
+ return hasFrame && !isFrameLocator;
37
+ }
38
+ /**
39
+ * Detect whether a locator is frame-scoped by checking its internal
40
+ * selector string for frame-related segments.
41
+ */
42
+ function isFrameScopedLocator(locator) {
43
+ const sel = locator._selector ?? locator["_impl"]?._selector ?? "";
44
+ return (typeof sel === "string" &&
45
+ (sel.includes("internal:control=enter-frame") ||
46
+ sel.includes(">> internal:control=enter-frame")));
47
+ }
48
+ /**
49
+ * Extracts the internal Playwright selector string from a real Locator.
50
+ */
51
+ function extractSelectorFromLocator(locator) {
52
+ const internal = locator._selector ?? locator["_impl"]?._selector;
53
+ return typeof internal === "string" ? internal : null;
54
+ }
55
+ /**
56
+ * Rebuild a locator from a healed selector string that may contain
57
+ * frame segments (e.g. "#modern-frame-container >> #status-label-v2").
58
+ *
59
+ * A plain page.locator() call with a frame >> element string is NOT
60
+ * a valid locator for frame content — Playwright rejects it with
61
+ * "toHaveText can be only used with Locator object".
62
+ *
63
+ * This function correctly chains frameLocator() calls for each frame
64
+ * segment, then calls .locator() for the final element segment.
65
+ *
66
+ * Convention used by FixwrightEngine segments:
67
+ * - Frame segments look like CSS selectors for iframes (#id, .class)
68
+ * but produce a FrameLocator, not a Locator.
69
+ * - The last segment is always the element selector.
70
+ * - "internal:control=enter-frame" segments are implicit in
71
+ * Playwright's FrameLocator and should be skipped.
72
+ *
73
+ * Examples:
74
+ * "#modern-frame-container >> #status-label-v2"
75
+ * → page.frameLocator("#modern-frame-container").locator("#status-label-v2")
76
+ *
77
+ * "#outer >> #inner-frame >> .button"
78
+ * → page.frameLocator("#outer").frameLocator("#inner-frame").locator(".button")
79
+ *
80
+ * "#simple-element"
81
+ * → page.locator("#simple-element")
82
+ */
83
+ function rebuildLocator(page, healedSelector) {
84
+ // --- הוספת השורה הזו ---
85
+ // מוודא שאנחנו עובדים עם האובייקט האמיתי של פליירייט ולא עם הפרוקסי שלנו
86
+ const rawPage = page._rawPage || page;
87
+ const segments = healedSelector
88
+ .split(" >> ")
89
+ .map((s) => s.trim())
90
+ .filter((s) => s.length > 0 && s !== "internal:control=enter-frame");
91
+ if (segments.length === 0)
92
+ return rawPage.locator(healedSelector);
93
+ if (segments.length === 1)
94
+ return rawPage.locator(segments[0]);
95
+ const frameSegments = segments.slice(0, segments.length - 1);
96
+ const elementSegment = segments[segments.length - 1];
97
+ let context = null;
98
+ for (const frameSel of frameSegments) {
99
+ if (context === null) {
100
+ context = rawPage.frameLocator(frameSel);
101
+ }
102
+ else {
103
+ context = context.frameLocator(frameSel);
104
+ }
105
+ }
106
+ // כאן אנחנו מחזירים לוקטור שנוצר ישירות מה-rawPage
107
+ return context.locator(elementSegment);
108
+ }
109
+ /**
110
+ * Wrap a single matcher so that element-not-found errors trigger the
111
+ * heal cycle and retry the assertion once on the correctly rebuilt locator.
112
+ */
113
+ function wrapMatcher(matcher, locator, matcherName, engine, page, ctx) {
114
+ return (async (...args) => {
115
+ try {
116
+ return await matcher(...args);
117
+ }
118
+ catch (err) {
119
+ if (!isElementNotFoundError(err))
120
+ throw err;
121
+ const rawSelector = extractSelectorFromLocator(locator);
122
+ if (!rawSelector)
123
+ throw err;
124
+ console.log(`[Fixwright-Expect] ⚠️ Assertion failed for "${rawSelector}", attempting heal…`);
125
+ // Fast path — already healed in this test via registry
126
+ const resolved = HealingRegistry_1.HealingRegistry.getInstance().resolveSelector(rawSelector, ctx);
127
+ let healedSelector = resolved;
128
+ if (resolved === rawSelector) {
129
+ // Slow path — ask the engine + LLM.
130
+ // engine.heal() writes the fix to disk AND returns the canonical
131
+ // healedLocatorString from SourceUpdater — the exact same string
132
+ // that was saved to the file. This is the handshake that guarantees
133
+ // disk and runtime are in sync (no "ghost failures").
134
+ const stableId = require("crypto")
135
+ .createHash("md5")
136
+ .update(rawSelector)
137
+ .digest("hex");
138
+ try {
139
+ healedSelector = await engine.heal(page, rawSelector, rawSelector, stableId, ctx.filePath, ctx.line, "assertion");
140
+ }
141
+ catch (healErr) {
142
+ if (healErr instanceof Error &&
143
+ healErr.message.includes("[SafetyGuard]")) {
144
+ throw healErr;
145
+ }
146
+ throw err;
147
+ }
148
+ }
149
+ if (!healedSelector || healedSelector === rawSelector)
150
+ throw err;
151
+ // Rebuild the locator from the canonical selector returned by the
152
+ // updater. rebuildLocator() correctly chains frameLocator() calls
153
+ // for each frame segment, then .locator() for the final element,
154
+ // ensuring page/frame/locator variables are scoped correctly at runtime.
155
+ const newLocator = rebuildLocator(page, healedSelector);
156
+ const newExpectation = (0, test_1.expect)(newLocator);
157
+ const retryMatcher = newExpectation[matcherName];
158
+ if (typeof retryMatcher !== "function")
159
+ throw err;
160
+ console.log(`[Fixwright-Expect] ♻️ Retrying assertion with healed selector: "${healedSelector}"`);
161
+ return await retryMatcher.apply(newExpectation, args);
162
+ }
163
+ });
164
+ }
165
+ const WRAPPED_MATCHERS = [
166
+ "toBeVisible",
167
+ "toBeHidden",
168
+ "toBeEnabled",
169
+ "toBeDisabled",
170
+ "toHaveText",
171
+ "toContainText",
172
+ "toHaveValue",
173
+ "toHaveAttribute",
174
+ "toHaveCount",
175
+ "toBeChecked",
176
+ "toBeFocused",
177
+ ];
178
+ /**
179
+ * createHealingExpect — drop-in replacement for Playwright's expect().
180
+ *
181
+ * @param resolveProxy Optional callback that unwraps a Fixwright proxy
182
+ * to its current live Locator. Supplied by
183
+ * fixtures/index.ts which owns proxyToActiveLocator.
184
+ */
185
+ function createHealingExpect(engine, page, filePath, initialLine, // השורה מהפיקסצ'ר (לרוב תהיה לא מדויקת או 0)
186
+ resolveProxy) {
187
+ return function expect(locatorOrValue) {
188
+ // 1. חילוץ דינמי של שורת הקוד האמיתית בזמן קריאת ה-expect
189
+ const getCallerLine = () => {
190
+ const err = new Error();
191
+ const stack = err.stack?.split("\n") || [];
192
+ // מחפשים את הקריאה הראשונה בשרשרת שמגיעה מקובץ הטסט ולא מקובץ הפרוקסי
193
+ const specLine = stack.find((l) => l.includes(filePath) && !l.includes("expectProxy"));
194
+ if (specLine) {
195
+ const match = specLine.match(/:(\d+):(\d+)/);
196
+ return match ? parseInt(match[1], 10) : initialLine;
197
+ }
198
+ return initialLine;
199
+ };
200
+ const actualLine = getCallerLine(); // כאן אנחנו מקבלים את השורה הנכונה!
201
+ // Step 1 — unwrap Fixwright proxy to real active Locator
202
+ let resolved = locatorOrValue;
203
+ if (resolveProxy) {
204
+ const unwrapped = resolveProxy(locatorOrValue);
205
+ if (unwrapped)
206
+ resolved = unwrapped;
207
+ }
208
+ const base = (0, test_1.expect)(resolved);
209
+ // Step 2 — only wrap matchers for genuine page-level Locator objects.
210
+ if (!isRealLocator(resolved)) {
211
+ return base;
212
+ }
213
+ const locator = resolved;
214
+ // משתמשים בשורה האמיתית שחילצנו עבור ה-Context שמועבר ל-Engine
215
+ const ctx = { filePath, line: actualLine };
216
+ const proxy = new Proxy(base, {
217
+ get(target, prop) {
218
+ const val = target[prop];
219
+ if (typeof val === "function" &&
220
+ WRAPPED_MATCHERS.includes(prop)) {
221
+ return wrapMatcher(val.bind(target), locator, prop, engine, page, ctx);
222
+ }
223
+ return val;
224
+ },
225
+ });
226
+ return proxy;
227
+ };
228
+ }
@@ -0,0 +1,6 @@
1
+ import { createHealingExpect } from "./expectProxy";
2
+ export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
3
+ expect: ReturnType<typeof createHealingExpect>;
4
+ }, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
5
+ export { createHealingExpect } from "./expectProxy";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAk2BpD,eAAO,MAAM,IAAI;YACP,UAAU,CAAC,OAAO,mBAAmB,CAAC;wGA+F9C,CAAC;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}