@sanity/cli 6.0.0-alpha.4 → 6.0.0-alpha.5

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 (291) hide show
  1. package/dist/actions/dev/startStudioDevServer.js +3 -8
  2. package/dist/actions/dev/startStudioDevServer.js.map +1 -1
  3. package/dist/actions/dev/types.d.ts +1 -3
  4. package/dist/actions/dev/types.js.map +1 -1
  5. package/dist/actions/documents/validate.d.ts +0 -2
  6. package/dist/actions/documents/validate.js +21 -1
  7. package/dist/actions/documents/validate.js.map +1 -1
  8. package/dist/actions/exec/execScript.js +1 -1
  9. package/dist/actions/exec/execScript.js.map +1 -1
  10. package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js +1 -1
  11. package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js.map +1 -1
  12. package/dist/actions/graphql/getGraphQLAPIs.js +1 -1
  13. package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
  14. package/dist/actions/manifest/extractManifest.js +1 -4
  15. package/dist/actions/manifest/extractManifest.js.map +1 -1
  16. package/dist/actions/schema/deleteSchemaAction.d.ts +13 -5
  17. package/dist/actions/schema/deleteSchemaAction.js +12 -17
  18. package/dist/actions/schema/deleteSchemaAction.js.map +1 -1
  19. package/dist/actions/schema/deploySchemas.d.ts +15 -0
  20. package/dist/actions/schema/deploySchemas.js +98 -0
  21. package/dist/actions/schema/deploySchemas.js.map +1 -0
  22. package/dist/actions/schema/listSchemas.d.ts +12 -0
  23. package/dist/actions/schema/listSchemas.js +119 -0
  24. package/dist/actions/schema/listSchemas.js.map +1 -0
  25. package/dist/actions/schema/schemaStoreTypes.d.ts +0 -11
  26. package/dist/actions/schema/schemaStoreTypes.js.map +1 -1
  27. package/dist/actions/schema/utils/debug.d.ts +2 -0
  28. package/dist/actions/schema/utils/debug.js +5 -0
  29. package/dist/actions/schema/utils/debug.js.map +1 -0
  30. package/dist/actions/schema/utils/manifestExtractor.d.ts +3 -8
  31. package/dist/actions/schema/utils/manifestExtractor.js +12 -17
  32. package/dist/actions/schema/utils/manifestExtractor.js.map +1 -1
  33. package/dist/actions/schema/utils/manifestReader.d.ts +2 -9
  34. package/dist/actions/schema/utils/manifestReader.js +6 -12
  35. package/dist/actions/schema/utils/manifestReader.js.map +1 -1
  36. package/dist/actions/schema/utils/schemaStoreOutStrings.d.ts +0 -1
  37. package/dist/actions/schema/utils/schemaStoreOutStrings.js +1 -1
  38. package/dist/actions/schema/utils/schemaStoreOutStrings.js.map +1 -1
  39. package/dist/actions/schema/utils/schemaStoreValidation.d.ts +10 -62
  40. package/dist/actions/schema/utils/schemaStoreValidation.js +38 -125
  41. package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
  42. package/dist/actions/schema/utils/uniqByProjectIdDataset.d.ts +14 -0
  43. package/dist/actions/schema/utils/uniqByProjectIdDataset.js +9 -0
  44. package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -0
  45. package/dist/actions/users/getMembersForProject.d.ts +1 -3
  46. package/dist/actions/users/getMembersForProject.js +6 -17
  47. package/dist/actions/users/getMembersForProject.js.map +1 -1
  48. package/dist/actions/users/types.d.ts +0 -11
  49. package/dist/actions/users/types.js.map +1 -1
  50. package/dist/commands/__tests__/debug.test.js +113 -220
  51. package/dist/commands/__tests__/debug.test.js.map +1 -1
  52. package/dist/commands/__tests__/deploy.test.js +325 -293
  53. package/dist/commands/__tests__/deploy.test.js.map +1 -1
  54. package/dist/commands/__tests__/dev.test.js +62 -19
  55. package/dist/commands/__tests__/dev.test.js.map +1 -1
  56. package/dist/commands/__tests__/init/init.authentication.test.js +40 -27
  57. package/dist/commands/__tests__/init/init.authentication.test.js.map +1 -1
  58. package/dist/commands/__tests__/init/init.create-new-project.test.js +84 -85
  59. package/dist/commands/__tests__/init/init.create-new-project.test.js.map +1 -1
  60. package/dist/commands/__tests__/init/init.plan.test.js +103 -44
  61. package/dist/commands/__tests__/init/init.plan.test.js.map +1 -1
  62. package/dist/commands/__tests__/init/init.setup.test.js +85 -29
  63. package/dist/commands/__tests__/init/init.setup.test.js.map +1 -1
  64. package/dist/commands/__tests__/install.test.js +46 -22
  65. package/dist/commands/__tests__/install.test.js.map +1 -1
  66. package/dist/commands/__tests__/logout.test.js +8 -5
  67. package/dist/commands/__tests__/logout.test.js.map +1 -1
  68. package/dist/commands/__tests__/manage.test.js +29 -24
  69. package/dist/commands/__tests__/manage.test.js.map +1 -1
  70. package/dist/commands/__tests__/versions.test.js +22 -14
  71. package/dist/commands/__tests__/versions.test.js.map +1 -1
  72. package/dist/commands/backup/__tests__/disable.test.js +72 -75
  73. package/dist/commands/backup/__tests__/disable.test.js.map +1 -1
  74. package/dist/commands/backup/__tests__/download.test.js +166 -77
  75. package/dist/commands/backup/__tests__/download.test.js.map +1 -1
  76. package/dist/commands/backup/__tests__/enable.test.js +109 -140
  77. package/dist/commands/backup/__tests__/enable.test.js.map +1 -1
  78. package/dist/commands/backup/__tests__/list.test.js +84 -75
  79. package/dist/commands/backup/__tests__/list.test.js.map +1 -1
  80. package/dist/commands/backup/disable.js +5 -11
  81. package/dist/commands/backup/disable.js.map +1 -1
  82. package/dist/commands/backup/enable.js +5 -11
  83. package/dist/commands/backup/enable.js.map +1 -1
  84. package/dist/commands/backup/list.js +7 -8
  85. package/dist/commands/backup/list.js.map +1 -1
  86. package/dist/commands/cors/__tests__/add.test.js +68 -38
  87. package/dist/commands/cors/__tests__/add.test.js.map +1 -1
  88. package/dist/commands/cors/__tests__/delete.test.js +52 -37
  89. package/dist/commands/cors/__tests__/delete.test.js.map +1 -1
  90. package/dist/commands/cors/__tests__/list.test.js +80 -57
  91. package/dist/commands/cors/__tests__/list.test.js.map +1 -1
  92. package/dist/commands/cors/add.js +5 -13
  93. package/dist/commands/cors/add.js.map +1 -1
  94. package/dist/commands/cors/delete.js +7 -15
  95. package/dist/commands/cors/delete.js.map +1 -1
  96. package/dist/commands/cors/list.js +2 -10
  97. package/dist/commands/cors/list.js.map +1 -1
  98. package/dist/commands/dataset/__tests__/copy.test.js +197 -89
  99. package/dist/commands/dataset/__tests__/copy.test.js.map +1 -1
  100. package/dist/commands/dataset/__tests__/create.test.js +147 -117
  101. package/dist/commands/dataset/__tests__/create.test.js.map +1 -1
  102. package/dist/commands/dataset/__tests__/delete.test.js +75 -68
  103. package/dist/commands/dataset/__tests__/delete.test.js.map +1 -1
  104. package/dist/commands/dataset/__tests__/export.test.js +123 -83
  105. package/dist/commands/dataset/__tests__/export.test.js.map +1 -1
  106. package/dist/commands/dataset/__tests__/list.test.js +107 -65
  107. package/dist/commands/dataset/__tests__/list.test.js.map +1 -1
  108. package/dist/commands/dataset/alias/__tests__/create.test.js +114 -74
  109. package/dist/commands/dataset/alias/__tests__/create.test.js.map +1 -1
  110. package/dist/commands/dataset/alias/__tests__/delete.test.js +40 -29
  111. package/dist/commands/dataset/alias/__tests__/delete.test.js.map +1 -1
  112. package/dist/commands/dataset/alias/__tests__/link.test.js +114 -74
  113. package/dist/commands/dataset/alias/__tests__/link.test.js.map +1 -1
  114. package/dist/commands/dataset/alias/__tests__/unlink.test.js +44 -29
  115. package/dist/commands/dataset/alias/__tests__/unlink.test.js.map +1 -1
  116. package/dist/commands/dataset/export.js +4 -4
  117. package/dist/commands/dataset/export.js.map +1 -1
  118. package/dist/commands/dataset/visibility/__tests__/get.test.js +48 -67
  119. package/dist/commands/dataset/visibility/__tests__/get.test.js.map +1 -1
  120. package/dist/commands/dataset/visibility/__tests__/set.test.js +76 -123
  121. package/dist/commands/dataset/visibility/__tests__/set.test.js.map +1 -1
  122. package/dist/commands/dev.js +0 -1
  123. package/dist/commands/dev.js.map +1 -1
  124. package/dist/commands/docs/__tests__/search.test.js +8 -7
  125. package/dist/commands/docs/__tests__/search.test.js.map +1 -1
  126. package/dist/commands/documents/__tests__/create.test.js +328 -265
  127. package/dist/commands/documents/__tests__/create.test.js.map +1 -1
  128. package/dist/commands/documents/__tests__/delete.test.js +119 -87
  129. package/dist/commands/documents/__tests__/delete.test.js.map +1 -1
  130. package/dist/commands/documents/__tests__/get.test.js +68 -95
  131. package/dist/commands/documents/__tests__/get.test.js.map +1 -1
  132. package/dist/commands/documents/__tests__/query.test.js +84 -189
  133. package/dist/commands/documents/__tests__/query.test.js.map +1 -1
  134. package/dist/commands/documents/__tests__/validate.test.js +52 -29
  135. package/dist/commands/documents/__tests__/validate.test.js.map +1 -1
  136. package/dist/commands/documents/create.d.ts +1 -0
  137. package/dist/commands/documents/create.js +10 -9
  138. package/dist/commands/documents/create.js.map +1 -1
  139. package/dist/commands/documents/delete.js +2 -3
  140. package/dist/commands/documents/delete.js.map +1 -1
  141. package/dist/commands/documents/get.js +2 -3
  142. package/dist/commands/documents/get.js.map +1 -1
  143. package/dist/commands/documents/query.js +2 -3
  144. package/dist/commands/documents/query.js.map +1 -1
  145. package/dist/commands/documents/validate.js +0 -20
  146. package/dist/commands/documents/validate.js.map +1 -1
  147. package/dist/commands/graphql/__tests__/list.test.js +57 -45
  148. package/dist/commands/graphql/__tests__/list.test.js.map +1 -1
  149. package/dist/commands/graphql/__tests__/undeploy.test.js +85 -59
  150. package/dist/commands/graphql/__tests__/undeploy.test.js.map +1 -1
  151. package/dist/commands/graphql/list.js +2 -2
  152. package/dist/commands/graphql/list.js.map +1 -1
  153. package/dist/commands/graphql/undeploy.js +4 -9
  154. package/dist/commands/graphql/undeploy.js.map +1 -1
  155. package/dist/commands/hook/__tests__/attempt.test.js +48 -33
  156. package/dist/commands/hook/__tests__/attempt.test.js.map +1 -1
  157. package/dist/commands/hook/__tests__/create.test.js +49 -51
  158. package/dist/commands/hook/__tests__/create.test.js.map +1 -1
  159. package/dist/commands/hook/__tests__/delete.test.js +43 -30
  160. package/dist/commands/hook/__tests__/delete.test.js.map +1 -1
  161. package/dist/commands/hook/__tests__/list.test.js +38 -31
  162. package/dist/commands/hook/__tests__/list.test.js.map +1 -1
  163. package/dist/commands/hook/__tests__/logs.test.js +68 -40
  164. package/dist/commands/hook/__tests__/logs.test.js.map +1 -1
  165. package/dist/commands/hook/create.js +2 -6
  166. package/dist/commands/hook/create.js.map +1 -1
  167. package/dist/commands/hook/delete.js +5 -17
  168. package/dist/commands/hook/delete.js.map +1 -1
  169. package/dist/commands/hook/list.js +2 -8
  170. package/dist/commands/hook/list.js.map +1 -1
  171. package/dist/commands/manifest/__tests__/extract.test.js +22 -13
  172. package/dist/commands/manifest/__tests__/extract.test.js.map +1 -1
  173. package/dist/commands/media/__tests__/create-aspect.test.js +41 -28
  174. package/dist/commands/media/__tests__/create-aspect.test.js.map +1 -1
  175. package/dist/commands/media/__tests__/delete-aspect.test.js +44 -35
  176. package/dist/commands/media/__tests__/delete-aspect.test.js.map +1 -1
  177. package/dist/commands/media/__tests__/deploy-aspect.test.js +67 -80
  178. package/dist/commands/media/__tests__/deploy-aspect.test.js.map +1 -1
  179. package/dist/commands/media/__tests__/export.test.js +365 -66
  180. package/dist/commands/media/__tests__/export.test.js.map +1 -1
  181. package/dist/commands/media/__tests__/import.test.js +171 -105
  182. package/dist/commands/media/__tests__/import.test.js.map +1 -1
  183. package/dist/commands/media/export.js +2 -2
  184. package/dist/commands/media/export.js.map +1 -1
  185. package/dist/commands/media/import.js +2 -2
  186. package/dist/commands/media/import.js.map +1 -1
  187. package/dist/commands/projects/__tests__/list.test.js +5 -4
  188. package/dist/commands/projects/__tests__/list.test.js.map +1 -1
  189. package/dist/commands/projects/list.js +2 -6
  190. package/dist/commands/projects/list.js.map +1 -1
  191. package/dist/commands/schema/__tests__/delete.test.js +396 -151
  192. package/dist/commands/schema/__tests__/delete.test.js.map +1 -1
  193. package/dist/commands/schema/__tests__/deploy.test.js +348 -0
  194. package/dist/commands/schema/__tests__/deploy.test.js.map +1 -0
  195. package/dist/commands/schema/__tests__/extract.test.js +19 -11
  196. package/dist/commands/schema/__tests__/extract.test.js.map +1 -1
  197. package/dist/commands/schema/__tests__/list.test.js +399 -0
  198. package/dist/commands/schema/__tests__/list.test.js.map +1 -0
  199. package/dist/commands/schema/__tests__/validate.test.js +27 -10
  200. package/dist/commands/schema/__tests__/validate.test.js.map +1 -1
  201. package/dist/commands/schema/delete.d.ts +1 -1
  202. package/dist/commands/schema/delete.js +20 -23
  203. package/dist/commands/schema/delete.js.map +1 -1
  204. package/dist/commands/schema/deploy.d.ts +16 -0
  205. package/dist/commands/schema/deploy.js +98 -0
  206. package/dist/commands/schema/deploy.js.map +1 -0
  207. package/dist/commands/schema/list.d.ts +15 -0
  208. package/dist/commands/schema/list.js +104 -0
  209. package/dist/commands/schema/list.js.map +1 -0
  210. package/dist/commands/telemetry/__tests__/disable.test.js +7 -5
  211. package/dist/commands/telemetry/__tests__/disable.test.js.map +1 -1
  212. package/dist/commands/telemetry/__tests__/enable.test.js +7 -5
  213. package/dist/commands/telemetry/__tests__/enable.test.js.map +1 -1
  214. package/dist/commands/telemetry/__tests__/status.test.js +7 -5
  215. package/dist/commands/telemetry/__tests__/status.test.js.map +1 -1
  216. package/dist/commands/tokens/__tests__/add.test.js +55 -40
  217. package/dist/commands/tokens/__tests__/add.test.js.map +1 -1
  218. package/dist/commands/tokens/__tests__/delete.test.js +72 -42
  219. package/dist/commands/tokens/__tests__/delete.test.js.map +1 -1
  220. package/dist/commands/tokens/__tests__/list.test.js +87 -60
  221. package/dist/commands/tokens/__tests__/list.test.js.map +1 -1
  222. package/dist/commands/tokens/add.js +3 -5
  223. package/dist/commands/tokens/add.js.map +1 -1
  224. package/dist/commands/users/__tests__/invite.test.js +100 -79
  225. package/dist/commands/users/__tests__/invite.test.js.map +1 -1
  226. package/dist/commands/users/__tests__/list.test.js +186 -180
  227. package/dist/commands/users/__tests__/list.test.js.map +1 -1
  228. package/dist/commands/users/invite.js +6 -17
  229. package/dist/commands/users/invite.js.map +1 -1
  230. package/dist/commands/users/list.js +4 -7
  231. package/dist/commands/users/list.js.map +1 -1
  232. package/dist/config/createCliConfig.d.ts +4 -4
  233. package/dist/services/backup.d.ts +8 -0
  234. package/dist/services/backup.js +19 -0
  235. package/dist/services/backup.js.map +1 -1
  236. package/dist/services/cors.d.ts +23 -0
  237. package/dist/services/cors.js +38 -0
  238. package/dist/services/cors.js.map +1 -0
  239. package/dist/services/graphql.d.ts +7 -0
  240. package/dist/services/graphql.js +11 -0
  241. package/dist/services/graphql.js.map +1 -1
  242. package/dist/services/hooks.d.ts +2 -0
  243. package/dist/services/hooks.js +19 -0
  244. package/dist/services/hooks.js.map +1 -1
  245. package/dist/services/organizations.d.ts +1 -1
  246. package/dist/services/organizations.js +1 -1
  247. package/dist/services/organizations.js.map +1 -1
  248. package/dist/services/projects.d.ts +11 -0
  249. package/dist/services/projects.js +41 -0
  250. package/dist/services/projects.js.map +1 -1
  251. package/dist/services/schemas.d.ts +4 -0
  252. package/dist/services/schemas.js +40 -0
  253. package/dist/services/schemas.js.map +1 -0
  254. package/dist/services/user.d.ts +8 -0
  255. package/dist/services/user.js +15 -2
  256. package/dist/services/user.js.map +1 -1
  257. package/dist/util/__tests__/getCliVersion.test.js +2 -2
  258. package/dist/util/__tests__/getCliVersion.test.js.map +1 -1
  259. package/dist/util/errorMessages.d.ts +1 -0
  260. package/dist/util/errorMessages.js +1 -0
  261. package/dist/util/errorMessages.js.map +1 -1
  262. package/dist/util/getCliVersion.js +1 -1
  263. package/dist/util/getCliVersion.js.map +1 -1
  264. package/dist/util/readPackageJson.d.ts +1 -15
  265. package/dist/util/readPackageJson.js +1 -1
  266. package/dist/util/readPackageJson.js.map +1 -1
  267. package/dist/util/uniqBy.d.ts +1 -0
  268. package/dist/util/uniqBy.js +14 -0
  269. package/dist/util/uniqBy.js.map +1 -0
  270. package/oclif.manifest.json +172 -27
  271. package/package.json +27 -28
  272. package/dist/actions/cors/constants.d.ts +0 -1
  273. package/dist/actions/cors/constants.js +0 -3
  274. package/dist/actions/cors/constants.js.map +0 -1
  275. package/dist/actions/cors/types.d.ts +0 -9
  276. package/dist/actions/cors/types.js +0 -3
  277. package/dist/actions/cors/types.js.map +0 -1
  278. package/dist/actions/schema/__tests__/deleteSchemaAction.test.js +0 -294
  279. package/dist/actions/schema/__tests__/deleteSchemaAction.test.js.map +0 -1
  280. package/dist/actions/schema/schemaStoreConstants.d.ts +0 -1
  281. package/dist/actions/schema/schemaStoreConstants.js +0 -4
  282. package/dist/actions/schema/schemaStoreConstants.js.map +0 -1
  283. package/dist/actions/schema/utils/schemaActionHelpers.d.ts +0 -1
  284. package/dist/actions/schema/utils/schemaActionHelpers.js +0 -5
  285. package/dist/actions/schema/utils/schemaActionHelpers.js.map +0 -1
  286. package/dist/actions/schema/utils/schemaApiClient.d.ts +0 -6
  287. package/dist/actions/schema/utils/schemaApiClient.js +0 -17
  288. package/dist/actions/schema/utils/schemaApiClient.js.map +0 -1
  289. package/dist/actions/users/apiVersion.d.ts +0 -6
  290. package/dist/actions/users/apiVersion.js +0 -7
  291. package/dist/actions/users/apiVersion.js.map +0 -1
@@ -3,7 +3,7 @@ import fs from 'node:fs/promises';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { runCommand } from '@oclif/test';
6
- import { getCliConfig, getProjectCliClient } from '@sanity/cli-core';
6
+ import { getProjectCliClient } from '@sanity/cli-core';
7
7
  import { testCommand } from '@sanity/cli-test';
8
8
  import { watch as chokidarWatch } from 'chokidar';
9
9
  import { execa, execaSync } from 'execa';
@@ -23,24 +23,13 @@ vi.mock('node:crypto', async ()=>{
23
23
  randomUUID: vi.fn()
24
24
  };
25
25
  });
26
- vi.mock('../../../../../cli-core/src/config/findProjectRoot.js', ()=>({
27
- findProjectRoot: vi.fn().mockResolvedValue({
28
- directory: '/test/path',
29
- root: '/test/path',
30
- type: 'studio'
31
- })
32
- }));
33
- vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', ()=>({
34
- getCliConfig: vi.fn()
35
- }));
36
- vi.mock('../../../../../cli-core/src/services/getCliToken.js', ()=>({
37
- getCliToken: vi.fn().mockResolvedValue('test-token')
38
- }));
39
- vi.mock('../../../../../cli-core/src/services/apiClient.js', ()=>({
26
+ vi.mock('@sanity/cli-core', async ()=>{
27
+ const actual = await vi.importActual('@sanity/cli-core');
28
+ return {
29
+ ...actual,
40
30
  getProjectCliClient: vi.fn()
41
- }));
42
- const mockGetCliConfig = vi.mocked(getCliConfig);
43
- const mockGetProjectCliClient = vi.mocked(getProjectCliClient);
31
+ };
32
+ });
44
33
  const mockFs = vi.mocked(fs);
45
34
  const mockOs = vi.mocked(os);
46
35
  const mockChokidarWatch = vi.mocked(chokidarWatch);
@@ -48,6 +37,7 @@ const mockExeca = vi.mocked(execa);
48
37
  const mockExecaSync = vi.mocked(execaSync);
49
38
  const mockJson5 = vi.mocked(json5);
50
39
  const mockRandomUUID = vi.mocked(randomUUID);
40
+ const mockGetProjectCliClient = vi.mocked(getProjectCliClient);
51
41
  const testProjectId = 'test-project';
52
42
  const testDataset = 'production';
53
43
  // Helper to set environment variable for tests
@@ -68,32 +58,17 @@ const baseConfig = {
68
58
  projectId: testProjectId
69
59
  }
70
60
  };
71
- // Helper functions moved to outer scope to fix linting
72
- const setupBaseMocks = (additionalConfig = {})=>{
73
- mockGetCliConfig.mockResolvedValue({
74
- ...baseConfig,
75
- ...additionalConfig
76
- });
77
- };
78
- const setupMocks = ()=>{
79
- setupBaseMocks();
80
- const mockClient = {
81
- transaction: vi.fn().mockReturnValue({
82
- commit: vi.fn().mockResolvedValue({
83
- results: [
84
- {
85
- id: 'test-doc',
86
- operation: 'create'
87
- }
88
- ]
89
- })
90
- })
91
- };
92
- mockGetProjectCliClient.mockResolvedValue(mockClient);
93
- return mockClient;
61
+ const defaultMocks = {
62
+ cliConfig: baseConfig,
63
+ projectRoot: {
64
+ directory: '/test/path',
65
+ path: '/test/path/sanity.config.ts',
66
+ type: 'studio'
67
+ },
68
+ token: 'test-token'
94
69
  };
70
+ // Helper functions
95
71
  const setupEditorMocks = ()=>{
96
- setupBaseMocks();
97
72
  mockOs.tmpdir.mockReturnValue('/tmp');
98
73
  mockFs.mkdir.mockResolvedValue(undefined);
99
74
  mockFs.writeFile.mockResolvedValue(undefined);
@@ -101,7 +76,6 @@ const setupEditorMocks = ()=>{
101
76
  mockExecaSync.mockReturnValue(undefined);
102
77
  };
103
78
  const setupWatchMocks = ()=>{
104
- setupBaseMocks();
105
79
  mockOs.tmpdir.mockReturnValue('/tmp');
106
80
  mockFs.mkdir.mockResolvedValue(undefined);
107
81
  mockFs.writeFile.mockResolvedValue(undefined);
@@ -171,7 +145,7 @@ describe('#documents:create', ()=>{
171
145
  _type: 'post',
172
146
  title: 'Test Post'
173
147
  };
174
- const mockTransaction = {
148
+ const mockTransaction = vi.fn().mockReturnValue({
175
149
  commit: vi.fn().mockResolvedValue({
176
150
  results: [
177
151
  {
@@ -180,26 +154,23 @@ describe('#documents:create', ()=>{
180
154
  }
181
155
  ]
182
156
  })
183
- };
184
- mockGetCliConfig.mockResolvedValue({
185
- api: {
186
- dataset: testDataset,
187
- projectId: testProjectId
188
- }
189
157
  });
190
- const mockClient = {
191
- transaction: vi.fn().mockReturnValue(mockTransaction)
192
- };
193
- mockGetProjectCliClient.mockResolvedValue(mockClient);
158
+ mockGetProjectCliClient.mockResolvedValue({
159
+ transaction: mockTransaction
160
+ });
194
161
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDoc));
195
162
  mockJson5.parse.mockReturnValue(mockDoc);
196
163
  const { stdout } = await testCommand(CreateDocumentCommand, [
197
164
  'test-doc.json'
198
- ]);
165
+ ], {
166
+ mocks: {
167
+ ...defaultMocks
168
+ }
169
+ });
199
170
  expect(stdout).toContain('Created:');
200
171
  expect(stdout).toContain('test-doc');
201
172
  expect(mockFs.readFile).toHaveBeenCalledWith(path.resolve(process.cwd(), 'test-doc.json'), 'utf8');
202
- expect(mockClient.transaction).toHaveBeenCalledWith([
173
+ expect(mockTransaction).toHaveBeenCalledWith([
203
174
  {
204
175
  create: mockDoc
205
176
  }
@@ -211,7 +182,7 @@ describe('#documents:create', ()=>{
211
182
  _type: 'post',
212
183
  title: 'Test Post'
213
184
  };
214
- const mockTransaction = {
185
+ const mockTransaction = vi.fn().mockReturnValue({
215
186
  commit: vi.fn().mockResolvedValue({
216
187
  results: [
217
188
  {
@@ -220,26 +191,23 @@ describe('#documents:create', ()=>{
220
191
  }
221
192
  ]
222
193
  })
223
- };
224
- mockGetCliConfig.mockResolvedValue({
225
- api: {
226
- dataset: testDataset,
227
- projectId: testProjectId
228
- }
229
194
  });
230
- const mockClient = {
231
- transaction: vi.fn().mockReturnValue(mockTransaction)
232
- };
233
- mockGetProjectCliClient.mockResolvedValue(mockClient);
195
+ mockGetProjectCliClient.mockResolvedValue({
196
+ transaction: mockTransaction
197
+ });
234
198
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDoc));
235
199
  mockJson5.parse.mockReturnValue(mockDoc);
236
200
  const { stdout } = await testCommand(CreateDocumentCommand, [
237
201
  'test-doc.json',
238
202
  '--replace'
239
- ]);
203
+ ], {
204
+ mocks: {
205
+ ...defaultMocks
206
+ }
207
+ });
240
208
  expect(stdout).toContain('Upserted:');
241
209
  expect(stdout).toContain('test-doc');
242
- expect(mockClient.transaction).toHaveBeenCalledWith([
210
+ expect(mockTransaction).toHaveBeenCalledWith([
243
211
  {
244
212
  createOrReplace: mockDoc
245
213
  }
@@ -251,7 +219,7 @@ describe('#documents:create', ()=>{
251
219
  _type: 'post',
252
220
  title: 'Test Post'
253
221
  };
254
- const mockTransaction = {
222
+ const mockTransaction = vi.fn().mockReturnValue({
255
223
  commit: vi.fn().mockResolvedValue({
256
224
  results: [
257
225
  {
@@ -260,64 +228,55 @@ describe('#documents:create', ()=>{
260
228
  }
261
229
  ]
262
230
  })
263
- };
264
- mockGetCliConfig.mockResolvedValue({
265
- api: {
266
- dataset: testDataset,
267
- projectId: testProjectId
268
- }
269
231
  });
270
- const mockClient = {
271
- transaction: vi.fn().mockReturnValue(mockTransaction)
272
- };
273
- mockGetProjectCliClient.mockResolvedValue(mockClient);
232
+ mockGetProjectCliClient.mockResolvedValue({
233
+ transaction: mockTransaction
234
+ });
274
235
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDoc));
275
236
  mockJson5.parse.mockReturnValue(mockDoc);
276
237
  const { stdout } = await testCommand(CreateDocumentCommand, [
277
238
  'test-doc.json',
278
239
  '--missing'
279
- ]);
240
+ ], {
241
+ mocks: {
242
+ ...defaultMocks
243
+ }
244
+ });
280
245
  expect(stdout).toContain('Skipped (already exists):');
281
246
  expect(stdout).toContain('test-doc');
282
- expect(mockClient.transaction).toHaveBeenCalledWith([
247
+ expect(mockTransaction).toHaveBeenCalledWith([
283
248
  {
284
249
  createIfNotExists: mockDoc
285
250
  }
286
251
  ]);
287
252
  });
288
253
  test('opens editor when no file specified and creates document from editor content', withEditorEnv(async ()=>{
289
- mockGetCliConfig.mockResolvedValue({
290
- api: {
291
- dataset: testDataset,
292
- projectId: testProjectId
293
- }
254
+ const mockTransaction = vi.fn().mockReturnValue({
255
+ commit: vi.fn().mockResolvedValue({
256
+ results: [
257
+ {
258
+ id: 'generated-id',
259
+ operation: 'create'
260
+ }
261
+ ]
262
+ })
294
263
  });
295
- const mockClient = {
264
+ mockGetProjectCliClient.mockResolvedValue({
296
265
  getDocument: vi.fn().mockResolvedValue(null),
297
- transaction: vi.fn().mockReturnValue({
298
- commit: vi.fn().mockResolvedValue({
299
- results: [
300
- {
301
- id: 'generated-id',
302
- operation: 'create'
303
- }
304
- ]
305
- })
306
- })
307
- };
308
- mockGetProjectCliClient.mockResolvedValue(mockClient);
309
- mockOs.tmpdir.mockReturnValue('/tmp');
310
- mockFs.mkdir.mockResolvedValue(undefined);
311
- mockFs.writeFile.mockResolvedValue(undefined);
266
+ transaction: mockTransaction
267
+ });
268
+ setupEditorMocks();
312
269
  mockFs.readFile.mockResolvedValue('{"_id": "generated-id", "_type": "updated-type"}');
313
- mockFs.unlink.mockResolvedValue(undefined);
314
270
  mockJson5.stringify.mockReturnValue('{"_id": "generated-id", "_type": "specify-me"}');
315
271
  mockJson5.parse.mockReturnValue({
316
272
  _id: 'generated-id',
317
273
  _type: 'updated-type'
318
274
  });
319
- mockExecaSync.mockReturnValue(undefined);
320
- const { stdout } = await testCommand(CreateDocumentCommand, []);
275
+ const { stdout } = await testCommand(CreateDocumentCommand, [], {
276
+ mocks: {
277
+ ...defaultMocks
278
+ }
279
+ });
321
280
  expect(stdout).toContain('Created:');
322
281
  expect(mockFs.mkdir).toHaveBeenCalledWith('/tmp/sanity-cli', {
323
282
  mode: 0o700,
@@ -331,76 +290,104 @@ describe('#documents:create', ()=>{
331
290
  _type: 'post',
332
291
  title: 'Test Post'
333
292
  };
334
- setupMocks();
293
+ const mockTransaction = vi.fn().mockReturnValue({
294
+ commit: vi.fn().mockResolvedValue({
295
+ results: [
296
+ {
297
+ id: 'test-doc',
298
+ operation: 'create'
299
+ }
300
+ ]
301
+ })
302
+ });
303
+ mockGetProjectCliClient.mockResolvedValue({
304
+ transaction: mockTransaction
305
+ });
335
306
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDoc));
336
307
  mockJson5.parse.mockReturnValue(mockDoc);
337
308
  const { stdout } = await testCommand(CreateDocumentCommand, [
338
309
  'test-doc.json',
339
310
  '--dataset',
340
311
  'staging'
341
- ]);
312
+ ], {
313
+ mocks: {
314
+ ...defaultMocks
315
+ }
316
+ });
342
317
  expect(stdout).toContain('Created:');
343
318
  expect(mockGetProjectCliClient).toHaveBeenCalledWith(expect.objectContaining({
344
319
  dataset: 'staging'
345
320
  }));
346
321
  });
347
322
  test('throws error when both --replace and --missing flags are used', async ()=>{
348
- setupBaseMocks();
349
323
  const { error } = await testCommand(CreateDocumentCommand, [
350
324
  'test-doc.json',
351
325
  '--replace',
352
326
  '--missing'
353
- ]);
327
+ ], {
328
+ mocks: defaultMocks
329
+ });
354
330
  expect(error).toBeInstanceOf(Error);
355
331
  expect(error?.message).toContain('Cannot use both --replace and --missing');
356
332
  expect(error?.oclif?.exit).toBe(1);
357
333
  });
358
334
  test('throws error when --id and file path are both provided', async ()=>{
359
- setupBaseMocks();
360
335
  const { error } = await testCommand(CreateDocumentCommand, [
361
336
  'test-doc.json',
362
337
  '--id',
363
338
  'myDocId'
364
- ]);
339
+ ], {
340
+ mocks: defaultMocks
341
+ });
365
342
  expect(error).toBeInstanceOf(Error);
366
343
  expect(error?.message).toContain('Cannot use --id when specifying a file path');
367
344
  expect(error?.oclif?.exit).toBe(1);
368
345
  });
369
346
  test('throws error when no project ID is configured', async ()=>{
370
- mockGetCliConfig.mockResolvedValue({
371
- api: {
372
- dataset: 'production',
373
- projectId: undefined
374
- }
375
- });
376
347
  const { error } = await testCommand(CreateDocumentCommand, [
377
348
  'test-doc.json'
378
- ]);
349
+ ], {
350
+ mocks: {
351
+ ...defaultMocks,
352
+ cliConfig: {
353
+ api: {
354
+ dataset: 'production',
355
+ projectId: undefined
356
+ }
357
+ }
358
+ }
359
+ });
379
360
  expect(error).toBeInstanceOf(Error);
380
361
  expect(error?.message).toEqual(NO_PROJECT_ID);
381
362
  expect(error?.oclif?.exit).toBe(1);
382
363
  });
383
364
  test('throws error when no dataset is configured and none provided', async ()=>{
384
- mockGetCliConfig.mockResolvedValue({
385
- api: {
386
- dataset: undefined,
387
- projectId: testProjectId
388
- }
389
- });
390
365
  const { error } = await testCommand(CreateDocumentCommand, [
391
366
  'test-doc.json'
392
- ]);
367
+ ], {
368
+ mocks: {
369
+ ...defaultMocks,
370
+ cliConfig: {
371
+ api: {
372
+ dataset: undefined,
373
+ projectId: testProjectId
374
+ }
375
+ }
376
+ }
377
+ });
393
378
  expect(error).toBeInstanceOf(Error);
394
379
  expect(error?.message).toContain('No dataset specified');
395
380
  expect(error?.oclif?.exit).toBe(1);
396
381
  });
397
382
  test('displays error message when file cannot be read', async ()=>{
398
- setupBaseMocks();
399
- mockGetProjectCliClient.mockResolvedValue({});
400
383
  mockFs.readFile.mockRejectedValue(new Error('File not found'));
401
384
  const { error } = await testCommand(CreateDocumentCommand, [
402
385
  'nonexistent.json'
403
- ]);
386
+ ], {
387
+ mocks: {
388
+ ...defaultMocks
389
+ }
390
+ });
404
391
  expect(error).toBeInstanceOf(Error);
405
392
  expect(error?.message).toContain('Failed to create documents');
406
393
  expect(error?.oclif?.exit).toBe(1);
@@ -410,52 +397,48 @@ describe('#documents:create', ()=>{
410
397
  title: 'Test Post'
411
398
  } // Missing _type
412
399
  ;
413
- setupBaseMocks();
414
- mockGetProjectCliClient.mockResolvedValue({});
415
400
  mockFs.readFile.mockResolvedValue(JSON.stringify(invalidDoc));
416
401
  mockJson5.parse.mockReturnValue(invalidDoc);
417
402
  const { error } = await testCommand(CreateDocumentCommand, [
418
403
  'invalid-doc.json'
419
- ]);
404
+ ], {
405
+ mocks: {
406
+ ...defaultMocks
407
+ }
408
+ });
420
409
  expect(error).toBeInstanceOf(Error);
421
410
  expect(error?.message).toContain('Failed to create documents');
422
411
  expect(error?.oclif?.exit).toBe(1);
423
412
  });
424
413
  test('uses JSON5 when --json5 flag is provided', withEditorEnv(async ()=>{
425
- mockGetCliConfig.mockResolvedValue({
426
- api: {
427
- dataset: testDataset,
428
- projectId: testProjectId
429
- }
414
+ const mockTransaction = vi.fn().mockReturnValue({
415
+ commit: vi.fn().mockResolvedValue({
416
+ results: [
417
+ {
418
+ id: 'generated-id',
419
+ operation: 'create'
420
+ }
421
+ ]
422
+ })
430
423
  });
431
- const mockClient = {
424
+ mockGetProjectCliClient.mockResolvedValue({
432
425
  getDocument: vi.fn().mockResolvedValue(null),
433
- transaction: vi.fn().mockReturnValue({
434
- commit: vi.fn().mockResolvedValue({
435
- results: [
436
- {
437
- id: 'generated-id',
438
- operation: 'create'
439
- }
440
- ]
441
- })
442
- })
443
- };
444
- mockGetProjectCliClient.mockResolvedValue(mockClient);
445
- mockOs.tmpdir.mockReturnValue('/tmp');
446
- mockFs.mkdir.mockResolvedValue(undefined);
447
- mockFs.writeFile.mockResolvedValue(undefined);
426
+ transaction: mockTransaction
427
+ });
428
+ setupEditorMocks();
448
429
  mockFs.readFile.mockResolvedValue('{"_id": "generated-id", "_type": "updated-type"}');
449
- mockFs.unlink.mockResolvedValue(undefined);
450
430
  mockJson5.stringify.mockReturnValue('{"_id": "generated-id", "_type": "specify-me"}');
451
431
  mockJson5.parse.mockReturnValue({
452
432
  _id: 'generated-id',
453
433
  _type: 'updated-type'
454
434
  });
455
- mockExecaSync.mockReturnValue(undefined);
456
435
  await testCommand(CreateDocumentCommand, [
457
436
  '--json5'
458
- ]);
437
+ ], {
438
+ mocks: {
439
+ ...defaultMocks
440
+ }
441
+ });
459
442
  expect(mockJson5.stringify).toHaveBeenCalled();
460
443
  expect(mockFs.writeFile).toHaveBeenCalledWith(expect.stringContaining('.json5'), expect.any(String), {
461
444
  encoding: 'utf8',
@@ -528,12 +511,28 @@ describe('#documents:create', ()=>{
528
511
  'Document _id cannot be longer than 200 characters'
529
512
  ]
530
513
  ])('validates %s', async (description, doc, expectedErrorSubstring)=>{
531
- setupMocks();
514
+ const mockTransaction = vi.fn().mockReturnValue({
515
+ commit: vi.fn().mockResolvedValue({
516
+ results: [
517
+ {
518
+ id: 'test-doc',
519
+ operation: 'create'
520
+ }
521
+ ]
522
+ })
523
+ });
524
+ mockGetProjectCliClient.mockResolvedValue({
525
+ transaction: mockTransaction
526
+ });
532
527
  mockFs.readFile.mockResolvedValue(JSON.stringify(doc));
533
528
  mockJson5.parse.mockReturnValue(doc);
534
529
  const { error } = await testCommand(CreateDocumentCommand, [
535
530
  'invalid-doc.json'
536
- ]);
531
+ ], {
532
+ mocks: {
533
+ ...defaultMocks
534
+ }
535
+ });
537
536
  expect(error).toBeInstanceOf(Error);
538
537
  expect(error?.message).toContain(expectedErrorSubstring);
539
538
  expect(error?.oclif?.exit).toBe(1);
@@ -566,12 +565,28 @@ describe('#documents:create', ()=>{
566
565
  'Document at index 1 must have a `_type` property of type string'
567
566
  ]
568
567
  ])('validates %s', async (description, docs, expectedErrorSubstring)=>{
569
- setupMocks();
568
+ const mockTransaction = vi.fn().mockReturnValue({
569
+ commit: vi.fn().mockResolvedValue({
570
+ results: [
571
+ {
572
+ id: 'test-doc',
573
+ operation: 'create'
574
+ }
575
+ ]
576
+ })
577
+ });
578
+ mockGetProjectCliClient.mockResolvedValue({
579
+ transaction: mockTransaction
580
+ });
570
581
  mockFs.readFile.mockResolvedValue(JSON.stringify(docs));
571
582
  mockJson5.parse.mockReturnValue(docs);
572
583
  const { error } = await testCommand(CreateDocumentCommand, [
573
584
  'invalid-docs.json'
574
- ]);
585
+ ], {
586
+ mocks: {
587
+ ...defaultMocks
588
+ }
589
+ });
575
590
  expect(error).toBeInstanceOf(Error);
576
591
  expect(error?.message).toContain(expectedErrorSubstring);
577
592
  expect(error?.oclif?.exit).toBe(1);
@@ -585,29 +600,32 @@ describe('#documents:create', ()=>{
585
600
  _updatedAt: '2024-01-02T00:00:00Z',
586
601
  title: 'Test Post'
587
602
  };
588
- setupMocks();
589
- const mockClient = {
590
- transaction: vi.fn().mockReturnValue({
591
- commit: vi.fn().mockResolvedValue({
592
- results: [
593
- {
594
- id: 'test-doc',
595
- operation: 'create'
596
- }
597
- ]
598
- })
603
+ const mockTransaction = vi.fn().mockReturnValue({
604
+ commit: vi.fn().mockResolvedValue({
605
+ results: [
606
+ {
607
+ id: 'test-doc',
608
+ operation: 'create'
609
+ }
610
+ ]
599
611
  })
600
- };
601
- mockGetProjectCliClient.mockResolvedValue(mockClient);
612
+ });
613
+ mockGetProjectCliClient.mockResolvedValue({
614
+ transaction: mockTransaction
615
+ });
602
616
  mockFs.readFile.mockResolvedValue(JSON.stringify(docWithReservedFields));
603
617
  mockJson5.parse.mockReturnValue(docWithReservedFields);
604
618
  // Should not throw error, but should proceed with document creation
605
619
  const { stdout } = await testCommand(CreateDocumentCommand, [
606
620
  'doc.json'
607
- ]);
621
+ ], {
622
+ mocks: {
623
+ ...defaultMocks
624
+ }
625
+ });
608
626
  expect(stdout).toContain('Created:');
609
627
  expect(stdout).toContain('test-doc');
610
- expect(mockClient.transaction).toHaveBeenCalledWith([
628
+ expect(mockTransaction).toHaveBeenCalledWith([
611
629
  {
612
630
  create: docWithReservedFields
613
631
  }
@@ -615,12 +633,28 @@ describe('#documents:create', ()=>{
615
633
  });
616
634
  test('validates empty document array throws error', async ()=>{
617
635
  const emptyArray = [];
618
- setupMocks();
636
+ const mockTransaction = vi.fn().mockReturnValue({
637
+ commit: vi.fn().mockResolvedValue({
638
+ results: [
639
+ {
640
+ id: 'test-doc',
641
+ operation: 'create'
642
+ }
643
+ ]
644
+ })
645
+ });
646
+ mockGetProjectCliClient.mockResolvedValue({
647
+ transaction: mockTransaction
648
+ });
619
649
  mockFs.readFile.mockResolvedValue(JSON.stringify(emptyArray));
620
650
  mockJson5.parse.mockReturnValue(emptyArray);
621
651
  const { error } = await testCommand(CreateDocumentCommand, [
622
652
  'empty-docs.json'
623
- ]);
653
+ ], {
654
+ mocks: {
655
+ ...defaultMocks
656
+ }
657
+ });
624
658
  expect(error).toBeInstanceOf(Error);
625
659
  expect(error?.message).toContain('No documents provided');
626
660
  expect(error?.oclif?.exit).toBe(1);
@@ -656,7 +690,7 @@ describe('#documents:create', ()=>{
656
690
  title: 'Post 2'
657
691
  }
658
692
  ];
659
- const mockTransaction = {
693
+ const mockTransaction = vi.fn().mockReturnValue({
660
694
  commit: vi.fn().mockResolvedValue({
661
695
  results: [
662
696
  {
@@ -669,26 +703,28 @@ describe('#documents:create', ()=>{
669
703
  }
670
704
  ]
671
705
  })
672
- };
673
- setupMocks();
674
- const mockClient = {
675
- transaction: vi.fn().mockReturnValue(mockTransaction)
676
- };
677
- mockGetProjectCliClient.mockResolvedValue(mockClient);
706
+ });
707
+ mockGetProjectCliClient.mockResolvedValue({
708
+ transaction: mockTransaction
709
+ });
678
710
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDocs));
679
711
  mockJson5.parse.mockReturnValue(mockDocs);
680
712
  const args = [
681
713
  'docs.json'
682
714
  ];
683
715
  if (flag !== 'create') args.push(`--${flag}`);
684
- const { stdout } = await testCommand(CreateDocumentCommand, args);
716
+ const { stdout } = await testCommand(CreateDocumentCommand, args, {
717
+ mocks: {
718
+ ...defaultMocks
719
+ }
720
+ });
685
721
  expect(stdout).toContain(expectedMessage);
686
722
  expect(stdout).toContain('doc1');
687
723
  expect(stdout).toContain('doc2');
688
724
  const expectedMutations = mockDocs.map((doc)=>({
689
725
  [operation]: doc
690
726
  }));
691
- expect(mockClient.transaction).toHaveBeenCalledWith(expectedMutations);
727
+ expect(mockTransaction).toHaveBeenCalledWith(expectedMutations);
692
728
  });
693
729
  test('handles mixed results for createIfNotExists', async ()=>{
694
730
  const mockDocs = [
@@ -708,7 +744,7 @@ describe('#documents:create', ()=>{
708
744
  title: 'Post 3'
709
745
  }
710
746
  ];
711
- const mockTransaction = {
747
+ const mockTransaction = vi.fn().mockReturnValue({
712
748
  commit: vi.fn().mockResolvedValue({
713
749
  results: [
714
750
  {
@@ -725,18 +761,20 @@ describe('#documents:create', ()=>{
725
761
  }
726
762
  ]
727
763
  })
728
- };
729
- setupMocks();
730
- const mockClient = {
731
- transaction: vi.fn().mockReturnValue(mockTransaction)
732
- };
733
- mockGetProjectCliClient.mockResolvedValue(mockClient);
764
+ });
765
+ mockGetProjectCliClient.mockResolvedValue({
766
+ transaction: mockTransaction
767
+ });
734
768
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDocs));
735
769
  mockJson5.parse.mockReturnValue(mockDocs);
736
770
  const { stdout } = await testCommand(CreateDocumentCommand, [
737
771
  'docs.json',
738
772
  '--missing'
739
- ]);
773
+ ], {
774
+ mocks: {
775
+ ...defaultMocks
776
+ }
777
+ });
740
778
  expect(stdout).toContain('Created:');
741
779
  expect(stdout).toContain('doc1');
742
780
  expect(stdout).toContain('doc3');
@@ -751,20 +789,21 @@ describe('#documents:create', ()=>{
751
789
  _type: 'post',
752
790
  title: 'Existing Post'
753
791
  };
754
- const mockClient = {
755
- getDocument: vi.fn().mockResolvedValue(existingDoc),
756
- transaction: vi.fn().mockReturnValue({
757
- commit: vi.fn().mockResolvedValue({
758
- results: [
759
- {
760
- id: 'existing-doc',
761
- operation: 'update'
762
- }
763
- ]
764
- })
792
+ const mockTransaction = vi.fn().mockReturnValue({
793
+ commit: vi.fn().mockResolvedValue({
794
+ results: [
795
+ {
796
+ id: 'existing-doc',
797
+ operation: 'update'
798
+ }
799
+ ]
765
800
  })
766
- };
767
- mockGetProjectCliClient.mockResolvedValue(mockClient);
801
+ });
802
+ const mockGetDocument = vi.fn().mockResolvedValue(existingDoc);
803
+ mockGetProjectCliClient.mockResolvedValue({
804
+ getDocument: mockGetDocument,
805
+ transaction: mockTransaction
806
+ });
768
807
  setupEditorMocks();
769
808
  mockFs.readFile.mockResolvedValue(JSON.stringify({
770
809
  ...existingDoc,
@@ -778,19 +817,23 @@ describe('#documents:create', ()=>{
778
817
  const { stdout } = await testCommand(CreateDocumentCommand, [
779
818
  '--id',
780
819
  'existing-doc'
781
- ]);
782
- expect(mockClient.getDocument).toHaveBeenCalledWith('existing-doc');
820
+ ], {
821
+ mocks: {
822
+ ...defaultMocks
823
+ }
824
+ });
825
+ expect(mockGetDocument).toHaveBeenCalledWith('existing-doc');
783
826
  expect(mockFs.writeFile).toHaveBeenCalledWith(expect.stringContaining('existing-doc.json'), JSON.stringify(existingDoc, null, 2), expect.objectContaining({
784
827
  mode: 0o600
785
828
  }));
786
829
  expect(stdout).toContain('Created:');
787
830
  }));
788
831
  test('handles no changes made in editor', withEditorEnv(async ()=>{
789
- const mockClient = {
832
+ const mockTransaction = vi.fn();
833
+ mockGetProjectCliClient.mockResolvedValue({
790
834
  getDocument: vi.fn().mockResolvedValue(null),
791
- transaction: vi.fn()
792
- };
793
- mockGetProjectCliClient.mockResolvedValue(mockClient);
835
+ transaction: mockTransaction
836
+ });
794
837
  setupEditorMocks();
795
838
  // Set up a predictable UUID so the test can verify no changes were made
796
839
  const testUuid = '123e4567-e89b-12d3-a456-426614174000';
@@ -806,9 +849,13 @@ describe('#documents:create', ()=>{
806
849
  mockFs.readFile.mockResolvedValue(writeFileContent);
807
850
  // Return the exact same object structure that was written
808
851
  mockJson5.parse.mockReturnValue(defaultDoc);
809
- await testCommand(CreateDocumentCommand, []);
852
+ await testCommand(CreateDocumentCommand, [], {
853
+ mocks: {
854
+ ...defaultMocks
855
+ }
856
+ });
810
857
  // The key test - transaction should not have been called since no changes were made
811
- expect(mockClient.transaction).not.toHaveBeenCalled();
858
+ expect(mockTransaction).not.toHaveBeenCalled();
812
859
  }));
813
860
  test('handles write error with already exists hint', withEditorEnv(async ()=>{
814
861
  const mockDoc = {
@@ -816,13 +863,13 @@ describe('#documents:create', ()=>{
816
863
  _type: 'post',
817
864
  title: 'Test Post'
818
865
  };
819
- const mockClient = {
866
+ const mockTransaction = vi.fn().mockReturnValue({
867
+ commit: vi.fn().mockRejectedValue(new Error('Document already exists'))
868
+ });
869
+ mockGetProjectCliClient.mockResolvedValue({
820
870
  getDocument: vi.fn().mockResolvedValue(null),
821
- transaction: vi.fn().mockReturnValue({
822
- commit: vi.fn().mockRejectedValue(new Error('Document already exists'))
823
- })
824
- };
825
- mockGetProjectCliClient.mockResolvedValue(mockClient);
871
+ transaction: mockTransaction
872
+ });
826
873
  setupEditorMocks();
827
874
  mockFs.readFile.mockResolvedValue(JSON.stringify(mockDoc));
828
875
  mockJson5.parse.mockReturnValue(mockDoc);
@@ -830,7 +877,11 @@ describe('#documents:create', ()=>{
830
877
  _id: 'test-doc',
831
878
  _type: 'specify-me'
832
879
  }, null, 2));
833
- const { error } = await testCommand(CreateDocumentCommand, []);
880
+ const { error } = await testCommand(CreateDocumentCommand, [], {
881
+ mocks: {
882
+ ...defaultMocks
883
+ }
884
+ });
834
885
  expect(error).toBeInstanceOf(Error);
835
886
  expect(error?.message).toContain('Failed to write documents: Document already exists');
836
887
  expect(error?.message).toContain('Perhaps you want to use `--replace` or `--missing`?');
@@ -842,20 +893,20 @@ describe('#documents:create', ()=>{
842
893
  _type: 'post',
843
894
  title: 'Test Post'
844
895
  };
845
- const mockClient = {
846
- getDocument: vi.fn().mockResolvedValue(null),
847
- transaction: vi.fn().mockReturnValue({
848
- commit: vi.fn().mockResolvedValue({
849
- results: [
850
- {
851
- id: 'test-doc',
852
- operation: 'create'
853
- }
854
- ]
855
- })
896
+ const mockTransaction = vi.fn().mockReturnValue({
897
+ commit: vi.fn().mockResolvedValue({
898
+ results: [
899
+ {
900
+ id: 'test-doc',
901
+ operation: 'create'
902
+ }
903
+ ]
856
904
  })
857
- };
858
- mockGetProjectCliClient.mockResolvedValue(mockClient);
905
+ });
906
+ mockGetProjectCliClient.mockResolvedValue({
907
+ getDocument: vi.fn().mockResolvedValue(null),
908
+ transaction: mockTransaction
909
+ });
859
910
  setupEditorMocks();
860
911
  // Mock unlink to throw an error (should be caught silently)
861
912
  mockFs.unlink.mockRejectedValue(new Error('Permission denied'));
@@ -865,7 +916,11 @@ describe('#documents:create', ()=>{
865
916
  _id: 'test-doc',
866
917
  _type: 'specify-me'
867
918
  }, null, 2));
868
- const { stdout } = await testCommand(CreateDocumentCommand, []);
919
+ const { stdout } = await testCommand(CreateDocumentCommand, [], {
920
+ mocks: {
921
+ ...defaultMocks
922
+ }
923
+ });
869
924
  // Should still succeed despite file cleanup error
870
925
  expect(stdout).toContain('Created:');
871
926
  expect(stdout).toContain('test-doc');
@@ -878,20 +933,20 @@ describe('#documents:create', ()=>{
878
933
  on: vi.fn().mockReturnThis()
879
934
  };
880
935
  mockChokidarWatch.mockReturnValue(mockWatcher);
881
- const mockClient = {
882
- getDocument: vi.fn().mockResolvedValue(null),
883
- transaction: vi.fn().mockReturnValue({
884
- commit: vi.fn().mockResolvedValue({
885
- results: [
886
- {
887
- id: 'test-doc',
888
- operation: 'create'
889
- }
890
- ]
891
- })
936
+ const mockTransaction = vi.fn().mockReturnValue({
937
+ commit: vi.fn().mockResolvedValue({
938
+ results: [
939
+ {
940
+ id: 'test-doc',
941
+ operation: 'create'
942
+ }
943
+ ]
892
944
  })
893
- };
894
- mockGetProjectCliClient.mockResolvedValue(mockClient);
945
+ });
946
+ mockGetProjectCliClient.mockResolvedValue({
947
+ getDocument: vi.fn().mockResolvedValue(null),
948
+ transaction: mockTransaction
949
+ });
895
950
  setupWatchMocks();
896
951
  mockJson5.stringify.mockReturnValue(JSON.stringify({
897
952
  _id: 'test-doc',
@@ -900,7 +955,11 @@ describe('#documents:create', ()=>{
900
955
  mockExeca.mockResolvedValue({});
901
956
  const { stdout } = await testCommand(CreateDocumentCommand, [
902
957
  '--watch'
903
- ]);
958
+ ], {
959
+ mocks: {
960
+ ...defaultMocks
961
+ }
962
+ });
904
963
  expect(stdout).toContain('Watch mode:');
905
964
  expect(stdout).toContain('Will write documents on each save.');
906
965
  expect(stdout).toContain('Press Ctrl + C to cancel watch mode.');
@@ -926,20 +985,20 @@ describe('#documents:create', ()=>{
926
985
  })
927
986
  };
928
987
  mockChokidarWatch.mockReturnValue(mockWatcher);
929
- const mockClient = {
930
- getDocument: vi.fn().mockResolvedValue(null),
931
- transaction: vi.fn().mockReturnValue({
932
- commit: vi.fn().mockResolvedValue({
933
- results: [
934
- {
935
- id: 'test-doc',
936
- operation: 'create'
937
- }
938
- ]
939
- })
988
+ const mockTransaction = vi.fn().mockReturnValue({
989
+ commit: vi.fn().mockResolvedValue({
990
+ results: [
991
+ {
992
+ id: 'test-doc',
993
+ operation: 'create'
994
+ }
995
+ ]
940
996
  })
941
- };
942
- mockGetProjectCliClient.mockResolvedValue(mockClient);
997
+ });
998
+ mockGetProjectCliClient.mockResolvedValue({
999
+ getDocument: vi.fn().mockResolvedValue(null),
1000
+ transaction: mockTransaction
1001
+ });
943
1002
  setupWatchMocks();
944
1003
  mockJson5.stringify.mockReturnValue(JSON.stringify({
945
1004
  _id: 'test-doc',
@@ -951,11 +1010,15 @@ describe('#documents:create', ()=>{
951
1010
  mockJson5.parse.mockReturnValue(mockDoc);
952
1011
  await testCommand(CreateDocumentCommand, [
953
1012
  '--watch'
954
- ]);
1013
+ ], {
1014
+ mocks: {
1015
+ ...defaultMocks
1016
+ }
1017
+ });
955
1018
  // Simulate file change
956
1019
  expect(changeHandler).toBeDefined();
957
1020
  await changeHandler();
958
- expect(mockClient.transaction).toHaveBeenCalledWith([
1021
+ expect(mockTransaction).toHaveBeenCalledWith([
959
1022
  {
960
1023
  create: mockDoc
961
1024
  }