carto-md 1.0.0 → 1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carto-md",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "The context layer for AI-native development.",
5
5
  "bin": {
6
6
  "carto": "src/cli/index.js"
@@ -37,7 +37,26 @@ function extractFrontend(content) {
37
37
  });
38
38
  }
39
39
 
40
- return { fetches, storageKeys };
40
+ // Collapse dynamic fetches into a single summary row
41
+ const staticFetches = fetches.filter(f => f.url !== '[dynamic]');
42
+ const dynamicCount = fetches.filter(f => f.url === '[dynamic]').length;
43
+ if (dynamicCount > 0) {
44
+ staticFetches.push({
45
+ url: `[dynamic \u00d7${dynamicCount}]`,
46
+ method: '\u2014'
47
+ });
48
+ }
49
+
50
+ // Deduplicate storage keys — keep first occurrence only
51
+ const seen = new Set();
52
+ const dedupedStorageKeys = storageKeys.filter(({ operation, key }) => {
53
+ const id = `${operation}::${key}`;
54
+ if (seen.has(id)) return false;
55
+ seen.add(id);
56
+ return true;
57
+ });
58
+
59
+ return { fetches: staticFetches, storageKeys: dedupedStorageKeys };
41
60
  }
42
61
 
43
62
  module.exports = { extractFrontend };
@@ -43,15 +43,16 @@ function extractFunctions(content, filename) {
43
43
  const rawParams = match[3];
44
44
  const returnType = match[4] ? match[4].trim() : '\u2014';
45
45
 
46
- // Step 3: Clean params
47
- const skipParams = new Set(['self', '*args', '**kwargs', '*', '']);
48
- const params = rawParams
49
- .split(',')
46
+ // Step 3: Clean params — use smart split to handle commas inside brackets
47
+ const skipParams = new Set(['self', '']);
48
+ const params = splitParams(rawParams)
50
49
  .map(p => {
51
50
  // Strip type annotation (everything after first ":")
52
51
  let cleaned = p.split(':')[0];
53
52
  // Strip default value (everything after first "=")
54
53
  cleaned = cleaned.split('=')[0];
54
+ // Strip leading * or **
55
+ cleaned = cleaned.replace(/^\*{1,2}/, '');
55
56
  return cleaned.trim();
56
57
  })
57
58
  .filter(p => !skipParams.has(p));
@@ -66,4 +67,26 @@ function extractFunctions(content, filename) {
66
67
  return functions;
67
68
  }
68
69
 
70
+ /**
71
+ * Splits params by comma at the top level only.
72
+ * Commas inside brackets [], parentheses (), or braces {} do NOT split.
73
+ */
74
+ function splitParams(rawParams) {
75
+ const params = [];
76
+ let depth = 0;
77
+ let current = '';
78
+ for (const char of rawParams) {
79
+ if (char === '[' || char === '(' || char === '{') depth++;
80
+ else if (char === ']' || char === ')' || char === '}') depth--;
81
+ else if (char === ',' && depth === 0) {
82
+ params.push(current.trim());
83
+ current = '';
84
+ continue;
85
+ }
86
+ current += char;
87
+ }
88
+ if (current.trim()) params.push(current.trim());
89
+ return params;
90
+ }
91
+
69
92
  module.exports = { extractFunctions };
package/src/sync.js CHANGED
@@ -142,6 +142,29 @@ async function runFullSync(config) {
142
142
  allStorageKeys = allStorageKeys.concat(result.storageKeys);
143
143
  }
144
144
 
145
+ // Global dedup: collapse dynamic fetches across all files into one summary row
146
+ const staticFetches = allFetches.filter(f => !f.url.startsWith('[dynamic'));
147
+ let totalDynamic = 0;
148
+ for (const f of allFetches) {
149
+ if (f.url === '[dynamic]') totalDynamic++;
150
+ // Also count already-collapsed per-file rows like "[dynamic ×1]"
151
+ const m = f.url.match(/^\[dynamic\s*\u00d7(\d+)\]$/);
152
+ if (m) totalDynamic += parseInt(m[1], 10);
153
+ }
154
+ if (totalDynamic > 0) {
155
+ staticFetches.push({ url: `[dynamic \u00d7${totalDynamic}]`, method: '\u2014' });
156
+ }
157
+ allFetches = staticFetches;
158
+
159
+ // Global dedup: storage keys across all files
160
+ const skSeen = new Set();
161
+ allStorageKeys = allStorageKeys.filter(({ operation, key }) => {
162
+ const id = `${operation}::${key}`;
163
+ if (skSeen.has(id)) return false;
164
+ skSeen.add(id);
165
+ return true;
166
+ });
167
+
145
168
  // Build file map
146
169
  const fileMap = [];
147
170
  for (const filePath of allCodeFiles) {