@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.
- package/bin/app/agg/impl.js +1 -1
- package/bin/app/cmds.d.ts +1 -1
- package/bin/app/cmds.js +1 -1
- package/bin/app/inject/cmd.d.ts +0 -24
- package/bin/app/inject/cmd.js +0 -47
- package/bin/app/{spell → magic}/cmd.d.ts +2 -0
- package/bin/app/magic/cmd.js +101 -0
- package/bin/app/pub/impl.js +4 -2
- package/bin/libs/cfg/cfg-mod.d.ts +24 -195
- package/bin/libs/cfg/cfg-mod.js +71 -66
- package/bin/libs/cfg/constants.d.ts +68 -0
- package/bin/libs/cfg/constants.js +60 -0
- package/bin/libs/cfg/rse/rse-impl/rse-create.js +1 -1
- package/bin/libs/cfg/rse/rse-impl/rse-define.d.ts +11 -11
- package/bin/libs/cfg/rse/rse-mod.d.ts +1 -1
- package/bin/libs/cfg/rse/rse-mod.js +1 -1
- package/bin/libs/sdk/sdk-impl/cmds/inject/inject-impl-mod.d.ts +63 -0
- package/bin/libs/sdk/sdk-impl/cmds/inject/inject-impl-mod.js +237 -0
- package/bin/libs/sdk/sdk-impl/config/info.js +1 -3
- package/bin/libs/sdk/sdk-impl/magic/apply.d.ts +63 -0
- package/bin/libs/sdk/sdk-impl/{spell/applyMagicSpells.js → magic/apply.js} +223 -70
- package/bin/libs/sdk/sdk-impl/{spell → magic}/spells.d.ts +16 -1
- package/bin/libs/sdk/sdk-impl/{spell → magic}/spells.js +41 -1
- package/bin/libs/sdk/sdk-impl/rules/reliverse/missing-deps/deps-types.d.ts +1 -1
- package/bin/libs/sdk/sdk-mod.d.ts +93 -42
- package/bin/libs/sdk/sdk-mod.js +119 -27
- package/package.json +2 -2
- package/bin/app/inject/impl.d.ts +0 -5
- package/bin/app/inject/impl.js +0 -159
- package/bin/app/spell/cmd.js +0 -47
- package/bin/libs/sdk/sdk-impl/spell/applyMagicSpells.d.ts +0 -38
- /package/bin/app/{spell → magic}/old.d.ts +0 -0
- /package/bin/app/{spell → magic}/old.js +0 -0
- /package/bin/libs/cfg/rse/rse-impl/{rse-inject.d.ts → rse-comments.d.ts} +0 -0
- /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
|
|
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
|
|
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 [
|
|
26
|
-
if (!
|
|
27
|
-
throw new Error(`Invalid
|
|
27
|
+
const [outputDir, lib] = target.split("/");
|
|
28
|
+
if (!outputDir) {
|
|
29
|
+
throw new Error(`Invalid output target: ${target}`);
|
|
28
30
|
}
|
|
29
|
-
|
|
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 (
|
|
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
|
-
|
|
54
|
+
outputDirs.add("dist-libs");
|
|
40
55
|
}
|
|
41
56
|
} else {
|
|
42
|
-
if (
|
|
43
|
-
throw new Error(`Duplicate
|
|
57
|
+
if (outputDirs.has(outputDir)) {
|
|
58
|
+
throw new Error(`Duplicate output target: ${outputDir}`);
|
|
44
59
|
}
|
|
45
|
-
|
|
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 [
|
|
71
|
-
if (dist
|
|
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
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
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
|
|
122
|
+
} else if (outputDir) {
|
|
123
|
+
const targetResult = await processOutputTarget(
|
|
101
124
|
sourceFilesWithDirectives,
|
|
102
|
-
|
|
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
|
|
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
|
|
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 =
|
|
253
|
+
const targetName = outputDir === "dist-libs" && libName ? `${outputDir}/${libName}` : outputDir;
|
|
166
254
|
relinka("log", `[spells] \u21D2 processing target: ${targetName}`);
|
|
167
255
|
}
|
|
168
|
-
const
|
|
256
|
+
const outputFilesToProcess = [];
|
|
169
257
|
for (const sourceFile of sourceFilesWithDirectives) {
|
|
170
|
-
const
|
|
171
|
-
|
|
258
|
+
const outputFiles = await findOutputFiles(
|
|
259
|
+
sourceFile,
|
|
260
|
+
outputDir,
|
|
261
|
+
libName,
|
|
262
|
+
options.customOutputPaths
|
|
263
|
+
);
|
|
264
|
+
outputFilesToProcess.push(...outputFiles);
|
|
172
265
|
}
|
|
173
|
-
if (
|
|
266
|
+
if (outputFilesToProcess.length === 0) {
|
|
174
267
|
if (DEBUG_MODE) {
|
|
175
|
-
const targetName =
|
|
176
|
-
relinka("log", `[spells] No corresponding
|
|
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 <
|
|
181
|
-
const batch =
|
|
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 (
|
|
277
|
+
async (outputFilePath) => {
|
|
185
278
|
try {
|
|
186
|
-
const wasProcessed = await
|
|
279
|
+
const wasProcessed = await processSingleOutputFile(outputFilePath, options);
|
|
187
280
|
if (wasProcessed) {
|
|
188
|
-
result.processedFiles.push(
|
|
281
|
+
result.processedFiles.push(outputFilePath);
|
|
189
282
|
}
|
|
190
283
|
} catch (error) {
|
|
191
|
-
const errorMessage = `Error processing ${
|
|
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
|
|
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
|
|
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
|
|
307
|
-
|
|
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
|
|
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
|
|
320
|
-
const
|
|
321
|
-
if (await fs.pathExists(
|
|
322
|
-
|
|
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 =
|
|
328
|
-
const
|
|
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
|
|
338
|
-
const
|
|
339
|
-
if (await fs.pathExists(
|
|
340
|
-
|
|
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
|
|
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 [
|
|
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 = {
|