@rohal12/twee-ts 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/twee-ts.js +47 -32
- package/dist/bin/twee-ts.js.map +1 -1
- package/dist/{diagnostic-text-BRddVulf.cjs → diagnostic-text-Bj-UQ0Jl.cjs} +4283 -3739
- package/dist/diagnostic-text-Bj-UQ0Jl.cjs.map +1 -0
- package/dist/{diagnostic-text-CebYCTPQ.js → diagnostic-text-DMVZfBh9.js} +4260 -3770
- package/dist/diagnostic-text-DMVZfBh9.js.map +1 -0
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +3 -3
- package/dist/{lint-VayZI_jp.js → lint-BkpfLGuP.js} +3 -3
- package/dist/{lint-VayZI_jp.js.map → lint-BkpfLGuP.js.map} +1 -1
- package/dist/plugins/rollup.cjs +9 -4
- package/dist/plugins/rollup.cjs.map +1 -1
- package/dist/plugins/rollup.d.cts +6 -0
- package/dist/plugins/rollup.d.ts +6 -0
- package/dist/plugins/rollup.js +9 -4
- package/dist/plugins/rollup.js.map +1 -1
- package/dist/plugins/vite.cjs +453 -154
- package/dist/plugins/vite.cjs.map +1 -1
- package/dist/plugins/vite.js +453 -154
- package/dist/plugins/vite.js.map +1 -1
- package/dist/{watch-targets-C0Anuw17.cjs → watch-targets-BrEYmUwU.cjs} +84 -16
- package/dist/watch-targets-BrEYmUwU.cjs.map +1 -0
- package/dist/{watch-targets-BI7jYrwa.js → watch-targets-DzvPyWDo.js} +79 -17
- package/dist/watch-targets-DzvPyWDo.js.map +1 -0
- package/package.json +2 -2
- package/dist/diagnostic-text-BRddVulf.cjs.map +0 -1
- package/dist/diagnostic-text-CebYCTPQ.js.map +0 -1
- package/dist/watch-targets-BI7jYrwa.js.map +0 -1
- package/dist/watch-targets-C0Anuw17.cjs.map +0 -1
package/dist/bin/twee-ts.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @rohal12/twee-ts (Unlicense). Bundles third-party code under its own licence: see THIRD_PARTY_NOTICES. */
|
|
3
|
-
import {
|
|
4
|
-
import { r as lintForOutputFile, t as formatLintReport } from "../lint-
|
|
3
|
+
import { $ as compareVersions, B as listCachedFormats, H as loadEntry, I as clearCachedFormats, K as writeFileAtomic, M as DEFAULT_SFA_INDICES, N as cachedUrlRecord, P as checkRemoteUrl, Pt as generateIFID, R as getCacheDir, T as VERSION, V as listRecords, X as makeFormatId, Y as getFormatSearchDirs, Z as pruneFormats, _ as tagAliasProblem, d as watchWithWriteFilter, et as parseVersion, g as scaffoldConfig, h as loadConfigFile, l as resourceLimitError, m as loadConfig, n as formatDiagnostic, o as compileForOutputFile, p as CONFIG_FILENAME, q as discoverAllFormats, t as escapeTerminalControls, tt as WatchPathError, wt as TweeTsError, z as getCacheSize } from "../diagnostic-text-DMVZfBh9.js";
|
|
4
|
+
import { r as lintForOutputFile, t as formatLintReport } from "../lint-BkpfLGuP.js";
|
|
5
5
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
//#region src/cli-request.ts
|
|
@@ -198,14 +198,17 @@ function parseCliArgs(argv) {
|
|
|
198
198
|
}
|
|
199
199
|
/** Whether `-h` or `--help` is given before any `--`, whatever else is on the line (even a malformed option). */
|
|
200
200
|
function asksForHelp(argv) {
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
201
|
+
const terminator = argv.indexOf("--");
|
|
202
|
+
return (terminator === -1 ? argv : argv.slice(0, terminator)).some((arg) => {
|
|
203
|
+
const { tokens } = parseArgs({
|
|
204
|
+
args: [arg],
|
|
205
|
+
options: OPTIONS,
|
|
206
|
+
allowPositionals: true,
|
|
207
|
+
strict: false,
|
|
208
|
+
tokens: true
|
|
209
|
+
});
|
|
210
|
+
return tokens.some((token) => token.kind === "option" && token.name === "help");
|
|
207
211
|
});
|
|
208
|
-
return tokens.some((token) => token.kind === "option" && token.name === "help");
|
|
209
212
|
}
|
|
210
213
|
/** The option a short letter stands for. */
|
|
211
214
|
function optionOfShort(letter) {
|
|
@@ -227,11 +230,17 @@ function expandShortAssignments(argv) {
|
|
|
227
230
|
const letters = assignment?.[1];
|
|
228
231
|
const value = assignment?.[2];
|
|
229
232
|
if (letters === void 0 || value === void 0) return [arg];
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
for (let index = 0; index < letters.length; index++) {
|
|
234
|
+
const name = optionOfShort(letters.charAt(index));
|
|
235
|
+
if (name === void 0) return [arg];
|
|
236
|
+
if (OPTIONS[name].type === "string") {
|
|
237
|
+
if (index !== letters.length - 1) return [arg];
|
|
238
|
+
const others = letters.slice(0, index);
|
|
239
|
+
return [...others === "" ? [] : [`-${others}`], `--${name}=${value}`];
|
|
240
|
+
}
|
|
241
|
+
if (index === letters.length - 1) throw new CliUsageError(`option ${optionLabel(name)} does not take an argument`);
|
|
242
|
+
}
|
|
243
|
+
return [arg];
|
|
235
244
|
}), ...argv.slice(options.length)];
|
|
236
245
|
}
|
|
237
246
|
function parseRequest(argv) {
|
|
@@ -481,7 +490,7 @@ function out(text) {
|
|
|
481
490
|
}
|
|
482
491
|
/** Writes a line to standard error: everything else. */
|
|
483
492
|
function log(text) {
|
|
484
|
-
process.stderr.write(`${text}\n`);
|
|
493
|
+
process.stderr.write(`${escapeTerminalControls(text, true)}\n`);
|
|
485
494
|
}
|
|
486
495
|
/**
|
|
487
496
|
* A reader that goes away (`twee-ts … | head`) closes the pipe: the rest of the output is dropped
|
|
@@ -497,7 +506,7 @@ function reportWriteErrors(stream, name) {
|
|
|
497
506
|
process.exitCode = EXIT_FAILED;
|
|
498
507
|
if (reported || name === void 0) return;
|
|
499
508
|
reported = true;
|
|
500
|
-
log(`error: Cannot write ${name}: ${e.message}`);
|
|
509
|
+
log(`error: Cannot write ${name}: ${escapeTerminalControls(e.message)}`);
|
|
501
510
|
});
|
|
502
511
|
}
|
|
503
512
|
async function main(argv) {
|
|
@@ -531,10 +540,19 @@ async function main(argv) {
|
|
|
531
540
|
}
|
|
532
541
|
}
|
|
533
542
|
function usageError(error) {
|
|
534
|
-
log(`error: ${error.message}`);
|
|
543
|
+
log(`error: ${escapeTerminalControls(error.message)}`);
|
|
535
544
|
log("Run \"twee-ts --help\" for usage.");
|
|
536
545
|
return EXIT_USAGE;
|
|
537
546
|
}
|
|
547
|
+
/** A CLI-authored hint: only its separator is a live newline; the compiler's message is escaped first. */
|
|
548
|
+
var CharsetConfigError = class extends TweeTsError {
|
|
549
|
+
constructor(error) {
|
|
550
|
+
super(`${escapeTerminalControls(error.message)}\nnote: -c is --config in twee-ts, not Tweego's --charset; twee-ts reads UTF-8 (or UTF-16 after a byte order mark) and falls back to Windows-1252.`, error.diagnostics, {
|
|
551
|
+
code: "INPUT_UNAVAILABLE",
|
|
552
|
+
cause: error
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
};
|
|
538
556
|
/** The config the request asks for, and its path (an input the output must not overwrite). */
|
|
539
557
|
function readConfig(choice) {
|
|
540
558
|
const diagnostics = [];
|
|
@@ -548,10 +566,7 @@ function readConfig(choice) {
|
|
|
548
566
|
path: choice.path
|
|
549
567
|
};
|
|
550
568
|
} catch (e) {
|
|
551
|
-
if (e instanceof TweeTsError && e.code === "INPUT_UNAVAILABLE" && looksLikeCharset(choice.path)) throw new
|
|
552
|
-
code: e.code,
|
|
553
|
-
cause: e
|
|
554
|
-
});
|
|
569
|
+
if (e instanceof TweeTsError && e.code === "INPUT_UNAVAILABLE" && looksLikeCharset(choice.path)) throw new CharsetConfigError(e);
|
|
555
570
|
throw e;
|
|
556
571
|
}
|
|
557
572
|
break;
|
|
@@ -630,10 +645,10 @@ function startWatch(options, outFile, logOptions, extraInputs) {
|
|
|
630
645
|
},
|
|
631
646
|
onError(error) {
|
|
632
647
|
process.exitCode = EXIT_FAILED;
|
|
633
|
-
if (error instanceof WatchPathError) log(`error: ${error.message}`);
|
|
648
|
+
if (error instanceof WatchPathError) log(`error: ${escapeTerminalControls(error.message)}`);
|
|
634
649
|
else {
|
|
635
650
|
logErrorDiagnostics(error);
|
|
636
|
-
log(`Build error: ${error.message}`);
|
|
651
|
+
log(`Build error: ${escapeTerminalControls(error.message)}`);
|
|
637
652
|
}
|
|
638
653
|
}
|
|
639
654
|
}, (result) => countErrors(result.diagnostics) === 0, { extraInputs });
|
|
@@ -642,9 +657,9 @@ function startWatch(options, outFile, logOptions, extraInputs) {
|
|
|
642
657
|
}
|
|
643
658
|
function logBuild(result, logOptions) {
|
|
644
659
|
if (logOptions.files) {
|
|
645
|
-
log(`\nFiles: ${result.stats.files.join(", ")}`);
|
|
660
|
+
log(`\nFiles: ${result.stats.files.map((file) => escapeTerminalControls(file)).join(", ")}`);
|
|
646
661
|
const external = result.stats.externalFiles ?? [];
|
|
647
|
-
if (external.length > 0) log(`External files: ${external.join(", ")}`);
|
|
662
|
+
if (external.length > 0) log(`External files: ${external.map((file) => escapeTerminalControls(file)).join(", ")}`);
|
|
648
663
|
}
|
|
649
664
|
if (logOptions.stats) logStats(result);
|
|
650
665
|
}
|
|
@@ -698,7 +713,7 @@ function listFormats(config) {
|
|
|
698
713
|
if (formats.size === 0) out(" (none)");
|
|
699
714
|
else for (const [id, f] of formats) {
|
|
700
715
|
const type = f.isTwine2 ? "Twine 2" : "Twine 1";
|
|
701
|
-
out(` ${id}: ${f.name || id} ${f.version} (${type})`);
|
|
716
|
+
out(` ${escapeTerminalControls(id)}: ${escapeTerminalControls(f.name || id)} ${escapeTerminalControls(f.version)} (${type})`);
|
|
702
717
|
}
|
|
703
718
|
const cachedById = /* @__PURE__ */ new Map();
|
|
704
719
|
for (const f of downloads) {
|
|
@@ -710,8 +725,8 @@ function listFormats(config) {
|
|
|
710
725
|
for (const [id, versions] of [...cachedById].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
|
|
711
726
|
const [newest, ...older] = [...versions].sort((a, b) => byVersionDescending(a.version, b.version));
|
|
712
727
|
if (!newest) continue;
|
|
713
|
-
const also = older.length > 0 ? ` (also cached: ${older.map((f) => f.version).join(", ")})` : "";
|
|
714
|
-
out(` ${id}: ${newest.name} ${newest.version}${also}`);
|
|
728
|
+
const also = older.length > 0 ? ` (also cached: ${older.map((f) => escapeTerminalControls(f.version)).join(", ")})` : "";
|
|
729
|
+
out(` ${escapeTerminalControls(id)}: ${escapeTerminalControls(newest.name)} ${escapeTerminalControls(newest.version)}${also}`);
|
|
715
730
|
}
|
|
716
731
|
}
|
|
717
732
|
}
|
|
@@ -804,7 +819,7 @@ function runCache(action) {
|
|
|
804
819
|
}
|
|
805
820
|
for (const e of entries) {
|
|
806
821
|
const date = e.modifiedAt.toISOString().slice(0, 10);
|
|
807
|
-
out(`${e.name.padEnd(16)} ${e.version.padEnd(10)} ${formatBytes(e.sizeBytes).padStart(6)} ${date}`);
|
|
822
|
+
out(`${escapeTerminalControls(e.name).padEnd(16)} ${escapeTerminalControls(e.version).padEnd(10)} ${formatBytes(e.sizeBytes).padStart(6)} ${date}`);
|
|
808
823
|
}
|
|
809
824
|
return;
|
|
810
825
|
}
|
|
@@ -814,14 +829,14 @@ function runCache(action) {
|
|
|
814
829
|
return;
|
|
815
830
|
}
|
|
816
831
|
case "path":
|
|
817
|
-
out(getCacheDir());
|
|
832
|
+
out(escapeTerminalControls(getCacheDir()));
|
|
818
833
|
return;
|
|
819
834
|
default: throw new Error(`unhandled cache action: ${String(action)}`);
|
|
820
835
|
}
|
|
821
836
|
}
|
|
822
837
|
function runCacheClear(name) {
|
|
823
838
|
const count = clearCachedFormats(name);
|
|
824
|
-
if (count === 0) out(name ? `No cached formats matching "${name}".` : "Cache is already empty.");
|
|
839
|
+
if (count === 0) out(name ? `No cached formats matching "${escapeTerminalControls(name)}".` : "Cache is already empty.");
|
|
825
840
|
else out(`Cleared ${count} cached format${count === 1 ? "" : "s"}.`);
|
|
826
841
|
}
|
|
827
842
|
reportWriteErrors(process.stdout, "standard output");
|
|
@@ -831,7 +846,7 @@ main(process.argv.slice(2)).then((status) => {
|
|
|
831
846
|
}, (thrown) => {
|
|
832
847
|
const err = resourceLimitError(thrown) ?? thrown;
|
|
833
848
|
logErrorDiagnostics(err);
|
|
834
|
-
log(`error: ${err instanceof Error ? err.message : String(err)}`);
|
|
849
|
+
log(`error: ${err instanceof CharsetConfigError ? err.message : escapeTerminalControls(err instanceof Error ? err.message : String(err))}`);
|
|
835
850
|
process.exitCode = EXIT_FAILED;
|
|
836
851
|
});
|
|
837
852
|
//#endregion
|
package/dist/bin/twee-ts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twee-ts.js","names":["_exhaustive"],"sources":["../../src/cli-request.ts","../../src/stream-errors.ts","../../bin/twee-ts.ts"],"sourcesContent":["/**\n * The command line, parsed completely into a typed request before anything runs.\n *\n * parseCliArgs() turns argv into a CliRequest or a CliUsageError; it never reads a file. resolveBuild()\n * then merges a build request with the config file into compile options. Every check that can be made on\n * the command line alone is made here: unknown options, missing or empty values, an option given twice,\n * options that conflict, tag aliases, and subcommands (only as the first word, never after `--`).\n */\nimport { parseArgs } from 'node:util';\nimport type { ExcludeGlob, OutputMode, TweeTsConfig, WordCountMethod } from './types.js';\nimport { tagAliasProblem } from './config.js';\n\n/** A command line that can't be run, with what to tell the user. The CLI prints it and exits with status 2. */\nexport class CliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliUsageError';\n }\n}\n\n/** Where the config comes from: `twee-ts.config.json` in the working directory, a named file, or none. */\nexport type ConfigChoice =\n { readonly kind: 'auto' } | { readonly kind: 'file'; readonly path: string } | { readonly kind: 'none' };\n\n/** The build settings given on the command line; a setting not given is undefined (the config decides). */\ninterface BuildFlags {\n readonly output?: string;\n readonly outputMode?: OutputMode;\n readonly formatId?: string;\n readonly startPassage?: string;\n readonly modules?: readonly string[];\n readonly headFile?: string;\n readonly exclude?: readonly string[];\n readonly formatIndices?: readonly string[];\n readonly formatUrls?: readonly string[];\n /** In order, a later one replacing an earlier one for the same alias. */\n readonly tagAliases?: readonly (readonly [string, string])[];\n readonly wordCountMethod?: WordCountMethod;\n readonly trim?: false;\n readonly twee2Compat?: true;\n readonly testMode?: true;\n readonly noRemote?: true;\n readonly useDefaultFormatIndices?: false;\n readonly sourceInfo?: true;\n}\n\ntype BuildAction = 'once' | 'watch' | 'lint';\n\nexport interface BuildRequest {\n readonly kind: 'build';\n readonly action: BuildAction;\n readonly sources: readonly string[];\n readonly flags: BuildFlags;\n readonly config: ConfigChoice;\n readonly log: { readonly files: boolean; readonly stats: boolean };\n}\n\nexport type CacheAction = 'list' | 'size' | 'path';\n\nexport type CliRequest =\n | { readonly kind: 'help' }\n | { readonly kind: 'version' }\n | { readonly kind: 'init' }\n | { readonly kind: 'cache-help' }\n | { readonly kind: 'cache'; readonly action: CacheAction }\n | { readonly kind: 'cache-clear'; readonly name?: string }\n | { readonly kind: 'list-formats'; readonly config: ConfigChoice }\n | BuildRequest;\n\nexport type CliParse =\n { readonly ok: true; readonly request: CliRequest } | { readonly ok: false; readonly error: CliUsageError };\n\nconst OUTPUT_MODE_FLAGS: Readonly<Record<string, OutputMode>> = {\n 'decompile-twee3': 'twee3',\n decompile: 'twee3',\n 'decompile-twee1': 'twee1',\n 'archive-twine2': 'twine2-archive',\n 'archive-twine1': 'twine1-archive',\n json: 'json',\n};\n\nconst WORD_COUNT_METHODS: readonly WordCountMethod[] = ['tweego', 'whitespace'];\n\n/** Every option, as node:util's parseArgs takes them. docs/cli.md documents each one (test/docs-reference.test.ts). */\nexport const OPTIONS = {\n output: { type: 'string', short: 'o' },\n format: { type: 'string', short: 'f' },\n start: { type: 'string', short: 's' },\n module: { type: 'string', short: 'm', multiple: true },\n head: { type: 'string' },\n 'decompile-twee3': { type: 'boolean', short: 'd' },\n // Tweego's deprecated spelling of --decompile-twee3.\n decompile: { type: 'boolean' },\n 'decompile-twee1': { type: 'boolean' },\n 'archive-twine2': { type: 'boolean', short: 'a' },\n 'archive-twine1': { type: 'boolean' },\n json: { type: 'boolean' },\n 'twee2-compat': { type: 'boolean' },\n 'no-trim': { type: 'boolean' },\n lint: { type: 'boolean' },\n test: { type: 'boolean', short: 't' },\n watch: { type: 'boolean', short: 'w' },\n 'log-stats': { type: 'boolean', short: 'l' },\n 'log-files': { type: 'boolean' },\n 'list-formats': { type: 'boolean' },\n init: { type: 'boolean' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n 'format-index': { type: 'string', multiple: true },\n 'format-url': { type: 'string', multiple: true },\n 'no-remote': { type: 'boolean' },\n 'no-default-format-indices': { type: 'boolean' },\n 'tag-alias': { type: 'string', multiple: true },\n exclude: { type: 'string', multiple: true },\n 'source-info': { type: 'boolean' },\n 'word-count-method': { type: 'string' },\n config: { type: 'string', short: 'c' },\n 'no-config': { type: 'boolean' },\n // Tweego's, which twee-ts doesn't support; recognised to say so.\n charset: { type: 'string' },\n 'list-charsets': { type: 'boolean' },\n} as const;\n\ntype OptionName = keyof typeof OPTIONS;\n\nfunction isOptionName(name: string): name is OptionName {\n return Object.hasOwn(OPTIONS, name);\n}\n\n/** How an option is shown in messages: its short form too, when it has one. */\nfunction optionLabel(name: OptionName): string {\n const option = OPTIONS[name];\n return 'short' in option ? `-${option.short}, --${name}` : `--${name}`;\n}\n\n/** The options that stand for a whole command, which take nothing else. */\nconst QUERY_OPTIONS: readonly OptionName[] = ['version', 'init', 'list-formats'];\n\n/** The options --list-formats accepts besides itself: those that choose the config, whose formatPaths it lists. */\nconst LIST_FORMATS_OPTIONS: readonly OptionName[] = ['list-formats', 'config', 'no-config'];\n\n/** What `parseArgs` threw, as a usage message without its code or its advice about `--`. */\nfunction parseArgsMessage(e: unknown): string {\n const message = e instanceof Error ? e.message : String(e);\n const unknown = /^Unknown option '([^']+)'/.exec(message);\n if (unknown?.[1] !== undefined) return `unknown option ${unknown[1]}`;\n return message.replace(/\\n[\\s\\S]*$/, '').replace(/^Option '([^']+)'/, 'option $1');\n}\n\nfunction parseCache(rest: readonly string[]): CliRequest {\n const [action, name, ...extra] = rest;\n const tooMany = (): CliUsageError =>\n new CliUsageError(`cache ${action ?? ''} takes ${action === 'clear' ? 'at most one name' : 'no arguments'}`);\n if (rest.some((arg) => arg.startsWith('-') && arg !== '-')) {\n throw new CliUsageError(\n 'the cache subcommand takes no options; to build a folder named \"cache\", write ./cache or put -- before it',\n );\n }\n switch (action) {\n case undefined:\n return { kind: 'cache-help' };\n case 'list':\n case 'size':\n case 'path':\n if (name !== undefined) throw tooMany();\n return { kind: 'cache', action };\n case 'clear':\n if (extra.length > 0) throw tooMany();\n // An empty name (an unset variable) must not mean \"everything\".\n if (name === '') throw new CliUsageError('cache clear needs a non-empty name; write cache clear alone for all');\n return name === undefined ? { kind: 'cache-clear' } : { kind: 'cache-clear', name };\n default:\n throw new CliUsageError(`unknown cache subcommand \"${action}\"; expected list, clear, size or path`);\n }\n}\n\n/** The tag aliases of `--tag-alias alias=target` values, each one checked. */\nfunction parseTagAliases(values: readonly string[]): [string, string][] {\n return values.map((pair) => {\n const eq = pair.indexOf('=');\n if (eq === -1) throw new CliUsageError(`invalid --tag-alias \"${pair}\": expected alias=target`);\n const alias = pair.slice(0, eq);\n const target = pair.slice(eq + 1);\n const problem = tagAliasProblem(alias, target);\n if (problem !== undefined) throw new CliUsageError(`invalid --tag-alias \"${pair}\": ${problem}`);\n return [alias, target];\n });\n}\n\n/**\n * Parses the arguments after `twee-ts` into a request. Never throws: a command line that can't be run\n * gives a CliUsageError.\n */\nexport function parseCliArgs(argv: readonly string[]): CliParse {\n try {\n return { ok: true, request: parseRequest(argv) };\n } catch (e) {\n if (e instanceof CliUsageError) return { ok: false, error: e };\n throw e;\n }\n}\n\n/** Whether `-h` or `--help` is given before any `--`, whatever else is on the line (even a malformed option). */\nfunction asksForHelp(argv: readonly string[]): boolean {\n const { tokens } = parseArgs({\n args: [...argv],\n options: OPTIONS,\n allowPositionals: true,\n strict: false,\n tokens: true,\n });\n return tokens.some((token) => token.kind === 'option' && token.name === 'help');\n}\n\n/** The option a short letter stands for. */\nfunction optionOfShort(letter: string): OptionName | undefined {\n return Object.keys(OPTIONS)\n .filter(isOptionName)\n .find((name) => {\n const option = OPTIONS[name];\n return 'short' in option && option.short === letter;\n });\n}\n\n/**\n * Reads `-<letter>=<value>` as Tweego does, as `-<letter> <value>`: it becomes `--<name>=<value>`, so\n * node:util's parseArgs doesn't take `=<value>` as the value. A short option that takes no value refuses\n * one. Letters of other bundled options before it (`-do=x`) stay as they are. After `--`, nothing changes.\n */\nfunction expandShortAssignments(argv: readonly string[]): string[] {\n const terminator = argv.indexOf('--');\n const options = terminator === -1 ? argv : argv.slice(0, terminator);\n const expanded = options.flatMap((arg) => {\n const assignment = /^-([A-Za-z]+)=([\\s\\S]*)$/.exec(arg);\n const letters = assignment?.[1];\n const value = assignment?.[2];\n if (letters === undefined || value === undefined) return [arg];\n const name = optionOfShort(letters.slice(-1));\n // An unknown letter is parseArgs' to report.\n if (name === undefined) return [arg];\n if (OPTIONS[name].type !== 'string') {\n throw new CliUsageError(`option ${optionLabel(name)} does not take an argument`);\n }\n const others = letters.slice(0, -1);\n return [...(others === '' ? [] : [`-${others}`]), `--${name}=${value}`];\n });\n return [...expanded, ...argv.slice(options.length)];\n}\n\nfunction parseRequest(argv: readonly string[]): CliRequest {\n // A subcommand only as the very first word: `twee-ts -o out.html cache` builds a folder named cache.\n if (argv[0] === 'cache') return parseCache(argv.slice(1));\n // Help is asked for before anything else is checked.\n if (asksForHelp(argv)) return { kind: 'help' };\n\n let parsed;\n try {\n parsed = parseArgs({\n args: expandShortAssignments(argv),\n options: OPTIONS,\n allowPositionals: true,\n strict: true,\n tokens: true,\n });\n } catch (e) {\n throw new CliUsageError(parseArgsMessage(e));\n }\n const { values, positionals, tokens } = parsed;\n\n // Each option once, except those that may repeat.\n const given = new Map<OptionName, number>();\n for (const token of tokens) {\n if (token.kind !== 'option') continue;\n const { name } = token;\n // parseArgs (strict) only yields names from OPTIONS; the check narrows the type.\n if (!isOptionName(name)) continue;\n given.set(name, (given.get(name) ?? 0) + 1);\n const option = OPTIONS[name];\n if (!('multiple' in option) && (given.get(name) ?? 0) > 1) {\n throw new CliUsageError(`${optionLabel(name)} given more than once`);\n }\n if (token.value === '' && OPTIONS[name].type === 'string') {\n throw new CliUsageError(`${optionLabel(name)} needs a non-empty value`);\n }\n }\n // As a source anywhere else (the config, the API, the plugins), an empty one names nothing.\n if (positionals.includes('')) throw new CliUsageError('a source must not be empty');\n const has = (name: OptionName): boolean => given.has(name);\n const names = [...given.keys()];\n\n if (has('charset') || has('list-charsets')) {\n throw new CliUsageError(\n 'twee-ts has no --charset: sources are read as UTF-8 (or UTF-16 after a byte order mark), and a file that is not valid UTF-8 as Windows-1252, as Tweego does by default',\n );\n }\n\n for (const query of QUERY_OPTIONS) {\n if (!has(query)) continue;\n const allowed = query === 'list-formats' ? LIST_FORMATS_OPTIONS : [query];\n const other = names.find((name) => !allowed.includes(name));\n if (other !== undefined) throw new CliUsageError(`--${query} can't be combined with ${optionLabel(other)}`);\n if (positionals.length > 0) throw new CliUsageError(`--${query} takes no sources`);\n }\n if (has('config') && has('no-config')) throw new CliUsageError('-c, --config and --no-config conflict');\n const config: ConfigChoice =\n values.config !== undefined\n ? { kind: 'file', path: values.config }\n : has('no-config')\n ? { kind: 'none' }\n : { kind: 'auto' };\n if (has('version')) return { kind: 'version' };\n if (has('init')) return { kind: 'init' };\n if (has('list-formats')) return { kind: 'list-formats', config };\n\n const modeFlags = names.filter((name) => Object.hasOwn(OUTPUT_MODE_FLAGS, name));\n const [modeFlag, otherModeFlag] = modeFlags;\n if (otherModeFlag !== undefined && modeFlag !== undefined) {\n throw new CliUsageError(\n `${optionLabel(modeFlag)} and ${optionLabel(otherModeFlag)} conflict: choose one output mode`,\n );\n }\n const outputMode = modeFlag === undefined ? undefined : OUTPUT_MODE_FLAGS[modeFlag];\n\n let action: BuildAction = 'once';\n if (has('lint')) {\n const conflict = names.find(\n (name) =>\n name === 'watch' || name === 'log-stats' || name === 'log-files' || Object.hasOwn(OUTPUT_MODE_FLAGS, name),\n );\n if (conflict !== undefined) throw new CliUsageError(`--lint can't be combined with ${optionLabel(conflict)}`);\n action = 'lint';\n } else if (has('watch')) {\n if (values.output === '-')\n throw new CliUsageError('watch mode needs an output file: standard output is not supported');\n action = 'watch';\n }\n\n const wordCountMethod = values['word-count-method'];\n if (wordCountMethod !== undefined && !WORD_COUNT_METHODS.some((m) => m === wordCountMethod)) {\n throw new CliUsageError(\n `invalid --word-count-method \"${wordCountMethod}\": expected ${WORD_COUNT_METHODS.join(' or ')}`,\n );\n }\n\n const flags: BuildFlags = {\n ...(values.output === undefined ? {} : { output: values.output }),\n ...(outputMode === undefined ? {} : { outputMode }),\n ...(values.format === undefined ? {} : { formatId: values.format }),\n ...(values.start === undefined ? {} : { startPassage: values.start }),\n ...(values.module === undefined ? {} : { modules: values.module }),\n ...(values.head === undefined ? {} : { headFile: values.head }),\n ...(values.exclude === undefined ? {} : { exclude: values.exclude }),\n ...(values['format-index'] === undefined ? {} : { formatIndices: values['format-index'] }),\n ...(values['format-url'] === undefined ? {} : { formatUrls: values['format-url'] }),\n ...(values['tag-alias'] === undefined ? {} : { tagAliases: parseTagAliases(values['tag-alias']) }),\n ...(wordCountMethod === 'tweego' || wordCountMethod === 'whitespace' ? { wordCountMethod } : {}),\n ...(has('no-trim') ? { trim: false } : {}),\n ...(has('twee2-compat') ? { twee2Compat: true } : {}),\n ...(has('test') ? { testMode: true } : {}),\n ...(has('no-remote') ? { noRemote: true } : {}),\n ...(has('no-default-format-indices') ? { useDefaultFormatIndices: false } : {}),\n ...(has('source-info') ? { sourceInfo: true } : {}),\n };\n\n return {\n kind: 'build',\n action,\n sources: positionals,\n flags,\n config,\n log: { files: has('log-files'), stats: has('log-stats') },\n };\n}\n\n/** The compile options of a build request, the command line's settings winning over the config's. */\nexport interface ResolvedBuild {\n readonly action: BuildAction;\n readonly sources: readonly string[];\n /** `-` for standard output. */\n readonly output: string;\n readonly options: {\n readonly outputMode: OutputMode;\n readonly exclude?: readonly (string | ExcludeGlob)[] | undefined;\n readonly formatId?: string | undefined;\n readonly startPassage?: string | undefined;\n readonly formatPaths?: readonly string[] | undefined;\n readonly modules?: readonly string[] | undefined;\n readonly headFile?: string | undefined;\n readonly trim: boolean;\n readonly twee2Compat: boolean;\n readonly testMode: boolean;\n readonly useTweegoPath?: boolean | undefined;\n readonly formatIndices?: readonly string[] | undefined;\n readonly formatUrls?: readonly string[] | undefined;\n readonly noRemote: boolean;\n readonly formatFetchTimeout?: number | undefined;\n readonly formatResolutionTimeout?: number | undefined;\n readonly useDefaultFormatIndices: boolean;\n readonly tagAliases?: Readonly<Record<string, string>> | undefined;\n readonly sourceInfo: boolean;\n readonly wordCountMethod?: WordCountMethod | undefined;\n };\n}\n\n/**\n * Merges a build request with the config (already validated and rebased onto the working directory):\n * a setting on the command line wins, and `--tag-alias` adds to (and overrides) the config's aliases.\n * Throws a CliUsageError when no sources are given anywhere, or watch mode has no output file.\n */\nexport function resolveBuild(request: BuildRequest, config: TweeTsConfig | null): ResolvedBuild {\n const { flags } = request;\n const sources = request.sources.length > 0 ? request.sources : (config?.sources ?? []);\n if (sources.length === 0) throw new CliUsageError('no input sources: name them, or set \"sources\" in the config');\n const output = flags.output ?? config?.output ?? '-';\n if (request.action === 'watch' && output === '-') {\n throw new CliUsageError('watch mode needs an output file (-o, or \"output\" in the config)');\n }\n // Own-property-safe: Object.fromEntries defines `__proto__` as an ordinary key (#241).\n const aliasEntries = [...Object.entries(config?.tagAliases ?? {}), ...(flags.tagAliases ?? [])];\n return {\n action: request.action,\n sources,\n output,\n options: {\n outputMode: flags.outputMode ?? config?.outputMode ?? 'html',\n exclude: flags.exclude ?? config?.exclude,\n formatId: flags.formatId ?? config?.formatId,\n startPassage: flags.startPassage ?? config?.startPassage,\n formatPaths: config?.formatPaths,\n modules: flags.modules ?? config?.modules,\n headFile: flags.headFile ?? config?.headFile,\n trim: flags.trim ?? config?.trim ?? true,\n twee2Compat: flags.twee2Compat ?? config?.twee2Compat ?? false,\n testMode: flags.testMode ?? config?.testMode ?? false,\n useTweegoPath: config?.useTweegoPath,\n formatIndices: flags.formatIndices ?? config?.formatIndices,\n formatUrls: flags.formatUrls ?? config?.formatUrls,\n noRemote: flags.noRemote ?? config?.noRemote ?? false,\n formatFetchTimeout: config?.formatFetchTimeout,\n formatResolutionTimeout: config?.formatResolutionTimeout,\n useDefaultFormatIndices: flags.useDefaultFormatIndices ?? config?.useDefaultFormatIndices ?? true,\n tagAliases:\n aliasEntries.length > 0 || config?.tagAliases !== undefined ? Object.fromEntries(aliasEntries) : undefined,\n sourceInfo: flags.sourceInfo ?? config?.sourceInfo ?? false,\n wordCountMethod: flags.wordCountMethod ?? config?.wordCountMethod,\n },\n };\n}\n\n/** Whether a `-c` value that names no file looks like a charset, as Tweego's `-c` takes one. */\nexport function looksLikeCharset(value: string): boolean {\n return /^(?:utf-?(?:8|16(?:le|be)?|32)|windows-\\d{3,4}|cp\\d{3,4}|iso-?8859-\\d{1,2}|latin-?\\d|(?:us-)?ascii|macintosh|koi8-[ru]|shift[-_]jis|euc-[a-z]{2}|gbk|big5)$/i.test(\n value,\n );\n}\n\n/** The help text. */\nexport function usageText(version: string, configFilename: string): string {\n return `twee-ts v${version} — TypeScript Twee-to-HTML compiler\n\nUsage: twee-ts [options] <sources...>\n twee-ts cache <list|clear [name]|size|path>\n\nOptions:\n -o, --output <file> Output file; - for standard output (default)\n -f, --format <id> Story format ID (default: sugarcube-2)\n -s, --start <name> Starting passage (default: Start)\n -m, --module <file> Module file to inject into <head> (repeatable)\n --head <file> Raw HTML file to append to <head>\n -d, --decompile-twee3 Output as Twee 3 source\n --decompile-twee1 Output as Twee 1 source\n -a, --archive-twine2 Output as Twine 2 archive\n --archive-twine1 Output as Twine 1 archive\n --json Output as JSON\n --twee2-compat Enable Twee2 syntax compatibility\n --lint Lint story structure (broken links, dead ends, orphans)\n --no-trim Don't trim passage whitespace\n -t, --test Enable test/debug mode\n -w, --watch Watch for changes and rebuild\n -l, --log-stats Log compilation statistics (to standard error)\n --log-files Log the files read (to standard error)\n --list-formats List available story formats\n --init Initialize a new project\n --format-index <url> SFA-compatible format index URL (repeatable)\n --format-url <url> Direct format.js URL (repeatable)\n --tag-alias <alias=target> Map a tag to a special tag (repeatable)\n --exclude <glob> Leave out source files matching a glob (repeatable)\n --source-info Emit source file/line as data- attributes on passages\n --word-count-method <m> Word counting method: tweego (default), whitespace\n --no-remote Disable remote format fetching\n --no-default-format-indices\n Don't ask the Story Formats Archive indices\n -c, --config <file> Config file path (default: ${configFilename})\n --no-config Skip config file loading\n -h, --help Show this help\n -v, --version Show version\n\nUse -- before sources whose names start with - (or a first source named cache).\n\nSubcommands:\n cache list List cached remote formats\n cache clear [name] Clear cached formats (all or by name)\n cache size Show total cache size\n cache path Print cache directory path\n\nExit status: 0 success, 1 build or lint errors, 2 usage errors.`;\n}\n\n/** The help text of the cache subcommand. */\nexport const CACHE_USAGE = `Usage: twee-ts cache <list|clear|size|path>\n\n list List cached formats with name, version, size\n clear Delete all cached formats\n clear <name> Delete cached formats matching name\n size Show total cache size\n path Print cache directory path`;\n","/**\n * Which errors of a write to a stream mean the reader at the other end has gone, as opposed to a write that\n * failed (a full disk, an I/O error, a closed descriptor).\n *\n * Writing to a pipe or socket whose reader has closed is reported differently by each platform; libuv passes\n * the operating system's error on:\n *\n * - `EPIPE`: Linux and macOS (the signal is ignored by Node), and Windows named pipes whose other end is\n * closing (`ERROR_NO_DATA`, `ERROR_PIPE_NOT_CONNECTED`).\n * - `EOF`: Windows named pipes whose other end is closed (`ERROR_BROKEN_PIPE`), which libuv reports as its\n * own end-of-file code.\n * - `ENOTCONN`: macOS, for a pipe or socket pair whose peer is gone, where Linux gives `EPIPE`; Windows sockets.\n * - `ECONNRESET`, `ECONNABORTED`: the peer reset or aborted the connection (a socket as standard output).\n * - `ESHUTDOWN`: the socket was shut down for writing.\n * - `ERR_STREAM_DESTROYED`: Node's own error for a write after the stream has been destroyed, which follows\n * any of the above.\n */\nconst READER_GONE: ReadonlySet<string> = new Set([\n 'EPIPE',\n 'EOF',\n 'ENOTCONN',\n 'ECONNRESET',\n 'ECONNABORTED',\n 'ESHUTDOWN',\n 'ERR_STREAM_DESTROYED',\n]);\n\n/** Whether a stream write error is the reader going away, which ends the output quietly. */\nexport function isReaderGone(error: { readonly code?: unknown }): boolean {\n return typeof error.code === 'string' && READER_GONE.has(error.code);\n}\n","/**\n * twee-ts CLI entry point.\n *\n * The command line is parsed completely into a request first (src/cli-request.ts), then run. Standard\n * output carries only what was asked for: the story when it goes there, or the answer of a query command\n * (--help, --version, --list-formats, cache, --lint's report, --init's report). Diagnostics, logs, --log-stats\n * and --log-files go to standard error. Exit status: 0 success, 1 build or lint errors, 2 usage errors.\n */\nimport { writeFileSync, mkdirSync } from 'node:fs';\nimport { compileForOutputFile, resourceLimitError, TweeTsError, watchWithWriteFilter } from '../src/compiler.js';\nimport type { ExtraInput } from '../src/compiler.js';\nimport { formatDiagnostic } from '../src/diagnostic-text.js';\nimport { WatchPathError } from '../src/filesystem.js';\nimport { writeFileAtomic } from '../src/atomic-write.js';\nimport { lintForOutputFile, formatLintReport } from '../src/lint.js';\nimport { discoverAllFormats, getFormatSearchDirs, makeFormatId, pruneFormats } from '../src/formats.js';\nimport { loadConfig, loadConfigFile, scaffoldConfig, CONFIG_FILENAME } from '../src/config.js';\nimport {\n CACHE_USAGE,\n CliUsageError,\n looksLikeCharset,\n parseCliArgs,\n resolveBuild,\n usageText,\n} from '../src/cli-request.js';\nimport type { BuildRequest, CacheAction, ConfigChoice, ResolvedBuild } from '../src/cli-request.js';\nimport { listRecords, loadEntry } from '../src/format-cache.js';\nimport {\n cachedUrlRecord,\n checkRemoteUrl,\n DEFAULT_SFA_INDICES,\n getCacheDir,\n listCachedFormats,\n clearCachedFormats,\n getCacheSize,\n} from '../src/remote-formats.js';\nimport type { CompileResult, Diagnostic, TweeTsConfig, WatchOptions } from '../src/types.js';\nimport { compareVersions, parseVersion } from '../src/semver.js';\n\nimport { isReaderGone } from '../src/stream-errors.js';\nimport { VERSION } from '../src/version.js';\nimport { generateIFID } from '../src/ifid.js';\n\n/** Exit statuses. */\nconst EXIT_OK = 0;\nconst EXIT_FAILED = 1;\nconst EXIT_USAGE = 2;\n\n/** Writes to standard output: only the story, or a query command's answer. */\nfunction out(text: string): void {\n process.stdout.write(text.endsWith('\\n') ? text : `${text}\\n`);\n}\n\n/** Writes a line to standard error: everything else. */\nfunction log(text: string): void {\n process.stderr.write(`${text}\\n`);\n}\n\n/**\n * A reader that goes away (`twee-ts … | head`) closes the pipe: the rest of the output is dropped\n * quietly, as other command-line tools do, instead of ending in an unhandled error (`EPIPE`, or what the\n * platform reports instead, see `isReaderGone`). Any other\n * failure to write (a full disk behind a redirect, an I/O error) is reported once, naming the stream\n * when `name` is given (standard error cannot report its own failure), and ends the run with status 1.\n */\nfunction reportWriteErrors(stream: NodeJS.WriteStream, name?: string): void {\n let reported = false;\n stream.on('error', (e: NodeJS.ErrnoException) => {\n if (isReaderGone(e)) return;\n process.exitCode = EXIT_FAILED;\n if (reported || name === undefined) return;\n reported = true;\n log(`error: Cannot write ${name}: ${e.message}`);\n });\n}\n\nasync function main(argv: readonly string[]): Promise<number> {\n const parsed = parseCliArgs(argv);\n if (!parsed.ok) return usageError(parsed.error);\n const { request } = parsed;\n switch (request.kind) {\n case 'help':\n out(usageText(VERSION, CONFIG_FILENAME));\n return EXIT_OK;\n case 'version':\n out(`twee-ts v${VERSION}`);\n return EXIT_OK;\n case 'init':\n runInit();\n return EXIT_OK;\n case 'cache-help':\n out(CACHE_USAGE);\n return EXIT_OK;\n case 'cache':\n runCache(request.action);\n return EXIT_OK;\n case 'cache-clear':\n runCacheClear(request.name);\n return EXIT_OK;\n case 'list-formats': {\n const config = readConfig(request.config);\n // Listed after the config is read, so the list shows what --format can select in this project.\n listFormats(config.config);\n return EXIT_OK;\n }\n case 'build':\n return runBuild(request);\n default: {\n const _exhaustive: never = request;\n throw new Error(`unhandled request: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\nfunction usageError(error: CliUsageError): number {\n log(`error: ${error.message}`);\n log('Run \"twee-ts --help\" for usage.');\n return EXIT_USAGE;\n}\n\n/** The config the request asks for, and its path (an input the output must not overwrite). */\nfunction readConfig(choice: ConfigChoice): { readonly config: TweeTsConfig | null; readonly path?: string } {\n // Warnings, such as unknown keys, which leave the config usable.\n const diagnostics: Diagnostic[] = [];\n let result: { readonly config: TweeTsConfig | null; readonly path?: string };\n switch (choice.kind) {\n case 'none':\n return { config: null };\n case 'file':\n try {\n result = { config: loadConfigFile(choice.path, diagnostics), path: choice.path };\n } catch (e) {\n // Tweego's -c is --charset: say so when the \"config file\" is a charset name.\n if (e instanceof TweeTsError && e.code === 'INPUT_UNAVAILABLE' && looksLikeCharset(choice.path)) {\n const note = `-c is --config in twee-ts, not Tweego's --charset; twee-ts reads UTF-8 (or UTF-16 after a byte order mark) and falls back to Windows-1252.`;\n throw new TweeTsError(`${e.message}\\nnote: ${note}`, e.diagnostics, { code: e.code, cause: e });\n }\n throw e;\n }\n break;\n case 'auto': {\n const config = loadConfig(undefined, diagnostics);\n result = config === null ? { config } : { config, path: CONFIG_FILENAME };\n break;\n }\n default: {\n const _exhaustive: never = choice;\n throw new Error(`unhandled config choice: ${JSON.stringify(_exhaustive)}`);\n }\n }\n logDiagnostics(diagnostics);\n return result;\n}\n\nasync function runBuild(request: BuildRequest): Promise<number> {\n const config = readConfig(request.config);\n let build: ResolvedBuild;\n try {\n build = resolveBuild(request, config.config);\n } catch (e) {\n if (e instanceof CliUsageError) return usageError(e);\n throw e;\n }\n const compileOptions = { ...build.options, sources: build.sources };\n // The output file, which every build (and lint) leaves out of the sources and modules,\n // so an earlier build inside a source folder is never read back as a source.\n const outPath = build.output === '-' ? undefined : build.output;\n const extraInputs: ExtraInput[] = config.path === undefined ? [] : [{ role: 'config', path: config.path }];\n\n switch (build.action) {\n case 'lint': {\n const lintResult = await lintForOutputFile(compileOptions, outPath);\n out(formatLintReport(lintResult));\n const hasErrors = lintResult.brokenLinks.length > 0 || lintResult.diagnostics.some((d) => d.level === 'error');\n return hasErrors ? EXIT_FAILED : EXIT_OK;\n }\n case 'watch':\n // resolveBuild() refuses watch mode without an output file.\n return startWatch(compileOptions, outPath ?? build.output, request.log, extraInputs);\n case 'once': {\n // An output that can't be written (a missing folder, a read-only file) fails before the build's work.\n const result = await compileForOutputFile(compileOptions, outPath, undefined, extraInputs, true);\n logDiagnostics(result.diagnostics);\n // Like Tweego, a build with errors produces no output: the output file (or stdout)\n // is left untouched and the exit status is 1, so scripts and CI can detect it.\n const errors = countErrors(result.diagnostics);\n let status = EXIT_OK;\n if (errors > 0) {\n log(`Compilation failed with ${pluralize(errors, 'error')}; output not written.`);\n status = EXIT_FAILED;\n } else if (outPath === undefined) {\n process.stdout.write(result.output);\n } else {\n writeFileAtomic(outPath, result.output);\n }\n logBuild(result, request.log);\n return status;\n }\n default: {\n const _exhaustive: never = build.action;\n throw new Error(`unhandled build action: ${String(_exhaustive)}`);\n }\n }\n}\n\n/** Starts watch mode; the process keeps running until it is stopped, or the watch stops on its own. */\nfunction startWatch(\n options: Omit<WatchOptions, 'outFile'>,\n outFile: string,\n logOptions: BuildRequest['log'],\n extraInputs: readonly ExtraInput[],\n): number {\n // As in a one-shot build, a build with errors is not written: the output file keeps\n // the last good build until a save fixes the errors.\n watchWithWriteFilter(\n {\n ...options,\n outFile,\n onBuild(result) {\n const counts = `${result.stats.passages} passages, ${result.stats.words} words`;\n const errors = countErrors(result.diagnostics);\n // A build is reported as built only when it is written (#451): the same test as the write filter below.\n if (errors === 0) log(`Built: ${counts}`);\n logDiagnostics(result.diagnostics);\n // A failed build must not stop the watcher: report it and wait for the next change.\n if (errors > 0) {\n log(`Build failed: ${counts}`);\n log(`Build has ${pluralize(errors, 'error')}; output not written. Still watching for changes.`);\n }\n logBuild(result, logOptions);\n },\n onError(error) {\n process.exitCode = EXIT_FAILED;\n if (error instanceof WatchPathError) {\n // The other paths are still watched; with nothing left to watch, the process exits with status 1.\n log(`error: ${error.message}`);\n } else {\n logErrorDiagnostics(error);\n log(`Build error: ${error.message}`);\n }\n },\n },\n (result) => countErrors(result.diagnostics) === 0,\n { extraInputs },\n );\n // Only now: watchWithWriteFilter() refuses options that cannot be watched before it watches anything.\n log('Watch mode started. Press CTRL+C to stop.');\n // Until the watch ends; the status is set by onError if it fails.\n return EXIT_OK;\n}\n\nfunction logBuild(result: CompileResult, logOptions: BuildRequest['log']): void {\n if (logOptions.files) {\n log(`\\nFiles: ${result.stats.files.join(', ')}`);\n const external = result.stats.externalFiles ?? [];\n if (external.length > 0) log(`External files: ${external.join(', ')}`);\n }\n if (logOptions.stats) logStats(result);\n}\n\nfunction countErrors(diagnostics: readonly Diagnostic[]): number {\n return diagnostics.filter((d) => d.level === 'error').length;\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\n/** Order version strings from highest to lowest SemVer precedence (unparseable ones last). */\nfunction byVersionDescending(a: string, b: string): number {\n const left = parseVersion(a);\n const right = parseVersion(b);\n if (!left || !right) return Number(!left) - Number(!right);\n return compareVersions(right, left);\n}\n\n/**\n * The cached downloads a build with these settings would consider, as resolution considers them (see\n * format-resolution.ts): the cached copy of each configured format URL, and what was downloaded from each\n * configured format index and, unless `useDefaultFormatIndices` is off, from the Story Formats Archive, each\n * under the name and version its source lists. A download from a URL or index the project doesn't configure\n * is never used, so it isn't listed; neither is an entry whose files are damaged. `cache list` lists every\n * download.\n */\nfunction consideredDownloads(\n formatUrls: readonly string[],\n formatIndices: readonly string[],\n useDefaultFormatIndices: boolean,\n diagnostics: Diagnostic[],\n): { readonly name: string; readonly version: string }[] {\n const checked = (urls: readonly string[], option: string): string[] =>\n urls.flatMap((text) => {\n const result = checkRemoteUrl(text);\n if (result.ok) return [result.url];\n diagnostics.push({ level: 'warning', message: `${option}: ${result.reason}` });\n return [];\n });\n const indices = new Set([\n ...checked(formatIndices, 'formatIndices'),\n ...(useDefaultFormatIndices ? DEFAULT_SFA_INDICES : []),\n ]);\n const fromUrls = checked(formatUrls, 'formatUrls').flatMap((url) => cachedUrlRecord(url) ?? []);\n const fromIndices = listRecords().filter((r) => r.origin.kind === 'index' && indices.has(r.origin.index));\n return [...fromUrls, ...fromIndices]\n .filter((record) => 'record' in loadEntry(record))\n .map((record) => (record.origin.kind === 'index' ? record.origin : record));\n}\n\n/**\n * Print the formats --format can select: local folders (pruned by SemVer), and the cached downloads a\n * build would consider (see consideredDownloads), by ID.\n */\nfunction listFormats(config: TweeTsConfig | null): void {\n const diagnostics: Diagnostic[] = [];\n const searchDirs = getFormatSearchDirs(config?.formatPaths ?? [], config?.useTweegoPath ?? true);\n const formats = pruneFormats(discoverAllFormats(searchDirs, diagnostics));\n const downloads = consideredDownloads(\n config?.formatUrls ?? [],\n config?.formatIndices ?? [],\n config?.useDefaultFormatIndices ?? true,\n diagnostics,\n );\n logDiagnostics(diagnostics);\n\n out('Local story formats:');\n if (formats.size === 0) {\n out(' (none)');\n } else {\n for (const [id, f] of formats) {\n const type = f.isTwine2 ? 'Twine 2' : 'Twine 1';\n out(` ${id}: ${f.name || id} ${f.version} (${type})`);\n }\n }\n\n // Cached downloads answer an ID request by name and major version, taking the greatest version.\n const cachedById = new Map<string, { readonly name: string; readonly version: string }[]>();\n for (const f of downloads) {\n const id = makeFormatId(f.name, f.version);\n cachedById.set(id, [...(cachedById.get(id) ?? []), f]);\n }\n if (cachedById.size > 0) {\n out('\\nCached remote formats:');\n for (const [id, versions] of [...cachedById].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {\n const [newest, ...older] = [...versions].sort((a, b) => byVersionDescending(a.version, b.version));\n if (!newest) continue;\n const also = older.length > 0 ? ` (also cached: ${older.map((f) => f.version).join(', ')})` : '';\n out(` ${id}: ${newest.name} ${newest.version}${also}`);\n }\n }\n}\n\n/** Prints diagnostics to standard error, each with the file and line it is about (see formatDiagnostic). */\nfunction logDiagnostics(diagnostics: readonly Diagnostic[]): void {\n for (const d of diagnostics) log(`${d.level === 'error' ? 'error' : 'warning'}: ${formatDiagnostic(d)}`);\n}\n\n/** Prints what a fatal TweeTsError collected (such as why no story format was found) before its message. */\nfunction logErrorDiagnostics(error: unknown): void {\n if (error instanceof TweeTsError) logDiagnostics(error.diagnostics);\n}\n\nfunction logStats(result: CompileResult): void {\n const s = result.stats;\n log(`\\nStatistics:`);\n log(` Passages: ${s.passages}`);\n log(` Words: ${s.words}`);\n log(` Files: ${s.files.length}`);\n}\n\ninterface ScaffoldFile {\n readonly path: string;\n readonly content: () => string;\n}\n\nconst SCAFFOLD_FILES: readonly ScaffoldFile[] = [\n { path: CONFIG_FILENAME, content: scaffoldConfig },\n {\n path: 'src/StoryData.tw',\n content: () => `:: StoryData\n{\n\\t\"ifid\": \"${generateIFID()}\"\n}\n`,\n },\n {\n path: 'src/StoryTitle.tw',\n content: () => `:: StoryTitle\nMy Story\n`,\n },\n {\n path: 'src/Start.tw',\n content: () => `:: Start\nWelcome to your new Twine story!\n\nThis is the starting passage. Edit this file to begin writing your story.\n`,\n },\n];\n\n/**\n * Writes `content` to `path` unless the file already exists.\n * The exclusive flag makes the check and the write one step, so an existing file is never truncated.\n * Returns false when the file was already there.\n */\nfunction writeNewFile(path: string, content: string): boolean {\n try {\n writeFileSync(path, content, { flag: 'wx' });\n return true;\n } catch (e) {\n if (e instanceof Error && 'code' in e && e.code === 'EEXIST') return false;\n throw new Error(`Cannot create ${path}: ${e instanceof Error ? e.message : String(e)}`, { cause: e });\n }\n}\n\nfunction runInit(): void {\n out('Initializing new twee-ts project...');\n mkdirSync('src', { recursive: true });\n\n // Existing files are kept as they are: --init never overwrites a story, its IFID, or a config.\n const results = SCAFFOLD_FILES.map((file) => ({ path: file.path, created: writeNewFile(file.path, file.content()) }));\n const created = results.filter((r) => r.created).map((r) => r.path);\n const skipped = results.filter((r) => !r.created).map((r) => r.path);\n\n if (created.length > 0) {\n out('Created:');\n for (const path of created) out(` ${path}`);\n }\n for (const path of skipped) out(`Skipped (already exists): ${path}`);\n out('\\nRun: npx @rohal12/twee-ts');\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${Math.round(kb)}K`;\n const mb = kb / 1024;\n return `${mb.toFixed(1)}M`;\n}\n\nfunction runCache(action: CacheAction): void {\n switch (action) {\n case 'list': {\n const entries = listCachedFormats();\n if (entries.length === 0) {\n out('No cached formats.');\n return;\n }\n for (const e of entries) {\n const date = e.modifiedAt.toISOString().slice(0, 10);\n out(`${e.name.padEnd(16)} ${e.version.padEnd(10)} ${formatBytes(e.sizeBytes).padStart(6)} ${date}`);\n }\n return;\n }\n case 'size': {\n const { totalBytes, count } = getCacheSize();\n out(\n count === 0\n ? 'Cache is empty.'\n : `Total: ${formatBytes(totalBytes)} (${count} format${count === 1 ? '' : 's'})`,\n );\n return;\n }\n case 'path':\n out(getCacheDir());\n return;\n default: {\n const _exhaustive: never = action;\n throw new Error(`unhandled cache action: ${String(_exhaustive)}`);\n }\n }\n}\n\nfunction runCacheClear(name: string | undefined): void {\n const count = clearCachedFormats(name);\n if (count === 0) {\n out(name ? `No cached formats matching \"${name}\".` : 'Cache is already empty.');\n } else {\n out(`Cleared ${count} cached format${count === 1 ? '' : 's'}.`);\n }\n}\n\nreportWriteErrors(process.stdout, 'standard output');\nreportWriteErrors(process.stderr);\n\nmain(process.argv.slice(2)).then(\n (status) => {\n // process.exitCode, not process.exit(): output still being written to a pipe is not cut off.\n if (process.exitCode === undefined || status !== EXIT_OK) process.exitCode = status;\n },\n (thrown: unknown) => {\n // An engine limit reached outside a build (in lint, say) is named as a build's is.\n const err = resourceLimitError(thrown) ?? thrown;\n logErrorDiagnostics(err);\n log(`error: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = EXIT_FAILED;\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,IAAa,gBAAb,cAAmC,MAAM;CACvC,YAAY,SAAiB;EAC3B,MAAM,OAAO;EACb,KAAK,OAAO;CACd;AACF;AAsDA,MAAM,oBAA0D;CAC9D,mBAAmB;CACnB,WAAW;CACX,mBAAmB;CACnB,kBAAkB;CAClB,kBAAkB;CAClB,MAAM;AACR;AAEA,MAAM,qBAAiD,CAAC,UAAU,YAAY;;AAG9E,MAAa,UAAU;CACrB,QAAQ;EAAE,MAAM;EAAU,OAAO;CAAI;CACrC,QAAQ;EAAE,MAAM;EAAU,OAAO;CAAI;CACrC,OAAO;EAAE,MAAM;EAAU,OAAO;CAAI;CACpC,QAAQ;EAAE,MAAM;EAAU,OAAO;EAAK,UAAU;CAAK;CACrD,MAAM,EAAE,MAAM,SAAS;CACvB,mBAAmB;EAAE,MAAM;EAAW,OAAO;CAAI;CAEjD,WAAW,EAAE,MAAM,UAAU;CAC7B,mBAAmB,EAAE,MAAM,UAAU;CACrC,kBAAkB;EAAE,MAAM;EAAW,OAAO;CAAI;CAChD,kBAAkB,EAAE,MAAM,UAAU;CACpC,MAAM,EAAE,MAAM,UAAU;CACxB,gBAAgB,EAAE,MAAM,UAAU;CAClC,WAAW,EAAE,MAAM,UAAU;CAC7B,MAAM,EAAE,MAAM,UAAU;CACxB,MAAM;EAAE,MAAM;EAAW,OAAO;CAAI;CACpC,OAAO;EAAE,MAAM;EAAW,OAAO;CAAI;CACrC,aAAa;EAAE,MAAM;EAAW,OAAO;CAAI;CAC3C,aAAa,EAAE,MAAM,UAAU;CAC/B,gBAAgB,EAAE,MAAM,UAAU;CAClC,MAAM,EAAE,MAAM,UAAU;CACxB,MAAM;EAAE,MAAM;EAAW,OAAO;CAAI;CACpC,SAAS;EAAE,MAAM;EAAW,OAAO;CAAI;CACvC,gBAAgB;EAAE,MAAM;EAAU,UAAU;CAAK;CACjD,cAAc;EAAE,MAAM;EAAU,UAAU;CAAK;CAC/C,aAAa,EAAE,MAAM,UAAU;CAC/B,6BAA6B,EAAE,MAAM,UAAU;CAC/C,aAAa;EAAE,MAAM;EAAU,UAAU;CAAK;CAC9C,SAAS;EAAE,MAAM;EAAU,UAAU;CAAK;CAC1C,eAAe,EAAE,MAAM,UAAU;CACjC,qBAAqB,EAAE,MAAM,SAAS;CACtC,QAAQ;EAAE,MAAM;EAAU,OAAO;CAAI;CACrC,aAAa,EAAE,MAAM,UAAU;CAE/B,SAAS,EAAE,MAAM,SAAS;CAC1B,iBAAiB,EAAE,MAAM,UAAU;AACrC;AAIA,SAAS,aAAa,MAAkC;CACtD,OAAO,OAAO,OAAO,SAAS,IAAI;AACpC;;AAGA,SAAS,YAAY,MAA0B;CAC7C,MAAM,SAAS,QAAQ;CACvB,OAAO,WAAW,SAAS,IAAI,OAAO,MAAM,MAAM,SAAS,KAAK;AAClE;;AAGA,MAAM,gBAAuC;CAAC;CAAW;CAAQ;AAAc;;AAG/E,MAAM,uBAA8C;CAAC;CAAgB;CAAU;AAAW;;AAG1F,SAAS,iBAAiB,GAAoB;CAC5C,MAAM,UAAU,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;CACzD,MAAM,UAAU,4BAA4B,KAAK,OAAO;CACxD,IAAI,UAAU,OAAO,KAAA,GAAW,OAAO,kBAAkB,QAAQ;CACjE,OAAO,QAAQ,QAAQ,cAAc,EAAE,CAAC,CAAC,QAAQ,qBAAqB,WAAW;AACnF;AAEA,SAAS,WAAW,MAAqC;CACvD,MAAM,CAAC,QAAQ,MAAM,GAAG,SAAS;CACjC,MAAM,gBACJ,IAAI,cAAc,SAAS,UAAU,GAAG,SAAS,WAAW,UAAU,qBAAqB,gBAAgB;CAC7G,IAAI,KAAK,MAAM,QAAQ,IAAI,WAAW,GAAG,KAAK,QAAQ,GAAG,GACvD,MAAM,IAAI,cACR,6GACF;CAEF,QAAQ,QAAR;EACE,KAAK,KAAA,GACH,OAAO,EAAE,MAAM,aAAa;EAC9B,KAAK;EACL,KAAK;EACL,KAAK;GACH,IAAI,SAAS,KAAA,GAAW,MAAM,QAAQ;GACtC,OAAO;IAAE,MAAM;IAAS;GAAO;EACjC,KAAK;GACH,IAAI,MAAM,SAAS,GAAG,MAAM,QAAQ;GAEpC,IAAI,SAAS,IAAI,MAAM,IAAI,cAAc,qEAAqE;GAC9G,OAAO,SAAS,KAAA,IAAY,EAAE,MAAM,cAAc,IAAI;IAAE,MAAM;IAAe;GAAK;EACpF,SACE,MAAM,IAAI,cAAc,6BAA6B,OAAO,sCAAsC;CACtG;AACF;;AAGA,SAAS,gBAAgB,QAA+C;CACtE,OAAO,OAAO,KAAK,SAAS;EAC1B,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,IAAI,OAAO,IAAI,MAAM,IAAI,cAAc,wBAAwB,KAAK,yBAAyB;EAC7F,MAAM,QAAQ,KAAK,MAAM,GAAG,EAAE;EAC9B,MAAM,SAAS,KAAK,MAAM,KAAK,CAAC;EAChC,MAAM,UAAU,gBAAgB,OAAO,MAAM;EAC7C,IAAI,YAAY,KAAA,GAAW,MAAM,IAAI,cAAc,wBAAwB,KAAK,KAAK,SAAS;EAC9F,OAAO,CAAC,OAAO,MAAM;CACvB,CAAC;AACH;;;;;AAMA,SAAgB,aAAa,MAAmC;CAC9D,IAAI;EACF,OAAO;GAAE,IAAI;GAAM,SAAS,aAAa,IAAI;EAAE;CACjD,SAAS,GAAG;EACV,IAAI,aAAa,eAAe,OAAO;GAAE,IAAI;GAAO,OAAO;EAAE;EAC7D,MAAM;CACR;AACF;;AAGA,SAAS,YAAY,MAAkC;CACrD,MAAM,EAAE,WAAW,UAAU;EAC3B,MAAM,CAAC,GAAG,IAAI;EACd,SAAS;EACT,kBAAkB;EAClB,QAAQ;EACR,QAAQ;CACV,CAAC;CACD,OAAO,OAAO,MAAM,UAAU,MAAM,SAAS,YAAY,MAAM,SAAS,MAAM;AAChF;;AAGA,SAAS,cAAc,QAAwC;CAC7D,OAAO,OAAO,KAAK,OAAO,CAAC,CACxB,OAAO,YAAY,CAAC,CACpB,MAAM,SAAS;EACd,MAAM,SAAS,QAAQ;EACvB,OAAO,WAAW,UAAU,OAAO,UAAU;CAC/C,CAAC;AACL;;;;;;AAOA,SAAS,uBAAuB,MAAmC;CACjE,MAAM,aAAa,KAAK,QAAQ,IAAI;CACpC,MAAM,UAAU,eAAe,KAAK,OAAO,KAAK,MAAM,GAAG,UAAU;CAenE,OAAO,CAAC,GAdS,QAAQ,SAAS,QAAQ;EACxC,MAAM,aAAa,2BAA2B,KAAK,GAAG;EACtD,MAAM,UAAU,aAAa;EAC7B,MAAM,QAAQ,aAAa;EAC3B,IAAI,YAAY,KAAA,KAAa,UAAU,KAAA,GAAW,OAAO,CAAC,GAAG;EAC7D,MAAM,OAAO,cAAc,QAAQ,MAAM,EAAE,CAAC;EAE5C,IAAI,SAAS,KAAA,GAAW,OAAO,CAAC,GAAG;EACnC,IAAI,QAAQ,KAAK,CAAC,SAAS,UACzB,MAAM,IAAI,cAAc,UAAU,YAAY,IAAI,EAAE,2BAA2B;EAEjF,MAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;EAClC,OAAO,CAAC,GAAI,WAAW,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAI,KAAK,KAAK,GAAG,OAAO;CACxE,CACkB,GAAG,GAAG,KAAK,MAAM,QAAQ,MAAM,CAAC;AACpD;AAEA,SAAS,aAAa,MAAqC;CAEzD,IAAI,KAAK,OAAO,SAAS,OAAO,WAAW,KAAK,MAAM,CAAC,CAAC;CAExD,IAAI,YAAY,IAAI,GAAG,OAAO,EAAE,MAAM,OAAO;CAE7C,IAAI;CACJ,IAAI;EACF,SAAS,UAAU;GACjB,MAAM,uBAAuB,IAAI;GACjC,SAAS;GACT,kBAAkB;GAClB,QAAQ;GACR,QAAQ;EACV,CAAC;CACH,SAAS,GAAG;EACV,MAAM,IAAI,cAAc,iBAAiB,CAAC,CAAC;CAC7C;CACA,MAAM,EAAE,QAAQ,aAAa,WAAW;CAGxC,MAAM,wBAAQ,IAAI,IAAwB;CAC1C,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,MAAM,SAAS,UAAU;EAC7B,MAAM,EAAE,SAAS;EAEjB,IAAI,CAAC,aAAa,IAAI,GAAG;EACzB,MAAM,IAAI,OAAO,MAAM,IAAI,IAAI,KAAK,KAAK,CAAC;EAE1C,IAAI,EAAE,cADS,QAAQ,WACS,MAAM,IAAI,IAAI,KAAK,KAAK,GACtD,MAAM,IAAI,cAAc,GAAG,YAAY,IAAI,EAAE,sBAAsB;EAErE,IAAI,MAAM,UAAU,MAAM,QAAQ,KAAK,CAAC,SAAS,UAC/C,MAAM,IAAI,cAAc,GAAG,YAAY,IAAI,EAAE,yBAAyB;CAE1E;CAEA,IAAI,YAAY,SAAS,EAAE,GAAG,MAAM,IAAI,cAAc,4BAA4B;CAClF,MAAM,OAAO,SAA8B,MAAM,IAAI,IAAI;CACzD,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC;CAE9B,IAAI,IAAI,SAAS,KAAK,IAAI,eAAe,GACvC,MAAM,IAAI,cACR,wKACF;CAGF,KAAK,MAAM,SAAS,eAAe;EACjC,IAAI,CAAC,IAAI,KAAK,GAAG;EACjB,MAAM,UAAU,UAAU,iBAAiB,uBAAuB,CAAC,KAAK;EACxE,MAAM,QAAQ,MAAM,MAAM,SAAS,CAAC,QAAQ,SAAS,IAAI,CAAC;EAC1D,IAAI,UAAU,KAAA,GAAW,MAAM,IAAI,cAAc,KAAK,MAAM,0BAA0B,YAAY,KAAK,GAAG;EAC1G,IAAI,YAAY,SAAS,GAAG,MAAM,IAAI,cAAc,KAAK,MAAM,kBAAkB;CACnF;CACA,IAAI,IAAI,QAAQ,KAAK,IAAI,WAAW,GAAG,MAAM,IAAI,cAAc,uCAAuC;CACtG,MAAM,SACJ,OAAO,WAAW,KAAA,IACd;EAAE,MAAM;EAAQ,MAAM,OAAO;CAAO,IACpC,IAAI,WAAW,IACb,EAAE,MAAM,OAAO,IACf,EAAE,MAAM,OAAO;CACvB,IAAI,IAAI,SAAS,GAAG,OAAO,EAAE,MAAM,UAAU;CAC7C,IAAI,IAAI,MAAM,GAAG,OAAO,EAAE,MAAM,OAAO;CACvC,IAAI,IAAI,cAAc,GAAG,OAAO;EAAE,MAAM;EAAgB;CAAO;CAG/D,MAAM,CAAC,UAAU,iBADC,MAAM,QAAQ,SAAS,OAAO,OAAO,mBAAmB,IAAI,CACpC;CAC1C,IAAI,kBAAkB,KAAA,KAAa,aAAa,KAAA,GAC9C,MAAM,IAAI,cACR,GAAG,YAAY,QAAQ,EAAE,OAAO,YAAY,aAAa,EAAE,kCAC7D;CAEF,MAAM,aAAa,aAAa,KAAA,IAAY,KAAA,IAAY,kBAAkB;CAE1E,IAAI,SAAsB;CAC1B,IAAI,IAAI,MAAM,GAAG;EACf,MAAM,WAAW,MAAM,MACpB,SACC,SAAS,WAAW,SAAS,eAAe,SAAS,eAAe,OAAO,OAAO,mBAAmB,IAAI,CAC7G;EACA,IAAI,aAAa,KAAA,GAAW,MAAM,IAAI,cAAc,iCAAiC,YAAY,QAAQ,GAAG;EAC5G,SAAS;CACX,OAAO,IAAI,IAAI,OAAO,GAAG;EACvB,IAAI,OAAO,WAAW,KACpB,MAAM,IAAI,cAAc,mEAAmE;EAC7F,SAAS;CACX;CAEA,MAAM,kBAAkB,OAAO;CAC/B,IAAI,oBAAoB,KAAA,KAAa,CAAC,mBAAmB,MAAM,MAAM,MAAM,eAAe,GACxF,MAAM,IAAI,cACR,gCAAgC,gBAAgB,cAAc,mBAAmB,KAAK,MAAM,GAC9F;CAGF,MAAM,QAAoB;EACxB,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO;EAC/D,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;EACjD,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,OAAO,OAAO;EACjE,GAAI,OAAO,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,OAAO,MAAM;EACnE,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,OAAO,OAAO;EAChE,GAAI,OAAO,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,OAAO,KAAK;EAC7D,GAAI,OAAO,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;EAClE,GAAI,OAAO,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,OAAO,gBAAgB;EACxF,GAAI,OAAO,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,OAAO,cAAc;EACjF,GAAI,OAAO,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,gBAAgB,OAAO,YAAY,EAAE;EAChG,GAAI,oBAAoB,YAAY,oBAAoB,eAAe,EAAE,gBAAgB,IAAI,CAAC;EAC9F,GAAI,IAAI,SAAS,IAAI,EAAE,MAAM,MAAM,IAAI,CAAC;EACxC,GAAI,IAAI,cAAc,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;EACnD,GAAI,IAAI,MAAM,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;EACxC,GAAI,IAAI,WAAW,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;EAC7C,GAAI,IAAI,2BAA2B,IAAI,EAAE,yBAAyB,MAAM,IAAI,CAAC;EAC7E,GAAI,IAAI,aAAa,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CACnD;CAEA,OAAO;EACL,MAAM;EACN;EACA,SAAS;EACT;EACA;EACA,KAAK;GAAE,OAAO,IAAI,WAAW;GAAG,OAAO,IAAI,WAAW;EAAE;CAC1D;AACF;;;;;;AAqCA,SAAgB,aAAa,SAAuB,QAA4C;CAC9F,MAAM,EAAE,UAAU;CAClB,MAAM,UAAU,QAAQ,QAAQ,SAAS,IAAI,QAAQ,UAAW,QAAQ,WAAW,CAAC;CACpF,IAAI,QAAQ,WAAW,GAAG,MAAM,IAAI,cAAc,+DAA6D;CAC/G,MAAM,SAAS,MAAM,UAAU,QAAQ,UAAU;CACjD,IAAI,QAAQ,WAAW,WAAW,WAAW,KAC3C,MAAM,IAAI,cAAc,mEAAiE;CAG3F,MAAM,eAAe,CAAC,GAAG,OAAO,QAAQ,QAAQ,cAAc,CAAC,CAAC,GAAG,GAAI,MAAM,cAAc,CAAC,CAAE;CAC9F,OAAO;EACL,QAAQ,QAAQ;EAChB;EACA;EACA,SAAS;GACP,YAAY,MAAM,cAAc,QAAQ,cAAc;GACtD,SAAS,MAAM,WAAW,QAAQ;GAClC,UAAU,MAAM,YAAY,QAAQ;GACpC,cAAc,MAAM,gBAAgB,QAAQ;GAC5C,aAAa,QAAQ;GACrB,SAAS,MAAM,WAAW,QAAQ;GAClC,UAAU,MAAM,YAAY,QAAQ;GACpC,MAAM,MAAM,QAAQ,QAAQ,QAAQ;GACpC,aAAa,MAAM,eAAe,QAAQ,eAAe;GACzD,UAAU,MAAM,YAAY,QAAQ,YAAY;GAChD,eAAe,QAAQ;GACvB,eAAe,MAAM,iBAAiB,QAAQ;GAC9C,YAAY,MAAM,cAAc,QAAQ;GACxC,UAAU,MAAM,YAAY,QAAQ,YAAY;GAChD,oBAAoB,QAAQ;GAC5B,yBAAyB,QAAQ;GACjC,yBAAyB,MAAM,2BAA2B,QAAQ,2BAA2B;GAC7F,YACE,aAAa,SAAS,KAAK,QAAQ,eAAe,KAAA,IAAY,OAAO,YAAY,YAAY,IAAI,KAAA;GACnG,YAAY,MAAM,cAAc,QAAQ,cAAc;GACtD,iBAAiB,MAAM,mBAAmB,QAAQ;EACpD;CACF;AACF;;AAGA,SAAgB,iBAAiB,OAAwB;CACvD,OAAO,+JAA+J,KACpK,KACF;AACF;;AAGA,SAAgB,UAAU,SAAiB,gBAAgC;CACzE,OAAO,YAAY,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDAkC4B,eAAe;;;;;;;;;;;;;;AAcxE;;AAGA,MAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;AC5e3B,MAAM,8BAAmC,IAAI,IAAI;CAC/C;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAGD,SAAgB,aAAa,OAA6C;CACxE,OAAO,OAAO,MAAM,SAAS,YAAY,YAAY,IAAI,MAAM,IAAI;AACrE;;;;;;;;;;;;ACcA,MAAM,UAAU;AAChB,MAAM,cAAc;AACpB,MAAM,aAAa;;AAGnB,SAAS,IAAI,MAAoB;CAC/B,QAAQ,OAAO,MAAM,KAAK,SAAS,IAAI,IAAI,OAAO,GAAG,KAAK,GAAG;AAC/D;;AAGA,SAAS,IAAI,MAAoB;CAC/B,QAAQ,OAAO,MAAM,GAAG,KAAK,GAAG;AAClC;;;;;;;;AASA,SAAS,kBAAkB,QAA4B,MAAqB;CAC1E,IAAI,WAAW;CACf,OAAO,GAAG,UAAU,MAA6B;EAC/C,IAAI,aAAa,CAAC,GAAG;EACrB,QAAQ,WAAW;EACnB,IAAI,YAAY,SAAS,KAAA,GAAW;EACpC,WAAW;EACX,IAAI,uBAAuB,KAAK,IAAI,EAAE,SAAS;CACjD,CAAC;AACH;AAEA,eAAe,KAAK,MAA0C;CAC5D,MAAM,SAAS,aAAa,IAAI;CAChC,IAAI,CAAC,OAAO,IAAI,OAAO,WAAW,OAAO,KAAK;CAC9C,MAAM,EAAE,YAAY;CACpB,QAAQ,QAAQ,MAAhB;EACE,KAAK;GACH,IAAI,UAAU,SAAS,eAAe,CAAC;GACvC,OAAO;EACT,KAAK;GACH,IAAI,YAAY,SAAS;GACzB,OAAO;EACT,KAAK;GACH,QAAQ;GACR,OAAO;EACT,KAAK;GACH,IAAI,WAAW;GACf,OAAO;EACT,KAAK;GACH,SAAS,QAAQ,MAAM;GACvB,OAAO;EACT,KAAK;GACH,cAAc,QAAQ,IAAI;GAC1B,OAAO;EACT,KAAK;GAGH,YAFe,WAAW,QAAQ,MAEjB,CAAC,CAAC,MAAM;GACzB,OAAO;EAET,KAAK,SACH,OAAO,SAAS,OAAO;EACzB,SAEE,MAAM,IAAI,MAAM,sBAAsB,KAAK,UAAUA,OAAW,GAAG;CAEvE;AACF;AAEA,SAAS,WAAW,OAA8B;CAChD,IAAI,UAAU,MAAM,SAAS;CAC7B,IAAI,mCAAiC;CACrC,OAAO;AACT;;AAGA,SAAS,WAAW,QAAwF;CAE1G,MAAM,cAA4B,CAAC;CACnC,IAAI;CACJ,QAAQ,OAAO,MAAf;EACE,KAAK,QACH,OAAO,EAAE,QAAQ,KAAK;EACxB,KAAK;GACH,IAAI;IACF,SAAS;KAAE,QAAQ,eAAe,OAAO,MAAM,WAAW;KAAG,MAAM,OAAO;IAAK;GACjF,SAAS,GAAG;IAEV,IAAI,aAAa,eAAe,EAAE,SAAS,uBAAuB,iBAAiB,OAAO,IAAI,GAE5F,MAAM,IAAI,YAAY,GAAG,EAAE,QAAQ,qJAAkB,EAAE,aAAa;KAAE,MAAM,EAAE;KAAM,OAAO;IAAE,CAAC;IAEhG,MAAM;GACR;GACA;EACF,KAAK,QAAQ;GACX,MAAM,SAAS,WAAW,KAAA,GAAW,WAAW;GAChD,SAAS,WAAW,OAAO,EAAE,OAAO,IAAI;IAAE;IAAQ,MAAM;GAAgB;GACxE;EACF;EACA,SAEE,MAAM,IAAI,MAAM,4BAA4B,KAAK,UAAUA,MAAW,GAAG;CAE7E;CACA,eAAe,WAAW;CAC1B,OAAO;AACT;AAEA,eAAe,SAAS,SAAwC;CAC9D,MAAM,SAAS,WAAW,QAAQ,MAAM;CACxC,IAAI;CACJ,IAAI;EACF,QAAQ,aAAa,SAAS,OAAO,MAAM;CAC7C,SAAS,GAAG;EACV,IAAI,aAAa,eAAe,OAAO,WAAW,CAAC;EACnD,MAAM;CACR;CACA,MAAM,iBAAiB;EAAE,GAAG,MAAM;EAAS,SAAS,MAAM;CAAQ;CAGlE,MAAM,UAAU,MAAM,WAAW,MAAM,KAAA,IAAY,MAAM;CACzD,MAAM,cAA4B,OAAO,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC;EAAE,MAAM;EAAU,MAAM,OAAO;CAAK,CAAC;CAEzG,QAAQ,MAAM,QAAd;EACE,KAAK,QAAQ;GACX,MAAM,aAAa,MAAM,kBAAkB,gBAAgB,OAAO;GAClE,IAAI,iBAAiB,UAAU,CAAC;GAEhC,OADkB,WAAW,YAAY,SAAS,KAAK,WAAW,YAAY,MAAM,MAAM,EAAE,UAAU,OAAO,IAC1F,cAAc;EACnC;EACA,KAAK,SAEH,OAAO,WAAW,gBAAgB,WAAW,MAAM,QAAQ,QAAQ,KAAK,WAAW;EACrF,KAAK,QAAQ;GAEX,MAAM,SAAS,MAAM,qBAAqB,gBAAgB,SAAS,KAAA,GAAW,aAAa,IAAI;GAC/F,eAAe,OAAO,WAAW;GAGjC,MAAM,SAAS,YAAY,OAAO,WAAW;GAC7C,IAAI,SAAS;GACb,IAAI,SAAS,GAAG;IACd,IAAI,2BAA2B,UAAU,QAAQ,OAAO,EAAE,sBAAsB;IAChF,SAAS;GACX,OAAO,IAAI,YAAY,KAAA,GACrB,QAAQ,OAAO,MAAM,OAAO,MAAM;QAElC,gBAAgB,SAAS,OAAO,MAAM;GAExC,SAAS,QAAQ,QAAQ,GAAG;GAC5B,OAAO;EACT;EACA,SAAS;GACP,MAAM,cAAqB,MAAM;GACjC,MAAM,IAAI,MAAM,2BAA2B,OAAO,WAAW,GAAG;EAClE;CACF;AACF;;AAGA,SAAS,WACP,SACA,SACA,YACA,aACQ;CAGR,qBACE;EACE,GAAG;EACH;EACA,QAAQ,QAAQ;GACd,MAAM,SAAS,GAAG,OAAO,MAAM,SAAS,aAAa,OAAO,MAAM,MAAM;GACxE,MAAM,SAAS,YAAY,OAAO,WAAW;GAE7C,IAAI,WAAW,GAAG,IAAI,UAAU,QAAQ;GACxC,eAAe,OAAO,WAAW;GAEjC,IAAI,SAAS,GAAG;IACd,IAAI,iBAAiB,QAAQ;IAC7B,IAAI,aAAa,UAAU,QAAQ,OAAO,EAAE,kDAAkD;GAChG;GACA,SAAS,QAAQ,UAAU;EAC7B;EACA,QAAQ,OAAO;GACb,QAAQ,WAAW;GACnB,IAAI,iBAAiB,gBAEnB,IAAI,UAAU,MAAM,SAAS;QACxB;IACL,oBAAoB,KAAK;IACzB,IAAI,gBAAgB,MAAM,SAAS;GACrC;EACF;CACF,IACC,WAAW,YAAY,OAAO,WAAW,MAAM,GAChD,EAAE,YAAY,CAChB;CAEA,IAAI,2CAA2C;CAE/C,OAAO;AACT;AAEA,SAAS,SAAS,QAAuB,YAAuC;CAC9E,IAAI,WAAW,OAAO;EACpB,IAAI,YAAY,OAAO,MAAM,MAAM,KAAK,IAAI,GAAG;EAC/C,MAAM,WAAW,OAAO,MAAM,iBAAiB,CAAC;EAChD,IAAI,SAAS,SAAS,GAAG,IAAI,mBAAmB,SAAS,KAAK,IAAI,GAAG;CACvE;CACA,IAAI,WAAW,OAAO,SAAS,MAAM;AACvC;AAEA,SAAS,YAAY,aAA4C;CAC/D,OAAO,YAAY,QAAQ,MAAM,EAAE,UAAU,OAAO,CAAC,CAAC;AACxD;AAEA,SAAS,UAAU,OAAe,MAAsB;CACtD,OAAO,GAAG,MAAM,GAAG,OAAO,UAAU,IAAI,KAAK;AAC/C;;AAGA,SAAS,oBAAoB,GAAW,GAAmB;CACzD,MAAM,OAAO,aAAa,CAAC;CAC3B,MAAM,QAAQ,aAAa,CAAC;CAC5B,IAAI,CAAC,QAAQ,CAAC,OAAO,OAAO,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK;CACzD,OAAO,gBAAgB,OAAO,IAAI;AACpC;;;;;;;;;AAUA,SAAS,oBACP,YACA,eACA,yBACA,aACuD;CACvD,MAAM,WAAW,MAAyB,WACxC,KAAK,SAAS,SAAS;EACrB,MAAM,SAAS,eAAe,IAAI;EAClC,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG;EACjC,YAAY,KAAK;GAAE,OAAO;GAAW,SAAS,GAAG,OAAO,IAAI,OAAO;EAAS,CAAC;EAC7E,OAAO,CAAC;CACV,CAAC;CACH,MAAM,0BAAU,IAAI,IAAI,CACtB,GAAG,QAAQ,eAAe,eAAe,GACzC,GAAI,0BAA0B,sBAAsB,CAAC,CACvD,CAAC;CACD,MAAM,WAAW,QAAQ,YAAY,YAAY,CAAC,CAAC,SAAS,QAAQ,gBAAgB,GAAG,KAAK,CAAC,CAAC;CAC9F,MAAM,cAAc,YAAY,CAAC,CAAC,QAAQ,MAAM,EAAE,OAAO,SAAS,WAAW,QAAQ,IAAI,EAAE,OAAO,KAAK,CAAC;CACxG,OAAO,CAAC,GAAG,UAAU,GAAG,WAAW,CAAC,CACjC,QAAQ,WAAW,YAAY,UAAU,MAAM,CAAC,CAAC,CACjD,KAAK,WAAY,OAAO,OAAO,SAAS,UAAU,OAAO,SAAS,MAAO;AAC9E;;;;;AAMA,SAAS,YAAY,QAAmC;CACtD,MAAM,cAA4B,CAAC;CACnC,MAAM,aAAa,oBAAoB,QAAQ,eAAe,CAAC,GAAG,QAAQ,iBAAiB,IAAI;CAC/F,MAAM,UAAU,aAAa,mBAAmB,YAAY,WAAW,CAAC;CACxE,MAAM,YAAY,oBAChB,QAAQ,cAAc,CAAC,GACvB,QAAQ,iBAAiB,CAAC,GAC1B,QAAQ,2BAA2B,MACnC,WACF;CACA,eAAe,WAAW;CAE1B,IAAI,sBAAsB;CAC1B,IAAI,QAAQ,SAAS,GACnB,IAAI,UAAU;MAEd,KAAK,MAAM,CAAC,IAAI,MAAM,SAAS;EAC7B,MAAM,OAAO,EAAE,WAAW,YAAY;EACtC,IAAI,KAAK,GAAG,IAAI,EAAE,QAAQ,GAAG,GAAG,EAAE,QAAQ,IAAI,KAAK,EAAE;CACvD;CAIF,MAAM,6BAAa,IAAI,IAAmE;CAC1F,KAAK,MAAM,KAAK,WAAW;EACzB,MAAM,KAAK,aAAa,EAAE,MAAM,EAAE,OAAO;EACzC,WAAW,IAAI,IAAI,CAAC,GAAI,WAAW,IAAI,EAAE,KAAK,CAAC,GAAI,CAAC,CAAC;CACvD;CACA,IAAI,WAAW,OAAO,GAAG;EACvB,IAAI,0BAA0B;EAC9B,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE,GAAG;GAC7F,MAAM,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,oBAAoB,EAAE,SAAS,EAAE,OAAO,CAAC;GACjG,IAAI,CAAC,QAAQ;GACb,MAAM,OAAO,MAAM,SAAS,IAAI,kBAAkB,MAAM,KAAK,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,KAAK;GAC9F,IAAI,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,OAAO,UAAU,MAAM;EACxD;CACF;AACF;;AAGA,SAAS,eAAe,aAA0C;CAChE,KAAK,MAAM,KAAK,aAAa,IAAI,GAAG,EAAE,UAAU,UAAU,UAAU,UAAU,IAAI,iBAAiB,CAAC,GAAG;AACzG;;AAGA,SAAS,oBAAoB,OAAsB;CACjD,IAAI,iBAAiB,aAAa,eAAe,MAAM,WAAW;AACpE;AAEA,SAAS,SAAS,QAA6B;CAC7C,MAAM,IAAI,OAAO;CACjB,IAAI,eAAe;CACnB,IAAI,eAAe,EAAE,UAAU;CAC/B,IAAI,YAAY,EAAE,OAAO;CACzB,IAAI,YAAY,EAAE,MAAM,QAAQ;AAClC;AAOA,MAAM,iBAA0C;CAC9C;EAAE,MAAM;EAAiB,SAAS;CAAe;CACjD;EACE,MAAM;EACN,eAAe;;aAEN,aAAa,EAAE;;;CAG1B;CACA;EACE,MAAM;EACN,eAAe;;;CAGjB;CACA;EACE,MAAM;EACN,eAAe;;;;;CAKjB;AACF;;;;;;AAOA,SAAS,aAAa,MAAc,SAA0B;CAC5D,IAAI;EACF,cAAc,MAAM,SAAS,EAAE,MAAM,KAAK,CAAC;EAC3C,OAAO;CACT,SAAS,GAAG;EACV,IAAI,aAAa,SAAS,UAAU,KAAK,EAAE,SAAS,UAAU,OAAO;EACrE,MAAM,IAAI,MAAM,iBAAiB,KAAK,IAAI,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;CACtG;AACF;AAEA,SAAS,UAAgB;CACvB,IAAI,qCAAqC;CACzC,UAAU,OAAO,EAAE,WAAW,KAAK,CAAC;CAGpC,MAAM,UAAU,eAAe,KAAK,UAAU;EAAE,MAAM,KAAK;EAAM,SAAS,aAAa,KAAK,MAAM,KAAK,QAAQ,CAAC;CAAE,EAAE;CACpH,MAAM,UAAU,QAAQ,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;CAClE,MAAM,UAAU,QAAQ,QAAQ,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;CAEnE,IAAI,QAAQ,SAAS,GAAG;EACtB,IAAI,UAAU;EACd,KAAK,MAAM,QAAQ,SAAS,IAAI,KAAK,MAAM;CAC7C;CACA,KAAK,MAAM,QAAQ,SAAS,IAAI,6BAA6B,MAAM;CACnE,IAAI,6BAA6B;AACnC;AAEA,SAAS,YAAY,OAAuB;CAC1C,IAAI,QAAQ,MAAM,OAAO,GAAG,MAAM;CAClC,MAAM,KAAK,QAAQ;CACnB,IAAI,KAAK,MAAM,OAAO,GAAG,KAAK,MAAM,EAAE,EAAE;CAExC,OAAO,IADI,KAAK,KAAA,CACH,QAAQ,CAAC,EAAE;AAC1B;AAEA,SAAS,SAAS,QAA2B;CAC3C,QAAQ,QAAR;EACE,KAAK,QAAQ;GACX,MAAM,UAAU,kBAAkB;GAClC,IAAI,QAAQ,WAAW,GAAG;IACxB,IAAI,oBAAoB;IACxB;GACF;GACA,KAAK,MAAM,KAAK,SAAS;IACvB,MAAM,OAAO,EAAE,WAAW,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;IACnD,IAAI,GAAG,EAAE,KAAK,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,OAAO,EAAE,EAAE,GAAG,YAAY,EAAE,SAAS,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,MAAM;GACtG;GACA;EACF;EACA,KAAK,QAAQ;GACX,MAAM,EAAE,YAAY,UAAU,aAAa;GAC3C,IACE,UAAU,IACN,oBACA,UAAU,YAAY,UAAU,EAAE,IAAI,MAAM,SAAS,UAAU,IAAI,KAAK,IAAI,EAClF;GACA;EACF;EACA,KAAK;GACH,IAAI,YAAY,CAAC;GACjB;EACF,SAEE,MAAM,IAAI,MAAM,2BAA2B,OAAOA,MAAW,GAAG;CAEpE;AACF;AAEA,SAAS,cAAc,MAAgC;CACrD,MAAM,QAAQ,mBAAmB,IAAI;CACrC,IAAI,UAAU,GACZ,IAAI,OAAO,+BAA+B,KAAK,MAAM,yBAAyB;MAE9E,IAAI,WAAW,MAAM,gBAAgB,UAAU,IAAI,KAAK,IAAI,EAAE;AAElE;AAEA,kBAAkB,QAAQ,QAAQ,iBAAiB;AACnD,kBAAkB,QAAQ,MAAM;AAEhC,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,MACzB,WAAW;CAEV,IAAI,QAAQ,aAAa,KAAA,KAAa,WAAW,SAAS,QAAQ,WAAW;AAC/E,IACC,WAAoB;CAEnB,MAAM,MAAM,mBAAmB,MAAM,KAAK;CAC1C,oBAAoB,GAAG;CACvB,IAAI,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,GAAG;CAChE,QAAQ,WAAW;AACrB,CACF"}
|
|
1
|
+
{"version":3,"file":"twee-ts.js","names":["_exhaustive"],"sources":["../../src/cli-request.ts","../../src/stream-errors.ts","../../bin/twee-ts.ts"],"sourcesContent":["/**\n * The command line, parsed completely into a typed request before anything runs.\n *\n * parseCliArgs() turns argv into a CliRequest or a CliUsageError; it never reads a file. resolveBuild()\n * then merges a build request with the config file into compile options. Every check that can be made on\n * the command line alone is made here: unknown options, missing or empty values, an option given twice,\n * options that conflict, tag aliases, and subcommands (only as the first word, never after `--`).\n */\nimport { parseArgs } from 'node:util';\nimport type { ExcludeGlob, OutputMode, TweeTsConfig, WordCountMethod } from './types.js';\nimport { tagAliasProblem } from './config.js';\n\n/** A command line that can't be run, with what to tell the user. The CLI prints it and exits with status 2. */\nexport class CliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliUsageError';\n }\n}\n\n/** Where the config comes from: `twee-ts.config.json` in the working directory, a named file, or none. */\nexport type ConfigChoice =\n { readonly kind: 'auto' } | { readonly kind: 'file'; readonly path: string } | { readonly kind: 'none' };\n\n/** The build settings given on the command line; a setting not given is undefined (the config decides). */\ninterface BuildFlags {\n readonly output?: string;\n readonly outputMode?: OutputMode;\n readonly formatId?: string;\n readonly startPassage?: string;\n readonly modules?: readonly string[];\n readonly headFile?: string;\n readonly exclude?: readonly string[];\n readonly formatIndices?: readonly string[];\n readonly formatUrls?: readonly string[];\n /** In order, a later one replacing an earlier one for the same alias. */\n readonly tagAliases?: readonly (readonly [string, string])[];\n readonly wordCountMethod?: WordCountMethod;\n readonly trim?: false;\n readonly twee2Compat?: true;\n readonly testMode?: true;\n readonly noRemote?: true;\n readonly useDefaultFormatIndices?: false;\n readonly sourceInfo?: true;\n}\n\ntype BuildAction = 'once' | 'watch' | 'lint';\n\nexport interface BuildRequest {\n readonly kind: 'build';\n readonly action: BuildAction;\n readonly sources: readonly string[];\n readonly flags: BuildFlags;\n readonly config: ConfigChoice;\n readonly log: { readonly files: boolean; readonly stats: boolean };\n}\n\nexport type CacheAction = 'list' | 'size' | 'path';\n\nexport type CliRequest =\n | { readonly kind: 'help' }\n | { readonly kind: 'version' }\n | { readonly kind: 'init' }\n | { readonly kind: 'cache-help' }\n | { readonly kind: 'cache'; readonly action: CacheAction }\n | { readonly kind: 'cache-clear'; readonly name?: string }\n | { readonly kind: 'list-formats'; readonly config: ConfigChoice }\n | BuildRequest;\n\nexport type CliParse =\n { readonly ok: true; readonly request: CliRequest } | { readonly ok: false; readonly error: CliUsageError };\n\nconst OUTPUT_MODE_FLAGS: Readonly<Record<string, OutputMode>> = {\n 'decompile-twee3': 'twee3',\n decompile: 'twee3',\n 'decompile-twee1': 'twee1',\n 'archive-twine2': 'twine2-archive',\n 'archive-twine1': 'twine1-archive',\n json: 'json',\n};\n\nconst WORD_COUNT_METHODS: readonly WordCountMethod[] = ['tweego', 'whitespace'];\n\n/** Every option, as node:util's parseArgs takes them. docs/cli.md documents each one (test/docs-reference.test.ts). */\nexport const OPTIONS = {\n output: { type: 'string', short: 'o' },\n format: { type: 'string', short: 'f' },\n start: { type: 'string', short: 's' },\n module: { type: 'string', short: 'm', multiple: true },\n head: { type: 'string' },\n 'decompile-twee3': { type: 'boolean', short: 'd' },\n // Tweego's deprecated spelling of --decompile-twee3.\n decompile: { type: 'boolean' },\n 'decompile-twee1': { type: 'boolean' },\n 'archive-twine2': { type: 'boolean', short: 'a' },\n 'archive-twine1': { type: 'boolean' },\n json: { type: 'boolean' },\n 'twee2-compat': { type: 'boolean' },\n 'no-trim': { type: 'boolean' },\n lint: { type: 'boolean' },\n test: { type: 'boolean', short: 't' },\n watch: { type: 'boolean', short: 'w' },\n 'log-stats': { type: 'boolean', short: 'l' },\n 'log-files': { type: 'boolean' },\n 'list-formats': { type: 'boolean' },\n init: { type: 'boolean' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n 'format-index': { type: 'string', multiple: true },\n 'format-url': { type: 'string', multiple: true },\n 'no-remote': { type: 'boolean' },\n 'no-default-format-indices': { type: 'boolean' },\n 'tag-alias': { type: 'string', multiple: true },\n exclude: { type: 'string', multiple: true },\n 'source-info': { type: 'boolean' },\n 'word-count-method': { type: 'string' },\n config: { type: 'string', short: 'c' },\n 'no-config': { type: 'boolean' },\n // Tweego's, which twee-ts doesn't support; recognised to say so.\n charset: { type: 'string' },\n 'list-charsets': { type: 'boolean' },\n} as const;\n\ntype OptionName = keyof typeof OPTIONS;\n\nfunction isOptionName(name: string): name is OptionName {\n return Object.hasOwn(OPTIONS, name);\n}\n\n/** How an option is shown in messages: its short form too, when it has one. */\nfunction optionLabel(name: OptionName): string {\n const option = OPTIONS[name];\n return 'short' in option ? `-${option.short}, --${name}` : `--${name}`;\n}\n\n/** The options that stand for a whole command, which take nothing else. */\nconst QUERY_OPTIONS: readonly OptionName[] = ['version', 'init', 'list-formats'];\n\n/** The options --list-formats accepts besides itself: those that choose the config, whose formatPaths it lists. */\nconst LIST_FORMATS_OPTIONS: readonly OptionName[] = ['list-formats', 'config', 'no-config'];\n\n/** What `parseArgs` threw, as a usage message without its code or its advice about `--`. */\nfunction parseArgsMessage(e: unknown): string {\n const message = e instanceof Error ? e.message : String(e);\n const unknown = /^Unknown option '([^']+)'/.exec(message);\n if (unknown?.[1] !== undefined) return `unknown option ${unknown[1]}`;\n return message.replace(/\\n[\\s\\S]*$/, '').replace(/^Option '([^']+)'/, 'option $1');\n}\n\nfunction parseCache(rest: readonly string[]): CliRequest {\n const [action, name, ...extra] = rest;\n const tooMany = (): CliUsageError =>\n new CliUsageError(`cache ${action ?? ''} takes ${action === 'clear' ? 'at most one name' : 'no arguments'}`);\n if (rest.some((arg) => arg.startsWith('-') && arg !== '-')) {\n throw new CliUsageError(\n 'the cache subcommand takes no options; to build a folder named \"cache\", write ./cache or put -- before it',\n );\n }\n switch (action) {\n case undefined:\n return { kind: 'cache-help' };\n case 'list':\n case 'size':\n case 'path':\n if (name !== undefined) throw tooMany();\n return { kind: 'cache', action };\n case 'clear':\n if (extra.length > 0) throw tooMany();\n // An empty name (an unset variable) must not mean \"everything\".\n if (name === '') throw new CliUsageError('cache clear needs a non-empty name; write cache clear alone for all');\n return name === undefined ? { kind: 'cache-clear' } : { kind: 'cache-clear', name };\n default:\n throw new CliUsageError(`unknown cache subcommand \"${action}\"; expected list, clear, size or path`);\n }\n}\n\n/** The tag aliases of `--tag-alias alias=target` values, each one checked. */\nfunction parseTagAliases(values: readonly string[]): [string, string][] {\n return values.map((pair) => {\n const eq = pair.indexOf('=');\n if (eq === -1) throw new CliUsageError(`invalid --tag-alias \"${pair}\": expected alias=target`);\n const alias = pair.slice(0, eq);\n const target = pair.slice(eq + 1);\n const problem = tagAliasProblem(alias, target);\n if (problem !== undefined) throw new CliUsageError(`invalid --tag-alias \"${pair}\": ${problem}`);\n return [alias, target];\n });\n}\n\n/**\n * Parses the arguments after `twee-ts` into a request. Never throws: a command line that can't be run\n * gives a CliUsageError.\n */\nexport function parseCliArgs(argv: readonly string[]): CliParse {\n try {\n return { ok: true, request: parseRequest(argv) };\n } catch (e) {\n if (e instanceof CliUsageError) return { ok: false, error: e };\n throw e;\n }\n}\n\n/** Whether `-h` or `--help` is given before any `--`, whatever else is on the line (even a malformed option). */\nfunction asksForHelp(argv: readonly string[]): boolean {\n const terminator = argv.indexOf('--');\n const options = terminator === -1 ? argv : argv.slice(0, terminator);\n // Read each word on its own: an unfinished string option must not consume a following help request.\n // parseArgs still understands short bundles and attached values, so -oh and --output=--help are values.\n return options.some((arg) => {\n const { tokens } = parseArgs({\n args: [arg],\n options: OPTIONS,\n allowPositionals: true,\n strict: false,\n tokens: true,\n });\n return tokens.some((token) => token.kind === 'option' && token.name === 'help');\n });\n}\n\n/** The option a short letter stands for. */\nfunction optionOfShort(letter: string): OptionName | undefined {\n return Object.keys(OPTIONS)\n .filter(isOptionName)\n .find((name) => {\n const option = OPTIONS[name];\n return 'short' in option && option.short === letter;\n });\n}\n\n/**\n * Reads `-<letter>=<value>` as Tweego does, as `-<letter> <value>`: it becomes `--<name>=<value>`, so\n * node:util's parseArgs doesn't take `=<value>` as the value. A short option that takes no value refuses\n * one. Letters of other bundled options before it (`-do=x`) stay as they are. After `--`, nothing changes.\n */\nfunction expandShortAssignments(argv: readonly string[]): string[] {\n const terminator = argv.indexOf('--');\n const options = terminator === -1 ? argv : argv.slice(0, terminator);\n const expanded = options.flatMap((arg) => {\n const assignment = /^-([A-Za-z]+)=([\\s\\S]*)$/.exec(arg);\n const letters = assignment?.[1];\n const value = assignment?.[2];\n if (letters === undefined || value === undefined) return [arg];\n for (let index = 0; index < letters.length; index++) {\n const name = optionOfShort(letters.charAt(index));\n // An unknown letter is parseArgs' to report. A string option consumes all following letters as its value.\n if (name === undefined) return [arg];\n if (OPTIONS[name].type === 'string') {\n if (index !== letters.length - 1) return [arg];\n const others = letters.slice(0, index);\n return [...(others === '' ? [] : [`-${others}`]), `--${name}=${value}`];\n }\n if (index === letters.length - 1) {\n throw new CliUsageError(`option ${optionLabel(name)} does not take an argument`);\n }\n }\n return [arg];\n });\n return [...expanded, ...argv.slice(options.length)];\n}\n\nfunction parseRequest(argv: readonly string[]): CliRequest {\n // A subcommand only as the very first word: `twee-ts -o out.html cache` builds a folder named cache.\n if (argv[0] === 'cache') return parseCache(argv.slice(1));\n // Help is asked for before anything else is checked.\n if (asksForHelp(argv)) return { kind: 'help' };\n\n let parsed;\n try {\n parsed = parseArgs({\n args: expandShortAssignments(argv),\n options: OPTIONS,\n allowPositionals: true,\n strict: true,\n tokens: true,\n });\n } catch (e) {\n throw new CliUsageError(parseArgsMessage(e));\n }\n const { values, positionals, tokens } = parsed;\n\n // Each option once, except those that may repeat.\n const given = new Map<OptionName, number>();\n for (const token of tokens) {\n if (token.kind !== 'option') continue;\n const { name } = token;\n // parseArgs (strict) only yields names from OPTIONS; the check narrows the type.\n if (!isOptionName(name)) continue;\n given.set(name, (given.get(name) ?? 0) + 1);\n const option = OPTIONS[name];\n if (!('multiple' in option) && (given.get(name) ?? 0) > 1) {\n throw new CliUsageError(`${optionLabel(name)} given more than once`);\n }\n if (token.value === '' && OPTIONS[name].type === 'string') {\n throw new CliUsageError(`${optionLabel(name)} needs a non-empty value`);\n }\n }\n // As a source anywhere else (the config, the API, the plugins), an empty one names nothing.\n if (positionals.includes('')) throw new CliUsageError('a source must not be empty');\n const has = (name: OptionName): boolean => given.has(name);\n const names = [...given.keys()];\n\n if (has('charset') || has('list-charsets')) {\n throw new CliUsageError(\n 'twee-ts has no --charset: sources are read as UTF-8 (or UTF-16 after a byte order mark), and a file that is not valid UTF-8 as Windows-1252, as Tweego does by default',\n );\n }\n\n for (const query of QUERY_OPTIONS) {\n if (!has(query)) continue;\n const allowed = query === 'list-formats' ? LIST_FORMATS_OPTIONS : [query];\n const other = names.find((name) => !allowed.includes(name));\n if (other !== undefined) throw new CliUsageError(`--${query} can't be combined with ${optionLabel(other)}`);\n if (positionals.length > 0) throw new CliUsageError(`--${query} takes no sources`);\n }\n if (has('config') && has('no-config')) throw new CliUsageError('-c, --config and --no-config conflict');\n const config: ConfigChoice =\n values.config !== undefined\n ? { kind: 'file', path: values.config }\n : has('no-config')\n ? { kind: 'none' }\n : { kind: 'auto' };\n if (has('version')) return { kind: 'version' };\n if (has('init')) return { kind: 'init' };\n if (has('list-formats')) return { kind: 'list-formats', config };\n\n const modeFlags = names.filter((name) => Object.hasOwn(OUTPUT_MODE_FLAGS, name));\n const [modeFlag, otherModeFlag] = modeFlags;\n if (otherModeFlag !== undefined && modeFlag !== undefined) {\n throw new CliUsageError(\n `${optionLabel(modeFlag)} and ${optionLabel(otherModeFlag)} conflict: choose one output mode`,\n );\n }\n const outputMode = modeFlag === undefined ? undefined : OUTPUT_MODE_FLAGS[modeFlag];\n\n let action: BuildAction = 'once';\n if (has('lint')) {\n const conflict = names.find(\n (name) =>\n name === 'watch' || name === 'log-stats' || name === 'log-files' || Object.hasOwn(OUTPUT_MODE_FLAGS, name),\n );\n if (conflict !== undefined) throw new CliUsageError(`--lint can't be combined with ${optionLabel(conflict)}`);\n action = 'lint';\n } else if (has('watch')) {\n if (values.output === '-')\n throw new CliUsageError('watch mode needs an output file: standard output is not supported');\n action = 'watch';\n }\n\n const wordCountMethod = values['word-count-method'];\n if (wordCountMethod !== undefined && !WORD_COUNT_METHODS.some((m) => m === wordCountMethod)) {\n throw new CliUsageError(\n `invalid --word-count-method \"${wordCountMethod}\": expected ${WORD_COUNT_METHODS.join(' or ')}`,\n );\n }\n\n const flags: BuildFlags = {\n ...(values.output === undefined ? {} : { output: values.output }),\n ...(outputMode === undefined ? {} : { outputMode }),\n ...(values.format === undefined ? {} : { formatId: values.format }),\n ...(values.start === undefined ? {} : { startPassage: values.start }),\n ...(values.module === undefined ? {} : { modules: values.module }),\n ...(values.head === undefined ? {} : { headFile: values.head }),\n ...(values.exclude === undefined ? {} : { exclude: values.exclude }),\n ...(values['format-index'] === undefined ? {} : { formatIndices: values['format-index'] }),\n ...(values['format-url'] === undefined ? {} : { formatUrls: values['format-url'] }),\n ...(values['tag-alias'] === undefined ? {} : { tagAliases: parseTagAliases(values['tag-alias']) }),\n ...(wordCountMethod === 'tweego' || wordCountMethod === 'whitespace' ? { wordCountMethod } : {}),\n ...(has('no-trim') ? { trim: false } : {}),\n ...(has('twee2-compat') ? { twee2Compat: true } : {}),\n ...(has('test') ? { testMode: true } : {}),\n ...(has('no-remote') ? { noRemote: true } : {}),\n ...(has('no-default-format-indices') ? { useDefaultFormatIndices: false } : {}),\n ...(has('source-info') ? { sourceInfo: true } : {}),\n };\n\n return {\n kind: 'build',\n action,\n sources: positionals,\n flags,\n config,\n log: { files: has('log-files'), stats: has('log-stats') },\n };\n}\n\n/** The compile options of a build request, the command line's settings winning over the config's. */\nexport interface ResolvedBuild {\n readonly action: BuildAction;\n readonly sources: readonly string[];\n /** `-` for standard output. */\n readonly output: string;\n readonly options: {\n readonly outputMode: OutputMode;\n readonly exclude?: readonly (string | ExcludeGlob)[] | undefined;\n readonly formatId?: string | undefined;\n readonly startPassage?: string | undefined;\n readonly formatPaths?: readonly string[] | undefined;\n readonly modules?: readonly string[] | undefined;\n readonly headFile?: string | undefined;\n readonly trim: boolean;\n readonly twee2Compat: boolean;\n readonly testMode: boolean;\n readonly useTweegoPath?: boolean | undefined;\n readonly formatIndices?: readonly string[] | undefined;\n readonly formatUrls?: readonly string[] | undefined;\n readonly noRemote: boolean;\n readonly formatFetchTimeout?: number | undefined;\n readonly formatResolutionTimeout?: number | undefined;\n readonly useDefaultFormatIndices: boolean;\n readonly tagAliases?: Readonly<Record<string, string>> | undefined;\n readonly sourceInfo: boolean;\n readonly wordCountMethod?: WordCountMethod | undefined;\n };\n}\n\n/**\n * Merges a build request with the config (already validated and rebased onto the working directory):\n * a setting on the command line wins, and `--tag-alias` adds to (and overrides) the config's aliases.\n * Throws a CliUsageError when no sources are given anywhere, or watch mode has no output file.\n */\nexport function resolveBuild(request: BuildRequest, config: TweeTsConfig | null): ResolvedBuild {\n const { flags } = request;\n const sources = request.sources.length > 0 ? request.sources : (config?.sources ?? []);\n if (sources.length === 0) throw new CliUsageError('no input sources: name them, or set \"sources\" in the config');\n const output = flags.output ?? config?.output ?? '-';\n if (request.action === 'watch' && output === '-') {\n throw new CliUsageError('watch mode needs an output file (-o, or \"output\" in the config)');\n }\n // Own-property-safe: Object.fromEntries defines `__proto__` as an ordinary key (#241).\n const aliasEntries = [...Object.entries(config?.tagAliases ?? {}), ...(flags.tagAliases ?? [])];\n return {\n action: request.action,\n sources,\n output,\n options: {\n outputMode: flags.outputMode ?? config?.outputMode ?? 'html',\n exclude: flags.exclude ?? config?.exclude,\n formatId: flags.formatId ?? config?.formatId,\n startPassage: flags.startPassage ?? config?.startPassage,\n formatPaths: config?.formatPaths,\n modules: flags.modules ?? config?.modules,\n headFile: flags.headFile ?? config?.headFile,\n trim: flags.trim ?? config?.trim ?? true,\n twee2Compat: flags.twee2Compat ?? config?.twee2Compat ?? false,\n testMode: flags.testMode ?? config?.testMode ?? false,\n useTweegoPath: config?.useTweegoPath,\n formatIndices: flags.formatIndices ?? config?.formatIndices,\n formatUrls: flags.formatUrls ?? config?.formatUrls,\n noRemote: flags.noRemote ?? config?.noRemote ?? false,\n formatFetchTimeout: config?.formatFetchTimeout,\n formatResolutionTimeout: config?.formatResolutionTimeout,\n useDefaultFormatIndices: flags.useDefaultFormatIndices ?? config?.useDefaultFormatIndices ?? true,\n tagAliases:\n aliasEntries.length > 0 || config?.tagAliases !== undefined ? Object.fromEntries(aliasEntries) : undefined,\n sourceInfo: flags.sourceInfo ?? config?.sourceInfo ?? false,\n wordCountMethod: flags.wordCountMethod ?? config?.wordCountMethod,\n },\n };\n}\n\n/** Whether a `-c` value that names no file looks like a charset, as Tweego's `-c` takes one. */\nexport function looksLikeCharset(value: string): boolean {\n return /^(?:utf-?(?:8|16(?:le|be)?|32)|windows-\\d{3,4}|cp\\d{3,4}|iso-?8859-\\d{1,2}|latin-?\\d|(?:us-)?ascii|macintosh|koi8-[ru]|shift[-_]jis|euc-[a-z]{2}|gbk|big5)$/i.test(\n value,\n );\n}\n\n/** The help text. */\nexport function usageText(version: string, configFilename: string): string {\n return `twee-ts v${version} — TypeScript Twee-to-HTML compiler\n\nUsage: twee-ts [options] <sources...>\n twee-ts cache <list|clear [name]|size|path>\n\nOptions:\n -o, --output <file> Output file; - for standard output (default)\n -f, --format <id> Story format ID (default: sugarcube-2)\n -s, --start <name> Starting passage (default: Start)\n -m, --module <file> Module file to inject into <head> (repeatable)\n --head <file> Raw HTML file to append to <head>\n -d, --decompile-twee3 Output as Twee 3 source\n --decompile-twee1 Output as Twee 1 source\n -a, --archive-twine2 Output as Twine 2 archive\n --archive-twine1 Output as Twine 1 archive\n --json Output as JSON\n --twee2-compat Enable Twee2 syntax compatibility\n --lint Lint story structure (broken links, dead ends, orphans)\n --no-trim Don't trim passage whitespace\n -t, --test Enable test/debug mode\n -w, --watch Watch for changes and rebuild\n -l, --log-stats Log compilation statistics (to standard error)\n --log-files Log the files read (to standard error)\n --list-formats List available story formats\n --init Initialize a new project\n --format-index <url> SFA-compatible format index URL (repeatable)\n --format-url <url> Direct format.js URL (repeatable)\n --tag-alias <alias=target> Map a tag to a special tag (repeatable)\n --exclude <glob> Leave out source files matching a glob (repeatable)\n --source-info Emit source file/line as data- attributes on passages\n --word-count-method <m> Word counting method: tweego (default), whitespace\n --no-remote Disable remote format fetching\n --no-default-format-indices\n Don't ask the Story Formats Archive indices\n -c, --config <file> Config file path (default: ${configFilename})\n --no-config Skip config file loading\n -h, --help Show this help\n -v, --version Show version\n\nUse -- before sources whose names start with - (or a first source named cache).\n\nSubcommands:\n cache list List cached remote formats\n cache clear [name] Clear cached formats (all or by name)\n cache size Show total cache size\n cache path Print cache directory path\n\nExit status: 0 success, 1 build or lint errors, 2 usage errors.`;\n}\n\n/** The help text of the cache subcommand. */\nexport const CACHE_USAGE = `Usage: twee-ts cache <list|clear|size|path>\n\n list List cached formats with name, version, size\n clear Delete all cached formats\n clear <name> Delete cached formats matching name\n size Show total cache size\n path Print cache directory path`;\n","/**\n * Which errors of a write to a stream mean the reader at the other end has gone, as opposed to a write that\n * failed (a full disk, an I/O error, a closed descriptor).\n *\n * Writing to a pipe or socket whose reader has closed is reported differently by each platform; libuv passes\n * the operating system's error on:\n *\n * - `EPIPE`: Linux and macOS (the signal is ignored by Node), and Windows named pipes whose other end is\n * closing (`ERROR_NO_DATA`, `ERROR_PIPE_NOT_CONNECTED`).\n * - `EOF`: Windows named pipes whose other end is closed (`ERROR_BROKEN_PIPE`), which libuv reports as its\n * own end-of-file code.\n * - `ENOTCONN`: macOS, for a pipe or socket pair whose peer is gone, where Linux gives `EPIPE`; Windows sockets.\n * - `ECONNRESET`, `ECONNABORTED`: the peer reset or aborted the connection (a socket as standard output).\n * - `ESHUTDOWN`: the socket was shut down for writing.\n * - `ERR_STREAM_DESTROYED`: Node's own error for a write after the stream has been destroyed, which follows\n * any of the above.\n */\nconst READER_GONE: ReadonlySet<string> = new Set([\n 'EPIPE',\n 'EOF',\n 'ENOTCONN',\n 'ECONNRESET',\n 'ECONNABORTED',\n 'ESHUTDOWN',\n 'ERR_STREAM_DESTROYED',\n]);\n\n/** Whether a stream write error is the reader going away, which ends the output quietly. */\nexport function isReaderGone(error: { readonly code?: unknown }): boolean {\n return typeof error.code === 'string' && READER_GONE.has(error.code);\n}\n","/**\n * twee-ts CLI entry point.\n *\n * The command line is parsed completely into a request first (src/cli-request.ts), then run. Standard\n * output carries only what was asked for: the story when it goes there, or the answer of a query command\n * (--help, --version, --list-formats, cache, --lint's report, --init's report). Diagnostics, logs, --log-stats\n * and --log-files go to standard error. Exit status: 0 success, 1 build or lint errors, 2 usage errors.\n */\nimport { writeFileSync, mkdirSync } from 'node:fs';\nimport { compileForOutputFile, resourceLimitError, TweeTsError, watchWithWriteFilter } from '../src/compiler.js';\nimport type { ExtraInput } from '../src/compiler.js';\nimport { escapeTerminalControls, formatDiagnostic } from '../src/diagnostic-text.js';\nimport { WatchPathError } from '../src/filesystem.js';\nimport { writeFileAtomic } from '../src/atomic-write.js';\nimport { lintForOutputFile, formatLintReport } from '../src/lint.js';\nimport { discoverAllFormats, getFormatSearchDirs, makeFormatId, pruneFormats } from '../src/formats.js';\nimport { loadConfig, loadConfigFile, scaffoldConfig, CONFIG_FILENAME } from '../src/config.js';\nimport {\n CACHE_USAGE,\n CliUsageError,\n looksLikeCharset,\n parseCliArgs,\n resolveBuild,\n usageText,\n} from '../src/cli-request.js';\nimport type { BuildRequest, CacheAction, ConfigChoice, ResolvedBuild } from '../src/cli-request.js';\nimport { listRecords, loadEntry } from '../src/format-cache.js';\nimport {\n cachedUrlRecord,\n checkRemoteUrl,\n DEFAULT_SFA_INDICES,\n getCacheDir,\n listCachedFormats,\n clearCachedFormats,\n getCacheSize,\n} from '../src/remote-formats.js';\nimport type { CompileResult, Diagnostic, TweeTsConfig, WatchOptions } from '../src/types.js';\nimport { compareVersions, parseVersion } from '../src/semver.js';\n\nimport { isReaderGone } from '../src/stream-errors.js';\nimport { VERSION } from '../src/version.js';\nimport { generateIFID } from '../src/ifid.js';\n\n/** Exit statuses. */\nconst EXIT_OK = 0;\nconst EXIT_FAILED = 1;\nconst EXIT_USAGE = 2;\n\n/** Writes to standard output: only the story, or a query command's answer. */\nfunction out(text: string): void {\n process.stdout.write(text.endsWith('\\n') ? text : `${text}\\n`);\n}\n\n/** Writes a line to standard error: everything else. */\nfunction log(text: string): void {\n process.stderr.write(`${escapeTerminalControls(text, true)}\\n`);\n}\n\n/**\n * A reader that goes away (`twee-ts … | head`) closes the pipe: the rest of the output is dropped\n * quietly, as other command-line tools do, instead of ending in an unhandled error (`EPIPE`, or what the\n * platform reports instead, see `isReaderGone`). Any other\n * failure to write (a full disk behind a redirect, an I/O error) is reported once, naming the stream\n * when `name` is given (standard error cannot report its own failure), and ends the run with status 1.\n */\nfunction reportWriteErrors(stream: NodeJS.WriteStream, name?: string): void {\n let reported = false;\n stream.on('error', (e: NodeJS.ErrnoException) => {\n if (isReaderGone(e)) return;\n process.exitCode = EXIT_FAILED;\n if (reported || name === undefined) return;\n reported = true;\n log(`error: Cannot write ${name}: ${escapeTerminalControls(e.message)}`);\n });\n}\n\nasync function main(argv: readonly string[]): Promise<number> {\n const parsed = parseCliArgs(argv);\n if (!parsed.ok) return usageError(parsed.error);\n const { request } = parsed;\n switch (request.kind) {\n case 'help':\n out(usageText(VERSION, CONFIG_FILENAME));\n return EXIT_OK;\n case 'version':\n out(`twee-ts v${VERSION}`);\n return EXIT_OK;\n case 'init':\n runInit();\n return EXIT_OK;\n case 'cache-help':\n out(CACHE_USAGE);\n return EXIT_OK;\n case 'cache':\n runCache(request.action);\n return EXIT_OK;\n case 'cache-clear':\n runCacheClear(request.name);\n return EXIT_OK;\n case 'list-formats': {\n const config = readConfig(request.config);\n // Listed after the config is read, so the list shows what --format can select in this project.\n listFormats(config.config);\n return EXIT_OK;\n }\n case 'build':\n return runBuild(request);\n default: {\n const _exhaustive: never = request;\n throw new Error(`unhandled request: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\nfunction usageError(error: CliUsageError): number {\n log(`error: ${escapeTerminalControls(error.message)}`);\n log('Run \"twee-ts --help\" for usage.');\n return EXIT_USAGE;\n}\n\n/** A CLI-authored hint: only its separator is a live newline; the compiler's message is escaped first. */\nclass CharsetConfigError extends TweeTsError {\n constructor(error: TweeTsError) {\n const note = `-c is --config in twee-ts, not Tweego's --charset; twee-ts reads UTF-8 (or UTF-16 after a byte order mark) and falls back to Windows-1252.`;\n super(`${escapeTerminalControls(error.message)}\\nnote: ${note}`, error.diagnostics, {\n code: 'INPUT_UNAVAILABLE',\n cause: error,\n });\n }\n}\n\n/** The config the request asks for, and its path (an input the output must not overwrite). */\nfunction readConfig(choice: ConfigChoice): { readonly config: TweeTsConfig | null; readonly path?: string } {\n // Warnings, such as unknown keys, which leave the config usable.\n const diagnostics: Diagnostic[] = [];\n let result: { readonly config: TweeTsConfig | null; readonly path?: string };\n switch (choice.kind) {\n case 'none':\n return { config: null };\n case 'file':\n try {\n result = { config: loadConfigFile(choice.path, diagnostics), path: choice.path };\n } catch (e) {\n // Tweego's -c is --charset: say so when the \"config file\" is a charset name.\n if (e instanceof TweeTsError && e.code === 'INPUT_UNAVAILABLE' && looksLikeCharset(choice.path)) {\n throw new CharsetConfigError(e);\n }\n throw e;\n }\n break;\n case 'auto': {\n const config = loadConfig(undefined, diagnostics);\n result = config === null ? { config } : { config, path: CONFIG_FILENAME };\n break;\n }\n default: {\n const _exhaustive: never = choice;\n throw new Error(`unhandled config choice: ${JSON.stringify(_exhaustive)}`);\n }\n }\n logDiagnostics(diagnostics);\n return result;\n}\n\nasync function runBuild(request: BuildRequest): Promise<number> {\n const config = readConfig(request.config);\n let build: ResolvedBuild;\n try {\n build = resolveBuild(request, config.config);\n } catch (e) {\n if (e instanceof CliUsageError) return usageError(e);\n throw e;\n }\n const compileOptions = { ...build.options, sources: build.sources };\n // The output file, which every build (and lint) leaves out of the sources and modules,\n // so an earlier build inside a source folder is never read back as a source.\n const outPath = build.output === '-' ? undefined : build.output;\n const extraInputs: ExtraInput[] = config.path === undefined ? [] : [{ role: 'config', path: config.path }];\n\n switch (build.action) {\n case 'lint': {\n const lintResult = await lintForOutputFile(compileOptions, outPath);\n out(formatLintReport(lintResult));\n const hasErrors = lintResult.brokenLinks.length > 0 || lintResult.diagnostics.some((d) => d.level === 'error');\n return hasErrors ? EXIT_FAILED : EXIT_OK;\n }\n case 'watch':\n // resolveBuild() refuses watch mode without an output file.\n return startWatch(compileOptions, outPath ?? build.output, request.log, extraInputs);\n case 'once': {\n // An output that can't be written (a missing folder, a read-only file) fails before the build's work.\n const result = await compileForOutputFile(compileOptions, outPath, undefined, extraInputs, true);\n logDiagnostics(result.diagnostics);\n // Like Tweego, a build with errors produces no output: the output file (or stdout)\n // is left untouched and the exit status is 1, so scripts and CI can detect it.\n const errors = countErrors(result.diagnostics);\n let status = EXIT_OK;\n if (errors > 0) {\n log(`Compilation failed with ${pluralize(errors, 'error')}; output not written.`);\n status = EXIT_FAILED;\n } else if (outPath === undefined) {\n process.stdout.write(result.output);\n } else {\n writeFileAtomic(outPath, result.output);\n }\n logBuild(result, request.log);\n return status;\n }\n default: {\n const _exhaustive: never = build.action;\n throw new Error(`unhandled build action: ${String(_exhaustive)}`);\n }\n }\n}\n\n/** Starts watch mode; the process keeps running until it is stopped, or the watch stops on its own. */\nfunction startWatch(\n options: Omit<WatchOptions, 'outFile'>,\n outFile: string,\n logOptions: BuildRequest['log'],\n extraInputs: readonly ExtraInput[],\n): number {\n // As in a one-shot build, a build with errors is not written: the output file keeps\n // the last good build until a save fixes the errors.\n watchWithWriteFilter(\n {\n ...options,\n outFile,\n onBuild(result) {\n const counts = `${result.stats.passages} passages, ${result.stats.words} words`;\n const errors = countErrors(result.diagnostics);\n // A build is reported as built only when it is written (#451): the same test as the write filter below.\n if (errors === 0) log(`Built: ${counts}`);\n logDiagnostics(result.diagnostics);\n // A failed build must not stop the watcher: report it and wait for the next change.\n if (errors > 0) {\n log(`Build failed: ${counts}`);\n log(`Build has ${pluralize(errors, 'error')}; output not written. Still watching for changes.`);\n }\n logBuild(result, logOptions);\n },\n onError(error) {\n process.exitCode = EXIT_FAILED;\n if (error instanceof WatchPathError) {\n // The other paths are still watched; with nothing left to watch, the process exits with status 1.\n log(`error: ${escapeTerminalControls(error.message)}`);\n } else {\n logErrorDiagnostics(error);\n log(`Build error: ${escapeTerminalControls(error.message)}`);\n }\n },\n },\n (result) => countErrors(result.diagnostics) === 0,\n { extraInputs },\n );\n // Only now: watchWithWriteFilter() refuses options that cannot be watched before it watches anything.\n log('Watch mode started. Press CTRL+C to stop.');\n // Until the watch ends; the status is set by onError if it fails.\n return EXIT_OK;\n}\n\nfunction logBuild(result: CompileResult, logOptions: BuildRequest['log']): void {\n if (logOptions.files) {\n log(`\\nFiles: ${result.stats.files.map((file) => escapeTerminalControls(file)).join(', ')}`);\n const external = result.stats.externalFiles ?? [];\n if (external.length > 0) log(`External files: ${external.map((file) => escapeTerminalControls(file)).join(', ')}`);\n }\n if (logOptions.stats) logStats(result);\n}\n\nfunction countErrors(diagnostics: readonly Diagnostic[]): number {\n return diagnostics.filter((d) => d.level === 'error').length;\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\n/** Order version strings from highest to lowest SemVer precedence (unparseable ones last). */\nfunction byVersionDescending(a: string, b: string): number {\n const left = parseVersion(a);\n const right = parseVersion(b);\n if (!left || !right) return Number(!left) - Number(!right);\n return compareVersions(right, left);\n}\n\n/**\n * The cached downloads a build with these settings would consider, as resolution considers them (see\n * format-resolution.ts): the cached copy of each configured format URL, and what was downloaded from each\n * configured format index and, unless `useDefaultFormatIndices` is off, from the Story Formats Archive, each\n * under the name and version its source lists. A download from a URL or index the project doesn't configure\n * is never used, so it isn't listed; neither is an entry whose files are damaged. `cache list` lists every\n * download.\n */\nfunction consideredDownloads(\n formatUrls: readonly string[],\n formatIndices: readonly string[],\n useDefaultFormatIndices: boolean,\n diagnostics: Diagnostic[],\n): { readonly name: string; readonly version: string }[] {\n const checked = (urls: readonly string[], option: string): string[] =>\n urls.flatMap((text) => {\n const result = checkRemoteUrl(text);\n if (result.ok) return [result.url];\n diagnostics.push({ level: 'warning', message: `${option}: ${result.reason}` });\n return [];\n });\n const indices = new Set([\n ...checked(formatIndices, 'formatIndices'),\n ...(useDefaultFormatIndices ? DEFAULT_SFA_INDICES : []),\n ]);\n const fromUrls = checked(formatUrls, 'formatUrls').flatMap((url) => cachedUrlRecord(url) ?? []);\n const fromIndices = listRecords().filter((r) => r.origin.kind === 'index' && indices.has(r.origin.index));\n return [...fromUrls, ...fromIndices]\n .filter((record) => 'record' in loadEntry(record))\n .map((record) => (record.origin.kind === 'index' ? record.origin : record));\n}\n\n/**\n * Print the formats --format can select: local folders (pruned by SemVer), and the cached downloads a\n * build would consider (see consideredDownloads), by ID.\n */\nfunction listFormats(config: TweeTsConfig | null): void {\n const diagnostics: Diagnostic[] = [];\n const searchDirs = getFormatSearchDirs(config?.formatPaths ?? [], config?.useTweegoPath ?? true);\n const formats = pruneFormats(discoverAllFormats(searchDirs, diagnostics));\n const downloads = consideredDownloads(\n config?.formatUrls ?? [],\n config?.formatIndices ?? [],\n config?.useDefaultFormatIndices ?? true,\n diagnostics,\n );\n logDiagnostics(diagnostics);\n\n out('Local story formats:');\n if (formats.size === 0) {\n out(' (none)');\n } else {\n for (const [id, f] of formats) {\n const type = f.isTwine2 ? 'Twine 2' : 'Twine 1';\n out(\n ` ${escapeTerminalControls(id)}: ${escapeTerminalControls(f.name || id)} ${escapeTerminalControls(f.version)} (${type})`,\n );\n }\n }\n\n // Cached downloads answer an ID request by name and major version, taking the greatest version.\n const cachedById = new Map<string, { readonly name: string; readonly version: string }[]>();\n for (const f of downloads) {\n const id = makeFormatId(f.name, f.version);\n cachedById.set(id, [...(cachedById.get(id) ?? []), f]);\n }\n if (cachedById.size > 0) {\n out('\\nCached remote formats:');\n for (const [id, versions] of [...cachedById].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {\n const [newest, ...older] = [...versions].sort((a, b) => byVersionDescending(a.version, b.version));\n if (!newest) continue;\n const also =\n older.length > 0 ? ` (also cached: ${older.map((f) => escapeTerminalControls(f.version)).join(', ')})` : '';\n out(\n ` ${escapeTerminalControls(id)}: ${escapeTerminalControls(newest.name)} ${escapeTerminalControls(newest.version)}${also}`,\n );\n }\n }\n}\n\n/** Prints diagnostics to standard error, each with the file and line it is about (see formatDiagnostic). */\nfunction logDiagnostics(diagnostics: readonly Diagnostic[]): void {\n for (const d of diagnostics) log(`${d.level === 'error' ? 'error' : 'warning'}: ${formatDiagnostic(d)}`);\n}\n\n/** Prints what a fatal TweeTsError collected (such as why no story format was found) before its message. */\nfunction logErrorDiagnostics(error: unknown): void {\n if (error instanceof TweeTsError) logDiagnostics(error.diagnostics);\n}\n\nfunction logStats(result: CompileResult): void {\n const s = result.stats;\n log(`\\nStatistics:`);\n log(` Passages: ${s.passages}`);\n log(` Words: ${s.words}`);\n log(` Files: ${s.files.length}`);\n}\n\ninterface ScaffoldFile {\n readonly path: string;\n readonly content: () => string;\n}\n\nconst SCAFFOLD_FILES: readonly ScaffoldFile[] = [\n { path: CONFIG_FILENAME, content: scaffoldConfig },\n {\n path: 'src/StoryData.tw',\n content: () => `:: StoryData\n{\n\\t\"ifid\": \"${generateIFID()}\"\n}\n`,\n },\n {\n path: 'src/StoryTitle.tw',\n content: () => `:: StoryTitle\nMy Story\n`,\n },\n {\n path: 'src/Start.tw',\n content: () => `:: Start\nWelcome to your new Twine story!\n\nThis is the starting passage. Edit this file to begin writing your story.\n`,\n },\n];\n\n/**\n * Writes `content` to `path` unless the file already exists.\n * The exclusive flag makes the check and the write one step, so an existing file is never truncated.\n * Returns false when the file was already there.\n */\nfunction writeNewFile(path: string, content: string): boolean {\n try {\n writeFileSync(path, content, { flag: 'wx' });\n return true;\n } catch (e) {\n if (e instanceof Error && 'code' in e && e.code === 'EEXIST') return false;\n throw new Error(`Cannot create ${path}: ${e instanceof Error ? e.message : String(e)}`, { cause: e });\n }\n}\n\nfunction runInit(): void {\n out('Initializing new twee-ts project...');\n mkdirSync('src', { recursive: true });\n\n // Existing files are kept as they are: --init never overwrites a story, its IFID, or a config.\n const results = SCAFFOLD_FILES.map((file) => ({ path: file.path, created: writeNewFile(file.path, file.content()) }));\n const created = results.filter((r) => r.created).map((r) => r.path);\n const skipped = results.filter((r) => !r.created).map((r) => r.path);\n\n if (created.length > 0) {\n out('Created:');\n for (const path of created) out(` ${path}`);\n }\n for (const path of skipped) out(`Skipped (already exists): ${path}`);\n out('\\nRun: npx @rohal12/twee-ts');\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${Math.round(kb)}K`;\n const mb = kb / 1024;\n return `${mb.toFixed(1)}M`;\n}\n\nfunction runCache(action: CacheAction): void {\n switch (action) {\n case 'list': {\n const entries = listCachedFormats();\n if (entries.length === 0) {\n out('No cached formats.');\n return;\n }\n for (const e of entries) {\n const date = e.modifiedAt.toISOString().slice(0, 10);\n out(\n `${escapeTerminalControls(e.name).padEnd(16)} ${escapeTerminalControls(e.version).padEnd(10)} ${formatBytes(e.sizeBytes).padStart(6)} ${date}`,\n );\n }\n return;\n }\n case 'size': {\n const { totalBytes, count } = getCacheSize();\n out(\n count === 0\n ? 'Cache is empty.'\n : `Total: ${formatBytes(totalBytes)} (${count} format${count === 1 ? '' : 's'})`,\n );\n return;\n }\n case 'path':\n out(escapeTerminalControls(getCacheDir()));\n return;\n default: {\n const _exhaustive: never = action;\n throw new Error(`unhandled cache action: ${String(_exhaustive)}`);\n }\n }\n}\n\nfunction runCacheClear(name: string | undefined): void {\n const count = clearCachedFormats(name);\n if (count === 0) {\n out(name ? `No cached formats matching \"${escapeTerminalControls(name)}\".` : 'Cache is already empty.');\n } else {\n out(`Cleared ${count} cached format${count === 1 ? '' : 's'}.`);\n }\n}\n\nreportWriteErrors(process.stdout, 'standard output');\nreportWriteErrors(process.stderr);\n\nmain(process.argv.slice(2)).then(\n (status) => {\n // process.exitCode, not process.exit(): output still being written to a pipe is not cut off.\n if (process.exitCode === undefined || status !== EXIT_OK) process.exitCode = status;\n },\n (thrown: unknown) => {\n // An engine limit reached outside a build (in lint, say) is named as a build's is.\n const err = resourceLimitError(thrown) ?? thrown;\n logErrorDiagnostics(err);\n const message =\n err instanceof CharsetConfigError\n ? err.message\n : escapeTerminalControls(err instanceof Error ? err.message : String(err));\n log(`error: ${message}`);\n process.exitCode = EXIT_FAILED;\n },\n);\n"],"mappings":"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"}
|