@pleaseai/ask 0.1.0 → 0.1.3
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/dist/agents.d.ts +2 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +73 -0
- package/dist/agents.js.map +1 -0
- package/dist/concurrency.d.ts +12 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +33 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -0
- package/dist/ignore-files.d.ts +59 -0
- package/dist/ignore-files.d.ts.map +1 -0
- package/dist/ignore-files.js +205 -0
- package/dist/ignore-files.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +485 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +55 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +159 -0
- package/dist/io.js.map +1 -0
- package/dist/manifest/index.d.ts +26 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +25 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/npm.d.ts +18 -0
- package/dist/manifest/npm.d.ts.map +1 -0
- package/dist/manifest/npm.js +155 -0
- package/dist/manifest/npm.js.map +1 -0
- package/dist/markers.d.ts +34 -0
- package/dist/markers.d.ts.map +1 -0
- package/dist/markers.js +82 -0
- package/dist/markers.js.map +1 -0
- package/dist/migrate-legacy.d.ts +24 -0
- package/dist/migrate-legacy.d.ts.map +1 -0
- package/dist/migrate-legacy.js +85 -0
- package/dist/migrate-legacy.js.map +1 -0
- package/dist/registry.d.ts +71 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +201 -0
- package/dist/registry.js.map +1 -0
- package/dist/resolvers/index.d.ts +32 -0
- package/dist/resolvers/index.d.ts.map +1 -0
- package/dist/resolvers/index.js +17 -0
- package/dist/resolvers/index.js.map +1 -0
- package/dist/resolvers/maven.d.ts +33 -0
- package/dist/resolvers/maven.d.ts.map +1 -0
- package/dist/resolvers/maven.js +187 -0
- package/dist/resolvers/maven.js.map +1 -0
- package/dist/resolvers/npm.d.ts +13 -0
- package/dist/resolvers/npm.d.ts.map +1 -0
- package/dist/resolvers/npm.js +67 -0
- package/dist/resolvers/npm.js.map +1 -0
- package/dist/resolvers/pub.d.ts +13 -0
- package/dist/resolvers/pub.d.ts.map +1 -0
- package/dist/resolvers/pub.js +50 -0
- package/dist/resolvers/pub.js.map +1 -0
- package/dist/resolvers/pypi.d.ts +12 -0
- package/dist/resolvers/pypi.d.ts.map +1 -0
- package/dist/resolvers/pypi.js +60 -0
- package/dist/resolvers/pypi.js.map +1 -0
- package/dist/resolvers/utils.d.ts +15 -0
- package/dist/resolvers/utils.d.ts.map +1 -0
- package/dist/resolvers/utils.js +26 -0
- package/dist/resolvers/utils.js.map +1 -0
- package/dist/schemas.d.ts +490 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +91 -0
- package/dist/schemas.js.map +1 -0
- package/dist/skill.d.ts +4 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +53 -0
- package/dist/skill.js.map +1 -0
- package/dist/sources/github.d.ts +14 -0
- package/dist/sources/github.d.ts.map +1 -0
- package/dist/sources/github.js +114 -0
- package/dist/sources/github.js.map +1 -0
- package/dist/sources/index.d.ts +41 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +14 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/llms-txt.d.ts +5 -0
- package/dist/sources/llms-txt.d.ts.map +1 -0
- package/dist/sources/llms-txt.js +33 -0
- package/dist/sources/llms-txt.js.map +1 -0
- package/dist/sources/npm.d.ts +14 -0
- package/dist/sources/npm.d.ts.map +1 -0
- package/dist/sources/npm.js +113 -0
- package/dist/sources/npm.js.map +1 -0
- package/dist/sources/web.d.ts +13 -0
- package/dist/sources/web.d.ts.map +1 -0
- package/dist/sources/web.js +143 -0
- package/dist/sources/web.js.map +1 -0
- package/dist/storage.d.ts +11 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +76 -0
- package/dist/storage.js.map +1 -0
- package/package.json +9 -8
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { consola } from 'consola';
|
|
6
|
+
const RE_LEADING_V = /^v/;
|
|
7
|
+
const RE_SHA40 = /^[0-9a-f]{40}$/;
|
|
8
|
+
const RE_WHITESPACE = /\s+/;
|
|
9
|
+
export class GithubSource {
|
|
10
|
+
async fetch(options) {
|
|
11
|
+
const opts = options;
|
|
12
|
+
const { repo, docsPath } = opts;
|
|
13
|
+
const ref = opts.tag ?? opts.branch ?? 'main';
|
|
14
|
+
// Resolve the ref to get the actual version (strip leading "v" from tags)
|
|
15
|
+
const tagVersion = opts.tag?.replace(RE_LEADING_V, '');
|
|
16
|
+
const resolvedVersion = tagVersion ?? opts.version;
|
|
17
|
+
// Download repo archive and extract docs
|
|
18
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ask-gh-'));
|
|
19
|
+
try {
|
|
20
|
+
const archiveUrl = `https://github.com/${repo}/archive/refs/${opts.tag ? 'tags' : 'heads'}/${ref}.tar.gz`;
|
|
21
|
+
execSync(`curl -sL "${archiveUrl}" | tar xz -C "${tmpDir}"`, {
|
|
22
|
+
encoding: 'utf-8',
|
|
23
|
+
});
|
|
24
|
+
// Find extracted directory (format: reponame-ref)
|
|
25
|
+
const extractedDirs = fs.readdirSync(tmpDir);
|
|
26
|
+
if (extractedDirs.length === 0) {
|
|
27
|
+
throw new Error(`Failed to extract archive from ${repo}@${ref}`);
|
|
28
|
+
}
|
|
29
|
+
const extractedDir = path.join(tmpDir, extractedDirs[0]);
|
|
30
|
+
// Find docs
|
|
31
|
+
const targetPath = docsPath ?? this.detectDocsPath(extractedDir);
|
|
32
|
+
if (!targetPath) {
|
|
33
|
+
throw new Error(`No docs directory found in ${repo}@${ref}. Specify --path to point to the docs directory.`);
|
|
34
|
+
}
|
|
35
|
+
const docsDir = path.join(extractedDir, targetPath);
|
|
36
|
+
if (!fs.existsSync(docsDir)) {
|
|
37
|
+
throw new Error(`Path "${targetPath}" not found in ${repo}@${ref}`);
|
|
38
|
+
}
|
|
39
|
+
let files;
|
|
40
|
+
if (fs.statSync(docsDir).isFile()) {
|
|
41
|
+
// Single file specified
|
|
42
|
+
const content = fs.readFileSync(docsDir, 'utf-8');
|
|
43
|
+
files = [{ path: path.basename(docsDir), content }];
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
files = this.collectDocFiles(docsDir, docsDir);
|
|
47
|
+
}
|
|
48
|
+
const commit = this.resolveCommit(repo, ref);
|
|
49
|
+
return {
|
|
50
|
+
files,
|
|
51
|
+
resolvedVersion,
|
|
52
|
+
meta: { commit, ref },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
detectDocsPath(dir) {
|
|
60
|
+
const candidates = ['docs', 'doc', 'documentation', 'guide', 'guides'];
|
|
61
|
+
for (const candidate of candidates) {
|
|
62
|
+
const fullPath = path.join(dir, candidate);
|
|
63
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
|
|
64
|
+
return candidate;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
collectDocFiles(baseDir, currentDir) {
|
|
70
|
+
const files = [];
|
|
71
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
74
|
+
if (entry.isDirectory()) {
|
|
75
|
+
files.push(...this.collectDocFiles(baseDir, fullPath));
|
|
76
|
+
}
|
|
77
|
+
else if (this.isDocFile(entry.name)) {
|
|
78
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
79
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
80
|
+
files.push({ path: relativePath, content });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return files;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve a ref (tag or branch) to a full commit sha via `git ls-remote`.
|
|
87
|
+
* Returns undefined when git is unavailable or the ref cannot be resolved
|
|
88
|
+
* — the lockfile leaves `commit` undefined rather than guessing.
|
|
89
|
+
*/
|
|
90
|
+
resolveCommit(repo, ref) {
|
|
91
|
+
try {
|
|
92
|
+
// execFileSync (not execSync) to bypass the shell — `ref` originates
|
|
93
|
+
// from user-supplied tag/branch and must not be interpolated into a
|
|
94
|
+
// shell command line.
|
|
95
|
+
const out = execFileSync('git', ['ls-remote', `https://github.com/${repo}.git`, ref], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
96
|
+
// ls-remote may return multiple lines (e.g. tag + ^{} dereference).
|
|
97
|
+
// Prefer the dereferenced commit if present.
|
|
98
|
+
const lines = out.split('\n').filter(Boolean);
|
|
99
|
+
const dereferenced = lines.find(l => l.includes(`refs/tags/${ref}^{}`));
|
|
100
|
+
const sha = (dereferenced ?? lines[0])?.split(RE_WHITESPACE)[0];
|
|
101
|
+
return sha && RE_SHA40.test(sha) ? sha : undefined;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
consola.warn(`Could not resolve commit for ${repo}@${ref}: ${err instanceof Error ? err.message : err}. `
|
|
105
|
+
+ 'Lockfile will not pin a commit sha for this entry.');
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
isDocFile(filename) {
|
|
110
|
+
const ext = path.extname(filename).toLowerCase();
|
|
111
|
+
return ['.md', '.mdx', '.txt', '.rst'].includes(ext);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/sources/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SourceConfig } from '../schemas.js';
|
|
2
|
+
export type { SourceConfig };
|
|
3
|
+
export type NpmSourceOptions = Extract<SourceConfig, {
|
|
4
|
+
source: 'npm';
|
|
5
|
+
}>;
|
|
6
|
+
export type GithubSourceOptions = Extract<SourceConfig, {
|
|
7
|
+
source: 'github';
|
|
8
|
+
}>;
|
|
9
|
+
export type WebSourceOptions = Extract<SourceConfig, {
|
|
10
|
+
source: 'web';
|
|
11
|
+
}>;
|
|
12
|
+
export type LlmsTxtSourceOptions = Extract<SourceConfig, {
|
|
13
|
+
source: 'llms-txt';
|
|
14
|
+
}>;
|
|
15
|
+
export interface DocFile {
|
|
16
|
+
path: string;
|
|
17
|
+
content: string;
|
|
18
|
+
}
|
|
19
|
+
export interface FetchResult {
|
|
20
|
+
files: DocFile[];
|
|
21
|
+
resolvedVersion: string;
|
|
22
|
+
/** Source-specific metadata propagated to ask.lock */
|
|
23
|
+
meta?: {
|
|
24
|
+
/** GitHub commit sha (40 hex chars) */
|
|
25
|
+
commit?: string;
|
|
26
|
+
/** GitHub ref used (tag name or branch name) */
|
|
27
|
+
ref?: string;
|
|
28
|
+
/** npm Subresource Integrity hash from dist.integrity */
|
|
29
|
+
integrity?: string;
|
|
30
|
+
/** npm tarball URL */
|
|
31
|
+
tarball?: string;
|
|
32
|
+
/** web/llms-txt source URL(s) */
|
|
33
|
+
urls?: string[];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export interface DocSource {
|
|
37
|
+
fetch: (options: SourceConfig) => Promise<FetchResult>;
|
|
38
|
+
}
|
|
39
|
+
type SourceKind = SourceConfig['source'];
|
|
40
|
+
export declare function getSource(type: SourceKind): DocSource;
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAMjD,YAAY,EAAE,YAAY,EAAE,CAAA;AAM5B,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AACvE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAA;AAC7E,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AACvE,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAAA;AAEhF,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,EAAE,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,sDAAsD;IACtD,IAAI,CAAC,EAAE;QACL,uCAAuC;QACvC,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,gDAAgD;QAChD,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,yDAAyD;QACzD,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,sBAAsB;QACtB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,iCAAiC;QACjC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAChB,CAAA;CACF;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;CACvD;AAED,KAAK,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;AASxC,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAErD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GithubSource } from './github.js';
|
|
2
|
+
import { LlmsTxtSource } from './llms-txt.js';
|
|
3
|
+
import { NpmSource } from './npm.js';
|
|
4
|
+
import { WebSource } from './web.js';
|
|
5
|
+
const sources = {
|
|
6
|
+
'npm': new NpmSource(),
|
|
7
|
+
'github': new GithubSource(),
|
|
8
|
+
'web': new WebSource(),
|
|
9
|
+
'llms-txt': new LlmsTxtSource(),
|
|
10
|
+
};
|
|
11
|
+
export function getSource(type) {
|
|
12
|
+
return sources[type];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sources/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AA0CpC,MAAM,OAAO,GAAkC;IAC7C,KAAK,EAAE,IAAI,SAAS,EAAE;IACtB,QAAQ,EAAE,IAAI,YAAY,EAAE;IAC5B,KAAK,EAAE,IAAI,SAAS,EAAE;IACtB,UAAU,EAAE,IAAI,aAAa,EAAE;CAChC,CAAA;AAED,MAAM,UAAU,SAAS,CAAC,IAAgB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;AACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms-txt.d.ts","sourceRoot":"","sources":["../../src/sources/llms-txt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EAEX,YAAY,EACb,MAAM,YAAY,CAAA;AAGnB,qBAAa,aAAc,YAAW,SAAS;IACvC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;CAqCzD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
export class LlmsTxtSource {
|
|
3
|
+
async fetch(options) {
|
|
4
|
+
const opts = options;
|
|
5
|
+
const url = opts.url;
|
|
6
|
+
consola.info(` Fetching: ${url}`);
|
|
7
|
+
const response = await fetch(url, {
|
|
8
|
+
headers: {
|
|
9
|
+
'User-Agent': 'ask-docs/0.1 (documentation downloader)',
|
|
10
|
+
'Accept': 'text/plain, text/markdown',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
15
|
+
}
|
|
16
|
+
const content = await response.text();
|
|
17
|
+
if (content.trim().length === 0) {
|
|
18
|
+
throw new Error(`No content found at ${url}`);
|
|
19
|
+
}
|
|
20
|
+
// Determine filename from URL path
|
|
21
|
+
const urlObj = new URL(url);
|
|
22
|
+
const filename = urlObj.pathname.split('/').pop() || 'llms.txt';
|
|
23
|
+
const filePath = filename.endsWith('.md') || filename.endsWith('.txt')
|
|
24
|
+
? filename
|
|
25
|
+
: `${filename}.md`;
|
|
26
|
+
consola.info(` Fetched: ${url} -> ${filePath} (${content.length} chars)`);
|
|
27
|
+
return {
|
|
28
|
+
files: [{ path: filePath, content }],
|
|
29
|
+
resolvedVersion: opts.version,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=llms-txt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms-txt.js","sourceRoot":"","sources":["../../src/sources/llms-txt.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEjC,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,MAAM,IAAI,GAAG,OAA+B,CAAA;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;QAEpB,OAAO,CAAC,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC,CAAA;QAElC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,YAAY,EAAE,yCAAyC;gBACvD,QAAQ,EAAE,2BAA2B;aACtC;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;QACtF,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAErC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAA;QAC/C,CAAC;QAED,mCAAmC;QACnC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,UAAU,CAAA;QAC/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;YACpE,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,GAAG,QAAQ,KAAK,CAAA;QAEpB,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,OAAO,QAAQ,KAAK,OAAO,CAAC,MAAM,SAAS,CAAC,CAAA;QAE1E,OAAO;YACL,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;YACpC,eAAe,EAAE,IAAI,CAAC,OAAO;SAC9B,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DocSource, FetchResult, SourceConfig } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated Use the npm ecosystem resolver (`resolvers/npm.ts`) + github source
|
|
4
|
+
* instead. This direct npm tarball source is kept for one release to avoid
|
|
5
|
+
* regressions in existing configs that specify `source: 'npm'` explicitly.
|
|
6
|
+
*/
|
|
7
|
+
export declare class NpmSource implements DocSource {
|
|
8
|
+
fetch(options: SourceConfig): Promise<FetchResult>;
|
|
9
|
+
private detectDocsPath;
|
|
10
|
+
private listDirs;
|
|
11
|
+
private collectMarkdownFiles;
|
|
12
|
+
private isDocFile;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=npm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/sources/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,WAAW,EAEX,YAAY,EACb,MAAM,YAAY,CAAA;AAOnB;;;;GAIG;AACH,qBAAa,SAAU,YAAW,SAAS;IACnC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAsExD,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,SAAS;CAIlB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { consola } from 'consola';
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Use the npm ecosystem resolver (`resolvers/npm.ts`) + github source
|
|
8
|
+
* instead. This direct npm tarball source is kept for one release to avoid
|
|
9
|
+
* regressions in existing configs that specify `source: 'npm'` explicitly.
|
|
10
|
+
*/
|
|
11
|
+
export class NpmSource {
|
|
12
|
+
async fetch(options) {
|
|
13
|
+
const opts = options;
|
|
14
|
+
const pkg = opts.package ?? opts.name;
|
|
15
|
+
const spec = `${pkg}@${opts.version}`;
|
|
16
|
+
// Get package info to resolve exact version and tarball URL
|
|
17
|
+
const resolvedVersion = execSync(`npm view ${spec} version`, {
|
|
18
|
+
encoding: 'utf-8',
|
|
19
|
+
}).trim();
|
|
20
|
+
const tarballUrl = execSync(`npm view ${spec} dist.tarball`, {
|
|
21
|
+
encoding: 'utf-8',
|
|
22
|
+
}).trim();
|
|
23
|
+
const integrity = (() => {
|
|
24
|
+
try {
|
|
25
|
+
return execSync(`npm view ${spec} dist.integrity`, {
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
}).trim() || undefined;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
})();
|
|
33
|
+
// Download and extract tarball
|
|
34
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ask-npm-'));
|
|
35
|
+
try {
|
|
36
|
+
consola.info(` Downloading ${pkg}@${resolvedVersion}...`);
|
|
37
|
+
execSync(`curl -sL "${tarballUrl}" | tar xz -C "${tmpDir}"`, {
|
|
38
|
+
encoding: 'utf-8',
|
|
39
|
+
});
|
|
40
|
+
// Find docs in the extracted package
|
|
41
|
+
const packageDir = path.join(tmpDir, 'package');
|
|
42
|
+
const docsPath = opts.docsPath ?? this.detectDocsPath(packageDir);
|
|
43
|
+
if (!docsPath) {
|
|
44
|
+
throw new Error(`No docs found in ${spec}. Specify --docs-path to point to the docs directory within the package.`);
|
|
45
|
+
}
|
|
46
|
+
const docsDir = path.join(packageDir, docsPath);
|
|
47
|
+
if (!fs.existsSync(docsDir)) {
|
|
48
|
+
throw new Error(`Docs path "${docsPath}" not found in ${spec}. Available paths:\n${this.listDirs(packageDir)}`);
|
|
49
|
+
}
|
|
50
|
+
let files;
|
|
51
|
+
if (fs.statSync(docsDir).isFile()) {
|
|
52
|
+
const content = fs.readFileSync(docsDir, 'utf-8');
|
|
53
|
+
files = [{ path: path.basename(docsDir), content }];
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
files = this.collectMarkdownFiles(docsDir, docsDir);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
files,
|
|
60
|
+
resolvedVersion,
|
|
61
|
+
meta: { tarball: tarballUrl, integrity },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
detectDocsPath(packageDir) {
|
|
69
|
+
const candidates = [
|
|
70
|
+
'docs',
|
|
71
|
+
'doc',
|
|
72
|
+
'dist/docs',
|
|
73
|
+
'documentation',
|
|
74
|
+
'guide',
|
|
75
|
+
'guides',
|
|
76
|
+
];
|
|
77
|
+
for (const candidate of candidates) {
|
|
78
|
+
const fullPath = path.join(packageDir, candidate);
|
|
79
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
|
|
80
|
+
return candidate;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
listDirs(dir) {
|
|
86
|
+
return fs
|
|
87
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
88
|
+
.filter(d => d.isDirectory())
|
|
89
|
+
.map(d => ` - ${d.name}/`)
|
|
90
|
+
.join('\n');
|
|
91
|
+
}
|
|
92
|
+
collectMarkdownFiles(baseDir, currentDir) {
|
|
93
|
+
const files = [];
|
|
94
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
97
|
+
if (entry.isDirectory()) {
|
|
98
|
+
files.push(...this.collectMarkdownFiles(baseDir, fullPath));
|
|
99
|
+
}
|
|
100
|
+
else if (this.isDocFile(entry.name)) {
|
|
101
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
102
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
103
|
+
files.push({ path: relativePath, content });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return files;
|
|
107
|
+
}
|
|
108
|
+
isDocFile(filename) {
|
|
109
|
+
const ext = path.extname(filename).toLowerCase();
|
|
110
|
+
return ['.md', '.mdx', '.txt', '.rst'].includes(ext);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=npm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/sources/npm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocSource, FetchResult, SourceConfig } from './index.js';
|
|
2
|
+
export declare class WebSource implements DocSource {
|
|
3
|
+
private nhm;
|
|
4
|
+
fetch(options: SourceConfig): Promise<FetchResult>;
|
|
5
|
+
private crawl;
|
|
6
|
+
private htmlToMarkdown;
|
|
7
|
+
private extractMainContent;
|
|
8
|
+
private extractLinks;
|
|
9
|
+
private isSkippableUrl;
|
|
10
|
+
private normalizeUrl;
|
|
11
|
+
private urlToFilePath;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/sources/web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,WAAW,EACX,YAAY,EAEb,MAAM,YAAY,CAAA;AAgBnB,qBAAa,SAAU,YAAW,SAAS;IACzC,OAAO,CAAC,GAAG,CAAyB;IAE9B,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;YAmB1C,KAAK;IA6DnB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,YAAY;IA+CpB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,aAAa;CAetB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
import { NodeHtmlMarkdown } from 'node-html-markdown';
|
|
3
|
+
/* eslint-disable regexp/no-unused-capturing-group -- all capturing groups accessed via match[1] */
|
|
4
|
+
const RE_MAIN = /<main[^>]*>([\s\S]*?)<\/main>/i;
|
|
5
|
+
const RE_ARTICLE = /<article[^>]*>([\s\S]*?)<\/article>/i;
|
|
6
|
+
const RE_CONTENT_DIV = /<div[^>]*class="[^"]*(?:content|docs|documentation)[^"]*"[^>]*>([\s\S]*?)<\/div>/i;
|
|
7
|
+
const RE_BODY = /<body[^>]*>([\s\S]*?)<\/body>/i;
|
|
8
|
+
const RE_HREF = /href="([^"]+)"/g;
|
|
9
|
+
const RE_SKIP_EXT = /\.(png|jpg|jpeg|gif|svg|ico|css|js|woff|woff2|ttf|eot)$/i;
|
|
10
|
+
const RE_SKIP_PATH = /\/(api|auth|login|signup|search)\/?$/i;
|
|
11
|
+
/* eslint-enable regexp/no-unused-capturing-group */
|
|
12
|
+
const RE_TRAILING_SLASH = /\/$/;
|
|
13
|
+
const RE_LEADING_SLASH = /^\//;
|
|
14
|
+
export class WebSource {
|
|
15
|
+
nhm = new NodeHtmlMarkdown();
|
|
16
|
+
async fetch(options) {
|
|
17
|
+
const opts = options;
|
|
18
|
+
const maxDepth = opts.maxDepth ?? 1;
|
|
19
|
+
const visited = new Set();
|
|
20
|
+
const files = [];
|
|
21
|
+
for (const startUrl of opts.urls) {
|
|
22
|
+
await this.crawl(startUrl, startUrl, maxDepth, 0, visited, files, opts);
|
|
23
|
+
}
|
|
24
|
+
if (files.length === 0) {
|
|
25
|
+
throw new Error(`No documentation content found from URLs: ${opts.urls.join(', ')}`);
|
|
26
|
+
}
|
|
27
|
+
return { files, resolvedVersion: opts.version };
|
|
28
|
+
}
|
|
29
|
+
async crawl(url, baseUrl, maxDepth, currentDepth, visited, files, opts) {
|
|
30
|
+
const normalized = this.normalizeUrl(url);
|
|
31
|
+
if (visited.has(normalized))
|
|
32
|
+
return;
|
|
33
|
+
visited.add(normalized);
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(url, {
|
|
36
|
+
headers: {
|
|
37
|
+
'User-Agent': 'ask-docs/0.1 (documentation downloader)',
|
|
38
|
+
'Accept': 'text/html',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
consola.warn(` Warning: ${url} returned ${response.status}, skipping`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
46
|
+
if (!contentType.includes('text/html'))
|
|
47
|
+
return;
|
|
48
|
+
const html = await response.text();
|
|
49
|
+
const markdown = this.htmlToMarkdown(html, url);
|
|
50
|
+
if (markdown.trim().length > 0) {
|
|
51
|
+
const filePath = this.urlToFilePath(url, baseUrl);
|
|
52
|
+
files.push({ path: filePath, content: markdown });
|
|
53
|
+
consola.info(` Fetched: ${url} -> ${filePath}`);
|
|
54
|
+
}
|
|
55
|
+
// Crawl linked pages if depth allows
|
|
56
|
+
if (currentDepth < maxDepth) {
|
|
57
|
+
const links = this.extractLinks(html, url, baseUrl, opts);
|
|
58
|
+
for (const link of links) {
|
|
59
|
+
await this.crawl(link, baseUrl, maxDepth, currentDepth + 1, visited, files, opts);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
consola.warn(` Warning: Failed to fetch ${url}: ${err}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
htmlToMarkdown(html, url) {
|
|
68
|
+
const mainContent = this.extractMainContent(html);
|
|
69
|
+
const markdown = this.nhm.translate(mainContent);
|
|
70
|
+
return `<!-- Source: ${url} -->\n\n${markdown}`;
|
|
71
|
+
}
|
|
72
|
+
extractMainContent(html) {
|
|
73
|
+
const patterns = [RE_MAIN, RE_ARTICLE, RE_CONTENT_DIV, RE_BODY];
|
|
74
|
+
for (const pattern of patterns) {
|
|
75
|
+
const match = html.match(pattern);
|
|
76
|
+
if (match)
|
|
77
|
+
return match[1];
|
|
78
|
+
}
|
|
79
|
+
return html;
|
|
80
|
+
}
|
|
81
|
+
extractLinks(html, currentUrl, baseUrl, opts) {
|
|
82
|
+
const links = [];
|
|
83
|
+
const base = new URL(baseUrl);
|
|
84
|
+
for (const match of html.matchAll(RE_HREF)) {
|
|
85
|
+
try {
|
|
86
|
+
const resolved = new URL(match[1], currentUrl);
|
|
87
|
+
// Only follow same-origin links
|
|
88
|
+
if (resolved.origin !== base.origin)
|
|
89
|
+
continue;
|
|
90
|
+
// Filter by path prefix if specified
|
|
91
|
+
if (opts.allowedPathPrefix) {
|
|
92
|
+
if (!resolved.pathname.startsWith(opts.allowedPathPrefix))
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Default: stay within the base URL's path
|
|
97
|
+
const basePath = new URL(baseUrl).pathname;
|
|
98
|
+
if (!resolved.pathname.startsWith(basePath))
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
// Skip non-doc links
|
|
102
|
+
if (this.isSkippableUrl(resolved.pathname))
|
|
103
|
+
continue;
|
|
104
|
+
// Remove hash and query
|
|
105
|
+
resolved.hash = '';
|
|
106
|
+
resolved.search = '';
|
|
107
|
+
links.push(resolved.toString());
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Invalid URL, skip
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return links;
|
|
114
|
+
}
|
|
115
|
+
isSkippableUrl(pathname) {
|
|
116
|
+
return RE_SKIP_EXT.test(pathname) || RE_SKIP_PATH.test(pathname);
|
|
117
|
+
}
|
|
118
|
+
normalizeUrl(url) {
|
|
119
|
+
try {
|
|
120
|
+
const u = new URL(url);
|
|
121
|
+
u.hash = '';
|
|
122
|
+
u.search = '';
|
|
123
|
+
u.pathname = u.pathname.replace(RE_TRAILING_SLASH, '') || '/';
|
|
124
|
+
return u.toString();
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return url;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
urlToFilePath(url, baseUrl) {
|
|
131
|
+
const u = new URL(url);
|
|
132
|
+
const base = new URL(baseUrl);
|
|
133
|
+
let relativePath = u.pathname.replace(base.pathname, '').replace(RE_LEADING_SLASH, '');
|
|
134
|
+
if (!relativePath)
|
|
135
|
+
relativePath = 'index';
|
|
136
|
+
relativePath = relativePath.replace(RE_TRAILING_SLASH, '');
|
|
137
|
+
if (!relativePath.endsWith('.md')) {
|
|
138
|
+
relativePath += '.md';
|
|
139
|
+
}
|
|
140
|
+
return relativePath;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/sources/web.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DocFile } from './sources/index.js';
|
|
2
|
+
export declare function getDocsDir(projectDir: string): string;
|
|
3
|
+
export declare function getLibraryDocsDir(projectDir: string, name: string, version: string): string;
|
|
4
|
+
export declare function saveDocs(projectDir: string, name: string, version: string, files: DocFile[]): string;
|
|
5
|
+
export declare function removeDocs(projectDir: string, name: string, version?: string): void;
|
|
6
|
+
export declare function listDocs(projectDir: string): Array<{
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
fileCount: number;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAKjD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,EAAE,GACf,MAAM,CA2BR;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAmBN;AAED,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,GACjB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAc7D"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getAskDir } from './io.js';
|
|
4
|
+
export function getDocsDir(projectDir) {
|
|
5
|
+
return path.join(getAskDir(projectDir), 'docs');
|
|
6
|
+
}
|
|
7
|
+
export function getLibraryDocsDir(projectDir, name, version) {
|
|
8
|
+
return path.join(getDocsDir(projectDir), `${name}@${version}`);
|
|
9
|
+
}
|
|
10
|
+
export function saveDocs(projectDir, name, version, files) {
|
|
11
|
+
const docsDir = getLibraryDocsDir(projectDir, name, version);
|
|
12
|
+
// Clean existing docs for this library version
|
|
13
|
+
if (fs.existsSync(docsDir)) {
|
|
14
|
+
fs.rmSync(docsDir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
fs.mkdirSync(docsDir, { recursive: true });
|
|
17
|
+
for (const file of files) {
|
|
18
|
+
const filePath = path.join(docsDir, file.path);
|
|
19
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
20
|
+
fs.writeFileSync(filePath, file.content, 'utf-8');
|
|
21
|
+
}
|
|
22
|
+
// Create an index file listing all docs
|
|
23
|
+
const index = files
|
|
24
|
+
.map(f => `- [${f.path}](./${f.path})`)
|
|
25
|
+
.join('\n');
|
|
26
|
+
fs.writeFileSync(path.join(docsDir, 'INDEX.md'), `# ${name}@${version} Documentation\n\n${index}\n`, 'utf-8');
|
|
27
|
+
return docsDir;
|
|
28
|
+
}
|
|
29
|
+
export function removeDocs(projectDir, name, version) {
|
|
30
|
+
if (version) {
|
|
31
|
+
const docsDir = getLibraryDocsDir(projectDir, name, version);
|
|
32
|
+
if (fs.existsSync(docsDir)) {
|
|
33
|
+
fs.rmSync(docsDir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Remove all versions for this library
|
|
38
|
+
const baseDir = getDocsDir(projectDir);
|
|
39
|
+
if (!fs.existsSync(baseDir))
|
|
40
|
+
return;
|
|
41
|
+
const entries = fs.readdirSync(baseDir);
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (entry.startsWith(`${name}@`)) {
|
|
44
|
+
fs.rmSync(path.join(baseDir, entry), { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function listDocs(projectDir) {
|
|
50
|
+
const baseDir = getDocsDir(projectDir);
|
|
51
|
+
if (!fs.existsSync(baseDir))
|
|
52
|
+
return [];
|
|
53
|
+
return fs
|
|
54
|
+
.readdirSync(baseDir, { withFileTypes: true })
|
|
55
|
+
.filter(d => d.isDirectory() && d.name.includes('@'))
|
|
56
|
+
.map((d) => {
|
|
57
|
+
const [name, version] = d.name.split('@');
|
|
58
|
+
const dirPath = path.join(baseDir, d.name);
|
|
59
|
+
const fileCount = countFiles(dirPath);
|
|
60
|
+
return { name, version, fileCount };
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function countFiles(dir) {
|
|
64
|
+
let count = 0;
|
|
65
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
66
|
+
for (const entry of entries) {
|
|
67
|
+
if (entry.isDirectory()) {
|
|
68
|
+
count += countFiles(path.join(dir, entry.name));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
count++;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return count;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=storage.js.map
|