@batijs/build 0.0.248 → 0.0.249

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 (2) hide show
  1. package/dist/index.js +187 -110
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,20 +1,23 @@
1
1
  // src/index.ts
2
2
  import { existsSync } from "node:fs";
3
- import { mkdir, opendir, readFile as readFile2, writeFile } from "node:fs/promises";
3
+ import { mkdir, opendir, rm, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
- import { formatCode, transformAndFormat as transformAndFormat2 } from "@batijs/core";
5
+ import "@batijs/core";
6
6
 
7
- // src/merge-dts.ts
7
+ // src/operations/file.ts
8
+ import { transformAndFormat as transformAndFormat2 } from "@batijs/core";
8
9
  import { readFile } from "node:fs/promises";
10
+ import { relative } from "node:path";
11
+
12
+ // src/operations/merge-dts.ts
9
13
  import { parseModule, transformAndFormat } from "@batijs/core";
10
14
  async function mergeDts({
11
- target,
12
15
  fileContent,
16
+ previousContent,
13
17
  filepath,
14
18
  meta
15
19
  }) {
16
- const previousCode = await readFile(target, { encoding: "utf-8" });
17
- const previousAst = parseModule(previousCode);
20
+ const previousAst = parseModule(previousContent);
18
21
  const currentAst = parseModule(fileContent);
19
22
  for (const imp of previousAst.imports.$items) {
20
23
  currentAst.imports[imp.local] = imp;
@@ -38,49 +41,38 @@ async function mergeDts({
38
41
  return res.code;
39
42
  }
40
43
 
41
- // src/queue.ts
42
- function queue() {
43
- const tasks = [];
44
+ // src/operations/file.ts
45
+ async function executeOperationFile(op, {
46
+ meta,
47
+ previousOperationSameDestination
48
+ }) {
49
+ const code = await readFile(op.sourceAbsolute, { encoding: "utf-8" });
50
+ const filepath = relative(op.source, op.sourceAbsolute);
51
+ const result = await transformAndFormat2(code, meta, {
52
+ filepath
53
+ });
54
+ let fileContent = result.code;
55
+ if (op.sourceAbsolute.endsWith(".d.ts") && previousOperationSameDestination?.content) {
56
+ fileContent = await mergeDts({
57
+ fileContent,
58
+ previousContent: previousOperationSameDestination.content,
59
+ meta,
60
+ filepath
61
+ });
62
+ }
44
63
  return {
45
- add(task) {
46
- tasks.push(task);
47
- },
48
- async run() {
49
- let task;
50
- while (task = tasks.shift()) {
51
- await task();
52
- }
53
- }
64
+ context: result.context,
65
+ content: fileContent ? fileContent.trimStart() : void 0
54
66
  };
55
67
  }
56
68
 
57
- // src/index.ts
58
- var reIgnoreFile = /^(chunk-|asset-|#)/gi;
69
+ // src/operations/transform.ts
70
+ import { parse } from "path";
71
+ import { formatCode } from "@batijs/core";
59
72
  var isWin = process.platform === "win32";
60
- function toDist(filepath, source, dist) {
61
- const split = filepath.split(path.sep);
62
- split[split.length - 1] = split[split.length - 1].replace(/^\$\$?(.*)\.[tj]sx?$/, "$1");
63
- return split.join(path.sep).replace(source, dist);
64
- }
65
- async function safeWriteFile(destination, content) {
66
- const destinationDir = path.dirname(destination);
67
- await mkdir(destinationDir, {
68
- recursive: true
69
- });
70
- await writeFile(destination, content, { encoding: "utf-8" });
71
- }
72
- async function* walk(dir) {
73
- if (!existsSync(dir)) return;
74
- for await (const d of await opendir(dir)) {
75
- const entry = path.join(dir, d.name);
76
- if (d.isDirectory()) {
77
- yield* walk(entry);
78
- } else if (d.isFile()) yield entry;
79
- }
80
- }
81
73
  async function transformFileAfterExec(filepath, fileContent) {
82
74
  if (fileContent === void 0 || fileContent === null) return null;
83
- const parsed = path.parse(filepath);
75
+ const parsed = parse(filepath);
84
76
  const toTest = [parsed.base, parsed.ext, parsed.name].filter(Boolean);
85
77
  for (const ext of toTest) {
86
78
  switch (ext) {
@@ -117,6 +109,111 @@ async function importTransformer(p) {
117
109
  const f = await import(importFile);
118
110
  return f.default;
119
111
  }
112
+ async function executeOperationTransform(op, {
113
+ meta,
114
+ previousOperationSameDestination
115
+ }) {
116
+ const transformer = await importTransformer(op.sourceAbsolute);
117
+ const previousContent = previousOperationSameDestination?.content;
118
+ const fileContent = await transformFileAfterExec(
119
+ op.destination,
120
+ await transformer({
121
+ readfile: previousContent ? () => previousContent : void 0,
122
+ meta,
123
+ source: op.source,
124
+ target: op.destination
125
+ })
126
+ );
127
+ return {
128
+ content: fileContent !== null ? fileContent : void 0
129
+ };
130
+ }
131
+
132
+ // src/utils.ts
133
+ function orderBy(array, getter) {
134
+ return array.slice().sort((a, b) => {
135
+ const valueA = getter(a);
136
+ const valueB = getter(b);
137
+ if (valueA < valueB) return -1;
138
+ if (valueA > valueB) return 1;
139
+ return 0;
140
+ });
141
+ }
142
+
143
+ // src/operations/rearranger.ts
144
+ var OperationsRearranger = class {
145
+ files;
146
+ constructor() {
147
+ this.files = /* @__PURE__ */ new Map();
148
+ }
149
+ addFile(file) {
150
+ if (!this.files.has(file.destination)) {
151
+ this.files.set(file.destination, []);
152
+ }
153
+ this.files.get(file.destination).push(file);
154
+ }
155
+ *compute() {
156
+ for (const file of this.files.values()) {
157
+ if (file.filter((op) => op.important).length >= 2) {
158
+ throw new Error(`Error while trying to generate file: '${file[0].destination}'.
159
+ Multiple important file is not yet supported.
160
+ Please report this issue to https://github.com/vikejs/bati`);
161
+ }
162
+ const newOrder = orderBy(file, (op) => {
163
+ if (op.kind === "file" && !op.important) return 1;
164
+ if (op.kind === "file" && op.important) return 2;
165
+ if (op.kind === "transform" && !op.important) return 3;
166
+ if (op.kind === "transform" && op.important) return 4;
167
+ throw new Error("Unhandled OperationsRearranger.compute orderBy case");
168
+ });
169
+ if (file[0].sourceAbsolute.endsWith(".d.ts")) {
170
+ yield* newOrder.filter((op) => op.kind === "file");
171
+ } else {
172
+ const input = newOrder.filter((op) => op.kind === "file").at(-1);
173
+ if (input) {
174
+ yield input;
175
+ }
176
+ }
177
+ yield* newOrder.filter((op) => op.kind !== "file");
178
+ }
179
+ }
180
+ };
181
+
182
+ // src/index.ts
183
+ var reIgnoreFile = /^(chunk-|asset-|#)/gi;
184
+ function toDist(filepath, source, dist) {
185
+ const split = filepath.split(path.sep);
186
+ split[split.length - 1] = split[split.length - 1].replace(/^\$\$?(.*)\.[tj]sx?$/, "$1").replace(/^!(.*)$/, "$1");
187
+ return split.join(path.sep).replace(source, dist);
188
+ }
189
+ async function safeWriteFile(destination, content) {
190
+ const destinationDir = path.dirname(destination);
191
+ await mkdir(destinationDir, {
192
+ recursive: true
193
+ });
194
+ await writeFile(destination, content, { encoding: "utf-8" });
195
+ }
196
+ async function safeRmFile(destination) {
197
+ try {
198
+ await rm(destination, {
199
+ force: true,
200
+ maxRetries: 3,
201
+ recursive: false,
202
+ retryDelay: 150
203
+ });
204
+ } catch {
205
+ console.warn(`Failed to remove unecessary file: ${destination}`);
206
+ }
207
+ }
208
+ async function* walk(dir) {
209
+ if (!existsSync(dir)) return;
210
+ for await (const d of await opendir(dir)) {
211
+ const entry = path.join(dir, d.name);
212
+ if (d.isDirectory()) {
213
+ yield* walk(entry);
214
+ } else if (d.isFile()) yield entry;
215
+ }
216
+ }
120
217
  function importToPotentialTargets(imp) {
121
218
  let subject = imp;
122
219
  const ext = path.extname(imp);
@@ -133,11 +230,8 @@ function importToPotentialTargets(imp) {
133
230
  }
134
231
  async function main(options, meta) {
135
232
  const sources = Array.isArray(options.source) ? options.source : [options.source];
136
- const targets = /* @__PURE__ */ new Set();
137
233
  const allImports = /* @__PURE__ */ new Set();
138
- const includeIfImported = /* @__PURE__ */ new Map();
139
- const priorityQ = queue();
140
- const transformAndWriteQ = queue();
234
+ const filesContainingIncludeIfImported = /* @__PURE__ */ new Set();
141
235
  function updateAllImports(target, imports) {
142
236
  if (!imports) return;
143
237
  for (const imp of imports.values()) {
@@ -148,21 +242,7 @@ async function main(options, meta) {
148
242
  }
149
243
  }
150
244
  }
151
- async function triggerPendingTargets(target, imports) {
152
- if (!imports) return;
153
- for (const imp of imports.values()) {
154
- const importTarget = path.resolve(path.dirname(target), imp);
155
- const importTargets = importToPotentialTargets(importTarget);
156
- for (const imp2 of importTargets) {
157
- if (includeIfImported.has(imp2)) {
158
- const fn = includeIfImported.get(imp2);
159
- includeIfImported.delete(imp2);
160
- await fn();
161
- break;
162
- }
163
- }
164
- }
165
- }
245
+ const rearranger = new OperationsRearranger();
166
246
  for (const source of sources) {
167
247
  for await (const p of walk(source)) {
168
248
  const target = toDist(p, source, options.dist);
@@ -175,61 +255,58 @@ async function main(options, meta) {
175
255
  `Typescript file needs to be compiled before it can be executed: '${p}'.
176
256
  Please report this issue to https://github.com/vikejs/bati`
177
257
  );
178
- } else if (parsed.name.startsWith("$") && parsed.ext.match(/\.jsx?$/)) {
179
- transformAndWriteQ.add(async () => {
180
- const transformer = await importTransformer(p);
181
- const rf = () => {
182
- return readFile2(target, { encoding: "utf-8" });
183
- };
184
- const fileContent = await transformFileAfterExec(
185
- target,
186
- await transformer({
187
- readfile: targets.has(target) ? rf : void 0,
188
- meta,
189
- source,
190
- target
191
- })
192
- );
193
- if (fileContent !== null) {
194
- await safeWriteFile(target, fileContent);
195
- targets.add(target);
196
- }
258
+ } else if ((parsed.name.startsWith("!$") || parsed.name.startsWith("$")) && parsed.ext.match(/\.jsx?$/)) {
259
+ rearranger.addFile({
260
+ source,
261
+ sourceAbsolute: p,
262
+ destination: target,
263
+ destinationAbsolute: targetAbsolute,
264
+ kind: "transform",
265
+ parsed,
266
+ important: parsed.name.startsWith("!")
197
267
  });
198
268
  } else {
199
- priorityQ.add(async () => {
200
- const code = await readFile2(p, { encoding: "utf-8" });
201
- const filepath = path.relative(source, p);
202
- const result = await transformAndFormat2(code, meta, {
203
- filepath
204
- });
205
- let fileContent = result.code;
206
- if (p.endsWith(".d.ts") && targets.has(target)) {
207
- fileContent = await mergeDts({
208
- fileContent,
209
- target,
210
- meta,
211
- filepath
212
- });
213
- }
214
- if (fileContent) {
215
- updateAllImports(targetAbsolute, result.context?.imports);
216
- if (!result.context?.flags.has("include-if-imported") || allImports.has(targetAbsolute)) {
217
- await safeWriteFile(target, fileContent.trimStart());
218
- await triggerPendingTargets(targetAbsolute, result.context?.imports);
219
- } else {
220
- includeIfImported.set(targetAbsolute, () => safeWriteFile(target, fileContent.trimStart()));
221
- }
222
- targets.add(target);
223
- }
269
+ rearranger.addFile({
270
+ source,
271
+ sourceAbsolute: p,
272
+ destination: target,
273
+ destinationAbsolute: targetAbsolute,
274
+ kind: "file",
275
+ parsed,
276
+ important: parsed.name.startsWith("!")
224
277
  });
225
278
  }
226
279
  }
227
280
  }
228
- await priorityQ.run();
229
- await transformAndWriteQ.run();
230
- for (const target of includeIfImported.keys()) {
231
- if (allImports.has(target)) {
232
- await includeIfImported.get(target)();
281
+ let previousOp = void 0;
282
+ for (const op of rearranger.compute()) {
283
+ if (previousOp?.destination !== op.destination) {
284
+ previousOp = void 0;
285
+ }
286
+ let report = {};
287
+ if (op.kind === "file") {
288
+ report = await executeOperationFile(op, {
289
+ meta,
290
+ previousOperationSameDestination: previousOp
291
+ });
292
+ updateAllImports(op.destinationAbsolute, report.context?.imports);
293
+ } else if (op.kind === "transform") {
294
+ report = await executeOperationTransform(op, {
295
+ meta,
296
+ previousOperationSameDestination: previousOp
297
+ });
298
+ }
299
+ if (report.content) {
300
+ await safeWriteFile(op.destination, report.content.trimStart());
301
+ }
302
+ previousOp = {
303
+ ...op,
304
+ ...report
305
+ };
306
+ }
307
+ for (const target of filesContainingIncludeIfImported) {
308
+ if (!allImports.has(target)) {
309
+ await safeRmFile(target);
233
310
  }
234
311
  }
235
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@batijs/build",
3
- "version": "0.0.248",
3
+ "version": "0.0.249",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -10,10 +10,10 @@
10
10
  "devDependencies": {
11
11
  "@types/node": "^18.19.14",
12
12
  "tsup": "^8.2.4",
13
- "@batijs/compile": "0.0.248"
13
+ "@batijs/compile": "0.0.249"
14
14
  },
15
15
  "dependencies": {
16
- "@batijs/core": "0.0.248"
16
+ "@batijs/core": "0.0.249"
17
17
  },
18
18
  "main": "./dist/index.js",
19
19
  "module": "./dist/index.js",