@kubb/core 3.0.0-alpha.2 → 3.0.0-alpha.20

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 (107) hide show
  1. package/README.md +13 -4
  2. package/dist/{FileManager-BW--rO8q.d.ts → FileManager-DQtWE_rp.d.ts} +112 -72
  3. package/dist/{FileManager-Bw-FNS3q.d.cts → FileManager-qZTz0oZl.d.cts} +112 -72
  4. package/dist/chunk-253UUWI5.cjs +101 -0
  5. package/dist/chunk-253UUWI5.cjs.map +1 -0
  6. package/dist/chunk-2EU7DMPM.js +96 -0
  7. package/dist/chunk-2EU7DMPM.js.map +1 -0
  8. package/dist/chunk-4X5FFJPJ.js +8 -13
  9. package/dist/chunk-4X5FFJPJ.js.map +1 -1
  10. package/dist/chunk-7O42P6ET.cjs +1088 -0
  11. package/dist/chunk-7O42P6ET.cjs.map +1 -0
  12. package/dist/chunk-CLTNHSMO.js +895 -0
  13. package/dist/chunk-CLTNHSMO.js.map +1 -0
  14. package/dist/{chunk-3OXCZ5DJ.js → chunk-E6CN2CZC.js} +63 -54
  15. package/dist/chunk-E6CN2CZC.js.map +1 -0
  16. package/dist/chunk-HBQM723K.js +1049 -0
  17. package/dist/chunk-HBQM723K.js.map +1 -0
  18. package/dist/{chunk-LM2YQC3T.cjs → chunk-HRJU3XOH.cjs} +81 -51
  19. package/dist/chunk-HRJU3XOH.cjs.map +1 -0
  20. package/dist/chunk-OAGN4FY6.cjs +42 -0
  21. package/dist/chunk-OAGN4FY6.cjs.map +1 -0
  22. package/dist/chunk-P37BU33L.cjs +1537 -0
  23. package/dist/chunk-P37BU33L.cjs.map +1 -0
  24. package/dist/{chunk-67C6RBGQ.cjs → chunk-U3S2ZR6C.cjs} +28 -29
  25. package/dist/chunk-U3S2ZR6C.cjs.map +1 -0
  26. package/dist/index.cjs +551 -599
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +6 -19
  29. package/dist/index.d.ts +6 -19
  30. package/dist/index.js +442 -512
  31. package/dist/index.js.map +1 -1
  32. package/dist/{logger-DChjnJMn.d.cts → logger-DvbHXjIO.d.cts} +29 -19
  33. package/dist/{logger-DChjnJMn.d.ts → logger-DvbHXjIO.d.ts} +29 -19
  34. package/dist/logger.cjs +25 -15
  35. package/dist/logger.cjs.map +1 -1
  36. package/dist/logger.d.cts +1 -2
  37. package/dist/logger.d.ts +1 -2
  38. package/dist/logger.js +3 -15
  39. package/dist/logger.js.map +1 -1
  40. package/dist/mocks.cjs +42 -31
  41. package/dist/mocks.cjs.map +1 -1
  42. package/dist/mocks.d.cts +7 -9
  43. package/dist/mocks.d.ts +7 -9
  44. package/dist/mocks.js +35 -33
  45. package/dist/mocks.js.map +1 -1
  46. package/dist/prompt-TK4KVZVL.cjs +760 -0
  47. package/dist/prompt-TK4KVZVL.cjs.map +1 -0
  48. package/dist/prompt-WQQUN22Z.js +749 -0
  49. package/dist/prompt-WQQUN22Z.js.map +1 -0
  50. package/dist/transformers.cjs +215 -49
  51. package/dist/transformers.cjs.map +1 -1
  52. package/dist/transformers.d.cts +1 -3
  53. package/dist/transformers.d.ts +1 -3
  54. package/dist/transformers.js +148 -35
  55. package/dist/transformers.js.map +1 -1
  56. package/dist/utils.cjs +65 -26
  57. package/dist/utils.cjs.map +1 -1
  58. package/dist/utils.d.cts +32 -3
  59. package/dist/utils.d.ts +32 -3
  60. package/dist/utils.js +3 -26
  61. package/dist/utils.js.map +1 -1
  62. package/package.json +10 -13
  63. package/src/BarrelManager.ts +95 -109
  64. package/src/{Generator.ts → BaseGenerator.ts} +1 -1
  65. package/src/FileManager.ts +190 -298
  66. package/src/PackageManager.ts +1 -1
  67. package/src/PluginManager.ts +149 -90
  68. package/src/PromiseManager.ts +1 -1
  69. package/src/__snapshots__/barrel.json +93 -0
  70. package/src/__snapshots__/grouped.json +120 -0
  71. package/src/__snapshots__/ordered.json +68 -0
  72. package/src/build.ts +87 -122
  73. package/src/config.ts +1 -1
  74. package/src/errors.ts +0 -11
  75. package/src/index.ts +2 -3
  76. package/src/logger.ts +76 -34
  77. package/src/plugin.ts +2 -5
  78. package/src/transformers/escape.ts +0 -10
  79. package/src/transformers/index.ts +2 -3
  80. package/src/transformers/trim.ts +0 -4
  81. package/src/types.ts +36 -5
  82. package/src/utils/TreeNode.ts +132 -50
  83. package/src/utils/executeStrategies.ts +3 -3
  84. package/src/utils/index.ts +2 -1
  85. package/src/utils/parser.ts +166 -0
  86. package/dist/chunk-3OXCZ5DJ.js.map +0 -1
  87. package/dist/chunk-5JZNFPUP.js +0 -309
  88. package/dist/chunk-5JZNFPUP.js.map +0 -1
  89. package/dist/chunk-67C6RBGQ.cjs.map +0 -1
  90. package/dist/chunk-ADC5UNZ5.cjs +0 -1227
  91. package/dist/chunk-ADC5UNZ5.cjs.map +0 -1
  92. package/dist/chunk-HMLY7DHA.js +0 -16
  93. package/dist/chunk-HMLY7DHA.js.map +0 -1
  94. package/dist/chunk-JKZG2IJR.js +0 -283
  95. package/dist/chunk-JKZG2IJR.js.map +0 -1
  96. package/dist/chunk-LM2YQC3T.cjs.map +0 -1
  97. package/dist/chunk-PZT4CTBV.cjs +0 -299
  98. package/dist/chunk-PZT4CTBV.cjs.map +0 -1
  99. package/dist/chunk-SA2GZKXS.js +0 -596
  100. package/dist/chunk-SA2GZKXS.js.map +0 -1
  101. package/dist/chunk-XCPFG6DO.cjs +0 -66
  102. package/dist/chunk-XCPFG6DO.cjs.map +0 -1
  103. package/dist/chunk-YTSNYMHW.cjs +0 -320
  104. package/dist/chunk-YTSNYMHW.cjs.map +0 -1
  105. package/schema.json +0 -86
  106. package/src/utils/cache.ts +0 -35
  107. package/src/utils/getParser.ts +0 -17
@@ -0,0 +1,120 @@
1
+ {
2
+ "name": "",
3
+ "path": "",
4
+ "children": [
5
+ {
6
+ "name": "src",
7
+ "path": "src",
8
+ "children": [
9
+ {
10
+ "name": "axios",
11
+ "path": "src/axios",
12
+ "children": [
13
+ {
14
+ "name": "file2.ts",
15
+ "file": {
16
+ "path": "src/axios/file2.ts",
17
+ "baseName": "file2.ts",
18
+ "sources": [],
19
+ "id": "6af477de6b602aafbb2e1ce0011b1f411a7ab3a5",
20
+ "name": "file2",
21
+ "extName": ".ts",
22
+ "imports": [],
23
+ "exports": [],
24
+ "meta": {}
25
+ },
26
+ "path": "src/axios/file2.ts"
27
+ },
28
+ {
29
+ "name": "file1.ts",
30
+ "file": {
31
+ "path": "src/axios/file1.ts",
32
+ "baseName": "file2.ts",
33
+ "sources": [],
34
+ "id": "a9679944d24c174b2f2fd5b1f19c9861f1d35d0e",
35
+ "name": "file2",
36
+ "extName": ".ts",
37
+ "imports": [],
38
+ "exports": [],
39
+ "meta": {}
40
+ },
41
+ "path": "src/axios/file1.ts"
42
+ },
43
+ {
44
+ "name": "controller",
45
+ "path": "src/axios/controller",
46
+ "children": [
47
+ {
48
+ "name": "pet.ts",
49
+ "file": {
50
+ "path": "src/axios/controller/pet.ts",
51
+ "baseName": "pet.ts",
52
+ "sources": [],
53
+ "id": "8beaaf5e1b1a6b89a11589c2e3dc5fd7f5eb5e8c",
54
+ "name": "pet",
55
+ "extName": ".ts",
56
+ "imports": [],
57
+ "exports": [],
58
+ "meta": {}
59
+ },
60
+ "path": "src/axios/controller/pet.ts"
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "name": "index.ts",
66
+ "file": {
67
+ "path": "src/axios/index.ts",
68
+ "baseName": "index.ts",
69
+ "sources": [],
70
+ "id": "b077038b83c1ef4050649be406937a73c1f41ad3",
71
+ "name": "index",
72
+ "extName": ".ts",
73
+ "imports": [],
74
+ "exports": [],
75
+ "meta": {}
76
+ },
77
+ "path": "src/axios/index.ts"
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "name": "controller",
83
+ "path": "src/controller",
84
+ "children": [
85
+ {
86
+ "name": "test.ts",
87
+ "file": {
88
+ "path": "src/controller/test.ts",
89
+ "baseName": "test.ts",
90
+ "sources": [],
91
+ "id": "a2d277093a81a74c56c0d094071195302d6bb484",
92
+ "name": "test",
93
+ "extName": ".ts",
94
+ "imports": [],
95
+ "exports": [],
96
+ "meta": {}
97
+ },
98
+ "path": "src/controller/test.ts"
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ "name": "test.ts",
104
+ "file": {
105
+ "path": "src/test.ts",
106
+ "baseName": "test.ts",
107
+ "sources": [],
108
+ "id": "f8e2d98f76d6e33f21aa686d674544b5c7d6fa3e",
109
+ "name": "test",
110
+ "extName": ".ts",
111
+ "imports": [],
112
+ "exports": [],
113
+ "meta": {}
114
+ },
115
+ "path": "src/test.ts"
116
+ }
117
+ ]
118
+ }
119
+ ]
120
+ }
@@ -0,0 +1,68 @@
1
+ [
2
+ {
3
+ "path": "src/test.ts",
4
+ "baseName": "test.ts",
5
+ "sources": [],
6
+ "id": "f8e2d98f76d6e33f21aa686d674544b5c7d6fa3e",
7
+ "name": "test",
8
+ "extName": ".ts",
9
+ "imports": [],
10
+ "exports": [],
11
+ "meta": {}
12
+ },
13
+ {
14
+ "path": "src/axios/file2.ts",
15
+ "baseName": "file2.ts",
16
+ "sources": [],
17
+ "id": "6af477de6b602aafbb2e1ce0011b1f411a7ab3a5",
18
+ "name": "file2",
19
+ "extName": ".ts",
20
+ "imports": [],
21
+ "exports": [],
22
+ "meta": {}
23
+ },
24
+ {
25
+ "path": "src/axios/file1.ts",
26
+ "baseName": "file2.ts",
27
+ "sources": [],
28
+ "id": "a9679944d24c174b2f2fd5b1f19c9861f1d35d0e",
29
+ "name": "file2",
30
+ "extName": ".ts",
31
+ "imports": [],
32
+ "exports": [],
33
+ "meta": {}
34
+ },
35
+ {
36
+ "path": "src/axios/index.ts",
37
+ "baseName": "index.ts",
38
+ "sources": [],
39
+ "id": "b077038b83c1ef4050649be406937a73c1f41ad3",
40
+ "name": "index",
41
+ "extName": ".ts",
42
+ "imports": [],
43
+ "exports": [],
44
+ "meta": {}
45
+ },
46
+ {
47
+ "path": "src/controller/test.ts",
48
+ "baseName": "test.ts",
49
+ "sources": [],
50
+ "id": "a2d277093a81a74c56c0d094071195302d6bb484",
51
+ "name": "test",
52
+ "extName": ".ts",
53
+ "imports": [],
54
+ "exports": [],
55
+ "meta": {}
56
+ },
57
+ {
58
+ "path": "src/axios/controller/pet.ts",
59
+ "baseName": "pet.ts",
60
+ "sources": [],
61
+ "id": "8beaaf5e1b1a6b89a11589c2e3dc5fd7f5eb5e8c",
62
+ "name": "pet",
63
+ "extName": ".ts",
64
+ "imports": [],
65
+ "exports": [],
66
+ "meta": {}
67
+ }
68
+ ]
package/src/build.ts CHANGED
@@ -1,14 +1,15 @@
1
- import c from 'tinyrainbow'
2
-
3
1
  import { clean, read } from '@kubb/fs'
4
- import { FileManager, type ResolvedFile } from './FileManager.ts'
2
+ import type * as KubbFile from '@kubb/fs/types'
3
+ import { FileManager, processFiles } from './FileManager.ts'
5
4
  import { PluginManager } from './PluginManager.ts'
6
5
  import { isInputPath } from './config.ts'
7
- import { LogLevel, createLogger, randomCliColour } from './logger.ts'
6
+ import { createLogger } from './logger.ts'
8
7
  import { URLPath } from './utils/URLPath.ts'
9
8
 
9
+ import { join, resolve } from 'node:path'
10
+ import { getRelativePath } from '@kubb/fs'
10
11
  import type { Logger } from './logger.ts'
11
- import type { PluginContext, PluginParameter } from './types.ts'
12
+ import type { Output, PluginContext } from './types.ts'
12
13
 
13
14
  type BuildOptions = {
14
15
  config: PluginContext['config']
@@ -28,8 +29,7 @@ type BuildOutput = {
28
29
  }
29
30
 
30
31
  async function setup(options: BuildOptions): Promise<PluginManager> {
31
- const { config, logger = createLogger({ logLevel: LogLevel.silent }) } = options
32
- let count = 0
32
+ const { config, logger = createLogger() } = options
33
33
 
34
34
  try {
35
35
  if (isInputPath(config) && !new URLPath(config.input.path).isURL) {
@@ -37,157 +37,122 @@ async function setup(options: BuildOptions): Promise<PluginManager> {
37
37
  }
38
38
  } catch (e) {
39
39
  if (isInputPath(config)) {
40
- throw new Error(
41
- `Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${c.dim(config.input.path)}`,
42
- {
43
- cause: e,
44
- },
45
- )
40
+ throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${config.input.path}`, {
41
+ cause: e,
42
+ })
46
43
  }
47
44
  }
48
45
 
49
46
  if (config.output.clean) {
50
47
  await clean(config.output.path)
48
+ await clean(join(config.root, '.kubb'))
51
49
  }
52
50
 
53
- const task = async (file: ResolvedFile): Promise<ResolvedFile> => {
54
- const { path } = file
55
-
56
- const source: string | null = await FileManager.getSource(file)
57
-
58
- if (source) {
59
- if (config.output.write || config.output.write === undefined) {
60
- await pluginManager.fileManager.write(path, source, { sanity: false })
61
- }
62
- }
63
-
64
- return {
65
- ...file,
66
- source: source || '',
67
- }
68
- }
69
-
70
- const pluginManager = new PluginManager(config, { logger, task })
71
-
72
- pluginManager.queue.on('add', () => {
73
- if (logger.logLevel !== LogLevel.info) {
74
- return
75
- }
76
-
77
- if (count === 0) {
78
- logger.emit('start', '💾 Writing')
79
- }
80
- })
81
-
82
- pluginManager.queue.on('active', () => {
83
- if (logger.logLevel !== LogLevel.info) {
84
- return
85
- }
86
-
87
- if (logger.spinner && pluginManager.queue.size > 0) {
88
- const text = `Item: ${count} Size: ${pluginManager.queue.size} Pending: ${pluginManager.queue.pending}`
89
-
90
- logger.spinner.suffixText = c.dim(text)
91
- }
92
- ++count
93
- })
94
-
95
- pluginManager.queue.on('completed', () => {
96
- if (logger.logLevel !== LogLevel.info) {
97
- return
98
- }
99
-
100
- if (logger.spinner) {
101
- const text = `Item: ${count} Size: ${pluginManager.queue.size} Pending: ${pluginManager.queue.pending}`
102
-
103
- logger.spinner.suffixText = c.dim(text)
104
- }
105
- })
106
-
107
- pluginManager.on('executed', (executer) => {
108
- const { hookName, plugin, output, parameters } = executer
109
-
110
- const logs = [
111
- `${randomCliColour(plugin.name)} Executing ${hookName}`,
112
- parameters && `${c.bgWhite('Parameters')} ${randomCliColour(plugin.name)} ${hookName}`,
113
- JSON.stringify(parameters, undefined, 2),
114
- output && `${c.bgWhite('Output')} ${randomCliColour(plugin.name)} ${hookName}`,
115
- output,
116
- ].filter(Boolean)
117
-
118
- logger.emit('debug', logs as string[])
119
- })
120
-
121
- return pluginManager
51
+ return new PluginManager(config, { logger })
122
52
  }
123
53
 
124
54
  export async function build(options: BuildOptions): Promise<BuildOutput> {
125
- const pluginManager = await setup(options)
126
-
127
- const { fileManager, logger } = pluginManager
128
-
129
- await pluginManager.hookParallel({
130
- hookName: 'buildStart',
131
- parameters: [options.config],
132
- })
55
+ const { files, pluginManager, error } = await safeBuild(options)
133
56
 
134
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
135
-
136
- if (logger.logLevel === LogLevel.info) {
137
- logger.emit('end', '💾 Writing completed')
138
- }
139
-
140
- const files = await Promise.all(
141
- fileManager.files.map(async (file) => ({
142
- ...file,
143
- source: await FileManager.getSource(file),
144
- })),
145
- )
57
+ if (error) throw error
146
58
 
147
59
  return {
148
60
  files,
149
61
  pluginManager,
62
+ error,
150
63
  }
151
64
  }
152
65
 
153
66
  export async function safeBuild(options: BuildOptions): Promise<BuildOutput> {
67
+ let files = []
154
68
  const pluginManager = await setup(options)
155
69
 
156
- const { fileManager, logger } = pluginManager
157
-
158
70
  try {
71
+ pluginManager.events.on('executing', ({ plugin, message }) => {
72
+ pluginManager.logger.emit('debug', { date: new Date(), logs: [`Executing pluginKey ${plugin.key?.join('.')} | ${message}`] })
73
+ })
74
+
75
+ pluginManager.events.on('executed', ({ plugin, message, output }) => {
76
+ pluginManager.logger.emit('debug', {
77
+ date: new Date(),
78
+ logs: [`Executed pluginKey ${plugin.key?.join('.')} | ${message} | ${JSON.stringify(output, undefined, 2)}`],
79
+ })
80
+ })
81
+
159
82
  await pluginManager.hookParallel({
160
83
  hookName: 'buildStart',
161
84
  parameters: [options.config],
85
+ message: 'buildStart',
86
+ })
87
+
88
+ // create root barrel file
89
+ const root = resolve(options.config.root)
90
+ const rootPath = resolve(root, options.config.output.path, 'index.ts')
91
+ const barrelFiles = pluginManager.fileManager.files.filter((file) => {
92
+ return file.sources.some((source) => source.isIndexable)
162
93
  })
163
94
 
164
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
95
+ const rootFile: KubbFile.File = {
96
+ path: rootPath,
97
+ baseName: 'index.ts',
98
+ exports: barrelFiles
99
+ .flatMap((file) => {
100
+ return file.sources
101
+ ?.map((source) => {
102
+ if (!file.path || !source.isIndexable) {
103
+ return undefined
104
+ }
105
+
106
+ // validate of the file is coming from plugin x, needs pluginKey on every file TODO update typing
107
+ const plugin = [...pluginManager.plugins].find((item) => {
108
+ const meta = file.meta as any
109
+ return item.key === meta?.pluginKey
110
+ })
111
+ const options = (plugin?.options as { output?: Output }) ?? {}
112
+
113
+ if (options.output?.exportType === false) {
114
+ return undefined
115
+ }
116
+
117
+ if (FileManager.getMode(options.output?.path) === 'single') {
118
+ return undefined
119
+ }
120
+ return {
121
+ name: options.output?.exportType === 'barrel' ? undefined : [source.name],
122
+ path: getRelativePath(rootPath, file.path),
123
+ isTypeOnly: source.isTypeOnly,
124
+ } as KubbFile.Export
125
+ })
126
+ .filter(Boolean)
127
+ })
128
+ .filter(Boolean),
129
+ sources: [],
130
+ meta: {},
131
+ }
165
132
 
166
- if (logger.logLevel === LogLevel.info) {
167
- logger.emit('end', '💾 Writing completed')
133
+ if (options.config.output.exportType) {
134
+ await pluginManager.fileManager.add(rootFile)
168
135
  }
169
- } catch (e) {
170
- const files = await Promise.all(
171
- fileManager.files.map(async (file) => ({
172
- ...file,
173
- source: await FileManager.getSource(file),
174
- })),
175
- )
176
136
 
137
+ //TODO set extName here instead of the files, extName is private. All exports will have extName, it's up the the process to hide.override the name
138
+ files = await processFiles({
139
+ config: options.config,
140
+ dryRun: !options.config.output.write,
141
+ files: pluginManager.fileManager.files,
142
+ logger: pluginManager.logger,
143
+ })
144
+
145
+ await pluginManager.hookParallel({ hookName: 'buildEnd', message: `Build stopped for ${options.config.name}` })
146
+
147
+ pluginManager.fileManager.clear()
148
+ } catch (e) {
177
149
  return {
178
- files,
150
+ files: [],
179
151
  pluginManager,
180
152
  error: e as Error,
181
153
  }
182
154
  }
183
155
 
184
- const files = await Promise.all(
185
- fileManager.files.map(async (file) => ({
186
- ...file,
187
- source: await FileManager.getSource(file),
188
- })),
189
- )
190
-
191
156
  return {
192
157
  files,
193
158
  pluginManager,
package/src/config.ts CHANGED
@@ -45,5 +45,5 @@ export function defineConfig(
45
45
  }
46
46
 
47
47
  export function isInputPath(result: Config | undefined): result is Config<InputPath> {
48
- return !!result && 'path' in (result as any)
48
+ return !!result && 'path' in (result?.input as any)
49
49
  }
package/src/errors.ts CHANGED
@@ -1,12 +1 @@
1
- /**
2
- * Behaves as an Error to log a warning in the console(still stops the execution)
3
- */
4
- export class Warning extends Error {
5
- constructor(message?: string, options?: { cause: Error }) {
6
- super(message, { cause: options?.cause })
7
-
8
- this.name = 'Warning'
9
- }
10
- }
11
-
12
1
  export class ValidationPluginError extends Error {}
package/src/index.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  export { build, build as default, safeBuild } from './build.ts'
2
2
  export { defineConfig, isInputPath } from './config.ts'
3
- export { Warning } from './errors.ts'
4
- export { FileManager } from './FileManager.ts'
3
+ export { FileManager, getSource } from './FileManager.ts'
5
4
  export type { FileMetaBase } from './FileManager.ts'
6
- export { Generator } from './Generator.ts'
5
+ export { BaseGenerator } from './BaseGenerator.ts'
7
6
  export { PackageManager } from './PackageManager.ts'
8
7
  export { createPlugin } from './plugin.ts'
9
8
  export { PluginManager } from './PluginManager.ts'
package/src/logger.ts CHANGED
@@ -3,16 +3,24 @@ import c, { createColors } from 'tinyrainbow'
3
3
 
4
4
  import { EventEmitter } from './utils/EventEmitter.ts'
5
5
 
6
- import type { ConsolaInstance } from 'consola'
7
- import type { Ora } from 'ora'
6
+ import { resolve } from 'node:path'
7
+ import { write } from '@kubb/fs'
8
+ import { type ConsolaInstance, type LogLevel, createConsola } from 'consola'
8
9
  import type { Formatter } from 'tinyrainbow'
9
10
 
10
- //TODO replace with verbose flag and debug flag
11
- export const LogLevel = {
12
- silent: 'silent',
13
- info: 'info',
14
- debug: 'debug',
15
- } as const
11
+ type DebugEvent = { date: Date; logs: string[]; fileName?: string }
12
+
13
+ type Events = {
14
+ start: [message: string]
15
+ success: [message: string]
16
+ error: [message: string, cause: Error]
17
+ warning: [message: string]
18
+ debug: [DebugEvent]
19
+ info: [message: string]
20
+ progress_start: [{ id: string; size: number; message?: string }]
21
+ progressed: [{ id: string; message?: string }]
22
+ progress_stop: [{ id: string }]
23
+ }
16
24
 
17
25
  export const LogMapper = {
18
26
  silent: Number.NEGATIVE_INFINITY,
@@ -20,54 +28,65 @@ export const LogMapper = {
20
28
  debug: 4,
21
29
  } as const
22
30
 
23
- export type LogLevel = keyof typeof LogLevel
24
-
25
- type Events = {
26
- start: [message: string]
27
- end: [message: string]
28
- error: [message: string, cause: Error]
29
- warning: [message: string]
30
- debug: [logs: string[]]
31
- }
32
31
  export type Logger = {
33
32
  /**
34
33
  * Optional config name to show in CLI output
35
34
  */
36
35
  name?: string
37
36
  logLevel: LogLevel
38
- spinner?: Ora
39
37
  consola?: ConsolaInstance
40
38
  on: EventEmitter<Events>['on']
41
39
  emit: EventEmitter<Events>['emit']
40
+ writeLogs: () => Promise<string[]>
42
41
  }
43
42
 
44
43
  type Props = {
45
44
  name?: string
46
- logLevel: LogLevel
47
- spinner?: Ora
45
+ logLevel?: LogLevel
48
46
  consola?: ConsolaInstance
49
47
  }
50
48
 
51
- export function createLogger({ logLevel, name, spinner, consola }: Props): Logger {
49
+ export function createLogger({ logLevel = 3, name, consola: _consola }: Props = {}): Logger {
52
50
  const events = new EventEmitter<Events>()
51
+ const startDate = Date.now()
52
+ const cachedLogs = new Set<DebugEvent>()
53
+
54
+ const consola =
55
+ _consola ||
56
+ createConsola({
57
+ level: logLevel,
58
+ formatOptions: {
59
+ colors: true,
60
+ date: true,
61
+ columns: 80,
62
+ compact: logLevel !== LogMapper.debug,
63
+ },
64
+ }).withTag(name ? randomCliColour(name) : '')
65
+
66
+ consola?.wrapConsole()
53
67
 
54
68
  events.on('start', (message) => {
55
- if (spinner) {
56
- spinner.start(message)
57
- }
69
+ consola.start(message)
58
70
  })
59
71
 
60
- events.on('end', (message) => {
61
- if (spinner) {
62
- spinner.suffixText = ''
63
- spinner.succeed(message)
64
- }
72
+ events.on('success', (message) => {
73
+ consola.success(message)
65
74
  })
66
75
 
67
76
  events.on('warning', (message) => {
68
- if (spinner) {
69
- spinner.warn(c.yellow(message))
77
+ consola.warn(c.yellow(message))
78
+ })
79
+
80
+ events.on('info', (message) => {
81
+ consola.info(c.yellow(message))
82
+ })
83
+
84
+ events.on('debug', (message) => {
85
+ if (message.logs.join('\n\n').length <= 100 && logLevel === LogMapper.debug) {
86
+ console.log(message.logs.join('\n\n'))
70
87
  }
88
+
89
+ cachedLogs.add(message)
71
90
  })
72
91
 
73
92
  events.on('error', (message, cause) => {
@@ -77,17 +96,40 @@ export function createLogger({ logLevel, name, spinner, consola }: Props): Logge
77
96
  throw error
78
97
  })
79
98
 
99
+ if (consola) {
100
+ consola.level = logLevel
101
+ }
102
+
80
103
  const logger: Logger = {
81
104
  name,
82
105
  logLevel,
83
- spinner,
84
106
  consola,
85
- on: (...args) => {
107
+ on(...args) {
86
108
  return events.on(...args)
87
109
  },
88
- emit: (...args) => {
110
+ emit(...args) {
89
111
  return events.emit(...args)
90
112
  },
113
+ async writeLogs() {
114
+ const files: Record<string, string[]> = {}
115
+
116
+ cachedLogs.forEach((log) => {
117
+ const fileName = resolve(process.cwd(), '.kubb', log.fileName || `kubb-${startDate}.log`)
118
+
119
+ if (!files[fileName]) {
120
+ files[fileName] = []
121
+ }
122
+
123
+ files[fileName] = [...files[fileName], `[${log.date.toLocaleString()}]: ${log.logs.join('\n\n')}`]
124
+ })
125
+ await Promise.all(
126
+ Object.entries(files).map(async ([fileName, logs]) => {
127
+ return write(fileName, logs.join('\n'))
128
+ }),
129
+ )
130
+
131
+ return Object.keys(files)
132
+ },
91
133
  }
92
134
 
93
135
  return logger
package/src/plugin.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  import path from 'node:path'
2
2
 
3
- import { createPluginCache } from './utils/cache.ts'
4
-
5
3
  import type { FileManager } from './FileManager.ts'
6
4
  import type { PluginManager } from './PluginManager.ts'
7
5
  import type { Plugin, PluginContext, PluginFactoryOptions, UserPluginWithLifeCycle } from './types.ts'
@@ -46,7 +44,7 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
46
44
  return options.getPlugins()
47
45
  },
48
46
  get plugin() {
49
- // see pluginManger.#execute where we override with `.call` the this with the correct plugin
47
+ // see pluginManger.#execute where we override with `.call` the context with the correct plugin
50
48
  return options.plugin as NonNullable<Options['plugin']>
51
49
  },
52
50
  logger,
@@ -63,11 +61,10 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
63
61
  },
64
62
  resolvePath,
65
63
  resolveName,
66
- cache: createPluginCache(),
67
64
  }
68
65
  },
69
66
  resolvePath(baseName) {
70
- const root = path.resolve(this.config.root, this.config.output.path)
67
+ const root = path.resolve(options.config.root, options.config.output.path)
71
68
 
72
69
  return path.resolve(root, baseName)
73
70
  },