@sanity/cli 7.10.0 → 7.11.0
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 +31 -22
- package/dist/actions/auth/ensureAuthenticated.js +2 -0
- package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
- package/dist/actions/auth/login/loginInstructions.js +19 -0
- package/dist/actions/auth/login/loginInstructions.js.map +1 -0
- package/dist/actions/dataset/resolveDataset.js +7 -1
- package/dist/actions/dataset/resolveDataset.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +17 -12
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +2 -0
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/graphql/resolveApiGeneration.js +9 -6
- package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
- package/dist/actions/init/initAction.js +23 -15
- package/dist/actions/init/initAction.js.map +1 -1
- package/dist/actions/manifest/extractCoreAppManifest.js +5 -3
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
- package/dist/actions/migration/constants.js +10 -0
- package/dist/actions/migration/constants.js.map +1 -0
- package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
- package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
- package/dist/actions/migration/fileExists.js +13 -0
- package/dist/actions/migration/fileExists.js.map +1 -0
- package/dist/actions/migration/prettyMutationFormatter.js +155 -0
- package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
- package/dist/actions/migration/resolveMigrationScript.js +75 -0
- package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
- package/dist/actions/migration/resolveMigrations.js +50 -0
- package/dist/actions/migration/resolveMigrations.js.map +1 -0
- package/dist/actions/migration/templates/index.js +7 -0
- package/dist/actions/migration/templates/index.js.map +1 -0
- package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
- package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
- package/dist/actions/migration/templates/minimalSimple.js +61 -0
- package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
- package/dist/actions/migration/templates/renameField.js +20 -0
- package/dist/actions/migration/templates/renameField.js.map +1 -0
- package/dist/actions/migration/templates/renameType.js +19 -0
- package/dist/actions/migration/templates/renameType.js.map +1 -0
- package/dist/actions/migration/templates/stringToPTE.js +32 -0
- package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
- package/dist/actions/migration/tree.js +111 -0
- package/dist/actions/migration/tree.js.map +1 -0
- package/dist/actions/preview/previewAction.js +33 -1
- package/dist/actions/preview/previewAction.js.map +1 -1
- package/dist/actions/schema/listSchemas.js +6 -4
- package/dist/actions/schema/listSchemas.js.map +1 -1
- package/dist/actions/tokens/validateRole.js +2 -1
- package/dist/actions/tokens/validateRole.js.map +1 -1
- package/dist/actions/undeploy/runUndeploy.js +13 -4
- package/dist/actions/undeploy/runUndeploy.js.map +1 -1
- package/dist/commands/backups/disable.js +5 -1
- package/dist/commands/backups/disable.js.map +1 -1
- package/dist/commands/backups/download.js +30 -6
- package/dist/commands/backups/download.js.map +1 -1
- package/dist/commands/backups/enable.js +5 -1
- package/dist/commands/backups/enable.js.map +1 -1
- package/dist/commands/backups/list.js +5 -1
- package/dist/commands/backups/list.js.map +1 -1
- package/dist/commands/cors/add.js +15 -7
- package/dist/commands/cors/add.js.map +1 -1
- package/dist/commands/cors/delete.js +6 -1
- package/dist/commands/cors/delete.js.map +1 -1
- package/dist/commands/datasets/alias/create.js +25 -18
- package/dist/commands/datasets/alias/create.js.map +1 -1
- package/dist/commands/datasets/alias/delete.js +15 -8
- package/dist/commands/datasets/alias/delete.js.map +1 -1
- package/dist/commands/datasets/alias/link.js +39 -17
- package/dist/commands/datasets/alias/link.js.map +1 -1
- package/dist/commands/datasets/alias/unlink.js +23 -2
- package/dist/commands/datasets/alias/unlink.js.map +1 -1
- package/dist/commands/datasets/copy.js +18 -2
- package/dist/commands/datasets/copy.js.map +1 -1
- package/dist/commands/datasets/create.js +8 -2
- package/dist/commands/datasets/create.js.map +1 -1
- package/dist/commands/datasets/delete.js +14 -17
- package/dist/commands/datasets/delete.js.map +1 -1
- package/dist/commands/datasets/embeddings/disable.js +3 -0
- package/dist/commands/datasets/embeddings/disable.js.map +1 -1
- package/dist/commands/datasets/embeddings/enable.js +5 -2
- package/dist/commands/datasets/embeddings/enable.js.map +1 -1
- package/dist/commands/datasets/embeddings/status.js +3 -0
- package/dist/commands/datasets/embeddings/status.js.map +1 -1
- package/dist/commands/datasets/export.js +27 -15
- package/dist/commands/datasets/export.js.map +1 -1
- package/dist/commands/datasets/import.js +3 -3
- package/dist/commands/datasets/import.js.map +1 -1
- package/dist/commands/datasets/visibility/get.js +2 -2
- package/dist/commands/datasets/visibility/get.js.map +1 -1
- package/dist/commands/datasets/visibility/set.js +2 -2
- package/dist/commands/datasets/visibility/set.js.map +1 -1
- package/dist/commands/docs/read.js +3 -3
- package/dist/commands/docs/read.js.map +1 -1
- package/dist/commands/documents/create.js +18 -13
- package/dist/commands/documents/create.js.map +1 -1
- package/dist/commands/documents/delete.js +3 -3
- package/dist/commands/documents/delete.js.map +1 -1
- package/dist/commands/documents/get.js +3 -3
- package/dist/commands/documents/get.js.map +1 -1
- package/dist/commands/documents/query.js +3 -3
- package/dist/commands/documents/query.js.map +1 -1
- package/dist/commands/documents/validate.js +29 -26
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/graphql/deploy.js +20 -16
- package/dist/commands/graphql/deploy.js.map +1 -1
- package/dist/commands/graphql/undeploy.js +15 -18
- package/dist/commands/graphql/undeploy.js.map +1 -1
- package/dist/commands/hooks/delete.js +2 -2
- package/dist/commands/hooks/delete.js.map +1 -1
- package/dist/commands/hooks/logs.js +2 -2
- package/dist/commands/hooks/logs.js.map +1 -1
- package/dist/commands/login.js +2 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/media/create-aspect.js +20 -8
- package/dist/commands/media/create-aspect.js.map +1 -1
- package/dist/commands/media/delete-aspect.js +31 -16
- package/dist/commands/media/delete-aspect.js.map +1 -1
- package/dist/commands/media/deploy-aspect.js +10 -5
- package/dist/commands/media/deploy-aspect.js.map +1 -1
- package/dist/commands/media/export.js +9 -4
- package/dist/commands/media/export.js.map +1 -1
- package/dist/commands/media/import.js +6 -1
- package/dist/commands/media/import.js.map +1 -1
- package/dist/commands/migrations/create.js +150 -0
- package/dist/commands/migrations/create.js.map +1 -0
- package/dist/commands/migrations/list.js +64 -0
- package/dist/commands/migrations/list.js.map +1 -0
- package/dist/commands/migrations/run.js +306 -0
- package/dist/commands/migrations/run.js.map +1 -0
- package/dist/commands/preview.js +1 -0
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/projects/create.js +2 -1
- package/dist/commands/projects/create.js.map +1 -1
- package/dist/commands/schemas/delete.js +23 -2
- package/dist/commands/schemas/delete.js.map +1 -1
- package/dist/commands/schemas/deploy.js +6 -4
- package/dist/commands/schemas/deploy.js.map +1 -1
- package/dist/commands/schemas/extract.js +22 -1
- package/dist/commands/schemas/extract.js.map +1 -1
- package/dist/commands/schemas/list.js +8 -8
- package/dist/commands/schemas/list.js.map +1 -1
- package/dist/commands/tokens/{add.js → create.js} +25 -18
- package/dist/commands/tokens/create.js.map +1 -0
- package/dist/commands/tokens/delete.js +41 -23
- package/dist/commands/tokens/delete.js.map +1 -1
- package/dist/commands/undeploy.js +2 -7
- package/dist/commands/undeploy.js.map +1 -1
- package/dist/commands/users/invite.js +25 -3
- package/dist/commands/users/invite.js.map +1 -1
- package/dist/topicAliases.js +3 -0
- package/dist/topicAliases.js.map +1 -1
- package/dist/util/formatCliErrorMessages.js +5 -0
- package/dist/util/formatCliErrorMessages.js.map +1 -0
- package/oclif.config.js +5 -1
- package/oclif.manifest.json +326 -121
- package/package.json +7 -7
- package/dist/commands/tokens/add.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { CLIError } from '@oclif/core/errors';
|
|
2
|
-
import {
|
|
2
|
+
import { exitCodes } from '@sanity/cli-core';
|
|
3
3
|
import { confirm } from '@sanity/cli-core/ux';
|
|
4
4
|
import { oneline } from 'oneline';
|
|
5
5
|
import { graphqlDebug } from './graphqlDebug.js';
|
|
6
6
|
const LATEST_GENERATION = 'gen3';
|
|
7
|
-
export async function resolveApiGeneration({ currentGeneration, force, index, output, specifiedGeneration }) {
|
|
7
|
+
export async function resolveApiGeneration({ currentGeneration, force, index, output, specifiedGeneration, unattended }) {
|
|
8
8
|
// a) If no API is currently deployed:
|
|
9
9
|
// use the specificed one from config, or use whichever generation is the latest
|
|
10
10
|
// b) If an API generation is specified explicitly:
|
|
@@ -17,12 +17,12 @@ export async function resolveApiGeneration({ currentGeneration, force, index, ou
|
|
|
17
17
|
return generation;
|
|
18
18
|
}
|
|
19
19
|
if (specifiedGeneration && specifiedGeneration !== currentGeneration) {
|
|
20
|
-
if (!force &&
|
|
20
|
+
if (!force && unattended) {
|
|
21
21
|
throw new CLIError(oneline`
|
|
22
22
|
Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).
|
|
23
|
-
|
|
23
|
+
Pass \`--force\` to continue.
|
|
24
24
|
`, {
|
|
25
|
-
exit:
|
|
25
|
+
exit: exitCodes.USAGE_ERROR
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
output.warn(`Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`);
|
|
@@ -30,7 +30,10 @@ export async function resolveApiGeneration({ currentGeneration, force, index, ou
|
|
|
30
30
|
default: false,
|
|
31
31
|
message: 'Are you sure you want to deploy?'
|
|
32
32
|
});
|
|
33
|
-
|
|
33
|
+
if (!confirmDeploy) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
return specifiedGeneration;
|
|
34
37
|
}
|
|
35
38
|
if (specifiedGeneration) {
|
|
36
39
|
graphqlDebug('Using specified (%s) generation', specifiedGeneration);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/graphql/resolveApiGeneration.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/graphql/resolveApiGeneration.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {exitCodes, type Output} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {graphqlDebug} from './graphqlDebug.js'\n\nconst LATEST_GENERATION = 'gen3'\n\nexport async function resolveApiGeneration({\n currentGeneration,\n force,\n index,\n output,\n specifiedGeneration,\n unattended,\n}: {\n currentGeneration?: string\n force?: boolean\n index: number\n output: Output\n specifiedGeneration?: string\n unattended: boolean\n}): Promise<string | undefined> {\n // a) If no API is currently deployed:\n // use the specificed one from config, or use whichever generation is the latest\n // b) If an API generation is specified explicitly:\n // use the given one, but _prompt_ if it differs from the current one\n // c) If no API generation is specified explicitly:\n // use whichever is already deployed, but warn if differs from latest\n if (!currentGeneration) {\n const generation = specifiedGeneration || LATEST_GENERATION\n graphqlDebug(\n 'There is no current generation deployed, using %s (%s)',\n generation,\n specifiedGeneration ? 'specified' : 'default',\n )\n return generation\n }\n\n if (specifiedGeneration && specifiedGeneration !== currentGeneration) {\n if (!force && unattended) {\n throw new CLIError(\n oneline`\n Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).\n Pass \\`--force\\` to continue.\n `,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n output.warn(\n `Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`,\n )\n\n const confirmDeploy =\n force ||\n (await confirm({\n default: false,\n message: 'Are you sure you want to deploy?',\n }))\n\n if (!confirmDeploy) {\n return undefined\n }\n\n return specifiedGeneration\n }\n\n if (specifiedGeneration) {\n graphqlDebug('Using specified (%s) generation', specifiedGeneration)\n return specifiedGeneration\n }\n\n graphqlDebug('Using the currently deployed version (%s)', currentGeneration)\n return currentGeneration\n}\n"],"names":["CLIError","exitCodes","confirm","oneline","graphqlDebug","LATEST_GENERATION","resolveApiGeneration","currentGeneration","force","index","output","specifiedGeneration","unattended","generation","exit","USAGE_ERROR","warn","confirmDeploy","default","message","undefined"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,SAAS,QAAoB,mBAAkB;AACvD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,OAAO,QAAO,UAAS;AAE/B,SAAQC,YAAY,QAAO,oBAAmB;AAE9C,MAAMC,oBAAoB;AAE1B,OAAO,eAAeC,qBAAqB,EACzCC,iBAAiB,EACjBC,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,mBAAmB,EACnBC,UAAU,EAQX;IACC,sCAAsC;IACtC,mFAAmF;IACnF,mDAAmD;IACnD,wEAAwE;IACxE,mDAAmD;IACnD,wEAAwE;IACxE,IAAI,CAACL,mBAAmB;QACtB,MAAMM,aAAaF,uBAAuBN;QAC1CD,aACE,0DACAS,YACAF,sBAAsB,cAAc;QAEtC,OAAOE;IACT;IAEA,IAAIF,uBAAuBA,wBAAwBJ,mBAAmB;QACpE,IAAI,CAACC,SAASI,YAAY;YACxB,MAAM,IAAIZ,SACRG,OAAO,CAAC;8BACc,EAAEQ,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB;;MAEvI,CAAC,EACC;gBAACO,MAAMb,UAAUc,WAAW;YAAA;QAEhC;QAEAL,OAAOM,IAAI,CACT,CAAC,sBAAsB,EAAEL,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB,EAAE,CAAC;QAG3I,MAAMU,gBACJT,SACC,MAAMN,QAAQ;YACbgB,SAAS;YACTC,SAAS;QACX;QAEF,IAAI,CAACF,eAAe;YAClB,OAAOG;QACT;QAEA,OAAOT;IACT;IAEA,IAAIA,qBAAqB;QACvBP,aAAa,mCAAmCO;QAChD,OAAOA;IACT;IAEAP,aAAa,6CAA6CG;IAC1D,OAAOA;AACT"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
|
-
import { subdebug } from '@sanity/cli-core';
|
|
2
|
+
import { exitCodes, subdebug } from '@sanity/cli-core';
|
|
3
3
|
import { logSymbols, spinner } from '@sanity/cli-core/ux';
|
|
4
4
|
import { frameworks } from '@vercel/frameworks';
|
|
5
5
|
import deburr from 'lodash-es/deburr.js';
|
|
@@ -7,10 +7,12 @@ import { promptForConfigFiles } from '../../prompts/init/nextjs.js';
|
|
|
7
7
|
import { getCliUser } from '../../services/user.js';
|
|
8
8
|
import { CLIInitStepCompleted } from '../../telemetry/init.telemetry.js';
|
|
9
9
|
import { detectFrameworkRecord } from '../../util/detectFramework.js';
|
|
10
|
+
import { formatCliErrorMessages } from '../../util/formatCliErrorMessages.js';
|
|
10
11
|
import { getProjectDefaults } from '../../util/getProjectDefaults.js';
|
|
11
12
|
import { validateSession } from '../auth/ensureAuthenticated.js';
|
|
12
13
|
import { getProviderName } from '../auth/getProviderName.js';
|
|
13
14
|
import { login } from '../auth/login/login.js';
|
|
15
|
+
import { LOGIN_REQUIRED_MESSAGE } from '../auth/login/loginInstructions.js';
|
|
14
16
|
import { detectAvailableEditors } from '../mcp/detectAvailableEditors.js';
|
|
15
17
|
import { setupMCP } from '../mcp/setupMCP.js';
|
|
16
18
|
import { setupSkills } from '../skills/setupSkills.js';
|
|
@@ -268,24 +270,29 @@ export async function initAction(options, context) {
|
|
|
268
270
|
}
|
|
269
271
|
function checkFlagsInUnattendedMode(options, { isAppTemplate, isNextJs }) {
|
|
270
272
|
debug('Unattended mode, validating required options');
|
|
271
|
-
|
|
272
|
-
throw new InitError('`--project-name` requires `--organization <id>` in unattended mode', 1);
|
|
273
|
-
}
|
|
273
|
+
const errors = [];
|
|
274
274
|
if (isAppTemplate) {
|
|
275
275
|
if (!options.outputPath) {
|
|
276
|
-
|
|
276
|
+
errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
|
|
277
277
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
278
|
+
if (options.projectName && !options.organization) {
|
|
279
|
+
errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
|
|
280
|
+
} else if (!options.project && !options.organization) {
|
|
281
|
+
errors.push('Project or organization is required for app templates in unattended mode. ' + 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' + '`--project-name <name>` with `--organization <id>`.');
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
if (!isNextJs && !options.bare && !options.outputPath) {
|
|
285
|
+
errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
|
|
286
|
+
}
|
|
287
|
+
if (!options.project && !options.projectName) {
|
|
288
|
+
errors.push('Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.');
|
|
289
|
+
}
|
|
290
|
+
if (!options.project && !options.organization) {
|
|
291
|
+
errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
|
|
281
292
|
}
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
if (!isNextJs && !options.bare && !options.outputPath) {
|
|
285
|
-
throw new InitError('`--output-path` must be specified in unattended mode', 1);
|
|
286
293
|
}
|
|
287
|
-
if (
|
|
288
|
-
throw new InitError(
|
|
294
|
+
if (errors.length > 0) {
|
|
295
|
+
throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR);
|
|
289
296
|
}
|
|
290
297
|
}
|
|
291
298
|
async function ensureAuthenticated(options, output, trace) {
|
|
@@ -301,11 +308,12 @@ async function ensureAuthenticated(options, output, trace) {
|
|
|
301
308
|
};
|
|
302
309
|
}
|
|
303
310
|
if (options.unattended) {
|
|
304
|
-
throw new InitError(
|
|
311
|
+
throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR);
|
|
305
312
|
}
|
|
306
313
|
trace.log({
|
|
307
314
|
step: 'login'
|
|
308
315
|
});
|
|
316
|
+
output.warn(LOGIN_REQUIRED_MESSAGE);
|
|
309
317
|
try {
|
|
310
318
|
await login({
|
|
311
319
|
output,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/initAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type SanityOrgUser, subdebug, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\nimport {type Framework, frameworks} from '@vercel/frameworks'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {promptForConfigFiles} from '../../prompts/init/nextjs.js'\nimport {getCliUser} from '../../services/user.js'\nimport {CLIInitStepCompleted, type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {validateSession} from '../auth/ensureAuthenticated.js'\nimport {getProviderName} from '../auth/getProviderName.js'\nimport {login} from '../auth/login/login.js'\nimport {detectAvailableEditors} from '../mcp/detectAvailableEditors.js'\nimport {setupMCP} from '../mcp/setupMCP.js'\nimport {setupSkills} from '../skills/setupSkills.js'\nimport {checkNextJsReactCompatibility} from './checkNextJsReactCompatibility.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {createOrAppendEnvVars} from './env/createOrAppendEnvVars.js'\nimport {initApp} from './initApp.js'\nimport {InitError} from './initError.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {initNextJs} from './initNextJs.js'\nimport {initStudio} from './initStudio.js'\nimport {getPlan} from './plan/getPlan.js'\nimport {createProjectFromName} from './project/createProjectFromName.js'\nimport {getProjectDetails} from './project/getProjectDetails.js'\nimport {getProjectOutputPath} from './project/getProjectOutputPath.js'\nimport {checkIsRemoteTemplate, getGitHubRepoInfo, type RepoInfo} from './remoteTemplate.js'\nimport {type InitContext, type InitOptions} from './types.js'\n\nconst debug = subdebug('init')\n\nexport async function initAction(options: InitOptions, context: InitContext): Promise<void> {\n const {output, workDir} = context\n\n if (options.argType) {\n throw new InitError(\n options.argType === 'plugin'\n ? 'Initializing plugins through the CLI is no longer supported'\n : `Unknown init type \"${options.argType}\"`,\n 1,\n )\n }\n\n const trace = context.telemetry.trace(CLIInitStepCompleted)\n\n if (options.reconfigure) {\n throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1)\n }\n\n if (options.project && options.organization) {\n throw new InitError(\n 'You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage',\n 1,\n )\n }\n\n const defaultConfig = options.datasetDefault\n let showDefaultConfigPrompt = !defaultConfig\n if (options.dataset || options.visibility || options.datasetDefault || options.unattended) {\n showDefaultConfigPrompt = false\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n const isNextJs = detectedFramework?.slug === 'nextjs'\n\n let remoteTemplateInfo: RepoInfo | undefined\n if (options.template && checkIsRemoteTemplate(options.template)) {\n remoteTemplateInfo = await getGitHubRepoInfo(options.template, options.templateToken)\n }\n\n if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {\n throw new InitError(\n `A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`,\n 1,\n )\n }\n\n const isAppTemplate = options.template ? determineAppTemplate(options.template) : false\n\n if (options.unattended) {\n checkFlagsInUnattendedMode(options, {isAppTemplate, isNextJs})\n }\n\n trace.start()\n trace.log({\n flags: {\n bare: options.bare,\n coupon: options.coupon,\n defaultConfig,\n env: options.env,\n git: typeof options.git === 'string' ? options.git : undefined,\n plan: options.projectPlan,\n reconfigure: options.reconfigure,\n unattended: options.unattended,\n },\n step: 'start',\n })\n\n const planId = await getPlan(options, output, trace)\n\n let envFilenameDefault = '.env'\n if (detectedFramework && detectedFramework.slug === 'nextjs') {\n envFilenameDefault = '.env.local'\n }\n const envFilename = typeof options.env === 'string' ? options.env : envFilenameDefault\n\n const {user} = await ensureAuthenticated(options, output, trace)\n if (!isAppTemplate) {\n output.log(`${logSymbols.success} Fetching existing projects`)\n output.log('')\n }\n\n let newProject: string | undefined\n if (options.projectName) {\n newProject = await createProjectFromName({\n coupon: options.coupon,\n createProjectName: options.projectName,\n dataset: options.dataset,\n organization: options.organization,\n planId,\n user,\n visibility: options.visibility,\n })\n }\n\n const {datasetName, displayName, isFirstProject, organizationId, projectId} =\n await getProjectDetails({\n coupon: options.coupon,\n dataset: options.dataset,\n datasetDefault: options.datasetDefault,\n isAppTemplate,\n newProject,\n organization: options.organization,\n output,\n planId,\n project: options.project,\n showDefaultConfigPrompt,\n trace,\n unattended: options.unattended,\n user,\n visibility: options.visibility,\n })\n\n if (options.bare) {\n output.log(`${logSymbols.success} Below are your project details`)\n output.log('')\n output.log(`Project ID: ${styleText('cyan', projectId)}`)\n output.log(`Dataset: ${styleText('cyan', datasetName)}`)\n output.log(\n `\\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\\n`,\n )\n trace.complete()\n return\n }\n\n // Detect editors once, then share the result with MCP and skills setup so\n // we don't pay the detection cost (filesystem probes + CLI execa calls) twice.\n const detectedEditors =\n options.mcpMode === 'skip' && options.skillsMode === 'skip'\n ? []\n : await detectAvailableEditors()\n\n const mcpResult = await setupMCP({\n editors: detectedEditors,\n mode: options.mcpMode,\n output,\n skillsMode: options.skillsMode,\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n skipped: mcpResult.skipped,\n step: 'mcpSetup',\n })\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n }\n const mcpConfigured = mcpResult.configuredEditors\n\n async function installSkills(): Promise<void> {\n if (mcpResult.skillsToInstall.length === 0) return\n try {\n const skillsResult = await setupSkills({agents: mcpResult.skillsToInstall, output})\n trace.log({\n installedAgents: skillsResult.installedAgents,\n skipped: skillsResult.skipped,\n step: 'skillsSetup',\n })\n if (skillsResult.error) {\n trace.error(skillsResult.error)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n debug('Unexpected error from setupSkills %O', err)\n output.warn(`Could not install Sanity agent skills: ${err.message}`)\n trace.error(err)\n }\n }\n\n // Install skills right after the MCP/skills prompt so the progress + result\n // surface in sequence, rather than trailing the studio \"Success!\" output.\n await installSkills()\n\n const {alreadyConfiguredEditors} = mcpResult\n if (alreadyConfiguredEditors.length > 0) {\n const label =\n alreadyConfiguredEditors.length === 1\n ? `${alreadyConfiguredEditors[0]} already configured for Sanity MCP`\n : `${alreadyConfiguredEditors.length} editors already configured for Sanity MCP`\n spinner(label).start().succeed()\n }\n\n let initNext = flagOrDefault(options.nextjsAddConfigFiles, false)\n if (isNextJs && shouldPrompt(options.unattended, options.nextjsAddConfigFiles)) {\n initNext = await promptForConfigFiles()\n }\n\n trace.log({\n detectedFramework: detectedFramework?.name,\n selectedOption: initNext ? 'yes' : 'no',\n step: 'useDetectedFramework',\n })\n\n const sluggedName = deburr(displayName.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n const initFramework = initNext\n\n const defaults = await getProjectDefaults({isPlugin: false, workDir})\n\n const outputPath = await getProjectOutputPath({\n initFramework,\n outputPath: options.outputPath,\n sluggedName,\n unattended: options.unattended,\n useEnv: Boolean(options.env),\n workDir,\n })\n\n if (isNextJs) {\n await checkNextJsReactCompatibility({\n detectedFramework,\n output,\n outputPath,\n })\n }\n\n if (initNext) {\n await initNextJs({\n datasetName,\n detectedFramework,\n envFilename,\n mcpConfigured,\n options,\n output,\n projectId,\n trace,\n workDir,\n })\n trace.complete()\n return\n }\n\n if (options.env) {\n await createOrAppendEnvVars({\n envVars: {\n DATASET: datasetName,\n PROJECT_ID: projectId,\n },\n filename: envFilename,\n framework: detectedFramework,\n log: false,\n output,\n outputPath,\n })\n await writeStagingEnvIfNeeded(output, outputPath)\n trace.complete()\n return\n }\n\n // Workbench is opt-in (no prompt): the flag swaps the scaffolded\n // `sanity.cli.*` over to `unstable_defineApp` — the branded app is the sole\n // workbench opt-in.\n const workbench = flagOrDefault(options.unstableWorkbench, false)\n\n const sharedParams = {\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n }\n\n await (isAppTemplate\n ? initApp({...sharedParams, datasetName, projectId})\n : initStudio({\n ...sharedParams,\n datasetName,\n displayName,\n isFirstProject,\n projectId,\n }))\n\n trace.complete()\n}\n\nfunction checkFlagsInUnattendedMode(\n options: InitOptions,\n {isAppTemplate, isNextJs}: {isAppTemplate: boolean; isNextJs: boolean},\n): void {\n debug('Unattended mode, validating required options')\n\n if (options.projectName && !options.organization) {\n throw new InitError('`--project-name` requires `--organization <id>` in unattended mode', 1)\n }\n\n if (isAppTemplate) {\n if (!options.outputPath) {\n throw new InitError('`--output-path` must be specified in unattended mode', 1)\n }\n\n const hasProjectFlag = Boolean(options.project || options.projectName)\n\n if (!hasProjectFlag && !options.organization) {\n throw new InitError(\n 'The --organization flag is required for app templates in unattended mode. ' +\n 'Use --organization <id>, or pass --project <id> / --project-name <name>.',\n 1,\n )\n }\n\n return\n }\n\n if (!isNextJs && !options.bare && !options.outputPath) {\n throw new InitError('`--output-path` must be specified in unattended mode', 1)\n }\n\n if (!options.project && !options.projectName) {\n throw new InitError(\n '`--project <id>` or `--project-name <name>` must be specified in unattended mode',\n 1,\n )\n }\n}\n\nasync function ensureAuthenticated(\n options: InitOptions,\n output: InitContext['output'],\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>,\n): Promise<{user: SanityOrgUser}> {\n const user = await validateSession()\n\n if (user) {\n trace.log({alreadyLoggedIn: true, step: 'login'})\n output.log(\n `${logSymbols.success} You are logged in as ${user.email} using ${getProviderName(user.provider)}`,\n )\n return {user}\n }\n\n if (options.unattended) {\n throw new InitError(\n 'Must be logged in to run this command in unattended mode, run `sanity login`',\n 1,\n )\n }\n\n trace.log({step: 'login'})\n\n try {\n await login({\n output,\n telemetry: trace.newContext('login'),\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new InitError(`Login failed: ${message}`, 1)\n }\n\n const loggedInUser = await getCliUser()\n\n output.log(\n `${logSymbols.success} You are logged in as ${loggedInUser.email} using ${getProviderName(loggedInUser.provider)}`,\n )\n return {user: loggedInUser}\n}\n"],"names":["styleText","subdebug","logSymbols","spinner","frameworks","deburr","promptForConfigFiles","getCliUser","CLIInitStepCompleted","detectFrameworkRecord","getProjectDefaults","validateSession","getProviderName","login","detectAvailableEditors","setupMCP","setupSkills","checkNextJsReactCompatibility","determineAppTemplate","createOrAppendEnvVars","initApp","InitError","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","initNextJs","initStudio","getPlan","createProjectFromName","getProjectDetails","getProjectOutputPath","checkIsRemoteTemplate","getGitHubRepoInfo","debug","initAction","options","context","output","workDir","argType","trace","telemetry","reconfigure","project","organization","defaultConfig","datasetDefault","showDefaultConfigPrompt","dataset","visibility","unattended","detectedFramework","frameworkList","rootPath","isNextJs","slug","remoteTemplateInfo","template","templateToken","name","isAppTemplate","checkFlagsInUnattendedMode","start","log","flags","bare","coupon","env","git","undefined","plan","projectPlan","step","planId","envFilenameDefault","envFilename","user","ensureAuthenticated","success","newProject","projectName","createProjectName","datasetName","displayName","isFirstProject","organizationId","projectId","complete","detectedEditors","mcpMode","skillsMode","mcpResult","editors","mode","configuredEditors","skipped","error","mcpConfigured","installSkills","skillsToInstall","length","skillsResult","agents","installedAgents","err","Error","String","warn","message","alreadyConfiguredEditors","label","succeed","initNext","nextjsAddConfigFiles","selectedOption","sluggedName","toLowerCase","replaceAll","initFramework","defaults","isPlugin","outputPath","useEnv","Boolean","envVars","DATASET","PROJECT_ID","filename","framework","workbench","unstableWorkbench","sharedParams","hasProjectFlag","alreadyLoggedIn","email","provider","newContext","loggedInUser"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/initAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n exitCodes,\n type SanityOrgUser,\n subdebug,\n type TelemetryUserProperties,\n} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\nimport {type Framework, frameworks} from '@vercel/frameworks'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {promptForConfigFiles} from '../../prompts/init/nextjs.js'\nimport {getCliUser} from '../../services/user.js'\nimport {CLIInitStepCompleted, type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {formatCliErrorMessages} from '../../util/formatCliErrorMessages.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {validateSession} from '../auth/ensureAuthenticated.js'\nimport {getProviderName} from '../auth/getProviderName.js'\nimport {login} from '../auth/login/login.js'\nimport {LOGIN_REQUIRED_MESSAGE} from '../auth/login/loginInstructions.js'\nimport {detectAvailableEditors} from '../mcp/detectAvailableEditors.js'\nimport {setupMCP} from '../mcp/setupMCP.js'\nimport {setupSkills} from '../skills/setupSkills.js'\nimport {checkNextJsReactCompatibility} from './checkNextJsReactCompatibility.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {createOrAppendEnvVars} from './env/createOrAppendEnvVars.js'\nimport {initApp} from './initApp.js'\nimport {InitError} from './initError.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {initNextJs} from './initNextJs.js'\nimport {initStudio} from './initStudio.js'\nimport {getPlan} from './plan/getPlan.js'\nimport {createProjectFromName} from './project/createProjectFromName.js'\nimport {getProjectDetails} from './project/getProjectDetails.js'\nimport {getProjectOutputPath} from './project/getProjectOutputPath.js'\nimport {checkIsRemoteTemplate, getGitHubRepoInfo, type RepoInfo} from './remoteTemplate.js'\nimport {type InitContext, type InitOptions} from './types.js'\n\nconst debug = subdebug('init')\n\nexport async function initAction(options: InitOptions, context: InitContext): Promise<void> {\n const {output, workDir} = context\n\n if (options.argType) {\n throw new InitError(\n options.argType === 'plugin'\n ? 'Initializing plugins through the CLI is no longer supported'\n : `Unknown init type \"${options.argType}\"`,\n 1,\n )\n }\n\n const trace = context.telemetry.trace(CLIInitStepCompleted)\n\n if (options.reconfigure) {\n throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1)\n }\n\n if (options.project && options.organization) {\n throw new InitError(\n 'You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage',\n 1,\n )\n }\n\n const defaultConfig = options.datasetDefault\n let showDefaultConfigPrompt = !defaultConfig\n if (options.dataset || options.visibility || options.datasetDefault || options.unattended) {\n showDefaultConfigPrompt = false\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n const isNextJs = detectedFramework?.slug === 'nextjs'\n\n let remoteTemplateInfo: RepoInfo | undefined\n if (options.template && checkIsRemoteTemplate(options.template)) {\n remoteTemplateInfo = await getGitHubRepoInfo(options.template, options.templateToken)\n }\n\n if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {\n throw new InitError(\n `A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`,\n 1,\n )\n }\n\n const isAppTemplate = options.template ? determineAppTemplate(options.template) : false\n\n if (options.unattended) {\n checkFlagsInUnattendedMode(options, {isAppTemplate, isNextJs})\n }\n\n trace.start()\n trace.log({\n flags: {\n bare: options.bare,\n coupon: options.coupon,\n defaultConfig,\n env: options.env,\n git: typeof options.git === 'string' ? options.git : undefined,\n plan: options.projectPlan,\n reconfigure: options.reconfigure,\n unattended: options.unattended,\n },\n step: 'start',\n })\n\n const planId = await getPlan(options, output, trace)\n\n let envFilenameDefault = '.env'\n if (detectedFramework && detectedFramework.slug === 'nextjs') {\n envFilenameDefault = '.env.local'\n }\n const envFilename = typeof options.env === 'string' ? options.env : envFilenameDefault\n\n const {user} = await ensureAuthenticated(options, output, trace)\n if (!isAppTemplate) {\n output.log(`${logSymbols.success} Fetching existing projects`)\n output.log('')\n }\n\n let newProject: string | undefined\n if (options.projectName) {\n newProject = await createProjectFromName({\n coupon: options.coupon,\n createProjectName: options.projectName,\n dataset: options.dataset,\n organization: options.organization,\n planId,\n user,\n visibility: options.visibility,\n })\n }\n\n const {datasetName, displayName, isFirstProject, organizationId, projectId} =\n await getProjectDetails({\n coupon: options.coupon,\n dataset: options.dataset,\n datasetDefault: options.datasetDefault,\n isAppTemplate,\n newProject,\n organization: options.organization,\n output,\n planId,\n project: options.project,\n showDefaultConfigPrompt,\n trace,\n unattended: options.unattended,\n user,\n visibility: options.visibility,\n })\n\n if (options.bare) {\n output.log(`${logSymbols.success} Below are your project details`)\n output.log('')\n output.log(`Project ID: ${styleText('cyan', projectId)}`)\n output.log(`Dataset: ${styleText('cyan', datasetName)}`)\n output.log(\n `\\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\\n`,\n )\n trace.complete()\n return\n }\n\n // Detect editors once, then share the result with MCP and skills setup so\n // we don't pay the detection cost (filesystem probes + CLI execa calls) twice.\n const detectedEditors =\n options.mcpMode === 'skip' && options.skillsMode === 'skip'\n ? []\n : await detectAvailableEditors()\n\n const mcpResult = await setupMCP({\n editors: detectedEditors,\n mode: options.mcpMode,\n output,\n skillsMode: options.skillsMode,\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n skipped: mcpResult.skipped,\n step: 'mcpSetup',\n })\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n }\n const mcpConfigured = mcpResult.configuredEditors\n\n async function installSkills(): Promise<void> {\n if (mcpResult.skillsToInstall.length === 0) return\n try {\n const skillsResult = await setupSkills({\n agents: mcpResult.skillsToInstall,\n output,\n })\n trace.log({\n installedAgents: skillsResult.installedAgents,\n skipped: skillsResult.skipped,\n step: 'skillsSetup',\n })\n if (skillsResult.error) {\n trace.error(skillsResult.error)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n debug('Unexpected error from setupSkills %O', err)\n output.warn(`Could not install Sanity agent skills: ${err.message}`)\n trace.error(err)\n }\n }\n\n // Install skills right after the MCP/skills prompt so the progress + result\n // surface in sequence, rather than trailing the studio \"Success!\" output.\n await installSkills()\n\n const {alreadyConfiguredEditors} = mcpResult\n if (alreadyConfiguredEditors.length > 0) {\n const label =\n alreadyConfiguredEditors.length === 1\n ? `${alreadyConfiguredEditors[0]} already configured for Sanity MCP`\n : `${alreadyConfiguredEditors.length} editors already configured for Sanity MCP`\n spinner(label).start().succeed()\n }\n\n let initNext = flagOrDefault(options.nextjsAddConfigFiles, false)\n if (isNextJs && shouldPrompt(options.unattended, options.nextjsAddConfigFiles)) {\n initNext = await promptForConfigFiles()\n }\n\n trace.log({\n detectedFramework: detectedFramework?.name,\n selectedOption: initNext ? 'yes' : 'no',\n step: 'useDetectedFramework',\n })\n\n const sluggedName = deburr(displayName.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n const initFramework = initNext\n\n const defaults = await getProjectDefaults({isPlugin: false, workDir})\n\n const outputPath = await getProjectOutputPath({\n initFramework,\n outputPath: options.outputPath,\n sluggedName,\n unattended: options.unattended,\n useEnv: Boolean(options.env),\n workDir,\n })\n\n if (isNextJs) {\n await checkNextJsReactCompatibility({\n detectedFramework,\n output,\n outputPath,\n })\n }\n\n if (initNext) {\n await initNextJs({\n datasetName,\n detectedFramework,\n envFilename,\n mcpConfigured,\n options,\n output,\n projectId,\n trace,\n workDir,\n })\n trace.complete()\n return\n }\n\n if (options.env) {\n await createOrAppendEnvVars({\n envVars: {\n DATASET: datasetName,\n PROJECT_ID: projectId,\n },\n filename: envFilename,\n framework: detectedFramework,\n log: false,\n output,\n outputPath,\n })\n await writeStagingEnvIfNeeded(output, outputPath)\n trace.complete()\n return\n }\n\n // Workbench is opt-in (no prompt): the flag swaps the scaffolded\n // `sanity.cli.*` over to `unstable_defineApp` — the branded app is the sole\n // workbench opt-in.\n const workbench = flagOrDefault(options.unstableWorkbench, false)\n\n const sharedParams = {\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n }\n\n await (isAppTemplate\n ? initApp({...sharedParams, datasetName, projectId})\n : initStudio({\n ...sharedParams,\n datasetName,\n displayName,\n isFirstProject,\n projectId,\n }))\n\n trace.complete()\n}\n\nfunction checkFlagsInUnattendedMode(\n options: InitOptions,\n {isAppTemplate, isNextJs}: {isAppTemplate: boolean; isNextJs: boolean},\n): void {\n debug('Unattended mode, validating required options')\n\n const errors: string[] = []\n\n if (isAppTemplate) {\n if (!options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (options.projectName && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n } else if (!options.project && !options.organization) {\n errors.push(\n 'Project or organization is required for app templates in unattended mode. ' +\n 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' +\n '`--project-name <name>` with `--organization <id>`.',\n )\n }\n } else {\n if (!isNextJs && !options.bare && !options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (!options.project && !options.projectName) {\n errors.push(\n 'Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.',\n )\n }\n\n if (!options.project && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n }\n }\n\n if (errors.length > 0) {\n throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR)\n }\n}\n\nasync function ensureAuthenticated(\n options: InitOptions,\n output: InitContext['output'],\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>,\n): Promise<{user: SanityOrgUser}> {\n const user = await validateSession()\n\n if (user) {\n trace.log({alreadyLoggedIn: true, step: 'login'})\n output.log(\n `${logSymbols.success} You are logged in as ${user.email} using ${getProviderName(user.provider)}`,\n )\n return {user}\n }\n\n if (options.unattended) {\n throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR)\n }\n\n trace.log({step: 'login'})\n output.warn(LOGIN_REQUIRED_MESSAGE)\n\n try {\n await login({\n output,\n telemetry: trace.newContext('login'),\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new InitError(`Login failed: ${message}`, 1)\n }\n\n const loggedInUser = await getCliUser()\n\n output.log(\n `${logSymbols.success} You are logged in as ${loggedInUser.email} using ${getProviderName(loggedInUser.provider)}`,\n )\n return {user: loggedInUser}\n}\n"],"names":["styleText","exitCodes","subdebug","logSymbols","spinner","frameworks","deburr","promptForConfigFiles","getCliUser","CLIInitStepCompleted","detectFrameworkRecord","formatCliErrorMessages","getProjectDefaults","validateSession","getProviderName","login","LOGIN_REQUIRED_MESSAGE","detectAvailableEditors","setupMCP","setupSkills","checkNextJsReactCompatibility","determineAppTemplate","createOrAppendEnvVars","initApp","InitError","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","initNextJs","initStudio","getPlan","createProjectFromName","getProjectDetails","getProjectOutputPath","checkIsRemoteTemplate","getGitHubRepoInfo","debug","initAction","options","context","output","workDir","argType","trace","telemetry","reconfigure","project","organization","defaultConfig","datasetDefault","showDefaultConfigPrompt","dataset","visibility","unattended","detectedFramework","frameworkList","rootPath","isNextJs","slug","remoteTemplateInfo","template","templateToken","name","isAppTemplate","checkFlagsInUnattendedMode","start","log","flags","bare","coupon","env","git","undefined","plan","projectPlan","step","planId","envFilenameDefault","envFilename","user","ensureAuthenticated","success","newProject","projectName","createProjectName","datasetName","displayName","isFirstProject","organizationId","projectId","complete","detectedEditors","mcpMode","skillsMode","mcpResult","editors","mode","configuredEditors","skipped","error","mcpConfigured","installSkills","skillsToInstall","length","skillsResult","agents","installedAgents","err","Error","String","warn","message","alreadyConfiguredEditors","label","succeed","initNext","nextjsAddConfigFiles","selectedOption","sluggedName","toLowerCase","replaceAll","initFramework","defaults","isPlugin","outputPath","useEnv","Boolean","envVars","DATASET","PROJECT_ID","filename","framework","workbench","unstableWorkbench","sharedParams","errors","push","USAGE_ERROR","alreadyLoggedIn","email","provider","RUNTIME_ERROR","newContext","loggedInUser"],"mappings":"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"}
|
|
@@ -31,13 +31,15 @@ const sanitizeIconPath = new URL('sanitizeIcon.js', import.meta.url).href;
|
|
|
31
31
|
return mod.sanitizeIcon;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* Resolves app.icon from config (a file path) to
|
|
35
|
-
*
|
|
34
|
+
* Resolves app.icon from config (a file path) to a sanitized SVG string. Used
|
|
35
|
+
* both for the manifest and, on deploy, for the icon shipped to Brett — the
|
|
36
|
+
* manifest expects the SVG inline, not a path.
|
|
36
37
|
*
|
|
37
38
|
* The file is sanitized through the same allowlist as the studio manifest's
|
|
38
39
|
* icon resolver (see {@link lazySanitizeIcon}) so both manifest paths inline the
|
|
39
40
|
* same trusted subset of SVG markup.
|
|
40
|
-
|
|
41
|
+
* @internal
|
|
42
|
+
*/ export async function readIconFromPath(workDir, iconPath) {
|
|
41
43
|
const resolvedPath = resolve(workDir, iconPath);
|
|
42
44
|
const pathRelativeToWorkDir = relative(workDir, resolvedPath);
|
|
43
45
|
if (pathRelativeToWorkDir.startsWith('..')) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/manifest/extractCoreAppManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {relative, resolve} from 'node:path'\n\nimport {doImport, getCliConfigUncached} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {type sanitizeIcon as sanitizeIconFn} from './sanitizeIcon.js'\nimport {type CoreAppManifest, coreAppManifestSchema} from './types.js'\n\ninterface ExtractCoreAppManifestOptions {\n workDir: string\n}\n\n/**\n * The title change a deploy would sync from the manifest to the user\n * application, or null when the titles already match (or none is set).\n *\n * @internal\n */\nexport function resolveTitleUpdate(\n manifest: CoreAppManifest | undefined,\n application: {title: string | null},\n): {from: string | null; to: string} | null {\n if (manifest?.title === undefined || manifest.title === application.title) {\n return null\n }\n return {from: application.title, to: manifest.title}\n}\n\nconst sanitizeIconPath = new URL('sanitizeIcon.js', import.meta.url).href\n\n/**\n * Lazy-load {@link sanitizeIconFn} so `isomorphic-dompurify` (and its jsdom\n * dependency) stays out of the CLI's eager import graph. The studio manifest\n * resolver lazy-loads its icon machinery for the same reason; this path runs in\n * the main process (not the manifest worker), so only an app deploy that\n * actually has an icon pays the cost.\n */\nasync function lazySanitizeIcon(): Promise<typeof sanitizeIconFn> {\n const mod = await doImport(sanitizeIconPath)\n return mod.sanitizeIcon\n}\n\n/**\n * Resolves app.icon from config (a file path) to
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/manifest/extractCoreAppManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {relative, resolve} from 'node:path'\n\nimport {doImport, getCliConfigUncached} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {type sanitizeIcon as sanitizeIconFn} from './sanitizeIcon.js'\nimport {type CoreAppManifest, coreAppManifestSchema} from './types.js'\n\ninterface ExtractCoreAppManifestOptions {\n workDir: string\n}\n\n/**\n * The title change a deploy would sync from the manifest to the user\n * application, or null when the titles already match (or none is set).\n *\n * @internal\n */\nexport function resolveTitleUpdate(\n manifest: CoreAppManifest | undefined,\n application: {title: string | null},\n): {from: string | null; to: string} | null {\n if (manifest?.title === undefined || manifest.title === application.title) {\n return null\n }\n return {from: application.title, to: manifest.title}\n}\n\nconst sanitizeIconPath = new URL('sanitizeIcon.js', import.meta.url).href\n\n/**\n * Lazy-load {@link sanitizeIconFn} so `isomorphic-dompurify` (and its jsdom\n * dependency) stays out of the CLI's eager import graph. The studio manifest\n * resolver lazy-loads its icon machinery for the same reason; this path runs in\n * the main process (not the manifest worker), so only an app deploy that\n * actually has an icon pays the cost.\n */\nasync function lazySanitizeIcon(): Promise<typeof sanitizeIconFn> {\n const mod = await doImport(sanitizeIconPath)\n return mod.sanitizeIcon\n}\n\n/**\n * Resolves app.icon from config (a file path) to a sanitized SVG string. Used\n * both for the manifest and, on deploy, for the icon shipped to Brett — the\n * manifest expects the SVG inline, not a path.\n *\n * The file is sanitized through the same allowlist as the studio manifest's\n * icon resolver (see {@link lazySanitizeIcon}) so both manifest paths inline the\n * same trusted subset of SVG markup.\n * @internal\n */\nexport async function readIconFromPath(workDir: string, iconPath: string): Promise<string> {\n const resolvedPath = resolve(workDir, iconPath)\n const pathRelativeToWorkDir = relative(workDir, resolvedPath)\n if (pathRelativeToWorkDir.startsWith('..')) {\n throw new Error(\n `Icon path \"${iconPath}\" resolves outside the project directory and is not allowed.`,\n )\n }\n\n let content: string\n try {\n content = await readFile(resolvedPath, 'utf8')\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Could not read icon file at \"${iconPath}\" (resolved: ${resolvedPath}): ${message}`,\n {cause: err},\n )\n }\n\n const trimmed = content.trim()\n if (!/<svg[\\s>]/i.test(trimmed)) {\n throw new Error(\n `Icon file at \"${iconPath}\" does not contain an SVG element. App manifest icons must be SVG files.`,\n )\n }\n\n const sanitizeIcon = await lazySanitizeIcon()\n return sanitizeIcon(trimmed)\n}\n\n/**\n * Unlike studio manifest extraction, skips schema/tool parsing. The config's\n * `app.icon` is a file path; its content is read and inlined in the manifest.\n */\nexport async function extractCoreAppManifest(\n options: ExtractCoreAppManifestOptions,\n): Promise<CoreAppManifest | undefined> {\n const {workDir} = options\n const {app} = await getCliConfigUncached(workDir)\n if (!app) {\n return undefined\n }\n\n const spin = spinner('Extracting manifest').start()\n\n try {\n let icon: string | undefined\n if (app.icon) {\n icon = await readIconFromPath(workDir, app.icon)\n }\n\n if (!icon && !app.title) {\n spin.info('Manifest creation skipped: no icon or title found in app configuration')\n return undefined\n }\n\n const slug = isWorkbenchApp(app) ? app.slug : undefined\n\n const manifest: CoreAppManifest = coreAppManifestSchema.parse({\n version: '1',\n ...(icon ? {icon} : {}),\n ...(app.title ? {title: app.title} : {}),\n ...(app.group ? {group: app.group} : {}),\n ...(app.priority === undefined ? {} : {priority: app.priority}),\n ...(slug ? {slug} : {}),\n })\n\n spin.succeed(`Extracted manifest`)\n\n return manifest\n } catch (err) {\n const message = getErrorMessage(err)\n spin.fail(message)\n throw err\n }\n}\n"],"names":["readFile","relative","resolve","doImport","getCliConfigUncached","getErrorMessage","spinner","isWorkbenchApp","coreAppManifestSchema","resolveTitleUpdate","manifest","application","title","undefined","from","to","sanitizeIconPath","URL","url","href","lazySanitizeIcon","mod","sanitizeIcon","readIconFromPath","workDir","iconPath","resolvedPath","pathRelativeToWorkDir","startsWith","Error","content","err","message","String","cause","trimmed","trim","test","extractCoreAppManifest","options","app","spin","start","icon","info","slug","parse","version","group","priority","succeed","fail"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AACzC,SAAQC,QAAQ,EAAEC,OAAO,QAAO,YAAW;AAE3C,SAAQC,QAAQ,EAAEC,oBAAoB,QAAO,mBAAkB;AAC/D,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,cAAc,QAAO,wBAAuB;AAGpD,SAA8BC,qBAAqB,QAAO,aAAY;AAMtE;;;;;CAKC,GACD,OAAO,SAASC,mBACdC,QAAqC,EACrCC,WAAmC;IAEnC,IAAID,UAAUE,UAAUC,aAAaH,SAASE,KAAK,KAAKD,YAAYC,KAAK,EAAE;QACzE,OAAO;IACT;IACA,OAAO;QAACE,MAAMH,YAAYC,KAAK;QAAEG,IAAIL,SAASE,KAAK;IAAA;AACrD;AAEA,MAAMI,mBAAmB,IAAIC,IAAI,mBAAmB,YAAYC,GAAG,EAAEC,IAAI;AAEzE;;;;;;CAMC,GACD,eAAeC;IACb,MAAMC,MAAM,MAAMlB,SAASa;IAC3B,OAAOK,IAAIC,YAAY;AACzB;AAEA;;;;;;;;;CASC,GACD,OAAO,eAAeC,iBAAiBC,OAAe,EAAEC,QAAgB;IACtE,MAAMC,eAAexB,QAAQsB,SAASC;IACtC,MAAME,wBAAwB1B,SAASuB,SAASE;IAChD,IAAIC,sBAAsBC,UAAU,CAAC,OAAO;QAC1C,MAAM,IAAIC,MACR,CAAC,WAAW,EAAEJ,SAAS,4DAA4D,CAAC;IAExF;IAEA,IAAIK;IACJ,IAAI;QACFA,UAAU,MAAM9B,SAAS0B,cAAc;IACzC,EAAE,OAAOK,KAAK;QACZ,MAAMC,UAAUD,eAAeF,QAAQE,IAAIC,OAAO,GAAGC,OAAOF;QAC5D,MAAM,IAAIF,MACR,CAAC,6BAA6B,EAAEJ,SAAS,aAAa,EAAEC,aAAa,GAAG,EAAEM,SAAS,EACnF;YAACE,OAAOH;QAAG;IAEf;IAEA,MAAMI,UAAUL,QAAQM,IAAI;IAC5B,IAAI,CAAC,aAAaC,IAAI,CAACF,UAAU;QAC/B,MAAM,IAAIN,MACR,CAAC,cAAc,EAAEJ,SAAS,wEAAwE,CAAC;IAEvG;IAEA,MAAMH,eAAe,MAAMF;IAC3B,OAAOE,aAAaa;AACtB;AAEA;;;CAGC,GACD,OAAO,eAAeG,uBACpBC,OAAsC;IAEtC,MAAM,EAACf,OAAO,EAAC,GAAGe;IAClB,MAAM,EAACC,GAAG,EAAC,GAAG,MAAMpC,qBAAqBoB;IACzC,IAAI,CAACgB,KAAK;QACR,OAAO3B;IACT;IAEA,MAAM4B,OAAOnC,QAAQ,uBAAuBoC,KAAK;IAEjD,IAAI;QACF,IAAIC;QACJ,IAAIH,IAAIG,IAAI,EAAE;YACZA,OAAO,MAAMpB,iBAAiBC,SAASgB,IAAIG,IAAI;QACjD;QAEA,IAAI,CAACA,QAAQ,CAACH,IAAI5B,KAAK,EAAE;YACvB6B,KAAKG,IAAI,CAAC;YACV,OAAO/B;QACT;QAEA,MAAMgC,OAAOtC,eAAeiC,OAAOA,IAAIK,IAAI,GAAGhC;QAE9C,MAAMH,WAA4BF,sBAAsBsC,KAAK,CAAC;YAC5DC,SAAS;YACT,GAAIJ,OAAO;gBAACA;YAAI,IAAI,CAAC,CAAC;YACtB,GAAIH,IAAI5B,KAAK,GAAG;gBAACA,OAAO4B,IAAI5B,KAAK;YAAA,IAAI,CAAC,CAAC;YACvC,GAAI4B,IAAIQ,KAAK,GAAG;gBAACA,OAAOR,IAAIQ,KAAK;YAAA,IAAI,CAAC,CAAC;YACvC,GAAIR,IAAIS,QAAQ,KAAKpC,YAAY,CAAC,IAAI;gBAACoC,UAAUT,IAAIS,QAAQ;YAAA,CAAC;YAC9D,GAAIJ,OAAO;gBAACA;YAAI,IAAI,CAAC,CAAC;QACxB;QAEAJ,KAAKS,OAAO,CAAC,CAAC,kBAAkB,CAAC;QAEjC,OAAOxC;IACT,EAAE,OAAOqB,KAAK;QACZ,MAAMC,UAAU3B,gBAAgB0B;QAChCU,KAAKU,IAAI,CAACnB;QACV,MAAMD;IACR;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/migration/constants.ts"],"sourcesContent":["export const MIGRATIONS_DIRECTORY = 'migrations'\nexport const MIGRATION_SCRIPT_EXTENSIONS = ['mjs', 'js', 'ts', 'cjs']\nexport const DEFAULT_API_VERSION = 'v2024-01-29'\n"],"names":["MIGRATIONS_DIRECTORY","MIGRATION_SCRIPT_EXTENSIONS","DEFAULT_API_VERSION"],"mappings":"AAAA,OAAO,MAAMA,uBAAuB,aAAY;AAChD,OAAO,MAAMC,8BAA8B;IAAC;IAAO;IAAM;IAAM;CAAM,CAAA;AACrE,OAAO,MAAMC,sBAAsB,cAAa"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const VERSION_PATTERN = /^v\d+-\d+-\d+$|^vX$/ // Matches version strings like vYYYY-MM-DD or vX
|
|
2
|
+
;
|
|
3
|
+
/**
|
|
4
|
+
* Ensures that the provided API version string is in the correct format.
|
|
5
|
+
* If the version does not start with 'v', it will be prefixed with 'v'.
|
|
6
|
+
* If the version does not match the expected pattern, an error will be thrown.
|
|
7
|
+
*/ export function ensureApiVersionFormat(version) {
|
|
8
|
+
const normalizedVersion = version.startsWith('v') ? version : `v${version}`;
|
|
9
|
+
// Check if the version matches the expected pattern
|
|
10
|
+
if (!VERSION_PATTERN.test(normalizedVersion)) {
|
|
11
|
+
throw new Error(`Invalid API version format: ${normalizedVersion}. Expected format: vYYYY-MM-DD or vX`);
|
|
12
|
+
}
|
|
13
|
+
return normalizedVersion;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=ensureApiVersionFormat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/migration/ensureApiVersionFormat.ts"],"sourcesContent":["import {type APIConfig} from '@sanity/migrate'\n\ntype ApiVersion = APIConfig['apiVersion']\n\nconst VERSION_PATTERN = /^v\\d+-\\d+-\\d+$|^vX$/ // Matches version strings like vYYYY-MM-DD or vX\n\n/**\n * Ensures that the provided API version string is in the correct format.\n * If the version does not start with 'v', it will be prefixed with 'v'.\n * If the version does not match the expected pattern, an error will be thrown.\n */\nexport function ensureApiVersionFormat(version: string): ApiVersion {\n const normalizedVersion = version.startsWith('v') ? version : `v${version}`\n\n // Check if the version matches the expected pattern\n if (!VERSION_PATTERN.test(normalizedVersion)) {\n throw new Error(\n `Invalid API version format: ${normalizedVersion}. Expected format: vYYYY-MM-DD or vX`,\n )\n }\n\n return normalizedVersion as ApiVersion\n}\n"],"names":["VERSION_PATTERN","ensureApiVersionFormat","version","normalizedVersion","startsWith","test","Error"],"mappings":"AAIA,MAAMA,kBAAkB,sBAAsB,iDAAiD;;AAE/F;;;;CAIC,GACD,OAAO,SAASC,uBAAuBC,OAAe;IACpD,MAAMC,oBAAoBD,QAAQE,UAAU,CAAC,OAAOF,UAAU,CAAC,CAAC,EAAEA,SAAS;IAE3E,oDAAoD;IACpD,IAAI,CAACF,gBAAgBK,IAAI,CAACF,oBAAoB;QAC5C,MAAM,IAAIG,MACR,CAAC,4BAA4B,EAAEH,kBAAkB,oCAAoC,CAAC;IAE1F;IAEA,OAAOA;AACT"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a file exists and can be "accessed".
|
|
4
|
+
* Prone to race conditions, but good enough for our use cases.
|
|
5
|
+
*
|
|
6
|
+
* @param filePath - The path to the file to check
|
|
7
|
+
* @returns A promise that resolves to true if the file exists, false otherwise
|
|
8
|
+
* @internal
|
|
9
|
+
*/ export function fileExists(filePath) {
|
|
10
|
+
return access(filePath).then(()=>true, ()=>false);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=fileExists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/migration/fileExists.ts"],"sourcesContent":["import {access} from 'node:fs/promises'\n\n/**\n * Checks if a file exists and can be \"accessed\".\n * Prone to race conditions, but good enough for our use cases.\n *\n * @param filePath - The path to the file to check\n * @returns A promise that resolves to true if the file exists, false otherwise\n * @internal\n */\nexport function fileExists(filePath: string): Promise<boolean> {\n return access(filePath).then(\n () => true,\n () => false,\n )\n}\n"],"names":["access","fileExists","filePath","then"],"mappings":"AAAA,SAAQA,MAAM,QAAO,mBAAkB;AAEvC;;;;;;;CAOC,GACD,OAAO,SAASC,WAAWC,QAAgB;IACzC,OAAOF,OAAOE,UAAUC,IAAI,CAC1B,IAAM,MACN,IAAM;AAEV"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { isatty } from 'node:tty';
|
|
2
|
+
import { styleText } from 'node:util';
|
|
3
|
+
import { convertToTree, formatTree, maxKeyLength } from './tree.js';
|
|
4
|
+
const isTty = isatty(1);
|
|
5
|
+
export function prettyFormat({ indentSize = 0, migration, subject }) {
|
|
6
|
+
return (Array.isArray(subject) ? subject : [
|
|
7
|
+
subject
|
|
8
|
+
]).map((subjectEntry)=>{
|
|
9
|
+
if (subjectEntry.type === 'transaction') {
|
|
10
|
+
return [
|
|
11
|
+
[
|
|
12
|
+
badge('transaction', 'info'),
|
|
13
|
+
subjectEntry.id === undefined ? null : styleText('underline', subjectEntry.id)
|
|
14
|
+
].filter(Boolean).join(' '),
|
|
15
|
+
indent(prettyFormat({
|
|
16
|
+
indentSize: indentSize,
|
|
17
|
+
migration,
|
|
18
|
+
subject: subjectEntry.mutations
|
|
19
|
+
}))
|
|
20
|
+
].join('\n\n');
|
|
21
|
+
}
|
|
22
|
+
return prettyFormatMutation({
|
|
23
|
+
indentSize,
|
|
24
|
+
migration,
|
|
25
|
+
subject: subjectEntry
|
|
26
|
+
});
|
|
27
|
+
}).join('\n\n');
|
|
28
|
+
}
|
|
29
|
+
function encodeItemRef(ref) {
|
|
30
|
+
return typeof ref === 'number' ? ref : ref._key;
|
|
31
|
+
}
|
|
32
|
+
function badgeStyle(variant, label) {
|
|
33
|
+
const styles = {
|
|
34
|
+
destructive: styleText([
|
|
35
|
+
'bgRed',
|
|
36
|
+
'black',
|
|
37
|
+
'bold'
|
|
38
|
+
], label),
|
|
39
|
+
incremental: styleText([
|
|
40
|
+
'bgGreen',
|
|
41
|
+
'black',
|
|
42
|
+
'bold'
|
|
43
|
+
], label),
|
|
44
|
+
info: styleText([
|
|
45
|
+
'bgWhite',
|
|
46
|
+
'black'
|
|
47
|
+
], label),
|
|
48
|
+
maybeDestructive: styleText([
|
|
49
|
+
'bgYellow',
|
|
50
|
+
'black',
|
|
51
|
+
'bold'
|
|
52
|
+
], label)
|
|
53
|
+
};
|
|
54
|
+
return styles[variant];
|
|
55
|
+
}
|
|
56
|
+
function badge(label, variant) {
|
|
57
|
+
if (!isTty) {
|
|
58
|
+
return `[${label}]`;
|
|
59
|
+
}
|
|
60
|
+
return badgeStyle(variant, ` ${label} `);
|
|
61
|
+
}
|
|
62
|
+
const mutationImpact = {
|
|
63
|
+
create: 'incremental',
|
|
64
|
+
createIfNotExists: 'incremental',
|
|
65
|
+
createOrReplace: 'maybeDestructive',
|
|
66
|
+
delete: 'destructive',
|
|
67
|
+
patch: 'maybeDestructive'
|
|
68
|
+
};
|
|
69
|
+
function documentId(mutation) {
|
|
70
|
+
if ('id' in mutation) {
|
|
71
|
+
return mutation.id;
|
|
72
|
+
}
|
|
73
|
+
if ('document' in mutation) {
|
|
74
|
+
return mutation.document._id;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const listFormatter = new Intl.ListFormat('en-US', {
|
|
79
|
+
type: 'disjunction'
|
|
80
|
+
});
|
|
81
|
+
function mutationHeader(mutation, migration) {
|
|
82
|
+
const mutationType = badge(mutation.type, mutationImpact[mutation.type]);
|
|
83
|
+
const documentType = 'document' in mutation || migration.documentTypes ? badge('document' in mutation ? mutation.document._type : listFormatter.format(migration.documentTypes ?? []), 'info') : null;
|
|
84
|
+
// TODO: Should we list documentType when a mutation can be yielded for any document type?
|
|
85
|
+
return [
|
|
86
|
+
mutationType,
|
|
87
|
+
documentType,
|
|
88
|
+
styleText('underline', documentId(mutation) ?? '')
|
|
89
|
+
].filter(Boolean).join(' ');
|
|
90
|
+
}
|
|
91
|
+
function prettyFormatMutation({ indentSize = 0, migration, subject }) {
|
|
92
|
+
const lock = 'options' in subject ? styleText('cyan', `(if revision==${subject.options?.ifRevision})`) : '';
|
|
93
|
+
const header = [
|
|
94
|
+
mutationHeader(subject, migration),
|
|
95
|
+
lock
|
|
96
|
+
].join(' ');
|
|
97
|
+
const padding = ' '.repeat(indentSize);
|
|
98
|
+
if (subject.type === 'create' || subject.type === 'createIfNotExists' || subject.type === 'createOrReplace') {
|
|
99
|
+
return [
|
|
100
|
+
header,
|
|
101
|
+
'\n',
|
|
102
|
+
indent(JSON.stringify(subject.document, null, 2), indentSize)
|
|
103
|
+
].join('');
|
|
104
|
+
}
|
|
105
|
+
if (subject.type === 'patch') {
|
|
106
|
+
const tree = convertToTree(subject.patches.flat());
|
|
107
|
+
const paddingLength = Math.max(maxKeyLength(tree.children) + 2, 30);
|
|
108
|
+
return [
|
|
109
|
+
header,
|
|
110
|
+
'\n',
|
|
111
|
+
formatTree({
|
|
112
|
+
getMessage: (patch)=>formatPatchMutation(patch),
|
|
113
|
+
indent: padding,
|
|
114
|
+
node: tree.children,
|
|
115
|
+
paddingLength
|
|
116
|
+
})
|
|
117
|
+
].join('');
|
|
118
|
+
}
|
|
119
|
+
return header;
|
|
120
|
+
}
|
|
121
|
+
function formatPatchMutation(patch) {
|
|
122
|
+
const { op } = patch;
|
|
123
|
+
const formattedType = styleText('bold', op.type);
|
|
124
|
+
if (op.type === 'unset') {
|
|
125
|
+
return `${styleText('red', formattedType)}()`;
|
|
126
|
+
}
|
|
127
|
+
if (op.type === 'diffMatchPatch') {
|
|
128
|
+
return `${styleText('yellow', formattedType)}(${op.value})`;
|
|
129
|
+
}
|
|
130
|
+
if (op.type === 'inc' || op.type === 'dec') {
|
|
131
|
+
return `${styleText('yellow', formattedType)}(${op.amount})`;
|
|
132
|
+
}
|
|
133
|
+
if (op.type === 'set') {
|
|
134
|
+
return `${styleText('yellow', formattedType)}(${JSON.stringify(op.value)})`;
|
|
135
|
+
}
|
|
136
|
+
if (op.type === 'setIfMissing') {
|
|
137
|
+
return `${styleText('green', formattedType)}(${JSON.stringify(op.value)})`;
|
|
138
|
+
}
|
|
139
|
+
if (op.type === 'insert') {
|
|
140
|
+
return `${styleText('green', formattedType)}(${op.position}, ${encodeItemRef(op.referenceItem)}, ${JSON.stringify(op.items)})`;
|
|
141
|
+
}
|
|
142
|
+
if (op.type === 'replace') {
|
|
143
|
+
return `${styleText('yellow', formattedType)}(${encodeItemRef(op.referenceItem)}, ${JSON.stringify(op.items)})`;
|
|
144
|
+
}
|
|
145
|
+
if (op.type === 'truncate') {
|
|
146
|
+
return `${styleText('red', formattedType)}(${op.startIndex}, ${op.endIndex})`;
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`Invalid operation type: ${op.type}`);
|
|
149
|
+
}
|
|
150
|
+
function indent(subject, size = 2) {
|
|
151
|
+
const padding = ' '.repeat(size);
|
|
152
|
+
return subject.split('\n').map((line)=>padding + line).join('\n');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=prettyMutationFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/migration/prettyMutationFormatter.ts"],"sourcesContent":["import {isatty} from 'node:tty'\nimport {styleText} from 'node:util'\n\nimport {type Migration, type Mutation, type NodePatch, type Transaction} from '@sanity/migrate'\nimport {type KeyedSegment} from '@sanity/types'\n\nimport {convertToTree, formatTree, maxKeyLength} from './tree.js'\n\ntype ItemRef = number | string\ntype Impact = 'destructive' | 'incremental' | 'maybeDestructive'\ntype Variant = 'info' | Impact\n\nconst isTty = isatty(1)\n\ninterface FormatterOptions<Subject> {\n migration: Migration\n subject: Subject\n\n indentSize?: number\n}\n\nexport function prettyFormat({\n indentSize = 0,\n migration,\n subject,\n}: FormatterOptions<(Mutation | Transaction)[] | Mutation | Transaction>): string {\n return (Array.isArray(subject) ? subject : [subject])\n .map((subjectEntry) => {\n if (subjectEntry.type === 'transaction') {\n return [\n [\n badge('transaction', 'info'),\n subjectEntry.id === undefined ? null : styleText('underline', subjectEntry.id),\n ]\n .filter(Boolean)\n .join(' '),\n indent(\n prettyFormat({\n indentSize: indentSize,\n migration,\n subject: subjectEntry.mutations,\n }),\n ),\n ].join('\\n\\n')\n }\n return prettyFormatMutation({\n indentSize,\n migration,\n subject: subjectEntry,\n })\n })\n .join('\\n\\n')\n}\n\nfunction encodeItemRef(ref: KeyedSegment | number): ItemRef {\n return typeof ref === 'number' ? ref : ref._key\n}\n\nfunction badgeStyle(variant: Variant, label: string) {\n const styles: Record<Variant, string> = {\n destructive: styleText(['bgRed', 'black', 'bold'], label),\n incremental: styleText(['bgGreen', 'black', 'bold'], label),\n info: styleText(['bgWhite', 'black'], label),\n maybeDestructive: styleText(['bgYellow', 'black', 'bold'], label),\n }\n\n return styles[variant]\n}\n\nfunction badge(label: string, variant: Variant): string {\n if (!isTty) {\n return `[${label}]`\n }\n\n return badgeStyle(variant, ` ${label} `)\n}\n\nconst mutationImpact: Record<Mutation['type'], Impact> = {\n create: 'incremental',\n createIfNotExists: 'incremental',\n createOrReplace: 'maybeDestructive',\n delete: 'destructive',\n patch: 'maybeDestructive',\n}\n\nfunction documentId(mutation: Mutation): string | undefined {\n if ('id' in mutation) {\n return mutation.id\n }\n\n if ('document' in mutation) {\n return mutation.document._id\n }\n\n return undefined\n}\n\nconst listFormatter = new Intl.ListFormat('en-US', {\n type: 'disjunction',\n})\n\nfunction mutationHeader(mutation: Mutation, migration: Migration): string {\n const mutationType = badge(mutation.type, mutationImpact[mutation.type])\n\n const documentType =\n 'document' in mutation || migration.documentTypes\n ? badge(\n 'document' in mutation\n ? mutation.document._type\n : listFormatter.format(migration.documentTypes ?? []),\n 'info',\n )\n : null\n\n // TODO: Should we list documentType when a mutation can be yielded for any document type?\n return [mutationType, documentType, styleText('underline', documentId(mutation) ?? '')]\n .filter(Boolean)\n .join(' ')\n}\n\nfunction prettyFormatMutation({\n indentSize = 0,\n migration,\n subject,\n}: FormatterOptions<Mutation>): string {\n const lock =\n 'options' in subject ? styleText('cyan', `(if revision==${subject.options?.ifRevision})`) : ''\n const header = [mutationHeader(subject, migration), lock].join(' ')\n const padding = ' '.repeat(indentSize)\n\n if (\n subject.type === 'create' ||\n subject.type === 'createIfNotExists' ||\n subject.type === 'createOrReplace'\n ) {\n return [header, '\\n', indent(JSON.stringify(subject.document, null, 2), indentSize)].join('')\n }\n\n if (subject.type === 'patch') {\n const tree = convertToTree<NodePatch>(subject.patches.flat())\n const paddingLength = Math.max(maxKeyLength(tree.children) + 2, 30)\n\n return [\n header,\n '\\n',\n formatTree<NodePatch>({\n getMessage: (patch: NodePatch) => formatPatchMutation(patch),\n indent: padding,\n node: tree.children,\n paddingLength,\n }),\n ].join('')\n }\n\n return header\n}\n\nfunction formatPatchMutation(patch: NodePatch): string {\n const {op} = patch\n const formattedType = styleText('bold', op.type)\n if (op.type === 'unset') {\n return `${styleText('red', formattedType)}()`\n }\n if (op.type === 'diffMatchPatch') {\n return `${styleText('yellow', formattedType)}(${op.value})`\n }\n if (op.type === 'inc' || op.type === 'dec') {\n return `${styleText('yellow', formattedType)}(${op.amount})`\n }\n if (op.type === 'set') {\n return `${styleText('yellow', formattedType)}(${JSON.stringify(op.value)})`\n }\n if (op.type === 'setIfMissing') {\n return `${styleText('green', formattedType)}(${JSON.stringify(op.value)})`\n }\n if (op.type === 'insert') {\n return `${styleText('green', formattedType)}(${op.position}, ${encodeItemRef(\n op.referenceItem,\n )}, ${JSON.stringify(op.items)})`\n }\n if (op.type === 'replace') {\n return `${styleText('yellow', formattedType)}(${encodeItemRef(op.referenceItem)}, ${JSON.stringify(\n op.items,\n )})`\n }\n if (op.type === 'truncate') {\n return `${styleText('red', formattedType)}(${op.startIndex}, ${op.endIndex})`\n }\n\n throw new Error(`Invalid operation type: ${(op as {type: string}).type}`)\n}\n\nfunction indent(subject: string, size = 2): string {\n const padding = ' '.repeat(size)\n\n return subject\n .split('\\n')\n .map((line) => padding + line)\n .join('\\n')\n}\n"],"names":["isatty","styleText","convertToTree","formatTree","maxKeyLength","isTty","prettyFormat","indentSize","migration","subject","Array","isArray","map","subjectEntry","type","badge","id","undefined","filter","Boolean","join","indent","mutations","prettyFormatMutation","encodeItemRef","ref","_key","badgeStyle","variant","label","styles","destructive","incremental","info","maybeDestructive","mutationImpact","create","createIfNotExists","createOrReplace","delete","patch","documentId","mutation","document","_id","listFormatter","Intl","ListFormat","mutationHeader","mutationType","documentType","documentTypes","_type","format","lock","options","ifRevision","header","padding","repeat","JSON","stringify","tree","patches","flat","paddingLength","Math","max","children","getMessage","formatPatchMutation","node","op","formattedType","value","amount","position","referenceItem","items","startIndex","endIndex","Error","size","split","line"],"mappings":"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"}
|