@reliverse/dler 1.6.6 → 1.6.7

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.
Files changed (82) hide show
  1. package/README.md +92 -10
  2. package/bin/app/build/cmd.js +1 -1
  3. package/bin/app/build/impl.js +1 -1
  4. package/bin/app/check/cmd.d.ts +0 -3
  5. package/bin/app/check/cmd.js +68 -351
  6. package/bin/app/cmds.d.ts +21 -437
  7. package/bin/app/cmds.js +38 -22
  8. package/bin/app/deps/cmd.js +2 -2
  9. package/bin/app/migrate/cmd.d.ts +12 -2
  10. package/bin/app/migrate/cmd.js +105 -58
  11. package/bin/app/migrate/codemods/anything-to-bun.d.ts +5 -0
  12. package/bin/app/migrate/codemods/anything-to-bun.js +597 -0
  13. package/bin/app/migrate/codemods/fs-to-relifso.d.ts +8 -0
  14. package/bin/app/migrate/codemods/fs-to-relifso.js +179 -0
  15. package/bin/app/migrate/codemods/path-to-pathkit.d.ts +8 -0
  16. package/bin/app/migrate/codemods/{lib-pathe-pathkit.js → path-to-pathkit.js} +22 -111
  17. package/bin/app/pub/cmd.js +1 -1
  18. package/bin/app/rempts/cmd/cmd.js +10 -3
  19. package/bin/cli.js +14 -4
  20. package/bin/libs/sdk/sdk-impl/build/build-library.js +23 -19
  21. package/bin/libs/sdk/sdk-impl/build/build-regular.js +13 -13
  22. package/bin/libs/sdk/sdk-impl/check/check-consts.d.ts +29 -0
  23. package/bin/libs/sdk/sdk-impl/check/check-consts.js +48 -0
  24. package/bin/libs/sdk/sdk-impl/check/check-mod.d.ts +2 -0
  25. package/bin/libs/sdk/sdk-impl/check/check-mod.js +87 -0
  26. package/bin/libs/sdk/sdk-impl/check/check-utils.d.ts +5 -0
  27. package/bin/libs/sdk/sdk-impl/check/check-utils.js +56 -0
  28. package/bin/libs/sdk/sdk-impl/check/rules/dler-config-health.d.ts +2 -0
  29. package/bin/libs/sdk/sdk-impl/check/rules/dler-config-health.js +37 -0
  30. package/bin/libs/sdk/sdk-impl/check/rules/file-extensions.d.ts +2 -0
  31. package/bin/libs/sdk/sdk-impl/check/rules/file-extensions.js +69 -0
  32. package/bin/{app/deps/impl/wrapper.d.ts → libs/sdk/sdk-impl/check/rules/missing-deps.d.ts} +1 -1
  33. package/bin/{app/deps/impl/wrapper.js → libs/sdk/sdk-impl/check/rules/missing-deps.js} +2 -2
  34. package/bin/libs/sdk/sdk-impl/check/rules/package-json-health.d.ts +2 -0
  35. package/bin/libs/sdk/sdk-impl/check/rules/package-json-health.js +67 -0
  36. package/bin/libs/sdk/sdk-impl/check/rules/path-extensions.d.ts +2 -0
  37. package/bin/libs/sdk/sdk-impl/check/rules/path-extensions.js +93 -0
  38. package/bin/libs/sdk/sdk-impl/check/rules/self-include.d.ts +2 -0
  39. package/bin/libs/sdk/sdk-impl/check/rules/self-include.js +98 -0
  40. package/bin/libs/sdk/sdk-impl/check/rules/tsconfig-health.d.ts +2 -0
  41. package/bin/libs/sdk/sdk-impl/check/rules/tsconfig-health.js +35 -0
  42. package/bin/libs/sdk/{default.d.ts → sdk-impl/config/default.d.ts} +1 -1
  43. package/bin/libs/sdk/{default.js → sdk-impl/config/default.js} +15 -5
  44. package/bin/libs/sdk/sdk-impl/config/define.d.ts +2 -0
  45. package/bin/libs/sdk/sdk-impl/config/define.js +4 -0
  46. package/bin/{init → libs/sdk/sdk-impl/config}/info.js +1 -1
  47. package/bin/{init → libs/sdk/sdk-impl/config}/init.js +8 -8
  48. package/bin/{init → libs/sdk/sdk-impl/config}/load.d.ts +2 -1
  49. package/bin/{init → libs/sdk/sdk-impl/config}/load.js +15 -6
  50. package/bin/libs/sdk/sdk-impl/library-flow.d.ts +1 -1
  51. package/bin/libs/sdk/sdk-impl/library-flow.js +3 -3
  52. package/bin/libs/sdk/sdk-impl/spell/spell-executors.js +1 -1
  53. package/bin/libs/sdk/sdk-impl/spell/spell-filesystem.d.ts +1 -1
  54. package/bin/libs/sdk/sdk-impl/spell/spell-filesystem.js +7 -1
  55. package/bin/libs/sdk/sdk-impl/utils/utils-build.d.ts +8 -2
  56. package/bin/libs/sdk/sdk-impl/utils/utils-build.js +5 -5
  57. package/bin/libs/sdk/sdk-impl/utils/utils-deps.js +36 -10
  58. package/bin/libs/sdk/sdk-impl/utils/utils-fs.js +20 -8
  59. package/bin/libs/sdk/sdk-impl/utils/utils-jsr-json.d.ts +2 -1
  60. package/bin/libs/sdk/sdk-impl/utils/utils-jsr-json.js +15 -4
  61. package/bin/libs/sdk/sdk-impl/utils/utils-pkg-json-libs.d.ts +5 -0
  62. package/bin/libs/sdk/sdk-impl/utils/utils-pkg-json-libs.js +98 -29
  63. package/bin/libs/sdk/sdk-impl/utils/utils-pkg-json-reg.js +12 -5
  64. package/bin/libs/sdk/sdk-types.d.ts +67 -33
  65. package/bin/mod.d.ts +1 -2
  66. package/bin/mod.js +1 -4
  67. package/package.json +1 -1
  68. package/bin/app/migrate/codemods/lib-pathe-pathkit.d.ts +0 -9
  69. /package/bin/app/migrate/codemods/{ts-module-resolution.d.ts → module-resolution.d.ts} +0 -0
  70. /package/bin/app/migrate/codemods/{ts-module-resolution.js → module-resolution.js} +0 -0
  71. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/analyzer.d.ts +0 -0
  72. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/analyzer.js +0 -0
  73. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/deps-types.d.ts +0 -0
  74. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/deps-types.js +0 -0
  75. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/filesystem.d.ts +0 -0
  76. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/filesystem.js +0 -0
  77. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/formatter.d.ts +0 -0
  78. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/formatter.js +0 -0
  79. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/parser.d.ts +0 -0
  80. /package/bin/{app/deps/impl → libs/sdk/sdk-impl/check/rules/deps}/parser.js +0 -0
  81. /package/bin/{init → libs/sdk/sdk-impl/config}/info.d.ts +0 -0
  82. /package/bin/{init → libs/sdk/sdk-impl/config}/init.d.ts +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # dler (prev. relidler) • reliverse bundler
1
+ # dler (prev. relidler) • framework for ts/js libs/cli/apps
2
2
 
3
- > @reliverse/dler (`/ˈdiː.lər/`, dealer) is a flexible, unified, and fully automated bundler for typescript and javascript projects, as well as an npm and jsr publishing tool. dler is not only a bundler, it also tries to serve as the most powerful codemod toolkit for js/ts.
3
+ > @reliverse/dler (`/ˈdiː.lər/`, dealer) is a flexible, unified, and fully automated bundler for ts/js projects, as well as an npm/jsr publishing tool. dler is not only a bundler, it also tries to serve as the most powerful codemod toolkit for ts/js.
4
4
 
5
5
  [sponsor](https://github.com/sponsors/blefnk) — [discord](https://discord.gg/pb8ukbwpsj) — [repo](https://github.com/reliverse/dler) — [npm](https://npmjs.com/@reliverse/dler) — [docs](https://docs.reliverse.org/reliverse/dler)
6
6
 
@@ -9,7 +9,7 @@
9
9
  - 😘 replacement for `unjs/unbuild`
10
10
  - ⚡ `dler` works via cli and sdk
11
11
  - 📦 automated npm/jsr publishing
12
- - ✅ ensures reliable js/ts builds
12
+ - ✅ ensures reliable ts/js builds
13
13
  - 🔄 handles automatic version bumps
14
14
  - 🔧 eliminates `package.json` headaches
15
15
  - 🎯 optimized for speed and modern workflows
@@ -170,6 +170,26 @@ checks your project for common issues and potential improvements. This command p
170
170
  - Compares against package.json
171
171
  - Reports missing dependencies
172
172
 
173
+ - **Self-Include**: Prevents circular dependencies and self-imports
174
+ - Checks for imports from the main package in dist directories
175
+ - Prevents libraries from importing themselves
176
+ - Allows libraries to import from other libraries
177
+
178
+ - **Module Resolution**: Validates TypeScript module resolution settings
179
+ - Ensures proper moduleResolution in tsconfig.json
180
+ - Supports both "bundler" and "nodenext" strategies
181
+ - Reports configuration issues
182
+
183
+ - **Dler Config Health**: Validates your dler configuration
184
+ - Checks libs main file format
185
+ - Ensures proper configuration structure
186
+ - Reports configuration issues
187
+
188
+ - **Package.json Validation**: Ensures your package.json follows best practices
189
+ - Requires: name, version, type=module, keywords
190
+ - Forbids: bin, exports, files, main, module (they are auto-generated by dler)
191
+ - Helps maintain consistent package configuration
192
+
173
193
  ```bash
174
194
  # Fully interactive mode (when no args provided)
175
195
  dler check
@@ -189,7 +209,7 @@ dler check --json
189
209
  **arguments:**
190
210
 
191
211
  - `--directory`: directory to check (src, dist-npm, dist-jsr, dist-libs/npm, dist-libs/jsr, or all)
192
- - `--checks`: comma-separated list of checks to run (missing-dependencies, file-extensions, path-extensions)
212
+ - `--checks`: comma-separated list of checks to run (missing-deps, file-extensions, path-extensions, dler-config-health, self-include, tsconfig-health, package-json-health)
193
213
  - `--strict`: enable strict mode (requires explicit extensions)
194
214
  - `--json`: output results in JSON format
195
215
 
@@ -277,7 +297,7 @@ libslist: {
277
297
  libdeclarations: true,
278
298
  libdescription: "@reliverse/dler without cli",
279
299
  libdirname: "sdk",
280
- libmainfile: "sdk/sdk-mod.ts",
300
+ libmainfile: "sdk-mod.ts",
281
301
  libpkgkeepdeps: false,
282
302
  libtranspileminify: true,
283
303
  },
@@ -304,9 +324,56 @@ not yet documented.
304
324
 
305
325
  helps migrate between different libraries and module resolution strategies. currently supports:
306
326
 
307
- - `pathe-to-pathkit`: migrate from pathe to pathkit library
308
- - `pathkit-to-pathe`: migrate from pathkit to pathe library
327
+ - `path-to-pathkit`: migrate from node:path and unjs/pathe to pathkit library
328
+ - `fs-to-relifso`: migrate from node:fs and fs-extra to relifso library
309
329
  - `module-resolution`: migrate between module resolution strategies
330
+ - `anything-to-bun`: migrate Node.js projects to Bun runtime
331
+
332
+ **path-to-pathkit features:**
333
+
334
+ - Migrates from both `pathe` and `node:path` to `@reliverse/pathkit`
335
+ - Handles both default and named exports
336
+ - Supports multi-line imports
337
+ - Converts require statements
338
+ - Updates package.json dependencies
339
+
340
+ **fs-to-relifso features:**
341
+
342
+ - Migrates from both `node:fs` and `fs-extra` to `@reliverse/relifso`
343
+ - Handles both default and named exports
344
+ - Supports multi-line imports
345
+ - Converts require statements
346
+ - Updates package.json dependencies
347
+ - Preserves import structure and formatting
348
+
349
+ **anything-to-bun features:**
350
+
351
+ - Migrates Node.js imports to use `node:` prefix
352
+ - Replaces npm/yarn/pnpm features with bun equivalents
353
+ - Converts to Bun-native APIs:
354
+ - Database: `pg`/`postgres` → `Bun.sql`, `sqlite3` → `bun:sqlite`
355
+ - Redis: `redis`/`ioredis` → `Bun.redis`
356
+ - Utilities: `glob` → `Bun.Glob`, `bcrypt`/`argon2` → `Bun.password`
357
+ - Testing: `jest`/`vitest` → `bun:test`
358
+ - FFI: `node-ffi` → `bun:ffi`
359
+ - Transforms file operations to `Bun.file` API
360
+ - Converts Express apps to `Bun.serve`
361
+ - Updates package.json scripts and dependencies
362
+ - Generates Bun configuration files
363
+ - Creates Dockerfile for Bun deployment
364
+
365
+ **usage example:**
366
+
367
+ ```bash
368
+ # Preview changes without applying them
369
+ dler migrate --lib anything-to-bun --dryRun
370
+
371
+ # Apply changes
372
+ dler migrate --lib anything-to-bun
373
+
374
+ # Migrate specific project
375
+ dler migrate --lib anything-to-bun --project ./my-app
376
+ ```
310
377
 
311
378
  **module resolution targets:**
312
379
 
@@ -316,8 +383,11 @@ helps migrate between different libraries and module resolution strategies. curr
316
383
  **usage examples:**
317
384
 
318
385
  ```bash
319
- # Migrate from pathe to pathkit
320
- dler migrate --lib pathe-to-pathkit
386
+ # Migrate from node:path and/or pathe to pathkit
387
+ dler migrate --lib path-to-pathkit
388
+
389
+ # Migrate from node:fs and/or fs-extra to relifso
390
+ dler migrate --lib fs-to-relifso
321
391
 
322
392
  # Migrate to nodenext module resolution
323
393
  dler migrate --lib module-resolution --target nodenext
@@ -340,16 +410,28 @@ dler migrate --lib module-resolution --target nodenext --dryRun
340
410
 
341
411
  **next steps after migration:**
342
412
 
343
- - for pathe-to-pathkit:
413
+ - for path-to-pathkit:
344
414
  1. run 'bun install' to install @reliverse/pathkit
345
415
  2. test your application
346
416
  3. consider using advanced pathkit features
347
417
 
418
+ - for fs-to-relifso:
419
+ 1. run 'bun install' to install @reliverse/relifso
420
+ 2. test your application
421
+ 3. review any file system operations that might need manual updates
422
+
348
423
  - for module-resolution:
349
424
  1. test your application
350
425
  2. ensure your build tools support the new module resolution
351
426
  3. review any warnings in the migration output
352
427
 
428
+ - for anything-to-bun:
429
+ 1. run 'bun install' to install dependencies with Bun
430
+ 2. test your application thoroughly
431
+ 3. review async/await usage in converted file operations
432
+ 4. update any custom database queries to use Bun.sql syntax
433
+ 5. review and update any custom middleware in Express apps
434
+
353
435
  ### 9. `pub`
354
436
 
355
437
  pub command is separated for its own build-in plugin as well.
@@ -1,6 +1,6 @@
1
1
  import { defineArgs, defineCommand } from "@reliverse/rempts";
2
2
  import { dlerBuild } from "./impl.js";
3
- import { ensureDlerConfig } from "../../init/init.js";
3
+ import { ensureDlerConfig } from "../../libs/sdk/sdk-impl/config/init.js";
4
4
  export default defineCommand({
5
5
  meta: {
6
6
  name: "build",
@@ -5,7 +5,7 @@ import {
5
5
  } from "@reliverse/bleump";
6
6
  import path from "@reliverse/pathkit";
7
7
  import fs from "@reliverse/relifso";
8
- import { loadConfig } from "../../init/load.js";
8
+ import { loadConfig } from "../../libs/sdk/sdk-impl/config/load.js";
9
9
  import { processLibraryFlow } from "../../libs/sdk/sdk-impl/library-flow.js";
10
10
  import { processRegularFlow } from "../../libs/sdk/sdk-impl/regular-flow.js";
11
11
  import { finalizeBuildPub } from "../../libs/sdk/sdk-impl/utils/finalize.js";
@@ -1,6 +1,3 @@
1
- import type { CheckResult, FileCheckOptions } from "../../libs/sdk/sdk-types.js";
2
- export declare function checkFileExtensions(options: FileCheckOptions): Promise<CheckResult>;
3
- export declare function checkPathExtensions(options: FileCheckOptions): Promise<CheckResult>;
4
1
  declare const _default: import("@reliverse/rempts").Command<{
5
2
  directory: {
6
3
  type: "string";
@@ -1,5 +1,3 @@
1
- import { getFileImportsExports, extname, join } from "@reliverse/pathkit";
2
- import fs from "@reliverse/relifso";
3
1
  import { relinka } from "@reliverse/relinka";
4
2
  import {
5
3
  defineCommand,
@@ -8,335 +6,14 @@ import {
8
6
  confirmPrompt,
9
7
  defineArgs
10
8
  } from "@reliverse/rempts";
11
- import { readTSConfig } from "pkg-types";
12
- import { checkMissingDependencies } from "../deps/impl/wrapper.js";
13
- import { IGNORE_PATTERNS } from "../../libs/sdk/sdk-impl/constants.js";
14
- const ALLOWED_FILE_EXTENSIONS = {
15
- src: ["", ".ts", ".css", ".json"],
16
- // .ts files allowed in src
17
- "dist-npm": ["", ".js", ".css", ".json"],
18
- // no .ts files in npm dist
19
- "dist-jsr": ["", ".ts", ".css", ".json"],
20
- // ✅ .ts files allowed in jsr dist
21
- "dist-libs/npm": ["", ".js", ".css", ".json"],
22
- // ❌ no .ts files in npm libs
23
- "dist-libs/jsr": ["", ".ts", ".css", ".json"]
24
- // ✅ .ts files allowed in jsr libs
25
- };
26
- const STRICT_FILE_EXTENSIONS = {
27
- src: [".ts", ".css", ".json"],
28
- // ✅ .ts files required in src
29
- "dist-npm": [".js", ".css", ".json"],
30
- // ❌ no .ts files in npm dist
31
- "dist-jsr": [".ts", ".css", ".json"],
32
- // ✅ .ts files required in jsr dist
33
- "dist-libs/npm": [".js", ".css", ".json"],
34
- // ❌ no .ts files in npm libs
35
- "dist-libs/jsr": [".ts", ".css", ".json"]
36
- // ✅ .ts files required in jsr libs
37
- };
38
- const ALLOWED_IMPORT_EXTENSIONS = {
39
- src: ["", ".js", ".css", ".json"],
40
- // ❌ no .ts imports (use .js)
41
- "dist-npm": ["", ".js", ".css", ".json"],
42
- // ❌ no .ts imports
43
- "dist-jsr": ["", ".ts", ".css", ".json"],
44
- // ✅ .ts imports allowed
45
- "dist-libs/npm": ["", ".js", ".css", ".json"],
46
- // ❌ no .ts imports
47
- "dist-libs/jsr": ["", ".ts", ".css", ".json"]
48
- // ✅ .ts imports allowed
49
- };
50
- const STRICT_IMPORT_EXTENSIONS = {
51
- src: [".js", ".css", ".json"],
52
- // ❌ no .ts imports, no empty
53
- "dist-npm": [".js", ".css", ".json"],
54
- // ❌ no .ts imports
55
- "dist-jsr": [".ts", ".css", ".json"],
56
- // ✅ .ts imports required
57
- "dist-libs/npm": [".js", ".css", ".json"],
58
- // ❌ no .ts imports
59
- "dist-libs/jsr": [".ts", ".css", ".json"]
60
- // ✅ .ts imports required
61
- };
62
- async function validateDirectory(dir) {
63
- try {
64
- const stat = await fs.stat(dir);
65
- return stat.isDirectory();
66
- } catch {
67
- return false;
68
- }
69
- }
70
- function shouldIgnoreFile(filePath) {
71
- const pathSegments = filePath.split("/");
72
- return IGNORE_PATTERNS.some(
73
- (pattern) => pathSegments.some((segment) => segment.includes(pattern))
74
- );
75
- }
76
- async function getAllFiles(dir, onProgress) {
77
- const results = [];
78
- let fileCount = 0;
79
- async function searchDirectory(directory) {
80
- try {
81
- const files = await fs.readdir(directory);
82
- for (const file of files) {
83
- const fullPath = join(directory, file);
84
- if (shouldIgnoreFile(fullPath)) {
85
- continue;
86
- }
87
- try {
88
- const stat = await fs.stat(fullPath);
89
- if (stat.isDirectory()) {
90
- if (file === "templates") continue;
91
- await searchDirectory(fullPath);
92
- } else {
93
- results.push(fullPath);
94
- fileCount++;
95
- onProgress?.(fileCount, fileCount, fullPath);
96
- }
97
- } catch {
98
- relinka("warn", `skipping inaccessible file: ${fullPath}`);
99
- }
100
- }
101
- } catch {
102
- relinka("warn", `skipping inaccessible directory: ${directory}`);
103
- }
104
- }
105
- if (!await validateDirectory(dir)) {
106
- throw new Error(`directory "${dir}" does not exist or is not accessible`);
107
- }
108
- await searchDirectory(dir);
109
- return results;
110
- }
111
- async function validateModuleResolution() {
112
- try {
113
- const tsconfig = await readTSConfig();
114
- const moduleResolution = tsconfig?.compilerOptions?.moduleResolution;
115
- if (!moduleResolution) {
116
- throw new Error("moduleResolution is not specified in tsconfig.json");
117
- }
118
- if (moduleResolution !== "bundler" && moduleResolution !== "nodenext") {
119
- throw new Error(
120
- `unsupported moduleResolution: ${moduleResolution}. Only "bundler" and "nodenext" are supported`
121
- );
122
- }
123
- return moduleResolution;
124
- } catch (error) {
125
- throw new Error(
126
- `failed to read tsconfig.json: ${error instanceof Error ? error.message : "unknown error"}`
127
- );
128
- }
129
- }
130
- function getAllowedFileExtensions(directory, strict, moduleResolution) {
131
- if (!strict) {
132
- return ALLOWED_FILE_EXTENSIONS[directory];
133
- }
134
- if (moduleResolution === "bundler") {
135
- return STRICT_FILE_EXTENSIONS[directory];
136
- }
137
- return STRICT_FILE_EXTENSIONS[directory];
138
- }
139
- function getAllowedImportExtensions(directory, strict) {
140
- if (strict) {
141
- return STRICT_IMPORT_EXTENSIONS[directory];
142
- }
143
- return ALLOWED_IMPORT_EXTENSIONS[directory];
144
- }
145
- export async function checkFileExtensions(options) {
146
- const startTime = Date.now();
147
- const issues = [];
148
- const { directory, strict, moduleResolution, onProgress } = options;
149
- const allowedExts = getAllowedFileExtensions(
150
- directory,
151
- strict,
152
- moduleResolution
153
- );
154
- try {
155
- const files = await getAllFiles(directory, onProgress);
156
- const batchSize = 50;
157
- const batches = [];
158
- for (let i = 0; i < files.length; i += batchSize) {
159
- batches.push(files.slice(i, i + batchSize));
160
- }
161
- for (const [batchIndex, batch] of batches.entries()) {
162
- const batchPromises = batch.map(async (file, fileIndex) => {
163
- const globalIndex = batchIndex * batchSize + fileIndex;
164
- onProgress?.(globalIndex + 1, files.length, file);
165
- const ext = extname(file);
166
- if (!allowedExts.includes(ext)) {
167
- let message = `file has disallowed extension "${ext}" (allowed: ${allowedExts.join(", ")})`;
168
- if (ext === ".ts" && (directory === "dist-npm" || directory === "dist-libs/npm")) {
169
- message = `typescript file found in javascript environment: ${file} (should be compiled to .js)`;
170
- } else if (ext === ".js" && (directory === "src" || directory === "dist-jsr" || directory === "dist-libs/jsr")) {
171
- message = `javascript file found in typescript environment: ${file} (should be .ts)`;
172
- }
173
- return {
174
- file,
175
- message,
176
- type: "file-extension"
177
- };
178
- }
179
- return null;
180
- });
181
- const batchResults = await Promise.all(batchPromises);
182
- issues.push(...batchResults.filter(Boolean));
183
- }
184
- return {
185
- success: issues.length === 0,
186
- issues,
187
- stats: {
188
- filesChecked: files.length,
189
- importsChecked: 0,
190
- timeElapsed: Date.now() - startTime
191
- }
192
- };
193
- } catch (error) {
194
- throw new Error(
195
- `failed to check file extensions: ${error instanceof Error ? error.message : "unknown error"}`
196
- );
197
- }
198
- }
199
- export async function checkPathExtensions(options) {
200
- const startTime = Date.now();
201
- const issues = [];
202
- const { directory, strict, onProgress } = options;
203
- const allowedExts = getAllowedImportExtensions(directory, strict);
204
- try {
205
- const files = await getAllFiles(directory);
206
- let totalImports = 0;
207
- const importableFiles = files.filter((file) => {
208
- const ext = extname(file);
209
- return [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext);
210
- });
211
- const batchSize = 20;
212
- const batches = [];
213
- for (let i = 0; i < importableFiles.length; i += batchSize) {
214
- batches.push(importableFiles.slice(i, i + batchSize));
215
- }
216
- for (const [batchIndex, batch] of batches.entries()) {
217
- const batchPromises = batch.map(async (file, fileIndex) => {
218
- const globalIndex = batchIndex * batchSize + fileIndex;
219
- onProgress?.(globalIndex + 1, importableFiles.length, file);
220
- try {
221
- const content = await fs.readFile(file, "utf-8");
222
- const imports = getFileImportsExports(content, {
223
- kind: "import",
224
- pathTypes: ["relative", "alias"]
225
- });
226
- totalImports += imports.length;
227
- const fileIssues = [];
228
- for (const imp of imports) {
229
- if (!imp.source) continue;
230
- const ext = extname(imp.source);
231
- if (!allowedExts.includes(ext)) {
232
- const isTypeScriptImport = ext === ".ts";
233
- const isJsEnvironment = directory === "src" || directory === "dist-npm" || directory === "dist-libs/npm";
234
- let message;
235
- if (isTypeScriptImport && isJsEnvironment) {
236
- message = `import uses .ts extension in javascript environment: ${imp.source} (use .js extension instead)`;
237
- } else {
238
- message = `import has disallowed extension "${ext}": ${imp.source} (allowed: ${allowedExts.join(", ")})`;
239
- }
240
- fileIssues.push({
241
- file,
242
- message,
243
- type: "path-extension",
244
- line: getLineNumber(content, imp.start),
245
- source: imp.source
246
- });
247
- }
248
- }
249
- return { issues: fileIssues, importCount: imports.length };
250
- } catch {
251
- relinka("warn", `skipping unreadable file: ${file}`);
252
- return { issues: [], importCount: 0 };
253
- }
254
- });
255
- const batchResults = await Promise.all(batchPromises);
256
- for (const result of batchResults) {
257
- issues.push(...result.issues);
258
- totalImports += result.importCount;
259
- }
260
- }
261
- return {
262
- success: issues.length === 0,
263
- issues,
264
- stats: {
265
- filesChecked: importableFiles.length,
266
- importsChecked: totalImports,
267
- timeElapsed: Date.now() - startTime
268
- }
269
- };
270
- } catch (error) {
271
- throw new Error(
272
- `failed to check path extensions: ${error instanceof Error ? error.message : "unknown error"}`
273
- );
274
- }
275
- }
276
- function getLineNumber(content, position) {
277
- return content.slice(0, position).split("\n").length;
278
- }
279
- function displayResults(checkType, directory, result) {
280
- const { success, issues, stats } = result;
281
- if (success) {
282
- relinka("success", `\u2713 ${checkType} check passed for ${directory}`);
283
- relinka(
284
- "info",
285
- ` files checked: ${stats.filesChecked}, imports: ${stats.importsChecked}, time: ${stats.timeElapsed}ms`
286
- );
287
- } else {
288
- relinka(
289
- "error",
290
- `\u2717 ${checkType} check failed for ${directory} (${issues.length} issues)`
291
- );
292
- const fileIssues = issues.filter((i) => i.type === "file-extension");
293
- const pathIssues = issues.filter((i) => i.type === "path-extension");
294
- const missingDepIssues = issues.filter(
295
- (i) => i.type === "missing-dependency"
296
- );
297
- const builtinIssues = issues.filter((i) => i.type === "builtin-module");
298
- if (fileIssues.length > 0) {
299
- relinka("error", ` file extension issues (${fileIssues.length}):`);
300
- for (const issue of fileIssues.slice(0, 10)) {
301
- relinka("error", ` ${issue.file}: ${issue.message}`);
302
- }
303
- if (fileIssues.length > 10) {
304
- relinka("error", ` ... and ${fileIssues.length - 10} more`);
305
- }
306
- }
307
- if (pathIssues.length > 0) {
308
- relinka("error", ` import extension issues (${pathIssues.length}):`);
309
- for (const issue of pathIssues.slice(0, 10)) {
310
- relinka("error", ` ${issue.file}:${issue.line}: ${issue.message}`);
311
- }
312
- if (pathIssues.length > 10) {
313
- relinka("error", ` ... and ${pathIssues.length - 10} more`);
314
- }
315
- }
316
- if (missingDepIssues.length > 0) {
317
- relinka("error", ` missing dependencies (${missingDepIssues.length}):`);
318
- for (const issue of missingDepIssues.slice(0, 10)) {
319
- relinka("error", ` ${issue.message}`);
320
- }
321
- if (missingDepIssues.length > 10) {
322
- relinka("error", ` ... and ${missingDepIssues.length - 10} more`);
323
- }
324
- }
325
- if (builtinIssues.length > 0) {
326
- relinka("warn", ` builtin modules used (${builtinIssues.length}):`);
327
- for (const issue of builtinIssues.slice(0, 10)) {
328
- relinka("warn", ` ${issue.message}`);
329
- }
330
- if (builtinIssues.length > 10) {
331
- relinka("warn", ` ... and ${builtinIssues.length - 10} more`);
332
- }
333
- }
334
- relinka(
335
- "info",
336
- ` stats: ${stats.filesChecked} files, ${stats.importsChecked} imports, ${stats.timeElapsed}ms`
337
- );
338
- }
339
- }
9
+ import { displayCheckResults } from "../../libs/sdk/sdk-impl/check/check-mod.js";
10
+ import { checkDlerConfigHealth } from "../../libs/sdk/sdk-impl/check/rules/dler-config-health.js";
11
+ import { checkFileExtensions } from "../../libs/sdk/sdk-impl/check/rules/file-extensions.js";
12
+ import { checkMissingDependencies } from "../../libs/sdk/sdk-impl/check/rules/missing-deps.js";
13
+ import { checkPackageJsonHealth } from "../../libs/sdk/sdk-impl/check/rules/package-json-health.js";
14
+ import { checkPathExtensions } from "../../libs/sdk/sdk-impl/check/rules/path-extensions.js";
15
+ import { checkSelfInclude } from "../../libs/sdk/sdk-impl/check/rules/self-include.js";
16
+ import { checkTsConfigHealth } from "../../libs/sdk/sdk-impl/check/rules/tsconfig-health.js";
340
17
  export default defineCommand({
341
18
  meta: {
342
19
  name: "check",
@@ -350,7 +27,7 @@ export default defineCommand({
350
27
  },
351
28
  checks: {
352
29
  type: "string",
353
- description: "comma-separated list of checks to run (missing-dependencies,file-extensions,path-extensions)"
30
+ description: "comma-separated list of checks to run (missing-deps,file-extensions,path-extensions,dler-config-health,self-include,tsconfig-health,package-json-health)"
354
31
  },
355
32
  strict: {
356
33
  type: "boolean",
@@ -374,17 +51,10 @@ export default defineCommand({
374
51
  "info",
375
52
  "\u{1F4E6} import rules: use .js imports in src/npm dirs, .ts imports in jsr dirs"
376
53
  );
377
- let moduleResolution;
378
- try {
379
- moduleResolution = await validateModuleResolution();
380
- relinka("info", `using moduleResolution: ${moduleResolution}`);
381
- } catch (error) {
382
- relinka(
383
- "error",
384
- error instanceof Error ? error.message : "unknown error"
385
- );
386
- return;
387
- }
54
+ relinka(
55
+ "info",
56
+ "\u{1F504} self-include rules: no importing from main package or self-imports in libs"
57
+ );
388
58
  let dir;
389
59
  let checks;
390
60
  let strict;
@@ -395,7 +65,9 @@ export default defineCommand({
395
65
  title: "select a directory to check",
396
66
  options: [
397
67
  { label: "all directories", value: "all" },
68
+ // TODO: run this automatically BEFORE `dler build`
398
69
  { label: "src (typescript source)", value: "src" },
70
+ // TODO: run this automatically AFTER `dler build`
399
71
  { label: "dist-npm (compiled js)", value: "dist-npm" },
400
72
  { label: "dist-jsr (typescript)", value: "dist-jsr" },
401
73
  { label: "dist-libs/npm (compiled js)", value: "dist-libs/npm" },
@@ -409,7 +81,7 @@ export default defineCommand({
409
81
  checks = await multiselectPrompt({
410
82
  title: "select checks to run",
411
83
  options: [
412
- { label: "missing dependencies", value: "missing-dependencies" },
84
+ { label: "missing dependencies", value: "missing-deps" },
413
85
  {
414
86
  label: "file extensions (.ts/.js files)",
415
87
  value: "file-extensions"
@@ -417,6 +89,22 @@ export default defineCommand({
417
89
  {
418
90
  label: "import path extensions (.ts/.js imports)",
419
91
  value: "path-extensions"
92
+ },
93
+ {
94
+ label: "dler configuration",
95
+ value: "dler-config-health"
96
+ },
97
+ {
98
+ label: "self-include (no self-imports)",
99
+ value: "self-include"
100
+ },
101
+ {
102
+ label: "tsconfig.json validation",
103
+ value: "tsconfig-health"
104
+ },
105
+ {
106
+ label: "package.json validation",
107
+ value: "package-json-health"
420
108
  }
421
109
  ]
422
110
  });
@@ -449,40 +137,69 @@ checking directory: ${directory}`);
449
137
  }
450
138
  };
451
139
  try {
452
- if (checks.includes("missing-dependencies")) {
140
+ if (checks.includes("package-json-health")) {
141
+ process.stdout.write(" checking package.json health...\n");
142
+ const result = await checkPackageJsonHealth();
143
+ process.stdout.write("\r");
144
+ displayCheckResults("package.json health", directory, result);
145
+ }
146
+ if (checks.includes("tsconfig-health")) {
147
+ process.stdout.write(" checking tsconfig.json health...\n");
148
+ const result = await checkTsConfigHealth();
149
+ process.stdout.write("\r");
150
+ displayCheckResults("tsconfig.json health", directory, result);
151
+ }
152
+ if (checks.includes("dler-config-health")) {
153
+ process.stdout.write(" checking libs main file format...\n");
154
+ const result = await checkDlerConfigHealth();
155
+ process.stdout.write("\r");
156
+ displayCheckResults("libs main file format", directory, result);
157
+ }
158
+ if (checks.includes("missing-deps")) {
453
159
  process.stdout.write(" checking missing dependencies...\n");
454
160
  const result = await checkMissingDependencies({
455
161
  directory,
456
162
  strict: false,
457
163
  // not used for deps check
458
- moduleResolution,
164
+ moduleResolution: "bundler",
459
165
  // not used for deps check
460
166
  onProgress
461
167
  });
462
168
  process.stdout.write("\r");
463
- displayResults("missing dependencies", directory, result);
169
+ displayCheckResults("missing dependencies", directory, result);
464
170
  }
465
171
  if (checks.includes("file-extensions")) {
466
172
  process.stdout.write(" checking file extensions...\n");
467
173
  const result = await checkFileExtensions({
468
174
  directory,
469
175
  strict,
470
- moduleResolution,
176
+ moduleResolution: "bundler",
471
177
  onProgress
472
178
  });
473
179
  process.stdout.write("\r");
474
- displayResults("file extensions", directory, result);
180
+ displayCheckResults("file extensions", directory, result);
475
181
  }
476
182
  if (checks.includes("path-extensions")) {
477
183
  process.stdout.write(" checking import path extensions...\n");
478
184
  const result = await checkPathExtensions({
479
185
  directory,
480
186
  strict,
481
- moduleResolution,
187
+ moduleResolution: "bundler",
188
+ onProgress
189
+ });
190
+ process.stdout.write("\r");
191
+ displayCheckResults("path extensions", directory, result);
192
+ }
193
+ if (checks.includes("self-include")) {
194
+ process.stdout.write(" checking self-includes...\n");
195
+ const result = await checkSelfInclude({
196
+ directory,
197
+ strict,
198
+ moduleResolution: "bundler",
482
199
  onProgress
483
200
  });
484
201
  process.stdout.write("\r");
485
- displayResults("path extensions", directory, result);
202
+ displayCheckResults("self-includes", directory, result);
486
203
  }
487
204
  } catch (error) {
488
205
  relinka(