@zukhruf/git-hooks 0.0.0-stage → 0.3.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +258 -2
  3. package/dist/build.d.ts +15 -0
  4. package/dist/build.d.ts.map +1 -0
  5. package/dist/build.js +163 -0
  6. package/dist/build.js.map +1 -0
  7. package/dist/codegen.d.ts +15 -0
  8. package/dist/codegen.d.ts.map +1 -0
  9. package/dist/codegen.js +38 -0
  10. package/dist/codegen.js.map +1 -0
  11. package/dist/commit.d.ts +15 -0
  12. package/dist/commit.d.ts.map +1 -0
  13. package/dist/commit.js +96 -0
  14. package/dist/commit.js.map +1 -0
  15. package/dist/format.d.ts +7 -0
  16. package/dist/format.d.ts.map +1 -0
  17. package/dist/format.js +44 -0
  18. package/dist/format.js.map +1 -0
  19. package/dist/index.d.ts +11 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +10 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/push.d.ts +29 -0
  24. package/dist/push.d.ts.map +1 -0
  25. package/dist/push.js +108 -0
  26. package/dist/push.js.map +1 -0
  27. package/dist/ref-update.d.ts +17 -0
  28. package/dist/ref-update.d.ts.map +1 -0
  29. package/dist/ref-update.js +43 -0
  30. package/dist/ref-update.js.map +1 -0
  31. package/dist/scripts/pre-commit.d.ts +4 -0
  32. package/dist/scripts/pre-commit.d.ts.map +1 -0
  33. package/dist/scripts/pre-commit.js +20 -0
  34. package/dist/scripts/pre-commit.js.map +1 -0
  35. package/dist/scripts/pre-push.d.ts +4 -0
  36. package/dist/scripts/pre-push.d.ts.map +1 -0
  37. package/dist/scripts/pre-push.js +35 -0
  38. package/dist/scripts/pre-push.js.map +1 -0
  39. package/dist/snapshot/commit-files.d.ts +5 -0
  40. package/dist/snapshot/commit-files.d.ts.map +1 -0
  41. package/dist/snapshot/commit-files.js +101 -0
  42. package/dist/snapshot/commit-files.js.map +1 -0
  43. package/dist/snapshot/drift.d.ts +3 -0
  44. package/dist/snapshot/drift.d.ts.map +1 -0
  45. package/dist/snapshot/drift.js +72 -0
  46. package/dist/snapshot/drift.js.map +1 -0
  47. package/dist/snapshot/installs.d.ts +2 -0
  48. package/dist/snapshot/installs.d.ts.map +1 -0
  49. package/dist/snapshot/installs.js +83 -0
  50. package/dist/snapshot/installs.js.map +1 -0
  51. package/dist/snapshot/nx.d.ts +7 -0
  52. package/dist/snapshot/nx.d.ts.map +1 -0
  53. package/dist/snapshot/nx.js +20 -0
  54. package/dist/snapshot/nx.js.map +1 -0
  55. package/dist/snapshot/packages.d.ts +2 -0
  56. package/dist/snapshot/packages.d.ts.map +1 -0
  57. package/dist/snapshot/packages.js +72 -0
  58. package/dist/snapshot/packages.js.map +1 -0
  59. package/dist/snapshot/workspaces.d.ts +2 -0
  60. package/dist/snapshot/workspaces.d.ts.map +1 -0
  61. package/dist/snapshot/workspaces.js +26 -0
  62. package/dist/snapshot/workspaces.js.map +1 -0
  63. package/dist/step.d.ts +12 -0
  64. package/dist/step.d.ts.map +1 -0
  65. package/dist/step.js +15 -0
  66. package/dist/step.js.map +1 -0
  67. package/dist/sync.d.ts +11 -0
  68. package/dist/sync.d.ts.map +1 -0
  69. package/dist/sync.js +38 -0
  70. package/dist/sync.js.map +1 -0
  71. package/package.json +58 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit-files.js","sourceRoot":"","sources":["../../src/snapshot/commit-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASnD,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAA2C,EAC3C,UAAmD,EACnD,GAAW,EACX,MAAc;IAEd,MAAM,KAAK,GAAW,CAAC,MAAM,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;SACzE,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;SAC7B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1E,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;IAC3D,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAEzC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;QACpD,GAAG,UAAU;QACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;KACnC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;YACjD,MAAM,IAAI,KAAK,CACb,sBAAsB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,CAC3D,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YACxB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;aAChE,CAAC;YACJ,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YACjD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,MAAM,MAAM,CAAC;IACb,uEAAuE;IACvE,uEAAuE;IACvE,gDAAgD;IAChD,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAAE,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;aACzD,CAAC;YACJ,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAC9B,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;YACF,IAAI,QAAQ;gBAAE,MAAM,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;;gBACnD,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,yBAAyB;AACzB,MAAM,OAAO;IACF,OAAO,CAAwB;IACxC,OAAO,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAElC,YAAY,MAAgB;QAC1B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACjE,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAa;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;YAChC,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACjC,OAAO,MAAM,GAAG,KAAK,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACzB,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClD,IAAI,IAAI,KAAK,IAAI;YACf,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export declare function hasInstallDrift(lockfile: string, hiddenLockfile: string): Promise<boolean>;
2
+ export declare function withInstallScripts(lockfile: string): Promise<string[]>;
3
+ //# sourceMappingURL=drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift.d.ts","sourceRoot":"","sources":["../../src/snapshot/drift.ts"],"names":[],"mappings":"AAcA,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAmCD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ5E"}
@@ -0,0 +1,72 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ // Whether the installed packages differ from the lockfile of a commit. npm's
3
+ // hidden lockfile, node_modules/.package-lock.json, lists what is installed.
4
+ // Each difference in the third-party packages is drift: a missing package, a
5
+ // different version, or an extra package, which would build here and fail in
6
+ // CI. Links are not compared: a workspace link points into the snapshot.
7
+ export async function hasInstallDrift(lockfile, hiddenLockfile) {
8
+ const wanted = await packagesOf(lockfile);
9
+ let installed;
10
+ try {
11
+ installed = await packagesOf(hiddenLockfile);
12
+ }
13
+ catch (error) {
14
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
15
+ return true;
16
+ throw error;
17
+ }
18
+ for (const [path, entry] of wanted) {
19
+ const have = installed.get(path);
20
+ if (have === undefined) {
21
+ // npm skips an optional package that does not fit the platform.
22
+ if (!entry.optional)
23
+ return true;
24
+ }
25
+ else if (have.version !== entry.version)
26
+ return true;
27
+ }
28
+ for (const path of installed.keys())
29
+ if (!wanted.has(path))
30
+ return true;
31
+ return false;
32
+ }
33
+ // The third-party packages of a lockfile: the entries in a node_modules
34
+ // folder that are not links.
35
+ async function packagesOf(path) {
36
+ const lockfile = JSON.parse(await readFile(path, 'utf8'));
37
+ const packages = typeof lockfile === 'object' && lockfile !== null && 'packages' in lockfile
38
+ ? lockfile.packages
39
+ : undefined;
40
+ if (typeof packages !== 'object' || packages === null)
41
+ throw new TypeError(`${path} has no "packages"; npm 7 or later writes it`);
42
+ const entries = new Map();
43
+ for (const [key, value] of Object.entries(packages)) {
44
+ if (!key.includes('node_modules/'))
45
+ continue;
46
+ const entry = {
47
+ version: field(value, 'version'),
48
+ link: field(value, 'link') === true,
49
+ optional: field(value, 'optional') === true,
50
+ hasInstallScript: field(value, 'hasInstallScript') === true,
51
+ };
52
+ if (!entry.link)
53
+ entries.set(key, entry);
54
+ }
55
+ return entries;
56
+ }
57
+ function field(value, name) {
58
+ return typeof value === 'object' && value !== null && name in value
59
+ ? Reflect.get(value, name)
60
+ : undefined;
61
+ }
62
+ // The third-party packages that the lockfile marks with an install script.
63
+ // The root and the workspace packages have the mark too, but their scripts
64
+ // must not run in the state folder.
65
+ export async function withInstallScripts(lockfile) {
66
+ const names = new Set();
67
+ for (const [key, entry] of await packagesOf(lockfile))
68
+ if (entry.hasInstallScript)
69
+ names.add(key.slice(key.lastIndexOf('node_modules/') + 'node_modules/'.length));
70
+ return [...names];
71
+ }
72
+ //# sourceMappingURL=drift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/snapshot/drift.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAS5C,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,cAAsB;IAEtB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,SAAiC,CAAC;IACtC,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YACtE,OAAO,IAAI,CAAC;QACd,MAAM,KAAK,CAAC;IACd,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,gEAAgE;YAChE,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;IACzD,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACxE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wEAAwE;AACxE,6BAA6B;AAC7B,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACnE,MAAM,QAAQ,GACZ,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,UAAU,IAAI,QAAQ;QACzE,CAAC,CAAC,QAAQ,CAAC,QAAQ;QACnB,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI;QACnD,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,8CAA8C,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,SAAS;QAC7C,MAAM,KAAK,GAAG;YACZ,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;YAChC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI;YACnC,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI;YAC3C,gBAAgB,EAAE,KAAK,CAAC,KAAK,EAAE,kBAAkB,CAAC,KAAK,IAAI;SAC5D,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,KAAK,CAAC,KAAc,EAAE,IAAY;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK;QACjE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC;QAC1B,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,2EAA2E;AAC3E,2EAA2E;AAC3E,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC;QACnD,IAAI,KAAK,CAAC,gBAAgB;YACxB,KAAK,CAAC,GAAG,CACP,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CACrE,CAAC;IACN,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function installFor(state: string, snapshot: string, environment: NodeJS.ProcessEnv, installing: () => void): Promise<string>;
2
+ //# sourceMappingURL=installs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installs.d.ts","sourceRoot":"","sources":["../../src/snapshot/installs.ts"],"names":[],"mappings":"AA8BA,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,UAAU,EAAE,MAAM,IAAI,GACrB,OAAO,CAAC,MAAM,CAAC,CAejB"}
@@ -0,0 +1,83 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { createHash } from 'node:crypto';
3
+ import { existsSync } from 'node:fs';
4
+ import { copyFile, mkdir, readFile, readdir, rm, stat, utimes, writeFile, } from 'node:fs/promises';
5
+ import { join } from 'node:path';
6
+ import { promisify } from 'node:util';
7
+ import { withInstallScripts } from "./drift.js";
8
+ import { workspaceFolders } from "./workspaces.js";
9
+ const execFileAsync = promisify(execFile);
10
+ // The installs that the hook keeps: the ones that it used last.
11
+ const kept = 2;
12
+ // Written last, so a folder without it is an install that did not end.
13
+ const marker = 'installed';
14
+ // An install of the lockfile of the snapshot in a folder of the state folder,
15
+ // named by the hash of the lockfile. A second push with the same lockfile
16
+ // uses the same install. `installing` runs before a new install, because a
17
+ // full install takes some time.
18
+ export async function installFor(state, snapshot, environment, installing) {
19
+ const lockfile = await readFile(join(snapshot, 'package-lock.json'));
20
+ const hash = createHash('sha256').update(lockfile).digest('hex');
21
+ const installs = join(state, 'installs');
22
+ const folder = join(installs, hash.slice(0, 16));
23
+ if (existsSync(join(folder, marker))) {
24
+ const now = new Date();
25
+ await utimes(join(folder, marker), now, now);
26
+ }
27
+ else {
28
+ installing();
29
+ await rm(folder, { recursive: true, force: true });
30
+ await install(snapshot, folder, environment);
31
+ }
32
+ await prune(installs);
33
+ return folder;
34
+ }
35
+ // `npm ci --ignore-scripts`, and then `npm rebuild` with only the
36
+ // third-party packages that have install scripts, such as esbuild. The
37
+ // scripts of the repo and of its workspace packages, such as `prepare`,
38
+ // would act on the repo from the state folder, so they do not run. Without
39
+ // names, `npm rebuild` runs them too.
40
+ async function install(snapshot, folder, environment) {
41
+ await mkdir(folder, { recursive: true });
42
+ for (const file of ['package.json', 'package-lock.json', '.npmrc'])
43
+ if (existsSync(join(snapshot, file)))
44
+ await copyFile(join(snapshot, file), join(folder, file));
45
+ for (const workspace of await workspaceFolders(snapshot)) {
46
+ await mkdir(join(folder, workspace), { recursive: true });
47
+ await copyFile(join(snapshot, workspace, 'package.json'), join(folder, workspace, 'package.json'));
48
+ }
49
+ await npm(folder, environment, 'ci', '--ignore-scripts', '--no-audit', '--no-fund');
50
+ const names = await withInstallScripts(join(folder, 'package-lock.json'));
51
+ if (names.length > 0)
52
+ await npm(folder, environment, 'rebuild', ...names);
53
+ await writeFile(join(folder, marker), '');
54
+ }
55
+ async function npm(cwd, environment, ...args) {
56
+ try {
57
+ await execFileAsync('npm', args, {
58
+ cwd,
59
+ env: environment,
60
+ encoding: 'utf8',
61
+ maxBuffer: 2 ** 30,
62
+ // npm is a .cmd file on Windows, which only a shell runs. The
63
+ // arguments are npm's own flags and package names, which need no quotes.
64
+ shell: process.platform === 'win32',
65
+ });
66
+ }
67
+ catch (error) {
68
+ if (!(error instanceof Error) || !('stderr' in error))
69
+ throw error;
70
+ throw new Error(`npm ${args.join(' ')} failed:\n${String(error.stderr).trimEnd()}`, { cause: error });
71
+ }
72
+ }
73
+ async function prune(installs) {
74
+ const used = await Promise.all((await readdir(installs)).map(async (name) => ({
75
+ name,
76
+ at: await stat(join(installs, name, marker)).then(({ mtimeMs }) => mtimeMs, () => -1),
77
+ })));
78
+ used.sort((left, right) => right.at - left.at);
79
+ for (const [index, { name, at }] of used.entries())
80
+ if (index >= kept || at < 0)
81
+ await rm(join(installs, name), { recursive: true, force: true });
82
+ }
83
+ //# sourceMappingURL=installs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installs.js","sourceRoot":"","sources":["../../src/snapshot/installs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface NxRun {
2
+ readonly code: number;
3
+ readonly stdout: string;
4
+ readonly stderr: string;
5
+ }
6
+ export declare function runNx(folder: string, environment: NodeJS.ProcessEnv, args: readonly string[]): Promise<NxRun>;
7
+ //# sourceMappingURL=nx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nx.d.ts","sourceRoot":"","sources":["../../src/snapshot/nx.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAID,wBAAgB,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,KAAK,CAAC,CAoBhB"}
@@ -0,0 +1,20 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { join } from 'node:path';
3
+ // Runs the nx of the snapshot's node_modules in the snapshot. On Windows,
4
+ // npm writes `.bin/nx.cmd`, which only a shell runs.
5
+ export function runNx(folder, environment, args) {
6
+ const windows = process.platform === 'win32';
7
+ return new Promise((resolve) => {
8
+ execFile(join(folder, 'node_modules/.bin', windows ? 'nx.cmd' : 'nx'), args, {
9
+ cwd: folder,
10
+ env: environment,
11
+ encoding: 'utf8',
12
+ maxBuffer: 2 ** 30,
13
+ shell: windows,
14
+ }, (error, stdout, stderr) => {
15
+ const code = error === null ? 0 : typeof error.code === 'number' ? error.code : 1;
16
+ resolve({ code, stdout, stderr });
17
+ });
18
+ });
19
+ }
20
+ //# sourceMappingURL=nx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nx.js","sourceRoot":"","sources":["../../src/snapshot/nx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,0EAA0E;AAC1E,qDAAqD;AACrD,MAAM,UAAU,KAAK,CACnB,MAAc,EACd,WAA8B,EAC9B,IAAuB;IAEvB,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CACN,IAAI,CAAC,MAAM,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAC5D,IAAI,EACJ;YACE,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,WAAW;YAChB,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,OAAO;SACf,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACxB,MAAM,IAAI,GACR,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACpC,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function linkPackages(installRoot: string, snapshot: string): Promise<void>;
2
+ //# sourceMappingURL=packages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.d.ts","sourceRoot":"","sources":["../../src/snapshot/packages.ts"],"names":[],"mappings":"AAsBA,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -0,0 +1,72 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { copyFile, lstat, mkdir, readdir, readlink, realpath, stat, symlink, } from 'node:fs/promises';
3
+ import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
+ import { workspaceFolders } from "./workspaces.js";
5
+ // Gives the snapshot a node_modules made from the install at `installRoot`
6
+ // (the repo, or an install in the state folder). Each node_modules folder is
7
+ // a real folder, so a tool that writes into node_modules (vite writes
8
+ // .vite-temp) writes into the snapshot. A workspace link points to the same
9
+ // path in the snapshot. Each other entry links to the installed entry, with
10
+ // an absolute path: a junction on Windows, which needs no administrator
11
+ // rights. Other dot entries are tool state, and are left out.
12
+ export async function linkPackages(installRoot, snapshot) {
13
+ const root = await realpath(installRoot);
14
+ if (!existsSync(join(root, 'node_modules')))
15
+ return;
16
+ // A link is read from where it really is: node_modules can be a link too.
17
+ const installed = await realpath(join(root, 'node_modules'));
18
+ await mirror(root, installed, join(snapshot, 'node_modules'), snapshot);
19
+ for (const folder of await workspaceFolders(snapshot)) {
20
+ const nested = join(root, folder, 'node_modules');
21
+ if (existsSync(nested))
22
+ await mirror(root, await realpath(nested), join(snapshot, folder, 'node_modules'), snapshot);
23
+ }
24
+ }
25
+ async function mirror(root, source, destination, snapshot) {
26
+ await mkdir(destination, { recursive: true });
27
+ for (const name of await readdir(source)) {
28
+ const entry = join(source, name);
29
+ if (name === '.bin')
30
+ await copyBin(entry, join(destination, name));
31
+ else if (name.startsWith('.'))
32
+ continue;
33
+ else if (name.startsWith('@') && (await lstat(entry)).isDirectory()) {
34
+ await mkdir(join(destination, name));
35
+ for (const scoped of await readdir(entry))
36
+ await link(root, join(entry, scoped), join(destination, name, scoped), snapshot);
37
+ }
38
+ else
39
+ await link(root, entry, join(destination, name), snapshot);
40
+ }
41
+ }
42
+ async function link(root, entry, destination, snapshot) {
43
+ const stats = await lstat(entry);
44
+ if (stats.isSymbolicLink()) {
45
+ // A workspace link points into the repo, outside node_modules. It can
46
+ // point to a folder that a build writes later, so it is read as text.
47
+ const target = resolve(dirname(entry), await readlink(entry));
48
+ const inTree = relative(root, target);
49
+ if (!inTree.startsWith('..') &&
50
+ !isAbsolute(inTree) &&
51
+ !inTree.split(sep).includes('node_modules'))
52
+ return symlink(join(snapshot, inTree), destination, 'junction');
53
+ }
54
+ const isFolder = await stat(entry).then((target) => target.isDirectory(), () => true);
55
+ if (isFolder)
56
+ return symlink(entry, destination, 'junction');
57
+ return copyFile(entry, destination);
58
+ }
59
+ // A link in .bin keeps its relative text, so `../pkg/bin/x` resolves through
60
+ // the snapshot's node_modules, and a workspace bin runs from the snapshot. A
61
+ // file, such as a Windows .cmd shim, is copied.
62
+ async function copyBin(source, destination) {
63
+ await mkdir(destination);
64
+ for (const name of await readdir(source)) {
65
+ const entry = join(source, name);
66
+ if ((await lstat(entry)).isSymbolicLink())
67
+ await symlink(await readlink(entry), join(destination, name));
68
+ else
69
+ await copyFile(entry, join(destination, name));
70
+ }
71
+ }
72
+ //# sourceMappingURL=packages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.js","sourceRoot":"","sources":["../../src/snapshot/packages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function workspaceFolders(folder: string): Promise<string[]>;
2
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/snapshot/workspaces.ts"],"names":[],"mappings":"AAKA,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BxE"}
@@ -0,0 +1,26 @@
1
+ import { glob, readFile } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ // The folders of the workspace packages that the `workspaces` field of the
4
+ // root package.json in `folder` names, relative to `folder`.
5
+ export async function workspaceFolders(folder) {
6
+ const manifest = JSON.parse(await readFile(join(folder, 'package.json'), 'utf8'));
7
+ const field = typeof manifest === 'object' &&
8
+ manifest !== null &&
9
+ 'workspaces' in manifest
10
+ ? manifest.workspaces
11
+ : [];
12
+ const patterns = typeof field === 'object' && field !== null && 'packages' in field
13
+ ? field.packages
14
+ : field;
15
+ if (!Array.isArray(patterns) ||
16
+ !patterns.every((pattern) => typeof pattern === 'string'))
17
+ return [];
18
+ const folders = new Set();
19
+ for await (const path of glob(patterns.map((pattern) => `${pattern}/package.json`), {
20
+ cwd: folder,
21
+ exclude: (path) => path.split(/[\\/]/).includes('node_modules'),
22
+ }))
23
+ folders.add(dirname(path));
24
+ return [...folders];
25
+ }
26
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../src/snapshot/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,2EAA2E;AAC3E,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAClC,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACrD,CAAC;IACF,MAAM,KAAK,GACT,OAAO,QAAQ,KAAK,QAAQ;QAC5B,QAAQ,KAAK,IAAI;QACjB,YAAY,IAAI,QAAQ;QACtB,CAAC,CAAC,QAAQ,CAAC,UAAU;QACrB,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,QAAQ,GACZ,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU,IAAI,KAAK;QAChE,CAAC,CAAC,KAAK,CAAC,QAAQ;QAChB,CAAC,CAAC,KAAK,CAAC;IACZ,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QACxB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC;QAEzD,OAAO,EAAE,CAAC;IACZ,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAC3B,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,eAAe,CAAC,EACpD;QACE,GAAG,EAAE,MAAM;QACX,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;KAChE,CACF;QACC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACtB,CAAC"}
package/dist/step.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export interface Outcome {
2
+ readonly kind: 'pass' | 'skip' | 'fail';
3
+ readonly message: string;
4
+ }
5
+ export declare abstract class Step<Subject> {
6
+ abstract readonly name: string;
7
+ abstract run(subject: Subject): Promise<Outcome>;
8
+ protected pass(message?: string): Outcome;
9
+ protected skip(message: string): Outcome;
10
+ protected fail(message: string): Outcome;
11
+ }
12
+ //# sourceMappingURL=step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAKD,8BAAsB,IAAI,CAAC,OAAO;IAChC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAE/B,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhD,SAAS,CAAC,IAAI,CAAC,OAAO,SAAK,GAAG,OAAO;IAIrC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIxC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAGzC"}
package/dist/step.js ADDED
@@ -0,0 +1,15 @@
1
+ // One check or task of a hook. A subclass names itself and says what it does
2
+ // with its subject: the staged commit for a pre-commit step, the push for a
3
+ // pre-push step. The hook runs the steps in order and stops at the first fail.
4
+ export class Step {
5
+ pass(message = '') {
6
+ return { kind: 'pass', message };
7
+ }
8
+ skip(message) {
9
+ return { kind: 'skip', message };
10
+ }
11
+ fail(message) {
12
+ return { kind: 'fail', message };
13
+ }
14
+ }
15
+ //# sourceMappingURL=step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.js","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"AAOA,6EAA6E;AAC7E,4EAA4E;AAC5E,+EAA+E;AAC/E,MAAM,OAAgB,IAAI;IAKd,IAAI,CAAC,OAAO,GAAG,EAAE;QACzB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACnC,CAAC;IAES,IAAI,CAAC,OAAe;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACnC,CAAC;IAES,IAAI,CAAC,OAAe;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACnC,CAAC;CACF"}
package/dist/sync.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { Commit } from './commit.ts';
2
+ import { type Outcome, Step } from './step.ts';
3
+ export declare class Sync extends Step<Commit> {
4
+ #private;
5
+ readonly name = "sync";
6
+ constructor({ stage, }?: {
7
+ stage?: readonly string[];
8
+ });
9
+ run(commit: Commit): Promise<Outcome>;
10
+ }
11
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAU/C,qBAAa,IAAK,SAAQ,IAAI,CAAC,MAAM,CAAC;;IACpC,QAAQ,CAAC,IAAI,UAAU;gBAGX,EACV,KAA6B,GAC9B,GAAE;QAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;IAK/B,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAmB5C"}
package/dist/sync.js ADDED
@@ -0,0 +1,38 @@
1
+ import { matchesGlob } from 'node:path';
2
+ import { Step } from "./step.js";
3
+ // Runs `nx sync`, then stages the files that it wrote. `sync.applyChanges`
4
+ // in nx.json applies only in an interactive terminal, so a commit from a GUI
5
+ // client or an agent shell would miss the synced files.
6
+ //
7
+ // A file counts as synced when it changed during the run and matches `stage`:
8
+ // the file names that the repo's sync generators write. Any other change
9
+ // during the run, or a file that was already modified before it, belongs to
10
+ // another session that edits the same working tree.
11
+ export class Sync extends Step {
12
+ name = 'sync';
13
+ #globs;
14
+ constructor({ stage = ['**/tsconfig*.json'], } = {}) {
15
+ super();
16
+ this.#globs = stage;
17
+ }
18
+ async run(commit) {
19
+ const before = new Set(await commit.modified());
20
+ try {
21
+ await commit.nx('sync');
22
+ }
23
+ catch (error) {
24
+ // A failed sync is the step's outcome: the author reads nx's reason, not
25
+ // a stack trace of the hook.
26
+ if (!(error instanceof Error))
27
+ throw error;
28
+ return this.fail(error.message.trimEnd());
29
+ }
30
+ const synced = (await commit.modified()).filter((path) => !before.has(path) &&
31
+ this.#globs.some((glob) => matchesGlob(path, glob)));
32
+ if (synced.length === 0)
33
+ return this.pass('nx sync wrote nothing to stage');
34
+ await commit.stage(synced);
35
+ return this.pass(`staged what nx sync wrote: ${synced.join(', ')}`);
36
+ }
37
+ }
38
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAgB,IAAI,EAAE,MAAM,WAAW,CAAC;AAE/C,2EAA2E;AAC3E,6EAA6E;AAC7E,wDAAwD;AACxD,EAAE;AACF,8EAA8E;AAC9E,yEAAyE;AACzE,4EAA4E;AAC5E,oDAAoD;AACpD,MAAM,OAAO,IAAK,SAAQ,IAAY;IAC3B,IAAI,GAAG,MAAM,CAAC;IACd,MAAM,CAAoB;IAEnC,YAAY,EACV,KAAK,GAAG,CAAC,mBAAmB,CAAC,MACI,EAAE;QACnC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAc;QACtB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yEAAyE;YACzE,6BAA6B;YAC7B,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAC7C,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CACtD,CAAC;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC5E,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,60 @@
1
1
  {
2
2
  "name": "@zukhruf/git-hooks",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.42",
4
+ "description": "Git hooks written in TypeScript. A pre-commit hook runs steps in order against the staged commit: it checks the staged copy of each file with Prettier and changes nothing, runs nx sync and stages only the files that sync wrote, and builds generated files when nx says their projects are affected. A repo adds a step of its own as a class.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/JanuaryLabs/zukhruf",
9
+ "directory": "packages/git-hooks"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/JanuaryLabs/zukhruf/issues"
13
+ },
14
+ "homepage": "https://github.com/JanuaryLabs/zukhruf/tree/main/packages/git-hooks#readme",
15
+ "keywords": [
16
+ "git",
17
+ "hooks",
18
+ "pre-commit",
19
+ "prettier",
20
+ "staged",
21
+ "index",
22
+ "nx",
23
+ "sync",
24
+ "codegen"
25
+ ],
26
+ "type": "module",
27
+ "exports": {
28
+ "./package.json": "./package.json",
29
+ ".": {
30
+ "@zukhruf/source": "./src/index.ts",
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "!dist/spec/**",
39
+ "!**/*.tsbuildinfo",
40
+ "!**/*.test.*"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "dependencies": {
46
+ "@zukhruf/fs": "^0.3.42"
47
+ },
48
+ "peerDependencies": {
49
+ "nx": ">=21.0.0",
50
+ "prettier": "^3.0.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "nx": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "devDependencies": {
58
+ "prettier": "^3.9.9"
59
+ }
60
+ }