@kubb/core 3.0.0-alpha.6 → 3.0.0-alpha.8

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 (72) hide show
  1. package/dist/{FileManager-wyXRkgIk.d.cts → FileManager-B0GJlthB.d.cts} +30 -16
  2. package/dist/{FileManager-Ceski1W9.d.ts → FileManager-BFycBDqG.d.ts} +30 -16
  3. package/dist/chunk-27CPVXAT.js +945 -0
  4. package/dist/chunk-27CPVXAT.js.map +1 -0
  5. package/dist/{chunk-34BPAXR2.cjs → chunk-5E2I6KH4.cjs} +7 -7
  6. package/dist/{chunk-34BPAXR2.cjs.map → chunk-5E2I6KH4.cjs.map} +1 -1
  7. package/dist/chunk-5IGANEGE.cjs +1564 -0
  8. package/dist/chunk-5IGANEGE.cjs.map +1 -0
  9. package/dist/{chunk-67C6RBGQ.cjs → chunk-A6PCLWEY.cjs} +5 -5
  10. package/dist/{chunk-67C6RBGQ.cjs.map → chunk-A6PCLWEY.cjs.map} +1 -1
  11. package/dist/{chunk-5HN4LW3R.cjs → chunk-DID47EQD.cjs} +3 -3
  12. package/dist/{chunk-5HN4LW3R.cjs.map → chunk-DID47EQD.cjs.map} +1 -1
  13. package/dist/{chunk-25NKJ3DV.js → chunk-HBQM723K.js} +6 -6
  14. package/dist/{chunk-LOLEBOMW.cjs → chunk-IPZQXBA2.cjs} +16 -21
  15. package/dist/chunk-IPZQXBA2.cjs.map +1 -0
  16. package/dist/{chunk-76UEJFFE.js → chunk-SCR3LUXT.js} +9 -16
  17. package/dist/{chunk-76UEJFFE.js.map → chunk-SCR3LUXT.js.map} +1 -1
  18. package/dist/{chunk-XCPFG6DO.cjs → chunk-SEH6NUCX.cjs} +4 -28
  19. package/dist/chunk-SEH6NUCX.cjs.map +1 -0
  20. package/dist/index.cjs +380 -378
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +2 -2
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +325 -319
  25. package/dist/index.js.map +1 -1
  26. package/dist/logger.cjs +4 -4
  27. package/dist/logger.js +2 -3
  28. package/dist/mocks.cjs +20 -15
  29. package/dist/mocks.cjs.map +1 -1
  30. package/dist/mocks.d.cts +6 -5
  31. package/dist/mocks.d.ts +6 -5
  32. package/dist/mocks.js +15 -11
  33. package/dist/mocks.js.map +1 -1
  34. package/dist/{prompt-6FWP747F.cjs → prompt-DVQN7JTN.cjs} +61 -61
  35. package/dist/{prompt-6FWP747F.cjs.map → prompt-DVQN7JTN.cjs.map} +1 -1
  36. package/dist/{prompt-HK3MWREM.js → prompt-WQQUN22Z.js} +5 -6
  37. package/dist/{prompt-HK3MWREM.js.map → prompt-WQQUN22Z.js.map} +1 -1
  38. package/dist/transformers.cjs +19 -19
  39. package/dist/transformers.js +0 -1
  40. package/dist/transformers.js.map +1 -1
  41. package/dist/utils.cjs +8 -4
  42. package/dist/utils.cjs.map +1 -1
  43. package/dist/utils.d.cts +25 -24
  44. package/dist/utils.d.ts +25 -24
  45. package/dist/utils.js +5 -2
  46. package/package.json +7 -7
  47. package/src/BarrelManager.ts +90 -40
  48. package/src/FileManager.ts +89 -109
  49. package/src/PluginManager.ts +2 -1
  50. package/src/__snapshots__/barrel.json +91 -0
  51. package/src/__snapshots__/grouped.json +114 -0
  52. package/src/__snapshots__/ordered.json +62 -0
  53. package/src/build.ts +60 -23
  54. package/src/plugin.ts +2 -2
  55. package/src/types.ts +22 -2
  56. package/src/utils/TreeNode.ts +43 -1
  57. package/src/utils/index.ts +1 -1
  58. package/src/utils/parser.ts +128 -67
  59. package/dist/chunk-AWAZR3D5.js +0 -360
  60. package/dist/chunk-AWAZR3D5.js.map +0 -1
  61. package/dist/chunk-DCZQYCCO.cjs +0 -1155
  62. package/dist/chunk-DCZQYCCO.cjs.map +0 -1
  63. package/dist/chunk-HMLY7DHA.js +0 -16
  64. package/dist/chunk-HMLY7DHA.js.map +0 -1
  65. package/dist/chunk-L3JJLZ5Q.cjs +0 -371
  66. package/dist/chunk-L3JJLZ5Q.cjs.map +0 -1
  67. package/dist/chunk-LOLEBOMW.cjs.map +0 -1
  68. package/dist/chunk-RIEGCND2.js +0 -525
  69. package/dist/chunk-RIEGCND2.js.map +0 -1
  70. package/dist/chunk-XCPFG6DO.cjs.map +0 -1
  71. package/schema.json +0 -86
  72. /package/dist/{chunk-25NKJ3DV.js.map → chunk-HBQM723K.js.map} +0 -0
package/src/build.ts CHANGED
@@ -1,12 +1,13 @@
1
- import c from 'tinyrainbow'
2
-
3
1
  import { clean, read } from '@kubb/fs'
4
- import { type FileManager, processFiles } 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
6
  import { createLogger } from './logger.ts'
8
7
  import { URLPath } from './utils/URLPath.ts'
9
8
 
9
+ import { resolve } from 'node:path'
10
+ import { getRelativePath } from '@kubb/fs'
10
11
  import type { Logger } from './logger.ts'
11
12
  import type { PluginContext } from './types.ts'
12
13
 
@@ -36,12 +37,9 @@ async function setup(options: BuildOptions): Promise<PluginManager> {
36
37
  }
37
38
  } catch (e) {
38
39
  if (isInputPath(config)) {
39
- throw new Error(
40
- `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)}`,
41
- {
42
- cause: e,
43
- },
44
- )
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
+ })
45
43
  }
46
44
  }
47
45
 
@@ -53,25 +51,14 @@ async function setup(options: BuildOptions): Promise<PluginManager> {
53
51
  }
54
52
 
55
53
  export async function build(options: BuildOptions): Promise<BuildOutput> {
56
- const pluginManager = await setup(options)
57
-
58
- await pluginManager.hookParallel({
59
- hookName: 'buildStart',
60
- parameters: [options.config],
61
- })
54
+ const { files, pluginManager, error } = await safeBuild(options)
62
55
 
63
- const files = await processFiles({
64
- config: options.config,
65
- dryRun: !options.config.output.write,
66
- files: pluginManager.fileManager.files,
67
- logger: pluginManager.logger,
68
- })
69
-
70
- await pluginManager.hookParallel({ hookName: 'buildEnd' })
56
+ if (error) throw error
71
57
 
72
58
  return {
73
59
  files,
74
60
  pluginManager,
61
+ error,
75
62
  }
76
63
  }
77
64
 
@@ -85,6 +72,54 @@ export async function safeBuild(options: BuildOptions): Promise<BuildOutput> {
85
72
  parameters: [options.config],
86
73
  })
87
74
 
75
+ // create root barrel file
76
+ const root = resolve(options.config.root)
77
+ const rootPath = resolve(root, options.config.output.path, 'index.ts')
78
+ const barrelFiles = pluginManager.fileManager.files.filter((file) => {
79
+ return file.sources.some((source) => source.isIndexable)
80
+ })
81
+
82
+ const rootFile: KubbFile.File = {
83
+ path: rootPath,
84
+ baseName: 'index.ts',
85
+ exports: barrelFiles
86
+ .flatMap((file) => {
87
+ return file.sources
88
+ ?.map((source) => {
89
+ if (!file.path || !source.isIndexable) {
90
+ return undefined
91
+ }
92
+
93
+ // validate of the file is coming from plugin x, needs pluginKey on every file TODO update typing
94
+ const plugin = pluginManager.plugins.find((item) => {
95
+ const meta = file.meta as any
96
+ return item.name === meta?.pluginKey?.[0]
97
+ })
98
+
99
+ if (plugin?.output?.exportType === false) {
100
+ return undefined
101
+ }
102
+
103
+ if (FileManager.getMode(plugin?.output?.path) === 'single') {
104
+ return undefined
105
+ }
106
+ return {
107
+ name: options.config.output.exportType === 'barrel' ? undefined : [source.name],
108
+ path: getRelativePath(rootPath, file.path),
109
+ isTypeOnly: source.isTypeOnly,
110
+ } as KubbFile.Export
111
+ })
112
+ .filter(Boolean)
113
+ })
114
+ .filter(Boolean),
115
+ sources: [],
116
+ meta: {},
117
+ }
118
+
119
+ if (options.config.output.exportType) {
120
+ await pluginManager.fileManager.add(rootFile)
121
+ }
122
+
88
123
  //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
89
124
  files = await processFiles({
90
125
  config: options.config,
@@ -94,6 +129,8 @@ export async function safeBuild(options: BuildOptions): Promise<BuildOutput> {
94
129
  })
95
130
 
96
131
  await pluginManager.hookParallel({ hookName: 'buildEnd' })
132
+
133
+ pluginManager.fileManager.clear()
97
134
  } catch (e) {
98
135
  return {
99
136
  files: [],
package/src/plugin.ts CHANGED
@@ -46,7 +46,7 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
46
46
  return options.getPlugins()
47
47
  },
48
48
  get plugin() {
49
- // see pluginManger.#execute where we override with `.call` the this with the correct plugin
49
+ // see pluginManger.#execute where we override with `.call` the context with the correct plugin
50
50
  return options.plugin as NonNullable<Options['plugin']>
51
51
  },
52
52
  logger,
@@ -67,7 +67,7 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
67
67
  }
68
68
  },
69
69
  resolvePath(baseName) {
70
- const root = path.resolve(this.config.root, this.config.output.path)
70
+ const root = path.resolve(options.config.root, options.config.output.path)
71
71
 
72
72
  return path.resolve(root, baseName)
73
73
  },
package/src/types.ts CHANGED
@@ -75,6 +75,11 @@ export type Config<TInput = Input> = {
75
75
  * @default true
76
76
  */
77
77
  write?: boolean
78
+ /**
79
+ * Define what needs to exported, here you can also disable the export of barrel files
80
+ * @default `'barrelNamed'`
81
+ */
82
+ exportType?: 'barrel' | 'barrelNamed' | false
78
83
  }
79
84
  /**
80
85
  * Array of Kubb plugins to use.
@@ -146,7 +151,7 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
146
151
  options: TOptions['resolvedOptions']
147
152
  /**
148
153
  * Specifies the preceding plugins for the current plugin. You can pass an array of preceding plugin names, and the current plugin will be executed after these plugins.
149
- * Can be used to validate depended plugins.
154
+ * Can be used to validate dependent plugins.
150
155
  */
151
156
  pre?: Array<string>
152
157
  /**
@@ -176,9 +181,24 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
176
181
  * @private
177
182
  */
178
183
  key: TOptions['key']
184
+ output?: {
185
+ /**
186
+ * Output to save the clients.
187
+ */
188
+ path: string
189
+ /**
190
+ * Add an extension to the generated imports and exports, default it will not use an extension
191
+ */
192
+ extName?: KubbFile.Extname
193
+ /**
194
+ * Define what needs to exported, here you can also disable the export of barrel files
195
+ * @default `'barrelNamed'`
196
+ */
197
+ exportType?: 'barrel' | 'barrelNamed' | false
198
+ }
179
199
  /**
180
200
  * Specifies the preceding plugins for the current plugin. You can pass an array of preceding plugin names, and the current plugin will be executed after these plugins.
181
- * Can be used to validate depended plugins.
201
+ * Can be used to validate dependent plugins.
182
202
  */
183
203
  pre?: Array<string>
184
204
  /**
@@ -95,6 +95,48 @@ export class TreeNode {
95
95
  return this
96
96
  }
97
97
 
98
+ filter(callback: (treeNode: TreeNode) => boolean): Array<TreeNode> {
99
+ let data: Array<TreeNode> = []
100
+ if (typeof callback !== 'function') {
101
+ throw new TypeError('forEach() callback must be a function')
102
+ }
103
+
104
+ // run this node through function
105
+ if (callback(this)) {
106
+ data.push(this)
107
+ }
108
+
109
+ // do the same for all children
110
+ if (this.children) {
111
+ for (let i = 0, { length } = this.children; i < length; i++) {
112
+ const childData = this.children[i]?.filter(callback).filter(Boolean) || []
113
+ data = [...new Set([...data, ...childData])]
114
+ }
115
+ }
116
+
117
+ return data
118
+ }
119
+
120
+ map<T>(callback: (treeNode: TreeNode) => T): Array<T> {
121
+ let data: Array<T> = []
122
+ if (typeof callback !== 'function') {
123
+ throw new TypeError('forEach() callback must be a function')
124
+ }
125
+
126
+ // run this node through function
127
+ data.push(callback(this))
128
+
129
+ // do the same for all children
130
+ if (this.children) {
131
+ for (let i = 0, { length } = this.children; i < length; i++) {
132
+ const childData = this.children[i]?.map(callback).filter(Boolean) || []
133
+ data = [...new Set([...data, ...childData])]
134
+ }
135
+ }
136
+
137
+ return data
138
+ }
139
+
98
140
  public static build(files: KubbFile.File[], root?: string): TreeNode | null {
99
141
  try {
100
142
  const filteredTree = buildDirectoryTree(files, root)
@@ -129,7 +171,7 @@ export class TreeNode {
129
171
 
130
172
  return treeNode
131
173
  } catch (e) {
132
- throw new Error('Something went wrong with creating index files with the TreehNode class', { cause: e })
174
+ throw new Error('Something went wrong with creating barrel files with the TreeNode class', { cause: e })
133
175
  }
134
176
  }
135
177
  }
@@ -10,5 +10,5 @@ export { timeout } from './timeout.ts'
10
10
  export { getUniqueName, setUniqueName } from './uniqueName.ts'
11
11
  export type { URLObject } from './URLPath.ts'
12
12
  export { URLPath } from './URLPath.ts'
13
- export { getFileParser, createFile, createFileParser } from './parser.ts'
13
+ export { getFileParser, createFileImport, createFileExport, createFile, createFileParser } from './parser.ts'
14
14
  export type { ParserModule } from './parser.ts'
@@ -1,92 +1,153 @@
1
+ import { extname } from 'node:path'
1
2
  import type * as KubbFile from '@kubb/fs/types'
2
3
 
4
+ import { getRelativePath } from '@kubb/fs'
3
5
  import hash from 'object-hash'
6
+ import { combineExports, combineImports, combineSources } from '../FileManager.ts'
7
+ import type { Logger } from '../logger.ts'
4
8
 
5
9
  /**
6
10
  * Helper to create a file with name and id set
7
11
  */
8
12
  export function createFile<TMeta extends object = object>(file: KubbFile.File<TMeta>): KubbFile.ResolvedFile<TMeta> {
13
+ const extName = extname(file.baseName) as KubbFile.Extname
14
+
15
+ if (!extName) {
16
+ throw new Error(`No extName found for ${file.baseName}`)
17
+ }
18
+
19
+ const source = file.sources.map((item) => item.value).join('\n\n')
20
+ const exports = file.exports ? combineExports(file.exports) : []
21
+ const imports = file.imports && source ? combineImports(file.imports, exports, source) : []
22
+ const sources = file.sources ? combineSources(file.sources) : []
23
+
9
24
  return {
25
+ ...file,
10
26
  id: hash({ path: file.path }),
11
27
  name: trimExtName(file.baseName),
12
- extName: file.baseName.split('.').pop() || '',
13
- ...file,
28
+ extName,
29
+ imports: imports.map((item) => createFileImport(item)),
30
+ exports: exports.map((item) => createFileExport(item)),
31
+ sources: sources.map((item) => createFileSource(item)),
14
32
  }
15
33
  }
16
34
 
17
- export type ParserModule<TImport = unknown, TExport = unknown> = {
18
- createImport: (props: {
19
- name:
20
- | string
21
- | Array<
22
- | string
23
- | {
24
- propertyName: string
25
- name?: string
26
- }
27
- >
28
- path: string
29
- isTypeOnly?: boolean
30
- isNameSpace?: boolean
31
- }) => TImport | undefined
32
- createExport: (props: {
33
- path: string
34
- asAlias?: boolean
35
- isTypeOnly?: boolean
36
- name?: string | Array<string>
37
- }) => TExport | undefined
38
- print: (props: { imports: Array<TImport>; exports: Array<TExport>; source: string }) => string
35
+ /**
36
+ * Helper to create a fileImport with extName set
37
+ */
38
+ export function createFileSource(source: KubbFile.Source): KubbFile.Source {
39
+ return source
40
+ }
41
+
42
+ /**
43
+ * Helper to create a fileImport with extName set
44
+ */
45
+ export function createFileImport(imp: KubbFile.Import): KubbFile.ResolvedImport {
46
+ const extName = extname(imp.path) as KubbFile.Extname
47
+
48
+ return {
49
+ ...imp,
50
+ extName: imp.extName ? imp.extName : extName,
51
+ }
39
52
  }
40
53
 
41
- export function createFileParser<TImport = unknown, TExport = unknown>(parser: ParserModule<TImport, TExport>): ParserModule<TImport, TExport> {
54
+ /**
55
+ * Helper to create a fileExport with extName set
56
+ */
57
+ export function createFileExport(exp: KubbFile.Export): KubbFile.ResolvedExport {
58
+ const extName = extname(exp.path) as KubbFile.Extname
59
+
60
+ return {
61
+ ...exp,
62
+ extName: exp.extName ? exp.extName : extName,
63
+ }
64
+ }
65
+
66
+ export type ParserModule<TMeta extends object = object> = {
67
+ /**
68
+ * By default @kubb/react is used
69
+ */
70
+ render: (item: any) => any
71
+ /**
72
+ * Convert a file to string
73
+ */
74
+ print: (file: KubbFile.ResolvedFile<TMeta>, options: PrintOptions) => Promise<string>
75
+ }
76
+
77
+ export function createFileParser<TMeta extends object = object>(parser: ParserModule<TMeta>): ParserModule<TMeta> {
42
78
  return parser
43
79
  }
44
80
 
45
- export async function getFileParser(extName: string | undefined): Promise<ParserModule<any, any>> {
46
- switch (extName) {
47
- case 'ts':
48
- case 'js':
49
- case 'tsx':
50
- case 'jsx': {
51
- const module = await import('@kubb/parser-ts')
52
-
53
- return createFileParser({
54
- createExport({ name, path, isTypeOnly, asAlias }) {
55
- return module.factory.createExportDeclaration({
56
- path,
57
- asAlias,
58
- isTypeOnly,
59
- name,
60
- })
61
- },
62
- createImport({ name, path, isTypeOnly }) {
63
- return module.factory.createImportDeclaration({
64
- name: name as any,
65
- path,
66
- isTypeOnly,
67
- })
68
- },
69
- print(props) {
70
- const source = [module.print([...props.imports, ...props.exports]), props.source].join('\n')
71
-
72
- // do some basic linting with the ts compiler
73
- return module.print([], { source, noEmitHelpers: false })
74
- },
81
+ type PrintOptions = {
82
+ logger?: Logger
83
+ }
84
+
85
+ const typeScriptParser = createFileParser({
86
+ render() {
87
+ return undefined
88
+ },
89
+ async print(file) {
90
+ const module = await import('@kubb/parser-ts')
91
+
92
+ const importNodes = file.imports
93
+ .map((item) => {
94
+ const path = item.root ? getRelativePath(item.root, item.path) : item.path
95
+
96
+ return module.factory.createImportDeclaration({
97
+ name: item.name,
98
+ path,
99
+ isTypeOnly: item.isTypeOnly,
100
+ })
75
101
  })
76
- }
77
- default:
78
- return createFileParser<string>({
79
- createExport() {
80
- return undefined
81
- },
82
- createImport() {
83
- return undefined
84
- },
85
- print(props) {
86
- return props.source
87
- },
102
+ .filter(Boolean)
103
+
104
+ const exportNodes = file.exports
105
+ .map((item) => {
106
+ return module.factory.createExportDeclaration({
107
+ name: item.name,
108
+ path: item.path,
109
+ isTypeOnly: item.isTypeOnly,
110
+ asAlias: item.asAlias,
111
+ })
88
112
  })
113
+ .filter(Boolean)
114
+
115
+ const source = [module.print([...importNodes, ...exportNodes]), file.sources.map((item) => item.value).join('\n\n')].join('\n')
116
+
117
+ // do some basic linting with the ts compiler
118
+ return module.print([], { source, noEmitHelpers: false })
119
+ },
120
+ })
121
+
122
+ const defaultParser = createFileParser({
123
+ render() {
124
+ return undefined
125
+ },
126
+ async print(file, { logger }) {
127
+ return file.sources.map((item) => item.value).join('\n\n')
128
+ },
129
+ })
130
+
131
+ const parsers: Record<KubbFile.Extname, ParserModule<any>> = {
132
+ '.ts': typeScriptParser,
133
+ '.js': typeScriptParser,
134
+ '.jsx': typeScriptParser,
135
+ '.tsx': typeScriptParser,
136
+ '.json': defaultParser,
137
+ }
138
+
139
+ export async function getFileParser<TMeta extends object = object>(extName: KubbFile.Extname | undefined): Promise<ParserModule<TMeta>> {
140
+ if (!extName) {
141
+ return defaultParser
89
142
  }
143
+
144
+ const parser = parsers[extName]
145
+
146
+ if (!parser) {
147
+ console.warn(`[parser] No parser found for ${extName}, default parser will be used`)
148
+ }
149
+
150
+ return parser || defaultParser
90
151
  }
91
152
 
92
153
  export function trimExtName(text: string): string {