@kubb/core 0.8.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,412 @@
1
+ import path from 'path';
2
+ import fse2 from 'fs-extra';
3
+ import prettier from 'prettier';
4
+
5
+ // src/build.ts
6
+
7
+ // src/utils/Emitter.ts
8
+ var Emitter = class {
9
+ listeners = /* @__PURE__ */ new Set();
10
+ topics;
11
+ constructor(topics) {
12
+ this.topics = topics;
13
+ }
14
+ emit(...params) {
15
+ const isTopic = (value) => !!this.topics?.includes(value);
16
+ if (isTopic(params[0])) {
17
+ this.listeners.forEach((listener) => {
18
+ if (listener.topic === params[0]) {
19
+ listener.cb(params[1]);
20
+ }
21
+ });
22
+ return;
23
+ }
24
+ this.listeners.forEach((listener) => listener.cb(params[0]));
25
+ }
26
+ subscribe = (cb) => {
27
+ const listener = {
28
+ topic: void 0,
29
+ cb
30
+ };
31
+ this.listeners.add(listener);
32
+ return () => this.listeners.delete(listener);
33
+ };
34
+ on(topic, cb) {
35
+ this.listeners.add({
36
+ topic,
37
+ cb
38
+ });
39
+ }
40
+ destroy = () => this.listeners.clear();
41
+ };
42
+
43
+ // src/utils/FileEmitter.ts
44
+ var FileEmitter = class {
45
+ emitter;
46
+ filesByReferenceId = /* @__PURE__ */ new Map();
47
+ constructor(emitter = new Emitter(["delete", "done", "new"])) {
48
+ this.emitter = emitter;
49
+ }
50
+ emitFile(emitedFile) {
51
+ this.assignReferenceId(emitedFile, emitedFile.id);
52
+ return this.emitter.emit("new", emitedFile);
53
+ }
54
+ delete(fileReferenceId) {
55
+ this.filesByReferenceId.delete(fileReferenceId);
56
+ if (this.filesByReferenceId.size === 0) {
57
+ this.emitter.emit("done");
58
+ }
59
+ return this.emitter.emit("delete");
60
+ }
61
+ subscribe(...params) {
62
+ this.emitter.subscribe(...params);
63
+ }
64
+ on(...params) {
65
+ this.emitter.on(...params);
66
+ }
67
+ assignReferenceId(emittedFile, fileReferenceId) {
68
+ if (fileReferenceId) {
69
+ this.filesByReferenceId.set(fileReferenceId, emittedFile);
70
+ }
71
+ }
72
+ getEmittedFile = (fileReferenceId) => {
73
+ return this.filesByReferenceId.get(fileReferenceId);
74
+ };
75
+ getFileName = (fileReferenceId) => {
76
+ return this.filesByReferenceId.get(fileReferenceId)?.fileName;
77
+ };
78
+ };
79
+
80
+ // src/utils/cache.ts
81
+ function createPluginCache(cache) {
82
+ return {
83
+ delete(id) {
84
+ return delete cache[id];
85
+ },
86
+ get(id) {
87
+ const item = cache[id];
88
+ if (!item)
89
+ return;
90
+ item[0] = 0;
91
+ return item[1];
92
+ },
93
+ has(id) {
94
+ const item = cache[id];
95
+ if (!item)
96
+ return false;
97
+ item[0] = 0;
98
+ return true;
99
+ },
100
+ set(id, value) {
101
+ cache[id] = [0, value];
102
+ }
103
+ };
104
+ }
105
+
106
+ // src/context.ts
107
+ function getPluginContext(plugin, pluginCache) {
108
+ const cacheKey = plugin.cacheKey || plugin.name;
109
+ const cacheInstance = createPluginCache(pluginCache[cacheKey] || (pluginCache[cacheKey] = /* @__PURE__ */ Object.create(null)));
110
+ return {
111
+ cache: cacheInstance
112
+ };
113
+ }
114
+ function createPlugin(factory) {
115
+ return (userOptions) => {
116
+ const plugin = factory(userOptions);
117
+ if (Array.isArray(plugin)) {
118
+ throw new Error("Not implemented");
119
+ }
120
+ if (!plugin.transform) {
121
+ plugin.transform = function transform(code) {
122
+ return code;
123
+ };
124
+ }
125
+ return plugin;
126
+ };
127
+ }
128
+ var createCorePlugin = createPlugin((options) => {
129
+ const { fileEmitter, resolveId } = options;
130
+ const config = {
131
+ ...options.config,
132
+ root: options.config.root || process.cwd()
133
+ };
134
+ const schema = fse2.readFileSync(path.resolve(config.root, config.input.schema), "utf-8");
135
+ return {
136
+ name: "core",
137
+ api: {
138
+ get config() {
139
+ return config;
140
+ },
141
+ get schema() {
142
+ return schema;
143
+ },
144
+ getFileName: fileEmitter.getFileName.bind(fileEmitter),
145
+ getEmittedFile: fileEmitter.getEmittedFile.bind(fileEmitter),
146
+ emitFile: fileEmitter.emitFile.bind(fileEmitter),
147
+ resolveId
148
+ }
149
+ };
150
+ });
151
+
152
+ // src/utils/PluginDriver.ts
153
+ var hookNames = {
154
+ validate: 1,
155
+ buildStart: 1,
156
+ resolveId: 1,
157
+ load: 1,
158
+ transform: 1,
159
+ writeFile: 1,
160
+ buildEnd: 1
161
+ };
162
+ var hooks = Object.keys(hookNames);
163
+ var PluginDriver = class {
164
+ pluginContexts;
165
+ plugins;
166
+ fileEmitter;
167
+ logger;
168
+ config;
169
+ sortedPlugins = /* @__PURE__ */ new Map();
170
+ constructor(config, pluginCache, options) {
171
+ this.logger = options.logger;
172
+ this.config = config;
173
+ this.fileEmitter = new FileEmitter();
174
+ this.emitFile = this.fileEmitter.emitFile.bind(this.fileEmitter);
175
+ const corePlugin = createCorePlugin({ config, fileEmitter: this.fileEmitter, resolveId: this.resolveId });
176
+ this.plugins = [corePlugin, ...config.plugins || []];
177
+ const coreApi = corePlugin.api;
178
+ this.pluginContexts = new Map(
179
+ this.plugins.map((plugin) => {
180
+ const context = {
181
+ ...coreApi,
182
+ ...getPluginContext.call(this, plugin, pluginCache)
183
+ };
184
+ return [plugin, context];
185
+ })
186
+ );
187
+ }
188
+ get apis() {
189
+ return this.pluginContexts;
190
+ }
191
+ get api() {
192
+ let context = {};
193
+ this.pluginContexts.forEach((value) => {
194
+ context = { ...context, ...value };
195
+ });
196
+ return context;
197
+ }
198
+ emitFile(...params) {
199
+ return this.fileEmitter.emitFile(...params);
200
+ }
201
+ resolveId = (source, _importer) => {
202
+ return this.hookFirst("resolveId", [source, path.resolve(source)]);
203
+ };
204
+ hookFirst(hookName, parameters, skipped) {
205
+ let promise = Promise.resolve(null);
206
+ for (const plugin of this.getSortedPlugins(hookName)) {
207
+ if (skipped && skipped.has(plugin))
208
+ continue;
209
+ promise = promise.then((result) => {
210
+ if (result != null)
211
+ return result;
212
+ return this.runHook("hookFirst", hookName, parameters, plugin);
213
+ });
214
+ }
215
+ return promise;
216
+ }
217
+ async hookParallel(hookName, parameters) {
218
+ const parallelPromises = [];
219
+ for (const plugin of this.getSortedPlugins(hookName)) {
220
+ if (plugin[hookName]?.sequential) {
221
+ await Promise.all(parallelPromises);
222
+ parallelPromises.length = 0;
223
+ await this.runHook("hookParallel", hookName, parameters, plugin);
224
+ } else {
225
+ const promise = this.runHook("hookParallel", hookName, parameters, plugin);
226
+ parallelPromises.push(promise);
227
+ }
228
+ }
229
+ return Promise.all(parallelPromises);
230
+ }
231
+ hookReduceArg0(hookName, [argument0, ...rest], reduce) {
232
+ let promise = Promise.resolve(argument0);
233
+ for (const plugin of this.getSortedPlugins(hookName)) {
234
+ promise = promise.then(
235
+ (argument02) => this.runHook("hookReduceArg0", hookName, [argument02, ...rest], plugin).then(
236
+ (result) => reduce.call(this.api, argument02, result, plugin)
237
+ )
238
+ );
239
+ }
240
+ return promise;
241
+ }
242
+ hookSeq(hookName, parameters) {
243
+ let promise = Promise.resolve();
244
+ for (const plugin of this.getSortedPlugins(hookName)) {
245
+ promise = promise.then(() => this.runHook("hookSeq", hookName, parameters, plugin));
246
+ }
247
+ return promise.then(noReturn);
248
+ }
249
+ getSortedPlugins(_hookName) {
250
+ return [...this.plugins];
251
+ }
252
+ runHook(strategy, hookName, parameters, plugin) {
253
+ const hook = plugin[hookName];
254
+ return Promise.resolve().then(() => {
255
+ if (typeof hook !== "function") {
256
+ return hook;
257
+ }
258
+ if (this.config.logLevel === "info" && this.logger?.spinner) {
259
+ this.logger.spinner.text = `[${strategy}] ${hookName}: Excecuting task for plugin ${plugin.name}
260
+ `;
261
+ }
262
+ const hookResult = hook.apply(this.api, parameters);
263
+ if (!hookResult?.then) {
264
+ if (this.config.logLevel === "info" && this.logger?.spinner) {
265
+ this.logger.spinner.succeed(`[${strategy}] ${hookName}: Excecuting task for plugin ${plugin.name}
266
+ `);
267
+ }
268
+ return hookResult;
269
+ }
270
+ return Promise.resolve(hookResult).then((result) => {
271
+ if (this.config.logLevel === "info" && this.logger?.spinner) {
272
+ this.logger.spinner.succeed(`[${strategy}] ${hookName}: Excecuting task for plugin ${plugin.name}
273
+ `);
274
+ }
275
+ return result;
276
+ });
277
+ });
278
+ }
279
+ runHookSync(hookName, parameters, plugin) {
280
+ const hook = plugin[hookName];
281
+ try {
282
+ return hook.apply(this.api, parameters);
283
+ } catch (error) {
284
+ return error;
285
+ }
286
+ }
287
+ };
288
+ function noReturn() {
289
+ }
290
+
291
+ // src/build.ts
292
+ async function transformReducer(previousCode, result, _plugin) {
293
+ if (result === null) {
294
+ return null;
295
+ }
296
+ return result;
297
+ }
298
+ async function buildImplementation(options, done) {
299
+ const { config } = options;
300
+ if (config.lifeCycle && config.lifeCycle !== "plugins") {
301
+ throw new Error("Only lifeCycle plugins possible");
302
+ }
303
+ if (config.strategy && config.strategy !== "lifo") {
304
+ throw new Error("Only strategy fifo possible");
305
+ }
306
+ const pluginCache = /* @__PURE__ */ Object.create(null);
307
+ const pluginDriver = new PluginDriver(config, pluginCache, { logger: this.logger });
308
+ const validations = await pluginDriver.hookParallel("validate", [pluginDriver.plugins]);
309
+ const validationsWithMessage = validations.filter(Boolean);
310
+ if (validationsWithMessage.some((validation) => typeof validation !== "boolean")) {
311
+ validationsWithMessage.forEach((validation) => {
312
+ if (validation && typeof validation !== "boolean" && validation?.message) {
313
+ this.logger?.log(validation.message, "warn");
314
+ }
315
+ });
316
+ return;
317
+ }
318
+ pluginDriver.fileEmitter.on("new", async (emittedFile) => {
319
+ if (!emittedFile?.fileName) {
320
+ return;
321
+ }
322
+ const resolvedId = await pluginDriver.hookFirst("resolveId", [emittedFile.fileName, path.resolve(emittedFile.fileName)]);
323
+ const id = resolvedId || emittedFile.fileName;
324
+ await pluginDriver.hookParallel("load", [id]);
325
+ if (emittedFile.source) {
326
+ const result = await pluginDriver.hookReduceArg0("transform", [emittedFile.source, id], transformReducer);
327
+ await pluginDriver.hookParallel("writeFile", [result, id]);
328
+ pluginDriver.fileEmitter.delete(emittedFile.id);
329
+ }
330
+ });
331
+ await pluginDriver.hookParallel("buildStart");
332
+ pluginDriver.emitFile({
333
+ id: pluginDriver.api.config.root,
334
+ fileName: pluginDriver.api.config.root,
335
+ name: void 0,
336
+ source: pluginDriver.api.schema,
337
+ type: "asset"
338
+ });
339
+ pluginDriver.fileEmitter.on("done", async (d) => {
340
+ await pluginDriver.hookParallel("buildEnd");
341
+ done();
342
+ });
343
+ }
344
+ function build(config, env) {
345
+ return new Promise((resolve) => {
346
+ buildImplementation.call(
347
+ this,
348
+ {
349
+ config,
350
+ env
351
+ },
352
+ resolve
353
+ );
354
+ });
355
+ }
356
+
357
+ // src/config.ts
358
+ function defineConfig(config) {
359
+ return config;
360
+ }
361
+
362
+ // src/utils/isPromise.ts
363
+ var isPromise = (result) => {
364
+ return typeof result?.then === "function";
365
+ };
366
+
367
+ // src/utils/createQueue.ts
368
+ var createQueue = (arr, fun) => {
369
+ const promises = [];
370
+ arr?.forEach((item) => {
371
+ const result = fun(item);
372
+ if (isPromise(result)) {
373
+ promises.push(result);
374
+ } else {
375
+ promises.push(Promise.resolve(result));
376
+ }
377
+ });
378
+ return Promise.all(promises);
379
+ };
380
+
381
+ // src/utils/format.ts
382
+ var format = {
383
+ tabWidth: 2,
384
+ printWidth: 160,
385
+ parser: "typescript",
386
+ singleQuote: false,
387
+ semi: true,
388
+ bracketSameLine: false,
389
+ endOfLine: "auto"
390
+ };
391
+
392
+ // src/utils/write.ts
393
+ var write = async (data, path4, options = { format: false }) => {
394
+ const formattedData = options.format ? prettier.format(data, format) : data;
395
+ try {
396
+ await fse2.stat(path4);
397
+ const oldContent = await fse2.readFile(path4, { encoding: "utf-8" });
398
+ if (oldContent?.toString() === formattedData) {
399
+ return;
400
+ }
401
+ } catch (_err) {
402
+ return fse2.outputFile(path4, formattedData);
403
+ }
404
+ return fse2.outputFile(path4, formattedData);
405
+ };
406
+
407
+ // src/index.ts
408
+ var src_default = build;
409
+
410
+ export { Emitter, FileEmitter, PluginDriver, build, createPlugin, createPluginCache, createQueue, src_default as default, defineConfig, format, getPluginContext, hooks, isPromise, write };
411
+ //# sourceMappingURL=out.js.map
412
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/build.ts","../src/utils/PluginDriver.ts","../src/utils/Emitter.ts","../src/utils/FileEmitter.ts","../src/utils/cache.ts","../src/context.ts","../src/plugin.ts","../src/config.ts","../src/utils/isPromise.ts","../src/utils/createQueue.ts","../src/utils/write.ts","../src/utils/format.ts","../src/index.ts"],"names":["path","argument0","fse"],"mappings":";AAIA,OAAOA,WAAU;;;ACGjB,OAAOA,WAAU;;;ACLV,IAAM,UAAN,MAAmD;AAAA,EACvC,YAGZ,oBAAI,IAAI;AAAA,EAEI;AAAA,EAEjB,YAAY,QAAoB;AAC9B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,QAAQ,QAA6D;AACnE,UAAM,UAAU,CAAC,UAAiC,CAAC,CAAC,KAAK,QAAQ,SAAS,KAAK;AAE/E,QAAI,QAAQ,OAAO,EAAE,GAAG;AACtB,WAAK,UAAU,QAAQ,CAAC,aAAa;AACnC,YAAI,SAAS,UAAU,OAAO,IAAI;AAChC,mBAAS,GAAG,OAAO,EAAE;AAAA,QACvB;AAAA,MACF,CAAC;AACD;AAAA,IACF;AACA,SAAK,UAAU,QAAQ,CAAC,aAAa,SAAS,GAAG,OAAO,EAAY,CAAC;AAAA,EACvE;AAAA,EAEA,YAAkD,CAAC,OAAO;AACxD,UAAM,WAAW;AAAA,MACf,OAAO;AAAA,MACP;AAAA,IACF;AACA,SAAK,UAAU,IAAI,QAAQ;AAE3B,WAAO,MAAM,KAAK,UAAU,OAAO,QAAQ;AAAA,EAC7C;AAAA,EAEA,GAAG,OAAgB,IAAsB;AACvC,SAAK,UAAU,IAAI;AAAA,MACjB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,UAAsB,MAAM,KAAK,UAAU,MAAM;AACnD;;;ACjCO,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EAEA,qBAA+C,oBAAI,IAAI;AAAA,EAExE,YAAY,UAAwC,IAAI,QAA6B,CAAC,UAAU,QAAQ,KAAK,CAAC,GAAG;AAC/G,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,SAAS,YAAyB;AAEhC,SAAK,kBAAkB,YAAY,WAAW,EAAE;AAChD,WAAO,KAAK,QAAQ,KAAK,OAAO,UAAU;AAAA,EAC5C;AAAA,EAEA,OAAO,iBAAyB;AAC9B,SAAK,mBAAmB,OAAO,eAAe;AAC9C,QAAI,KAAK,mBAAmB,SAAS,GAAG;AACtC,WAAK,QAAQ,KAAK,MAAM;AAAA,IAC1B;AACA,WAAO,KAAK,QAAQ,KAAK,QAAQ;AAAA,EACnC;AAAA,EAEA,aAAa,QAAsD;AACjE,SAAK,QAAQ,UAAU,GAAG,MAAM;AAAA,EAClC;AAAA,EAEA,MAAM,QAA+C;AACnD,SAAK,QAAQ,GAAG,GAAG,MAAM;AAAA,EAC3B;AAAA,EAEQ,kBAAkB,aAA0B,iBAAqC;AACvF,QAAI,iBAAiB;AACnB,WAAK,mBAAmB,IAAI,iBAAiB,WAAW;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,iBAAiB,CAAC,oBAAqD;AACrE,WAAO,KAAK,mBAAmB,IAAI,eAAe;AAAA,EACpD;AAAA,EAEA,cAAc,CAAC,oBAAgD;AAC7D,WAAO,KAAK,mBAAmB,IAAI,eAAe,GAAG;AAAA,EACvD;AACF;;;AC5CO,SAAS,kBAAkB,OAAuC;AACvE,SAAO;AAAA,IACL,OAAO,IAAY;AACjB,aAAO,OAAO,MAAM;AAAA,IACtB;AAAA,IACA,IAAI,IAAY;AACd,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC;AAAM;AACX,WAAK,KAAK;AACV,aAAO,KAAK;AAAA,IACd;AAAA,IACA,IAAI,IAAY;AACd,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC;AAAM,eAAO;AAClB,WAAK,KAAK;AACV,aAAO;AAAA,IACT;AAAA,IACA,IAAI,IAAY,OAAY;AAC1B,YAAM,MAAM,CAAC,GAAG,KAAK;AAAA,IACvB;AAAA,EACF;AACF;;;AC3BO,SAAS,iBAAqC,QAAgB,aAA6D;AAChI,QAAM,WAAW,OAAO,YAAa,OAAO;AAE5C,QAAM,gBAAgB,kBAAkB,YAAY,cAAc,YAAY,YAAY,uBAAO,OAAO,IAAI,EAAE;AAE9G,SAAO;AAAA,IACL,OAAO;AAAA,EACT;AACF;;;ACbA,OAAO,UAAU;AACjB,OAAO,SAAS;AAuBT,SAAS,aAA6D,SAAkC;AAC7G,SAAO,CAAC,gBAAyC;AAC/C,UAAM,SAAS,QAAQ,WAAW;AAClC,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AAGA,QAAI,CAAC,OAAO,WAAW;AACrB,aAAO,YAAY,SAAS,UAAU,MAAM;AAC1C,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AAWO,IAAM,mBAAmB,aAAgC,CAAC,YAAY;AAC3E,QAAM,EAAE,aAAa,UAAU,IAAI;AACnC,QAAM,SAAS;AAAA,IACb,GAAG,QAAQ;AAAA,IACX,MAAM,QAAQ,OAAO,QAAQ,QAAQ,IAAI;AAAA,EAC3C;AACA,QAAM,SAAS,IAAI,aAAa,KAAK,QAAQ,OAAO,MAAM,OAAO,MAAM,MAAM,GAAG,OAAO;AAEvF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,MACH,IAAI,SAAS;AACX,eAAO;AAAA,MACT;AAAA,MACA,IAAI,SAAS;AACX,eAAO;AAAA,MACT;AAAA,MACA,aAAa,YAAY,YAAY,KAAK,WAAW;AAAA,MACrD,gBAAgB,YAAY,eAAe,KAAK,WAAW;AAAA,MAC3D,UAAU,YAAY,SAAS,KAAK,WAAW;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;AL/CD,IAAM,YAEF;AAAA,EACF,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,MAAM;AAAA,EACN,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AACZ;AACO,IAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EAEV;AAAA,EAES;AAAA,EAEC;AAAA,EAEA;AAAA,EAEA,gBAAgB,oBAAI,IAAoC;AAAA,EAEzE,YAAY,QAAoB,aAAkE,SAA6C;AAC7I,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS;AAEd,SAAK,cAAc,IAAI,YAAY;AAEnC,SAAK,WAAW,KAAK,YAAY,SAAS,KAAK,KAAK,WAAW;AAE/D,UAAM,aAAa,iBAAiB,EAAE,QAAQ,aAAa,KAAK,aAAa,WAAW,KAAK,UAAU,CAAC;AACxG,SAAK,UAAU,CAAC,YAAY,GAAI,OAAO,WAAW,CAAC,CAAE;AACrD,UAAM,UAAU,WAAW;AAC3B,SAAK,iBAAiB,IAAI;AAAA,MACxB,KAAK,QAAQ,IAAI,CAAC,WAAW;AAC3B,cAAM,UAAU;AAAA,UACd,GAAG;AAAA,UACH,GAAG,iBAAiB,KAAK,MAAM,QAAQ,WAAW;AAAA,QACpD;AACA,eAAO,CAAC,QAAQ,OAAO;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,MAAM;AACR,QAAI,UAAU,CAAC;AACf,SAAK,eAAe,QAAQ,CAAC,UAAU;AACrC,gBAAU,EAAE,GAAG,SAAS,GAAG,MAAM;AAAA,IACnC,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,QAA6C;AACvD,WAAO,KAAK,YAAY,SAAS,GAAG,MAAM;AAAA,EAC5C;AAAA,EAEA,YAAY,CAAC,QAAgB,cAAkC;AAC7D,WAAO,KAAK,UAAU,aAAa,CAAC,QAAQA,MAAK,QAAQ,MAAM,CAAC,CAAC;AAAA,EACnE;AAAA,EAGA,UACE,UACA,YACA,SACgD;AAChD,QAAI,UAA0D,QAAQ,QAAQ,IAAI;AAClF,eAAW,UAAU,KAAK,iBAAiB,QAAQ,GAAG;AACpD,UAAI,WAAW,QAAQ,IAAI,MAAM;AAAG;AACpC,gBAAU,QAAQ,KAAK,CAAC,WAAW;AACjC,YAAI,UAAU;AAAM,iBAAO;AAC3B,eAAO,KAAK,QAAQ,aAAa,UAAU,YAAY,MAAM;AAAA,MAC/D,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAGA,MAAM,aAA4D,UAAa,YAAyD;AACtI,UAAM,mBAAsC,CAAC;AAE7C,eAAW,UAAU,KAAK,iBAAiB,QAAQ,GAAG;AACpD,UAAK,OAAO,WAAwC,YAAY;AAC9D,cAAM,QAAQ,IAAI,gBAAgB;AAClC,yBAAiB,SAAS;AAC1B,cAAM,KAAK,QAAQ,gBAAgB,UAAU,YAAY,MAAM;AAAA,MACjE,OAAO;AACL,cAAM,UAA2B,KAAK,QAAQ,gBAAgB,UAAU,YAAY,MAAM;AAE1F,yBAAiB,KAAK,OAAO;AAAA,MAC/B;AAAA,IACF;AACA,WAAO,QAAQ,IAAI,gBAAgB;AAAA,EACrC;AAAA,EAGA,eACE,UACA,CAAC,cAAc,IAAI,GACnB,QACuB;AACvB,QAAI,UAAU,QAAQ,QAAQ,SAAS;AACvC,eAAW,UAAU,KAAK,iBAAiB,QAAQ,GAAG;AACpD,gBAAU,QAAQ;AAAA,QAAK,CAACC,eACtB,KAAK,QAAQ,kBAAkB,UAAU,CAACA,YAAW,GAAG,IAAI,GAAqC,MAAM,EAAE;AAAA,UAAK,CAAC,WAC7G,OAAO,KAAK,KAAK,KAAKA,YAAW,QAAQ,MAAM;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAIA,QAAwC,UAAa,YAA6C;AAChG,QAAI,UAAyB,QAAQ,QAAQ;AAC7C,eAAW,UAAU,KAAK,iBAAiB,QAAQ,GAAG;AACpD,gBAAU,QAAQ,KAAK,MAAM,KAAK,QAAQ,WAAW,UAAU,YAAY,MAAM,CAAC;AAAA,IACpF;AACA,WAAO,QAAQ,KAAK,QAAQ;AAAA,EAC9B;AAAA,EAEQ,iBAAiB,WAA4C;AACnE,WAAO,CAAC,GAAG,KAAK,OAAO;AAAA,EACzB;AAAA,EASQ,QACN,UACA,UACA,YACA,QACkB;AAElB,UAAM,OAAO,OAAO;AAGpB,WAAO,QAAQ,QAAQ,EAAE,KAAK,MAAM;AAClC,UAAI,OAAO,SAAS,YAAY;AAC9B,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,OAAO,aAAa,UAAU,KAAK,QAAQ,SAAS;AAC3D,aAAK,OAAO,QAAQ,OAAO,IAAI,aAAa,wCAAwC,OAAO;AAAA;AAAA,MAC7F;AAEA,YAAM,aAAc,KAAa,MAAM,KAAK,KAAK,UAAU;AAE3D,UAAI,CAAC,YAAY,MAAM;AAErB,YAAI,KAAK,OAAO,aAAa,UAAU,KAAK,QAAQ,SAAS;AAC3D,eAAK,OAAO,QAAQ,QAAQ,IAAI,aAAa,wCAAwC,OAAO;AAAA,CAAS;AAAA,QACvG;AACA,eAAO;AAAA,MACT;AAEA,aAAO,QAAQ,QAAQ,UAAU,EAAE,KAAK,CAAC,WAAW;AAElD,YAAI,KAAK,OAAO,aAAa,UAAU,KAAK,QAAQ,SAAS;AAC3D,eAAK,OAAO,QAAQ,QAAQ,IAAI,aAAa,wCAAwC,OAAO;AAAA,CAAS;AAAA,QACvG;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EASQ,YAA4C,UAAa,YAA4C,QAAgD;AAC3J,UAAM,OAAO,OAAO;AAIpB,QAAI;AAEF,aAAQ,KAAkB,MAAM,KAAK,KAAK,UAAU;AAAA,IACtD,SAAS,OAAP;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,SAAS,WAAW;AAAC;;;ADvMrB,eAAe,iBAAsC,cAAsB,QAAyB,SAAiB;AACnH,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOA,eAAe,oBAAwC,SAAqC,MAAqC;AAC/H,QAAM,EAAE,OAAO,IAAI;AACnB,MAAI,OAAO,aAAa,OAAO,cAAc,WAAW;AACtD,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,MAAI,OAAO,YAAY,OAAO,aAAa,QAAQ;AACjD,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAEA,QAAM,cAAc,uBAAO,OAAO,IAAI;AACtC,QAAM,eAAe,IAAI,aAAa,QAAQ,aAAa,EAAE,QAAQ,KAAK,OAAO,CAAC;AAElF,QAAM,cAAc,MAAM,aAAa,aAA2C,YAAY,CAAC,aAAa,OAAO,CAAC;AAEpH,QAAM,yBAAyB,YAAY,OAAO,OAAO;AAEzD,MAAI,uBAAuB,KAAK,CAAC,eAAe,OAAO,eAAe,SAAS,GAAG;AAChF,2BAAuB,QAAQ,CAAC,eAAe;AAC7C,UAAI,cAAc,OAAO,eAAe,aAAa,YAAY,SAAS;AACxE,aAAK,QAAQ,IAAI,WAAW,SAAS,MAAM;AAAA,MAC7C;AAAA,IACF,CAAC;AAED;AAAA,EACF;AAEA,eAAa,YAAY,GAAG,OAAO,OAAO,gBAAgB;AACxD,QAAI,CAAC,aAAa,UAAU;AAC1B;AAAA,IACF;AAEA,UAAM,aAAa,MAAM,aAAa,UAAU,aAAa,CAAC,YAAY,UAAUD,MAAK,QAAQ,YAAY,QAAQ,CAAC,CAAC;AACvH,UAAM,KAAK,cAAc,YAAY;AAErC,UAAM,aAAa,aAAa,QAAQ,CAAC,EAAE,CAAC;AAE5C,QAAI,YAAY,QAAQ;AACtB,YAAM,SAAS,MAAM,aAAa,eAAe,aAAa,CAAC,YAAY,QAAQ,EAAE,GAAG,gBAAgB;AAExG,YAAM,aAAa,aAAa,aAAa,CAAC,QAAQ,EAAE,CAAC;AACzD,mBAAa,YAAY,OAAO,YAAY,EAAE;AAAA,IAChD;AAAA,EACF,CAAC;AAED,QAAM,aAAa,aAAa,YAAY;AAE5C,eAAa,SAAS;AAAA,IACpB,IAAI,aAAa,IAAI,OAAO;AAAA,IAC5B,UAAU,aAAa,IAAI,OAAO;AAAA,IAClC,MAAM;AAAA,IACN,QAAQ,aAAa,IAAI;AAAA,IACzB,MAAM;AAAA,EACR,CAAC;AAED,eAAa,YAAY,GAAG,QAAQ,OAAO,MAAM;AAC/C,UAAM,aAAa,aAAa,UAAU;AAC1C,SAAK;AAAA,EACP,CAAC;AACH;AAEO,SAAS,MAA0B,QAAoB,KAAsC;AAClG,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,wBAAoB;AAAA,MAClB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AOlEO,SAAS,aAAa,QAA4C;AACvE,SAAO;AACT;;;AClDO,IAAM,YAAY,CAAI,WAAiD;AAC5E,SAAO,OAAQ,QAAgB,SAAS;AAC1C;;;ACAO,IAAM,cAAc,CACzB,KACA,QACG;AACH,QAAM,WAA8B,CAAC;AAErC,OAAK,QAAQ,CAAC,SAAS;AACrB,UAAM,SAAS,IAAI,IAAI;AACvB,QAAI,UAAkB,MAAM,GAAG;AAC7B,eAAS,KAAK,MAAM;AAAA,IACtB,OAAO;AACL,eAAS,KAAK,QAAQ,QAAQ,MAAM,CAAC;AAAA,IACvC;AAAA,EACF,CAAC;AAED,SAAO,QAAQ,IAAI,QAAQ;AAC7B;;;ACnBA,OAAOE,UAAS;AAChB,OAAO,cAAc;;;ACAd,IAAM,SAAkB;AAAA,EAC7B,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AACb;;;ADAO,IAAM,QAAQ,OAAO,MAAcF,OAAc,UAAwB,EAAE,QAAQ,MAAM,MAAM;AACpG,QAAM,gBAAgB,QAAQ,SAAS,SAAS,OAAO,MAAM,MAAM,IAAI;AAEvE,MAAI;AACF,UAAME,KAAI,KAAKF,KAAI;AACnB,UAAM,aAAa,MAAME,KAAI,SAASF,OAAM,EAAE,UAAU,QAAQ,CAAC;AACjE,QAAI,YAAY,SAAS,MAAM,eAAe;AAC5C;AAAA,IACF;AAAA,EACF,SAAS,MAAP;AACA,WAAOE,KAAI,WAAWF,OAAM,aAAa;AAAA,EAC3C;AAEA,SAAOE,KAAI,WAAWF,OAAM,aAAa;AAC3C;;;AEdA,IAAO,cAAQ","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-empty-function */\n/* eslint-disable no-console */\n\nimport path from 'path'\n\nimport { PluginDriver } from './utils/PluginDriver'\n\nimport type { PluginContext, TransformResult, ValidationResult } from './types'\nimport type { UserConfig, ConfigEnv } from './config'\nimport type { LogLevel } from './utils/logger'\nimport type { Plugin } from './plugin'\n\ntype BuildOutput = void\n\n// Same type as ora\ntype Spinner = {\n start: (text?: string) => Spinner\n succeed: (text: string) => Spinner\n stopAndPersist: (options: { text: string }) => Spinner\n render: () => Spinner\n text: string\n info: (text: string) => Spinner\n}\n\nexport type BuildContext = {\n logger?: {\n log: (message: string, logLevel: LogLevel) => void\n spinner?: Spinner\n }\n}\n\nasync function transformReducer(this: PluginContext, previousCode: string, result: TransformResult, _plugin: Plugin) {\n if (result === null) {\n return null\n }\n return result\n}\n\ntype BuildImplementationOptions = {\n config: UserConfig\n env: ConfigEnv\n}\n\nasync function buildImplementation(this: BuildContext, options: BuildImplementationOptions, done: (output: BuildOutput) => void) {\n const { config } = options\n if (config.lifeCycle && config.lifeCycle !== 'plugins') {\n throw new Error('Only lifeCycle plugins possible')\n }\n\n if (config.strategy && config.strategy !== 'lifo') {\n throw new Error('Only strategy fifo possible')\n }\n\n const pluginCache = Object.create(null)\n const pluginDriver = new PluginDriver(config, pluginCache, { logger: this.logger })\n\n const validations = await pluginDriver.hookParallel<'validate', ValidationResult>('validate', [pluginDriver.plugins])\n\n const validationsWithMessage = validations.filter(Boolean)\n\n if (validationsWithMessage.some((validation) => typeof validation !== 'boolean')) {\n validationsWithMessage.forEach((validation) => {\n if (validation && typeof validation !== 'boolean' && validation?.message) {\n this.logger?.log(validation.message, 'warn')\n }\n })\n\n return\n }\n\n pluginDriver.fileEmitter.on('new', async (emittedFile) => {\n if (!emittedFile?.fileName) {\n return\n }\n\n const resolvedId = await pluginDriver.hookFirst('resolveId', [emittedFile.fileName, path.resolve(emittedFile.fileName)])\n const id = resolvedId || emittedFile.fileName\n\n await pluginDriver.hookParallel('load', [id])\n\n if (emittedFile.source) {\n const result = await pluginDriver.hookReduceArg0('transform', [emittedFile.source, id], transformReducer)\n\n await pluginDriver.hookParallel('writeFile', [result, id])\n pluginDriver.fileEmitter.delete(emittedFile.id)\n }\n })\n\n await pluginDriver.hookParallel('buildStart')\n\n pluginDriver.emitFile({\n id: pluginDriver.api.config.root,\n fileName: pluginDriver.api.config.root,\n name: undefined,\n source: pluginDriver.api.schema,\n type: 'asset',\n })\n\n pluginDriver.fileEmitter.on('done', async (d) => {\n await pluginDriver.hookParallel('buildEnd')\n done()\n })\n}\n\nexport function build(this: BuildContext, config: UserConfig, env: ConfigEnv): Promise<BuildOutput> {\n return new Promise((resolve) => {\n buildImplementation.call(\n this,\n {\n config,\n env,\n },\n resolve\n )\n })\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable no-restricted-syntax */\n/* eslint-disable no-await-in-loop */\n/* eslint-disable no-undef */\n// inspired by: https://github.com/rollup/rollup/blob/master/src/utils/PluginDriver.ts#\n\nimport path from 'path'\n\nimport { FileEmitter } from './FileEmitter'\n\nimport { getPluginContext } from '../context'\nimport { createCorePlugin } from '../plugin'\n\nimport type { BuildContext } from '../build'\nimport type { SerializablePluginCache } from './cache'\nimport type { Plugin } from '../plugin'\nimport type { UserConfig } from '../config'\nimport type { PluginLifecycleHooks, PluginLifecycle, WithPromise, PluginContext } from '../types'\n\n/**\n * Get the type of the first argument in a function.\n * @example Arg0<(a: string, b: number) => void> -> string\n */\nexport type Argument0<H extends keyof PluginLifecycle> = Parameters<PluginLifecycle[H]>[0]\n\ntype Strategy = 'hookFirst' | 'hookParallel' | 'hookReduceArg0' | 'hookSeq'\n\n// This will make sure no input hook is omitted\nconst hookNames: {\n [P in PluginLifecycleHooks]: 1\n} = {\n validate: 1,\n buildStart: 1,\n resolveId: 1,\n load: 1,\n transform: 1,\n writeFile: 1,\n buildEnd: 1,\n}\nexport const hooks = Object.keys(hookNames) as [PluginLifecycleHooks]\n\nexport class PluginDriver {\n private readonly pluginContexts: ReadonlyMap<Plugin, PluginContext>\n\n public plugins: Plugin[]\n\n public readonly fileEmitter: FileEmitter\n\n private readonly logger?: BuildContext['logger']\n\n private readonly config: UserConfig\n\n private readonly sortedPlugins = new Map<PluginLifecycleHooks, Plugin[]>()\n\n constructor(config: UserConfig, pluginCache: Record<string, SerializablePluginCache> | undefined, options: { logger: BuildContext['logger'] }) {\n this.logger = options.logger\n this.config = config\n\n this.fileEmitter = new FileEmitter()\n\n this.emitFile = this.fileEmitter.emitFile.bind(this.fileEmitter)\n\n const corePlugin = createCorePlugin({ config, fileEmitter: this.fileEmitter, resolveId: this.resolveId })\n this.plugins = [corePlugin, ...(config.plugins || [])]\n const coreApi = corePlugin.api\n this.pluginContexts = new Map(\n this.plugins.map((plugin) => {\n const context = {\n ...coreApi,\n ...getPluginContext.call(this, plugin, pluginCache),\n }\n return [plugin, context]\n })\n )\n }\n\n get apis() {\n return this.pluginContexts\n }\n\n get api() {\n let context = {}\n this.pluginContexts.forEach((value) => {\n context = { ...context, ...value }\n })\n return context as PluginContext\n }\n\n emitFile(...params: Parameters<FileEmitter['emitFile']>) {\n return this.fileEmitter.emitFile(...params)\n }\n\n resolveId = (source: string, _importer: string | undefined) => {\n return this.hookFirst('resolveId', [source, path.resolve(source)])\n }\n\n // chains, first non-null result stops and returns\n hookFirst<H extends PluginLifecycleHooks>(\n hookName: H,\n parameters: Parameters<PluginLifecycle[H]>,\n skipped?: ReadonlySet<Plugin> | null\n ): Promise<ReturnType<PluginLifecycle[H]> | null> {\n let promise: Promise<ReturnType<PluginLifecycle[H]> | null> = Promise.resolve(null)\n for (const plugin of this.getSortedPlugins(hookName)) {\n if (skipped && skipped.has(plugin)) continue\n promise = promise.then((result) => {\n if (result != null) return result\n return this.runHook('hookFirst', hookName, parameters, plugin) as any\n })\n }\n return promise\n }\n\n // parallel\n async hookParallel<H extends PluginLifecycleHooks, TOuput = void>(hookName: H, parameters?: Parameters<PluginLifecycle[H]> | undefined) {\n const parallelPromises: Promise<TOuput>[] = []\n\n for (const plugin of this.getSortedPlugins(hookName)) {\n if ((plugin[hookName] as { sequential?: boolean })?.sequential) {\n await Promise.all(parallelPromises)\n parallelPromises.length = 0\n await this.runHook('hookParallel', hookName, parameters, plugin)\n } else {\n const promise: Promise<TOuput> = this.runHook('hookParallel', hookName, parameters, plugin)\n\n parallelPromises.push(promise)\n }\n }\n return Promise.all(parallelPromises)\n }\n\n // chains, reduces returned value, handling the reduced value as the first hook argument\n hookReduceArg0<H extends PluginLifecycleHooks>(\n hookName: H,\n [argument0, ...rest]: Parameters<PluginLifecycle[H]>,\n reduce: (reduction: Argument0<H>, result: ReturnType<PluginLifecycle[H]>, plugin: Plugin) => WithPromise<Argument0<H> | null>\n ): Promise<Argument0<H>> {\n let promise = Promise.resolve(argument0)\n for (const plugin of this.getSortedPlugins(hookName)) {\n promise = promise.then((argument0) =>\n this.runHook('hookReduceArg0', hookName, [argument0, ...rest] as Parameters<PluginLifecycle[H]>, plugin).then((result) =>\n reduce.call(this.api, argument0, result, plugin)\n )\n )\n }\n return promise\n }\n\n // chains\n\n hookSeq<H extends PluginLifecycleHooks>(hookName: H, parameters?: Parameters<PluginLifecycle[H]>) {\n let promise: Promise<void> = Promise.resolve()\n for (const plugin of this.getSortedPlugins(hookName)) {\n promise = promise.then(() => this.runHook('hookSeq', hookName, parameters, plugin))\n }\n return promise.then(noReturn)\n }\n\n private getSortedPlugins(_hookName: keyof PluginLifecycle): Plugin[] {\n return [...this.plugins]\n }\n\n /**\n * Run an async plugin hook and return the result.\n * @param hookName Name of the plugin hook. Must be either in `PluginHooks` or `OutputPluginValueHooks`.\n * @param args Arguments passed to the plugin hook.\n * @param plugin The actual pluginObject to run.\n */\n // Implementation signature\n private runHook<H extends PluginLifecycleHooks, TResult = void>(\n strategy: Strategy,\n hookName: H,\n parameters: unknown[] | undefined,\n plugin: Plugin\n ): Promise<TResult> {\n // We always filter for plugins that support the hook before running it\n const hook = plugin[hookName]!\n // const context = this.pluginContexts.get(plugin) || {};\n\n return Promise.resolve().then(() => {\n if (typeof hook !== 'function') {\n return hook\n }\n\n if (this.config.logLevel === 'info' && this.logger?.spinner) {\n this.logger.spinner.text = `[${strategy}] ${hookName}: Excecuting task for plugin ${plugin.name} \\n`\n }\n\n const hookResult = (hook as any).apply(this.api, parameters)\n\n if (!hookResult?.then) {\n // short circuit for non-thenables and non-Promises\n if (this.config.logLevel === 'info' && this.logger?.spinner) {\n this.logger.spinner.succeed(`[${strategy}] ${hookName}: Excecuting task for plugin ${plugin.name} \\n`)\n }\n return hookResult\n }\n\n return Promise.resolve(hookResult).then((result) => {\n // action was fulfilled\n if (this.config.logLevel === 'info' && this.logger?.spinner) {\n this.logger.spinner.succeed(`[${strategy}] ${hookName}: Excecuting task for plugin ${plugin.name} \\n`)\n }\n return result\n })\n })\n }\n\n /**\n * Run a sync plugin hook and return the result.\n * @param hookName Name of the plugin hook. Must be in `PluginHooks`.\n * @param args Arguments passed to the plugin hook.\n * @param plugin The acutal plugin\n * @param replaceContext When passed, the plugin context can be overridden.\n */\n private runHookSync<H extends PluginLifecycleHooks>(hookName: H, parameters: Parameters<PluginLifecycle[H]>, plugin: Plugin): ReturnType<PluginLifecycle[H]> {\n const hook = plugin[hookName]!\n\n // const context = this.pluginContexts.get(plugin)!;\n\n try {\n // eslint-disable-next-line @typescript-eslint/ban-types\n return (hook as Function).apply(this.api, parameters)\n } catch (error: any) {\n return error\n }\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noReturn() {}\n","export type Listener<T> = (value?: T) => void\n\nexport class Emitter<TValue = unknown, TTopics = unknown> {\n private readonly listeners: Set<{\n topic?: TTopics\n cb: Listener<TValue>\n }> = new Set()\n\n private readonly topics?: TTopics[]\n\n constructor(topics?: TTopics[]) {\n this.topics = topics\n }\n\n emit(...params: [topic: TTopics, value?: TValue] | [value?: TValue]) {\n const isTopic = (value: any): value is TTopics => !!this.topics?.includes(value)\n\n if (isTopic(params[0])) {\n this.listeners.forEach((listener) => {\n if (listener.topic === params[0]) {\n listener.cb(params[1])\n }\n })\n return\n }\n this.listeners.forEach((listener) => listener.cb(params[0] as TValue))\n }\n\n subscribe: (cb: Listener<TValue>) => () => void = (cb) => {\n const listener = {\n topic: undefined,\n cb,\n }\n this.listeners.add(listener)\n // Unsubscribe\n return () => this.listeners.delete(listener)\n }\n\n on(topic: TTopics, cb: Listener<TValue>) {\n this.listeners.add({\n topic,\n cb,\n })\n }\n\n destroy: () => void = () => this.listeners.clear()\n}\n","import { Emitter } from './Emitter'\n\nexport interface EmittedFile {\n id: string\n fileName: string | undefined\n name: string | undefined\n source: string | undefined\n type: 'asset'\n}\n\nexport type EmitFile = (emittedFile: EmittedFile) => void\n\ntype Topics = 'new' | 'delete' | 'done'\nexport class FileEmitter {\n private readonly emitter: Emitter<EmittedFile, Topics>\n\n private readonly filesByReferenceId: Map<string, EmittedFile> = new Map()\n\n constructor(emitter: Emitter<EmittedFile, Topics> = new Emitter<EmittedFile, Topics>(['delete', 'done', 'new'])) {\n this.emitter = emitter\n }\n\n emitFile(emitedFile: EmittedFile) {\n // save locally in this class\n this.assignReferenceId(emitedFile, emitedFile.id)\n return this.emitter.emit('new', emitedFile)\n }\n\n delete(fileReferenceId: string) {\n this.filesByReferenceId.delete(fileReferenceId)\n if (this.filesByReferenceId.size === 0) {\n this.emitter.emit('done')\n }\n return this.emitter.emit('delete')\n }\n\n subscribe(...params: Parameters<typeof this.emitter['subscribe']>) {\n this.emitter.subscribe(...params)\n }\n\n on(...params: Parameters<typeof this.emitter['on']>) {\n this.emitter.on(...params)\n }\n\n private assignReferenceId(emittedFile: EmittedFile, fileReferenceId: string | undefined) {\n if (fileReferenceId) {\n this.filesByReferenceId.set(fileReferenceId, emittedFile)\n }\n }\n\n getEmittedFile = (fileReferenceId: string): EmittedFile | undefined => {\n return this.filesByReferenceId.get(fileReferenceId)\n }\n\n getFileName = (fileReferenceId: string): string | undefined => {\n return this.filesByReferenceId.get(fileReferenceId)?.fileName\n }\n}\n","/* eslint-disable no-param-reassign */\n/* eslint-disable consistent-return */\nexport interface SerializablePluginCache {\n [key: string]: [number, any]\n}\n\nexport interface Cache<TCache = any> {\n delete(id: string): boolean\n get<T = TCache>(id: string): T\n has(id: string): boolean\n set<T = TCache>(id: string, value: T): void\n}\n\nexport function createPluginCache(cache: SerializablePluginCache): Cache {\n return {\n delete(id: string) {\n return delete cache[id]\n },\n get(id: string) {\n const item = cache[id]\n if (!item) return\n item[0] = 0\n return item[1]\n },\n has(id: string) {\n const item = cache[id]\n if (!item) return false\n item[0] = 0\n return true\n },\n set(id: string, value: any) {\n cache[id] = [0, value]\n },\n }\n}\n","/* eslint-disable no-param-reassign */\nimport { createPluginCache } from './utils/cache'\n\nimport type { PluginDriver } from './utils/PluginDriver'\nimport type { SerializablePluginCache } from './utils/cache'\nimport type { Plugin } from './plugin'\n\nexport function getPluginContext(this: PluginDriver, plugin: Plugin, pluginCache: Record<string, SerializablePluginCache> | void) {\n const cacheKey = plugin.cacheKey || (plugin.name as string)\n\n const cacheInstance = createPluginCache(pluginCache[cacheKey] || (pluginCache[cacheKey] = Object.create(null)))\n\n return {\n cache: cacheInstance,\n }\n}\n","/* eslint-disable no-console */\n\nimport path from 'path'\nimport fse from 'fs-extra'\n\nimport type { FileEmitter } from './utils'\nimport type { PluginLifecycle, PluginName, Api } from './types'\nimport type { UserConfig } from './config'\n\n// use of type objects\nexport type PluginOptions<UserOptions = unknown, Nested extends boolean = false, Api = any> = {\n userOptions: UserOptions\n nested: Nested\n api: Api\n}\n\nexport type Plugin<TOptions extends PluginOptions = PluginOptions> = {\n name: PluginName | Omit<string, PluginName>\n cacheKey?: string\n api?: TOptions['api']\n} & Partial<PluginLifecycle>\n\nexport type PluginFactory<TOptions extends PluginOptions = PluginOptions> = (\n options: TOptions['userOptions']\n) => TOptions['nested'] extends true ? Array<Plugin<TOptions>> : Plugin<TOptions>\n\nexport function createPlugin<TOptions extends PluginOptions = PluginOptions>(factory: PluginFactory<TOptions>) {\n return (userOptions: TOptions['userOptions']) => {\n const plugin = factory(userOptions)\n if (Array.isArray(plugin)) {\n throw new Error('Not implemented')\n }\n\n // default transform\n if (!plugin.transform) {\n plugin.transform = function transform(code) {\n return code\n }\n }\n\n return plugin\n }\n}\n\ntype Options = {\n config: UserConfig\n fileEmitter: FileEmitter\n resolveId: Api['resolveId']\n}\n\n// not exported\ntype CorePluginOptions = PluginOptions<Options, false, Api>\n\nexport const createCorePlugin = createPlugin<CorePluginOptions>((options) => {\n const { fileEmitter, resolveId } = options\n const config = {\n ...options.config,\n root: options.config.root || process.cwd(),\n }\n const schema = fse.readFileSync(path.resolve(config.root, config.input.schema), 'utf-8')\n\n return {\n name: 'core',\n api: {\n get config() {\n return config\n },\n get schema() {\n return schema\n },\n getFileName: fileEmitter.getFileName.bind(fileEmitter),\n getEmittedFile: fileEmitter.getEmittedFile.bind(fileEmitter),\n emitFile: fileEmitter.emitFile.bind(fileEmitter),\n resolveId,\n },\n }\n})\n","import type { WithPromise } from './types'\nimport type { LogLevel } from './utils/logger'\nimport type { Plugin } from './plugin'\n\nexport interface ConfigEnv {\n mode: string\n}\n// TODO revert to this to have multiple options like async, object, ...\n// export type PluginOption = PluginOptions | false | null | undefined | PluginOption[] | Promise<PluginOptions | false | null | undefined | PluginOption[]>;\n\nexport interface UserConfig {\n /**\n * Project root directory. Can be an absolute path, or a path relative from\n * the location of the config file itself.\n * @default process.cwd()\n */\n root?: string\n mode?: 'single'\n /**\n * plugins means it will run context, buildStart, transform and buildEnd based on order of the plugins array\n * Example of an order(plugin x does not have a buildEnd): [buildStart of plugin x, buildStart of plugin y, transform of plugin x, transform of plugin y, buildEnd of plugin y ]\n * Default: plugins\n */\n lifeCycle?: 'plugins'\n /**\n * Default: fifo\n */\n strategy?: 'fifo' | 'lifo'\n input: {\n schema: string\n }\n output: {\n path: string\n }\n /**\n * Array of regenerator plugins to use.\n */\n plugins?: Plugin[]\n\n logLevel?: LogLevel\n}\n\nexport type UserConfigFn = (env: ConfigEnv) => WithPromise<UserConfig>\nexport type UserConfigExport = WithPromise<UserConfig> | UserConfigFn\n\n/**\n * Type helper to make it easier to use regenerator.config.ts\n * accepts a direct {@link UserConfig} object, or a function that returns it.\n * The function receives a {@link ConfigEnv} object that exposes two properties:\n */\nexport function defineConfig(config: UserConfigExport): UserConfigExport {\n return config\n}\n","import type { WithPromise } from '../types'\n\nexport const isPromise = <T>(result: WithPromise<T>): result is Promise<T> => {\n return typeof (result as any)?.then === 'function'\n}\n","import { isPromise } from './isPromise'\n\nimport type { WithPromise } from '../types'\n\nexport const createQueue = <TArray extends readonly any[] = readonly any[], TInput = TArray[number], TOuput = void>(\n arr: TArray | undefined,\n fun: (item: TInput) => WithPromise<TOuput>\n) => {\n const promises: Promise<TOuput>[] = []\n\n arr?.forEach((item) => {\n const result = fun(item)\n if (isPromise<TOuput>(result)) {\n promises.push(result)\n } else {\n promises.push(Promise.resolve(result))\n }\n })\n\n return Promise.all(promises)\n}\n","/* eslint-disable consistent-return */\nimport fse from 'fs-extra'\nimport prettier from 'prettier'\n\nimport { format } from './format'\n\ntype WriteOptions = {\n format: boolean\n}\n\nexport const write = async (data: string, path: string, options: WriteOptions = { format: false }) => {\n const formattedData = options.format ? prettier.format(data, format) : data\n\n try {\n await fse.stat(path)\n const oldContent = await fse.readFile(path, { encoding: 'utf-8' })\n if (oldContent?.toString() === formattedData) {\n return\n }\n } catch (_err) {\n return fse.outputFile(path, formattedData)\n }\n\n return fse.outputFile(path, formattedData)\n}\n","import type { Options } from 'prettier'\n\nexport const format: Options = {\n tabWidth: 2,\n printWidth: 160,\n parser: 'typescript',\n singleQuote: false,\n semi: true,\n bracketSameLine: false,\n endOfLine: 'auto',\n}\n","/* eslint-disable @typescript-eslint/no-empty-interface */\nimport { build } from './build'\n\nexport * from './config'\nexport * from './build'\nexport { Plugin, PluginOptions, PluginFactory, createPlugin } from './plugin'\nexport * from './utils'\nexport * from './types'\nexport * from './context'\n\nexport default build\n\nexport namespace Plugins {\n export interface Context {}\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@kubb/core",
3
+ "version": "0.8.0",
4
+ "description": "Generator core",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git://github.com/stijnvanhulle/kubb.git",
8
+ "directory": "packages/core"
9
+ },
10
+ "license": "MIT",
11
+ "author": "Stijn Van Hulle <stijn@stijnvanhulle.be",
12
+ "sideEffects": false,
13
+ "main": "dist/index.js",
14
+ "unpkg": "dist/index.global.js",
15
+ "module": "dist/index.mjs",
16
+ "browser": "build/index.global.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "import": "./dist/index.mjs",
21
+ "module": "./dist/index.mjs",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./ast": {
25
+ "import": "./dist/ast/index.mjs",
26
+ "module": "./dist/ast/index.mjs",
27
+ "default": "./dist/ast/index.js"
28
+ }
29
+ },
30
+ "typesVersions": {
31
+ "*": {
32
+ "ast": [
33
+ "./types/ast/index.d.ts"
34
+ ]
35
+ }
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "schemas",
40
+ "!/**/**.test.**",
41
+ "!/**/__tests__/**"
42
+ ],
43
+ "dependencies": {
44
+ "change-case": "^4.1.2",
45
+ "fs-extra": "^10.1.0",
46
+ "prettier": "^2.7.1",
47
+ "talt": "^2.4.0",
48
+ "typescript": "^4.9.3"
49
+ },
50
+ "devDependencies": {
51
+ "@types/fs-extra": "^9.0.13",
52
+ "openapi-types": "^12.0.2",
53
+ "tsup": "^6.5.0"
54
+ },
55
+ "publishConfig": {
56
+ "access": "public",
57
+ "registry": "https://registry.npmjs.org/"
58
+ },
59
+ "scripts": {
60
+ "build": "tsup",
61
+ "start": "tsup --watch",
62
+ "release": "pnpm publish --no-git-check",
63
+ "pre-commit": "echo 'pre-commit not configured'",
64
+ "pre-push": "pnpm typecheck",
65
+ "test": "jest --config ../../jest.config.js --passWithNoTests --runInBand --testPathPattern=packages/core/src",
66
+ "test:local": "jest --config ../../jest.config.js --testPathPattern=packages/core/src --maxWorkers=50%",
67
+ "test:watch": "jest --config ../../jest.config.js --testPathPattern=packages/core/src --maxWorkers=25% --watch",
68
+ "upgrade": "ncu -u",
69
+ "upgrade:local": "ncu --interactive --doctor",
70
+ "typecheck": "tsc -p ./tsconfig.json --noEmit"
71
+ }
72
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "@kubb/define-config",
4
+ "title": "JSON schema for @kubb/core define-config",
5
+ "type": "object",
6
+ "properties": {
7
+ "root": {
8
+ "type": "string",
9
+ "description": "Root",
10
+ "default": "process.cwd()"
11
+ },
12
+ "input": {
13
+ "type": "object",
14
+ "description": "Input type",
15
+ "properties": {
16
+ "schema": {
17
+ "type": "string",
18
+ "description": "Your JSON schema"
19
+ }
20
+ }
21
+ },
22
+ "mode": {
23
+ "type": "string",
24
+ "description": "Mode type",
25
+ "enum": ["single"]
26
+ },
27
+ "output": {
28
+ "type": "object",
29
+ "description": "Output type",
30
+ "properties": {
31
+ "path": {
32
+ "type": "string",
33
+ "description": "Output path"
34
+ }
35
+ }
36
+ },
37
+ "plugins": {
38
+ "type": "array",
39
+ "items": {
40
+ "type": "array",
41
+ "prefixItems": [
42
+ {
43
+ "type": "string"
44
+ }
45
+ ],
46
+ "items": { "type": "object" }
47
+ },
48
+ "description": "Plugins"
49
+ },
50
+ "lifeCycle": {
51
+ "type": "string",
52
+ "description": "lifeCycle, default will be plugins",
53
+ "enum": ["plugins"],
54
+ "default": "plugins"
55
+ },
56
+ "strategy": {
57
+ "type": "string",
58
+ "description": "Strategy, default will be fifo",
59
+ "enum": ["fifo", "lifo"],
60
+ "default": "fifo"
61
+ },
62
+ "logLevel": {
63
+ "type": "string",
64
+ "description": "Log level",
65
+ "enum": ["error", "warn", "info","silent"]
66
+ }
67
+ }
68
+ }