@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.
- package/dist/actions/dev/startStudioDevServer.js +3 -8
- package/dist/actions/dev/startStudioDevServer.js.map +1 -1
- package/dist/actions/dev/types.d.ts +1 -3
- package/dist/actions/dev/types.js.map +1 -1
- package/dist/actions/documents/validate.d.ts +0 -2
- package/dist/actions/documents/validate.js +21 -1
- package/dist/actions/documents/validate.js.map +1 -1
- package/dist/actions/exec/execScript.js +1 -1
- package/dist/actions/exec/execScript.js.map +1 -1
- package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js +1 -1
- package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js.map +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.js +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
- package/dist/actions/manifest/extractManifest.js +1 -4
- package/dist/actions/manifest/extractManifest.js.map +1 -1
- package/dist/actions/schema/deleteSchemaAction.d.ts +13 -5
- package/dist/actions/schema/deleteSchemaAction.js +12 -17
- package/dist/actions/schema/deleteSchemaAction.js.map +1 -1
- package/dist/actions/schema/deploySchemas.d.ts +15 -0
- package/dist/actions/schema/deploySchemas.js +98 -0
- package/dist/actions/schema/deploySchemas.js.map +1 -0
- package/dist/actions/schema/listSchemas.d.ts +12 -0
- package/dist/actions/schema/listSchemas.js +119 -0
- package/dist/actions/schema/listSchemas.js.map +1 -0
- package/dist/actions/schema/schemaStoreTypes.d.ts +0 -11
- package/dist/actions/schema/schemaStoreTypes.js.map +1 -1
- package/dist/actions/schema/utils/debug.d.ts +2 -0
- package/dist/actions/schema/utils/debug.js +5 -0
- package/dist/actions/schema/utils/debug.js.map +1 -0
- package/dist/actions/schema/utils/manifestExtractor.d.ts +3 -8
- package/dist/actions/schema/utils/manifestExtractor.js +12 -17
- package/dist/actions/schema/utils/manifestExtractor.js.map +1 -1
- package/dist/actions/schema/utils/manifestReader.d.ts +2 -9
- package/dist/actions/schema/utils/manifestReader.js +6 -12
- package/dist/actions/schema/utils/manifestReader.js.map +1 -1
- package/dist/actions/schema/utils/schemaStoreOutStrings.d.ts +0 -1
- package/dist/actions/schema/utils/schemaStoreOutStrings.js +1 -1
- package/dist/actions/schema/utils/schemaStoreOutStrings.js.map +1 -1
- package/dist/actions/schema/utils/schemaStoreValidation.d.ts +10 -62
- package/dist/actions/schema/utils/schemaStoreValidation.js +38 -125
- package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
- package/dist/actions/schema/utils/uniqByProjectIdDataset.d.ts +14 -0
- package/dist/actions/schema/utils/uniqByProjectIdDataset.js +9 -0
- package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -0
- package/dist/actions/users/getMembersForProject.d.ts +1 -3
- package/dist/actions/users/getMembersForProject.js +6 -17
- package/dist/actions/users/getMembersForProject.js.map +1 -1
- package/dist/actions/users/types.d.ts +0 -11
- package/dist/actions/users/types.js.map +1 -1
- package/dist/commands/__tests__/debug.test.js +113 -220
- package/dist/commands/__tests__/debug.test.js.map +1 -1
- package/dist/commands/__tests__/deploy.test.js +325 -293
- package/dist/commands/__tests__/deploy.test.js.map +1 -1
- package/dist/commands/__tests__/dev.test.js +62 -19
- package/dist/commands/__tests__/dev.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.authentication.test.js +40 -27
- package/dist/commands/__tests__/init/init.authentication.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.create-new-project.test.js +84 -85
- package/dist/commands/__tests__/init/init.create-new-project.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.plan.test.js +103 -44
- package/dist/commands/__tests__/init/init.plan.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.setup.test.js +85 -29
- package/dist/commands/__tests__/init/init.setup.test.js.map +1 -1
- package/dist/commands/__tests__/install.test.js +46 -22
- package/dist/commands/__tests__/install.test.js.map +1 -1
- package/dist/commands/__tests__/logout.test.js +8 -5
- package/dist/commands/__tests__/logout.test.js.map +1 -1
- package/dist/commands/__tests__/manage.test.js +29 -24
- package/dist/commands/__tests__/manage.test.js.map +1 -1
- package/dist/commands/__tests__/versions.test.js +22 -14
- package/dist/commands/__tests__/versions.test.js.map +1 -1
- package/dist/commands/backup/__tests__/disable.test.js +72 -75
- package/dist/commands/backup/__tests__/disable.test.js.map +1 -1
- package/dist/commands/backup/__tests__/download.test.js +166 -77
- package/dist/commands/backup/__tests__/download.test.js.map +1 -1
- package/dist/commands/backup/__tests__/enable.test.js +109 -140
- package/dist/commands/backup/__tests__/enable.test.js.map +1 -1
- package/dist/commands/backup/__tests__/list.test.js +84 -75
- package/dist/commands/backup/__tests__/list.test.js.map +1 -1
- package/dist/commands/backup/disable.js +5 -11
- package/dist/commands/backup/disable.js.map +1 -1
- package/dist/commands/backup/enable.js +5 -11
- package/dist/commands/backup/enable.js.map +1 -1
- package/dist/commands/backup/list.js +7 -8
- package/dist/commands/backup/list.js.map +1 -1
- package/dist/commands/cors/__tests__/add.test.js +68 -38
- package/dist/commands/cors/__tests__/add.test.js.map +1 -1
- package/dist/commands/cors/__tests__/delete.test.js +52 -37
- package/dist/commands/cors/__tests__/delete.test.js.map +1 -1
- package/dist/commands/cors/__tests__/list.test.js +80 -57
- package/dist/commands/cors/__tests__/list.test.js.map +1 -1
- package/dist/commands/cors/add.js +5 -13
- package/dist/commands/cors/add.js.map +1 -1
- package/dist/commands/cors/delete.js +7 -15
- package/dist/commands/cors/delete.js.map +1 -1
- package/dist/commands/cors/list.js +2 -10
- package/dist/commands/cors/list.js.map +1 -1
- package/dist/commands/dataset/__tests__/copy.test.js +197 -89
- package/dist/commands/dataset/__tests__/copy.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/create.test.js +147 -117
- package/dist/commands/dataset/__tests__/create.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/delete.test.js +75 -68
- package/dist/commands/dataset/__tests__/delete.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/export.test.js +123 -83
- package/dist/commands/dataset/__tests__/export.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/list.test.js +107 -65
- package/dist/commands/dataset/__tests__/list.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/create.test.js +114 -74
- package/dist/commands/dataset/alias/__tests__/create.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/delete.test.js +40 -29
- package/dist/commands/dataset/alias/__tests__/delete.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/link.test.js +114 -74
- package/dist/commands/dataset/alias/__tests__/link.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/unlink.test.js +44 -29
- package/dist/commands/dataset/alias/__tests__/unlink.test.js.map +1 -1
- package/dist/commands/dataset/export.js +4 -4
- package/dist/commands/dataset/export.js.map +1 -1
- package/dist/commands/dataset/visibility/__tests__/get.test.js +48 -67
- package/dist/commands/dataset/visibility/__tests__/get.test.js.map +1 -1
- package/dist/commands/dataset/visibility/__tests__/set.test.js +76 -123
- package/dist/commands/dataset/visibility/__tests__/set.test.js.map +1 -1
- package/dist/commands/dev.js +0 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/docs/__tests__/search.test.js +8 -7
- package/dist/commands/docs/__tests__/search.test.js.map +1 -1
- package/dist/commands/documents/__tests__/create.test.js +328 -265
- package/dist/commands/documents/__tests__/create.test.js.map +1 -1
- package/dist/commands/documents/__tests__/delete.test.js +119 -87
- package/dist/commands/documents/__tests__/delete.test.js.map +1 -1
- package/dist/commands/documents/__tests__/get.test.js +68 -95
- package/dist/commands/documents/__tests__/get.test.js.map +1 -1
- package/dist/commands/documents/__tests__/query.test.js +84 -189
- package/dist/commands/documents/__tests__/query.test.js.map +1 -1
- package/dist/commands/documents/__tests__/validate.test.js +52 -29
- package/dist/commands/documents/__tests__/validate.test.js.map +1 -1
- package/dist/commands/documents/create.d.ts +1 -0
- package/dist/commands/documents/create.js +10 -9
- package/dist/commands/documents/create.js.map +1 -1
- package/dist/commands/documents/delete.js +2 -3
- package/dist/commands/documents/delete.js.map +1 -1
- package/dist/commands/documents/get.js +2 -3
- package/dist/commands/documents/get.js.map +1 -1
- package/dist/commands/documents/query.js +2 -3
- package/dist/commands/documents/query.js.map +1 -1
- package/dist/commands/documents/validate.js +0 -20
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/graphql/__tests__/list.test.js +57 -45
- package/dist/commands/graphql/__tests__/list.test.js.map +1 -1
- package/dist/commands/graphql/__tests__/undeploy.test.js +85 -59
- package/dist/commands/graphql/__tests__/undeploy.test.js.map +1 -1
- package/dist/commands/graphql/list.js +2 -2
- package/dist/commands/graphql/list.js.map +1 -1
- package/dist/commands/graphql/undeploy.js +4 -9
- package/dist/commands/graphql/undeploy.js.map +1 -1
- package/dist/commands/hook/__tests__/attempt.test.js +48 -33
- package/dist/commands/hook/__tests__/attempt.test.js.map +1 -1
- package/dist/commands/hook/__tests__/create.test.js +49 -51
- package/dist/commands/hook/__tests__/create.test.js.map +1 -1
- package/dist/commands/hook/__tests__/delete.test.js +43 -30
- package/dist/commands/hook/__tests__/delete.test.js.map +1 -1
- package/dist/commands/hook/__tests__/list.test.js +38 -31
- package/dist/commands/hook/__tests__/list.test.js.map +1 -1
- package/dist/commands/hook/__tests__/logs.test.js +68 -40
- package/dist/commands/hook/__tests__/logs.test.js.map +1 -1
- package/dist/commands/hook/create.js +2 -6
- package/dist/commands/hook/create.js.map +1 -1
- package/dist/commands/hook/delete.js +5 -17
- package/dist/commands/hook/delete.js.map +1 -1
- package/dist/commands/hook/list.js +2 -8
- package/dist/commands/hook/list.js.map +1 -1
- package/dist/commands/manifest/__tests__/extract.test.js +22 -13
- package/dist/commands/manifest/__tests__/extract.test.js.map +1 -1
- package/dist/commands/media/__tests__/create-aspect.test.js +41 -28
- package/dist/commands/media/__tests__/create-aspect.test.js.map +1 -1
- package/dist/commands/media/__tests__/delete-aspect.test.js +44 -35
- package/dist/commands/media/__tests__/delete-aspect.test.js.map +1 -1
- package/dist/commands/media/__tests__/deploy-aspect.test.js +67 -80
- package/dist/commands/media/__tests__/deploy-aspect.test.js.map +1 -1
- package/dist/commands/media/__tests__/export.test.js +365 -66
- package/dist/commands/media/__tests__/export.test.js.map +1 -1
- package/dist/commands/media/__tests__/import.test.js +171 -105
- package/dist/commands/media/__tests__/import.test.js.map +1 -1
- package/dist/commands/media/export.js +2 -2
- package/dist/commands/media/export.js.map +1 -1
- package/dist/commands/media/import.js +2 -2
- package/dist/commands/media/import.js.map +1 -1
- package/dist/commands/projects/__tests__/list.test.js +5 -4
- package/dist/commands/projects/__tests__/list.test.js.map +1 -1
- package/dist/commands/projects/list.js +2 -6
- package/dist/commands/projects/list.js.map +1 -1
- package/dist/commands/schema/__tests__/delete.test.js +396 -151
- package/dist/commands/schema/__tests__/delete.test.js.map +1 -1
- package/dist/commands/schema/__tests__/deploy.test.js +348 -0
- package/dist/commands/schema/__tests__/deploy.test.js.map +1 -0
- package/dist/commands/schema/__tests__/extract.test.js +19 -11
- package/dist/commands/schema/__tests__/extract.test.js.map +1 -1
- package/dist/commands/schema/__tests__/list.test.js +399 -0
- package/dist/commands/schema/__tests__/list.test.js.map +1 -0
- package/dist/commands/schema/__tests__/validate.test.js +27 -10
- package/dist/commands/schema/__tests__/validate.test.js.map +1 -1
- package/dist/commands/schema/delete.d.ts +1 -1
- package/dist/commands/schema/delete.js +20 -23
- package/dist/commands/schema/delete.js.map +1 -1
- package/dist/commands/schema/deploy.d.ts +16 -0
- package/dist/commands/schema/deploy.js +98 -0
- package/dist/commands/schema/deploy.js.map +1 -0
- package/dist/commands/schema/list.d.ts +15 -0
- package/dist/commands/schema/list.js +104 -0
- package/dist/commands/schema/list.js.map +1 -0
- package/dist/commands/telemetry/__tests__/disable.test.js +7 -5
- package/dist/commands/telemetry/__tests__/disable.test.js.map +1 -1
- package/dist/commands/telemetry/__tests__/enable.test.js +7 -5
- package/dist/commands/telemetry/__tests__/enable.test.js.map +1 -1
- package/dist/commands/telemetry/__tests__/status.test.js +7 -5
- package/dist/commands/telemetry/__tests__/status.test.js.map +1 -1
- package/dist/commands/tokens/__tests__/add.test.js +55 -40
- package/dist/commands/tokens/__tests__/add.test.js.map +1 -1
- package/dist/commands/tokens/__tests__/delete.test.js +72 -42
- package/dist/commands/tokens/__tests__/delete.test.js.map +1 -1
- package/dist/commands/tokens/__tests__/list.test.js +87 -60
- package/dist/commands/tokens/__tests__/list.test.js.map +1 -1
- package/dist/commands/tokens/add.js +3 -5
- package/dist/commands/tokens/add.js.map +1 -1
- package/dist/commands/users/__tests__/invite.test.js +100 -79
- package/dist/commands/users/__tests__/invite.test.js.map +1 -1
- package/dist/commands/users/__tests__/list.test.js +186 -180
- package/dist/commands/users/__tests__/list.test.js.map +1 -1
- package/dist/commands/users/invite.js +6 -17
- package/dist/commands/users/invite.js.map +1 -1
- package/dist/commands/users/list.js +4 -7
- package/dist/commands/users/list.js.map +1 -1
- package/dist/config/createCliConfig.d.ts +4 -4
- package/dist/services/backup.d.ts +8 -0
- package/dist/services/backup.js +19 -0
- package/dist/services/backup.js.map +1 -1
- package/dist/services/cors.d.ts +23 -0
- package/dist/services/cors.js +38 -0
- package/dist/services/cors.js.map +1 -0
- package/dist/services/graphql.d.ts +7 -0
- package/dist/services/graphql.js +11 -0
- package/dist/services/graphql.js.map +1 -1
- package/dist/services/hooks.d.ts +2 -0
- package/dist/services/hooks.js +19 -0
- package/dist/services/hooks.js.map +1 -1
- package/dist/services/organizations.d.ts +1 -1
- package/dist/services/organizations.js +1 -1
- package/dist/services/organizations.js.map +1 -1
- package/dist/services/projects.d.ts +11 -0
- package/dist/services/projects.js +41 -0
- package/dist/services/projects.js.map +1 -1
- package/dist/services/schemas.d.ts +4 -0
- package/dist/services/schemas.js +40 -0
- package/dist/services/schemas.js.map +1 -0
- package/dist/services/user.d.ts +8 -0
- package/dist/services/user.js +15 -2
- package/dist/services/user.js.map +1 -1
- package/dist/util/__tests__/getCliVersion.test.js +2 -2
- package/dist/util/__tests__/getCliVersion.test.js.map +1 -1
- package/dist/util/errorMessages.d.ts +1 -0
- package/dist/util/errorMessages.js +1 -0
- package/dist/util/errorMessages.js.map +1 -1
- package/dist/util/getCliVersion.js +1 -1
- package/dist/util/getCliVersion.js.map +1 -1
- package/dist/util/readPackageJson.d.ts +1 -15
- package/dist/util/readPackageJson.js +1 -1
- package/dist/util/readPackageJson.js.map +1 -1
- package/dist/util/uniqBy.d.ts +1 -0
- package/dist/util/uniqBy.js +14 -0
- package/dist/util/uniqBy.js.map +1 -0
- package/oclif.manifest.json +172 -27
- package/package.json +27 -28
- package/dist/actions/cors/constants.d.ts +0 -1
- package/dist/actions/cors/constants.js +0 -3
- package/dist/actions/cors/constants.js.map +0 -1
- package/dist/actions/cors/types.d.ts +0 -9
- package/dist/actions/cors/types.js +0 -3
- package/dist/actions/cors/types.js.map +0 -1
- package/dist/actions/schema/__tests__/deleteSchemaAction.test.js +0 -294
- package/dist/actions/schema/__tests__/deleteSchemaAction.test.js.map +0 -1
- package/dist/actions/schema/schemaStoreConstants.d.ts +0 -1
- package/dist/actions/schema/schemaStoreConstants.js +0 -4
- package/dist/actions/schema/schemaStoreConstants.js.map +0 -1
- package/dist/actions/schema/utils/schemaActionHelpers.d.ts +0 -1
- package/dist/actions/schema/utils/schemaActionHelpers.js +0 -5
- package/dist/actions/schema/utils/schemaActionHelpers.js.map +0 -1
- package/dist/actions/schema/utils/schemaApiClient.d.ts +0 -6
- package/dist/actions/schema/utils/schemaApiClient.js +0 -17
- package/dist/actions/schema/utils/schemaApiClient.js.map +0 -1
- package/dist/actions/users/apiVersion.d.ts +0 -6
- package/dist/actions/users/apiVersion.js +0 -7
- package/dist/actions/users/apiVersion.js.map +0 -1
|
@@ -2,7 +2,6 @@ import { existsSync, mkdirSync } from 'node:fs';
|
|
|
2
2
|
import { mkdir, mkdtemp, writeFile } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { runCommand } from '@oclif/test';
|
|
5
|
-
import { getCliConfig, getProjectCliClient } from '@sanity/cli-core';
|
|
6
5
|
import { confirm, input, select } from '@sanity/cli-core/ux';
|
|
7
6
|
import { mockApi, testCommand } from '@sanity/cli-test';
|
|
8
7
|
import nock from 'nock';
|
|
@@ -10,28 +9,16 @@ import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
|
10
9
|
import { BACKUP_API_VERSION } from '../../../actions/backup/constants.js';
|
|
11
10
|
import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
|
|
12
11
|
import { DownloadBackupCommand } from '../download.js';
|
|
13
|
-
vi.
|
|
14
|
-
|
|
15
|
-
directory: '/test/path',
|
|
16
|
-
root: '/test/path',
|
|
17
|
-
type: 'studio'
|
|
18
|
-
})
|
|
19
|
-
}));
|
|
20
|
-
vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', ()=>({
|
|
21
|
-
getCliConfig: vi.fn().mockResolvedValue({
|
|
22
|
-
api: {
|
|
23
|
-
projectId: 'test-project'
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
}));
|
|
27
|
-
vi.mock('../../../../../cli-core/src/services/getCliToken.js', ()=>({
|
|
28
|
-
getCliToken: vi.fn().mockResolvedValue('test-token')
|
|
29
|
-
}));
|
|
30
|
-
vi.mock(import('../../../../../cli-core/src/services/apiClient.js'), async (importOriginal)=>{
|
|
12
|
+
const mockListDatasets = vi.hoisted(()=>vi.fn());
|
|
13
|
+
vi.mock('@sanity/cli-core', async (importOriginal)=>{
|
|
31
14
|
const actual = await importOriginal();
|
|
32
15
|
return {
|
|
33
16
|
...actual,
|
|
34
|
-
getProjectCliClient: vi.fn()
|
|
17
|
+
getProjectCliClient: vi.fn().mockResolvedValue({
|
|
18
|
+
datasets: {
|
|
19
|
+
list: mockListDatasets
|
|
20
|
+
}
|
|
21
|
+
})
|
|
35
22
|
};
|
|
36
23
|
});
|
|
37
24
|
vi.mock(import('node:fs/promises'), async (importOriginal)=>{
|
|
@@ -50,30 +37,25 @@ vi.mock('@sanity/cli-core/ux', async ()=>{
|
|
|
50
37
|
select: vi.fn()
|
|
51
38
|
};
|
|
52
39
|
});
|
|
53
|
-
const mockGetProjectCliClient = vi.mocked(getProjectCliClient);
|
|
54
40
|
const mockMkdtemp = vi.mocked(mkdtemp);
|
|
55
|
-
const mockGetCliConfig = vi.mocked(getCliConfig);
|
|
56
41
|
const mockSelect = vi.mocked(select);
|
|
57
42
|
const mockInput = vi.mocked(input);
|
|
58
43
|
const mockConfirm = vi.mocked(confirm);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
datasets: {
|
|
65
|
-
list: vi.fn().mockResolvedValue(datasets.map((name)=>({
|
|
66
|
-
aclMode: 'public',
|
|
67
|
-
addonFor: null,
|
|
68
|
-
createdAt: '2024-01-01T00:00:00Z',
|
|
69
|
-
createdByUserId: 'user-123',
|
|
70
|
-
datasetProfile: 'standard',
|
|
71
|
-
features: [],
|
|
72
|
-
name,
|
|
73
|
-
tags: []
|
|
74
|
-
})))
|
|
44
|
+
const testProjectId = 'test-project';
|
|
45
|
+
const defaultMocks = {
|
|
46
|
+
cliConfig: {
|
|
47
|
+
api: {
|
|
48
|
+
projectId: testProjectId
|
|
75
49
|
}
|
|
76
|
-
}
|
|
50
|
+
},
|
|
51
|
+
projectRoot: {
|
|
52
|
+
directory: '/test/path',
|
|
53
|
+
path: '/test/path/sanity.config.ts',
|
|
54
|
+
type: 'studio'
|
|
55
|
+
},
|
|
56
|
+
token: 'test-token'
|
|
57
|
+
};
|
|
58
|
+
function setupTempDir() {
|
|
77
59
|
mockMkdtemp.mockResolvedValue((()=>{
|
|
78
60
|
const tmpOutDir = path.join(process.cwd(), `tmp/sanity-backup-test-${Date.now()}`);
|
|
79
61
|
mkdirSync(tmpOutDir, {
|
|
@@ -184,11 +166,21 @@ describe('#backup:download', ()=>{
|
|
|
184
166
|
'concurrency should be in 1 to 24 range'
|
|
185
167
|
]
|
|
186
168
|
])('should reject %s', async (_, flags, expectedError)=>{
|
|
187
|
-
|
|
169
|
+
setupTempDir();
|
|
170
|
+
mockListDatasets.mockResolvedValue([
|
|
171
|
+
{
|
|
172
|
+
name: 'production'
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'staging'
|
|
176
|
+
}
|
|
177
|
+
]);
|
|
188
178
|
const { error } = await testCommand(DownloadBackupCommand, [
|
|
189
179
|
'production',
|
|
190
180
|
...flags
|
|
191
|
-
]
|
|
181
|
+
], {
|
|
182
|
+
mocks: defaultMocks
|
|
183
|
+
});
|
|
192
184
|
expect(error?.message).toContain(expectedError);
|
|
193
185
|
});
|
|
194
186
|
});
|
|
@@ -196,39 +188,56 @@ describe('#backup:download', ()=>{
|
|
|
196
188
|
test.each([
|
|
197
189
|
[
|
|
198
190
|
'no datasets exist in project',
|
|
199
|
-
|
|
191
|
+
[],
|
|
200
192
|
'No datasets found'
|
|
201
193
|
],
|
|
202
194
|
[
|
|
203
195
|
'dataset is not found',
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
196
|
+
[
|
|
197
|
+
{
|
|
198
|
+
name: 'staging'
|
|
199
|
+
}
|
|
200
|
+
],
|
|
207
201
|
'not found'
|
|
208
202
|
]
|
|
209
|
-
])('should error when %s', async (_,
|
|
210
|
-
|
|
203
|
+
])('should error when %s', async (_, datasets, expectedError)=>{
|
|
204
|
+
setupTempDir();
|
|
205
|
+
mockListDatasets.mockResolvedValue(datasets);
|
|
211
206
|
const { error } = await testCommand(DownloadBackupCommand, [
|
|
212
207
|
'production',
|
|
213
208
|
'--backup-id',
|
|
214
209
|
'backup-123'
|
|
215
|
-
]
|
|
210
|
+
], {
|
|
211
|
+
mocks: defaultMocks
|
|
212
|
+
});
|
|
216
213
|
expect(error?.message).toContain(expectedError);
|
|
217
214
|
});
|
|
218
215
|
test('should error when no project ID is configured', async ()=>{
|
|
219
|
-
mockGetCliConfig.mockResolvedValueOnce({
|
|
220
|
-
api: {}
|
|
221
|
-
});
|
|
222
216
|
const { error } = await testCommand(DownloadBackupCommand, [
|
|
223
217
|
'production',
|
|
224
218
|
'--backup-id',
|
|
225
219
|
'backup-123'
|
|
226
|
-
]
|
|
220
|
+
], {
|
|
221
|
+
mocks: {
|
|
222
|
+
...defaultMocks,
|
|
223
|
+
cliConfig: {
|
|
224
|
+
api: {}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
227
228
|
expect(error?.message).toContain(NO_PROJECT_ID);
|
|
228
229
|
expect(error?.oclif?.exit).toBe(1);
|
|
229
230
|
});
|
|
230
231
|
test('should error when no backups are available to select', async ()=>{
|
|
231
|
-
|
|
232
|
+
setupTempDir();
|
|
233
|
+
mockListDatasets.mockResolvedValue([
|
|
234
|
+
{
|
|
235
|
+
name: 'production'
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: 'staging'
|
|
239
|
+
}
|
|
240
|
+
]);
|
|
232
241
|
mockApi({
|
|
233
242
|
apiVersion: BACKUP_API_VERSION,
|
|
234
243
|
method: 'get',
|
|
@@ -243,26 +252,34 @@ describe('#backup:download', ()=>{
|
|
|
243
252
|
'production',
|
|
244
253
|
'--out',
|
|
245
254
|
'backup.tar.gz'
|
|
246
|
-
]
|
|
255
|
+
], {
|
|
256
|
+
mocks: defaultMocks
|
|
257
|
+
});
|
|
247
258
|
expect(error?.message).toContain('Failed to fetch backups for dataset production: No backups found');
|
|
248
259
|
expect(error?.oclif?.exit).toBe(1);
|
|
249
260
|
});
|
|
250
261
|
test('should error when cannot list datasets', async ()=>{
|
|
251
|
-
|
|
252
|
-
datasets: {
|
|
253
|
-
list: vi.fn().mockRejectedValue(new Error('Failed to fetch datasets'))
|
|
254
|
-
}
|
|
255
|
-
});
|
|
262
|
+
mockListDatasets.mockRejectedValue(new Error('Failed to fetch datasets'));
|
|
256
263
|
const { error } = await testCommand(DownloadBackupCommand, [
|
|
257
264
|
'production',
|
|
258
265
|
'--backup-id',
|
|
259
266
|
'backup-123'
|
|
260
|
-
]
|
|
267
|
+
], {
|
|
268
|
+
mocks: defaultMocks
|
|
269
|
+
});
|
|
261
270
|
expect(error?.message).toContain('Failed to list datasets: Failed to fetch datasets');
|
|
262
271
|
expect(error?.oclif?.exit).toBe(1);
|
|
263
272
|
});
|
|
264
273
|
test('should cancel operation when user rejects file overwrite', async ()=>{
|
|
265
|
-
|
|
274
|
+
setupTempDir();
|
|
275
|
+
mockListDatasets.mockResolvedValue([
|
|
276
|
+
{
|
|
277
|
+
name: 'production'
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: 'staging'
|
|
281
|
+
}
|
|
282
|
+
]);
|
|
266
283
|
const out = `tmp/${Date.now()}-backup-docs/backup.tar.gz`;
|
|
267
284
|
await mkdir(path.dirname(out), {
|
|
268
285
|
recursive: true
|
|
@@ -275,7 +292,9 @@ describe('#backup:download', ()=>{
|
|
|
275
292
|
'backup-123',
|
|
276
293
|
'--out',
|
|
277
294
|
out
|
|
278
|
-
]
|
|
295
|
+
], {
|
|
296
|
+
mocks: defaultMocks
|
|
297
|
+
});
|
|
279
298
|
const fullPath = path.join(process.cwd(), out);
|
|
280
299
|
expect(mockConfirm).toHaveBeenCalledWith({
|
|
281
300
|
default: false,
|
|
@@ -369,7 +388,15 @@ describe('#backup:download', ()=>{
|
|
|
369
388
|
}
|
|
370
389
|
]
|
|
371
390
|
])('should error when %s', async (description, setupMock)=>{
|
|
372
|
-
|
|
391
|
+
setupTempDir();
|
|
392
|
+
mockListDatasets.mockResolvedValue([
|
|
393
|
+
{
|
|
394
|
+
name: 'production'
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
name: 'staging'
|
|
398
|
+
}
|
|
399
|
+
]);
|
|
373
400
|
setupMock();
|
|
374
401
|
const out = `tmp/${Date.now()}-backup-error/backup.tar.gz`;
|
|
375
402
|
const { error } = await testCommand(DownloadBackupCommand, [
|
|
@@ -378,14 +405,24 @@ describe('#backup:download', ()=>{
|
|
|
378
405
|
'backup-123',
|
|
379
406
|
'--out',
|
|
380
407
|
out
|
|
381
|
-
]
|
|
408
|
+
], {
|
|
409
|
+
mocks: defaultMocks
|
|
410
|
+
});
|
|
382
411
|
expect(error?.message).toContain('Downloading dataset backup failed');
|
|
383
412
|
expect(error?.oclif?.exit).toBe(1);
|
|
384
413
|
});
|
|
385
414
|
});
|
|
386
415
|
describe('successful downloads', ()=>{
|
|
387
416
|
test('should download backup with all flags specified', async ()=>{
|
|
388
|
-
|
|
417
|
+
setupTempDir();
|
|
418
|
+
mockListDatasets.mockResolvedValue([
|
|
419
|
+
{
|
|
420
|
+
name: 'production'
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: 'staging'
|
|
424
|
+
}
|
|
425
|
+
]);
|
|
389
426
|
mockApi({
|
|
390
427
|
apiVersion: BACKUP_API_VERSION,
|
|
391
428
|
method: 'get',
|
|
@@ -424,7 +461,9 @@ describe('#backup:download', ()=>{
|
|
|
424
461
|
'--overwrite',
|
|
425
462
|
'--concurrency',
|
|
426
463
|
'5'
|
|
427
|
-
]
|
|
464
|
+
], {
|
|
465
|
+
mocks: defaultMocks
|
|
466
|
+
});
|
|
428
467
|
expect(error).toBeUndefined();
|
|
429
468
|
expect(stdout).toContain('Downloading backup for:');
|
|
430
469
|
expect(stdout).toContain('projectId');
|
|
@@ -465,12 +504,20 @@ describe('#backup:download', ()=>{
|
|
|
465
504
|
]
|
|
466
505
|
]
|
|
467
506
|
])('should download backup with %s', async (description, files)=>{
|
|
468
|
-
|
|
507
|
+
setupTempDir();
|
|
508
|
+
mockListDatasets.mockResolvedValue([
|
|
509
|
+
{
|
|
510
|
+
name: 'production'
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
name: 'staging'
|
|
514
|
+
}
|
|
515
|
+
]);
|
|
469
516
|
mockBackupAPI({
|
|
470
517
|
files
|
|
471
518
|
});
|
|
472
519
|
mockFileDownloads(files);
|
|
473
|
-
const out = `tmp/${Date.now()}-backup-${description.replaceAll(
|
|
520
|
+
const out = `tmp/${Date.now()}-backup-${description.replaceAll(/\s+/g, '-')}/backup.tar.gz`;
|
|
474
521
|
const { error, stderr } = await testCommand(DownloadBackupCommand, [
|
|
475
522
|
'production',
|
|
476
523
|
'--backup-id',
|
|
@@ -478,13 +525,23 @@ describe('#backup:download', ()=>{
|
|
|
478
525
|
'--out',
|
|
479
526
|
out,
|
|
480
527
|
'--overwrite'
|
|
481
|
-
]
|
|
528
|
+
], {
|
|
529
|
+
mocks: defaultMocks
|
|
530
|
+
});
|
|
482
531
|
expect(error).toBeUndefined();
|
|
483
532
|
expect(stderr).toContain('Backup download complete');
|
|
484
533
|
expect(existsSync(out)).toBe(true);
|
|
485
534
|
});
|
|
486
535
|
test('should overwrite existing file when user confirms', async ()=>{
|
|
487
|
-
|
|
536
|
+
setupTempDir();
|
|
537
|
+
mockListDatasets.mockResolvedValue([
|
|
538
|
+
{
|
|
539
|
+
name: 'production'
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: 'staging'
|
|
543
|
+
}
|
|
544
|
+
]);
|
|
488
545
|
const files = [
|
|
489
546
|
{
|
|
490
547
|
name: 'doc1.json',
|
|
@@ -508,7 +565,9 @@ describe('#backup:download', ()=>{
|
|
|
508
565
|
'backup-123',
|
|
509
566
|
'--out',
|
|
510
567
|
out
|
|
511
|
-
]
|
|
568
|
+
], {
|
|
569
|
+
mocks: defaultMocks
|
|
570
|
+
});
|
|
512
571
|
const fullPath = path.join(process.cwd(), out);
|
|
513
572
|
expect(mockConfirm).toHaveBeenCalledWith({
|
|
514
573
|
default: false,
|
|
@@ -519,7 +578,15 @@ describe('#backup:download', ()=>{
|
|
|
519
578
|
expect(existsSync(out)).toBe(true);
|
|
520
579
|
});
|
|
521
580
|
test('should download backup with paginated API response', async ()=>{
|
|
522
|
-
|
|
581
|
+
setupTempDir();
|
|
582
|
+
mockListDatasets.mockResolvedValue([
|
|
583
|
+
{
|
|
584
|
+
name: 'production'
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
name: 'staging'
|
|
588
|
+
}
|
|
589
|
+
]);
|
|
523
590
|
// First page
|
|
524
591
|
mockApi({
|
|
525
592
|
apiVersion: BACKUP_API_VERSION,
|
|
@@ -571,7 +638,9 @@ describe('#backup:download', ()=>{
|
|
|
571
638
|
'--out',
|
|
572
639
|
out,
|
|
573
640
|
'--overwrite'
|
|
574
|
-
]
|
|
641
|
+
], {
|
|
642
|
+
mocks: defaultMocks
|
|
643
|
+
});
|
|
575
644
|
expect(error).toBeUndefined();
|
|
576
645
|
expect(stderr).toContain('Backup download complete');
|
|
577
646
|
expect(existsSync(out)).toBe(true);
|
|
@@ -579,7 +648,15 @@ describe('#backup:download', ()=>{
|
|
|
579
648
|
});
|
|
580
649
|
describe('interactive prompts', ()=>{
|
|
581
650
|
test('should prompt for backup selection when backup-id is not provided', async ()=>{
|
|
582
|
-
|
|
651
|
+
setupTempDir();
|
|
652
|
+
mockListDatasets.mockResolvedValue([
|
|
653
|
+
{
|
|
654
|
+
name: 'production'
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
name: 'staging'
|
|
658
|
+
}
|
|
659
|
+
]);
|
|
583
660
|
mockApi({
|
|
584
661
|
apiVersion: BACKUP_API_VERSION,
|
|
585
662
|
method: 'get',
|
|
@@ -623,7 +700,9 @@ describe('#backup:download', ()=>{
|
|
|
623
700
|
'--out',
|
|
624
701
|
out,
|
|
625
702
|
'--overwrite'
|
|
626
|
-
]
|
|
703
|
+
], {
|
|
704
|
+
mocks: defaultMocks
|
|
705
|
+
});
|
|
627
706
|
expect(error).toBeUndefined();
|
|
628
707
|
expect(mockSelect).toHaveBeenCalledWith(expect.objectContaining({
|
|
629
708
|
choices: expect.arrayContaining([
|
|
@@ -642,7 +721,15 @@ describe('#backup:download', ()=>{
|
|
|
642
721
|
expect(existsSync(out)).toBe(true);
|
|
643
722
|
});
|
|
644
723
|
test('should prompt for dataset selection when no dataset is specified', async ()=>{
|
|
645
|
-
|
|
724
|
+
setupTempDir();
|
|
725
|
+
mockListDatasets.mockResolvedValue([
|
|
726
|
+
{
|
|
727
|
+
name: 'production'
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
name: 'staging'
|
|
731
|
+
}
|
|
732
|
+
]);
|
|
646
733
|
mockBackupAPI({
|
|
647
734
|
files: []
|
|
648
735
|
});
|
|
@@ -652,7 +739,9 @@ describe('#backup:download', ()=>{
|
|
|
652
739
|
const { stdout } = await testCommand(DownloadBackupCommand, [
|
|
653
740
|
'--backup-id',
|
|
654
741
|
'backup-123'
|
|
655
|
-
]
|
|
742
|
+
], {
|
|
743
|
+
mocks: defaultMocks
|
|
744
|
+
});
|
|
656
745
|
expect(mockSelect).toHaveBeenCalledWith({
|
|
657
746
|
choices: [
|
|
658
747
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/backup/__tests__/download.test.ts"],"sourcesContent":["import {existsSync, mkdirSync} from 'node:fs'\nimport {mkdir, mkdtemp, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {runCommand} from '@oclif/test'\nimport {getCliConfig, getProjectCliClient} from '@sanity/cli-core'\nimport {confirm, input, select} from '@sanity/cli-core/ux'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {BACKUP_API_VERSION} from '../../../actions/backup/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {DownloadBackupCommand} from '../download.js'\n\nvi.mock('../../../../../cli-core/src/config/findProjectRoot.js', () => ({\n findProjectRoot: vi.fn().mockResolvedValue({\n directory: '/test/path',\n root: '/test/path',\n type: 'studio',\n }),\n}))\nvi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', () => ({\n getCliConfig: vi.fn().mockResolvedValue({\n api: {\n projectId: 'test-project',\n },\n }),\n}))\nvi.mock('../../../../../cli-core/src/services/getCliToken.js', () => ({\n getCliToken: vi.fn().mockResolvedValue('test-token'),\n}))\nvi.mock(import('../../../../../cli-core/src/services/apiClient.js'), async (importOriginal) => {\n const actual = await importOriginal()\n return {\n ...actual,\n getProjectCliClient: vi.fn(),\n }\n})\nvi.mock(import('node:fs/promises'), async (importOriginal) => {\n const actual = await importOriginal()\n return {\n ...actual,\n mkdtemp: vi.fn(),\n }\n})\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n confirm: vi.fn(),\n input: vi.fn(),\n select: vi.fn(),\n }\n})\n\nconst mockGetProjectCliClient = vi.mocked(getProjectCliClient)\nconst mockMkdtemp = vi.mocked(mkdtemp)\nconst mockGetCliConfig = vi.mocked(getCliConfig)\nconst mockSelect = vi.mocked(select)\nconst mockInput = vi.mocked(input)\nconst mockConfirm = vi.mocked(confirm)\n\nfunction setupTestEnvironment(datasets = ['production', 'staging']) {\n mockGetProjectCliClient.mockResolvedValue({\n datasets: {\n list: vi.fn().mockResolvedValue(\n datasets.map((name) => ({\n aclMode: 'public',\n addonFor: null,\n createdAt: '2024-01-01T00:00:00Z',\n createdByUserId: 'user-123',\n datasetProfile: 'standard',\n features: [],\n name,\n tags: [],\n })),\n ),\n },\n } as unknown as Awaited<ReturnType<typeof getProjectCliClient>>)\n\n mockMkdtemp.mockResolvedValue(\n (() => {\n const tmpOutDir = path.join(process.cwd(), `tmp/sanity-backup-test-${Date.now()}`)\n mkdirSync(tmpOutDir, {recursive: true})\n return tmpOutDir\n })(),\n )\n}\n\nfunction mockBackupAPI({\n files,\n id = 'backup-123',\n nextCursor,\n}: {\n files: {name: string; type: string; url: string}[]\n id?: string\n nextCursor?: string\n}) {\n return mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/${id}`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files,\n totalFiles: files.length,\n ...(nextCursor && {nextCursor}),\n })\n}\n\nfunction mockFileDownloads(files: {name: string; type: string; url: string}[]) {\n for (const file of files) {\n const urlPath = new URL(file.url).pathname\n if (file.type === 'document') {\n nock('https://api.sanity.io').get(urlPath).reply(200, '{\"_id\":\"doc1\"}')\n } else {\n nock('https://api.sanity.io')\n .get(urlPath)\n .reply(200, Buffer.from(`fake-${file.type}-data`))\n }\n }\n}\n\ndescribe('#backup:download', () => {\n afterEach(() => {\n const pending = nock.pendingMocks()\n nock.cleanAll()\n vi.clearAllMocks()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand(['backup download', '--help'])\n\n expect(stdout).toMatchInlineSnapshot(String.raw`\n \"Download a dataset backup to a local file.\n\n USAGE\n $ sanity backup download [DATASET] [--backup-id <value>] [--concurrency\n <value>] [--out <value>] [--overwrite]\n\n ARGUMENTS\n [DATASET] Dataset name to download backup from\n\n FLAGS\n --backup-id=<value> The backup ID to download\n --concurrency=<value> [default: 10] Concurrent number of backup item\n downloads (max: 24)\n --out=<value> The file or directory path the backup should download\n to\n --overwrite Allows overwriting of existing backup file\n\n DESCRIPTION\n Download a dataset backup to a local file.\n\n EXAMPLES\n Interactively download a backup\n\n $ sanity backup download\n\n Download a specific backup for the production dataset\n\n $ sanity backup download production --backup-id 2024-01-01-backup-1\n\n Download backup to a specific file\n\n $ sanity backup download production --backup-id 2024-01-01-backup-2 \\\n --out /path/to/file\n\n Download backup and overwrite existing file\n\n $ sanity backup download production --backup-id 2024-01-01-backup-3 \\\n --out /path/to/file --overwrite\n\n \"\n `)\n })\n\n describe('validation', () => {\n test.each([\n [\n 'concurrency value below minimum',\n ['--backup-id', 'test', '--concurrency', '0'],\n 'concurrency should be in 1 to 24 range',\n ],\n [\n 'concurrency value above maximum',\n ['--backup-id', 'test', '--concurrency', '25'],\n 'concurrency should be in 1 to 24 range',\n ],\n ])('should reject %s', async (_, flags, expectedError) => {\n setupTestEnvironment()\n\n const {error} = await testCommand(DownloadBackupCommand, ['production', ...flags])\n\n expect(error?.message).toContain(expectedError)\n })\n })\n\n describe('error handling', () => {\n test.each([\n ['no datasets exist in project', () => setupTestEnvironment([]), 'No datasets found'],\n ['dataset is not found', () => setupTestEnvironment(['staging']), 'not found'],\n ])('should error when %s', async (_, setupMock, expectedError) => {\n setupMock()\n\n const {error} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n ])\n\n expect(error?.message).toContain(expectedError)\n })\n\n test('should error when no project ID is configured', async () => {\n mockGetCliConfig.mockResolvedValueOnce({\n api: {},\n } as never)\n\n const {error} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n ])\n\n expect(error?.message).toContain(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('should error when no backups are available to select', async () => {\n setupTestEnvironment()\n\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {limit: '100'},\n uri: `/projects/test-project/datasets/production/backups`,\n }).reply(200, {\n backups: [],\n })\n\n const {error} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--out',\n 'backup.tar.gz',\n ])\n\n expect(error?.message).toContain(\n 'Failed to fetch backups for dataset production: No backups found',\n )\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('should error when cannot list datasets', async () => {\n mockGetProjectCliClient.mockResolvedValue({\n datasets: {\n list: vi.fn().mockRejectedValue(new Error('Failed to fetch datasets')),\n },\n } as unknown as Awaited<ReturnType<typeof getProjectCliClient>>)\n\n const {error} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n ])\n\n expect(error?.message).toContain('Failed to list datasets: Failed to fetch datasets')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('should cancel operation when user rejects file overwrite', async () => {\n setupTestEnvironment()\n\n const out = `tmp/${Date.now()}-backup-docs/backup.tar.gz`\n\n await mkdir(path.dirname(out), {recursive: true})\n await writeFile(out, 'fake-data')\n\n mockConfirm.mockResolvedValue(false)\n\n const {error} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n ])\n\n const fullPath = path.join(process.cwd(), out)\n\n expect(mockConfirm).toHaveBeenCalledWith({\n default: false,\n message: `File \"${fullPath}\" already exists, would you like to overwrite it?`,\n })\n\n expect(error?.message).toContain('Operation cancelled.')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n [\n 'document download fails',\n () => {\n const name = 'doc1.json'\n const type = 'document'\n mockBackupAPI({\n files: [{name, type, url: `https://api.sanity.io/${BACKUP_API_VERSION}/${name}`}],\n })\n nock('https://api.sanity.io').get(`/${BACKUP_API_VERSION}/${name}`).reply(500, {\n message: 'Internal Server Error',\n })\n },\n ],\n [\n 'asset download fails',\n () => {\n const name = 'image1.jpg'\n const type = 'asset'\n mockBackupAPI({\n files: [{name, type, url: `https://api.sanity.io/${BACKUP_API_VERSION}/${name}`}],\n })\n nock('https://api.sanity.io').get(`/${BACKUP_API_VERSION}/${name}`).reply(500, {\n message: 'Internal Server Error',\n })\n },\n ],\n [\n 'initial backup API call fails',\n () => {\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(500, {\n message: 'Backup API error',\n })\n },\n ],\n [\n 'backup API fails on subsequent pages',\n () => {\n // First page succeeds\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ],\n nextCursor: 'page2',\n totalFiles: 2,\n })\n\n // Second page fails\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {nextCursor: 'page2'},\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(500, {\n message: 'Second page error',\n })\n },\n ],\n ])('should error when %s', async (description, setupMock) => {\n setupTestEnvironment()\n setupMock()\n\n const out = `tmp/${Date.now()}-backup-error/backup.tar.gz`\n const {error} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n ])\n\n expect(error?.message).toContain('Downloading dataset backup failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('successful downloads', () => {\n test('should download backup with all flags specified', async () => {\n setupTestEnvironment()\n\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n {\n name: 'image1.jpg',\n type: 'image',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/image1`,\n },\n {\n name: 'file1.pdf',\n type: 'file',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/file1`,\n },\n ],\n totalFiles: 3,\n })\n\n nock('https://api.sanity.io')\n .get(`/${BACKUP_API_VERSION}/doc1`)\n .reply(200, '{\"_id\":\"doc1\",\"title\":\"Document 1\"}')\n .get(`/${BACKUP_API_VERSION}/image1`)\n .reply(200, Buffer.from('fake-image-data'), {'content-type': 'image/jpeg'})\n .get(`/${BACKUP_API_VERSION}/file1`)\n .reply(200, Buffer.from('fake-file-data'))\n\n const out = `tmp/${Date.now()}-backup/backup.tar.gz`\n const {error, stderr, stdout} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n '--overwrite',\n '--concurrency',\n '5',\n ])\n\n expect(error).toBeUndefined()\n\n expect(stdout).toContain('Downloading backup for:')\n expect(stdout).toContain('projectId')\n expect(stdout).toContain('dataset')\n expect(stdout).toContain('backupId')\n\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test.each([\n [\n 'documents only',\n [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ],\n ],\n [\n 'mixed file types',\n [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n {\n name: 'image1.jpg',\n type: 'image',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/image1`,\n },\n {\n name: 'file1.pdf',\n type: 'file',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/file1`,\n },\n ],\n ],\n ])('should download backup with %s', async (description, files) => {\n setupTestEnvironment()\n\n mockBackupAPI({files})\n mockFileDownloads(files)\n\n const out = `tmp/${Date.now()}-backup-${description.replaceAll(/\\\\s+/g, '-')}/backup.tar.gz`\n const {error, stderr} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n '--overwrite',\n ])\n\n expect(error).toBeUndefined()\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test('should overwrite existing file when user confirms', async () => {\n setupTestEnvironment()\n\n const files = [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ]\n\n mockBackupAPI({files})\n mockFileDownloads(files)\n\n const out = `tmp/${Date.now()}-backup-confirm/backup.tar.gz`\n\n await mkdir(path.dirname(out), {recursive: true})\n await writeFile(out, 'fake-data')\n\n mockConfirm.mockResolvedValue(true)\n\n const {error, stderr} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n ])\n\n const fullPath = path.join(process.cwd(), out)\n\n expect(mockConfirm).toHaveBeenCalledWith({\n default: false,\n message: `File \"${fullPath}\" already exists, would you like to overwrite it?`,\n })\n expect(error).toBeUndefined()\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test('should download backup with paginated API response', async () => {\n setupTestEnvironment()\n\n // First page\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n {\n name: 'image1.jpg',\n type: 'image',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/image1`,\n },\n ],\n nextCursor: 'page2',\n totalFiles: 3,\n })\n\n // Second page\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {nextCursor: 'page2'},\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'file1.pdf',\n type: 'file',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/file1`,\n },\n ],\n totalFiles: 3,\n })\n\n // Mock file downloads\n nock('https://api.sanity.io')\n .get(`/${BACKUP_API_VERSION}/doc1`)\n .reply(200, '{\"_id\":\"doc1\",\"title\":\"Document 1\"}')\n .get(`/${BACKUP_API_VERSION}/image1`)\n .reply(200, Buffer.from('fake-image-data'))\n .get(`/${BACKUP_API_VERSION}/file1`)\n .reply(200, Buffer.from('fake-file-data'))\n\n const out = `tmp/${Date.now()}-backup-paginated/backup.tar.gz`\n const {error, stderr} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n '--overwrite',\n ])\n\n expect(error).toBeUndefined()\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n })\n\n describe('interactive prompts', () => {\n test('should prompt for backup selection when backup-id is not provided', async () => {\n setupTestEnvironment()\n\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {limit: '100'},\n uri: `/projects/test-project/datasets/production/backups`,\n }).reply(200, {\n backups: [\n {createdAt: '2024-01-01T00:00:00Z', id: 'backup-1'},\n {createdAt: '2024-01-02T00:00:00Z', id: 'backup-2'},\n ],\n })\n\n mockSelect.mockResolvedValue('backup-1')\n\n const files = [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ]\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-1`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files,\n totalFiles: files.length,\n })\n mockFileDownloads(files)\n\n const out = `tmp/${Date.now()}-backup-prompt/backup.tar.gz`\n\n const {error, stderr} = await testCommand(DownloadBackupCommand, [\n 'production',\n '--out',\n out,\n '--overwrite',\n ])\n\n expect(error).toBeUndefined()\n expect(mockSelect).toHaveBeenCalledWith(\n expect.objectContaining({\n choices: expect.arrayContaining([\n {name: 'backup-1', value: 'backup-1'},\n {name: 'backup-2', value: 'backup-2'},\n ]),\n message: expect.stringContaining('Select backup ID'),\n }),\n )\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test('should prompt for dataset selection when no dataset is specified', async () => {\n setupTestEnvironment()\n\n mockBackupAPI({files: []})\n mockSelect.mockResolvedValue('production')\n const out = `tmp/${Date.now()}-backup-dataset-prompt/backup.tar.gz`\n mockInput.mockResolvedValue(out)\n\n const {stdout} = await testCommand(DownloadBackupCommand, ['--backup-id', 'backup-123'])\n\n expect(mockSelect).toHaveBeenCalledWith({\n choices: [\n {name: 'production', value: 'production'},\n {name: 'staging', value: 'staging'},\n ],\n message: 'Select the dataset name:',\n })\n expect(stdout).toContain('Downloading backup for:')\n expect(stdout).toContain('projectId')\n expect(stdout).toContain('dataset')\n expect(stdout).toContain('backupId')\n expect(stdout).toContain('Downloading backup to')\n expect(existsSync(out)).toBe(true)\n })\n })\n})\n"],"names":["existsSync","mkdirSync","mkdir","mkdtemp","writeFile","path","runCommand","getCliConfig","getProjectCliClient","confirm","input","select","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","BACKUP_API_VERSION","NO_PROJECT_ID","DownloadBackupCommand","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","api","projectId","getCliToken","importOriginal","actual","importActual","mockGetProjectCliClient","mocked","mockMkdtemp","mockGetCliConfig","mockSelect","mockInput","mockConfirm","setupTestEnvironment","datasets","list","map","name","aclMode","addonFor","createdAt","createdByUserId","datasetProfile","features","tags","tmpOutDir","join","process","cwd","Date","now","recursive","mockBackupAPI","files","id","nextCursor","apiVersion","method","uri","reply","totalFiles","length","mockFileDownloads","file","urlPath","URL","url","pathname","get","Buffer","from","pending","pendingMocks","cleanAll","clearAllMocks","toEqual","stdout","toMatchInlineSnapshot","String","raw","each","_","flags","expectedError","error","message","toContain","setupMock","mockResolvedValueOnce","oclif","exit","toBe","query","limit","backups","mockRejectedValue","Error","out","dirname","fullPath","toHaveBeenCalledWith","default","description","stderr","toBeUndefined","replaceAll","objectContaining","choices","arrayContaining","value","stringContaining"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/backup/__tests__/download.test.ts"],"sourcesContent":["import {existsSync, mkdirSync} from 'node:fs'\nimport {mkdir, mkdtemp, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {runCommand} from '@oclif/test'\nimport {confirm, input, select} from '@sanity/cli-core/ux'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {BACKUP_API_VERSION} from '../../../actions/backup/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {DownloadBackupCommand} from '../download.js'\n\nconst mockListDatasets = vi.hoisted(() => vi.fn())\n\nvi.mock('@sanity/cli-core', async (importOriginal) => {\n const actual = await importOriginal<typeof import('@sanity/cli-core')>()\n return {\n ...actual,\n getProjectCliClient: vi.fn().mockResolvedValue({\n datasets: {\n list: mockListDatasets,\n } as never,\n }),\n }\n})\n\nvi.mock(import('node:fs/promises'), async (importOriginal) => {\n const actual = await importOriginal()\n return {\n ...actual,\n mkdtemp: vi.fn(),\n }\n})\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n confirm: vi.fn(),\n input: vi.fn(),\n select: vi.fn(),\n }\n})\n\nconst mockMkdtemp = vi.mocked(mkdtemp)\nconst mockSelect = vi.mocked(select)\nconst mockInput = vi.mocked(input)\nconst mockConfirm = vi.mocked(confirm)\n\nconst testProjectId = 'test-project'\n\nconst defaultMocks = {\n cliConfig: {api: {projectId: testProjectId}},\n projectRoot: {\n directory: '/test/path',\n path: '/test/path/sanity.config.ts',\n type: 'studio' as const,\n },\n token: 'test-token',\n}\n\nfunction setupTempDir() {\n mockMkdtemp.mockResolvedValue(\n (() => {\n const tmpOutDir = path.join(process.cwd(), `tmp/sanity-backup-test-${Date.now()}`)\n mkdirSync(tmpOutDir, {recursive: true})\n return tmpOutDir\n })(),\n )\n}\n\nfunction mockBackupAPI({\n files,\n id = 'backup-123',\n nextCursor,\n}: {\n files: {name: string; type: string; url: string}[]\n id?: string\n nextCursor?: string\n}) {\n return mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/${id}`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files,\n totalFiles: files.length,\n ...(nextCursor && {nextCursor}),\n })\n}\n\nfunction mockFileDownloads(files: {name: string; type: string; url: string}[]) {\n for (const file of files) {\n const urlPath = new URL(file.url).pathname\n if (file.type === 'document') {\n nock('https://api.sanity.io').get(urlPath).reply(200, '{\"_id\":\"doc1\"}')\n } else {\n nock('https://api.sanity.io')\n .get(urlPath)\n .reply(200, Buffer.from(`fake-${file.type}-data`))\n }\n }\n}\n\ndescribe('#backup:download', () => {\n afterEach(() => {\n const pending = nock.pendingMocks()\n nock.cleanAll()\n vi.clearAllMocks()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand(['backup download', '--help'])\n\n expect(stdout).toMatchInlineSnapshot(String.raw`\n \"Download a dataset backup to a local file.\n\n USAGE\n $ sanity backup download [DATASET] [--backup-id <value>] [--concurrency\n <value>] [--out <value>] [--overwrite]\n\n ARGUMENTS\n [DATASET] Dataset name to download backup from\n\n FLAGS\n --backup-id=<value> The backup ID to download\n --concurrency=<value> [default: 10] Concurrent number of backup item\n downloads (max: 24)\n --out=<value> The file or directory path the backup should download\n to\n --overwrite Allows overwriting of existing backup file\n\n DESCRIPTION\n Download a dataset backup to a local file.\n\n EXAMPLES\n Interactively download a backup\n\n $ sanity backup download\n\n Download a specific backup for the production dataset\n\n $ sanity backup download production --backup-id 2024-01-01-backup-1\n\n Download backup to a specific file\n\n $ sanity backup download production --backup-id 2024-01-01-backup-2 \\\n --out /path/to/file\n\n Download backup and overwrite existing file\n\n $ sanity backup download production --backup-id 2024-01-01-backup-3 \\\n --out /path/to/file --overwrite\n\n \"\n `)\n })\n\n describe('validation', () => {\n test.each([\n [\n 'concurrency value below minimum',\n ['--backup-id', 'test', '--concurrency', '0'],\n 'concurrency should be in 1 to 24 range',\n ],\n [\n 'concurrency value above maximum',\n ['--backup-id', 'test', '--concurrency', '25'],\n 'concurrency should be in 1 to 24 range',\n ],\n ])('should reject %s', async (_, flags, expectedError) => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n const {error} = await testCommand(DownloadBackupCommand, ['production', ...flags], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain(expectedError)\n })\n })\n\n describe('error handling', () => {\n test.each([\n ['no datasets exist in project', [], 'No datasets found'],\n ['dataset is not found', [{name: 'staging'}], 'not found'],\n ])('should error when %s', async (_, datasets, expectedError) => {\n setupTempDir()\n mockListDatasets.mockResolvedValue(datasets)\n\n const {error} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error?.message).toContain(expectedError)\n })\n\n test('should error when no project ID is configured', async () => {\n const {error} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123'],\n {\n mocks: {\n ...defaultMocks,\n cliConfig: {api: {}},\n },\n },\n )\n\n expect(error?.message).toContain(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('should error when no backups are available to select', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {limit: '100'},\n uri: `/projects/test-project/datasets/production/backups`,\n }).reply(200, {\n backups: [],\n })\n\n const {error} = await testCommand(\n DownloadBackupCommand,\n ['production', '--out', 'backup.tar.gz'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error?.message).toContain(\n 'Failed to fetch backups for dataset production: No backups found',\n )\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('should error when cannot list datasets', async () => {\n mockListDatasets.mockRejectedValue(new Error('Failed to fetch datasets'))\n\n const {error} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error?.message).toContain('Failed to list datasets: Failed to fetch datasets')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('should cancel operation when user rejects file overwrite', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n const out = `tmp/${Date.now()}-backup-docs/backup.tar.gz`\n\n await mkdir(path.dirname(out), {recursive: true})\n await writeFile(out, 'fake-data')\n\n mockConfirm.mockResolvedValue(false)\n\n const {error} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123', '--out', out],\n {\n mocks: defaultMocks,\n },\n )\n\n const fullPath = path.join(process.cwd(), out)\n\n expect(mockConfirm).toHaveBeenCalledWith({\n default: false,\n message: `File \"${fullPath}\" already exists, would you like to overwrite it?`,\n })\n\n expect(error?.message).toContain('Operation cancelled.')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n [\n 'document download fails',\n () => {\n const name = 'doc1.json'\n const type = 'document'\n mockBackupAPI({\n files: [{name, type, url: `https://api.sanity.io/${BACKUP_API_VERSION}/${name}`}],\n })\n nock('https://api.sanity.io').get(`/${BACKUP_API_VERSION}/${name}`).reply(500, {\n message: 'Internal Server Error',\n })\n },\n ],\n [\n 'asset download fails',\n () => {\n const name = 'image1.jpg'\n const type = 'asset'\n mockBackupAPI({\n files: [{name, type, url: `https://api.sanity.io/${BACKUP_API_VERSION}/${name}`}],\n })\n nock('https://api.sanity.io').get(`/${BACKUP_API_VERSION}/${name}`).reply(500, {\n message: 'Internal Server Error',\n })\n },\n ],\n [\n 'initial backup API call fails',\n () => {\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(500, {\n message: 'Backup API error',\n })\n },\n ],\n [\n 'backup API fails on subsequent pages',\n () => {\n // First page succeeds\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ],\n nextCursor: 'page2',\n totalFiles: 2,\n })\n\n // Second page fails\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {nextCursor: 'page2'},\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(500, {\n message: 'Second page error',\n })\n },\n ],\n ])('should error when %s', async (description, setupMock) => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n setupMock()\n\n const out = `tmp/${Date.now()}-backup-error/backup.tar.gz`\n const {error} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123', '--out', out],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error?.message).toContain('Downloading dataset backup failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('successful downloads', () => {\n test('should download backup with all flags specified', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n {\n name: 'image1.jpg',\n type: 'image',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/image1`,\n },\n {\n name: 'file1.pdf',\n type: 'file',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/file1`,\n },\n ],\n totalFiles: 3,\n })\n\n nock('https://api.sanity.io')\n .get(`/${BACKUP_API_VERSION}/doc1`)\n .reply(200, '{\"_id\":\"doc1\",\"title\":\"Document 1\"}')\n .get(`/${BACKUP_API_VERSION}/image1`)\n .reply(200, Buffer.from('fake-image-data'), {'content-type': 'image/jpeg'})\n .get(`/${BACKUP_API_VERSION}/file1`)\n .reply(200, Buffer.from('fake-file-data'))\n\n const out = `tmp/${Date.now()}-backup/backup.tar.gz`\n const {error, stderr, stdout} = await testCommand(\n DownloadBackupCommand,\n [\n 'production',\n '--backup-id',\n 'backup-123',\n '--out',\n out,\n '--overwrite',\n '--concurrency',\n '5',\n ],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error).toBeUndefined()\n\n expect(stdout).toContain('Downloading backup for:')\n expect(stdout).toContain('projectId')\n expect(stdout).toContain('dataset')\n expect(stdout).toContain('backupId')\n\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test.each([\n [\n 'documents only',\n [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ],\n ],\n [\n 'mixed file types',\n [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n {\n name: 'image1.jpg',\n type: 'image',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/image1`,\n },\n {\n name: 'file1.pdf',\n type: 'file',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/file1`,\n },\n ],\n ],\n ])('should download backup with %s', async (description, files) => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n mockBackupAPI({files})\n mockFileDownloads(files)\n\n const out = `tmp/${Date.now()}-backup-${description.replaceAll(/\\s+/g, '-')}/backup.tar.gz`\n const {error, stderr} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123', '--out', out, '--overwrite'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error).toBeUndefined()\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test('should overwrite existing file when user confirms', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n const files = [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ]\n\n mockBackupAPI({files})\n mockFileDownloads(files)\n\n const out = `tmp/${Date.now()}-backup-confirm/backup.tar.gz`\n\n await mkdir(path.dirname(out), {recursive: true})\n await writeFile(out, 'fake-data')\n\n mockConfirm.mockResolvedValue(true)\n\n const {error, stderr} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123', '--out', out],\n {\n mocks: defaultMocks,\n },\n )\n\n const fullPath = path.join(process.cwd(), out)\n\n expect(mockConfirm).toHaveBeenCalledWith({\n default: false,\n message: `File \"${fullPath}\" already exists, would you like to overwrite it?`,\n })\n expect(error).toBeUndefined()\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test('should download backup with paginated API response', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n // First page\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n {\n name: 'image1.jpg',\n type: 'image',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/image1`,\n },\n ],\n nextCursor: 'page2',\n totalFiles: 3,\n })\n\n // Second page\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {nextCursor: 'page2'},\n uri: `/projects/test-project/datasets/production/backups/backup-123`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files: [\n {\n name: 'file1.pdf',\n type: 'file',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/file1`,\n },\n ],\n totalFiles: 3,\n })\n\n // Mock file downloads\n nock('https://api.sanity.io')\n .get(`/${BACKUP_API_VERSION}/doc1`)\n .reply(200, '{\"_id\":\"doc1\",\"title\":\"Document 1\"}')\n .get(`/${BACKUP_API_VERSION}/image1`)\n .reply(200, Buffer.from('fake-image-data'))\n .get(`/${BACKUP_API_VERSION}/file1`)\n .reply(200, Buffer.from('fake-file-data'))\n\n const out = `tmp/${Date.now()}-backup-paginated/backup.tar.gz`\n const {error, stderr} = await testCommand(\n DownloadBackupCommand,\n ['production', '--backup-id', 'backup-123', '--out', out, '--overwrite'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error).toBeUndefined()\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n })\n\n describe('interactive prompts', () => {\n test('should prompt for backup selection when backup-id is not provided', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n query: {limit: '100'},\n uri: `/projects/test-project/datasets/production/backups`,\n }).reply(200, {\n backups: [\n {createdAt: '2024-01-01T00:00:00Z', id: 'backup-1'},\n {createdAt: '2024-01-02T00:00:00Z', id: 'backup-2'},\n ],\n })\n\n mockSelect.mockResolvedValue('backup-1')\n\n const files = [\n {\n name: 'doc1.json',\n type: 'document',\n url: `https://api.sanity.io/${BACKUP_API_VERSION}/doc1`,\n },\n ]\n mockApi({\n apiVersion: BACKUP_API_VERSION,\n method: 'get',\n uri: `/projects/test-project/datasets/production/backups/backup-1`,\n }).reply(200, {\n createdAt: '2024-01-15T10:30:00Z',\n files,\n totalFiles: files.length,\n })\n mockFileDownloads(files)\n\n const out = `tmp/${Date.now()}-backup-prompt/backup.tar.gz`\n\n const {error, stderr} = await testCommand(\n DownloadBackupCommand,\n ['production', '--out', out, '--overwrite'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(error).toBeUndefined()\n expect(mockSelect).toHaveBeenCalledWith(\n expect.objectContaining({\n choices: expect.arrayContaining([\n {name: 'backup-1', value: 'backup-1'},\n {name: 'backup-2', value: 'backup-2'},\n ]),\n message: expect.stringContaining('Select backup ID'),\n }),\n )\n expect(stderr).toContain('Backup download complete')\n expect(existsSync(out)).toBe(true)\n })\n\n test('should prompt for dataset selection when no dataset is specified', async () => {\n setupTempDir()\n mockListDatasets.mockResolvedValue([{name: 'production'}, {name: 'staging'}])\n\n mockBackupAPI({files: []})\n mockSelect.mockResolvedValue('production')\n const out = `tmp/${Date.now()}-backup-dataset-prompt/backup.tar.gz`\n mockInput.mockResolvedValue(out)\n\n const {stdout} = await testCommand(DownloadBackupCommand, ['--backup-id', 'backup-123'], {\n mocks: defaultMocks,\n })\n\n expect(mockSelect).toHaveBeenCalledWith({\n choices: [\n {name: 'production', value: 'production'},\n {name: 'staging', value: 'staging'},\n ],\n message: 'Select the dataset name:',\n })\n expect(stdout).toContain('Downloading backup for:')\n expect(stdout).toContain('projectId')\n expect(stdout).toContain('dataset')\n expect(stdout).toContain('backupId')\n expect(stdout).toContain('Downloading backup to')\n expect(existsSync(out)).toBe(true)\n })\n })\n})\n"],"names":["existsSync","mkdirSync","mkdir","mkdtemp","writeFile","path","runCommand","confirm","input","select","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","BACKUP_API_VERSION","NO_PROJECT_ID","DownloadBackupCommand","mockListDatasets","hoisted","fn","mock","importOriginal","actual","getProjectCliClient","mockResolvedValue","datasets","list","importActual","mockMkdtemp","mocked","mockSelect","mockInput","mockConfirm","testProjectId","defaultMocks","cliConfig","api","projectId","projectRoot","directory","type","token","setupTempDir","tmpOutDir","join","process","cwd","Date","now","recursive","mockBackupAPI","files","id","nextCursor","apiVersion","method","uri","reply","createdAt","totalFiles","length","mockFileDownloads","file","urlPath","URL","url","pathname","get","Buffer","from","pending","pendingMocks","cleanAll","clearAllMocks","toEqual","stdout","toMatchInlineSnapshot","String","raw","each","_","flags","expectedError","name","error","mocks","message","toContain","oclif","exit","toBe","query","limit","backups","mockRejectedValue","Error","out","dirname","fullPath","toHaveBeenCalledWith","default","description","setupMock","stderr","toBeUndefined","replaceAll","objectContaining","choices","arrayContaining","value","stringContaining"],"mappings":"AAAA,SAAQA,UAAU,EAAEC,SAAS,QAAO,UAAS;AAC7C,SAAQC,KAAK,EAAEC,OAAO,EAAEC,SAAS,QAAO,mBAAkB;AAC1D,OAAOC,UAAU,YAAW;AAE5B,SAAQC,UAAU,QAAO,cAAa;AACtC,SAAQC,OAAO,EAAEC,KAAK,EAAEC,MAAM,QAAO,sBAAqB;AAC1D,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAkB;AACrD,OAAOC,UAAU,OAAM;AACvB,SAAQC,SAAS,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,IAAI,EAAEC,EAAE,QAAO,SAAQ;AAE5D,SAAQC,kBAAkB,QAAO,uCAAsC;AACvE,SAAQC,aAAa,QAAO,iCAAgC;AAC5D,SAAQC,qBAAqB,QAAO,iBAAgB;AAEpD,MAAMC,mBAAmBJ,GAAGK,OAAO,CAAC,IAAML,GAAGM,EAAE;AAE/CN,GAAGO,IAAI,CAAC,oBAAoB,OAAOC;IACjC,MAAMC,SAAS,MAAMD;IACrB,OAAO;QACL,GAAGC,MAAM;QACTC,qBAAqBV,GAAGM,EAAE,GAAGK,iBAAiB,CAAC;YAC7CC,UAAU;gBACRC,MAAMT;YACR;QACF;IACF;AACF;AAEAJ,GAAGO,IAAI,CAAC,MAAM,CAAC,qBAAqB,OAAOC;IACzC,MAAMC,SAAS,MAAMD;IACrB,OAAO;QACL,GAAGC,MAAM;QACTvB,SAASc,GAAGM,EAAE;IAChB;AACF;AACAN,GAAGO,IAAI,CAAC,uBAAuB;IAC7B,MAAME,SAAS,MAAMT,GAAGc,YAAY,CAAuC;IAC3E,OAAO;QACL,GAAGL,MAAM;QACTnB,SAASU,GAAGM,EAAE;QACdf,OAAOS,GAAGM,EAAE;QACZd,QAAQQ,GAAGM,EAAE;IACf;AACF;AAEA,MAAMS,cAAcf,GAAGgB,MAAM,CAAC9B;AAC9B,MAAM+B,aAAajB,GAAGgB,MAAM,CAACxB;AAC7B,MAAM0B,YAAYlB,GAAGgB,MAAM,CAACzB;AAC5B,MAAM4B,cAAcnB,GAAGgB,MAAM,CAAC1B;AAE9B,MAAM8B,gBAAgB;AAEtB,MAAMC,eAAe;IACnBC,WAAW;QAACC,KAAK;YAACC,WAAWJ;QAAa;IAAC;IAC3CK,aAAa;QACXC,WAAW;QACXtC,MAAM;QACNuC,MAAM;IACR;IACAC,OAAO;AACT;AAEA,SAASC;IACPd,YAAYJ,iBAAiB,CAC3B,AAAC,CAAA;QACC,MAAMmB,YAAY1C,KAAK2C,IAAI,CAACC,QAAQC,GAAG,IAAI,CAAC,uBAAuB,EAAEC,KAAKC,GAAG,IAAI;QACjFnD,UAAU8C,WAAW;YAACM,WAAW;QAAI;QACrC,OAAON;IACT,CAAA;AAEJ;AAEA,SAASO,cAAc,EACrBC,KAAK,EACLC,KAAK,YAAY,EACjBC,UAAU,EAKX;IACC,OAAO/C,QAAQ;QACbgD,YAAYxC;QACZyC,QAAQ;QACRC,KAAK,CAAC,mDAAmD,EAAEJ,IAAI;IACjE,GAAGK,KAAK,CAAC,KAAK;QACZC,WAAW;QACXP;QACAQ,YAAYR,MAAMS,MAAM;QACxB,GAAIP,cAAc;YAACA;QAAU,CAAC;IAChC;AACF;AAEA,SAASQ,kBAAkBV,KAAkD;IAC3E,KAAK,MAAMW,QAAQX,MAAO;QACxB,MAAMY,UAAU,IAAIC,IAAIF,KAAKG,GAAG,EAAEC,QAAQ;QAC1C,IAAIJ,KAAKtB,IAAI,KAAK,YAAY;YAC5BhC,KAAK,yBAAyB2D,GAAG,CAACJ,SAASN,KAAK,CAAC,KAAK;QACxD,OAAO;YACLjD,KAAK,yBACF2D,GAAG,CAACJ,SACJN,KAAK,CAAC,KAAKW,OAAOC,IAAI,CAAC,CAAC,KAAK,EAAEP,KAAKtB,IAAI,CAAC,KAAK,CAAC;QACpD;IACF;AACF;AAEA9B,SAAS,oBAAoB;IAC3BD,UAAU;QACR,MAAM6D,UAAU9D,KAAK+D,YAAY;QACjC/D,KAAKgE,QAAQ;QACb3D,GAAG4D,aAAa;QAChB9D,OAAO2D,SAAS,iBAAiBI,OAAO,CAAC,EAAE;IAC7C;IAEA9D,KAAK,gBAAgB;QACnB,MAAM,EAAC+D,MAAM,EAAC,GAAG,MAAMzE,WAAW;YAAC;YAAmB;SAAS;QAE/DS,OAAOgE,QAAQC,qBAAqB,CAACC,OAAOC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyChD,CAAC;IACH;IAEApE,SAAS,cAAc;QACrBE,KAAKmE,IAAI,CAAC;YACR;gBACE;gBACA;oBAAC;oBAAe;oBAAQ;oBAAiB;iBAAI;gBAC7C;aACD;YACD;gBACE;gBACA;oBAAC;oBAAe;oBAAQ;oBAAiB;iBAAK;gBAC9C;aACD;SACF,EAAE,oBAAoB,OAAOC,GAAGC,OAAOC;YACtCxC;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E,MAAM,EAACC,KAAK,EAAC,GAAG,MAAM7E,YAAYS,uBAAuB;gBAAC;mBAAiBiE;aAAM,EAAE;gBACjFI,OAAOnD;YACT;YAEAvB,OAAOyE,OAAOE,SAASC,SAAS,CAACL;QACnC;IACF;IAEAxE,SAAS,kBAAkB;QACzBE,KAAKmE,IAAI,CAAC;YACR;gBAAC;gBAAgC,EAAE;gBAAE;aAAoB;YACzD;gBAAC;gBAAwB;oBAAC;wBAACI,MAAM;oBAAS;iBAAE;gBAAE;aAAY;SAC3D,EAAE,wBAAwB,OAAOH,GAAGvD,UAAUyD;YAC7CxC;YACAzB,iBAAiBO,iBAAiB,CAACC;YAEnC,MAAM,EAAC2D,KAAK,EAAC,GAAG,MAAM7E,YACpBS,uBACA;gBAAC;gBAAc;gBAAe;aAAa,EAC3C;gBACEqE,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOE,SAASC,SAAS,CAACL;QACnC;QAEAtE,KAAK,iDAAiD;YACpD,MAAM,EAACwE,KAAK,EAAC,GAAG,MAAM7E,YACpBS,uBACA;gBAAC;gBAAc;gBAAe;aAAa,EAC3C;gBACEqE,OAAO;oBACL,GAAGnD,YAAY;oBACfC,WAAW;wBAACC,KAAK,CAAC;oBAAC;gBACrB;YACF;YAGFzB,OAAOyE,OAAOE,SAASC,SAAS,CAACxE;YACjCJ,OAAOyE,OAAOI,OAAOC,MAAMC,IAAI,CAAC;QAClC;QAEA9E,KAAK,wDAAwD;YAC3D8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E7E,QAAQ;gBACNgD,YAAYxC;gBACZyC,QAAQ;gBACRoC,OAAO;oBAACC,OAAO;gBAAK;gBACpBpC,KAAK,CAAC,kDAAkD,CAAC;YAC3D,GAAGC,KAAK,CAAC,KAAK;gBACZoC,SAAS,EAAE;YACb;YAEA,MAAM,EAACT,KAAK,EAAC,GAAG,MAAM7E,YACpBS,uBACA;gBAAC;gBAAc;gBAAS;aAAgB,EACxC;gBACEqE,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOE,SAASC,SAAS,CAC9B;YAEF5E,OAAOyE,OAAOI,OAAOC,MAAMC,IAAI,CAAC;QAClC;QAEA9E,KAAK,0CAA0C;YAC7CK,iBAAiB6E,iBAAiB,CAAC,IAAIC,MAAM;YAE7C,MAAM,EAACX,KAAK,EAAC,GAAG,MAAM7E,YACpBS,uBACA;gBAAC;gBAAc;gBAAe;aAAa,EAC3C;gBACEqE,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOE,SAASC,SAAS,CAAC;YACjC5E,OAAOyE,OAAOI,OAAOC,MAAMC,IAAI,CAAC;QAClC;QAEA9E,KAAK,4DAA4D;YAC/D8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E,MAAMa,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,0BAA0B,CAAC;YAEzD,MAAMlD,MAAMG,KAAKgG,OAAO,CAACD,MAAM;gBAAC/C,WAAW;YAAI;YAC/C,MAAMjD,UAAUgG,KAAK;YAErBhE,YAAYR,iBAAiB,CAAC;YAE9B,MAAM,EAAC4D,KAAK,EAAC,GAAG,MAAM7E,YACpBS,uBACA;gBAAC;gBAAc;gBAAe;gBAAc;gBAASgF;aAAI,EACzD;gBACEX,OAAOnD;YACT;YAGF,MAAMgE,WAAWjG,KAAK2C,IAAI,CAACC,QAAQC,GAAG,IAAIkD;YAE1CrF,OAAOqB,aAAamE,oBAAoB,CAAC;gBACvCC,SAAS;gBACTd,SAAS,CAAC,MAAM,EAAEY,SAAS,iDAAiD,CAAC;YAC/E;YAEAvF,OAAOyE,OAAOE,SAASC,SAAS,CAAC;YACjC5E,OAAOyE,OAAOI,OAAOC,MAAMC,IAAI,CAAC;QAClC;QAEA9E,KAAKmE,IAAI,CAAC;YACR;gBACE;gBACA;oBACE,MAAMI,OAAO;oBACb,MAAM3C,OAAO;oBACbU,cAAc;wBACZC,OAAO;4BAAC;gCAACgC;gCAAM3C;gCAAMyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,CAAC,EAAEqE,MAAM;4BAAA;yBAAE;oBACnF;oBACA3E,KAAK,yBAAyB2D,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,CAAC,EAAEqE,MAAM,EAAE1B,KAAK,CAAC,KAAK;wBAC7E6B,SAAS;oBACX;gBACF;aACD;YACD;gBACE;gBACA;oBACE,MAAMH,OAAO;oBACb,MAAM3C,OAAO;oBACbU,cAAc;wBACZC,OAAO;4BAAC;gCAACgC;gCAAM3C;gCAAMyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,CAAC,EAAEqE,MAAM;4BAAA;yBAAE;oBACnF;oBACA3E,KAAK,yBAAyB2D,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,CAAC,EAAEqE,MAAM,EAAE1B,KAAK,CAAC,KAAK;wBAC7E6B,SAAS;oBACX;gBACF;aACD;YACD;gBACE;gBACA;oBACEhF,QAAQ;wBACNgD,YAAYxC;wBACZyC,QAAQ;wBACRC,KAAK,CAAC,6DAA6D,CAAC;oBACtE,GAAGC,KAAK,CAAC,KAAK;wBACZ6B,SAAS;oBACX;gBACF;aACD;YACD;gBACE;gBACA;oBACE,sBAAsB;oBACtBhF,QAAQ;wBACNgD,YAAYxC;wBACZyC,QAAQ;wBACRC,KAAK,CAAC,6DAA6D,CAAC;oBACtE,GAAGC,KAAK,CAAC,KAAK;wBACZC,WAAW;wBACXP,OAAO;4BACL;gCACEgC,MAAM;gCACN3C,MAAM;gCACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;4BACzD;yBACD;wBACDuC,YAAY;wBACZM,YAAY;oBACd;oBAEA,oBAAoB;oBACpBrD,QAAQ;wBACNgD,YAAYxC;wBACZyC,QAAQ;wBACRoC,OAAO;4BAACtC,YAAY;wBAAO;wBAC3BG,KAAK,CAAC,6DAA6D,CAAC;oBACtE,GAAGC,KAAK,CAAC,KAAK;wBACZ6B,SAAS;oBACX;gBACF;aACD;SACF,EAAE,wBAAwB,OAAOe,aAAaC;YAC7C5D;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAC5EmB;YAEA,MAAMN,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,2BAA2B,CAAC;YAC1D,MAAM,EAACoC,KAAK,EAAC,GAAG,MAAM7E,YACpBS,uBACA;gBAAC;gBAAc;gBAAe;gBAAc;gBAASgF;aAAI,EACzD;gBACEX,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOE,SAASC,SAAS,CAAC;YACjC5E,OAAOyE,OAAOI,OAAOC,MAAMC,IAAI,CAAC;QAClC;IACF;IAEAhF,SAAS,wBAAwB;QAC/BE,KAAK,mDAAmD;YACtD8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E7E,QAAQ;gBACNgD,YAAYxC;gBACZyC,QAAQ;gBACRC,KAAK,CAAC,6DAA6D,CAAC;YACtE,GAAGC,KAAK,CAAC,KAAK;gBACZC,WAAW;gBACXP,OAAO;oBACL;wBACEgC,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;oBACzD;oBACA;wBACEqE,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,OAAO,CAAC;oBAC3D;oBACA;wBACEqE,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,MAAM,CAAC;oBAC1D;iBACD;gBACD6C,YAAY;YACd;YAEAnD,KAAK,yBACF2D,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,KAAK,CAAC,EACjC2C,KAAK,CAAC,KAAK,uCACXU,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,OAAO,CAAC,EACnC2C,KAAK,CAAC,KAAKW,OAAOC,IAAI,CAAC,oBAAoB;gBAAC,gBAAgB;YAAY,GACxEF,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,MAAM,CAAC,EAClC2C,KAAK,CAAC,KAAKW,OAAOC,IAAI,CAAC;YAE1B,MAAM2B,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,qBAAqB,CAAC;YACpD,MAAM,EAACoC,KAAK,EAAEmB,MAAM,EAAE5B,MAAM,EAAC,GAAG,MAAMpE,YACpCS,uBACA;gBACE;gBACA;gBACA;gBACA;gBACAgF;gBACA;gBACA;gBACA;aACD,EACD;gBACEX,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOoB,aAAa;YAE3B7F,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YAEzB5E,OAAO4F,QAAQhB,SAAS,CAAC;YACzB5E,OAAOf,WAAWoG,MAAMN,IAAI,CAAC;QAC/B;QAEA9E,KAAKmE,IAAI,CAAC;YACR;gBACE;gBACA;oBACE;wBACEI,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;oBACzD;iBACD;aACF;YACD;gBACE;gBACA;oBACE;wBACEqE,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;oBACzD;oBACA;wBACEqE,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,OAAO,CAAC;oBAC3D;oBACA;wBACEqE,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,MAAM,CAAC;oBAC1D;iBACD;aACF;SACF,EAAE,kCAAkC,OAAOuF,aAAalD;YACvDT;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5EjC,cAAc;gBAACC;YAAK;YACpBU,kBAAkBV;YAElB,MAAM6C,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,QAAQ,EAAEqD,YAAYI,UAAU,CAAC,QAAQ,KAAK,cAAc,CAAC;YAC3F,MAAM,EAACrB,KAAK,EAAEmB,MAAM,EAAC,GAAG,MAAMhG,YAC5BS,uBACA;gBAAC;gBAAc;gBAAe;gBAAc;gBAASgF;gBAAK;aAAc,EACxE;gBACEX,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOoB,aAAa;YAC3B7F,OAAO4F,QAAQhB,SAAS,CAAC;YACzB5E,OAAOf,WAAWoG,MAAMN,IAAI,CAAC;QAC/B;QAEA9E,KAAK,qDAAqD;YACxD8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E,MAAMhC,QAAQ;gBACZ;oBACEgC,MAAM;oBACN3C,MAAM;oBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;gBACzD;aACD;YAEDoC,cAAc;gBAACC;YAAK;YACpBU,kBAAkBV;YAElB,MAAM6C,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,6BAA6B,CAAC;YAE5D,MAAMlD,MAAMG,KAAKgG,OAAO,CAACD,MAAM;gBAAC/C,WAAW;YAAI;YAC/C,MAAMjD,UAAUgG,KAAK;YAErBhE,YAAYR,iBAAiB,CAAC;YAE9B,MAAM,EAAC4D,KAAK,EAAEmB,MAAM,EAAC,GAAG,MAAMhG,YAC5BS,uBACA;gBAAC;gBAAc;gBAAe;gBAAc;gBAASgF;aAAI,EACzD;gBACEX,OAAOnD;YACT;YAGF,MAAMgE,WAAWjG,KAAK2C,IAAI,CAACC,QAAQC,GAAG,IAAIkD;YAE1CrF,OAAOqB,aAAamE,oBAAoB,CAAC;gBACvCC,SAAS;gBACTd,SAAS,CAAC,MAAM,EAAEY,SAAS,iDAAiD,CAAC;YAC/E;YACAvF,OAAOyE,OAAOoB,aAAa;YAC3B7F,OAAO4F,QAAQhB,SAAS,CAAC;YACzB5E,OAAOf,WAAWoG,MAAMN,IAAI,CAAC;QAC/B;QAEA9E,KAAK,sDAAsD;YACzD8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E,aAAa;YACb7E,QAAQ;gBACNgD,YAAYxC;gBACZyC,QAAQ;gBACRC,KAAK,CAAC,6DAA6D,CAAC;YACtE,GAAGC,KAAK,CAAC,KAAK;gBACZC,WAAW;gBACXP,OAAO;oBACL;wBACEgC,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;oBACzD;oBACA;wBACEqE,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,OAAO,CAAC;oBAC3D;iBACD;gBACDuC,YAAY;gBACZM,YAAY;YACd;YAEA,cAAc;YACdrD,QAAQ;gBACNgD,YAAYxC;gBACZyC,QAAQ;gBACRoC,OAAO;oBAACtC,YAAY;gBAAO;gBAC3BG,KAAK,CAAC,6DAA6D,CAAC;YACtE,GAAGC,KAAK,CAAC,KAAK;gBACZC,WAAW;gBACXP,OAAO;oBACL;wBACEgC,MAAM;wBACN3C,MAAM;wBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,MAAM,CAAC;oBAC1D;iBACD;gBACD6C,YAAY;YACd;YAEA,sBAAsB;YACtBnD,KAAK,yBACF2D,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,KAAK,CAAC,EACjC2C,KAAK,CAAC,KAAK,uCACXU,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,OAAO,CAAC,EACnC2C,KAAK,CAAC,KAAKW,OAAOC,IAAI,CAAC,oBACvBF,GAAG,CAAC,CAAC,CAAC,EAAErD,mBAAmB,MAAM,CAAC,EAClC2C,KAAK,CAAC,KAAKW,OAAOC,IAAI,CAAC;YAE1B,MAAM2B,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,+BAA+B,CAAC;YAC9D,MAAM,EAACoC,KAAK,EAAEmB,MAAM,EAAC,GAAG,MAAMhG,YAC5BS,uBACA;gBAAC;gBAAc;gBAAe;gBAAc;gBAASgF;gBAAK;aAAc,EACxE;gBACEX,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOoB,aAAa;YAC3B7F,OAAO4F,QAAQhB,SAAS,CAAC;YACzB5E,OAAOf,WAAWoG,MAAMN,IAAI,CAAC;QAC/B;IACF;IAEAhF,SAAS,uBAAuB;QAC9BE,KAAK,qEAAqE;YACxE8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5E7E,QAAQ;gBACNgD,YAAYxC;gBACZyC,QAAQ;gBACRoC,OAAO;oBAACC,OAAO;gBAAK;gBACpBpC,KAAK,CAAC,kDAAkD,CAAC;YAC3D,GAAGC,KAAK,CAAC,KAAK;gBACZoC,SAAS;oBACP;wBAACnC,WAAW;wBAAwBN,IAAI;oBAAU;oBAClD;wBAACM,WAAW;wBAAwBN,IAAI;oBAAU;iBACnD;YACH;YAEAtB,WAAWN,iBAAiB,CAAC;YAE7B,MAAM2B,QAAQ;gBACZ;oBACEgC,MAAM;oBACN3C,MAAM;oBACNyB,KAAK,CAAC,sBAAsB,EAAEnD,mBAAmB,KAAK,CAAC;gBACzD;aACD;YACDR,QAAQ;gBACNgD,YAAYxC;gBACZyC,QAAQ;gBACRC,KAAK,CAAC,2DAA2D,CAAC;YACpE,GAAGC,KAAK,CAAC,KAAK;gBACZC,WAAW;gBACXP;gBACAQ,YAAYR,MAAMS,MAAM;YAC1B;YACAC,kBAAkBV;YAElB,MAAM6C,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,4BAA4B,CAAC;YAE3D,MAAM,EAACoC,KAAK,EAAEmB,MAAM,EAAC,GAAG,MAAMhG,YAC5BS,uBACA;gBAAC;gBAAc;gBAASgF;gBAAK;aAAc,EAC3C;gBACEX,OAAOnD;YACT;YAGFvB,OAAOyE,OAAOoB,aAAa;YAC3B7F,OAAOmB,YAAYqE,oBAAoB,CACrCxF,OAAO+F,gBAAgB,CAAC;gBACtBC,SAAShG,OAAOiG,eAAe,CAAC;oBAC9B;wBAACzB,MAAM;wBAAY0B,OAAO;oBAAU;oBACpC;wBAAC1B,MAAM;wBAAY0B,OAAO;oBAAU;iBACrC;gBACDvB,SAAS3E,OAAOmG,gBAAgB,CAAC;YACnC;YAEFnG,OAAO4F,QAAQhB,SAAS,CAAC;YACzB5E,OAAOf,WAAWoG,MAAMN,IAAI,CAAC;QAC/B;QAEA9E,KAAK,oEAAoE;YACvE8B;YACAzB,iBAAiBO,iBAAiB,CAAC;gBAAC;oBAAC2D,MAAM;gBAAY;gBAAG;oBAACA,MAAM;gBAAS;aAAE;YAE5EjC,cAAc;gBAACC,OAAO,EAAE;YAAA;YACxBrB,WAAWN,iBAAiB,CAAC;YAC7B,MAAMwE,MAAM,CAAC,IAAI,EAAEjD,KAAKC,GAAG,GAAG,oCAAoC,CAAC;YACnEjB,UAAUP,iBAAiB,CAACwE;YAE5B,MAAM,EAACrB,MAAM,EAAC,GAAG,MAAMpE,YAAYS,uBAAuB;gBAAC;gBAAe;aAAa,EAAE;gBACvFqE,OAAOnD;YACT;YAEAvB,OAAOmB,YAAYqE,oBAAoB,CAAC;gBACtCQ,SAAS;oBACP;wBAACxB,MAAM;wBAAc0B,OAAO;oBAAY;oBACxC;wBAAC1B,MAAM;wBAAW0B,OAAO;oBAAS;iBACnC;gBACDvB,SAAS;YACX;YACA3E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOgE,QAAQY,SAAS,CAAC;YACzB5E,OAAOf,WAAWoG,MAAMN,IAAI,CAAC;QAC/B;IACF;AACF"}
|