@oxog/npm-llms 1.0.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/dist/index.js ADDED
@@ -0,0 +1,3558 @@
1
+ import { createHash } from 'crypto';
2
+ import { join, dirname } from 'path';
3
+ import { tmpdir } from 'os';
4
+ import { access, readFile, unlink, rm, mkdir, writeFile, readdir, stat } from 'fs/promises';
5
+ import { constants } from 'fs';
6
+ import { gunzipSync } from 'zlib';
7
+
8
+ // src/errors.ts
9
+ var NpmLlmsError = class extends Error {
10
+ /**
11
+ * Create a new NpmLlmsError
12
+ * @param message - Error message
13
+ * @param code - Error code
14
+ * @param details - Additional error details
15
+ */
16
+ constructor(message, code, details) {
17
+ super(message);
18
+ this.code = code;
19
+ this.details = details;
20
+ this.name = "NpmLlmsError";
21
+ if (Error.captureStackTrace) {
22
+ Error.captureStackTrace(this, this.constructor);
23
+ }
24
+ }
25
+ /**
26
+ * Convert error to JSON
27
+ */
28
+ toJSON() {
29
+ return {
30
+ name: this.name,
31
+ message: this.message,
32
+ code: this.code,
33
+ details: this.details
34
+ };
35
+ }
36
+ };
37
+ var PackageNotFoundError = class extends NpmLlmsError {
38
+ constructor(packageName) {
39
+ super(`Package "${packageName}" not found on npm`, "PACKAGE_NOT_FOUND", { packageName });
40
+ this.name = "PackageNotFoundError";
41
+ }
42
+ };
43
+ var VersionNotFoundError = class extends NpmLlmsError {
44
+ constructor(packageName, version) {
45
+ super(`Version "${version}" not found for package "${packageName}"`, "VERSION_NOT_FOUND", {
46
+ packageName,
47
+ version
48
+ });
49
+ this.name = "VersionNotFoundError";
50
+ }
51
+ };
52
+ var DownloadError = class extends NpmLlmsError {
53
+ constructor(message, url) {
54
+ super(message, "DOWNLOAD_FAILED", { url });
55
+ this.name = "DownloadError";
56
+ }
57
+ };
58
+ var ParseError = class extends NpmLlmsError {
59
+ constructor(message, file, position) {
60
+ super(message, "PARSE_ERROR", { file, position });
61
+ this.name = "ParseError";
62
+ }
63
+ };
64
+ var AIError = class extends NpmLlmsError {
65
+ constructor(message, provider) {
66
+ super(message, "AI_ERROR", { provider });
67
+ this.name = "AIError";
68
+ }
69
+ };
70
+ var PluginError = class extends NpmLlmsError {
71
+ constructor(message, pluginName) {
72
+ super(message, "PLUGIN_ERROR", { pluginName });
73
+ this.name = "PluginError";
74
+ }
75
+ };
76
+ var CacheError = class extends NpmLlmsError {
77
+ constructor(message) {
78
+ super(message, "CACHE_ERROR");
79
+ this.name = "CacheError";
80
+ }
81
+ };
82
+ var ConfigError = class extends NpmLlmsError {
83
+ constructor(message) {
84
+ super(message, "CONFIG_ERROR");
85
+ this.name = "ConfigError";
86
+ }
87
+ };
88
+ var TarError = class extends NpmLlmsError {
89
+ constructor(message, offset) {
90
+ super(message, "TAR_ERROR", { offset });
91
+ this.name = "TarError";
92
+ }
93
+ };
94
+ var TimeoutError = class extends NpmLlmsError {
95
+ constructor(message, timeout) {
96
+ super(message, "TIMEOUT_ERROR", { timeout });
97
+ this.name = "TimeoutError";
98
+ }
99
+ };
100
+ var ValidationError = class extends NpmLlmsError {
101
+ constructor(message, field) {
102
+ super(message, "VALIDATION_ERROR", { field });
103
+ this.name = "ValidationError";
104
+ }
105
+ };
106
+ function isNpmLlmsError(error) {
107
+ return error instanceof NpmLlmsError;
108
+ }
109
+ function getErrorCode(error) {
110
+ if (isNpmLlmsError(error)) {
111
+ return error.code;
112
+ }
113
+ return "UNKNOWN_ERROR";
114
+ }
115
+ function wrapError(error, code = "UNKNOWN_ERROR") {
116
+ if (isNpmLlmsError(error)) {
117
+ return error;
118
+ }
119
+ const message = error instanceof Error ? error.message : String(error);
120
+ return new NpmLlmsError(message, code, {
121
+ originalError: error instanceof Error ? error.name : typeof error
122
+ });
123
+ }
124
+
125
+ // src/kernel.ts
126
+ function createKernel() {
127
+ const plugins = /* @__PURE__ */ new Map();
128
+ const eventHandlers = /* @__PURE__ */ new Map();
129
+ const handlerToPlugin = /* @__PURE__ */ new Map();
130
+ function handlePluginError(error, pluginName) {
131
+ const plugin = pluginName ? plugins.get(pluginName) : void 0;
132
+ if (plugin?.onError) {
133
+ try {
134
+ plugin.onError(error);
135
+ } catch {
136
+ }
137
+ }
138
+ }
139
+ function use(plugin) {
140
+ if (!plugin.name) {
141
+ throw new PluginError("Plugin must have a name");
142
+ }
143
+ if (plugins.has(plugin.name)) {
144
+ throw new PluginError(`Plugin "${plugin.name}" is already registered`, plugin.name);
145
+ }
146
+ if (plugin.dependencies) {
147
+ for (const dep of plugin.dependencies) {
148
+ if (!plugins.has(dep)) {
149
+ throw new PluginError(
150
+ `Plugin "${plugin.name}" depends on "${dep}" which is not registered`,
151
+ plugin.name
152
+ );
153
+ }
154
+ }
155
+ }
156
+ try {
157
+ plugin.install(kernel);
158
+ plugins.set(plugin.name, plugin);
159
+ } catch (error) {
160
+ const err = error instanceof Error ? error : new Error(String(error));
161
+ throw new PluginError(
162
+ `Failed to install plugin "${plugin.name}": ${err.message}`,
163
+ plugin.name
164
+ );
165
+ }
166
+ return kernel;
167
+ }
168
+ function unregister(name) {
169
+ const plugin = plugins.get(name);
170
+ if (!plugin) {
171
+ return false;
172
+ }
173
+ for (const [, p] of plugins) {
174
+ if (p.dependencies?.includes(name)) {
175
+ throw new PluginError(
176
+ `Cannot unregister "${name}": plugin "${p.name}" depends on it`,
177
+ name
178
+ );
179
+ }
180
+ }
181
+ for (const [event, handlers] of eventHandlers) {
182
+ const toRemove = [];
183
+ for (const entry of handlers) {
184
+ if (entry.pluginName === name) {
185
+ toRemove.push(entry);
186
+ handlerToPlugin.delete(entry.handler);
187
+ }
188
+ }
189
+ for (const entry of toRemove) {
190
+ handlers.delete(entry);
191
+ }
192
+ if (handlers.size === 0) {
193
+ eventHandlers.delete(event);
194
+ }
195
+ }
196
+ try {
197
+ plugin.onDestroy?.();
198
+ } catch {
199
+ }
200
+ plugins.delete(name);
201
+ return true;
202
+ }
203
+ function on(event, handler) {
204
+ if (!eventHandlers.has(event)) {
205
+ eventHandlers.set(event, /* @__PURE__ */ new Set());
206
+ }
207
+ const pluginName = getCurrentPluginContext() ?? "unknown";
208
+ const entry = { handler, pluginName };
209
+ eventHandlers.get(event).add(entry);
210
+ handlerToPlugin.set(handler, pluginName);
211
+ }
212
+ function off(event, handler) {
213
+ const handlers = eventHandlers.get(event);
214
+ if (!handlers) return;
215
+ for (const entry of handlers) {
216
+ if (entry.handler === handler) {
217
+ handlers.delete(entry);
218
+ handlerToPlugin.delete(handler);
219
+ break;
220
+ }
221
+ }
222
+ if (handlers.size === 0) {
223
+ eventHandlers.delete(event);
224
+ }
225
+ }
226
+ async function emit(event, context, ...args) {
227
+ const handlers = eventHandlers.get(event);
228
+ if (!handlers || handlers.size === 0) return;
229
+ for (const entry of handlers) {
230
+ try {
231
+ await entry.handler(context, ...args);
232
+ } catch (error) {
233
+ const err = error instanceof Error ? error : new Error(String(error));
234
+ handlePluginError(err, entry.pluginName);
235
+ }
236
+ }
237
+ }
238
+ function listPlugins() {
239
+ return Array.from(plugins.values()).map((p) => ({
240
+ name: p.name,
241
+ version: p.version,
242
+ category: p.category,
243
+ dependencies: p.dependencies ?? []
244
+ }));
245
+ }
246
+ function getPlugin(name) {
247
+ return plugins.get(name);
248
+ }
249
+ function hasPlugin(name) {
250
+ return plugins.has(name);
251
+ }
252
+ async function destroy() {
253
+ const pluginNames = Array.from(plugins.keys()).reverse();
254
+ for (const name of pluginNames) {
255
+ const plugin = plugins.get(name);
256
+ if (plugin?.onDestroy) {
257
+ try {
258
+ await plugin.onDestroy();
259
+ } catch {
260
+ }
261
+ }
262
+ }
263
+ plugins.clear();
264
+ eventHandlers.clear();
265
+ handlerToPlugin.clear();
266
+ }
267
+ let currentPluginContext = null;
268
+ function getCurrentPluginContext() {
269
+ return currentPluginContext;
270
+ }
271
+ const originalUse = use;
272
+ function wrappedUse(plugin) {
273
+ currentPluginContext = plugin.name;
274
+ try {
275
+ originalUse(plugin);
276
+ return kernel;
277
+ } finally {
278
+ currentPluginContext = null;
279
+ }
280
+ }
281
+ const kernel = {
282
+ use: wrappedUse,
283
+ unregister,
284
+ on,
285
+ off,
286
+ emit,
287
+ listPlugins,
288
+ getPlugin,
289
+ hasPlugin,
290
+ destroy
291
+ };
292
+ return kernel;
293
+ }
294
+ function definePlugin(definition) {
295
+ return definition;
296
+ }
297
+ function composePlugins(name, plugins) {
298
+ return {
299
+ name,
300
+ version: "1.0.0",
301
+ category: "utility",
302
+ dependencies: plugins.flatMap((p) => p.dependencies ?? []),
303
+ install(kernel) {
304
+ for (const plugin of plugins) {
305
+ kernel.use(plugin);
306
+ }
307
+ },
308
+ async onDestroy() {
309
+ }
310
+ };
311
+ }
312
+ async function exists(path) {
313
+ try {
314
+ await access(path, constants.F_OK);
315
+ return true;
316
+ } catch {
317
+ return false;
318
+ }
319
+ }
320
+ async function ensureDir(dirPath) {
321
+ try {
322
+ await mkdir(dirPath, { recursive: true });
323
+ return true;
324
+ } catch (error) {
325
+ if (error.code === "EEXIST") {
326
+ return false;
327
+ }
328
+ throw error;
329
+ }
330
+ }
331
+ async function readJsonFile(filePath) {
332
+ const content = await readFile(filePath, "utf-8");
333
+ return JSON.parse(content);
334
+ }
335
+ async function writeTextFile(filePath, content) {
336
+ await ensureDir(dirname(filePath));
337
+ await writeFile(filePath, content, "utf-8");
338
+ }
339
+ async function writeJsonFile(filePath, data, pretty = true) {
340
+ const content = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
341
+ await writeTextFile(filePath, content);
342
+ }
343
+ async function deleteFile(filePath) {
344
+ try {
345
+ await unlink(filePath);
346
+ return true;
347
+ } catch (error) {
348
+ if (error.code === "ENOENT") {
349
+ return false;
350
+ }
351
+ throw error;
352
+ }
353
+ }
354
+ async function deleteDir(dirPath) {
355
+ try {
356
+ await rm(dirPath, { recursive: true, force: true });
357
+ return true;
358
+ } catch (error) {
359
+ if (error.code === "ENOENT") {
360
+ return false;
361
+ }
362
+ throw error;
363
+ }
364
+ }
365
+ async function listFiles(dirPath, recursive = false) {
366
+ const files = [];
367
+ async function scanDir(currentPath, prefix = "") {
368
+ const entries = await readdir(currentPath, { withFileTypes: true });
369
+ for (const entry of entries) {
370
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
371
+ if (entry.isFile()) {
372
+ files.push(relativePath);
373
+ } else if (entry.isDirectory() && recursive) {
374
+ await scanDir(join(currentPath, entry.name), relativePath);
375
+ }
376
+ }
377
+ }
378
+ try {
379
+ await scanDir(dirPath);
380
+ } catch (error) {
381
+ if (error.code === "ENOENT") {
382
+ return [];
383
+ }
384
+ throw error;
385
+ }
386
+ return files;
387
+ }
388
+ async function getDirSize(dirPath) {
389
+ let totalSize = 0;
390
+ async function scanDir(currentPath) {
391
+ try {
392
+ const entries = await readdir(currentPath, { withFileTypes: true });
393
+ for (const entry of entries) {
394
+ const fullPath = join(currentPath, entry.name);
395
+ if (entry.isFile()) {
396
+ const stats = await stat(fullPath);
397
+ totalSize += stats.size;
398
+ } else if (entry.isDirectory()) {
399
+ await scanDir(fullPath);
400
+ }
401
+ }
402
+ } catch {
403
+ }
404
+ }
405
+ await scanDir(dirPath);
406
+ return totalSize;
407
+ }
408
+
409
+ // src/core/cache.ts
410
+ var DEFAULT_CACHE_DIR = ".npm-llms-cache";
411
+ var DEFAULT_TTL = 7 * 24 * 60 * 60 * 1e3;
412
+ var CACHE_VERSION = 1;
413
+ var FileCache = class {
414
+ dir;
415
+ defaultTtl;
416
+ /**
417
+ * Create a new FileCache
418
+ * @param dir - Cache directory path
419
+ * @param defaultTtl - Default TTL in milliseconds
420
+ */
421
+ constructor(dir, defaultTtl = DEFAULT_TTL) {
422
+ this.dir = dir ?? join(tmpdir(), DEFAULT_CACHE_DIR);
423
+ this.defaultTtl = defaultTtl;
424
+ }
425
+ /**
426
+ * Generate a cache key hash
427
+ * @param input - Input string
428
+ * @returns Hashed key
429
+ */
430
+ getKey(input) {
431
+ return createHash("sha256").update(input).digest("hex").slice(0, 16);
432
+ }
433
+ /**
434
+ * Get file path for a cache key
435
+ * @param key - Cache key
436
+ * @returns File path
437
+ */
438
+ getPath(key) {
439
+ const hash = this.getKey(key);
440
+ return join(this.dir, hash.slice(0, 2), `${hash}.json`);
441
+ }
442
+ /**
443
+ * Get cached data
444
+ * @param key - Cache key
445
+ * @returns Cached data or null if not found/expired
446
+ */
447
+ async get(key) {
448
+ const path = this.getPath(key);
449
+ try {
450
+ if (!await exists(path)) {
451
+ return null;
452
+ }
453
+ const entry = await readJsonFile(path);
454
+ if (entry.version !== CACHE_VERSION) {
455
+ await this.delete(key);
456
+ return null;
457
+ }
458
+ const age = Date.now() - entry.timestamp;
459
+ if (age > entry.ttl) {
460
+ await this.delete(key);
461
+ return null;
462
+ }
463
+ return entry.data;
464
+ } catch {
465
+ await this.delete(key).catch(() => {
466
+ });
467
+ return null;
468
+ }
469
+ }
470
+ /**
471
+ * Set cached data
472
+ * @param key - Cache key
473
+ * @param data - Data to cache
474
+ * @param ttl - Optional TTL override
475
+ */
476
+ async set(key, data, ttl) {
477
+ const path = this.getPath(key);
478
+ const entry = {
479
+ data,
480
+ timestamp: Date.now(),
481
+ ttl: ttl ?? this.defaultTtl,
482
+ key,
483
+ version: CACHE_VERSION
484
+ };
485
+ try {
486
+ await writeJsonFile(path, entry, false);
487
+ } catch (error) {
488
+ const message = error instanceof Error ? error.message : String(error);
489
+ throw new CacheError(`Failed to write cache: ${message}`);
490
+ }
491
+ }
492
+ /**
493
+ * Delete a cached entry
494
+ * @param key - Cache key
495
+ * @returns True if deleted, false if not found
496
+ */
497
+ async delete(key) {
498
+ const path = this.getPath(key);
499
+ return deleteFile(path);
500
+ }
501
+ /**
502
+ * Check if a key is cached and not expired
503
+ * @param key - Cache key
504
+ * @returns True if cached and valid
505
+ */
506
+ async has(key) {
507
+ const data = await this.get(key);
508
+ return data !== null;
509
+ }
510
+ /**
511
+ * Clear all cached data
512
+ */
513
+ async clear() {
514
+ try {
515
+ await deleteDir(this.dir);
516
+ await ensureDir(this.dir);
517
+ } catch (error) {
518
+ const message = error instanceof Error ? error.message : String(error);
519
+ throw new CacheError(`Failed to clear cache: ${message}`);
520
+ }
521
+ }
522
+ /**
523
+ * Remove expired entries
524
+ * @returns Number of entries removed
525
+ */
526
+ async prune() {
527
+ let removed = 0;
528
+ try {
529
+ const files = await listFiles(this.dir, true);
530
+ for (const file of files) {
531
+ if (!file.endsWith(".json")) continue;
532
+ const path = join(this.dir, file);
533
+ try {
534
+ const entry = await readJsonFile(path);
535
+ const expired = entry.version !== CACHE_VERSION || Date.now() - entry.timestamp > entry.ttl;
536
+ if (expired) {
537
+ await deleteFile(path);
538
+ removed++;
539
+ }
540
+ } catch {
541
+ await deleteFile(path);
542
+ removed++;
543
+ }
544
+ }
545
+ } catch {
546
+ }
547
+ return removed;
548
+ }
549
+ /**
550
+ * Get cache statistics
551
+ * @returns Cache stats
552
+ */
553
+ async getStats() {
554
+ try {
555
+ if (!await exists(this.dir)) {
556
+ return { entries: 0, size: 0, dir: this.dir };
557
+ }
558
+ const files = await listFiles(this.dir, true);
559
+ const jsonFiles = files.filter((f) => f.endsWith(".json"));
560
+ const size = await getDirSize(this.dir);
561
+ return {
562
+ entries: jsonFiles.length,
563
+ size,
564
+ dir: this.dir
565
+ };
566
+ } catch {
567
+ return { entries: 0, size: 0, dir: this.dir };
568
+ }
569
+ }
570
+ /**
571
+ * Get cache directory path
572
+ */
573
+ getDir() {
574
+ return this.dir;
575
+ }
576
+ /**
577
+ * Get default TTL
578
+ */
579
+ getDefaultTtl() {
580
+ return this.defaultTtl;
581
+ }
582
+ };
583
+ function createCache(options) {
584
+ if (options?.enabled === false) {
585
+ return null;
586
+ }
587
+ const dir = options?.dir ?? join(process.cwd(), DEFAULT_CACHE_DIR);
588
+ const ttl = options?.ttl ?? DEFAULT_TTL;
589
+ return new FileCache(dir, ttl);
590
+ }
591
+ function formatBytes(bytes) {
592
+ if (bytes < 1024) {
593
+ return `${bytes} B`;
594
+ }
595
+ if (bytes < 1024 * 1024) {
596
+ return `${(bytes / 1024).toFixed(1)} KB`;
597
+ }
598
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
599
+ }
600
+ function buildPackageCacheKey(name, version, type = "result") {
601
+ return `pkg:${name}@${version}:${type}`;
602
+ }
603
+ var DEFAULT_REGISTRY = "https://registry.npmjs.org";
604
+ var DEFAULT_TIMEOUT = 3e4;
605
+ function createTimeoutController(timeout) {
606
+ const controller = new AbortController();
607
+ const timeoutId = setTimeout(() => {
608
+ controller.abort();
609
+ }, timeout);
610
+ return {
611
+ controller,
612
+ cleanup: () => clearTimeout(timeoutId)
613
+ };
614
+ }
615
+ async function fetchJson(url, options = {}) {
616
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
617
+ const { controller, cleanup } = createTimeoutController(timeout);
618
+ try {
619
+ const response = await fetch(url, {
620
+ method: "GET",
621
+ headers: {
622
+ Accept: "application/json",
623
+ ...options.headers
624
+ },
625
+ signal: controller.signal
626
+ });
627
+ if (!response.ok) {
628
+ throw new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
629
+ }
630
+ const data = await response.json();
631
+ return {
632
+ data,
633
+ status: response.status,
634
+ headers: response.headers
635
+ };
636
+ } catch (error) {
637
+ if (error instanceof DownloadError) {
638
+ throw error;
639
+ }
640
+ if (error instanceof Error) {
641
+ if (error.name === "AbortError") {
642
+ throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
643
+ }
644
+ throw new DownloadError(error.message, url);
645
+ }
646
+ throw new DownloadError("Unknown fetch error", url);
647
+ } finally {
648
+ cleanup();
649
+ }
650
+ }
651
+ async function fetchBinary(url, options = {}) {
652
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
653
+ const { controller, cleanup } = createTimeoutController(timeout);
654
+ try {
655
+ const response = await fetch(url, {
656
+ method: "GET",
657
+ headers: {
658
+ Accept: "application/octet-stream",
659
+ ...options.headers
660
+ },
661
+ signal: controller.signal
662
+ });
663
+ if (!response.ok) {
664
+ throw new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
665
+ }
666
+ const data = await response.arrayBuffer();
667
+ return {
668
+ data,
669
+ status: response.status,
670
+ headers: response.headers
671
+ };
672
+ } catch (error) {
673
+ if (error instanceof DownloadError) {
674
+ throw error;
675
+ }
676
+ if (error instanceof Error) {
677
+ if (error.name === "AbortError") {
678
+ throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
679
+ }
680
+ throw new DownloadError(error.message, url);
681
+ }
682
+ throw new DownloadError("Unknown fetch error", url);
683
+ } finally {
684
+ cleanup();
685
+ }
686
+ }
687
+ async function fetchGzipped(url, options = {}) {
688
+ const { data: gzipped } = await fetchBinary(url, options);
689
+ try {
690
+ return gunzipSync(Buffer.from(gzipped));
691
+ } catch (error) {
692
+ const message = error instanceof Error ? error.message : "Unknown decompression error";
693
+ throw new DownloadError(`Failed to decompress gzip: ${message}`, url);
694
+ }
695
+ }
696
+ function encodePackageName(name) {
697
+ if (name.startsWith("@")) {
698
+ const slashIndex = name.indexOf("/");
699
+ if (slashIndex === -1) {
700
+ return encodeURIComponent(name);
701
+ }
702
+ const scope = name.slice(0, slashIndex);
703
+ const pkg = name.slice(slashIndex + 1);
704
+ return `${scope}%2F${encodeURIComponent(pkg)}`;
705
+ }
706
+ return encodeURIComponent(name);
707
+ }
708
+ function buildPackageUrl(name, version, registry = DEFAULT_REGISTRY) {
709
+ const encodedName = encodePackageName(name);
710
+ const base = `${registry}/${encodedName}`;
711
+ return version ? `${base}/${version}` : base;
712
+ }
713
+
714
+ // src/utils/tar.ts
715
+ var BLOCK_SIZE = 512;
716
+ var TAR_TYPES = {
717
+ FILE: "0",
718
+ FILE_ALT: "",
719
+ GNU_LONGNAME: "L"};
720
+ var decoder = new TextDecoder("utf-8");
721
+ function isZeroBlock(buffer, offset) {
722
+ const end = Math.min(offset + BLOCK_SIZE, buffer.length);
723
+ for (let i = offset; i < end; i++) {
724
+ if (buffer[i] !== 0) return false;
725
+ }
726
+ return true;
727
+ }
728
+ function parseOctal(buffer, offset, length) {
729
+ const bytes = buffer.slice(offset, offset + length);
730
+ const str = decoder.decode(bytes).replace(/\0/g, "").trim();
731
+ if (!str) return 0;
732
+ return parseInt(str, 8) || 0;
733
+ }
734
+ function parseString(buffer, offset, length) {
735
+ const bytes = buffer.slice(offset, offset + length);
736
+ const str = decoder.decode(bytes);
737
+ const nullIndex = str.indexOf("\0");
738
+ return nullIndex >= 0 ? str.slice(0, nullIndex) : str;
739
+ }
740
+ function calculateChecksum(buffer, offset) {
741
+ let sum = 0;
742
+ for (let i = 0; i < BLOCK_SIZE; i++) {
743
+ if (i >= 148 && i < 156) {
744
+ sum += 32;
745
+ } else {
746
+ sum += buffer[offset + i] ?? 0;
747
+ }
748
+ }
749
+ return sum;
750
+ }
751
+ function parseTarHeader(buffer, offset) {
752
+ if (isZeroBlock(buffer, offset)) {
753
+ return null;
754
+ }
755
+ if (offset + BLOCK_SIZE > buffer.length) {
756
+ throw new TarError("Unexpected end of tar archive", offset);
757
+ }
758
+ const name = parseString(buffer, offset, 100);
759
+ const mode = parseOctal(buffer, offset + 100, 8);
760
+ const uid = parseOctal(buffer, offset + 108, 8);
761
+ const gid = parseOctal(buffer, offset + 116, 8);
762
+ const size = parseOctal(buffer, offset + 124, 12);
763
+ const mtime = parseOctal(buffer, offset + 136, 12);
764
+ const checksum = parseOctal(buffer, offset + 148, 8);
765
+ const type = parseString(buffer, offset + 156, 1);
766
+ const linkname = parseString(buffer, offset + 157, 100);
767
+ const calculatedChecksum = calculateChecksum(buffer, offset);
768
+ if (checksum !== 0 && checksum !== calculatedChecksum) {
769
+ throw new TarError(`Invalid tar header checksum: expected ${checksum}, got ${calculatedChecksum}`, offset);
770
+ }
771
+ const magic = parseString(buffer, offset + 257, 6);
772
+ let fullName = name;
773
+ if (magic === "ustar" || magic === "ustar ") {
774
+ const prefix = parseString(buffer, offset + 345, 155);
775
+ if (prefix) {
776
+ fullName = `${prefix}/${name}`;
777
+ }
778
+ }
779
+ return {
780
+ name: fullName,
781
+ mode,
782
+ uid,
783
+ gid,
784
+ size,
785
+ mtime,
786
+ checksum,
787
+ type,
788
+ linkname
789
+ };
790
+ }
791
+ function sanitizePath(path) {
792
+ let normalized = path.replace(/\\/g, "/");
793
+ if (normalized.startsWith("/")) {
794
+ normalized = normalized.slice(1);
795
+ }
796
+ const parts = normalized.split("/");
797
+ const safeParts = [];
798
+ for (const part of parts) {
799
+ if (part === "..") {
800
+ throw new TarError(`Path traversal detected: ${path}`);
801
+ }
802
+ if (part && part !== ".") {
803
+ safeParts.push(part);
804
+ }
805
+ }
806
+ return safeParts.join("/");
807
+ }
808
+ function removePackagePrefix(path) {
809
+ const prefixes = ["package/", "package\\"];
810
+ for (const prefix of prefixes) {
811
+ if (path.startsWith(prefix)) {
812
+ return path.slice(prefix.length);
813
+ }
814
+ }
815
+ return path;
816
+ }
817
+ function getEntryType(_type) {
818
+ return "file";
819
+ }
820
+ function shouldExtract(path) {
821
+ const lower = path.toLowerCase();
822
+ if (lower.endsWith(".d.ts") || lower.endsWith(".d.mts") || lower.endsWith(".d.cts")) {
823
+ return true;
824
+ }
825
+ if (lower.endsWith(".ts") || lower.endsWith(".tsx") || lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".cjs") || lower.endsWith(".jsx")) {
826
+ return true;
827
+ }
828
+ if (lower.endsWith(".md") || lower.endsWith(".txt") || lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml")) {
829
+ return true;
830
+ }
831
+ const filename = path.split("/").pop() ?? "";
832
+ if (filename === "package.json" || filename === "README.md" || filename === "CHANGELOG.md" || filename === "LICENSE" || filename === "LICENSE.md") {
833
+ return true;
834
+ }
835
+ return false;
836
+ }
837
+ function* extractTarSync(buffer) {
838
+ const data = buffer instanceof Buffer ? new Uint8Array(buffer) : new Uint8Array(buffer);
839
+ let offset = 0;
840
+ let gnuLongName = null;
841
+ while (offset < data.length) {
842
+ const header = parseTarHeader(data, offset);
843
+ if (!header) {
844
+ break;
845
+ }
846
+ offset += BLOCK_SIZE;
847
+ if (header.type === TAR_TYPES.GNU_LONGNAME) {
848
+ const contentBytes = data.slice(offset, offset + header.size);
849
+ gnuLongName = decoder.decode(contentBytes).replace(/\0/g, "");
850
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
851
+ continue;
852
+ }
853
+ const entryName = gnuLongName ?? header.name;
854
+ gnuLongName = null;
855
+ if (header.type !== TAR_TYPES.FILE && header.type !== TAR_TYPES.FILE_ALT) {
856
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
857
+ continue;
858
+ }
859
+ let path;
860
+ try {
861
+ path = sanitizePath(entryName);
862
+ path = removePackagePrefix(path);
863
+ } catch {
864
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
865
+ continue;
866
+ }
867
+ if (!shouldExtract(path)) {
868
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
869
+ continue;
870
+ }
871
+ const content = data.slice(offset, offset + header.size);
872
+ const textContent = decoder.decode(content);
873
+ yield {
874
+ path,
875
+ content: textContent,
876
+ size: header.size,
877
+ type: getEntryType(header.type)
878
+ };
879
+ offset += Math.ceil(header.size / BLOCK_SIZE) * BLOCK_SIZE;
880
+ }
881
+ }
882
+ function extractTarToMap(buffer) {
883
+ const files = /* @__PURE__ */ new Map();
884
+ for (const entry of extractTarSync(buffer)) {
885
+ if (entry.type === "file") {
886
+ files.set(entry.path, entry.content);
887
+ }
888
+ }
889
+ return files;
890
+ }
891
+
892
+ // src/core/fetcher.ts
893
+ function validatePackageName(name) {
894
+ if (!name || typeof name !== "string") {
895
+ throw new ValidationError("Package name is required", "name");
896
+ }
897
+ const validPattern = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
898
+ if (!validPattern.test(name)) {
899
+ throw new ValidationError(
900
+ `Invalid package name: "${name}". Package names must be lowercase and may contain letters, numbers, hyphens, dots, and underscores.`,
901
+ "name"
902
+ );
903
+ }
904
+ if (name.length > 214) {
905
+ throw new ValidationError("Package name cannot exceed 214 characters", "name");
906
+ }
907
+ }
908
+ function parsePackageSpec(spec) {
909
+ if (!spec || typeof spec !== "string") {
910
+ throw new ValidationError("Package specifier is required", "spec");
911
+ }
912
+ const trimmed = spec.trim();
913
+ if (trimmed.startsWith("@")) {
914
+ const firstSlash = trimmed.indexOf("/");
915
+ if (firstSlash === -1) {
916
+ throw new ValidationError(`Invalid scoped package: "${spec}"`, "spec");
917
+ }
918
+ const afterScope = trimmed.slice(firstSlash + 1);
919
+ const versionSep = afterScope.lastIndexOf("@");
920
+ if (versionSep > 0) {
921
+ const name = trimmed.slice(0, firstSlash + 1 + versionSep);
922
+ const version = afterScope.slice(versionSep + 1);
923
+ return { name, version: version || void 0 };
924
+ }
925
+ return { name: trimmed };
926
+ }
927
+ const atIndex = trimmed.lastIndexOf("@");
928
+ if (atIndex > 0) {
929
+ const name = trimmed.slice(0, atIndex);
930
+ const version = trimmed.slice(atIndex + 1);
931
+ return { name, version: version || void 0 };
932
+ }
933
+ return { name: trimmed };
934
+ }
935
+ function resolveVersion(packageName, versions, distTags, requested) {
936
+ if (!requested) {
937
+ const latest = distTags["latest"];
938
+ if (latest && versions.includes(latest)) {
939
+ return latest;
940
+ }
941
+ return versions.sort(compareVersions).pop();
942
+ }
943
+ if (distTags[requested]) {
944
+ return distTags[requested];
945
+ }
946
+ if (versions.includes(requested)) {
947
+ return requested;
948
+ }
949
+ const matching = versions.filter((v) => v.startsWith(requested));
950
+ if (matching.length > 0) {
951
+ return matching.sort(compareVersions).pop();
952
+ }
953
+ throw new VersionNotFoundError(packageName, requested);
954
+ }
955
+ function compareVersions(a, b) {
956
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
957
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
958
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
959
+ const na = pa[i] || 0;
960
+ const nb = pb[i] || 0;
961
+ if (na !== nb) return na - nb;
962
+ }
963
+ return 0;
964
+ }
965
+ async function fetchPackageMetadata(name, version, options = {}) {
966
+ validatePackageName(name);
967
+ const registry = options.registry ?? DEFAULT_REGISTRY;
968
+ const httpOptions = { timeout: options.timeout };
969
+ if (version && !["latest", "next", "beta", "alpha"].includes(version)) {
970
+ try {
971
+ const url2 = buildPackageUrl(name, version, registry);
972
+ const { data } = await fetchJson(url2, httpOptions);
973
+ return extractMetadata(data);
974
+ } catch (error) {
975
+ if (!(error instanceof DownloadError) || !error.message.includes("404")) {
976
+ throw error;
977
+ }
978
+ }
979
+ }
980
+ const url = buildPackageUrl(name, void 0, registry);
981
+ try {
982
+ const { data } = await fetchJson(url, httpOptions);
983
+ const versions = Object.keys(data.versions ?? {});
984
+ if (versions.length === 0) {
985
+ throw new PackageNotFoundError(name);
986
+ }
987
+ const resolvedVersion = resolveVersion(
988
+ name,
989
+ versions,
990
+ data["dist-tags"] ?? {},
991
+ version
992
+ );
993
+ const versionData = data.versions[resolvedVersion];
994
+ if (!versionData) {
995
+ throw new VersionNotFoundError(name, resolvedVersion);
996
+ }
997
+ return extractMetadata(versionData);
998
+ } catch (error) {
999
+ if (error instanceof DownloadError && error.message.includes("404")) {
1000
+ throw new PackageNotFoundError(name);
1001
+ }
1002
+ throw error;
1003
+ }
1004
+ }
1005
+ function extractMetadata(data) {
1006
+ if (!data.dist?.tarball) {
1007
+ throw new DownloadError("Package metadata missing tarball URL");
1008
+ }
1009
+ let repository;
1010
+ if (data.repository) {
1011
+ if (typeof data.repository === "string") {
1012
+ repository = { type: "git", url: data.repository };
1013
+ } else {
1014
+ repository = data.repository;
1015
+ }
1016
+ }
1017
+ return {
1018
+ name: data.name,
1019
+ version: data.version,
1020
+ description: data.description,
1021
+ tarball: data.dist.tarball,
1022
+ types: data.types ?? data.typings,
1023
+ main: data.main,
1024
+ exports: data.exports,
1025
+ repository,
1026
+ keywords: data.keywords,
1027
+ author: data.author,
1028
+ license: data.license,
1029
+ homepage: data.homepage
1030
+ };
1031
+ }
1032
+ async function downloadPackageFiles(tarballUrl, options = {}) {
1033
+ const buffer = await fetchGzipped(tarballUrl, options);
1034
+ return extractTarToMap(buffer);
1035
+ }
1036
+ async function fetchPackage(spec, options = {}) {
1037
+ const { name, version } = parsePackageSpec(spec);
1038
+ const metadata = await fetchPackageMetadata(name, version, options);
1039
+ const files = await downloadPackageFiles(metadata.tarball, {
1040
+ timeout: options.timeout
1041
+ });
1042
+ return {
1043
+ ...metadata,
1044
+ files
1045
+ };
1046
+ }
1047
+
1048
+ // src/plugins/core/types-resolver.ts
1049
+ function hasDtsFiles(files) {
1050
+ for (const path of files.keys()) {
1051
+ if (path.endsWith(".d.ts")) {
1052
+ return true;
1053
+ }
1054
+ }
1055
+ return false;
1056
+ }
1057
+ function getTypesPackageName(packageName) {
1058
+ if (packageName.startsWith("@")) {
1059
+ const withoutAt = packageName.slice(1);
1060
+ return `@types/${withoutAt.replace("/", "__")}`;
1061
+ }
1062
+ return `@types/${packageName}`;
1063
+ }
1064
+ function isTypesPackage(packageName) {
1065
+ return packageName.startsWith("@types/");
1066
+ }
1067
+ var typesResolverPlugin = {
1068
+ name: "types-resolver",
1069
+ version: "1.0.0",
1070
+ category: "parser",
1071
+ install(kernel) {
1072
+ kernel.on("package:fetched", async (context) => {
1073
+ const { files, name } = context.package;
1074
+ if (isTypesPackage(name)) {
1075
+ return;
1076
+ }
1077
+ if (hasDtsFiles(files)) {
1078
+ return;
1079
+ }
1080
+ const typesPackageName = getTypesPackageName(name);
1081
+ try {
1082
+ const typesPackage = await fetchPackage(typesPackageName);
1083
+ let mergedCount = 0;
1084
+ for (const [path, content] of typesPackage.files) {
1085
+ if (path.endsWith(".d.ts")) {
1086
+ const newPath = `__types__/${path}`;
1087
+ files.set(newPath, content);
1088
+ mergedCount++;
1089
+ }
1090
+ }
1091
+ if (typesPackage.types && !context.package.types) {
1092
+ context.package.types = `__types__/${typesPackage.types}`;
1093
+ }
1094
+ if (mergedCount > 0) {
1095
+ console.error(
1096
+ `[types-resolver] Merged ${mergedCount} .d.ts files from ${typesPackageName}`
1097
+ );
1098
+ }
1099
+ } catch (error) {
1100
+ }
1101
+ });
1102
+ }
1103
+ };
1104
+
1105
+ // src/parsers/jsdoc.ts
1106
+ var TAG_PATTERNS = {
1107
+ /** @param {type} name - description */
1108
+ param: /@param\s+(?:\{([^}]*)\})?\s*(\[?\w+(?:\.\w+)*\]?)\s*(?:-\s*)?(.*)$/gm,
1109
+ /** @returns {type} description */
1110
+ returns: /@returns?\s+(?:\{([^}]*)\})?\s*(.*)/g,
1111
+ /** @example ... */
1112
+ example: /@example\s*([\s\S]*?)(?=@\w|$)/g,
1113
+ /** @deprecated reason */
1114
+ deprecated: /@deprecated\s*(.*)/g,
1115
+ /** @since version */
1116
+ since: /@since\s*(.*)/g,
1117
+ /** @see reference */
1118
+ see: /@see\s*(.*)/g,
1119
+ /** @throws {type} description */
1120
+ throws: /@throws?\s+(?:\{([^}]*)\})?\s*(.*)/g,
1121
+ /** @template T - description */
1122
+ typeParam: /@template\s+(\w+)\s*(?:-\s*)?(.*)/g};
1123
+ function cleanJSDocComment(comment) {
1124
+ return comment.replace(/^\/\*\*\s*/, "").replace(/\s*\*\/$/, "").replace(/^\s*\*\s?/gm, "").trim();
1125
+ }
1126
+ function extractDescription(content) {
1127
+ const tagMatch = content.match(/@\w+/);
1128
+ if (!tagMatch) {
1129
+ return content.trim() || void 0;
1130
+ }
1131
+ const description = content.slice(0, tagMatch.index).trim();
1132
+ return description || void 0;
1133
+ }
1134
+ function parseParams(content) {
1135
+ const params = [];
1136
+ const pattern = new RegExp(TAG_PATTERNS.param.source, "gm");
1137
+ let match;
1138
+ while ((match = pattern.exec(content)) !== null) {
1139
+ const [, type, rawName, description] = match;
1140
+ if (!rawName) continue;
1141
+ const name = rawName;
1142
+ const isOptional = name.startsWith("[") && name.endsWith("]");
1143
+ const cleanName = isOptional ? name.slice(1, -1) : name;
1144
+ params.push({
1145
+ name: cleanName,
1146
+ type: type?.trim(),
1147
+ description: description?.trim() || void 0,
1148
+ optional: isOptional
1149
+ });
1150
+ }
1151
+ return params;
1152
+ }
1153
+ function parseReturns(content) {
1154
+ const pattern = new RegExp(TAG_PATTERNS.returns.source, "g");
1155
+ const match = pattern.exec(content);
1156
+ if (!match) return void 0;
1157
+ const [, type, description] = match;
1158
+ return {
1159
+ type: type?.trim(),
1160
+ description: description?.trim() || void 0
1161
+ };
1162
+ }
1163
+ function parseExamples(content) {
1164
+ const examples = [];
1165
+ const pattern = new RegExp(TAG_PATTERNS.example.source, "g");
1166
+ let match;
1167
+ while ((match = pattern.exec(content)) !== null) {
1168
+ const example = match[1]?.trim();
1169
+ if (example) {
1170
+ examples.push(example);
1171
+ }
1172
+ }
1173
+ return examples;
1174
+ }
1175
+ function parseDeprecated(content) {
1176
+ const pattern = new RegExp(TAG_PATTERNS.deprecated.source, "g");
1177
+ const match = pattern.exec(content);
1178
+ return match ? match[1]?.trim() || "true" : void 0;
1179
+ }
1180
+ function parseSince(content) {
1181
+ const pattern = new RegExp(TAG_PATTERNS.since.source, "g");
1182
+ const match = pattern.exec(content);
1183
+ return match ? match[1]?.trim() : void 0;
1184
+ }
1185
+ function parseSee(content) {
1186
+ const refs = [];
1187
+ const pattern = new RegExp(TAG_PATTERNS.see.source, "g");
1188
+ let match;
1189
+ while ((match = pattern.exec(content)) !== null) {
1190
+ const ref = match[1]?.trim();
1191
+ if (ref) {
1192
+ refs.push(ref);
1193
+ }
1194
+ }
1195
+ return refs;
1196
+ }
1197
+ function parseThrows(content) {
1198
+ const throws = [];
1199
+ const pattern = new RegExp(TAG_PATTERNS.throws.source, "g");
1200
+ let match;
1201
+ while ((match = pattern.exec(content)) !== null) {
1202
+ const [, type, description] = match;
1203
+ throws.push({
1204
+ type: type?.trim(),
1205
+ description: description?.trim() || void 0
1206
+ });
1207
+ }
1208
+ return throws;
1209
+ }
1210
+ function parseTypeParams(content) {
1211
+ const params = [];
1212
+ const pattern = new RegExp(TAG_PATTERNS.typeParam.source, "g");
1213
+ let match;
1214
+ while ((match = pattern.exec(content)) !== null) {
1215
+ const [, name, description] = match;
1216
+ if (!name) continue;
1217
+ params.push({
1218
+ name: name.trim(),
1219
+ description: description?.trim() || void 0
1220
+ });
1221
+ }
1222
+ return params;
1223
+ }
1224
+ function parseJSDoc(comment) {
1225
+ const content = cleanJSDocComment(comment);
1226
+ return {
1227
+ description: extractDescription(content),
1228
+ params: parseParams(content).map((p) => ({
1229
+ name: p.name,
1230
+ type: p.type,
1231
+ description: p.description,
1232
+ optional: p.optional,
1233
+ defaultValue: p.defaultValue
1234
+ })),
1235
+ returns: parseReturns(content),
1236
+ examples: parseExamples(content),
1237
+ deprecated: parseDeprecated(content),
1238
+ since: parseSince(content),
1239
+ see: parseSee(content),
1240
+ throws: parseThrows(content),
1241
+ typeParams: parseTypeParams(content)
1242
+ };
1243
+ }
1244
+ function extractJSDocComments(source) {
1245
+ const comments = [];
1246
+ const pattern = /\/\*\*[\s\S]*?\*\//g;
1247
+ let match;
1248
+ while ((match = pattern.exec(source)) !== null) {
1249
+ comments.push({
1250
+ comment: match[0],
1251
+ start: match.index,
1252
+ end: match.index + match[0].length
1253
+ });
1254
+ }
1255
+ return comments;
1256
+ }
1257
+ function findPrecedingJSDoc(source, position, comments) {
1258
+ const allComments = comments ?? extractJSDocComments(source);
1259
+ for (let i = allComments.length - 1; i >= 0; i--) {
1260
+ const comment = allComments[i];
1261
+ if (!comment || comment.end > position) continue;
1262
+ const between = source.slice(comment.end, position);
1263
+ if (/^\s*$/.test(between)) {
1264
+ return parseJSDoc(comment.comment);
1265
+ }
1266
+ if (comment.end < position - 500) break;
1267
+ }
1268
+ return void 0;
1269
+ }
1270
+
1271
+ // src/parsers/dts.ts
1272
+ var PATTERNS = {
1273
+ /** Export function declaration */
1274
+ exportFunction: /export\s+(?:declare\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*:\s*([^;{]+)/g,
1275
+ /** Export const declaration */
1276
+ exportConst: /export\s+(?:declare\s+)?const\s+(\w+)\s*:\s*([^;=]+)/g,
1277
+ /** Export class declaration */
1278
+ exportClass: /export\s+(?:declare\s+)?(?:abstract\s+)?class\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^\s{]+))?(?:\s+implements\s+([^{]+))?\s*\{/g,
1279
+ /** Export interface declaration */
1280
+ exportInterface: /export\s+(?:declare\s+)?interface\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^{]+))?\s*\{/g,
1281
+ /** Export type declaration */
1282
+ exportType: /export\s+(?:declare\s+)?type\s+(\w+)(?:\s*<([^>]*)>)?\s*=\s*([^;]+)/g,
1283
+ /** Export enum declaration */
1284
+ exportEnum: /export\s+(?:declare\s+)?(?:const\s+)?enum\s+(\w+)\s*\{/g,
1285
+ /** Import statement */
1286
+ importStatement: /import\s*(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s*from\s*['"]([^'"]+)['"]/g,
1287
+ /** Declare module (module augmentation) */
1288
+ declareModule: /declare\s+module\s+['"]([^'"]+)['"]\s*\{/g};
1289
+ function parseParameters(paramStr) {
1290
+ if (!paramStr.trim()) return [];
1291
+ const params = [];
1292
+ const parts = splitParameters(paramStr);
1293
+ for (const part of parts) {
1294
+ const trimmed = part.trim();
1295
+ if (!trimmed) continue;
1296
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
1297
+ const colonIndex = findTypeColonIndex(trimmed);
1298
+ if (colonIndex > 0) {
1299
+ params.push({
1300
+ name: "options",
1301
+ type: trimmed.slice(colonIndex + 1).trim(),
1302
+ optional: trimmed.includes("?")
1303
+ });
1304
+ }
1305
+ continue;
1306
+ }
1307
+ const match = trimmed.match(/^(\w+)(\?)?\s*:\s*(.+?)(?:\s*=\s*(.+))?$/);
1308
+ if (match) {
1309
+ const [, name, optional, type, defaultValue] = match;
1310
+ if (name && type) {
1311
+ params.push({
1312
+ name,
1313
+ type: type.trim(),
1314
+ optional: !!optional,
1315
+ defaultValue: defaultValue?.trim()
1316
+ });
1317
+ }
1318
+ } else {
1319
+ const nameMatch = trimmed.match(/^(\w+)(\?)?$/);
1320
+ if (nameMatch && nameMatch[1]) {
1321
+ params.push({
1322
+ name: nameMatch[1],
1323
+ type: "unknown",
1324
+ optional: !!nameMatch[2]
1325
+ });
1326
+ }
1327
+ }
1328
+ }
1329
+ return params;
1330
+ }
1331
+ function splitParameters(paramStr) {
1332
+ const parts = [];
1333
+ let current = "";
1334
+ let depth = 0;
1335
+ for (let i = 0; i < paramStr.length; i++) {
1336
+ const char = paramStr[i];
1337
+ if (char === "<" || char === "{" || char === "[" || char === "(") {
1338
+ depth++;
1339
+ current += char;
1340
+ } else if (char === ">" || char === "}" || char === "]" || char === ")") {
1341
+ depth--;
1342
+ current += char;
1343
+ } else if (char === "," && depth === 0) {
1344
+ parts.push(current);
1345
+ current = "";
1346
+ } else {
1347
+ current += char;
1348
+ }
1349
+ }
1350
+ if (current.trim()) {
1351
+ parts.push(current);
1352
+ }
1353
+ return parts;
1354
+ }
1355
+ function findTypeColonIndex(str) {
1356
+ let depth = 0;
1357
+ for (let i = 0; i < str.length; i++) {
1358
+ const char = str[i];
1359
+ if (char === "{" || char === "[" || char === "<" || char === "(") {
1360
+ depth++;
1361
+ } else if (char === "}" || char === "]" || char === ">" || char === ")") {
1362
+ depth--;
1363
+ } else if (char === ":" && depth === 0) {
1364
+ return i;
1365
+ }
1366
+ }
1367
+ return -1;
1368
+ }
1369
+ function extractBody(source, startIndex) {
1370
+ let depth = 0;
1371
+ let i = startIndex;
1372
+ while (i < source.length) {
1373
+ if (source[i] === "{") depth++;
1374
+ else if (source[i] === "}") {
1375
+ depth--;
1376
+ if (depth === 0) break;
1377
+ }
1378
+ i++;
1379
+ }
1380
+ return source.slice(startIndex + 1, i);
1381
+ }
1382
+ function parseClassMembers(body, comments, bodyOffset) {
1383
+ const methods = [];
1384
+ const properties = [];
1385
+ const methodPattern = /(?:(?:public|private|protected|static|readonly)\s+)*(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*:\s*([^;{]+)/g;
1386
+ let match;
1387
+ while ((match = methodPattern.exec(body)) !== null) {
1388
+ const [fullMatch, name, generics, params, returnType] = match;
1389
+ if (!name || !returnType) continue;
1390
+ const jsdoc = findPrecedingJSDoc(body, match.index, comments.map((c) => ({
1391
+ ...c,
1392
+ start: c.start - bodyOffset,
1393
+ end: c.end - bodyOffset
1394
+ })));
1395
+ methods.push({
1396
+ kind: "function",
1397
+ name,
1398
+ signature: `${name}${generics || ""}(${params || ""}): ${returnType.trim()}`,
1399
+ description: jsdoc?.description,
1400
+ params: mergeParamDocs(parseParameters(params || ""), jsdoc?.params),
1401
+ returns: {
1402
+ type: returnType.trim(),
1403
+ description: jsdoc?.returns?.description
1404
+ },
1405
+ examples: jsdoc?.examples
1406
+ });
1407
+ }
1408
+ const propPattern = /(?:(?:public|private|protected|static|readonly)\s+)*(\w+)(\?)?\s*:\s*([^;]+)/g;
1409
+ while ((match = propPattern.exec(body)) !== null) {
1410
+ const [, name, optional, type] = match;
1411
+ if (!name || !type) continue;
1412
+ if (type.includes("=>") || type.includes("(")) continue;
1413
+ properties.push({
1414
+ kind: "constant",
1415
+ name,
1416
+ signature: `${name}${optional || ""}: ${type.trim()}`,
1417
+ description: findPrecedingJSDoc(body, match.index)?.description
1418
+ });
1419
+ }
1420
+ return { methods, properties };
1421
+ }
1422
+ function mergeParamDocs(sigParams, jsdocParams) {
1423
+ if (!jsdocParams || jsdocParams.length === 0) return sigParams;
1424
+ return sigParams.map((param) => {
1425
+ const jsdocParam = jsdocParams.find((p) => p.name === param.name);
1426
+ if (jsdocParam) {
1427
+ return {
1428
+ ...param,
1429
+ description: jsdocParam.description || param.description,
1430
+ type: param.type || jsdocParam.type,
1431
+ optional: param.optional || jsdocParam.optional,
1432
+ defaultValue: param.defaultValue || jsdocParam.defaultValue
1433
+ };
1434
+ }
1435
+ return param;
1436
+ });
1437
+ }
1438
+ function parseEnumMembers(body) {
1439
+ const members = [];
1440
+ const pattern = /(\w+)\s*(?:=\s*([^,}]+))?/g;
1441
+ let match;
1442
+ while ((match = pattern.exec(body)) !== null) {
1443
+ const [, name, value] = match;
1444
+ if (!name) continue;
1445
+ let parsedValue;
1446
+ if (value !== void 0) {
1447
+ const trimmed = value.trim();
1448
+ const num = Number(trimmed);
1449
+ if (!isNaN(num)) {
1450
+ parsedValue = num;
1451
+ } else {
1452
+ parsedValue = trimmed.replace(/^['"]|['"]$/g, "");
1453
+ }
1454
+ }
1455
+ members.push({ name, value: parsedValue });
1456
+ }
1457
+ return members;
1458
+ }
1459
+ function parseDts(content, filePath) {
1460
+ const exports$1 = [];
1461
+ const imports = [];
1462
+ let moduleName;
1463
+ const comments = extractJSDocComments(content);
1464
+ const moduleMatch = PATTERNS.declareModule.exec(content);
1465
+ if (moduleMatch) {
1466
+ moduleName = moduleMatch[1];
1467
+ }
1468
+ let match;
1469
+ PATTERNS.exportFunction.lastIndex = 0;
1470
+ while ((match = PATTERNS.exportFunction.exec(content)) !== null) {
1471
+ const [fullMatch, name, generics, params, returnType] = match;
1472
+ if (!name || !returnType) continue;
1473
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1474
+ exports$1.push({
1475
+ kind: "function",
1476
+ name,
1477
+ signature: `function ${name}${generics || ""}(${params || ""}): ${returnType.trim()}`,
1478
+ description: jsdoc?.description,
1479
+ params: mergeParamDocs(parseParameters(params || ""), jsdoc?.params),
1480
+ returns: {
1481
+ type: returnType.trim(),
1482
+ description: jsdoc?.returns?.description
1483
+ },
1484
+ examples: jsdoc?.examples,
1485
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1486
+ since: jsdoc?.since,
1487
+ see: jsdoc?.see,
1488
+ sourceFile: filePath
1489
+ });
1490
+ }
1491
+ PATTERNS.exportConst.lastIndex = 0;
1492
+ while ((match = PATTERNS.exportConst.exec(content)) !== null) {
1493
+ const [, name, type] = match;
1494
+ if (!name || !type) continue;
1495
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1496
+ exports$1.push({
1497
+ kind: "constant",
1498
+ name,
1499
+ signature: `const ${name}: ${type.trim()}`,
1500
+ description: jsdoc?.description,
1501
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1502
+ sourceFile: filePath
1503
+ });
1504
+ }
1505
+ PATTERNS.exportClass.lastIndex = 0;
1506
+ while ((match = PATTERNS.exportClass.exec(content)) !== null) {
1507
+ const [, name, generics, extendsClause, implementsClause] = match;
1508
+ if (!name) continue;
1509
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1510
+ const bodyStart = match.index + match[0].length - 1;
1511
+ const body = extractBody(content, bodyStart);
1512
+ const { methods, properties } = parseClassMembers(body, comments, bodyStart);
1513
+ exports$1.push({
1514
+ kind: "class",
1515
+ name,
1516
+ signature: `class ${name}${generics ? `<${generics}>` : ""}`,
1517
+ description: jsdoc?.description,
1518
+ extends: extendsClause ? [extendsClause.trim()] : void 0,
1519
+ implements: implementsClause ? implementsClause.split(",").map((s) => s.trim()) : void 0,
1520
+ methods,
1521
+ properties,
1522
+ typeParams: generics ? generics.split(",").map((s) => s.trim()) : void 0,
1523
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1524
+ sourceFile: filePath
1525
+ });
1526
+ }
1527
+ PATTERNS.exportInterface.lastIndex = 0;
1528
+ while ((match = PATTERNS.exportInterface.exec(content)) !== null) {
1529
+ const [, name, generics, extendsClause] = match;
1530
+ if (!name) continue;
1531
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1532
+ const bodyStart = match.index + match[0].length - 1;
1533
+ const body = extractBody(content, bodyStart);
1534
+ const { methods, properties } = parseClassMembers(body, comments, bodyStart);
1535
+ exports$1.push({
1536
+ kind: "interface",
1537
+ name,
1538
+ signature: `interface ${name}${generics ? `<${generics}>` : ""}`,
1539
+ description: jsdoc?.description,
1540
+ extends: extendsClause ? extendsClause.split(",").map((s) => s.trim()) : void 0,
1541
+ methods,
1542
+ properties,
1543
+ typeParams: generics ? generics.split(",").map((s) => s.trim()) : void 0,
1544
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1545
+ sourceFile: filePath
1546
+ });
1547
+ }
1548
+ PATTERNS.exportType.lastIndex = 0;
1549
+ while ((match = PATTERNS.exportType.exec(content)) !== null) {
1550
+ const [, name, generics, definition] = match;
1551
+ if (!name || !definition) continue;
1552
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1553
+ exports$1.push({
1554
+ kind: "type",
1555
+ name,
1556
+ signature: `type ${name}${generics ? `<${generics}>` : ""} = ${definition.trim()}`,
1557
+ description: jsdoc?.description,
1558
+ typeParams: generics ? generics.split(",").map((s) => s.trim()) : void 0,
1559
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1560
+ sourceFile: filePath
1561
+ });
1562
+ }
1563
+ PATTERNS.exportEnum.lastIndex = 0;
1564
+ while ((match = PATTERNS.exportEnum.exec(content)) !== null) {
1565
+ const [, name] = match;
1566
+ if (!name) continue;
1567
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1568
+ const bodyStart = match.index + match[0].length - 1;
1569
+ const body = extractBody(content, bodyStart);
1570
+ const members = parseEnumMembers(body);
1571
+ exports$1.push({
1572
+ kind: "enum",
1573
+ name,
1574
+ signature: `enum ${name}`,
1575
+ description: jsdoc?.description,
1576
+ members,
1577
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1578
+ sourceFile: filePath
1579
+ });
1580
+ }
1581
+ PATTERNS.importStatement.lastIndex = 0;
1582
+ while ((match = PATTERNS.importStatement.exec(content)) !== null) {
1583
+ if (match[1]) {
1584
+ imports.push(match[1]);
1585
+ }
1586
+ }
1587
+ PATTERNS.declareModule.lastIndex = 0;
1588
+ while ((match = PATTERNS.declareModule.exec(content)) !== null) {
1589
+ const moduleBodyStart = match.index + match[0].length - 1;
1590
+ const moduleBody = extractBody(content, moduleBodyStart);
1591
+ const moduleExports = parseModuleAugmentation(moduleBody, comments, moduleBodyStart, filePath);
1592
+ for (const entry of moduleExports) {
1593
+ exports$1.push(entry);
1594
+ }
1595
+ }
1596
+ return { exports: exports$1, imports, moduleName };
1597
+ }
1598
+ function parseModuleAugmentation(body, _comments, _bodyOffset, filePath) {
1599
+ const entries = [];
1600
+ const moduleComments = extractJSDocComments(body);
1601
+ const interfacePattern = /interface\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^{]+))?\s*\{/g;
1602
+ let match;
1603
+ while ((match = interfacePattern.exec(body)) !== null) {
1604
+ const [, interfaceName, generics, extendsClause] = match;
1605
+ if (!interfaceName) continue;
1606
+ const ifaceBodyStart = match.index + match[0].length - 1;
1607
+ const ifaceBody = extractBody(body, ifaceBodyStart);
1608
+ if (interfaceName === "LoDashStatic" || interfaceName.endsWith("Static")) {
1609
+ const methods = parseInterfaceMethodsAsExports(
1610
+ ifaceBody,
1611
+ moduleComments,
1612
+ ifaceBodyStart,
1613
+ filePath
1614
+ );
1615
+ for (const method of methods) {
1616
+ entries.push(method);
1617
+ }
1618
+ }
1619
+ }
1620
+ return entries;
1621
+ }
1622
+ function parseInterfaceMethodsAsExports(body, _comments, _bodyOffset, filePath) {
1623
+ const methods = [];
1624
+ const bodyComments = extractJSDocComments(body);
1625
+ const methodPattern = /(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)\s*:\s*([^;]+);/g;
1626
+ let match;
1627
+ while ((match = methodPattern.exec(body)) !== null) {
1628
+ const [fullMatch, name, generics, params, returnType] = match;
1629
+ if (!name || !returnType) continue;
1630
+ if (["constructor", "toString", "valueOf", "toJSON"].includes(name)) continue;
1631
+ const jsdoc = findPrecedingJSDoc(body, match.index, bodyComments);
1632
+ methods.push({
1633
+ kind: "function",
1634
+ name,
1635
+ signature: `function ${name}${generics || ""}(${params || ""}): ${returnType.trim()}`,
1636
+ description: jsdoc?.description,
1637
+ params: mergeParamDocs(parseParameters(params || ""), jsdoc?.params),
1638
+ returns: {
1639
+ type: returnType.trim(),
1640
+ description: jsdoc?.returns?.description
1641
+ },
1642
+ examples: jsdoc?.examples,
1643
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1644
+ since: jsdoc?.since,
1645
+ see: jsdoc?.see,
1646
+ sourceFile: filePath
1647
+ });
1648
+ }
1649
+ return methods;
1650
+ }
1651
+ function sortExports(exports$1) {
1652
+ const kindOrder = {
1653
+ function: 1,
1654
+ class: 2,
1655
+ interface: 3,
1656
+ type: 4,
1657
+ enum: 5,
1658
+ constant: 6
1659
+ };
1660
+ return [...exports$1].sort((a, b) => {
1661
+ const kindDiff = kindOrder[a.kind] - kindOrder[b.kind];
1662
+ if (kindDiff !== 0) return kindDiff;
1663
+ return a.name.localeCompare(b.name);
1664
+ });
1665
+ }
1666
+ function findMainDtsFile(files, typesField) {
1667
+ if (typesField) {
1668
+ const normalized = typesField.replace(/^\.\//, "");
1669
+ if (files.has(normalized)) return normalized;
1670
+ }
1671
+ const priorities = [
1672
+ "index.d.ts",
1673
+ "dist/index.d.ts",
1674
+ "lib/index.d.ts",
1675
+ "types/index.d.ts",
1676
+ "src/index.d.ts",
1677
+ // @types packages merged via types-resolver plugin
1678
+ "__types__/index.d.ts",
1679
+ "__types__/dist/index.d.ts",
1680
+ "__types__/lib/index.d.ts",
1681
+ "__types__/types/index.d.ts"
1682
+ ];
1683
+ for (const path of priorities) {
1684
+ if (files.has(path)) return path;
1685
+ }
1686
+ for (const path of files.keys()) {
1687
+ if (path.endsWith(".d.ts") && !path.startsWith("__types__/")) {
1688
+ return path;
1689
+ }
1690
+ }
1691
+ for (const path of files.keys()) {
1692
+ if (path.endsWith(".d.ts") && path.startsWith("__types__/")) {
1693
+ return path;
1694
+ }
1695
+ }
1696
+ return void 0;
1697
+ }
1698
+
1699
+ // src/plugins/core/dts-parser.ts
1700
+ var dtsParserPlugin = {
1701
+ name: "dts-parser",
1702
+ version: "1.0.0",
1703
+ category: "parser",
1704
+ install(kernel) {
1705
+ kernel.on("parse:start", async (context) => {
1706
+ const { files } = context.package;
1707
+ const mainDts = findMainDtsFile(files, context.package.types);
1708
+ if (!mainDts) {
1709
+ return;
1710
+ }
1711
+ const dtsFiles = Array.from(files.entries()).filter(([path]) => path.endsWith(".d.ts")).sort(([a], [b]) => {
1712
+ if (a === mainDts) return -1;
1713
+ if (b === mainDts) return 1;
1714
+ if (a.includes("index.d.ts")) return -1;
1715
+ if (b.includes("index.d.ts")) return 1;
1716
+ return a.localeCompare(b);
1717
+ });
1718
+ const seenNames = /* @__PURE__ */ new Set();
1719
+ for (const [path, content] of dtsFiles) {
1720
+ try {
1721
+ const result = parseDts(content, path);
1722
+ for (const entry of result.exports) {
1723
+ if (!seenNames.has(entry.name)) {
1724
+ seenNames.add(entry.name);
1725
+ context.api.push(entry);
1726
+ }
1727
+ }
1728
+ } catch (error) {
1729
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
1730
+ }
1731
+ }
1732
+ context.api = sortExports(context.api);
1733
+ });
1734
+ }
1735
+ };
1736
+
1737
+ // src/parsers/typescript.ts
1738
+ var PATTERNS2 = {
1739
+ /** Export function */
1740
+ exportFunction: /export\s+(?:async\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(([^)]*)\)(?:\s*:\s*([^{]+))?\s*\{/g,
1741
+ /** Export arrow function */
1742
+ exportArrow: /export\s+const\s+(\w+)\s*(?::\s*([^=]+))?\s*=\s*(?:async\s*)?\([^)]*\)\s*(?::\s*([^=]+))?\s*=>/g,
1743
+ /** Export class */
1744
+ exportClass: /export\s+(?:abstract\s+)?class\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^\s{]+))?(?:\s+implements\s+([^{]+))?\s*\{/g,
1745
+ /** Export interface */
1746
+ exportInterface: /export\s+interface\s+(\w+)(?:\s*<([^>]*)>)?(?:\s+extends\s+([^{]+))?\s*\{/g,
1747
+ /** Export type */
1748
+ exportType: /export\s+type\s+(\w+)(?:\s*<([^>]*)>)?\s*=\s*([^;]+)/g,
1749
+ /** Export const/let */
1750
+ exportConst: /export\s+(?:const|let)\s+(\w+)(?:\s*:\s*([^=]+))?\s*=/g,
1751
+ /** Export enum */
1752
+ exportEnum: /export\s+(?:const\s+)?enum\s+(\w+)\s*\{/g};
1753
+ function parseSourceParams(paramStr) {
1754
+ if (!paramStr.trim()) return [];
1755
+ const params = [];
1756
+ const parts = splitParams(paramStr);
1757
+ for (const part of parts) {
1758
+ const trimmed = part.trim();
1759
+ if (!trimmed) continue;
1760
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
1761
+ const colonIndex = findBalancedColon(trimmed);
1762
+ if (colonIndex > 0) {
1763
+ params.push({
1764
+ name: "options",
1765
+ type: trimmed.slice(colonIndex + 1).trim(),
1766
+ optional: trimmed.includes("?")
1767
+ });
1768
+ } else {
1769
+ params.push({
1770
+ name: "options",
1771
+ type: "object"
1772
+ });
1773
+ }
1774
+ continue;
1775
+ }
1776
+ const match = trimmed.match(/^(\w+)(\?)?\s*(?::\s*(.+?))?(?:\s*=\s*(.+))?$/);
1777
+ if (match && match[1]) {
1778
+ const [, name, optional, type, defaultValue] = match;
1779
+ params.push({
1780
+ name,
1781
+ type: type?.trim() || inferTypeFromDefault(defaultValue),
1782
+ optional: !!optional || !!defaultValue,
1783
+ defaultValue: defaultValue?.trim()
1784
+ });
1785
+ }
1786
+ }
1787
+ return params;
1788
+ }
1789
+ function splitParams(str) {
1790
+ const parts = [];
1791
+ let current = "";
1792
+ let depth = 0;
1793
+ for (const char of str) {
1794
+ if (char === "<" || char === "{" || char === "[" || char === "(") {
1795
+ depth++;
1796
+ current += char;
1797
+ } else if (char === ">" || char === "}" || char === "]" || char === ")") {
1798
+ depth--;
1799
+ current += char;
1800
+ } else if (char === "," && depth === 0) {
1801
+ parts.push(current);
1802
+ current = "";
1803
+ } else {
1804
+ current += char;
1805
+ }
1806
+ }
1807
+ if (current.trim()) parts.push(current);
1808
+ return parts;
1809
+ }
1810
+ function findBalancedColon(str) {
1811
+ let depth = 0;
1812
+ for (let i = 0; i < str.length; i++) {
1813
+ const char = str[i];
1814
+ if (char === "{" || char === "[" || char === "<" || char === "(") {
1815
+ depth++;
1816
+ } else if (char === "}" || char === "]" || char === ">" || char === ")") {
1817
+ depth--;
1818
+ } else if (char === ":" && depth === 0) {
1819
+ return i;
1820
+ }
1821
+ }
1822
+ return -1;
1823
+ }
1824
+ function inferTypeFromDefault(defaultValue) {
1825
+ if (!defaultValue) return "unknown";
1826
+ const trimmed = defaultValue.trim();
1827
+ if (trimmed === "true" || trimmed === "false") return "boolean";
1828
+ if (trimmed.startsWith("'") || trimmed.startsWith('"') || trimmed.startsWith("`")) {
1829
+ return "string";
1830
+ }
1831
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) return "number";
1832
+ if (trimmed === "null") return "null";
1833
+ if (trimmed === "undefined") return "undefined";
1834
+ if (trimmed.startsWith("[")) return "unknown[]";
1835
+ if (trimmed.startsWith("{")) return "object";
1836
+ if (trimmed.startsWith("()") || trimmed.includes("=>")) return "Function";
1837
+ return "unknown";
1838
+ }
1839
+ function parseTypeScript(content, filePath) {
1840
+ const exports$1 = [];
1841
+ let hasTypes = false;
1842
+ hasTypes = /:\s*\w+/.test(content) || content.includes("interface ") || content.includes("type ");
1843
+ const comments = extractJSDocComments(content);
1844
+ let match;
1845
+ PATTERNS2.exportFunction.lastIndex = 0;
1846
+ while ((match = PATTERNS2.exportFunction.exec(content)) !== null) {
1847
+ const [, name, generics, params, returnType] = match;
1848
+ if (!name) continue;
1849
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1850
+ const paramStr = params || "";
1851
+ exports$1.push({
1852
+ kind: "function",
1853
+ name,
1854
+ signature: `function ${name}${generics || ""}(${paramStr})${returnType ? `: ${returnType.trim()}` : ""}`,
1855
+ description: jsdoc?.description,
1856
+ params: mergeParams(parseSourceParams(paramStr), jsdoc?.params),
1857
+ returns: returnType ? { type: returnType.trim(), description: jsdoc?.returns?.description } : void 0,
1858
+ examples: jsdoc?.examples,
1859
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1860
+ sourceFile: filePath
1861
+ });
1862
+ }
1863
+ PATTERNS2.exportArrow.lastIndex = 0;
1864
+ while ((match = PATTERNS2.exportArrow.exec(content)) !== null) {
1865
+ const [fullMatch, name, typeAnnotation, returnType] = match;
1866
+ if (!name || !fullMatch) continue;
1867
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1868
+ const paramsStart = fullMatch.indexOf("(");
1869
+ const paramsEnd = fullMatch.indexOf(")", paramsStart);
1870
+ const params = fullMatch.slice(paramsStart + 1, paramsEnd);
1871
+ exports$1.push({
1872
+ kind: "function",
1873
+ name,
1874
+ signature: typeAnnotation ? `const ${name}: ${typeAnnotation.trim()}` : `const ${name} = (${params})${returnType ? ` => ${returnType.trim()}` : ""}`,
1875
+ description: jsdoc?.description,
1876
+ params: mergeParams(parseSourceParams(params), jsdoc?.params),
1877
+ returns: returnType ? { type: returnType.trim(), description: jsdoc?.returns?.description } : void 0,
1878
+ examples: jsdoc?.examples,
1879
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1880
+ sourceFile: filePath
1881
+ });
1882
+ }
1883
+ PATTERNS2.exportClass.lastIndex = 0;
1884
+ while ((match = PATTERNS2.exportClass.exec(content)) !== null) {
1885
+ const [, name, generics, extendsClause, implementsClause] = match;
1886
+ if (!name) continue;
1887
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1888
+ exports$1.push({
1889
+ kind: "class",
1890
+ name,
1891
+ signature: `class ${name}${generics ? `<${generics}>` : ""}`,
1892
+ description: jsdoc?.description,
1893
+ extends: extendsClause ? [extendsClause.trim()] : void 0,
1894
+ implements: implementsClause ? implementsClause.split(",").map((s) => s.trim()) : void 0,
1895
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1896
+ sourceFile: filePath
1897
+ });
1898
+ }
1899
+ PATTERNS2.exportInterface.lastIndex = 0;
1900
+ while ((match = PATTERNS2.exportInterface.exec(content)) !== null) {
1901
+ const [, name, generics, extendsClause] = match;
1902
+ if (!name) continue;
1903
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1904
+ exports$1.push({
1905
+ kind: "interface",
1906
+ name,
1907
+ signature: `interface ${name}${generics ? `<${generics}>` : ""}`,
1908
+ description: jsdoc?.description,
1909
+ extends: extendsClause ? extendsClause.split(",").map((s) => s.trim()) : void 0,
1910
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1911
+ sourceFile: filePath
1912
+ });
1913
+ }
1914
+ PATTERNS2.exportType.lastIndex = 0;
1915
+ while ((match = PATTERNS2.exportType.exec(content)) !== null) {
1916
+ const [, name, generics, definition] = match;
1917
+ if (!name || !definition) continue;
1918
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1919
+ exports$1.push({
1920
+ kind: "type",
1921
+ name,
1922
+ signature: `type ${name}${generics ? `<${generics}>` : ""} = ${definition.trim()}`,
1923
+ description: jsdoc?.description,
1924
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1925
+ sourceFile: filePath
1926
+ });
1927
+ }
1928
+ PATTERNS2.exportConst.lastIndex = 0;
1929
+ while ((match = PATTERNS2.exportConst.exec(content)) !== null) {
1930
+ const [, name, type] = match;
1931
+ if (!name) continue;
1932
+ if (content.slice(match.index, match.index + 200).includes("=>")) continue;
1933
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1934
+ exports$1.push({
1935
+ kind: "constant",
1936
+ name,
1937
+ signature: `const ${name}${type ? `: ${type.trim()}` : ""}`,
1938
+ description: jsdoc?.description,
1939
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1940
+ sourceFile: filePath
1941
+ });
1942
+ }
1943
+ PATTERNS2.exportEnum.lastIndex = 0;
1944
+ while ((match = PATTERNS2.exportEnum.exec(content)) !== null) {
1945
+ const [, name] = match;
1946
+ if (!name) continue;
1947
+ const jsdoc = findPrecedingJSDoc(content, match.index, comments);
1948
+ exports$1.push({
1949
+ kind: "enum",
1950
+ name,
1951
+ signature: `enum ${name}`,
1952
+ description: jsdoc?.description,
1953
+ deprecated: jsdoc?.deprecated ? jsdoc.deprecated : void 0,
1954
+ sourceFile: filePath
1955
+ });
1956
+ }
1957
+ return { exports: exports$1, hasTypes };
1958
+ }
1959
+ function mergeParams(sourceParams, jsdocParams) {
1960
+ if (!jsdocParams || jsdocParams.length === 0) return sourceParams;
1961
+ return sourceParams.map((param) => {
1962
+ const jsdocParam = jsdocParams.find((p) => p.name === param.name);
1963
+ if (jsdocParam) {
1964
+ return {
1965
+ ...param,
1966
+ description: jsdocParam.description || param.description,
1967
+ type: param.type !== "unknown" ? param.type : jsdocParam.type
1968
+ };
1969
+ }
1970
+ return param;
1971
+ });
1972
+ }
1973
+ function findTypeScriptFiles(files, mainField) {
1974
+ const tsFiles = [];
1975
+ const priorities = [];
1976
+ if (mainField) {
1977
+ const base = mainField.replace(/^\.\//, "").replace(/\.[jt]sx?$/, "");
1978
+ priorities.push(
1979
+ `${base}.ts`,
1980
+ `${base}.tsx`,
1981
+ `src/${base}.ts`,
1982
+ `src/${base}.tsx`
1983
+ );
1984
+ }
1985
+ priorities.push(
1986
+ "src/index.ts",
1987
+ "src/index.tsx",
1988
+ "index.ts",
1989
+ "index.tsx",
1990
+ "lib/index.ts",
1991
+ "src/main.ts"
1992
+ );
1993
+ for (const path of priorities) {
1994
+ if (files.has(path) && !tsFiles.includes(path)) {
1995
+ tsFiles.push(path);
1996
+ }
1997
+ }
1998
+ for (const path of files.keys()) {
1999
+ if ((path.endsWith(".ts") || path.endsWith(".tsx")) && !path.endsWith(".d.ts")) {
2000
+ if (!tsFiles.includes(path)) {
2001
+ tsFiles.push(path);
2002
+ }
2003
+ }
2004
+ }
2005
+ return tsFiles;
2006
+ }
2007
+
2008
+ // src/plugins/core/ts-source-parser.ts
2009
+ var tsSourceParserPlugin = {
2010
+ name: "ts-source-parser",
2011
+ version: "1.0.0",
2012
+ category: "parser",
2013
+ install(kernel) {
2014
+ kernel.on("parse:start", async (context) => {
2015
+ if (context.api.length > 0) {
2016
+ return;
2017
+ }
2018
+ const { files } = context.package;
2019
+ const tsFiles = findTypeScriptFiles(files, context.package.main);
2020
+ if (tsFiles.length === 0) {
2021
+ return;
2022
+ }
2023
+ const seenNames = /* @__PURE__ */ new Set();
2024
+ for (const path of tsFiles) {
2025
+ const content = files.get(path);
2026
+ if (!content) continue;
2027
+ try {
2028
+ const result = parseTypeScript(content, path);
2029
+ for (const entry of result.exports) {
2030
+ if (!seenNames.has(entry.name)) {
2031
+ seenNames.add(entry.name);
2032
+ context.api.push(entry);
2033
+ }
2034
+ }
2035
+ } catch (error) {
2036
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2037
+ }
2038
+ }
2039
+ context.api = sortExports(context.api);
2040
+ });
2041
+ }
2042
+ };
2043
+
2044
+ // src/parsers/readme.ts
2045
+ var SECTION_PATTERNS = {
2046
+ installation: /^#+\s*(installation|install|setup|getting started)/i,
2047
+ quickStart: /^#+\s*(quick\s*start|usage|getting\s*started|basic\s*usage)/i,
2048
+ api: /^#+\s*(api|api\s*reference|reference|methods|functions)/i,
2049
+ examples: /^#+\s*(examples?|code\s*examples?)/i};
2050
+ var BADGE_PATTERN = /\[!\[([^\]]*)\]\(([^)]+)\)\]\([^)]+\)|\!\[([^\]]*)\]\(([^)]+)\)/g;
2051
+ var CODE_BLOCK_PATTERN = /```(\w+)?\s*\n([\s\S]*?)```/g;
2052
+ function parseReadme(content) {
2053
+ const sections = extractSections(content);
2054
+ const badges = extractBadges(content);
2055
+ const { title, description } = extractTitleAndDescription(content, sections);
2056
+ const installation = findSection(sections, SECTION_PATTERNS.installation);
2057
+ const quickStart = findSection(sections, SECTION_PATTERNS.quickStart);
2058
+ const api = findSection(sections, SECTION_PATTERNS.api);
2059
+ const examples = findExampleSections(sections);
2060
+ return {
2061
+ title,
2062
+ description,
2063
+ badges,
2064
+ installation: installation?.content,
2065
+ quickStart: quickStart?.content || findQuickStartFromCode(content),
2066
+ examples,
2067
+ api: api?.content,
2068
+ sections
2069
+ };
2070
+ }
2071
+ function extractSections(content) {
2072
+ const sections = [];
2073
+ const lines = content.split("\n");
2074
+ let currentSection = null;
2075
+ let currentContent = [];
2076
+ let charIndex = 0;
2077
+ function finishSection() {
2078
+ if (currentSection) {
2079
+ currentSection.content = currentContent.join("\n").trim();
2080
+ currentSection.endIndex = charIndex;
2081
+ sections.push(currentSection);
2082
+ currentContent = [];
2083
+ }
2084
+ }
2085
+ for (const line of lines) {
2086
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
2087
+ if (headingMatch && headingMatch[1] && headingMatch[2]) {
2088
+ finishSection();
2089
+ const level = headingMatch[1].length;
2090
+ const title = headingMatch[2].trim();
2091
+ currentSection = {
2092
+ title,
2093
+ content: "",
2094
+ level,
2095
+ startIndex: charIndex,
2096
+ endIndex: 0
2097
+ };
2098
+ currentContent = [];
2099
+ } else if (currentSection) {
2100
+ currentContent.push(line);
2101
+ }
2102
+ charIndex += line.length + 1;
2103
+ }
2104
+ finishSection();
2105
+ return sections;
2106
+ }
2107
+ function findSection(sections, pattern) {
2108
+ return sections.find((s) => pattern.test(`# ${s.title}`));
2109
+ }
2110
+ function findExampleSections(sections) {
2111
+ const examples = [];
2112
+ for (const section of sections) {
2113
+ if (SECTION_PATTERNS.examples.test(`# ${section.title}`)) {
2114
+ const codeBlocks = extractCodeBlocks(section.content);
2115
+ examples.push(...codeBlocks);
2116
+ }
2117
+ }
2118
+ return examples;
2119
+ }
2120
+ function extractCodeBlocks(content) {
2121
+ const blocks = [];
2122
+ const pattern = new RegExp(CODE_BLOCK_PATTERN.source, "g");
2123
+ let match;
2124
+ while ((match = pattern.exec(content)) !== null) {
2125
+ const [, language, code] = match;
2126
+ if (code && code.trim()) {
2127
+ blocks.push(language ? `\`\`\`${language}
2128
+ ${code.trim()}
2129
+ \`\`\`` : code.trim());
2130
+ }
2131
+ }
2132
+ return blocks;
2133
+ }
2134
+ function extractBadges(content) {
2135
+ const badges = [];
2136
+ const pattern = new RegExp(BADGE_PATTERN.source, "g");
2137
+ let match;
2138
+ while ((match = pattern.exec(content)) !== null) {
2139
+ const altText = match[1] || match[3] || "";
2140
+ if (altText) {
2141
+ badges.push(altText);
2142
+ }
2143
+ }
2144
+ return badges;
2145
+ }
2146
+ function extractTitleAndDescription(content, sections) {
2147
+ let title;
2148
+ let description;
2149
+ const firstHeading = sections[0];
2150
+ if (firstHeading?.level === 1) {
2151
+ title = firstHeading.title;
2152
+ } else {
2153
+ const lines = content.split("\n");
2154
+ for (const line of lines) {
2155
+ const trimmed = line.trim();
2156
+ if (!trimmed) continue;
2157
+ if (trimmed.startsWith("!") || trimmed.startsWith("[!")) continue;
2158
+ if (trimmed.startsWith("#")) {
2159
+ title = trimmed.replace(/^#+\s*/, "");
2160
+ break;
2161
+ }
2162
+ }
2163
+ }
2164
+ const afterTitle = content.split("\n").slice(1);
2165
+ let foundContent = false;
2166
+ for (const line of afterTitle) {
2167
+ const trimmed = line.trim();
2168
+ if (trimmed.startsWith("!") || trimmed.startsWith("[!")) continue;
2169
+ if (trimmed.startsWith("#")) break;
2170
+ if (!trimmed && !foundContent) continue;
2171
+ if (!trimmed && foundContent) break;
2172
+ if (trimmed) {
2173
+ foundContent = true;
2174
+ if (!description) {
2175
+ description = trimmed;
2176
+ } else {
2177
+ description += " " + trimmed;
2178
+ }
2179
+ }
2180
+ }
2181
+ if (description) {
2182
+ description = description.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").trim();
2183
+ }
2184
+ return { title, description };
2185
+ }
2186
+ function findQuickStartFromCode(content) {
2187
+ const installMatch = content.match(/installation|install|setup/i);
2188
+ const startIndex = installMatch?.index ?? 0;
2189
+ const searchArea = content.slice(startIndex, startIndex + 2e3);
2190
+ const codeBlocks = extractCodeBlocks(searchArea);
2191
+ for (const block of codeBlocks) {
2192
+ if (block.startsWith("```javascript") || block.startsWith("```typescript") || block.startsWith("```js") || block.startsWith("```ts") || block.startsWith("```jsx") || block.startsWith("```tsx")) {
2193
+ return block;
2194
+ }
2195
+ }
2196
+ return codeBlocks[0];
2197
+ }
2198
+
2199
+ // src/plugins/core/readme-parser.ts
2200
+ var readmeParserPlugin = {
2201
+ name: "readme-parser",
2202
+ version: "1.0.0",
2203
+ category: "parser",
2204
+ install(kernel) {
2205
+ kernel.on("parse:start", async (context) => {
2206
+ const { files } = context.package;
2207
+ let readmeContent;
2208
+ const readmePatterns = [
2209
+ "README.md",
2210
+ "readme.md",
2211
+ "Readme.md",
2212
+ "README.MD",
2213
+ "README",
2214
+ "readme"
2215
+ ];
2216
+ for (const pattern of readmePatterns) {
2217
+ if (files.has(pattern)) {
2218
+ readmeContent = files.get(pattern);
2219
+ break;
2220
+ }
2221
+ }
2222
+ if (!readmeContent) {
2223
+ for (const [path, content] of files) {
2224
+ if (path.toLowerCase().includes("readme")) {
2225
+ readmeContent = content;
2226
+ break;
2227
+ }
2228
+ }
2229
+ }
2230
+ if (!readmeContent) {
2231
+ return;
2232
+ }
2233
+ try {
2234
+ context.readme = parseReadme(readmeContent);
2235
+ if (!context.package.description && context.readme.description) {
2236
+ context.package.description = context.readme.description;
2237
+ }
2238
+ } catch (error) {
2239
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2240
+ }
2241
+ });
2242
+ }
2243
+ };
2244
+
2245
+ // src/core/tokens.ts
2246
+ var CHARS_PER_TOKEN = {
2247
+ /** English prose: ~4 chars per token */
2248
+ prose: 4,
2249
+ /** Code blocks: ~3 chars per token (more special tokens) */
2250
+ code: 3};
2251
+ var PRIORITY_ORDER = {
2252
+ functions: 100,
2253
+ examples: 90,
2254
+ classes: 80,
2255
+ interfaces: 70,
2256
+ types: 60,
2257
+ readme: 50
2258
+ };
2259
+ function countTokens(text) {
2260
+ if (!text) return 0;
2261
+ let tokens = 0;
2262
+ const codeBlockRegex = /```[\s\S]*?```/g;
2263
+ const parts = [];
2264
+ let lastIndex = 0;
2265
+ let match;
2266
+ while ((match = codeBlockRegex.exec(text)) !== null) {
2267
+ if (match.index > lastIndex) {
2268
+ parts.push({
2269
+ text: text.slice(lastIndex, match.index),
2270
+ isCode: false
2271
+ });
2272
+ }
2273
+ parts.push({
2274
+ text: match[0],
2275
+ isCode: true
2276
+ });
2277
+ lastIndex = match.index + match[0].length;
2278
+ }
2279
+ if (lastIndex < text.length) {
2280
+ parts.push({
2281
+ text: text.slice(lastIndex),
2282
+ isCode: false
2283
+ });
2284
+ }
2285
+ for (const part of parts) {
2286
+ const charsPerToken = part.isCode ? CHARS_PER_TOKEN.code : CHARS_PER_TOKEN.prose;
2287
+ tokens += Math.ceil(part.text.length / charsPerToken);
2288
+ }
2289
+ return tokens;
2290
+ }
2291
+ function parseSections(text) {
2292
+ const sections = [];
2293
+ const lines = text.split("\n");
2294
+ let currentSection = null;
2295
+ let currentContent = [];
2296
+ function finishSection() {
2297
+ if (currentSection) {
2298
+ currentSection.content = currentContent.join("\n").trim();
2299
+ currentSection.tokens = countTokens(currentSection.content);
2300
+ sections.push(currentSection);
2301
+ currentContent = [];
2302
+ }
2303
+ }
2304
+ for (const line of lines) {
2305
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
2306
+ if (headingMatch && headingMatch[2]) {
2307
+ finishSection();
2308
+ const title = headingMatch[2].trim();
2309
+ const priority = inferPriority(title);
2310
+ currentSection = {
2311
+ id: title.toLowerCase().replace(/[^a-z0-9]+/g, "-"),
2312
+ title,
2313
+ content: "",
2314
+ priority,
2315
+ tokens: 0
2316
+ };
2317
+ currentContent = [line];
2318
+ } else if (currentSection) {
2319
+ currentContent.push(line);
2320
+ } else {
2321
+ if (line.trim()) {
2322
+ if (!currentSection) {
2323
+ currentSection = {
2324
+ id: "intro",
2325
+ title: "Introduction",
2326
+ content: "",
2327
+ priority: "readme",
2328
+ tokens: 0
2329
+ };
2330
+ }
2331
+ currentContent.push(line);
2332
+ }
2333
+ }
2334
+ }
2335
+ finishSection();
2336
+ return sections;
2337
+ }
2338
+ function inferPriority(title) {
2339
+ const lower = title.toLowerCase();
2340
+ if (lower.includes("function") || lower.includes("method") || lower.includes("api")) {
2341
+ return "functions";
2342
+ }
2343
+ if (lower.includes("example") || lower.includes("usage") || lower.includes("quick start")) {
2344
+ return "examples";
2345
+ }
2346
+ if (lower.includes("class")) {
2347
+ return "classes";
2348
+ }
2349
+ if (lower.includes("interface")) {
2350
+ return "interfaces";
2351
+ }
2352
+ if (lower.includes("type")) {
2353
+ return "types";
2354
+ }
2355
+ return "readme";
2356
+ }
2357
+ function prioritizeSections(sections, priorities = ["functions", "examples"]) {
2358
+ const customOrder = { ...PRIORITY_ORDER };
2359
+ priorities.forEach((p, i) => {
2360
+ customOrder[p] = 1e3 - i;
2361
+ });
2362
+ return [...sections].sort((a, b) => {
2363
+ return (customOrder[b.priority] ?? 0) - (customOrder[a.priority] ?? 0);
2364
+ });
2365
+ }
2366
+ function truncateToTokenLimit(text, limit, priorities = ["functions", "examples"]) {
2367
+ const currentTokens = countTokens(text);
2368
+ if (currentTokens <= limit) {
2369
+ return {
2370
+ text,
2371
+ truncated: false,
2372
+ tokenCount: currentTokens,
2373
+ includedSections: [],
2374
+ removedSections: []
2375
+ };
2376
+ }
2377
+ const sections = parseSections(text);
2378
+ const prioritized = prioritizeSections(sections, priorities);
2379
+ const included = [];
2380
+ const removed = [];
2381
+ let usedTokens = 0;
2382
+ for (const section of prioritized) {
2383
+ if (usedTokens + section.tokens <= limit) {
2384
+ included.push(section);
2385
+ usedTokens += section.tokens;
2386
+ } else {
2387
+ const remaining = limit - usedTokens;
2388
+ if (remaining > 50 && section.tokens > 0) {
2389
+ const truncated = truncateSectionContent(section, remaining);
2390
+ if (truncated) {
2391
+ included.push(truncated);
2392
+ usedTokens += truncated.tokens;
2393
+ }
2394
+ }
2395
+ removed.push(section);
2396
+ }
2397
+ }
2398
+ const sectionOrder = sections.map((s) => s.id);
2399
+ included.sort((a, b) => sectionOrder.indexOf(a.id) - sectionOrder.indexOf(b.id));
2400
+ const output = included.map((s) => s.content).join("\n\n");
2401
+ return {
2402
+ text: output.trim(),
2403
+ truncated: true,
2404
+ tokenCount: countTokens(output),
2405
+ includedSections: included.map((s) => s.title),
2406
+ removedSections: removed.map((s) => s.title)
2407
+ };
2408
+ }
2409
+ function truncateSectionContent(section, maxTokens) {
2410
+ const lines = section.content.split("\n");
2411
+ const truncatedLines = [];
2412
+ let tokens = 0;
2413
+ for (const line of lines) {
2414
+ const lineTokens = countTokens(line);
2415
+ if (tokens + lineTokens <= maxTokens) {
2416
+ truncatedLines.push(line);
2417
+ tokens += lineTokens;
2418
+ } else {
2419
+ break;
2420
+ }
2421
+ }
2422
+ if (truncatedLines.length === 0) {
2423
+ return null;
2424
+ }
2425
+ truncatedLines.push("\n...(truncated)");
2426
+ return {
2427
+ ...section,
2428
+ content: truncatedLines.join("\n"),
2429
+ tokens: countTokens(truncatedLines.join("\n"))
2430
+ };
2431
+ }
2432
+ function formatTokenCount(tokens) {
2433
+ if (tokens < 1e3) {
2434
+ return `${tokens} tokens`;
2435
+ }
2436
+ return `${(tokens / 1e3).toFixed(1)}k tokens`;
2437
+ }
2438
+
2439
+ // src/outputs/llms.ts
2440
+ var DEFAULT_LLMS_TOKEN_LIMIT = Infinity;
2441
+ function generateLlmsTxt(context, options = {}) {
2442
+ const {
2443
+ tokenLimit = DEFAULT_LLMS_TOKEN_LIMIT,
2444
+ includeInstall = true,
2445
+ includeQuickStart = true,
2446
+ maxFunctions = Infinity,
2447
+ maxClasses = Infinity
2448
+ } = options;
2449
+ const { package: pkg, api, readme } = context;
2450
+ const sections = [];
2451
+ sections.push(`# ${pkg.name}`);
2452
+ if (pkg.description) {
2453
+ sections.push(`
2454
+ > ${pkg.description}`);
2455
+ }
2456
+ sections.push("");
2457
+ if (includeInstall) {
2458
+ sections.push("## Install\n");
2459
+ sections.push("```bash");
2460
+ sections.push(`npm install ${pkg.name}`);
2461
+ sections.push("```\n");
2462
+ }
2463
+ if (includeQuickStart && readme?.quickStart) {
2464
+ sections.push("## Quick Start\n");
2465
+ sections.push(readme.quickStart);
2466
+ sections.push("");
2467
+ }
2468
+ sections.push("## API\n");
2469
+ const functions = api.filter((e) => e.kind === "function");
2470
+ const classes = api.filter((e) => e.kind === "class");
2471
+ const interfaces = api.filter((e) => e.kind === "interface");
2472
+ const types = api.filter((e) => e.kind === "type");
2473
+ const constants = api.filter((e) => e.kind === "constant");
2474
+ if (functions.length > 0) {
2475
+ sections.push("### Functions\n");
2476
+ const limit = Math.min(functions.length, maxFunctions);
2477
+ for (let i = 0; i < limit; i++) {
2478
+ sections.push(formatFunctionBrief(functions[i]));
2479
+ }
2480
+ if (functions.length > maxFunctions && maxFunctions < Infinity) {
2481
+ sections.push(`
2482
+ ...and ${functions.length - maxFunctions} more functions.`);
2483
+ }
2484
+ sections.push("");
2485
+ }
2486
+ if (classes.length > 0) {
2487
+ sections.push("### Classes\n");
2488
+ const limit = Math.min(classes.length, maxClasses);
2489
+ for (let i = 0; i < limit; i++) {
2490
+ sections.push(formatClassBrief(classes[i]));
2491
+ }
2492
+ if (classes.length > maxClasses && maxClasses < Infinity) {
2493
+ sections.push(`
2494
+ ...and ${classes.length - maxClasses} more classes.`);
2495
+ }
2496
+ sections.push("");
2497
+ }
2498
+ if (interfaces.length > 0 || types.length > 0) {
2499
+ sections.push("### Types\n");
2500
+ const allTypes = [...interfaces, ...types];
2501
+ for (const t of allTypes) {
2502
+ const desc = t.description ? ` - ${truncate(t.description, 80)}` : "";
2503
+ sections.push(`- \`${t.name}\`${desc}`);
2504
+ }
2505
+ sections.push("");
2506
+ }
2507
+ if (constants.length > 0) {
2508
+ sections.push("### Constants\n");
2509
+ for (const c of constants) {
2510
+ const desc = c.description ? ` - ${truncate(c.description, 80)}` : "";
2511
+ sections.push(`- \`${c.name}\`${desc}`);
2512
+ }
2513
+ sections.push("");
2514
+ }
2515
+ let output = sections.join("\n");
2516
+ const currentTokens = countTokens(output);
2517
+ if (currentTokens > tokenLimit) {
2518
+ const result = truncateToTokenLimit(output, tokenLimit, ["functions", "examples"]);
2519
+ output = result.text;
2520
+ context.truncated = result.truncated;
2521
+ }
2522
+ context.tokenCount = countTokens(output);
2523
+ return output;
2524
+ }
2525
+ function formatFunctionBrief(fn) {
2526
+ const params = fn.params?.map((p) => `${p.name}${p.optional ? "?" : ""}`).join(", ") || "";
2527
+ const returnType = fn.returns?.type ? `: ${simplifyType(fn.returns.type)}` : "";
2528
+ const desc = fn.description ? ` - ${truncate(fn.description, 60)}` : "";
2529
+ return `- \`${fn.name}(${params})${returnType}\`${desc}`;
2530
+ }
2531
+ function formatClassBrief(cls) {
2532
+ const lines = [];
2533
+ const desc = cls.description ? ` - ${truncate(cls.description, 60)}` : "";
2534
+ lines.push(`- \`${cls.name}\`${desc}`);
2535
+ if (cls.methods && cls.methods.length > 0) {
2536
+ const keyMethods = cls.methods.slice(0, 3);
2537
+ for (const method of keyMethods) {
2538
+ lines.push(` - \`${method.name}()\``);
2539
+ }
2540
+ if (cls.methods.length > 3) {
2541
+ lines.push(` - ...${cls.methods.length - 3} more methods`);
2542
+ }
2543
+ }
2544
+ return lines.join("\n");
2545
+ }
2546
+ function simplifyType(type) {
2547
+ if (type.length > 30) {
2548
+ const genericStart = type.indexOf("<");
2549
+ if (genericStart > 0) {
2550
+ return type.slice(0, genericStart) + "<...>";
2551
+ }
2552
+ }
2553
+ return type;
2554
+ }
2555
+ function truncate(text, maxLength) {
2556
+ if (text.length <= maxLength) return text;
2557
+ return text.slice(0, maxLength - 3) + "...";
2558
+ }
2559
+
2560
+ // src/plugins/core/llms-output.ts
2561
+ var llmsOutputPlugin = {
2562
+ name: "llms-output",
2563
+ version: "1.0.0",
2564
+ category: "output",
2565
+ install(kernel) {
2566
+ kernel.on("output:start", async (context) => {
2567
+ if (!context.options.formats?.includes("llms")) {
2568
+ return;
2569
+ }
2570
+ try {
2571
+ const tokenLimit = context.options.llmsTokenLimit ?? DEFAULT_LLMS_TOKEN_LIMIT;
2572
+ const output = generateLlmsTxt(context, {
2573
+ tokenLimit,
2574
+ includeInstall: true,
2575
+ includeQuickStart: true
2576
+ });
2577
+ context.outputs.set("llms", output);
2578
+ } catch (error) {
2579
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2580
+ }
2581
+ });
2582
+ }
2583
+ };
2584
+
2585
+ // src/outputs/llms-full.ts
2586
+ function generateLlmsFullTxt(context, options = {}) {
2587
+ const {
2588
+ includeExamples = true,
2589
+ includeParamDescriptions = true,
2590
+ includeSourceLocations = false,
2591
+ includeDeprecations = true
2592
+ } = options;
2593
+ const { package: pkg, api, readme } = context;
2594
+ const sections = [];
2595
+ sections.push(`# ${pkg.name} v${pkg.version}`);
2596
+ if (pkg.description) {
2597
+ sections.push(`
2598
+ > ${pkg.description}`);
2599
+ }
2600
+ sections.push("");
2601
+ sections.push("## Package Info\n");
2602
+ sections.push(`- **Version:** ${pkg.version}`);
2603
+ if (pkg.license) {
2604
+ sections.push(`- **License:** ${pkg.license}`);
2605
+ }
2606
+ if (pkg.homepage) {
2607
+ sections.push(`- **Homepage:** ${pkg.homepage}`);
2608
+ }
2609
+ if (pkg.repository) {
2610
+ sections.push(`- **Repository:** ${pkg.repository.url}`);
2611
+ }
2612
+ sections.push("");
2613
+ sections.push("## Installation\n");
2614
+ sections.push("```bash");
2615
+ sections.push(`# npm`);
2616
+ sections.push(`npm install ${pkg.name}`);
2617
+ sections.push("");
2618
+ sections.push(`# yarn`);
2619
+ sections.push(`yarn add ${pkg.name}`);
2620
+ sections.push("");
2621
+ sections.push(`# pnpm`);
2622
+ sections.push(`pnpm add ${pkg.name}`);
2623
+ sections.push("```\n");
2624
+ if (readme?.quickStart) {
2625
+ sections.push("## Quick Start\n");
2626
+ sections.push(readme.quickStart);
2627
+ sections.push("");
2628
+ }
2629
+ sections.push("## API Reference\n");
2630
+ const functions = api.filter((e) => e.kind === "function");
2631
+ const classes = api.filter((e) => e.kind === "class");
2632
+ const interfaces = api.filter((e) => e.kind === "interface");
2633
+ const types = api.filter((e) => e.kind === "type");
2634
+ const constants = api.filter((e) => e.kind === "constant");
2635
+ const enums = api.filter((e) => e.kind === "enum");
2636
+ if (functions.length > 0) {
2637
+ sections.push("### Functions\n");
2638
+ for (const fn of functions) {
2639
+ sections.push(formatFunction(fn, { includeExamples, includeParamDescriptions, includeDeprecations, includeSourceLocations }));
2640
+ sections.push("");
2641
+ }
2642
+ }
2643
+ if (classes.length > 0) {
2644
+ sections.push("### Classes\n");
2645
+ for (const cls of classes) {
2646
+ sections.push(formatClass(cls, { includeExamples, includeDeprecations}));
2647
+ sections.push("");
2648
+ }
2649
+ }
2650
+ if (interfaces.length > 0) {
2651
+ sections.push("### Interfaces\n");
2652
+ for (const iface of interfaces) {
2653
+ sections.push(formatInterface(iface, { includeDeprecations}));
2654
+ sections.push("");
2655
+ }
2656
+ }
2657
+ if (types.length > 0) {
2658
+ sections.push("### Types\n");
2659
+ for (const type of types) {
2660
+ sections.push(formatType(type, { includeDeprecations }));
2661
+ sections.push("");
2662
+ }
2663
+ }
2664
+ if (enums.length > 0) {
2665
+ sections.push("### Enums\n");
2666
+ for (const enumEntry of enums) {
2667
+ sections.push(formatEnum(enumEntry));
2668
+ sections.push("");
2669
+ }
2670
+ }
2671
+ if (constants.length > 0) {
2672
+ sections.push("### Constants\n");
2673
+ for (const constant of constants) {
2674
+ sections.push(formatConstant(constant));
2675
+ sections.push("");
2676
+ }
2677
+ }
2678
+ const output = sections.join("\n");
2679
+ context.tokenCount = countTokens(output);
2680
+ return output;
2681
+ }
2682
+ function formatFunction(fn, options) {
2683
+ const lines = [];
2684
+ lines.push(`#### \`${fn.name}\``);
2685
+ if (options.includeDeprecations && fn.deprecated) {
2686
+ lines.push(`
2687
+ > \u26A0\uFE0F **Deprecated:** ${typeof fn.deprecated === "string" ? fn.deprecated : "This function is deprecated."}`);
2688
+ }
2689
+ if (fn.description) {
2690
+ lines.push(`
2691
+ ${fn.description}`);
2692
+ }
2693
+ lines.push("\n**Signature:**");
2694
+ lines.push("```typescript");
2695
+ lines.push(fn.signature);
2696
+ lines.push("```");
2697
+ if (fn.params && fn.params.length > 0 && options.includeParamDescriptions) {
2698
+ lines.push("\n**Parameters:**\n");
2699
+ for (const param of fn.params) {
2700
+ const optional = param.optional ? " (optional)" : "";
2701
+ const defaultVal = param.defaultValue ? ` = \`${param.defaultValue}\`` : "";
2702
+ lines.push(`- \`${param.name}: ${param.type || "unknown"}\`${optional}${defaultVal}`);
2703
+ if (param.description) {
2704
+ lines.push(` - ${param.description}`);
2705
+ }
2706
+ }
2707
+ }
2708
+ if (fn.returns) {
2709
+ lines.push("\n**Returns:**");
2710
+ lines.push(`- \`${fn.returns.type}\`${fn.returns.description ? ` - ${fn.returns.description}` : ""}`);
2711
+ }
2712
+ if (options.includeExamples && fn.examples && fn.examples.length > 0) {
2713
+ lines.push("\n**Examples:**");
2714
+ for (const example of fn.examples) {
2715
+ if (example.includes("```")) {
2716
+ lines.push(example);
2717
+ } else {
2718
+ lines.push("```typescript");
2719
+ lines.push(example);
2720
+ lines.push("```");
2721
+ }
2722
+ }
2723
+ }
2724
+ if (options.includeSourceLocations && fn.sourceFile) {
2725
+ lines.push(`
2726
+ *Source: ${fn.sourceFile}${fn.line ? `:${fn.line}` : ""}*`);
2727
+ }
2728
+ return lines.join("\n");
2729
+ }
2730
+ function formatClass(cls, options) {
2731
+ const lines = [];
2732
+ lines.push(`#### \`${cls.name}\``);
2733
+ if (options.includeDeprecations && cls.deprecated) {
2734
+ lines.push(`
2735
+ > \u26A0\uFE0F **Deprecated:** ${typeof cls.deprecated === "string" ? cls.deprecated : "This class is deprecated."}`);
2736
+ }
2737
+ if (cls.description) {
2738
+ lines.push(`
2739
+ ${cls.description}`);
2740
+ }
2741
+ lines.push("\n**Signature:**");
2742
+ lines.push("```typescript");
2743
+ let sig = cls.signature;
2744
+ if (cls.extends && cls.extends.length > 0) {
2745
+ sig += ` extends ${cls.extends.join(", ")}`;
2746
+ }
2747
+ if (cls.implements && cls.implements.length > 0) {
2748
+ sig += ` implements ${cls.implements.join(", ")}`;
2749
+ }
2750
+ lines.push(sig);
2751
+ lines.push("```");
2752
+ if (cls.properties && cls.properties.length > 0) {
2753
+ lines.push("\n**Properties:**\n");
2754
+ for (const prop of cls.properties) {
2755
+ lines.push(`- \`${prop.name}\`: \`${prop.signature.split(":").slice(1).join(":").trim() || "unknown"}\``);
2756
+ if (prop.description) {
2757
+ lines.push(` - ${prop.description}`);
2758
+ }
2759
+ }
2760
+ }
2761
+ if (cls.methods && cls.methods.length > 0) {
2762
+ lines.push("\n**Methods:**\n");
2763
+ for (const method of cls.methods) {
2764
+ const params = method.params?.map((p) => `${p.name}: ${p.type || "unknown"}`).join(", ") || "";
2765
+ const returnType = method.returns?.type || "void";
2766
+ lines.push(`- \`${method.name}(${params}): ${returnType}\``);
2767
+ if (method.description) {
2768
+ lines.push(` - ${method.description}`);
2769
+ }
2770
+ }
2771
+ }
2772
+ if (options.includeExamples && cls.examples && cls.examples.length > 0) {
2773
+ lines.push("\n**Examples:**");
2774
+ for (const example of cls.examples) {
2775
+ if (example.includes("```")) {
2776
+ lines.push(example);
2777
+ } else {
2778
+ lines.push("```typescript");
2779
+ lines.push(example);
2780
+ lines.push("```");
2781
+ }
2782
+ }
2783
+ }
2784
+ return lines.join("\n");
2785
+ }
2786
+ function formatInterface(iface, options) {
2787
+ const lines = [];
2788
+ lines.push(`#### \`${iface.name}\``);
2789
+ if (options.includeDeprecations && iface.deprecated) {
2790
+ lines.push(`
2791
+ > \u26A0\uFE0F **Deprecated**`);
2792
+ }
2793
+ if (iface.description) {
2794
+ lines.push(`
2795
+ ${iface.description}`);
2796
+ }
2797
+ lines.push("\n```typescript");
2798
+ let sig = iface.signature;
2799
+ if (iface.extends && iface.extends.length > 0) {
2800
+ sig += ` extends ${iface.extends.join(", ")}`;
2801
+ }
2802
+ lines.push(sig + " {");
2803
+ if (iface.properties && iface.properties.length > 0) {
2804
+ for (const prop of iface.properties) {
2805
+ lines.push(` ${prop.signature};`);
2806
+ }
2807
+ }
2808
+ if (iface.methods && iface.methods.length > 0) {
2809
+ for (const method of iface.methods) {
2810
+ lines.push(` ${method.signature};`);
2811
+ }
2812
+ }
2813
+ lines.push("}");
2814
+ lines.push("```");
2815
+ return lines.join("\n");
2816
+ }
2817
+ function formatType(type, options) {
2818
+ const lines = [];
2819
+ lines.push(`#### \`${type.name}\``);
2820
+ if (options.includeDeprecations && type.deprecated) {
2821
+ lines.push(`
2822
+ > \u26A0\uFE0F **Deprecated**`);
2823
+ }
2824
+ if (type.description) {
2825
+ lines.push(`
2826
+ ${type.description}`);
2827
+ }
2828
+ lines.push("\n```typescript");
2829
+ lines.push(type.signature);
2830
+ lines.push("```");
2831
+ return lines.join("\n");
2832
+ }
2833
+ function formatEnum(enumEntry) {
2834
+ const lines = [];
2835
+ lines.push(`#### \`${enumEntry.name}\``);
2836
+ if (enumEntry.description) {
2837
+ lines.push(`
2838
+ ${enumEntry.description}`);
2839
+ }
2840
+ lines.push("\n```typescript");
2841
+ lines.push(`enum ${enumEntry.name} {`);
2842
+ if (enumEntry.members) {
2843
+ for (const member of enumEntry.members) {
2844
+ if (member.value !== void 0) {
2845
+ lines.push(` ${member.name} = ${JSON.stringify(member.value)},`);
2846
+ } else {
2847
+ lines.push(` ${member.name},`);
2848
+ }
2849
+ }
2850
+ }
2851
+ lines.push("}");
2852
+ lines.push("```");
2853
+ return lines.join("\n");
2854
+ }
2855
+ function formatConstant(constant) {
2856
+ const lines = [];
2857
+ lines.push(`#### \`${constant.name}\``);
2858
+ if (constant.description) {
2859
+ lines.push(`
2860
+ ${constant.description}`);
2861
+ }
2862
+ lines.push("\n```typescript");
2863
+ lines.push(constant.signature);
2864
+ lines.push("```");
2865
+ return lines.join("\n");
2866
+ }
2867
+
2868
+ // src/plugins/core/llms-full-output.ts
2869
+ var llmsFullOutputPlugin = {
2870
+ name: "llms-full-output",
2871
+ version: "1.0.0",
2872
+ category: "output",
2873
+ install(kernel) {
2874
+ kernel.on("output:start", async (context) => {
2875
+ if (!context.options.formats?.includes("llms-full")) {
2876
+ return;
2877
+ }
2878
+ try {
2879
+ const output = generateLlmsFullTxt(context, {
2880
+ includeExamples: true,
2881
+ includeParamDescriptions: true,
2882
+ includeDeprecations: true
2883
+ });
2884
+ context.outputs.set("llms-full", output);
2885
+ } catch (error) {
2886
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
2887
+ }
2888
+ });
2889
+ }
2890
+ };
2891
+
2892
+ // src/outputs/markdown.ts
2893
+ function generateMarkdown(context, options = {}) {
2894
+ const {
2895
+ includeToc = true,
2896
+ includeParamTables = true,
2897
+ includeBadges = true,
2898
+ repositoryUrl
2899
+ } = options;
2900
+ const { package: pkg, api, readme } = context;
2901
+ const sections = [];
2902
+ sections.push(`# ${pkg.name}`);
2903
+ sections.push("");
2904
+ if (includeBadges) {
2905
+ const badges = [];
2906
+ badges.push(`![npm version](https://img.shields.io/npm/v/${encodeURIComponent(pkg.name)})`);
2907
+ if (pkg.license) {
2908
+ badges.push(`![license](https://img.shields.io/npm/l/${encodeURIComponent(pkg.name)})`);
2909
+ }
2910
+ if (badges.length > 0) {
2911
+ sections.push(badges.join(" "));
2912
+ sections.push("");
2913
+ }
2914
+ }
2915
+ if (pkg.description) {
2916
+ sections.push(`> ${pkg.description}`);
2917
+ sections.push("");
2918
+ }
2919
+ if (includeToc) {
2920
+ sections.push("## Table of Contents\n");
2921
+ sections.push("- [Installation](#installation)");
2922
+ if (readme?.quickStart) {
2923
+ sections.push("- [Quick Start](#quick-start)");
2924
+ }
2925
+ sections.push("- [API Reference](#api-reference)");
2926
+ const functions2 = api.filter((e) => e.kind === "function");
2927
+ const classes2 = api.filter((e) => e.kind === "class");
2928
+ const interfaces2 = api.filter((e) => e.kind === "interface");
2929
+ const types2 = api.filter((e) => e.kind === "type");
2930
+ if (functions2.length > 0) {
2931
+ sections.push(" - [Functions](#functions)");
2932
+ }
2933
+ if (classes2.length > 0) {
2934
+ sections.push(" - [Classes](#classes)");
2935
+ }
2936
+ if (interfaces2.length > 0) {
2937
+ sections.push(" - [Interfaces](#interfaces)");
2938
+ }
2939
+ if (types2.length > 0) {
2940
+ sections.push(" - [Types](#types)");
2941
+ }
2942
+ sections.push("");
2943
+ }
2944
+ sections.push("## Installation\n");
2945
+ sections.push("```bash");
2946
+ sections.push(`npm install ${pkg.name}`);
2947
+ sections.push("```\n");
2948
+ sections.push("Or with yarn:\n");
2949
+ sections.push("```bash");
2950
+ sections.push(`yarn add ${pkg.name}`);
2951
+ sections.push("```\n");
2952
+ if (readme?.quickStart) {
2953
+ sections.push("## Quick Start\n");
2954
+ sections.push(readme.quickStart);
2955
+ sections.push("");
2956
+ }
2957
+ sections.push("## API Reference\n");
2958
+ const functions = api.filter((e) => e.kind === "function");
2959
+ const classes = api.filter((e) => e.kind === "class");
2960
+ const interfaces = api.filter((e) => e.kind === "interface");
2961
+ const types = api.filter((e) => e.kind === "type");
2962
+ const enums = api.filter((e) => e.kind === "enum");
2963
+ const constants = api.filter((e) => e.kind === "constant");
2964
+ if (functions.length > 0) {
2965
+ sections.push("### Functions\n");
2966
+ for (const fn of functions) {
2967
+ sections.push(formatFunctionMd(fn, { includeParamTables, repositoryUrl }));
2968
+ sections.push("");
2969
+ sections.push("---\n");
2970
+ }
2971
+ }
2972
+ if (classes.length > 0) {
2973
+ sections.push("### Classes\n");
2974
+ for (const cls of classes) {
2975
+ sections.push(formatClassMd(cls));
2976
+ sections.push("");
2977
+ sections.push("---\n");
2978
+ }
2979
+ }
2980
+ if (interfaces.length > 0) {
2981
+ sections.push("### Interfaces\n");
2982
+ for (const iface of interfaces) {
2983
+ sections.push(formatInterfaceMd(iface));
2984
+ sections.push("");
2985
+ sections.push("---\n");
2986
+ }
2987
+ }
2988
+ if (types.length > 0) {
2989
+ sections.push("### Types\n");
2990
+ for (const type of types) {
2991
+ sections.push(formatTypeMd(type));
2992
+ sections.push("");
2993
+ }
2994
+ }
2995
+ if (enums.length > 0) {
2996
+ sections.push("### Enums\n");
2997
+ for (const enumEntry of enums) {
2998
+ sections.push(formatEnumMd(enumEntry));
2999
+ sections.push("");
3000
+ }
3001
+ }
3002
+ if (constants.length > 0) {
3003
+ sections.push("### Constants\n");
3004
+ for (const constant of constants) {
3005
+ sections.push(formatConstantMd(constant));
3006
+ }
3007
+ sections.push("");
3008
+ }
3009
+ const output = sections.join("\n");
3010
+ context.tokenCount = countTokens(output);
3011
+ return output;
3012
+ }
3013
+ function formatFunctionMd(fn, options) {
3014
+ const lines = [];
3015
+ const anchor = fn.name.toLowerCase();
3016
+ lines.push(`<a name="${anchor}"></a>`);
3017
+ lines.push(`#### \`${fn.name}()\``);
3018
+ if (fn.deprecated) {
3019
+ lines.push(`
3020
+ > \u26A0\uFE0F **Deprecated:** ${typeof fn.deprecated === "string" ? fn.deprecated : "This function is deprecated."}
3021
+ `);
3022
+ }
3023
+ if (fn.description) {
3024
+ lines.push(`
3025
+ ${fn.description}
3026
+ `);
3027
+ }
3028
+ lines.push("**Signature:**\n");
3029
+ lines.push("```typescript");
3030
+ lines.push(fn.signature);
3031
+ lines.push("```\n");
3032
+ if (fn.params && fn.params.length > 0 && options.includeParamTables) {
3033
+ lines.push("**Parameters:**\n");
3034
+ lines.push("| Name | Type | Required | Description |");
3035
+ lines.push("|------|------|----------|-------------|");
3036
+ for (const param of fn.params) {
3037
+ const required = param.optional ? "No" : "Yes";
3038
+ const desc = param.description || "-";
3039
+ const defaultVal = param.defaultValue ? ` (default: \`${param.defaultValue}\`)` : "";
3040
+ lines.push(`| \`${param.name}\` | \`${param.type || "unknown"}\` | ${required} | ${desc}${defaultVal} |`);
3041
+ }
3042
+ lines.push("");
3043
+ }
3044
+ if (fn.returns) {
3045
+ lines.push("**Returns:**\n");
3046
+ lines.push(`\`${fn.returns.type}\`${fn.returns.description ? ` - ${fn.returns.description}` : ""}
3047
+ `);
3048
+ }
3049
+ if (fn.examples && fn.examples.length > 0) {
3050
+ lines.push("**Example:**\n");
3051
+ for (const example of fn.examples) {
3052
+ if (example.includes("```")) {
3053
+ lines.push(example);
3054
+ } else {
3055
+ lines.push("```typescript");
3056
+ lines.push(example);
3057
+ lines.push("```");
3058
+ }
3059
+ }
3060
+ lines.push("");
3061
+ }
3062
+ if (options.repositoryUrl && fn.sourceFile) {
3063
+ const sourceUrl = `${options.repositoryUrl}/blob/main/${fn.sourceFile}${fn.line ? `#L${fn.line}` : ""}`;
3064
+ lines.push(`[View source](${sourceUrl})
3065
+ `);
3066
+ }
3067
+ return lines.join("\n");
3068
+ }
3069
+ function formatClassMd(cls, options) {
3070
+ const lines = [];
3071
+ const anchor = cls.name.toLowerCase();
3072
+ lines.push(`<a name="${anchor}"></a>`);
3073
+ lines.push(`#### \`${cls.name}\``);
3074
+ if (cls.deprecated) {
3075
+ lines.push(`
3076
+ > \u26A0\uFE0F **Deprecated**
3077
+ `);
3078
+ }
3079
+ if (cls.description) {
3080
+ lines.push(`
3081
+ ${cls.description}
3082
+ `);
3083
+ }
3084
+ if (cls.extends && cls.extends.length > 0) {
3085
+ lines.push(`**Extends:** ${cls.extends.map((e) => `\`${e}\``).join(", ")}
3086
+ `);
3087
+ }
3088
+ if (cls.implements && cls.implements.length > 0) {
3089
+ lines.push(`**Implements:** ${cls.implements.map((e) => `\`${e}\``).join(", ")}
3090
+ `);
3091
+ }
3092
+ const constructor = cls.methods?.find((m) => m.name === "constructor");
3093
+ if (constructor) {
3094
+ lines.push("**Constructor:**\n");
3095
+ lines.push("```typescript");
3096
+ lines.push(`new ${cls.name}(${constructor.params?.map((p) => `${p.name}: ${p.type}`).join(", ") || ""})`);
3097
+ lines.push("```\n");
3098
+ }
3099
+ if (cls.properties && cls.properties.length > 0) {
3100
+ lines.push("**Properties:**\n");
3101
+ lines.push("| Name | Type | Description |");
3102
+ lines.push("|------|------|-------------|");
3103
+ for (const prop of cls.properties) {
3104
+ const type = prop.signature.split(":").slice(1).join(":").trim() || "unknown";
3105
+ lines.push(`| \`${prop.name}\` | \`${type}\` | ${prop.description || "-"} |`);
3106
+ }
3107
+ lines.push("");
3108
+ }
3109
+ const methods = cls.methods?.filter((m) => m.name !== "constructor") || [];
3110
+ if (methods.length > 0) {
3111
+ lines.push("**Methods:**\n");
3112
+ lines.push("| Method | Returns | Description |");
3113
+ lines.push("|--------|---------|-------------|");
3114
+ for (const method of methods) {
3115
+ const params = method.params?.map((p) => `${p.name}`).join(", ") || "";
3116
+ const returnType = method.returns?.type || "void";
3117
+ lines.push(`| \`${method.name}(${params})\` | \`${returnType}\` | ${method.description || "-"} |`);
3118
+ }
3119
+ lines.push("");
3120
+ }
3121
+ return lines.join("\n");
3122
+ }
3123
+ function formatInterfaceMd(iface) {
3124
+ const lines = [];
3125
+ lines.push(`#### \`${iface.name}\``);
3126
+ if (iface.description) {
3127
+ lines.push(`
3128
+ ${iface.description}
3129
+ `);
3130
+ }
3131
+ if (iface.extends && iface.extends.length > 0) {
3132
+ lines.push(`**Extends:** ${iface.extends.map((e) => `\`${e}\``).join(", ")}
3133
+ `);
3134
+ }
3135
+ if (iface.properties && iface.properties.length > 0) {
3136
+ lines.push("| Property | Type | Description |");
3137
+ lines.push("|----------|------|-------------|");
3138
+ for (const prop of iface.properties) {
3139
+ const type = prop.signature.split(":").slice(1).join(":").trim() || "unknown";
3140
+ lines.push(`| \`${prop.name}\` | \`${type}\` | ${prop.description || "-"} |`);
3141
+ }
3142
+ lines.push("");
3143
+ }
3144
+ lines.push("<details>");
3145
+ lines.push("<summary>Full Definition</summary>\n");
3146
+ lines.push("```typescript");
3147
+ lines.push(`interface ${iface.name} {`);
3148
+ if (iface.properties) {
3149
+ for (const prop of iface.properties) {
3150
+ lines.push(` ${prop.signature};`);
3151
+ }
3152
+ }
3153
+ if (iface.methods) {
3154
+ for (const method of iface.methods) {
3155
+ lines.push(` ${method.signature};`);
3156
+ }
3157
+ }
3158
+ lines.push("}");
3159
+ lines.push("```");
3160
+ lines.push("</details>");
3161
+ return lines.join("\n");
3162
+ }
3163
+ function formatTypeMd(type) {
3164
+ const lines = [];
3165
+ lines.push(`#### \`${type.name}\``);
3166
+ if (type.description) {
3167
+ lines.push(`
3168
+ ${type.description}
3169
+ `);
3170
+ }
3171
+ lines.push("```typescript");
3172
+ lines.push(type.signature);
3173
+ lines.push("```");
3174
+ return lines.join("\n");
3175
+ }
3176
+ function formatEnumMd(enumEntry) {
3177
+ const lines = [];
3178
+ lines.push(`#### \`${enumEntry.name}\``);
3179
+ if (enumEntry.description) {
3180
+ lines.push(`
3181
+ ${enumEntry.description}
3182
+ `);
3183
+ }
3184
+ if (enumEntry.members && enumEntry.members.length > 0) {
3185
+ lines.push("| Member | Value |");
3186
+ lines.push("|--------|-------|");
3187
+ for (const member of enumEntry.members) {
3188
+ const value = member.value !== void 0 ? `\`${JSON.stringify(member.value)}\`` : "-";
3189
+ lines.push(`| \`${member.name}\` | ${value} |`);
3190
+ }
3191
+ lines.push("");
3192
+ }
3193
+ return lines.join("\n");
3194
+ }
3195
+ function formatConstantMd(constant) {
3196
+ const lines = [];
3197
+ lines.push(`- **\`${constant.name}\`**: \`${constant.signature.split(":").slice(1).join(":").trim() || "unknown"}\``);
3198
+ if (constant.description) {
3199
+ lines.push(` - ${constant.description}`);
3200
+ }
3201
+ return lines.join("\n");
3202
+ }
3203
+
3204
+ // src/plugins/core/markdown-output.ts
3205
+ var markdownOutputPlugin = {
3206
+ name: "markdown-output",
3207
+ version: "1.0.0",
3208
+ category: "output",
3209
+ install(kernel) {
3210
+ kernel.on("output:start", async (context) => {
3211
+ if (!context.options.formats?.includes("markdown")) {
3212
+ return;
3213
+ }
3214
+ try {
3215
+ const repositoryUrl = context.package.repository?.url?.replace(/^git\+/, "").replace(/\.git$/, "");
3216
+ const output = generateMarkdown(context, {
3217
+ includeToc: true,
3218
+ includeParamTables: true,
3219
+ includeBadges: true,
3220
+ repositoryUrl
3221
+ });
3222
+ context.outputs.set("markdown", output);
3223
+ } catch (error) {
3224
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
3225
+ }
3226
+ });
3227
+ }
3228
+ };
3229
+
3230
+ // src/outputs/json.ts
3231
+ function generateJson(context, options = {}) {
3232
+ const { pretty = true, includeEmpty = false, includeSourceLocations = true } = options;
3233
+ const output = generateJsonObject(context, { includeEmpty, includeSourceLocations });
3234
+ return pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);
3235
+ }
3236
+ function generateJsonObject(context, options = {}) {
3237
+ const { includeEmpty = false, includeSourceLocations = true } = options;
3238
+ const { package: pkg, api } = context;
3239
+ const functions = api.filter((e) => e.kind === "function");
3240
+ const classes = api.filter((e) => e.kind === "class");
3241
+ const interfaces = api.filter((e) => e.kind === "interface");
3242
+ const types = api.filter((e) => e.kind === "type");
3243
+ const enums = api.filter((e) => e.kind === "enum");
3244
+ const constants = api.filter((e) => e.kind === "constant");
3245
+ const documented = api.filter((e) => e.description).length;
3246
+ const withExamples = api.filter((e) => e.examples && e.examples.length > 0).length;
3247
+ const output = {
3248
+ $schema: "https://npm-llms.oxog.dev/schema/v1.json",
3249
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3250
+ package: {
3251
+ name: pkg.name,
3252
+ version: pkg.version,
3253
+ description: pkg.description,
3254
+ license: pkg.license,
3255
+ homepage: pkg.homepage,
3256
+ repository: pkg.repository?.url,
3257
+ keywords: pkg.keywords
3258
+ },
3259
+ api: {
3260
+ functions: functions.map((fn) => transformFunction(fn, includeSourceLocations)),
3261
+ classes: classes.map((cls) => transformClass(cls, includeSourceLocations)),
3262
+ interfaces: interfaces.map(transformInterface),
3263
+ types: types.map(transformType),
3264
+ enums: enums.map(transformEnum),
3265
+ constants: constants.map(transformConstant)
3266
+ },
3267
+ stats: {
3268
+ totalExports: api.length,
3269
+ functions: functions.length,
3270
+ classes: classes.length,
3271
+ interfaces: interfaces.length,
3272
+ types: types.length,
3273
+ enums: enums.length,
3274
+ constants: constants.length,
3275
+ documented,
3276
+ withExamples
3277
+ }
3278
+ };
3279
+ if (!includeEmpty) {
3280
+ const apiObj = output.api;
3281
+ for (const [key, value] of Object.entries(apiObj)) {
3282
+ if (Array.isArray(value) && value.length === 0) {
3283
+ delete apiObj[key];
3284
+ }
3285
+ }
3286
+ }
3287
+ return output;
3288
+ }
3289
+ function transformFunction(entry, includeSource) {
3290
+ const result = {
3291
+ name: entry.name,
3292
+ signature: entry.signature,
3293
+ description: entry.description,
3294
+ params: (entry.params || []).map((p) => ({
3295
+ name: p.name,
3296
+ type: p.type || "unknown",
3297
+ optional: p.optional ?? false,
3298
+ defaultValue: p.defaultValue,
3299
+ description: p.description
3300
+ })),
3301
+ returns: entry.returns ? {
3302
+ type: entry.returns.type,
3303
+ description: entry.returns.description
3304
+ } : void 0,
3305
+ examples: entry.examples || [],
3306
+ deprecated: entry.deprecated,
3307
+ since: entry.since,
3308
+ see: entry.see
3309
+ };
3310
+ if (includeSource) {
3311
+ result.sourceFile = entry.sourceFile;
3312
+ result.line = entry.line;
3313
+ }
3314
+ return result;
3315
+ }
3316
+ function transformClass(entry, includeSource) {
3317
+ const result = {
3318
+ name: entry.name,
3319
+ signature: entry.signature,
3320
+ description: entry.description,
3321
+ extends: entry.extends,
3322
+ implements: entry.implements,
3323
+ typeParams: entry.typeParams,
3324
+ properties: (entry.properties || []).map((p) => ({
3325
+ name: p.name,
3326
+ type: p.signature.split(":").slice(1).join(":").trim() || "unknown",
3327
+ description: p.description
3328
+ })),
3329
+ methods: (entry.methods || []).map((m) => transformFunction(m, includeSource)),
3330
+ deprecated: entry.deprecated
3331
+ };
3332
+ if (includeSource) {
3333
+ result.sourceFile = entry.sourceFile;
3334
+ }
3335
+ return result;
3336
+ }
3337
+ function transformInterface(entry) {
3338
+ return {
3339
+ name: entry.name,
3340
+ signature: entry.signature,
3341
+ description: entry.description,
3342
+ extends: entry.extends,
3343
+ typeParams: entry.typeParams,
3344
+ properties: (entry.properties || []).map((p) => ({
3345
+ name: p.name,
3346
+ type: p.signature.split(":").slice(1).join(":").trim() || "unknown",
3347
+ optional: p.signature.includes("?:"),
3348
+ description: p.description
3349
+ })),
3350
+ methods: (entry.methods || []).map((m) => ({
3351
+ name: m.name,
3352
+ signature: m.signature,
3353
+ description: m.description
3354
+ })),
3355
+ deprecated: entry.deprecated
3356
+ };
3357
+ }
3358
+ function transformType(entry) {
3359
+ return {
3360
+ name: entry.name,
3361
+ signature: entry.signature,
3362
+ description: entry.description,
3363
+ typeParams: entry.typeParams,
3364
+ deprecated: entry.deprecated
3365
+ };
3366
+ }
3367
+ function transformEnum(entry) {
3368
+ return {
3369
+ name: entry.name,
3370
+ description: entry.description,
3371
+ members: entry.members || []
3372
+ };
3373
+ }
3374
+ function transformConstant(entry) {
3375
+ return {
3376
+ name: entry.name,
3377
+ type: entry.signature.split(":").slice(1).join(":").trim() || "unknown",
3378
+ description: entry.description
3379
+ };
3380
+ }
3381
+
3382
+ // src/plugins/core/json-output.ts
3383
+ var jsonOutputPlugin = {
3384
+ name: "json-output",
3385
+ version: "1.0.0",
3386
+ category: "output",
3387
+ install(kernel) {
3388
+ kernel.on("output:start", async (context) => {
3389
+ if (!context.options.formats?.includes("json")) {
3390
+ return;
3391
+ }
3392
+ try {
3393
+ const output = generateJson(context, {
3394
+ pretty: true,
3395
+ includeEmpty: false,
3396
+ includeSourceLocations: true
3397
+ });
3398
+ context.outputs.set("json", output);
3399
+ } catch (error) {
3400
+ context.errors.push(error instanceof Error ? error : new Error(String(error)));
3401
+ }
3402
+ });
3403
+ }
3404
+ };
3405
+
3406
+ // src/plugins/core/index.ts
3407
+ var coreParserPlugins = [
3408
+ typesResolverPlugin,
3409
+ dtsParserPlugin,
3410
+ tsSourceParserPlugin,
3411
+ readmeParserPlugin
3412
+ ];
3413
+ var coreOutputPlugins = [
3414
+ llmsOutputPlugin,
3415
+ llmsFullOutputPlugin,
3416
+ markdownOutputPlugin,
3417
+ jsonOutputPlugin
3418
+ ];
3419
+ var corePlugins = [
3420
+ ...coreParserPlugins,
3421
+ ...coreOutputPlugins
3422
+ ];
3423
+
3424
+ // src/core/extractor.ts
3425
+ var DEFAULT_FORMATS = ["llms", "llms-full", "markdown", "json"];
3426
+ function createExtractor(options = {}) {
3427
+ const kernel = createKernel();
3428
+ const cache = createCache(options.cache);
3429
+ for (const plugin of corePlugins) {
3430
+ kernel.use(plugin);
3431
+ }
3432
+ if (options.plugins) {
3433
+ for (const plugin of options.plugins) {
3434
+ kernel.use(plugin);
3435
+ }
3436
+ }
3437
+ async function extract2(packageSpec, extractOptions = {}) {
3438
+ const startTime = Date.now();
3439
+ const { name, version } = parsePackageSpec(packageSpec);
3440
+ const cacheKey = buildPackageCacheKey(name, version ?? "latest", "result");
3441
+ let fromCache = false;
3442
+ if (cache && !extractOptions.ignoreCache) {
3443
+ const cached = await cache.get(cacheKey);
3444
+ if (cached) {
3445
+ return {
3446
+ ...cached,
3447
+ fromCache: true
3448
+ };
3449
+ }
3450
+ }
3451
+ const pkg = await fetchPackage(packageSpec, {
3452
+ registry: options.registry,
3453
+ timeout: options.ai?.timeout
3454
+ });
3455
+ const context = createContext(pkg, extractOptions);
3456
+ await kernel.emit("package:fetched", context);
3457
+ await kernel.emit("parse:start", context);
3458
+ await kernel.emit("parse:complete", context);
3459
+ if (extractOptions.enrichWithAI && options.ai) {
3460
+ await kernel.emit("enrich:start", context);
3461
+ await kernel.emit("enrich:complete", context);
3462
+ }
3463
+ await kernel.emit("output:start", context);
3464
+ await kernel.emit("output:complete", context);
3465
+ const result = {
3466
+ package: {
3467
+ name: pkg.name,
3468
+ version: pkg.version,
3469
+ description: pkg.description,
3470
+ tarball: pkg.tarball,
3471
+ types: pkg.types,
3472
+ main: pkg.main,
3473
+ exports: pkg.exports,
3474
+ repository: pkg.repository,
3475
+ keywords: pkg.keywords,
3476
+ author: pkg.author,
3477
+ license: pkg.license,
3478
+ homepage: pkg.homepage
3479
+ },
3480
+ api: context.api,
3481
+ outputs: Object.fromEntries(context.outputs),
3482
+ tokenCount: context.tokenCount,
3483
+ truncated: context.truncated,
3484
+ duration: Date.now() - startTime,
3485
+ fromCache
3486
+ };
3487
+ if (cache && !extractOptions.ignoreCache) {
3488
+ await cache.set(cacheKey, result);
3489
+ }
3490
+ return result;
3491
+ }
3492
+ async function fetchOnly(packageSpec) {
3493
+ return fetchPackage(packageSpec, {
3494
+ registry: options.registry
3495
+ });
3496
+ }
3497
+ function use(plugin) {
3498
+ kernel.use(plugin);
3499
+ return extractor;
3500
+ }
3501
+ function unregister(name) {
3502
+ return kernel.unregister(name);
3503
+ }
3504
+ function listPlugins() {
3505
+ return kernel.listPlugins();
3506
+ }
3507
+ async function clearCache() {
3508
+ if (cache) {
3509
+ await cache.clear();
3510
+ }
3511
+ }
3512
+ async function getCacheStats() {
3513
+ if (cache) {
3514
+ return cache.getStats();
3515
+ }
3516
+ return { entries: 0, size: 0, dir: "" };
3517
+ }
3518
+ const extractor = {
3519
+ extract: extract2,
3520
+ fetch: fetchOnly,
3521
+ use,
3522
+ unregister,
3523
+ listPlugins,
3524
+ clearCache,
3525
+ getCacheStats
3526
+ };
3527
+ return extractor;
3528
+ }
3529
+ function createContext(pkg, options) {
3530
+ return {
3531
+ package: pkg,
3532
+ api: [],
3533
+ readme: void 0,
3534
+ changelog: void 0,
3535
+ options: {
3536
+ formats: options.formats ?? DEFAULT_FORMATS,
3537
+ enrichWithAI: options.enrichWithAI ?? false,
3538
+ aiTasks: options.aiTasks ?? ["descriptions", "examples", "summary"],
3539
+ llmsTokenLimit: options.llmsTokenLimit ?? 2e3,
3540
+ prioritize: options.prioritize ?? ["functions", "examples"],
3541
+ ignoreCache: options.ignoreCache ?? false
3542
+ },
3543
+ outputs: /* @__PURE__ */ new Map(),
3544
+ tokenCount: 0,
3545
+ truncated: false,
3546
+ startTime: Date.now(),
3547
+ fromCache: false,
3548
+ errors: []
3549
+ };
3550
+ }
3551
+ async function extract(packageSpec, options) {
3552
+ const extractor = createExtractor();
3553
+ return extractor.extract(packageSpec, options);
3554
+ }
3555
+
3556
+ export { AIError, CacheError, ConfigError, DownloadError, FileCache, NpmLlmsError, PackageNotFoundError, ParseError, PluginError, TarError, TimeoutError, ValidationError, VersionNotFoundError, composePlugins, countTokens, createCache, createExtractor, createKernel, definePlugin, extract, fetchPackage, fetchPackageMetadata, formatBytes, formatTokenCount, getErrorCode, isNpmLlmsError, parsePackageSpec, truncateToTokenLimit, validatePackageName, wrapError };
3557
+ //# sourceMappingURL=index.js.map
3558
+ //# sourceMappingURL=index.js.map