@jk2908/cxx 0.2.6 → 0.3.3
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/README.md +18 -2
- package/dist/build.d.ts +22 -11
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +242 -73
- package/dist/build.js.map +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -7
- package/dist/index.js.map +3 -3
- package/dist/logger.d.ts +0 -2
- package/dist/logger.d.ts.map +1 -1
- package/dist/next/cxx-loader.cjs +287 -146
- package/dist/next/cxx-loader.cjs.map +7 -7
- package/dist/next/index.d.ts +34 -9
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +338 -142
- package/dist/next/index.js.map +5 -5
- package/dist/types.d.ts +5 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +16 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/vite/index.d.ts +4 -3
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +336 -139
- package/dist/vite/index.js.map +6 -6
- package/package.json +85 -81
- package/src/build.ts +312 -108
- package/src/index.ts +26 -9
- package/src/logger.ts +5 -13
- package/src/next/cxx-loader.js +9 -6
- package/src/next/index.ts +152 -100
- package/src/types.ts +5 -8
- package/src/utils.ts +81 -8
- package/src/vite/index.ts +141 -89
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,MAAM;;;;;;CAMF,CAAA;AAEV,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,MAAM;;;;;;CAMF,CAAA;AAEV,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAA;AAiB1C;;GAEG;AACH,qBAAa,MAAM;;IAKV,IAAI,CAAC,EAAE,MAAM;gBADpB,KAAK,CAAC,EAAE,QAAQ,EACT,IAAI,CAAC,EAAE,MAAM,YAAA;IAKrB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO;IAI3B;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO;IAoBzB,IAAI,KAAK,CAAC,KAAK,EAAE,QAAQ,EAExB;IAED,IAAI,KAAK,IAJQ,QAAQ,CAMxB;IAED;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;IA6BnD;;OAEG;IACH,KAAK,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE;IAI3B;;OAEG;IACH,IAAI,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE;IAI1B;;OAEG;IACH,IAAI,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE;IAI1B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;IAItC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAGtC"}
|
package/dist/next/cxx-loader.cjs
CHANGED
|
@@ -19,12 +19,14 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
19
19
|
}
|
|
20
20
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
21
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
23
|
+
for (let key of __getOwnPropNames(mod))
|
|
24
|
+
if (!__hasOwnProp.call(to, key))
|
|
25
|
+
__defProp(to, key, {
|
|
26
|
+
get: __accessProp.bind(mod, key),
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
28
30
|
if (canCache)
|
|
29
31
|
cache.set(mod, to);
|
|
30
32
|
return to;
|
|
@@ -75,20 +77,14 @@ var LEVELS = {
|
|
|
75
77
|
error: 3,
|
|
76
78
|
fatal: 4
|
|
77
79
|
};
|
|
80
|
+
var defaultLevel = process.env["NODE_ENV"] === "production" ? "error" : "info";
|
|
78
81
|
|
|
79
82
|
class Logger {
|
|
80
83
|
name;
|
|
81
|
-
static #defaultLevel = "info";
|
|
82
84
|
#level;
|
|
83
85
|
constructor(level, name) {
|
|
84
86
|
this.name = name;
|
|
85
|
-
this.#level = level;
|
|
86
|
-
}
|
|
87
|
-
static set defaultLevel(level) {
|
|
88
|
-
Logger.#defaultLevel = level;
|
|
89
|
-
}
|
|
90
|
-
static get defaultLevel() {
|
|
91
|
-
return Logger.#defaultLevel;
|
|
87
|
+
this.#level = level ?? defaultLevel;
|
|
92
88
|
}
|
|
93
89
|
static toError(err) {
|
|
94
90
|
return err instanceof Error ? err : new Error(String(err), { cause: err });
|
|
@@ -111,7 +107,7 @@ ${err.stack}` : "");
|
|
|
111
107
|
this.#level = level;
|
|
112
108
|
}
|
|
113
109
|
get level() {
|
|
114
|
-
return this.#level
|
|
110
|
+
return this.#level;
|
|
115
111
|
}
|
|
116
112
|
log(level, message, error) {
|
|
117
113
|
if (LEVELS[level] < LEVELS[this.level])
|
|
@@ -158,13 +154,13 @@ ${Logger.print(entry.error)}` : "";
|
|
|
158
154
|
var import_promises2 = __toESM(require("node:fs/promises"));
|
|
159
155
|
var import_node_path2 = __toESM(require("node:path"));
|
|
160
156
|
var import_node_url = require("node:url");
|
|
161
|
-
var import_watcher = __toESM(require("@parcel/watcher"));
|
|
162
157
|
|
|
163
158
|
// src/build.ts
|
|
164
159
|
var import_node_crypto = require("node:crypto");
|
|
165
160
|
var import_promises = __toESM(require("node:fs/promises"));
|
|
166
161
|
var import_node_path = __toESM(require("node:path"));
|
|
167
162
|
var import_lightningcss = require("lightningcss");
|
|
163
|
+
var import_magic_string = __toESM(require("magic-string"));
|
|
168
164
|
|
|
169
165
|
// src/config.ts
|
|
170
166
|
var NAME = "cxx";
|
|
@@ -216,32 +212,45 @@ function pascalise(str) {
|
|
|
216
212
|
}
|
|
217
213
|
|
|
218
214
|
// src/build.ts
|
|
215
|
+
var decoder = new TextDecoder;
|
|
216
|
+
var encoder = new TextEncoder;
|
|
219
217
|
var collectCache = new LruCache;
|
|
220
|
-
var
|
|
218
|
+
var writeChain = Promise.resolve();
|
|
221
219
|
function isENOENT(err) {
|
|
222
220
|
return err instanceof Error && "code" in err && err.code === "ENOENT";
|
|
223
221
|
}
|
|
224
|
-
async function
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
222
|
+
async function writeFileAtomic(filePath, content) {
|
|
223
|
+
const tmp = `${filePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
224
|
+
await import_promises.default.writeFile(tmp, content);
|
|
225
|
+
try {
|
|
226
|
+
await import_promises.default.rename(tmp, filePath);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
await import_promises.default.rm(tmp, { force: true });
|
|
229
|
+
throw err;
|
|
230
230
|
}
|
|
231
|
+
}
|
|
232
|
+
function enqueueWrite(task) {
|
|
233
|
+
const run = writeChain.then(task, task);
|
|
234
|
+
writeChain = run.then(() => {
|
|
235
|
+
return;
|
|
236
|
+
}, () => {
|
|
237
|
+
return;
|
|
238
|
+
});
|
|
239
|
+
return run;
|
|
240
|
+
}
|
|
241
|
+
async function maybeWrite(filePath, content) {
|
|
231
242
|
try {
|
|
232
|
-
if (await import_promises.default.readFile(filePath, "utf-8") === content)
|
|
233
|
-
fileCache.set(filePath, content);
|
|
243
|
+
if (await import_promises.default.readFile(filePath, "utf-8") === content)
|
|
234
244
|
return false;
|
|
235
|
-
}
|
|
236
245
|
} catch (err) {
|
|
237
246
|
if (!isENOENT(err))
|
|
238
247
|
throw err;
|
|
239
248
|
}
|
|
240
|
-
await
|
|
241
|
-
fileCache.set(filePath, content);
|
|
249
|
+
await writeFileAtomic(filePath, content);
|
|
242
250
|
return true;
|
|
243
251
|
}
|
|
244
|
-
var regex = /(?:const|var|let)\s*\[(\w
|
|
252
|
+
var regex = /((?:export\s+)?)(?:const|var|let)\s*\[(\w*)\s*,?\s*(\w*)\s*,?\s*(\w*)\s*\]\s*=\s*cxx(?:\s*`([\s\S]*?)`|\s*\.\s*tag(?:\s*<[^>]+>)?\s*\(\s*(['"])(.*?)\6\s*\)\s*`([\s\S]*?)`)/gm;
|
|
253
|
+
var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
245
254
|
function hashCss(code) {
|
|
246
255
|
return `cxx-${import_node_crypto.createHash("sha256").update(code).digest("base64url").slice(0, 12)}`;
|
|
247
256
|
}
|
|
@@ -252,73 +261,137 @@ class DuplicateTagError extends Error {
|
|
|
252
261
|
super(`Tag ${tag} has already been seen. Tags must be unique across your application`);
|
|
253
262
|
}
|
|
254
263
|
}
|
|
264
|
+
|
|
265
|
+
class InvalidTagError extends Error {
|
|
266
|
+
name = "InvalidTagError";
|
|
267
|
+
constructor(tag) {
|
|
268
|
+
super(`Tag "${tag}" does not map to a valid TypeScript identifier. ` + `Use letters, numbers, spaces, "_" or "-"`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
255
271
|
function collect(source, id, config) {
|
|
256
|
-
const
|
|
272
|
+
const configKey = JSON.stringify(config);
|
|
257
273
|
const cached = collectCache.get(id);
|
|
258
|
-
if (cached?.source === source)
|
|
274
|
+
if (cached?.source === source && cached.config === configKey)
|
|
259
275
|
return cached;
|
|
260
|
-
const
|
|
276
|
+
const tags = new Map;
|
|
277
|
+
const magic = new import_magic_string.default(source);
|
|
278
|
+
let matched = false;
|
|
279
|
+
regex.lastIndex = 0;
|
|
280
|
+
let match;
|
|
281
|
+
while (match = regex.exec(source)) {
|
|
282
|
+
matched = true;
|
|
283
|
+
const [, exp, varOne, varTwo, varThree, plainCss, , tag, taggedCss] = match;
|
|
261
284
|
const css = plainCss ?? taggedCss;
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
285
|
+
const matchIndex = match.index;
|
|
286
|
+
const { code, exports: classExports = {} } = (() => {
|
|
287
|
+
try {
|
|
288
|
+
return import_lightningcss.transform({
|
|
289
|
+
minify: true,
|
|
290
|
+
cssModules: true,
|
|
291
|
+
filename: id,
|
|
292
|
+
code: encoder.encode(css)
|
|
293
|
+
});
|
|
294
|
+
} catch (err) {
|
|
295
|
+
const line = source.slice(0, matchIndex).split(`
|
|
296
|
+
`).length;
|
|
297
|
+
throw new Error(`Failed to compile cxx CSS at ${id}:${line}`, { cause: err });
|
|
298
|
+
}
|
|
299
|
+
})();
|
|
268
300
|
const href = hashCss(code);
|
|
269
|
-
const styles = Object.fromEntries(Object.entries(
|
|
301
|
+
const styles = Object.fromEntries(Object.entries(classExports).map(([k, v]) => [k, v.name]));
|
|
270
302
|
if (tag) {
|
|
271
303
|
const suffix = typeof config.typeSuffix === "string" ? config.typeSuffix : config.typeSuffix === false ? "" : "Classes";
|
|
272
304
|
const tagWithSuffix = pascalise(`${tag}${suffix}`);
|
|
305
|
+
if (!IDENTIFIER.test(tagWithSuffix))
|
|
306
|
+
throw new InvalidTagError(tag);
|
|
273
307
|
if (tags.has(tagWithSuffix))
|
|
274
308
|
throw new DuplicateTagError(tagWithSuffix);
|
|
275
309
|
tags.set(tagWithSuffix, Object.keys(styles));
|
|
276
310
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
311
|
+
const statements = [];
|
|
312
|
+
if (varOne) {
|
|
313
|
+
statements.push(`${exp}const ${varOne} = ${JSON.stringify(decoder.decode(code))}`);
|
|
314
|
+
}
|
|
315
|
+
if (varTwo) {
|
|
316
|
+
statements.push(`${exp}const ${varTwo} = ${JSON.stringify(styles)}`);
|
|
317
|
+
}
|
|
318
|
+
if (varThree) {
|
|
319
|
+
statements.push(`${exp}const ${varThree} = ${JSON.stringify(href)}`);
|
|
320
|
+
}
|
|
321
|
+
magic.overwrite(matchIndex, matchIndex + match[0].length, statements.join(`
|
|
322
|
+
`));
|
|
323
|
+
}
|
|
324
|
+
const template = magic.toString();
|
|
325
|
+
const map = matched ? magic.generateMap({ source: id, includeContent: true, hires: true }) : null;
|
|
326
|
+
const result = { source, config: configKey, template, tags, map };
|
|
327
|
+
collectCache.set(id, result);
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
function renderTypes(tags) {
|
|
331
|
+
return [
|
|
332
|
+
AUTOGEN_MSG,
|
|
333
|
+
"",
|
|
334
|
+
`import '${PKG_NAME}'`,
|
|
335
|
+
"",
|
|
336
|
+
`declare module '${PKG_NAME}' {`,
|
|
337
|
+
tagsToType(tags),
|
|
338
|
+
"}",
|
|
339
|
+
""
|
|
340
|
+
].join(`
|
|
282
341
|
`);
|
|
283
|
-
});
|
|
284
|
-
collectCache.set(id, { source, template, tags });
|
|
285
|
-
return {
|
|
286
|
-
template,
|
|
287
|
-
tags
|
|
288
|
-
};
|
|
289
342
|
}
|
|
290
|
-
async function
|
|
343
|
+
async function writeRenderedTypes(tags) {
|
|
291
344
|
const filePath = import_node_path.default.join(GENERATED_DIR, "index.d.ts");
|
|
292
345
|
if (!tags.size) {
|
|
293
|
-
|
|
294
|
-
await import_promises.default.rm(filePath, { force: true });
|
|
295
|
-
fileCache.delete(filePath);
|
|
296
|
-
} catch (err) {
|
|
297
|
-
if (!isENOENT(err))
|
|
298
|
-
throw err;
|
|
299
|
-
}
|
|
346
|
+
await import_promises.default.rm(filePath, { force: true });
|
|
300
347
|
return;
|
|
301
348
|
}
|
|
302
349
|
await import_promises.default.mkdir(GENERATED_DIR, { recursive: true });
|
|
303
|
-
await maybeWrite(filePath,
|
|
304
|
-
|
|
305
|
-
import '${PKG_NAME}'
|
|
306
|
-
|
|
307
|
-
declare module '${PKG_NAME}' {
|
|
308
|
-
${tagsToType(tags)}
|
|
309
|
-
}
|
|
310
|
-
`);
|
|
350
|
+
await maybeWrite(filePath, renderTypes(tags));
|
|
311
351
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
352
|
+
var PARTIAL_DIR = import_node_path.default.join(GENERATED_DIR, "tags");
|
|
353
|
+
var REBUILD_WAIT = 100;
|
|
354
|
+
var rebuildTimer = null;
|
|
355
|
+
var rebuildError = null;
|
|
356
|
+
function partialPath(filePath) {
|
|
357
|
+
return import_node_path.default.join(PARTIAL_DIR, `${import_node_crypto.createHash("sha1").update(filePath).digest("hex")}.json`);
|
|
317
358
|
}
|
|
318
|
-
function
|
|
359
|
+
async function partialDirMtime() {
|
|
360
|
+
try {
|
|
361
|
+
return (await import_promises.default.stat(PARTIAL_DIR)).mtimeMs;
|
|
362
|
+
} catch (err) {
|
|
363
|
+
if (isENOENT(err))
|
|
364
|
+
return 0;
|
|
365
|
+
throw err;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async function readPartials() {
|
|
369
|
+
let entries;
|
|
370
|
+
try {
|
|
371
|
+
entries = await import_promises.default.readdir(PARTIAL_DIR);
|
|
372
|
+
} catch (err) {
|
|
373
|
+
if (isENOENT(err))
|
|
374
|
+
return new Map;
|
|
375
|
+
throw err;
|
|
376
|
+
}
|
|
319
377
|
const tags = new Map;
|
|
320
|
-
for (const
|
|
321
|
-
|
|
378
|
+
for (const entry of entries) {
|
|
379
|
+
if (!entry.endsWith(".json"))
|
|
380
|
+
continue;
|
|
381
|
+
const partial = import_node_path.default.join(PARTIAL_DIR, entry);
|
|
382
|
+
let parsed;
|
|
383
|
+
try {
|
|
384
|
+
parsed = JSON.parse(await import_promises.default.readFile(partial, "utf-8"));
|
|
385
|
+
} catch {
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
try {
|
|
389
|
+
await import_promises.default.access(parsed.file);
|
|
390
|
+
} catch {
|
|
391
|
+
await import_promises.default.rm(partial, { force: true });
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
for (const [name, classes] of Object.entries(parsed.tags)) {
|
|
322
395
|
if (tags.has(name))
|
|
323
396
|
throw new DuplicateTagError(name);
|
|
324
397
|
tags.set(name, classes);
|
|
@@ -326,106 +399,174 @@ function flattenTags(tagsByFile) {
|
|
|
326
399
|
}
|
|
327
400
|
return tags;
|
|
328
401
|
}
|
|
402
|
+
function writeTypesForFile(filePath, tags) {
|
|
403
|
+
return enqueueWrite(async () => {
|
|
404
|
+
await import_promises.default.mkdir(PARTIAL_DIR, { recursive: true });
|
|
405
|
+
const partial = partialPath(filePath);
|
|
406
|
+
if (!tags.size) {
|
|
407
|
+
await import_promises.default.rm(partial, { force: true });
|
|
408
|
+
} else {
|
|
409
|
+
await writeFileAtomic(partial, JSON.stringify({ file: filePath, tags: Object.fromEntries(tags) }));
|
|
410
|
+
}
|
|
411
|
+
}).then(() => {
|
|
412
|
+
scheduleRebuild();
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function scheduleRebuild() {
|
|
416
|
+
if (rebuildTimer)
|
|
417
|
+
clearTimeout(rebuildTimer);
|
|
418
|
+
rebuildTimer = setTimeout(() => {
|
|
419
|
+
rebuildTimer = null;
|
|
420
|
+
flushTypes().catch((err) => {
|
|
421
|
+
rebuildError = err;
|
|
422
|
+
});
|
|
423
|
+
}, REBUILD_WAIT);
|
|
424
|
+
}
|
|
425
|
+
function flushTypes() {
|
|
426
|
+
if (rebuildTimer) {
|
|
427
|
+
clearTimeout(rebuildTimer);
|
|
428
|
+
rebuildTimer = null;
|
|
429
|
+
}
|
|
430
|
+
return enqueueWrite(async () => {
|
|
431
|
+
let before = await partialDirMtime();
|
|
432
|
+
for (let attempt = 0;attempt < 3; attempt++) {
|
|
433
|
+
await writeRenderedTypes(await readPartials());
|
|
434
|
+
const after = await partialDirMtime();
|
|
435
|
+
if (after === before)
|
|
436
|
+
return;
|
|
437
|
+
before = after;
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
function takeRebuildError() {
|
|
442
|
+
const err = rebuildError;
|
|
443
|
+
rebuildError = null;
|
|
444
|
+
return err;
|
|
445
|
+
}
|
|
446
|
+
function tagsToType(tags) {
|
|
447
|
+
return [...tags].toSorted(([a], [b]) => a.localeCompare(b)).map(([tag, classes]) => {
|
|
448
|
+
const union = classes.length > 0 ? classes.toSorted((a, b) => a.length - b.length).map((c) => `'${c}'`).join(" | ") : "never";
|
|
449
|
+
return ` export type ${tag} = ${union}`;
|
|
450
|
+
}).join(`
|
|
451
|
+
`);
|
|
452
|
+
}
|
|
329
453
|
|
|
330
454
|
// src/next/index.ts
|
|
331
455
|
var nextDir = import_node_path2.default.dirname(import_node_url.fileURLToPath("file:///Users/jeromekenway/Documents/dev.nosync/me/repo/cxx/packages/cxx/src/next/index.ts"));
|
|
332
456
|
var loader = import_node_path2.default.join(nextDir, "cxx-loader.cjs");
|
|
333
|
-
var tagsByFile = new Map;
|
|
334
457
|
var watchedFiles = new Map;
|
|
335
|
-
var
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
458
|
+
var subscription = null;
|
|
459
|
+
var subscriptionPromise = null;
|
|
460
|
+
var cleanupRegistered = false;
|
|
461
|
+
var watcherLogger = null;
|
|
462
|
+
var DEFAULT_IGNORE = [
|
|
463
|
+
"**/node_modules/**",
|
|
464
|
+
"**/.next/**",
|
|
465
|
+
`**/${GENERATED_DIR}/**`,
|
|
466
|
+
"**/.git/**"
|
|
467
|
+
];
|
|
468
|
+
async function onEvent(event, filePath) {
|
|
469
|
+
const watched = watchedFiles.get(filePath);
|
|
470
|
+
if (!watched)
|
|
339
471
|
return;
|
|
340
|
-
const { pluginConfig, logger } =
|
|
341
|
-
const hadTags = tagsByFile.has(filePath);
|
|
472
|
+
const { pluginConfig, logger } = watched;
|
|
342
473
|
if (event === "delete") {
|
|
343
|
-
|
|
344
|
-
if (!hadTags)
|
|
345
|
-
return;
|
|
346
|
-
await writeTypes(flattenTags(tagsByFile));
|
|
474
|
+
await writeTypesForFile(filePath, new Map);
|
|
347
475
|
logger.info(`updated types from ${filePath}`);
|
|
348
476
|
return;
|
|
349
477
|
}
|
|
478
|
+
let source;
|
|
350
479
|
try {
|
|
351
|
-
|
|
352
|
-
const { tags } = collect(source, filePath, pluginConfig);
|
|
353
|
-
const hasTags = tags.size > 0;
|
|
354
|
-
if (hasTags) {
|
|
355
|
-
tagsByFile.set(filePath, tags);
|
|
356
|
-
} else {
|
|
357
|
-
tagsByFile.delete(filePath);
|
|
358
|
-
}
|
|
359
|
-
if (!hadTags && !hasTags)
|
|
360
|
-
return;
|
|
361
|
-
await writeTypes(flattenTags(tagsByFile));
|
|
362
|
-
logger.info(`updated types from ${filePath}`);
|
|
480
|
+
source = await import_promises2.default.readFile(filePath, "utf-8");
|
|
363
481
|
} catch (err) {
|
|
364
482
|
if (!isENOENT(err))
|
|
365
483
|
throw err;
|
|
366
|
-
|
|
367
|
-
return;
|
|
368
|
-
tagsByFile.delete(filePath);
|
|
369
|
-
await writeTypes(flattenTags(tagsByFile));
|
|
484
|
+
await writeTypesForFile(filePath, new Map);
|
|
370
485
|
logger.info(`updated types from ${filePath}`);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
const tags = source.includes("cxx") ? collect(source, filePath, pluginConfig).tags : new Map;
|
|
489
|
+
await writeTypesForFile(filePath, tags);
|
|
490
|
+
logger.info(`updated types from ${filePath}`);
|
|
491
|
+
}
|
|
492
|
+
function ensureWatcher(pluginConfig, logger) {
|
|
493
|
+
watcherLogger = logger;
|
|
494
|
+
if (subscriptionPromise)
|
|
495
|
+
return;
|
|
496
|
+
const root = pluginConfig.watch?.root ?? process.cwd();
|
|
497
|
+
const ignore = [...DEFAULT_IGNORE, ...pluginConfig.watch?.ignore ?? []];
|
|
498
|
+
subscriptionPromise = (async () => {
|
|
499
|
+
const { subscribe } = await import("@parcel/watcher");
|
|
500
|
+
subscription = await subscribe(root, (watchErr, events) => {
|
|
501
|
+
if (watchErr) {
|
|
502
|
+
watcherLogger?.error(`failed to watch ${root}`, watchErr);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
for (const event of events) {
|
|
506
|
+
const filePath = import_node_path2.default.resolve(event.path);
|
|
507
|
+
if (!watchedFiles.has(filePath))
|
|
508
|
+
continue;
|
|
509
|
+
onEvent(event.type, filePath).catch((err) => {
|
|
510
|
+
watcherLogger?.error(`failed to update types from ${filePath}`, err);
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}, { ignore });
|
|
514
|
+
registerCleanup();
|
|
515
|
+
})().catch((err) => {
|
|
516
|
+
watcherLogger?.error("failed to start cxx watcher", err);
|
|
517
|
+
subscriptionPromise = null;
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
async function cleanup() {
|
|
521
|
+
const active = subscription;
|
|
522
|
+
subscription = null;
|
|
523
|
+
subscriptionPromise = null;
|
|
524
|
+
watchedFiles.clear();
|
|
525
|
+
if (active)
|
|
526
|
+
await active.unsubscribe();
|
|
527
|
+
}
|
|
528
|
+
async function shutdown(signal) {
|
|
529
|
+
try {
|
|
530
|
+
await cleanup();
|
|
531
|
+
} finally {
|
|
532
|
+
process.kill(process.pid, signal);
|
|
371
533
|
}
|
|
372
534
|
}
|
|
535
|
+
function registerCleanup() {
|
|
536
|
+
if (cleanupRegistered)
|
|
537
|
+
return;
|
|
538
|
+
cleanupRegistered = true;
|
|
539
|
+
process.once("SIGINT", () => void shutdown("SIGINT"));
|
|
540
|
+
process.once("SIGTERM", () => void shutdown("SIGTERM"));
|
|
541
|
+
}
|
|
373
542
|
function processFile(source, filePath, pluginConfig, logger) {
|
|
374
543
|
const resolvedFilePath = import_node_path2.default.resolve(filePath);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (true) {
|
|
378
|
-
watchedFiles.set(resolvedFilePath, { pluginConfig, logger });
|
|
379
|
-
if (!subscription) {
|
|
380
|
-
subscription = import_watcher.default.subscribe(directoryPath, async (err, events) => {
|
|
381
|
-
if (err) {
|
|
382
|
-
logger.error(`failed to update types from ${directoryPath}`, err);
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
for (const event of events) {
|
|
386
|
-
const eventFilePath = import_node_path2.default.resolve(event.path);
|
|
387
|
-
if (!watchedFiles.has(eventFilePath))
|
|
388
|
-
continue;
|
|
389
|
-
try {
|
|
390
|
-
await rebuildFile(eventFilePath, event.type);
|
|
391
|
-
} catch (watchErr) {
|
|
392
|
-
logger.error(`failed to update types from ${eventFilePath}`, watchErr);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
subscriptionsByDir.set(directoryPath, subscription);
|
|
397
|
-
}
|
|
544
|
+
if (!source.includes("cxx") || /[\\/]node_modules[\\/]/.test(resolvedFilePath)) {
|
|
545
|
+
return { template: source, tags: new Map, map: null };
|
|
398
546
|
}
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
547
|
+
const priorError = takeRebuildError();
|
|
548
|
+
if (priorError)
|
|
549
|
+
throw priorError;
|
|
550
|
+
if (process.env["NODE_ENV"] !== "production") {
|
|
551
|
+
watchedFiles.set(resolvedFilePath, { pluginConfig, logger });
|
|
552
|
+
ensureWatcher(pluginConfig, logger);
|
|
404
553
|
}
|
|
405
|
-
|
|
554
|
+
const result = collect(source, resolvedFilePath, pluginConfig);
|
|
555
|
+
writeTypesForFile(resolvedFilePath, result.tags);
|
|
406
556
|
return result;
|
|
407
557
|
}
|
|
408
|
-
async function cleanup() {
|
|
409
|
-
await Promise.all([...subscriptionsByDir].map(async ([directoryPath, subPromise]) => {
|
|
410
|
-
subscriptionsByDir.delete(directoryPath);
|
|
411
|
-
await (await subPromise).unsubscribe();
|
|
412
|
-
}));
|
|
413
|
-
subscriptionsByDir.clear();
|
|
414
|
-
}
|
|
415
|
-
process.once("SIGINT", () => {
|
|
416
|
-
cleanup().finally(() => process.exit(130));
|
|
417
|
-
});
|
|
418
|
-
process.once("SIGTERM", () => {
|
|
419
|
-
cleanup().finally(() => process.exit(143));
|
|
420
|
-
});
|
|
421
558
|
|
|
422
559
|
// src/next/cxx-loader.js
|
|
423
560
|
var loader2 = function(source) {
|
|
424
561
|
const { pluginConfig } = this.getOptions();
|
|
425
|
-
const logger = new Logger
|
|
426
|
-
const { template } = processFile(source, this.resourcePath, pluginConfig, logger);
|
|
562
|
+
const logger = new Logger;
|
|
563
|
+
const { template, map } = processFile(source, this.resourcePath, pluginConfig, logger);
|
|
564
|
+
if (map && typeof this.callback === "function") {
|
|
565
|
+
this.callback(null, template, map);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
427
568
|
return template;
|
|
428
569
|
};
|
|
429
570
|
var cxx_loader_default = loader2;
|
|
430
571
|
|
|
431
|
-
//# debugId=
|
|
572
|
+
//# debugId=57CAE560E6EB2D4464756E2164756E21
|