create-interview-cockpit 0.16.0 → 0.17.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 +1 -1
- package/template/client/package-lock.json +75 -2
- package/template/client/package.json +3 -1
- package/template/client/src/browserSecurityTemplates.ts +75 -72
- package/template/client/src/components/CodeRunnerModal.tsx +504 -24
- package/template/client/src/reactLab.ts +374 -152
- package/template/cockpit.json +1 -1
- package/template/server/src/index.ts +134 -47
package/template/cockpit.json
CHANGED
|
@@ -1641,7 +1641,34 @@ Examples (illustrative only — use real ids and names from the list above):
|
|
|
1641
1641
|
|
|
1642
1642
|
// ─── Code Context Browser ────────────────────────────────
|
|
1643
1643
|
|
|
1644
|
-
|
|
1644
|
+
function parseListEnv(value: string | undefined): string[] {
|
|
1645
|
+
if (!value) return [];
|
|
1646
|
+
return value
|
|
1647
|
+
.split(/[\n,;]/)
|
|
1648
|
+
.map((item) => item.trim())
|
|
1649
|
+
.filter(Boolean);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
function normalizeName(value: string): string {
|
|
1653
|
+
return path.basename(value).trim().toLowerCase();
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
function normalizePathPrefix(value: string): string {
|
|
1657
|
+
return value
|
|
1658
|
+
.replaceAll("\\", "/")
|
|
1659
|
+
.replace(/^\.\//, "")
|
|
1660
|
+
.replace(/^\/+/, "")
|
|
1661
|
+
.replace(/\/+$/, "")
|
|
1662
|
+
.toLowerCase();
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
function normalizeExtension(value: string): string {
|
|
1666
|
+
const ext = value.trim().toLowerCase();
|
|
1667
|
+
if (!ext) return "";
|
|
1668
|
+
return ext.startsWith(".") ? ext : `.${ext}`;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
const DEFAULT_IGNORE_DIRS = [
|
|
1645
1672
|
"node_modules",
|
|
1646
1673
|
".git",
|
|
1647
1674
|
"dist",
|
|
@@ -1667,70 +1694,130 @@ const IGNORE_DIRS = new Set([
|
|
|
1667
1694
|
"venv",
|
|
1668
1695
|
".venv",
|
|
1669
1696
|
// macOS / editor noise
|
|
1670
|
-
".DS_Store",
|
|
1671
1697
|
".Spotlight-V100",
|
|
1672
1698
|
".Trashes",
|
|
1699
|
+
];
|
|
1700
|
+
|
|
1701
|
+
const DEFAULT_IGNORE_FILES = [
|
|
1702
|
+
".DS_Store",
|
|
1673
1703
|
".env",
|
|
1674
1704
|
".env.local",
|
|
1675
1705
|
".env.development",
|
|
1676
1706
|
".env.production",
|
|
1677
|
-
]
|
|
1707
|
+
];
|
|
1708
|
+
|
|
1709
|
+
const IGNORE_DIRS = new Set(
|
|
1710
|
+
[
|
|
1711
|
+
...DEFAULT_IGNORE_DIRS,
|
|
1712
|
+
...parseListEnv(process.env.CODE_CONTEXT_IGNORE_DIRS),
|
|
1713
|
+
...parseListEnv(process.env.IGNORE_DIRS),
|
|
1714
|
+
].map(normalizeName),
|
|
1715
|
+
);
|
|
1716
|
+
|
|
1717
|
+
const IGNORE_FILES = new Set(
|
|
1718
|
+
[
|
|
1719
|
+
...DEFAULT_IGNORE_FILES,
|
|
1720
|
+
...parseListEnv(process.env.CODE_CONTEXT_IGNORE_FILES),
|
|
1721
|
+
].map(normalizeName),
|
|
1722
|
+
);
|
|
1678
1723
|
|
|
1679
1724
|
// File extensions that are binary or auto-generated — never useful as context
|
|
1680
|
-
const IGNORE_EXTENSIONS = new Set(
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1725
|
+
const IGNORE_EXTENSIONS = new Set(
|
|
1726
|
+
[
|
|
1727
|
+
// .NET compiled outputs
|
|
1728
|
+
".dll",
|
|
1729
|
+
".exe",
|
|
1730
|
+
".pdb",
|
|
1731
|
+
".nupkg",
|
|
1732
|
+
".snupkg",
|
|
1733
|
+
".suo",
|
|
1734
|
+
// Lock / generated
|
|
1735
|
+
".lock",
|
|
1736
|
+
".user",
|
|
1737
|
+
// Images
|
|
1738
|
+
".png",
|
|
1739
|
+
".jpg",
|
|
1740
|
+
".jpeg",
|
|
1741
|
+
".gif",
|
|
1742
|
+
".svg",
|
|
1743
|
+
".ico",
|
|
1744
|
+
".webp",
|
|
1745
|
+
".bmp",
|
|
1746
|
+
// Fonts
|
|
1747
|
+
".woff",
|
|
1748
|
+
".woff2",
|
|
1749
|
+
".ttf",
|
|
1750
|
+
".eot",
|
|
1751
|
+
// Archives / binaries
|
|
1752
|
+
".zip",
|
|
1753
|
+
".tar",
|
|
1754
|
+
".gz",
|
|
1755
|
+
".rar",
|
|
1756
|
+
".7z",
|
|
1757
|
+
".bin",
|
|
1758
|
+
".so",
|
|
1759
|
+
".dylib",
|
|
1760
|
+
".lib",
|
|
1761
|
+
".obj",
|
|
1762
|
+
// Misc
|
|
1763
|
+
".min.js",
|
|
1764
|
+
".d.ts",
|
|
1765
|
+
".map",
|
|
1766
|
+
...parseListEnv(process.env.CODE_CONTEXT_IGNORE_EXTENSIONS),
|
|
1767
|
+
]
|
|
1768
|
+
.map(normalizeExtension)
|
|
1769
|
+
.filter(Boolean),
|
|
1770
|
+
);
|
|
1771
|
+
|
|
1772
|
+
const IGNORE_MULTI_EXTENSIONS = Array.from(IGNORE_EXTENSIONS).filter((ext) =>
|
|
1773
|
+
ext.slice(1).includes("."),
|
|
1774
|
+
);
|
|
1775
|
+
|
|
1776
|
+
const IGNORE_PATH_PREFIXES = new Set(
|
|
1777
|
+
parseListEnv(process.env.CODE_CONTEXT_IGNORE_PATHS)
|
|
1778
|
+
.map(normalizePathPrefix)
|
|
1779
|
+
.filter(Boolean),
|
|
1780
|
+
);
|
|
1781
|
+
|
|
1782
|
+
function shouldIgnorePath(relPath: string): boolean {
|
|
1783
|
+
if (IGNORE_PATH_PREFIXES.size === 0) return false;
|
|
1784
|
+
const normalized = normalizePathPrefix(relPath);
|
|
1785
|
+
if (!normalized) return false;
|
|
1786
|
+
|
|
1787
|
+
for (const prefix of IGNORE_PATH_PREFIXES) {
|
|
1788
|
+
if (normalized === prefix || normalized.startsWith(`${prefix}/`)) {
|
|
1789
|
+
return true;
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
return false;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
function hasIgnoredExtension(fileNameLower: string): boolean {
|
|
1796
|
+
if (IGNORE_EXTENSIONS.has(path.extname(fileNameLower))) {
|
|
1797
|
+
return true;
|
|
1798
|
+
}
|
|
1799
|
+
for (const ext of IGNORE_MULTI_EXTENSIONS) {
|
|
1800
|
+
if (fileNameLower.endsWith(ext)) {
|
|
1801
|
+
return true;
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
return false;
|
|
1805
|
+
}
|
|
1720
1806
|
|
|
1721
1807
|
async function walkDir(dir: string, prefix = ""): Promise<string[]> {
|
|
1722
1808
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
1723
1809
|
const files: string[] = [];
|
|
1724
1810
|
for (const entry of entries) {
|
|
1725
|
-
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
1726
1811
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
1812
|
+
const lowerName = entry.name.toLowerCase();
|
|
1813
|
+
|
|
1727
1814
|
if (entry.isDirectory()) {
|
|
1815
|
+
if (IGNORE_DIRS.has(lowerName) || shouldIgnorePath(rel)) continue;
|
|
1728
1816
|
files.push(...(await walkDir(path.join(dir, entry.name), rel)));
|
|
1729
1817
|
} else {
|
|
1818
|
+
if (IGNORE_FILES.has(lowerName) || shouldIgnorePath(rel)) continue;
|
|
1730
1819
|
const lower = entry.name.toLowerCase();
|
|
1731
|
-
if (
|
|
1732
|
-
// Also catch compound extensions like .min.js, .d.ts generated files
|
|
1733
|
-
if (lower.endsWith(".min.js") || lower.endsWith(".d.ts")) continue;
|
|
1820
|
+
if (hasIgnoredExtension(lower)) continue;
|
|
1734
1821
|
files.push(rel);
|
|
1735
1822
|
}
|
|
1736
1823
|
}
|