ts-repo-utils 10.3.3 → 10.5.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/README.md +16 -0
- package/dist/cmd/assert-repo-is-clean.mjs +1 -0
- package/dist/cmd/assert-repo-is-clean.mjs.map +1 -1
- package/dist/cmd/check-should-run-type-checks.mjs +1 -0
- package/dist/cmd/check-should-run-type-checks.mjs.map +1 -1
- package/dist/cmd/check-should-run.mjs +1 -0
- package/dist/cmd/check-should-run.mjs.map +1 -1
- package/dist/cmd/format-diff-from.mjs +1 -0
- package/dist/cmd/format-diff-from.mjs.map +1 -1
- package/dist/cmd/format-uncommitted.mjs +1 -0
- package/dist/cmd/format-uncommitted.mjs.map +1 -1
- package/dist/cmd/gen-index-ts.mjs +10 -2
- package/dist/cmd/gen-index-ts.mjs.map +1 -1
- package/dist/entry-point.mjs +1 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functions/assert-ext.mjs.map +1 -1
- package/dist/functions/assert-path-exists.mjs.map +1 -1
- package/dist/functions/assert-repo-is-clean.mjs.map +1 -1
- package/dist/functions/create-result-assert.mjs.map +1 -1
- package/dist/functions/diff.mjs.map +1 -1
- package/dist/functions/exec-async.mjs.map +1 -1
- package/dist/functions/format.mjs.map +1 -1
- package/dist/functions/gen-index.d.mts +17 -0
- package/dist/functions/gen-index.d.mts.map +1 -1
- package/dist/functions/gen-index.mjs +26 -9
- package/dist/functions/gen-index.mjs.map +1 -1
- package/dist/functions/glob.mjs.map +1 -1
- package/dist/functions/index.d.mts +1 -0
- package/dist/functions/index.d.mts.map +1 -1
- package/dist/functions/index.mjs +1 -0
- package/dist/functions/index.mjs.map +1 -1
- package/dist/functions/is-directly-executed.mjs.map +1 -1
- package/dist/functions/make-empty-dir.mjs.map +1 -1
- package/dist/functions/should-run.mjs.map +1 -1
- package/dist/functions/strip-dev-only-code.d.mts +85 -0
- package/dist/functions/strip-dev-only-code.d.mts.map +1 -0
- package/dist/functions/strip-dev-only-code.mjs +302 -0
- package/dist/functions/strip-dev-only-code.mjs.map +1 -0
- package/dist/functions/workspace-utils/execute-parallel.mjs.map +1 -1
- package/dist/functions/workspace-utils/get-workspace-packages.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs.map +1 -1
- package/dist/functions/workspace-utils/run-cmd-in-stages.mjs.map +1 -1
- package/dist/functions/workspace-utils/types.mjs.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -12
- package/src/cmd/gen-index-ts.mts +11 -0
- package/src/functions/gen-index.mts +92 -9
- package/src/functions/index.mts +1 -0
- package/src/functions/strip-dev-only-code.mts +672 -0
- package/src/functions/strip-dev-only-code.test.mts +458 -0
package/README.md
CHANGED
|
@@ -133,6 +133,10 @@ npm exec -- gen-index-ts ./src --target-ext .ts --index-ext .ts --export-ext .js
|
|
|
133
133
|
# Skip generating index files at the root level (depth 0), only generate from depth 1 onwards
|
|
134
134
|
npm exec -- gen-index-ts ./src --target-ext .mts --index-ext .mts --export-ext .mjs --min-depth 1
|
|
135
135
|
|
|
136
|
+
# Leave hand-written index files alone: an executable entry point at ./src/index.mts,
|
|
137
|
+
# and a curated list of named re-exports in every ./src/v*/index.mts
|
|
138
|
+
npm exec -- gen-index-ts ./src --target-ext .mts --index-ext .mts --export-ext .mjs --preserve index.mts --preserve 'v*/index.mts'
|
|
139
|
+
|
|
136
140
|
# Example in npm scripts
|
|
137
141
|
"gi": "gen-index-ts ./src --index-ext .mts --export-ext .mjs --target-ext .mts --target-ext .tsx --fmt 'npm run fmt'"
|
|
138
142
|
```
|
|
@@ -159,8 +163,20 @@ npm exec -- gen-index-ts ./src --target-ext .mts --index-ext .mts --export-ext .
|
|
|
159
163
|
- `--exclude` - Glob patterns of files to exclude (optional, can be specified multiple times)
|
|
160
164
|
- `--fmt` - Command to format after generating the index file (optional)
|
|
161
165
|
- `--min-depth` - Minimum depth to start generating index files (default: 0)
|
|
166
|
+
- `--preserve` - Glob patterns of index files to leave untouched (optional, can be specified multiple times)
|
|
162
167
|
- `--silent` - Suppress output messages (optional)
|
|
163
168
|
|
|
169
|
+
`--exclude` and `--preserve` answer different questions. `--exclude` says what an
|
|
170
|
+
index file may not _export_, and its patterns are matched against a bare file
|
|
171
|
+
name as well as a path relative to the target directory. `--preserve` says which
|
|
172
|
+
index files must not be _written_, and matches on the relative path alone — so
|
|
173
|
+
`--preserve index.mts` names the one at the root of the walk, where
|
|
174
|
+
`--exclude index.mts` would name every index file in the tree (and, index files
|
|
175
|
+
never being exported in the first place, does nothing at all).
|
|
176
|
+
|
|
177
|
+
A preserved directory is still walked, so index files below it are still
|
|
178
|
+
generated, and its parent still re-exports it.
|
|
179
|
+
|
|
164
180
|
### `check-should-run`
|
|
165
181
|
|
|
166
182
|
Checks whether a CI step should run, based on which files differ from the base branch. Reports `false` when every changed file matches one of the `--paths-ignore` patterns, so a step can be skipped when nothing it checks has changed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-repo-is-clean.mjs","sources":["../../src/cmd/assert-repo-is-clean.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { assertRepoIsClean } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'assert-repo-is-clean-cli',\n version: '10.1.8',\n args: {\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (args: Readonly<{ silent?: boolean }>): Promise<void> => {\n await assertRepoIsClean({ silent: args.silent });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assert-repo-is-clean.mjs","sources":["../../src/cmd/assert-repo-is-clean.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { assertRepoIsClean } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'assert-repo-is-clean-cli',\n version: '10.1.8',\n args: {\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (args: Readonly<{ silent?: boolean }>): Promise<void> => {\n await assertRepoIsClean({ silent: args.silent });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAMA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ;AAAA,EACzB,IAAA,EAAM,0BAAA;AAAA,EACN,OAAA,EAAS,QAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,MAAA,EAAQ,IAAI,IAAA,CAAK;AAAA,MACf,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA;AAAA,MAC9B,WAAA,EAAa;AAAA,KACd;AAAA,GACH;AAAA,EACA,OAAA,EAAS,CAAC,IAAA,KAAS;AACjB,IAAA,IAAA,CAAK,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AACnC,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AAEzC,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAED,MAAM,IAAA,GAAO,OAAO,IAAA,KAAwD;AAC1E,EAAA,MAAM,iBAAA,CAAkB,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAQ,CAAA;AACjD,CAAA;AAEA,MAAM,GAAA,CAAI,IAAI,MAAA,EAAQ,GAAA,CAAI,KAAK,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-should-run-type-checks.mjs","sources":["../../src/cmd/check-should-run-type-checks.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { checkShouldRunTypeChecks } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'check-should-run-type-checks-cli',\n version: '10.1.8',\n args: {\n pathsIgnore: cmd.multioption({\n long: 'paths-ignore',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Patterns to ignore when checking if type checks should run. Supports exact file matches, directory prefixes (ending with \"/\"), and file extensions (starting with \"**.\")',\n }),\n baseBranch: cmd.option({\n long: 'base-branch',\n type: cmd.optional(cmd.string),\n description:\n 'Base branch to compare against for determining changed files. Defaults to \"origin/main\"',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<void> => {\n await checkShouldRunTypeChecks({\n pathsIgnore: args.pathsIgnore,\n baseBranch: args.baseBranch,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check-should-run-type-checks.mjs","sources":["../../src/cmd/check-should-run-type-checks.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { checkShouldRunTypeChecks } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'check-should-run-type-checks-cli',\n version: '10.1.8',\n args: {\n pathsIgnore: cmd.multioption({\n long: 'paths-ignore',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Patterns to ignore when checking if type checks should run. Supports exact file matches, directory prefixes (ending with \"/\"), and file extensions (starting with \"**.\")',\n }),\n baseBranch: cmd.option({\n long: 'base-branch',\n type: cmd.optional(cmd.string),\n description:\n 'Base branch to compare against for determining changed files. Defaults to \"origin/main\"',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<void> => {\n await checkShouldRunTypeChecks({\n pathsIgnore: args.pathsIgnore,\n baseBranch: args.baseBranch,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAMA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ;AAAA,EACzB,IAAA,EAAM,kCAAA;AAAA,EACN,OAAA,EAAS,QAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,WAAA,EAAa,IAAI,WAAA,CAAY;AAAA,MAC3B,IAAA,EAAM,cAAA;AAAA,MACN,MAAM,GAAA,CAAI,QAAA,CAAS,IAAI,KAAA,CAAM,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,MACxC,WAAA,EACE;AAAA,KACH,CAAA;AAAA,IACD,UAAA,EAAY,IAAI,MAAA,CAAO;AAAA,MACrB,IAAA,EAAM,aAAA;AAAA,MACN,IAAA,EAAM,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA;AAAA,MAC7B,WAAA,EACE;AAAA,KACH;AAAA,GACH;AAAA,EACA,OAAA,EAAS,CAAC,IAAA,KAAS;AACjB,IAAA,IAAA,CAAK,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AACnC,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AAEzC,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAED,MAAM,IAAA,GAAO,OACX,IAAA,KAIkB;AAClB,EAAA,MAAM,wBAAA,CAAyB;AAAA,IAC7B,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,YAAY,IAAA,CAAK;AAAA,GAClB,CAAA;AACH,CAAA;AAEA,MAAM,GAAA,CAAI,IAAI,MAAA,EAAQ,GAAA,CAAI,KAAK,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-should-run.mjs","sources":["../../src/cmd/check-should-run.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { checkShouldRun } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'check-should-run-cli',\n version: '10.2.0',\n args: {\n pathsIgnore: cmd.multioption({\n long: 'paths-ignore',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Patterns whose files do not affect the gated step. Matched with micromatch against repository-relative paths, with a trailing \"/\" as the shorthand for a directory (e.g. \"experimental/\", \".editorconfig\", \"**.md\"). Defaults to ignoring nothing.',\n }),\n baseBranch: cmd.option({\n long: 'base-branch',\n type: cmd.optional(cmd.string),\n description:\n 'Base branch to compare against for determining changed files. Defaults to \"origin/main\"',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<void> => {\n await checkShouldRun({\n pathsIgnore: args.pathsIgnore,\n baseBranch: args.baseBranch,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check-should-run.mjs","sources":["../../src/cmd/check-should-run.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr } from 'ts-data-forge';\nimport { checkShouldRun } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'check-should-run-cli',\n version: '10.2.0',\n args: {\n pathsIgnore: cmd.multioption({\n long: 'paths-ignore',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Patterns whose files do not affect the gated step. Matched with micromatch against repository-relative paths, with a trailing \"/\" as the shorthand for a directory (e.g. \"experimental/\", \".editorconfig\", \"**.md\"). Defaults to ignoring nothing.',\n }),\n baseBranch: cmd.option({\n long: 'base-branch',\n type: cmd.optional(cmd.string),\n description:\n 'Base branch to compare against for determining changed files. Defaults to \"origin/main\"',\n }),\n },\n handler: (args) => {\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n pathsIgnore?: readonly string[];\n baseBranch?: string;\n }>,\n): Promise<void> => {\n await checkShouldRun({\n pathsIgnore: args.pathsIgnore,\n baseBranch: args.baseBranch,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAMA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ;AAAA,EACzB,IAAA,EAAM,sBAAA;AAAA,EACN,OAAA,EAAS,QAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,WAAA,EAAa,IAAI,WAAA,CAAY;AAAA,MAC3B,IAAA,EAAM,cAAA;AAAA,MACN,MAAM,GAAA,CAAI,QAAA,CAAS,IAAI,KAAA,CAAM,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,MACxC,WAAA,EACE;AAAA,KACH,CAAA;AAAA,IACD,UAAA,EAAY,IAAI,MAAA,CAAO;AAAA,MACrB,IAAA,EAAM,aAAA;AAAA,MACN,IAAA,EAAM,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA;AAAA,MAC7B,WAAA,EACE;AAAA,KACH;AAAA,GACH;AAAA,EACA,OAAA,EAAS,CAAC,IAAA,KAAS;AACjB,IAAA,IAAA,CAAK,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AACnC,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AAEzC,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAED,MAAM,IAAA,GAAO,OACX,IAAA,KAIkB;AAClB,EAAA,MAAM,cAAA,CAAe;AAAA,IACnB,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,YAAY,IAAA,CAAK;AAAA,GAClB,CAAA;AACH,CAAA;AAEA,MAAM,GAAA,CAAI,IAAI,MAAA,EAAQ,GAAA,CAAI,KAAK,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-diff-from.mjs","sources":["../../src/cmd/format-diff-from.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, Result } from 'ts-data-forge';\nimport { formatDiffFrom } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'format-diff-from-cli',\n version: '10.1.8',\n args: {\n base: cmd.positional({\n type: cmd.string,\n displayName: 'base',\n description: 'Base branch name or commit hash to compare against',\n }),\n excludeUntracked: cmd.flag({\n long: 'exclude-untracked',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude untracked files in addition to diff files (default: false)',\n }),\n excludeModified: cmd.flag({\n long: 'exclude-modified',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude modified files in addition to diff files (default: false)',\n }),\n excludeStaged: cmd.flag({\n long: 'exclude-staged',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude staged files in addition to diff files (default: false)',\n }),\n ignoreUnknown: cmd.flag({\n long: 'ignore-unknown',\n type: cmd.optional(cmd.boolean),\n description: 'Ignore unknown files (default: true)',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n cwd: cmd.option({\n long: 'cwd',\n type: cmd.optional(cmd.string),\n description:\n 'If provided, only files within this directory are formatted. Relative paths are resolved against the current working directory (process.cwd()), not the git repository root.',\n }),\n },\n handler: (args) => {\n main({\n base: args.base,\n excludeUntracked: args.excludeUntracked ?? false,\n excludeModified: args.excludeModified ?? false,\n excludeStaged: args.excludeStaged ?? false,\n ignoreUnknown: args.ignoreUnknown ?? true,\n silent: args.silent ?? false,\n cwd: args.cwd,\n }).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n base: string;\n excludeUntracked: boolean;\n excludeModified: boolean;\n excludeStaged: boolean;\n ignoreUnknown: boolean;\n silent: boolean;\n cwd: string | undefined;\n }>,\n): Promise<void> => {\n const result = await formatDiffFrom(args.base, {\n includeUntracked: !args.excludeUntracked,\n includeModified: !args.excludeModified,\n includeStaged: !args.excludeStaged,\n ignoreUnknown: args.ignoreUnknown,\n silent: args.silent,\n cwd: args.cwd,\n });\n\n if (Result.isErr(result)) {\n process.exit(1);\n }\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"format-diff-from.mjs","sources":["../../src/cmd/format-diff-from.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, Result } from 'ts-data-forge';\nimport { formatDiffFrom } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'format-diff-from-cli',\n version: '10.1.8',\n args: {\n base: cmd.positional({\n type: cmd.string,\n displayName: 'base',\n description: 'Base branch name or commit hash to compare against',\n }),\n excludeUntracked: cmd.flag({\n long: 'exclude-untracked',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude untracked files in addition to diff files (default: false)',\n }),\n excludeModified: cmd.flag({\n long: 'exclude-modified',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude modified files in addition to diff files (default: false)',\n }),\n excludeStaged: cmd.flag({\n long: 'exclude-staged',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude staged files in addition to diff files (default: false)',\n }),\n ignoreUnknown: cmd.flag({\n long: 'ignore-unknown',\n type: cmd.optional(cmd.boolean),\n description: 'Ignore unknown files (default: true)',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n cwd: cmd.option({\n long: 'cwd',\n type: cmd.optional(cmd.string),\n description:\n 'If provided, only files within this directory are formatted. Relative paths are resolved against the current working directory (process.cwd()), not the git repository root.',\n }),\n },\n handler: (args) => {\n main({\n base: args.base,\n excludeUntracked: args.excludeUntracked ?? false,\n excludeModified: args.excludeModified ?? false,\n excludeStaged: args.excludeStaged ?? false,\n ignoreUnknown: args.ignoreUnknown ?? true,\n silent: args.silent ?? false,\n cwd: args.cwd,\n }).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n base: string;\n excludeUntracked: boolean;\n excludeModified: boolean;\n excludeStaged: boolean;\n ignoreUnknown: boolean;\n silent: boolean;\n cwd: string | undefined;\n }>,\n): Promise<void> => {\n const result = await formatDiffFrom(args.base, {\n includeUntracked: !args.excludeUntracked,\n includeModified: !args.excludeModified,\n includeStaged: !args.excludeStaged,\n ignoreUnknown: args.ignoreUnknown,\n silent: args.silent,\n cwd: args.cwd,\n });\n\n if (Result.isErr(result)) {\n process.exit(1);\n }\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-uncommitted.mjs","sources":["../../src/cmd/format-uncommitted.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, Result } from 'ts-data-forge';\nimport { formatUncommittedFiles } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'format-uncommitted-cli',\n version: '10.1.8',\n args: {\n excludeUntracked: cmd.flag({\n long: 'exclude-untracked',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude untracked files in addition to diff files (default: false)',\n }),\n excludeModified: cmd.flag({\n long: 'exclude-modified',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude modified files in addition to diff files (default: false)',\n }),\n excludeStaged: cmd.flag({\n long: 'exclude-staged',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude staged files in addition to diff files (default: false)',\n }),\n ignoreUnknown: cmd.flag({\n long: 'ignore-unknown',\n type: cmd.optional(cmd.boolean),\n description: 'Ignore unknown files (default: true)',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n cwd: cmd.option({\n long: 'cwd',\n type: cmd.optional(cmd.string),\n description:\n 'If provided, only files within this directory are formatted. Relative paths are resolved against the current working directory (process.cwd()), not the git repository root.',\n }),\n },\n handler: (args) => {\n main({\n excludeUntracked: args.excludeUntracked ?? false,\n excludeModified: args.excludeModified ?? false,\n excludeStaged: args.excludeStaged ?? false,\n ignoreUnknown: args.ignoreUnknown ?? true,\n silent: args.silent ?? false,\n cwd: args.cwd,\n }).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n excludeUntracked: boolean;\n excludeModified: boolean;\n excludeStaged: boolean;\n ignoreUnknown: boolean;\n silent: boolean;\n cwd: string | undefined;\n }>,\n): Promise<void> => {\n const result = await formatUncommittedFiles({\n untracked: !args.excludeUntracked,\n modified: !args.excludeModified,\n staged: !args.excludeStaged,\n ignoreUnknown: args.ignoreUnknown,\n silent: args.silent,\n cwd: args.cwd,\n });\n\n if (Result.isErr(result)) {\n process.exit(1);\n }\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"format-uncommitted.mjs","sources":["../../src/cmd/format-uncommitted.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, Result } from 'ts-data-forge';\nimport { formatUncommittedFiles } from '../functions/index.mjs';\n\nconst cmdDef = cmd.command({\n name: 'format-uncommitted-cli',\n version: '10.1.8',\n args: {\n excludeUntracked: cmd.flag({\n long: 'exclude-untracked',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude untracked files in addition to diff files (default: false)',\n }),\n excludeModified: cmd.flag({\n long: 'exclude-modified',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude modified files in addition to diff files (default: false)',\n }),\n excludeStaged: cmd.flag({\n long: 'exclude-staged',\n type: cmd.optional(cmd.boolean),\n description:\n 'Exclude staged files in addition to diff files (default: false)',\n }),\n ignoreUnknown: cmd.flag({\n long: 'ignore-unknown',\n type: cmd.optional(cmd.boolean),\n description: 'Ignore unknown files (default: true)',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n cwd: cmd.option({\n long: 'cwd',\n type: cmd.optional(cmd.string),\n description:\n 'If provided, only files within this directory are formatted. Relative paths are resolved against the current working directory (process.cwd()), not the git repository root.',\n }),\n },\n handler: (args) => {\n main({\n excludeUntracked: args.excludeUntracked ?? false,\n excludeModified: args.excludeModified ?? false,\n excludeStaged: args.excludeStaged ?? false,\n ignoreUnknown: args.ignoreUnknown ?? true,\n silent: args.silent ?? false,\n cwd: args.cwd,\n }).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async (\n args: Readonly<{\n excludeUntracked: boolean;\n excludeModified: boolean;\n excludeStaged: boolean;\n ignoreUnknown: boolean;\n silent: boolean;\n cwd: string | undefined;\n }>,\n): Promise<void> => {\n const result = await formatUncommittedFiles({\n untracked: !args.excludeUntracked,\n modified: !args.excludeModified,\n staged: !args.excludeStaged,\n ignoreUnknown: args.ignoreUnknown,\n silent: args.silent,\n cwd: args.cwd,\n });\n\n if (Result.isErr(result)) {\n process.exit(1);\n }\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import { genIndex } from '../functions/gen-index.mjs';
|
|
|
10
10
|
import 'node:fs';
|
|
11
11
|
import 'node:url';
|
|
12
12
|
import 'micromatch';
|
|
13
|
+
import 'typescript';
|
|
13
14
|
import '@sindresorhus/is';
|
|
14
15
|
|
|
15
16
|
const extensionType = cmd.extendType(cmd.string, {
|
|
@@ -91,6 +92,11 @@ const cmdDef = cmd.command({
|
|
|
91
92
|
long: "min-depth",
|
|
92
93
|
type: cmd.optional(cmd.number),
|
|
93
94
|
description: "Minimum depth to start generating index files (default: 0)"
|
|
95
|
+
}),
|
|
96
|
+
preserve: cmd.multioption({
|
|
97
|
+
long: "preserve",
|
|
98
|
+
type: cmd.optional(cmd.array(cmd.string)),
|
|
99
|
+
description: 'Glob patterns of index files to leave untouched, matched against the path relative to the target directory (e.g., "index.mts", "v*/index.mts")'
|
|
94
100
|
})
|
|
95
101
|
},
|
|
96
102
|
handler: (args) => {
|
|
@@ -108,7 +114,8 @@ const main = async ({
|
|
|
108
114
|
exclude,
|
|
109
115
|
formatCommand,
|
|
110
116
|
silent,
|
|
111
|
-
minDepth
|
|
117
|
+
minDepth,
|
|
118
|
+
preserve
|
|
112
119
|
}) => {
|
|
113
120
|
await genIndex({
|
|
114
121
|
targetDirectory: targetDirectory.includes(",") ? targetDirectory.split(",").map((dir) => dir.trim()) : targetDirectory,
|
|
@@ -118,7 +125,8 @@ const main = async ({
|
|
|
118
125
|
indexFileExtension,
|
|
119
126
|
formatCommand,
|
|
120
127
|
silent,
|
|
121
|
-
minDepth
|
|
128
|
+
minDepth,
|
|
129
|
+
preserve
|
|
122
130
|
});
|
|
123
131
|
};
|
|
124
132
|
await cmd.run(cmdDef, Arr.skip(process.argv, 2));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gen-index-ts.mjs","sources":["../../src/cmd/gen-index-ts.mts"],"sourcesContent":["#!/usr/bin/env node\n\n/* transformer-ignore convert-to-readonly */\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, expectType } from 'ts-data-forge';\n// eslint-disable-next-line import-x/no-internal-modules, import-x/extensions\nimport { type InputOf, type OutputOf } from 'cmd-ts/dist/esm/from.js';\nimport { type NonEmptyArray } from 'ts-type-forge';\nimport { genIndex } from '../functions/index.mjs';\n\ntype Ext = `.${string}`;\n\nconst extensionType = cmd.extendType(cmd.string, {\n from: (s) => {\n if (!s.startsWith('.')) {\n throw new Error(`ext should start with '.'`);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(s as Ext);\n },\n});\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst nonEmptyArray = <T extends cmd.Type<any, any>>(\n t: T,\n commandName: string,\n): cmd.Type<readonly InputOf<T>[], NonEmptyArray<OutputOf<T>>> =>\n cmd.extendType(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n cmd.array(t) as cmd.Type<readonly InputOf<T>[], OutputOf<T>[]>,\n {\n from: (arr) => {\n if (Arr.isEmpty(arr)) {\n throw new Error(\n `No value provided for --${commandName}. At least one value is required.`,\n );\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(arr as unknown as NonEmptyArray<OutputOf<T>>);\n },\n },\n );\n\nconst cmdDef = cmd.command({\n name: 'gen-index-ts-cli',\n version: '10.1.8',\n args: {\n // required args\n targetDirectory: cmd.positional({\n type: cmd.string,\n displayName: 'target-directory',\n description:\n 'Directory where the index file will be generated (Comma-separated list can be used)',\n }),\n\n targetExtensions: cmd.multioption({\n long: 'target-ext',\n type: nonEmptyArray(extensionType, 'target-ext'),\n description: 'File extensions to include in the index file',\n }),\n indexFileExtension: cmd.option({\n long: 'index-ext',\n type: extensionType,\n description: 'Extension of the index file to be generated',\n }),\n exportStatementExtension: cmd.option({\n long: 'export-ext',\n type: cmd.union([\n extensionType,\n cmd.extendType(cmd.string, {\n from: (s) => {\n if (s !== 'none') {\n throw new Error(\n `export-ext should be 'none' or a valid extension`,\n );\n }\n\n return Promise.resolve('none' as const);\n },\n }),\n ]),\n description: 'Extension of the export statements in the index file',\n }),\n\n // optional args\n exclude: cmd.multioption({\n long: 'exclude',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Glob patterns of files to exclude from the index file (e.g., \"*.d.mts\", \"*.test.mts\")',\n }),\n formatCommand: cmd.option({\n long: 'fmt',\n type: cmd.optional(cmd.string),\n description:\n 'Command to format after generating the index file (e.g., \"npm run fmt\")',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n minDepth: cmd.option({\n long: 'min-depth',\n type: cmd.optional(cmd.number),\n description: 'Minimum depth to start generating index files (default: 0)',\n }),\n },\n handler: (args) => {\n expectType<typeof args.targetDirectory, string>('=');\n\n expectType<typeof args.targetExtensions, NonEmptyArray<Ext>>('=');\n\n expectType<typeof args.exportStatementExtension, Ext | 'none'>('=');\n\n expectType<typeof args.indexFileExtension, Ext>('=');\n\n expectType<typeof args.exclude, string[] | undefined>('=');\n\n expectType<typeof args.formatCommand, string | undefined>('=');\n\n expectType<typeof args.silent, boolean | undefined>('=');\n\n expectType<typeof args.minDepth, number | undefined>('=');\n\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async ({\n targetDirectory,\n targetExtensions,\n exportStatementExtension,\n indexFileExtension,\n exclude,\n formatCommand,\n silent,\n minDepth,\n}: Readonly<{\n targetDirectory: string;\n targetExtensions: readonly Ext[];\n exportStatementExtension: Ext | 'none';\n indexFileExtension: Ext;\n exclude?: readonly string[] | undefined;\n formatCommand?: string | undefined;\n silent?: boolean | undefined;\n minDepth?: number | undefined;\n}>): Promise<void> => {\n await genIndex({\n targetDirectory: targetDirectory.includes(',')\n ? targetDirectory.split(',').map((dir) => dir.trim())\n : targetDirectory,\n exportStatementExtension,\n targetExtensions,\n exclude,\n indexFileExtension,\n formatCommand,\n silent,\n minDepth,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gen-index-ts.mjs","sources":["../../src/cmd/gen-index-ts.mts"],"sourcesContent":["#!/usr/bin/env node\n\n/* transformer-ignore convert-to-readonly */\n\nimport * as cmd from 'cmd-ts';\nimport { Arr, expectType } from 'ts-data-forge';\n// eslint-disable-next-line import-x/no-internal-modules, import-x/extensions\nimport { type InputOf, type OutputOf } from 'cmd-ts/dist/esm/from.js';\nimport { type NonEmptyArray } from 'ts-type-forge';\nimport { genIndex } from '../functions/index.mjs';\n\ntype Ext = `.${string}`;\n\nconst extensionType = cmd.extendType(cmd.string, {\n from: (s) => {\n if (!s.startsWith('.')) {\n throw new Error(`ext should start with '.'`);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(s as Ext);\n },\n});\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst nonEmptyArray = <T extends cmd.Type<any, any>>(\n t: T,\n commandName: string,\n): cmd.Type<readonly InputOf<T>[], NonEmptyArray<OutputOf<T>>> =>\n cmd.extendType(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n cmd.array(t) as cmd.Type<readonly InputOf<T>[], OutputOf<T>[]>,\n {\n from: (arr) => {\n if (Arr.isEmpty(arr)) {\n throw new Error(\n `No value provided for --${commandName}. At least one value is required.`,\n );\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Promise.resolve(arr as unknown as NonEmptyArray<OutputOf<T>>);\n },\n },\n );\n\nconst cmdDef = cmd.command({\n name: 'gen-index-ts-cli',\n version: '10.1.8',\n args: {\n // required args\n targetDirectory: cmd.positional({\n type: cmd.string,\n displayName: 'target-directory',\n description:\n 'Directory where the index file will be generated (Comma-separated list can be used)',\n }),\n\n targetExtensions: cmd.multioption({\n long: 'target-ext',\n type: nonEmptyArray(extensionType, 'target-ext'),\n description: 'File extensions to include in the index file',\n }),\n indexFileExtension: cmd.option({\n long: 'index-ext',\n type: extensionType,\n description: 'Extension of the index file to be generated',\n }),\n exportStatementExtension: cmd.option({\n long: 'export-ext',\n type: cmd.union([\n extensionType,\n cmd.extendType(cmd.string, {\n from: (s) => {\n if (s !== 'none') {\n throw new Error(\n `export-ext should be 'none' or a valid extension`,\n );\n }\n\n return Promise.resolve('none' as const);\n },\n }),\n ]),\n description: 'Extension of the export statements in the index file',\n }),\n\n // optional args\n exclude: cmd.multioption({\n long: 'exclude',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Glob patterns of files to exclude from the index file (e.g., \"*.d.mts\", \"*.test.mts\")',\n }),\n formatCommand: cmd.option({\n long: 'fmt',\n type: cmd.optional(cmd.string),\n description:\n 'Command to format after generating the index file (e.g., \"npm run fmt\")',\n }),\n silent: cmd.flag({\n long: 'silent',\n type: cmd.optional(cmd.boolean),\n description: 'If true, suppresses output messages (default: false)',\n }),\n minDepth: cmd.option({\n long: 'min-depth',\n type: cmd.optional(cmd.number),\n description: 'Minimum depth to start generating index files (default: 0)',\n }),\n preserve: cmd.multioption({\n long: 'preserve',\n type: cmd.optional(cmd.array(cmd.string)),\n description:\n 'Glob patterns of index files to leave untouched, matched against the path relative to the target directory (e.g., \"index.mts\", \"v*/index.mts\")',\n }),\n },\n handler: (args) => {\n expectType<typeof args.targetDirectory, string>('=');\n\n expectType<typeof args.targetExtensions, NonEmptyArray<Ext>>('=');\n\n expectType<typeof args.exportStatementExtension, Ext | 'none'>('=');\n\n expectType<typeof args.indexFileExtension, Ext>('=');\n\n expectType<typeof args.exclude, string[] | undefined>('=');\n\n expectType<typeof args.formatCommand, string | undefined>('=');\n\n expectType<typeof args.silent, boolean | undefined>('=');\n\n expectType<typeof args.minDepth, number | undefined>('=');\n\n expectType<typeof args.preserve, string[] | undefined>('=');\n\n main(args).catch((error: unknown) => {\n console.error('An error occurred:', error);\n\n process.exit(1);\n });\n },\n});\n\nconst main = async ({\n targetDirectory,\n targetExtensions,\n exportStatementExtension,\n indexFileExtension,\n exclude,\n formatCommand,\n silent,\n minDepth,\n preserve,\n}: Readonly<{\n targetDirectory: string;\n targetExtensions: readonly Ext[];\n exportStatementExtension: Ext | 'none';\n indexFileExtension: Ext;\n exclude?: readonly string[] | undefined;\n formatCommand?: string | undefined;\n silent?: boolean | undefined;\n minDepth?: number | undefined;\n preserve?: readonly string[] | undefined;\n}>): Promise<void> => {\n await genIndex({\n targetDirectory: targetDirectory.includes(',')\n ? targetDirectory.split(',').map((dir) => dir.trim())\n : targetDirectory,\n exportStatementExtension,\n targetExtensions,\n exclude,\n indexFileExtension,\n formatCommand,\n silent,\n minDepth,\n preserve,\n });\n};\n\nawait cmd.run(cmdDef, Arr.skip(process.argv, 2));\n"],"names":[],"mappings":"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"}
|
package/dist/entry-point.mjs
CHANGED
|
@@ -11,6 +11,7 @@ export { glob } from './functions/glob.mjs';
|
|
|
11
11
|
export { isDirectlyExecuted } from './functions/is-directly-executed.mjs';
|
|
12
12
|
export { makeEmptyDir } from './functions/make-empty-dir.mjs';
|
|
13
13
|
export { checkShouldRun, checkShouldRunTypeChecks } from './functions/should-run.mjs';
|
|
14
|
+
export { stripDevOnlyCode, stripDevOnlyCodeInDir } from './functions/strip-dev-only-code.mjs';
|
|
14
15
|
export { executeParallel, executeStages } from './functions/workspace-utils/execute-parallel.mjs';
|
|
15
16
|
export { getWorkspacePackages } from './functions/workspace-utils/get-workspace-packages.mjs';
|
|
16
17
|
export { runCmdInParallelAcrossWorkspaces } from './functions/workspace-utils/run-cmd-in-parallel.mjs';
|
package/dist/entry-point.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-ext.mjs","sources":["../../src/functions/assert-ext.mts"],"sourcesContent":["import * as path from 'node:path';\nimport {\n Arr,\n type IMap,\n isString,\n Result,\n unknownToString,\n} from 'ts-data-forge';\nimport { type DeepReadonly } from 'ts-type-forge';\nimport { assertPathExists } from './assert-path-exists.mjs';\nimport { createResultAssert } from './create-result-assert.mjs';\nimport { glob } from './glob.mjs';\n\n/** Configuration for directory extension checking. */\nexport type CheckExtConfig = DeepReadonly<{\n /** Array of directory paths and their expected extensions */\n directories: {\n /** Directory path to check */\n path: string;\n\n /**\n * Expected file extension(s) (including the dot). Can be a single extension\n * or an array of valid extensions\n */\n extension: `.${string}` | `.${string}`[];\n\n /**\n * Optional glob patterns to ignore (defaults to ['tsconfig.json'])\n */\n ignorePatterns?: string[];\n }[];\n}>;\n\nexport type CheckExtError = Readonly<{\n message: string;\n files: readonly string[];\n}>;\n\n/**\n * Validates that all files in specified directories have the correct\n * extensions.\n *\n * @param config - Configuration specifying directories and expected extensions.\n * @returns Result.ok when all files pass, otherwise Result.err with details.\n */\nexport const checkExt = async (\n config: CheckExtConfig,\n): Promise<Result<undefined, CheckExtError>> => {\n // Check all directories in parallel\n const results = await Promise.all(\n config.directories.map(async ({ path: dir, extension, ignorePatterns }) => {\n try {\n return await getFilesWithIncorrectExtension(\n dir,\n isString(extension) ? [extension] : extension,\n ignorePatterns,\n );\n } catch (error) {\n console.error(\n `Failed to check directory ${dir}: ${unknownToString(error)}`,\n );\n\n return [];\n }\n }),\n );\n\n // Collect all incorrect files\n const allIncorrectFiles: readonly string[] = results.flat();\n\n if (Arr.isEmpty(allIncorrectFiles)) {\n return Result.ok(undefined);\n }\n\n const message = [\n 'Files with incorrect extensions found:',\n ...allIncorrectFiles.map((file) => ` - ${file}`),\n '',\n describeExpectedExtensions(config),\n ].join('\\n');\n\n return Result.err({\n message,\n files: allIncorrectFiles,\n });\n};\n\n/**\n * Validates that all files in specified directories have the correct\n * extensions. Exits with code 1 if any files have incorrect extensions.\n *\n * @param config - Configuration specifying directories and expected extensions.\n */\nexport const assertExt = createResultAssert<\n CheckExtConfig,\n undefined,\n CheckExtError\n>({\n run: checkExt,\n onError: (error) => {\n console.info(error.message);\n },\n onSuccess: () => {\n console.info('✓ All files have correct extensions');\n },\n});\n\n/**\n * Checks if all files in a directory have the expected extension.\n *\n * @param dir - The directory to check.\n * @param expectedExtensions - The expected file extensions.\n * @param ignorePatterns - Optional glob patterns to ignore.\n * @returns Array of files with incorrect extensions.\n */\nconst getFilesWithIncorrectExtension = async (\n dir: string,\n expectedExtensions: readonly string[],\n ignorePatterns?: readonly string[],\n): Promise<readonly string[]> => {\n await assertPathExists(dir, 'Directory');\n\n const defaultIgnorePatterns = ['tsconfig.json'] as const;\n\n const finalIgnorePatterns = ignorePatterns ?? defaultIgnorePatterns;\n\n // Convert relative patterns to absolute paths for the glob ignore option\n const absoluteIgnorePatterns = finalIgnorePatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : `${dir}/${pattern}`,\n );\n\n const filesResult = await glob(`${dir}/**/*`, {\n ignore: absoluteIgnorePatterns,\n });\n\n if (Result.isErr(filesResult)) {\n throw new Error(\n `Failed to glob files in ${dir}: ${unknownToString(filesResult.value)}`,\n );\n }\n\n const files = filesResult.value;\n\n return files.filter((file) =>\n expectedExtensions.every((ext) => !file.endsWith(ext)),\n );\n};\n\nconst describeExpectedExtensions = (config: CheckExtConfig): string => {\n // Group directories by extension for a cleaner message\n const extensionGroups: IMap<\n string,\n readonly Readonly<{\n relativePath: string;\n extKey: string;\n }>[]\n > = Arr.groupBy(\n config.directories.map(({ path: dirPath, extension }) => {\n const relativePath = path.relative(process.cwd(), dirPath);\n\n const extKey = isString(extension) ? extension : extension.join(' or ');\n\n return {\n relativePath,\n extKey,\n };\n }),\n ({ extKey }) => extKey,\n );\n\n // Generate message parts for each extension\n const messageParts = Array.from(extensionGroups.entries(), ([ext, dirs]) => {\n const dirList = Arr.isFixedLengthArray(1, dirs)\n ? dirs[0].relativePath\n : dirs.map((d) => d.relativePath).join(', ');\n\n return `${dirList} should have ${ext} extension`;\n });\n\n return `All files in ${messageParts.join(' and ')}.`;\n};\n"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"assert-ext.mjs","sources":["../../src/functions/assert-ext.mts"],"sourcesContent":["import * as path from 'node:path';\nimport {\n Arr,\n type IMap,\n isString,\n Result,\n unknownToString,\n} from 'ts-data-forge';\nimport { type DeepReadonly } from 'ts-type-forge';\nimport { assertPathExists } from './assert-path-exists.mjs';\nimport { createResultAssert } from './create-result-assert.mjs';\nimport { glob } from './glob.mjs';\n\n/** Configuration for directory extension checking. */\nexport type CheckExtConfig = DeepReadonly<{\n /** Array of directory paths and their expected extensions */\n directories: {\n /** Directory path to check */\n path: string;\n\n /**\n * Expected file extension(s) (including the dot). Can be a single extension\n * or an array of valid extensions\n */\n extension: `.${string}` | `.${string}`[];\n\n /**\n * Optional glob patterns to ignore (defaults to ['tsconfig.json'])\n */\n ignorePatterns?: string[];\n }[];\n}>;\n\nexport type CheckExtError = Readonly<{\n message: string;\n files: readonly string[];\n}>;\n\n/**\n * Validates that all files in specified directories have the correct\n * extensions.\n *\n * @param config - Configuration specifying directories and expected extensions.\n * @returns Result.ok when all files pass, otherwise Result.err with details.\n */\nexport const checkExt = async (\n config: CheckExtConfig,\n): Promise<Result<undefined, CheckExtError>> => {\n // Check all directories in parallel\n const results = await Promise.all(\n config.directories.map(async ({ path: dir, extension, ignorePatterns }) => {\n try {\n return await getFilesWithIncorrectExtension(\n dir,\n isString(extension) ? [extension] : extension,\n ignorePatterns,\n );\n } catch (error) {\n console.error(\n `Failed to check directory ${dir}: ${unknownToString(error)}`,\n );\n\n return [];\n }\n }),\n );\n\n // Collect all incorrect files\n const allIncorrectFiles: readonly string[] = results.flat();\n\n if (Arr.isEmpty(allIncorrectFiles)) {\n return Result.ok(undefined);\n }\n\n const message = [\n 'Files with incorrect extensions found:',\n ...allIncorrectFiles.map((file) => ` - ${file}`),\n '',\n describeExpectedExtensions(config),\n ].join('\\n');\n\n return Result.err({\n message,\n files: allIncorrectFiles,\n });\n};\n\n/**\n * Validates that all files in specified directories have the correct\n * extensions. Exits with code 1 if any files have incorrect extensions.\n *\n * @param config - Configuration specifying directories and expected extensions.\n */\nexport const assertExt = createResultAssert<\n CheckExtConfig,\n undefined,\n CheckExtError\n>({\n run: checkExt,\n onError: (error) => {\n console.info(error.message);\n },\n onSuccess: () => {\n console.info('✓ All files have correct extensions');\n },\n});\n\n/**\n * Checks if all files in a directory have the expected extension.\n *\n * @param dir - The directory to check.\n * @param expectedExtensions - The expected file extensions.\n * @param ignorePatterns - Optional glob patterns to ignore.\n * @returns Array of files with incorrect extensions.\n */\nconst getFilesWithIncorrectExtension = async (\n dir: string,\n expectedExtensions: readonly string[],\n ignorePatterns?: readonly string[],\n): Promise<readonly string[]> => {\n await assertPathExists(dir, 'Directory');\n\n const defaultIgnorePatterns = ['tsconfig.json'] as const;\n\n const finalIgnorePatterns = ignorePatterns ?? defaultIgnorePatterns;\n\n // Convert relative patterns to absolute paths for the glob ignore option\n const absoluteIgnorePatterns = finalIgnorePatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : `${dir}/${pattern}`,\n );\n\n const filesResult = await glob(`${dir}/**/*`, {\n ignore: absoluteIgnorePatterns,\n });\n\n if (Result.isErr(filesResult)) {\n throw new Error(\n `Failed to glob files in ${dir}: ${unknownToString(filesResult.value)}`,\n );\n }\n\n const files = filesResult.value;\n\n return files.filter((file) =>\n expectedExtensions.every((ext) => !file.endsWith(ext)),\n );\n};\n\nconst describeExpectedExtensions = (config: CheckExtConfig): string => {\n // Group directories by extension for a cleaner message\n const extensionGroups: IMap<\n string,\n readonly Readonly<{\n relativePath: string;\n extKey: string;\n }>[]\n > = Arr.groupBy(\n config.directories.map(({ path: dirPath, extension }) => {\n const relativePath = path.relative(process.cwd(), dirPath);\n\n const extKey = isString(extension) ? extension : extension.join(' or ');\n\n return {\n relativePath,\n extKey,\n };\n }),\n ({ extKey }) => extKey,\n );\n\n // Generate message parts for each extension\n const messageParts = Array.from(extensionGroups.entries(), ([ext, dirs]) => {\n const dirList = Arr.isFixedLengthArray(1, dirs)\n ? dirs[0].relativePath\n : dirs.map((d) => d.relativePath).join(', ');\n\n return `${dirList} should have ${ext} extension`;\n });\n\n return `All files in ${messageParts.join(' and ')}.`;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-path-exists.mjs","sources":["../../src/functions/assert-path-exists.mts"],"sourcesContent":["import * as fs from 'node:fs/promises';\n\n/**\n * Checks if a file or directory exists.\n *\n * @param filePath - The path to check.\n * @returns True if the path exists.\n */\nexport const pathExists = async (filePath: string): Promise<boolean> => {\n try {\n await fs.access(filePath);\n\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Validates that a path exists and exits with code 1 if it doesn't.\n *\n * @param filePath - The path to validate.\n * @param description - Description for error message (defaults to 'Path').\n */\nexport const assertPathExists = async (\n filePath: string,\n description = 'Path',\n): Promise<void> => {\n if (await pathExists(filePath)) {\n return;\n }\n\n console.info(`${description} does not exist: ${filePath}`);\n\n process.exit(1);\n};\n"],"names":[],"mappings":";;AAQO,MAAM,UAAA,GAAa,OAAO,QAAA,KAAuC;AACtE,EAAA,IAAI;AACF,IAAA,MAAM,EAAA,CAAG,OAAO,QAAQ,CAAA;AAExB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAQO,MAAM,gBAAA,GAAmB,OAC9B,QAAA,EACA,WAAA,GAAc,MAAA,KACI;AAClB,EAAA,IAAI,MAAM,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC9B,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,EAAG,WAAW,CAAA,iBAAA,EAAoB,QAAQ,CAAA,CAAE,CAAA;AAEzD,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB
|
|
1
|
+
{"version":3,"file":"assert-path-exists.mjs","sources":["../../src/functions/assert-path-exists.mts"],"sourcesContent":["import * as fs from 'node:fs/promises';\n\n/**\n * Checks if a file or directory exists.\n *\n * @param filePath - The path to check.\n * @returns True if the path exists.\n */\nexport const pathExists = async (filePath: string): Promise<boolean> => {\n try {\n await fs.access(filePath);\n\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Validates that a path exists and exits with code 1 if it doesn't.\n *\n * @param filePath - The path to validate.\n * @param description - Description for error message (defaults to 'Path').\n */\nexport const assertPathExists = async (\n filePath: string,\n description = 'Path',\n): Promise<void> => {\n if (await pathExists(filePath)) {\n return;\n }\n\n console.info(`${description} does not exist: ${filePath}`);\n\n process.exit(1);\n};\n"],"names":[],"mappings":";;AAQO,MAAM,UAAA,GAAa,OAAO,QAAA,KAAuC;AACtE,EAAA,IAAI;AACF,IAAA,MAAM,EAAA,CAAG,OAAO,QAAQ,CAAA;AAExB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAQO,MAAM,gBAAA,GAAmB,OAC9B,QAAA,EACA,WAAA,GAAc,MAAA,KACI;AAClB,EAAA,IAAI,MAAM,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC9B,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,EAAG,WAAW,CAAA,iBAAA,EAAoB,QAAQ,CAAA,CAAE,CAAA;AAEzD,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-repo-is-clean.mjs","sources":["../../src/functions/assert-repo-is-clean.mts"],"sourcesContent":["import { Result } from 'ts-data-forge';\nimport { $ } from './exec-async.mjs';\n\n/**\n * Checks if the repository has uncommitted changes.\n *\n * @returns True if the repo is dirty, false otherwise.\n * @throws Error if git command fails.\n */\nexport const repoIsDirty = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<boolean> => {\n const status = await getGitStatus({ silent: options?.silent ?? false });\n\n if (Result.isErr(status)) {\n throw new Error(`Failed to get git status: ${status.value}`);\n }\n\n return status.value.isDirty;\n};\n\n/**\n * Checks if the repository is clean and exits with code 1 if it is dirty. Shows\n * git status and diff output before exiting.\n */\nexport const assertRepoIsClean = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<void> => {\n const silent = options?.silent ?? false;\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n const gitStatusResult = await getGitStatus({ silent });\n\n if (Result.isErr(gitStatusResult)) {\n conditionalEcho(gitStatusResult.value);\n\n return;\n }\n\n const gitStatus = gitStatusResult.value;\n\n if (!gitStatus.isDirty) {\n conditionalEcho('Repo is clean\\n');\n\n return;\n }\n\n conditionalEcho('Repo is dirty\\n');\n\n conditionalEcho('Changed files:\\n');\n\n conditionalEcho(gitStatus.stdout);\n\n // Show files not tracked by git and unstaged changes\n const addResult = await $('git add -N .', { silent });\n\n if (Result.isErr(addResult)) {\n conditionalEcho('Warning: Failed to add untracked files for diff\\n');\n }\n\n const diffResult = await $('git diff', { silent });\n\n if (Result.isErr(diffResult)) {\n conditionalEcho('Warning: Failed to show diff\\n');\n }\n\n process.exit(1);\n};\n\n/**\n * Gets the git status of the repository.\n *\n * @returns An object containing status information.\n */\nconst getGitStatus = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<\n Result<\n Readonly<{\n isDirty: boolean;\n stdout: string;\n }>,\n string\n >\n> => {\n const res = await $('git status --porcelain', {\n silent: options?.silent ?? false,\n });\n\n if (Result.isErr(res)) {\n return Result.err(`Failed to get git status: ${res.value.message}`);\n }\n\n const { stdout } = res.value;\n\n return Result.ok({\n isDirty: stdout.trim() !== '',\n stdout,\n });\n};\n"],"names":[],"mappings":";;;AASO,MAAM,WAAA,GAAc,OACzB,OAAA,KACqB;AACrB,EAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,EAAE,QAAQ,OAAA,EAAS,MAAA,IAAU,OAAO,CAAA;AAEtE,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAAA,EAC7D;AAEA,EAAA,OAAO,OAAO,KAAA,CAAM,OAAA;AACtB;AAMO,MAAM,iBAAA,GAAoB,OAC/B,OAAA,KACkB;AAClB,EAAA,MAAM,MAAA,GAAS,SAAS,MAAA,IAAU,KAAA;AAElC,EAAA,MAAM,eAAA,GAAkB,SAAS,MAAM;AAAA,EAAC,IAAI,OAAA,CAAQ,IAAA;AAEpD,EAAA,MAAM,eAAA,GAAkB,MAAM,YAAA,CAAa,EAAE,QAAQ,CAAA;AAErD,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,eAAe,CAAA,EAAG;AACjC,IAAA,eAAA,CAAgB,gBAAgB,KAAK,CAAA;AAErC,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,YAAY,eAAA,CAAgB,KAAA;AAElC,EAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,IAAA,eAAA,CAAgB,iBAAiB,CAAA;AAEjC,IAAA;AAAA,EACF;AAEA,EAAA,eAAA,CAAgB,iBAAiB,CAAA;AAEjC,EAAA,eAAA,CAAgB,kBAAkB,CAAA;AAElC,EAAA,eAAA,CAAgB,UAAU,MAAM,CAAA;AAGhC,EAAA,MAAM,YAAY,MAAM,CAAA,CAAE,cAAA,EAAgB,EAAE,QAAQ,CAAA;AAEpD,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AAC3B,IAAA,eAAA,CAAgB,mDAAmD,CAAA;AAAA,EACrE;AAEA,EAAA,MAAM,aAAa,MAAM,CAAA,CAAE,UAAA,EAAY,EAAE,QAAQ,CAAA;AAEjD,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,EAAG;AAC5B,IAAA,eAAA,CAAgB,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAOA,MAAM,YAAA,GAAe,OACnB,OAAA,KASG;AACH,EAAA,MAAM,GAAA,GAAM,MAAM,CAAA,CAAE,wBAAA,EAA0B;AAAA,IAC5C,MAAA,EAAQ,SAAS,MAAA,IAAU;AAAA,GAC5B,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACrB,IAAA,OAAO,OAAO,GAAA,CAAI,CAAA,0BAAA,EAA6B,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,EACpE;AAEA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,GAAA,CAAI,KAAA;AAEvB,EAAA,OAAO,OAAO,EAAA,CAAG;AAAA,IACf,OAAA,EAAS,MAAA,CAAO,IAAA,EAAK,KAAM,EAAA;AAAA,IAC3B;AAAA,GACD,CAAA;AACH,CAAA
|
|
1
|
+
{"version":3,"file":"assert-repo-is-clean.mjs","sources":["../../src/functions/assert-repo-is-clean.mts"],"sourcesContent":["import { Result } from 'ts-data-forge';\nimport { $ } from './exec-async.mjs';\n\n/**\n * Checks if the repository has uncommitted changes.\n *\n * @returns True if the repo is dirty, false otherwise.\n * @throws Error if git command fails.\n */\nexport const repoIsDirty = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<boolean> => {\n const status = await getGitStatus({ silent: options?.silent ?? false });\n\n if (Result.isErr(status)) {\n throw new Error(`Failed to get git status: ${status.value}`);\n }\n\n return status.value.isDirty;\n};\n\n/**\n * Checks if the repository is clean and exits with code 1 if it is dirty. Shows\n * git status and diff output before exiting.\n */\nexport const assertRepoIsClean = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<void> => {\n const silent = options?.silent ?? false;\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n const gitStatusResult = await getGitStatus({ silent });\n\n if (Result.isErr(gitStatusResult)) {\n conditionalEcho(gitStatusResult.value);\n\n return;\n }\n\n const gitStatus = gitStatusResult.value;\n\n if (!gitStatus.isDirty) {\n conditionalEcho('Repo is clean\\n');\n\n return;\n }\n\n conditionalEcho('Repo is dirty\\n');\n\n conditionalEcho('Changed files:\\n');\n\n conditionalEcho(gitStatus.stdout);\n\n // Show files not tracked by git and unstaged changes\n const addResult = await $('git add -N .', { silent });\n\n if (Result.isErr(addResult)) {\n conditionalEcho('Warning: Failed to add untracked files for diff\\n');\n }\n\n const diffResult = await $('git diff', { silent });\n\n if (Result.isErr(diffResult)) {\n conditionalEcho('Warning: Failed to show diff\\n');\n }\n\n process.exit(1);\n};\n\n/**\n * Gets the git status of the repository.\n *\n * @returns An object containing status information.\n */\nconst getGitStatus = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<\n Result<\n Readonly<{\n isDirty: boolean;\n stdout: string;\n }>,\n string\n >\n> => {\n const res = await $('git status --porcelain', {\n silent: options?.silent ?? false,\n });\n\n if (Result.isErr(res)) {\n return Result.err(`Failed to get git status: ${res.value.message}`);\n }\n\n const { stdout } = res.value;\n\n return Result.ok({\n isDirty: stdout.trim() !== '',\n stdout,\n });\n};\n"],"names":[],"mappings":";;;AASO,MAAM,WAAA,GAAc,OACzB,OAAA,KACqB;AACrB,EAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,EAAE,QAAQ,OAAA,EAAS,MAAA,IAAU,OAAO,CAAA;AAEtE,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAAA,EAC7D;AAEA,EAAA,OAAO,OAAO,KAAA,CAAM,OAAA;AACtB;AAMO,MAAM,iBAAA,GAAoB,OAC/B,OAAA,KACkB;AAClB,EAAA,MAAM,MAAA,GAAS,SAAS,MAAA,IAAU,KAAA;AAElC,EAAA,MAAM,eAAA,GAAkB,SAAS,MAAM;AAAA,EAAC,IAAI,OAAA,CAAQ,IAAA;AAEpD,EAAA,MAAM,eAAA,GAAkB,MAAM,YAAA,CAAa,EAAE,QAAQ,CAAA;AAErD,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,eAAe,CAAA,EAAG;AACjC,IAAA,eAAA,CAAgB,gBAAgB,KAAK,CAAA;AAErC,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,YAAY,eAAA,CAAgB,KAAA;AAElC,EAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,IAAA,eAAA,CAAgB,iBAAiB,CAAA;AAEjC,IAAA;AAAA,EACF;AAEA,EAAA,eAAA,CAAgB,iBAAiB,CAAA;AAEjC,EAAA,eAAA,CAAgB,kBAAkB,CAAA;AAElC,EAAA,eAAA,CAAgB,UAAU,MAAM,CAAA;AAGhC,EAAA,MAAM,YAAY,MAAM,CAAA,CAAE,cAAA,EAAgB,EAAE,QAAQ,CAAA;AAEpD,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AAC3B,IAAA,eAAA,CAAgB,mDAAmD,CAAA;AAAA,EACrE;AAEA,EAAA,MAAM,aAAa,MAAM,CAAA,CAAE,UAAA,EAAY,EAAE,QAAQ,CAAA;AAEjD,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,EAAG;AAC5B,IAAA,eAAA,CAAgB,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAOA,MAAM,YAAA,GAAe,OACnB,OAAA,KASG;AACH,EAAA,MAAM,GAAA,GAAM,MAAM,CAAA,CAAE,wBAAA,EAA0B;AAAA,IAC5C,MAAA,EAAQ,SAAS,MAAA,IAAU;AAAA,GAC5B,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACrB,IAAA,OAAO,OAAO,GAAA,CAAI,CAAA,0BAAA,EAA6B,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,EACpE;AAEA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,GAAA,CAAI,KAAA;AAEvB,EAAA,OAAO,OAAO,EAAA,CAAG;AAAA,IACf,OAAA,EAAS,MAAA,CAAO,IAAA,EAAK,KAAM,EAAA;AAAA,IAC3B;AAAA,GACD,CAAA;AACH,CAAA;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-result-assert.mjs","sources":["../../src/functions/create-result-assert.mts"],"sourcesContent":["import { hasKey, isRecord, isString, Result } from 'ts-data-forge';\n\ntype ResultProducer<TConfig, TOk, TErr> = (\n config: TConfig,\n) => Promise<Result<TOk, TErr>>;\n\nexport type CreateResultAssertOptions<Config, Ok, Err> = Readonly<{\n run: ResultProducer<Config, Ok, Err>;\n onSuccess?: (value: Ok, config: Config) => void | Promise<void>;\n onError?: (error: Err, config: Config) => void | Promise<void>;\n exitCode?: number;\n}>;\n\n/**\n * Converts a function that returns a Result into an assert-style variant that\n * exits the process when the Result is Err. This is useful for building CLI\n * commands that should stop execution on failure but remain composable when a\n * Result is preferred.\n */\nexport const createResultAssert = <Config, Ok, Err>({\n run,\n onSuccess,\n onError,\n exitCode = 1,\n}: CreateResultAssertOptions<Config, Ok, Err>): ((\n config: Config,\n) => Promise<Ok>) => {\n const defaultOnError = (error: Err): void => {\n if (\n isRecord(error) &&\n hasKey(error, 'message') &&\n isString(error.message)\n ) {\n console.info(error.message);\n } else {\n console.error(error);\n }\n };\n\n return async (config: Config): Promise<Ok> => {\n const result = await run(config);\n\n if (Result.isErr(result)) {\n if (onError !== undefined) {\n await onError(result.value, config);\n } else {\n defaultOnError(result.value);\n }\n\n process.exit(exitCode);\n }\n\n if (onSuccess !== undefined) {\n await onSuccess(result.value, config);\n }\n\n return result.value;\n };\n};\n"],"names":[],"mappings":";;AAmBO,MAAM,qBAAqB,CAAkB;AAAA,EAClD,GAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,KAEqB;AACnB,EAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,KAAqB;AAC3C,IAAA,IACE,QAAA,CAAS,KAAK,CAAA,IACd,MAAA,CAAO,KAAA,EAAO,SAAS,CAAA,IACvB,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA,EACtB;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC5B,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,IACrB;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,OAAO,MAAA,KAAgC;AAC5C,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,MAAM,CAAA;AAE/B,IAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,MAAA,IAAI,YAAY,MAAA,EAAW;AACzB,QAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAAA,MACpC,CAAA,MAAO;AACL,QAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAAA,MAC7B;AAEA,MAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,IACvB;AAEA,IAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,MAAA,MAAM,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAAA,IACtC;AAEA,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB,CAAA;AACF
|
|
1
|
+
{"version":3,"file":"create-result-assert.mjs","sources":["../../src/functions/create-result-assert.mts"],"sourcesContent":["import { hasKey, isRecord, isString, Result } from 'ts-data-forge';\n\ntype ResultProducer<TConfig, TOk, TErr> = (\n config: TConfig,\n) => Promise<Result<TOk, TErr>>;\n\nexport type CreateResultAssertOptions<Config, Ok, Err> = Readonly<{\n run: ResultProducer<Config, Ok, Err>;\n onSuccess?: (value: Ok, config: Config) => void | Promise<void>;\n onError?: (error: Err, config: Config) => void | Promise<void>;\n exitCode?: number;\n}>;\n\n/**\n * Converts a function that returns a Result into an assert-style variant that\n * exits the process when the Result is Err. This is useful for building CLI\n * commands that should stop execution on failure but remain composable when a\n * Result is preferred.\n */\nexport const createResultAssert = <Config, Ok, Err>({\n run,\n onSuccess,\n onError,\n exitCode = 1,\n}: CreateResultAssertOptions<Config, Ok, Err>): ((\n config: Config,\n) => Promise<Ok>) => {\n const defaultOnError = (error: Err): void => {\n if (\n isRecord(error) &&\n hasKey(error, 'message') &&\n isString(error.message)\n ) {\n console.info(error.message);\n } else {\n console.error(error);\n }\n };\n\n return async (config: Config): Promise<Ok> => {\n const result = await run(config);\n\n if (Result.isErr(result)) {\n if (onError !== undefined) {\n await onError(result.value, config);\n } else {\n defaultOnError(result.value);\n }\n\n process.exit(exitCode);\n }\n\n if (onSuccess !== undefined) {\n await onSuccess(result.value, config);\n }\n\n return result.value;\n };\n};\n"],"names":[],"mappings":";;AAmBO,MAAM,qBAAqB,CAAkB;AAAA,EAClD,GAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,KAEqB;AACnB,EAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,KAAqB;AAC3C,IAAA,IACE,QAAA,CAAS,KAAK,CAAA,IACd,MAAA,CAAO,KAAA,EAAO,SAAS,CAAA,IACvB,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA,EACtB;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC5B,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,IACrB;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,OAAO,MAAA,KAAgC;AAC5C,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,MAAM,CAAA;AAE/B,IAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,MAAA,IAAI,YAAY,MAAA,EAAW;AACzB,QAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAAA,MACpC,CAAA,MAAO;AACL,QAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAAA,MAC7B;AAEA,MAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,IACvB;AAEA,IAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,MAAA,MAAM,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAAA,IACtC;AAEA,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB,CAAA;AACF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.mjs","sources":["../../src/functions/diff.mts"],"sourcesContent":["import { type ExecException } from 'node:child_process';\nimport * as path from 'node:path';\nimport { Result } from 'ts-data-forge';\nimport { $ } from './exec-async.mjs';\n\n/**\n * Get the git repository root directory\n */\nexport const getGitRoot = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<Result<string, ExecException | Readonly<{ message: string }>>> => {\n const result = await $('git rev-parse --show-toplevel', {\n silent: options?.silent ?? false,\n });\n\n if (Result.isErr(result)) {\n return result;\n }\n\n return Result.ok(result.value.stdout.trim());\n};\n\n/**\n * Get untracked files from the working tree (files not added to git). Runs `git\n * ls-files --others --exclude-standard [--deleted]`\n */\nexport const getUntrackedFiles = async (\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git ls-files --others --exclude-standard`,\n cmdOptionToExcludeDeleted: '',\n cmdOptionToIncludeDeleted: '--deleted',\n options,\n });\n\n/**\n * Get modified files from the working tree (files that have been changed but\n * not staged). Runs `git diff --name-only [--diff-filter=d]`\n */\nexport const getModifiedFiles = async (\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git diff --name-only`,\n cmdOptionToExcludeDeleted: '--diff-filter=d', // lower case 'd' means exclude deleted files\n cmdOptionToIncludeDeleted: '',\n options,\n });\n\n/**\n * Get files that are staged for commit (files added with git add). Runs `git\n * diff --staged --name-only [--diff-filter=d]`\n */\nexport const getStagedFiles = async (\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git diff --staged --name-only`,\n cmdOptionToExcludeDeleted: '--diff-filter=d', // lower case 'd' means exclude deleted files\n cmdOptionToIncludeDeleted: '',\n options,\n });\n\n/**\n * Get files that differ from the specified base branch or commit. Runs `git\n * diff --name-only <base> [--diff-filter=d]`\n */\nexport const getDiffFrom = async (\n base: string,\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git diff --name-only ${base}`,\n cmdOptionToExcludeDeleted: '--diff-filter=d',\n cmdOptionToIncludeDeleted: '',\n options,\n });\n\nconst cmdResultToFiles = async ({\n cmd,\n cmdOptionToExcludeDeleted,\n cmdOptionToIncludeDeleted,\n options,\n}: Readonly<{\n cmd: string;\n cmdOptionToExcludeDeleted: string;\n cmdOptionToIncludeDeleted: string;\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>;\n}>): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> => {\n // Get git root directory\n const gitRootResult = await getGitRoot({ silent: options?.silent ?? false });\n\n if (Result.isErr(gitRootResult)) {\n return gitRootResult;\n }\n\n const gitRoot = gitRootResult.value;\n\n const result = await $(\n [\n cmd,\n (options?.excludeDeleted ?? true)\n ? cmdOptionToExcludeDeleted\n : cmdOptionToIncludeDeleted,\n ]\n .filter((s) => s !== '')\n .join(' '),\n {\n silent: options?.silent ?? false,\n // Run git from the repository root so that `git ls-files` (which\n // defaults to cwd-relative paths) and other commands return paths\n // relative to the repository root, matching the `path.join(gitRoot, …)`\n // computation below regardless of the caller's current working\n // directory.\n cwd: gitRoot,\n },\n );\n\n if (Result.isErr(result)) {\n return result;\n }\n\n const { stdout } = result.value;\n\n // Parse git output and convert to absolute paths\n const files = stdout\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line !== '')\n .map((relativePath) => path.join(gitRoot, relativePath));\n\n return Result.ok(files);\n};\n"],"names":[],"mappings":";;;;AAQO,MAAM,UAAA,GAAa,OACxB,OAAA,KAC2E;AAC3E,EAAA,MAAM,MAAA,GAAS,MAAM,CAAA,CAAE,+BAAA,EAAiC;AAAA,IACtD,MAAA,EAAQ,SAAS,MAAA,IAAU;AAAA,GAC5B,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,OAAO,EAAA,CAAG,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA;AAC7C;AAMO,MAAM,iBAAA,GAAoB,OAC/B,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,CAAA,wCAAA,CAAA;AAAA,EACL,yBAAA,EAA2B,EAAA;AAAA,EAC3B,yBAAA,EAA2B,WAAA;AAAA,EAC3B;AACF,CAAC;AAMI,MAAM,gBAAA,GAAmB,OAC9B,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,CAAA,oBAAA,CAAA;AAAA,EACL,yBAAA,EAA2B,iBAAA;AAAA;AAAA,EAC3B,yBAAA,EAA2B,EAAA;AAAA,EAC3B;AACF,CAAC;AAMI,MAAM,cAAA,GAAiB,OAC5B,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,CAAA,6BAAA,CAAA;AAAA,EACL,yBAAA,EAA2B,iBAAA;AAAA;AAAA,EAC3B,yBAAA,EAA2B,EAAA;AAAA,EAC3B;AACF,CAAC;AAMI,MAAM,WAAA,GAAc,OACzB,IAAA,EACA,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,wBAAwB,IAAI,CAAA,CAAA;AAAA,EACjC,yBAAA,EAA2B,iBAAA;AAAA,EAC3B,yBAAA,EAA2B,EAAA;AAAA,EAC3B;AACF,CAAC;AAEH,MAAM,mBAAmB,OAAO;AAAA,EAC9B,GAAA;AAAA,EACA,yBAAA;AAAA,EACA,yBAAA;AAAA,EACA;AACF,CAAA,KAYK;AAEH,EAAA,MAAM,aAAA,GAAgB,MAAM,UAAA,CAAW,EAAE,QAAQ,OAAA,EAAS,MAAA,IAAU,OAAO,CAAA;AAE3E,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA,EAAG;AAC/B,IAAA,OAAO,aAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAU,aAAA,CAAc,KAAA;AAE9B,EAAA,MAAM,SAAS,MAAM,CAAA;AAAA,IACnB;AAAA,MACE,GAAA;AAAA,MACC,OAAA,EAAS,cAAA,IAAkB,IAAA,GACxB,yBAAA,GACA;AAAA,KACN,CACG,OAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA,CACtB,KAAK,GAAG,CAAA;AAAA,IACX;AAAA,MACE,MAAA,EAAQ,SAAS,MAAA,IAAU,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM3B,GAAA,EAAK;AAAA;AACP,GACF;AAEA,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAA,CAAO,KAAA;AAG1B,EAAA,MAAM,KAAA,GAAQ,MAAA,CACX,KAAA,CAAM,IAAI,CAAA,CACV,IAAI,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,EAAM,CAAA,CACzB,OAAO,CAAC,IAAA,KAAS,IAAA,KAAS,EAAE,CAAA,CAC5B,GAAA,CAAI,CAAC,YAAA,KAAiB,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,YAAY,CAAC,CAAA;AAEzD,EAAA,OAAO,MAAA,CAAO,GAAG,KAAK,CAAA;AACxB,CAAA
|
|
1
|
+
{"version":3,"file":"diff.mjs","sources":["../../src/functions/diff.mts"],"sourcesContent":["import { type ExecException } from 'node:child_process';\nimport * as path from 'node:path';\nimport { Result } from 'ts-data-forge';\nimport { $ } from './exec-async.mjs';\n\n/**\n * Get the git repository root directory\n */\nexport const getGitRoot = async (\n options?: Readonly<{ silent?: boolean }>,\n): Promise<Result<string, ExecException | Readonly<{ message: string }>>> => {\n const result = await $('git rev-parse --show-toplevel', {\n silent: options?.silent ?? false,\n });\n\n if (Result.isErr(result)) {\n return result;\n }\n\n return Result.ok(result.value.stdout.trim());\n};\n\n/**\n * Get untracked files from the working tree (files not added to git). Runs `git\n * ls-files --others --exclude-standard [--deleted]`\n */\nexport const getUntrackedFiles = async (\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git ls-files --others --exclude-standard`,\n cmdOptionToExcludeDeleted: '',\n cmdOptionToIncludeDeleted: '--deleted',\n options,\n });\n\n/**\n * Get modified files from the working tree (files that have been changed but\n * not staged). Runs `git diff --name-only [--diff-filter=d]`\n */\nexport const getModifiedFiles = async (\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git diff --name-only`,\n cmdOptionToExcludeDeleted: '--diff-filter=d', // lower case 'd' means exclude deleted files\n cmdOptionToIncludeDeleted: '',\n options,\n });\n\n/**\n * Get files that are staged for commit (files added with git add). Runs `git\n * diff --staged --name-only [--diff-filter=d]`\n */\nexport const getStagedFiles = async (\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git diff --staged --name-only`,\n cmdOptionToExcludeDeleted: '--diff-filter=d', // lower case 'd' means exclude deleted files\n cmdOptionToIncludeDeleted: '',\n options,\n });\n\n/**\n * Get files that differ from the specified base branch or commit. Runs `git\n * diff --name-only <base> [--diff-filter=d]`\n */\nexport const getDiffFrom = async (\n base: string,\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>,\n): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> =>\n cmdResultToFiles({\n cmd: `git diff --name-only ${base}`,\n cmdOptionToExcludeDeleted: '--diff-filter=d',\n cmdOptionToIncludeDeleted: '',\n options,\n });\n\nconst cmdResultToFiles = async ({\n cmd,\n cmdOptionToExcludeDeleted,\n cmdOptionToIncludeDeleted,\n options,\n}: Readonly<{\n cmd: string;\n cmdOptionToExcludeDeleted: string;\n cmdOptionToIncludeDeleted: string;\n options?: Readonly<{\n /** @default true */\n excludeDeleted?: boolean;\n /** @default false */\n silent?: boolean;\n }>;\n}>): Promise<\n Result<readonly string[], ExecException | Readonly<{ message: string }>>\n> => {\n // Get git root directory\n const gitRootResult = await getGitRoot({ silent: options?.silent ?? false });\n\n if (Result.isErr(gitRootResult)) {\n return gitRootResult;\n }\n\n const gitRoot = gitRootResult.value;\n\n const result = await $(\n [\n cmd,\n (options?.excludeDeleted ?? true)\n ? cmdOptionToExcludeDeleted\n : cmdOptionToIncludeDeleted,\n ]\n .filter((s) => s !== '')\n .join(' '),\n {\n silent: options?.silent ?? false,\n // Run git from the repository root so that `git ls-files` (which\n // defaults to cwd-relative paths) and other commands return paths\n // relative to the repository root, matching the `path.join(gitRoot, …)`\n // computation below regardless of the caller's current working\n // directory.\n cwd: gitRoot,\n },\n );\n\n if (Result.isErr(result)) {\n return result;\n }\n\n const { stdout } = result.value;\n\n // Parse git output and convert to absolute paths\n const files = stdout\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line !== '')\n .map((relativePath) => path.join(gitRoot, relativePath));\n\n return Result.ok(files);\n};\n"],"names":[],"mappings":";;;;AAQO,MAAM,UAAA,GAAa,OACxB,OAAA,KAC2E;AAC3E,EAAA,MAAM,MAAA,GAAS,MAAM,CAAA,CAAE,+BAAA,EAAiC;AAAA,IACtD,MAAA,EAAQ,SAAS,MAAA,IAAU;AAAA,GAC5B,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,OAAO,EAAA,CAAG,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA;AAC7C;AAMO,MAAM,iBAAA,GAAoB,OAC/B,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,CAAA,wCAAA,CAAA;AAAA,EACL,yBAAA,EAA2B,EAAA;AAAA,EAC3B,yBAAA,EAA2B,WAAA;AAAA,EAC3B;AACF,CAAC;AAMI,MAAM,gBAAA,GAAmB,OAC9B,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,CAAA,oBAAA,CAAA;AAAA,EACL,yBAAA,EAA2B,iBAAA;AAAA;AAAA,EAC3B,yBAAA,EAA2B,EAAA;AAAA,EAC3B;AACF,CAAC;AAMI,MAAM,cAAA,GAAiB,OAC5B,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,CAAA,6BAAA,CAAA;AAAA,EACL,yBAAA,EAA2B,iBAAA;AAAA;AAAA,EAC3B,yBAAA,EAA2B,EAAA;AAAA,EAC3B;AACF,CAAC;AAMI,MAAM,WAAA,GAAc,OACzB,IAAA,EACA,OAAA,KASA,gBAAA,CAAiB;AAAA,EACf,GAAA,EAAK,wBAAwB,IAAI,CAAA,CAAA;AAAA,EACjC,yBAAA,EAA2B,iBAAA;AAAA,EAC3B,yBAAA,EAA2B,EAAA;AAAA,EAC3B;AACF,CAAC;AAEH,MAAM,mBAAmB,OAAO;AAAA,EAC9B,GAAA;AAAA,EACA,yBAAA;AAAA,EACA,yBAAA;AAAA,EACA;AACF,CAAA,KAYK;AAEH,EAAA,MAAM,aAAA,GAAgB,MAAM,UAAA,CAAW,EAAE,QAAQ,OAAA,EAAS,MAAA,IAAU,OAAO,CAAA;AAE3E,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA,EAAG;AAC/B,IAAA,OAAO,aAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAU,aAAA,CAAc,KAAA;AAE9B,EAAA,MAAM,SAAS,MAAM,CAAA;AAAA,IACnB;AAAA,MACE,GAAA;AAAA,MACC,OAAA,EAAS,cAAA,IAAkB,IAAA,GACxB,yBAAA,GACA;AAAA,KACN,CACG,OAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA,CACtB,KAAK,GAAG,CAAA;AAAA,IACX;AAAA,MACE,MAAA,EAAQ,SAAS,MAAA,IAAU,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM3B,GAAA,EAAK;AAAA;AACP,GACF;AAEA,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAA,CAAO,KAAA;AAG1B,EAAA,MAAM,KAAA,GAAQ,MAAA,CACX,KAAA,CAAM,IAAI,CAAA,CACV,IAAI,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,EAAM,CAAA,CACzB,OAAO,CAAC,IAAA,KAAS,IAAA,KAAS,EAAE,CAAA,CAC5B,GAAA,CAAI,CAAC,YAAA,KAAiB,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,YAAY,CAAC,CAAA;AAEzD,EAAA,OAAO,MAAA,CAAO,GAAG,KAAK,CAAA;AACxB,CAAA;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec-async.mjs","sources":["../../src/functions/exec-async.mts"],"sourcesContent":["import * as childProcess from 'node:child_process';\nimport { Result } from 'ts-data-forge';\n\ntype ExecOptionsCustom = Readonly<{\n silent?: boolean;\n}>;\n\ntype ExecOptionsWithStringEncoding =\n childProcess.ExecOptionsWithStringEncoding & ExecOptionsCustom;\n\ntype ExecOptionsWithBufferEncoding =\n childProcess.ExecOptionsWithBufferEncoding & ExecOptionsCustom;\n\ntype NormalizedExecOptions = childProcess.ExecOptions &\n Readonly<{ encoding?: BufferEncoding | 'buffer' | null }>;\n\nexport type ExecOptions = childProcess.ExecOptions & ExecOptionsCustom;\n\nexport type ExecResult<T extends string | Buffer> = Result<\n Readonly<{ stdout: T; stderr: T }>,\n childProcess.ExecException\n>;\n\n/**\n * Executes a shell command asynchronously.\n *\n * @param command - The command to execute.\n * @param options - Optional configuration for command execution.\n * @returns A promise that resolves with the command result.\n */\n\nexport function $(\n command: string,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n options?: ExecOptionsWithStringEncoding,\n): Promise<ExecResult<string>>;\n\nexport function $(\n command: string,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n options: ExecOptionsWithBufferEncoding,\n): Promise<ExecResult<Buffer>>;\n\nexport function $<\n TOptions extends\n ExecOptionsWithBufferEncoding | ExecOptionsWithStringEncoding | undefined =\n undefined,\n>(\n command: string,\n options?: TOptions,\n): Promise<\n ExecResult<TOptions extends ExecOptionsWithBufferEncoding ? Buffer : string>\n>;\n\nexport function $(\n command: string,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n options?: ExecOptionsWithStringEncoding | ExecOptionsWithBufferEncoding,\n): Promise<ExecResult<string | Buffer>> {\n const { silent = false, ...restOptions } = options ?? {};\n\n const normalizedOptions: NormalizedExecOptions = restOptions;\n\n if (!silent) {\n console.info(`$ ${command}`);\n }\n\n return new Promise((resolve) => {\n const handleResult = <T extends string | Buffer>(\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n error: childProcess.ExecException | null,\n stdout: T,\n stderr: T,\n ): void => {\n if (!silent) {\n if (!isEmpty(stdout)) {\n console.info(stdout);\n }\n\n if (!isEmpty(stderr)) {\n console.error(stderr);\n }\n }\n\n if (error !== null) {\n resolve(Result.err(error));\n\n return;\n }\n\n resolve(\n Result.ok<Readonly<{ stdout: T; stderr: T }>>({ stdout, stderr }),\n );\n };\n\n const encoding = normalizedOptions.encoding;\n\n if (encoding === 'buffer' || encoding === null) {\n // eslint-disable-next-line security/detect-child-process\n childProcess.exec(\n command,\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n normalizedOptions as childProcess.ExecOptionsWithBufferEncoding,\n (error, stdout, stderr) => {\n handleResult(error, stdout, stderr);\n },\n );\n\n return;\n }\n\n // eslint-disable-next-line security/detect-child-process\n childProcess.exec(\n command,\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n normalizedOptions as childProcess.ExecOptionsWithStringEncoding,\n (error, stdout, stderr) => {\n handleResult(error, stdout, stderr);\n },\n );\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\nconst isEmpty = (value: string | Buffer): boolean =>\n typeof value === 'string' ? value === '' : value.length === 0;\n"],"names":[],"mappings":";;;AAsDO,SAAS,CAAA,CACd,SAEA,OAAA,EACsC;AACtC,EAAA,MAAM,EAAE,MAAA,GAAS,KAAA,EAAO,GAAG,WAAA,EAAY,GAAI,WAAW,EAAC;AAEvD,EAAA,MAAM,iBAAA,GAA2C,WAAA;AAEjD,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,YAAA,GAAe,CAEnB,KAAA,EACA,MAAA,EACA,MAAA,KACS;AACT,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,IAAI,CAAC,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpB,UAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,QACrB;AAEA,QAAA,IAAI,CAAC,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpB,UAAA,OAAA,CAAQ,MAAM,MAAM,CAAA;AAAA,QACtB;AAAA,MACF;AAEA,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA,OAAA,CAAQ,MAAA,CAAO,GAAA,CAAI,KAAK,CAAC,CAAA;AAEzB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA;AAAA,QACE,MAAA,CAAO,EAAA,CAAuC,EAAE,MAAA,EAAQ,QAAQ;AAAA,OAClE;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,WAAW,iBAAA,CAAkB,QAAA;AAEnC,IAAA,IAAI,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,IAAA,EAAM;AAE9C,MAAA,YAAA,CAAa,IAAA;AAAA,QACX,OAAA;AAAA;AAAA,QAEA,iBAAA;AAAA,QACA,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,KAAW;AACzB,UAAA,YAAA,CAAa,KAAA,EAAO,QAAQ,MAAM,CAAA;AAAA,QACpC;AAAA,OACF;AAEA,MAAA;AAAA,IACF;AAGA,IAAA,YAAA,CAAa,IAAA;AAAA,MACX,OAAA;AAAA;AAAA,MAEA,iBAAA;AAAA,MACA,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,KAAW;AACzB,QAAA,YAAA,CAAa,KAAA,EAAO,QAAQ,MAAM,CAAA;AAAA,MACpC;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAGA,MAAM,OAAA,GAAU,CAAC,KAAA,KACf,OAAO,UAAU,QAAA,GAAW,KAAA,KAAU,EAAA,GAAK,KAAA,CAAM,MAAA,KAAW,CAAA
|
|
1
|
+
{"version":3,"file":"exec-async.mjs","sources":["../../src/functions/exec-async.mts"],"sourcesContent":["import * as childProcess from 'node:child_process';\nimport { Result } from 'ts-data-forge';\n\ntype ExecOptionsCustom = Readonly<{\n silent?: boolean;\n}>;\n\ntype ExecOptionsWithStringEncoding =\n childProcess.ExecOptionsWithStringEncoding & ExecOptionsCustom;\n\ntype ExecOptionsWithBufferEncoding =\n childProcess.ExecOptionsWithBufferEncoding & ExecOptionsCustom;\n\ntype NormalizedExecOptions = childProcess.ExecOptions &\n Readonly<{ encoding?: BufferEncoding | 'buffer' | null }>;\n\nexport type ExecOptions = childProcess.ExecOptions & ExecOptionsCustom;\n\nexport type ExecResult<T extends string | Buffer> = Result<\n Readonly<{ stdout: T; stderr: T }>,\n childProcess.ExecException\n>;\n\n/**\n * Executes a shell command asynchronously.\n *\n * @param command - The command to execute.\n * @param options - Optional configuration for command execution.\n * @returns A promise that resolves with the command result.\n */\n\nexport function $(\n command: string,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n options?: ExecOptionsWithStringEncoding,\n): Promise<ExecResult<string>>;\n\nexport function $(\n command: string,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n options: ExecOptionsWithBufferEncoding,\n): Promise<ExecResult<Buffer>>;\n\nexport function $<\n TOptions extends\n ExecOptionsWithBufferEncoding | ExecOptionsWithStringEncoding | undefined =\n undefined,\n>(\n command: string,\n options?: TOptions,\n): Promise<\n ExecResult<TOptions extends ExecOptionsWithBufferEncoding ? Buffer : string>\n>;\n\nexport function $(\n command: string,\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n options?: ExecOptionsWithStringEncoding | ExecOptionsWithBufferEncoding,\n): Promise<ExecResult<string | Buffer>> {\n const { silent = false, ...restOptions } = options ?? {};\n\n const normalizedOptions: NormalizedExecOptions = restOptions;\n\n if (!silent) {\n console.info(`$ ${command}`);\n }\n\n return new Promise((resolve) => {\n const handleResult = <T extends string | Buffer>(\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n error: childProcess.ExecException | null,\n stdout: T,\n stderr: T,\n ): void => {\n if (!silent) {\n if (!isEmpty(stdout)) {\n console.info(stdout);\n }\n\n if (!isEmpty(stderr)) {\n console.error(stderr);\n }\n }\n\n if (error !== null) {\n resolve(Result.err(error));\n\n return;\n }\n\n resolve(\n Result.ok<Readonly<{ stdout: T; stderr: T }>>({ stdout, stderr }),\n );\n };\n\n const encoding = normalizedOptions.encoding;\n\n if (encoding === 'buffer' || encoding === null) {\n // eslint-disable-next-line security/detect-child-process\n childProcess.exec(\n command,\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n normalizedOptions as childProcess.ExecOptionsWithBufferEncoding,\n (error, stdout, stderr) => {\n handleResult(error, stdout, stderr);\n },\n );\n\n return;\n }\n\n // eslint-disable-next-line security/detect-child-process\n childProcess.exec(\n command,\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n normalizedOptions as childProcess.ExecOptionsWithStringEncoding,\n (error, stdout, stderr) => {\n handleResult(error, stdout, stderr);\n },\n );\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\nconst isEmpty = (value: string | Buffer): boolean =>\n typeof value === 'string' ? value === '' : value.length === 0;\n"],"names":[],"mappings":";;;AAsDO,SAAS,CAAA,CACd,SAEA,OAAA,EACsC;AACtC,EAAA,MAAM,EAAE,MAAA,GAAS,KAAA,EAAO,GAAG,WAAA,EAAY,GAAI,WAAW,EAAC;AAEvD,EAAA,MAAM,iBAAA,GAA2C,WAAA;AAEjD,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,YAAA,GAAe,CAEnB,KAAA,EACA,MAAA,EACA,MAAA,KACS;AACT,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,IAAI,CAAC,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpB,UAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,QACrB;AAEA,QAAA,IAAI,CAAC,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpB,UAAA,OAAA,CAAQ,MAAM,MAAM,CAAA;AAAA,QACtB;AAAA,MACF;AAEA,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA,OAAA,CAAQ,MAAA,CAAO,GAAA,CAAI,KAAK,CAAC,CAAA;AAEzB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA;AAAA,QACE,MAAA,CAAO,EAAA,CAAuC,EAAE,MAAA,EAAQ,QAAQ;AAAA,OAClE;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,WAAW,iBAAA,CAAkB,QAAA;AAEnC,IAAA,IAAI,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,IAAA,EAAM;AAE9C,MAAA,YAAA,CAAa,IAAA;AAAA,QACX,OAAA;AAAA;AAAA,QAEA,iBAAA;AAAA,QACA,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,KAAW;AACzB,UAAA,YAAA,CAAa,KAAA,EAAO,QAAQ,MAAM,CAAA;AAAA,QACpC;AAAA,OACF;AAEA,MAAA;AAAA,IACF;AAGA,IAAA,YAAA,CAAa,IAAA;AAAA,MACX,OAAA;AAAA;AAAA,MAEA,iBAAA;AAAA,MACA,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,KAAW;AACzB,QAAA,YAAA,CAAa,KAAA,EAAO,QAAQ,MAAM,CAAA;AAAA,MACpC;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAGA,MAAM,OAAA,GAAU,CAAC,KAAA,KACf,OAAO,UAAU,QAAA,GAAW,KAAA,KAAU,EAAA,GAAK,KAAA,CAAM,MAAA,KAAW,CAAA;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.mjs","sources":["../../src/functions/format.mts"],"sourcesContent":["import { type ExecException } from 'node:child_process';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as prettier from 'prettier';\nimport { Arr, isNotUndefined, pipe, Result } from 'ts-data-forge';\nimport { pathExists } from './assert-path-exists.mjs';\nimport {\n getDiffFrom,\n getGitRoot,\n getModifiedFiles,\n getStagedFiles,\n getUntrackedFiles,\n} from './diff.mjs';\nimport { glob } from './glob.mjs';\n\n/**\n * Format a list of files using Prettier\n *\n * @param files - Array of file paths to format\n */\nexport const formatFiles = async (\n files: readonly string[],\n options?: Readonly<{\n silent?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n ignoreUnknown?: boolean;\n }>,\n): Promise<Result<undefined, readonly unknown[]>> => {\n const silent = options?.silent ?? false;\n\n const noIgnore = options?.ignore === false;\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n if (Arr.isEmpty(files)) {\n conditionalEcho('No files to format');\n\n return Result.ok(undefined);\n }\n\n conditionalEcho(`Formatting ${files.length} files...`);\n\n // Get git root for display purposes\n const gitRootResult = await getGitRoot({ silent: true });\n\n const gitRoot = Result.isOk(gitRootResult) ? gitRootResult.value : undefined;\n\n // Helper function to get display path (relative to git root if available)\n const getDisplayPath = (filePath: string): string => {\n if (gitRoot === undefined) {\n return filePath;\n }\n\n const relativePath = path.relative(gitRoot, filePath);\n\n return relativePath.startsWith('..') ? filePath : relativePath;\n };\n\n // Skips are counted rather than named. A repository can hand this function\n // thousands of files it will not touch — a subtree formatted by another tool,\n // or a first diff that contains a whole imported directory — and a line each\n // is both unreadable and enough output to overflow the stdout buffer of a\n // parent process capturing this run.\n const mut_skipped = { nonExistent: 0, ignored: 0, noParser: 0 };\n\n // Format each file\n const results: readonly PromiseSettledResult<Result<undefined, unknown>>[] =\n // NOTE: Using Promise.allSettled to ensure all files are processed even if some fail\n await Promise.allSettled(\n files.map(async (filePath) => {\n try {\n // Check if file exists first\n if (!(await pathExists(filePath))) {\n mut_skipped.nonExistent += 1;\n\n return Result.ok(undefined);\n }\n\n if (!noIgnore && (options?.ignore ?? defaultIgnoreFn)(filePath)) {\n mut_skipped.ignored += 1;\n\n return Result.ok(undefined);\n }\n\n // Check if file is ignored by prettier\n const fileInfo = await prettier.getFileInfo(filePath, {\n ignorePath: '.prettierignore',\n });\n\n if (!noIgnore && fileInfo.ignored) {\n mut_skipped.ignored += 1;\n\n return Result.ok(undefined);\n }\n\n if (\n !noIgnore &&\n (options?.ignoreUnknown ?? true) &&\n fileInfo.inferredParser === null\n ) {\n mut_skipped.noParser += 1;\n\n return Result.ok(undefined);\n }\n\n // Read file content\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n const content = await fs.readFile(filePath, 'utf8');\n\n // Resolve prettier config for this file\n const prettierOptions = await prettier.resolveConfig(filePath);\n\n // Format the content\n const formatted = await prettier.format(content, {\n ...prettierOptions,\n filepath: filePath,\n });\n\n // Only write if content changed\n if (formatted === content) {\n conditionalEcho(`Unchanged: ${getDisplayPath(filePath)}`);\n } else {\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n await fs.writeFile(filePath, formatted, 'utf8');\n\n conditionalEcho(`Formatted: ${getDisplayPath(filePath)}`);\n }\n\n return Result.ok(undefined);\n } catch (error) {\n if (!silent) {\n console.error(\n `Error formatting ${getDisplayPath(filePath)}:`,\n error,\n );\n }\n\n return Result.err(error);\n }\n }),\n );\n\n const skipReport = [\n mut_skipped.ignored === 0 ? '' : `${mut_skipped.ignored} ignored`,\n mut_skipped.noParser === 0 ? '' : `${mut_skipped.noParser} with no parser`,\n mut_skipped.nonExistent === 0\n ? ''\n : `${mut_skipped.nonExistent} non-existent`,\n ].filter((part) => part !== '');\n\n if (Arr.isNonEmpty(skipReport)) {\n conditionalEcho(`Skipped ${skipReport.join(', ')}.`);\n }\n\n if (results.every((r) => r.status === 'fulfilled')) {\n const fulfilled = results.map((r) => r.value);\n\n if (fulfilled.every(Result.isOk)) {\n return Result.ok(undefined);\n }\n\n return Result.err(fulfilled.filter(Result.isErr).map((r) => r.value));\n }\n\n return Result.err(\n results\n .filter((r) => r.status === 'rejected')\n .map((r): unknown => r.reason),\n );\n};\n\nconst defaultIgnoreFn = (filePath: string): boolean => {\n const filename = path.basename(filePath);\n\n return (\n ignoreFiles.has(filename) ||\n filename.startsWith('.env') ||\n ignoreExtensions.some((ext) => filePath.endsWith(ext)) ||\n pipe(filePath.split(path.sep)).map((pathSegments) =>\n pathSegments.some((segment) => ignoreDirs.includes(segment)),\n ).value\n );\n};\n\nconst ignoreFiles: ReadonlySet<string> = new Set([\n '.DS_Store',\n 'package-lock.json',\n 'yarn.lock',\n 'pnpm-lock.yaml',\n 'LICENSE',\n '.prettierignore',\n '.editorconfig',\n '.gitignore',\n '.npmignore',\n '.envrc',\n '.nvmrc',\n '.npmrc',\n]);\n\nconst ignoreExtensions: readonly `.${string}`[] = [\n '.svg',\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.tiff',\n '.bak',\n '.log',\n '.zip',\n '.tar',\n '.gz',\n '.7z',\n '.mp3',\n '.mp4',\n '.avi',\n '.mkv',\n '.tsbuildinfo',\n] as const;\n\nconst ignoreDirs: readonly string[] = [\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n 'out',\n '.cache',\n '.vscode',\n '.yarn',\n '.wireit',\n] as const;\n\n/**\n * Format files matching the given glob pattern using Prettier\n *\n * @param pathGlob - Glob pattern to match files\n */\nexport const formatFilesGlob = async (\n pathGlob: string,\n options?: Readonly<{\n silent?: boolean;\n ignoreUnknown?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n }>,\n): Promise<Result<undefined, unknown>> => {\n const silent = options?.silent ?? false;\n\n const ignoreUnknown = options?.ignoreUnknown ?? true;\n\n const ignore = options?.ignore;\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n // Find all files matching the glob\n const globResult = await glob(pathGlob, {\n absolute: true,\n ignore: ignore === false ? [] : ['**/node_modules/**', '**/.git/**'],\n dot: true,\n });\n\n if (Result.isErr(globResult)) {\n const error = globResult.value;\n\n if (!silent) {\n console.error('Error in formatFiles:', error);\n }\n\n return Result.err(error);\n }\n\n const files = globResult.value;\n\n if (Arr.isEmpty(files)) {\n conditionalEcho('No files found matching pattern:', pathGlob);\n\n return Result.ok(undefined);\n }\n\n return formatFiles(files, { silent, ignoreUnknown, ignore });\n};\n\n/**\n * Format only files that have been changed (git status)\n *\n * @param options - Options for formatting\n * @param options.cwd - If provided, only files within this directory will be\n * formatted. Relative paths are resolved against `process.cwd()`. Defaults to\n * undefined (no filtering; all changed files in the repository are\n * formatted).\n */\nexport const formatUncommittedFiles = async (\n options?: Readonly<{\n untracked?: boolean;\n modified?: boolean;\n staged?: boolean;\n silent?: boolean;\n ignoreUnknown?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n cwd?: string;\n }>,\n): Promise<\n Result<\n undefined,\n ExecException | Readonly<{ message: string }> | readonly unknown[]\n >\n> => {\n const {\n untracked = true,\n modified = true,\n staged = true,\n silent = false,\n ignoreUnknown = true,\n ignore,\n cwd,\n } = options ?? {};\n\n const mut_files: string[] = [];\n\n if (untracked) {\n const untrackedFilesResult = await getUntrackedFiles({ silent });\n\n if (Result.isErr(untrackedFilesResult)) {\n if (!silent) {\n console.error(\n 'Error getting changed files:',\n untrackedFilesResult.value,\n );\n }\n\n return untrackedFilesResult;\n }\n\n mut_files.push(...untrackedFilesResult.value);\n }\n\n if (modified) {\n const diffFilesResult = await getModifiedFiles({ silent });\n\n if (Result.isErr(diffFilesResult)) {\n if (!silent) {\n console.error('Error getting changed files:', diffFilesResult.value);\n }\n\n return diffFilesResult;\n }\n\n mut_files.push(...diffFilesResult.value);\n }\n\n if (staged) {\n const stagedFilesResult = await getStagedFiles({ silent });\n\n if (Result.isErr(stagedFilesResult)) {\n if (!silent) {\n console.error('Error getting changed files:', stagedFilesResult.value);\n }\n\n return stagedFilesResult;\n }\n\n mut_files.push(...stagedFilesResult.value);\n }\n\n return formatFiles(filterFilesByCwd(Arr.uniq(mut_files), cwd), {\n silent,\n ignoreUnknown,\n ignore,\n });\n};\n\n/**\n * Filter a list of file paths to those inside `cwd`. If `cwd` is undefined,\n * returns the original list unchanged. Relative `cwd` is resolved against\n * `process.cwd()`.\n */\nconst filterFilesByCwd = (\n files: readonly string[],\n cwd: string | undefined,\n): readonly string[] => {\n if (cwd === undefined) {\n return files;\n }\n\n const resolvedCwd = path.resolve(cwd);\n\n const cwdWithSep = resolvedCwd.endsWith(path.sep)\n ? resolvedCwd\n : (`${resolvedCwd}${path.sep}` as const);\n\n return files.filter((file) => {\n const absFile = path.isAbsolute(file) ? file : path.resolve(file);\n\n return absFile === resolvedCwd || absFile.startsWith(cwdWithSep);\n });\n};\n\n/**\n * Format only files that differ from the specified base branch or commit\n *\n * @param base - Base branch name or commit hash to compare against (defaults to\n * 'main')\n * @param options - Options for formatting\n * @param options.includeUntracked - Include untracked files in addition to diff\n * files (default is true)\n * @param options.includeStaged - Include staged files in addition to diff files\n * (default is true)\n * @param options.silent - Silent mode to suppress command output (default is\n * false)\n */\nexport const formatDiffFrom = async (\n base: string,\n options?: Readonly<{\n includeUntracked?: boolean;\n includeModified?: boolean;\n includeStaged?: boolean;\n silent?: boolean;\n ignoreUnknown?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n /**\n * If provided, only files within this directory will be formatted.\n * Relative paths are resolved against `process.cwd()`. Defaults to\n * undefined (no filtering; all changed files in the repository are\n * formatted).\n */\n cwd?: string;\n }>,\n): Promise<\n Result<\n undefined,\n | ExecException\n | Readonly<{\n message: string;\n }>\n | readonly unknown[]\n >\n> => {\n // const silent = options?.silent ?? false;\n const {\n silent = false,\n includeUntracked = true,\n includeModified = true,\n includeStaged = true,\n ignoreUnknown = true,\n ignore,\n cwd,\n } = options ?? {};\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n // Get files that differ from base branch/commit (excluding deleted files)\n const diffFromBaseResult = await getDiffFrom(base, {\n silent,\n });\n\n if (Result.isErr(diffFromBaseResult)) {\n if (!silent) {\n console.error('Error getting changed files:', diffFromBaseResult.value);\n }\n\n return diffFromBaseResult;\n }\n\n const diffFiles = diffFromBaseResult.value;\n\n const mut_allFiles: string[] = diffFiles.slice();\n\n // If includeUntracked is true, also get untracked files\n for (const { type, flag, fn } of [\n { type: 'untracked', flag: includeUntracked, fn: getUntrackedFiles },\n { type: 'modified', flag: includeModified, fn: getModifiedFiles },\n { type: 'staged', flag: includeStaged, fn: getStagedFiles },\n ]) {\n if (!flag) {\n continue;\n }\n\n // eslint-disable-next-line no-await-in-loop\n const filesResult = await fn({ silent });\n\n if (Result.isErr(filesResult)) {\n if (!silent) {\n console.error(`Error getting ${type} files:`, filesResult.value);\n }\n\n return filesResult;\n }\n\n const files = filesResult.value;\n\n // Combine and deduplicate files\n mut_allFiles.push(...files);\n }\n\n const allFiles = filterFilesByCwd(Arr.uniq(mut_allFiles), cwd);\n\n if (!silent) {\n const includedFileTypes = [\n includeUntracked ? 'untracked files' : undefined,\n includeModified ? 'modified files' : undefined,\n includeStaged ? 'staged files' : undefined,\n ].filter(isNotUndefined);\n\n const message = [\n `Formatting files that differ from ${base}`,\n includedFileTypes\n .map((s, i) =>\n i !== includedFileTypes.length - 1 ? `, ${s}` : ` and ${s}`,\n )\n .join(''),\n ].join('');\n\n conditionalEcho(`${message}:`, allFiles);\n }\n\n if (Arr.isEmpty(allFiles)) {\n conditionalEcho('No files to format');\n\n return Result.ok(undefined);\n }\n\n return formatFiles(allFiles, {\n silent,\n ignoreUnknown,\n ignore,\n });\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"format.mjs","sources":["../../src/functions/format.mts"],"sourcesContent":["import { type ExecException } from 'node:child_process';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as prettier from 'prettier';\nimport { Arr, isNotUndefined, pipe, Result } from 'ts-data-forge';\nimport { pathExists } from './assert-path-exists.mjs';\nimport {\n getDiffFrom,\n getGitRoot,\n getModifiedFiles,\n getStagedFiles,\n getUntrackedFiles,\n} from './diff.mjs';\nimport { glob } from './glob.mjs';\n\n/**\n * Format a list of files using Prettier\n *\n * @param files - Array of file paths to format\n */\nexport const formatFiles = async (\n files: readonly string[],\n options?: Readonly<{\n silent?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n ignoreUnknown?: boolean;\n }>,\n): Promise<Result<undefined, readonly unknown[]>> => {\n const silent = options?.silent ?? false;\n\n const noIgnore = options?.ignore === false;\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n if (Arr.isEmpty(files)) {\n conditionalEcho('No files to format');\n\n return Result.ok(undefined);\n }\n\n conditionalEcho(`Formatting ${files.length} files...`);\n\n // Get git root for display purposes\n const gitRootResult = await getGitRoot({ silent: true });\n\n const gitRoot = Result.isOk(gitRootResult) ? gitRootResult.value : undefined;\n\n // Helper function to get display path (relative to git root if available)\n const getDisplayPath = (filePath: string): string => {\n if (gitRoot === undefined) {\n return filePath;\n }\n\n const relativePath = path.relative(gitRoot, filePath);\n\n return relativePath.startsWith('..') ? filePath : relativePath;\n };\n\n // Skips are counted rather than named. A repository can hand this function\n // thousands of files it will not touch — a subtree formatted by another tool,\n // or a first diff that contains a whole imported directory — and a line each\n // is both unreadable and enough output to overflow the stdout buffer of a\n // parent process capturing this run.\n const mut_skipped = { nonExistent: 0, ignored: 0, noParser: 0 };\n\n // Format each file\n const results: readonly PromiseSettledResult<Result<undefined, unknown>>[] =\n // NOTE: Using Promise.allSettled to ensure all files are processed even if some fail\n await Promise.allSettled(\n files.map(async (filePath) => {\n try {\n // Check if file exists first\n if (!(await pathExists(filePath))) {\n mut_skipped.nonExistent += 1;\n\n return Result.ok(undefined);\n }\n\n if (!noIgnore && (options?.ignore ?? defaultIgnoreFn)(filePath)) {\n mut_skipped.ignored += 1;\n\n return Result.ok(undefined);\n }\n\n // Check if file is ignored by prettier\n const fileInfo = await prettier.getFileInfo(filePath, {\n ignorePath: '.prettierignore',\n });\n\n if (!noIgnore && fileInfo.ignored) {\n mut_skipped.ignored += 1;\n\n return Result.ok(undefined);\n }\n\n if (\n !noIgnore &&\n (options?.ignoreUnknown ?? true) &&\n fileInfo.inferredParser === null\n ) {\n mut_skipped.noParser += 1;\n\n return Result.ok(undefined);\n }\n\n // Read file content\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n const content = await fs.readFile(filePath, 'utf8');\n\n // Resolve prettier config for this file\n const prettierOptions = await prettier.resolveConfig(filePath);\n\n // Format the content\n const formatted = await prettier.format(content, {\n ...prettierOptions,\n filepath: filePath,\n });\n\n // Only write if content changed\n if (formatted === content) {\n conditionalEcho(`Unchanged: ${getDisplayPath(filePath)}`);\n } else {\n // eslint-disable-next-line security/detect-non-literal-fs-filename\n await fs.writeFile(filePath, formatted, 'utf8');\n\n conditionalEcho(`Formatted: ${getDisplayPath(filePath)}`);\n }\n\n return Result.ok(undefined);\n } catch (error) {\n if (!silent) {\n console.error(\n `Error formatting ${getDisplayPath(filePath)}:`,\n error,\n );\n }\n\n return Result.err(error);\n }\n }),\n );\n\n const skipReport = [\n mut_skipped.ignored === 0 ? '' : `${mut_skipped.ignored} ignored`,\n mut_skipped.noParser === 0 ? '' : `${mut_skipped.noParser} with no parser`,\n mut_skipped.nonExistent === 0\n ? ''\n : `${mut_skipped.nonExistent} non-existent`,\n ].filter((part) => part !== '');\n\n if (Arr.isNonEmpty(skipReport)) {\n conditionalEcho(`Skipped ${skipReport.join(', ')}.`);\n }\n\n if (results.every((r) => r.status === 'fulfilled')) {\n const fulfilled = results.map((r) => r.value);\n\n if (fulfilled.every(Result.isOk)) {\n return Result.ok(undefined);\n }\n\n return Result.err(fulfilled.filter(Result.isErr).map((r) => r.value));\n }\n\n return Result.err(\n results\n .filter((r) => r.status === 'rejected')\n .map((r): unknown => r.reason),\n );\n};\n\nconst defaultIgnoreFn = (filePath: string): boolean => {\n const filename = path.basename(filePath);\n\n return (\n ignoreFiles.has(filename) ||\n filename.startsWith('.env') ||\n ignoreExtensions.some((ext) => filePath.endsWith(ext)) ||\n pipe(filePath.split(path.sep)).map((pathSegments) =>\n pathSegments.some((segment) => ignoreDirs.includes(segment)),\n ).value\n );\n};\n\nconst ignoreFiles: ReadonlySet<string> = new Set([\n '.DS_Store',\n 'package-lock.json',\n 'yarn.lock',\n 'pnpm-lock.yaml',\n 'LICENSE',\n '.prettierignore',\n '.editorconfig',\n '.gitignore',\n '.npmignore',\n '.envrc',\n '.nvmrc',\n '.npmrc',\n]);\n\nconst ignoreExtensions: readonly `.${string}`[] = [\n '.svg',\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.tiff',\n '.bak',\n '.log',\n '.zip',\n '.tar',\n '.gz',\n '.7z',\n '.mp3',\n '.mp4',\n '.avi',\n '.mkv',\n '.tsbuildinfo',\n] as const;\n\nconst ignoreDirs: readonly string[] = [\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n 'out',\n '.cache',\n '.vscode',\n '.yarn',\n '.wireit',\n] as const;\n\n/**\n * Format files matching the given glob pattern using Prettier\n *\n * @param pathGlob - Glob pattern to match files\n */\nexport const formatFilesGlob = async (\n pathGlob: string,\n options?: Readonly<{\n silent?: boolean;\n ignoreUnknown?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n }>,\n): Promise<Result<undefined, unknown>> => {\n const silent = options?.silent ?? false;\n\n const ignoreUnknown = options?.ignoreUnknown ?? true;\n\n const ignore = options?.ignore;\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n // Find all files matching the glob\n const globResult = await glob(pathGlob, {\n absolute: true,\n ignore: ignore === false ? [] : ['**/node_modules/**', '**/.git/**'],\n dot: true,\n });\n\n if (Result.isErr(globResult)) {\n const error = globResult.value;\n\n if (!silent) {\n console.error('Error in formatFiles:', error);\n }\n\n return Result.err(error);\n }\n\n const files = globResult.value;\n\n if (Arr.isEmpty(files)) {\n conditionalEcho('No files found matching pattern:', pathGlob);\n\n return Result.ok(undefined);\n }\n\n return formatFiles(files, { silent, ignoreUnknown, ignore });\n};\n\n/**\n * Format only files that have been changed (git status)\n *\n * @param options - Options for formatting\n * @param options.cwd - If provided, only files within this directory will be\n * formatted. Relative paths are resolved against `process.cwd()`. Defaults to\n * undefined (no filtering; all changed files in the repository are\n * formatted).\n */\nexport const formatUncommittedFiles = async (\n options?: Readonly<{\n untracked?: boolean;\n modified?: boolean;\n staged?: boolean;\n silent?: boolean;\n ignoreUnknown?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n cwd?: string;\n }>,\n): Promise<\n Result<\n undefined,\n ExecException | Readonly<{ message: string }> | readonly unknown[]\n >\n> => {\n const {\n untracked = true,\n modified = true,\n staged = true,\n silent = false,\n ignoreUnknown = true,\n ignore,\n cwd,\n } = options ?? {};\n\n const mut_files: string[] = [];\n\n if (untracked) {\n const untrackedFilesResult = await getUntrackedFiles({ silent });\n\n if (Result.isErr(untrackedFilesResult)) {\n if (!silent) {\n console.error(\n 'Error getting changed files:',\n untrackedFilesResult.value,\n );\n }\n\n return untrackedFilesResult;\n }\n\n mut_files.push(...untrackedFilesResult.value);\n }\n\n if (modified) {\n const diffFilesResult = await getModifiedFiles({ silent });\n\n if (Result.isErr(diffFilesResult)) {\n if (!silent) {\n console.error('Error getting changed files:', diffFilesResult.value);\n }\n\n return diffFilesResult;\n }\n\n mut_files.push(...diffFilesResult.value);\n }\n\n if (staged) {\n const stagedFilesResult = await getStagedFiles({ silent });\n\n if (Result.isErr(stagedFilesResult)) {\n if (!silent) {\n console.error('Error getting changed files:', stagedFilesResult.value);\n }\n\n return stagedFilesResult;\n }\n\n mut_files.push(...stagedFilesResult.value);\n }\n\n return formatFiles(filterFilesByCwd(Arr.uniq(mut_files), cwd), {\n silent,\n ignoreUnknown,\n ignore,\n });\n};\n\n/**\n * Filter a list of file paths to those inside `cwd`. If `cwd` is undefined,\n * returns the original list unchanged. Relative `cwd` is resolved against\n * `process.cwd()`.\n */\nconst filterFilesByCwd = (\n files: readonly string[],\n cwd: string | undefined,\n): readonly string[] => {\n if (cwd === undefined) {\n return files;\n }\n\n const resolvedCwd = path.resolve(cwd);\n\n const cwdWithSep = resolvedCwd.endsWith(path.sep)\n ? resolvedCwd\n : (`${resolvedCwd}${path.sep}` as const);\n\n return files.filter((file) => {\n const absFile = path.isAbsolute(file) ? file : path.resolve(file);\n\n return absFile === resolvedCwd || absFile.startsWith(cwdWithSep);\n });\n};\n\n/**\n * Format only files that differ from the specified base branch or commit\n *\n * @param base - Base branch name or commit hash to compare against (defaults to\n * 'main')\n * @param options - Options for formatting\n * @param options.includeUntracked - Include untracked files in addition to diff\n * files (default is true)\n * @param options.includeStaged - Include staged files in addition to diff files\n * (default is true)\n * @param options.silent - Silent mode to suppress command output (default is\n * false)\n */\nexport const formatDiffFrom = async (\n base: string,\n options?: Readonly<{\n includeUntracked?: boolean;\n includeModified?: boolean;\n includeStaged?: boolean;\n silent?: boolean;\n ignoreUnknown?: boolean;\n ignore?: false | ((filePath: string) => boolean);\n /**\n * If provided, only files within this directory will be formatted.\n * Relative paths are resolved against `process.cwd()`. Defaults to\n * undefined (no filtering; all changed files in the repository are\n * formatted).\n */\n cwd?: string;\n }>,\n): Promise<\n Result<\n undefined,\n | ExecException\n | Readonly<{\n message: string;\n }>\n | readonly unknown[]\n >\n> => {\n // const silent = options?.silent ?? false;\n const {\n silent = false,\n includeUntracked = true,\n includeModified = true,\n includeStaged = true,\n ignoreUnknown = true,\n ignore,\n cwd,\n } = options ?? {};\n\n const conditionalEcho = silent ? () => {} : console.info;\n\n // Get files that differ from base branch/commit (excluding deleted files)\n const diffFromBaseResult = await getDiffFrom(base, {\n silent,\n });\n\n if (Result.isErr(diffFromBaseResult)) {\n if (!silent) {\n console.error('Error getting changed files:', diffFromBaseResult.value);\n }\n\n return diffFromBaseResult;\n }\n\n const diffFiles = diffFromBaseResult.value;\n\n const mut_allFiles: string[] = diffFiles.slice();\n\n // If includeUntracked is true, also get untracked files\n for (const { type, flag, fn } of [\n { type: 'untracked', flag: includeUntracked, fn: getUntrackedFiles },\n { type: 'modified', flag: includeModified, fn: getModifiedFiles },\n { type: 'staged', flag: includeStaged, fn: getStagedFiles },\n ]) {\n if (!flag) {\n continue;\n }\n\n // eslint-disable-next-line no-await-in-loop\n const filesResult = await fn({ silent });\n\n if (Result.isErr(filesResult)) {\n if (!silent) {\n console.error(`Error getting ${type} files:`, filesResult.value);\n }\n\n return filesResult;\n }\n\n const files = filesResult.value;\n\n // Combine and deduplicate files\n mut_allFiles.push(...files);\n }\n\n const allFiles = filterFilesByCwd(Arr.uniq(mut_allFiles), cwd);\n\n if (!silent) {\n const includedFileTypes = [\n includeUntracked ? 'untracked files' : undefined,\n includeModified ? 'modified files' : undefined,\n includeStaged ? 'staged files' : undefined,\n ].filter(isNotUndefined);\n\n const message = [\n `Formatting files that differ from ${base}`,\n includedFileTypes\n .map((s, i) =>\n i !== includedFileTypes.length - 1 ? `, ${s}` : ` and ${s}`,\n )\n .join(''),\n ].join('');\n\n conditionalEcho(`${message}:`, allFiles);\n }\n\n if (Arr.isEmpty(allFiles)) {\n conditionalEcho('No files to format');\n\n return Result.ok(undefined);\n }\n\n return formatFiles(allFiles, {\n silent,\n ignoreUnknown,\n ignore,\n });\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,23 @@ export type GenIndexConfig = DeepReadonly<{
|
|
|
26
26
|
silent?: boolean;
|
|
27
27
|
/** Minimum depth to start generating index files (default: 0) */
|
|
28
28
|
minDepth?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Glob patterns of index files to leave untouched, matched against the
|
|
31
|
+
* index file's own path relative to the target directory (POSIX
|
|
32
|
+
* separators), e.g. `'index.mts'` for the one at the root of the walk and
|
|
33
|
+
* `'v*\/index.mts'` for a whole generation of them.
|
|
34
|
+
*
|
|
35
|
+
* This is what protects a hand-written index file — an executable entry
|
|
36
|
+
* point, or a curated list of named re-exports — from being overwritten
|
|
37
|
+
* with a barrel. `exclude` cannot express it: it says what an index file
|
|
38
|
+
* may not *export*, and is matched against a bare file name as well as a
|
|
39
|
+
* relative path, so `'index.mts'` there would name every index file in the
|
|
40
|
+
* tree rather than one of them.
|
|
41
|
+
*
|
|
42
|
+
* A preserved directory is still walked, so index files below it are still
|
|
43
|
+
* generated, and its parent still re-exports it. (default: none)
|
|
44
|
+
*/
|
|
45
|
+
preserve?: string[];
|
|
29
46
|
}>;
|
|
30
47
|
/**
|
|
31
48
|
* Generates index.ts files recursively in `config.targetDirectory`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gen-index.d.mts","sourceRoot":"","sources":["../../src/functions/gen-index.mts"],"names":[],"mappings":"AAGA,OAAO,EAML,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAIvB,+CAA+C;AAC/C,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC;IACxC,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEnC;;;;OAIG;IACH,OAAO,CAAC,EACJ,MAAM,EAAE,GACR,CAAC,CACC,IAAI,EAAE,QAAQ,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,KACC,OAAO,CAAC,CAAC;IAElB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,IAAI,MAAM,EAAE,EAAE,CAAC;IAElC,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;IAElC,kEAAkE;IAClE,wBAAwB,CAAC,EAAE,IAAI,MAAM,EAAE,GAAG,MAAM,CAAC;IAEjD,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"gen-index.d.mts","sourceRoot":"","sources":["../../src/functions/gen-index.mts"],"names":[],"mappings":"AAGA,OAAO,EAML,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAIvB,+CAA+C;AAC/C,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC;IACxC,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEnC;;;;OAIG;IACH,OAAO,CAAC,EACJ,MAAM,EAAE,GACR,CAAC,CACC,IAAI,EAAE,QAAQ,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,KACC,OAAO,CAAC,CAAC;IAElB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,IAAI,MAAM,EAAE,EAAE,CAAC;IAElC,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;IAElC,kEAAkE;IAClE,wBAAwB,CAAC,EAAE,IAAI,MAAM,EAAE,GAAG,MAAM,CAAC;IAEjD,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC,CAAC;AAgCH;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,WACX,cAAc,KACrB,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CA0DpC,CAAC"}
|