watskeburt 3.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -2,21 +2,6 @@
2
2
 
3
3
  Get changed files & their statuses since any git _revision_
4
4
 
5
- ## what's this do?
6
-
7
- A micro-lib to retrieve an array of file names that were changed since a
8
- revision. Also sports a cli for use outside of JavaScript c.s.
9
-
10
- ## why?
11
-
12
- I needed something simple and robust to support some upcoming features in
13
- [dependency-cruiser](https://github.com/sverweij/dependency-cruiser) and to
14
- run standalone to use _in combination_ with dependency-cruiser.
15
-
16
- There are a few specialized packages like this on npm, but it seems they've
17
- fallen out of maintenance. More generic packages are still maintained,
18
- but for just this simple usage they're a bit overkill.
19
-
20
5
  ## :construction_worker: usage
21
6
 
22
7
  ### :scroll: API
@@ -30,20 +15,23 @@ console.log(await getSHA());
30
15
  // list all files that differ between 'main' and the current revision (including
31
16
  // files not staged for commit and files not under revision control)
32
17
  /** @type {import('watskeburt').IChange[]} */
33
- const lChangedFiles = await list("main");
18
+ const lChangedFiles = await list({ oldRevision: "main" });
34
19
 
35
20
  // list all files that differ between 'v0.6.1' and 'v0.7.1' (by definition
36
21
  // won't include files staged for commit and/ or not under revision control)
37
22
  /** @type {import('watskeburt').IChange[]} */
38
- const lChangedFiles = await list("v0.6.1", "v0.7.1");
23
+ const lChangedFiles = await list({
24
+ oldRevision: "v0.6.1",
25
+ newRevision: "v0.7.1",
26
+ });
39
27
 
28
+ // list all files that differ between 'main' and the current revision
29
+ // (excluding files not staged for commit)
40
30
  /** @type {import('watskeburt').IChange[]|string} */
41
31
  const lChangedFiles = await list({
42
32
  oldRevision: "main",
43
- // this compares the working tree with the oldRevision. If you want to compare
44
- // to another branch or revision you can pass that in a `newRevision` field
45
33
  trackedOnly: false, // when set to true leaves out files not under revision control
46
- outputType: "object", // other options: "json" and "regex" (as used in the CLI)
34
+ outputType: "json", // options: "object", "json" and "regex"
47
35
  });
48
36
  ```
49
37
 
@@ -53,23 +41,23 @@ The array of changes this returns looks like this:
53
41
  [
54
42
  {
55
43
  name: "doc/cli.md",
56
- changeType: "modified",
44
+ type: "modified",
57
45
  },
58
46
  {
59
47
  name: "test/thing.spec.mjs",
60
- changeType: "renamed",
48
+ type: "renamed",
61
49
  oldName: "test/old-thing.spec.mjs",
62
50
  },
63
51
  {
64
52
  name: "src/not-tracked-yet.mjs",
65
- changeType: "untracked",
53
+ type: "untracked",
66
54
  },
67
55
  ];
68
56
  ```
69
57
 
70
58
  ### :shell: cli
71
59
 
72
- There's also a simple command line interface (which works from node >=18.11).
60
+ Works with node >=18.11
73
61
 
74
62
  ```shell
75
63
  # list all JavaScript-ish files changed since main in a regular expression
@@ -77,19 +65,18 @@ $ npx watskeburt main
77
65
  ^(src/cli[.]mjs|src/formatters/regex[.]mjs|src/version[.]mjs)$
78
66
  ```
79
67
 
80
- By default this returns a regex that contains all changed files that could be
81
- source files in the JavaScript ecosystem (.js, .mjs, .ts, .tsx ...) that can
82
- be used in e.g. the `--focus` and `--reaches` filters of dependency-cruiser.
68
+ This emits a regex that contains all changed files that could be
69
+ source files in the JavaScript ecosystem (.js, .mjs, .ts, .tsx ...). It can
70
+ be used in e.g. dependency-cruiser's `--focus` and `--reaches` filters.
83
71
 
84
- The JSON output (which looks a lot like the array above) is unfiltered and
85
- also contains other extensions.
72
+ The JSON output (= the array above, serialized) also contains other extensions.
86
73
 
87
74
  ```
88
75
  Usage: watskeburt [options] [old-revision] [new-revision]
89
76
 
90
77
  lists files & their statuses since [old-revision] or between [old-revision] and [new-revision].
91
78
 
92
- -> When you don't pass a revision at all old-revision defaults to the current one.
79
+ -> When you don't pass a revision old-revision defaults to the current one.
93
80
 
94
81
  Options:
95
82
  -T, --outputType <type> what format to emit (choices: "json", "regex", default: "regex")
@@ -98,11 +85,19 @@ Options:
98
85
  -h, --help display help for command
99
86
  ```
100
87
 
88
+ ## why?
89
+
90
+ I needed something robust to support caching in
91
+ [dependency-cruiser](https://github.com/sverweij/dependency-cruiser) and to
92
+ run standalone to use _in combination_ with dependency-cruiser.
93
+
94
+ A few specialized packages like this existed, but they had fallen out of
95
+ maintenance. More generic packages still were maintained, but for my use
96
+ case they were overkill.
97
+
101
98
  ## 🇳🇱 what does 'watskeburt' mean?
102
99
 
103
100
  Wazzup.
104
101
 
105
102
  _watskeburt_ is a fast pronunciation of the Dutch "wat is er gebeurd?"
106
- (_what has happened?_) or "wat er is gebeurd" (_what has happened_). It's
107
- also the title of a song by the Dutch band "De Jeugd van Tegenwoordig"
108
- (_Youth these days_).
103
+ (_what has happened?_) or "wat er is gebeurd" (_what has happened_).
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ const HELP_MESSAGE = `Usage: watskeburt [options] [old-revision] [new-revision]
6
6
 
7
7
  lists files & their statuses since [old-revision] or between [old-revision] and [new-revision].
8
8
 
9
- -> When you don't pass a revision at all old-revision defaults to the current one.
9
+ -> When you don't pass a revision old-revision defaults to the current one.
10
10
 
11
11
  Options:
12
12
  -T, --outputType <type> what format to emit (choices: "json", "regex", default: "regex")
@@ -0,0 +1,9 @@
1
+ import formatAsRegex from "./regex.js";
2
+ import formatAsJSON from "./json.js";
3
+ const OUTPUT_TYPE_TO_FUNCTION = new Map([
4
+ ["regex", formatAsRegex],
5
+ ["json", formatAsJSON],
6
+ ]);
7
+ export function format(pChanges, pOutputType) {
8
+ return OUTPUT_TYPE_TO_FUNCTION.get(pOutputType)(pChanges);
9
+ }
@@ -1,4 +1,4 @@
1
1
  const INDENT = 2;
2
- export default function formatToJSON(pChanges) {
2
+ export default function formatAsJSON(pChanges) {
3
3
  return JSON.stringify(pChanges, null, INDENT);
4
4
  }
@@ -25,7 +25,7 @@ const DEFAULT_CHANGE_TYPES = new Set([
25
25
  "copied",
26
26
  "untracked",
27
27
  ]);
28
- export default function formatToRegex(
28
+ export default function formatAsRegex(
29
29
  pChanges,
30
30
  pExtensions = DEFAULT_EXTENSIONS,
31
31
  pChangeTypes = DEFAULT_CHANGE_TYPES,
@@ -33,7 +33,7 @@ export default function formatToRegex(
33
33
  const lChanges = pChanges
34
34
  .filter(
35
35
  (pChange) =>
36
- pChangeTypes.has(pChange.changeType) &&
36
+ pChangeTypes.has(pChange.type) &&
37
37
  pExtensions.has(extname(pChange.name)),
38
38
  )
39
39
  .map(({ name }) => name.replace(/\\/g, "\\\\").replace(/\./g, "[.]"))
package/dist/main.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { parseDiffLines } from "./parse-diff-lines.js";
2
2
  import { parseStatusLines } from "./parse-status-lines.js";
3
3
  import * as primitives from "./git-primitives.js";
4
- import format from "./formatters/format.js";
5
4
  export async function list(pOptions) {
6
5
  const lOldRevision = pOptions?.oldRevision || (await primitives.getSHA());
7
6
  const lOptions = pOptions || {};
@@ -13,10 +12,14 @@ export async function list(pOptions) {
13
12
  if (!lOptions.trackedOnly) {
14
13
  lChanges = lChanges.concat(
15
14
  parseStatusLines(lStatusLines).filter(
16
- ({ changeType }) => changeType === "untracked",
15
+ ({ type: changeType }) => changeType === "untracked",
17
16
  ),
18
17
  );
19
18
  }
19
+ if (!lOptions.outputType) {
20
+ return lChanges;
21
+ }
22
+ const { format } = await import("./format/format.js");
20
23
  return format(lChanges, lOptions.outputType);
21
24
  }
22
25
  export function getSHA() {
@@ -1,21 +1,19 @@
1
1
  import { EOL } from "node:os";
2
2
  import { changeChar2ChangeType } from "./map-change-type.js";
3
3
  const DIFF_NAME_STATUS_LINE_PATTERN =
4
- /^(?<changeType>[ACDMRTUXB])(?<similarity>[0-9]{3})?[ \t]+(?<name>[^ \t]+)[ \t]*(?<newName>[^ \t]+)?$/;
4
+ /^(?<type>[ACDMRTUXB])(?<similarity>[0-9]{3})?[ \t]+(?<name>[^ \t]+)[ \t]*(?<newName>[^ \t]+)?$/;
5
5
  export function parseDiffLines(pString) {
6
6
  return pString
7
7
  .split(EOL)
8
8
  .filter(Boolean)
9
9
  .map(parseDiffLine)
10
- .filter(({ name, changeType }) => Boolean(name) && Boolean(changeType));
10
+ .filter(({ name, type }) => Boolean(name) && Boolean(type));
11
11
  }
12
12
  export function parseDiffLine(pString) {
13
13
  const lMatchResult = pString.match(DIFF_NAME_STATUS_LINE_PATTERN);
14
14
  const lReturnValue = {};
15
15
  if (lMatchResult?.groups) {
16
- lReturnValue.changeType = changeChar2ChangeType(
17
- lMatchResult.groups.changeType,
18
- );
16
+ lReturnValue.type = changeChar2ChangeType(lMatchResult.groups.type);
19
17
  if (lMatchResult.groups.newName) {
20
18
  lReturnValue.name = lMatchResult.groups.newName;
21
19
  lReturnValue.oldName = lMatchResult.groups.name;
@@ -1,28 +1,24 @@
1
1
  import { EOL } from "node:os";
2
2
  import { changeChar2ChangeType } from "./map-change-type.js";
3
3
  const DIFF_SHORT_STATUS_LINE_PATTERN =
4
- /^(?<stagedChangeType>[ ACDMRTUXB?!])(?<unStagedChangeType>[ ACDMRTUXB?!])[ \t]+(?<name>[^ \t]+)(( -> )(?<newName>[^ \t]+))?$/;
4
+ /^(?<stagedType>[ ACDMRTUXB?!])(?<unStagedType>[ ACDMRTUXB?!])[ \t]+(?<name>[^ \t]+)(( -> )(?<newName>[^ \t]+))?$/;
5
5
  export function parseStatusLines(pString) {
6
6
  return pString
7
7
  .split(EOL)
8
8
  .filter(Boolean)
9
9
  .map(parseStatusLine)
10
- .filter(({ name, changeType }) => Boolean(name) && Boolean(changeType));
10
+ .filter(({ name, type }) => Boolean(name) && Boolean(type));
11
11
  }
12
12
  export function parseStatusLine(pString) {
13
13
  const lMatchResult = pString.match(DIFF_SHORT_STATUS_LINE_PATTERN);
14
14
  const lReturnValue = {};
15
15
  if (lMatchResult?.groups) {
16
- const lStagedChangeType = changeChar2ChangeType(
17
- lMatchResult.groups.stagedChangeType,
16
+ const lStagedType = changeChar2ChangeType(lMatchResult.groups.stagedType);
17
+ const lUnStagedType = changeChar2ChangeType(
18
+ lMatchResult.groups.unStagedType,
18
19
  );
19
- const lUnStagedChangeType = changeChar2ChangeType(
20
- lMatchResult.groups.unStagedChangeType,
21
- );
22
- lReturnValue.changeType =
23
- lStagedChangeType === "unmodified"
24
- ? lUnStagedChangeType
25
- : lStagedChangeType;
20
+ lReturnValue.type =
21
+ lStagedType === "unmodified" ? lUnStagedType : lStagedType;
26
22
  if (lMatchResult.groups.newName) {
27
23
  lReturnValue.name = lMatchResult.groups.newName;
28
24
  lReturnValue.oldName = lMatchResult.groups.name;
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "3.0.0";
1
+ export const VERSION = "4.0.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "watskeburt",
3
- "version": "3.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "List files changed since a git revision",
5
5
  "keywords": [
6
6
  "git",
@@ -1,4 +1,4 @@
1
- export type changeTypeType =
1
+ export type changeType =
2
2
  | "added"
3
3
  | "copied"
4
4
  | "deleted"
@@ -20,63 +20,59 @@ export interface IChange {
20
20
  /**
21
21
  * how the file was changed
22
22
  */
23
- changeType: changeTypeType;
23
+ type: changeType;
24
24
  /**
25
25
  * if the file was renamed: what the old file's name was
26
26
  */
27
27
  oldName?: string;
28
28
  }
29
29
 
30
- export type outputTypeType = "regex" | "json" | "object";
30
+ export type outputTypeType = "regex" | "json";
31
31
 
32
32
  export interface IBaseOptions {
33
33
  /**
34
- * The revision against which to compare. E.g. a commit-hash,
35
- * a branch or a tag. When not passed defaults to the _current_
36
- * commit hash (if there's any)
34
+ * The revision against which to compare. When not passed defaults to the
35
+ * _current_ commit hash (if there's any)
37
36
  */
38
37
  oldRevision?: string;
39
38
  /**
40
- * Newer revision against which to compare. Leave out or pass
41
- * null when you want to compare against the working tree
39
+ * Newer revision against which to compare. Leave out when you want to
40
+ * compare against the working tree
42
41
  */
43
42
  newRevision?: string;
44
43
  /**
45
- * When true _only_ takes already tracked files into account.
46
- * When false also takes untracked files into account.
47
- *
48
- * Defaults to false.
44
+ * When true only takes already tracked files into account.
45
+ * When false also takes untracked files into account (default)
49
46
  */
50
47
  trackedOnly?: boolean;
51
48
  }
52
49
 
53
50
  export interface IFormatOptions extends IBaseOptions {
54
51
  /**
55
- * The type of output to deliver. Defaults to "object" - in which case
56
- * the listSync function returns an IChange[] object
52
+ * The type of output to deliver.
57
53
  */
58
54
  outputType: "regex" | "json";
59
55
  }
60
56
 
61
57
  export interface IInternalOptions extends IBaseOptions {
62
58
  /**
63
- * The type of output to deliver. Defaults to "object" - in which case
64
- * the listSync function returns an IChange[] object
59
+ * The type of output to deliver. undefined/ left out
60
+ * the outputType defaults to a list of `IChange`s
65
61
  */
66
- outputType?: "object";
62
+ outputType?: undefined;
67
63
  }
68
64
 
69
65
  export type IOptions = IFormatOptions | IInternalOptions;
70
66
 
71
67
  /**
72
- * returns a promise of a list of files changed since pOldRevision.
68
+ * promises a list of files changed since pOldRevision.
73
69
  *
74
70
  * @throws {Error}
75
71
  */
76
72
  export function list(pOptions?: IInternalOptions): Promise<IChange[]>;
77
73
 
78
74
  /**
79
- * returns a promise of a list of files changed since pOldRevision, formatted
75
+ * promises a list of files changed since pOldRevision, formatted
80
76
  * into a string as a pOptions.outputType
81
77
  *
82
78
  * @throws {Error}
@@ -84,7 +80,7 @@ export function list(pOptions?: IInternalOptions): Promise<IChange[]>;
84
80
  export function list(pOptions?: IFormatOptions): Promise<string>;
85
81
 
86
82
  /**
87
- * Returns the SHA1 of the current HEAD
83
+ * Promises the SHA1 of the current HEAD
88
84
  *
89
85
  * @throws {Error}
90
86
  */
@@ -1,12 +0,0 @@
1
- import formatToRegex from "./regex.js";
2
- import formatToJSON from "./json.js";
3
- const identity = (pX) => pX;
4
- const OUTPUT_TYPE_TO_FUNCTION = new Map([
5
- ["regex", formatToRegex],
6
- ["json", formatToJSON],
7
- ]);
8
- export default function format(pChanges, pOutputType) {
9
- return (OUTPUT_TYPE_TO_FUNCTION.get(pOutputType ?? "unknown") || identity)(
10
- pChanges,
11
- );
12
- }