@kubb/fabric-core 0.0.0 → 0.1.0

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,6 +1,6 @@
1
1
  import pLimit from 'p-limit'
2
2
 
3
- import type * as KubbFile from './types.ts'
3
+ import type * as KubbFile from './KubbFile.ts'
4
4
  import { parseFile } from './parsers/parser.ts'
5
5
  import { Cache } from './utils/Cache.ts'
6
6
  import { trimExtName, write } from './fs.ts'
@@ -14,91 +14,6 @@ type WriteFilesProps = {
14
14
  dryRun?: boolean
15
15
  }
16
16
 
17
- export class FileManager {
18
- #cache = new Cache<KubbFile.ResolvedFile>()
19
- #limit = pLimit(100)
20
-
21
- constructor() {
22
- return this
23
- }
24
-
25
- async add(...files: Array<KubbFile.File>) {
26
- const resolvedFiles: Array<KubbFile.ResolvedFile> = []
27
-
28
- const mergedFiles = new Map<string, KubbFile.File>()
29
-
30
- files.forEach((file) => {
31
- const existing = mergedFiles.get(file.path)
32
- if (existing) {
33
- mergedFiles.set(file.path, mergeFile(existing, file))
34
- } else {
35
- mergedFiles.set(file.path, file)
36
- }
37
- })
38
-
39
- for (const file of mergedFiles.values()) {
40
- const existing = this.#cache.get(file.path)
41
-
42
- const merged = existing ? mergeFile(existing, file) : file
43
- const resolvedFile = createFile(merged)
44
-
45
- this.#cache.set(resolvedFile.path, resolvedFile)
46
- this.flush()
47
-
48
- resolvedFiles.push(resolvedFile)
49
- }
50
-
51
- return resolvedFiles
52
- }
53
-
54
- flush() {
55
- this.#cache.flush()
56
- }
57
-
58
- getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | null {
59
- return this.#cache.get(path)
60
- }
61
-
62
- deleteByPath(path: KubbFile.Path): void {
63
- this.#cache.delete(path)
64
- }
65
-
66
- clear(): void {
67
- this.#cache.clear()
68
- }
69
-
70
- getFiles(): Array<KubbFile.ResolvedFile> {
71
- const cachedKeys = this.#cache.keys()
72
-
73
- // order by path length and if file is a barrel file
74
- const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])
75
-
76
- const files = keys.map((key) => this.#cache.get(key))
77
-
78
- return files.filter(Boolean)
79
- }
80
-
81
- async processFiles({ dryRun, extension }: WriteFilesProps): Promise<Array<KubbFile.ResolvedFile>> {
82
- const files = this.getFiles()
83
-
84
- const promises = files.map((resolvedFile) => {
85
- return this.#limit(async () => {
86
- const extname = extension ? extension[resolvedFile.extname] || undefined : resolvedFile.extname
87
-
88
- if (!dryRun) {
89
- const source = await parseFile(resolvedFile, { extname })
90
-
91
- await write(resolvedFile.path, source, { sanity: false })
92
- }
93
- })
94
- })
95
-
96
- await Promise.all(promises)
97
-
98
- return files
99
- }
100
- }
101
-
102
17
  function hashObject(obj: Record<string, unknown>): string {
103
18
  const str = JSON.stringify(obj, Object.keys(obj).sort())
104
19
  return createHash('sha256').update(str).digest('hex')
@@ -268,3 +183,88 @@ export function createFile<TMeta extends object = object>(file: KubbFile.File<TM
268
183
  meta: file.meta || ({} as TMeta),
269
184
  }
270
185
  }
186
+
187
+ export class FileManager {
188
+ #cache = new Cache<KubbFile.ResolvedFile>()
189
+ #limit = pLimit(100)
190
+
191
+ constructor() {
192
+ return this
193
+ }
194
+
195
+ async add(...files: Array<KubbFile.File>) {
196
+ const resolvedFiles: Array<KubbFile.ResolvedFile> = []
197
+
198
+ const mergedFiles = new Map<string, KubbFile.File>()
199
+
200
+ files.forEach((file) => {
201
+ const existing = mergedFiles.get(file.path)
202
+ if (existing) {
203
+ mergedFiles.set(file.path, mergeFile(existing, file))
204
+ } else {
205
+ mergedFiles.set(file.path, file)
206
+ }
207
+ })
208
+
209
+ for (const file of mergedFiles.values()) {
210
+ const existing = this.#cache.get(file.path)
211
+
212
+ const merged = existing ? mergeFile(existing, file) : file
213
+ const resolvedFile = createFile(merged)
214
+
215
+ this.#cache.set(resolvedFile.path, resolvedFile)
216
+ this.flush()
217
+
218
+ resolvedFiles.push(resolvedFile)
219
+ }
220
+
221
+ return resolvedFiles
222
+ }
223
+
224
+ flush() {
225
+ this.#cache.flush()
226
+ }
227
+
228
+ getByPath(path: KubbFile.Path): KubbFile.ResolvedFile | null {
229
+ return this.#cache.get(path)
230
+ }
231
+
232
+ deleteByPath(path: KubbFile.Path): void {
233
+ this.#cache.delete(path)
234
+ }
235
+
236
+ clear(): void {
237
+ this.#cache.clear()
238
+ }
239
+
240
+ getFiles(): Array<KubbFile.ResolvedFile> {
241
+ const cachedKeys = this.#cache.keys()
242
+
243
+ // order by path length and if file is a barrel file
244
+ const keys = orderBy(cachedKeys, [(v) => v.length, (v) => trimExtName(v).endsWith('index')])
245
+
246
+ const files = keys.map((key) => this.#cache.get(key))
247
+
248
+ return files.filter(Boolean)
249
+ }
250
+
251
+ async processFiles({ dryRun, extension }: WriteFilesProps): Promise<Array<KubbFile.ResolvedFile>> {
252
+ const files = this.getFiles()
253
+
254
+ const promises = files.map((resolvedFile) => {
255
+ return this.#limit(async () => {
256
+ const extname = extension ? extension[resolvedFile.extname] || undefined : resolvedFile.extname
257
+
258
+ if (!dryRun) {
259
+ const source = await parseFile(resolvedFile, { extname })
260
+
261
+ await write(resolvedFile.path, source, { sanity: false })
262
+ }
263
+ })
264
+ })
265
+
266
+ await Promise.all(promises)
267
+
268
+ return files
269
+ }
270
+ }
@@ -0,0 +1,132 @@
1
+ type BasePath<T extends string = string> = `${T}/`
2
+
3
+ export type Import = {
4
+ /**
5
+ * Import name to be used
6
+ * @example ["useState"]
7
+ * @example "React"
8
+ */
9
+ name:
10
+ | string
11
+ | Array<
12
+ | string
13
+ | {
14
+ propertyName: string
15
+ name?: string
16
+ }
17
+ >
18
+ /**
19
+ * Path for the import
20
+ * @example '@kubb/core'
21
+ */
22
+ path: string
23
+ /**
24
+ * Add `type` prefix to the import, this will result in: `import type { Type } from './path'`.
25
+ */
26
+ isTypeOnly?: boolean
27
+
28
+ isNameSpace?: boolean
29
+ /**
30
+ * When root is set it will get the path with relative getRelativePath(root, path).
31
+ */
32
+ root?: string
33
+ }
34
+
35
+ export type Source = {
36
+ name?: string
37
+ value?: string
38
+ isTypeOnly?: boolean
39
+ /**
40
+ * Has const or type 'export'
41
+ * @default false
42
+ */
43
+ isExportable?: boolean
44
+ /**
45
+ * When set, barrel generation will add this
46
+ * @default false
47
+ */
48
+ isIndexable?: boolean
49
+ }
50
+
51
+ export type Export = {
52
+ /**
53
+ * Export name to be used.
54
+ * @example ["useState"]
55
+ * @example "React"
56
+ */
57
+ name?: string | Array<string>
58
+ /**
59
+ * Path for the import.
60
+ * @example '@kubb/core'
61
+ */
62
+ path: string
63
+ /**
64
+ * Add `type` prefix to the export, this will result in: `export type { Type } from './path'`.
65
+ */
66
+ isTypeOnly?: boolean
67
+ /**
68
+ * Make it possible to override the name, this will result in: `export * as aliasName from './path'`.
69
+ */
70
+ asAlias?: boolean
71
+ }
72
+
73
+ export type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`
74
+
75
+ export type Mode = 'single' | 'split'
76
+
77
+ /**
78
+ * Name to be used to dynamicly create the baseName(based on input.path)
79
+ * Based on UNIX basename
80
+ * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
81
+ */
82
+ export type BaseName = `${string}.${string}`
83
+
84
+ /**
85
+ * Path will be full qualified path to a specified file
86
+ */
87
+ export type Path = string
88
+
89
+ export type AdvancedPath<T extends BaseName = BaseName> = `${BasePath}${T}`
90
+
91
+ export type OptionalPath = Path | undefined | null
92
+
93
+ export type File<TMeta extends object = object> = {
94
+ /**
95
+ * Name to be used to create the path
96
+ * Based on UNIX basename, `${name}.extname`
97
+ * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
98
+ */
99
+ baseName: BaseName
100
+ /**
101
+ * Path will be full qualified path to a specified file
102
+ */
103
+ path: AdvancedPath<BaseName> | Path
104
+ sources: Array<Source>
105
+ imports?: Array<Import>
106
+ exports?: Array<Export>
107
+ /**
108
+ * Use extra meta, this is getting used to generate the barrel/index files.
109
+ */
110
+ meta?: TMeta
111
+ banner?: string
112
+ footer?: string
113
+ }
114
+
115
+ export type ResolvedImport = Import
116
+
117
+ export type ResolvedExport = Export
118
+
119
+ export type ResolvedFile<TMeta extends object = object> = File<TMeta> & {
120
+ /**
121
+ * @default hash
122
+ */
123
+ id: string
124
+ /**
125
+ * Contains the first part of the baseName, generated based on baseName
126
+ * @link https://nodejs.org/api/path.html#pathformatpathobject
127
+ */
128
+ name: string
129
+ extname: Extname
130
+ imports: Array<ResolvedImport>
131
+ exports: Array<ResolvedExport>
132
+ }
package/src/defineApp.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type * as KubbFile from './types.ts'
1
+ import type * as KubbFile from './KubbFile.ts'
2
2
  import { FileManager } from './FileManager.ts'
3
3
  import { isPromise } from 'remeda'
4
4
 
@@ -19,46 +19,42 @@ type AppRenderer = {
19
19
  waitUntilExit(): Promise<void>
20
20
  }
21
21
 
22
- export type AppContext = {
22
+ export type AppContext<TOptions = unknown> = {
23
+ options?: TOptions
23
24
  fileManager: FileManager
24
25
  addFile(...files: Array<KubbFile.File>): Promise<void>
25
26
  files: Array<KubbFile.ResolvedFile>
26
27
  clear: () => void
27
28
  }
28
29
 
29
- type RootRenderFunction<THostElement = unknown> = (this: AppContext, container: THostElement, context: AppContext) => AppRenderer
30
+ type RootRenderFunction<THostElement, TContext extends AppContext> = (this: TContext, container: THostElement, context: TContext) => AppRenderer
30
31
 
31
32
  type Plugin<Options = any[], P extends unknown[] = Options extends unknown[] ? Options : [Options]> = FunctionPlugin<P> | ObjectPlugin<P>
32
33
 
33
- export interface App<_THostElement = unknown> {
34
+ type WriteOptions = {
35
+ extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
36
+ dryRun?: boolean
37
+ }
38
+
39
+ export interface App {
34
40
  _component: Component
35
41
  render(): Promise<void>
36
42
  renderToString(): Promise<string>
37
43
  getFiles(): Promise<Array<KubbFile.ResolvedFile>>
38
44
  use<Options>(plugin: Plugin<Options>, options: NoInfer<Options>): this
39
- write(): Promise<void>
45
+ write(options?: WriteOptions): Promise<void>
40
46
  addFile(...files: Array<KubbFile.File>): Promise<void>
41
47
  waitUntilExit(): Promise<void>
42
48
  }
43
49
 
44
- type DefineOptions = {
45
- extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
46
- dryRun?: boolean
47
- }
50
+ export type DefineApp<TContext extends AppContext> = (rootComponent?: Component, options?: TContext['options']) => App
48
51
 
49
- export type DefineApp<THostElement> = (rootComponent?: Component, options?: DefineOptions) => App<THostElement>
50
-
51
- export function defineApp<THostElement>(instance: RootRenderFunction<THostElement>): DefineApp<THostElement> {
52
- function createApp(
53
- rootComponent: Component,
54
- options: DefineOptions = {
55
- extension: { '.ts': '.ts' },
56
- dryRun: false,
57
- },
58
- ) {
52
+ export function defineApp<THostElement, TContext extends AppContext>(instance: RootRenderFunction<THostElement, TContext>): DefineApp<TContext> {
53
+ function createApp(rootComponent: Component, options?: TContext['options']): App {
59
54
  const installedPlugins = new WeakSet()
60
55
  const fileManager = new FileManager()
61
- const context: AppContext = {
56
+ const context = {
57
+ options,
62
58
  fileManager,
63
59
  async addFile(...newFiles) {
64
60
  await fileManager.add(...newFiles)
@@ -69,11 +65,11 @@ export function defineApp<THostElement>(instance: RootRenderFunction<THostElemen
69
65
  get files() {
70
66
  return fileManager.getFiles()
71
67
  },
72
- }
68
+ } as TContext
73
69
 
74
70
  const { render, renderToString, waitUntilExit } = instance.call(context, rootComponent, context)
75
71
 
76
- const app: App<THostElement> = {
72
+ const app: App = {
77
73
  _component: rootComponent,
78
74
  async render() {
79
75
  if (isPromise(render)) {
@@ -90,7 +86,12 @@ export function defineApp<THostElement>(instance: RootRenderFunction<THostElemen
90
86
  },
91
87
  waitUntilExit,
92
88
  addFile: context.addFile,
93
- async write() {
89
+ async write(
90
+ options = {
91
+ extension: { '.ts': '.ts' },
92
+ dryRun: false,
93
+ },
94
+ ) {
94
95
  await fileManager.processFiles({
95
96
  extension: options.extension,
96
97
  dryRun: options.dryRun,
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { createApp } from './createApp.ts'
2
- export type { DefineApp, AppContext } from './defineApp.ts'
3
2
  export { defineApp } from './defineApp.ts'
4
- export * as KubbFile from './types.ts'
3
+ export { FileManager } from './FileManager.ts'
4
+ export { parseFile } from './parsers/parser.ts'
@@ -1,4 +1,4 @@
1
- import type * as KubbFile from '../types.ts'
1
+ import type * as KubbFile from '../KubbFile.ts'
2
2
  import { typeScriptParser } from './typescript.ts'
3
3
  import { tsxParser } from './tsx.ts'
4
4
 
package/src/types.ts CHANGED
@@ -1,132 +1,2 @@
1
- type BasePath<T extends string = string> = `${T}/`
2
-
3
- export type Import = {
4
- /**
5
- * Import name to be used
6
- * @example ["useState"]
7
- * @example "React"
8
- */
9
- name:
10
- | string
11
- | Array<
12
- | string
13
- | {
14
- propertyName: string
15
- name?: string
16
- }
17
- >
18
- /**
19
- * Path for the import
20
- * @example '@kubb/core'
21
- */
22
- path: string
23
- /**
24
- * Add `type` prefix to the import, this will result in: `import type { Type } from './path'`.
25
- */
26
- isTypeOnly?: boolean
27
-
28
- isNameSpace?: boolean
29
- /**
30
- * When root is set it will get the path with relative getRelativePath(root, path).
31
- */
32
- root?: string
33
- }
34
-
35
- export type Source = {
36
- name?: string
37
- value?: string
38
- isTypeOnly?: boolean
39
- /**
40
- * Has const or type 'export'
41
- * @default false
42
- */
43
- isExportable?: boolean
44
- /**
45
- * When set, barrel generation will add this
46
- * @default false
47
- */
48
- isIndexable?: boolean
49
- }
50
-
51
- export type Export = {
52
- /**
53
- * Export name to be used.
54
- * @example ["useState"]
55
- * @example "React"
56
- */
57
- name?: string | Array<string>
58
- /**
59
- * Path for the import.
60
- * @example '@kubb/core'
61
- */
62
- path: string
63
- /**
64
- * Add `type` prefix to the export, this will result in: `export type { Type } from './path'`.
65
- */
66
- isTypeOnly?: boolean
67
- /**
68
- * Make it possible to override the name, this will result in: `export * as aliasName from './path'`.
69
- */
70
- asAlias?: boolean
71
- }
72
-
73
- export type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`
74
-
75
- export type Mode = 'single' | 'split'
76
-
77
- /**
78
- * Name to be used to dynamicly create the baseName(based on input.path)
79
- * Based on UNIX basename
80
- * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
81
- */
82
- export type BaseName = `${string}.${string}`
83
-
84
- /**
85
- * Path will be full qualified path to a specified file
86
- */
87
- export type Path = string
88
-
89
- export type AdvancedPath<T extends BaseName = BaseName> = `${BasePath}${T}`
90
-
91
- export type OptionalPath = Path | undefined | null
92
-
93
- export type File<TMeta extends object = object> = {
94
- /**
95
- * Name to be used to create the path
96
- * Based on UNIX basename, `${name}.extname`
97
- * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
98
- */
99
- baseName: BaseName
100
- /**
101
- * Path will be full qualified path to a specified file
102
- */
103
- path: AdvancedPath<BaseName> | Path
104
- sources: Array<Source>
105
- imports?: Array<Import>
106
- exports?: Array<Export>
107
- /**
108
- * Use extra meta, this is getting used to generate the barrel/index files.
109
- */
110
- meta?: TMeta
111
- banner?: string
112
- footer?: string
113
- }
114
-
115
- export type ResolvedImport = Import
116
-
117
- export type ResolvedExport = Export
118
-
119
- export type ResolvedFile<TMeta extends object = object> = File<TMeta> & {
120
- /**
121
- * @default hash
122
- */
123
- id: string
124
- /**
125
- * Contains the first part of the baseName, generated based on baseName
126
- * @link https://nodejs.org/api/path.html#pathformatpathobject
127
- */
128
- name: string
129
- extname: Extname
130
- imports: Array<ResolvedImport>
131
- exports: Array<ResolvedExport>
132
- }
1
+ export * as KubbFile from './KubbFile.ts'
2
+ export type { DefineApp, AppContext, App } from './defineApp.ts'
@@ -1,15 +0,0 @@
1
- import { i as ResolvedFile, t as Extname } from "./types-lS0JaZqX.cjs";
2
-
3
- //#region src/parsers/parser.d.ts
4
- type ParserModule<TMeta extends object = object> = {
5
- /**
6
- * Convert a file to string
7
- */
8
- print: (file: ResolvedFile<TMeta>, options: PrintOptions) => Promise<string>;
9
- };
10
- type PrintOptions = {
11
- extname?: Extname;
12
- };
13
- //#endregion
14
- export { ParserModule as t };
15
- //# sourceMappingURL=parser-Bck6QDwN.d.cts.map
@@ -1,15 +0,0 @@
1
- import { i as ResolvedFile, t as Extname } from "./types-BY5X8xoR.js";
2
-
3
- //#region src/parsers/parser.d.ts
4
- type ParserModule<TMeta extends object = object> = {
5
- /**
6
- * Convert a file to string
7
- */
8
- print: (file: ResolvedFile<TMeta>, options: PrintOptions) => Promise<string>;
9
- };
10
- type PrintOptions = {
11
- extname?: Extname;
12
- };
13
- //#endregion
14
- export { ParserModule as t };
15
- //# sourceMappingURL=parser-CRl-iUw1.d.ts.map