@aaronshaf/ger 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bun.lock CHANGED
@@ -71,8 +71,6 @@
71
71
 
72
72
  "@bundled-es-modules/statuses": ["@bundled-es-modules/statuses@1.0.1", "", { "dependencies": { "statuses": "^2.0.1" } }, "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg=="],
73
73
 
74
- "@bundled-es-modules/tough-cookie": ["@bundled-es-modules/tough-cookie@0.1.6", "", { "dependencies": { "@types/tough-cookie": "^4.0.5", "tough-cookie": "^4.1.4" } }, "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw=="],
75
-
76
74
  "@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
77
75
 
78
76
  "@effect/cluster": ["@effect/cluster@0.46.4", "", { "peerDependencies": { "@effect/platform": "^0.90.0", "@effect/rpc": "^0.68.3", "@effect/sql": "^0.44.1", "@effect/workflow": "^0.8.3", "effect": "^3.17.6" } }, "sha512-81nWw5ABtRZZFmQTrWvfsUnqTg9LybIFYvmsiIL7xQ2t+g6746IZe9Tcv9bSmMdioJLgeuO4CiRg0FfDP2qCWA=="],
@@ -151,21 +149,21 @@
151
149
 
152
150
  "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="],
153
151
 
154
- "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.13.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-evpsj1aaWNEd2VRGTbptiMwC8vYSDadAYtq92Ks3UIe0VoMtY9n5bLeD9Ctw/OHIM7Eh7/EQlNDLOOP/b2GBKA=="],
152
+ "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.14.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rcTw0QWeOc6IeVp+Up7WtcwdS9l4j7TOq4tihF0Ud/fl+VUVdvDCPuZ9QTnLXJhwMXiyQRWdxRyI6XBwf80ncQ=="],
155
153
 
156
- "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.13.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-a4gmSsuQq/ZK/QRDlAcfcwF4UVErZ3Q0noBkypyMdacizLzexlKQvWhXC5Bh1v4/9cWempx+Uf6iaScfo7FmCg=="],
154
+ "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.14.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-TWFSEmyl2/DN4HoXNwQl0y/y3EXFJDctfv5MiDtVOV1GJKX80cGSIxMxXb08Q3CCWqteqEijmfSMo5TG8X1H/A=="],
157
155
 
158
- "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.13.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-GT8WyPomb2AE5ciNzmDZlvVdYL2OmWObaV47dwAk4KH13IAqduOlA17S5IZRrwW1q4FHsRhfJ1eVofAhOtZexQ=="],
156
+ "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.14.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-N1FqdKfwhVWPpMElv8qlGqdEefTbDYaRVhdGWOjs/2f7FESa5vX0cvA7ToqzkoXyXZI5DqByWiPML33njK30Kg=="],
159
157
 
160
- "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.13.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-EY8PHd4U0QYoPFVkGbkBPAN1ZDXmIr5Am6QOqnPtvrOVfR6cRW/o9Qd9Q3zB+HR+pEHl8d25/QSgHpaSQr+hEA=="],
158
+ "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.14.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-v/BPuiateLBb7Gz1STb69EWjkgKdlPQ1NM56z+QQur21ly2hiMkBX2n0zEhqfu9PQVRUizu6AlsYuzcPY/zsIQ=="],
161
159
 
162
- "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.13.0", "", { "os": "linux", "cpu": "x64" }, "sha512-iP30520DYHsqAk3rmCJ4YpcNuWJejhbvl/YcHmrcWH8OJ5a+He2EG6gU9BogfFzsM1HtDn3pZbn69PItqaLJCg=="],
160
+ "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.14.0", "", { "os": "linux", "cpu": "x64" }, "sha512-gUTp8KIrSYt97dn+tRRC3LKnH4xlHKCwrPwiDcGmLbCxojuN9/H5mnIhPKEfwNuZNdoKGS/ABuq3neVyvRCRtQ=="],
163
161
 
164
- "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.13.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SJl0aenYerXS6uFshdpsracwl02sr8dpUK1522p4Tp27aXHUxk55gF5YmFj9rGUQ9h6MyZgJL9fNS5U7PUUxxA=="],
162
+ "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.14.0", "", { "os": "linux", "cpu": "x64" }, "sha512-DpN6cW2HPjYXeENG0JBbmubO8LtfKt6qJqEMBw9gUevbyBaX+k+Jn7sYgh6S23wGOkzmTNphBsf/7ulj4nIVYA=="],
165
163
 
166
- "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.13.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-nAxRno4VF73obGWbBMMslWDYx0hFgqwKR7wqhhVowH5793p1tHvYbV9lrUY8lRqMUHRpYP4pahcipoAEiTlf1w=="],
164
+ "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.14.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-oXxJksnUTUMgJ0NvjKS1mrCXAy1ttPgIVacRSlxQ+1XHy+aJDMM7I8fsCtoKoEcTIpPaD98eqUqlLYs0H2MGjA=="],
167
165
 
168
- "@oxlint/win32-x64": ["@oxlint/win32-x64@1.13.0", "", { "os": "win32", "cpu": "x64" }, "sha512-8p6OwSl6/iauD5TZrTXXZFdKZkj1blGwMOlhnHfSb6FRcjcvR6dv54u3PYssrtqh7nvHLJI0PAwSeJVhvoxxqg=="],
166
+ "@oxlint/win32-x64": ["@oxlint/win32-x64@1.14.0", "", { "os": "win32", "cpu": "x64" }, "sha512-iRYy2rhTQKFztyx0jtNMRBnFpzsRwFdjWQ7sKKzJpmbijA3Tw3DCqlGT7QRgoVRF0+X/ccNGvvsrgMohPVfLeQ=="],
169
167
 
170
168
  "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
171
169
 
@@ -199,14 +197,12 @@
199
197
 
200
198
  "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
201
199
 
202
- "@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
200
+ "@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="],
203
201
 
204
202
  "@types/react": ["@types/react@19.1.11", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ=="],
205
203
 
206
204
  "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
207
205
 
208
- "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="],
209
-
210
206
  "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
211
207
 
212
208
  "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
@@ -287,7 +283,7 @@
287
283
 
288
284
  "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
289
285
 
290
- "effect": ["effect@3.17.9", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-Nkkn9n1zhy30Dq0MpQatDCH7nfYnOIiebkOHNxmmvoVnEDKCto+2ZwDDWFGzcN/ojwfqjRXWGC9Lo91K5kwZCg=="],
286
+ "effect": ["effect@3.17.13", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-JMz5oBxs/6mu4FP9Csjub4jYMUwMLrp+IzUmSDVIzn2NoeoyOXMl7x1lghfr3dLKWffWrdnv/d8nFFdgrHXPqw=="],
291
287
 
292
288
  "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
293
289
 
@@ -393,9 +389,9 @@
393
389
 
394
390
  "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
395
391
 
396
- "lint-staged": ["lint-staged@16.1.5", "", { "dependencies": { "chalk": "^5.5.0", "commander": "^14.0.0", "debug": "^4.4.1", "lilconfig": "^3.1.3", "listr2": "^9.0.1", "micromatch": "^4.0.8", "nano-spawn": "^1.0.2", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-uAeQQwByI6dfV7wpt/gVqg+jAPaSp8WwOA8kKC/dv1qw14oGpnpAisY65ibGHUGDUv0rYaZ8CAJZ/1U8hUvC2A=="],
392
+ "lint-staged": ["lint-staged@16.1.6", "", { "dependencies": { "chalk": "^5.6.0", "commander": "^14.0.0", "debug": "^4.4.1", "lilconfig": "^3.1.3", "listr2": "^9.0.3", "micromatch": "^4.0.8", "nano-spawn": "^1.0.2", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-U4kuulU3CKIytlkLlaHcGgKscNfJPNTiDF2avIUGFCv7K95/DCYQ7Ra62ydeRWmgQGg9zJYw2dzdbztwJlqrow=="],
397
393
 
398
- "listr2": ["listr2@9.0.2", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-VVd7cS6W+vLJu2wmq4QmfVj14Iep7cz4r/OWNk36Aq5ZOY7G8/BfCrQFexcwB1OIxB3yERiePfE/REBjEFulag=="],
394
+ "listr2": ["listr2@9.0.3", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-0aeh5HHHgmq1KRdMMDHfhMWQmIT/m7nRDTlxlFqni2Sp0had9baqsjJRvDGdlvgd6NmPE0nPloOipiQJGFtTHQ=="],
399
395
 
400
396
  "locate-path": ["locate-path@2.0.0", "", { "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA=="],
401
397
 
@@ -425,7 +421,7 @@
425
421
 
426
422
  "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="],
427
423
 
428
- "msw": ["msw@2.10.5", "", { "dependencies": { "@bundled-es-modules/cookie": "^2.0.1", "@bundled-es-modules/statuses": "^1.0.1", "@bundled-es-modules/tough-cookie": "^0.1.6", "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.39.1", "@open-draft/deferred-promise": "^2.2.0", "@open-draft/until": "^2.1.0", "@types/cookie": "^0.6.0", "@types/statuses": "^2.0.4", "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "strict-event-emitter": "^0.5.1", "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-0EsQCrCI1HbhpBWd89DvmxY6plmvrM96b0sCIztnvcNHQbXn5vqwm1KlXslo6u4wN9LFGLC1WFjjgljcQhe40A=="],
424
+ "msw": ["msw@2.11.1", "", { "dependencies": { "@bundled-es-modules/cookie": "^2.0.1", "@bundled-es-modules/statuses": "^1.0.1", "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.39.1", "@open-draft/deferred-promise": "^2.2.0", "@open-draft/until": "^2.1.0", "@types/cookie": "^0.6.0", "@types/statuses": "^2.0.4", "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-dGSRx0AJmQVQfpGXTsAAq4JFdwdhOBdJ6sJS/jnN0ac3s0NZB6daacHF1z5Pefx+IejmvuiLWw260RlyQOf3sQ=="],
429
425
 
430
426
  "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
431
427
 
@@ -455,7 +451,7 @@
455
451
 
456
452
  "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
457
453
 
458
- "oxlint": ["oxlint@1.13.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.13.0", "@oxlint/darwin-x64": "1.13.0", "@oxlint/linux-arm64-gnu": "1.13.0", "@oxlint/linux-arm64-musl": "1.13.0", "@oxlint/linux-x64-gnu": "1.13.0", "@oxlint/linux-x64-musl": "1.13.0", "@oxlint/win32-arm64": "1.13.0", "@oxlint/win32-x64": "1.13.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.0.4" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-wEoHG0WCbxSfpXqrJPbB6q7j16xoiUJD2WHJffpR9CCPB1ZYgOwf/qRSzH9KGW/Uda7oxm/1Ebx4q4hGALJmeQ=="],
454
+ "oxlint": ["oxlint@1.14.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.14.0", "@oxlint/darwin-x64": "1.14.0", "@oxlint/linux-arm64-gnu": "1.14.0", "@oxlint/linux-arm64-musl": "1.14.0", "@oxlint/linux-x64-gnu": "1.14.0", "@oxlint/linux-x64-musl": "1.14.0", "@oxlint/win32-arm64": "1.14.0", "@oxlint/win32-x64": "1.14.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.1.5" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-oo0nq3zF9hmgATGc9esoMahLuEESOodUxEDeHDA2K7tbYcSfcmReE9G2QNppnq9rOSQHLTwlMtzGAjjttYaufQ=="],
459
455
 
460
456
  "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="],
461
457
 
@@ -487,22 +483,14 @@
487
483
 
488
484
  "pseudomap": ["pseudomap@1.0.2", "", {}, "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="],
489
485
 
490
- "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="],
491
-
492
- "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
493
-
494
486
  "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
495
487
 
496
- "querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="],
497
-
498
488
  "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
499
489
 
500
490
  "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
501
491
 
502
492
  "require-main-filename": ["require-main-filename@1.0.1", "", {}, "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug=="],
503
493
 
504
- "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
505
-
506
494
  "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
507
495
 
508
496
  "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
@@ -539,9 +527,13 @@
539
527
 
540
528
  "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
541
529
 
530
+ "tldts": ["tldts@7.0.12", "", { "dependencies": { "tldts-core": "^7.0.12" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-M9ZQBPp6FyqhMcl233vHYyYRkxXOA1SKGlnq13S0mJdUhRSwr2w6I8rlchPL73wBwRlyIZpFvpu2VcdSMWLYXw=="],
531
+
532
+ "tldts-core": ["tldts-core@7.0.12", "", {}, "sha512-3K76aXywJFduGRsOYoY5JzINLs/WMlOkeDwPL+8OCPq2Rh39gkSDtWAxdJQlWjpun/xF/LHf29yqCi6VC/rHDA=="],
533
+
542
534
  "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
543
535
 
544
- "tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="],
536
+ "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="],
545
537
 
546
538
  "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
547
539
 
@@ -551,10 +543,6 @@
551
543
 
552
544
  "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
553
545
 
554
- "universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
555
-
556
- "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="],
557
-
558
546
  "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
559
547
 
560
548
  "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
@@ -591,6 +579,8 @@
591
579
 
592
580
  "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
593
581
 
582
+ "bun-types/@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
583
+
594
584
  "cli-truncate/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
595
585
 
596
586
  "cliui/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aaronshaf/ger",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,13 +16,13 @@
16
16
  "homepage": "https://github.com/aaronshaf/ger#readme",
17
17
  "devDependencies": {
18
18
  "@biomejs/biome": "^2.2.2",
19
- "@types/node": "^24.3.0",
19
+ "@types/node": "^24.3.1",
20
20
  "ast-grep": "^0.1.0",
21
21
  "bun-types": "^1.2.21",
22
22
  "husky": "^9.1.7",
23
- "lint-staged": "^16.1.5",
24
- "msw": "^2.10.5",
25
- "oxlint": "^1.13.0",
23
+ "lint-staged": "^16.1.6",
24
+ "msw": "^2.11.1",
25
+ "oxlint": "^1.14.0",
26
26
  "typescript": "^5.9.2"
27
27
  },
28
28
  "peerDependencies": {
@@ -36,7 +36,7 @@
36
36
  "chalk": "^5.6.0",
37
37
  "cli-table3": "^0.6.5",
38
38
  "commander": "^14.0.0",
39
- "effect": "^3.17.9",
39
+ "effect": "^3.17.13",
40
40
  "signal-exit": "3.0.7"
41
41
  },
42
42
  "scripts": {
@@ -9,6 +9,13 @@
9
9
  - **EMPTY ARRAY IS PERFECTLY VALID** for clean code without issues
10
10
  - No other text before or after the tags
11
11
 
12
+ **GERRIT FORMATTING RULES FOR YOUR MESSAGE CONTENT:**
13
+ - Each message starts with "🤖 " (robot emoji and space)
14
+ - Use CAPS for emphasis, NOT markdown bold or italic
15
+ - Reference code using quotes: 'variable' or "function()"
16
+ - NO backticks (`) in your message text
17
+ - Keep explanations clear and concise
18
+
12
19
  **START YOUR ANALYSIS NOW. DO NOT ASK QUESTIONS. DO NOT WAIT FOR MORE INPUT.**
13
20
 
14
21
  ## JSON Structure for Inline Comments
@@ -28,6 +28,22 @@ Gerrit uses a LIMITED markdown subset. Follow these rules EXACTLY:
28
28
  - Always add blank lines between sections for readability
29
29
  - Keep code blocks simple and well-spaced
30
30
 
31
+ **CRITICAL GERRIT FORMATTING RULES:**
32
+
33
+ 1. NEVER start regular text lines with spaces - this creates unintended code blocks!
34
+ 2. Only use 4 leading spaces when showing actual code examples
35
+ 3. Regular text should start at column 1 (no indentation)
36
+ 4. When explaining something after a bullet point, don't indent - start a new line
37
+ 5. Use blank lines to separate sections and improve readability
38
+
39
+ WRONG (creates code blocks):
40
+ * Issue with authentication
41
+ This explanation will become a code block due to leading spaces
42
+
43
+ CORRECT:
44
+ * Issue with authentication
45
+ This explanation stays as regular text
46
+
31
47
  ### Content Guidelines
32
48
 
33
49
  1. Start with the most important findings
@@ -64,22 +80,22 @@ CRITICAL ISSUES
64
80
 
65
81
  1. SQL Injection Vulnerability - src/api/users.ts:45
66
82
 
67
- The query construction uses string concatenation with user input:
83
+ The query construction uses string concatenation with user input:
68
84
 
69
85
  const query = "SELECT * FROM users WHERE id = " + userId
70
86
 
71
- This allows SQL injection attacks. Use parameterized queries:
87
+ This allows SQL injection attacks. Use parameterized queries:
72
88
 
73
89
  const query = "SELECT * FROM users WHERE id = $1"
74
90
  const result = await db.query(query, [userId])
75
91
 
76
92
  2. Authentication Bypass - src/middleware/auth.ts:78-82
77
93
 
78
- The token validation can be bypassed when 'debug' header is present:
94
+ The token validation can be bypassed when 'debug' header is present:
79
95
 
80
96
  if (req.headers.debug) return next()
81
97
 
82
- This MUST be removed from production code.
98
+ This MUST be removed from production code.
83
99
 
84
100
  SIGNIFICANT CONCERNS
85
101
 
@@ -103,12 +119,12 @@ Add proper cleanup in a finally block:
103
119
  PERFORMANCE ANALYSIS
104
120
 
105
121
  - N+1 Query Pattern in src/api/posts.ts:234-248
106
- Loading comments for each post individually causes N+1 queries.
107
- Consider using a single query with JOIN or batch loading.
122
+ Loading comments for each post individually causes N+1 queries.
123
+ Consider using a single query with JOIN or batch loading.
108
124
 
109
125
  - Unbounded Memory Usage in src/utils/processor.ts:89
110
- Loading entire dataset into memory without pagination.
111
- For large datasets, this will cause OOM errors.
126
+ Loading entire dataset into memory without pagination.
127
+ For large datasets, this will cause OOM errors.
112
128
 
113
129
  TEST COVERAGE
114
130
 
@@ -129,19 +145,19 @@ The security issues are blocking and must be fixed. The performance concerns sho
129
145
  ## Review Tone and Approach
130
146
 
131
147
  1. **Be Direct but Constructive**
132
- - State issues clearly without hedging
133
- - Explain impact and provide solutions
134
- - Focus on the code, not the coder
148
+ - State issues clearly without hedging
149
+ - Explain impact and provide solutions
150
+ - Focus on the code, not the coder
135
151
 
136
152
  2. **Prioritize Effectively**
137
- - Lead with blocking issues
138
- - Group related problems
139
- - Don't bury critical findings
153
+ - Lead with blocking issues
154
+ - Group related problems
155
+ - Don't bury critical findings
140
156
 
141
157
  3. **Provide Value**
142
- - Every comment should help improve the code
143
- - Skip trivial issues unless they indicate patterns
144
- - Include concrete fix suggestions
158
+ - Every comment should help improve the code
159
+ - Skip trivial issues unless they indicate patterns
160
+ - Include concrete fix suggestions
145
161
 
146
162
  ## GIT REPOSITORY ACCESS
147
163
 
@@ -180,6 +196,8 @@ CRITICAL FORMATTING RULES:
180
196
  - Use exactly 4 spaces to start each line of code blocks
181
197
  - Keep code blocks simple and readable
182
198
  - Add proper spacing for readability
199
+ - NEVER indent regular text - start all non-code text at column 1
200
+ - Only code examples should have leading spaces (exactly 4)
183
201
 
184
202
  ## TASK SUMMARY
185
203
 
@@ -0,0 +1,70 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+
3
+ describe('Init Command', () => {
4
+ describe('token obscuring', () => {
5
+ test('should obscure short tokens', () => {
6
+ const obscureToken = (token: string): string => {
7
+ if (token.length <= 8) return '****'
8
+ return `${token.substring(0, 4)}****${token.substring(token.length - 4)}`
9
+ }
10
+
11
+ expect(obscureToken('1234')).toBe('****')
12
+ })
13
+
14
+ test('should obscure long tokens', () => {
15
+ const obscureToken = (token: string): string => {
16
+ if (token.length <= 8) return '****'
17
+ return `${token.substring(0, 4)}****${token.substring(token.length - 4)}`
18
+ }
19
+
20
+ expect(obscureToken('verylongpassword123456')).toBe('very****3456')
21
+ })
22
+ })
23
+
24
+ describe('URL normalization', () => {
25
+ test('should remove trailing slashes', () => {
26
+ const url = 'https://gerrit.example.com/'
27
+ const normalized = url.replace(/\/$/, '')
28
+ expect(normalized).toBe('https://gerrit.example.com')
29
+ })
30
+ })
31
+
32
+ describe('input validation', () => {
33
+ test('should require non-empty host', () => {
34
+ const host = ''
35
+ expect(host).toBeFalsy()
36
+ })
37
+
38
+ test('should require non-empty username', () => {
39
+ const username = ''
40
+ expect(username).toBeFalsy()
41
+ })
42
+
43
+ test('should require non-empty password', () => {
44
+ const password = ''
45
+ expect(password).toBeFalsy()
46
+ })
47
+ })
48
+
49
+ describe('control characters', () => {
50
+ test('should handle Ctrl+C', () => {
51
+ const charCode = '\x03'.charCodeAt(0) // Ctrl+C
52
+ expect(charCode).toBe(3)
53
+ })
54
+
55
+ test('should handle Enter key', () => {
56
+ const charCode = '\r'.charCodeAt(0) // Enter
57
+ expect(charCode).toBe(13)
58
+ })
59
+
60
+ test('should handle backspace', () => {
61
+ const charCode = '\x7f'.charCodeAt(0) // Backspace
62
+ expect(charCode).toBe(127)
63
+ })
64
+
65
+ test('should filter printable characters', () => {
66
+ const charCode = 'a'.charCodeAt(0)
67
+ expect(charCode >= 32 && charCode <= 126).toBe(true)
68
+ })
69
+ })
70
+ })
@@ -0,0 +1,67 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+
3
+ describe('Setup Command', () => {
4
+ describe('URL processing', () => {
5
+ test('should remove trailing slashes', () => {
6
+ const url = 'https://gerrit.example.com/'
7
+ const normalized = url.replace(/\/$/, '')
8
+ expect(normalized).toBe('https://gerrit.example.com')
9
+ })
10
+
11
+ test('should handle URLs without trailing slashes', () => {
12
+ const url = 'https://gerrit.example.com'
13
+ const normalized = url.replace(/\/$/, '')
14
+ expect(normalized).toBe('https://gerrit.example.com')
15
+ })
16
+ })
17
+
18
+ describe('Configuration validation', () => {
19
+ test('should validate required fields', () => {
20
+ const config = {
21
+ host: 'https://gerrit.example.com',
22
+ username: 'testuser',
23
+ password: 'testpass',
24
+ }
25
+
26
+ expect(config.host).toBeTruthy()
27
+ expect(config.username).toBeTruthy()
28
+ expect(config.password).toBeTruthy()
29
+ })
30
+
31
+ test('should reject empty required fields', () => {
32
+ const config = {
33
+ host: '',
34
+ username: 'testuser',
35
+ password: 'testpass',
36
+ }
37
+
38
+ expect(config.host).toBeFalsy()
39
+ })
40
+ })
41
+
42
+ describe('AI tool detection', () => {
43
+ test('should check for available tools', () => {
44
+ const availableTools = ['claude', 'llm', 'chatgpt']
45
+ expect(availableTools).toContain('claude')
46
+ })
47
+
48
+ test('should handle missing tools', () => {
49
+ const availableTools: string[] = []
50
+ expect(availableTools).not.toContain('nonexistent-tool')
51
+ })
52
+ })
53
+
54
+ describe('Connection verification', () => {
55
+ test('should test connection success scenario', () => {
56
+ const mockResponse = { ok: true, status: 200 }
57
+ expect(mockResponse.ok).toBe(true)
58
+ expect(mockResponse.status).toBe(200)
59
+ })
60
+
61
+ test('should handle connection failures', () => {
62
+ const mockResponse = { ok: false, status: 401 }
63
+ expect(mockResponse.ok).toBe(false)
64
+ expect(mockResponse.status).toBe(401)
65
+ })
66
+ })
67
+ })
@@ -0,0 +1,145 @@
1
+ import { describe, test, expect, mock, beforeEach, afterEach } from 'bun:test'
2
+
3
+ // Mock console
4
+ const mockConsole = {
5
+ log: mock(),
6
+ error: mock(),
7
+ }
8
+
9
+ // Mock global console
10
+ global.console = mockConsole as any
11
+
12
+ describe('Status Command', () => {
13
+ beforeEach(() => {
14
+ mockConsole.log.mockReset()
15
+ mockConsole.error.mockReset()
16
+ })
17
+
18
+ afterEach(() => {
19
+ mock.restore()
20
+ })
21
+
22
+ describe('pretty output format', () => {
23
+ test('should show success message when connected', () => {
24
+ console.log('✓ Connected to Gerrit successfully!')
25
+
26
+ expect(mockConsole.log).toHaveBeenCalledWith('✓ Connected to Gerrit successfully!')
27
+ })
28
+
29
+ test('should show failure message when connection fails', () => {
30
+ console.log('✗ Failed to connect to Gerrit')
31
+ console.log('Please check your credentials and network connection')
32
+
33
+ expect(mockConsole.log).toHaveBeenCalledWith('✗ Failed to connect to Gerrit')
34
+ expect(mockConsole.log).toHaveBeenCalledWith(
35
+ 'Please check your credentials and network connection',
36
+ )
37
+ })
38
+ })
39
+
40
+ describe('XML output format', () => {
41
+ test('should output XML format when connected successfully', () => {
42
+ console.log('<?xml version="1.0" encoding="UTF-8"?>')
43
+ console.log('<status_result>')
44
+ console.log(' <connected>true</connected>')
45
+ console.log('</status_result>')
46
+
47
+ expect(mockConsole.log).toHaveBeenCalledWith('<?xml version="1.0" encoding="UTF-8"?>')
48
+ expect(mockConsole.log).toHaveBeenCalledWith('<status_result>')
49
+ expect(mockConsole.log).toHaveBeenCalledWith(' <connected>true</connected>')
50
+ expect(mockConsole.log).toHaveBeenCalledWith('</status_result>')
51
+ })
52
+
53
+ test('should output XML format when connection fails', () => {
54
+ console.log('<?xml version="1.0" encoding="UTF-8"?>')
55
+ console.log('<status_result>')
56
+ console.log(' <connected>false</connected>')
57
+ console.log('</status_result>')
58
+
59
+ expect(mockConsole.log).toHaveBeenCalledWith('<?xml version="1.0" encoding="UTF-8"?>')
60
+ expect(mockConsole.log).toHaveBeenCalledWith('<status_result>')
61
+ expect(mockConsole.log).toHaveBeenCalledWith(' <connected>false</connected>')
62
+ expect(mockConsole.log).toHaveBeenCalledWith('</status_result>')
63
+ })
64
+ })
65
+
66
+ describe('option handling', () => {
67
+ test('should handle xml option correctly', () => {
68
+ const options: { xml?: boolean } = { xml: true }
69
+ expect(options.xml).toBe(true)
70
+ })
71
+
72
+ test('should handle undefined xml option correctly', () => {
73
+ const options = { xml: undefined }
74
+ expect(options.xml).toBeUndefined()
75
+ })
76
+
77
+ test('should handle missing xml option', () => {
78
+ const options: { xml?: boolean } = {}
79
+ expect(options.xml).toBeUndefined()
80
+ })
81
+ })
82
+
83
+ describe('connection testing', () => {
84
+ test('should simulate connection success', async () => {
85
+ const mockTestConnection = mock(() => Promise.resolve(true))
86
+ const result = await mockTestConnection()
87
+ expect(result).toBe(true)
88
+ })
89
+
90
+ test('should simulate connection failure', async () => {
91
+ const mockTestConnection = mock(() => Promise.resolve(false))
92
+ const result = await mockTestConnection()
93
+ expect(result).toBe(false)
94
+ })
95
+
96
+ test('should handle connection errors', async () => {
97
+ const mockTestConnection = mock(() => Promise.reject(new Error('Network error')))
98
+
99
+ try {
100
+ await mockTestConnection()
101
+ } catch (error: any) {
102
+ expect(error.message).toBe('Network error')
103
+ }
104
+ })
105
+ })
106
+
107
+ describe('console output verification', () => {
108
+ test('should output exactly the expected XML structure', () => {
109
+ const expectedXML = [
110
+ '<?xml version="1.0" encoding="UTF-8"?>',
111
+ '<status_result>',
112
+ ' <connected>true</connected>',
113
+ '</status_result>',
114
+ ]
115
+
116
+ expectedXML.forEach((line) => console.log(line))
117
+
118
+ const calls = mockConsole.log.mock.calls.map((call) => call[0])
119
+ expect(calls).toEqual(expectedXML)
120
+ })
121
+
122
+ test('should output exactly one success message in pretty mode', () => {
123
+ console.log('✓ Connected to Gerrit successfully!')
124
+
125
+ expect(mockConsole.log).toHaveBeenCalledTimes(1)
126
+ expect(mockConsole.log).toHaveBeenCalledWith('✓ Connected to Gerrit successfully!')
127
+ })
128
+ })
129
+
130
+ describe('status indicators', () => {
131
+ test('should use checkmark for success', () => {
132
+ const successIcon = '✓'
133
+ console.log(`${successIcon} Connected to Gerrit successfully!`)
134
+
135
+ expect(mockConsole.log).toHaveBeenCalledWith('✓ Connected to Gerrit successfully!')
136
+ })
137
+
138
+ test('should use X mark for failure', () => {
139
+ const failureIcon = '✗'
140
+ console.log(`${failureIcon} Failed to connect to Gerrit`)
141
+
142
+ expect(mockConsole.log).toHaveBeenCalledWith('✗ Failed to connect to Gerrit')
143
+ })
144
+ })
145
+ })