@adonisjs/assembler 8.0.0-next.22 → 8.0.0-next.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.
@@ -1,468 +0,0 @@
1
- import {
2
- VirtualFileSystem,
3
- debug_default,
4
- removeExtension,
5
- throttle
6
- } from "./chunk-JFBQ4OEM.js";
7
-
8
- // src/index_generator/source.ts
9
- import string from "@poppinss/utils/string";
10
- import { mkdir, writeFile } from "fs/promises";
11
- import { dirname, join, relative } from "path/posix";
12
- import StringBuilder from "@poppinss/utils/string_builder";
13
-
14
- // src/file_buffer.ts
15
- var FileBuffer = class _FileBuffer {
16
- /**
17
- * Whether to add an end-of-line character at the end of the output
18
- */
19
- #eol = false;
20
- /**
21
- * Collected lines
22
- */
23
- #buffer = [];
24
- /**
25
- * Current indentation size. Each call to indent will increment
26
- * it by 2
27
- */
28
- #identationSize = 0;
29
- /**
30
- * Cached compiled output. Once this value is set, the `flush`
31
- * method will become a noop
32
- */
33
- #compiledOutput;
34
- /**
35
- * Creates a new child buffer instance
36
- *
37
- * @returns A new FileBuffer instance
38
- */
39
- create() {
40
- return new _FileBuffer();
41
- }
42
- /**
43
- * Returns the size of buffer text
44
- *
45
- * @returns The number of lines in the buffer
46
- */
47
- get size() {
48
- return this.#buffer.length;
49
- }
50
- /**
51
- * Enable or disable end-of-line character at the end of output
52
- *
53
- * @param enabled - Whether to add EOL character
54
- * @returns This FileBuffer instance for method chaining
55
- *
56
- * @example
57
- * const buffer = new FileBuffer()
58
- * buffer.eol(true).writeLine('Hello').flush() // 'Hello\n\n'
59
- */
60
- eol(enabled) {
61
- this.#eol = enabled;
62
- return this;
63
- }
64
- /**
65
- * Write a new line to the output with current indentation
66
- *
67
- * @param text - The text to write as a new line
68
- * @returns This FileBuffer instance for method chaining
69
- */
70
- writeLine(text) {
71
- if (typeof text === "string") {
72
- this.#buffer.push(`${" ".repeat(this.#identationSize)}${text}
73
- `);
74
- } else {
75
- this.#buffer.push(text);
76
- this.#buffer.push("");
77
- }
78
- return this;
79
- }
80
- /**
81
- * Write text to the output without adding a new line
82
- *
83
- * @param text - The text to write without a newline
84
- * @returns This FileBuffer instance for method chaining
85
- */
86
- write(text) {
87
- if (typeof text === "string") {
88
- this.#buffer.push(`${" ".repeat(this.#identationSize)}${text}`);
89
- } else {
90
- this.#buffer.push(text);
91
- }
92
- return this;
93
- }
94
- /**
95
- * Increase indentation by 2 spaces
96
- *
97
- * @returns This FileBuffer instance for method chaining
98
- */
99
- indent() {
100
- this.#identationSize += 2;
101
- return this;
102
- }
103
- /**
104
- * Decrease indentation by 2 spaces (minimum of 0)
105
- *
106
- * @returns This FileBuffer instance for method chaining
107
- */
108
- dedent() {
109
- this.#identationSize -= 2;
110
- if (this.#identationSize < 0) {
111
- this.#identationSize = 0;
112
- }
113
- return this;
114
- }
115
- /**
116
- * Convert the buffer to a string representation
117
- *
118
- * @example
119
- * const buffer = new FileBuffer()
120
- * buffer.writeLine('Hello')
121
- * console.log(buffer.toString())
122
- */
123
- toString() {
124
- return this.flush();
125
- }
126
- /**
127
- * Return template as a string, joining all buffer lines
128
- *
129
- * Once called, the output is cached and subsequent calls return the same result.
130
- * The flush method becomes a no-op after the first call.
131
- *
132
- * @returns The complete buffer content as a string
133
- */
134
- flush() {
135
- if (this.#compiledOutput !== void 0) {
136
- return this.#compiledOutput;
137
- }
138
- this.#compiledOutput = this.#buffer.join("\n");
139
- return this.#eol ? `${this.#compiledOutput}
140
- ` : this.#compiledOutput;
141
- }
142
- };
143
-
144
- // src/index_generator/source.ts
145
- var IndexGeneratorSource = class {
146
- /**
147
- * The application root directory path
148
- */
149
- #appRoot;
150
- /**
151
- * The absolute path to the output file
152
- */
153
- #output;
154
- /**
155
- * The absolute path to the source directory
156
- */
157
- #source;
158
- /**
159
- * The directory containing the output file
160
- */
161
- #outputDirname;
162
- /**
163
- * Virtual file system for scanning source files
164
- */
165
- #vfs;
166
- /**
167
- * Configuration for this index generator source
168
- */
169
- #config;
170
- /**
171
- * CLI logger instance for output messages
172
- */
173
- #cliLogger;
174
- /**
175
- * Generate the output content and write it to the output file
176
- *
177
- * This method creates the file buffer, populates it with the generated
178
- * content based on configuration, and writes it to disk.
179
- */
180
- #generateOutput = throttle(async () => {
181
- const buffer = new FileBuffer().eol(true);
182
- if (this.#config.as === "barrelFile") {
183
- this.#asBarrelFile(
184
- this.#vfs,
185
- buffer,
186
- this.#config.exportName,
187
- this.#config.disableLazyImports
188
- );
189
- } else {
190
- this.#config.as(this.#vfs, buffer, this.#config, {
191
- toImportPath: this.#createBarrelFileImportGenerator(
192
- this.#source,
193
- this.#outputDirname,
194
- this.#config
195
- )
196
- });
197
- }
198
- await mkdir(dirname(this.#output), { recursive: true });
199
- await writeFile(this.#output, buffer.flush());
200
- });
201
- /**
202
- * Unique name for this index generator source
203
- */
204
- name;
205
- /**
206
- * Create a new IndexGeneratorSource instance
207
- *
208
- * @param name - Unique name for this index generator source
209
- * @param appRoot - The application root directory path
210
- * @param cliLogger - Logger instance for CLI output
211
- * @param config - Configuration for this index generator source
212
- */
213
- constructor(name, appRoot, cliLogger, config) {
214
- this.name = name;
215
- this.#config = config;
216
- this.#appRoot = appRoot;
217
- this.#cliLogger = cliLogger;
218
- this.#source = join(this.#appRoot, this.#config.source);
219
- this.#output = join(this.#appRoot, this.#config.output);
220
- this.#outputDirname = dirname(this.#output);
221
- this.#vfs = new VirtualFileSystem(this.#source, {
222
- glob: this.#config.glob
223
- });
224
- }
225
- /**
226
- * Converts a recursive file tree to a string representation
227
- *
228
- * This method recursively processes a file tree structure and writes
229
- * it as JavaScript object notation to the provided buffer.
230
- *
231
- * @param input - The recursive file tree to convert
232
- * @param buffer - The file buffer to write the output to
233
- */
234
- #treeToString(input, buffer) {
235
- Object.keys(input).forEach((key) => {
236
- const value = input[key];
237
- if (typeof value === "string") {
238
- buffer.write(`${key}: ${value},`);
239
- } else {
240
- buffer.write(`${key}: {`).indent();
241
- this.#treeToString(value, buffer);
242
- buffer.dedent().write(`},`);
243
- }
244
- });
245
- }
246
- /**
247
- * Transforms the barrel file index key. Converts basename to PascalCase
248
- * and all other paths to camelCase
249
- *
250
- * @param config - Configuration containing suffix removal options
251
- * @returns Function that transforms file paths to appropriate keys
252
- */
253
- #createBarrelFileKeyGenerator(config) {
254
- return function(key) {
255
- let paths = key.split("/");
256
- let baseName = new StringBuilder(paths.pop());
257
- if (config.skipSegments?.length) {
258
- paths = paths.filter((p) => !config.skipSegments.includes(p));
259
- }
260
- if (config.computeBaseName) {
261
- baseName = config.computeBaseName(baseName);
262
- } else {
263
- baseName = baseName.removeSuffix(config.removeSuffix ?? "").pascalCase();
264
- }
265
- return [...paths.map((p) => string.camelCase(p)), baseName.toString()].join("/");
266
- };
267
- }
268
- /**
269
- * Converts the file path to a lazy import. In case of an alias, the source
270
- * path is replaced with the alias, otherwise a relative import is created
271
- * from the output dirname.
272
- *
273
- * @param source - The source directory path
274
- * @param outputDirname - The output directory path
275
- * @param config - Configuration containing import alias options
276
- * @returns Function that converts file paths to import statements
277
- */
278
- #createBarrelFileImportGenerator(source, outputDirname, config) {
279
- return function(filePath) {
280
- if (config.importAlias) {
281
- debug_default('converting "%s" to import alias, source "%s"', filePath, source);
282
- return removeExtension(filePath.replace(source, config.importAlias));
283
- }
284
- debug_default('converting "%s" to relative import, source "%s"', filePath, outputDirname);
285
- return relative(outputDirname, filePath);
286
- };
287
- }
288
- /**
289
- * Generate a barrel file export structure
290
- *
291
- * This method creates a nested object structure that represents all
292
- * discovered files as lazy imports, organized by directory structure.
293
- *
294
- * @param vfs - Virtual file system containing the scanned files
295
- * @param buffer - File buffer to write the barrel exports to
296
- * @param exportName - Name for the main export object
297
- */
298
- #asBarrelFile(vfs, buffer, exportName, disableLazyImports) {
299
- const useEagerImports = disableLazyImports === true ? true : false;
300
- const keyGenerator = this.#createBarrelFileKeyGenerator(this.#config);
301
- const importsBuffer = buffer.create();
302
- const importGenerator = this.#createBarrelFileImportGenerator(
303
- this.#source,
304
- this.#outputDirname,
305
- this.#config
306
- );
307
- const tree = vfs.asTree({
308
- transformKey: keyGenerator,
309
- transformValue: (filePath, key) => {
310
- if (useEagerImports) {
311
- const importKey = new StringBuilder(key).pascalCase().toString();
312
- importsBuffer.write(`import ${importKey} from '${importGenerator(filePath)}'`);
313
- return importKey;
314
- }
315
- return `() => import('${importGenerator(filePath)}')`;
316
- }
317
- });
318
- const treeLength = Object.keys(tree).length;
319
- if (!treeLength) {
320
- buffer.write(`export const ${exportName} = {}`);
321
- return;
322
- }
323
- if (useEagerImports) {
324
- buffer.writeLine(importsBuffer);
325
- }
326
- buffer.write(`export const ${exportName} = {`).indent();
327
- this.#treeToString(tree, buffer);
328
- buffer.dedent().write(`}`);
329
- }
330
- /**
331
- * Displays the log message after generating the index file
332
- *
333
- * @example
334
- * const startTime = process.hrtime()
335
- * // ... perform operations
336
- * this.#logCreation(startTime)
337
- */
338
- #logCreation(startTime) {
339
- this.#cliLogger.info(`created ${this.#config.output}`, { startTime });
340
- }
341
- /**
342
- * Add a file to the virtual file system and regenerate index if needed
343
- *
344
- * If the file matches the configured glob patterns, it will be added
345
- * to the virtual file system and the index file will be regenerated.
346
- *
347
- * @param filePath - Absolute path of the file to add
348
- */
349
- async addFile(filePath) {
350
- const added = this.#vfs.add(filePath);
351
- if (added) {
352
- debug_default('file added, re-generating "%s" index', this.name);
353
- const startTime = process.hrtime();
354
- await this.#generateOutput();
355
- this.#logCreation(startTime);
356
- }
357
- }
358
- /**
359
- * Remove a file from the virtual file system and regenerate index if needed
360
- *
361
- * If the file was previously tracked, it will be removed from the
362
- * virtual file system and the index file will be regenerated.
363
- *
364
- * @param filePath - Absolute path of the file to remove
365
- */
366
- async removeFile(filePath) {
367
- const removed = this.#vfs.remove(filePath);
368
- if (removed) {
369
- debug_default('file removed, re-generating "%s" index', this.name);
370
- const startTime = process.hrtime();
371
- await this.#generateOutput();
372
- this.#logCreation(startTime);
373
- }
374
- }
375
- /**
376
- * Generate the index file
377
- *
378
- * This method scans the source directory, processes files according to
379
- * the configuration, and writes the generated index file to disk.
380
- */
381
- async generate() {
382
- const startTime = process.hrtime();
383
- await this.#vfs.scan();
384
- await this.#generateOutput();
385
- this.#logCreation(startTime);
386
- }
387
- };
388
-
389
- // src/index_generator/main.ts
390
- var IndexGenerator = class {
391
- /**
392
- * The application root directory path
393
- */
394
- appRoot;
395
- /**
396
- * Collection of registered index generator sources
397
- */
398
- #sources = {};
399
- #cliLogger;
400
- /**
401
- * Create a new IndexGenerator instance
402
- *
403
- * @param appRoot - The application root directory path
404
- * @param cliLogger - Logger instance for CLI output
405
- */
406
- constructor(appRoot, cliLogger) {
407
- this.appRoot = appRoot;
408
- this.#cliLogger = cliLogger;
409
- }
410
- /**
411
- * Add a new index generator source
412
- *
413
- * @param name - Unique name for the source
414
- * @param config - Configuration for the index generator source
415
- * @returns This IndexGenerator instance for method chaining
416
- */
417
- add(name, config) {
418
- this.#sources[name] = new IndexGeneratorSource(name, this.appRoot, this.#cliLogger, config);
419
- return this;
420
- }
421
- /**
422
- * Add a file to all registered index generator sources
423
- *
424
- * This method propagates the file addition to all registered sources,
425
- * allowing them to regenerate their index files if the new file matches
426
- * their glob patterns.
427
- *
428
- * @param filePath - Absolute path of the file to add
429
- */
430
- async addFile(filePath) {
431
- const sources = Object.values(this.#sources);
432
- for (let source of sources) {
433
- await source.addFile(filePath);
434
- }
435
- }
436
- /**
437
- * Remove a file from all registered index generator sources
438
- *
439
- * This method propagates the file removal to all registered sources,
440
- * allowing them to regenerate their index files if the removed file
441
- * was previously tracked.
442
- *
443
- * @param filePath - Absolute path of the file to remove
444
- */
445
- async removeFile(filePath) {
446
- const sources = Object.values(this.#sources);
447
- for (let source of sources) {
448
- await source.removeFile(filePath);
449
- }
450
- }
451
- /**
452
- * Generate all registered index files
453
- *
454
- * Iterates through all registered sources and generates their
455
- * corresponding index files.
456
- */
457
- async generate() {
458
- const sources = Object.values(this.#sources);
459
- for (let source of sources) {
460
- await source.generate();
461
- }
462
- }
463
- };
464
-
465
- export {
466
- FileBuffer,
467
- IndexGenerator
468
- };
@@ -1,116 +0,0 @@
1
- // src/helpers.ts
2
- import { parseImports } from "parse-imports";
3
- async function findImport(code, importReference) {
4
- const importIdentifier = importReference.split(".")[0];
5
- for (const $import of await parseImports(code, {})) {
6
- if (!$import.importClause) {
7
- continue;
8
- }
9
- if (!$import.moduleSpecifier.value) {
10
- continue;
11
- }
12
- if ($import.importClause.default === importIdentifier) {
13
- return {
14
- specifier: $import.moduleSpecifier.value,
15
- isConstant: $import.moduleSpecifier.isConstant,
16
- clause: {
17
- type: "default",
18
- value: importIdentifier
19
- }
20
- };
21
- }
22
- if ($import.importClause.namespace === importIdentifier) {
23
- return {
24
- specifier: $import.moduleSpecifier.value,
25
- isConstant: $import.moduleSpecifier.isConstant,
26
- clause: {
27
- type: "namespace",
28
- value: importIdentifier
29
- }
30
- };
31
- }
32
- const namedImport = $import.importClause.named.find(({ binding }) => {
33
- return binding === importIdentifier;
34
- });
35
- if (namedImport) {
36
- return {
37
- specifier: $import.moduleSpecifier.value,
38
- isConstant: $import.moduleSpecifier.isConstant,
39
- clause: {
40
- type: "named",
41
- value: namedImport.specifier,
42
- ...namedImport.binding !== namedImport.specifier ? {
43
- alias: namedImport.binding
44
- } : {}
45
- }
46
- };
47
- }
48
- }
49
- return null;
50
- }
51
- function inspectClass(node) {
52
- return node.find({
53
- rule: {
54
- kind: "class_declaration"
55
- }
56
- });
57
- }
58
- function inspectClassMethods(node) {
59
- return node.findAll({
60
- rule: {
61
- kind: "method_definition"
62
- }
63
- });
64
- }
65
- function nodeToPlainText(node) {
66
- let out = [];
67
- function toText(one) {
68
- const children = one.children();
69
- if (!children.length) {
70
- out.push(one.text());
71
- } else {
72
- children.forEach((child) => toText(child));
73
- }
74
- }
75
- toText(node);
76
- return out.join("");
77
- }
78
- function inspectMethodArguments(node, methodCalls) {
79
- const matchingExpressions = node.findAll({
80
- rule: {
81
- any: methodCalls.map((methodCall) => {
82
- return {
83
- pattern: {
84
- context: `${methodCall}($$$ARGUMENTS)`,
85
- selector: "call_expression"
86
- }
87
- };
88
- })
89
- }
90
- });
91
- return matchingExpressions.flatMap((matchingExpression) => {
92
- return matchingExpression.findAll({ rule: { kind: "arguments" } });
93
- });
94
- }
95
- function searchValidatorDirectUsage(node) {
96
- const matchingExpressions = node.findAll({
97
- rule: {
98
- pattern: {
99
- context: "$$$VALIDATOR.validate($$$)",
100
- selector: "call_expression"
101
- }
102
- }
103
- });
104
- return matchingExpressions.flatMap((expression) => {
105
- return expression.getMultipleMatches("VALIDATOR");
106
- });
107
- }
108
-
109
- export {
110
- findImport,
111
- inspectClass,
112
- inspectClassMethods,
113
- nodeToPlainText,
114
- inspectMethodArguments,
115
- searchValidatorDirectUsage
116
- };