@aigne/doc-smith 0.8.11-beta → 0.8.11-beta.2

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 (257) hide show
  1. package/.aigne/doc-smith/config.yaml +2 -0
  2. package/.aigne/doc-smith/output/structure-plan.json +3 -3
  3. package/.aigne/doc-smith/upload-cache.yaml +252 -0
  4. package/.github/workflows/publish-docs.yml +67 -0
  5. package/.release-please-manifest.json +1 -1
  6. package/CHANGELOG.md +22 -0
  7. package/README.md +45 -115
  8. package/agents/clear/choose-contents.mjs +170 -0
  9. package/agents/clear/clear-auth-tokens.mjs +111 -0
  10. package/agents/clear/clear-document-config.mjs +39 -0
  11. package/agents/clear/clear-document-structure.mjs +106 -0
  12. package/agents/clear/clear-generated-docs.mjs +51 -0
  13. package/agents/clear/index.yaml +23 -0
  14. package/agents/evaluate/code-snippet.mjs +93 -0
  15. package/agents/evaluate/document-structure.yaml +70 -0
  16. package/agents/evaluate/document.yaml +79 -0
  17. package/agents/evaluate/generate-report.mjs +78 -0
  18. package/agents/evaluate/index.yaml +39 -0
  19. package/agents/generate/document-structure-tools/add-document.mjs +56 -0
  20. package/agents/generate/document-structure-tools/delete-document.mjs +49 -0
  21. package/agents/generate/document-structure-tools/move-document.mjs +82 -0
  22. package/agents/generate/document-structure-tools/update-document.mjs +50 -0
  23. package/agents/generate/generate-structure.yaml +1 -1
  24. package/agents/generate/update-document-structure.yaml +42 -0
  25. package/agents/generate/user-review-document-structure.mjs +6 -4
  26. package/agents/init/index.mjs +1 -1
  27. package/agents/publish/publish-docs.mjs +12 -3
  28. package/agents/translate/choose-language.mjs +1 -1
  29. package/agents/update/batch-update-document.yaml +7 -0
  30. package/agents/update/check-update-is-single.mjs +38 -0
  31. package/agents/update/document-tools/update-document-content.mjs +293 -0
  32. package/agents/update/index.yaml +4 -10
  33. package/agents/update/update-document-detail.yaml +52 -0
  34. package/agents/update/update-single-document.yaml +15 -0
  35. package/agents/update/user-review-document.mjs +248 -0
  36. package/agents/utils/choose-docs.mjs +4 -2
  37. package/agents/utils/format-document-structure.mjs +12 -2
  38. package/agents/utils/load-document-all-content.mjs +84 -0
  39. package/agents/utils/load-sources.mjs +4 -1
  40. package/aigne.yaml +59 -20
  41. package/assets/report-template/report.html +198 -0
  42. package/biome.json +14 -2
  43. package/docs/advanced-how-it-works.ja.md +101 -0
  44. package/docs/advanced-how-it-works.zh-TW.md +101 -0
  45. package/docs/advanced-how-it-works.zh.md +20 -20
  46. package/docs/advanced-quality-assurance.ja.md +96 -0
  47. package/docs/advanced-quality-assurance.zh-TW.md +96 -0
  48. package/docs/advanced-quality-assurance.zh.md +18 -18
  49. package/docs/advanced.ja.md +16 -0
  50. package/docs/advanced.zh-TW.md +16 -0
  51. package/docs/advanced.zh.md +4 -4
  52. package/docs/changelog.ja.md +309 -0
  53. package/docs/changelog.zh-TW.md +309 -0
  54. package/docs/changelog.zh.md +23 -23
  55. package/docs/cli-reference.ja.md +210 -0
  56. package/docs/cli-reference.zh-TW.md +210 -0
  57. package/docs/cli-reference.zh.md +21 -21
  58. package/docs/configuration-interactive-setup.ja.md +135 -0
  59. package/docs/configuration-interactive-setup.zh-TW.md +135 -0
  60. package/docs/configuration-interactive-setup.zh.md +29 -29
  61. package/docs/configuration-language-support.ja.md +94 -0
  62. package/docs/configuration-language-support.zh-TW.md +94 -0
  63. package/docs/configuration-language-support.zh.md +13 -13
  64. package/docs/configuration-llm-setup.ja.md +54 -0
  65. package/docs/configuration-llm-setup.zh-TW.md +54 -0
  66. package/docs/configuration-llm-setup.zh.md +12 -12
  67. package/docs/configuration-preferences.ja.md +129 -0
  68. package/docs/configuration-preferences.zh-TW.md +129 -0
  69. package/docs/configuration-preferences.zh.md +36 -36
  70. package/docs/configuration.ja.md +172 -0
  71. package/docs/configuration.zh-TW.md +172 -0
  72. package/docs/configuration.zh.md +49 -49
  73. package/docs/features-generate-documentation.ja.md +101 -0
  74. package/docs/features-generate-documentation.zh-TW.md +101 -0
  75. package/docs/features-generate-documentation.zh.md +17 -17
  76. package/docs/features-publish-your-docs.ja.md +107 -0
  77. package/docs/features-publish-your-docs.zh-TW.md +107 -0
  78. package/docs/features-publish-your-docs.zh.md +22 -22
  79. package/docs/features-translate-documentation.ja.md +79 -0
  80. package/docs/features-translate-documentation.zh-TW.md +79 -0
  81. package/docs/features-translate-documentation.zh.md +12 -12
  82. package/docs/features-update-and-refine.ja.md +138 -0
  83. package/docs/features-update-and-refine.zh-TW.md +138 -0
  84. package/docs/features-update-and-refine.zh.md +21 -21
  85. package/docs/features.ja.md +52 -0
  86. package/docs/features.zh-TW.md +52 -0
  87. package/docs/features.zh.md +8 -8
  88. package/docs/getting-started.ja.md +123 -0
  89. package/docs/getting-started.zh-TW.md +123 -0
  90. package/docs/getting-started.zh.md +24 -24
  91. package/docs/overview.ja.md +30 -0
  92. package/docs/overview.zh-TW.md +30 -0
  93. package/docs/overview.zh.md +8 -8
  94. package/package.json +19 -11
  95. package/prompts/common/document/content-rules-core.md +19 -0
  96. package/prompts/common/document/media-handling-rules.md +9 -0
  97. package/prompts/common/document/role-and-personality.md +15 -0
  98. package/prompts/common/document/user-preferences.md +9 -0
  99. package/prompts/common/document-structure/conflict-resolution-guidance.md +16 -0
  100. package/prompts/common/document-structure/document-structure-rules.md +45 -0
  101. package/prompts/common/document-structure/glossary.md +7 -0
  102. package/prompts/common/document-structure/intj-traits.md +5 -0
  103. package/prompts/common/document-structure/output-constraints.md +9 -0
  104. package/prompts/common/document-structure/user-locale-rules.md +10 -0
  105. package/prompts/common/document-structure/user-preferences.md +9 -0
  106. package/prompts/detail/custom/custom-components.md +9 -1
  107. package/prompts/detail/document-rules.md +6 -6
  108. package/prompts/detail/generate-document.md +5 -45
  109. package/prompts/detail/update-document.md +145 -0
  110. package/prompts/evaluate/document-structure.md +94 -0
  111. package/prompts/evaluate/document.md +149 -0
  112. package/prompts/structure/document-rules.md +1 -1
  113. package/prompts/structure/generate-structure-system.md +74 -0
  114. package/prompts/structure/generate-structure-user.md +41 -0
  115. package/prompts/structure/update-document-structure.md +118 -0
  116. package/prompts/translate/translate-document.md +1 -1
  117. package/prompts/utils/feedback-refiner.md +3 -3
  118. package/release-please-config.json +1 -7
  119. package/tests/agents/clear/choose-contents.test.mjs +280 -0
  120. package/tests/agents/clear/clear-auth-tokens.test.mjs +268 -0
  121. package/tests/agents/clear/clear-document-config.test.mjs +167 -0
  122. package/tests/agents/clear/clear-document-structure.test.mjs +374 -0
  123. package/tests/agents/clear/clear-generated-docs.test.mjs +222 -0
  124. package/tests/agents/evaluate/code-snippet.test.mjs +163 -0
  125. package/tests/agents/evaluate/fixtures/api-services.md +87 -0
  126. package/tests/agents/evaluate/fixtures/js-sdk.md +94 -0
  127. package/tests/agents/evaluate/generate-report.test.mjs +312 -0
  128. package/tests/agents/generate/check-document-structure.test.mjs +0 -6
  129. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +449 -0
  130. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +410 -0
  131. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +476 -0
  132. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +548 -0
  133. package/tests/agents/generate/generate-structure.test.mjs +0 -6
  134. package/tests/agents/generate/user-review-document-structure.test.mjs +9 -9
  135. package/tests/agents/publish/publish-docs.test.mjs +2 -2
  136. package/tests/agents/update/check-update-is-single.test.mjs +300 -0
  137. package/tests/agents/update/document-tools/update-document-content.test.mjs +326 -0
  138. package/tests/agents/update/user-review-document.test.mjs +561 -0
  139. package/tests/agents/utils/format-document-structure.test.mjs +100 -0
  140. package/tests/utils/auth-utils.test.mjs +239 -1
  141. package/tests/utils/blocklet.test.mjs +9 -7
  142. package/tests/utils/constants.test.mjs +1 -1
  143. package/tests/utils/d2-utils.test.mjs +1 -1
  144. package/tests/utils/deploy.test.mjs +310 -366
  145. package/tests/utils/kroki-utils.test.mjs +2 -15
  146. package/tests/utils/linter/fixtures/css/keyword-error.css +1 -0
  147. package/tests/utils/linter/fixtures/css/missing-semicolon.css +1 -0
  148. package/tests/utils/linter/fixtures/css/syntax-error.css +1 -0
  149. package/tests/utils/linter/fixtures/css/undeclare-variable.css +1 -0
  150. package/tests/utils/linter/fixtures/css/unused-variable.css +2 -0
  151. package/tests/utils/linter/fixtures/css/valid-code.css +1 -0
  152. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +1 -0
  153. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +2 -0
  154. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +2 -0
  155. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +1 -0
  156. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +1 -0
  157. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +2 -0
  158. package/tests/utils/linter/fixtures/go/keyword-error.go +5 -0
  159. package/tests/utils/linter/fixtures/go/missing-semicolon.go +5 -0
  160. package/tests/utils/linter/fixtures/go/syntax-error.go +6 -0
  161. package/tests/utils/linter/fixtures/go/undeclare-variable.go +5 -0
  162. package/tests/utils/linter/fixtures/go/unused-variable.go +5 -0
  163. package/tests/utils/linter/fixtures/go/valid-code.go +7 -0
  164. package/tests/utils/linter/fixtures/js/keyword-error.js +3 -0
  165. package/tests/utils/linter/fixtures/js/missing-semicolon.js +6 -0
  166. package/tests/utils/linter/fixtures/js/syntax-error.js +4 -0
  167. package/tests/utils/linter/fixtures/js/undeclare-variable.js +3 -0
  168. package/tests/utils/linter/fixtures/js/unused-variable.js +7 -0
  169. package/tests/utils/linter/fixtures/js/valid-code.js +15 -0
  170. package/tests/utils/linter/fixtures/json/keyword-error.json +1 -0
  171. package/tests/utils/linter/fixtures/json/missing-semicolon.json +1 -0
  172. package/tests/utils/linter/fixtures/json/syntax-error.json +1 -0
  173. package/tests/utils/linter/fixtures/json/undeclare-variable.json +1 -0
  174. package/tests/utils/linter/fixtures/json/unused-variable.json +1 -0
  175. package/tests/utils/linter/fixtures/json/valid-code.json +1 -0
  176. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +5 -0
  177. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +5 -0
  178. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +5 -0
  179. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +5 -0
  180. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +4 -0
  181. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +5 -0
  182. package/tests/utils/linter/fixtures/python/keyword-error.py +3 -0
  183. package/tests/utils/linter/fixtures/python/missing-semicolon.py +2 -0
  184. package/tests/utils/linter/fixtures/python/syntax-error.py +3 -0
  185. package/tests/utils/linter/fixtures/python/undeclare-variable.py +3 -0
  186. package/tests/utils/linter/fixtures/python/unused-variable.py +6 -0
  187. package/tests/utils/linter/fixtures/python/valid-code.py +12 -0
  188. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +2 -0
  189. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +1 -0
  190. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +2 -0
  191. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +1 -0
  192. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +2 -0
  193. package/tests/utils/linter/fixtures/ruby/valid-code.rb +1 -0
  194. package/tests/utils/linter/fixtures/sass/keyword-error.sass +2 -0
  195. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +3 -0
  196. package/tests/utils/linter/fixtures/sass/syntax-error.sass +3 -0
  197. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +2 -0
  198. package/tests/utils/linter/fixtures/sass/unused-variable.sass +4 -0
  199. package/tests/utils/linter/fixtures/sass/valid-code.sass +2 -0
  200. package/tests/utils/linter/fixtures/scss/keyword-error.scss +1 -0
  201. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +1 -0
  202. package/tests/utils/linter/fixtures/scss/syntax-error.scss +1 -0
  203. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +1 -0
  204. package/tests/utils/linter/fixtures/scss/unused-variable.scss +2 -0
  205. package/tests/utils/linter/fixtures/scss/valid-code.scss +1 -0
  206. package/tests/utils/linter/fixtures/shell/keyword-error.sh +5 -0
  207. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +3 -0
  208. package/tests/utils/linter/fixtures/shell/syntax-error.sh +4 -0
  209. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +3 -0
  210. package/tests/utils/linter/fixtures/shell/unused-variable.sh +4 -0
  211. package/tests/utils/linter/fixtures/shell/valid-code.sh +3 -0
  212. package/tests/utils/linter/fixtures/ts/keyword-error.ts +1 -0
  213. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +1 -0
  214. package/tests/utils/linter/fixtures/ts/syntax-error.ts +1 -0
  215. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +1 -0
  216. package/tests/utils/linter/fixtures/ts/unused-variable.ts +3 -0
  217. package/tests/utils/linter/fixtures/ts/valid-code.ts +3 -0
  218. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +5 -0
  219. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +5 -0
  220. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +5 -0
  221. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +6 -0
  222. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +6 -0
  223. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +5 -0
  224. package/tests/utils/linter/fixtures/vue/keyword-error.vue +6 -0
  225. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +6 -0
  226. package/tests/utils/linter/fixtures/vue/syntax-error.vue +6 -0
  227. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +6 -0
  228. package/tests/utils/linter/fixtures/vue/unused-variable.vue +7 -0
  229. package/tests/utils/linter/fixtures/vue/valid-code.vue +6 -0
  230. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +1 -0
  231. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +2 -0
  232. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +1 -0
  233. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +1 -0
  234. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +2 -0
  235. package/tests/utils/linter/fixtures/yaml/valid-code.yml +3 -0
  236. package/tests/utils/linter/index.test.mjs +440 -0
  237. package/tests/utils/linter/scan-results.mjs +42 -0
  238. package/tests/utils/markdown/index.test.mjs +478 -0
  239. package/tests/utils/mermaid-validator.test.mjs +2 -2
  240. package/tests/utils/utils.test.mjs +3 -1
  241. package/types/document-schema.mjs +54 -0
  242. package/types/document-structure-schema.mjs +244 -0
  243. package/utils/auth-utils.mjs +131 -6
  244. package/utils/conflict-detector.mjs +5 -1
  245. package/utils/{constants.mjs → constants/index.mjs} +109 -0
  246. package/utils/constants/linter.mjs +102 -0
  247. package/utils/d2-utils.mjs +2 -4
  248. package/utils/debug.mjs +3 -0
  249. package/utils/deploy.mjs +81 -385
  250. package/utils/evaluate/report-utils.mjs +131 -0
  251. package/utils/file-utils.mjs +36 -1
  252. package/utils/kroki-utils.mjs +1 -1
  253. package/utils/linter/index.mjs +50 -0
  254. package/utils/markdown/index.mjs +26 -0
  255. package/utils/markdown-checker.mjs +1 -1
  256. package/utils/utils.mjs +19 -7
  257. package/prompts/structure/generate-structure.md +0 -161
@@ -14,8 +14,9 @@ import * as fsPromises from "node:fs/promises";
14
14
  import * as os from "node:os";
15
15
  import * as path from "node:path";
16
16
  import * as yaml from "yaml";
17
- import { getAccessToken } from "../../utils/auth-utils.mjs";
17
+ import { getAccessToken, getOfficialAccessToken } from "../../utils/auth-utils.mjs";
18
18
  import * as blockletUtils from "../../utils/blocklet.mjs";
19
+ import { DOC_OFFICIAL_ACCESS_TOKEN } from "../../utils/constants/index.mjs";
19
20
 
20
21
  // Mock external modules that involve network requests
21
22
  const mockCreateConnect = mock(() => Promise.resolve({ accessKeySecret: "new-access-token" }));
@@ -55,6 +56,7 @@ describe("auth-utils", () => {
55
56
  beforeEach(() => {
56
57
  originalEnv = { ...process.env };
57
58
  delete process.env.DOC_DISCUSS_KIT_ACCESS_TOKEN;
59
+ delete process.env[DOC_OFFICIAL_ACCESS_TOKEN];
58
60
 
59
61
  // Reset external mocks
60
62
  mockCreateConnect.mockClear();
@@ -355,4 +357,240 @@ describe("auth-utils", () => {
355
357
  "Failed to obtain access token. Please check your network connection and try again later.",
356
358
  );
357
359
  });
360
+
361
+ // OFFICIAL ACCESS TOKEN TESTS
362
+ describe("getOfficialAccessToken", () => {
363
+ test("should throw error for missing baseUrl parameter", async () => {
364
+ await expect(getOfficialAccessToken()).rejects.toThrow(
365
+ "baseUrl parameter is required for getOfficialAccessToken.",
366
+ );
367
+ await expect(getOfficialAccessToken("")).rejects.toThrow(
368
+ "baseUrl parameter is required for getOfficialAccessToken.",
369
+ );
370
+ });
371
+
372
+ test("should return access token from environment variable", async () => {
373
+ process.env[DOC_OFFICIAL_ACCESS_TOKEN] = "env-official-token";
374
+
375
+ const result = await getOfficialAccessToken("https://example.com");
376
+
377
+ expect(result).toBe("env-official-token");
378
+ });
379
+
380
+ test("should handle different URL formats", async () => {
381
+ process.env[DOC_OFFICIAL_ACCESS_TOKEN] = "test-official-token";
382
+
383
+ const urls = [
384
+ "https://example.com",
385
+ "http://example.com",
386
+ "https://example.com:8080",
387
+ "https://sub.example.com/path",
388
+ ];
389
+
390
+ for (const url of urls) {
391
+ const result = await getOfficialAccessToken(url);
392
+ expect(result).toBe("test-official-token");
393
+ }
394
+ });
395
+
396
+ test("should handle invalid URL", async () => {
397
+ process.env[DOC_OFFICIAL_ACCESS_TOKEN] = "test-official-token";
398
+
399
+ await expect(getOfficialAccessToken("invalid-url")).rejects.toThrow();
400
+ });
401
+
402
+ test("should work with localhost URLs", async () => {
403
+ process.env[DOC_OFFICIAL_ACCESS_TOKEN] = "local-official-token";
404
+
405
+ const result = await getOfficialAccessToken("http://localhost:3000");
406
+
407
+ expect(result).toBe("local-official-token");
408
+ });
409
+
410
+ test("should preserve environment variable after function call", async () => {
411
+ process.env[DOC_OFFICIAL_ACCESS_TOKEN] = "persistent-official-token";
412
+
413
+ await getOfficialAccessToken("https://example.com");
414
+
415
+ expect(process.env[DOC_OFFICIAL_ACCESS_TOKEN]).toBe("persistent-official-token");
416
+ });
417
+
418
+ // CONFIG FILE READING TESTS
419
+ test("should read access token from config file", async () => {
420
+ existsSyncSpy.mockReturnValue(true);
421
+ readFileSpy.mockResolvedValue(`DOC_OFFICIAL_ACCESS_TOKEN: config-official-token`);
422
+ parseSpy.mockReturnValue({
423
+ "example.com": {
424
+ [DOC_OFFICIAL_ACCESS_TOKEN]: "config-official-token",
425
+ },
426
+ });
427
+
428
+ const result = await getOfficialAccessToken("https://example.com");
429
+
430
+ expect(result).toBe("config-official-token");
431
+ expect(joinSpy).toHaveBeenCalledWith("/mock/home", ".aigne", "doc-smith-connected.yaml");
432
+ expect(existsSyncSpy).toHaveBeenCalledWith("/mock/home/.aigne/doc-smith-connected.yaml");
433
+ expect(readFileSpy).toHaveBeenCalledWith(
434
+ "/mock/home/.aigne/doc-smith-connected.yaml",
435
+ "utf8",
436
+ );
437
+ expect(parseSpy).toHaveBeenCalled();
438
+ });
439
+
440
+ test("should handle config file without token field", async () => {
441
+ existsSyncSpy.mockReturnValue(true);
442
+ readFileSpy.mockResolvedValue("other: value");
443
+ parseSpy.mockReturnValue({
444
+ "example.com": {
445
+ other: "value",
446
+ },
447
+ });
448
+
449
+ const result = await getOfficialAccessToken("https://example.com");
450
+ expect(result).toBe("new-access-token");
451
+ });
452
+
453
+ test("should handle missing hostname in config", async () => {
454
+ existsSyncSpy.mockReturnValue(true);
455
+ readFileSpy.mockResolvedValue(`${DOC_OFFICIAL_ACCESS_TOKEN}: token`);
456
+ parseSpy.mockReturnValue({
457
+ "other-domain.com": {
458
+ [DOC_OFFICIAL_ACCESS_TOKEN]: "other-token",
459
+ },
460
+ });
461
+
462
+ const result = await getOfficialAccessToken("https://example.com");
463
+ expect(result).toBe("new-access-token");
464
+ });
465
+
466
+ test("should handle config file read errors silently", async () => {
467
+ existsSyncSpy.mockReturnValue(true);
468
+ readFileSpy.mockRejectedValue(new Error("File read error"));
469
+
470
+ const result = await getOfficialAccessToken("https://example.com");
471
+ expect(result).toBe("new-access-token");
472
+ // Should not call console.warn for config file errors in getOfficialAccessToken
473
+ });
474
+
475
+ test("should handle empty config file", async () => {
476
+ existsSyncSpy.mockReturnValue(true);
477
+ readFileSpy.mockResolvedValue("");
478
+ parseSpy.mockReturnValue(null);
479
+
480
+ const result = await getOfficialAccessToken("https://example.com");
481
+ expect(result).toBe("new-access-token");
482
+ });
483
+
484
+ // AUTHORIZATION FLOW TESTS
485
+ test("should successfully complete authorization flow", async () => {
486
+ const result = await getOfficialAccessToken("https://example.com");
487
+
488
+ expect(result).toBe("new-access-token");
489
+
490
+ // Verify the authorization flow
491
+ expect(mockCreateConnect).toHaveBeenCalledWith(
492
+ expect.objectContaining({
493
+ connectAction: "gen-simple-access-key",
494
+ source: "AIGNE DocSmith connect to official service",
495
+ closeOnSuccess: true,
496
+ appName: "AIGNE DocSmith",
497
+ openPage: expect.any(Function),
498
+ }),
499
+ );
500
+
501
+ // Verify environment variable is set
502
+ expect(process.env[DOC_OFFICIAL_ACCESS_TOKEN]).toBe("new-access-token");
503
+
504
+ // Verify config file is saved
505
+ expect(writeFileSpy).toHaveBeenCalledWith(
506
+ "/mock/home/.aigne/doc-smith-connected.yaml",
507
+ "mock yaml",
508
+ );
509
+ expect(stringifySpy).toHaveBeenCalledWith(
510
+ expect.objectContaining({
511
+ "example.com": {
512
+ [DOC_OFFICIAL_ACCESS_TOKEN]: "new-access-token",
513
+ },
514
+ }),
515
+ );
516
+ });
517
+
518
+ test("should create .aigne directory if it doesn't exist", async () => {
519
+ existsSyncSpy.mockReturnValueOnce(false); // .aigne directory doesn't exist
520
+
521
+ const result = await getOfficialAccessToken("https://example.com");
522
+
523
+ expect(result).toBe("new-access-token");
524
+ expect(mkdirSyncSpy).toHaveBeenCalledWith("/mock/home/.aigne", { recursive: true });
525
+ });
526
+
527
+ test("should merge with existing config file", async () => {
528
+ existsSyncSpy
529
+ .mockReturnValueOnce(true) // .aigne directory exists
530
+ .mockReturnValueOnce(true); // config file exists at save time
531
+ readFileSpy.mockResolvedValue("other.com:\n token: other-token");
532
+ parseSpy.mockReturnValue({ "other.com": { token: "other-token" } });
533
+
534
+ const result = await getOfficialAccessToken("https://example.com");
535
+
536
+ expect(result).toBe("new-access-token");
537
+ expect(stringifySpy).toHaveBeenCalled();
538
+ expect(writeFileSpy).toHaveBeenCalled();
539
+ });
540
+
541
+ test("should call openPage function with correct behavior", async () => {
542
+ let capturedOpenPage;
543
+ mockCreateConnect.mockImplementation((options) => {
544
+ capturedOpenPage = options.openPage;
545
+ return Promise.resolve({ accessKeySecret: "new-access-token" });
546
+ });
547
+
548
+ const result = await getOfficialAccessToken("https://example.com");
549
+
550
+ expect(result).toBe("new-access-token");
551
+ expect(typeof capturedOpenPage).toBe("function");
552
+
553
+ // Test that openPage calls the mock open function and logs
554
+ const consoleSpy = spyOn(console, "log").mockImplementation(() => {});
555
+ await capturedOpenPage("https://auth.example.com");
556
+ expect(mockOpen).toHaveBeenCalledWith("https://auth.example.com");
557
+ expect(consoleSpy).toHaveBeenCalledWith(
558
+ "🔗 Please open this URL in your browser to authorize access: ",
559
+ expect.any(String),
560
+ "\n",
561
+ );
562
+ consoleSpy.mockRestore();
563
+ });
564
+
565
+ test("should handle authorization failure", async () => {
566
+ mockCreateConnect.mockRejectedValue(new Error("Authorization failed"));
567
+
568
+ await expect(getOfficialAccessToken("https://example.com")).rejects.toThrow(
569
+ "Failed to obtain official access token. Please check your network connection and try again later.",
570
+ );
571
+ expect(consoleDebugSpy).toHaveBeenCalledWith(expect.any(Error));
572
+ });
573
+
574
+ test("should handle createConnect with different error types", async () => {
575
+ mockCreateConnect.mockRejectedValue(new TypeError("Network error"));
576
+
577
+ await expect(getOfficialAccessToken("https://example.com")).rejects.toThrow(
578
+ "Failed to obtain official access token. Please check your network connection and try again later.",
579
+ );
580
+ });
581
+
582
+ test("should handle config file save errors gracefully", async () => {
583
+ writeFileSpy.mockRejectedValue(new Error("Write error"));
584
+ const consoleWarnSpy = spyOn(console, "warn").mockImplementation(() => {});
585
+
586
+ const result = await getOfficialAccessToken("https://example.com");
587
+
588
+ expect(result).toBe("new-access-token");
589
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
590
+ expect.stringContaining("Failed to save token to config file"),
591
+ expect.any(Error),
592
+ );
593
+ consoleWarnSpy.mockRestore();
594
+ });
595
+ });
358
596
  });
@@ -1,21 +1,23 @@
1
- import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
2
  import {
3
3
  ComponentNotFoundError,
4
4
  getComponentMountPoint,
5
5
  InvalidBlockletError,
6
6
  } from "../../utils/blocklet.mjs";
7
7
 
8
- // Mock global fetch
9
- const mockFetch = mock();
10
- global.fetch = mockFetch;
11
-
12
8
  describe("blocklet", () => {
9
+ let mockFetch;
13
10
  beforeEach(() => {
14
- mockFetch.mockClear();
11
+ // Mock global fetch
12
+ mockFetch = spyOn(global, "fetch").mockResolvedValue({
13
+ ok: true,
14
+ json: () => Promise.resolve({ name: "test-repo", description: "Test repo" }),
15
+ statusText: "OK",
16
+ });
15
17
  });
16
18
 
17
19
  afterEach(() => {
18
- mockFetch.mockRestore?.();
20
+ mockFetch?.mockRestore();
19
21
  });
20
22
 
21
23
  // ERROR CLASSES TESTS
@@ -20,7 +20,7 @@ import {
20
20
  TMP_ASSETS_DIR,
21
21
  TMP_DIR,
22
22
  TMP_DOCS_DIR,
23
- } from "../../utils/constants.mjs";
23
+ } from "../../utils/constants/index.mjs";
24
24
 
25
25
  describe("constants", () => {
26
26
  describe("DEFAULT_INCLUDE_PATTERNS", () => {
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
 
7
7
  import Debug from "debug";
8
8
 
9
- import { TMP_ASSETS_DIR } from "../../utils/constants.mjs";
9
+ import { TMP_ASSETS_DIR } from "../../utils/constants/index.mjs";
10
10
  import {
11
11
  beforePublishHook,
12
12
  checkContent,