@design.estate/wcctools 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/changelog.md +13 -0
  2. package/dist_shell/bundle.js +3 -3
  3. package/dist_shell/bundle.js.map +1 -1
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/cli.js +8 -2
  6. package/dist_ts/plugins.d.ts +7 -2
  7. package/dist_ts/plugins.js +9 -3
  8. package/dist_ts/standards/baselines.d.ts +27 -0
  9. package/dist_ts/standards/baselines.js +83 -0
  10. package/dist_ts/standards/checker.d.ts +21 -0
  11. package/dist_ts/standards/checker.js +88 -0
  12. package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
  13. package/dist_ts/standards/classes.gitrepo.js +43 -0
  14. package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
  15. package/dist_ts/standards/classes.sourceedits.js +54 -0
  16. package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
  17. package/dist_ts/standards/classes.standardfixer.js +210 -0
  18. package/dist_ts/standards/classes.standardproject.d.ts +80 -0
  19. package/dist_ts/standards/classes.standardproject.js +195 -0
  20. package/dist_ts/standards/classes.standardtree.d.ts +56 -0
  21. package/dist_ts/standards/classes.standardtree.js +207 -0
  22. package/dist_ts/standards/cli.d.ts +7 -0
  23. package/dist_ts/standards/cli.js +89 -0
  24. package/dist_ts/standards/config.d.ts +33 -0
  25. package/dist_ts/standards/config.js +139 -0
  26. package/dist_ts/standards/errors.d.ts +9 -0
  27. package/dist_ts/standards/errors.js +17 -0
  28. package/dist_ts/standards/helpers.ast.d.ts +56 -0
  29. package/dist_ts/standards/helpers.ast.js +172 -0
  30. package/dist_ts/standards/helpers.paths.d.ts +36 -0
  31. package/dist_ts/standards/helpers.paths.js +86 -0
  32. package/dist_ts/standards/index.d.ts +14 -0
  33. package/dist_ts/standards/index.js +15 -0
  34. package/dist_ts/standards/output.d.ts +7 -0
  35. package/dist_ts/standards/output.js +57 -0
  36. package/dist_ts/standards/ratchet.d.ts +15 -0
  37. package/dist_ts/standards/ratchet.js +45 -0
  38. package/dist_ts/standards/rule.d.ts +50 -0
  39. package/dist_ts/standards/rule.js +9 -0
  40. package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
  41. package/dist_ts/standards/rules/barrel.element-index.js +108 -0
  42. package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
  43. package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
  44. package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
  45. package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
  46. package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
  47. package/dist_ts/standards/rules/demo.groups.js +72 -0
  48. package/dist_ts/standards/rules/demo.required.d.ts +3 -0
  49. package/dist_ts/standards/rules/demo.required.js +48 -0
  50. package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
  51. package/dist_ts/standards/rules/demo.separate-file.js +38 -0
  52. package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
  53. package/dist_ts/standards/rules/demo.shape.js +38 -0
  54. package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
  55. package/dist_ts/standards/rules/docs.component-index.js +84 -0
  56. package/dist_ts/standards/rules/element.exported.d.ts +3 -0
  57. package/dist_ts/standards/rules/element.exported.js +33 -0
  58. package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
  59. package/dist_ts/standards/rules/element.literal-tag.js +30 -0
  60. package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
  61. package/dist_ts/standards/rules/element.reachable.js +48 -0
  62. package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
  63. package/dist_ts/standards/rules/element.tag-map.js +83 -0
  64. package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
  65. package/dist_ts/standards/rules/i18n.literals.js +52 -0
  66. package/dist_ts/standards/rules/index.d.ts +12 -0
  67. package/dist_ts/standards/rules/index.js +83 -0
  68. package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
  69. package/dist_ts/standards/rules/layout.element-folder.js +47 -0
  70. package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
  71. package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
  72. package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
  73. package/dist_ts/standards/rules/layout.entry.js +38 -0
  74. package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
  75. package/dist_ts/standards/rules/layout.group-folder.js +22 -0
  76. package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
  77. package/dist_ts/standards/rules/layout.shared-00.js +36 -0
  78. package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
  79. package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
  80. package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
  81. package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
  82. package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
  83. package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
  84. package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
  85. package/dist_ts/standards/rules/props.accessor.js +35 -0
  86. package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
  87. package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
  88. package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
  89. package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
  90. package/dist_ts/standards/rules/props.typed.d.ts +6 -0
  91. package/dist_ts/standards/rules/props.typed.js +64 -0
  92. package/dist_ts/standards/rules/shared.d.ts +38 -0
  93. package/dist_ts/standards/rules/shared.js +103 -0
  94. package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
  95. package/dist_ts/standards/rules/style.bdtheme.js +28 -0
  96. package/dist_ts_interfaces/index.d.ts +1 -0
  97. package/dist_ts_interfaces/index.js +2 -1
  98. package/dist_ts_interfaces/standard.d.ts +93 -0
  99. package/dist_ts_interfaces/standard.js +6 -0
  100. package/dist_ts_web/00_commitinfo_data.js +1 -1
  101. package/package.json +4 -2
  102. package/readme.md +34 -1
  103. package/ts/00_commitinfo_data.ts +1 -1
  104. package/ts/cli.ts +8 -1
  105. package/ts/plugins.ts +10 -2
  106. package/ts/standards/baselines.ts +100 -0
  107. package/ts/standards/checker.ts +114 -0
  108. package/ts/standards/classes.gitrepo.ts +48 -0
  109. package/ts/standards/classes.sourceedits.ts +58 -0
  110. package/ts/standards/classes.standardfixer.ts +234 -0
  111. package/ts/standards/classes.standardproject.ts +250 -0
  112. package/ts/standards/classes.standardtree.ts +220 -0
  113. package/ts/standards/cli.ts +86 -0
  114. package/ts/standards/config.ts +160 -0
  115. package/ts/standards/errors.ts +18 -0
  116. package/ts/standards/helpers.ast.ts +208 -0
  117. package/ts/standards/helpers.paths.ts +119 -0
  118. package/ts/standards/index.ts +22 -0
  119. package/ts/standards/output.ts +65 -0
  120. package/ts/standards/ratchet.ts +63 -0
  121. package/ts/standards/rule.ts +58 -0
  122. package/ts/standards/rules/barrel.element-index.ts +112 -0
  123. package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
  124. package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
  125. package/ts/standards/rules/demo.groups.ts +74 -0
  126. package/ts/standards/rules/demo.required.ts +49 -0
  127. package/ts/standards/rules/demo.separate-file.ts +40 -0
  128. package/ts/standards/rules/demo.shape.ts +42 -0
  129. package/ts/standards/rules/docs.component-index.ts +88 -0
  130. package/ts/standards/rules/element.exported.ts +35 -0
  131. package/ts/standards/rules/element.literal-tag.ts +30 -0
  132. package/ts/standards/rules/element.reachable.ts +49 -0
  133. package/ts/standards/rules/element.tag-map.ts +87 -0
  134. package/ts/standards/rules/i18n.literals.ts +58 -0
  135. package/ts/standards/rules/index.ts +87 -0
  136. package/ts/standards/rules/layout.element-folder.ts +49 -0
  137. package/ts/standards/rules/layout.entry-file-name.ts +73 -0
  138. package/ts/standards/rules/layout.entry.ts +40 -0
  139. package/ts/standards/rules/layout.group-folder.ts +23 -0
  140. package/ts/standards/rules/layout.shared-00.ts +37 -0
  141. package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
  142. package/ts/standards/rules/naming.lowercase-files.ts +27 -0
  143. package/ts/standards/rules/naming.tag-prefix.ts +24 -0
  144. package/ts/standards/rules/props.accessor.ts +37 -0
  145. package/ts/standards/rules/props.object-no-attribute.ts +45 -0
  146. package/ts/standards/rules/props.reflect-primitive.ts +44 -0
  147. package/ts/standards/rules/props.typed.ts +70 -0
  148. package/ts/standards/rules/shared.ts +127 -0
  149. package/ts/standards/rules/style.bdtheme.ts +31 -0
  150. package/ts_web/00_commitinfo_data.ts +1 -1
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/wcctools',
6
- version: '6.0.0',
6
+ version: '6.1.0',
7
7
  description: 'A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLG1KQUFtSjtDQUNqSyxDQUFBIn0=
package/dist_ts/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as plugins from './plugins.js';
2
2
  import { commitinfo } from './00_commitinfo_data.js';
3
3
  import { WccDevServer } from './classes.devserver.js';
4
+ import { StandardConfigError, StandardUsageError, registerStandardCommands } from './standards/index.js';
4
5
  /**
5
6
  * Registers the wcctools commands on the given console.
6
7
  */
@@ -24,6 +25,7 @@ export const registerCommands = (out) => {
24
25
  const address = await devServer.start();
25
26
  await out.log(`wcctools dev: ${address.url}`);
26
27
  });
28
+ registerStandardCommands(out);
27
29
  out.cli.default({}, async () => {
28
30
  await out.log(out.cli.renderHelp());
29
31
  });
@@ -36,10 +38,14 @@ export const runCli = async () => {
36
38
  }
37
39
  catch (error) {
38
40
  await out.error(error instanceof Error ? error.message : String(error));
39
- process.exitCode = 1;
41
+ // Configuration and usage errors exit with 2, every other failure with 1.
42
+ const usageError = error instanceof plugins.smartconsole.CliUsageError
43
+ || error instanceof StandardConfigError
44
+ || error instanceof StandardUsageError;
45
+ process.exitCode = usageError ? 2 : 1;
40
46
  }
41
47
  finally {
42
48
  await out.dispose();
43
49
  }
44
50
  };
45
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFdEQ7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLEdBQXNDLEVBQVEsRUFBRTtJQUMvRSxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztRQUNoQixJQUFJLEVBQUUsVUFBVTtRQUNoQixPQUFPLEVBQUUsVUFBVSxDQUFDLE9BQU87UUFDM0IsV0FBVyxFQUFFLHVEQUF1RDtLQUNyRSxDQUFDLENBQUM7SUFFSCxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUNkLElBQUksRUFBRSxLQUFLO1FBQ1gsV0FBVyxFQUFFLHdFQUF3RTtRQUNyRixPQUFPLEVBQUU7WUFDUCxJQUFJLEVBQUU7Z0JBQ0osSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsV0FBVyxFQUFFLDhFQUE4RTthQUM1RjtTQUNGO0tBQ0YsRUFBRSxLQUFLLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3ZCLE1BQU0sU0FBUyxHQUFHLElBQUksWUFBWSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzNELE1BQU0sT0FBTyxHQUFHLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3hDLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDN0IsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUN0QyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQUksRUFBRTtJQUMvQixNQUFNLEdBQUcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDcEQsSUFBSSxDQUFDO1FBQ0gsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEIsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7WUFBUyxDQUFDO1FBQ1QsTUFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDdEIsQ0FBQztBQUNILENBQUMsQ0FBQyJ9
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGtCQUFrQixFQUFFLHdCQUF3QixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFekc7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLEdBQXNDLEVBQVEsRUFBRTtJQUMvRSxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztRQUNoQixJQUFJLEVBQUUsVUFBVTtRQUNoQixPQUFPLEVBQUUsVUFBVSxDQUFDLE9BQU87UUFDM0IsV0FBVyxFQUFFLHVEQUF1RDtLQUNyRSxDQUFDLENBQUM7SUFFSCxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUNkLElBQUksRUFBRSxLQUFLO1FBQ1gsV0FBVyxFQUFFLHdFQUF3RTtRQUNyRixPQUFPLEVBQUU7WUFDUCxJQUFJLEVBQUU7Z0JBQ0osSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsV0FBVyxFQUFFLDhFQUE4RTthQUM1RjtTQUNGO0tBQ0YsRUFBRSxLQUFLLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3ZCLE1BQU0sU0FBUyxHQUFHLElBQUksWUFBWSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzNELE1BQU0sT0FBTyxHQUFHLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3hDLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFFSCx3QkFBd0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUU5QixHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDN0IsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUN0QyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQUksRUFBRTtJQUMvQixNQUFNLEdBQUcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDcEQsSUFBSSxDQUFDO1FBQ0gsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEIsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3hFLDBFQUEwRTtRQUMxRSxNQUFNLFVBQVUsR0FBRyxLQUFLLFlBQVksT0FBTyxDQUFDLFlBQVksQ0FBQyxhQUFhO2VBQ2pFLEtBQUssWUFBWSxtQkFBbUI7ZUFDcEMsS0FBSyxZQUFZLGtCQUFrQixDQUFDO1FBQ3pDLE9BQU8sQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QyxDQUFDO1lBQVMsQ0FBQztRQUNULE1BQU0sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDLENBQUMifQ==
@@ -1,15 +1,20 @@
1
+ import * as childProcess from 'node:child_process';
1
2
  import * as fs from 'node:fs/promises';
3
+ import * as fsSync from 'node:fs';
2
4
  import * as path from 'node:path';
3
5
  import * as url from 'node:url';
4
- export { fs, path, url };
6
+ export { childProcess, fs, fsSync, path, url };
5
7
  import * as typedrequest from '@api.global/typedrequest';
6
8
  import * as typedserver from '@api.global/typedserver';
7
9
  export { typedrequest, typedserver };
8
10
  import * as tswatch from '@git.zone/tswatch';
9
11
  export { tswatch };
12
+ import * as smartconfig from '@push.rocks/smartconfig';
10
13
  import * as smartconsole from '@push.rocks/smartconsole';
11
14
  import * as smartexit from '@push.rocks/smartexit';
12
- export { smartconsole, smartexit };
15
+ export { smartconfig, smartconsole, smartexit };
16
+ import typescript from 'typescript';
17
+ export { typescript };
13
18
  import * as interfaces from '../dist_ts_interfaces/index.js';
14
19
  import * as shared from '../dist_ts_shared/index.js';
15
20
  export { interfaces, shared };
@@ -1,8 +1,10 @@
1
1
  // node native scope
2
+ import * as childProcess from 'node:child_process';
2
3
  import * as fs from 'node:fs/promises';
4
+ import * as fsSync from 'node:fs';
3
5
  import * as path from 'node:path';
4
6
  import * as url from 'node:url';
5
- export { fs, path, url };
7
+ export { childProcess, fs, fsSync, path, url };
6
8
  // @api.global scope
7
9
  import * as typedrequest from '@api.global/typedrequest';
8
10
  import * as typedserver from '@api.global/typedserver';
@@ -11,11 +13,15 @@ export { typedrequest, typedserver };
11
13
  import * as tswatch from '@git.zone/tswatch';
12
14
  export { tswatch };
13
15
  // @push.rocks scope
16
+ import * as smartconfig from '@push.rocks/smartconfig';
14
17
  import * as smartconsole from '@push.rocks/smartconsole';
15
18
  import * as smartexit from '@push.rocks/smartexit';
16
- export { smartconsole, smartexit };
19
+ export { smartconfig, smartconsole, smartexit };
20
+ // third party scope
21
+ import typescript from 'typescript';
22
+ export { typescript };
17
23
  // project scope
18
24
  import * as interfaces from '../dist_ts_interfaces/index.js';
19
25
  import * as shared from '../dist_ts_shared/index.js';
20
26
  export { interfaces, shared };
21
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxVQUFVLENBQUM7QUFFaEMsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFekIsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxZQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxDQUFDO0FBRXJDLGtCQUFrQjtBQUNsQixPQUFPLEtBQUssT0FBTyxNQUFNLG1CQUFtQixDQUFDO0FBRTdDLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUVuQixvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBRW5ELE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLENBQUM7QUFFbkMsZ0JBQWdCO0FBQ2hCLE9BQU8sS0FBSyxVQUFVLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxLQUFLLE1BQU0sTUFBTSx1QkFBdUIsQ0FBQztBQUVoRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxDQUFDIn0=
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxZQUFZLE1BQU0sb0JBQW9CLENBQUM7QUFDbkQsT0FBTyxLQUFLLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN2QyxPQUFPLEtBQUssTUFBTSxNQUFNLFNBQVMsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUVoQyxPQUFPLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBRS9DLG9CQUFvQjtBQUNwQixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUVyQyxrQkFBa0I7QUFDbEIsT0FBTyxLQUFLLE9BQU8sTUFBTSxtQkFBbUIsQ0FBQztBQUU3QyxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFFbkIsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBRW5ELE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBRWhELG9CQUFvQjtBQUNwQixPQUFPLFVBQVUsTUFBTSxZQUFZLENBQUM7QUFFcEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBRXRCLGdCQUFnQjtBQUNoQixPQUFPLEtBQUssVUFBVSxNQUFNLDJCQUEyQixDQUFDO0FBQ3hELE9BQU8sS0FBSyxNQUFNLE1BQU0sdUJBQXVCLENBQUM7QUFFaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQyJ9
@@ -0,0 +1,27 @@
1
+ import * as plugins from '../plugins.js';
2
+ type IStandardConfig = plugins.interfaces.IStandardConfig;
3
+ type IStandardReport = plugins.interfaces.IStandardReport;
4
+ type TBaselines = NonNullable<IStandardConfig['baselines']>;
5
+ /** `--init-baseline`: the current error counts of every rule. Only valid while the configuration has no baselines. */
6
+ export declare const initialBaselines: (reportArg: IStandardReport) => TBaselines;
7
+ export interface IBaselineRaise {
8
+ ruleId: string;
9
+ file: string;
10
+ baseline: number;
11
+ current: number;
12
+ }
13
+ /**
14
+ * `--update-baseline`: lowers every count to the current one and removes entries that reach 0.
15
+ * `raised` lists every file whose count would have to grow, including files without an entry;
16
+ * when it is not empty the update is refused.
17
+ */
18
+ export declare const updatedBaselines: (reportArg: IStandardReport, baselinesArg: TBaselines) => {
19
+ baselines: TBaselines;
20
+ raised: IBaselineRaise[];
21
+ };
22
+ /** The configuration with allowlist and baseline file paths moved along with `wcctools fix` moves. */
23
+ export declare const rekeyStandardConfig: (configArg: IStandardConfig, movesArg: readonly plugins.interfaces.IStandardFileMove[]) => {
24
+ config: IStandardConfig;
25
+ changed: string[];
26
+ };
27
+ export {};
@@ -0,0 +1,83 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { allowlistStaleRuleId } from './rules/index.js';
3
+ /**
4
+ * Baseline arithmetic of the ratchet. Pure functions: persisting the result goes through
5
+ * IStandardConfigWriter (see config.ts).
6
+ */
7
+ /** Per rule and file, the error findings a baseline would have to accept (allowlisted findings excluded). */
8
+ const errorCounts = (reportArg) => {
9
+ const counts = {};
10
+ for (const finding of reportArg.findings) {
11
+ if (finding.severity !== 'error' || finding.covered === 'allowlist' || finding.ruleId === allowlistStaleRuleId) {
12
+ continue;
13
+ }
14
+ counts[finding.ruleId] ??= {};
15
+ counts[finding.ruleId][finding.file] = (counts[finding.ruleId][finding.file] ?? 0) + 1;
16
+ }
17
+ return counts;
18
+ };
19
+ const sortBaselines = (baselinesArg) => {
20
+ const sorted = {};
21
+ for (const ruleId of Object.keys(baselinesArg).sort()) {
22
+ const files = Object.keys(baselinesArg[ruleId]).sort();
23
+ if (files.length > 0) {
24
+ sorted[ruleId] = Object.fromEntries(files.map((fileArg) => [fileArg, baselinesArg[ruleId][fileArg]]));
25
+ }
26
+ }
27
+ return sorted;
28
+ };
29
+ /** `--init-baseline`: the current error counts of every rule. Only valid while the configuration has no baselines. */
30
+ export const initialBaselines = (reportArg) => sortBaselines(errorCounts(reportArg));
31
+ /**
32
+ * `--update-baseline`: lowers every count to the current one and removes entries that reach 0.
33
+ * `raised` lists every file whose count would have to grow, including files without an entry;
34
+ * when it is not empty the update is refused.
35
+ */
36
+ export const updatedBaselines = (reportArg, baselinesArg) => {
37
+ const current = errorCounts(reportArg);
38
+ const raised = [];
39
+ const baselines = {};
40
+ for (const [ruleId, counts] of Object.entries(baselinesArg)) {
41
+ baselines[ruleId] = {};
42
+ for (const [file, baseline] of Object.entries(counts)) {
43
+ const count = current[ruleId]?.[file] ?? 0;
44
+ if (count > baseline) {
45
+ raised.push({ ruleId, file, baseline, current: count });
46
+ }
47
+ else if (count > 0) {
48
+ baselines[ruleId][file] = count;
49
+ }
50
+ }
51
+ }
52
+ for (const [ruleId, counts] of Object.entries(current)) {
53
+ for (const [file, count] of Object.entries(counts)) {
54
+ if (baselinesArg[ruleId]?.[file] === undefined) {
55
+ raised.push({ ruleId, file, baseline: 0, current: count });
56
+ }
57
+ }
58
+ }
59
+ return { baselines: sortBaselines(baselines), raised };
60
+ };
61
+ /** The configuration with allowlist and baseline file paths moved along with `wcctools fix` moves. */
62
+ export const rekeyStandardConfig = (configArg, movesArg) => {
63
+ const moved = new Map(movesArg.map((moveArg) => [moveArg.from, moveArg.to]));
64
+ const changed = [];
65
+ const rekey = (keyArg) => {
66
+ const [file, ...member] = keyArg.split('#');
67
+ const target = moved.get(file);
68
+ if (!target) {
69
+ return keyArg;
70
+ }
71
+ changed.push(keyArg);
72
+ return [target, ...member].join('#');
73
+ };
74
+ const config = { ...configArg };
75
+ if (configArg.allowlist) {
76
+ config.allowlist = Object.fromEntries(Object.entries(configArg.allowlist).map(([ruleId, entries]) => [ruleId, Object.fromEntries(Object.entries(entries).map(([key, value]) => [rekey(key), value]))]));
77
+ }
78
+ if (configArg.baselines) {
79
+ config.baselines = Object.fromEntries(Object.entries(configArg.baselines).map(([ruleId, counts]) => [ruleId, Object.fromEntries(Object.entries(counts).map(([file, count]) => [rekey(file), count]))]));
80
+ }
81
+ return { config, changed };
82
+ };
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZWxpbmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RhbmRhcmRzL2Jhc2VsaW5lcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU14RDs7O0dBR0c7QUFFSCw2R0FBNkc7QUFDN0csTUFBTSxXQUFXLEdBQUcsQ0FBQyxTQUEwQixFQUFjLEVBQUU7SUFDN0QsTUFBTSxNQUFNLEdBQWUsRUFBRSxDQUFDO0lBQzlCLEtBQUssTUFBTSxPQUFPLElBQUksU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3pDLElBQUksT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sS0FBSyxXQUFXLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxvQkFBb0IsRUFBRSxDQUFDO1lBQy9HLFNBQVM7UUFDWCxDQUFDO1FBQ0QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDOUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekYsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQztBQUVGLE1BQU0sYUFBYSxHQUFHLENBQUMsWUFBd0IsRUFBYyxFQUFFO0lBQzdELE1BQU0sTUFBTSxHQUFlLEVBQUUsQ0FBQztJQUM5QixLQUFLLE1BQU0sTUFBTSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUN0RCxNQUFNLEtB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
@@ -0,0 +1,21 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { StandardProject } from './classes.standardproject.js';
3
+ import type { ILoadedStandardConfig } from './config.js';
4
+ import { type IRuleFinding, type IStandardRule } from './rule.js';
5
+ type IStandardReport = plugins.interfaces.IStandardReport;
6
+ type TStandardProfile = plugins.interfaces.TStandardProfile;
7
+ /** The rules of a profile, in the order of docs/standard.md. */
8
+ export declare const rulesOfProfile: (profileArg: TStandardProfile) => IStandardRule[];
9
+ /** The rules of a profile as the shell and the AI agent see them. */
10
+ export declare const describeStandardRules: (profileArg: TStandardProfile) => plugins.interfaces.IStandardRuleInfo[];
11
+ /** A finding of one rule with its allowlist state. */
12
+ export interface IDetectedFinding {
13
+ rule: IStandardRule;
14
+ finding: IRuleFinding;
15
+ allowlisted: boolean;
16
+ }
17
+ /** Runs the rules of the configured profile; findings carry their fix actions. */
18
+ export declare const detectFindings: (projectArg: StandardProject, loadedArg: ILoadedStandardConfig, rulesArg?: readonly IStandardRule[]) => IDetectedFinding[];
19
+ /** Checks a repository against the standard: findings, allowlist, baselines. */
20
+ export declare const checkStandard: (projectArg: StandardProject, loadedArg: ILoadedStandardConfig) => IStandardReport;
21
+ export {};
@@ -0,0 +1,88 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { severityIn } from './rule.js';
3
+ import { allowlistStaleRuleId, standardRules } from './rules/index.js';
4
+ /** The rules of a profile, in the order of docs/standard.md. */
5
+ export const rulesOfProfile = (profileArg) => standardRules.filter((ruleArg) => severityIn(ruleArg, profileArg) !== null);
6
+ /** The rules of a profile as the shell and the AI agent see them. */
7
+ export const describeStandardRules = (profileArg) => rulesOfProfile(profileArg).map((ruleArg) => ({
8
+ id: ruleArg.id,
9
+ severity: severityIn(ruleArg, profileArg),
10
+ fixMode: ruleArg.fixMode,
11
+ allowlistCategories: [...(ruleArg.allowlistCategories ?? [])],
12
+ }));
13
+ /** Runs the rules of the configured profile; findings carry their fix actions. */
14
+ export const detectFindings = (projectArg, loadedArg, rulesArg = rulesOfProfile(loadedArg.profile)) => {
15
+ const context = { project: projectArg, config: loadedArg.config, profile: loadedArg.profile };
16
+ const detected = [];
17
+ for (const rule of rulesArg) {
18
+ const allowlist = loadedArg.config.allowlist?.[rule.id] ?? {};
19
+ for (const finding of rule.detect(context)) {
20
+ detected.push({ rule, finding, allowlisted: Object.hasOwn(allowlist, finding.key) });
21
+ }
22
+ }
23
+ return detected;
24
+ };
25
+ const locate = (projectArg, fileArg, positionArg) => {
26
+ const text = projectArg.files.get(fileArg);
27
+ if (text === undefined) {
28
+ return { line: 1, column: 1 };
29
+ }
30
+ if (/\.(ts|tsx|mts|cts)$/.test(fileArg)) {
31
+ return projectArg.lineAndColumn(fileArg, positionArg);
32
+ }
33
+ const before = text.slice(0, positionArg);
34
+ return { line: before.split('\n').length, column: positionArg - before.lastIndexOf('\n') };
35
+ };
36
+ /** Checks a repository against the standard: findings, allowlist, baselines. */
37
+ export const checkStandard = (projectArg, loadedArg) => {
38
+ const { config, profile } = loadedArg;
39
+ const detected = detectFindings(projectArg, loadedArg);
40
+ const findings = detected.map(({ rule, finding, allowlisted }) => ({
41
+ ruleId: rule.id,
42
+ severity: severityIn(rule, profile),
43
+ file: finding.file,
44
+ ...locate(projectArg, finding.file, finding.position),
45
+ message: finding.message,
46
+ fixable: !!finding.fix,
47
+ ...(allowlisted ? { covered: 'allowlist' } : {}),
48
+ }));
49
+ // An allowlist entry without its finding is stale: the list only shrinks.
50
+ for (const [ruleId, entries] of Object.entries(config.allowlist ?? {})) {
51
+ for (const key of Object.keys(entries)) {
52
+ if (!detected.some(({ rule, finding }) => rule.id === ruleId && finding.key === key)) {
53
+ findings.push({
54
+ ruleId: allowlistStaleRuleId,
55
+ severity: 'error',
56
+ file: '.smartconfig.json',
57
+ line: 1,
58
+ column: 1,
59
+ message: `the ${ruleId} allowlist entry '${key}' matches no finding; remove it`,
60
+ fixable: false,
61
+ });
62
+ }
63
+ }
64
+ }
65
+ // Baselines: per rule and file, a count at or below the baseline is covered; above it nothing is.
66
+ const baselineSlack = [];
67
+ for (const [ruleId, counts] of Object.entries(config.baselines ?? {})) {
68
+ for (const [file, baseline] of Object.entries(counts)) {
69
+ const inFile = findings.filter((findingArg) => findingArg.ruleId === ruleId && findingArg.file === file && !findingArg.covered);
70
+ if (inFile.length <= baseline) {
71
+ inFile.forEach((findingArg) => {
72
+ findingArg.covered = 'baseline';
73
+ });
74
+ }
75
+ if (inFile.length < baseline) {
76
+ baselineSlack.push({ ruleId, file, baseline, current: inFile.length });
77
+ }
78
+ }
79
+ }
80
+ findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.column - b.column || a.ruleId.localeCompare(b.ruleId));
81
+ return {
82
+ profile,
83
+ findings,
84
+ baselineSlack,
85
+ ok: !findings.some((findingArg) => findingArg.severity === 'error' && !findingArg.covered),
86
+ };
87
+ };
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3N0YW5kYXJkcy9jaGVja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBR3pDLE9BQU8sRUFBRSxVQUFVLEVBQXlDLE1BQU0sV0FBVyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU12RSxnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLENBQUMsVUFBNEIsRUFBbUIsRUFBRSxDQUM5RSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO0FBRTlFLHFFQUFxRTtBQUNyRSxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLFVBQTRCLEVBQTBDLEVBQUUsQ0FDNUcsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMzQyxFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUU7SUFDZCxRQUFRLEVBQUUsVUFBVSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUU7SUFDMUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO0lBQ3hCLG1CQUFtQixFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsSUFBSSxFQUFFLENBQUMsQ0FBQztDQUM5RCxDQUFDLENBQUMsQ0FBQztBQVNOLGtGQUFrRjtBQUNsRixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FDNUIsVUFBMkIsRUFDM0IsU0FBZ0MsRUFDaEMsV0FBcUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFDbEQsRUFBRTtJQUN0QixNQUFNLE9BQU8sR0FBRyxFQUFF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
@@ -0,0 +1,13 @@
1
+ /** The git operations `wcctools fix` needs, run with an argument vector and no shell. */
2
+ export declare class GitRepo {
3
+ readonly rootDir: string;
4
+ constructor(rootDirArg: string);
5
+ run(argsArg: string[]): Promise<string>;
6
+ /** The repository's top-level directory, or null when the directory is not inside a git work tree. */
7
+ topLevel(): Promise<string | null>;
8
+ /** `git status --porcelain` lines; empty for a clean tree (untracked files count as changes). */
9
+ statusLines(): Promise<string[]>;
10
+ /** Tracked files, relative to the repository root. */
11
+ trackedFiles(): Promise<string[]>;
12
+ move(fromArg: string, toArg: string): Promise<void>;
13
+ }
@@ -0,0 +1,43 @@
1
+ import * as plugins from '../plugins.js';
2
+ /** The git operations `wcctools fix` needs, run with an argument vector and no shell. */
3
+ export class GitRepo {
4
+ rootDir;
5
+ constructor(rootDirArg) {
6
+ this.rootDir = rootDirArg;
7
+ }
8
+ run(argsArg) {
9
+ return new Promise((resolve, reject) => {
10
+ plugins.childProcess.execFile('git', argsArg, { cwd: this.rootDir, maxBuffer: 64 * 1024 * 1024, encoding: 'utf8' }, (error, stdout, stderr) => {
11
+ if (error) {
12
+ reject(new Error(`git ${argsArg.join(' ')} failed: ${stderr.trim() || error.message}`));
13
+ return;
14
+ }
15
+ resolve(stdout);
16
+ });
17
+ });
18
+ }
19
+ /** The repository's top-level directory, or null when the directory is not inside a git work tree. */
20
+ async topLevel() {
21
+ try {
22
+ return (await this.run(['rev-parse', '--show-toplevel'])).trim();
23
+ }
24
+ catch (error) {
25
+ if (error instanceof Error && /not a git repository/i.test(error.message)) {
26
+ return null;
27
+ }
28
+ throw error;
29
+ }
30
+ }
31
+ /** `git status --porcelain` lines; empty for a clean tree (untracked files count as changes). */
32
+ async statusLines() {
33
+ return (await this.run(['status', '--porcelain'])).split('\n').filter((lineArg) => lineArg.length > 0);
34
+ }
35
+ /** Tracked files, relative to the repository root. */
36
+ async trackedFiles() {
37
+ return (await this.run(['ls-files', '-z'])).split('\0').filter((fileArg) => fileArg.length > 0);
38
+ }
39
+ async move(fromArg, toArg) {
40
+ await this.run(['mv', '--', fromArg, toArg]);
41
+ }
42
+ }
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5naXRyZXBvLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RhbmRhcmRzL2NsYXNzZXMuZ2l0cmVwby50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUV6Qyx5RkFBeUY7QUFDekYsTUFBTSxPQUFPLE9BQU87SUFDRixPQUFPLENBQVM7SUFFaEMsWUFBWSxVQUFrQjtRQUM1QixJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztJQUM1QixDQUFDO0lBRU0sR0FBRyxDQUFDLE9BQWlCO1FBQzFCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsT0FBTyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUM1SSxJQUFJLEtBQUssRUFBRSxDQUFDO29CQUNWLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ3hGLE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbEIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxzR0FBc0c7SUFDL0YsS0FBSyxDQUFDLFFBQVE7UUFDbkIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNuRSxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksS0FBSyxZQUFZLEtBQUssSUFBSSx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQzFFLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUNELE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRCxpR0FBaUc7SUFDMUYsS0FBSyxDQUFDLFdBQVc7UUFDdEIsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN6RyxDQUFDO0lBRUQsc0RBQXNEO0lBQy9DLEtBQUssQ0FBQyxZQUFZO1FBQ3ZCLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbEcsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBZSxFQUFFLEtBQWE7UUFDOUMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMvQyxDQUFDO0NBQ0YifQ==
@@ -0,0 +1,15 @@
1
+ import type { ITextEdit } from './helpers.ast.js';
2
+ /**
3
+ * Span edits of one file's text. Edits never re-print the file: each replaces [start, end) of the
4
+ * original text. Identical edits count once; an edit overlapping an earlier accepted one is
5
+ * dropped (the fixer retries it on the edited text). Insertions at the same offset keep the order
6
+ * they were added in.
7
+ */
8
+ export declare class SourceEdits {
9
+ private readonly accepted;
10
+ dropped: number;
11
+ add(editArg: ITextEdit): boolean;
12
+ get size(): number;
13
+ /** Applies the accepted edits from the end of the text backwards. */
14
+ apply(textArg: string): string;
15
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Span edits of one file's text. Edits never re-print the file: each replaces [start, end) of the
3
+ * original text. Identical edits count once; an edit overlapping an earlier accepted one is
4
+ * dropped (the fixer retries it on the edited text). Insertions at the same offset keep the order
5
+ * they were added in.
6
+ */
7
+ export class SourceEdits {
8
+ accepted = [];
9
+ dropped = 0;
10
+ add(editArg) {
11
+ if (editArg.start > editArg.end) {
12
+ throw new Error(`Invalid edit span ${editArg.start}-${editArg.end}`);
13
+ }
14
+ if (this.accepted.some((otherArg) => otherArg.start === editArg.start && otherArg.end === editArg.end && otherArg.text === editArg.text)) {
15
+ return true;
16
+ }
17
+ const overlaps = this.accepted.some((otherArg) => {
18
+ const otherIsInsert = otherArg.start === otherArg.end;
19
+ const isInsert = editArg.start === editArg.end;
20
+ if (otherIsInsert && isInsert) {
21
+ return false;
22
+ }
23
+ if (isInsert) {
24
+ return editArg.start > otherArg.start && editArg.start < otherArg.end;
25
+ }
26
+ if (otherIsInsert) {
27
+ return otherArg.start > editArg.start && otherArg.start < editArg.end;
28
+ }
29
+ return editArg.start < otherArg.end && otherArg.start < editArg.end;
30
+ });
31
+ if (overlaps) {
32
+ this.dropped++;
33
+ return false;
34
+ }
35
+ this.accepted.push({ ...editArg, order: this.accepted.length });
36
+ return true;
37
+ }
38
+ get size() {
39
+ return this.accepted.length;
40
+ }
41
+ /** Applies the accepted edits from the end of the text backwards. */
42
+ apply(textArg) {
43
+ const ordered = [...this.accepted].sort((a, b) => b.start - a.start || b.end - a.end || b.order - a.order);
44
+ let text = textArg;
45
+ for (const edit of ordered) {
46
+ if (edit.end > text.length) {
47
+ throw new Error(`Edit span ${edit.start}-${edit.end} exceeds the text length ${text.length}`);
48
+ }
49
+ text = text.slice(0, edit.start) + edit.text + text.slice(edit.end);
50
+ }
51
+ return text;
52
+ }
53
+ }
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zb3VyY2VlZGl0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3N0YW5kYXJkcy9jbGFzc2VzLnNvdXJjZWVkaXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDTCxRQUFRLEdBQXlDLEVBQUUsQ0FBQztJQUM5RCxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBRVosR0FBRyxDQUFDLE9BQWtCO1FBQzNCLElBQUksT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDaEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsT0FBTyxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN2RSxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssS0FBSyxPQUFPLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQyxHQUFHLEtBQUssT0FBTyxDQUFDLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3pJLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7WUFDL0MsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUMsR0FBRyxDQUFDO1lBQ3RELE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUMvQyxJQUFJLGFBQWEsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDOUIsT0FBTyxLQUFLLENBQUM7WUFDZixDQUFDO1lBQ0QsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDYixPQUFPLE9BQU8sQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUM7WUFDeEUsQ0FBQztZQUNELElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLE9BQU8sUUFBUSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUN4RSxDQUFDO1lBQ0QsT0FBTyxPQUFPLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxHQUFHLElBQUksUUFBUSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ3RFLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNmLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUNELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNoRSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxJQUFXLElBQUk7UUFDYixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO0lBQzlCLENBQUM7SUFFRCxxRUFBcUU7SUFDOUQsS0FBSyxDQUFDLE9BQWU7UUFDMUIsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNHLElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQztRQUNuQixLQUFLLE1BQU0sSUFBSSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzNCLElBQUksSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsYUFBYSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxHQUFHLDRCQUE0QixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNoRyxDQUFDO1lBQ0QsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7Q0FDRiJ9
@@ -0,0 +1,40 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { ILoadedStandardConfig, IStandardConfigWriter } from './config.js';
3
+ export interface IStandardFixOptions {
4
+ rootDir: string;
5
+ loaded: ILoadedStandardConfig;
6
+ /** Rules to fix; opt-in rules run only when named here. Default: every `auto` rule of the profile. */
7
+ rules?: readonly string[];
8
+ dryRun?: boolean;
9
+ /** Persists the configuration when moves rename files the allowlist or baselines name; without it such moves are refused. */
10
+ configWriter?: IStandardConfigWriter;
11
+ }
12
+ /**
13
+ * `wcctools fix`: applies the fixes of the selected rules to an in-memory copy of the repository,
14
+ * one rule after another on the re-parsed result, validates that every path of the resulting plan
15
+ * stays inside the repository root, then writes the configuration, moves files with `git mv`, writes
16
+ * the edited files and checks again. Refuses to run on a dirty work tree and never commits, so a
17
+ * failure part-way through the writes is undone with `git reset --hard` and `git clean -fd`.
18
+ */
19
+ export declare class StandardFixer {
20
+ private readonly options;
21
+ constructor(optionsArg: IStandardFixOptions);
22
+ private selectRules;
23
+ run(): Promise<plugins.interfaces.IStandardFixResult>;
24
+ /**
25
+ * Refuses a plan with a path that leaves the repository root, lexically (an absolute path or a `..`
26
+ * segment) or physically (through a symbolic link that resolves outside the root or dangles).
27
+ * Runs before anything is written, so a refused plan leaves the repository and its surroundings as
28
+ * they were.
29
+ */
30
+ private assertInsideRoot;
31
+ /** True when the file, or its nearest existing ancestor, resolves to a path inside the real root. */
32
+ private resolvesInside;
33
+ private isSymbolicLink;
34
+ /** `git mv` in an order where no move overwrites a file that has not moved away yet. */
35
+ private commitMoves;
36
+ /** Creates a directory one path component at a time. */
37
+ private ensureDir;
38
+ /** Removes directories that moves left empty, walking up towards the repository root. */
39
+ private removeEmptyDirs;
40
+ }