@sanity/cli 6.0.0-alpha.16 → 6.0.0-alpha.18
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/README.md +592 -470
- package/dist/SanityHelp.js +74 -21
- package/dist/SanityHelp.js.map +1 -1
- package/dist/actions/build/buildApp.js +42 -15
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStudio.js +64 -45
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/buildVendorDependencies.js +3 -16
- package/dist/actions/build/buildVendorDependencies.js.map +1 -1
- package/dist/actions/build/checkStudioDependencyVersions.js +7 -7
- package/dist/actions/build/checkStudioDependencyVersions.js.map +1 -1
- package/dist/actions/build/createExternalFromImportMap.js +1 -1
- package/dist/actions/build/createExternalFromImportMap.js.map +1 -1
- package/dist/actions/build/determineBasePath.js +5 -2
- package/dist/actions/build/determineBasePath.js.map +1 -1
- package/dist/actions/build/handlePrereleaseVersions.js +44 -0
- package/dist/actions/build/handlePrereleaseVersions.js.map +1 -0
- package/dist/actions/build/types.js.map +1 -1
- package/dist/actions/dataset/create.js +7 -1
- package/dist/actions/dataset/create.js.map +1 -1
- package/dist/actions/dataset/resolveDataset.js +26 -0
- package/dist/actions/dataset/resolveDataset.js.map +1 -0
- package/dist/actions/deploy/deployApp.js +1 -8
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +1 -0
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/dev/getDevServerConfig.js +5 -2
- package/dist/actions/dev/getDevServerConfig.js.map +1 -1
- package/dist/actions/dev/startStudioDevServer.js +8 -3
- package/dist/actions/dev/startStudioDevServer.js.map +1 -1
- package/dist/actions/documents/types.js.map +1 -1
- package/dist/actions/documents/validate.js +11 -2
- package/dist/actions/documents/validate.js.map +1 -1
- package/dist/actions/documents/validateDocuments.worker.js +2 -2
- package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
- package/dist/actions/documents/validation/reporters/jsonReporter.js +1 -1
- package/dist/actions/documents/validation/reporters/jsonReporter.js.map +1 -1
- package/dist/actions/documents/validation/reporters/ndjsonReporter.js +1 -1
- package/dist/actions/documents/validation/reporters/ndjsonReporter.js.map +1 -1
- package/dist/actions/graphql/SchemaError.js +1 -1
- package/dist/actions/graphql/SchemaError.js.map +1 -1
- package/dist/actions/graphql/__tests__/fixtures/many-self-refs.js +540 -0
- package/dist/actions/graphql/__tests__/fixtures/many-self-refs.js.map +1 -0
- package/dist/actions/graphql/__tests__/fixtures/test-studio.js +1143 -0
- package/dist/actions/graphql/__tests__/fixtures/test-studio.js.map +1 -0
- package/dist/actions/graphql/__tests__/fixtures/union-refs.js +591 -0
- package/dist/actions/graphql/__tests__/fixtures/union-refs.js.map +1 -0
- package/dist/actions/graphql/__tests__/helpers.js +23 -0
- package/dist/actions/graphql/__tests__/helpers.js.map +1 -0
- package/dist/actions/graphql/extractFromSanitySchema.js +2 -1
- package/dist/actions/graphql/extractFromSanitySchema.js.map +1 -1
- package/dist/actions/graphql/gen1/generateTypeFilters.js +1 -1
- package/dist/actions/graphql/gen1/generateTypeFilters.js.map +1 -1
- package/dist/actions/graphql/gen1/generateTypeQueries.js +2 -1
- package/dist/actions/graphql/gen1/generateTypeQueries.js.map +1 -1
- package/dist/actions/graphql/gen2/generateTypeQueries.js +1 -1
- package/dist/actions/graphql/gen2/generateTypeQueries.js.map +1 -1
- package/dist/actions/graphql/gen3/generateTypeQueries.js +1 -1
- package/dist/actions/graphql/gen3/generateTypeQueries.js.map +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.js +2 -10
- package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.worker.js +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.worker.js.map +1 -1
- package/dist/actions/graphql/types.js.map +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.js +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
- package/dist/actions/manifest/extractAppManifest.js.map +1 -1
- package/dist/actions/manifest/extractManifest.js +3 -22
- package/dist/actions/manifest/extractManifest.js.map +1 -1
- package/dist/actions/manifest/extractManifest.worker.js +5 -1
- package/dist/actions/manifest/extractManifest.worker.js.map +1 -1
- package/dist/actions/manifest/types.js.map +1 -1
- package/dist/actions/schema/deploySchemas.js +57 -80
- package/dist/actions/schema/deploySchemas.js.map +1 -1
- package/dist/actions/schema/extractSanityWorkspace.worker.js +24 -0
- package/dist/actions/schema/extractSanityWorkspace.worker.js.map +1 -0
- package/dist/actions/schema/extractSchemaWatcher.js +1 -1
- package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
- package/dist/actions/schema/types.js +4 -0
- package/dist/actions/schema/types.js.map +1 -1
- package/dist/actions/schema/uniqueWorkspaces.worker.js +3 -1
- package/dist/actions/schema/uniqueWorkspaces.worker.js.map +1 -1
- package/dist/actions/schema/utils/schemaStoreValidation.js +1 -7
- package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
- package/dist/actions/schema/utils/uniqByProjectIdDataset.js +1 -1
- package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -1
- package/dist/actions/schema/watchExtractSchema.js +2 -1
- package/dist/actions/schema/watchExtractSchema.js.map +1 -1
- package/dist/actions/versions/getFormatters.js +1 -1
- package/dist/actions/versions/getFormatters.js.map +1 -1
- package/dist/commands/backup/list.js +4 -1
- package/dist/commands/backup/list.js.map +1 -1
- package/dist/commands/dataset/copy.js +3 -1
- package/dist/commands/dataset/copy.js.map +1 -1
- package/dist/commands/dataset/create.js +12 -0
- package/dist/commands/dataset/create.js.map +1 -1
- package/dist/commands/dataset/embeddings/disable.js +62 -0
- package/dist/commands/dataset/embeddings/disable.js.map +1 -0
- package/dist/commands/dataset/embeddings/enable.js +128 -0
- package/dist/commands/dataset/embeddings/enable.js.map +1 -0
- package/dist/commands/dataset/embeddings/status.js +61 -0
- package/dist/commands/dataset/embeddings/status.js.map +1 -0
- package/dist/commands/debug.js +2 -1
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/documents/create.js +2 -1
- package/dist/commands/documents/create.js.map +1 -1
- package/dist/commands/graphql/deploy.js +1 -1
- package/dist/commands/graphql/deploy.js.map +1 -1
- package/dist/commands/hook/logs.js +1 -1
- package/dist/commands/hook/logs.js.map +1 -1
- package/dist/commands/init.js +13 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/manage.js +0 -1
- package/dist/commands/manage.js.map +1 -1
- package/dist/commands/media/create-aspect.js +1 -1
- package/dist/commands/media/create-aspect.js.map +1 -1
- package/dist/commands/projects/list.js +2 -1
- package/dist/commands/projects/list.js.map +1 -1
- package/dist/commands/schema/deploy.js +11 -27
- package/dist/commands/schema/deploy.js.map +1 -1
- package/dist/commands/users/list.js +1 -1
- package/dist/commands/users/list.js.map +1 -1
- package/dist/commands/versions.js +1 -1
- package/dist/commands/versions.js.map +1 -1
- package/dist/exports/index.d.ts +62 -2
- package/dist/exports/index.js.map +1 -1
- package/dist/prompts/selectMediaLibrary.js +1 -1
- package/dist/prompts/selectMediaLibrary.js.map +1 -1
- package/dist/services/datasets.js +7 -5
- package/dist/services/datasets.js.map +1 -1
- package/dist/services/embeddings.js +25 -0
- package/dist/services/embeddings.js.map +1 -0
- package/dist/services/graphql.js.map +1 -1
- package/dist/services/schemas.js +1 -1
- package/dist/services/schemas.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/util/compareDependencyVersions.js +28 -7
- package/dist/util/compareDependencyVersions.js.map +1 -1
- package/dist/util/errorMessages.js +0 -1
- package/dist/util/errorMessages.js.map +1 -1
- package/dist/util/packageManager/getPeerDependencies.js +44 -0
- package/dist/util/packageManager/getPeerDependencies.js.map +1 -0
- package/oclif.manifest.json +325 -191
- package/package.json +19 -20
- package/dist/actions/schema/schemaStoreTypes.js +0 -19
- package/dist/actions/schema/schemaStoreTypes.js.map +0 -1
- package/dist/actions/schema/utils/manifestExtractor.js +0 -29
- package/dist/actions/schema/utils/manifestExtractor.js.map +0 -1
- package/dist/actions/schema/utils/manifestReader.js +0 -71
- package/dist/actions/schema/utils/manifestReader.js.map +0 -1
- package/dist/util/workerChannels.js +0 -172
- package/dist/util/workerChannels.js.map +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { styleText } from 'node:util';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { SanityCommand, subdebug, waitForAsync } from '@sanity/cli-core';
|
|
4
|
+
import { spinner } from '@sanity/cli-core/ux';
|
|
5
|
+
import { resolveDataset } from '../../../actions/dataset/resolveDataset.js';
|
|
6
|
+
import { getEmbeddingsSettings, setEmbeddingsSettings } from '../../../services/embeddings.js';
|
|
7
|
+
import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
|
|
8
|
+
const debug = subdebug('dataset:embeddings:enable');
|
|
9
|
+
const INITIAL_POLL_INTERVAL_MS = 10_000;
|
|
10
|
+
const MAX_POLL_INTERVAL_MS = 10 * 60 * 1000;
|
|
11
|
+
const POLL_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
12
|
+
export class DatasetEmbeddingsEnableCommand extends SanityCommand {
|
|
13
|
+
static args = {
|
|
14
|
+
dataset: Args.string({
|
|
15
|
+
description: 'Dataset name to enable embeddings for',
|
|
16
|
+
required: false
|
|
17
|
+
})
|
|
18
|
+
};
|
|
19
|
+
static description = 'Enable embeddings for a dataset';
|
|
20
|
+
static examples = [
|
|
21
|
+
{
|
|
22
|
+
command: '<%= config.bin %> <%= command.id %> production',
|
|
23
|
+
description: 'Enable embeddings for the production dataset'
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
command: '<%= config.bin %> <%= command.id %> production --projection "{ title, body }"',
|
|
27
|
+
description: 'Enable embeddings with a specific projection'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
command: '<%= config.bin %> <%= command.id %> production --wait',
|
|
31
|
+
description: 'Enable embeddings and wait for processing to complete'
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
static flags = {
|
|
35
|
+
projection: Flags.string({
|
|
36
|
+
description: 'GROQ projection defining which fields to embed (e.g. "{ title, body }")',
|
|
37
|
+
required: false
|
|
38
|
+
}),
|
|
39
|
+
wait: Flags.boolean({
|
|
40
|
+
default: false,
|
|
41
|
+
description: 'Wait for embeddings processing to complete before returning'
|
|
42
|
+
})
|
|
43
|
+
};
|
|
44
|
+
async run() {
|
|
45
|
+
const { args, flags } = await this.parse(DatasetEmbeddingsEnableCommand);
|
|
46
|
+
let { dataset } = args;
|
|
47
|
+
const { projection, wait } = flags;
|
|
48
|
+
const projectId = await this.getProjectId();
|
|
49
|
+
if (!projectId) {
|
|
50
|
+
this.error(NO_PROJECT_ID, {
|
|
51
|
+
exit: 1
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
;
|
|
56
|
+
({ dataset } = await resolveDataset({
|
|
57
|
+
dataset,
|
|
58
|
+
projectId
|
|
59
|
+
}));
|
|
60
|
+
} catch (error) {
|
|
61
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
+
debug(`Failed to resolve dataset: ${message}`, error);
|
|
63
|
+
this.error(message, {
|
|
64
|
+
exit: 1
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
await setEmbeddingsSettings({
|
|
69
|
+
dataset,
|
|
70
|
+
enabled: true,
|
|
71
|
+
projectId,
|
|
72
|
+
projection
|
|
73
|
+
});
|
|
74
|
+
} catch (error) {
|
|
75
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
76
|
+
debug(`Failed to enable embeddings: ${message}`, error);
|
|
77
|
+
this.error(`Failed to enable embeddings: ${message}`, {
|
|
78
|
+
exit: 1
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
this.log(styleText('green', `Embeddings enabled for dataset ${dataset}.`));
|
|
82
|
+
if (projection) {
|
|
83
|
+
this.log(`Projection: ${projection}`);
|
|
84
|
+
}
|
|
85
|
+
if (wait) {
|
|
86
|
+
await this.waitForReady(projectId, dataset);
|
|
87
|
+
} else {
|
|
88
|
+
this.log('Processing documents in the background. Use --wait to wait for completion.');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async waitForReady(projectId, dataset) {
|
|
92
|
+
const spin = spinner('Waiting for embeddings to be ready...').start();
|
|
93
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
94
|
+
let interval = INITIAL_POLL_INTERVAL_MS;
|
|
95
|
+
while(Date.now() < deadline){
|
|
96
|
+
await waitForAsync(interval);
|
|
97
|
+
interval = Math.min(interval * 1.5, MAX_POLL_INTERVAL_MS);
|
|
98
|
+
let settings;
|
|
99
|
+
try {
|
|
100
|
+
settings = await getEmbeddingsSettings(projectId, dataset);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
103
|
+
spin.fail('Failed while waiting for embeddings.');
|
|
104
|
+
this.error(`Failed while waiting for embeddings: ${message}`, {
|
|
105
|
+
exit: 1
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
debug(`Poll status: ${settings.status}, next interval: ${Math.round(interval)}ms`);
|
|
109
|
+
if (settings.status === 'ready') {
|
|
110
|
+
spin.succeed('Embeddings ready.');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (settings.status !== 'updating') {
|
|
114
|
+
spin.fail(`Unexpected status: ${settings.status}`);
|
|
115
|
+
this.error(`Embeddings entered unexpected status: ${settings.status}`, {
|
|
116
|
+
exit: 1
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
spin.text = 'Still processing...';
|
|
120
|
+
}
|
|
121
|
+
spin.fail('Timed out waiting for embeddings.');
|
|
122
|
+
this.error('Timed out. Check status with: sanity dataset embeddings status', {
|
|
123
|
+
exit: 1
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=enable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/dataset/embeddings/enable.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug, waitForAsync} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {resolveDataset} from '../../../actions/dataset/resolveDataset.js'\nimport {getEmbeddingsSettings, setEmbeddingsSettings} from '../../../services/embeddings.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\n\nconst debug = subdebug('dataset:embeddings:enable')\n\nconst INITIAL_POLL_INTERVAL_MS = 10_000\nconst MAX_POLL_INTERVAL_MS = 10 * 60 * 1000\nconst POLL_TIMEOUT_MS = 24 * 60 * 60 * 1000\n\nexport class DatasetEmbeddingsEnableCommand extends SanityCommand<\n typeof DatasetEmbeddingsEnableCommand\n> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to enable embeddings for',\n required: false,\n }),\n }\n\n static override description = 'Enable embeddings for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Enable embeddings for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --projection \"{ title, body }\"',\n description: 'Enable embeddings with a specific projection',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --wait',\n description: 'Enable embeddings and wait for processing to complete',\n },\n ]\n\n static override flags = {\n projection: Flags.string({\n description: 'GROQ projection defining which fields to embed (e.g. \"{ title, body }\")',\n required: false,\n }),\n wait: Flags.boolean({\n default: false,\n description: 'Wait for embeddings processing to complete before returning',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DatasetEmbeddingsEnableCommand)\n let {dataset} = args\n const {projection, wait} = flags\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n try {\n ;({dataset} = await resolveDataset({dataset, projectId}))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to resolve dataset: ${message}`, error)\n this.error(message, {exit: 1})\n }\n\n try {\n await setEmbeddingsSettings({dataset, enabled: true, projectId, projection})\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to enable embeddings: ${message}`, error)\n this.error(`Failed to enable embeddings: ${message}`, {exit: 1})\n }\n\n this.log(styleText('green', `Embeddings enabled for dataset ${dataset}.`))\n if (projection) {\n this.log(`Projection: ${projection}`)\n }\n\n if (wait) {\n await this.waitForReady(projectId, dataset)\n } else {\n this.log('Processing documents in the background. Use --wait to wait for completion.')\n }\n }\n\n private async waitForReady(projectId: string, dataset: string): Promise<void> {\n const spin = spinner('Waiting for embeddings to be ready...').start()\n const deadline = Date.now() + POLL_TIMEOUT_MS\n let interval = INITIAL_POLL_INTERVAL_MS\n\n while (Date.now() < deadline) {\n await waitForAsync(interval)\n interval = Math.min(interval * 1.5, MAX_POLL_INTERVAL_MS)\n\n let settings\n try {\n settings = await getEmbeddingsSettings(projectId, dataset)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n spin.fail('Failed while waiting for embeddings.')\n this.error(`Failed while waiting for embeddings: ${message}`, {exit: 1})\n }\n debug(`Poll status: ${settings.status}, next interval: ${Math.round(interval)}ms`)\n\n if (settings.status === 'ready') {\n spin.succeed('Embeddings ready.')\n return\n }\n\n if (settings.status !== 'updating') {\n spin.fail(`Unexpected status: ${settings.status}`)\n this.error(`Embeddings entered unexpected status: ${settings.status}`, {exit: 1})\n }\n\n spin.text = 'Still processing...'\n }\n\n spin.fail('Timed out waiting for embeddings.')\n this.error('Timed out. Check status with: sanity dataset embeddings status', {exit: 1})\n }\n}\n"],"names":["styleText","Args","Flags","SanityCommand","subdebug","waitForAsync","spinner","resolveDataset","getEmbeddingsSettings","setEmbeddingsSettings","NO_PROJECT_ID","debug","INITIAL_POLL_INTERVAL_MS","MAX_POLL_INTERVAL_MS","POLL_TIMEOUT_MS","DatasetEmbeddingsEnableCommand","args","dataset","string","description","required","examples","command","flags","projection","wait","boolean","default","run","parse","projectId","getProjectId","error","exit","message","Error","String","enabled","log","waitForReady","spin","start","deadline","Date","now","interval","Math","min","settings","fail","status","round","succeed","text"],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { SanityCommand, subdebug } from '@sanity/cli-core';
|
|
3
|
+
import { resolveDataset } from '../../../actions/dataset/resolveDataset.js';
|
|
4
|
+
import { getEmbeddingsSettings } from '../../../services/embeddings.js';
|
|
5
|
+
import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
|
|
6
|
+
const debug = subdebug('dataset:embeddings:status');
|
|
7
|
+
export class DatasetEmbeddingsStatusCommand extends SanityCommand {
|
|
8
|
+
static args = {
|
|
9
|
+
dataset: Args.string({
|
|
10
|
+
description: 'The name of the dataset to check embeddings status for',
|
|
11
|
+
required: false
|
|
12
|
+
})
|
|
13
|
+
};
|
|
14
|
+
static description = 'Show embeddings settings and status for a dataset';
|
|
15
|
+
static examples = [
|
|
16
|
+
{
|
|
17
|
+
command: '<%= config.bin %> <%= command.id %> production',
|
|
18
|
+
description: 'Show embeddings status for the production dataset'
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
async run() {
|
|
22
|
+
const { args } = await this.parse(DatasetEmbeddingsStatusCommand);
|
|
23
|
+
let { dataset } = args;
|
|
24
|
+
const projectId = await this.getProjectId();
|
|
25
|
+
if (!projectId) {
|
|
26
|
+
this.error(NO_PROJECT_ID, {
|
|
27
|
+
exit: 1
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
;
|
|
32
|
+
({ dataset } = await resolveDataset({
|
|
33
|
+
dataset,
|
|
34
|
+
projectId
|
|
35
|
+
}));
|
|
36
|
+
} catch (error) {
|
|
37
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
38
|
+
debug(`Failed to resolve dataset: ${message}`, error);
|
|
39
|
+
this.error(message, {
|
|
40
|
+
exit: 1
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const settings = await getEmbeddingsSettings(projectId, dataset);
|
|
45
|
+
this.log(`Dataset: ${dataset}`);
|
|
46
|
+
this.log(`Embeddings: ${settings.enabled ? 'enabled' : 'disabled'}`);
|
|
47
|
+
if (settings.projection) {
|
|
48
|
+
this.log(`Projection: ${settings.projection}`);
|
|
49
|
+
}
|
|
50
|
+
this.log(`Status: ${settings.status}`);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
+
debug(`Failed to get embeddings settings: ${message}`, error);
|
|
54
|
+
this.error(`Failed to get embeddings settings: ${message}`, {
|
|
55
|
+
exit: 1
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/dataset/embeddings/status.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {resolveDataset} from '../../../actions/dataset/resolveDataset.js'\nimport {getEmbeddingsSettings} from '../../../services/embeddings.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\n\nconst debug = subdebug('dataset:embeddings:status')\n\nexport class DatasetEmbeddingsStatusCommand extends SanityCommand<\n typeof DatasetEmbeddingsStatusCommand\n> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to check embeddings status for',\n required: false,\n }),\n }\n\n static override description = 'Show embeddings settings and status for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Show embeddings status for the production dataset',\n },\n ]\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetEmbeddingsStatusCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n try {\n ;({dataset} = await resolveDataset({dataset, projectId}))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to resolve dataset: ${message}`, error)\n this.error(message, {exit: 1})\n }\n\n try {\n const settings = await getEmbeddingsSettings(projectId, dataset)\n\n this.log(`Dataset: ${dataset}`)\n this.log(`Embeddings: ${settings.enabled ? 'enabled' : 'disabled'}`)\n if (settings.projection) {\n this.log(`Projection: ${settings.projection}`)\n }\n this.log(`Status: ${settings.status}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to get embeddings settings: ${message}`, error)\n this.error(`Failed to get embeddings settings: ${message}`, {exit: 1})\n }\n }\n}\n"],"names":["Args","SanityCommand","subdebug","resolveDataset","getEmbeddingsSettings","NO_PROJECT_ID","debug","DatasetEmbeddingsStatusCommand","args","dataset","string","description","required","examples","command","run","parse","projectId","getProjectId","error","exit","message","Error","String","settings","log","enabled","projection","status"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,cAAc,QAAO,6CAA4C;AACzE,SAAQC,qBAAqB,QAAO,kCAAiC;AACrE,SAAQC,aAAa,QAAO,iCAAgC;AAE5D,MAAMC,QAAQJ,SAAS;AAEvB,OAAO,MAAMK,uCAAuCN;IAGlD,OAAgBO,OAAO;QACrBC,SAAST,KAAKU,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,oDAAmD;IAEjF,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,MAAaI,MAAqB;QAChC,MAAM,EAACP,IAAI,EAAC,GAAG,MAAM,IAAI,CAACQ,KAAK,CAACT;QAChC,IAAI,EAACE,OAAO,EAAC,GAAGD;QAEhB,MAAMS,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACd,eAAe;gBAACe,MAAM;YAAC;QACpC;QAEA,IAAI;;YACA,CAAA,EAACX,OAAO,EAAC,GAAG,MAAMN,eAAe;gBAACM;gBAASQ;YAAS,EAAC;QACzD,EAAE,OAAOE,OAAO;YACd,MAAME,UAAUF,iBAAiBG,QAAQH,MAAME,OAAO,GAAGE,OAAOJ;YAChEb,MAAM,CAAC,2BAA2B,EAAEe,SAAS,EAAEF;YAC/C,IAAI,CAACA,KAAK,CAACE,SAAS;gBAACD,MAAM;YAAC;QAC9B;QAEA,IAAI;YACF,MAAMI,WAAW,MAAMpB,sBAAsBa,WAAWR;YAExD,IAAI,CAACgB,GAAG,CAAC,CAAC,YAAY,EAAEhB,SAAS;YACjC,IAAI,CAACgB,GAAG,CAAC,CAAC,YAAY,EAAED,SAASE,OAAO,GAAG,YAAY,YAAY;YACnE,IAAIF,SAASG,UAAU,EAAE;gBACvB,IAAI,CAACF,GAAG,CAAC,CAAC,YAAY,EAAED,SAASG,UAAU,EAAE;YAC/C;YACA,IAAI,CAACF,GAAG,CAAC,CAAC,YAAY,EAAED,SAASI,MAAM,EAAE;QAC3C,EAAE,OAAOT,OAAO;YACd,MAAME,UAAUF,iBAAiBG,QAAQH,MAAME,OAAO,GAAGE,OAAOJ;YAChEb,MAAM,CAAC,mCAAmC,EAAEe,SAAS,EAAEF;YACvD,IAAI,CAACA,KAAK,CAAC,CAAC,mCAAmC,EAAEE,SAAS,EAAE;gBAACD,MAAM;YAAC;QACtE;IACF;AACF"}
|
package/dist/commands/debug.js
CHANGED
|
@@ -2,7 +2,8 @@ import path from 'node:path';
|
|
|
2
2
|
import { styleText } from 'node:util';
|
|
3
3
|
import { Flags } from '@oclif/core';
|
|
4
4
|
import { formatObject, printKeyValue, SanityCommand } from '@sanity/cli-core';
|
|
5
|
-
import
|
|
5
|
+
import omit from 'lodash-es/omit.js';
|
|
6
|
+
import padStart from 'lodash-es/padStart.js';
|
|
6
7
|
import { gatherDebugInfo } from '../actions/debug/gatherDebugInfo.js';
|
|
7
8
|
import { getGlobalConfigLocation } from '../actions/debug/getGlobalConfigLocation.js';
|
|
8
9
|
import { getDisplayName, getFormatters } from '../actions/versions/getFormatters.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/debug.ts"],"sourcesContent":["import path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {formatObject, printKeyValue, SanityCommand} from '@sanity/cli-core'\nimport
|
|
1
|
+
{"version":3,"sources":["../../src/commands/debug.ts"],"sourcesContent":["import path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {formatObject, printKeyValue, SanityCommand} from '@sanity/cli-core'\nimport omit from 'lodash-es/omit.js'\nimport padStart from 'lodash-es/padStart.js'\n\nimport {gatherDebugInfo} from '../actions/debug/gatherDebugInfo.js'\nimport {getGlobalConfigLocation} from '../actions/debug/getGlobalConfigLocation.js'\nimport {getDisplayName, getFormatters} from '../actions/versions/getFormatters.js'\n\nexport class Debug extends SanityCommand<typeof Debug> {\n static override description = 'Provides diagnostic info for Sanity Studio troubleshooting'\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n '<%= config.bin %> <%= command.id %> --secrets',\n ]\n\n static override flags = {\n secrets: Flags.boolean({\n default: false,\n description: 'Include API keys in output',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = this\n\n try {\n const projectRoot = await this.getProjectRoot()\n const cliConfig = await this.getCliConfig()\n\n const {auth, globalConfig, project, projectConfig, user, versions} = await gatherDebugInfo({\n cliConfig,\n includeSecrets: flags.secrets,\n projectRoot,\n })\n\n this.output.log('\\nUser:')\n if (user instanceof Error) {\n this.log(` ${styleText('red', user.message)}\\n`)\n } else if (user) {\n printKeyValue({\n ID: user.id,\n Name: user.name,\n // eslint-disable-next-line perfectionist/sort-objects\n Email: user.email,\n Roles: project && 'userRoles' in project ? project.userRoles : undefined,\n })\n }\n\n // Project info (API-based)\n if (project && 'id' in project) {\n this.log('Project:')\n printKeyValue({\n ID: project.id,\n // eslint-disable-next-line perfectionist/sort-objects\n 'Display name': project.displayName,\n })\n }\n\n // Auth info\n if (auth.hasToken) {\n this.log('Authentication:')\n printKeyValue({\n 'Auth token': flags.secrets ? auth.authToken : `<redacted>`,\n 'User type': globalConfig.authType || 'normal',\n })\n\n if (!flags.secrets) {\n this.log(' (run with --secrets to reveal token)\\n')\n }\n }\n\n // Global configuration (user home dir config file)\n this.log(`Global config (${styleText('yellow', getGlobalConfigLocation())}):`)\n const globalCfg = omit(globalConfig, ['authType', 'authToken'])\n this.log(` ${formatObject(globalCfg).replaceAll('\\n', '\\n ')}\\n`)\n\n // Project configuration (projectDir/sanity.json)\n if (projectConfig) {\n const configLocation = projectConfig\n ? ` (${styleText('yellow', path.relative(process.cwd(), projectRoot.path))})`\n : ''\n\n this.log(`Project config${configLocation}:`)\n this.log(` ${formatObject(projectConfig).replaceAll('\\n', '\\n ')}`)\n }\n\n // Print installed package versions\n if (versions) {\n this.log('\\nPackage versions:')\n\n const {formatName, versionLength} = getFormatters(versions)\n for (const mod of versions) {\n const version = padStart(mod.installed || '<missing>', versionLength)\n const latest =\n mod.installed === mod.latest\n ? styleText('green', '(up to date)')\n : `(latest: ${styleText('yellow', mod.latest)})`\n\n this.log(`${formatName(getDisplayName(mod))} ${version} ${latest}`)\n }\n\n this.log('')\n }\n } catch (error) {\n this.error(\n `Failed to gather debug information: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n }\n}\n"],"names":["path","styleText","Flags","formatObject","printKeyValue","SanityCommand","omit","padStart","gatherDebugInfo","getGlobalConfigLocation","getDisplayName","getFormatters","Debug","description","examples","flags","secrets","boolean","default","run","projectRoot","getProjectRoot","cliConfig","getCliConfig","auth","globalConfig","project","projectConfig","user","versions","includeSecrets","output","log","Error","message","ID","id","Name","name","Email","email","Roles","userRoles","undefined","displayName","hasToken","authToken","authType","globalCfg","replaceAll","configLocation","relative","process","cwd","formatName","versionLength","mod","version","installed","latest","error"],"mappings":"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"}
|
|
@@ -7,7 +7,8 @@ import { getProjectCliClient, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
|
7
7
|
import { watch as chokidarWatch } from 'chokidar';
|
|
8
8
|
import { execa, execaSync } from 'execa';
|
|
9
9
|
import json5 from 'json5';
|
|
10
|
-
import
|
|
10
|
+
import isEqual from 'lodash-es/isEqual.js';
|
|
11
|
+
import isPlainObject from 'lodash-es/isPlainObject.js';
|
|
11
12
|
import { DOCUMENTS_API_VERSION } from '../../actions/documents/constants.js';
|
|
12
13
|
import { getEditor, registerUnlinkOnSigInt } from '../../actions/documents/editor.js';
|
|
13
14
|
import { NO_PROJECT_ID } from '../../util/errorMessages.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/documents/create.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {type MultipleMutationResult, type Mutation} from '@sanity/client'\nimport {watch as chokidarWatch} from 'chokidar'\nimport {execa, execaSync} from 'execa'\nimport json5 from 'json5'\nimport {isEqual, isPlainObject} from 'lodash-es'\n\nimport {DOCUMENTS_API_VERSION} from '../../actions/documents/constants.js'\nimport {getEditor, registerUnlinkOnSigInt} from '../../actions/documents/editor.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {isIdentifiedSanityDocument, isSanityDocumentish} from '../../util/isSanityDocumentish.js'\n\nexport type MutationOperationName = 'create' | 'createIfNotExists' | 'createOrReplace'\n\nconst createDocumentDebug = subdebug('documents:create')\n\nexport class CreateDocumentCommand extends SanityCommand<typeof CreateDocumentCommand> {\n static override args = {\n file: Args.string({\n description: 'JSON file to create document(s) from',\n required: false,\n }),\n }\n\n static override description = 'Create one or more documents'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> myDocument.json',\n description: 'Create the document specified in \"myDocument.json\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Open configured $EDITOR and create the specified document(s)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --replace',\n description:\n 'Fetch document with the ID \"myDocId\" and open configured $EDITOR with the current document content (if any). Replace document with the edited version when the editor closes',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --watch --replace --json5',\n description:\n 'Open configured $EDITOR and replace the document with the given content on each save. Use JSON5 file extension and parser for simplified syntax.',\n },\n ]\n\n static override flags = {\n dataset: Flags.string({\n char: 'd',\n description: 'Dataset to create document(s) in (overrides config)',\n }),\n id: Flags.string({\n description:\n 'Specify a document ID to use. Will fetch remote document ID and populate editor.',\n }),\n json5: Flags.boolean({\n description: 'Use JSON5 file type to allow a \"simplified\" version of JSON',\n }),\n missing: Flags.boolean({\n description: \"On duplicate document IDs, don't modify the target document(s)\",\n }),\n replace: Flags.boolean({\n description:\n 'On duplicate document IDs, replace existing document with specified document(s)',\n }),\n watch: Flags.boolean({\n description: 'Write the documents whenever the target file or buffer changes',\n }),\n }\n\n private client!: Awaited<ReturnType<typeof getProjectCliClient>>\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CreateDocumentCommand)\n const {file} = args\n const {dataset, id, json5: useJson5, missing, replace, watch} = flags\n const cliConfig = await this.getCliConfig()\n const projectId = await this.getProjectId()\n\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n if (!cliConfig.api?.dataset && !dataset) {\n this.error(\n 'No dataset specified. Either configure a dataset in sanity.cli.ts or use the --dataset flag',\n {exit: 1},\n )\n }\n\n const targetDataset = dataset || cliConfig.api?.dataset\n\n this.client = await getProjectCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n dataset: targetDataset,\n projectId,\n requireUser: true,\n })\n\n if (replace && missing) {\n this.error('Cannot use both --replace and --missing', {exit: 1})\n }\n\n if (id && file) {\n this.error('Cannot use --id when specifying a file path', {exit: 1})\n }\n\n let operation: MutationOperationName = 'create'\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n }\n\n if (file) {\n try {\n const contentPath = path.resolve(process.cwd(), file)\n const content = json5.parse(await fs.readFile(contentPath, 'utf8'))\n const result = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(result, operation))\n return\n } catch (error) {\n const err = error as Error\n createDocumentDebug(`Error creating documents from file ${file}`, err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n try {\n // Create a temporary file and use that as source, opening an editor on it\n const docId = id || randomUUID()\n const ext = useJson5 ? 'json5' : 'json'\n // Add UUID prefix to prevent predictable file names and potential conflicts\n const tmpFile = path.join(os.tmpdir(), 'sanity-cli', `${randomUUID()}-${docId}.${ext}`)\n const stringify = useJson5 ? json5.stringify : JSON.stringify\n const defaultValue = (id && (await this.client.getDocument(id))) || {\n _id: docId,\n _type: 'specify-me',\n }\n\n // Create temp directory with restricted permissions (owner only)\n const tempDir = path.join(os.tmpdir(), 'sanity-cli')\n await fs.mkdir(tempDir, {\n mode: 0o700, // rwx------ (owner read/write/execute only)\n recursive: true,\n })\n\n // Write file with restricted permissions (owner read/write only)\n await fs.writeFile(tmpFile, stringify(defaultValue, null, 2), {\n encoding: 'utf8',\n mode: 0o600, // rw------- (owner read/write only)\n })\n\n const editor = getEditor()\n const readAndPerformCreatesFromFile = this.readAndPerformCreatesFromFile.bind(this, operation)\n\n if (watch) {\n // If we're in watch mode, we want to run the creation on each change (if it validates)\n registerUnlinkOnSigInt(tmpFile)\n this.log(`Watch mode: ${tmpFile}`)\n this.log('Watch mode: Will write documents on each save.')\n this.log('Watch mode: Press Ctrl + C to cancel watch mode.')\n\n // Add race condition protection\n let isProcessing = false\n chokidarWatch(tmpFile).on('change', async () => {\n if (isProcessing) {\n return // Skip if already processing\n }\n isProcessing = true\n\n this.log('')\n try {\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n } finally {\n isProcessing = false\n }\n })\n execa(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n } else {\n // While in normal mode, we just want to wait for the editor to close and run the thing once\n execaSync(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n await fs.unlink(tmpFile).catch(() => {})\n }\n } catch (error) {\n const err = error as Error\n createDocumentDebug('Error in editor workflow', err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n private getErrorMessage(message: string, index: number, isSingle: boolean): string {\n return isSingle ? `Document ${message}` : `Document at index ${index} ${message}`\n }\n\n /**\n * Formats the result message for document operations\n */\n private getResultMessage(\n result: MultipleMutationResult,\n operation: MutationOperationName,\n ): string {\n const joiner = '\\n - '\n if (operation === 'createOrReplace') {\n return `Upserted:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n if (operation === 'create') {\n return `Created:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n // \"Missing\" (createIfNotExists)\n const created: string[] = []\n const skipped: string[] = []\n for (const res of result.results) {\n if (res.operation === 'update') {\n skipped.push(res.id)\n } else {\n created.push(res.id)\n }\n }\n\n if (created.length > 0 && skipped.length > 0) {\n return [\n `Created:\\n - ${created.join(joiner)}`,\n `Skipped (already exists):${joiner}${skipped.join(joiner)}`,\n ].join('\\n\\n')\n } else if (created.length > 0) {\n return `Created:\\n - ${created.join(joiner)}`\n }\n\n return `Skipped (already exists):\\n - ${skipped.join(joiner)}`\n }\n\n /**\n * Reads and processes documents from a file for creation\n */\n private async readAndPerformCreatesFromFile(\n operation: MutationOperationName,\n filePath: string,\n defaultValue: unknown,\n ): Promise<void> {\n let content\n try {\n content = json5.parse(await fs.readFile(filePath, 'utf8'))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to read input file ${filePath}`, error)\n this.log(`Failed to read input: ${error.message}`)\n return\n }\n\n if (isEqual(content, defaultValue)) {\n this.log('Value not modified, doing nothing.')\n this.log('Modify document to trigger creation.')\n return\n }\n\n try {\n const writeResult = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(writeResult, operation))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to write documents`, error)\n let errorMessage = `Failed to write documents: ${error.message}`\n if (error.message.includes('already exists')) {\n errorMessage += '\\nPerhaps you want to use `--replace` or `--missing`?'\n }\n this.error(errorMessage, {exit: 1})\n }\n }\n\n /**\n * Validates a document for Sanity requirements\n */\n private validateDocument(doc: unknown, index: number, arr: unknown[]): void {\n const isSingle = arr.length === 1\n\n if (!isPlainObject(doc)) {\n throw new Error(this.getErrorMessage('must be an object', index, isSingle))\n }\n\n if (!isSanityDocumentish(doc)) {\n throw new Error(\n this.getErrorMessage('must have a `_type` property of type string', index, isSingle),\n )\n }\n\n // Enhanced validations for Sanity document constraints\n const docObj = doc as Record<string, unknown>\n\n // Validate _type is non-empty\n const typeValue = docObj._type?.toString().trim()\n if (!typeValue) {\n throw new Error(this.getErrorMessage('_type cannot be empty', index, isSingle))\n }\n\n // Validate _type format (alphanumeric, underscore, hyphen, dot)\n if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(typeValue)) {\n throw new Error(\n this.getErrorMessage(\n '_type must start with a letter and contain only alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Validate _id format if present\n if (docObj._id && typeof docObj._id === 'string') {\n const idValue = docObj._id.trim()\n if (!idValue) {\n throw new Error(this.getErrorMessage('_id cannot be empty', index, isSingle))\n }\n\n // Sanity document IDs can contain alphanumeric chars, hyphens, underscores, and dots\n if (!/^[a-zA-Z0-9_.-]+$/.test(idValue)) {\n throw new Error(\n this.getErrorMessage(\n '_id can only contain alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Check length constraints (Sanity has reasonable limits)\n if (idValue.length > 200) {\n throw new Error(\n this.getErrorMessage('_id cannot be longer than 200 characters', index, isSingle),\n )\n }\n }\n\n // Warn about reserved fields (these are managed by Sanity)\n const reservedFields = ['_rev', '_updatedAt', '_createdAt']\n for (const field of reservedFields) {\n if (field in docObj) {\n // Note: We don't throw an error here as these might be present in fetched documents\n // that are being re-uploaded, but we could add a debug warning\n createDocumentDebug(\n `Warning: Document ${index} contains reserved field '${field}' which will be ignored by Sanity`,\n )\n }\n }\n }\n\n /**\n * Writes documents to Sanity using the specified operation\n */\n private async writeDocuments(\n documents: {_id?: string; _type: string} | {_id?: string; _type: string}[],\n operation: MutationOperationName,\n ): Promise<MultipleMutationResult> {\n const docs = Array.isArray(documents) ? documents : [documents]\n if (docs.length === 0) {\n throw new Error('No documents provided')\n }\n\n const mutations = docs.map((doc, index): Mutation => {\n this.validateDocument(doc, index, docs)\n if (operation === 'create') {\n return {create: doc}\n }\n\n if (operation === 'createIfNotExists') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createIfNotExists: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n if (operation === 'createOrReplace') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createOrReplace: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n throw new Error(`Unsupported operation ${operation}`)\n })\n\n return this.client.transaction(mutations).commit()\n }\n}\n"],"names":["randomUUID","fs","os","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","watch","chokidarWatch","execa","execaSync","json5","isEqual","isPlainObject","DOCUMENTS_API_VERSION","getEditor","registerUnlinkOnSigInt","NO_PROJECT_ID","isIdentifiedSanityDocument","isSanityDocumentish","createDocumentDebug","CreateDocumentCommand","args","file","string","description","required","examples","command","flags","dataset","char","id","boolean","missing","replace","client","run","parse","useJson5","cliConfig","getCliConfig","projectId","getProjectId","error","exit","api","targetDataset","apiVersion","requireUser","operation","contentPath","resolve","process","cwd","content","readFile","result","writeDocuments","log","getResultMessage","err","message","docId","ext","tmpFile","join","tmpdir","stringify","JSON","defaultValue","getDocument","_id","_type","tempDir","mkdir","mode","recursive","writeFile","encoding","editor","readAndPerformCreatesFromFile","bind","isProcessing","on","bin","stdio","unlink","catch","getErrorMessage","index","isSingle","joiner","results","map","res","created","skipped","push","length","filePath","writeResult","errorMessage","includes","validateDocument","doc","arr","Error","docObj","typeValue","toString","trim","test","idValue","reservedFields","field","documents","docs","Array","isArray","mutations","create","createIfNotExists","createOrReplace","transaction","commit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/documents/create.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {type MultipleMutationResult, type Mutation} from '@sanity/client'\nimport {watch as chokidarWatch} from 'chokidar'\nimport {execa, execaSync} from 'execa'\nimport json5 from 'json5'\nimport isEqual from 'lodash-es/isEqual.js'\nimport isPlainObject from 'lodash-es/isPlainObject.js'\n\nimport {DOCUMENTS_API_VERSION} from '../../actions/documents/constants.js'\nimport {getEditor, registerUnlinkOnSigInt} from '../../actions/documents/editor.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {isIdentifiedSanityDocument, isSanityDocumentish} from '../../util/isSanityDocumentish.js'\n\nexport type MutationOperationName = 'create' | 'createIfNotExists' | 'createOrReplace'\n\nconst createDocumentDebug = subdebug('documents:create')\n\nexport class CreateDocumentCommand extends SanityCommand<typeof CreateDocumentCommand> {\n static override args = {\n file: Args.string({\n description: 'JSON file to create document(s) from',\n required: false,\n }),\n }\n\n static override description = 'Create one or more documents'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> myDocument.json',\n description: 'Create the document specified in \"myDocument.json\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Open configured $EDITOR and create the specified document(s)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --replace',\n description:\n 'Fetch document with the ID \"myDocId\" and open configured $EDITOR with the current document content (if any). Replace document with the edited version when the editor closes',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --watch --replace --json5',\n description:\n 'Open configured $EDITOR and replace the document with the given content on each save. Use JSON5 file extension and parser for simplified syntax.',\n },\n ]\n\n static override flags = {\n dataset: Flags.string({\n char: 'd',\n description: 'Dataset to create document(s) in (overrides config)',\n }),\n id: Flags.string({\n description:\n 'Specify a document ID to use. Will fetch remote document ID and populate editor.',\n }),\n json5: Flags.boolean({\n description: 'Use JSON5 file type to allow a \"simplified\" version of JSON',\n }),\n missing: Flags.boolean({\n description: \"On duplicate document IDs, don't modify the target document(s)\",\n }),\n replace: Flags.boolean({\n description:\n 'On duplicate document IDs, replace existing document with specified document(s)',\n }),\n watch: Flags.boolean({\n description: 'Write the documents whenever the target file or buffer changes',\n }),\n }\n\n private client!: Awaited<ReturnType<typeof getProjectCliClient>>\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CreateDocumentCommand)\n const {file} = args\n const {dataset, id, json5: useJson5, missing, replace, watch} = flags\n const cliConfig = await this.getCliConfig()\n const projectId = await this.getProjectId()\n\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n if (!cliConfig.api?.dataset && !dataset) {\n this.error(\n 'No dataset specified. Either configure a dataset in sanity.cli.ts or use the --dataset flag',\n {exit: 1},\n )\n }\n\n const targetDataset = dataset || cliConfig.api?.dataset\n\n this.client = await getProjectCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n dataset: targetDataset,\n projectId,\n requireUser: true,\n })\n\n if (replace && missing) {\n this.error('Cannot use both --replace and --missing', {exit: 1})\n }\n\n if (id && file) {\n this.error('Cannot use --id when specifying a file path', {exit: 1})\n }\n\n let operation: MutationOperationName = 'create'\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n }\n\n if (file) {\n try {\n const contentPath = path.resolve(process.cwd(), file)\n const content = json5.parse(await fs.readFile(contentPath, 'utf8'))\n const result = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(result, operation))\n return\n } catch (error) {\n const err = error as Error\n createDocumentDebug(`Error creating documents from file ${file}`, err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n try {\n // Create a temporary file and use that as source, opening an editor on it\n const docId = id || randomUUID()\n const ext = useJson5 ? 'json5' : 'json'\n // Add UUID prefix to prevent predictable file names and potential conflicts\n const tmpFile = path.join(os.tmpdir(), 'sanity-cli', `${randomUUID()}-${docId}.${ext}`)\n const stringify = useJson5 ? json5.stringify : JSON.stringify\n const defaultValue = (id && (await this.client.getDocument(id))) || {\n _id: docId,\n _type: 'specify-me',\n }\n\n // Create temp directory with restricted permissions (owner only)\n const tempDir = path.join(os.tmpdir(), 'sanity-cli')\n await fs.mkdir(tempDir, {\n mode: 0o700, // rwx------ (owner read/write/execute only)\n recursive: true,\n })\n\n // Write file with restricted permissions (owner read/write only)\n await fs.writeFile(tmpFile, stringify(defaultValue, null, 2), {\n encoding: 'utf8',\n mode: 0o600, // rw------- (owner read/write only)\n })\n\n const editor = getEditor()\n const readAndPerformCreatesFromFile = this.readAndPerformCreatesFromFile.bind(this, operation)\n\n if (watch) {\n // If we're in watch mode, we want to run the creation on each change (if it validates)\n registerUnlinkOnSigInt(tmpFile)\n this.log(`Watch mode: ${tmpFile}`)\n this.log('Watch mode: Will write documents on each save.')\n this.log('Watch mode: Press Ctrl + C to cancel watch mode.')\n\n // Add race condition protection\n let isProcessing = false\n chokidarWatch(tmpFile).on('change', async () => {\n if (isProcessing) {\n return // Skip if already processing\n }\n isProcessing = true\n\n this.log('')\n try {\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n } finally {\n isProcessing = false\n }\n })\n execa(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n } else {\n // While in normal mode, we just want to wait for the editor to close and run the thing once\n execaSync(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n await fs.unlink(tmpFile).catch(() => {})\n }\n } catch (error) {\n const err = error as Error\n createDocumentDebug('Error in editor workflow', err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n private getErrorMessage(message: string, index: number, isSingle: boolean): string {\n return isSingle ? `Document ${message}` : `Document at index ${index} ${message}`\n }\n\n /**\n * Formats the result message for document operations\n */\n private getResultMessage(\n result: MultipleMutationResult,\n operation: MutationOperationName,\n ): string {\n const joiner = '\\n - '\n if (operation === 'createOrReplace') {\n return `Upserted:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n if (operation === 'create') {\n return `Created:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n // \"Missing\" (createIfNotExists)\n const created: string[] = []\n const skipped: string[] = []\n for (const res of result.results) {\n if (res.operation === 'update') {\n skipped.push(res.id)\n } else {\n created.push(res.id)\n }\n }\n\n if (created.length > 0 && skipped.length > 0) {\n return [\n `Created:\\n - ${created.join(joiner)}`,\n `Skipped (already exists):${joiner}${skipped.join(joiner)}`,\n ].join('\\n\\n')\n } else if (created.length > 0) {\n return `Created:\\n - ${created.join(joiner)}`\n }\n\n return `Skipped (already exists):\\n - ${skipped.join(joiner)}`\n }\n\n /**\n * Reads and processes documents from a file for creation\n */\n private async readAndPerformCreatesFromFile(\n operation: MutationOperationName,\n filePath: string,\n defaultValue: unknown,\n ): Promise<void> {\n let content\n try {\n content = json5.parse(await fs.readFile(filePath, 'utf8'))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to read input file ${filePath}`, error)\n this.log(`Failed to read input: ${error.message}`)\n return\n }\n\n if (isEqual(content, defaultValue)) {\n this.log('Value not modified, doing nothing.')\n this.log('Modify document to trigger creation.')\n return\n }\n\n try {\n const writeResult = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(writeResult, operation))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to write documents`, error)\n let errorMessage = `Failed to write documents: ${error.message}`\n if (error.message.includes('already exists')) {\n errorMessage += '\\nPerhaps you want to use `--replace` or `--missing`?'\n }\n this.error(errorMessage, {exit: 1})\n }\n }\n\n /**\n * Validates a document for Sanity requirements\n */\n private validateDocument(doc: unknown, index: number, arr: unknown[]): void {\n const isSingle = arr.length === 1\n\n if (!isPlainObject(doc)) {\n throw new Error(this.getErrorMessage('must be an object', index, isSingle))\n }\n\n if (!isSanityDocumentish(doc)) {\n throw new Error(\n this.getErrorMessage('must have a `_type` property of type string', index, isSingle),\n )\n }\n\n // Enhanced validations for Sanity document constraints\n const docObj = doc as Record<string, unknown>\n\n // Validate _type is non-empty\n const typeValue = docObj._type?.toString().trim()\n if (!typeValue) {\n throw new Error(this.getErrorMessage('_type cannot be empty', index, isSingle))\n }\n\n // Validate _type format (alphanumeric, underscore, hyphen, dot)\n if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(typeValue)) {\n throw new Error(\n this.getErrorMessage(\n '_type must start with a letter and contain only alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Validate _id format if present\n if (docObj._id && typeof docObj._id === 'string') {\n const idValue = docObj._id.trim()\n if (!idValue) {\n throw new Error(this.getErrorMessage('_id cannot be empty', index, isSingle))\n }\n\n // Sanity document IDs can contain alphanumeric chars, hyphens, underscores, and dots\n if (!/^[a-zA-Z0-9_.-]+$/.test(idValue)) {\n throw new Error(\n this.getErrorMessage(\n '_id can only contain alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Check length constraints (Sanity has reasonable limits)\n if (idValue.length > 200) {\n throw new Error(\n this.getErrorMessage('_id cannot be longer than 200 characters', index, isSingle),\n )\n }\n }\n\n // Warn about reserved fields (these are managed by Sanity)\n const reservedFields = ['_rev', '_updatedAt', '_createdAt']\n for (const field of reservedFields) {\n if (field in docObj) {\n // Note: We don't throw an error here as these might be present in fetched documents\n // that are being re-uploaded, but we could add a debug warning\n createDocumentDebug(\n `Warning: Document ${index} contains reserved field '${field}' which will be ignored by Sanity`,\n )\n }\n }\n }\n\n /**\n * Writes documents to Sanity using the specified operation\n */\n private async writeDocuments(\n documents: {_id?: string; _type: string} | {_id?: string; _type: string}[],\n operation: MutationOperationName,\n ): Promise<MultipleMutationResult> {\n const docs = Array.isArray(documents) ? documents : [documents]\n if (docs.length === 0) {\n throw new Error('No documents provided')\n }\n\n const mutations = docs.map((doc, index): Mutation => {\n this.validateDocument(doc, index, docs)\n if (operation === 'create') {\n return {create: doc}\n }\n\n if (operation === 'createIfNotExists') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createIfNotExists: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n if (operation === 'createOrReplace') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createOrReplace: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n throw new Error(`Unsupported operation ${operation}`)\n })\n\n return this.client.transaction(mutations).commit()\n }\n}\n"],"names":["randomUUID","fs","os","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","watch","chokidarWatch","execa","execaSync","json5","isEqual","isPlainObject","DOCUMENTS_API_VERSION","getEditor","registerUnlinkOnSigInt","NO_PROJECT_ID","isIdentifiedSanityDocument","isSanityDocumentish","createDocumentDebug","CreateDocumentCommand","args","file","string","description","required","examples","command","flags","dataset","char","id","boolean","missing","replace","client","run","parse","useJson5","cliConfig","getCliConfig","projectId","getProjectId","error","exit","api","targetDataset","apiVersion","requireUser","operation","contentPath","resolve","process","cwd","content","readFile","result","writeDocuments","log","getResultMessage","err","message","docId","ext","tmpFile","join","tmpdir","stringify","JSON","defaultValue","getDocument","_id","_type","tempDir","mkdir","mode","recursive","writeFile","encoding","editor","readAndPerformCreatesFromFile","bind","isProcessing","on","bin","stdio","unlink","catch","getErrorMessage","index","isSingle","joiner","results","map","res","created","skipped","push","length","filePath","writeResult","errorMessage","includes","validateDocument","doc","arr","Error","docObj","typeValue","toString","trim","test","idValue","reservedFields","field","documents","docs","Array","isArray","mutations","create","createIfNotExists","createOrReplace","transaction","commit"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import { isInteractive, SanityCommand } from '@sanity/cli-core';
|
|
3
3
|
import { confirm, spinner } from '@sanity/cli-core/ux';
|
|
4
|
-
import
|
|
4
|
+
import get from 'lodash-es/get.js';
|
|
5
5
|
import { extractFromSanitySchema } from '../../actions/graphql/extractFromSanitySchema.js';
|
|
6
6
|
import gen1 from '../../actions/graphql/gen1/index.js';
|
|
7
7
|
import gen2 from '../../actions/graphql/gen2/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/graphql/deploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {isInteractive, SanityCommand} from '@sanity/cli-core'\nimport {confirm, spinner} from '@sanity/cli-core/ux'\nimport {get} from 'lodash-es'\n\nimport {extractFromSanitySchema} from '../../actions/graphql/extractFromSanitySchema.js'\nimport gen1 from '../../actions/graphql/gen1/index.js'\nimport gen2 from '../../actions/graphql/gen2/index.js'\nimport gen3 from '../../actions/graphql/gen3/index.js'\nimport {getGraphQLAPIs} from '../../actions/graphql/getGraphQLAPIs.js'\nimport {graphqlDebug} from '../../actions/graphql/graphqlDebug.js'\nimport {resolveApiGeneration} from '../../actions/graphql/resolveApiGeneration.js'\nimport {SchemaError} from '../../actions/graphql/SchemaError.js'\nimport {\n type GeneratedApiSpecification,\n type ResolvedGraphQLAPI,\n type ValidationResponse,\n} from '../../actions/graphql/types.js'\nimport {\n deployGraphQLAPI,\n getClientUrl,\n getCurrentSchemaProps,\n validateGraphQLAPI,\n} from '../../services/graphql.js'\n\ninterface DeployTask {\n dataset: string\n enablePlayground: boolean\n projectId: string\n schema: GeneratedApiSpecification\n tag: string\n}\n\nconst apiIdRegex = /^[a-z0-9_-]+$/\nconst generations = {\n gen1,\n gen2,\n gen3,\n}\n\nconst ignoredBreaking = new Set<string>(['OPTIONAL_INPUT_FIELD_ADDED'])\n// Reserved for future use to filter out specific dangerous change types\nconst ignoredWarnings = new Set<string>()\n\nconst debug = graphqlDebug.extend('deploy')\n\nexport class GraphQLDeployCommand extends SanityCommand<typeof GraphQLDeployCommand> {\n static override description = 'Deploy a GraphQL API from the current Sanity schema'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Deploy all defined GraphQL APIs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dry-run',\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api staging --api ios',\n description: 'Deploy only the GraphQL APIs with the IDs \"staging\" and \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --playground',\n description: 'Deploy all defined GraphQL APIs, overriding any playground setting',\n },\n ]\n\n static override flags = {\n api: Flags.string({\n description: 'Only deploy API with this ID. Can be specified multiple times.',\n multiple: true,\n }),\n dataset: Flags.string({\n description: 'Deploy API for the given dataset',\n }),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n }),\n force: Flags.boolean({\n description: 'Deploy API without confirming breaking changes',\n }),\n generation: Flags.string({\n description: 'API generation to deploy (defaults to \"gen3\")',\n options: ['gen1', 'gen2', 'gen3'],\n }),\n 'non-null-document-fields': Flags.boolean({\n description: 'Use non-null document fields (_id, _type etc)',\n }),\n playground: Flags.boolean({\n allowNo: true,\n description: 'Enable GraphQL playground for easier debugging',\n }),\n tag: Flags.string({\n description: 'Deploy API(s) to given tag (defaults to \"default\")',\n }),\n 'with-union-cache': Flags.boolean({\n description:\n 'Enable union cache that optimizes schema generation for schemas with many self referencing types',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(GraphQLDeployCommand)\n const {\n api: onlyApis,\n dataset: datasetFlag,\n 'dry-run': dryRun,\n generation: generationFlag,\n 'non-null-document-fields': nonNullDocumentFieldsFlag,\n playground: playgroundFlag,\n tag: tagFlag,\n 'with-union-cache': withUnionCache,\n } = flags\n\n const workDir = (await this.getProjectRoot()).directory\n\n let apiDefs: ResolvedGraphQLAPI[] = []\n let spin: ReturnType<typeof spinner>\n\n try {\n apiDefs = await getGraphQLAPIs(workDir)\n } catch (error) {\n debug('Failed to get GraphQL APIs', error)\n this.error('Failed to get GraphQL APIs', {exit: 1})\n }\n\n const hasMultipleApis = flags.api ? flags.api.length > 1 : apiDefs.length > 1\n\n const usedFlags = [\n datasetFlag && '--dataset',\n tagFlag && '--tag',\n playgroundFlag !== undefined && '--playground',\n generationFlag !== undefined && '--generation',\n nonNullDocumentFieldsFlag !== undefined && '--non-null-document-fields',\n ].filter(Boolean)\n\n if (hasMultipleApis && usedFlags.length > 0) {\n this.warn(`More than one API defined, and ${usedFlags.join('/')} is specified`)\n this.warn(`This will use the specified flag(s) for ALL APIs, overriding config!`)\n\n if (flags.force) {\n this.warn(`--force specified, continuing...`)\n } else {\n const confirmed = await confirm({\n default: false,\n message: 'Continue with flag overrides for all APIs?',\n })\n if (!confirmed) {\n this.error('Operation cancelled', {exit: 1})\n }\n }\n }\n\n const deployTasks: DeployTask[] = []\n let hasErrors = false\n\n for (const apiId of onlyApis || []) {\n if (!apiDefs.some((apiDef) => apiDef.id === apiId)) {\n this.error(`GraphQL API with id \"${apiId}\" not found`, {exit: 1})\n }\n }\n\n const apiNames = new Set<string>()\n const apiIds = new Set<string>()\n\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n const {apiName} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n if (apiNames.has(apiName)) {\n this.error(`Multiple GraphQL APIs with the same dataset and tag found (${apiName})`, {\n exit: 1,\n })\n }\n\n if (apiDef.id) {\n if (typeof apiDef.id !== 'string' || !apiIdRegex.test(apiDef.id)) {\n this.error(\n `Invalid GraphQL API id \"${apiDef.id}\" - only a-z, 0-9, underscore and dashes are allowed`,\n {exit: 1},\n )\n }\n\n if (apiIds.has(apiDef.id)) {\n this.error(`Multiple GraphQL APIs with the same ID found (${apiDef.id})`, {exit: 1})\n }\n\n apiIds.add(apiDef.id)\n }\n\n apiNames.add(apiName)\n }\n\n if (onlyApis) {\n this.warn(`Deploying only specified APIs: ${onlyApis.join(', ')}`)\n }\n\n let index = -1\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n index++\n\n const {apiName, dataset, tag} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n const {nonNullDocumentFields, playground, projectId, schema} = apiDef\n spin = spinner(`Generating GraphQL API: ${apiName}`).start()\n\n if (!dataset) {\n spin.fail()\n this.error(`No dataset specified for API at index ${index}`, {exit: 1})\n }\n\n let currentGeneration: string | undefined\n let playgroundEnabled: boolean | undefined\n try {\n const schemaProps = await getCurrentSchemaProps(projectId, dataset, tag)\n currentGeneration = schemaProps.currentGeneration\n playgroundEnabled = schemaProps.playgroundEnabled\n } catch (err) {\n debug('Failed to get current GraphQL schema properties', err)\n spin.fail()\n this.error('Failed to get current GraphQL schema properties', {exit: 1})\n }\n\n // CLI flag takes precedence over configuration\n const specifiedGeneration = generationFlag === undefined ? apiDef.generation : generationFlag\n\n const generation = await resolveApiGeneration({\n currentGeneration,\n force: flags.force,\n index,\n output: this.output,\n specifiedGeneration,\n })\n\n if (!generation) {\n // User cancelled\n spin.fail()\n continue\n }\n\n if (!this.isRecognizedApiGeneration(generation)) {\n spin.fail()\n this.error(`Unknown API generation \"${generation}\" for API at index ${index}`, {exit: 1})\n }\n\n const enablePlayground = await this.shouldEnablePlayground({\n dryRun,\n playgroundCliFlag: playgroundFlag,\n playgroundConfiguration: playground,\n playgroundCurrentlyEnabled: playgroundEnabled,\n spin,\n })\n\n let apiSpec: GeneratedApiSpecification\n try {\n const generateSchema = generations[generation]\n const extracted = extractFromSanitySchema(schema, {\n // Allow CLI flag to override configured setting\n nonNullDocumentFields:\n nonNullDocumentFieldsFlag === undefined\n ? nonNullDocumentFields\n : nonNullDocumentFieldsFlag,\n withUnionCache,\n })\n\n apiSpec = generateSchema(extracted, {filterSuffix: apiDef.filterSuffix})\n } catch (err) {\n debug('Failed to extract schema', err)\n spin.fail()\n\n if (err instanceof SchemaError) {\n err.print(this.output)\n this.error('Failed to extract schema', {exit: 1})\n } else {\n const message = err instanceof Error ? err.message : 'Unknown error'\n this.error(`Failed to extract schema: ${message}`, {exit: 1})\n }\n }\n\n let valid: ValidationResponse | undefined\n try {\n valid = await validateGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n } catch (err) {\n debug('validateGraphQLAPI error', err)\n const validationError = get(err, 'response.body.validationError')\n spin.fail()\n this.error(validationError ?? 'Failed to validate GraphQL API', {exit: 1})\n }\n\n // when the result is not valid and there are breaking changes afoot!\n if (!this.isResultValid(valid, {force: flags.force, spin})) {\n // not valid and a dry run? then it can exit with a error\n if (dryRun) {\n spin.fail()\n this.renderBreakingChanges(valid)\n hasErrors = true\n continue\n }\n\n if (!isInteractive()) {\n spin.fail()\n this.renderBreakingChanges(valid)\n this.error(\n 'Dangerous changes found - falling back. Re-run the command with the `--force` flag to force deployment.',\n {exit: 1},\n )\n }\n\n spin.stop()\n this.renderBreakingChanges(valid)\n const shouldDeploy = await confirm({\n default: false,\n message: 'Do you want to deploy a new API despite the dangerous changes?',\n })\n\n if (!shouldDeploy) {\n spin.fail()\n continue\n }\n\n spin.succeed()\n } else if (dryRun) {\n spin.succeed()\n this.log('GraphQL API is valid and has no breaking changes')\n continue\n }\n\n deployTasks.push({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n }\n\n // Give some space for deployment tasks\n this.log('')\n\n for (const task of deployTasks) {\n const {dataset, enablePlayground, projectId, schema, tag} = task\n\n this.log(`Project: ${projectId}`)\n this.log(`Dataset: ${dataset}`)\n this.log(`Tag: ${tag}`)\n\n spin = spinner('Deploying GraphQL API').start()\n\n try {\n const response = await deployGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema,\n tag,\n })\n\n spin.stop()\n const apiUrl = await getClientUrl(\n projectId,\n response.location.replace(/^\\/(v1|v\\d{4}-\\d{2}-\\d{2})\\//, '/'),\n )\n this.log(`URL: ${apiUrl}`)\n spin.start('Deployed!').succeed()\n this.log('')\n } catch (error) {\n spin.fail()\n debug('Failed to deploy GraphQL API', error)\n this.error('Failed to deploy GraphQL API', {exit: 1})\n }\n }\n\n if (hasErrors) {\n this.exit(1)\n }\n }\n\n private filterChanges(valid: ValidationResponse) {\n const {breakingChanges: breaking, dangerousChanges: dangerous} = valid\n return {\n breakingChanges: breaking.filter((change) => !ignoredBreaking.has(change.type)),\n dangerousChanges: dangerous.filter((change) => !ignoredWarnings.has(change.type)),\n }\n }\n\n private getApiIdentifiers(apiDef: ResolvedGraphQLAPI, datasetFlag?: string, tagFlag?: string) {\n const dataset = datasetFlag || apiDef.dataset\n const tag = tagFlag || apiDef.tag || 'default'\n const apiName = [dataset, tag].join('/')\n return {apiName, dataset, tag}\n }\n\n private isRecognizedApiGeneration(generation: string): generation is 'gen1' | 'gen2' | 'gen3' {\n return ['gen1', 'gen2', 'gen3'].includes(generation)\n }\n\n private isResultValid(\n valid: ValidationResponse,\n {force, spin}: {force?: boolean; spin: ReturnType<typeof spinner>},\n ) {\n const {validationError} = valid\n if (validationError) {\n spin.fail()\n this.error(`GraphQL schema is not valid:\\n\\n${validationError}`, {exit: 1})\n }\n\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n const hasProblematicChanges = breakingChanges.length > 0 || dangerousChanges.length > 0\n\n if (!hasProblematicChanges) {\n spin.succeed()\n return true\n }\n\n if (force) {\n spin.text = 'Validating GraphQL API: Dangerous changes. Forced with `--force`.'\n spin.warn()\n return true\n }\n\n spin.warn()\n return false\n }\n\n private renderBreakingChanges(valid: ValidationResponse) {\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n if (dangerousChanges.length > 0) {\n this.log('\\nFound potentially dangerous changes from previous schema:')\n for (const change of dangerousChanges) this.log(` - ${change.description}`)\n }\n\n if (breakingChanges.length > 0) {\n this.log('\\nFound BREAKING changes from previous schema:')\n for (const change of breakingChanges) this.log(` - ${change.description}`)\n }\n\n this.output.log('')\n }\n\n private async shouldEnablePlayground({\n dryRun,\n playgroundCliFlag,\n playgroundConfiguration,\n playgroundCurrentlyEnabled,\n spin,\n }: {\n dryRun: boolean\n playgroundCliFlag?: boolean\n playgroundConfiguration?: boolean\n playgroundCurrentlyEnabled?: boolean\n spin: ReturnType<typeof spinner>\n }): Promise<boolean> {\n // On a dry run, it doesn't matter, return true 🤷♂️\n if (dryRun) {\n return true\n }\n\n // Prioritize CLI flag if set\n if (playgroundCliFlag !== undefined) {\n return playgroundCliFlag\n }\n\n // If explicitly set true/false in configuration, use that\n if (playgroundConfiguration !== undefined) {\n return playgroundConfiguration\n }\n\n // If API is already deployed, use the current state\n if (playgroundCurrentlyEnabled !== undefined) {\n return playgroundCurrentlyEnabled\n }\n\n // If no API is deployed, default to true if non-interactive\n if (!isInteractive()) {\n return true\n }\n\n // Interactive environment, so prompt the user\n const prevText = spin.text\n spin.warn()\n const shouldDeploy = await confirm({\n default: true,\n message: 'Do you want to enable a GraphQL playground?',\n })\n spin.clear().start(prevText)\n\n return shouldDeploy\n }\n}\n"],"names":["Flags","isInteractive","SanityCommand","confirm","spinner","get","extractFromSanitySchema","gen1","gen2","gen3","getGraphQLAPIs","graphqlDebug","resolveApiGeneration","SchemaError","deployGraphQLAPI","getClientUrl","getCurrentSchemaProps","validateGraphQLAPI","apiIdRegex","generations","ignoredBreaking","Set","ignoredWarnings","debug","extend","GraphQLDeployCommand","description","examples","command","flags","api","string","multiple","dataset","boolean","default","force","generation","options","playground","allowNo","tag","run","parse","onlyApis","datasetFlag","dryRun","generationFlag","nonNullDocumentFieldsFlag","playgroundFlag","tagFlag","withUnionCache","workDir","getProjectRoot","directory","apiDefs","spin","error","exit","hasMultipleApis","length","usedFlags","undefined","filter","Boolean","warn","join","confirmed","message","deployTasks","hasErrors","apiId","some","apiDef","id","apiNames","apiIds","includes","apiName","getApiIdentifiers","has","test","add","index","nonNullDocumentFields","projectId","schema","start","fail","currentGeneration","playgroundEnabled","schemaProps","err","specifiedGeneration","output","isRecognizedApiGeneration","enablePlayground","shouldEnablePlayground","playgroundCliFlag","playgroundConfiguration","playgroundCurrentlyEnabled","apiSpec","generateSchema","extracted","filterSuffix","print","Error","valid","validationError","isResultValid","renderBreakingChanges","stop","shouldDeploy","succeed","log","push","task","response","apiUrl","location","replace","filterChanges","breakingChanges","breaking","dangerousChanges","dangerous","change","type","hasProblematicChanges","text","prevText","clear"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/graphql/deploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {isInteractive, SanityCommand} from '@sanity/cli-core'\nimport {confirm, spinner} from '@sanity/cli-core/ux'\nimport get from 'lodash-es/get.js'\n\nimport {extractFromSanitySchema} from '../../actions/graphql/extractFromSanitySchema.js'\nimport gen1 from '../../actions/graphql/gen1/index.js'\nimport gen2 from '../../actions/graphql/gen2/index.js'\nimport gen3 from '../../actions/graphql/gen3/index.js'\nimport {getGraphQLAPIs} from '../../actions/graphql/getGraphQLAPIs.js'\nimport {graphqlDebug} from '../../actions/graphql/graphqlDebug.js'\nimport {resolveApiGeneration} from '../../actions/graphql/resolveApiGeneration.js'\nimport {SchemaError} from '../../actions/graphql/SchemaError.js'\nimport {\n type GeneratedApiSpecification,\n type ResolvedGraphQLAPI,\n type ValidationResponse,\n} from '../../actions/graphql/types.js'\nimport {\n deployGraphQLAPI,\n getClientUrl,\n getCurrentSchemaProps,\n validateGraphQLAPI,\n} from '../../services/graphql.js'\n\ninterface DeployTask {\n dataset: string\n enablePlayground: boolean\n projectId: string\n schema: GeneratedApiSpecification\n tag: string\n}\n\nconst apiIdRegex = /^[a-z0-9_-]+$/\nconst generations = {\n gen1,\n gen2,\n gen3,\n}\n\nconst ignoredBreaking = new Set<string>(['OPTIONAL_INPUT_FIELD_ADDED'])\n// Reserved for future use to filter out specific dangerous change types\nconst ignoredWarnings = new Set<string>()\n\nconst debug = graphqlDebug.extend('deploy')\n\nexport class GraphQLDeployCommand extends SanityCommand<typeof GraphQLDeployCommand> {\n static override description = 'Deploy a GraphQL API from the current Sanity schema'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Deploy all defined GraphQL APIs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dry-run',\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api staging --api ios',\n description: 'Deploy only the GraphQL APIs with the IDs \"staging\" and \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --playground',\n description: 'Deploy all defined GraphQL APIs, overriding any playground setting',\n },\n ]\n\n static override flags = {\n api: Flags.string({\n description: 'Only deploy API with this ID. Can be specified multiple times.',\n multiple: true,\n }),\n dataset: Flags.string({\n description: 'Deploy API for the given dataset',\n }),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n }),\n force: Flags.boolean({\n description: 'Deploy API without confirming breaking changes',\n }),\n generation: Flags.string({\n description: 'API generation to deploy (defaults to \"gen3\")',\n options: ['gen1', 'gen2', 'gen3'],\n }),\n 'non-null-document-fields': Flags.boolean({\n description: 'Use non-null document fields (_id, _type etc)',\n }),\n playground: Flags.boolean({\n allowNo: true,\n description: 'Enable GraphQL playground for easier debugging',\n }),\n tag: Flags.string({\n description: 'Deploy API(s) to given tag (defaults to \"default\")',\n }),\n 'with-union-cache': Flags.boolean({\n description:\n 'Enable union cache that optimizes schema generation for schemas with many self referencing types',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(GraphQLDeployCommand)\n const {\n api: onlyApis,\n dataset: datasetFlag,\n 'dry-run': dryRun,\n generation: generationFlag,\n 'non-null-document-fields': nonNullDocumentFieldsFlag,\n playground: playgroundFlag,\n tag: tagFlag,\n 'with-union-cache': withUnionCache,\n } = flags\n\n const workDir = (await this.getProjectRoot()).directory\n\n let apiDefs: ResolvedGraphQLAPI[] = []\n let spin: ReturnType<typeof spinner>\n\n try {\n apiDefs = await getGraphQLAPIs(workDir)\n } catch (error) {\n debug('Failed to get GraphQL APIs', error)\n this.error('Failed to get GraphQL APIs', {exit: 1})\n }\n\n const hasMultipleApis = flags.api ? flags.api.length > 1 : apiDefs.length > 1\n\n const usedFlags = [\n datasetFlag && '--dataset',\n tagFlag && '--tag',\n playgroundFlag !== undefined && '--playground',\n generationFlag !== undefined && '--generation',\n nonNullDocumentFieldsFlag !== undefined && '--non-null-document-fields',\n ].filter(Boolean)\n\n if (hasMultipleApis && usedFlags.length > 0) {\n this.warn(`More than one API defined, and ${usedFlags.join('/')} is specified`)\n this.warn(`This will use the specified flag(s) for ALL APIs, overriding config!`)\n\n if (flags.force) {\n this.warn(`--force specified, continuing...`)\n } else {\n const confirmed = await confirm({\n default: false,\n message: 'Continue with flag overrides for all APIs?',\n })\n if (!confirmed) {\n this.error('Operation cancelled', {exit: 1})\n }\n }\n }\n\n const deployTasks: DeployTask[] = []\n let hasErrors = false\n\n for (const apiId of onlyApis || []) {\n if (!apiDefs.some((apiDef) => apiDef.id === apiId)) {\n this.error(`GraphQL API with id \"${apiId}\" not found`, {exit: 1})\n }\n }\n\n const apiNames = new Set<string>()\n const apiIds = new Set<string>()\n\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n const {apiName} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n if (apiNames.has(apiName)) {\n this.error(`Multiple GraphQL APIs with the same dataset and tag found (${apiName})`, {\n exit: 1,\n })\n }\n\n if (apiDef.id) {\n if (typeof apiDef.id !== 'string' || !apiIdRegex.test(apiDef.id)) {\n this.error(\n `Invalid GraphQL API id \"${apiDef.id}\" - only a-z, 0-9, underscore and dashes are allowed`,\n {exit: 1},\n )\n }\n\n if (apiIds.has(apiDef.id)) {\n this.error(`Multiple GraphQL APIs with the same ID found (${apiDef.id})`, {exit: 1})\n }\n\n apiIds.add(apiDef.id)\n }\n\n apiNames.add(apiName)\n }\n\n if (onlyApis) {\n this.warn(`Deploying only specified APIs: ${onlyApis.join(', ')}`)\n }\n\n let index = -1\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n index++\n\n const {apiName, dataset, tag} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n const {nonNullDocumentFields, playground, projectId, schema} = apiDef\n spin = spinner(`Generating GraphQL API: ${apiName}`).start()\n\n if (!dataset) {\n spin.fail()\n this.error(`No dataset specified for API at index ${index}`, {exit: 1})\n }\n\n let currentGeneration: string | undefined\n let playgroundEnabled: boolean | undefined\n try {\n const schemaProps = await getCurrentSchemaProps(projectId, dataset, tag)\n currentGeneration = schemaProps.currentGeneration\n playgroundEnabled = schemaProps.playgroundEnabled\n } catch (err) {\n debug('Failed to get current GraphQL schema properties', err)\n spin.fail()\n this.error('Failed to get current GraphQL schema properties', {exit: 1})\n }\n\n // CLI flag takes precedence over configuration\n const specifiedGeneration = generationFlag === undefined ? apiDef.generation : generationFlag\n\n const generation = await resolveApiGeneration({\n currentGeneration,\n force: flags.force,\n index,\n output: this.output,\n specifiedGeneration,\n })\n\n if (!generation) {\n // User cancelled\n spin.fail()\n continue\n }\n\n if (!this.isRecognizedApiGeneration(generation)) {\n spin.fail()\n this.error(`Unknown API generation \"${generation}\" for API at index ${index}`, {exit: 1})\n }\n\n const enablePlayground = await this.shouldEnablePlayground({\n dryRun,\n playgroundCliFlag: playgroundFlag,\n playgroundConfiguration: playground,\n playgroundCurrentlyEnabled: playgroundEnabled,\n spin,\n })\n\n let apiSpec: GeneratedApiSpecification\n try {\n const generateSchema = generations[generation]\n const extracted = extractFromSanitySchema(schema, {\n // Allow CLI flag to override configured setting\n nonNullDocumentFields:\n nonNullDocumentFieldsFlag === undefined\n ? nonNullDocumentFields\n : nonNullDocumentFieldsFlag,\n withUnionCache,\n })\n\n apiSpec = generateSchema(extracted, {filterSuffix: apiDef.filterSuffix})\n } catch (err) {\n debug('Failed to extract schema', err)\n spin.fail()\n\n if (err instanceof SchemaError) {\n err.print(this.output)\n this.error('Failed to extract schema', {exit: 1})\n } else {\n const message = err instanceof Error ? err.message : 'Unknown error'\n this.error(`Failed to extract schema: ${message}`, {exit: 1})\n }\n }\n\n let valid: ValidationResponse | undefined\n try {\n valid = await validateGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n } catch (err) {\n debug('validateGraphQLAPI error', err)\n const validationError = get(err, 'response.body.validationError')\n spin.fail()\n this.error(validationError ?? 'Failed to validate GraphQL API', {exit: 1})\n }\n\n // when the result is not valid and there are breaking changes afoot!\n if (!this.isResultValid(valid, {force: flags.force, spin})) {\n // not valid and a dry run? then it can exit with a error\n if (dryRun) {\n spin.fail()\n this.renderBreakingChanges(valid)\n hasErrors = true\n continue\n }\n\n if (!isInteractive()) {\n spin.fail()\n this.renderBreakingChanges(valid)\n this.error(\n 'Dangerous changes found - falling back. Re-run the command with the `--force` flag to force deployment.',\n {exit: 1},\n )\n }\n\n spin.stop()\n this.renderBreakingChanges(valid)\n const shouldDeploy = await confirm({\n default: false,\n message: 'Do you want to deploy a new API despite the dangerous changes?',\n })\n\n if (!shouldDeploy) {\n spin.fail()\n continue\n }\n\n spin.succeed()\n } else if (dryRun) {\n spin.succeed()\n this.log('GraphQL API is valid and has no breaking changes')\n continue\n }\n\n deployTasks.push({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n }\n\n // Give some space for deployment tasks\n this.log('')\n\n for (const task of deployTasks) {\n const {dataset, enablePlayground, projectId, schema, tag} = task\n\n this.log(`Project: ${projectId}`)\n this.log(`Dataset: ${dataset}`)\n this.log(`Tag: ${tag}`)\n\n spin = spinner('Deploying GraphQL API').start()\n\n try {\n const response = await deployGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema,\n tag,\n })\n\n spin.stop()\n const apiUrl = await getClientUrl(\n projectId,\n response.location.replace(/^\\/(v1|v\\d{4}-\\d{2}-\\d{2})\\//, '/'),\n )\n this.log(`URL: ${apiUrl}`)\n spin.start('Deployed!').succeed()\n this.log('')\n } catch (error) {\n spin.fail()\n debug('Failed to deploy GraphQL API', error)\n this.error('Failed to deploy GraphQL API', {exit: 1})\n }\n }\n\n if (hasErrors) {\n this.exit(1)\n }\n }\n\n private filterChanges(valid: ValidationResponse) {\n const {breakingChanges: breaking, dangerousChanges: dangerous} = valid\n return {\n breakingChanges: breaking.filter((change) => !ignoredBreaking.has(change.type)),\n dangerousChanges: dangerous.filter((change) => !ignoredWarnings.has(change.type)),\n }\n }\n\n private getApiIdentifiers(apiDef: ResolvedGraphQLAPI, datasetFlag?: string, tagFlag?: string) {\n const dataset = datasetFlag || apiDef.dataset\n const tag = tagFlag || apiDef.tag || 'default'\n const apiName = [dataset, tag].join('/')\n return {apiName, dataset, tag}\n }\n\n private isRecognizedApiGeneration(generation: string): generation is 'gen1' | 'gen2' | 'gen3' {\n return ['gen1', 'gen2', 'gen3'].includes(generation)\n }\n\n private isResultValid(\n valid: ValidationResponse,\n {force, spin}: {force?: boolean; spin: ReturnType<typeof spinner>},\n ) {\n const {validationError} = valid\n if (validationError) {\n spin.fail()\n this.error(`GraphQL schema is not valid:\\n\\n${validationError}`, {exit: 1})\n }\n\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n const hasProblematicChanges = breakingChanges.length > 0 || dangerousChanges.length > 0\n\n if (!hasProblematicChanges) {\n spin.succeed()\n return true\n }\n\n if (force) {\n spin.text = 'Validating GraphQL API: Dangerous changes. Forced with `--force`.'\n spin.warn()\n return true\n }\n\n spin.warn()\n return false\n }\n\n private renderBreakingChanges(valid: ValidationResponse) {\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n if (dangerousChanges.length > 0) {\n this.log('\\nFound potentially dangerous changes from previous schema:')\n for (const change of dangerousChanges) this.log(` - ${change.description}`)\n }\n\n if (breakingChanges.length > 0) {\n this.log('\\nFound BREAKING changes from previous schema:')\n for (const change of breakingChanges) this.log(` - ${change.description}`)\n }\n\n this.output.log('')\n }\n\n private async shouldEnablePlayground({\n dryRun,\n playgroundCliFlag,\n playgroundConfiguration,\n playgroundCurrentlyEnabled,\n spin,\n }: {\n dryRun: boolean\n playgroundCliFlag?: boolean\n playgroundConfiguration?: boolean\n playgroundCurrentlyEnabled?: boolean\n spin: ReturnType<typeof spinner>\n }): Promise<boolean> {\n // On a dry run, it doesn't matter, return true 🤷♂️\n if (dryRun) {\n return true\n }\n\n // Prioritize CLI flag if set\n if (playgroundCliFlag !== undefined) {\n return playgroundCliFlag\n }\n\n // If explicitly set true/false in configuration, use that\n if (playgroundConfiguration !== undefined) {\n return playgroundConfiguration\n }\n\n // If API is already deployed, use the current state\n if (playgroundCurrentlyEnabled !== undefined) {\n return playgroundCurrentlyEnabled\n }\n\n // If no API is deployed, default to true if non-interactive\n if (!isInteractive()) {\n return true\n }\n\n // Interactive environment, so prompt the user\n const prevText = spin.text\n spin.warn()\n const shouldDeploy = await confirm({\n default: true,\n message: 'Do you want to enable a GraphQL playground?',\n })\n spin.clear().start(prevText)\n\n return shouldDeploy\n }\n}\n"],"names":["Flags","isInteractive","SanityCommand","confirm","spinner","get","extractFromSanitySchema","gen1","gen2","gen3","getGraphQLAPIs","graphqlDebug","resolveApiGeneration","SchemaError","deployGraphQLAPI","getClientUrl","getCurrentSchemaProps","validateGraphQLAPI","apiIdRegex","generations","ignoredBreaking","Set","ignoredWarnings","debug","extend","GraphQLDeployCommand","description","examples","command","flags","api","string","multiple","dataset","boolean","default","force","generation","options","playground","allowNo","tag","run","parse","onlyApis","datasetFlag","dryRun","generationFlag","nonNullDocumentFieldsFlag","playgroundFlag","tagFlag","withUnionCache","workDir","getProjectRoot","directory","apiDefs","spin","error","exit","hasMultipleApis","length","usedFlags","undefined","filter","Boolean","warn","join","confirmed","message","deployTasks","hasErrors","apiId","some","apiDef","id","apiNames","apiIds","includes","apiName","getApiIdentifiers","has","test","add","index","nonNullDocumentFields","projectId","schema","start","fail","currentGeneration","playgroundEnabled","schemaProps","err","specifiedGeneration","output","isRecognizedApiGeneration","enablePlayground","shouldEnablePlayground","playgroundCliFlag","playgroundConfiguration","playgroundCurrentlyEnabled","apiSpec","generateSchema","extracted","filterSuffix","print","Error","valid","validationError","isResultValid","renderBreakingChanges","stop","shouldDeploy","succeed","log","push","task","response","apiUrl","location","replace","filterChanges","breakingChanges","breaking","dangerousChanges","dangerous","change","type","hasProblematicChanges","text","prevText","clear"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { inspect, styleText } from 'node:util';
|
|
|
2
2
|
import { Args, Flags } from '@oclif/core';
|
|
3
3
|
import { SanityCommand, subdebug } from '@sanity/cli-core';
|
|
4
4
|
import { select } from '@sanity/cli-core/ux';
|
|
5
|
-
import
|
|
5
|
+
import groupBy from 'lodash-es/groupBy.js';
|
|
6
6
|
import { formatFailure } from '../../actions/hook/formatFailure.js';
|
|
7
7
|
import { getHookAttemptsForProject, getHookMessagesForProject, getHooksForProject } from '../../services/hooks.js';
|
|
8
8
|
import { NO_PROJECT_ID } from '../../util/errorMessages.js';
|