@tinyviber/a2h 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.
- package/README.md +229 -0
- package/bin/a2h.js +7 -0
- package/dist/actions/engine.d.ts +40 -0
- package/dist/actions/engine.d.ts.map +1 -0
- package/dist/actions/engine.js +227 -0
- package/dist/actions/engine.js.map +1 -0
- package/dist/actions/policy.d.ts +8 -0
- package/dist/actions/policy.d.ts.map +1 -0
- package/dist/actions/policy.js +55 -0
- package/dist/actions/policy.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +258 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +8 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +69 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/ir/build.d.ts +8 -0
- package/dist/ir/build.d.ts.map +1 -0
- package/dist/ir/build.js +397 -0
- package/dist/ir/build.js.map +1 -0
- package/dist/ir/enrich.d.ts +21 -0
- package/dist/ir/enrich.d.ts.map +1 -0
- package/dist/ir/enrich.js +177 -0
- package/dist/ir/enrich.js.map +1 -0
- package/dist/ir/identity.d.ts +3 -0
- package/dist/ir/identity.d.ts.map +1 -0
- package/dist/ir/identity.js +91 -0
- package/dist/ir/identity.js.map +1 -0
- package/dist/ir/scoring.d.ts +7 -0
- package/dist/ir/scoring.d.ts.map +1 -0
- package/dist/ir/scoring.js +88 -0
- package/dist/ir/scoring.js.map +1 -0
- package/dist/parsers/code.d.ts +3 -0
- package/dist/parsers/code.d.ts.map +1 -0
- package/dist/parsers/code.js +17 -0
- package/dist/parsers/code.js.map +1 -0
- package/dist/parsers/diff.d.ts +11 -0
- package/dist/parsers/diff.d.ts.map +1 -0
- package/dist/parsers/diff.js +125 -0
- package/dist/parsers/diff.js.map +1 -0
- package/dist/parsers/json.d.ts +3 -0
- package/dist/parsers/json.d.ts.map +1 -0
- package/dist/parsers/json.js +16 -0
- package/dist/parsers/json.js.map +1 -0
- package/dist/parsers/log.d.ts +3 -0
- package/dist/parsers/log.d.ts.map +1 -0
- package/dist/parsers/log.js +105 -0
- package/dist/parsers/log.js.map +1 -0
- package/dist/parsers/markdown.d.ts +15 -0
- package/dist/parsers/markdown.d.ts.map +1 -0
- package/dist/parsers/markdown.js +89 -0
- package/dist/parsers/markdown.js.map +1 -0
- package/dist/parsers/text.d.ts +24 -0
- package/dist/parsers/text.d.ts.map +1 -0
- package/dist/parsers/text.js +98 -0
- package/dist/parsers/text.js.map +1 -0
- package/dist/presentation/blocks.d.ts +14 -0
- package/dist/presentation/blocks.d.ts.map +1 -0
- package/dist/presentation/blocks.js +87 -0
- package/dist/presentation/blocks.js.map +1 -0
- package/dist/presentation/present.d.ts +12 -0
- package/dist/presentation/present.d.ts.map +1 -0
- package/dist/presentation/present.js +115 -0
- package/dist/presentation/present.js.map +1 -0
- package/dist/providers/mock.d.ts +3 -0
- package/dist/providers/mock.d.ts.map +1 -0
- package/dist/providers/mock.js +171 -0
- package/dist/providers/mock.js.map +1 -0
- package/dist/providers/registry.d.ts +12 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +20 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/types.d.ts +64 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +40 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/renderer/assets/index.html +41 -0
- package/dist/renderer/assets/js/actions.js +205 -0
- package/dist/renderer/assets/js/api.js +75 -0
- package/dist/renderer/assets/js/artifacts.js +422 -0
- package/dist/renderer/assets/js/blocks.js +301 -0
- package/dist/renderer/assets/js/bus.js +21 -0
- package/dist/renderer/assets/js/cards.js +137 -0
- package/dist/renderer/assets/js/dom.js +61 -0
- package/dist/renderer/assets/js/format.js +118 -0
- package/dist/renderer/assets/js/main.js +125 -0
- package/dist/renderer/assets/js/nav.js +80 -0
- package/dist/renderer/assets/js/router.js +64 -0
- package/dist/renderer/assets/js/store.js +69 -0
- package/dist/renderer/assets/js/views.js +356 -0
- package/dist/renderer/assets/styles.css +856 -0
- package/dist/renderer/content.d.ts +11 -0
- package/dist/renderer/content.d.ts.map +1 -0
- package/dist/renderer/content.js +114 -0
- package/dist/renderer/content.js.map +1 -0
- package/dist/scanner/classify.d.ts +17 -0
- package/dist/scanner/classify.d.ts.map +1 -0
- package/dist/scanner/classify.js +117 -0
- package/dist/scanner/classify.js.map +1 -0
- package/dist/scanner/git.d.ts +3 -0
- package/dist/scanner/git.d.ts.map +1 -0
- package/dist/scanner/git.js +43 -0
- package/dist/scanner/git.js.map +1 -0
- package/dist/scanner/ignore.d.ts +22 -0
- package/dist/scanner/ignore.d.ts.map +1 -0
- package/dist/scanner/ignore.js +57 -0
- package/dist/scanner/ignore.js.map +1 -0
- package/dist/scanner/scan.d.ts +8 -0
- package/dist/scanner/scan.d.ts.map +1 -0
- package/dist/scanner/scan.js +108 -0
- package/dist/scanner/scan.js.map +1 -0
- package/dist/security/boundary.d.ts +19 -0
- package/dist/security/boundary.d.ts.map +1 -0
- package/dist/security/boundary.js +59 -0
- package/dist/security/boundary.js.map +1 -0
- package/dist/security/urlPolicy.d.ts +4 -0
- package/dist/security/urlPolicy.d.ts.map +1 -0
- package/dist/security/urlPolicy.js +56 -0
- package/dist/security/urlPolicy.js.map +1 -0
- package/dist/security/workspaceRead.d.ts +25 -0
- package/dist/security/workspaceRead.d.ts.map +1 -0
- package/dist/security/workspaceRead.js +103 -0
- package/dist/security/workspaceRead.js.map +1 -0
- package/dist/semantics/load.d.ts +11 -0
- package/dist/semantics/load.d.ts.map +1 -0
- package/dist/semantics/load.js +537 -0
- package/dist/semantics/load.js.map +1 -0
- package/dist/semantics/resolve.d.ts +37 -0
- package/dist/semantics/resolve.d.ts.map +1 -0
- package/dist/semantics/resolve.js +211 -0
- package/dist/semantics/resolve.js.map +1 -0
- package/dist/semantics/types.d.ts +158 -0
- package/dist/semantics/types.d.ts.map +1 -0
- package/dist/semantics/types.js +3 -0
- package/dist/semantics/types.js.map +1 -0
- package/dist/server/server.d.ts +17 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +510 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/workspace.d.ts +53 -0
- package/dist/server/workspace.d.ts.map +1 -0
- package/dist/server/workspace.js +211 -0
- package/dist/server/workspace.js.map +1 -0
- package/dist/types.d.ts +570 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/util/path.d.ts +11 -0
- package/dist/util/path.d.ts.map +1 -0
- package/dist/util/path.js +35 -0
- package/dist/util/path.js.map +1 -0
- package/dist/util/safeRead.d.ts +38 -0
- package/dist/util/safeRead.d.ts.map +1 -0
- package/dist/util/safeRead.js +117 -0
- package/dist/util/safeRead.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ArtifactContent, ContentKind, FileEntry } from '../types';
|
|
2
|
+
export interface ContentContext {
|
|
3
|
+
rootDir: string;
|
|
4
|
+
/** Workspace-relative paths (normalized) of all image files. */
|
|
5
|
+
knownImages: Set<string>;
|
|
6
|
+
/** Maps a workspace-relative path to a safe URL the renderer can load. */
|
|
7
|
+
fileUrl: (relPath: string) => string;
|
|
8
|
+
}
|
|
9
|
+
export declare function contentKindFor(entry: FileEntry): ContentKind;
|
|
10
|
+
export declare function renderContent(entry: FileEntry, ctx: ContentContext, mode?: 'tail' | 'full'): ArtifactContent;
|
|
11
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/renderer/content.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAgBxE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,0EAA0E;IAC1E,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CAE5D;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,cAAc,EACnB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GACrB,eAAe,CA0CjB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contentKindFor = contentKindFor;
|
|
4
|
+
exports.renderContent = renderContent;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const classify_1 = require("../scanner/classify");
|
|
7
|
+
const markdown_1 = require("../parsers/markdown");
|
|
8
|
+
const diff_1 = require("../parsers/diff");
|
|
9
|
+
const json_1 = require("../parsers/json");
|
|
10
|
+
const log_1 = require("../parsers/log");
|
|
11
|
+
const code_1 = require("../parsers/code");
|
|
12
|
+
const text_1 = require("../parsers/text");
|
|
13
|
+
const safeRead_1 = require("../util/safeRead");
|
|
14
|
+
const path_1 = require("../util/path");
|
|
15
|
+
function contentKindFor(entry) {
|
|
16
|
+
return (0, classify_1.contentKindOf)(entry.kind);
|
|
17
|
+
}
|
|
18
|
+
function renderContent(entry, ctx, mode) {
|
|
19
|
+
if (entry.sensitive) {
|
|
20
|
+
return { type: 'file', isBinary: false, note: 'Content hidden (sensitive file)' };
|
|
21
|
+
}
|
|
22
|
+
// Symlinks are never followed. A link whose name looks like markdown must not
|
|
23
|
+
// become a read primitive for files outside the workspace.
|
|
24
|
+
if (entry.isSymlink) {
|
|
25
|
+
return { type: 'file', isBinary: false, note: 'Symlink (not followed)' };
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
switch (contentKindFor(entry)) {
|
|
29
|
+
case 'markdown': {
|
|
30
|
+
const { text } = (0, text_1.readFileText)(entry.absolutePath, 2 * 1024 * 1024);
|
|
31
|
+
const { frontmatter, body } = (0, markdown_1.splitFrontmatter)(text);
|
|
32
|
+
const baseDir = entry.path.includes('/') ? entry.path.slice(0, entry.path.lastIndexOf('/')) : '';
|
|
33
|
+
const html = (0, markdown_1.renderMarkdown)(body, (src) => resolveImage(src, baseDir, ctx));
|
|
34
|
+
return { type: 'markdown', html, frontmatter };
|
|
35
|
+
}
|
|
36
|
+
case 'diff': {
|
|
37
|
+
const { text } = (0, text_1.readFileText)(entry.absolutePath, 2 * 1024 * 1024);
|
|
38
|
+
return (0, diff_1.parseDiff)(text);
|
|
39
|
+
}
|
|
40
|
+
case 'json':
|
|
41
|
+
return (0, json_1.parseJson)(entry.absolutePath);
|
|
42
|
+
case 'log':
|
|
43
|
+
return (0, log_1.parseLog)(entry.absolutePath, mode === 'full');
|
|
44
|
+
case 'code':
|
|
45
|
+
return (0, code_1.parseCode)(entry.absolutePath, entry.ext);
|
|
46
|
+
case 'image':
|
|
47
|
+
return { type: 'image', url: ctx.fileUrl(entry.path) };
|
|
48
|
+
case 'file':
|
|
49
|
+
default:
|
|
50
|
+
return renderFile(entry);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
return renderFileFallback(entry, `Could not render this file as ${contentKindFor(entry)} — showing raw text instead.`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function resolveImage(src, baseDir, ctx) {
|
|
58
|
+
// Ignore query/hash and URL-encoded spaces, then resolve relative to the
|
|
59
|
+
// markdown file's directory.
|
|
60
|
+
const clean = decodeURIComponent(src.split('#')[0].split('?')[0]).trim();
|
|
61
|
+
const rel = baseDir ? (0, path_1.normalizeRel)(`${baseDir}/${clean}`) : (0, path_1.normalizeRel)(clean);
|
|
62
|
+
if (!rel)
|
|
63
|
+
return undefined;
|
|
64
|
+
if (!ctx.knownImages.has(rel))
|
|
65
|
+
return undefined;
|
|
66
|
+
return ctx.fileUrl(rel);
|
|
67
|
+
}
|
|
68
|
+
function renderFile(entry) {
|
|
69
|
+
if (entry.isSymlink) {
|
|
70
|
+
return { type: 'file', isBinary: false, note: 'Symlink (not followed)' };
|
|
71
|
+
}
|
|
72
|
+
if (entry.kind === 'binary') {
|
|
73
|
+
return { type: 'file', isBinary: true };
|
|
74
|
+
}
|
|
75
|
+
// Unknown extension: inspect the first chunk for a binary signature.
|
|
76
|
+
const head = readBytes(entry.absolutePath, 8192);
|
|
77
|
+
if (hasNullByte(head)) {
|
|
78
|
+
return { type: 'file', isBinary: true };
|
|
79
|
+
}
|
|
80
|
+
const { text, truncated } = (0, text_1.readFileText)(entry.absolutePath, 64 * 1024);
|
|
81
|
+
return { type: 'file', isBinary: false, text, truncated };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Last-resort rendering. An artifact page must never fail because a file was
|
|
85
|
+
* stranger than expected — a malformed patch, a truncated image header, an
|
|
86
|
+
* encoding surprise. Better a plain text view with a note than an error.
|
|
87
|
+
*/
|
|
88
|
+
function renderFileFallback(entry, reason) {
|
|
89
|
+
const { text, truncated } = (0, text_1.readFileText)(entry.absolutePath, 64 * 1024);
|
|
90
|
+
if (hasNullByte(Buffer.from(text.slice(0, 8192), 'utf8'))) {
|
|
91
|
+
return { type: 'file', isBinary: true, note: reason };
|
|
92
|
+
}
|
|
93
|
+
return { type: 'file', isBinary: false, text, truncated, note: reason };
|
|
94
|
+
}
|
|
95
|
+
function readBytes(path, max) {
|
|
96
|
+
const buf = Buffer.alloc(max);
|
|
97
|
+
let fd;
|
|
98
|
+
try {
|
|
99
|
+
fd = (0, safeRead_1.openNoFollow)(path);
|
|
100
|
+
const n = (0, node_fs_1.readSync)(fd, buf, 0, max, 0);
|
|
101
|
+
return buf.subarray(0, n);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return Buffer.alloc(0);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
if (fd !== undefined)
|
|
108
|
+
(0, node_fs_1.closeSync)(fd);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function hasNullByte(buf) {
|
|
112
|
+
return buf.includes(0);
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/renderer/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ContentKind, FileKind } from '../types';
|
|
2
|
+
export declare function extensionOf(name: string): string;
|
|
3
|
+
export interface Classification {
|
|
4
|
+
kind: FileKind;
|
|
5
|
+
language?: string;
|
|
6
|
+
sensitive: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function classifyFile(name: string): Classification;
|
|
9
|
+
/** True for content we treat as image previews. */
|
|
10
|
+
export declare function isImageExt(ext: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Maps the scanner's broad file kind onto the way the content should be drawn.
|
|
13
|
+
* Everything the renderer has no special handling for degrades to "file", which
|
|
14
|
+
* is the safe default (hex/text preview, or a binary notice).
|
|
15
|
+
*/
|
|
16
|
+
export declare function contentKindOf(kind: FileKind): ContentKind;
|
|
17
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/scanner/classify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAqEtD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuBzD;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,CAUzD"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extensionOf = extensionOf;
|
|
4
|
+
exports.classifyFile = classifyFile;
|
|
5
|
+
exports.isImageExt = isImageExt;
|
|
6
|
+
exports.contentKindOf = contentKindOf;
|
|
7
|
+
// Extension-based classification. Deterministic and convention-driven; the
|
|
8
|
+
// semantic IR layer adds meaning on top of these broad categories.
|
|
9
|
+
const MARKDOWN_EXTS = new Set([
|
|
10
|
+
'md', 'markdown', 'mdown', 'mkd', 'mkdn', 'mdx', 'rst',
|
|
11
|
+
]);
|
|
12
|
+
const CODE_EXTS = new Set([
|
|
13
|
+
'ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs',
|
|
14
|
+
'py', 'go', 'rs', 'java', 'c', 'cc', 'cpp', 'cxx', 'h', 'hh', 'hpp',
|
|
15
|
+
'cs', 'rb', 'php', 'swift', 'kt', 'kts', 'scala', 'dart', 'lua',
|
|
16
|
+
'sh', 'bash', 'zsh', 'fish', 'ps1', 'bat', 'cmd',
|
|
17
|
+
'sql', 'graphql', 'gql',
|
|
18
|
+
'html', 'htm', 'css', 'scss', 'sass', 'less', 'styl',
|
|
19
|
+
'vue', 'svelte', 'astro',
|
|
20
|
+
'yaml', 'yml', 'toml', 'xml', 'proto', 'nim',
|
|
21
|
+
'el', 'ex', 'exs', 'clj', 'cljs', 'erl', 'hrl', 'hs', 'fs', 'fsx',
|
|
22
|
+
]);
|
|
23
|
+
const JSON_EXTS = new Set(['json', 'jsonc', 'geojson', 'jsonl', 'ndjson', 'ipynb']);
|
|
24
|
+
const LOG_EXTS = new Set(['log', 'out']);
|
|
25
|
+
const DIFF_EXTS = new Set(['diff', 'patch']);
|
|
26
|
+
const IMAGE_EXTS = new Set([
|
|
27
|
+
'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif', 'tif', 'tiff',
|
|
28
|
+
]);
|
|
29
|
+
const BINARY_EXTS = new Set([
|
|
30
|
+
'pdf', 'zip', 'gz', 'tgz', 'tar', '7z', 'rar',
|
|
31
|
+
'exe', 'dll', 'so', 'dylib', 'o', 'a', 'class', 'jar', 'war', 'bin',
|
|
32
|
+
'dat', 'db', 'sqlite', 'sqlite3',
|
|
33
|
+
'woff', 'woff2', 'ttf', 'otf', 'eot',
|
|
34
|
+
'mp3', 'mp4', 'mov', 'avi', 'mkv', 'wav', 'flac', 'webm', 'wasm',
|
|
35
|
+
'pyc', 'dmg', 'iso', 'docx', 'xlsx', 'pptx', 'doc', 'xls', 'ppt',
|
|
36
|
+
]);
|
|
37
|
+
const LANGUAGE_BY_EXT = {
|
|
38
|
+
ts: 'TypeScript', tsx: 'TSX', js: 'JavaScript', jsx: 'JSX', mjs: 'JavaScript', cjs: 'JavaScript',
|
|
39
|
+
py: 'Python', go: 'Go', rs: 'Rust', java: 'Java',
|
|
40
|
+
c: 'C', cc: 'C++', cpp: 'C++', cxx: 'C++', h: 'C', hh: 'C++', hpp: 'C++',
|
|
41
|
+
cs: 'C#', rb: 'Ruby', php: 'PHP', swift: 'Swift', kt: 'Kotlin', kts: 'Kotlin',
|
|
42
|
+
scala: 'Scala', dart: 'Dart', lua: 'Lua',
|
|
43
|
+
sh: 'Shell', bash: 'Shell', zsh: 'Shell', fish: 'Shell', ps1: 'PowerShell', bat: 'Batch', cmd: 'Batch',
|
|
44
|
+
sql: 'SQL', graphql: 'GraphQL', gql: 'GraphQL',
|
|
45
|
+
html: 'HTML', htm: 'HTML', css: 'CSS', scss: 'SCSS', sass: 'Sass', less: 'Less', styl: 'Stylus',
|
|
46
|
+
vue: 'Vue', svelte: 'Svelte', astro: 'Astro',
|
|
47
|
+
yaml: 'YAML', yml: 'YAML', toml: 'TOML', xml: 'XML', proto: 'Protobuf', nim: 'Nim',
|
|
48
|
+
el: 'Elixir', ex: 'Elixir', exs: 'Elixir', clj: 'Clojure', cljs: 'ClojureScript',
|
|
49
|
+
erl: 'Erlang', hrl: 'Erlang', hs: 'Haskell', fs: 'F#', fsx: 'F#',
|
|
50
|
+
};
|
|
51
|
+
/** Filenames whose content should not be previewed (secrets / credentials). */
|
|
52
|
+
const SENSITIVE_PATTERNS = [
|
|
53
|
+
/^\.env(\..*)?$/,
|
|
54
|
+
/\.pem$/,
|
|
55
|
+
/\.key$/,
|
|
56
|
+
/\.p12$/,
|
|
57
|
+
/\.pfx$/,
|
|
58
|
+
/^id_rsa($|\.)/,
|
|
59
|
+
/^id_dsa($|\.)/,
|
|
60
|
+
/credential/i,
|
|
61
|
+
/secret/i,
|
|
62
|
+
/token/i,
|
|
63
|
+
];
|
|
64
|
+
function extensionOf(name) {
|
|
65
|
+
const dot = name.lastIndexOf('.');
|
|
66
|
+
if (dot <= 0)
|
|
67
|
+
return '';
|
|
68
|
+
return name.slice(dot + 1).toLowerCase();
|
|
69
|
+
}
|
|
70
|
+
function classifyFile(name) {
|
|
71
|
+
const base = name.toLowerCase();
|
|
72
|
+
const ext = extensionOf(base);
|
|
73
|
+
// Filename-driven overrides take precedence over extension.
|
|
74
|
+
if (base === 'readme.md' || base === 'readme.markdown' || base === 'readme') {
|
|
75
|
+
return { kind: 'markdown', language: 'Markdown', sensitive: false };
|
|
76
|
+
}
|
|
77
|
+
if (/\.(diff|patch)$/.test(base)) {
|
|
78
|
+
return { kind: 'diff', sensitive: false };
|
|
79
|
+
}
|
|
80
|
+
const sensitive = SENSITIVE_PATTERNS.some((re) => re.test(base));
|
|
81
|
+
if (MARKDOWN_EXTS.has(ext))
|
|
82
|
+
return { kind: 'markdown', language: 'Markdown', sensitive };
|
|
83
|
+
if (DIFF_EXTS.has(ext))
|
|
84
|
+
return { kind: 'diff', sensitive };
|
|
85
|
+
if (LOG_EXTS.has(ext))
|
|
86
|
+
return { kind: 'log', sensitive };
|
|
87
|
+
if (JSON_EXTS.has(ext))
|
|
88
|
+
return { kind: 'json', language: 'JSON', sensitive };
|
|
89
|
+
if (IMAGE_EXTS.has(ext))
|
|
90
|
+
return { kind: 'image', sensitive };
|
|
91
|
+
if (BINARY_EXTS.has(ext))
|
|
92
|
+
return { kind: 'binary', sensitive };
|
|
93
|
+
if (CODE_EXTS.has(ext))
|
|
94
|
+
return { kind: 'code', language: LANGUAGE_BY_EXT[ext], sensitive };
|
|
95
|
+
return { kind: 'other', sensitive };
|
|
96
|
+
}
|
|
97
|
+
/** True for content we treat as image previews. */
|
|
98
|
+
function isImageExt(ext) {
|
|
99
|
+
return IMAGE_EXTS.has(ext.toLowerCase());
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Maps the scanner's broad file kind onto the way the content should be drawn.
|
|
103
|
+
* Everything the renderer has no special handling for degrades to "file", which
|
|
104
|
+
* is the safe default (hex/text preview, or a binary notice).
|
|
105
|
+
*/
|
|
106
|
+
function contentKindOf(kind) {
|
|
107
|
+
switch (kind) {
|
|
108
|
+
case 'markdown': return 'markdown';
|
|
109
|
+
case 'diff': return 'diff';
|
|
110
|
+
case 'json': return 'json';
|
|
111
|
+
case 'log': return 'log';
|
|
112
|
+
case 'image': return 'image';
|
|
113
|
+
case 'code': return 'code';
|
|
114
|
+
default: return 'file';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/scanner/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/scanner/git.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAmBxC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAoBjD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readGitInfo = readGitInfo;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
// Git metadata is read-only and best-effort. If git is unavailable or the
|
|
8
|
+
// directory is not a repository, we degrade to `{ isRepo: false }` silently.
|
|
9
|
+
function tryGit(root, args) {
|
|
10
|
+
try {
|
|
11
|
+
const out = (0, node_child_process_1.execFileSync)('git', args, {
|
|
12
|
+
cwd: root,
|
|
13
|
+
encoding: 'utf8',
|
|
14
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
15
|
+
timeout: 3000,
|
|
16
|
+
});
|
|
17
|
+
return out.trim();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function readGitInfo(root) {
|
|
24
|
+
if (!(0, node_fs_1.existsSync)((0, node_path_1.join)(root, '.git'))) {
|
|
25
|
+
return { isRepo: false };
|
|
26
|
+
}
|
|
27
|
+
const branch = tryGit(root, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
28
|
+
const hash = tryGit(root, ['rev-parse', '--short', 'HEAD']);
|
|
29
|
+
const subject = tryGit(root, ['log', '-1', '--pretty=%s']);
|
|
30
|
+
const date = tryGit(root, ['log', '-1', '--pretty=%ct']);
|
|
31
|
+
const info = { isRepo: true };
|
|
32
|
+
if (branch && branch !== 'HEAD')
|
|
33
|
+
info.branch = branch;
|
|
34
|
+
if (hash) {
|
|
35
|
+
info.lastCommit = {
|
|
36
|
+
hash,
|
|
37
|
+
dateMs: date ? Number(date) * 1000 : 0,
|
|
38
|
+
subject: subject ?? '',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return info;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/scanner/git.ts"],"names":[],"mappings":";;AAsBA,kCAoBC;AA1CD,2DAAkD;AAClD,qCAAqC;AACrC,yCAAiC;AAGjC,0EAA0E;AAC1E,6EAA6E;AAE7E,SAAS,MAAM,CAAC,IAAY,EAAE,IAAc;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,iCAAY,EAAC,KAAK,EAAE,IAAI,EAAE;YACpC,GAAG,EAAE,IAAI;YACT,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;YACnC,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QACpC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACvC,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM;QAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtD,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,UAAU,GAAG;YAChB,IAAI;YACJ,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACtC,OAAO,EAAE,OAAO,IAAI,EAAE;SACvB,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface IgnoreRule {
|
|
2
|
+
reason: string;
|
|
3
|
+
}
|
|
4
|
+
export declare function shouldIgnoreDir(name: string): {
|
|
5
|
+
ignore: boolean;
|
|
6
|
+
reason?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function shouldIgnoreFile(name: string): {
|
|
9
|
+
ignore: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
};
|
|
12
|
+
/** Files larger than this are ignored entirely. */
|
|
13
|
+
export declare const MAX_FILE_BYTES: number;
|
|
14
|
+
/** Text files larger than this are truncated when previewed. */
|
|
15
|
+
export declare const MAX_TEXT_BYTES: number;
|
|
16
|
+
/** Safety cap on the total number of scanned files. */
|
|
17
|
+
export declare const MAX_TOTAL_FILES = 20000;
|
|
18
|
+
/** Safety cap on entries within a single directory. */
|
|
19
|
+
export declare const MAX_DIR_ENTRIES = 2000;
|
|
20
|
+
/** Maximum number of lines we will tail from a log for the preview. */
|
|
21
|
+
export declare const LOG_TAIL_LINES = 200;
|
|
22
|
+
//# sourceMappingURL=ignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/scanner/ignore.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAyBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAKlF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAQnF;AAMD,mDAAmD;AACnD,eAAO,MAAM,cAAc,QAAmB,CAAC;AAE/C,gEAAgE;AAChE,eAAO,MAAM,cAAc,QAAa,CAAC;AAEzC,uDAAuD;AACvD,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,uDAAuD;AACvD,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,uEAAuE;AACvE,eAAO,MAAM,cAAc,MAAM,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Ignore rules for directories and files that are clearly not worth scanning.
|
|
3
|
+
// Kept as a single table so future configuration has one obvious seam.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.LOG_TAIL_LINES = exports.MAX_DIR_ENTRIES = exports.MAX_TOTAL_FILES = exports.MAX_TEXT_BYTES = exports.MAX_FILE_BYTES = void 0;
|
|
6
|
+
exports.shouldIgnoreDir = shouldIgnoreDir;
|
|
7
|
+
exports.shouldIgnoreFile = shouldIgnoreFile;
|
|
8
|
+
const IGNORED_DIRS = new Set([
|
|
9
|
+
'.git', '.hg', '.svn',
|
|
10
|
+
'node_modules', 'bower_components',
|
|
11
|
+
'.cache', '.parcel-cache', '.next', '.nuxt', '.turbo', '.svelte-kit',
|
|
12
|
+
'dist', 'build', 'out', 'target', '.output',
|
|
13
|
+
'coverage', '.nyc_output',
|
|
14
|
+
'__pycache__', '.pytest_cache', '.mypy_cache', '.ruff_cache', '.tox',
|
|
15
|
+
'.venv', 'venv', '.virtualenv',
|
|
16
|
+
'.yarn', '.pnpm-store',
|
|
17
|
+
'vendor',
|
|
18
|
+
'.idea', '.vscode', '.fleet',
|
|
19
|
+
// A2H protocol directory: it is read as semantics, never shown as content.
|
|
20
|
+
'.a2h',
|
|
21
|
+
]);
|
|
22
|
+
const IGNORED_FILE_NAMES = new Set([
|
|
23
|
+
'.DS_Store', 'Thumbs.db', 'desktop.ini',
|
|
24
|
+
'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb',
|
|
25
|
+
'Cargo.lock', 'Pipfile.lock', 'poetry.lock', 'go.sum',
|
|
26
|
+
// Reserved protocol name — consumed as the manifest, not rendered as data.
|
|
27
|
+
'a2h.json',
|
|
28
|
+
]);
|
|
29
|
+
function shouldIgnoreDir(name) {
|
|
30
|
+
if (IGNORED_DIRS.has(name)) {
|
|
31
|
+
return { ignore: true, reason: 'ignored directory' };
|
|
32
|
+
}
|
|
33
|
+
return { ignore: false };
|
|
34
|
+
}
|
|
35
|
+
function shouldIgnoreFile(name) {
|
|
36
|
+
if (IGNORED_FILE_NAMES.has(name)) {
|
|
37
|
+
return { ignore: true, reason: 'lockfile / os metadata' };
|
|
38
|
+
}
|
|
39
|
+
if (name.endsWith('~') || name.endsWith('.swp') || name.endsWith('.swo')) {
|
|
40
|
+
return { ignore: true, reason: 'editor temp file' };
|
|
41
|
+
}
|
|
42
|
+
return { ignore: false };
|
|
43
|
+
}
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Size / count guards
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
/** Files larger than this are ignored entirely. */
|
|
48
|
+
exports.MAX_FILE_BYTES = 20 * 1024 * 1024;
|
|
49
|
+
/** Text files larger than this are truncated when previewed. */
|
|
50
|
+
exports.MAX_TEXT_BYTES = 512 * 1024;
|
|
51
|
+
/** Safety cap on the total number of scanned files. */
|
|
52
|
+
exports.MAX_TOTAL_FILES = 20000;
|
|
53
|
+
/** Safety cap on entries within a single directory. */
|
|
54
|
+
exports.MAX_DIR_ENTRIES = 2000;
|
|
55
|
+
/** Maximum number of lines we will tail from a log for the preview. */
|
|
56
|
+
exports.LOG_TAIL_LINES = 200;
|
|
57
|
+
//# sourceMappingURL=ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/scanner/ignore.ts"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,uEAAuE;;;AA6BvE,0CAKC;AAED,4CAQC;AAtCD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,MAAM,EAAE,KAAK,EAAE,MAAM;IACrB,cAAc,EAAE,kBAAkB;IAClC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa;IACpE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS;IAC3C,UAAU,EAAE,aAAa;IACzB,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM;IACpE,OAAO,EAAE,MAAM,EAAE,aAAa;IAC9B,OAAO,EAAE,aAAa;IACtB,QAAQ;IACR,OAAO,EAAE,SAAS,EAAE,QAAQ;IAC5B,2EAA2E;IAC3E,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,WAAW,EAAE,WAAW,EAAE,aAAa;IACvC,mBAAmB,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW;IAC/D,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ;IACrD,2EAA2E;IAC3E,UAAU;CACX,CAAC,CAAC;AAEH,SAAgB,eAAe,CAAC,IAAY;IAC1C,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACvD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,mDAAmD;AACtC,QAAA,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/C,gEAAgE;AACnD,QAAA,cAAc,GAAG,GAAG,GAAG,IAAI,CAAC;AAEzC,uDAAuD;AAC1C,QAAA,eAAe,GAAG,KAAK,CAAC;AAErC,uDAAuD;AAC1C,QAAA,eAAe,GAAG,IAAI,CAAC;AAEpC,uEAAuE;AAC1D,QAAA,cAAc,GAAG,GAAG,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { relative, sep } from 'node:path';
|
|
2
|
+
import type { ScanResult } from '../types';
|
|
3
|
+
export interface ScanOptions {
|
|
4
|
+
rootDir: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function scanWorkspace(options: ScanOptions): ScanResult;
|
|
7
|
+
export { relative as relativePath, sep };
|
|
8
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/scanner/scan.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,QAAQ,EAAW,GAAG,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAA2B,UAAU,EAAE,MAAM,UAAU,CAAC;AAgBpE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAa9D;AAqGD,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sep = exports.relativePath = void 0;
|
|
4
|
+
exports.scanWorkspace = scanWorkspace;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
Object.defineProperty(exports, "relativePath", { enumerable: true, get: function () { return node_path_1.relative; } });
|
|
8
|
+
Object.defineProperty(exports, "sep", { enumerable: true, get: function () { return node_path_1.sep; } });
|
|
9
|
+
const classify_1 = require("./classify");
|
|
10
|
+
const ignore_1 = require("./ignore");
|
|
11
|
+
const git_1 = require("./git");
|
|
12
|
+
const identity_1 = require("../ir/identity");
|
|
13
|
+
const ROOT_NAME_IGNORE = new Set([
|
|
14
|
+
'.git', 'node_modules', '.hg', '.svn',
|
|
15
|
+
]);
|
|
16
|
+
function scanWorkspace(options) {
|
|
17
|
+
const rootDir = (0, node_path_1.resolve)(options.rootDir);
|
|
18
|
+
const files = [];
|
|
19
|
+
const ignored = [];
|
|
20
|
+
const warnings = [];
|
|
21
|
+
const state = { count: 0 };
|
|
22
|
+
walk(rootDir, '', files, ignored, warnings, state);
|
|
23
|
+
const identity = (0, identity_1.deriveIdentity)(rootDir, files);
|
|
24
|
+
const git = (0, git_1.readGitInfo)(rootDir);
|
|
25
|
+
return { rootDir, identity, git, files, ignored, warnings };
|
|
26
|
+
}
|
|
27
|
+
function walk(absDir, relDir, files, ignored, warnings, state) {
|
|
28
|
+
let entries;
|
|
29
|
+
try {
|
|
30
|
+
entries = (0, node_fs_1.readdirSync)(absDir, { withFileTypes: true });
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
warnings.push(`could not read directory ${relDir || '.'}: ${err.message}`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (entries.length > ignore_1.MAX_DIR_ENTRIES) {
|
|
37
|
+
warnings.push(`directory ${relDir || '.'} has ${entries.length} entries; only first ${ignore_1.MAX_DIR_ENTRIES} scanned`);
|
|
38
|
+
entries = entries.slice(0, ignore_1.MAX_DIR_ENTRIES);
|
|
39
|
+
}
|
|
40
|
+
for (const dirent of entries) {
|
|
41
|
+
if (state.count >= ignore_1.MAX_TOTAL_FILES) {
|
|
42
|
+
warnings.push(`stopped scanning after ${ignore_1.MAX_TOTAL_FILES} files`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const name = dirent.name;
|
|
46
|
+
const relPath = relDir ? `${relDir}/${name}` : name;
|
|
47
|
+
if (dirent.isDirectory()) {
|
|
48
|
+
if (ROOT_NAME_IGNORE.has(name)) {
|
|
49
|
+
ignored.push({ path: relPath, reason: 'ignored directory' });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const dirCheck = (0, ignore_1.shouldIgnoreDir)(name);
|
|
53
|
+
if (dirCheck.ignore) {
|
|
54
|
+
ignored.push({ path: relPath, reason: dirCheck.reason ?? 'ignored directory' });
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
walk((0, node_path_1.join)(absDir, name), relPath, files, ignored, warnings, state);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// Non-directory (file, symlink, socket, etc.).
|
|
61
|
+
const fileCheck = (0, ignore_1.shouldIgnoreFile)(name);
|
|
62
|
+
if (fileCheck.ignore) {
|
|
63
|
+
ignored.push({ path: relPath, reason: fileCheck.reason ?? 'ignored file' });
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const absPath = (0, node_path_1.join)(absDir, name);
|
|
67
|
+
let st;
|
|
68
|
+
try {
|
|
69
|
+
st = (0, node_fs_1.lstatSync)(absPath);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
warnings.push(`could not stat ${relPath}`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const isSymlink = st.isSymbolicLink();
|
|
76
|
+
if (!isSymlink && !st.isFile()) {
|
|
77
|
+
continue; // sockets, fifos, devices — skip silently.
|
|
78
|
+
}
|
|
79
|
+
// Resolve size / mtime (for symlinks, stat the link itself; we do not follow).
|
|
80
|
+
const size = st.size;
|
|
81
|
+
const mtimeMs = st.mtimeMs;
|
|
82
|
+
if (size > ignore_1.MAX_FILE_BYTES) {
|
|
83
|
+
ignored.push({ path: relPath, reason: 'too large' });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const { kind, language, sensitive } = (0, classify_1.classifyFile)(name);
|
|
87
|
+
const ext = extensionLower(name);
|
|
88
|
+
files.push({
|
|
89
|
+
path: relPath,
|
|
90
|
+
absolutePath: absPath,
|
|
91
|
+
kind,
|
|
92
|
+
size,
|
|
93
|
+
mtimeMs,
|
|
94
|
+
ext,
|
|
95
|
+
isSymlink,
|
|
96
|
+
sensitive,
|
|
97
|
+
depth: relDir.split('/').length,
|
|
98
|
+
});
|
|
99
|
+
state.count += 1;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function extensionLower(name) {
|
|
103
|
+
const dot = name.lastIndexOf('.');
|
|
104
|
+
if (dot <= 0)
|
|
105
|
+
return '';
|
|
106
|
+
return name.slice(dot + 1).toLowerCase();
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/scanner/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function isWithin(root: string, target: string): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a workspace-relative POSIX path to an absolute path strictly
|
|
4
|
+
* inside the workspace root. Returns null on traversal attempts.
|
|
5
|
+
*
|
|
6
|
+
* This is a lexical check: it refuses `..`, but says nothing about symlinks.
|
|
7
|
+
* Use `resolveRealPath` when the answer must survive a link in the tree.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveRelPath(root: string, rel: string): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Like resolveRelPath, but also resolves symlinks and verifies the *real* path
|
|
12
|
+
* stays inside the workspace. This is the check that catches an intermediate
|
|
13
|
+
* directory which is a link out of the tree — `leak -> /etc` makes
|
|
14
|
+
* `leak/passwd` lexical, but never contained.
|
|
15
|
+
*
|
|
16
|
+
* Returns the lexical absolute path (stable, knows no symlinks) on success.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveRealPath(root: string, rel: string): string | null;
|
|
19
|
+
//# sourceMappingURL=boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/security/boundary.ts"],"names":[],"mappings":"AAWA,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMvE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWxE"}
|