@reliverse/dler 1.7.21 → 1.7.23

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 (35) hide show
  1. package/bin/app/agg/impl.js +1 -1
  2. package/bin/app/cmds.d.ts +1 -1
  3. package/bin/app/cmds.js +1 -1
  4. package/bin/app/inject/cmd.d.ts +0 -24
  5. package/bin/app/inject/cmd.js +0 -47
  6. package/bin/app/{spell → magic}/cmd.d.ts +2 -0
  7. package/bin/app/magic/cmd.js +101 -0
  8. package/bin/app/pub/impl.js +4 -2
  9. package/bin/libs/cfg/cfg-mod.d.ts +24 -195
  10. package/bin/libs/cfg/cfg-mod.js +71 -66
  11. package/bin/libs/cfg/constants.d.ts +68 -0
  12. package/bin/libs/cfg/constants.js +60 -0
  13. package/bin/libs/cfg/rse/rse-impl/rse-create.js +1 -1
  14. package/bin/libs/cfg/rse/rse-impl/rse-define.d.ts +11 -11
  15. package/bin/libs/cfg/rse/rse-mod.d.ts +1 -1
  16. package/bin/libs/cfg/rse/rse-mod.js +1 -1
  17. package/bin/libs/sdk/sdk-impl/cmds/inject/inject-impl-mod.d.ts +63 -0
  18. package/bin/libs/sdk/sdk-impl/cmds/inject/inject-impl-mod.js +237 -0
  19. package/bin/libs/sdk/sdk-impl/config/info.js +1 -3
  20. package/bin/libs/sdk/sdk-impl/magic/apply.d.ts +63 -0
  21. package/bin/libs/sdk/sdk-impl/{spell/applyMagicSpells.js → magic/apply.js} +223 -70
  22. package/bin/libs/sdk/sdk-impl/{spell → magic}/spells.d.ts +16 -1
  23. package/bin/libs/sdk/sdk-impl/{spell → magic}/spells.js +41 -1
  24. package/bin/libs/sdk/sdk-impl/rules/reliverse/missing-deps/deps-types.d.ts +1 -1
  25. package/bin/libs/sdk/sdk-mod.d.ts +93 -42
  26. package/bin/libs/sdk/sdk-mod.js +119 -27
  27. package/package.json +2 -2
  28. package/bin/app/inject/impl.d.ts +0 -5
  29. package/bin/app/inject/impl.js +0 -159
  30. package/bin/app/spell/cmd.js +0 -47
  31. package/bin/libs/sdk/sdk-impl/spell/applyMagicSpells.d.ts +0 -38
  32. /package/bin/app/{spell → magic}/old.d.ts +0 -0
  33. /package/bin/app/{spell → magic}/old.js +0 -0
  34. /package/bin/libs/cfg/rse/rse-impl/{rse-inject.d.ts → rse-comments.d.ts} +0 -0
  35. /package/bin/libs/cfg/rse/rse-impl/{rse-inject.js → rse-comments.js} +0 -0
@@ -13,36 +13,51 @@ const DEFAULT_OPTIONS = {
13
13
  stopOnError: false,
14
14
  copyFileWithDirectivesFromSrcBeforeProcessing: true
15
15
  };
16
- const DIST_PATHS = {
16
+ const DEFAULT_OUTPUT_PATHS = {
17
17
  "dist-jsr": "dist-jsr/bin",
18
18
  "dist-npm": "dist-npm/bin",
19
19
  "dist-libs": "dist-libs"
20
20
  };
21
- function validateTargets(targets) {
22
- const distLibs = /* @__PURE__ */ new Set();
21
+ function validateTargets(targets, customOutputPaths) {
22
+ const outputDirs = /* @__PURE__ */ new Set();
23
23
  const specificLibs = /* @__PURE__ */ new Set();
24
+ const customTargets = /* @__PURE__ */ new Set();
25
+ const allOutputPaths = { ...DEFAULT_OUTPUT_PATHS, ...customOutputPaths };
24
26
  for (const target of targets) {
25
- const [dist, lib] = target.split("/");
26
- if (!dist || !Object.keys(DIST_PATHS).includes(dist)) {
27
- throw new Error(`Invalid distribution target: ${dist}`);
27
+ const [outputDir, lib] = target.split("/");
28
+ if (!outputDir) {
29
+ throw new Error(`Invalid output target: ${target}`);
28
30
  }
29
- if (dist === "dist-libs") {
31
+ const outputPath = allOutputPaths[outputDir] || outputDir;
32
+ const fullPath = path.join(process.cwd(), outputPath);
33
+ if (!fs.existsSync(fullPath)) {
34
+ throw new Error(`Output directory does not exist: ${outputPath}`);
35
+ }
36
+ const isCustomTarget = !["dist-npm", "dist-jsr", "dist-libs"].includes(outputDir);
37
+ if (isCustomTarget) {
38
+ if (customTargets.has(outputDir)) {
39
+ throw new Error(`Duplicate custom target: ${outputDir}`);
40
+ }
41
+ customTargets.add(outputDir);
42
+ continue;
43
+ }
44
+ if (outputDir === "dist-libs") {
30
45
  if (lib) {
31
46
  if (specificLibs.has(lib)) {
32
47
  throw new Error(`Duplicate library target: ${target}`);
33
48
  }
34
49
  specificLibs.add(lib);
35
50
  } else {
36
- if (distLibs.has("dist-libs") || specificLibs.size > 0) {
51
+ if (outputDirs.has("dist-libs") || specificLibs.size > 0) {
37
52
  throw new Error("Cannot mix 'dist-libs' with specific library targets");
38
53
  }
39
- distLibs.add("dist-libs");
54
+ outputDirs.add("dist-libs");
40
55
  }
41
56
  } else {
42
- if (distLibs.has(dist)) {
43
- throw new Error(`Duplicate distribution target: ${dist}`);
57
+ if (outputDirs.has(outputDir)) {
58
+ throw new Error(`Duplicate output target: ${outputDir}`);
44
59
  }
45
- distLibs.add(dist);
60
+ outputDirs.add(outputDir);
46
61
  }
47
62
  }
48
63
  }
@@ -51,36 +66,44 @@ export async function applyMagicSpells(targets, options = {}) {
51
66
  processedFiles: []
52
67
  };
53
68
  try {
54
- validateTargets(targets);
55
- const srcRoot = path.resolve(process.cwd(), "src");
56
- const sourceFilesWithDirectives = await scanSourceForMagicDirectives(srcRoot, options);
57
- if (sourceFilesWithDirectives.length === 0) {
58
- if (DEBUG_MODE) relinka("log", "[spells] No source files with magic directives found");
59
- return result;
60
- }
61
- if (DEBUG_MODE) {
62
- relinka(
63
- "log",
64
- `[spells] Found ${sourceFilesWithDirectives.length} source files with magic directives`
65
- );
66
- }
69
+ validateTargets(targets, options.customOutputPaths);
67
70
  await pMap(
68
71
  targets,
69
72
  async (target) => {
70
- const [dist, lib] = target.split("/");
71
- if (dist === "dist-libs") {
73
+ const [outputDir, lib] = target.split("/");
74
+ if (outputDir && !["dist-npm", "dist-jsr", "dist-libs"].includes(outputDir)) {
75
+ const targetResult = await processCustomTarget(outputDir, options);
76
+ result.processedFiles.push(...targetResult.processedFiles);
77
+ return;
78
+ }
79
+ const srcRoot = path.resolve(process.cwd(), "src");
80
+ const sourceFilesWithDirectives = await scanSourceForMagicDirectives(srcRoot, options);
81
+ if (sourceFilesWithDirectives.length === 0) {
82
+ if (DEBUG_MODE) relinka("log", "[spells] No source files with magic directives found");
83
+ return;
84
+ }
85
+ if (DEBUG_MODE) {
86
+ relinka(
87
+ "log",
88
+ `[spells] Found ${sourceFilesWithDirectives.length} source files with magic directives`
89
+ );
90
+ }
91
+ if (outputDir === "dist-libs") {
72
92
  if (!lib) {
73
- const libDirs = await readdir(DIST_PATHS["dist-libs"]);
93
+ const distLibsPath = DEFAULT_OUTPUT_PATHS["dist-libs"] ?? "dist-libs";
94
+ const libDirs = await readdir(distLibsPath, { withFileTypes: true });
74
95
  await pMap(
75
96
  libDirs,
76
97
  async (libDir) => {
77
- const targetResult = await processDistributionTarget(
78
- sourceFilesWithDirectives,
79
- "dist-libs",
80
- libDir,
81
- options
82
- );
83
- result.processedFiles.push(...targetResult.processedFiles);
98
+ if (libDir.isDirectory()) {
99
+ const targetResult = await processOutputTarget(
100
+ sourceFilesWithDirectives,
101
+ "dist-libs",
102
+ libDir.name,
103
+ options
104
+ );
105
+ result.processedFiles.push(...targetResult.processedFiles);
106
+ }
84
107
  },
85
108
  {
86
109
  concurrency: options.concurrency ?? 4,
@@ -88,7 +111,7 @@ export async function applyMagicSpells(targets, options = {}) {
88
111
  }
89
112
  );
90
113
  } else {
91
- const targetResult = await processDistributionTarget(
114
+ const targetResult = await processOutputTarget(
92
115
  sourceFilesWithDirectives,
93
116
  "dist-libs",
94
117
  lib,
@@ -96,10 +119,10 @@ export async function applyMagicSpells(targets, options = {}) {
96
119
  );
97
120
  result.processedFiles.push(...targetResult.processedFiles);
98
121
  }
99
- } else {
100
- const targetResult = await processDistributionTarget(
122
+ } else if (outputDir) {
123
+ const targetResult = await processOutputTarget(
101
124
  sourceFilesWithDirectives,
102
- dist,
125
+ outputDir,
103
126
  void 0,
104
127
  options
105
128
  );
@@ -113,9 +136,74 @@ export async function applyMagicSpells(targets, options = {}) {
113
136
  );
114
137
  return result;
115
138
  } catch (error) {
116
- throw new Error(`Failed to process distribution files: ${formatError(error)}`);
139
+ throw new Error(`Failed to process output files: ${formatError(error)}`);
117
140
  }
118
141
  }
142
+ async function processCustomTarget(outputDir, options = {}) {
143
+ const { concurrency = DEFAULT_OPTIONS.concurrency, batchSize = DEFAULT_OPTIONS.batchSize } = options;
144
+ const result = {
145
+ processedFiles: []
146
+ };
147
+ if (DEBUG_MODE) {
148
+ relinka("log", `[spells] \u21D2 processing custom target: ${outputDir}`);
149
+ }
150
+ const outputFilesToProcess = [];
151
+ const outputPath = options.customOutputPaths?.[outputDir] || outputDir;
152
+ const fullOutputPath = path.join(process.cwd(), outputPath);
153
+ for await (const filePath of walkDirectoryTree(fullOutputPath)) {
154
+ if (await isBinaryExt(filePath)) {
155
+ continue;
156
+ }
157
+ try {
158
+ const content = await fs.readFile(filePath, "utf8");
159
+ if (containsMagicDirectives(content)) {
160
+ outputFilesToProcess.push(filePath);
161
+ if (DEBUG_MODE) {
162
+ relinka(
163
+ "log",
164
+ `[spells] \u21D2 found directives in ${path.relative(process.cwd(), filePath)}`
165
+ );
166
+ }
167
+ }
168
+ } catch (error) {
169
+ if (options.stopOnError) {
170
+ throw new Error(`Failed to read file ${filePath}: ${formatError(error)}`);
171
+ }
172
+ relinka("error", `Failed to read file ${filePath}: ${formatError(error)}`);
173
+ }
174
+ }
175
+ if (outputFilesToProcess.length === 0) {
176
+ if (DEBUG_MODE) {
177
+ relinka(
178
+ "log",
179
+ `[spells] No files with magic directives found in custom target: ${outputDir}`
180
+ );
181
+ }
182
+ return result;
183
+ }
184
+ for (let i = 0; i < outputFilesToProcess.length; i += batchSize) {
185
+ const batch = outputFilesToProcess.slice(i, i + batchSize);
186
+ await pMap(
187
+ batch,
188
+ async (outputFilePath) => {
189
+ try {
190
+ const wasProcessed = await processSingleOutputFile(outputFilePath, options);
191
+ if (wasProcessed) {
192
+ result.processedFiles.push(outputFilePath);
193
+ }
194
+ } catch (error) {
195
+ const errorMessage = `Error processing ${outputFilePath}: ${formatError(error)}`;
196
+ if (options.stopOnError) {
197
+ throw new Error(errorMessage);
198
+ }
199
+ relinka("error", errorMessage);
200
+ }
201
+ },
202
+ { concurrency }
203
+ );
204
+ }
205
+ return result;
206
+ }
119
207
  async function scanSourceForMagicDirectives(srcRoot, options = {}) {
120
208
  if (DEBUG_MODE) {
121
209
  relinka("log", `[spells] \u21D2 scanning src: ${srcRoot}`);
@@ -156,39 +244,44 @@ async function scanSourceForMagicDirectives(srcRoot, options = {}) {
156
244
  }
157
245
  return sourceFilesWithDirectives;
158
246
  }
159
- async function processDistributionTarget(sourceFilesWithDirectives, dist, libName, options = {}) {
247
+ async function processOutputTarget(sourceFilesWithDirectives, outputDir, libName, options = {}) {
160
248
  const { concurrency = DEFAULT_OPTIONS.concurrency, batchSize = DEFAULT_OPTIONS.batchSize } = options;
161
249
  const result = {
162
250
  processedFiles: []
163
251
  };
164
252
  if (DEBUG_MODE) {
165
- const targetName = dist === "dist-libs" && libName ? `${dist}/${libName}` : dist;
253
+ const targetName = outputDir === "dist-libs" && libName ? `${outputDir}/${libName}` : outputDir;
166
254
  relinka("log", `[spells] \u21D2 processing target: ${targetName}`);
167
255
  }
168
- const distFilesToProcess = [];
256
+ const outputFilesToProcess = [];
169
257
  for (const sourceFile of sourceFilesWithDirectives) {
170
- const distFiles = await findDistributionFiles(sourceFile, dist, libName);
171
- distFilesToProcess.push(...distFiles);
258
+ const outputFiles = await findOutputFiles(
259
+ sourceFile,
260
+ outputDir,
261
+ libName,
262
+ options.customOutputPaths
263
+ );
264
+ outputFilesToProcess.push(...outputFiles);
172
265
  }
173
- if (distFilesToProcess.length === 0) {
266
+ if (outputFilesToProcess.length === 0) {
174
267
  if (DEBUG_MODE) {
175
- const targetName = dist === "dist-libs" && libName ? `${dist}/${libName}` : dist;
176
- relinka("log", `[spells] No corresponding dist files found for target: ${targetName}`);
268
+ const targetName = outputDir === "dist-libs" && libName ? `${outputDir}/${libName}` : outputDir;
269
+ relinka("log", `[spells] No corresponding output files found for target: ${targetName}`);
177
270
  }
178
271
  return result;
179
272
  }
180
- for (let i = 0; i < distFilesToProcess.length; i += batchSize) {
181
- const batch = distFilesToProcess.slice(i, i + batchSize);
273
+ for (let i = 0; i < outputFilesToProcess.length; i += batchSize) {
274
+ const batch = outputFilesToProcess.slice(i, i + batchSize);
182
275
  await pMap(
183
276
  batch,
184
- async (distFilePath) => {
277
+ async (outputFilePath) => {
185
278
  try {
186
- const wasProcessed = await processSingleDistFile(distFilePath, options);
279
+ const wasProcessed = await processSingleOutputFile(outputFilePath, options);
187
280
  if (wasProcessed) {
188
- result.processedFiles.push(distFilePath);
281
+ result.processedFiles.push(outputFilePath);
189
282
  }
190
283
  } catch (error) {
191
- const errorMessage = `Error processing ${distFilePath}: ${formatError(error)}`;
284
+ const errorMessage = `Error processing ${outputFilePath}: ${formatError(error)}`;
192
285
  if (options.stopOnError) {
193
286
  throw new Error(errorMessage);
194
287
  }
@@ -247,7 +340,7 @@ async function findSourceFile(distFilePath) {
247
340
  }
248
341
  return null;
249
342
  }
250
- async function processSingleDistFile(filePath, options = {}) {
343
+ async function processSingleOutputFile(filePath, options = {}) {
251
344
  const projectRel = path.relative(process.cwd(), filePath).replaceAll(path.sep, "/");
252
345
  if (await isBinaryExt(filePath)) {
253
346
  if (DEBUG_MODE) relinka("log", `[spells] \u2298 binary ${projectRel}`);
@@ -296,18 +389,19 @@ async function processSingleDistFile(filePath, options = {}) {
296
389
  }
297
390
  return false;
298
391
  }
299
- async function findDistributionFiles(sourceFilePath, dist, libName) {
392
+ async function findOutputFiles(sourceFilePath, outputDir, libName, customOutputPaths) {
300
393
  const projectRel = path.relative(process.cwd(), sourceFilePath).replaceAll(path.sep, "/");
301
394
  const srcRelativePath = projectRel.replace(/^src\//, "");
302
395
  const ext = path.extname(sourceFilePath);
303
396
  const baseName = path.basename(sourceFilePath, ext);
304
397
  const dirPath = path.dirname(srcRelativePath);
305
398
  const isDts = sourceFilePath.endsWith(".d.ts");
306
- const distFiles = [];
307
- if (dist === "dist-libs" && libName) {
399
+ const outputFiles = [];
400
+ const allOutputPaths = { ...DEFAULT_OUTPUT_PATHS, ...customOutputPaths };
401
+ if (outputDir === "dist-libs" && libName) {
308
402
  const targets = await getAvailableRegistries(libName);
309
403
  for (const target of targets) {
310
- const distPath = join("dist-libs", libName, target, "bin", dirPath === "." ? "" : dirPath);
404
+ const outputPath = join("dist-libs", libName, target, "bin", dirPath === "." ? "" : dirPath);
311
405
  let extensions;
312
406
  if (isDts && PROCESS_DTS_FILES) {
313
407
  extensions = [".d.ts"];
@@ -316,16 +410,16 @@ async function findDistributionFiles(sourceFilePath, dist, libName) {
316
410
  } else {
317
411
  extensions = [ext];
318
412
  }
319
- for (const distExt of extensions) {
320
- const distFile = path.join(process.cwd(), distPath, `${baseName}${distExt}`);
321
- if (await fs.pathExists(distFile)) {
322
- distFiles.push(distFile);
413
+ for (const outputExt of extensions) {
414
+ const outputFile = path.join(process.cwd(), outputPath, `${baseName}${outputExt}`);
415
+ if (await fs.pathExists(outputFile)) {
416
+ outputFiles.push(outputFile);
323
417
  }
324
418
  }
325
419
  }
326
420
  } else {
327
- const basePath = DIST_PATHS[dist];
328
- const distPath = path.join(basePath, dirPath === "." ? "" : dirPath);
421
+ const basePath = allOutputPaths[outputDir] || outputDir;
422
+ const outputPath = path.join(basePath, dirPath === "." ? "" : dirPath);
329
423
  let extensions;
330
424
  if (isDts && PROCESS_DTS_FILES) {
331
425
  extensions = [".d.ts"];
@@ -334,14 +428,14 @@ async function findDistributionFiles(sourceFilePath, dist, libName) {
334
428
  } else {
335
429
  extensions = [ext];
336
430
  }
337
- for (const distExt of extensions) {
338
- const distFile = path.join(process.cwd(), distPath, `${baseName}${distExt}`);
339
- if (await fs.pathExists(distFile)) {
340
- distFiles.push(distFile);
431
+ for (const outputExt of extensions) {
432
+ const outputFile = path.join(process.cwd(), outputPath, `${baseName}${outputExt}`);
433
+ if (await fs.pathExists(outputFile)) {
434
+ outputFiles.push(outputFile);
341
435
  }
342
436
  }
343
437
  }
344
- return distFiles;
438
+ return outputFiles;
345
439
  }
346
440
  const SPELL_REGEX = /\/\/\s*(?:@ts-expect-error\s+.*?)?<\s*(dler-[^>\s]+)(.*?)>/i;
347
441
  let spellImplementationPaths = null;
@@ -472,3 +566,62 @@ async function* walkDirectoryTree(dir) {
472
566
  throw new Error(errorMessage);
473
567
  }
474
568
  }
569
+ export async function getFilesWithMagicSpells(dirs, options = {}) {
570
+ const { stopOnError = false, excludeSpellImplementation = true } = options;
571
+ const filesWithSpells = [];
572
+ try {
573
+ await pMap(
574
+ dirs,
575
+ async (dir) => {
576
+ const fullPath = path.join(process.cwd(), dir);
577
+ if (!await fs.pathExists(fullPath)) {
578
+ const error = `Directory does not exist: ${dir}`;
579
+ if (stopOnError) {
580
+ throw new Error(error);
581
+ }
582
+ relinka("warn", error);
583
+ return;
584
+ }
585
+ for await (const filePath of walkDirectoryTree(fullPath)) {
586
+ if (await isBinaryExt(filePath)) {
587
+ continue;
588
+ }
589
+ const projectRel = path.relative(process.cwd(), filePath).replaceAll(path.sep, "/");
590
+ if (excludeSpellImplementation && await isSpellImplementationFile(projectRel)) {
591
+ continue;
592
+ }
593
+ try {
594
+ const content = await fs.readFile(filePath, "utf8");
595
+ const lines = content.split(/\r?\n/);
596
+ const spellLines = [];
597
+ for (let i = 0; i < lines.length; i++) {
598
+ const line = lines[i];
599
+ if (line && /\/\/\s*(?:@ts-expect-error\s+.*?)?<\s*(dler-[^>\s]+)(.*?)>/i.test(line)) {
600
+ spellLines.push(i + 1);
601
+ }
602
+ }
603
+ if (spellLines.length > 0) {
604
+ filesWithSpells.push({
605
+ path: filePath,
606
+ spellLines
607
+ });
608
+ }
609
+ } catch (error) {
610
+ const errorMessage = `Failed to read file ${filePath}: ${formatError(error)}`;
611
+ if (stopOnError) {
612
+ throw new Error(errorMessage);
613
+ }
614
+ relinka("error", errorMessage);
615
+ }
616
+ }
617
+ },
618
+ {
619
+ concurrency: 4,
620
+ stopOnError
621
+ }
622
+ );
623
+ return filesWithSpells;
624
+ } catch (error) {
625
+ throw new Error(`Failed to scan directories: ${formatError(error)}`);
626
+ }
627
+ }
@@ -6,6 +6,7 @@
6
6
  * // <dler-replace-line-to `NEW CONTENT` [if 'cond'] [else 'alt']>
7
7
  * // <dler-remove-line>
8
8
  * // <dler-remove-file>
9
+ * // <dler-remove-comment>
9
10
  *
10
11
  * A directive is recognised whether written as:
11
12
  * // <dler-…> or
@@ -23,7 +24,21 @@ export interface SpellOutcome {
23
24
  removeLine: boolean;
24
25
  removeFile: boolean;
25
26
  }
26
- export type SpellDirective = "dler-replace-line-to" | "dler-remove-line" | "dler-remove-file";
27
+ export type SpellDirective = "dler-replace-line-to" | "dler-remove-line" | "dler-remove-file" | "dler-remove-comment";
28
+ export interface SpellInfo {
29
+ /** The name of the spell directive */
30
+ name: SpellDirective;
31
+ /** A short description of what the spell does */
32
+ description: string;
33
+ /** Example usage of the spell */
34
+ example: string;
35
+ /** Additional notes about the spell's behavior */
36
+ notes?: string;
37
+ }
38
+ /**
39
+ * Returns information about all available magic directives
40
+ */
41
+ export declare function getAvailableSpells(): SpellInfo[];
27
42
  /**
28
43
  * Evaluates a single line for magic directives and returns the effect.
29
44
  * If no directive is present, returns neutral outcome.
@@ -4,6 +4,34 @@ const REPLACEMENT_REGEX = /`([^`]+)`/;
4
4
  const IF_CONDITION_REGEX = /\bif\s+['"`]([^'"`]+)['"`]/i;
5
5
  const ELSE_CONTENT_REGEX = /\belse\s+['"`]([^'"`]+)['"`]/i;
6
6
  const STARTS_WITH_REGEX = /current file path starts with\s+(.+)$/i;
7
+ export function getAvailableSpells() {
8
+ return [
9
+ {
10
+ name: "dler-replace-line-to",
11
+ description: "Replaces the current line with new content, optionally based on a condition",
12
+ example: "// <dler-replace-line-to `export const version = \"1.0.0\";` if 'current file path starts with dist-npm'>",
13
+ notes: "If condition is not met and else content is provided, uses else content. Otherwise keeps original line. Also supports @ts-expect-error prefix."
14
+ },
15
+ {
16
+ name: "dler-remove-line",
17
+ description: "Removes the current line from the output",
18
+ example: "// <dler-remove-line>",
19
+ notes: "Also supports @ts-expect-error prefix."
20
+ },
21
+ {
22
+ name: "dler-remove-file",
23
+ description: "Removes the entire file from the output",
24
+ example: "// <dler-remove-file>",
25
+ notes: "This directive should be placed at the top of the file for clarity. Also supports @ts-expect-error prefix."
26
+ },
27
+ {
28
+ name: "dler-remove-comment",
29
+ description: "Removes the current line if it's a comment",
30
+ example: "// <dler-remove-comment>",
31
+ notes: "Only removes the line if it starts with //. Useful for cleaning up comments in output files. Also supports @ts-expect-error prefix."
32
+ }
33
+ ];
34
+ }
7
35
  export function evaluateMagicDirective(line, ctx) {
8
36
  const match = line.match(SPELL_REGEX);
9
37
  if (!match) return NO_OP;
@@ -26,6 +54,13 @@ export function evaluateMagicDirective(line, ctx) {
26
54
  return { removeLine: true, removeFile: false };
27
55
  }
28
56
  /* -------------------------------------------------------------- */
57
+ /* dler-remove-comment */
58
+ /* -------------------------------------------------------------- */
59
+ case "dler-remove-comment": {
60
+ const isComment = line.trim().startsWith("//");
61
+ return { removeLine: isComment, removeFile: false };
62
+ }
63
+ /* -------------------------------------------------------------- */
29
64
  /* dler-replace-line-to */
30
65
  /* -------------------------------------------------------------- */
31
66
  case "dler-replace-line-to": {
@@ -49,7 +84,12 @@ export function evaluateMagicDirective(line, ctx) {
49
84
  }
50
85
  const NO_OP = { removeLine: false, removeFile: false };
51
86
  function isValidMagicDirective(directive) {
52
- return ["dler-replace-line-to", "dler-remove-line", "dler-remove-file"].includes(directive);
87
+ return [
88
+ "dler-replace-line-to",
89
+ "dler-remove-line",
90
+ "dler-remove-file",
91
+ "dler-remove-comment"
92
+ ].includes(directive);
53
93
  }
54
94
  function parseReplacementDirective(body) {
55
95
  const parts = {
@@ -1,4 +1,4 @@
1
- export type FileType = ".js" | ".jsx" | ".ts" | ".tsx";
1
+ export type MissingDepsFileType = ".js" | ".jsx" | ".ts" | ".tsx";
2
2
  export interface PackageJson {
3
3
  name?: string;
4
4
  dependencies?: Record<string, string>;