@shidesheng0218/dsh-plugin-lint 0.1.0 → 0.4.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/NOTICE +1 -1
- package/README.md +515 -81
- package/bin/dsh-plugin-analyze.mjs +378 -0
- package/bin/dsh-plugin-lint.mjs +315 -27
- package/bin/dsh-plugin-matrix.mjs +78 -0
- package/bin/dsh-plugin-upgrade-plan.mjs +180 -0
- package/package.json +12 -4
- package/schema/dsh-manifest.schema.json +134 -0
- package/scripts/lib/probe.mjs +28 -385
- package/scripts/probe-boot.mjs +103 -37
- package/src/composition.js +1 -0
- package/src/core/baseline.js +98 -0
- package/src/core/changed.js +41 -0
- package/src/core/load.js +145 -0
- package/src/core/mask.js +207 -0
- package/src/core/pack.js +95 -0
- package/src/core/packlist.js +186 -0
- package/src/core/peer.js +39 -0
- package/src/core/profile-scan.js +121 -0
- package/src/core/report.js +174 -0
- package/src/core/rules.js +581 -0
- package/src/core/semver.js +192 -0
- package/src/core/tarball.js +90 -0
- package/src/data/event-types.json +111 -9
- package/src/experimental/conflicts.js +315 -0
- package/src/experimental/index.js +4 -0
- package/src/experimental/performance.js +515 -0
- package/src/experimental/security.js +462 -0
- package/src/index.js +15 -17
- package/src/load.js +1 -116
- package/src/mask.js +1 -156
- package/src/matrix/cache.js +19 -0
- package/src/matrix/cell.js +79 -0
- package/src/matrix/cells.js +58 -0
- package/src/matrix/conflicts.js +210 -0
- package/src/matrix/export.js +155 -0
- package/src/matrix/index.js +71 -0
- package/src/matrix/manifest.js +17 -0
- package/src/matrix/migrate.js +41 -0
- package/src/matrix/run.js +241 -0
- package/src/matrix/sanitize.js +42 -0
- package/src/matrix/schema.js +178 -0
- package/src/matrix/site.js +61 -0
- package/src/matrix/sync.js +72 -0
- package/src/matrix/verify.js +152 -0
- package/src/performance.js +1 -0
- package/src/probe/artifact-resolver.js +161 -0
- package/src/probe/classify.js +8 -0
- package/src/probe/dsh-adapter.js +212 -0
- package/src/probe/environment/docker.js +270 -0
- package/src/probe/environment/host-unsafe.js +39 -0
- package/src/probe/environment/materialize.js +22 -0
- package/src/probe/environment.js +50 -0
- package/src/probe/installed-artifact.js +17 -0
- package/src/probe/probe.js +278 -0
- package/src/report.js +1 -79
- package/src/rules.js +1 -379
- package/src/security.js +1 -0
- package/src/shared/errors.js +7 -0
- package/src/shared/hash.js +31 -0
- package/src/shared/status.js +12 -0
- package/src/shared/validate.js +14 -0
- package/src/shared/version.js +4 -0
- package/src/upgrade/compatibility.js +14 -0
- package/src/upgrade/planner.js +119 -0
- package/src/upgrade/profile.js +82 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
function readJson(path) {
|
|
5
|
+
return JSON.parse(readFileSync(path, 'utf8'));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function isDirectory(path) {
|
|
9
|
+
try { return statSync(path).isDirectory(); } catch { return false; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function exactVersion(value) {
|
|
13
|
+
return typeof value === 'string' && /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value) ? value : undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function installedVersion(profileDir, name, entry, profileManifest) {
|
|
17
|
+
if (entry && typeof entry === 'object' && exactVersion(entry.version)) return entry.version;
|
|
18
|
+
const manifestPath = join(profileDir, 'node_modules', ...name.split('/'), 'package.json');
|
|
19
|
+
if (existsSync(manifestPath)) {
|
|
20
|
+
try {
|
|
21
|
+
const manifest = readJson(manifestPath);
|
|
22
|
+
if (exactVersion(manifest.version)) return manifest.version;
|
|
23
|
+
} catch { /* use the profile declaration below */ }
|
|
24
|
+
}
|
|
25
|
+
return exactVersion({ ...(profileManifest?.dependencies || {}), ...(profileManifest?.devDependencies || {}) }[name]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function readProfile(profileDir) {
|
|
29
|
+
if (!existsSync(profileDir) || !isDirectory(profileDir)) throw new Error('profile directory not found: ' + profileDir);
|
|
30
|
+
const manifestPath = join(profileDir, 'package.json');
|
|
31
|
+
const manifest = existsSync(manifestPath) ? readJson(manifestPath) : undefined;
|
|
32
|
+
const declared = manifest?.dsh?.profile?.bundles;
|
|
33
|
+
const composition = ['headless', 'web'].includes(manifest?.dsh?.profile?.composition) ? manifest.dsh.profile.composition : undefined;
|
|
34
|
+
const plugins = [];
|
|
35
|
+
const seen = new Set();
|
|
36
|
+
if (Array.isArray(declared) && declared.length > 0) {
|
|
37
|
+
for (const entry of declared) {
|
|
38
|
+
const name = typeof entry === 'string'
|
|
39
|
+
? entry.trim()
|
|
40
|
+
: entry && typeof entry === 'object'
|
|
41
|
+
? entry.name || entry.id || entry.package || entry.bundle || entry.plugin
|
|
42
|
+
: undefined;
|
|
43
|
+
if (typeof name !== 'string' || !name || seen.has(name)) continue;
|
|
44
|
+
seen.add(name);
|
|
45
|
+
plugins.push({ name, version: installedVersion(profileDir, name, entry, manifest), firstParty: name.startsWith('@deepseek-ai/'), source: 'dsh.profile.bundles' });
|
|
46
|
+
}
|
|
47
|
+
return { path: profileDir, manifest, plugins, source: 'dsh.profile.bundles', composition };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const nodeModulesDir = join(profileDir, 'node_modules');
|
|
51
|
+
if (manifest === undefined && (!existsSync(nodeModulesDir) || !isDirectory(nodeModulesDir))) {
|
|
52
|
+
throw new Error('not a profile directory (no package.json and no node_modules): ' + profileDir);
|
|
53
|
+
}
|
|
54
|
+
if (!existsSync(nodeModulesDir) || !isDirectory(nodeModulesDir)) {
|
|
55
|
+
return { path: profileDir, manifest, plugins: [], source: 'none', composition };
|
|
56
|
+
}
|
|
57
|
+
const consider = (dir, fallbackName) => {
|
|
58
|
+
const manifestFile = join(dir, 'package.json');
|
|
59
|
+
if (!existsSync(manifestFile)) return;
|
|
60
|
+
let pkg;
|
|
61
|
+
try { pkg = readJson(manifestFile); } catch { return; }
|
|
62
|
+
if (!pkg.dsh && !(Array.isArray(pkg.keywords) && pkg.keywords.includes('dsh-plugin'))) return;
|
|
63
|
+
const name = typeof pkg.name === 'string' && pkg.name ? pkg.name : fallbackName;
|
|
64
|
+
if (seen.has(name)) return;
|
|
65
|
+
seen.add(name);
|
|
66
|
+
plugins.push({ name, version: exactVersion(pkg.version), firstParty: name.startsWith('@deepseek-ai/'), source: 'node_modules' });
|
|
67
|
+
};
|
|
68
|
+
for (const entry of readdirSync(nodeModulesDir, { withFileTypes: true })) {
|
|
69
|
+
if (entry.name.startsWith('.')) continue;
|
|
70
|
+
const entryPath = join(nodeModulesDir, entry.name);
|
|
71
|
+
if (!(entry.isDirectory() || (entry.isSymbolicLink() && isDirectory(entryPath)))) continue;
|
|
72
|
+
if (entry.name.startsWith('@')) {
|
|
73
|
+
for (const child of readdirSync(entryPath, { withFileTypes: true })) {
|
|
74
|
+
const childPath = join(entryPath, child.name);
|
|
75
|
+
if (child.isDirectory() || (child.isSymbolicLink() && isDirectory(childPath))) consider(childPath, entry.name + '/' + child.name);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
consider(entryPath, entry.name);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { path: profileDir, manifest, plugins, source: 'node_modules', composition };
|
|
82
|
+
}
|