@kubb/core 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (102) hide show
  1. package/dist/{FileManager-EVJig-LT.d.ts → FileManager-BbUCeEyv.d.cts} +108 -94
  2. package/dist/{FileManager-DSLZ6ps7.d.cts → FileManager-CpuFz6eH.d.ts} +108 -94
  3. package/dist/chunk-2EU7DMPM.js +96 -0
  4. package/dist/chunk-2EU7DMPM.js.map +1 -0
  5. package/dist/chunk-4X5FFJPJ.js +8 -13
  6. package/dist/chunk-4X5FFJPJ.js.map +1 -1
  7. package/dist/chunk-52WA2JF5.cjs +1536 -0
  8. package/dist/chunk-52WA2JF5.cjs.map +1 -0
  9. package/dist/chunk-ADFKVVPE.cjs +42 -0
  10. package/dist/chunk-ADFKVVPE.cjs.map +1 -0
  11. package/dist/{chunk-3OXCZ5DJ.js → chunk-E6CN2CZC.js} +63 -54
  12. package/dist/chunk-E6CN2CZC.js.map +1 -0
  13. package/dist/chunk-HBQM723K.js +1049 -0
  14. package/dist/chunk-HBQM723K.js.map +1 -0
  15. package/dist/{chunk-67C6RBGQ.cjs → chunk-HMCSWG5L.cjs} +25 -26
  16. package/dist/chunk-HMCSWG5L.cjs.map +1 -0
  17. package/dist/chunk-L6YLVCKM.js +894 -0
  18. package/dist/chunk-L6YLVCKM.js.map +1 -0
  19. package/dist/chunk-PJLUPV3P.cjs +1088 -0
  20. package/dist/chunk-PJLUPV3P.cjs.map +1 -0
  21. package/dist/chunk-TTDCUWK7.cjs +101 -0
  22. package/dist/chunk-TTDCUWK7.cjs.map +1 -0
  23. package/dist/{chunk-LM2YQC3T.cjs → chunk-YEVCYV36.cjs} +81 -51
  24. package/dist/chunk-YEVCYV36.cjs.map +1 -0
  25. package/dist/index.cjs +545 -610
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +6 -19
  28. package/dist/index.d.ts +6 -19
  29. package/dist/index.js +438 -522
  30. package/dist/index.js.map +1 -1
  31. package/dist/{logger-DChjnJMn.d.cts → logger-DvbHXjIO.d.cts} +29 -19
  32. package/dist/{logger-DChjnJMn.d.ts → logger-DvbHXjIO.d.ts} +29 -19
  33. package/dist/logger.cjs +25 -15
  34. package/dist/logger.cjs.map +1 -1
  35. package/dist/logger.d.cts +1 -2
  36. package/dist/logger.d.ts +1 -2
  37. package/dist/logger.js +3 -15
  38. package/dist/logger.js.map +1 -1
  39. package/dist/mocks.cjs +27 -26
  40. package/dist/mocks.cjs.map +1 -1
  41. package/dist/mocks.d.cts +6 -9
  42. package/dist/mocks.d.ts +6 -9
  43. package/dist/mocks.js +22 -24
  44. package/dist/mocks.js.map +1 -1
  45. package/dist/prompt-L5KFKY73.cjs +760 -0
  46. package/dist/prompt-L5KFKY73.cjs.map +1 -0
  47. package/dist/prompt-WQQUN22Z.js +749 -0
  48. package/dist/prompt-WQQUN22Z.js.map +1 -0
  49. package/dist/transformers.cjs +215 -49
  50. package/dist/transformers.cjs.map +1 -1
  51. package/dist/transformers.d.cts +1 -3
  52. package/dist/transformers.d.ts +1 -3
  53. package/dist/transformers.js +148 -35
  54. package/dist/transformers.js.map +1 -1
  55. package/dist/utils.cjs +65 -26
  56. package/dist/utils.cjs.map +1 -1
  57. package/dist/utils.d.cts +31 -3
  58. package/dist/utils.d.ts +31 -3
  59. package/dist/utils.js +3 -26
  60. package/dist/utils.js.map +1 -1
  61. package/package.json +10 -10
  62. package/src/BarrelManager.ts +93 -107
  63. package/src/{Generator.ts → BaseGenerator.ts} +1 -1
  64. package/src/FileManager.ts +198 -297
  65. package/src/PackageManager.ts +1 -1
  66. package/src/PluginManager.ts +152 -101
  67. package/src/__snapshots__/barrel.json +91 -0
  68. package/src/__snapshots__/grouped.json +114 -0
  69. package/src/__snapshots__/ordered.json +62 -0
  70. package/src/build.ts +86 -171
  71. package/src/errors.ts +0 -11
  72. package/src/index.ts +1 -2
  73. package/src/logger.ts +76 -34
  74. package/src/plugin.ts +3 -3
  75. package/src/transformers/index.ts +2 -3
  76. package/src/transformers/trim.ts +0 -4
  77. package/src/types.ts +35 -35
  78. package/src/utils/TreeNode.ts +132 -50
  79. package/src/utils/executeStrategies.ts +1 -1
  80. package/src/utils/index.ts +2 -1
  81. package/src/utils/parser.ts +157 -0
  82. package/dist/chunk-3OXCZ5DJ.js.map +0 -1
  83. package/dist/chunk-5JZNFPUP.js +0 -309
  84. package/dist/chunk-5JZNFPUP.js.map +0 -1
  85. package/dist/chunk-67C6RBGQ.cjs.map +0 -1
  86. package/dist/chunk-ADC5UNZ5.cjs +0 -1227
  87. package/dist/chunk-ADC5UNZ5.cjs.map +0 -1
  88. package/dist/chunk-HMLY7DHA.js +0 -16
  89. package/dist/chunk-HMLY7DHA.js.map +0 -1
  90. package/dist/chunk-JKZG2IJR.js +0 -283
  91. package/dist/chunk-JKZG2IJR.js.map +0 -1
  92. package/dist/chunk-LM2YQC3T.cjs.map +0 -1
  93. package/dist/chunk-PZT4CTBV.cjs +0 -299
  94. package/dist/chunk-PZT4CTBV.cjs.map +0 -1
  95. package/dist/chunk-SA2GZKXS.js +0 -596
  96. package/dist/chunk-SA2GZKXS.js.map +0 -1
  97. package/dist/chunk-XCPFG6DO.cjs +0 -66
  98. package/dist/chunk-XCPFG6DO.cjs.map +0 -1
  99. package/dist/chunk-YTSNYMHW.cjs +0 -320
  100. package/dist/chunk-YTSNYMHW.cjs.map +0 -1
  101. package/schema.json +0 -86
  102. package/src/utils/getParser.ts +0 -17
package/src/plugin.ts CHANGED
@@ -37,7 +37,7 @@ export const pluginCore = createPlugin<PluginCore>((options) => {
37
37
  name: 'core',
38
38
  options,
39
39
  key: ['core'],
40
- api() {
40
+ context() {
41
41
  return {
42
42
  get config() {
43
43
  return options.config
@@ -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
  },
@@ -11,7 +11,7 @@ import { searchAndReplace } from './searchAndReplace.ts'
11
11
  import { stringify, stringifyObject } from './stringify.ts'
12
12
  import { toRegExp, toRegExpString } from './toRegExp.ts'
13
13
  import { transformReservedWord } from './transformReservedWord.ts'
14
- import { trim, trimExtName, trimQuotes } from './trim.ts'
14
+ import { trim, trimQuotes } from './trim.ts'
15
15
 
16
16
  export { camelCase, pascalCase, pathCase } from './casing.ts'
17
17
  export { combineCodes } from './combineCodes.ts'
@@ -23,7 +23,7 @@ export { searchAndReplace } from './searchAndReplace.ts'
23
23
  export { stringify, stringifyObject } from './stringify.ts'
24
24
  export { toRegExp, toRegExpString } from './toRegExp.ts'
25
25
  export { transformReservedWord } from './transformReservedWord.ts'
26
- export { trim, trimExtName, trimQuotes } from './trim.ts'
26
+ export { trim, trimQuotes } from './trim.ts'
27
27
  export { merge } from 'remeda'
28
28
  export { orderBy } from 'natural-orderby'
29
29
 
@@ -41,7 +41,6 @@ export default {
41
41
  toRegExpString,
42
42
  trim,
43
43
  trimQuotes,
44
- trimExtName,
45
44
  JSDoc: {
46
45
  createJSDocBlockText,
47
46
  },
@@ -16,7 +16,3 @@ export function trimQuotes(text: string): string {
16
16
 
17
17
  return text
18
18
  }
19
-
20
- export function trimExtName(text: string): string {
21
- return text.replace(/\.[^/.]+$/, '')
22
- }
package/src/types.ts CHANGED
@@ -23,11 +23,9 @@ export type UserConfig = Omit<Config, 'root' | 'plugins'> & {
23
23
  */
24
24
  root?: string
25
25
  /**
26
- * Plugin type can be KubbJSONPlugin or Plugin
27
- * Example: ['@kubb/plugin-oas', { output: false }]
28
- * Or: pluginOas({ output: false })
26
+ * Plugin type should be a Kubb plugin
29
27
  */
30
- plugins?: Array<Omit<UnknownUserPlugin, 'api'>>
28
+ plugins?: Array<Omit<UnknownUserPlugin, 'context'>>
31
29
  }
32
30
 
33
31
  export type InputPath = {
@@ -77,6 +75,11 @@ export type Config<TInput = Input> = {
77
75
  * @default true
78
76
  */
79
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
80
83
  }
81
84
  /**
82
85
  * Array of Kubb plugins to use.
@@ -112,9 +115,9 @@ export type PluginFactoryOptions<
112
115
  */
113
116
  TResolvedOptions extends object = TOptions,
114
117
  /**
115
- * API that you want to expose to other plugins.
118
+ * Context that you want to expose to other plugins.
116
119
  */
117
- TAPI = any,
120
+ TContext = any,
118
121
  /**
119
122
  * When calling `resolvePath` you can specify better types.
120
123
  */
@@ -127,7 +130,7 @@ export type PluginFactoryOptions<
127
130
  key: PluginKey<TName | string>
128
131
  options: TOptions
129
132
  resolvedOptions: TResolvedOptions
130
- api: TAPI
133
+ context: TContext
131
134
  resolvePathOptions: TResolvePathOptions
132
135
  }
133
136
 
@@ -148,19 +151,19 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
148
151
  options: TOptions['resolvedOptions']
149
152
  /**
150
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.
151
- * Can be used to validate depended plugins.
154
+ * Can be used to validate dependent plugins.
152
155
  */
153
156
  pre?: Array<string>
154
157
  /**
155
158
  * Specifies the succeeding plugins for the current plugin. You can pass an array of succeeding plugin names, and the current plugin will be executed before these plugins.
156
159
  */
157
160
  post?: Array<string>
158
- } & (TOptions['api'] extends never
161
+ } & (TOptions['context'] extends never
159
162
  ? {
160
- api?: never
163
+ context?: never
161
164
  }
162
165
  : {
163
- api: (this: TOptions['name'] extends 'core' ? null : Omit<PluginContext<TOptions>, 'addFile'>) => TOptions['api']
166
+ context: (this: TOptions['name'] extends 'core' ? null : Omit<PluginContext<TOptions>, 'addFile'>) => TOptions['context']
164
167
  })
165
168
 
166
169
  export type UserPluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = UserPlugin<TOptions> & PluginLifecycle<TOptions>
@@ -178,9 +181,24 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
178
181
  * @private
179
182
  */
180
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
+ }
181
199
  /**
182
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.
183
- * Can be used to validate depended plugins.
201
+ * Can be used to validate dependent plugins.
184
202
  */
185
203
  pre?: Array<string>
186
204
  /**
@@ -192,14 +210,14 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
192
210
  */
193
211
  options: TOptions['resolvedOptions']
194
212
  /**
195
- * Define an api that can be used by other plugins, see `PluginManager' where we convert from `UserPlugin` to `Plugin`(used when calling `createPlugin`).
213
+ * Define a context that can be used by other plugins, see `PluginManager' where we convert from `UserPlugin` to `Plugin`(used when calling `createPlugin`).
196
214
  */
197
- } & (TOptions['api'] extends never
215
+ } & (TOptions['context'] extends never
198
216
  ? {
199
- api?: never
217
+ context?: never
200
218
  }
201
219
  : {
202
- api: TOptions['api']
220
+ context: TOptions['context']
203
221
  })
204
222
 
205
223
  export type PluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & PluginLifecycle<TOptions>
@@ -224,21 +242,6 @@ export type PluginLifecycle<TOptions extends PluginFactoryOptions = PluginFactor
224
242
  * @example ('pet') => 'Pet'
225
243
  */
226
244
  resolveName?: (this: PluginContext<TOptions>, name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
227
- /**
228
- * Makes it possible to run async logic to override the path defined previously by `resolvePath`.
229
- * @type hookFirst
230
- */
231
- load?: (this: Omit<PluginContext<TOptions>, 'addFile'>, path: KubbFile.Path) => PossiblePromise<TransformResult | null>
232
- /**
233
- * Transform the source-code.
234
- * @type hookReduceArg0
235
- */
236
- transform?: (this: Omit<PluginContext<TOptions>, 'addFile'>, source: string, path: KubbFile.Path) => PossiblePromise<TransformResult>
237
- /**
238
- * Write the result to the file-system based on the id(defined by `resolvePath` or changed by `load`).
239
- * @type hookParallel
240
- */
241
- writeFile?: (this: Omit<PluginContext<TOptions>, 'addFile'>, path: KubbFile.Path, source: string | undefined) => PossiblePromise<string | void>
242
245
  /**
243
246
  * End of the plugin lifecycle.
244
247
  * @type hookParallel
@@ -278,7 +281,7 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
278
281
  cache: Cache<PluginCache>
279
282
  fileManager: FileManager
280
283
  pluginManager: PluginManager
281
- addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.File>>
284
+ addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.ResolvedFile>>
282
285
  resolvePath: (params: ResolvePathParams<TOptions['resolvePathOptions']>) => KubbFile.OptionalPath
283
286
  resolveName: (params: ResolveNameParams) => string
284
287
  logger: Logger
@@ -291,6 +294,3 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
291
294
  */
292
295
  plugin: Plugin<TOptions>
293
296
  }
294
-
295
- // null will mean clear the watcher for this key
296
- export type TransformResult = string | null
@@ -1,28 +1,29 @@
1
- import dirTree from 'directory-tree'
2
-
3
- import { FileManager } from '../FileManager.ts'
4
-
5
1
  import type * as KubbFile from '@kubb/fs/types'
6
- import type { DirectoryTree, DirectoryTreeOptions } from 'directory-tree'
7
-
8
- export type TreeNodeOptions = DirectoryTreeOptions
9
-
10
- type BarrelData = { type: KubbFile.Mode; path: KubbFile.Path; name: string }
11
-
12
- export class TreeNode<T = BarrelData> {
13
- public data: T
2
+ import { FileManager } from '../FileManager.ts'
14
3
 
15
- public parent?: TreeNode<T>
4
+ type BarrelData = {
5
+ file?: KubbFile.File
6
+ /**
7
+ * @deprecated use file instead
8
+ */
9
+ type: KubbFile.Mode
10
+ path: string
11
+ name: string
12
+ }
16
13
 
17
- public children: Array<TreeNode<T>> = []
14
+ export class TreeNode {
15
+ data: BarrelData
16
+ parent?: TreeNode
17
+ children: Array<TreeNode> = []
18
+ #cachedLeaves?: Array<TreeNode> = undefined
18
19
 
19
- constructor(data: T, parent?: TreeNode<T>) {
20
+ constructor(data: BarrelData, parent?: TreeNode) {
20
21
  this.data = data
21
22
  this.parent = parent
22
23
  return this
23
24
  }
24
25
 
25
- addChild(data: T): TreeNode<T> {
26
+ addChild(data: BarrelData): TreeNode {
26
27
  const child = new TreeNode(data, this)
27
28
  if (!this.children) {
28
29
  this.children = []
@@ -31,51 +32,37 @@ export class TreeNode<T = BarrelData> {
31
32
  return child
32
33
  }
33
34
 
34
- find(data?: T): TreeNode<T> | null {
35
- if (!data) {
36
- return null
37
- }
38
-
39
- if (data === this.data) {
35
+ get root(): TreeNode {
36
+ if (!this.parent) {
40
37
  return this
41
38
  }
42
-
43
- if (this.children?.length) {
44
- for (let i = 0, { length } = this.children, target: TreeNode<T> | null = null; i < length; i++) {
45
- target = this.children[i]!.find(data)
46
- if (target) {
47
- return target
48
- }
49
- }
50
- }
51
-
52
- return null
39
+ return this.parent.root
53
40
  }
54
41
 
55
- get leaves(): TreeNode<T>[] {
42
+ get leaves(): Array<TreeNode> {
56
43
  if (!this.children || this.children.length === 0) {
57
44
  // this is a leaf
58
45
  return [this]
59
46
  }
60
47
 
48
+ if (this.#cachedLeaves) {
49
+ return this.#cachedLeaves
50
+ }
51
+
61
52
  // if not a leaf, return all children's leaves recursively
62
- const leaves: TreeNode<T>[] = []
53
+ const leaves: TreeNode[] = []
63
54
  if (this.children) {
64
55
  for (let i = 0, { length } = this.children; i < length; i++) {
65
56
  leaves.push.apply(leaves, this.children[i]!.leaves)
66
57
  }
67
58
  }
68
- return leaves
69
- }
70
59
 
71
- get root(): TreeNode<T> {
72
- if (!this.parent) {
73
- return this
74
- }
75
- return this.parent.root
60
+ this.#cachedLeaves = leaves
61
+
62
+ return leaves
76
63
  }
77
64
 
78
- forEach(callback: (treeNode: TreeNode<T>) => void): this {
65
+ forEach(callback: (treeNode: TreeNode) => void): this {
79
66
  if (typeof callback !== 'function') {
80
67
  throw new TypeError('forEach() callback must be a function')
81
68
  }
@@ -93,13 +80,41 @@ export class TreeNode<T = BarrelData> {
93
80
  return this
94
81
  }
95
82
 
96
- public static build(path: string, options: TreeNodeOptions = {}): TreeNode | null {
83
+ findDeep(predicate?: (value: TreeNode, index: number, obj: TreeNode[]) => boolean): TreeNode | undefined {
84
+ if (typeof predicate !== 'function') {
85
+ throw new TypeError('find() predicate must be a function')
86
+ }
87
+
88
+ return this.leaves.find(predicate)
89
+ }
90
+
91
+ forEachDeep(callback: (treeNode: TreeNode) => void): void {
92
+ if (typeof callback !== 'function') {
93
+ throw new TypeError('forEach() callback must be a function')
94
+ }
95
+
96
+ this.leaves.forEach(callback)
97
+ }
98
+
99
+ filterDeep(callback: (treeNode: TreeNode) => boolean): Array<TreeNode> {
100
+ if (typeof callback !== 'function') {
101
+ throw new TypeError('filter() callback must be a function')
102
+ }
103
+
104
+ return this.leaves.filter(callback)
105
+ }
106
+
107
+ mapDeep<T>(callback: (treeNode: TreeNode) => T): Array<T> {
108
+ if (typeof callback !== 'function') {
109
+ throw new TypeError('map() callback must be a function')
110
+ }
111
+
112
+ return this.leaves.map(callback)
113
+ }
114
+
115
+ public static build(files: KubbFile.File[], root?: string): TreeNode | null {
97
116
  try {
98
- const exclude = Array.isArray(options.exclude) ? options.exclude : [options.exclude].filter(Boolean)
99
- const filteredTree = dirTree(path, {
100
- extensions: options.extensions,
101
- exclude: [/node_modules/, ...exclude],
102
- })
117
+ const filteredTree = buildDirectoryTree(files, root)
103
118
 
104
119
  if (!filteredTree) {
105
120
  return null
@@ -108,6 +123,7 @@ export class TreeNode<T = BarrelData> {
108
123
  const treeNode = new TreeNode({
109
124
  name: filteredTree.name,
110
125
  path: filteredTree.path,
126
+ file: filteredTree.file,
111
127
  type: FileManager.getMode(filteredTree.path),
112
128
  })
113
129
 
@@ -115,6 +131,7 @@ export class TreeNode<T = BarrelData> {
115
131
  const subNode = node.addChild({
116
132
  name: item.name,
117
133
  path: item.path,
134
+ file: item.file,
118
135
  type: FileManager.getMode(item.path),
119
136
  })
120
137
 
@@ -129,7 +146,72 @@ export class TreeNode<T = BarrelData> {
129
146
 
130
147
  return treeNode
131
148
  } catch (e) {
132
- throw new Error('Something went wrong with creating index files with the TreehNode class', { cause: e })
149
+ throw new Error('Something went wrong with creating barrel files with the TreeNode class', { cause: e })
133
150
  }
134
151
  }
135
152
  }
153
+
154
+ export type DirectoryTree = {
155
+ name: string
156
+ path: string
157
+ file?: KubbFile.File
158
+ children: Array<DirectoryTree>
159
+ }
160
+
161
+ export function buildDirectoryTree(files: Array<KubbFile.File>, rootFolder = ''): DirectoryTree | null {
162
+ const rootPrefix = rootFolder.endsWith('/') ? rootFolder : `${rootFolder}/`
163
+ const filteredFiles = files.filter((file) => (rootFolder ? file.path.startsWith(rootPrefix) && !file.path.endsWith('.json') : !file.path.endsWith('.json')))
164
+
165
+ if (filteredFiles.length === 0) {
166
+ return null // No files match the root folder
167
+ }
168
+
169
+ const root: DirectoryTree = {
170
+ name: rootFolder || '',
171
+ path: rootFolder || '',
172
+ children: [],
173
+ }
174
+
175
+ filteredFiles.forEach((file) => {
176
+ const path = file.path.slice(rootFolder.length)
177
+ const parts = path.split('/')
178
+ let currentLevel: DirectoryTree[] = root.children
179
+ let currentPath = rootFolder
180
+
181
+ parts.forEach((part, index) => {
182
+ if (index !== 0) {
183
+ currentPath += `/${part}`
184
+ } else {
185
+ currentPath += `${part}`
186
+ }
187
+
188
+ let existingNode = currentLevel.find((node) => node.name === part)
189
+
190
+ if (!existingNode) {
191
+ if (index === parts.length - 1) {
192
+ // If it's the last part, it's a file
193
+ existingNode = {
194
+ name: part,
195
+ file,
196
+ path: currentPath,
197
+ } as DirectoryTree
198
+ } else {
199
+ // Otherwise, it's a folder
200
+ existingNode = {
201
+ name: part,
202
+ path: currentPath,
203
+ children: [],
204
+ } as DirectoryTree
205
+ }
206
+ currentLevel.push(existingNode)
207
+ }
208
+
209
+ // Move to the next level if it's a folder
210
+ if (!existingNode.file) {
211
+ currentLevel = existingNode.children
212
+ }
213
+ })
214
+ })
215
+
216
+ return root
217
+ }
@@ -4,7 +4,7 @@ export type ValueOfPromiseFuncArray<TInput extends Array<unknown>> = TInput exte
4
4
 
5
5
  export function noReturn(): void {}
6
6
 
7
- type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Array<Awaited<ValueOfPromiseFuncArray<TInput>>>
7
+ type SeqOutput<TInput extends Array<PromiseFunc<TValue, null>>, TValue> = Promise<Array<Awaited<ValueOfPromiseFuncArray<TInput>>>>
8
8
 
9
9
  /**
10
10
  * Chains promises
@@ -10,4 +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 { getParser } from './getParser.ts'
13
+ export { getFileParser, createFileImport, createFileExport, createFile, createFileParser } from './parser.ts'
14
+ export type { ParserModule } from './parser.ts'
@@ -0,0 +1,157 @@
1
+ import { extname } from 'node:path'
2
+ import type * as KubbFile from '@kubb/fs/types'
3
+
4
+ import { getRelativePath } from '@kubb/fs'
5
+ import hash from 'object-hash'
6
+ import { combineExports, combineImports, combineSources } from '../FileManager.ts'
7
+ import type { Logger } from '../logger.ts'
8
+
9
+ /**
10
+ * Helper to create a file with name and id set
11
+ */
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
+
24
+ return {
25
+ ...file,
26
+ id: hash({ path: file.path }),
27
+ name: trimExtName(file.baseName),
28
+ extName,
29
+ imports: imports.map((item) => createFileImport(item)),
30
+ exports: exports.map((item) => createFileExport(item)),
31
+ sources: sources.map((item) => createFileSource(item)),
32
+ }
33
+ }
34
+
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
+ }
52
+ }
53
+
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> {
78
+ return parser
79
+ }
80
+
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
+ })
101
+ })
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
+ })
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
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
151
+ }
152
+
153
+ export function trimExtName(text: string): string {
154
+ const extName = text.split('.').pop()
155
+
156
+ return text.replace(`.${extName}`, '')
157
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/logger.ts","../../../node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js","../../../node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.js","../src/utils/EventEmitter.ts"],"sourcesContent":["import seedrandom from 'seedrandom'\nimport c, { createColors } from 'tinyrainbow'\n\nimport { EventEmitter } from './utils/EventEmitter.ts'\n\nimport type { ConsolaInstance } from 'consola'\nimport type { Ora } from 'ora'\nimport type { Formatter } from 'tinyrainbow'\n\n//TODO replace with verbose flag and debug flag\nexport const LogLevel = {\n silent: 'silent',\n info: 'info',\n debug: 'debug',\n} as const\n\nexport const LogMapper = {\n silent: Number.NEGATIVE_INFINITY,\n info: 3,\n debug: 4,\n} as const\n\nexport type LogLevel = keyof typeof LogLevel\n\ntype Events = {\n start: [message: string]\n end: [message: string]\n error: [message: string, cause: Error]\n warning: [message: string]\n debug: [logs: string[]]\n}\nexport type Logger = {\n /**\n * Optional config name to show in CLI output\n */\n name?: string\n logLevel: LogLevel\n spinner?: Ora\n consola?: ConsolaInstance\n on: EventEmitter<Events>['on']\n emit: EventEmitter<Events>['emit']\n}\n\ntype Props = {\n name?: string\n logLevel: LogLevel\n spinner?: Ora\n consola?: ConsolaInstance\n}\n\nexport function createLogger({ logLevel, name, spinner, consola }: Props): Logger {\n const events = new EventEmitter<Events>()\n\n events.on('start', (message) => {\n if (spinner) {\n spinner.start(message)\n }\n })\n\n events.on('end', (message) => {\n if (spinner) {\n spinner.suffixText = ''\n spinner.succeed(message)\n }\n })\n\n events.on('warning', (message) => {\n if (spinner) {\n spinner.warn(c.yellow(message))\n }\n })\n\n events.on('error', (message, cause) => {\n const error = new Error(message || 'Something went wrong')\n error.cause = cause\n\n throw error\n })\n\n const logger: Logger = {\n name,\n logLevel,\n spinner,\n consola,\n on: (...args) => {\n return events.on(...args)\n },\n emit: (...args) => {\n return events.emit(...args)\n },\n }\n\n return logger\n}\n\nconst defaultColours = ['black', 'blue', 'darkBlue', 'cyan', 'gray', 'green', 'darkGreen', 'magenta', 'red', 'darkRed', 'yellow', 'darkYellow'] as const\n\nexport function randomColour(text?: string, colours = defaultColours): string {\n if (!text) {\n return 'white'\n }\n\n const random = seedrandom(text)\n const colour = colours.at(Math.floor(random() * colours.length)) || 'white'\n\n return colour\n}\n\nexport function randomCliColour(text?: string, colors = defaultColours): string {\n const colours = createColors(true)\n\n if (!text) {\n return colours.white(text)\n }\n\n const colour = randomColour(text, colors)\n const isDark = colour.includes('dark')\n const key = colour.replace('dark', '').toLowerCase() as keyof typeof colours\n const formatter: Formatter = colours[key] as Formatter\n\n if (isDark) {\n return c.bold(formatter(text))\n }\n\n if (typeof formatter !== 'function') {\n throw new Error('Formatter for picoColor is not of type function/Formatter')\n }\n return formatter(text)\n}\n","// src/index.ts\nvar f = {\n reset: [0, 0],\n bold: [1, 22, \"\\x1B[22m\\x1B[1m\"],\n dim: [2, 22, \"\\x1B[22m\\x1B[2m\"],\n italic: [3, 23],\n underline: [4, 24],\n inverse: [7, 27],\n hidden: [8, 28],\n strikethrough: [9, 29],\n black: [30, 39],\n red: [31, 39],\n green: [32, 39],\n yellow: [33, 39],\n blue: [34, 39],\n magenta: [35, 39],\n cyan: [36, 39],\n white: [37, 39],\n gray: [90, 39],\n bgBlack: [40, 49],\n bgRed: [41, 49],\n bgGreen: [42, 49],\n bgYellow: [43, 49],\n bgBlue: [44, 49],\n bgMagenta: [45, 49],\n bgCyan: [46, 49],\n bgWhite: [47, 49],\n blackBright: [90, 39],\n redBright: [91, 39],\n greenBright: [92, 39],\n yellowBright: [93, 39],\n blueBright: [94, 39],\n magentaBright: [95, 39],\n cyanBright: [96, 39],\n whiteBright: [97, 39],\n bgBlackBright: [100, 49],\n bgRedBright: [101, 49],\n bgGreenBright: [102, 49],\n bgYellowBright: [103, 49],\n bgBlueBright: [104, 49],\n bgMagentaBright: [105, 49],\n bgCyanBright: [106, 49],\n bgWhiteBright: [107, 49]\n}, h = Object.entries(f);\nfunction a(n) {\n return String(n);\n}\na.open = \"\";\na.close = \"\";\nvar B = /* @__PURE__ */ h.reduce(\n (n, [e]) => (n[e] = a, n),\n { isColorSupported: !1 }\n);\nfunction m() {\n return { ...B };\n}\nfunction C(n = !1) {\n let e = typeof process != \"undefined\" ? process : void 0, i = (e == null ? void 0 : e.env) || {}, g = (e == null ? void 0 : e.argv) || [];\n return !(\"NO_COLOR\" in i || g.includes(\"--no-color\")) && (\"FORCE_COLOR\" in i || g.includes(\"--color\") || (e == null ? void 0 : e.platform) === \"win32\" || n && i.TERM !== \"dumb\" || \"CI\" in i) || typeof window != \"undefined\" && !!window.chrome;\n}\nfunction p(n = !1) {\n let e = C(n), i = (r, t, c, o) => {\n let l = \"\", s = 0;\n do\n l += r.substring(s, o) + c, s = o + t.length, o = r.indexOf(t, s);\n while (~o);\n return l + r.substring(s);\n }, g = (r, t, c = r) => {\n let o = (l) => {\n let s = String(l), b = s.indexOf(t, r.length);\n return ~b ? r + i(s, t, c, b) + t : r + s + t;\n };\n return o.open = r, o.close = t, o;\n }, u = {\n isColorSupported: e\n }, d = (r) => `\\x1B[${r}m`;\n for (let [r, t] of h)\n u[r] = e ? g(\n d(t[0]),\n d(t[1]),\n t[2]\n ) : a;\n return u;\n}\n\nexport {\n m as a,\n C as b,\n p as c\n};\n","import {\n a as t,\n b as e,\n c as o\n} from \"./chunk-BVHSVHOK.js\";\n\n// src/node.ts\nimport { isatty as r } from \"tty\";\nvar p = o(r(1));\nexport {\n o as createColors,\n p as default,\n t as getDefaultColors,\n e as isSupported\n};\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\n\nexport class EventEmitter<TEvents extends Record<string, any>> {\n constructor() {\n this.#emitter.setMaxListeners(100)\n }\n #emitter = new NodeEventEmitter()\n\n emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArg: TEvents[TEventName]): void {\n this.#emitter.emit(eventName, ...(eventArg as []))\n }\n\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.on(eventName, handler as any)\n }\n\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void {\n this.#emitter.off(eventName, handler as any)\n }\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n"],"mappings":"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","names":["r","p","p"]}