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,75 @@
1
+ /**
2
+ * @fileoverview Application Root & Provider Orchestration.
3
+ * This module manages the final wrapping phase of the AST transformation.
4
+ * It ensures that the transformed component tree is encapsulated within
5
+ * the custom Casper Context Provider, enabling global state distribution.
6
+ */
7
+
8
+ /**
9
+ * Core Logic Constants
10
+ * @description
11
+ * - _CCTX_CMP_NAME_PREFIX: The prefix used to identify and generate unique
12
+ * Context Provider instances (e.g., '_$_ctx_').
13
+ * - _CCTX_EMPTY: A safe fallback initializer for string-based AST properties.
14
+ */
15
+ import { _CCTX_CMP_NAME_PREFIX, _CCTX_EMPTY } from '../utils/constants';
16
+
17
+ /**
18
+ * AST Transformation Helpers
19
+ * @description
20
+ * - buildCtxProvider: A structural helper that wraps a JSX element or
21
+ * Function body with a `<Context.Provider>` component, mapping internal
22
+ * state to the Provider's `value` prop.
23
+ */
24
+ import { buildCtxProvider } from '../utils/astHelpers';
25
+
26
+ /**
27
+ * @module Logger
28
+ * @description Provides a controlled logging interface for the Babel transformation process.
29
+ */
30
+ import { log } from '../utils/utilityHelpers';
31
+
32
+ /**
33
+ * @important
34
+ * The `buildCtxProvider` function is typically invoked during the `Program.exit`
35
+ * or `ExportDefaultDeclaration` phase to ensure all nested transformations
36
+ * are complete before the final Provider wrapping occurs.
37
+ */
38
+
39
+ /**
40
+ * Visitor for `ReturnStatement` nodes inside a function declaration.
41
+ *
42
+ * This function inspects the return statement of a component function
43
+ * and wraps its returned JSX or value with the corresponding context provider.
44
+ * It ensures that the component correctly provides state and context to its children.
45
+ *
46
+ * @param {NodePath} path - The Babel AST path representing the `ReturnStatement` node.
47
+ * @param {Object} state - Plugin state, including import information and configuration.
48
+ * @param {Object} t - Babel types helper (`@babel/types`) used to generate AST nodes.
49
+ * @param {Object} entry - Registry entry for the component, containing `ctxName` and variable names.
50
+ *
51
+ * @returns {void}
52
+ * Modifies the return statement node in place, replacing it with a `React.createElement`
53
+ * call that wraps the original return value with a context provider.
54
+ *
55
+ * @important
56
+ * - Only processes return statements that have a non-null argument.
57
+ * - Uses `buildCtxProvider` to generate the provider wrapper.
58
+ * - Errors are silently caught; no changes occur if an exception is thrown.
59
+ *
60
+ * @example
61
+ * ```js
62
+ * functionDeclarationReturnStatementVisitor(path, state, t, entry);
63
+ * // Wraps the return value of a component function with its context provider
64
+ * ```
65
+ */
66
+ export function functionDeclarationReturnStatementVisitor (path, state, t, entry) {
67
+ try {
68
+ const returnNode = path.node.argument;
69
+ if (!returnNode) return;
70
+ const stateName = entry.ctxName.replace(_CCTX_CMP_NAME_PREFIX, _CCTX_EMPTY);
71
+ buildCtxProvider(path, t, returnNode, state, stateName);
72
+ } catch (e) {
73
+ log('error', '[::functionDeclarationReturnStatementVisitor::]', e.message);
74
+ }
75
+ }
@@ -0,0 +1,216 @@
1
+ /**
2
+ * @fileoverview Variable Registration & Classification Logic.
3
+ * This module is responsible for the initial discovery phase of the transformation.
4
+ * It identifies custom context variables during their declaration, classifies their
5
+ * initial values, and registers them within the global tracking registry.
6
+ */
7
+
8
+ /**
9
+ * AST Literal & Expression Constants
10
+ * @description These constants are used to evaluate the 'init' value of a variable.
11
+ * Your library uses these to distinguish between simple state and complex logic.
12
+ */
13
+ import {
14
+ NUMERIC_LITERAL, // e.g., 42
15
+ STRING_LITERAL, // e.g., "hello"
16
+ BOOLEAN_LITERAL, // e.g., true
17
+ ARRAY_EXPRESSION, // e.g., [1, 2, 3]
18
+ OBJECT_EXPRESSION,// e.g., { key: 'value' }
19
+ _CCTX_EMPTY // Default fallback for uninitialized variables
20
+ } from '../utils/constants';
21
+
22
+ /**
23
+ * Registration & Lifecycle Utilities
24
+ * @description
25
+ * - isExcludeFile: Prevents tracking variables in ignored files or directories.
26
+ * - registerVariable: The core method that saves variable metadata to the virtualRegistry.
27
+ * - getFilePathHASH: Ensures variables are scoped to a unique file ID to prevent collisions.
28
+ */
29
+ import { isExcludeFile, registerVariable, getFilePathHASH } from '../utils/utilityHelpers';
30
+
31
+ /**
32
+ * Scope & Inheritance Helpers
33
+ * @description
34
+ * - getInheritantDecComponent: Traverses upward from a variable declaration to find
35
+ * the parent component name, ensuring the variable is correctly scoped to its owner.
36
+ */
37
+ import { getInheritantDecComponent } 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
+ * **Classification Note:** When a variable is registered, its "Literal Type" determines
48
+ * how the subsequent `useState` hook is initialized. Non-literal initializers
49
+ * may require different handling during the `functionDeclarationExit` phase.
50
+ */
51
+
52
+ /**
53
+ * Extracts the initial value of a variable from a Babel AST `VariableDeclarator` node.
54
+ *
55
+ * This function inspects the `init` property of a variable declaration and
56
+ * attempts to determine its literal value. It handles primitive literals,
57
+ * arrays, and objects with literal values. Non-literal or complex expressions
58
+ * are flagged as `NON_LITERAL`.
59
+ *
60
+ * @param {NodePath} path - Babel AST path for a `VariableDeclarator` node.
61
+ *
62
+ * @returns {any} The initial value of the variable:
63
+ * - `number` for numeric literals
64
+ * - `string` for string literals
65
+ * - `boolean` for boolean literals
66
+ * - `Array` of literal values for array expressions
67
+ * - `Object` of literal key-value pairs for object expressions
68
+ * - `NON_LITERAL` for other expressions or complex initializers
69
+ * - `undefined` if the variable has no initializer
70
+ *
71
+ * @important
72
+ * - Only inspects direct literal values. Nested expressions inside arrays or objects
73
+ * that are not literals will be ignored or marked as `null`.
74
+ * - Errors during traversal or invalid AST nodes will return the current `initValue`.
75
+ *
76
+ * @example
77
+ * ```js
78
+ * // For "const a = 5;" → returns 5
79
+ * // For "const b = [1, 2];" → returns [1, 2]
80
+ * // For "const c = { x: 1, y: 'a' };" → returns { x: 1, y: 'a' }
81
+ * ```
82
+ */
83
+ function getVariableInitValue(path) {
84
+ let initValue = undefined;
85
+ try {
86
+ if (path.node.init) {
87
+ const valNode = path.node.init;
88
+ if (valNode.type === NUMERIC_LITERAL ||
89
+ valNode.type === STRING_LITERAL ||
90
+ valNode.type === BOOLEAN_LITERAL) {
91
+ initValue = valNode.value;
92
+ }
93
+ else if (valNode.type === ARRAY_EXPRESSION) {
94
+ initValue =
95
+ valNode.elements.map(e => e.value ?? null);
96
+ }
97
+ else if (valNode.type === OBJECT_EXPRESSION) {
98
+ const obj = {};
99
+ for (const prop of valNode.properties) {
100
+ if (prop.key && prop.value && prop.value.value !== undefined) {
101
+ obj[prop.key.name || prop.key.value] = prop.value.value;
102
+ }
103
+ }
104
+ initValue = obj;
105
+ }
106
+ else {
107
+ initValue = NON_LITERAL;
108
+ }
109
+ }
110
+ return initValue;
111
+ } catch (e) {
112
+ return initValue;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Visitor for `VariableDeclarator` nodes to register state variables in the virtual registry.
118
+ *
119
+ * This function checks if a variable's name matches the plugin's configured prefix.
120
+ * If so, it extracts the initial value, identifies the enclosing component, and
121
+ * registers the variable in the `virtualRegistry`. It also ensures React and global
122
+ * context imports are flagged if needed.
123
+ *
124
+ * @param {NodePath} path - Babel AST path for a `VariableDeclarator` node.
125
+ * @param {Object} state - Plugin state, including filename, import metadata, and configuration flags.
126
+ * @param {Object} t - Babel types helper (`@babel/types`) used to inspect or create AST nodes.
127
+ * @param {Object<string, Object>} virtualRegistry - Registry of components and their registered variables.
128
+ *
129
+ * @returns {void}
130
+ * - Registers the variable in the `virtualRegistry` under the component hash.
131
+ * - Sets `state.needsGblContext` if the variable belongs to a global context.
132
+ * - Flags `state.needUseStateImport` if `useState` is not yet imported.
133
+ *
134
+ * @important
135
+ * - Only processes variables whose names start with the configured prefix.
136
+ * - Uses `getVariableInitValue` to determine the variable's initial value.
137
+ * - Errors are silently caught; no action is taken if an exception occurs.
138
+ *
139
+ * @example
140
+ * ```js
141
+ * variableDeclarationVisitor(path, state, t, virtualRegistry);
142
+ * // Registers a prefixed variable in the virtual registry with its initial value
143
+ * ```
144
+ */
145
+ export default function variableDeclarationVisitor(path, state, t, virtualRegistry) {
146
+ try {
147
+ const fileName = state.filename || _CCTX_EMPTY;
148
+ if (!isExcludeFile(fileName, this.opts)) return;
149
+ if (path.node.id.name?.startsWith(state.casperConfig.prefix)) {
150
+ const inheritantCMP = getInheritantDecComponent(path);
151
+ if (!inheritantCMP) return;
152
+ const filePathHash = getFilePathHASH(fileName);
153
+ let _init_value = getVariableInitValue(path);
154
+ state.needsGblContext = true;
155
+ if (
156
+ !state.importState.reactId &&
157
+ !state.importState.useStateId
158
+ ) {
159
+ state.needUseStateImport = true
160
+ }
161
+ registerVariable(`${inheritantCMP}_${filePathHash}`, path.node.id.name, _init_value, virtualRegistry);
162
+ }
163
+ } catch (e) {
164
+ log('error', '[::variableDeclarationVisitor::]', e.message);
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Visitor for `VariableDeclarator` nodes inside a function's body to collect state variables.
170
+ *
171
+ * This function inspects variable declarations within a component function and collects
172
+ * those whose names start with the plugin's configured prefix. Collected variables are
173
+ * added to `localStateVars` for later use in context or state initialization.
174
+ * The original declaration line is removed from the AST to prevent duplication.
175
+ *
176
+ * @param {NodePath} path - Babel AST path for a `VariableDeclarator` node.
177
+ * @param {Object} state - Plugin state, containing the configuration and flags.
178
+ * @param {Object} t - Babel types helper (`@babel/types`) used to inspect and manipulate AST nodes.
179
+ * @param {Array<Object>} localStateVars - Array to collect state variables with `{ name, init }`.
180
+ *
181
+ * @returns {void}
182
+ * - Pushes matched variables into `localStateVars`.
183
+ * - Removes the original variable declaration or the specific declarator from the AST.
184
+ *
185
+ * @important
186
+ * - Only processes identifiers whose names match the configured prefix.
187
+ * - Safely handles declarations with multiple declarators by removing only the matched one.
188
+ * - Errors are silently caught; no action occurs if an exception is thrown.
189
+ *
190
+ * @example
191
+ * ```js
192
+ * const localStateVars = [];
193
+ * functionReturnVariableDelarationVisitor(path, state, t, localStateVars);
194
+ * // localStateVars now contains the prefixed variables from the function
195
+ * ```
196
+ */
197
+ export function functionReturnVariableDelarationVisitor(path, state, t, localStateVars) {
198
+ try {
199
+ const id = path.node.id;
200
+ const init = path.node.init;
201
+ if (!t.isIdentifier(id)) return;
202
+ if (id.name.startsWith(state.casperConfig.prefix)) {
203
+ localStateVars.push({ name: id.name, init });
204
+ // remove declaration line
205
+ if (t.isVariableDeclaration(path.parent)) {
206
+ if (path.parent.declarations.length === 1) {
207
+ path.parentPath.remove();
208
+ } else {
209
+ path.remove();
210
+ }
211
+ }
212
+ }
213
+ } catch (e) {
214
+ log('error', '[::functionReturnVariableDelarationVisitor::]', e.message);
215
+ }
216
+ }