apdev-js 0.1.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,550 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ buildDependencyGraph: () => buildDependencyGraph,
34
+ checkCircularImports: () => checkCircularImports,
35
+ checkFile: () => checkFile,
36
+ checkPaths: () => checkPaths,
37
+ fileToModule: () => fileToModule,
38
+ findCycles: () => findCycles,
39
+ isAllowedChar: () => isAllowedChar,
40
+ loadConfig: () => loadConfig,
41
+ version: () => version
42
+ });
43
+ module.exports = __toCommonJS(src_exports);
44
+
45
+ // node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
46
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
47
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
48
+
49
+ // src/check-chars.ts
50
+ var import_node_fs = require("fs");
51
+ var import_node_path = require("path");
52
+ var EMOJI_RANGES = [
53
+ [127744, 128511],
54
+ // Symbols and Pictographs
55
+ [128512, 128591],
56
+ // Emoticons
57
+ [128640, 128767],
58
+ // Transport and Map Symbols
59
+ [128896, 129023],
60
+ // Geometric Shapes Extended
61
+ [129280, 129535],
62
+ // Supplemental Symbols and Pictographs
63
+ [9728, 9983],
64
+ // Miscellaneous Symbols
65
+ [9984, 10175]
66
+ // Dingbats
67
+ ];
68
+ var EXTRA_ALLOWED_RANGES = [
69
+ [128, 255],
70
+ // Latin-1 Supplement
71
+ [8192, 8303],
72
+ // General Punctuation
73
+ [8448, 8527],
74
+ // Letterlike Symbols
75
+ [8592, 8703],
76
+ // Arrows
77
+ [8704, 8959],
78
+ // Mathematical Operators
79
+ [8960, 9215],
80
+ // Miscellaneous Technical
81
+ [9472, 9599],
82
+ // Box Drawing
83
+ [9632, 9727],
84
+ // Geometric Shapes
85
+ [11008, 11263],
86
+ // Miscellaneous Symbols and Arrows
87
+ [65024, 65039]
88
+ // Variation Selectors
89
+ ];
90
+ var ALL_RANGES = [...EMOJI_RANGES, ...EXTRA_ALLOWED_RANGES];
91
+ var DANGEROUS_CODEPOINTS = /* @__PURE__ */ new Map([
92
+ // Bidi control characters (Trojan Source - CVE-2021-42574)
93
+ [8234, "LEFT-TO-RIGHT EMBEDDING"],
94
+ [8235, "RIGHT-TO-LEFT EMBEDDING"],
95
+ [8236, "POP DIRECTIONAL FORMATTING"],
96
+ [8237, "LEFT-TO-RIGHT OVERRIDE"],
97
+ [8238, "RIGHT-TO-LEFT OVERRIDE"],
98
+ [8294, "LEFT-TO-RIGHT ISOLATE"],
99
+ [8295, "RIGHT-TO-LEFT ISOLATE"],
100
+ [8296, "FIRST STRONG ISOLATE"],
101
+ [8297, "POP DIRECTIONAL ISOLATE"],
102
+ // Zero-width characters
103
+ [8203, "ZERO WIDTH SPACE"],
104
+ [8204, "ZERO WIDTH NON-JOINER"],
105
+ [8205, "ZERO WIDTH JOINER"],
106
+ [8206, "LEFT-TO-RIGHT MARK"],
107
+ [8207, "RIGHT-TO-LEFT MARK"],
108
+ [8288, "WORD JOINER"]
109
+ ]);
110
+ var PYTHON_SUFFIXES = /* @__PURE__ */ new Set([".py"]);
111
+ var JS_SUFFIXES = /* @__PURE__ */ new Set([".js", ".ts", ".tsx", ".jsx", ".mjs", ".cjs"]);
112
+ function isAllowedChar(c) {
113
+ const code = c.codePointAt(0);
114
+ if (code <= 127) {
115
+ return true;
116
+ }
117
+ for (const [start, end] of ALL_RANGES) {
118
+ if (code >= start && code <= end) {
119
+ return true;
120
+ }
121
+ }
122
+ return false;
123
+ }
124
+ function isDangerousChar(c) {
125
+ return DANGEROUS_CODEPOINTS.has(c.codePointAt(0));
126
+ }
127
+ function computeCommentMask(content, suffix) {
128
+ if (PYTHON_SUFFIXES.has(suffix)) {
129
+ return computeCommentMaskPython(content);
130
+ }
131
+ if (JS_SUFFIXES.has(suffix)) {
132
+ return computeCommentMaskJs(content);
133
+ }
134
+ return /* @__PURE__ */ new Set();
135
+ }
136
+ function computeCommentMaskPython(content) {
137
+ const mask = /* @__PURE__ */ new Set();
138
+ let i = 0;
139
+ const n = content.length;
140
+ while (i < n) {
141
+ if (i + 2 < n && (content.slice(i, i + 3) === '"""' || content.slice(i, i + 3) === "'''")) {
142
+ const quote = content.slice(i, i + 3);
143
+ i += 3;
144
+ while (i < n) {
145
+ if (content[i] === "\\" && i + 1 < n) {
146
+ i += 2;
147
+ continue;
148
+ }
149
+ if (i + 2 < n && content.slice(i, i + 3) === quote) {
150
+ i += 3;
151
+ break;
152
+ }
153
+ i++;
154
+ }
155
+ continue;
156
+ }
157
+ if (content[i] === '"' || content[i] === "'") {
158
+ const quoteChar = content[i];
159
+ i++;
160
+ while (i < n && content[i] !== "\n") {
161
+ if (content[i] === "\\" && i + 1 < n) {
162
+ i += 2;
163
+ continue;
164
+ }
165
+ if (content[i] === quoteChar) {
166
+ i++;
167
+ break;
168
+ }
169
+ i++;
170
+ }
171
+ continue;
172
+ }
173
+ if (content[i] === "#") {
174
+ while (i < n && content[i] !== "\n") {
175
+ mask.add(i);
176
+ i++;
177
+ }
178
+ continue;
179
+ }
180
+ i++;
181
+ }
182
+ return mask;
183
+ }
184
+ function computeCommentMaskJs(content) {
185
+ const mask = /* @__PURE__ */ new Set();
186
+ let i = 0;
187
+ const n = content.length;
188
+ while (i < n) {
189
+ if (content[i] === "`") {
190
+ i++;
191
+ while (i < n) {
192
+ if (content[i] === "\\" && i + 1 < n) {
193
+ i += 2;
194
+ continue;
195
+ }
196
+ if (content[i] === "`") {
197
+ i++;
198
+ break;
199
+ }
200
+ i++;
201
+ }
202
+ continue;
203
+ }
204
+ if (content[i] === '"' || content[i] === "'") {
205
+ const quoteChar = content[i];
206
+ i++;
207
+ while (i < n && content[i] !== "\n") {
208
+ if (content[i] === "\\" && i + 1 < n) {
209
+ i += 2;
210
+ continue;
211
+ }
212
+ if (content[i] === quoteChar) {
213
+ i++;
214
+ break;
215
+ }
216
+ i++;
217
+ }
218
+ continue;
219
+ }
220
+ if (i + 1 < n && content[i] === "/" && content[i + 1] === "/") {
221
+ while (i < n && content[i] !== "\n") {
222
+ mask.add(i);
223
+ i++;
224
+ }
225
+ continue;
226
+ }
227
+ if (i + 1 < n && content[i] === "/" && content[i + 1] === "*") {
228
+ while (i < n) {
229
+ if (i + 1 < n && content[i] === "*" && content[i + 1] === "/") {
230
+ mask.add(i);
231
+ mask.add(i + 1);
232
+ i += 2;
233
+ break;
234
+ }
235
+ mask.add(i);
236
+ i++;
237
+ }
238
+ continue;
239
+ }
240
+ i++;
241
+ }
242
+ return mask;
243
+ }
244
+ function checkFile(filePath, maxProblems = 5) {
245
+ const problems = [];
246
+ try {
247
+ const content = (0, import_node_fs.readFileSync)(filePath, "utf-8");
248
+ const suffix = (0, import_node_path.extname)(filePath).toLowerCase();
249
+ const commentMask = computeCommentMask(content, suffix);
250
+ let position = 0;
251
+ let offset = 0;
252
+ for (const char of content) {
253
+ position++;
254
+ const code = char.codePointAt(0);
255
+ if (isDangerousChar(char)) {
256
+ if (!commentMask.has(offset)) {
257
+ const name = DANGEROUS_CODEPOINTS.get(code);
258
+ const hex = code.toString(16).toUpperCase().padStart(4, "0");
259
+ problems.push(
260
+ `Dangerous character in code at position ${position}: U+${hex} (${name})`
261
+ );
262
+ }
263
+ } else if (!isAllowedChar(char)) {
264
+ const hex = code.toString(16).toUpperCase().padStart(4, "0");
265
+ problems.push(
266
+ `Illegal character at position ${position}: ${JSON.stringify(char)} (U+${hex})`
267
+ );
268
+ }
269
+ if (problems.length >= maxProblems) {
270
+ break;
271
+ }
272
+ offset += char.length;
273
+ }
274
+ } catch {
275
+ problems.push(`Failed to read file: ${filePath}`);
276
+ }
277
+ return problems;
278
+ }
279
+ function checkPaths(paths) {
280
+ let hasError = false;
281
+ for (const path of paths) {
282
+ const problems = checkFile(path);
283
+ if (problems.length > 0) {
284
+ hasError = true;
285
+ console.log(`
286
+ ${path} contains illegal characters:`);
287
+ for (const p of problems) {
288
+ console.log(` ${p}`);
289
+ }
290
+ }
291
+ }
292
+ return hasError ? 1 : 0;
293
+ }
294
+
295
+ // src/check-imports.ts
296
+ var import_node_fs2 = require("fs");
297
+ var import_node_path2 = require("path");
298
+ var import_typescript = __toESM(require("typescript"), 1);
299
+ var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
300
+ ".ts",
301
+ ".tsx",
302
+ ".js",
303
+ ".jsx",
304
+ ".mjs",
305
+ ".cjs"
306
+ ]);
307
+ var INDEX_BASENAMES = /* @__PURE__ */ new Set([
308
+ "index.ts",
309
+ "index.tsx",
310
+ "index.js",
311
+ "index.jsx",
312
+ "index.mjs",
313
+ "index.cjs"
314
+ ]);
315
+ function fileToModule(filePath, srcDir) {
316
+ const rel = (0, import_node_path2.relative)(srcDir, filePath);
317
+ const parts = rel.split(import_node_path2.sep);
318
+ const last = parts[parts.length - 1];
319
+ if (last === "index.ts" || last === "index.js" || last === "index.tsx" || last === "index.jsx") {
320
+ parts.pop();
321
+ } else {
322
+ const ext = (0, import_node_path2.extname)(last);
323
+ parts[parts.length - 1] = (0, import_node_path2.basename)(last, ext);
324
+ }
325
+ return parts.join(".");
326
+ }
327
+ function extractImports(source, fileName) {
328
+ const imports = /* @__PURE__ */ new Set();
329
+ const sourceFile = import_typescript.default.createSourceFile(
330
+ fileName,
331
+ source,
332
+ import_typescript.default.ScriptTarget.Latest,
333
+ true,
334
+ fileName.endsWith(".tsx") || fileName.endsWith(".jsx") ? import_typescript.default.ScriptKind.TSX : void 0
335
+ );
336
+ function visit(node) {
337
+ if (import_typescript.default.isImportDeclaration(node) && import_typescript.default.isStringLiteral(node.moduleSpecifier)) {
338
+ imports.add(node.moduleSpecifier.text);
339
+ }
340
+ if (import_typescript.default.isExportDeclaration(node) && node.moduleSpecifier && import_typescript.default.isStringLiteral(node.moduleSpecifier)) {
341
+ imports.add(node.moduleSpecifier.text);
342
+ }
343
+ if (import_typescript.default.isCallExpression(node) && node.expression.kind === import_typescript.default.SyntaxKind.Identifier && node.expression.text === "require" && node.arguments.length === 1 && import_typescript.default.isStringLiteral(node.arguments[0])) {
344
+ imports.add(node.arguments[0].text);
345
+ }
346
+ import_typescript.default.forEachChild(node, visit);
347
+ }
348
+ visit(sourceFile);
349
+ return imports;
350
+ }
351
+ function resolveImports(rawImports, basePackage, currentModule, isPackage) {
352
+ const resolved = /* @__PURE__ */ new Set();
353
+ for (const imp of rawImports) {
354
+ if (imp.startsWith("./") || imp.startsWith("../")) {
355
+ if (!currentModule) continue;
356
+ const moduleParts = currentModule.split(".");
357
+ let dirParts;
358
+ if (isPackage) {
359
+ dirParts = [...moduleParts];
360
+ } else {
361
+ dirParts = moduleParts.slice(0, -1);
362
+ }
363
+ const segments = imp.split("/");
364
+ for (const seg of segments) {
365
+ if (seg === ".") continue;
366
+ if (seg === "..") {
367
+ dirParts.pop();
368
+ } else {
369
+ dirParts.push(seg);
370
+ }
371
+ }
372
+ const resolvedModule = dirParts.join(".");
373
+ if (resolvedModule === basePackage || resolvedModule.startsWith(basePackage + ".")) {
374
+ resolved.add(resolvedModule);
375
+ }
376
+ } else if (imp === basePackage || imp.startsWith(basePackage + "/")) {
377
+ resolved.add(imp.replaceAll("/", "."));
378
+ }
379
+ }
380
+ return resolved;
381
+ }
382
+ function findSourceFiles(dir) {
383
+ const results = [];
384
+ function walk(d) {
385
+ const entries = (0, import_node_fs2.readdirSync)(d);
386
+ for (const entry of entries) {
387
+ if (entry === "node_modules" || entry === "dist" || entry === ".git") {
388
+ continue;
389
+ }
390
+ const full = (0, import_node_path2.join)(d, entry);
391
+ const stat = (0, import_node_fs2.statSync)(full);
392
+ if (stat.isDirectory()) {
393
+ walk(full);
394
+ } else if (SUPPORTED_EXTENSIONS.has((0, import_node_path2.extname)(entry))) {
395
+ results.push(full);
396
+ }
397
+ }
398
+ }
399
+ walk(dir);
400
+ return results;
401
+ }
402
+ function buildDependencyGraph(srcDir, basePackage) {
403
+ const graph = /* @__PURE__ */ new Map();
404
+ const files = findSourceFiles(srcDir);
405
+ for (const file of files) {
406
+ const moduleName = fileToModule(file, srcDir);
407
+ if (!moduleName) continue;
408
+ let source;
409
+ try {
410
+ source = (0, import_node_fs2.readFileSync)(file, "utf-8");
411
+ } catch (e) {
412
+ console.error(`Warning: could not read ${file}: ${e}`);
413
+ continue;
414
+ }
415
+ let rawImports;
416
+ try {
417
+ rawImports = extractImports(source, file);
418
+ } catch (e) {
419
+ console.error(`Warning: could not parse ${file}: ${e}`);
420
+ continue;
421
+ }
422
+ const isPackage = INDEX_BASENAMES.has((0, import_node_path2.basename)(file));
423
+ const deps = resolveImports(rawImports, basePackage, moduleName, isPackage);
424
+ deps.delete(moduleName);
425
+ graph.set(moduleName, deps);
426
+ }
427
+ return graph;
428
+ }
429
+ function findCycles(graph) {
430
+ const WHITE = 0;
431
+ const GRAY = 1;
432
+ const BLACK = 2;
433
+ const color = /* @__PURE__ */ new Map();
434
+ const path = [];
435
+ const cycles = [];
436
+ function dfs(node) {
437
+ color.set(node, GRAY);
438
+ path.push(node);
439
+ const neighbors = graph.get(node) ?? /* @__PURE__ */ new Set();
440
+ for (const neighbor of [...neighbors].sort()) {
441
+ if (color.get(neighbor) === GRAY && path.includes(neighbor)) {
442
+ const idx = path.indexOf(neighbor);
443
+ cycles.push([...path.slice(idx), neighbor]);
444
+ } else if ((color.get(neighbor) ?? WHITE) === WHITE) {
445
+ dfs(neighbor);
446
+ }
447
+ }
448
+ path.pop();
449
+ color.set(node, BLACK);
450
+ }
451
+ for (const node of [...graph.keys()].sort()) {
452
+ if ((color.get(node) ?? WHITE) === WHITE) {
453
+ dfs(node);
454
+ }
455
+ }
456
+ const unique = [];
457
+ const seen = /* @__PURE__ */ new Set();
458
+ for (const cycle of cycles) {
459
+ const ring = cycle.slice(0, -1);
460
+ let minVal = ring[0];
461
+ let minIdx = 0;
462
+ for (let i = 1; i < ring.length; i++) {
463
+ if (ring[i] < minVal) {
464
+ minVal = ring[i];
465
+ minIdx = i;
466
+ }
467
+ }
468
+ const normalized = [...ring.slice(minIdx), ...ring.slice(0, minIdx)].join(",");
469
+ if (!seen.has(normalized)) {
470
+ seen.add(normalized);
471
+ unique.push(cycle);
472
+ }
473
+ }
474
+ return unique;
475
+ }
476
+ function checkCircularImports(srcDir, basePackage) {
477
+ let stat;
478
+ try {
479
+ stat = (0, import_node_fs2.statSync)(srcDir);
480
+ } catch {
481
+ console.error(`Error: ${srcDir}/ directory not found`);
482
+ return 1;
483
+ }
484
+ if (!stat.isDirectory()) {
485
+ console.error(`Error: ${srcDir}/ is not a directory`);
486
+ return 1;
487
+ }
488
+ const graph = buildDependencyGraph(srcDir, basePackage);
489
+ console.log(`Scanned ${graph.size} modules`);
490
+ const cycles = findCycles(graph);
491
+ if (cycles.length > 0) {
492
+ console.log(`
493
+ Found ${cycles.length} circular import(s):
494
+ `);
495
+ for (let i = 0; i < cycles.length; i++) {
496
+ console.log(` Cycle ${i + 1}: ${cycles[i].join(" -> ")}`);
497
+ }
498
+ console.log();
499
+ return 1;
500
+ }
501
+ console.log("No circular imports detected.");
502
+ return 0;
503
+ }
504
+
505
+ // src/config.ts
506
+ var import_node_fs3 = require("fs");
507
+ var import_node_path3 = require("path");
508
+ function loadConfig(projectDir) {
509
+ const dir = projectDir ?? process.cwd();
510
+ const pkgPath = (0, import_node_path3.join)(dir, "package.json");
511
+ let raw;
512
+ try {
513
+ raw = (0, import_node_fs3.readFileSync)(pkgPath, "utf-8");
514
+ } catch {
515
+ return {};
516
+ }
517
+ const pkg = JSON.parse(raw);
518
+ const apdev = pkg["apdev"];
519
+ if (apdev && typeof apdev === "object" && !Array.isArray(apdev)) {
520
+ return apdev;
521
+ }
522
+ return {};
523
+ }
524
+
525
+ // src/index.ts
526
+ var import_node_fs4 = require("fs");
527
+ var import_node_path4 = require("path");
528
+ var import_node_url = require("url");
529
+ function readVersion() {
530
+ const thisDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
531
+ try {
532
+ const pkg = JSON.parse((0, import_node_fs4.readFileSync)((0, import_node_path4.join)(thisDir, "..", "package.json"), "utf-8"));
533
+ return pkg.version ?? "0.0.0";
534
+ } catch {
535
+ return "0.0.0";
536
+ }
537
+ }
538
+ var version = readVersion();
539
+ // Annotate the CommonJS export names for ESM import in node:
540
+ 0 && (module.exports = {
541
+ buildDependencyGraph,
542
+ checkCircularImports,
543
+ checkFile,
544
+ checkPaths,
545
+ fileToModule,
546
+ findCycles,
547
+ isAllowedChar,
548
+ loadConfig,
549
+ version
550
+ });
@@ -0,0 +1,41 @@
1
+ /** Return true if the character is in the allowed set. */
2
+ declare function isAllowedChar(c: string): boolean;
3
+ /**
4
+ * Check a single file for illegal characters.
5
+ * Returns a list of problem descriptions (empty if the file is clean).
6
+ */
7
+ declare function checkFile(filePath: string, maxProblems?: number): string[];
8
+ /**
9
+ * Check multiple files. Returns 0 if all clean, 1 if any have problems.
10
+ */
11
+ declare function checkPaths(paths: string[]): number;
12
+
13
+ /**
14
+ * Circular import detection tool.
15
+ *
16
+ * Builds a module-level dependency graph within a JS/TS package
17
+ * and reports any circular import chains.
18
+ */
19
+ /** Convert a file path to a dotted module name (relative to srcDir). */
20
+ declare function fileToModule(filePath: string, srcDir: string): string;
21
+ /** Build a module-to-module dependency graph for the given package. */
22
+ declare function buildDependencyGraph(srcDir: string, basePackage: string): Map<string, Set<string>>;
23
+ /** Find all elementary cycles in the dependency graph using DFS. */
24
+ declare function findCycles(graph: Map<string, Set<string>>): string[][];
25
+ /** Run circular import detection. Returns 0 if clean, 1 if cycles found. */
26
+ declare function checkCircularImports(srcDir: string, basePackage: string): number;
27
+
28
+ /**
29
+ * Configuration loading for apdev.
30
+ *
31
+ * Reads the "apdev" field from the consumer project's package.json.
32
+ */
33
+ declare function loadConfig(projectDir?: string): Record<string, unknown>;
34
+
35
+ /**
36
+ * apdev - Shared development tools for TypeScript/JavaScript projects.
37
+ */
38
+
39
+ declare const version: string;
40
+
41
+ export { buildDependencyGraph, checkCircularImports, checkFile, checkPaths, fileToModule, findCycles, isAllowedChar, loadConfig, version };
@@ -0,0 +1,41 @@
1
+ /** Return true if the character is in the allowed set. */
2
+ declare function isAllowedChar(c: string): boolean;
3
+ /**
4
+ * Check a single file for illegal characters.
5
+ * Returns a list of problem descriptions (empty if the file is clean).
6
+ */
7
+ declare function checkFile(filePath: string, maxProblems?: number): string[];
8
+ /**
9
+ * Check multiple files. Returns 0 if all clean, 1 if any have problems.
10
+ */
11
+ declare function checkPaths(paths: string[]): number;
12
+
13
+ /**
14
+ * Circular import detection tool.
15
+ *
16
+ * Builds a module-level dependency graph within a JS/TS package
17
+ * and reports any circular import chains.
18
+ */
19
+ /** Convert a file path to a dotted module name (relative to srcDir). */
20
+ declare function fileToModule(filePath: string, srcDir: string): string;
21
+ /** Build a module-to-module dependency graph for the given package. */
22
+ declare function buildDependencyGraph(srcDir: string, basePackage: string): Map<string, Set<string>>;
23
+ /** Find all elementary cycles in the dependency graph using DFS. */
24
+ declare function findCycles(graph: Map<string, Set<string>>): string[][];
25
+ /** Run circular import detection. Returns 0 if clean, 1 if cycles found. */
26
+ declare function checkCircularImports(srcDir: string, basePackage: string): number;
27
+
28
+ /**
29
+ * Configuration loading for apdev.
30
+ *
31
+ * Reads the "apdev" field from the consumer project's package.json.
32
+ */
33
+ declare function loadConfig(projectDir?: string): Record<string, unknown>;
34
+
35
+ /**
36
+ * apdev - Shared development tools for TypeScript/JavaScript projects.
37
+ */
38
+
39
+ declare const version: string;
40
+
41
+ export { buildDependencyGraph, checkCircularImports, checkFile, checkPaths, fileToModule, findCycles, isAllowedChar, loadConfig, version };