@keak/sdk 1.0.9 → 2.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.
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Webpack loader that uses Babel to inject Keak source attributes into JSX
3
- * This runs BEFORE SWC compilation to add data-keak-src, data-keak-component, and data-keak-idx attributes
3
+ * Simplified version - runs BEFORE SWC compilation
4
+ * Only runs in development mode
4
5
  */
5
6
 
6
7
  const path = require('path');
@@ -9,38 +10,23 @@ const babelTraverse = require('@babel/traverse').default;
9
10
  const babelGenerator = require('@babel/generator').default;
10
11
  const t = require('@babel/types');
11
12
 
12
- let elementIndexMap = new Map(); // Track element index per file
13
-
14
13
  module.exports = function keakLoaderBabel(source) {
15
- // Make loader cacheable for better performance
16
14
  this.cacheable(true);
17
15
 
18
16
  const resourcePath = this.resourcePath;
19
17
  const options = this.getOptions() || {};
20
- const { projectRoot = process.cwd(), includeElementIndex = true, devWarnings = false } = options;
21
18
 
22
- // Skip if not a JSX/TSX file
23
- if (!/\.(jsx|tsx|js|ts)$/.test(resourcePath)) {
19
+ // Skip in production
20
+ if (process.env.NODE_ENV === 'production' && !options.forceProduction) {
24
21
  return source;
25
22
  }
26
23
 
27
- // Skip files based on skip patterns
28
- const skipPatterns = options.skipPatterns || [];
29
- if (skipPatterns.some(pattern => {
30
- const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
31
- return regex.test(resourcePath);
32
- })) {
24
+ // Skip if not a JSX/TSX file
25
+ if (!/\.(jsx|tsx|js|ts)$/.test(resourcePath)) {
33
26
  return source;
34
27
  }
35
28
 
36
29
  try {
37
- console.log(`[keak-loader-pre] Processing ${path.relative(projectRoot || process.cwd(), resourcePath)} with Babel AST`);
38
-
39
- // Reset element index for this file
40
- if (includeElementIndex) {
41
- elementIndexMap.set(resourcePath, 0);
42
- }
43
-
44
30
  // Parse the source code
45
31
  const ast = babelParser.parse(source, {
46
32
  sourceType: 'module',
@@ -50,20 +36,15 @@ module.exports = function keakLoaderBabel(source) {
50
36
  'decorators-legacy',
51
37
  'classProperties',
52
38
  'objectRestSpread',
53
- 'functionBind',
54
- 'exportDefaultFrom',
55
- 'exportNamespaceFrom',
56
39
  'dynamicImport',
57
40
  'nullishCoalescingOperator',
58
- 'optionalChaining',
59
- 'topLevelAwait'
41
+ 'optionalChaining'
60
42
  ]
61
43
  });
62
44
 
63
- let elementCount = 0;
64
45
  let skipFile = false;
65
46
 
66
- // First pass: Check for next/font imports (Babel/SWC conflict)
47
+ // Check for next/font imports (Babel/SWC conflict)
67
48
  babelTraverse(ast, {
68
49
  ImportDeclaration(importPath) {
69
50
  const source = importPath.node.source.value;
@@ -75,125 +56,70 @@ module.exports = function keakLoaderBabel(source) {
75
56
  });
76
57
 
77
58
  if (skipFile) {
78
- if (devWarnings) {
79
- console.log(`[keak-loader-pre] ⚠️ Skipping ${path.relative(projectRoot || process.cwd(), resourcePath)} (contains next/font)`);
80
- }
81
59
  return source;
82
60
  }
83
61
 
84
- // Second pass: Transform JSX elements
62
+ // Transform JSX elements
85
63
  babelTraverse(ast, {
86
64
  JSXOpeningElement(nodePath) {
87
65
  const node = nodePath.node;
88
66
 
89
- // Skip if element already has keak source attribute
90
- const hasKeakSrc = node.attributes.some(attr =>
67
+ // Skip if already has keak attributes
68
+ const hasKeakAttr = node.attributes.some(attr =>
91
69
  t.isJSXAttribute(attr) &&
92
70
  t.isJSXIdentifier(attr.name) &&
93
- attr.name.name === 'data-keak-src'
71
+ (attr.name.name === 'data-keak-file' || attr.name.name === 'data-keak-src')
94
72
  );
95
73
 
96
- if (hasKeakSrc) {
74
+ if (hasKeakAttr || !node.loc) {
97
75
  return;
98
76
  }
99
77
 
100
- // Get source location
101
- const loc = node.loc;
102
- if (!loc) return;
103
-
104
- // Create relative path from project root
105
- const relativePath = path.relative(projectRoot || process.cwd(), resourcePath).replace(/\\/g, '/');
106
-
107
- // Create source location string: "file:line:column"
108
- const sourceLocation = `${relativePath}:${loc.start.line}:${loc.start.column}`;
109
-
110
- // Get element name
111
- let tagName = '';
112
- let componentName = '';
113
-
114
- if (t.isJSXIdentifier(node.name)) {
115
- tagName = node.name.name;
116
- // Try to find component name from parent scope
117
- const parentFunction = nodePath.getFunctionParent();
118
- if (parentFunction && parentFunction.isFunctionDeclaration()) {
119
- componentName = parentFunction.node.id?.name || '';
120
- } else if (parentFunction && parentFunction.isArrowFunctionExpression()) {
121
- const parentVar = parentFunction.getFunctionParent();
122
- if (parentVar && parentVar.isVariableDeclarator() && t.isIdentifier(parentVar.node.id)) {
123
- componentName = parentVar.node.id.name;
78
+ // Smart relative path detection
79
+ let sourceFile;
80
+ const srcParts = resourcePath.split('/src/');
81
+ if (srcParts.length > 1) {
82
+ sourceFile = 'src/' + srcParts[srcParts.length - 1];
83
+ } else {
84
+ const appParts = resourcePath.split('/app/');
85
+ if (appParts.length > 1) {
86
+ sourceFile = 'app/' + appParts[appParts.length - 1];
87
+ } else {
88
+ const compParts = resourcePath.split('/components/');
89
+ if (compParts.length > 1) {
90
+ sourceFile = 'components/' + compParts[compParts.length - 1];
91
+ } else {
92
+ sourceFile = path.relative(process.cwd(), resourcePath);
124
93
  }
125
94
  }
126
- } else if (t.isJSXMemberExpression(node.name)) {
127
- tagName = node.name.property.name;
128
- }
129
-
130
- // Only instrument DOM elements (lowercase) or all elements if configured
131
- const isDOMElement = /^[a-z]/.test(tagName);
132
-
133
- if (!isDOMElement && !options.instrumentComponents) {
134
- return;
135
95
  }
136
96
 
137
- // Get element index if enabled
138
- let elementIdx = null;
139
- if (includeElementIndex) {
140
- const currentIndex = elementIndexMap.get(resourcePath) || 0;
141
- elementIdx = currentIndex;
142
- elementIndexMap.set(resourcePath, currentIndex + 1);
143
- }
97
+ const { line } = node.loc.start;
144
98
 
145
- // Create attributes to inject
146
- const attributesToAdd = [
99
+ // Add data-keak-file and data-keak-line attributes
100
+ node.attributes.push(
101
+ t.jsxAttribute(
102
+ t.jsxIdentifier('data-keak-file'),
103
+ t.stringLiteral(sourceFile)
104
+ ),
147
105
  t.jsxAttribute(
148
- t.jsxIdentifier('data-keak-src'),
149
- t.stringLiteral(sourceLocation)
106
+ t.jsxIdentifier('data-keak-line'),
107
+ t.stringLiteral(String(line))
150
108
  )
151
- ];
152
-
153
- // Add component name if available
154
- if (componentName) {
155
- attributesToAdd.push(
156
- t.jsxAttribute(
157
- t.jsxIdentifier('data-keak-component'),
158
- t.stringLiteral(componentName)
159
- )
160
- );
161
- }
162
-
163
- // Add element index if enabled
164
- if (elementIdx !== null) {
165
- attributesToAdd.push(
166
- t.jsxAttribute(
167
- t.jsxIdentifier('data-keak-idx'),
168
- t.stringLiteral(String(elementIdx))
169
- )
170
- );
171
- }
172
-
173
- // Add attributes to the node
174
- node.attributes.push(...attributesToAdd);
175
- elementCount++;
109
+ );
176
110
  }
177
111
  });
178
112
 
179
- // Generate the transformed code
113
+ // Generate transformed code
180
114
  const output = babelGenerator(ast, {
181
115
  retainLines: false,
182
- compact: false,
183
- sourceMaps: false
116
+ compact: false
184
117
  }, source);
185
118
 
186
- if (elementCount > 0) {
187
- console.log(`[keak-loader-pre] ✓ Injected attributes into ${elementCount} elements in ${path.relative(projectRoot || process.cwd(), resourcePath)}`);
188
- }
189
-
190
119
  return output.code;
191
120
  } catch (error) {
192
- // If transformation fails, return original source
193
- console.error(`[keak-loader-pre] Error processing ${resourcePath}:`, error.message);
194
- if (devWarnings) {
195
- console.error('[keak-loader-pre] Stack:', error.stack);
196
- }
121
+ // Return original source on error
122
+ console.error(`[keak-loader] Error processing ${resourcePath}:`, error.message);
197
123
  return source;
198
124
  }
199
- };
125
+ };