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