dsh-d365-kit 0.34.1 → 0.34.4

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 (75) hide show
  1. package/CHANGELOG.md +319 -308
  2. package/CHANGELOG.zh-CN.md +318 -307
  3. package/INSTALL.md +94 -94
  4. package/INSTALL.zh-CN.md +93 -93
  5. package/LICENSE +21 -21
  6. package/README.md +336 -327
  7. package/README.zh-CN.md +336 -327
  8. package/client.js +1818 -1818
  9. package/cordis.patch.yml +44 -44
  10. package/docs/en/architecture.md +172 -172
  11. package/docs/en/checks.md +184 -184
  12. package/docs/en/installation.md +151 -151
  13. package/docs/en/permissions.md +161 -161
  14. package/docs/en/scenarios.md +202 -202
  15. package/docs/en/tools.md +665 -665
  16. package/docs/en/troubleshooting.md +131 -131
  17. package/docs/zh/architecture.md +172 -172
  18. package/docs/zh/checks.md +184 -184
  19. package/docs/zh/installation.md +151 -151
  20. package/docs/zh/permissions.md +161 -161
  21. package/docs/zh/scenarios.md +202 -202
  22. package/docs/zh/tools.md +665 -665
  23. package/docs/zh/troubleshooting.md +131 -131
  24. package/examples/prompts.en.md +206 -206
  25. package/examples/prompts.zh-CN.md +206 -206
  26. package/examples/waivers.example.json +20 -20
  27. package/icon.svg +6 -6
  28. package/index.js +139 -139
  29. package/lib/auth.js +181 -181
  30. package/lib/client.js +496 -496
  31. package/lib/code-check.js +549 -549
  32. package/lib/config.js +323 -323
  33. package/lib/contract-history.js +49 -49
  34. package/lib/contract.js +583 -583
  35. package/lib/csharp-check.js +493 -493
  36. package/lib/data-migrate.js +1318 -1318
  37. package/lib/data-policy.js +78 -78
  38. package/lib/error-codes.js +80 -80
  39. package/lib/gitlab.js +161 -161
  40. package/lib/health.js +205 -205
  41. package/lib/migrate.js +732 -732
  42. package/lib/preflight.js +116 -116
  43. package/lib/refs.js +191 -191
  44. package/lib/resources.js +320 -320
  45. package/lib/retention-defaults.js +17 -17
  46. package/lib/retention.js +384 -384
  47. package/lib/runtime.js +232 -232
  48. package/lib/settings-http.js +512 -512
  49. package/lib/settings-store.js +371 -371
  50. package/lib/snapshot.js +149 -149
  51. package/lib/tool-code-check.js +133 -133
  52. package/lib/tool-configure.js +169 -169
  53. package/lib/tool-contract.js +376 -376
  54. package/lib/tool-data-sync.js +559 -559
  55. package/lib/tool-data-write.js +203 -203
  56. package/lib/tool-data.js +282 -282
  57. package/lib/tool-diff.js +484 -484
  58. package/lib/tool-environments.js +106 -106
  59. package/lib/tool-flows.js +540 -540
  60. package/lib/tool-health.js +127 -127
  61. package/lib/tool-layers.js +497 -497
  62. package/lib/tool-metadata.js +417 -417
  63. package/lib/tool-migrate.js +102 -102
  64. package/lib/tool-refs.js +206 -206
  65. package/lib/tool-reports.js +299 -299
  66. package/lib/tool-sync.js +430 -430
  67. package/lib/tool-write.js +563 -563
  68. package/lib/waivers.js +83 -83
  69. package/lib/write-actions.js +1374 -1374
  70. package/lib/write-policy.js +199 -199
  71. package/lib/write-store.js +167 -167
  72. package/locale/en.json +68 -68
  73. package/locale/zh.json +68 -68
  74. package/package.json +2 -2
  75. package/skills/d365-troubleshooting/SKILL.md +115 -115
package/lib/waivers.js CHANGED
@@ -1,83 +1,83 @@
1
- /**
2
- * Waivers: differences a team has decided to accept.
3
- *
4
- * A waiver is data, not code — it lives in `<data dir>/waivers.json` so it can
5
- * be reviewed in a pull request. Every waiver must carry a reason and an expiry:
6
- * an accepted difference that never expires is just a forgotten one.
7
- */
8
-
9
- import { readFile, writeFile, mkdir } from 'node:fs/promises'
10
- import { dirname, join } from 'node:path'
11
- import { dataRoot } from './snapshot.js'
12
-
13
- export function waiversPath(config) {
14
- return join(dataRoot(config), 'waivers.json')
15
- }
16
-
17
- const EMPTY = { waivers: [] }
18
-
19
- export async function readWaivers(config) {
20
- try {
21
- const text = await readFile(waiversPath(config), 'utf8')
22
- const parsed = JSON.parse(text.replace(/^\uFEFF/, ''))
23
- return Array.isArray(parsed?.waivers) ? parsed : EMPTY
24
- } catch (error) {
25
- if (error?.code === 'ENOENT') return EMPTY
26
- throw error
27
- }
28
- }
29
-
30
- export async function writeWaivers(config, document) {
31
- const path = waiversPath(config)
32
- await mkdir(dirname(path), { recursive: true })
33
- await writeFile(path, JSON.stringify(document, null, 2), 'utf8')
34
- }
35
-
36
- /** Add or replace a waiver (same rule + env + object). */
37
- export async function addWaiver(config, entry) {
38
- const document = await readWaivers(config)
39
- const key = `${entry.rule}|${entry.env}|${entry.object}`
40
- document.waivers = document.waivers.filter(
41
- (item) => `${item.rule}|${item.env}|${item.object}` !== key,
42
- )
43
- document.waivers.push(entry)
44
- await writeWaivers(config, document)
45
- return document.waivers
46
- }
47
-
48
- export function isExpired(waiver, now = Date.now()) {
49
- if (!waiver.expiresAt) return false
50
- const at = Date.parse(waiver.expiresAt)
51
- return Number.isFinite(at) && at < now
52
- }
53
-
54
- /** `*` matches everything, a trailing `*` matches a prefix. */
55
- export function matchesWaiver(waiver, finding) {
56
- if (waiver.rule !== finding.rule) return false
57
- if (waiver.env !== '*' && waiver.env !== finding.env) return false
58
- const object = String(waiver.object ?? '')
59
- if (object === '*') return true
60
- if (object.endsWith('*')) return String(finding.object).startsWith(object.slice(0, -1))
61
- return object === String(finding.object)
62
- }
63
-
64
- /**
65
- * Split findings into kept and waived, and report expired waivers so the
66
- * report can say "this waiver expired, so the finding is back".
67
- */
68
- export function applyWaivers(findings, document, now = Date.now()) {
69
- const active = []
70
- const expired = []
71
- for (const waiver of document.waivers ?? []) {
72
- if (isExpired(waiver, now)) expired.push(waiver)
73
- else active.push(waiver)
74
- }
75
- const kept = []
76
- const waived = []
77
- for (const finding of findings) {
78
- const match = active.find((waiver) => matchesWaiver(waiver, finding))
79
- if (match) waived.push({ ...finding, waiver: { reason: match.reason, expiresAt: match.expiresAt ?? null } })
80
- else kept.push(finding)
81
- }
82
- return { kept, waived, expired }
83
- }
1
+ /**
2
+ * Waivers: differences a team has decided to accept.
3
+ *
4
+ * A waiver is data, not code — it lives in `<data dir>/waivers.json` so it can
5
+ * be reviewed in a pull request. Every waiver must carry a reason and an expiry:
6
+ * an accepted difference that never expires is just a forgotten one.
7
+ */
8
+
9
+ import { readFile, writeFile, mkdir } from 'node:fs/promises'
10
+ import { dirname, join } from 'node:path'
11
+ import { dataRoot } from './snapshot.js'
12
+
13
+ export function waiversPath(config) {
14
+ return join(dataRoot(config), 'waivers.json')
15
+ }
16
+
17
+ const EMPTY = { waivers: [] }
18
+
19
+ export async function readWaivers(config) {
20
+ try {
21
+ const text = await readFile(waiversPath(config), 'utf8')
22
+ const parsed = JSON.parse(text.replace(/^\uFEFF/, ''))
23
+ return Array.isArray(parsed?.waivers) ? parsed : EMPTY
24
+ } catch (error) {
25
+ if (error?.code === 'ENOENT') return EMPTY
26
+ throw error
27
+ }
28
+ }
29
+
30
+ export async function writeWaivers(config, document) {
31
+ const path = waiversPath(config)
32
+ await mkdir(dirname(path), { recursive: true })
33
+ await writeFile(path, JSON.stringify(document, null, 2), 'utf8')
34
+ }
35
+
36
+ /** Add or replace a waiver (same rule + env + object). */
37
+ export async function addWaiver(config, entry) {
38
+ const document = await readWaivers(config)
39
+ const key = `${entry.rule}|${entry.env}|${entry.object}`
40
+ document.waivers = document.waivers.filter(
41
+ (item) => `${item.rule}|${item.env}|${item.object}` !== key,
42
+ )
43
+ document.waivers.push(entry)
44
+ await writeWaivers(config, document)
45
+ return document.waivers
46
+ }
47
+
48
+ export function isExpired(waiver, now = Date.now()) {
49
+ if (!waiver.expiresAt) return false
50
+ const at = Date.parse(waiver.expiresAt)
51
+ return Number.isFinite(at) && at < now
52
+ }
53
+
54
+ /** `*` matches everything, a trailing `*` matches a prefix. */
55
+ export function matchesWaiver(waiver, finding) {
56
+ if (waiver.rule !== finding.rule) return false
57
+ if (waiver.env !== '*' && waiver.env !== finding.env) return false
58
+ const object = String(waiver.object ?? '')
59
+ if (object === '*') return true
60
+ if (object.endsWith('*')) return String(finding.object).startsWith(object.slice(0, -1))
61
+ return object === String(finding.object)
62
+ }
63
+
64
+ /**
65
+ * Split findings into kept and waived, and report expired waivers so the
66
+ * report can say "this waiver expired, so the finding is back".
67
+ */
68
+ export function applyWaivers(findings, document, now = Date.now()) {
69
+ const active = []
70
+ const expired = []
71
+ for (const waiver of document.waivers ?? []) {
72
+ if (isExpired(waiver, now)) expired.push(waiver)
73
+ else active.push(waiver)
74
+ }
75
+ const kept = []
76
+ const waived = []
77
+ for (const finding of findings) {
78
+ const match = active.find((waiver) => matchesWaiver(waiver, finding))
79
+ if (match) waived.push({ ...finding, waiver: { reason: match.reason, expiresAt: match.expiresAt ?? null } })
80
+ else kept.push(finding)
81
+ }
82
+ return { kept, waived, expired }
83
+ }