@rohal12/twee-ts 1.18.2 → 2.0.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.
Files changed (42) hide show
  1. package/README.md +23 -3
  2. package/THIRD_PARTY_NOTICES +111 -0
  3. package/UNLICENSE +24 -0
  4. package/dist/bin/twee-ts.js +689 -9446
  5. package/dist/bin/twee-ts.js.map +1 -1
  6. package/dist/diagnostic-text-BRddVulf.cjs +26463 -0
  7. package/dist/diagnostic-text-BRddVulf.cjs.map +1 -0
  8. package/dist/diagnostic-text-CebYCTPQ.js +26040 -0
  9. package/dist/diagnostic-text-CebYCTPQ.js.map +1 -0
  10. package/dist/index.cjs +86 -9137
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +192 -416
  13. package/dist/index.d.ts +192 -416
  14. package/dist/index.js +4 -9317
  15. package/dist/lint-VayZI_jp.js +288 -0
  16. package/dist/lint-VayZI_jp.js.map +1 -0
  17. package/dist/options-DuBkFyqi.d.cts +28 -0
  18. package/dist/options-nc5NpnSc.d.ts +28 -0
  19. package/dist/plugins/rollup.cjs +172 -0
  20. package/dist/plugins/rollup.cjs.map +1 -0
  21. package/dist/plugins/rollup.d.cts +46 -0
  22. package/dist/plugins/rollup.d.ts +7 -12
  23. package/dist/plugins/rollup.js +130 -65
  24. package/dist/plugins/rollup.js.map +1 -1
  25. package/dist/plugins/vite.cjs +1926 -0
  26. package/dist/plugins/vite.cjs.map +1 -0
  27. package/dist/plugins/vite.d.cts +15 -0
  28. package/dist/plugins/vite.d.ts +5 -12
  29. package/dist/plugins/vite.js +1763 -458
  30. package/dist/plugins/vite.js.map +1 -1
  31. package/dist/types-BvI6pg2y.d.cts +389 -0
  32. package/dist/types-BvI6pg2y.d.ts +389 -0
  33. package/dist/watch-targets-BI7jYrwa.js +486 -0
  34. package/dist/watch-targets-BI7jYrwa.js.map +1 -0
  35. package/dist/watch-targets-C0Anuw17.cjs +575 -0
  36. package/dist/watch-targets-C0Anuw17.cjs.map +1 -0
  37. package/package.json +80 -27
  38. package/schemas/twee-ts.config.schema.json +55 -17
  39. package/dist/index.js.map +0 -1
  40. package/dist/paths-BuTAg2av.js +0 -7044
  41. package/dist/paths-BuTAg2av.js.map +0 -1
  42. package/dist/types-D8Xfe0l8.d.ts +0 -71
@@ -0,0 +1,575 @@
1
+ /*! @rohal12/twee-ts (Unlicense). Bundles third-party code under its own licence: see THIRD_PARTY_NOTICES. */
2
+ const require_diagnostic_text = require("./diagnostic-text-BRddVulf.cjs");
3
+ let node_path = require("node:path");
4
+ let node_fs = require("node:fs");
5
+ //#region src/plugins/diagnostics.ts
6
+ /** Returns the warnings; throws a LocatedError when the compile reported errors. */
7
+ function splitDiagnostics(result) {
8
+ const errors = result.diagnostics.filter((d) => d.level === "error");
9
+ if (errors.length === 0) return result.diagnostics.filter((d) => d.level === "warning");
10
+ const error = new Error(errors.map(require_diagnostic_text.formatDiagnostic).join("\n"));
11
+ const [first] = errors;
12
+ if (first?.file) {
13
+ error.id = first.file;
14
+ error.loc = {
15
+ file: first.file,
16
+ line: first.line ?? 1,
17
+ column: 1
18
+ };
19
+ }
20
+ throw error;
21
+ }
22
+ /** An error thrown by the compiler or bundler, with a TweeTsError's error diagnostics folded into its message. */
23
+ function fatalError(e) {
24
+ if (e instanceof require_diagnostic_text.TweeTsError) {
25
+ const errors = e.diagnostics.filter((d) => d.level === "error").map(require_diagnostic_text.formatDiagnostic);
26
+ return new Error([...errors, e.message].join("\n"));
27
+ }
28
+ return e instanceof Error ? e : new Error(String(e));
29
+ }
30
+ /**
31
+ * Compiles the story for a plugin, leaving out what a build writes (`outputs`).
32
+ * `writesStory` is whether the story goes to a file (a build, not the dev server): a story path in `outputs`
33
+ * that holds an authored file of a source folder then fails the compile (`OUTPUT_IS_INPUT`), as a named output
34
+ * does. Throws a LocatedError when the compile fails or reports errors.
35
+ */
36
+ async function compileStory(options, outputs, cache, writesStory = false) {
37
+ let result;
38
+ try {
39
+ result = await require_diagnostic_text.compileForOutputFile(options, writesStory ? outputs : {
40
+ files: outputs.files,
41
+ dirs: outputs.dirs
42
+ }, cache);
43
+ } catch (e) {
44
+ throw fatalError(e);
45
+ }
46
+ return {
47
+ output: result.output,
48
+ warnings: splitDiagnostics(result).map(require_diagnostic_text.formatDiagnostic)
49
+ };
50
+ }
51
+ //#endregion
52
+ //#region src/plugins/paths.ts
53
+ /**
54
+ * Path helpers for the bundler plugins. Watchers and bundlers spell one file
55
+ * differently: macOS FSEvents reports /private/var/… for a file under /var/…,
56
+ * Vite resolves module ids through symbolic links, Windows keeps a short 8.3
57
+ * folder name (C:\Users\RUNNER~1) where another tool gives the long one, and
58
+ * a case-insensitive volume takes any letter case. So the plugins compare
59
+ * files by their identity key (see path-identity.ts), and spell a path they
60
+ * hand a watcher by its canonical (real) path.
61
+ */
62
+ /** The real path of `path`, with forward slashes: how the Vite plugin spells a path it hands a watcher. */
63
+ function canonicalPath(path) {
64
+ return toPosix(require_diagnostic_text.identify(path).canonical);
65
+ }
66
+ /** The key a file is compared by: two paths name the same file exactly when their keys are equal. */
67
+ function fileKey(path) {
68
+ return require_diagnostic_text.identify(path).key;
69
+ }
70
+ /** Whether the file with key `key` is one of the folders (or files) with keys `within`, or inside one. */
71
+ function keyWithin(key, within) {
72
+ return within.some((outer) => require_diagnostic_text.isKeyInside(key, outer, node_path.sep));
73
+ }
74
+ /**
75
+ * The absolute path a bundle writes the file it emits as `fileName` to: inside
76
+ * `output.dir`, or next to `output.file`, either resolved against the working
77
+ * directory, as the bundler resolves them. Undefined when the output names
78
+ * neither, as for a bundle only generated in memory.
79
+ */
80
+ function emittedFilePath(output, fileName) {
81
+ const dir = output.dir ?? (output.file === void 0 ? void 0 : (0, node_path.dirname)(output.file));
82
+ return dir === void 0 ? void 0 : (0, node_path.resolve)(dir, fileName);
83
+ }
84
+ /**
85
+ * The locations a bundler's `output` option names: one output's settings or an
86
+ * array of them, as a config gives them. Outputs that name neither `dir` nor
87
+ * `file`, and anything that isn't an output's settings, are left out.
88
+ */
89
+ function outputLocations(option) {
90
+ return (Array.isArray(option) ? option : [option]).flatMap((output) => {
91
+ if (typeof output !== "object" || output === null) return [];
92
+ const dir = "dir" in output ? output.dir : void 0;
93
+ const file = "file" in output ? output.file : void 0;
94
+ const location = {
95
+ ...typeof dir === "string" ? { dir } : {},
96
+ ...typeof file === "string" ? { file } : {}
97
+ };
98
+ return location.dir === void 0 && location.file === void 0 ? [] : [location];
99
+ });
100
+ }
101
+ /** An empty OutputRecord for a plugin that writes its story as `storyFileName`. */
102
+ function createOutputRecord(storyFileName) {
103
+ const files = /* @__PURE__ */ new Set();
104
+ const stories = /* @__PURE__ */ new Set();
105
+ const dirs = /* @__PURE__ */ new Set();
106
+ const addFiles = (output, fileNames) => {
107
+ for (const fileName of fileNames) {
108
+ const path = emittedFilePath(output, fileName);
109
+ if (path !== void 0) files.add(path);
110
+ }
111
+ };
112
+ return {
113
+ addLocation(output) {
114
+ if (output.dir !== void 0) dirs.add((0, node_path.resolve)(output.dir));
115
+ if (output.file !== void 0) files.add((0, node_path.resolve)(output.file));
116
+ addFiles(output, [storyFileName]);
117
+ const story = emittedFilePath(output, storyFileName);
118
+ if (story !== void 0) stories.add(story);
119
+ },
120
+ addFiles,
121
+ outputs: () => ({
122
+ files: [...files],
123
+ stories: [...stories],
124
+ dirs: [...dirs]
125
+ })
126
+ };
127
+ }
128
+ /**
129
+ * The path with the platform's separators turned into forward slashes. Only Windows has a backslash separator;
130
+ * on POSIX a backslash is an ordinary filename character and stays one.
131
+ */
132
+ function toPosix(path) {
133
+ return node_path.sep === "\\" ? path.replaceAll("\\", "/") : path;
134
+ }
135
+ /**
136
+ * Whether `file` is a temporary copy of a Vite config file. Vite writes one next
137
+ * to the config file each time it loads it (when no node_modules folder is
138
+ * above the config, and always under Deno), then deletes it.
139
+ */
140
+ function isViteConfigTemp(file) {
141
+ return /\.timestamp-\d+-[0-9a-f]*\.mjs$/.test(file);
142
+ }
143
+ //#endregion
144
+ //#region src/plugins/options.ts
145
+ /**
146
+ * The options both bundler plugins take, checked once where the plugin is
147
+ * created and turned into what the plugin works with: the compile options of a
148
+ * build, the files whose changes rebuild the story, and which of them
149
+ * `compileOptions.exclude` leaves out. The Vite and the Rollup plugin share this,
150
+ * so the same options mean the same thing in both.
151
+ */
152
+ /** The option names each plugin accepts. */
153
+ const OPTION_NAMES = {
154
+ rollup: [
155
+ "sources",
156
+ "format",
157
+ "outputFilename",
158
+ "compileOptions"
159
+ ],
160
+ vite: [
161
+ "sources",
162
+ "format",
163
+ "outputFilename",
164
+ "compileOptions",
165
+ "entry"
166
+ ]
167
+ };
168
+ /** The compile options each plugin sets from an option of its own, by that option's name. */
169
+ const PLUGIN_SET_COMPILE_OPTIONS = [["sources", "sources"], ["formatId", "format"]];
170
+ function fail(kind, message) {
171
+ throw new require_diagnostic_text.TweeTsError(`twee-ts ${kind} plugin: ${message}`, [], { code: "INVALID_OPTIONS" });
172
+ }
173
+ /** The oldest Vite the plugin works with (the `vite` peer dependency). */
174
+ const MINIMUM_VITE_MAJOR = 8;
175
+ /**
176
+ * Throws a TweeTsError (`INVALID_OPTIONS`) that names twee-ts and the Vite version when Vite is older than the
177
+ * plugin supports, instead of the obscure failure an older Vite gives (a missing `index.html`, say). A version
178
+ * that is not a SemVer version (a custom build) is accepted.
179
+ */
180
+ function checkViteVersion(viteVersion) {
181
+ const parsed = require_diagnostic_text.parseVersion(viteVersion);
182
+ if (parsed === null) return;
183
+ if (parsed.major < MINIMUM_VITE_MAJOR) fail("vite", `Vite ${viteVersion} is not supported; the plugin needs Vite ${MINIMUM_VITE_MAJOR} or newer. Upgrade Vite, or use an older twee-ts release for this Vite.`);
184
+ }
185
+ /**
186
+ * Characters a file name can't hold on every file system (Windows rejects
187
+ * `<>:"|?*`, the control characters and `\`), and those a URL path reads
188
+ * differently from the file name (`#`, `?`, `%`).
189
+ */
190
+ const UNPORTABLE = /[\u0000-\u001f\u007f<>:"|?*#%\\]/;
191
+ /** Names Windows reserves for devices, with or without an extension. */
192
+ const WINDOWS_DEVICE = /^(con|prn|aux|nul|com[0-9¹²³]|lpt[0-9¹²³])(\..*)?$/i;
193
+ /**
194
+ * Why `name` can't be an output file name, or undefined when it can. It must be
195
+ * a relative path: names separated by forward slashes, none of them empty, `.`
196
+ * or `..`, nor one a file system or a URL would read differently. The bundler
197
+ * writes it inside the output folder, and the dev server serves it at the same
198
+ * path under the base URL.
199
+ */
200
+ function outputFilenameProblem(name) {
201
+ if (name === "") return "it is empty";
202
+ if (UNPORTABLE.test(name)) return "it holds a character that is not portable in a file name or URL path";
203
+ if (name.startsWith("/")) return "it is an absolute path";
204
+ const segments = name.split("/");
205
+ if (segments.includes("")) return "it has an empty name between slashes, or ends with a slash";
206
+ if (segments.some((segment) => segment === "." || segment === "..")) return "it has a \".\" or \"..\" segment";
207
+ if (segments.some((segment) => segment.endsWith(".") || segment.endsWith(" "))) return "a name in it ends with \".\" or a space, which Windows drops";
208
+ if (segments.some((segment) => WINDOWS_DEVICE.test(segment))) return "a name in it is reserved on Windows";
209
+ }
210
+ function checkString(kind, value, name) {
211
+ if (value !== void 0 && (typeof value !== "string" || value === "")) fail(kind, `\`${name}\` must be a non-empty string.`);
212
+ }
213
+ function checkStringList(kind, value, name) {
214
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item === "")) fail(kind, `\`${name}\` must be an array of non-empty strings.`);
215
+ }
216
+ /**
217
+ * Checks the options as a JavaScript caller may pass them, whatever their type
218
+ * says: an object with only the accepted option names, each of the right type.
219
+ */
220
+ function checkOptions(kind, options) {
221
+ if (!require_diagnostic_text.isRecord(options)) fail(kind, "the options must be an object.");
222
+ const accepted = OPTION_NAMES[kind];
223
+ const unknown = Object.keys(options).filter((key) => !accepted.includes(key));
224
+ if (unknown.length > 0) fail(kind, `unknown option ${unknown.map((key) => `\`${key}\``).join(", ")}; the options are ${accepted.join(", ")}.`);
225
+ checkStringList(kind, options["sources"], "sources");
226
+ for (const name of [
227
+ "format",
228
+ "outputFilename",
229
+ "entry"
230
+ ]) checkString(kind, options[name], name);
231
+ const outputFilename = options["outputFilename"];
232
+ const problem = typeof outputFilename === "string" ? outputFilenameProblem(outputFilename) : void 0;
233
+ if (problem !== void 0) fail(kind, `\`outputFilename\` ${JSON.stringify(outputFilename)} can't be used: ${problem}.`);
234
+ const compileOptions = options["compileOptions"];
235
+ if (compileOptions === void 0) return;
236
+ if (!require_diagnostic_text.isRecord(compileOptions)) fail(kind, "`compileOptions` must be an object.");
237
+ for (const [key, own] of PLUGIN_SET_COMPILE_OPTIONS) if (Object.hasOwn(compileOptions, key)) fail(kind, `\`compileOptions.${key}\` is not accepted; set the plugin's \`${own}\` option instead.`);
238
+ const errors = require_diagnostic_text.compileOptionErrors(compileOptions, [], "compileOptions.");
239
+ if (errors.length > 0) fail(kind, errors.join(" "));
240
+ }
241
+ /** Absolute forward-slash path of a path given relative to the working directory. */
242
+ function absolute(path) {
243
+ return toPosix((0, node_path.resolve)(path));
244
+ }
245
+ /**
246
+ * How the compiler spells `file` when it finds it by walking each source it is inside: the source
247
+ * as given, then the file's path below it. A watcher may report the real path of a file the sources
248
+ * (and so the exclude globs) reach through a link, which the globs would otherwise not match.
249
+ */
250
+ function spellingsUnderSources(file, sources) {
251
+ const real = require_diagnostic_text.identify(file).canonical;
252
+ return sources.flatMap((source) => {
253
+ const below = (0, node_path.relative)(require_diagnostic_text.identify(source).canonical, real);
254
+ return below === ".." || below.startsWith(`..${node_path.sep}`) || (0, node_path.isAbsolute)(below) ? [] : [(0, node_path.join)((0, node_path.resolve)(source), below)];
255
+ });
256
+ }
257
+ /**
258
+ * Checks a plugin's options and resolves them. Throws a TweeTsError naming the
259
+ * option for anything outside what the plugin supports: an unknown option, a
260
+ * value of the wrong type, `compileOptions.sources` or `compileOptions.formatId`
261
+ * (the plugin's `sources` and `format` set them), or an output file name that
262
+ * is not a plain relative path.
263
+ */
264
+ function resolvePluginOptions(kind, options) {
265
+ checkOptions(kind, options);
266
+ const { sources, format, entry } = options;
267
+ const compileOptions = { ...options.compileOptions };
268
+ const { headFile, modules = [], exclude = [] } = compileOptions;
269
+ const notExcludable = [...headFile === void 0 ? [] : [headFile], ...modules].map(absolute);
270
+ return {
271
+ sources: [...sources],
272
+ format,
273
+ outputFilename: options.outputFilename ?? "index.html",
274
+ compileOptions,
275
+ entry: entry === void 0 ? void 0 : (0, node_path.resolve)(entry),
276
+ inputs: [...sources.map(absolute), ...notExcludable],
277
+ excluded: (file) => exclude.length > 0 && [file, ...spellingsUnderSources(file, sources)].some((spelling) => require_diagnostic_text.isExcluded(spelling, exclude)) && !notExcludable.some((path) => require_diagnostic_text.isSameOrInside(file, path)),
278
+ compile: (inline = []) => ({
279
+ ...compileOptions,
280
+ sources: [...sources, ...inline],
281
+ formatId: format
282
+ })
283
+ };
284
+ }
285
+ //#endregion
286
+ //#region src/plugins/watch-targets.ts
287
+ /**
288
+ * What a bundler's watch mode (`rollup --watch`, `vite build --watch`) is told
289
+ * to watch for the story, whose inputs the plugins read outside the module
290
+ * graph. Rollup's watcher and the Rolldown watcher of later Vite 8 releases
291
+ * watch a registered folder recursively; earlier ones see only the folder's own
292
+ * entries. So every path is registered on its own as well.
293
+ */
294
+ const NOTHING = {
295
+ targets: [],
296
+ whole: false
297
+ };
298
+ /**
299
+ * The paths to register for the inputs (forward-slash paths): every file under
300
+ * them that source discovery reads, but those `skip` returns true for, and no
301
+ * path the build writes (`outputs`). With `real` spelling, each link an input is reached through is registered as
302
+ * authored too, every hop of a chain of links (see linksOnTheWay), but those that lead to a folder holding an output.
303
+ *
304
+ * A folder is registered, with what it holds, only when watching it reports
305
+ * nothing the story leaves out: nothing below it is skipped (an `exclude`
306
+ * match), is an output or holds one, or is a link to a folder (which source
307
+ * discovery doesn't follow, and which may lead to the output). Of any other
308
+ * folder only what it holds is registered, minus those, so writing the outputs
309
+ * or editing an excluded file starts no build. A file added straight to such a folder is read at the next build
310
+ * something else starts. An input that can't be read is registered as it is
311
+ * (unless it is an output folder), so its creation may start a build; below an
312
+ * input, what can't be read is left out, as source discovery leaves it out.
313
+ */
314
+ function watchTargets(inputs, skip, outputs, spelling) {
315
+ return watchPlan(inputs, skip, outputs, spelling).targets;
316
+ }
317
+ /** What watchTargets registers for the inputs, and the links they are reached through. */
318
+ function watchPlan(inputs, skip, outputs, spelling) {
319
+ const links = /* @__PURE__ */ new Set();
320
+ /** Every link on the way to `path`, noted; those registered by real path are the ones that lead to no output. */
321
+ const hopsOf = (path) => {
322
+ const hops = linksOnTheWay(path);
323
+ for (const hop of hops) links.add(hop);
324
+ return hops.filter((hop) => !outputs.holds(require_diagnostic_text.realPathOf(hop))).map(toPosix);
325
+ };
326
+ const reals = /* @__PURE__ */ new Map();
327
+ const spell = (path, real, isRoot) => {
328
+ if (spelling === "real") return [toPosix(real), ...isRoot || isLink(path) ? hopsOf(path) : []];
329
+ if (!isRoot && isLink(path)) for (const hop of linksOnTheWay(path)) links.add(hop);
330
+ if (isLoop(path)) return [];
331
+ if (!isLoop(real)) reals.set(path, real);
332
+ return [path];
333
+ };
334
+ const walk = (path, real, isRoot) => {
335
+ if (outputs.isFile(real) || !isRoot && outputs.isDir(real)) return NOTHING;
336
+ let entry;
337
+ let names;
338
+ try {
339
+ entry = isRoot ? {
340
+ stat: (0, node_fs.statSync)(path),
341
+ real
342
+ } : require_diagnostic_text.walkedEntry(path, real);
343
+ if (entry === void 0 || outputs.isFile(entry.real)) return NOTHING;
344
+ if (!entry.stat.isDirectory()) return skip(path) ? NOTHING : {
345
+ targets: spell(path, entry.real, isRoot),
346
+ whole: true
347
+ };
348
+ names = (0, node_fs.readdirSync)(path);
349
+ } catch {
350
+ return isRoot && !outputs.isDir(real) ? {
351
+ targets: spell(path, real, isRoot),
352
+ whole: true
353
+ } : NOTHING;
354
+ }
355
+ const folder = entry.real;
356
+ const children = names.map((name) => walk(`${path}/${name}`, (0, node_path.join)(folder, name), false));
357
+ const held = children.flatMap((child) => child.targets);
358
+ const whole = !outputs.holds(folder) && children.every((child) => child.whole);
359
+ return whole ? {
360
+ targets: [...spell(path, folder, isRoot), ...held],
361
+ whole
362
+ } : {
363
+ targets: held,
364
+ whole
365
+ };
366
+ };
367
+ const targets = inputs.flatMap((input) => {
368
+ for (const link of linksOnTheWay(input)) links.add(link);
369
+ return [...spelling === "real" ? ancestorLinks(input, outputs) : [], ...walk(input, require_diagnostic_text.realPathOf(input), true).targets];
370
+ });
371
+ return {
372
+ targets: [...new Set(targets)],
373
+ links: [...links],
374
+ reals
375
+ };
376
+ }
377
+ /**
378
+ * The paths to register, besides the real paths of the files a bundle read, so that the build watch sees what
379
+ * changes how the entry's imports resolve: for each spelling (absolute) of an import that reaches a file through
380
+ * links, every link on the way (see linksOnTheWay), the links a link leads through too (replacing any of them changes
381
+ * the file the import reads); and for a spelling
382
+ * that reaches nothing, the nearest folder that exists, where creating the file shows (a bundle that failed for a
383
+ * missing import). A folder that holds a build output is left out, since the watcher would report what the build
384
+ * writes there and rebuild for ever: a file created straight in it is read with the next build something else starts.
385
+ */
386
+ function importWatchTargets(authored, outputs) {
387
+ const targets = /* @__PURE__ */ new Set();
388
+ const missing = [];
389
+ for (const spelling of authored) {
390
+ if ((0, node_fs.existsSync)(spelling)) {
391
+ if (toPosix(require_diagnostic_text.realPathOf(spelling)) === toPosix(spelling)) continue;
392
+ for (const link of linksOnTheWay(spelling)) if (!outputs.holds(require_diagnostic_text.realPathOf(link))) targets.add(toPosix(link));
393
+ continue;
394
+ }
395
+ missing.push(spelling);
396
+ }
397
+ for (const folder of missingImportFolders(missing)) if (!outputs.holds(require_diagnostic_text.realPathOf(folder))) targets.add(toPosix(folder));
398
+ return [...targets];
399
+ }
400
+ /**
401
+ * The nearest folder that exists, for each of the paths in `authored` that reaches nothing: where creating that
402
+ * file (or the folders above it) shows. Of a path that exists there is none, and neither is the root of a file
403
+ * system (an absolute import such as `/missing.js`, which Vite reads from the project root first), which no watcher
404
+ * is asked to watch whole.
405
+ */
406
+ function missingImportFolders(authored) {
407
+ const folders = /* @__PURE__ */ new Set();
408
+ for (const spelling of authored) {
409
+ if ((0, node_fs.existsSync)(spelling)) continue;
410
+ let folder = (0, node_path.dirname)(spelling);
411
+ while (!(0, node_fs.existsSync)(folder) && (0, node_path.dirname)(folder) !== folder) folder = (0, node_path.dirname)(folder);
412
+ if ((0, node_fs.existsSync)(folder) && (0, node_path.dirname)(folder) !== folder) folders.add(folder);
413
+ }
414
+ return [...folders];
415
+ }
416
+ /**
417
+ * The links among the folders above `path`, as authored (forward slashes), every hop of a chain, in the order they are
418
+ * followed. Replacing one of them changes what the input is, and only its own location sees that. A link directly in
419
+ * the root of the file system (`/var` on macOS) is the system's own alias and is left out, as is a link to a folder that
420
+ * holds a build output, since watching it whole would rebuild for what the build writes.
421
+ */
422
+ function ancestorLinks(path, outputs) {
423
+ return linksOnTheWay((0, node_path.dirname)(path)).filter((link) => !outputs.holds(require_diagnostic_text.realPathOf(link))).map(toPosix);
424
+ }
425
+ /** How many links the file system follows for one path before it gives up (ELOOP on Linux). */
426
+ const MAX_LINK_HOPS = 40;
427
+ /**
428
+ * Every link the file system follows to reach `path`, in the order it follows them: each link along the path, and
429
+ * along the target each one leads to, so every hop of a link to a link (a chain) is there. A link directly in the
430
+ * root of the file system (`/var` on macOS) is the system's own alias and is left out. The walk ends where a name
431
+ * reaches nothing, or after as many hops as the file system follows.
432
+ */
433
+ function linksOnTheWay(path) {
434
+ const links = [];
435
+ /** The names of a path or a link's target below its root; `..` is kept for the walk to take. */
436
+ const names = (text, root) => text.slice(root.length).split(/[/\\]/).filter((name) => name !== "" && name !== ".");
437
+ const start = (0, node_path.resolve)(path);
438
+ let reached = (0, node_path.parse)(start).root;
439
+ let rest = names(start, reached);
440
+ for (let hops = 0; rest.length > 0 && hops <= MAX_LINK_HOPS;) {
441
+ const [name = "", ...more] = rest;
442
+ rest = more;
443
+ if (name === "..") {
444
+ reached = (0, node_path.dirname)(reached);
445
+ continue;
446
+ }
447
+ const next = (0, node_path.join)(reached, name);
448
+ let target;
449
+ try {
450
+ target = (0, node_fs.lstatSync)(next).isSymbolicLink() ? (0, node_fs.readlinkSync)(next) : void 0;
451
+ } catch {
452
+ break;
453
+ }
454
+ if (target === void 0) {
455
+ reached = next;
456
+ continue;
457
+ }
458
+ hops += 1;
459
+ if ((0, node_path.dirname)(next) !== (0, node_path.dirname)((0, node_path.dirname)(next))) links.push(next);
460
+ const root = (0, node_path.isAbsolute)(target) ? (0, node_path.parse)(target).root : "";
461
+ if (root !== "") reached = root;
462
+ rest = [...names(target, root), ...rest];
463
+ }
464
+ return links;
465
+ }
466
+ /** Whether `path` is a loop of links, which the file system gives up following (ELOOP). */
467
+ function isLoop(path) {
468
+ try {
469
+ (0, node_fs.statSync)(path);
470
+ return false;
471
+ } catch (error) {
472
+ return error instanceof Error && Reflect.get(error, "code") === "ELOOP";
473
+ }
474
+ }
475
+ /** Whether `path` is a symbolic link (or a Windows junction); a path that can't be read is none. */
476
+ function isLink(path) {
477
+ try {
478
+ return (0, node_fs.lstatSync)(path).isSymbolicLink();
479
+ } catch {
480
+ return false;
481
+ }
482
+ }
483
+ //#endregion
484
+ Object.defineProperty(exports, "canonicalPath", {
485
+ enumerable: true,
486
+ get: function() {
487
+ return canonicalPath;
488
+ }
489
+ });
490
+ Object.defineProperty(exports, "checkViteVersion", {
491
+ enumerable: true,
492
+ get: function() {
493
+ return checkViteVersion;
494
+ }
495
+ });
496
+ Object.defineProperty(exports, "compileStory", {
497
+ enumerable: true,
498
+ get: function() {
499
+ return compileStory;
500
+ }
501
+ });
502
+ Object.defineProperty(exports, "createOutputRecord", {
503
+ enumerable: true,
504
+ get: function() {
505
+ return createOutputRecord;
506
+ }
507
+ });
508
+ Object.defineProperty(exports, "fatalError", {
509
+ enumerable: true,
510
+ get: function() {
511
+ return fatalError;
512
+ }
513
+ });
514
+ Object.defineProperty(exports, "fileKey", {
515
+ enumerable: true,
516
+ get: function() {
517
+ return fileKey;
518
+ }
519
+ });
520
+ Object.defineProperty(exports, "importWatchTargets", {
521
+ enumerable: true,
522
+ get: function() {
523
+ return importWatchTargets;
524
+ }
525
+ });
526
+ Object.defineProperty(exports, "isViteConfigTemp", {
527
+ enumerable: true,
528
+ get: function() {
529
+ return isViteConfigTemp;
530
+ }
531
+ });
532
+ Object.defineProperty(exports, "keyWithin", {
533
+ enumerable: true,
534
+ get: function() {
535
+ return keyWithin;
536
+ }
537
+ });
538
+ Object.defineProperty(exports, "missingImportFolders", {
539
+ enumerable: true,
540
+ get: function() {
541
+ return missingImportFolders;
542
+ }
543
+ });
544
+ Object.defineProperty(exports, "outputLocations", {
545
+ enumerable: true,
546
+ get: function() {
547
+ return outputLocations;
548
+ }
549
+ });
550
+ Object.defineProperty(exports, "resolvePluginOptions", {
551
+ enumerable: true,
552
+ get: function() {
553
+ return resolvePluginOptions;
554
+ }
555
+ });
556
+ Object.defineProperty(exports, "toPosix", {
557
+ enumerable: true,
558
+ get: function() {
559
+ return toPosix;
560
+ }
561
+ });
562
+ Object.defineProperty(exports, "watchPlan", {
563
+ enumerable: true,
564
+ get: function() {
565
+ return watchPlan;
566
+ }
567
+ });
568
+ Object.defineProperty(exports, "watchTargets", {
569
+ enumerable: true,
570
+ get: function() {
571
+ return watchTargets;
572
+ }
573
+ });
574
+
575
+ //# sourceMappingURL=watch-targets-C0Anuw17.cjs.map