@reactiive/ennio 0.0.1

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 (57) hide show
  1. package/EnnioCore.podspec +61 -0
  2. package/LICENSE +21 -0
  3. package/README.md +50 -0
  4. package/android/CMakeLists.txt +40 -0
  5. package/android/build.gradle +64 -0
  6. package/cpp/ElementMatcher.cpp +661 -0
  7. package/cpp/ElementMatcher.hpp +244 -0
  8. package/cpp/EnnioLog.hpp +182 -0
  9. package/cpp/HybridEnnio.cpp +1161 -0
  10. package/cpp/HybridEnnio.hpp +174 -0
  11. package/cpp/IdleMonitor.hpp +277 -0
  12. package/cpp/Protocol.cpp +135 -0
  13. package/cpp/Protocol.hpp +47 -0
  14. package/cpp/SelectorCriteria.hpp +281 -0
  15. package/cpp/SelectorParser.cpp +649 -0
  16. package/cpp/SelectorParser.hpp +94 -0
  17. package/cpp/ShadowTreeTraverser.cpp +305 -0
  18. package/cpp/ShadowTreeTraverser.hpp +142 -0
  19. package/cpp/TestIDRegistry.cpp +109 -0
  20. package/cpp/TestIDRegistry.hpp +84 -0
  21. package/dist/cli.js +16221 -0
  22. package/ios/EnnioAutoInit.mm +338 -0
  23. package/ios/EnnioDebugBanner.h +19 -0
  24. package/ios/EnnioDebugBanner.mm +178 -0
  25. package/ios/EnnioRuntimeHelper.h +264 -0
  26. package/ios/EnnioRuntimeHelper.mm +2443 -0
  27. package/lib/Ennio.nitro.d.ts +263 -0
  28. package/lib/Ennio.nitro.d.ts.map +1 -0
  29. package/lib/Ennio.nitro.js +2 -0
  30. package/lib/Ennio.nitro.js.map +1 -0
  31. package/lib/index.d.ts +16 -0
  32. package/lib/index.d.ts.map +1 -0
  33. package/lib/index.js +45 -0
  34. package/lib/index.js.map +1 -0
  35. package/nitro.json +24 -0
  36. package/nitrogen/generated/.gitattributes +1 -0
  37. package/nitrogen/generated/android/EnnioCore+autolinking.cmake +81 -0
  38. package/nitrogen/generated/android/EnnioCore+autolinking.gradle +27 -0
  39. package/nitrogen/generated/android/EnnioCoreOnLoad.cpp +49 -0
  40. package/nitrogen/generated/android/EnnioCoreOnLoad.hpp +34 -0
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/ennio/EnnioCoreOnLoad.kt +35 -0
  42. package/nitrogen/generated/ios/EnnioCore+autolinking.rb +62 -0
  43. package/nitrogen/generated/ios/EnnioCore-Swift-Cxx-Bridge.cpp +17 -0
  44. package/nitrogen/generated/ios/EnnioCore-Swift-Cxx-Bridge.hpp +27 -0
  45. package/nitrogen/generated/ios/EnnioCore-Swift-Cxx-Umbrella.hpp +38 -0
  46. package/nitrogen/generated/ios/EnnioCoreAutolinking.mm +35 -0
  47. package/nitrogen/generated/ios/EnnioCoreAutolinking.swift +16 -0
  48. package/nitrogen/generated/shared/c++/ExtendedElementInfo.hpp +118 -0
  49. package/nitrogen/generated/shared/c++/HybridEnnioSpec.cpp +44 -0
  50. package/nitrogen/generated/shared/c++/HybridEnnioSpec.hpp +93 -0
  51. package/nitrogen/generated/shared/c++/LayoutMetrics.hpp +103 -0
  52. package/nitrogen/generated/shared/c++/ScrollDirection.hpp +84 -0
  53. package/package.json +78 -0
  54. package/react-native.config.js +14 -0
  55. package/src/Ennio.nitro.ts +363 -0
  56. package/src/cli/hid-daemon.py +129 -0
  57. package/src/index.ts +72 -0
@@ -0,0 +1,244 @@
1
+ #pragma once
2
+
3
+ #include "SelectorCriteria.hpp"
4
+ #include "ShadowTreeTraverser.hpp"
5
+ #include "TestIDRegistry.hpp"
6
+
7
+ #include <memory>
8
+ #include <optional>
9
+ #include <regex>
10
+ #include <string>
11
+ #include <vector>
12
+
13
+ #include <react/renderer/core/ShadowNode.h>
14
+
15
+ namespace ennio {
16
+
17
+ /**
18
+ * Extended element info with additional state properties
19
+ */
20
+ struct ExtendedElementInfo : public ElementInfo {
21
+ bool checked = false;
22
+ bool focused = false;
23
+ bool selected = false;
24
+
25
+ // Parent tracking for childOf queries
26
+ const facebook::react::ShadowNode* parent = nullptr;
27
+ };
28
+
29
+ /**
30
+ * ElementMatcher - Multi-criteria element matching engine
31
+ *
32
+ * Optimized matching with:
33
+ * - O(1) fast path for id-only selectors via TestIDRegistry
34
+ * - Efficient spatial matching using pre-computed reference positions
35
+ * - Parent chain tracking for hierarchical queries
36
+ */
37
+ class ElementMatcher {
38
+ public:
39
+ using ShadowNodePtr = std::shared_ptr<const facebook::react::ShadowNode>;
40
+
41
+ /**
42
+ * Find the first element matching the criteria
43
+ *
44
+ * @param root - Shadow tree root
45
+ * @param criteria - Selection criteria
46
+ * @return Matching node or nullptr
47
+ */
48
+ static ShadowNodePtr findFirst(
49
+ ShadowNodePtr root,
50
+ const SelectorCriteria& criteria
51
+ );
52
+
53
+ /**
54
+ * Find all elements matching the criteria
55
+ *
56
+ * @param root - Shadow tree root
57
+ * @param criteria - Selection criteria
58
+ * @return Vector of matching nodes
59
+ */
60
+ static std::vector<ShadowNodePtr> findAll(
61
+ ShadowNodePtr root,
62
+ const SelectorCriteria& criteria
63
+ );
64
+
65
+ /**
66
+ * Get extended element info including state properties
67
+ */
68
+ static std::optional<ExtendedElementInfo> getExtendedElementInfo(
69
+ ShadowNodePtr root,
70
+ ShadowNodePtr node
71
+ );
72
+
73
+ private:
74
+ /**
75
+ * Context for matching operations
76
+ */
77
+ struct MatchContext {
78
+ ShadowNodePtr root;
79
+ float screenWidth = 430.0f;
80
+ float screenHeight = 932.0f;
81
+
82
+ // Resolved reference elements for spatial queries
83
+ std::optional<LayoutMetrics> belowRef;
84
+ std::optional<LayoutMetrics> aboveRef;
85
+ std::optional<LayoutMetrics> leftOfRef;
86
+ std::optional<LayoutMetrics> rightOfRef;
87
+
88
+ // Parent tracking
89
+ std::vector<const facebook::react::ShadowNode*> parentChain;
90
+ };
91
+
92
+ /**
93
+ * Resolve spatial reference elements
94
+ */
95
+ static void resolveSpatialRefs(
96
+ const SelectorCriteria& criteria,
97
+ MatchContext& ctx
98
+ );
99
+
100
+ /**
101
+ * Check if a node matches all criteria
102
+ */
103
+ static bool matches(
104
+ ShadowNodePtr node,
105
+ const SelectorCriteria& criteria,
106
+ const MatchContext& ctx
107
+ );
108
+
109
+ /**
110
+ * Match primary criteria (id, text, point)
111
+ */
112
+ static bool matchesPrimary(
113
+ ShadowNodePtr node,
114
+ const SelectorCriteria& criteria
115
+ );
116
+
117
+ /**
118
+ * Match text with different modes
119
+ */
120
+ static bool matchesText(
121
+ const std::string& actual,
122
+ const TextMatcher& matcher
123
+ );
124
+
125
+ /**
126
+ * Match state criteria (enabled, checked, focused, selected)
127
+ */
128
+ static bool matchesState(
129
+ ShadowNodePtr node,
130
+ const SelectorCriteria& criteria
131
+ );
132
+
133
+ /**
134
+ * Match spatial criteria (below, above, leftOf, rightOf)
135
+ */
136
+ static bool matchesSpatial(
137
+ ShadowNodePtr node,
138
+ const LayoutMetrics& nodeMetrics,
139
+ const MatchContext& ctx
140
+ );
141
+
142
+ /**
143
+ * Check if candidate is below reference
144
+ */
145
+ static bool isBelow(const LayoutMetrics& candidate, const LayoutMetrics& reference);
146
+
147
+ /**
148
+ * Check if candidate is above reference
149
+ */
150
+ static bool isAbove(const LayoutMetrics& candidate, const LayoutMetrics& reference);
151
+
152
+ /**
153
+ * Check if candidate is left of reference
154
+ */
155
+ static bool isLeftOf(const LayoutMetrics& candidate, const LayoutMetrics& reference);
156
+
157
+ /**
158
+ * Check if candidate is right of reference
159
+ */
160
+ static bool isRightOf(const LayoutMetrics& candidate, const LayoutMetrics& reference);
161
+
162
+ /**
163
+ * Match hierarchical criteria (containsChild, childOf, containsDescendants)
164
+ */
165
+ static bool matchesHierarchical(
166
+ ShadowNodePtr node,
167
+ const SelectorCriteria& criteria,
168
+ const MatchContext& ctx
169
+ );
170
+
171
+ /**
172
+ * Check if node contains a direct child matching criteria
173
+ */
174
+ static bool containsChild(
175
+ ShadowNodePtr node,
176
+ const SelectorCriteria& criteria,
177
+ const MatchContext& ctx
178
+ );
179
+
180
+ /**
181
+ * Check if node is a child of an element matching criteria
182
+ */
183
+ static bool isChildOf(
184
+ const std::vector<const facebook::react::ShadowNode*>& parentChain,
185
+ const SelectorCriteria& criteria,
186
+ const MatchContext& ctx
187
+ );
188
+
189
+ /**
190
+ * Check if node contains all descendants matching each criteria
191
+ */
192
+ static bool containsDescendants(
193
+ ShadowNodePtr node,
194
+ const std::vector<SelectorCriteriaPtr>& criteria,
195
+ const MatchContext& ctx
196
+ );
197
+
198
+ /**
199
+ * Match dimension criteria (width, height with tolerance)
200
+ */
201
+ static bool matchesDimensions(
202
+ const LayoutMetrics& metrics,
203
+ const SelectorCriteria& criteria
204
+ );
205
+
206
+ /**
207
+ * Match trait criteria
208
+ */
209
+ static bool matchesTraits(
210
+ ShadowNodePtr node,
211
+ const LayoutMetrics& metrics,
212
+ const std::vector<Trait>& traits
213
+ );
214
+
215
+ /**
216
+ * Get the layout metrics for a node
217
+ */
218
+ static std::optional<LayoutMetrics> getNodeMetrics(
219
+ ShadowNodePtr root,
220
+ ShadowNodePtr node
221
+ );
222
+
223
+ /**
224
+ * Extract state properties from node props
225
+ */
226
+ static void extractStateProps(
227
+ ShadowNodePtr node,
228
+ bool& outChecked,
229
+ bool& outFocused,
230
+ bool& outSelected
231
+ );
232
+
233
+ /**
234
+ * Collect all matching nodes via tree traversal
235
+ */
236
+ static void collectMatches(
237
+ ShadowNodePtr node,
238
+ const SelectorCriteria& criteria,
239
+ MatchContext& ctx,
240
+ std::vector<ShadowNodePtr>& results
241
+ );
242
+ };
243
+
244
+ } // namespace ennio
@@ -0,0 +1,182 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <sstream>
5
+ #include <iostream>
6
+ #include <chrono>
7
+ #include <iomanip>
8
+
9
+ namespace ennio {
10
+
11
+ /**
12
+ * Log levels for Ennio debugging
13
+ */
14
+ enum class LogLevel {
15
+ Error = 0,
16
+ Warn = 1,
17
+ Info = 2,
18
+ Debug = 3,
19
+ Trace = 4
20
+ };
21
+
22
+ /**
23
+ * EnnioLog provides structured logging for the native module.
24
+ *
25
+ * Logging is controlled by the ENNIO_DEBUG environment variable:
26
+ * - Not set or "0": No logging
27
+ * - "1": Error and Warn only
28
+ * - "2": Info level
29
+ * - "3": Debug level
30
+ * - "4": Trace level (verbose)
31
+ *
32
+ * In a compiled app, use ENNIO_DEBUG preprocessor flag.
33
+ */
34
+ class EnnioLog {
35
+ public:
36
+ /**
37
+ * Get the current log level
38
+ */
39
+ static LogLevel getLevel() {
40
+ #ifdef ENNIO_DEBUG
41
+ #if ENNIO_DEBUG >= 4
42
+ return LogLevel::Trace;
43
+ #elif ENNIO_DEBUG >= 3
44
+ return LogLevel::Debug;
45
+ #elif ENNIO_DEBUG >= 2
46
+ return LogLevel::Info;
47
+ #elif ENNIO_DEBUG >= 1
48
+ return LogLevel::Warn;
49
+ #else
50
+ return LogLevel::Error;
51
+ #endif
52
+ #else
53
+ // In release builds, default to no logging
54
+ return LogLevel::Error;
55
+ #endif
56
+ }
57
+
58
+ /**
59
+ * Check if a log level is enabled
60
+ */
61
+ static bool isEnabled(LogLevel level) {
62
+ return static_cast<int>(level) <= static_cast<int>(getLevel());
63
+ }
64
+
65
+ /**
66
+ * Log a message at the given level
67
+ */
68
+ static void log(LogLevel level, const std::string& tag, const std::string& message) {
69
+ if (!isEnabled(level)) {
70
+ return;
71
+ }
72
+
73
+ // Get timestamp
74
+ auto now = std::chrono::system_clock::now();
75
+ auto time = std::chrono::system_clock::to_time_t(now);
76
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
77
+ now.time_since_epoch()
78
+ ).count() % 1000;
79
+
80
+ // Get level string
81
+ const char* levelStr = "???";
82
+ switch (level) {
83
+ case LogLevel::Error: levelStr = "ERR"; break;
84
+ case LogLevel::Warn: levelStr = "WRN"; break;
85
+ case LogLevel::Info: levelStr = "INF"; break;
86
+ case LogLevel::Debug: levelStr = "DBG"; break;
87
+ case LogLevel::Trace: levelStr = "TRC"; break;
88
+ }
89
+
90
+ // Format: [HH:MM:SS.mmm] [LEVEL] [TAG] Message
91
+ std::ostringstream oss;
92
+ oss << std::put_time(std::localtime(&time), "%H:%M:%S");
93
+ oss << "." << std::setfill('0') << std::setw(3) << ms;
94
+ oss << " [" << levelStr << "] [" << tag << "] " << message;
95
+
96
+ // Output to stderr (always available)
97
+ std::cerr << oss.str() << std::endl;
98
+ }
99
+
100
+ // Convenience methods
101
+ static void error(const std::string& tag, const std::string& message) {
102
+ log(LogLevel::Error, tag, message);
103
+ }
104
+
105
+ static void warn(const std::string& tag, const std::string& message) {
106
+ log(LogLevel::Warn, tag, message);
107
+ }
108
+
109
+ static void info(const std::string& tag, const std::string& message) {
110
+ log(LogLevel::Info, tag, message);
111
+ }
112
+
113
+ static void debug(const std::string& tag, const std::string& message) {
114
+ log(LogLevel::Debug, tag, message);
115
+ }
116
+
117
+ static void trace(const std::string& tag, const std::string& message) {
118
+ log(LogLevel::Trace, tag, message);
119
+ }
120
+ };
121
+
122
+ // ============================================
123
+ // Logging Macros
124
+ // ============================================
125
+
126
+ // These macros are completely compiled out when ENNIO_DEBUG is not defined
127
+ // or when the level is higher than the configured level
128
+
129
+ #ifdef ENNIO_DEBUG
130
+
131
+ #define ENNIO_LOG_ERROR(tag, msg) ::ennio::EnnioLog::error(tag, msg)
132
+ #define ENNIO_LOG_WARN(tag, msg) ::ennio::EnnioLog::warn(tag, msg)
133
+
134
+ #if ENNIO_DEBUG >= 2
135
+ #define ENNIO_LOG_INFO(tag, msg) ::ennio::EnnioLog::info(tag, msg)
136
+ #else
137
+ #define ENNIO_LOG_INFO(tag, msg) do {} while(0)
138
+ #endif
139
+
140
+ #if ENNIO_DEBUG >= 3
141
+ #define ENNIO_LOG_DEBUG(tag, msg) ::ennio::EnnioLog::debug(tag, msg)
142
+ #else
143
+ #define ENNIO_LOG_DEBUG(tag, msg) do {} while(0)
144
+ #endif
145
+
146
+ #if ENNIO_DEBUG >= 4
147
+ #define ENNIO_LOG_TRACE(tag, msg) ::ennio::EnnioLog::trace(tag, msg)
148
+ #else
149
+ #define ENNIO_LOG_TRACE(tag, msg) do {} while(0)
150
+ #endif
151
+
152
+ // Format helper for building messages with stream syntax
153
+ #define ENNIO_LOG_FMT(...) ([]() { \
154
+ std::ostringstream _oss; \
155
+ _oss << __VA_ARGS__; \
156
+ return _oss.str(); \
157
+ }())
158
+
159
+ // Printf-style format helper for DEBUG level (used by legacy code)
160
+ #if ENNIO_DEBUG >= 3
161
+ #define ENNIO_LOG_DEBUG_F(tag, fmt, ...) do { \
162
+ char _buf[512]; \
163
+ snprintf(_buf, sizeof(_buf), fmt, ##__VA_ARGS__); \
164
+ ::ennio::EnnioLog::debug(tag, _buf); \
165
+ } while(0)
166
+ #else
167
+ #define ENNIO_LOG_DEBUG_F(tag, fmt, ...) do {} while(0)
168
+ #endif
169
+
170
+ #else // ENNIO_DEBUG not defined
171
+
172
+ #define ENNIO_LOG_ERROR(tag, msg) do {} while(0)
173
+ #define ENNIO_LOG_WARN(tag, msg) do {} while(0)
174
+ #define ENNIO_LOG_INFO(tag, msg) do {} while(0)
175
+ #define ENNIO_LOG_DEBUG(tag, msg) do {} while(0)
176
+ #define ENNIO_LOG_TRACE(tag, msg) do {} while(0)
177
+ #define ENNIO_LOG_FMT(...) std::string()
178
+ #define ENNIO_LOG_DEBUG_F(tag, fmt, ...) do {} while(0)
179
+
180
+ #endif // ENNIO_DEBUG
181
+
182
+ } // namespace ennio