@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
|
@@ -1,30 +1,11 @@
|
|
|
1
1
|
import { runCommand } from '@oclif/test';
|
|
2
|
-
import { getCliConfig } from '@sanity/cli-core';
|
|
3
2
|
import { select } from '@sanity/cli-core/ux';
|
|
4
3
|
import { mockApi, testCommand } from '@sanity/cli-test';
|
|
5
4
|
import nock from 'nock';
|
|
6
|
-
import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
5
|
+
import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
7
6
|
import { HOOK_API_VERSION } from '../../../actions/hook/constants.js';
|
|
8
7
|
import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
|
|
9
8
|
import { LogsHookCommand } from '../logs.js';
|
|
10
|
-
vi.mock('../../../../../cli-core/src/config/findProjectRoot.js', async ()=>{
|
|
11
|
-
return {
|
|
12
|
-
findProjectRoot: vi.fn().mockResolvedValue({
|
|
13
|
-
directory: '/test/path',
|
|
14
|
-
root: '/test/path',
|
|
15
|
-
type: 'studio'
|
|
16
|
-
})
|
|
17
|
-
};
|
|
18
|
-
});
|
|
19
|
-
vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', async ()=>{
|
|
20
|
-
return {
|
|
21
|
-
getCliConfig: vi.fn().mockResolvedValue({
|
|
22
|
-
api: {
|
|
23
|
-
projectId: 'test-project'
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
};
|
|
27
|
-
});
|
|
28
9
|
vi.mock('@sanity/cli-core/ux', async ()=>{
|
|
29
10
|
const actual = await vi.importActual('@sanity/cli-core/ux');
|
|
30
11
|
return {
|
|
@@ -32,7 +13,20 @@ vi.mock('@sanity/cli-core/ux', async ()=>{
|
|
|
32
13
|
select: vi.fn()
|
|
33
14
|
};
|
|
34
15
|
});
|
|
35
|
-
const
|
|
16
|
+
const testProjectId = 'test-project';
|
|
17
|
+
const defaultMocks = {
|
|
18
|
+
cliConfig: {
|
|
19
|
+
api: {
|
|
20
|
+
projectId: testProjectId
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
projectRoot: {
|
|
24
|
+
directory: '/test/path',
|
|
25
|
+
path: '/test/path/sanity.config.ts',
|
|
26
|
+
type: 'studio'
|
|
27
|
+
},
|
|
28
|
+
token: 'test-token'
|
|
29
|
+
};
|
|
36
30
|
const mockedSelect = vi.mocked(select);
|
|
37
31
|
describe('#hook:logs', ()=>{
|
|
38
32
|
afterEach(()=>{
|
|
@@ -49,12 +43,16 @@ describe('#hook:logs', ()=>{
|
|
|
49
43
|
expect(stdout).toContain('List latest log entries for a given hook');
|
|
50
44
|
});
|
|
51
45
|
test('displays error when no project ID is found', async ()=>{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
const { error } = await testCommand(LogsHookCommand, [], {
|
|
47
|
+
mocks: {
|
|
48
|
+
...defaultMocks,
|
|
49
|
+
cliConfig: {
|
|
50
|
+
api: {
|
|
51
|
+
projectId: undefined
|
|
52
|
+
}
|
|
53
|
+
}
|
|
55
54
|
}
|
|
56
55
|
});
|
|
57
|
-
const { error } = await testCommand(LogsHookCommand);
|
|
58
56
|
expect(error).toBeInstanceOf(Error);
|
|
59
57
|
expect(error?.message).toEqual(NO_PROJECT_ID);
|
|
60
58
|
expect(error?.oclif?.exit).toBe(1);
|
|
@@ -64,7 +62,9 @@ describe('#hook:logs', ()=>{
|
|
|
64
62
|
apiVersion: HOOK_API_VERSION,
|
|
65
63
|
uri: '/hooks/projects/test-project'
|
|
66
64
|
}).reply(200, []);
|
|
67
|
-
const { error } = await testCommand(LogsHookCommand
|
|
65
|
+
const { error } = await testCommand(LogsHookCommand, [], {
|
|
66
|
+
mocks: defaultMocks
|
|
67
|
+
});
|
|
68
68
|
expect(error).toBeInstanceOf(Error);
|
|
69
69
|
expect(error?.message).toContain('No hooks currently registered');
|
|
70
70
|
expect(error?.oclif?.exit).toBe(1);
|
|
@@ -83,7 +83,9 @@ describe('#hook:logs', ()=>{
|
|
|
83
83
|
]);
|
|
84
84
|
const { error } = await testCommand(LogsHookCommand, [
|
|
85
85
|
'non-existent-hook'
|
|
86
|
-
]
|
|
86
|
+
], {
|
|
87
|
+
mocks: defaultMocks
|
|
88
|
+
});
|
|
87
89
|
expect(error).toBeInstanceOf(Error);
|
|
88
90
|
expect(error?.message).toContain('Hook with name "non-existent-hook" not found');
|
|
89
91
|
expect(error?.oclif?.exit).toBe(1);
|
|
@@ -134,7 +136,9 @@ describe('#hook:logs', ()=>{
|
|
|
134
136
|
resultCode: 404
|
|
135
137
|
}
|
|
136
138
|
]);
|
|
137
|
-
const { stdout } = await testCommand(LogsHookCommand
|
|
139
|
+
const { stdout } = await testCommand(LogsHookCommand, [], {
|
|
140
|
+
mocks: defaultMocks
|
|
141
|
+
});
|
|
138
142
|
expect(stdout).toContain('Date: 2025-08-07T09:15:36.628Z');
|
|
139
143
|
expect(stdout).toContain('Status: failure');
|
|
140
144
|
expect(stdout).toContain('Result code: 404');
|
|
@@ -194,7 +198,9 @@ describe('#hook:logs', ()=>{
|
|
|
194
198
|
]);
|
|
195
199
|
const { stdout } = await testCommand(LogsHookCommand, [
|
|
196
200
|
'test-hook'
|
|
197
|
-
]
|
|
201
|
+
], {
|
|
202
|
+
mocks: defaultMocks
|
|
203
|
+
});
|
|
198
204
|
expect(stdout).toContain('Date: 2025-08-07T09:15:36.628Z');
|
|
199
205
|
expect(stdout).toContain('Status: success');
|
|
200
206
|
expect(stdout).toContain('Result code: 200');
|
|
@@ -218,7 +224,9 @@ describe('#hook:logs', ()=>{
|
|
|
218
224
|
}).reply(500, {
|
|
219
225
|
message: 'Internal Server Error'
|
|
220
226
|
});
|
|
221
|
-
const { error } = await testCommand(LogsHookCommand
|
|
227
|
+
const { error } = await testCommand(LogsHookCommand, [], {
|
|
228
|
+
mocks: defaultMocks
|
|
229
|
+
});
|
|
222
230
|
expect(error).toBeInstanceOf(Error);
|
|
223
231
|
expect(error?.message).toContain('Hook logs retrieval failed');
|
|
224
232
|
expect(error?.oclif?.exit).toBe(1);
|
|
@@ -263,7 +271,9 @@ describe('#hook:logs', ()=>{
|
|
|
263
271
|
apiVersion: HOOK_API_VERSION,
|
|
264
272
|
uri: `/hooks/projects/test-project/${HOOK_ID_2}/attempts`
|
|
265
273
|
}).reply(200, []);
|
|
266
|
-
const { stdout } = await testCommand(LogsHookCommand
|
|
274
|
+
const { stdout } = await testCommand(LogsHookCommand, [], {
|
|
275
|
+
mocks: defaultMocks
|
|
276
|
+
});
|
|
267
277
|
expect(vi.mocked(select)).toHaveBeenCalledWith({
|
|
268
278
|
choices: [
|
|
269
279
|
{
|
|
@@ -317,7 +327,9 @@ describe('#hook:logs', ()=>{
|
|
|
317
327
|
}).reply(200, []);
|
|
318
328
|
const { stdout } = await testCommand(LogsHookCommand, [
|
|
319
329
|
'test-hook'
|
|
320
|
-
]
|
|
330
|
+
], {
|
|
331
|
+
mocks: defaultMocks
|
|
332
|
+
});
|
|
321
333
|
expect(stdout).toContain('Date: 2025-08-07T11:00:00.000Z');
|
|
322
334
|
expect(stdout).toContain('Status: success');
|
|
323
335
|
expect(stdout).toContain('Result code: 200');
|
|
@@ -357,7 +369,9 @@ describe('#hook:logs', ()=>{
|
|
|
357
369
|
}).reply(500, {
|
|
358
370
|
message: 'Internal Server Error'
|
|
359
371
|
});
|
|
360
|
-
const { error } = await testCommand(LogsHookCommand
|
|
372
|
+
const { error } = await testCommand(LogsHookCommand, [], {
|
|
373
|
+
mocks: defaultMocks
|
|
374
|
+
});
|
|
361
375
|
expect(error).toBeInstanceOf(Error);
|
|
362
376
|
expect(error?.message).toContain('Hook logs retrieval failed');
|
|
363
377
|
expect(error?.oclif?.exit).toBe(1);
|
|
@@ -428,7 +442,9 @@ describe('#hook:logs', ()=>{
|
|
|
428
442
|
]);
|
|
429
443
|
const { stdout } = await testCommand(LogsHookCommand, [
|
|
430
444
|
'--detailed'
|
|
431
|
-
]
|
|
445
|
+
], {
|
|
446
|
+
mocks: defaultMocks
|
|
447
|
+
});
|
|
432
448
|
expect(stdout).toContain('Date: 2025-08-07T13:00:00.000Z');
|
|
433
449
|
expect(stdout).toContain('Status: failure');
|
|
434
450
|
expect(stdout).toContain('Result code: 400');
|
|
@@ -494,7 +510,9 @@ describe('#hook:logs', ()=>{
|
|
|
494
510
|
]);
|
|
495
511
|
const { stdout } = await testCommand(LogsHookCommand, [
|
|
496
512
|
'--detailed'
|
|
497
|
-
]
|
|
513
|
+
], {
|
|
514
|
+
mocks: defaultMocks
|
|
515
|
+
});
|
|
498
516
|
expect(stdout).toContain('Date: 2025-08-07T14:00:00.000Z');
|
|
499
517
|
expect(stdout).toContain('Status: success');
|
|
500
518
|
expect(stdout).toContain('Result code: 201');
|
|
@@ -585,7 +603,9 @@ describe('#hook:logs', ()=>{
|
|
|
585
603
|
]);
|
|
586
604
|
const { stdout } = await testCommand(LogsHookCommand, [
|
|
587
605
|
'--detailed'
|
|
588
|
-
]
|
|
606
|
+
], {
|
|
607
|
+
mocks: defaultMocks
|
|
608
|
+
});
|
|
589
609
|
expect(stdout).toContain('Date: 2025-08-07T15:00:00.000Z');
|
|
590
610
|
expect(stdout).toContain('Status: failure');
|
|
591
611
|
expect(stdout).toContain('Failures: 4');
|
|
@@ -672,7 +692,9 @@ describe('#hook:logs', ()=>{
|
|
|
672
692
|
updatedAt: '2025-08-07T16:01:01.200Z'
|
|
673
693
|
}
|
|
674
694
|
]);
|
|
675
|
-
const { stdout } = await testCommand(LogsHookCommand
|
|
695
|
+
const { stdout } = await testCommand(LogsHookCommand, [], {
|
|
696
|
+
mocks: defaultMocks
|
|
697
|
+
});
|
|
676
698
|
expect(stdout).toContain('Date: 2025-08-07T16:00:00.000Z');
|
|
677
699
|
expect(stdout).toContain('Status: success');
|
|
678
700
|
expect(stdout).toContain('Result code: 200');
|
|
@@ -692,7 +714,9 @@ describe('#hook:logs', ()=>{
|
|
|
692
714
|
}).reply(500, {
|
|
693
715
|
message: 'Internal Server Error'
|
|
694
716
|
});
|
|
695
|
-
const { error } = await testCommand(LogsHookCommand
|
|
717
|
+
const { error } = await testCommand(LogsHookCommand, [], {
|
|
718
|
+
mocks: defaultMocks
|
|
719
|
+
});
|
|
696
720
|
expect(error).toBeInstanceOf(Error);
|
|
697
721
|
expect(error?.message).toContain('Hook list retrieval failed');
|
|
698
722
|
expect(error?.message).toContain('Internal Server Error');
|
|
@@ -717,7 +741,9 @@ describe('#hook:logs', ()=>{
|
|
|
717
741
|
type: 'document'
|
|
718
742
|
}
|
|
719
743
|
]);
|
|
720
|
-
const { error } = await testCommand(LogsHookCommand
|
|
744
|
+
const { error } = await testCommand(LogsHookCommand, [], {
|
|
745
|
+
mocks: defaultMocks
|
|
746
|
+
});
|
|
721
747
|
expect(error).toBeInstanceOf(Error);
|
|
722
748
|
expect(error?.message).toContain('No hook selected');
|
|
723
749
|
expect(error?.oclif?.exit).toBe(1);
|
|
@@ -757,7 +783,9 @@ describe('#hook:logs', ()=>{
|
|
|
757
783
|
}).reply(200, []);
|
|
758
784
|
const { stdout } = await testCommand(LogsHookCommand, [
|
|
759
785
|
'--detailed'
|
|
760
|
-
]
|
|
786
|
+
], {
|
|
787
|
+
mocks: defaultMocks
|
|
788
|
+
});
|
|
761
789
|
expect(stdout).toContain('Date: 2025-08-07T17:00:00.000Z');
|
|
762
790
|
expect(stdout).toContain('Status: queued');
|
|
763
791
|
expect(stdout).toContain('Result code: 200');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/hook/__tests__/logs.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {getCliConfig} from '@sanity/cli-core'\nimport {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' // This should match the version in services/hooks.ts\n\nimport {HOOK_API_VERSION} from '../../../actions/hook/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {LogsHookCommand} from '../logs.js'\n\nvi.mock('../../../../../cli-core/src/config/findProjectRoot.js', async () => {\n return {\n findProjectRoot: vi.fn().mockResolvedValue({\n directory: '/test/path',\n root: '/test/path',\n type: 'studio',\n }),\n }\n})\n\nvi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', async () => {\n return {\n getCliConfig: vi.fn().mockResolvedValue({\n api: {\n projectId: 'test-project',\n },\n }),\n }\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 select: vi.fn(),\n }\n})\n\nconst mockedGetCliConfig = vi.mocked(getCliConfig)\nconst mockedSelect = vi.mocked(select)\n\ndescribe('#hook:logs', () => {\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand(['hook logs', '--help'])\n\n expect(stdout).toContain('List latest log entries for a given hook')\n })\n\n test('displays error when no project ID is found', async () => {\n mockedGetCliConfig.mockResolvedValueOnce({\n api: {\n projectId: undefined,\n },\n })\n\n const {error} = await testCommand(LogsHookCommand)\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays error when no hooks are registered', async () => {\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [])\n\n const {error} = await testCommand(LogsHookCommand)\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('No hooks currently registered')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays error when specified hook is not found', async () => {\n const HOOK_ID = 'not-found-hook-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n const {error} = await testCommand(LogsHookCommand, ['non-existent-hook'])\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook with name \"non-existent-hook\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays logs for a single hook', async () => {\n const HOOK_ID = 'single-hook-test'\n const MESSAGE_ID = 'single-msg-test'\n const ATTEMPT_ID = 'single-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n dataset: 'production',\n failureCount: 1,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"test\": true}',\n projectId: 'test-project',\n resultCode: 404,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n failureReason: 'http',\n hookId: HOOK_ID,\n id: ATTEMPT_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultCode: 404,\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand)\n\n expect(stdout).toContain('Date: 2025-08-07T09:15:36.628Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 404')\n expect(stdout).toContain('Failures: 1')\n })\n\n test('displays logs for a specified hook', async () => {\n const HOOK_ID_1 = 'specified-hook-test-1'\n const HOOK_ID_2 = 'specified-hook-test-2'\n const MESSAGE_ID = 'specified-msg-test'\n const ATTEMPT_ID = 'specified-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID_1,\n name: 'test-hook',\n type: 'document',\n },\n {\n id: HOOK_ID_2,\n name: 'another-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_1}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID_1,\n id: MESSAGE_ID,\n payload: '{\"test\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_1}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n failureReason: '',\n hookId: HOOK_ID_1,\n id: ATTEMPT_ID,\n inProgress: false,\n isFailure: false,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultCode: 200,\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['test-hook'])\n\n expect(stdout).toContain('Date: 2025-08-07T09:15:36.628Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 200')\n expect(stdout).not.toContain('Failures:')\n })\n\n test('displays error when hook logs retrieval fails', async () => {\n const HOOK_ID = 'error-logs-hook-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(LogsHookCommand)\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook logs retrieval failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('prompts user to select hook when multiple hooks exist', async () => {\n const HOOK_ID_1 = 'select-hook-test-1'\n const HOOK_ID_2 = 'select-hook-test-2'\n const MESSAGE_ID = 'select-msg-test'\n\n mockedSelect.mockResolvedValue(HOOK_ID_2)\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID_1,\n name: 'first-hook',\n type: 'document',\n },\n {\n id: HOOK_ID_2,\n name: 'second-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_2}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T10:00:00.000Z',\n dataset: 'production',\n failureCount: 1,\n hookId: HOOK_ID_2,\n id: MESSAGE_ID,\n payload: '{\"selected\": true}',\n projectId: 'test-project',\n resultCode: 500,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_2}/attempts`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(LogsHookCommand)\n\n expect(vi.mocked(select)).toHaveBeenCalledWith({\n choices: [\n {name: 'first-hook', value: HOOK_ID_1},\n {name: 'second-hook', value: HOOK_ID_2},\n ],\n message: 'Select hook to list logs for',\n })\n\n expect(stdout).toContain('Date: 2025-08-07T10:00:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 500')\n expect(stdout).toContain('Failures: 1')\n })\n\n test('matches hook name case-insensitively', async () => {\n const HOOK_ID = 'case-hook-test'\n const MESSAGE_ID = 'case-msg-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'Test-Hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T11:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"case\": \"insensitive\"}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(LogsHookCommand, ['test-hook'])\n\n expect(stdout).toContain('Date: 2025-08-07T11:00:00.000Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 200')\n })\n\n test('displays error when hook attempts retrieval fails', async () => {\n const HOOK_ID = 'attempt-error-hook-test'\n const MESSAGE_ID = 'attempt-error-msg-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T12:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"test\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(LogsHookCommand)\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook logs retrieval failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays detailed output with --detailed flag', async () => {\n const HOOK_ID = 'detailed-hook-test'\n const MESSAGE_ID = 'detailed-msg-test'\n const ATTEMPT_TIMEOUT_ID = 'detailed-timeout-attempt-test'\n const ATTEMPT_PENDING_ID = 'detailed-pending-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T13:00:00.000Z',\n dataset: 'production',\n failureCount: 2,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"document\": {\"_id\": \"test\", \"_type\": \"post\"}, \"event\": \"create\"}',\n projectId: 'test-project',\n resultCode: 400,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T13:00:01.000Z',\n duration: 5000,\n failureReason: 'timeout',\n hookId: HOOK_ID,\n id: ATTEMPT_TIMEOUT_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: '2025-08-07T13:00:06.000Z',\n },\n {\n createdAt: '2025-08-07T13:00:10.000Z',\n duration: null,\n failureReason: '',\n hookId: HOOK_ID,\n id: ATTEMPT_PENDING_ID,\n inProgress: true,\n isFailure: false,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: null,\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'])\n\n expect(stdout).toContain('Date: 2025-08-07T13:00:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 400')\n expect(stdout).toContain('Failures: 2')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain('document')\n expect(stdout).toContain('_type')\n expect(stdout).toContain('post')\n expect(stdout).toContain('Attempts:')\n expect(stdout).toContain('[2025-08-07T13:00:01Z]')\n expect(stdout).toContain('Failure: Request timed out')\n expect(stdout).toContain('[2025-08-07T13:00:10Z]')\n expect(stdout).toContain('Pending')\n })\n\n test('displays detailed output with successful attempts', async () => {\n const HOOK_ID = 'success-detailed-hook-test'\n const MESSAGE_ID = 'success-detailed-msg-test'\n const ATTEMPT_ID = 'success-detailed-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T14:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"success\": true}',\n projectId: 'test-project',\n resultCode: 201,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T14:00:01.500Z',\n duration: 250,\n failureReason: '',\n hookId: HOOK_ID,\n id: ATTEMPT_ID,\n inProgress: false,\n isFailure: false,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: 'Created',\n resultCode: 201,\n updatedAt: '2025-08-07T14:00:01.750Z',\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'])\n\n expect(stdout).toContain('Date: 2025-08-07T14:00:00.000Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 201')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain('{ success: true }')\n expect(stdout).toContain('Attempts:')\n expect(stdout).toContain('[2025-08-07T14:00:01Z]')\n expect(stdout).toContain('Success: HTTP 201 (250ms)')\n })\n\n test('displays different failure reasons with detailed output', async () => {\n const HOOK_ID = 'failure-reasons-hook-test'\n const MESSAGE_ID = 'failure-reasons-msg-test'\n const ATTEMPT_HTTP_ID = 'failure-http-attempt-test'\n const ATTEMPT_NETWORK_ID = 'failure-network-attempt-test'\n const ATTEMPT_OTHER_ID = 'failure-other-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T15:00:00.000Z',\n dataset: 'production',\n failureCount: 4,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"failures\": \"test\"}',\n projectId: 'test-project',\n resultCode: null,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T15:00:01.000Z',\n duration: 100,\n failureReason: 'http',\n hookId: HOOK_ID,\n id: ATTEMPT_HTTP_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: 'Not Found',\n resultCode: 404,\n updatedAt: '2025-08-07T15:00:01.100Z',\n },\n {\n createdAt: '2025-08-07T15:00:02.000Z',\n duration: 0,\n failureReason: 'network',\n hookId: HOOK_ID,\n id: ATTEMPT_NETWORK_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: '2025-08-07T15:00:02.000Z',\n },\n {\n createdAt: '2025-08-07T15:00:03.000Z',\n duration: 200,\n failureReason: 'other',\n hookId: HOOK_ID,\n id: ATTEMPT_OTHER_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: '2025-08-07T15:00:03.200Z',\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'])\n\n expect(stdout).toContain('Date: 2025-08-07T15:00:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Failures: 4')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain(\"{ failures: 'test' }\")\n expect(stdout).toContain('Attempts:')\n expect(stdout).toContain(\n `Failure: HTTP 404 (run \\`sanity hook attempt ${ATTEMPT_HTTP_ID}\\` for details)`,\n )\n expect(stdout).toContain('Failure: Network error')\n expect(stdout).toContain('Failure: Unknown error')\n })\n\n test('displays multiple messages with separators', async () => {\n const HOOK_ID = 'multiple-messages-hook-test'\n const MESSAGE_ID_1 = 'multiple-msg-1-test'\n const MESSAGE_ID_2 = 'multiple-msg-2-test'\n const ATTEMPT_ID_1 = 'multiple-attempt-1-test'\n const ATTEMPT_ID_2 = 'multiple-attempt-2-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T16:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID_1,\n payload: '{\"first\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n {\n createdAt: '2025-08-07T16:01:00.000Z',\n dataset: 'production',\n failureCount: 1,\n hookId: HOOK_ID,\n id: MESSAGE_ID_2,\n payload: '{\"second\": true}',\n projectId: 'test-project',\n resultCode: 500,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T16:00:01.000Z',\n duration: 100,\n failureReason: '',\n hookId: HOOK_ID,\n id: ATTEMPT_ID_1,\n inProgress: false,\n isFailure: false,\n messageId: MESSAGE_ID_1,\n projectId: 'test-project',\n resultBody: 'OK',\n resultCode: 200,\n updatedAt: '2025-08-07T16:00:01.100Z',\n },\n {\n createdAt: '2025-08-07T16:01:01.000Z',\n duration: 200,\n failureReason: 'http',\n hookId: HOOK_ID,\n id: ATTEMPT_ID_2,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID_2,\n projectId: 'test-project',\n resultBody: 'Error',\n resultCode: 500,\n updatedAt: '2025-08-07T16:01:01.200Z',\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand)\n\n expect(stdout).toContain('Date: 2025-08-07T16:00:00.000Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 200')\n expect(stdout).toContain('---') // Separator between messages\n expect(stdout).toContain('Date: 2025-08-07T16:01:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 500')\n expect(stdout).toContain('Failures: 1')\n\n // Verify that the first message section (before \"---\") doesn't have failures\n const [firstSection] = stdout.split('---')\n expect(firstSection).not.toContain('Failures:')\n })\n\n test('displays error when fetching hooks fails', async () => {\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(LogsHookCommand)\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook list retrieval failed')\n expect(error?.message).toContain('Internal Server Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays error when no hook is selected from prompt', async () => {\n const HOOK_ID_1 = 'no-select-hook-1-test'\n const HOOK_ID_2 = 'no-select-hook-2-test'\n\n mockedSelect.mockResolvedValue('non-existent-hook-id')\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID_1,\n name: 'first-hook',\n type: 'document',\n },\n {\n id: HOOK_ID_2,\n name: 'second-hook',\n type: 'document',\n },\n ])\n\n const {error} = await testCommand(LogsHookCommand)\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('No hook selected')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays message without attempts section when attempts array is empty', async () => {\n const HOOK_ID = 'empty-attempts-hook-test'\n const MESSAGE_ID = 'empty-attempts-msg-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T17:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"no_attempts\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'queued',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'])\n\n expect(stdout).toContain('Date: 2025-08-07T17:00:00.000Z')\n expect(stdout).toContain('Status: queued')\n expect(stdout).toContain('Result code: 200')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain('{ no_attempts: true }')\n expect(stdout).not.toContain('Attempts:') // No attempts section when empty\n })\n})\n"],"names":["runCommand","getCliConfig","select","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","HOOK_API_VERSION","NO_PROJECT_ID","LogsHookCommand","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","api","projectId","actual","importActual","mockedGetCliConfig","mocked","mockedSelect","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","mockResolvedValueOnce","undefined","error","toBeInstanceOf","Error","message","oclif","exit","toBe","apiVersion","uri","reply","HOOK_ID","id","name","MESSAGE_ID","ATTEMPT_ID","createdAt","dataset","failureCount","hookId","payload","resultCode","status","failureReason","inProgress","isFailure","messageId","HOOK_ID_1","HOOK_ID_2","not","toHaveBeenCalledWith","choices","value","ATTEMPT_TIMEOUT_ID","ATTEMPT_PENDING_ID","duration","resultBody","updatedAt","ATTEMPT_HTTP_ID","ATTEMPT_NETWORK_ID","ATTEMPT_OTHER_ID","MESSAGE_ID_1","MESSAGE_ID_2","ATTEMPT_ID_1","ATTEMPT_ID_2","firstSection","split"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/hook/__tests__/logs.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {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 {HOOK_API_VERSION} from '../../../actions/hook/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {LogsHookCommand} from '../logs.js'\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 select: vi.fn(),\n }\n})\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\nconst mockedSelect = vi.mocked(select)\n\ndescribe('#hook:logs', () => {\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand(['hook logs', '--help'])\n\n expect(stdout).toContain('List latest log entries for a given hook')\n })\n\n test('displays error when no project ID is found', async () => {\n const {error} = await testCommand(LogsHookCommand, [], {\n mocks: {\n ...defaultMocks,\n cliConfig: {api: {projectId: undefined}},\n },\n })\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays error when no hooks are registered', async () => {\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [])\n\n const {error} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('No hooks currently registered')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays error when specified hook is not found', async () => {\n const HOOK_ID = 'not-found-hook-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n const {error} = await testCommand(LogsHookCommand, ['non-existent-hook'], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook with name \"non-existent-hook\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays logs for a single hook', async () => {\n const HOOK_ID = 'single-hook-test'\n const MESSAGE_ID = 'single-msg-test'\n const ATTEMPT_ID = 'single-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n dataset: 'production',\n failureCount: 1,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"test\": true}',\n projectId: 'test-project',\n resultCode: 404,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n failureReason: 'http',\n hookId: HOOK_ID,\n id: ATTEMPT_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultCode: 404,\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T09:15:36.628Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 404')\n expect(stdout).toContain('Failures: 1')\n })\n\n test('displays logs for a specified hook', async () => {\n const HOOK_ID_1 = 'specified-hook-test-1'\n const HOOK_ID_2 = 'specified-hook-test-2'\n const MESSAGE_ID = 'specified-msg-test'\n const ATTEMPT_ID = 'specified-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID_1,\n name: 'test-hook',\n type: 'document',\n },\n {\n id: HOOK_ID_2,\n name: 'another-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_1}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID_1,\n id: MESSAGE_ID,\n payload: '{\"test\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_1}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T09:15:36.628Z',\n failureReason: '',\n hookId: HOOK_ID_1,\n id: ATTEMPT_ID,\n inProgress: false,\n isFailure: false,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultCode: 200,\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['test-hook'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T09:15:36.628Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 200')\n expect(stdout).not.toContain('Failures:')\n })\n\n test('displays error when hook logs retrieval fails', async () => {\n const HOOK_ID = 'error-logs-hook-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook logs retrieval failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('prompts user to select hook when multiple hooks exist', async () => {\n const HOOK_ID_1 = 'select-hook-test-1'\n const HOOK_ID_2 = 'select-hook-test-2'\n const MESSAGE_ID = 'select-msg-test'\n\n mockedSelect.mockResolvedValue(HOOK_ID_2)\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID_1,\n name: 'first-hook',\n type: 'document',\n },\n {\n id: HOOK_ID_2,\n name: 'second-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_2}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T10:00:00.000Z',\n dataset: 'production',\n failureCount: 1,\n hookId: HOOK_ID_2,\n id: MESSAGE_ID,\n payload: '{\"selected\": true}',\n projectId: 'test-project',\n resultCode: 500,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID_2}/attempts`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(vi.mocked(select)).toHaveBeenCalledWith({\n choices: [\n {name: 'first-hook', value: HOOK_ID_1},\n {name: 'second-hook', value: HOOK_ID_2},\n ],\n message: 'Select hook to list logs for',\n })\n\n expect(stdout).toContain('Date: 2025-08-07T10:00:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 500')\n expect(stdout).toContain('Failures: 1')\n })\n\n test('matches hook name case-insensitively', async () => {\n const HOOK_ID = 'case-hook-test'\n const MESSAGE_ID = 'case-msg-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'Test-Hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T11:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"case\": \"insensitive\"}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(LogsHookCommand, ['test-hook'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T11:00:00.000Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 200')\n })\n\n test('displays error when hook attempts retrieval fails', async () => {\n const HOOK_ID = 'attempt-error-hook-test'\n const MESSAGE_ID = 'attempt-error-msg-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T12:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"test\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook logs retrieval failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays detailed output with --detailed flag', async () => {\n const HOOK_ID = 'detailed-hook-test'\n const MESSAGE_ID = 'detailed-msg-test'\n const ATTEMPT_TIMEOUT_ID = 'detailed-timeout-attempt-test'\n const ATTEMPT_PENDING_ID = 'detailed-pending-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T13:00:00.000Z',\n dataset: 'production',\n failureCount: 2,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"document\": {\"_id\": \"test\", \"_type\": \"post\"}, \"event\": \"create\"}',\n projectId: 'test-project',\n resultCode: 400,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T13:00:01.000Z',\n duration: 5000,\n failureReason: 'timeout',\n hookId: HOOK_ID,\n id: ATTEMPT_TIMEOUT_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: '2025-08-07T13:00:06.000Z',\n },\n {\n createdAt: '2025-08-07T13:00:10.000Z',\n duration: null,\n failureReason: '',\n hookId: HOOK_ID,\n id: ATTEMPT_PENDING_ID,\n inProgress: true,\n isFailure: false,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: null,\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T13:00:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 400')\n expect(stdout).toContain('Failures: 2')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain('document')\n expect(stdout).toContain('_type')\n expect(stdout).toContain('post')\n expect(stdout).toContain('Attempts:')\n expect(stdout).toContain('[2025-08-07T13:00:01Z]')\n expect(stdout).toContain('Failure: Request timed out')\n expect(stdout).toContain('[2025-08-07T13:00:10Z]')\n expect(stdout).toContain('Pending')\n })\n\n test('displays detailed output with successful attempts', async () => {\n const HOOK_ID = 'success-detailed-hook-test'\n const MESSAGE_ID = 'success-detailed-msg-test'\n const ATTEMPT_ID = 'success-detailed-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T14:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"success\": true}',\n projectId: 'test-project',\n resultCode: 201,\n status: 'success',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T14:00:01.500Z',\n duration: 250,\n failureReason: '',\n hookId: HOOK_ID,\n id: ATTEMPT_ID,\n inProgress: false,\n isFailure: false,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: 'Created',\n resultCode: 201,\n updatedAt: '2025-08-07T14:00:01.750Z',\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T14:00:00.000Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 201')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain('{ success: true }')\n expect(stdout).toContain('Attempts:')\n expect(stdout).toContain('[2025-08-07T14:00:01Z]')\n expect(stdout).toContain('Success: HTTP 201 (250ms)')\n })\n\n test('displays different failure reasons with detailed output', async () => {\n const HOOK_ID = 'failure-reasons-hook-test'\n const MESSAGE_ID = 'failure-reasons-msg-test'\n const ATTEMPT_HTTP_ID = 'failure-http-attempt-test'\n const ATTEMPT_NETWORK_ID = 'failure-network-attempt-test'\n const ATTEMPT_OTHER_ID = 'failure-other-attempt-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T15:00:00.000Z',\n dataset: 'production',\n failureCount: 4,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"failures\": \"test\"}',\n projectId: 'test-project',\n resultCode: null,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T15:00:01.000Z',\n duration: 100,\n failureReason: 'http',\n hookId: HOOK_ID,\n id: ATTEMPT_HTTP_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: 'Not Found',\n resultCode: 404,\n updatedAt: '2025-08-07T15:00:01.100Z',\n },\n {\n createdAt: '2025-08-07T15:00:02.000Z',\n duration: 0,\n failureReason: 'network',\n hookId: HOOK_ID,\n id: ATTEMPT_NETWORK_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: '2025-08-07T15:00:02.000Z',\n },\n {\n createdAt: '2025-08-07T15:00:03.000Z',\n duration: 200,\n failureReason: 'other',\n hookId: HOOK_ID,\n id: ATTEMPT_OTHER_ID,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID,\n projectId: 'test-project',\n resultBody: '',\n resultCode: 0,\n updatedAt: '2025-08-07T15:00:03.200Z',\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T15:00:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Failures: 4')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain(\"{ failures: 'test' }\")\n expect(stdout).toContain('Attempts:')\n expect(stdout).toContain(\n `Failure: HTTP 404 (run \\`sanity hook attempt ${ATTEMPT_HTTP_ID}\\` for details)`,\n )\n expect(stdout).toContain('Failure: Network error')\n expect(stdout).toContain('Failure: Unknown error')\n })\n\n test('displays multiple messages with separators', async () => {\n const HOOK_ID = 'multiple-messages-hook-test'\n const MESSAGE_ID_1 = 'multiple-msg-1-test'\n const MESSAGE_ID_2 = 'multiple-msg-2-test'\n const ATTEMPT_ID_1 = 'multiple-attempt-1-test'\n const ATTEMPT_ID_2 = 'multiple-attempt-2-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T16:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID_1,\n payload: '{\"first\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'success',\n },\n {\n createdAt: '2025-08-07T16:01:00.000Z',\n dataset: 'production',\n failureCount: 1,\n hookId: HOOK_ID,\n id: MESSAGE_ID_2,\n payload: '{\"second\": true}',\n projectId: 'test-project',\n resultCode: 500,\n status: 'failure',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T16:00:01.000Z',\n duration: 100,\n failureReason: '',\n hookId: HOOK_ID,\n id: ATTEMPT_ID_1,\n inProgress: false,\n isFailure: false,\n messageId: MESSAGE_ID_1,\n projectId: 'test-project',\n resultBody: 'OK',\n resultCode: 200,\n updatedAt: '2025-08-07T16:00:01.100Z',\n },\n {\n createdAt: '2025-08-07T16:01:01.000Z',\n duration: 200,\n failureReason: 'http',\n hookId: HOOK_ID,\n id: ATTEMPT_ID_2,\n inProgress: false,\n isFailure: true,\n messageId: MESSAGE_ID_2,\n projectId: 'test-project',\n resultBody: 'Error',\n resultCode: 500,\n updatedAt: '2025-08-07T16:01:01.200Z',\n },\n ])\n\n const {stdout} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T16:00:00.000Z')\n expect(stdout).toContain('Status: success')\n expect(stdout).toContain('Result code: 200')\n expect(stdout).toContain('---') // Separator between messages\n expect(stdout).toContain('Date: 2025-08-07T16:01:00.000Z')\n expect(stdout).toContain('Status: failure')\n expect(stdout).toContain('Result code: 500')\n expect(stdout).toContain('Failures: 1')\n\n // Verify that the first message section (before \"---\") doesn't have failures\n const [firstSection] = stdout.split('---')\n expect(firstSection).not.toContain('Failures:')\n })\n\n test('displays error when fetching hooks fails', async () => {\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Hook list retrieval failed')\n expect(error?.message).toContain('Internal Server Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays error when no hook is selected from prompt', async () => {\n const HOOK_ID_1 = 'no-select-hook-1-test'\n const HOOK_ID_2 = 'no-select-hook-2-test'\n\n mockedSelect.mockResolvedValue('non-existent-hook-id')\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID_1,\n name: 'first-hook',\n type: 'document',\n },\n {\n id: HOOK_ID_2,\n name: 'second-hook',\n type: 'document',\n },\n ])\n\n const {error} = await testCommand(LogsHookCommand, [], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('No hook selected')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('displays message without attempts section when attempts array is empty', async () => {\n const HOOK_ID = 'empty-attempts-hook-test'\n const MESSAGE_ID = 'empty-attempts-msg-test'\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: '/hooks/projects/test-project',\n }).reply(200, [\n {\n id: HOOK_ID,\n name: 'test-hook',\n type: 'document',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/messages`,\n }).reply(200, [\n {\n createdAt: '2025-08-07T17:00:00.000Z',\n dataset: 'production',\n failureCount: 0,\n hookId: HOOK_ID,\n id: MESSAGE_ID,\n payload: '{\"no_attempts\": true}',\n projectId: 'test-project',\n resultCode: 200,\n status: 'queued',\n },\n ])\n\n mockApi({\n apiVersion: HOOK_API_VERSION,\n uri: `/hooks/projects/test-project/${HOOK_ID}/attempts`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(LogsHookCommand, ['--detailed'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Date: 2025-08-07T17:00:00.000Z')\n expect(stdout).toContain('Status: queued')\n expect(stdout).toContain('Result code: 200')\n expect(stdout).toContain('Payload:')\n expect(stdout).toContain('{ no_attempts: true }')\n expect(stdout).not.toContain('Attempts:') // No attempts section when empty\n })\n})\n"],"names":["runCommand","select","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","HOOK_API_VERSION","NO_PROJECT_ID","LogsHookCommand","mock","actual","importActual","fn","testProjectId","defaultMocks","cliConfig","api","projectId","projectRoot","directory","path","type","token","mockedSelect","mocked","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","error","mocks","undefined","toBeInstanceOf","Error","message","oclif","exit","toBe","apiVersion","uri","reply","HOOK_ID","id","name","MESSAGE_ID","ATTEMPT_ID","createdAt","dataset","failureCount","hookId","payload","resultCode","status","failureReason","inProgress","isFailure","messageId","HOOK_ID_1","HOOK_ID_2","not","mockResolvedValue","toHaveBeenCalledWith","choices","value","ATTEMPT_TIMEOUT_ID","ATTEMPT_PENDING_ID","duration","resultBody","updatedAt","ATTEMPT_HTTP_ID","ATTEMPT_NETWORK_ID","ATTEMPT_OTHER_ID","MESSAGE_ID_1","MESSAGE_ID_2","ATTEMPT_ID_1","ATTEMPT_ID_2","firstSection","split"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getSanityUrl, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
2
2
|
import open from 'open';
|
|
3
|
-
import {
|
|
3
|
+
import { getProjectById } from '../../services/projects.js';
|
|
4
4
|
import { NO_PROJECT_ID } from '../../util/errorMessages.js';
|
|
5
5
|
const createHookDebug = subdebug('hook:create');
|
|
6
6
|
export class CreateHookCommand extends SanityCommand {
|
|
@@ -12,10 +12,6 @@ export class CreateHookCommand extends SanityCommand {
|
|
|
12
12
|
}
|
|
13
13
|
];
|
|
14
14
|
async run() {
|
|
15
|
-
const client = await this.getGlobalApiClient({
|
|
16
|
-
apiVersion: HOOK_API_VERSION,
|
|
17
|
-
requireUser: true
|
|
18
|
-
});
|
|
19
15
|
const projectId = await this.getProjectId();
|
|
20
16
|
if (!projectId) {
|
|
21
17
|
this.error(NO_PROJECT_ID, {
|
|
@@ -24,7 +20,7 @@ export class CreateHookCommand extends SanityCommand {
|
|
|
24
20
|
}
|
|
25
21
|
let projectInfo;
|
|
26
22
|
try {
|
|
27
|
-
projectInfo = await
|
|
23
|
+
projectInfo = await getProjectById(projectId);
|
|
28
24
|
} catch (error) {
|
|
29
25
|
const err = error;
|
|
30
26
|
createHookDebug(`Error fetching project info for project ${projectId}`, err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/hook/create.ts"],"sourcesContent":["import {getSanityUrl, SanityCommand, subdebug} from '@sanity/cli-core'\nimport open from 'open'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/hook/create.ts"],"sourcesContent":["import {getSanityUrl, SanityCommand, subdebug} from '@sanity/cli-core'\nimport open from 'open'\n\nimport {getProjectById} from '../../services/projects.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst createHookDebug = subdebug('hook:create')\n\nexport class CreateHookCommand extends SanityCommand<typeof CreateHookCommand> {\n static override description = 'Create a new webhook for the current project'\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a new webhook for the current project',\n },\n ]\n\n public async run() {\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n let projectInfo: {organizationId?: string | null}\n try {\n projectInfo = await getProjectById(projectId)\n } catch (error) {\n const err = error as Error\n createHookDebug(`Error fetching project info for project ${projectId}`, err)\n this.error(`Failed to fetch project information:\\n${err.message}`, {exit: 1})\n }\n\n const organizationId = projectInfo.organizationId || 'personal'\n const manageUrl = `${getSanityUrl()}/organizations/${organizationId}/project/${projectId}/api/webhooks/new`\n\n this.log(`Opening ${manageUrl}`)\n\n try {\n await open(manageUrl)\n } catch (error) {\n const err = error as Error\n createHookDebug('Error opening browser', err)\n this.error(`Failed to open browser:\\n${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["getSanityUrl","SanityCommand","subdebug","open","getProjectById","NO_PROJECT_ID","createHookDebug","CreateHookCommand","description","examples","command","run","projectId","getProjectId","error","exit","projectInfo","err","message","organizationId","manageUrl","log"],"mappings":"AAAA,SAAQA,YAAY,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACtE,OAAOC,UAAU,OAAM;AAEvB,SAAQC,cAAc,QAAO,6BAA4B;AACzD,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,MAAMC,kBAAkBJ,SAAS;AAEjC,OAAO,MAAMK,0BAA0BN;IACrC,OAAgBO,cAAc,+CAA8C;IAC5E,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,MAAaG,MAAM;QACjB,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACT,eAAe;gBAACU,MAAM;YAAC;QACpC;QAEA,IAAIC;QACJ,IAAI;YACFA,cAAc,MAAMZ,eAAeQ;QACrC,EAAE,OAAOE,OAAO;YACd,MAAMG,MAAMH;YACZR,gBAAgB,CAAC,wCAAwC,EAAEM,WAAW,EAAEK;YACxE,IAAI,CAACH,KAAK,CAAC,CAAC,sCAAsC,EAAEG,IAAIC,OAAO,EAAE,EAAE;gBAACH,MAAM;YAAC;QAC7E;QAEA,MAAMI,iBAAiBH,YAAYG,cAAc,IAAI;QACrD,MAAMC,YAAY,GAAGpB,eAAe,eAAe,EAAEmB,eAAe,SAAS,EAAEP,UAAU,iBAAiB,CAAC;QAE3G,IAAI,CAACS,GAAG,CAAC,CAAC,QAAQ,EAAED,WAAW;QAE/B,IAAI;YACF,MAAMjB,KAAKiB;QACb,EAAE,OAAON,OAAO;YACd,MAAMG,MAAMH;YACZR,gBAAgB,yBAAyBW;YACzC,IAAI,CAACH,KAAK,CAAC,CAAC,yBAAyB,EAAEG,IAAIC,OAAO,EAAE,EAAE;gBAACH,MAAM;YAAC;QAChE;IACF;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { SanityCommand, subdebug } from '@sanity/cli-core';
|
|
3
3
|
import { select } from '@sanity/cli-core/ux';
|
|
4
|
-
import {
|
|
4
|
+
import { deleteHookForProject, listHooksForProject } from '../../services/hooks.js';
|
|
5
5
|
import { NO_PROJECT_ID } from '../../util/errorMessages.js';
|
|
6
6
|
const deleteHookDebug = subdebug('hook:delete');
|
|
7
7
|
export class Delete extends SanityCommand {
|
|
@@ -24,11 +24,6 @@ export class Delete extends SanityCommand {
|
|
|
24
24
|
];
|
|
25
25
|
async run() {
|
|
26
26
|
const { args } = await this.parse(Delete);
|
|
27
|
-
const client = await this.getGlobalApiClient({
|
|
28
|
-
apiVersion: HOOK_API_VERSION,
|
|
29
|
-
requireUser: true
|
|
30
|
-
});
|
|
31
|
-
// Ensure we have project context
|
|
32
27
|
const projectId = await this.getProjectId();
|
|
33
28
|
if (!projectId) {
|
|
34
29
|
this.error(NO_PROJECT_ID, {
|
|
@@ -36,13 +31,9 @@ export class Delete extends SanityCommand {
|
|
|
36
31
|
});
|
|
37
32
|
}
|
|
38
33
|
// Get the hook ID to delete
|
|
39
|
-
const hookId = await this.promptForHook(args.name,
|
|
40
|
-
// Delete the hook
|
|
34
|
+
const hookId = await this.promptForHook(args.name, projectId);
|
|
41
35
|
try {
|
|
42
|
-
await
|
|
43
|
-
method: 'DELETE',
|
|
44
|
-
uri: `/hooks/projects/${projectId}/${hookId}`
|
|
45
|
-
});
|
|
36
|
+
await deleteHookForProject(projectId, hookId);
|
|
46
37
|
this.log('Hook deleted');
|
|
47
38
|
} catch (error) {
|
|
48
39
|
const err = error;
|
|
@@ -52,13 +43,10 @@ export class Delete extends SanityCommand {
|
|
|
52
43
|
});
|
|
53
44
|
}
|
|
54
45
|
}
|
|
55
|
-
async promptForHook(specifiedName,
|
|
56
|
-
// Fetch all hooks for this project
|
|
46
|
+
async promptForHook(specifiedName, projectId) {
|
|
57
47
|
let hooks;
|
|
58
48
|
try {
|
|
59
|
-
hooks = await
|
|
60
|
-
uri: `/hooks/projects/${projectId}`
|
|
61
|
-
});
|
|
49
|
+
hooks = await listHooksForProject(projectId);
|
|
62
50
|
} catch (error) {
|
|
63
51
|
const err = error;
|
|
64
52
|
deleteHookDebug(`Error fetching hooks for project ${projectId}`, err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/hook/delete.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/hook/delete.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {type Hook} from '../../actions/hook/types'\nimport {deleteHookForProject, listHooksForProject} from '../../services/hooks.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst deleteHookDebug = subdebug('hook:delete')\n\nexport class Delete extends SanityCommand<typeof Delete> {\n static override args = {\n name: Args.string({\n description: 'Name of hook to delete (will prompt if not provided)',\n required: false,\n }),\n }\n\n static override description = 'Delete a hook within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively select and delete a hook',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-hook',\n description: 'Delete a specific hook by name',\n },\n ]\n\n public async run(): Promise<void> {\n const {args} = await this.parse(Delete)\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n // Get the hook ID to delete\n const hookId = await this.promptForHook(args.name, projectId)\n\n try {\n await deleteHookForProject(projectId, hookId)\n\n this.log('Hook deleted')\n } catch (error) {\n const err = error as Error\n deleteHookDebug(`Error deleting hook ${hookId} for project ${projectId}`, err)\n this.error(`Hook deletion failed:\\n${err.message}`, {exit: 1})\n }\n }\n\n private async promptForHook(\n specifiedName: string | undefined,\n projectId: string,\n ): Promise<string> {\n let hooks: Hook[]\n try {\n hooks = await listHooksForProject(projectId)\n } catch (error) {\n const err = error as Error\n deleteHookDebug(`Error fetching hooks for project ${projectId}`, err)\n this.error(`Failed to fetch hooks:\\n${err.message}`, {exit: 1})\n }\n\n if (hooks.length === 0) {\n this.error('No hooks configured for this project.', {exit: 1})\n }\n\n // If hook name is specified, find it in the list\n if (specifiedName) {\n const specifiedNameLower = specifiedName.toLowerCase()\n const selectedHook = hooks.find((hook) => hook.name.toLowerCase() === specifiedNameLower)\n\n if (!selectedHook) {\n this.error(`Hook with name \"${specifiedName}\" not found`, {exit: 1})\n }\n\n return selectedHook.id\n }\n\n // If no hook name specified, prompt user to select one\n const choices = hooks.map((hook) => ({\n name: hook.name,\n value: hook.id,\n }))\n\n const selectedId = await select({\n choices,\n message: 'Select hook to delete',\n })\n\n return selectedId\n }\n}\n"],"names":["Args","SanityCommand","subdebug","select","deleteHookForProject","listHooksForProject","NO_PROJECT_ID","deleteHookDebug","Delete","args","name","string","description","required","examples","command","run","parse","projectId","getProjectId","error","exit","hookId","promptForHook","log","err","message","specifiedName","hooks","length","specifiedNameLower","toLowerCase","selectedHook","find","hook","id","choices","map","value","selectedId"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,MAAM,QAAO,sBAAqB;AAG1C,SAAQC,oBAAoB,EAAEC,mBAAmB,QAAO,0BAAyB;AACjF,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,MAAMC,kBAAkBL,SAAS;AAEjC,OAAO,MAAMM,eAAeP;IAC1B,OAAgBQ,OAAO;QACrBC,MAAMV,KAAKW,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,oCAAmC;IAEjE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,MAAaI,MAAqB;QAChC,MAAM,EAACP,IAAI,EAAC,GAAG,MAAM,IAAI,CAACQ,KAAK,CAACT;QAEhC,MAAMU,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACd,eAAe;gBAACe,MAAM;YAAC;QACpC;QAEA,4BAA4B;QAC5B,MAAMC,SAAS,MAAM,IAAI,CAACC,aAAa,CAACd,KAAKC,IAAI,EAAEQ;QAEnD,IAAI;YACF,MAAMd,qBAAqBc,WAAWI;YAEtC,IAAI,CAACE,GAAG,CAAC;QACX,EAAE,OAAOJ,OAAO;YACd,MAAMK,MAAML;YACZb,gBAAgB,CAAC,oBAAoB,EAAEe,OAAO,aAAa,EAAEJ,WAAW,EAAEO;YAC1E,IAAI,CAACL,KAAK,CAAC,CAAC,uBAAuB,EAAEK,IAAIC,OAAO,EAAE,EAAE;gBAACL,MAAM;YAAC;QAC9D;IACF;IAEA,MAAcE,cACZI,aAAiC,EACjCT,SAAiB,EACA;QACjB,IAAIU;QACJ,IAAI;YACFA,QAAQ,MAAMvB,oBAAoBa;QACpC,EAAE,OAAOE,OAAO;YACd,MAAMK,MAAML;YACZb,gBAAgB,CAAC,iCAAiC,EAAEW,WAAW,EAAEO;YACjE,IAAI,CAACL,KAAK,CAAC,CAAC,wBAAwB,EAAEK,IAAIC,OAAO,EAAE,EAAE;gBAACL,MAAM;YAAC;QAC/D;QAEA,IAAIO,MAAMC,MAAM,KAAK,GAAG;YACtB,IAAI,CAACT,KAAK,CAAC,yCAAyC;gBAACC,MAAM;YAAC;QAC9D;QAEA,iDAAiD;QACjD,IAAIM,eAAe;YACjB,MAAMG,qBAAqBH,cAAcI,WAAW;YACpD,MAAMC,eAAeJ,MAAMK,IAAI,CAAC,CAACC,OAASA,KAAKxB,IAAI,CAACqB,WAAW,OAAOD;YAEtE,IAAI,CAACE,cAAc;gBACjB,IAAI,CAACZ,KAAK,CAAC,CAAC,gBAAgB,EAAEO,cAAc,WAAW,CAAC,EAAE;oBAACN,MAAM;gBAAC;YACpE;YAEA,OAAOW,aAAaG,EAAE;QACxB;QAEA,uDAAuD;QACvD,MAAMC,UAAUR,MAAMS,GAAG,CAAC,CAACH,OAAU,CAAA;gBACnCxB,MAAMwB,KAAKxB,IAAI;gBACf4B,OAAOJ,KAAKC,EAAE;YAChB,CAAA;QAEA,MAAMI,aAAa,MAAMpC,OAAO;YAC9BiC;YACAV,SAAS;QACX;QAEA,OAAOa;IACT;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SanityCommand, subdebug } from '@sanity/cli-core';
|
|
2
|
-
import {
|
|
2
|
+
import { listHooksForProject } from '../../services/hooks.js';
|
|
3
3
|
import { NO_PROJECT_ID } from '../../util/errorMessages.js';
|
|
4
4
|
const listHookDebug = subdebug('hook:list');
|
|
5
5
|
export class List extends SanityCommand {
|
|
@@ -11,10 +11,6 @@ export class List extends SanityCommand {
|
|
|
11
11
|
}
|
|
12
12
|
];
|
|
13
13
|
async run() {
|
|
14
|
-
const client = await this.getGlobalApiClient({
|
|
15
|
-
apiVersion: HOOK_API_VERSION,
|
|
16
|
-
requireUser: true
|
|
17
|
-
});
|
|
18
14
|
// Ensure we have project context
|
|
19
15
|
const projectId = await this.getProjectId();
|
|
20
16
|
if (!projectId) {
|
|
@@ -24,9 +20,7 @@ export class List extends SanityCommand {
|
|
|
24
20
|
}
|
|
25
21
|
let hooks;
|
|
26
22
|
try {
|
|
27
|
-
hooks = await
|
|
28
|
-
uri: `/hooks/projects/${projectId}`
|
|
29
|
-
});
|
|
23
|
+
hooks = await listHooksForProject(projectId);
|
|
30
24
|
} catch (error) {
|
|
31
25
|
const err = error;
|
|
32
26
|
listHookDebug(`Error fetching hooks for project ${projectId}`, err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/hook/list.ts"],"sourcesContent":["import {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/hook/list.ts"],"sourcesContent":["import {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {type Hook} from '../../actions/hook/types'\nimport {listHooksForProject} from '../../services/hooks.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst listHookDebug = subdebug('hook:list')\n\nexport class List extends SanityCommand<typeof List> {\n static override description = 'List hooks for a given project'\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List hooks for a given project',\n },\n ]\n\n public async run() {\n // Ensure we have project context\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n let hooks: Hook[]\n try {\n hooks = await listHooksForProject(projectId)\n } catch (error) {\n const err = error as Error\n\n listHookDebug(`Error fetching hooks for project ${projectId}`, err)\n this.error(`Hook list retrieval failed:\\n${err.message}`, {exit: 1})\n }\n\n for (const hook of hooks) {\n this.log(`Name: ${hook.name}`)\n this.log(`Dataset: ${hook.dataset}`)\n this.log(`URL: ${hook.url}`)\n\n if (hook.type === 'document') {\n this.log(`HTTP method: ${hook.httpMethod}`)\n\n if (hook.description) {\n this.log(`Description: ${hook.description}`)\n }\n }\n\n this.log('')\n }\n }\n}\n"],"names":["SanityCommand","subdebug","listHooksForProject","NO_PROJECT_ID","listHookDebug","List","description","examples","command","run","projectId","getProjectId","error","exit","hooks","err","message","hook","log","name","dataset","url","type","httpMethod"],"mappings":"AAAA,SAAQA,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAGxD,SAAQC,mBAAmB,QAAO,0BAAyB;AAC3D,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,MAAMC,gBAAgBH,SAAS;AAE/B,OAAO,MAAMI,aAAaL;IACxB,OAAgBM,cAAc,iCAAgC;IAC9D,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,MAAaG,MAAM;QACjB,iCAAiC;QACjC,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACT,eAAe;gBAACU,MAAM;YAAC;QACpC;QAEA,IAAIC;QACJ,IAAI;YACFA,QAAQ,MAAMZ,oBAAoBQ;QACpC,EAAE,OAAOE,OAAO;YACd,MAAMG,MAAMH;YAEZR,cAAc,CAAC,iCAAiC,EAAEM,WAAW,EAAEK;YAC/D,IAAI,CAACH,KAAK,CAAC,CAAC,6BAA6B,EAAEG,IAAIC,OAAO,EAAE,EAAE;gBAACH,MAAM;YAAC;QACpE;QAEA,KAAK,MAAMI,QAAQH,MAAO;YACxB,IAAI,CAACI,GAAG,CAAC,CAAC,MAAM,EAAED,KAAKE,IAAI,EAAE;YAC7B,IAAI,CAACD,GAAG,CAAC,CAAC,SAAS,EAAED,KAAKG,OAAO,EAAE;YACnC,IAAI,CAACF,GAAG,CAAC,CAAC,KAAK,EAAED,KAAKI,GAAG,EAAE;YAE3B,IAAIJ,KAAKK,IAAI,KAAK,YAAY;gBAC5B,IAAI,CAACJ,GAAG,CAAC,CAAC,aAAa,EAAED,KAAKM,UAAU,EAAE;gBAE1C,IAAIN,KAAKX,WAAW,EAAE;oBACpB,IAAI,CAACY,GAAG,CAAC,CAAC,aAAa,EAAED,KAAKX,WAAW,EAAE;gBAC7C;YACF;YAEA,IAAI,CAACY,GAAG,CAAC;QACX;IACF;AACF"}
|