casper-context 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 (44) hide show
  1. package/README.md +253 -0
  2. package/dist/index.js +9 -0
  3. package/dist/lifecycle/post.js +239 -0
  4. package/dist/lifecycle/pre.js +113 -0
  5. package/dist/plugin.js +57 -0
  6. package/dist/transforms/autoContextTransform.js +1 -0
  7. package/dist/transforms/contextTransform.js +1 -0
  8. package/dist/transforms/stateTransform.js +1 -0
  9. package/dist/types/plugin.d.js +1 -0
  10. package/dist/utils/astHelpers.js +644 -0
  11. package/dist/utils/constants.js +111 -0
  12. package/dist/utils/names.js +1 -0
  13. package/dist/utils/scope.js +1 -0
  14. package/dist/utils/utilityHelpers.js +606 -0
  15. package/dist/visitors/AssignmentExpression.js +104 -0
  16. package/dist/visitors/CallExpression.js +1 -0
  17. package/dist/visitors/FunctionDeclaration.js +116 -0
  18. package/dist/visitors/Identifier.js +123 -0
  19. package/dist/visitors/JSXElement.js +1 -0
  20. package/dist/visitors/Program.js +278 -0
  21. package/dist/visitors/ReturnStatement.js +81 -0
  22. package/dist/visitors/VariableDeclaration.js +209 -0
  23. package/package.json +60 -0
  24. package/src/index.js +2 -0
  25. package/src/lifecycle/post.js +237 -0
  26. package/src/lifecycle/pre.js +103 -0
  27. package/src/plugin.js +51 -0
  28. package/src/transforms/autoContextTransform.js +0 -0
  29. package/src/transforms/contextTransform.js +0 -0
  30. package/src/transforms/stateTransform.js +0 -0
  31. package/src/types/plugin.d.ts +0 -0
  32. package/src/utils/astHelpers.js +767 -0
  33. package/src/utils/constants.js +102 -0
  34. package/src/utils/names.js +0 -0
  35. package/src/utils/scope.js +0 -0
  36. package/src/utils/utilityHelpers.js +636 -0
  37. package/src/visitors/AssignmentExpression.js +100 -0
  38. package/src/visitors/CallExpression.js +0 -0
  39. package/src/visitors/FunctionDeclaration.js +114 -0
  40. package/src/visitors/Identifier.js +142 -0
  41. package/src/visitors/JSXElement.js +0 -0
  42. package/src/visitors/Program.js +280 -0
  43. package/src/visitors/ReturnStatement.js +75 -0
  44. package/src/visitors/VariableDeclaration.js +216 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @fileoverview Transformation Logic & Node Orchestration.
3
+ * This module integrates AST helpers with utility validators to perform
4
+ * the actual replacement of custom global variables (`_$_`) with
5
+ * React-compatible State and Context setters.
6
+ */
7
+
8
+ /**
9
+ * Core Constants
10
+ * @description
11
+ * - IDENTIFIER: Used to validate if the left-hand side of an assignment is a variable.
12
+ * - _CCTX_EMPTY: Fallback value for filenames or uninitialized state strings.
13
+ */
14
+ import { IDENTIFIER, _CCTX_EMPTY } from '../utils/constants';
15
+
16
+ /**
17
+ * Utility & Validation Helpers
18
+ * @description
19
+ * - findContextByVar: Maps a `_$_` variable to its corresponding Context instance name.
20
+ * - isExcludeFile: Security/Performance gate to prevent processing ignored files.
21
+ */
22
+ import { findContextByVar, isExcludeFile } from '../utils/utilityHelpers';
23
+
24
+ /**
25
+ * AST Transformation Utilities
26
+ * @description The functional "engine" of the plugin that manipulates the Babel tree.
27
+ * - buildSpreadObject: Creates the updated state object for setters.
28
+ * - replaceWithSetState: Handles local component state updates.
29
+ * - buildUseContextInstance: Injects `useContext` hooks when variables are cross-component.
30
+ * - replaceWithContextSetState: Handles global/context-based state updates.
31
+ * - getComponentName: Identifies the immediate parent function.
32
+ * - getRootParentComponent: Recursively climbs the tree to find the top-level React Component.
33
+ */
34
+ import { buildSpreadObject, replaceWithSetState, buildUseContextInstance, replaceWithContextSetState, getComponentName, getRootParentComponent } from '../utils/astHelpers';
35
+
36
+ /**
37
+ * @module Logger
38
+ * @description Provides a controlled logging interface for the Babel transformation process.
39
+ */
40
+ import { log } from '../utils/utilityHelpers';
41
+
42
+ /**
43
+ * Babel visitor function for handling assignment expressions in the AST.
44
+ *
45
+ * This visitor inspects assignments in the code and replaces or augments them
46
+ * with state/context updates for variables registered in the `virtualRegistry`.
47
+ * It handles both direct component state updates and global/shared context updates.
48
+ *
49
+ * @param {NodePath} path - The Babel AST path representing the current node.
50
+ * @param {Object} state - Plugin state, including file info, config, and import metadata.
51
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate AST nodes.
52
+ * @param {Object<string, Object>} virtualRegistry - Registry of components and their
53
+ * registered variables/context info.
54
+ *
55
+ * @returns {void}
56
+ * Updates AST nodes in place and sets plugin state flags; no return value.
57
+ *
58
+ * @important
59
+ * - Only handles assignments where the left-hand identifier starts with the configured prefix.
60
+ * - Supports both direct component `useState` updates and context-based updates.
61
+ * - Automatically marks that a global context is needed (`state.needsGblContext = true`).
62
+ * - Injects `useState` import if missing.
63
+ * - Silent error handling; consider logging `e` for debugging.
64
+ */
65
+ export default function assignmentExpressionVisitor(path, state, t, virtualRegistry) {
66
+ try {
67
+ const fileName = state.filename || _CCTX_EMPTY;
68
+ if (!isExcludeFile(fileName, this.opts)) return;
69
+ if (path.node.left.type === IDENTIFIER) {
70
+ if (path.node.left.name?.startsWith(state.casperConfig.prefix)) {
71
+ state.needsGblContext = true;
72
+ const ctxName = findContextByVar(path.node.left.name, virtualRegistry);
73
+ if (!ctxName) return;
74
+ let { currentFuncParent, componentName } = getRootParentComponent(path);
75
+ if (!componentName) return;
76
+ let isSameCMP = false;
77
+ if (ctxName.startsWith(componentName)) {
78
+ isSameCMP = true;
79
+ }
80
+ state.needsGblContext = true;
81
+ if (
82
+ !state.importState.reactId &&
83
+ !state.importState.useStateId
84
+ ) {
85
+ state.needUseStateImport = true
86
+ }
87
+ const updateFunction = buildSpreadObject(path, t);
88
+ if (isSameCMP) {
89
+ replaceWithSetState(path, t, ctxName, updateFunction);
90
+ } else {
91
+ buildUseContextInstance(currentFuncParent, state, t, ctxName);
92
+ replaceWithContextSetState(path, t, ctxName, updateFunction);
93
+ }
94
+
95
+ }
96
+ }
97
+ } catch (e) {
98
+ log('error', '[::assignmentExpressionVisitor::]', e.message);
99
+ }
100
+ }
File without changes
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @fileoverview Logic Orchestration for Function Transformation.
3
+ * This module coordinates the 'Exit' phase of function traversal. It integrates
4
+ * specialized visitors for variable declarations and return statements to
5
+ * aggregate state metadata before injecting final React Hook declarations.
6
+ */
7
+
8
+ /**
9
+ * Validation & Hashing Utilities
10
+ * @description
11
+ * - isExcludeFile: Determines if the current file should be bypassed based on plugin configuration.
12
+ * - getFilePathHASH: Generates a unique identifier based on the file path to prevent naming collisions.
13
+ */
14
+ import { isExcludeFile, getFilePathHASH } from '../utils/utilityHelpers';
15
+
16
+ /**
17
+ * Specialized Sub-Visitors
18
+ * @description These visitors are manually invoked during the function's traversal
19
+ * to target specific node types within the component body.
20
+ * - functionReturnVariableDelarationVisitor: Extracts state-relevant variable data.
21
+ * - functionDeclarationReturnStatementVisitor: Processes JSX or return values for context binding.
22
+ */
23
+ import { functionReturnVariableDelarationVisitor } from './VariableDeclaration';
24
+ import { functionDeclarationReturnStatementVisitor } from './ReturnStatement';
25
+
26
+ /**
27
+ * AST Construction Helpers
28
+ * @description
29
+ * - buildCtxUseStateDeclaration: Physically constructs and injects the `useState`
30
+ * node into the Abstract Syntax Tree.
31
+ */
32
+ import { buildCtxUseStateDeclaration } from '../utils/astHelpers';
33
+
34
+ /**
35
+ * Core Constants
36
+ * @description
37
+ * - _CCTX_EMPTY: Provides a safe string fallback for file naming and path resolution.
38
+ */
39
+ import { _CCTX_EMPTY } from '../utils/constants';
40
+
41
+ /**
42
+ * @module Logger
43
+ * @description Provides a controlled logging interface for the Babel transformation process.
44
+ */
45
+ import { log } from '../utils/utilityHelpers';
46
+
47
+ /**
48
+ * @important
49
+ * The coordination between these imports ensures that state is only injected
50
+ * once per component, and only if the component contains variables prefixed
51
+ * with the library's global identifier.
52
+ */
53
+
54
+ /**
55
+ * Babel visitor exit handler for `FunctionDeclaration` nodes.
56
+ *
57
+ * This function is invoked when exiting a function declaration during AST traversal.
58
+ * It inspects the function for any state variables registered in the `virtualRegistry`
59
+ * and transforms them into React `useState` declarations or context state as needed.
60
+ *
61
+ * @param {NodePath} path - The Babel AST path representing the current function declaration.
62
+ * @param {Object} state - Plugin state, including file info, config, and import metadata.
63
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate AST nodes.
64
+ * @param {Object<string, Object>} virtualRegistry - Registry of components and their
65
+ * registered variables/context info. Each key is `${componentName}_${fileHash}`.
66
+ *
67
+ * @returns {void}
68
+ * Modifies AST nodes in place to inject state declarations and context usage;
69
+ * does not return a value.
70
+ *
71
+ * @important
72
+ * - Skips files excluded by `isExcludeFile`.
73
+ * - Only processes functions with a valid name.
74
+ * - Collects local state variable declarations and return statements using
75
+ * `functionReturnVariableDelarationVisitor` and `functionDeclarationReturnStatementVisitor`.
76
+ * - Converts collected variables into an object expression for `buildCtxUseStateDeclaration`.
77
+ * - Silent error handling; errors are caught but ignored.
78
+ *
79
+ * @example
80
+ * ```js
81
+ * // During Babel traversal:
82
+ * functionDeclarationExit(path, state, t, virtualRegistry);
83
+ * // Injects useState or context declarations for local state variables in the function
84
+ * ```
85
+ */
86
+ export function functionDeclarationExit(path, state, t, virtualRegistry) {
87
+ try {
88
+ const fileName = state.filename || _CCTX_EMPTY;
89
+ if (!isExcludeFile(fileName, this.opts)) return;
90
+ const name = path.node.id?.name;
91
+ if (!name) return;
92
+ const filePathHASH = getFilePathHASH(fileName);
93
+ const key = `${name}_${filePathHASH}`;
94
+ const entry = virtualRegistry[key];
95
+ if (!entry || !entry.varNames.length) return;
96
+ const localStateVars = [];
97
+ path.traverse({
98
+ VariableDeclarator(varPath) {
99
+ functionReturnVariableDelarationVisitor.call(this, varPath, state, t, localStateVars);
100
+ },
101
+ ReturnStatement(retPath) {
102
+ functionDeclarationReturnStatementVisitor.call(this, retPath, state, t, entry);
103
+ },
104
+ })
105
+ if (localStateVars.length === 0) return;
106
+ const objProps = localStateVars.map(v =>
107
+ t.objectProperty(t.identifier(v.name), v.init || t.nullLiteral())
108
+ );
109
+ buildCtxUseStateDeclaration(path, t, state, objProps, key);
110
+
111
+ } catch (e) {
112
+ log('error', '[::functionDeclarationExit::]', e.message);
113
+ }
114
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @fileoverview Variable Reference & Usage Orchestration.
3
+ * This module manages the detection and transformation of custom context variables
4
+ * when they are referenced in expressions. It handles the replacement of `_$_`
5
+ * identifiers with either local state accessors or injected Context hooks.
6
+ */
7
+
8
+ /**
9
+ * AST Node & Property Constants
10
+ * @description Identifiers for specific nodes and keys used to navigate the AST
11
+ * during variable resolution and replacement.
12
+ */
13
+ import {
14
+ VARIABLE_DECLARATOR, // Target for initial variable definitions
15
+ _CCTX_ID, // Key for the identifier in a declaration
16
+ ASSIGNMENT_EXPRESSION, // Target for variable updates
17
+ _CCTX_LEFT, // The 'write' side of an assignment
18
+ UPDATE_EXPRESSION, // Target for increments/decrements (e.g., ++, --)
19
+ _CCTX_ARGUMENT, // The variable inside an update expression
20
+ _CCTX_KEY, // Property key in object patterns
21
+ _CCTX_UNKNOW, // Fallback for unresolved identifiers
22
+ _CCTX_EMPTY // Default string initializer
23
+ } from '../utils/constants';
24
+
25
+ /**
26
+ * Validation & Discovery Utilities
27
+ * @description
28
+ * - isExcludeFile: Ensures the transformation doesn't run on ignored directories.
29
+ * - findContextByVar: Locates the specific Context instance associated with a variable name.
30
+ */
31
+ import { isExcludeFile, findContextByVar } from '../utils/utilityHelpers';
32
+
33
+ /**
34
+ * AST Transformation & Scope Helpers
35
+ * @description Functions that physically modify the code and resolve component hierarchy.
36
+ * - replaceWithContextState: Replaces a reference with a Context-based accessor.
37
+ * - replaceWithState: Replaces a reference with a local `useState` accessor.
38
+ * - buildUseContextInstance: Injects the `useContext` hook if the variable is defined elsewhere.
39
+ * - getRootParentComponent: Finds the top-level React Component to ensure hooks are valid.
40
+ */
41
+ import { replaceWithContextState, replaceWithState, buildUseContextInstance, getRootParentComponent } from '../utils/astHelpers';
42
+
43
+ /**
44
+ * @module Logger
45
+ * @description Provides a controlled logging interface for the Babel transformation process.
46
+ */
47
+ import { log } from '../utils/utilityHelpers';
48
+
49
+ /**
50
+ * @important
51
+ * This module is highly sensitive to Scope. It must distinguish between a variable
52
+ * being "written to" (Assignment) and "read from" (Reference) to prevent
53
+ * infinite loops in the Babel transformation.
54
+ */
55
+
56
+ /**
57
+ * Babel visitor for handling identifier nodes in the AST.
58
+ *
59
+ * This visitor inspects identifiers that start with the configured Casper prefix.
60
+ * It determines whether the identifier corresponds to a registered component or
61
+ * context variable and replaces it with the appropriate state or context access
62
+ * expression. This handles both component-local state and global/shared context usage.
63
+ *
64
+ * @param {NodePath} path - The Babel AST path representing the current identifier node.
65
+ * @param {Object} state - Plugin state, including file info, configuration, and import metadata.
66
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate AST nodes.
67
+ * @param {Set<Node>} seen - A Set tracking identifiers that have already been processed to avoid duplicates.
68
+ * @param {Object<string, Object>} virtualRegistry - Registry of components and their
69
+ * registered variables/context info.
70
+ *
71
+ * @returns {void}
72
+ * Modifies AST nodes in place by replacing identifiers with either direct state access
73
+ * or context-based access. Does not return a value.
74
+ *
75
+ * @important
76
+ * - Skips identifiers that are part of declarations, assignments, object keys, or JSX expressions.
77
+ * - Only processes referenced identifiers matching the configured Casper prefix.
78
+ * - Sets `state.needsGblContext` when global context usage is required.
79
+ * - Automatically injects `useState` import if missing.
80
+ * - Differentiates between same-component state and context usage across components.
81
+ * - Errors are silently caught.
82
+ *
83
+ * @example
84
+ * ```js
85
+ * import identifierVisitor from './identifierVisitor';
86
+ *
87
+ * identifierVisitor(path, state, t, seen, virtualRegistry);
88
+ * // Replaces matching identifiers with state or context references
89
+ * ```
90
+ */
91
+ export default function identifierVisitor (path, state, t, seen, virtualRegistry) {
92
+ try {
93
+ const fileName = state.filename || _CCTX_EMPTY;
94
+ if (!isExcludeFile(fileName, this.opts)) return;
95
+ if (path.node?.name?.startsWith(state.casperConfig.prefix)) {
96
+ if (
97
+ (path.parent.type === VARIABLE_DECLARATOR && path.parentKey === _CCTX_ID) ||
98
+ (path.parent.type === ASSIGNMENT_EXPRESSION && path.parentKey === _CCTX_LEFT) ||
99
+ (path.parent.type === UPDATE_EXPRESSION && path.parentKey === _CCTX_ARGUMENT)
100
+ ) return;
101
+ if (
102
+ path.parentPath.isObjectProperty() &&
103
+ path.parentKey === _CCTX_KEY &&
104
+ !path.parent.computed
105
+ ) return;
106
+ if (path.findParent(p =>
107
+ p.isJSXExpressionContainer() ||
108
+ p.isJSXAttribute() ||
109
+ p.isJSXOpeningElement() ||
110
+ p.isJSXClosingElement() ||
111
+ p.isJSXMemberExpression()
112
+ )) return;
113
+ if (!path.isReferencedIdentifier()) return;
114
+ if (!seen.has(path.node)) {
115
+ seen.add(path.node);
116
+ state.needsGblContext = true;
117
+ let {currentFuncParent,componentName} = getRootParentComponent(path);
118
+ const ctxName = findContextByVar(path.node.name, virtualRegistry);
119
+ if (!ctxName) return;
120
+ let isSameCMP = false;
121
+ if (ctxName.startsWith(componentName)) {
122
+ isSameCMP = true;
123
+ }
124
+ state.needsGblContext = true;
125
+ if (
126
+ !state.importState.reactId &&
127
+ !state.importState.useStateId
128
+ ) {
129
+ state.needUseStateImport = true
130
+ }
131
+ if (isSameCMP) {
132
+ replaceWithState(path, t, ctxName);
133
+ } else {
134
+ buildUseContextInstance(currentFuncParent, state, t, ctxName);
135
+ replaceWithContextState(path, t, ctxName);
136
+ }
137
+ }
138
+ }
139
+ } catch (e) {
140
+ log('error', '[::identifierVisitor::]', e.message);
141
+ }
142
+ }
File without changes
@@ -0,0 +1,280 @@
1
+ /**
2
+ * @fileoverview Library Initialization & Dependency Injection Orchestrator.
3
+ * This module manages the "Prep Phase" of the transformation, ensuring that
4
+ * required React hooks and internal global context bridges are correctly
5
+ * imported or required before any code modifications occur.
6
+ */
7
+
8
+ /**
9
+ * Dependency & Alias Constants
10
+ * @description Identifiers for React and internal library references used to
11
+ * avoid naming collisions with user-defined variables.
12
+ */
13
+ import {
14
+ _CCTX_REACT, // Internal alias for the React object
15
+ _CCTX_EMPTY, // Safe string fallback for paths/names
16
+ _CCTX_UNDUS_CORE_REACT, // Normalized identifier for the React import
17
+ _CCTX_UNDUS_CORE_GBL_CONTEXT, // Identifier for the auto-generated global context
18
+ REACT_IMPORT_CORE_NAME, // Literal 'react' package name
19
+ REACT_IMPORT_USE_STATE_HOOKS_NAME // Literal 'useState' hook name
20
+ } from '../utils/constants';
21
+
22
+ /**
23
+ * File System & Lifecycle Utilities
24
+ * @description
25
+ * - CONTEXT_FILE_PATH: The absolute path to the generated context bridge.
26
+ * - resetVarsForFile: Cleanup utility to clear tracking caches between file traversals.
27
+ * - isExcludeFile: Security gate to prevent transformation of ignored files.
28
+ * - getFilePathHASH: Generates a unique, stable ID for the current file's state bucket.
29
+ */
30
+ import { CONTEXT_FILE_PATH, resetVarsForFile, isExcludeFile, getFilePathHASH } from '../utils/utilityHelpers';
31
+
32
+ /**
33
+ * AST Injection Helpers
34
+ * @description
35
+ * - buildRequireDeclaration: Injects CommonJS `require` statements at the top of the file.
36
+ */
37
+ import { buildRequireDeclaration } from '../utils/astHelpers';
38
+
39
+ /**
40
+ * @module Logger
41
+ * @description Provides a controlled logging interface for the Babel transformation process.
42
+ */
43
+ import { log } from '../utils/utilityHelpers';
44
+
45
+ /**
46
+ * @important
47
+ * This module is responsible for "Stateful Reset." Every time a new file is
48
+ * entered, `resetVarsForFile` must be called to ensure that context variables
49
+ * from the previous file do not leak into the current transformation scope.
50
+ */
51
+
52
+ /**
53
+ * Resolves and collects React import information from a file's AST.
54
+ *
55
+ * This function inspects all import declarations in the given file's AST
56
+ * and identifies the React import. It tracks whether React was imported as
57
+ * a default import, named import, or namespace import, and whether `useState`
58
+ * is explicitly imported.
59
+ *
60
+ * @param {NodePath} path - The Babel AST path representing the file/program node.
61
+ * @param {Object} state - Plugin state object where resolved import information
62
+ * will be stored under `state.importState`.
63
+ * @param {Object} t - Babel types helper (`@babel/types`) used for AST type checks.
64
+ *
65
+ * @returns {void}
66
+ * Updates `state.importState` with the following structure:
67
+ * ```js
68
+ * {
69
+ * reactId: Identifier | null, // Local identifier for React import
70
+ * useStateId: Identifier | null, // Local identifier for useState import
71
+ * isDefault: boolean, // True if React is default-imported
72
+ * isNamed: boolean, // True if useState is explicitly named-imported
73
+ * isNamespace: boolean, // True if React is namespace-imported
74
+ * reactImportPath: ImportDeclaration | null, // AST node of React import
75
+ * }
76
+ * ```
77
+ *
78
+ * @important
79
+ * - Only resolves imports where `source.value` equals `REACT_IMPORT_CORE_NAME`.
80
+ * - Handles three import forms:
81
+ * - `import React from 'react'`
82
+ * - `import { useState } from 'react'`
83
+ * - `import * as ReactNS from 'react'`
84
+ * - Errors are silently caught; unresolved imports will leave `state.importState` with nulls.
85
+ *
86
+ * @example
87
+ * ```js
88
+ * importStateResolver(path, state, t);
89
+ * console.log(state.importState.reactId); // Identifier for React import
90
+ * console.log(state.importState.useStateId); // Identifier for useState if imported
91
+ * ```
92
+ */
93
+ function importStateResolver(path, state, t) {
94
+ try {
95
+ const importState = {
96
+ reactId: null,
97
+ useStateId: null,
98
+ isDefault: false,
99
+ isNamed: false,
100
+ isNamespace: false,
101
+ reactImportPath: null,
102
+ };
103
+ path.node.body.forEach(node => {
104
+ if (!t.isImportDeclaration(node)) return;
105
+ if (node.source.value !== REACT_IMPORT_CORE_NAME) return;
106
+ importState.reactImportPath = node;
107
+ node.specifiers.forEach(spec => {
108
+
109
+ // import React from 'react'
110
+ if (t.isImportDefaultSpecifier(spec)) {
111
+ importState.reactId = spec.local;
112
+ importState.isDefault = true;
113
+ }
114
+
115
+ // import { useState } from 'react'
116
+ if (t.isImportSpecifier(spec)) {
117
+ if (spec.imported.name === REACT_IMPORT_USE_STATE_HOOKS_NAME) {
118
+ importState.useStateId = spec.local;
119
+ importState.isNamed = true;
120
+ }
121
+ }
122
+
123
+ // import * as ReactNS from 'react'
124
+ if (t.isImportNamespaceSpecifier(spec)) {
125
+ importState.reactId = spec.local;
126
+ importState.isNamespace = true;
127
+ }
128
+ });
129
+ });
130
+ state.importState = importState;
131
+ } catch (e) {
132
+ log('error', '[::importStateResolver::]', e.message);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Resets the variable registry for the current file during AST traversal.
138
+ *
139
+ * This function clears any registered state variables in the `virtualRegistry`
140
+ * that are associated with the current file. It is useful for ensuring that
141
+ * state tracking does not leak across files when processing multiple files
142
+ * in the plugin.
143
+ *
144
+ * @param {Object} state - Plugin state, including the filename and plugin options.
145
+ * @param {Object<string, Object>} virtualRegistry - Registry of components and
146
+ * their registered variables/context info.
147
+ *
148
+ * @returns {void}
149
+ * Updates the `virtualRegistry` in place, resetting all variable names and
150
+ * default values associated with the current file.
151
+ *
152
+ * @important
153
+ * - Skips files excluded by `isExcludeFile`.
154
+ * - Uses a hash of the filename to identify the relevant registry entries.
155
+ * - Errors are silently caught.
156
+ *
157
+ * @example
158
+ * ```js
159
+ * resetRegisteryProcess(state, virtualRegistry);
160
+ * // Clears all state variables for the current file in the virtualRegistry
161
+ * ```
162
+ */
163
+ function resetRegisteryProcess(state, virtualRegistry) {
164
+ try {
165
+ const fileName = state.filename || _CCTX_EMPTY;
166
+ if (!isExcludeFile(fileName, this.opts)) return;
167
+ const hash = getFilePathHASH(fileName);
168
+ resetVarsForFile(virtualRegistry, hash);
169
+ } catch (e) {
170
+ log('error', '[::resetRegisteryProcess::]', e.message);
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Babel visitor handler for the `Program` node when entering a file.
176
+ *
177
+ * This function initializes plugin state for the file, resolves React imports,
178
+ * and resets the variable registry for the current file. It is typically used
179
+ * at the beginning of processing each file to ensure a clean state.
180
+ *
181
+ * @param {NodePath} path - The Babel AST path representing the Program node.
182
+ * @param {Object} state - Plugin state, including filename, import metadata, and configuration.
183
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate or check AST nodes.
184
+ * @param {Object<string, Object>} virtualRegistry - Registry of components and their
185
+ * registered variables/context info.
186
+ * @param {Object} config - The plugin configuration for the current file.
187
+ *
188
+ * @returns {void}
189
+ * - Updates `state.casperConfig` with the provided config.
190
+ * - Populates `state.importState` with resolved React imports.
191
+ * - Resets the variable registry for the current file in `virtualRegistry`.
192
+ *
193
+ * @important
194
+ * - Must be called at the entry of each Program node to ensure correct setup.
195
+ * - Errors are silently caught; consider logging during debugging.
196
+ *
197
+ * @example
198
+ * ```js
199
+ * programEnter(path, state, t, virtualRegistry, pluginConfig);
200
+ * // Initializes plugin state, resolves React imports, resets file-specific registry
201
+ * ```
202
+ */
203
+ export function programEnter(path, state, t, virtualRegistry, config) {
204
+ try {
205
+ state.casperConfig = config
206
+ importStateResolver(path, state, t);
207
+ resetRegisteryProcess.call(this, state, virtualRegistry);
208
+ } catch (e) {
209
+ log('error', '[::programEnter::]', e.message);
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Injects required imports for React and global context if they are missing.
215
+ *
216
+ * This function ensures that the necessary modules are imported at the top of
217
+ * the file when the AST traversal detects that `useState` or global context usage
218
+ * is needed. It adds the imports only when required, avoiding duplicate or
219
+ * unnecessary imports.
220
+ *
221
+ * @param {NodePath} path - The Babel AST path where imports should be injected.
222
+ * @param {Object} state - Plugin state, containing flags `needUseStateImport` and `needsGblContext`.
223
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate AST nodes.
224
+ *
225
+ * @returns {void}
226
+ * - Conditionally injects `React` import if `useState` is required.
227
+ * - Conditionally injects global context import if any global context is used.
228
+ * - Uses `buildRequireDeclaration` to insert the import statements at the top of the file.
229
+ *
230
+ * @important
231
+ * - Checks `state.needUseStateImport` and `state.needsGblContext` to determine necessity.
232
+ * - Errors are silently caught; no exception is thrown if import insertion fails.
233
+ *
234
+ * @example
235
+ * ```js
236
+ * bindMissingImport(path, state, t);
237
+ * // Injects React and global context imports if they are missing
238
+ * ```
239
+ */
240
+ function bindMissingImport(path, state, t) {
241
+ try {
242
+ if (state?.needUseStateImport) buildRequireDeclaration(path, t, _CCTX_UNDUS_CORE_REACT, _CCTX_REACT);
243
+ if (state?.needsGblContext) buildRequireDeclaration(path, t, _CCTX_UNDUS_CORE_GBL_CONTEXT, CONTEXT_FILE_PATH);
244
+ } catch (e) {
245
+ log('error', '[::bindMissingImport::]', e.message);
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Babel visitor handler for the `Program` node when exiting a file.
251
+ *
252
+ * This function is called after the AST traversal of the entire file is complete.
253
+ * Its primary purpose is to inject any missing imports for React or global context
254
+ * that were flagged as required during traversal.
255
+ *
256
+ * @param {NodePath} path - The Babel AST path representing the Program node.
257
+ * @param {Object} state - Plugin state, including flags `needUseStateImport` and `needsGblContext`.
258
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate AST nodes.
259
+ *
260
+ * @returns {void}
261
+ * Modifies the AST in place by calling `bindMissingImport` to insert necessary imports.
262
+ *
263
+ * @important
264
+ * - Should be paired with `programEnter` at the start of traversal.
265
+ * - Only injects imports if flagged during traversal (`state.needUseStateImport` or `state.needsGblContext`).
266
+ * - Errors are silently caught; AST modifications fail gracefully if errors occur.
267
+ *
268
+ * @example
269
+ * ```js
270
+ * programExit(path, state, t);
271
+ * // Ensures React and global context imports are added if needed
272
+ * ```
273
+ */
274
+ export function programExit(path, state, t) {
275
+ try {
276
+ bindMissingImport(path, state, t);
277
+ } catch (e) {
278
+ log('error', '[::programExit::]', e.message);
279
+ }
280
+ }