logicstamp-context 0.2.6 → 0.3.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.
- package/LLM_CONTEXT.md +2 -2
- package/README.md +79 -36
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +36 -10
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/ignore.d.ts +16 -0
- package/dist/cli/commands/ignore.d.ts.map +1 -0
- package/dist/cli/commands/ignore.js +61 -0
- package/dist/cli/commands/ignore.js.map +1 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +83 -9
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/security.d.ts +37 -0
- package/dist/cli/commands/security.d.ts.map +1 -0
- package/dist/cli/commands/security.js +304 -0
- package/dist/cli/commands/security.js.map +1 -0
- package/dist/cli/handlers/ignoreHandler.d.ts +5 -0
- package/dist/cli/handlers/ignoreHandler.d.ts.map +1 -0
- package/dist/cli/handlers/ignoreHandler.js +23 -0
- package/dist/cli/handlers/ignoreHandler.js.map +1 -0
- package/dist/cli/handlers/securityHandler.d.ts +5 -0
- package/dist/cli/handlers/securityHandler.d.ts.map +1 -0
- package/dist/cli/handlers/securityHandler.js +41 -0
- package/dist/cli/handlers/securityHandler.js.map +1 -0
- package/dist/cli/parser/argumentParser.d.ts +9 -0
- package/dist/cli/parser/argumentParser.d.ts.map +1 -1
- package/dist/cli/parser/argumentParser.js +50 -0
- package/dist/cli/parser/argumentParser.js.map +1 -1
- package/dist/cli/parser/helpText.d.ts +3 -0
- package/dist/cli/parser/helpText.d.ts.map +1 -1
- package/dist/cli/parser/helpText.js +492 -348
- package/dist/cli/parser/helpText.js.map +1 -1
- package/dist/cli/stamp.js +61 -1
- package/dist/cli/stamp.js.map +1 -1
- package/dist/core/pack/builder.d.ts.map +1 -1
- package/dist/core/pack/builder.js +25 -5
- package/dist/core/pack/builder.js.map +1 -1
- package/dist/core/pack/loader.d.ts +14 -0
- package/dist/core/pack/loader.d.ts.map +1 -1
- package/dist/core/pack/loader.js +86 -2
- package/dist/core/pack/loader.js.map +1 -1
- package/dist/core/pack.d.ts.map +1 -1
- package/dist/core/pack.js +15 -2
- package/dist/core/pack.js.map +1 -1
- package/dist/utils/codeSanitizer.d.ts +24 -0
- package/dist/utils/codeSanitizer.d.ts.map +1 -0
- package/dist/utils/codeSanitizer.js +234 -0
- package/dist/utils/codeSanitizer.js.map +1 -0
- package/dist/utils/gitignore.d.ts +30 -2
- package/dist/utils/gitignore.d.ts.map +1 -1
- package/dist/utils/gitignore.js +132 -20
- package/dist/utils/gitignore.js.map +1 -1
- package/dist/utils/secretDetector.d.ts +21 -0
- package/dist/utils/secretDetector.d.ts.map +1 -0
- package/dist/utils/secretDetector.js +145 -0
- package/dist/utils/secretDetector.js.map +1 -0
- package/dist/utils/stampignore.d.ts +49 -0
- package/dist/utils/stampignore.d.ts.map +1 -0
- package/dist/utils/stampignore.js +211 -0
- package/dist/utils/stampignore.js.map +1 -0
- package/package.json +1 -1
- package/schema/logicstamp.context.schema.json +1 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple secret detection utilities
|
|
3
|
+
* Detects common patterns for API keys, tokens, passwords, etc.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Common secret patterns to detect
|
|
7
|
+
*/
|
|
8
|
+
const SECRET_PATTERNS = [
|
|
9
|
+
// API Keys
|
|
10
|
+
{
|
|
11
|
+
name: 'API Key',
|
|
12
|
+
pattern: /['"`]?(?:api[_-]?key|apikey)['"`]?\s*[=:]\s*['"`]?([a-zA-Z0-9_\-]{20,})['"`]?/i,
|
|
13
|
+
severity: 'high',
|
|
14
|
+
},
|
|
15
|
+
// AWS Access Keys
|
|
16
|
+
{
|
|
17
|
+
name: 'AWS Access Key',
|
|
18
|
+
// Pattern obfuscated to avoid GitHub secret scanning false positives
|
|
19
|
+
// This is a detection pattern, not an actual secret
|
|
20
|
+
pattern: (() => {
|
|
21
|
+
const part1 = 'A'.concat('K');
|
|
22
|
+
const part2 = 'I'.concat('A');
|
|
23
|
+
return new RegExp(part1 + part2 + '[0-9A-Z]{16}');
|
|
24
|
+
})(),
|
|
25
|
+
severity: 'high',
|
|
26
|
+
},
|
|
27
|
+
// GitHub Tokens
|
|
28
|
+
{
|
|
29
|
+
name: 'GitHub Token',
|
|
30
|
+
// Pattern obfuscated to avoid GitHub secret scanning false positives
|
|
31
|
+
// This is a detection pattern, not an actual secret
|
|
32
|
+
pattern: (() => {
|
|
33
|
+
const prefixes = [
|
|
34
|
+
'g'.concat('h').concat('p_'),
|
|
35
|
+
'g'.concat('h').concat('o_'),
|
|
36
|
+
'g'.concat('h').concat('u_'),
|
|
37
|
+
'g'.concat('h').concat('s_'),
|
|
38
|
+
'g'.concat('h').concat('r_'),
|
|
39
|
+
];
|
|
40
|
+
return new RegExp(prefixes.map(prefix => `${prefix}[a-zA-Z0-9]{36}`).join('|'));
|
|
41
|
+
})(),
|
|
42
|
+
severity: 'high',
|
|
43
|
+
},
|
|
44
|
+
// Private Keys
|
|
45
|
+
{
|
|
46
|
+
name: 'Private Key',
|
|
47
|
+
pattern: /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/,
|
|
48
|
+
severity: 'high',
|
|
49
|
+
},
|
|
50
|
+
// Passwords
|
|
51
|
+
{
|
|
52
|
+
name: 'Password',
|
|
53
|
+
pattern: /['"`]?(?:password|passwd|pwd)['"`]?\s*[=:]\s*['"`]?([^\s'"`]{8,})['"`]?/i,
|
|
54
|
+
severity: 'high',
|
|
55
|
+
},
|
|
56
|
+
// Tokens
|
|
57
|
+
{
|
|
58
|
+
name: 'Token',
|
|
59
|
+
pattern: /['"`]?(?:token|bearer)['"`]?\s*[=:]\s*['"`]?([a-zA-Z0-9_\-]{20,})['"`]?/i,
|
|
60
|
+
severity: 'high',
|
|
61
|
+
},
|
|
62
|
+
// OAuth Secrets
|
|
63
|
+
{
|
|
64
|
+
name: 'OAuth Secret',
|
|
65
|
+
pattern: /['"`]?(?:oauth[_-]?secret|client[_-]?secret)['"`]?\s*[=:]\s*['"`]?([a-zA-Z0-9_\-]{16,})['"`]?/i,
|
|
66
|
+
severity: 'high',
|
|
67
|
+
},
|
|
68
|
+
// Database URLs with credentials
|
|
69
|
+
{
|
|
70
|
+
name: 'Database URL with Credentials',
|
|
71
|
+
pattern: /(?:postgres|mysql|mongodb):\/\/[^:]+:[^@]+@/i,
|
|
72
|
+
severity: 'high',
|
|
73
|
+
},
|
|
74
|
+
// JWT Secrets
|
|
75
|
+
{
|
|
76
|
+
name: 'JWT Secret',
|
|
77
|
+
pattern: /['"`]?(?:jwt[_-]?secret|jwt[_-]?key)['"`]?\s*[=:]\s*['"`]?([a-zA-Z0-9_\-]{16,})['"`]?/i,
|
|
78
|
+
severity: 'high',
|
|
79
|
+
},
|
|
80
|
+
// Generic secrets
|
|
81
|
+
{
|
|
82
|
+
name: 'Secret',
|
|
83
|
+
pattern: /['"`]?(?:secret|secret[_-]?key)['"`]?\s*[=:]\s*['"`]?([a-zA-Z0-9_\-]{16,})['"`]?/i,
|
|
84
|
+
severity: 'medium',
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* Scan a file for secrets
|
|
89
|
+
*/
|
|
90
|
+
export function scanFileForSecrets(filePath, content) {
|
|
91
|
+
const matches = [];
|
|
92
|
+
const lines = content.split('\n');
|
|
93
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
94
|
+
const line = lines[lineIndex];
|
|
95
|
+
for (const { name, pattern, severity } of SECRET_PATTERNS) {
|
|
96
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
97
|
+
let match;
|
|
98
|
+
while ((match = regex.exec(line)) !== null) {
|
|
99
|
+
// Extract snippet (first 100 chars around match)
|
|
100
|
+
const matchStart = Math.max(0, match.index - 20);
|
|
101
|
+
const matchEnd = Math.min(line.length, match.index + match[0].length + 20);
|
|
102
|
+
const snippet = line.slice(matchStart, matchEnd).trim();
|
|
103
|
+
matches.push({
|
|
104
|
+
file: filePath,
|
|
105
|
+
line: lineIndex + 1,
|
|
106
|
+
column: match.index + 1,
|
|
107
|
+
type: name,
|
|
108
|
+
snippet,
|
|
109
|
+
severity,
|
|
110
|
+
});
|
|
111
|
+
// Prevent infinite loops
|
|
112
|
+
if (!pattern.global) {
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return matches;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Filter out false positives (common patterns that look like secrets but aren't)
|
|
122
|
+
*/
|
|
123
|
+
export function filterFalsePositives(matches) {
|
|
124
|
+
return matches.filter(match => {
|
|
125
|
+
// Skip if snippet contains common false positive patterns
|
|
126
|
+
const snippet = match.snippet.toLowerCase();
|
|
127
|
+
// Skip example/test patterns
|
|
128
|
+
if (snippet.includes('example') || snippet.includes('test') || snippet.includes('sample')) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
// Skip if it's clearly a comment or documentation
|
|
132
|
+
if (snippet.includes('//') || snippet.includes('/*') || snippet.includes('*')) {
|
|
133
|
+
// But keep if it's an actual assignment
|
|
134
|
+
if (!snippet.includes('=') && !snippet.includes(':')) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Skip very short matches (likely false positives)
|
|
139
|
+
if (match.type === 'Secret' && match.snippet.length < 20) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=secretDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretDetector.js","sourceRoot":"","sources":["../../src/utils/secretDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for managing .stampignore files
|
|
3
|
+
* Similar to .gitignore, but for LogicStamp context generation
|
|
4
|
+
*/
|
|
5
|
+
export interface StampIgnoreConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Array of file paths or glob patterns to ignore
|
|
8
|
+
* Paths are relative to the project root
|
|
9
|
+
*/
|
|
10
|
+
ignore: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Default .stampignore filename
|
|
14
|
+
*/
|
|
15
|
+
export declare const STAMPIGNORE_FILENAME = ".stampignore";
|
|
16
|
+
/**
|
|
17
|
+
* Check if .stampignore exists in the given directory
|
|
18
|
+
*/
|
|
19
|
+
export declare function stampignoreExists(targetDir: string): Promise<boolean>;
|
|
20
|
+
/**
|
|
21
|
+
* Read .stampignore content
|
|
22
|
+
*/
|
|
23
|
+
export declare function readStampignore(targetDir: string): Promise<StampIgnoreConfig | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Write .stampignore content
|
|
26
|
+
*/
|
|
27
|
+
export declare function writeStampignore(targetDir: string, config: StampIgnoreConfig): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Add paths to .stampignore
|
|
30
|
+
* Creates the file if it doesn't exist
|
|
31
|
+
*/
|
|
32
|
+
export declare function addToStampignore(targetDir: string, pathsToAdd: string[]): Promise<{
|
|
33
|
+
added: boolean;
|
|
34
|
+
created: boolean;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a file path matches any ignore pattern
|
|
38
|
+
* Supports glob patterns and exact paths
|
|
39
|
+
*/
|
|
40
|
+
export declare function matchesIgnorePattern(filePath: string, patterns: string[], projectRoot: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Filter files based on .stampignore patterns
|
|
43
|
+
*/
|
|
44
|
+
export declare function filterIgnoredFiles(files: string[], patterns: string[], projectRoot: string): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Delete .stampignore file
|
|
47
|
+
*/
|
|
48
|
+
export declare function deleteStampignore(targetDir: string): Promise<boolean>;
|
|
49
|
+
//# sourceMappingURL=stampignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stampignore.d.ts","sourceRoot":"","sources":["../../src/utils/stampignore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AAEnD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAsC1F;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAuB/C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAgET;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAMV;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB3E"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for managing .stampignore files
|
|
3
|
+
* Similar to .gitignore, but for LogicStamp context generation
|
|
4
|
+
*/
|
|
5
|
+
import { readFile, writeFile, access, unlink } from 'node:fs/promises';
|
|
6
|
+
import { join, isAbsolute } from 'node:path';
|
|
7
|
+
import { debugError } from './debug.js';
|
|
8
|
+
import { normalizeEntryId, getRelativePath } from './fsx.js';
|
|
9
|
+
/**
|
|
10
|
+
* Default .stampignore filename
|
|
11
|
+
*/
|
|
12
|
+
export const STAMPIGNORE_FILENAME = '.stampignore';
|
|
13
|
+
/**
|
|
14
|
+
* Check if .stampignore exists in the given directory
|
|
15
|
+
*/
|
|
16
|
+
export async function stampignoreExists(targetDir) {
|
|
17
|
+
try {
|
|
18
|
+
await access(join(targetDir, STAMPIGNORE_FILENAME));
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read .stampignore content
|
|
27
|
+
*/
|
|
28
|
+
export async function readStampignore(targetDir) {
|
|
29
|
+
const stampignorePath = join(targetDir, STAMPIGNORE_FILENAME);
|
|
30
|
+
try {
|
|
31
|
+
const content = await readFile(stampignorePath, 'utf-8');
|
|
32
|
+
const config = JSON.parse(content);
|
|
33
|
+
// Validate structure
|
|
34
|
+
if (!config || typeof config !== 'object') {
|
|
35
|
+
debugError('stampignore', 'readStampignore', {
|
|
36
|
+
stampignorePath,
|
|
37
|
+
message: 'Invalid config structure',
|
|
38
|
+
});
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (!Array.isArray(config.ignore)) {
|
|
42
|
+
debugError('stampignore', 'readStampignore', {
|
|
43
|
+
stampignorePath,
|
|
44
|
+
message: 'Config.ignore must be an array',
|
|
45
|
+
});
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const err = error;
|
|
52
|
+
if (err.code === 'ENOENT') {
|
|
53
|
+
// File doesn't exist - that's fine, return null
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
debugError('stampignore', 'readStampignore', {
|
|
57
|
+
stampignorePath,
|
|
58
|
+
message: err.message,
|
|
59
|
+
code: err.code,
|
|
60
|
+
});
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Write .stampignore content
|
|
66
|
+
*/
|
|
67
|
+
export async function writeStampignore(targetDir, config) {
|
|
68
|
+
const stampignorePath = join(targetDir, STAMPIGNORE_FILENAME);
|
|
69
|
+
try {
|
|
70
|
+
const content = JSON.stringify(config, null, 2);
|
|
71
|
+
await writeFile(stampignorePath, content, 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const err = error;
|
|
75
|
+
debugError('stampignore', 'writeStampignore', {
|
|
76
|
+
stampignorePath,
|
|
77
|
+
targetDir,
|
|
78
|
+
message: err.message,
|
|
79
|
+
code: err.code,
|
|
80
|
+
});
|
|
81
|
+
let userMessage;
|
|
82
|
+
switch (err.code) {
|
|
83
|
+
case 'ENOENT':
|
|
84
|
+
userMessage = `Parent directory not found for: "${stampignorePath}"`;
|
|
85
|
+
break;
|
|
86
|
+
case 'EACCES':
|
|
87
|
+
userMessage = `Permission denied writing to: "${stampignorePath}"`;
|
|
88
|
+
break;
|
|
89
|
+
case 'ENOSPC':
|
|
90
|
+
userMessage = `No space left on device. Cannot write: "${stampignorePath}"`;
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
userMessage = `Failed to write .stampignore file "${stampignorePath}": ${err.message}`;
|
|
94
|
+
}
|
|
95
|
+
throw new Error(userMessage);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Add paths to .stampignore
|
|
100
|
+
* Creates the file if it doesn't exist
|
|
101
|
+
*/
|
|
102
|
+
export async function addToStampignore(targetDir, pathsToAdd) {
|
|
103
|
+
const exists = await stampignoreExists(targetDir);
|
|
104
|
+
const config = await readStampignore(targetDir);
|
|
105
|
+
const currentIgnore = config?.ignore || [];
|
|
106
|
+
const normalizedCurrent = currentIgnore.map(p => normalizeEntryId(p));
|
|
107
|
+
// Normalize paths to add and filter out duplicates
|
|
108
|
+
const normalizedToAdd = pathsToAdd
|
|
109
|
+
.map(p => normalizeEntryId(p))
|
|
110
|
+
.filter(p => !normalizedCurrent.includes(p));
|
|
111
|
+
if (normalizedToAdd.length === 0) {
|
|
112
|
+
return { added: false, created: false };
|
|
113
|
+
}
|
|
114
|
+
const newConfig = {
|
|
115
|
+
ignore: [...currentIgnore, ...normalizedToAdd],
|
|
116
|
+
};
|
|
117
|
+
await writeStampignore(targetDir, newConfig);
|
|
118
|
+
return { added: true, created: !exists };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Check if a file path matches any ignore pattern
|
|
122
|
+
* Supports glob patterns and exact paths
|
|
123
|
+
*/
|
|
124
|
+
export function matchesIgnorePattern(filePath, patterns, projectRoot) {
|
|
125
|
+
// Get relative path from project root
|
|
126
|
+
// Use getRelativePath which properly handles Windows paths and converts to forward slashes
|
|
127
|
+
let relativePath;
|
|
128
|
+
if (isAbsolute(filePath)) {
|
|
129
|
+
relativePath = getRelativePath(projectRoot, filePath);
|
|
130
|
+
// If the relative path starts with '..', the file is outside the project root
|
|
131
|
+
// Don't match files outside the project root
|
|
132
|
+
if (relativePath.startsWith('../')) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
relativePath = filePath;
|
|
138
|
+
}
|
|
139
|
+
// Handle edge case: if relative path is empty or just '.', skip matching
|
|
140
|
+
if (!relativePath || relativePath === '.' || relativePath === './') {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
// Normalize the relative path for consistent matching
|
|
144
|
+
// normalizeEntryId normalizes path separators, drive letters, and removes leading ./
|
|
145
|
+
const normalizedRelativePath = normalizeEntryId(relativePath);
|
|
146
|
+
// Extract just the filename for filename-only pattern matching
|
|
147
|
+
const fileName = normalizedRelativePath.split('/').pop() || '';
|
|
148
|
+
for (const pattern of patterns) {
|
|
149
|
+
// Normalize the pattern (should already be relative, but normalize for consistency)
|
|
150
|
+
const normalizedPattern = normalizeEntryId(pattern);
|
|
151
|
+
// Exact match against full relative path
|
|
152
|
+
if (normalizedPattern === normalizedRelativePath) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
// Filename-only match: if pattern doesn't contain a slash, match against filename
|
|
156
|
+
// This allows patterns like "not-found.tsx" to match "src/not-found.tsx" or "app/not-found.tsx"
|
|
157
|
+
if (!normalizedPattern.includes('/') && normalizedPattern === fileName) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
// Glob pattern matching (simple implementation)
|
|
161
|
+
// Convert glob to regex
|
|
162
|
+
const regexPattern = normalizedPattern
|
|
163
|
+
.replace(/\./g, '\\.')
|
|
164
|
+
.replace(/\*\*/g, '.*')
|
|
165
|
+
.replace(/\*/g, '[^/]*')
|
|
166
|
+
.replace(/\?/g, '.');
|
|
167
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
168
|
+
// Check against normalized relative path
|
|
169
|
+
if (regex.test(normalizedRelativePath)) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
// Also check filename-only glob patterns (e.g., "*.test.tsx")
|
|
173
|
+
if (!normalizedPattern.includes('/') && regex.test(fileName)) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Filter files based on .stampignore patterns
|
|
181
|
+
*/
|
|
182
|
+
export function filterIgnoredFiles(files, patterns, projectRoot) {
|
|
183
|
+
if (patterns.length === 0) {
|
|
184
|
+
return files;
|
|
185
|
+
}
|
|
186
|
+
return files.filter(file => !matchesIgnorePattern(file, patterns, projectRoot));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Delete .stampignore file
|
|
190
|
+
*/
|
|
191
|
+
export async function deleteStampignore(targetDir) {
|
|
192
|
+
const stampignorePath = join(targetDir, STAMPIGNORE_FILENAME);
|
|
193
|
+
try {
|
|
194
|
+
await unlink(stampignorePath);
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
const err = error;
|
|
199
|
+
if (err.code === 'ENOENT') {
|
|
200
|
+
// File doesn't exist - that's fine, return false
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
debugError('stampignore', 'deleteStampignore', {
|
|
204
|
+
stampignorePath,
|
|
205
|
+
message: err.message,
|
|
206
|
+
code: err.code,
|
|
207
|
+
});
|
|
208
|
+
throw new Error(`Failed to delete .stampignore: ${err.message}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=stampignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stampignore.js","sourceRoot":"","sources":["../../src/utils/stampignore.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"source": {
|
|
118
118
|
"type": "string",
|
|
119
119
|
"pattern": "^logicstamp-context@\\d+\\.\\d+\\.\\d+$",
|
|
120
|
-
"description": "Generator identifier with version (e.g., 'logicstamp-context@0.
|
|
120
|
+
"description": "Generator identifier with version (e.g., 'logicstamp-context@0.3.0'). Used for compatibility tracking and debugging."
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
"additionalProperties": false
|