@happyvertical/smrt-scanner 0.40.61 → 0.40.63
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/AGENTS.md +27 -0
- package/dist/chunks/{scanner-DEGZfoLz.js → scanner-LeMvLJ6X.js} +73 -11
- package/dist/chunks/scanner-LeMvLJ6X.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +63 -1
- package/dist/index.js +3 -3
- package/dist/types.d.ts +10 -0
- package/package.json +1 -1
- package/dist/chunks/scanner-DEGZfoLz.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -22,11 +22,37 @@ executes the source.
|
|
|
22
22
|
and asserts every `@smrt()` object reached `dist/manifest.json` (issue #1483).
|
|
23
23
|
Returns `ok` / `incomplete` / `missing-manifest` / `scan-error` / `skipped`.
|
|
24
24
|
Driven by `scripts/verify-manifest-completeness.mjs` from `prepack`.
|
|
25
|
+
- `discoverSourceFiles(options)` — shared bounded source-discovery policy used
|
|
26
|
+
by `OxcScanner` and the core manifest preflight.
|
|
25
27
|
- Types (re-exported from `./types`): `RawClassDefinition`,
|
|
26
28
|
`RawFieldDefinition`, `RawMethodDefinition`, `ResolvedClassDefinition`,
|
|
27
29
|
`ScanResults`, `FileScanResult`, `OxcScannerOptions`, `InferredFieldType`,
|
|
28
30
|
`FieldTypeInference`.
|
|
29
31
|
|
|
32
|
+
## Discovery boundaries
|
|
33
|
+
|
|
34
|
+
File discovery is the difference between a scan that finishes and one that
|
|
35
|
+
exhausts the heap when the scanner is pointed at an application root (#2275):
|
|
36
|
+
|
|
37
|
+
- `dot: true` is set so ignore patterns apply beneath dot directories. Without
|
|
38
|
+
it a `**` cannot cross a dot segment, so `**/node_modules/**` pruned the root
|
|
39
|
+
`node_modules` but nothing under `.svelte-kit/`, `.vercel/`, or `.turbo/`.
|
|
40
|
+
- Mandatory excludes (`**/node_modules/**`, `**/.*/**`, `**/.*`) are unioned
|
|
41
|
+
with the caller's `exclude` and cannot be overridden. `exclude` REPLACES the
|
|
42
|
+
defaults, so every caller that narrowed it had silently reopened
|
|
43
|
+
`node_modules`.
|
|
44
|
+
- `followSymbolicLinks` defaults to `false`. A pnpm `node_modules` is a symlink
|
|
45
|
+
graph with cycles, not a tree, so a link-following walk reaches the same real
|
|
46
|
+
directory once per path leading to it. This drops symlinked *files* as well as
|
|
47
|
+
directories, so pass `followSymbolicLinks: true` for a project that genuinely
|
|
48
|
+
keeps sources behind a link — it is threaded through `smrtPlugin` and
|
|
49
|
+
`ManifestBuilderOptions` for the build path.
|
|
50
|
+
- Patterns are rewritten relative to `cwd` before globbing. Globs match as text,
|
|
51
|
+
so an absolute pattern would hand `**/.*/**` the project's own ancestors and a
|
|
52
|
+
checkout under `~/.worktrees` or `~/.cache` would match nothing at all.
|
|
53
|
+
- `dot: true` would otherwise widen the result to hidden files, so `**/.*` is in
|
|
54
|
+
the mandatory prunes too: hidden files stay out, exactly as before.
|
|
55
|
+
|
|
30
56
|
## How It Works
|
|
31
57
|
|
|
32
58
|
1. `fast-glob` finds `.ts` files matching include/exclude patterns.
|
|
@@ -43,6 +69,7 @@ executes the source.
|
|
|
43
69
|
`parseSource`, `extractSmrtImports`, field/decorator/type extractors).
|
|
44
70
|
- `src/scanner.ts` — `OxcScanner`: globbing + multi-file orchestration
|
|
45
71
|
(`scan` / `scanAndResolve`).
|
|
72
|
+
- `src/discovery.ts` — shared bounded glob policy for every scanner entry point.
|
|
46
73
|
- `src/inheritance-resolver.ts` — `InheritanceResolver`: cross-file inheritance
|
|
47
74
|
merging.
|
|
48
75
|
- `src/manifest-adapter.ts` — `ManifestAdapter`: raw → manifest conversion and
|
|
@@ -1,7 +1,49 @@
|
|
|
1
|
+
import { isAbsolute, resolve, sep, win32 } from "node:path";
|
|
2
|
+
import fg from "fast-glob";
|
|
1
3
|
import { readFileSync } from "node:fs";
|
|
2
4
|
import { parseSync } from "oxc-parser";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
//#region src/discovery.ts
|
|
6
|
+
var MANDATORY_DISCOVERY_EXCLUDES = Object.freeze([
|
|
7
|
+
"**/node_modules/**",
|
|
8
|
+
"**/.*/**",
|
|
9
|
+
"**/.*"
|
|
10
|
+
]);
|
|
11
|
+
async function discoverSourceFiles(options) {
|
|
12
|
+
const cwd = resolve(options.cwd);
|
|
13
|
+
return fg(options.include.map((pattern) => relativeGlobToCwd(pattern, cwd)), {
|
|
14
|
+
cwd,
|
|
15
|
+
ignore: [...options.exclude.map((pattern) => relativeGlobToCwd(pattern, cwd)), ...MANDATORY_DISCOVERY_EXCLUDES],
|
|
16
|
+
absolute: true,
|
|
17
|
+
onlyFiles: true,
|
|
18
|
+
dot: true,
|
|
19
|
+
followSymbolicLinks: options.followSymbolicLinks ?? false
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function relativeGlobToCwd(pattern, cwd) {
|
|
23
|
+
const windowsAbsolute = win32.isAbsolute(pattern);
|
|
24
|
+
if (!isAbsolute(pattern) && !windowsAbsolute) return pattern;
|
|
25
|
+
const cwdVariants = [
|
|
26
|
+
cwd,
|
|
27
|
+
cwd.replaceAll("\\", "/"),
|
|
28
|
+
cwd.replaceAll("/", "\\")
|
|
29
|
+
];
|
|
30
|
+
for (const prefix of new Set(cwdVariants)) {
|
|
31
|
+
const comparablePattern = windowsAbsolute ? pattern.toLowerCase() : pattern;
|
|
32
|
+
const comparablePrefix = windowsAbsolute ? prefix.toLowerCase() : prefix;
|
|
33
|
+
if (comparablePattern === comparablePrefix) return ".";
|
|
34
|
+
const boundary = pattern.charAt(prefix.length);
|
|
35
|
+
if (comparablePattern.startsWith(comparablePrefix) && (boundary === "/" || boundary === "\\")) {
|
|
36
|
+
const rewritten = pattern.slice(prefix.length + 1);
|
|
37
|
+
return boundary === "\\" ? normalizeGlobSeparators(rewritten, "\\") : rewritten;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const slashAuthoredWindows = /^[A-Za-z]:\//.test(pattern);
|
|
41
|
+
return windowsAbsolute && !slashAuthoredWindows ? normalizeGlobSeparators(pattern, "\\") : pattern;
|
|
42
|
+
}
|
|
43
|
+
function normalizeGlobSeparators(pattern, pathSeparator = sep) {
|
|
44
|
+
return pathSeparator === "/" ? pattern : pattern.replaceAll(pathSeparator, "/");
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
5
47
|
//#region src/inheritance-resolver.ts
|
|
6
48
|
var FRAMEWORK_BASE_CLASSES = /* @__PURE__ */ new Set([
|
|
7
49
|
"SmrtObject",
|
|
@@ -1928,7 +1970,8 @@ var OxcScanner = class {
|
|
|
1928
1970
|
baseClasses: options.baseClasses || [],
|
|
1929
1971
|
includePrivateMethods: options.includePrivateMethods ?? false,
|
|
1930
1972
|
includeStaticMethods: options.includeStaticMethods ?? true,
|
|
1931
|
-
externalManifests: options.externalManifests || /* @__PURE__ */ new Map()
|
|
1973
|
+
externalManifests: options.externalManifests || /* @__PURE__ */ new Map(),
|
|
1974
|
+
followSymbolicLinks: options.followSymbolicLinks ?? false
|
|
1932
1975
|
};
|
|
1933
1976
|
this.resolver = new InheritanceResolver({
|
|
1934
1977
|
baseClasses: this.options.baseClasses,
|
|
@@ -2085,15 +2128,34 @@ var OxcScanner = class {
|
|
|
2085
2128
|
};
|
|
2086
2129
|
}
|
|
2087
2130
|
/**
|
|
2088
|
-
* Discover files to scan using fast-glob
|
|
2131
|
+
* Discover files to scan using fast-glob.
|
|
2132
|
+
*
|
|
2133
|
+
* Two settings here decide whether discovery terminates at all when the
|
|
2134
|
+
* scanner is pointed at an application root rather than a package `src/`:
|
|
2135
|
+
*
|
|
2136
|
+
* - `dot: true`. Without it a `**` in an ignore pattern cannot cross a
|
|
2137
|
+
* dot segment, so `**\/node_modules/**` prunes `node_modules` at the root
|
|
2138
|
+
* but NOT `.svelte-kit/…/node_modules` or any other `node_modules` under a
|
|
2139
|
+
* dot directory. Those subtrees were then walked in full and every entry
|
|
2140
|
+
* discarded — unbounded work that could never produce a match.
|
|
2141
|
+
* - `followSymbolicLinks: false`. pnpm materializes `node_modules` as a
|
|
2142
|
+
* symlink graph with cycles, so a link-following walk revisits the same
|
|
2143
|
+
* real directories once per path that reaches them.
|
|
2144
|
+
*
|
|
2145
|
+
* Together they were enough to exhaust a 4 GB heap on a consumer app that
|
|
2146
|
+
* installs the published packages (#2275).
|
|
2147
|
+
*
|
|
2148
|
+
* Patterns are rewritten relative to `cwd` first. fast-glob matches `ignore`
|
|
2149
|
+
* in whatever space the patterns use, so an absolute pattern would hand
|
|
2150
|
+
* `**\/.*\/**` the project's own ancestors — a checkout under `~/.worktrees`
|
|
2151
|
+
* or `~/.cache` would then match nothing at all, silently.
|
|
2089
2152
|
*/
|
|
2090
2153
|
async discoverFiles() {
|
|
2091
|
-
|
|
2092
|
-
return await fg(patterns, {
|
|
2154
|
+
return discoverSourceFiles({
|
|
2093
2155
|
cwd: this.options.cwd,
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2156
|
+
include: this.options.include,
|
|
2157
|
+
exclude: this.options.exclude,
|
|
2158
|
+
followSymbolicLinks: this.options.followSymbolicLinks
|
|
2097
2159
|
});
|
|
2098
2160
|
}
|
|
2099
2161
|
/**
|
|
@@ -2104,6 +2166,6 @@ var OxcScanner = class {
|
|
|
2104
2166
|
}
|
|
2105
2167
|
};
|
|
2106
2168
|
//#endregion
|
|
2107
|
-
export { parseSource as a, parseFile as i, ManifestAdapter as n, InheritanceResolver as o, extractSmrtImports as r, OxcScanner as t };
|
|
2169
|
+
export { parseSource as a, normalizeGlobSeparators as c, parseFile as i, relativeGlobToCwd as l, ManifestAdapter as n, InheritanceResolver as o, extractSmrtImports as r, discoverSourceFiles as s, OxcScanner as t };
|
|
2108
2170
|
|
|
2109
|
-
//# sourceMappingURL=scanner-
|
|
2171
|
+
//# sourceMappingURL=scanner-LeMvLJ6X.js.map
|