@sanity/cli 6.0.0-alpha.6 → 6.0.0-alpha.8
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 +2907 -109
- package/dist/actions/build/renderDocumentWorker/tryLoadDocumentComponent.js +2 -1
- package/dist/actions/build/renderDocumentWorker/tryLoadDocumentComponent.js.map +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.d.ts +13 -0
- package/dist/actions/init/bootstrapLocalTemplate.js +136 -0
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -0
- package/dist/actions/init/bootstrapRemoteTemplate.d.ts +12 -0
- package/dist/actions/init/bootstrapRemoteTemplate.js +109 -0
- package/dist/actions/init/bootstrapRemoteTemplate.js.map +1 -0
- package/dist/actions/init/bootstrapTemplate.d.ts +18 -0
- package/dist/actions/init/bootstrapTemplate.js +32 -0
- package/dist/actions/init/bootstrapTemplate.js.map +1 -0
- package/dist/actions/init/checkNextJsReactCompatibility.d.ts +9 -0
- package/dist/actions/init/checkNextJsReactCompatibility.js +21 -0
- package/dist/actions/init/checkNextJsReactCompatibility.js.map +1 -0
- package/dist/actions/init/countNestedFolders.d.ts +1 -0
- package/dist/actions/init/countNestedFolders.js +6 -0
- package/dist/actions/init/countNestedFolders.js.map +1 -0
- package/dist/actions/init/createAppCliConfig.d.ts +5 -0
- package/dist/actions/init/createAppCliConfig.js +19 -0
- package/dist/actions/init/createAppCliConfig.js.map +1 -0
- package/dist/actions/init/createCliConfig.d.ts +6 -0
- package/dist/actions/init/createCliConfig.js +27 -0
- package/dist/actions/init/createCliConfig.js.map +1 -0
- package/dist/actions/init/createPackageManifest.d.ts +6 -0
- package/dist/actions/init/createPackageManifest.js +86 -0
- package/dist/actions/init/createPackageManifest.js.map +1 -0
- package/dist/actions/init/createStudioConfig.d.ts +13 -0
- package/dist/actions/init/createStudioConfig.js +41 -0
- package/dist/actions/init/createStudioConfig.js.map +1 -0
- package/dist/actions/init/env/createOrAppendEnvVars.d.ts +12 -0
- package/dist/actions/init/env/createOrAppendEnvVars.js +25 -0
- package/dist/actions/init/env/createOrAppendEnvVars.js.map +1 -0
- package/dist/actions/init/env/parseAndUpdateEnvVars.d.ts +9 -0
- package/dist/actions/init/env/parseAndUpdateEnvVars.js +42 -0
- package/dist/actions/init/env/parseAndUpdateEnvVars.js.map +1 -0
- package/dist/actions/init/env/writeEnvVarsToFile.d.ts +12 -0
- package/dist/actions/init/env/writeEnvVarsToFile.js +49 -0
- package/dist/actions/init/env/writeEnvVarsToFile.js.map +1 -0
- package/dist/actions/init/fetchPostInitPrompt.d.ts +6 -0
- package/dist/actions/init/fetchPostInitPrompt.js +30 -0
- package/dist/actions/init/fetchPostInitPrompt.js.map +1 -0
- package/dist/actions/init/git.d.ts +1 -0
- package/dist/actions/init/git.js +65 -0
- package/dist/actions/init/git.js.map +1 -0
- package/dist/actions/init/processTemplate.d.ts +7 -0
- package/dist/actions/init/processTemplate.js +56 -0
- package/dist/actions/init/processTemplate.js.map +1 -0
- package/dist/actions/init/remoteTemplate.d.ts +0 -3
- package/dist/actions/init/remoteTemplate.js +2 -40
- package/dist/actions/init/remoteTemplate.js.map +1 -1
- package/dist/actions/init/resolvePackageManager.d.ts +10 -0
- package/dist/actions/init/resolvePackageManager.js +20 -0
- package/dist/actions/init/resolvePackageManager.js.map +1 -0
- package/dist/actions/init/setupMCP.d.ts +21 -0
- package/dist/actions/init/setupMCP.js +258 -0
- package/dist/actions/init/setupMCP.js.map +1 -0
- package/dist/actions/init/templates/appQuickstart.d.ts +3 -0
- package/dist/actions/init/templates/appQuickstart.js +28 -0
- package/dist/actions/init/templates/appQuickstart.js.map +1 -0
- package/dist/actions/init/templates/appSanityUi.d.ts +3 -0
- package/dist/actions/init/templates/appSanityUi.js +30 -0
- package/dist/actions/init/templates/appSanityUi.js.map +1 -0
- package/dist/actions/init/templates/blog.d.ts +3 -0
- package/dist/actions/init/templates/blog.js +4 -0
- package/dist/actions/init/templates/blog.js.map +1 -0
- package/dist/actions/init/templates/clean.d.ts +3 -0
- package/dist/actions/init/templates/clean.js +4 -0
- package/dist/actions/init/templates/clean.js.map +1 -0
- package/dist/actions/init/templates/getStarted.d.ts +3 -0
- package/dist/actions/init/templates/getStarted.js +35 -0
- package/dist/actions/init/templates/getStarted.js.map +1 -0
- package/dist/actions/init/templates/index.d.ts +3 -0
- package/dist/actions/init/templates/index.js +23 -0
- package/dist/actions/init/templates/index.js.map +1 -0
- package/dist/actions/init/templates/moviedb.d.ts +3 -0
- package/dist/actions/init/templates/moviedb.js +34 -0
- package/dist/actions/init/templates/moviedb.js.map +1 -0
- package/dist/actions/init/templates/nextjs/index.d.ts +6 -0
- package/dist/actions/init/templates/nextjs/index.js +213 -0
- package/dist/actions/init/templates/nextjs/index.js.map +1 -0
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.d.ts +3 -0
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.js +247 -0
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.js.map +1 -0
- package/dist/actions/init/templates/quickstart.d.ts +3 -0
- package/dist/actions/init/templates/quickstart.js +4 -0
- package/dist/actions/init/templates/quickstart.js.map +1 -0
- package/dist/actions/init/templates/shopify.d.ts +3 -0
- package/dist/actions/init/templates/shopify.js +77 -0
- package/dist/actions/init/templates/shopify.js.map +1 -0
- package/dist/actions/init/templates/shopifyOnline.d.ts +3 -0
- package/dist/actions/init/templates/shopifyOnline.js +49 -0
- package/dist/actions/init/templates/shopifyOnline.js.map +1 -0
- package/dist/actions/init/types.d.ts +15 -0
- package/dist/actions/init/types.js +3 -0
- package/dist/actions/init/types.js.map +1 -0
- package/dist/actions/init/updateInitialTemplateMetadata.d.ts +1 -0
- package/dist/actions/init/updateInitialTemplateMetadata.js +17 -0
- package/dist/actions/init/updateInitialTemplateMetadata.js.map +1 -0
- package/dist/actions/telemetry/resolveConsent.d.ts +1 -9
- package/dist/actions/telemetry/resolveConsent.js +2 -2
- package/dist/actions/telemetry/resolveConsent.js.map +1 -1
- package/dist/actions/telemetry/setConsent.d.ts +1 -4
- package/dist/actions/telemetry/setConsent.js +4 -8
- package/dist/actions/telemetry/setConsent.js.map +1 -1
- package/dist/commands/init.d.ts +24 -14
- package/dist/commands/init.js +544 -26
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/telemetry/disable.js +0 -1
- package/dist/commands/telemetry/disable.js.map +1 -1
- package/dist/commands/telemetry/enable.js +0 -1
- package/dist/commands/telemetry/enable.js.map +1 -1
- package/dist/commands/telemetry/status.js +1 -3
- package/dist/commands/telemetry/status.js.map +1 -1
- package/dist/hooks/prerun/flushTelemetry.worker.d.ts +2 -0
- package/dist/hooks/prerun/flushTelemetry.worker.js +22 -0
- package/dist/hooks/prerun/flushTelemetry.worker.js.map +1 -0
- package/dist/hooks/prerun/setupTelemetry.js +65 -1
- package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
- package/dist/prompts/init/nextjs.d.ts +5 -0
- package/dist/prompts/init/nextjs.js +56 -0
- package/dist/prompts/init/nextjs.js.map +1 -0
- package/dist/prompts/init/promptForTypescript.d.ts +0 -1
- package/dist/prompts/init/promptForTypescript.js +0 -6
- package/dist/prompts/init/promptForTypescript.js.map +1 -1
- package/dist/services/mcp.d.ts +10 -0
- package/dist/services/mcp.js +16 -0
- package/dist/services/mcp.js.map +1 -1
- package/dist/services/projects.d.ts +5 -2
- package/dist/services/projects.js +37 -0
- package/dist/services/projects.js.map +1 -1
- package/dist/services/telemetry.d.ts +2 -0
- package/dist/services/telemetry.js +20 -0
- package/dist/services/telemetry.js.map +1 -0
- package/dist/studioDependencies.d.ts +16 -0
- package/dist/studioDependencies.js +24 -0
- package/dist/studioDependencies.js.map +1 -0
- package/dist/telemetry/cli.telemetry.d.ts +20 -0
- package/dist/telemetry/cli.telemetry.js +8 -0
- package/dist/telemetry/cli.telemetry.js.map +1 -0
- package/dist/telemetry/store/cleanupOldTelemetryFiles.d.ts +5 -0
- package/dist/telemetry/store/cleanupOldTelemetryFiles.js +30 -0
- package/dist/telemetry/store/cleanupOldTelemetryFiles.js.map +1 -0
- package/dist/telemetry/store/createTelemetryStore.d.ts +39 -0
- package/dist/telemetry/store/createTelemetryStore.js +95 -0
- package/dist/telemetry/store/createTelemetryStore.js.map +1 -0
- package/dist/telemetry/store/createTraceId.d.ts +10 -0
- package/dist/telemetry/store/createTraceId.js +10 -0
- package/dist/telemetry/store/createTraceId.js.map +1 -0
- package/dist/telemetry/store/debug.d.ts +5 -0
- package/dist/telemetry/store/debug.js +7 -0
- package/dist/telemetry/store/debug.js.map +1 -0
- package/dist/telemetry/store/findTelemetryFiles.d.ts +13 -0
- package/dist/telemetry/store/findTelemetryFiles.js +34 -0
- package/dist/telemetry/store/findTelemetryFiles.js.map +1 -0
- package/dist/telemetry/store/flushTelemetryFiles.d.ts +20 -0
- package/dist/telemetry/store/flushTelemetryFiles.js +107 -0
- package/dist/telemetry/store/flushTelemetryFiles.js.map +1 -0
- package/dist/telemetry/store/generateTelemetryFilePath.d.ts +17 -0
- package/dist/telemetry/store/generateTelemetryFilePath.js +30 -0
- package/dist/telemetry/store/generateTelemetryFilePath.js.map +1 -0
- package/dist/telemetry/store/getTelemetryBaseInfo.d.ts +27 -0
- package/dist/telemetry/store/getTelemetryBaseInfo.js +34 -0
- package/dist/telemetry/store/getTelemetryBaseInfo.js.map +1 -0
- package/dist/telemetry/store/logger.d.ts +6 -0
- package/dist/telemetry/store/logger.js +54 -0
- package/dist/telemetry/store/logger.js.map +1 -0
- package/dist/telemetry/store/trace.d.ts +6 -0
- package/dist/telemetry/store/trace.js +150 -0
- package/dist/telemetry/store/trace.js.map +1 -0
- package/dist/telemetry/utils/readNDJSON.d.ts +10 -0
- package/dist/telemetry/utils/readNDJSON.js +18 -0
- package/dist/telemetry/utils/readNDJSON.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.js.map +1 -1
- package/dist/typings/deepSortObject.d.js +2 -0
- package/dist/typings/deepSortObject.d.js.map +1 -0
- package/dist/util/copy.d.ts +5 -0
- package/dist/util/copy.js +37 -0
- package/dist/util/copy.js.map +1 -0
- package/dist/util/detectRuntime.d.ts +8 -0
- package/dist/util/detectRuntime.js +20 -0
- package/dist/util/detectRuntime.js.map +1 -0
- package/dist/util/frameworkPort.d.ts +12 -0
- package/dist/util/frameworkPort.js +61 -0
- package/dist/util/frameworkPort.js.map +1 -0
- package/dist/util/fsUtils.d.ts +2 -0
- package/dist/util/fsUtils.js +34 -0
- package/dist/util/fsUtils.js.map +1 -0
- package/dist/util/getProjectDefaults.d.ts +11 -0
- package/dist/util/getProjectDefaults.js +77 -0
- package/dist/util/getProjectDefaults.js.map +1 -0
- package/dist/util/isStaging.d.ts +7 -0
- package/dist/util/isStaging.js +10 -0
- package/dist/util/isStaging.js.map +1 -0
- package/dist/util/packageManager/packageManagerChoice.d.ts +2 -0
- package/dist/util/packageManager/packageManagerChoice.js +8 -0
- package/dist/util/packageManager/packageManagerChoice.js.map +1 -1
- package/dist/util/parseArguments.d.ts +35 -0
- package/dist/util/parseArguments.js +42 -0
- package/dist/util/parseArguments.js.map +1 -0
- package/dist/util/readdirRecursive.d.ts +5 -0
- package/dist/util/readdirRecursive.js +24 -0
- package/dist/util/readdirRecursive.js.map +1 -0
- package/dist/util/resolveLatestVersions.d.ts +7 -0
- package/dist/util/resolveLatestVersions.js +21 -0
- package/dist/util/resolveLatestVersions.js.map +1 -0
- package/oclif.manifest.json +154 -141
- package/package.json +26 -14
package/dist/commands/init.js
CHANGED
|
@@ -1,26 +1,49 @@
|
|
|
1
1
|
// @Todo will remove by time migration of this command is complete
|
|
2
|
-
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
6
|
import { CLIError } from '@oclif/core/errors';
|
|
4
7
|
import { getCliToken, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
5
8
|
import { chalk, confirm, input, logSymbols, select, Separator, spinner } from '@sanity/cli-core/ux';
|
|
6
9
|
import { isHttpError } from '@sanity/client';
|
|
10
|
+
import { DatasetImportCommand } from '@sanity/import';
|
|
7
11
|
import { frameworks } from '@vercel/frameworks';
|
|
8
12
|
import { detectFrameworkRecord, LocalFileSystemDetector } from '@vercel/fs-detectors';
|
|
13
|
+
import { execa } from 'execa';
|
|
14
|
+
import { deburr } from 'lodash-es';
|
|
9
15
|
import { getProviderName } from '../actions/auth/getProviderName.js';
|
|
10
16
|
import { login } from '../actions/auth/login/login.js';
|
|
11
17
|
import { createDataset } from '../actions/dataset/create.js';
|
|
18
|
+
import { bootstrapTemplate } from '../actions/init/bootstrapTemplate.js';
|
|
19
|
+
import { checkNextJsReactCompatibility } from '../actions/init/checkNextJsReactCompatibility.js';
|
|
20
|
+
import { countNestedFolders } from '../actions/init/countNestedFolders.js';
|
|
12
21
|
import { determineAppTemplate } from '../actions/init/determineAppTemplate.js';
|
|
22
|
+
import { createOrAppendEnvVars } from '../actions/init/env/createOrAppendEnvVars.js';
|
|
23
|
+
import { fetchPostInitPrompt } from '../actions/init/fetchPostInitPrompt.js';
|
|
24
|
+
import { tryGitInit } from '../actions/init/git.js';
|
|
13
25
|
import { checkIsRemoteTemplate, getGitHubRepoInfo } from '../actions/init/remoteTemplate.js';
|
|
26
|
+
import { resolvePackageManager } from '../actions/init/resolvePackageManager.js';
|
|
27
|
+
import { setupMCP } from '../actions/init/setupMCP.js';
|
|
28
|
+
import templates from '../actions/init/templates/index.js';
|
|
29
|
+
import { sanityCliTemplate, sanityConfigTemplate, sanityFolder, sanityStudioTemplate } from '../actions/init/templates/nextjs/index.js';
|
|
14
30
|
import { getOrganizationChoices } from '../actions/organizations/getOrganizationChoices.js';
|
|
15
31
|
import { getOrganizationsWithAttachGrantInfo } from '../actions/organizations/getOrganizationsWithAttachGrantInfo.js';
|
|
16
32
|
import { hasProjectAttachGrant } from '../actions/organizations/hasProjectAttachGrant.js';
|
|
33
|
+
import { promptForAppendEnv, promptForConfigFiles, promptForEmbeddedStudio, promptForNextTemplate, promptForStudioPath } from '../prompts/init/nextjs.js';
|
|
34
|
+
import { promptForTypeScript } from '../prompts/init/promptForTypescript.js';
|
|
17
35
|
import { promptForDatasetName } from '../prompts/promptForDatasetName.js';
|
|
36
|
+
import { createCorsOrigin, listCorsOrigins } from '../services/cors.js';
|
|
18
37
|
import { createDataset as createDatasetService, listDatasets } from '../services/datasets.js';
|
|
19
38
|
import { getProjectFeatures } from '../services/getProjectFeatures.js';
|
|
20
39
|
import { createOrganization, listOrganizations } from '../services/organizations.js';
|
|
21
40
|
import { getPlanId, getPlanIdFromCoupon } from '../services/plans.js';
|
|
22
|
-
import { createProject, listProjects } from '../services/projects.js';
|
|
41
|
+
import { createProject, listProjects, updateProjectInitializedAt } from '../services/projects.js';
|
|
23
42
|
import { getCliUser } from '../services/user.js';
|
|
43
|
+
import { absolutify, validateEmptyPath } from '../util/fsUtils.js';
|
|
44
|
+
import { getProjectDefaults } from '../util/getProjectDefaults.js';
|
|
45
|
+
import { installDeclaredPackages, installNewPackages } from '../util/packageManager/installPackages.js';
|
|
46
|
+
import { getPartialEnvWithNpmPath } from '../util/packageManager/packageManagerChoice.js';
|
|
24
47
|
const debug = subdebug('init');
|
|
25
48
|
export class InitCommand extends SanityCommand {
|
|
26
49
|
static args = {
|
|
@@ -116,19 +139,19 @@ export class InitCommand extends SanityCommand {
|
|
|
116
139
|
}),
|
|
117
140
|
'nextjs-add-config-files': Flags.boolean({
|
|
118
141
|
allowNo: true,
|
|
119
|
-
default:
|
|
142
|
+
default: undefined,
|
|
120
143
|
description: 'Add config files to Next.js project',
|
|
121
144
|
helpGroup: 'Next.js'
|
|
122
145
|
}),
|
|
123
146
|
'nextjs-append-env': Flags.boolean({
|
|
124
147
|
allowNo: true,
|
|
125
|
-
default:
|
|
148
|
+
default: undefined,
|
|
126
149
|
description: 'Append project ID and dataset to .env file',
|
|
127
150
|
helpGroup: 'Next.js'
|
|
128
151
|
}),
|
|
129
152
|
'nextjs-embed-studio': Flags.boolean({
|
|
130
153
|
allowNo: true,
|
|
131
|
-
default:
|
|
154
|
+
default: undefined,
|
|
132
155
|
description: 'Embed the Studio in Next.js application',
|
|
133
156
|
helpGroup: 'Next.js'
|
|
134
157
|
}),
|
|
@@ -154,7 +177,8 @@ export class InitCommand extends SanityCommand {
|
|
|
154
177
|
helpValue: '<path>'
|
|
155
178
|
}),
|
|
156
179
|
'overwrite-files': Flags.boolean({
|
|
157
|
-
|
|
180
|
+
allowNo: true,
|
|
181
|
+
default: undefined,
|
|
158
182
|
description: 'Overwrite existing files'
|
|
159
183
|
}),
|
|
160
184
|
'package-manager': Flags.string({
|
|
@@ -187,6 +211,11 @@ export class InitCommand extends SanityCommand {
|
|
|
187
211
|
description: 'Login provider to use',
|
|
188
212
|
helpValue: '<provider>'
|
|
189
213
|
}),
|
|
214
|
+
quickstart: Flags.boolean({
|
|
215
|
+
deprecated: true,
|
|
216
|
+
description: 'Used for initializing a project from a server schema that is saved in the Journey API',
|
|
217
|
+
hidden: true
|
|
218
|
+
}),
|
|
190
219
|
reconfigure: Flags.boolean({
|
|
191
220
|
deprecated: {
|
|
192
221
|
message: 'This flag is no longer supported',
|
|
@@ -196,7 +225,6 @@ export class InitCommand extends SanityCommand {
|
|
|
196
225
|
hidden: true
|
|
197
226
|
}),
|
|
198
227
|
template: Flags.string({
|
|
199
|
-
default: 'clean',
|
|
200
228
|
description: 'Project template to use [default: "clean"]',
|
|
201
229
|
exclusive: [
|
|
202
230
|
'bare'
|
|
@@ -211,7 +239,7 @@ export class InitCommand extends SanityCommand {
|
|
|
211
239
|
}),
|
|
212
240
|
typescript: Flags.boolean({
|
|
213
241
|
allowNo: true,
|
|
214
|
-
default:
|
|
242
|
+
default: undefined,
|
|
215
243
|
description: 'Enable TypeScript support',
|
|
216
244
|
exclusive: [
|
|
217
245
|
'bare'
|
|
@@ -232,14 +260,14 @@ export class InitCommand extends SanityCommand {
|
|
|
232
260
|
})
|
|
233
261
|
};
|
|
234
262
|
async run() {
|
|
235
|
-
const
|
|
263
|
+
const workDir = process.cwd();
|
|
236
264
|
const createProjectName = this.flags['create-project'];
|
|
237
265
|
// For backwards "compatibility" - we used to allow `sanity init plugin`,
|
|
238
266
|
// and no longer do - but instead of printing an error about an unknown
|
|
239
267
|
// _command_, we want to acknowledge that the user is trying to do something
|
|
240
268
|
// that no longer exists but might have at some point in the past.
|
|
241
|
-
if (args.type) {
|
|
242
|
-
this.error(args.type === 'plugin' ? 'Initializing plugins through the CLI is no longer supported' : `Unknown init type "${args.type}"`, {
|
|
269
|
+
if (this.args.type) {
|
|
270
|
+
this.error(this.args.type === 'plugin' ? 'Initializing plugins through the CLI is no longer supported' : `Unknown init type "${this.args.type}"`, {
|
|
243
271
|
exit: 1
|
|
244
272
|
});
|
|
245
273
|
}
|
|
@@ -269,8 +297,8 @@ export class InitCommand extends SanityCommand {
|
|
|
269
297
|
});
|
|
270
298
|
const isNextJs = detectedFramework?.slug === 'nextjs';
|
|
271
299
|
let remoteTemplateInfo;
|
|
272
|
-
if (flags.template && checkIsRemoteTemplate(flags.template)) {
|
|
273
|
-
remoteTemplateInfo = await getGitHubRepoInfo(flags.template, flags['template-token']);
|
|
300
|
+
if (this.flags.template && checkIsRemoteTemplate(this.flags.template)) {
|
|
301
|
+
remoteTemplateInfo = await getGitHubRepoInfo(this.flags.template, this.flags['template-token']);
|
|
274
302
|
}
|
|
275
303
|
if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {
|
|
276
304
|
this.error(`A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`, {
|
|
@@ -309,24 +337,26 @@ export class InitCommand extends SanityCommand {
|
|
|
309
337
|
if (detectedFramework && detectedFramework.slug === 'nextjs') {
|
|
310
338
|
envFilenameDefault = '.env.local';
|
|
311
339
|
}
|
|
312
|
-
const
|
|
340
|
+
const envFilename = typeof this.flags.env === 'string' ? this.flags.env : envFilenameDefault;
|
|
313
341
|
// If the user isn't already autenticated, make it so
|
|
314
342
|
const { user } = await this.ensureAuthenticated();
|
|
315
|
-
|
|
316
|
-
const template = this.flags.template;
|
|
317
|
-
const isAppTemplate = template ? determineAppTemplate(template) : false // Default to false
|
|
343
|
+
const isAppTemplate = this.flags.template ? determineAppTemplate(this.flags.template) : false // Default to false
|
|
318
344
|
;
|
|
319
345
|
if (!isAppTemplate) {
|
|
320
346
|
this.log(`${logSymbols.success} Fetching existing projects`);
|
|
321
347
|
this.log('');
|
|
322
348
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
349
|
+
let newProject;
|
|
350
|
+
if (createProjectName) {
|
|
351
|
+
newProject = await this.createProjectFromName({
|
|
352
|
+
createProjectName,
|
|
353
|
+
planId,
|
|
354
|
+
user
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
const { datasetName, displayName, isFirstProject, organizationId, projectId } = await this.getProjectDetails({
|
|
329
358
|
isAppTemplate,
|
|
359
|
+
newProject,
|
|
330
360
|
planId,
|
|
331
361
|
showDefaultConfigPrompt,
|
|
332
362
|
user
|
|
@@ -340,6 +370,227 @@ export class InitCommand extends SanityCommand {
|
|
|
340
370
|
this.log(`\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\n`);
|
|
341
371
|
return;
|
|
342
372
|
}
|
|
373
|
+
let initNext = this.flagOrDefault('nextjs-add-config-files', false);
|
|
374
|
+
if (isNextJs && this.promptForUndefinedFlag(this.flags['nextjs-add-config-files'])) {
|
|
375
|
+
initNext = await promptForConfigFiles();
|
|
376
|
+
}
|
|
377
|
+
// @todo
|
|
378
|
+
// trace.log({
|
|
379
|
+
// step: 'useDetectedFramework',
|
|
380
|
+
// selectedOption: initNext ? 'yes' : 'no',
|
|
381
|
+
// detectedFramework: detectedFramework?.name,
|
|
382
|
+
// })
|
|
383
|
+
const sluggedName = deburr(displayName.toLowerCase()).replaceAll(/\s+/g, '-').replaceAll(/[^a-z0-9-]/g, '');
|
|
384
|
+
// add more frameworks to this as we add support for them
|
|
385
|
+
// this is used to skip the getProjectInfo prompt
|
|
386
|
+
const initFramework = initNext;
|
|
387
|
+
// Gather project defaults based on environment
|
|
388
|
+
const defaults = await getProjectDefaults({
|
|
389
|
+
isPlugin: false,
|
|
390
|
+
workDir
|
|
391
|
+
});
|
|
392
|
+
// Prompt the user for required information
|
|
393
|
+
const outputPath = await this.getProjectOutputPath({
|
|
394
|
+
initFramework,
|
|
395
|
+
sluggedName,
|
|
396
|
+
workDir
|
|
397
|
+
});
|
|
398
|
+
// Set up MCP integration
|
|
399
|
+
const mcpResult = await setupMCP({
|
|
400
|
+
mcp: this.flags.mcp,
|
|
401
|
+
output: this.output
|
|
402
|
+
});
|
|
403
|
+
// @todo
|
|
404
|
+
// trace.log({
|
|
405
|
+
// step: 'mcpSetup',
|
|
406
|
+
// detectedEditors: mcpResult.detectedEditors,
|
|
407
|
+
// configuredEditors: mcpResult.configuredEditors,
|
|
408
|
+
// skipped: mcpResult.skipped,
|
|
409
|
+
// })
|
|
410
|
+
// if (mcpResult.error) {
|
|
411
|
+
// trace.error(mcpResult.error)
|
|
412
|
+
// }
|
|
413
|
+
const mcpConfigured = mcpResult.configuredEditors;
|
|
414
|
+
if (isNextJs) {
|
|
415
|
+
await checkNextJsReactCompatibility({
|
|
416
|
+
detectedFramework,
|
|
417
|
+
output: this.output,
|
|
418
|
+
outputPath
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
if (initNext) {
|
|
422
|
+
await this.initNextJs({
|
|
423
|
+
datasetName,
|
|
424
|
+
detectedFramework,
|
|
425
|
+
envFilename,
|
|
426
|
+
mcpConfigured,
|
|
427
|
+
projectId,
|
|
428
|
+
workDir
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
// user wants to write environment variables to file
|
|
432
|
+
if (this.flags.env) {
|
|
433
|
+
await createOrAppendEnvVars({
|
|
434
|
+
envVars: {
|
|
435
|
+
DATASET: datasetName,
|
|
436
|
+
PROJECT_ID: projectId
|
|
437
|
+
},
|
|
438
|
+
filename: envFilename,
|
|
439
|
+
framework: detectedFramework,
|
|
440
|
+
log: false,
|
|
441
|
+
output: this.output,
|
|
442
|
+
outputPath
|
|
443
|
+
});
|
|
444
|
+
this.exit(0);
|
|
445
|
+
}
|
|
446
|
+
// Prompt for template to use
|
|
447
|
+
const templateName = await this.promptForTemplate();
|
|
448
|
+
// @todo
|
|
449
|
+
// trace.log({step: 'selectProjectTemplate', selectedOption: templateName})
|
|
450
|
+
const template = templates[templateName];
|
|
451
|
+
if (!remoteTemplateInfo && !template) {
|
|
452
|
+
this.error(`Template "${templateName}" not found`, {
|
|
453
|
+
exit: 1
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
let useTypeScript = this.flags.typescript;
|
|
457
|
+
if (!remoteTemplateInfo && template && template.typescriptOnly === true) {
|
|
458
|
+
useTypeScript = true;
|
|
459
|
+
} else if (this.promptForUndefinedFlag(this.flags.typescript)) {
|
|
460
|
+
useTypeScript = await promptForTypeScript();
|
|
461
|
+
// @todo
|
|
462
|
+
// trace.log({step: 'useTypeScript', selectedOption: useTypeScript ? 'yes' : 'no'})
|
|
463
|
+
}
|
|
464
|
+
// If the template has a sample dataset, prompt the user whether or not we should import it
|
|
465
|
+
const shouldImport = !this.isUnattended() && template?.datasetUrl && await this.promptForDatasetImport(template.importPrompt);
|
|
466
|
+
// @todo
|
|
467
|
+
// trace.log({step: 'importTemplateDataset', selectedOption: shouldImport ? 'yes' : 'no'})
|
|
468
|
+
try {
|
|
469
|
+
await updateProjectInitializedAt(projectId);
|
|
470
|
+
} catch (err) {
|
|
471
|
+
// Non-critical update
|
|
472
|
+
debug('Failed to update cliInitializedAt metadata', err);
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
await bootstrapTemplate({
|
|
476
|
+
autoUpdates: this.flags['auto-updates'],
|
|
477
|
+
bearerToken: this.flags['template-token'],
|
|
478
|
+
dataset: datasetName,
|
|
479
|
+
organizationId,
|
|
480
|
+
output: this.output,
|
|
481
|
+
outputPath,
|
|
482
|
+
overwriteFiles: this.flags['overwrite-files'],
|
|
483
|
+
packageName: sluggedName,
|
|
484
|
+
projectId,
|
|
485
|
+
projectName: displayName || defaults.projectName,
|
|
486
|
+
remoteTemplateInfo,
|
|
487
|
+
templateName,
|
|
488
|
+
useTypeScript
|
|
489
|
+
});
|
|
490
|
+
} catch (error) {
|
|
491
|
+
if (error instanceof Error) {
|
|
492
|
+
throw error;
|
|
493
|
+
}
|
|
494
|
+
throw new Error(String(error));
|
|
495
|
+
}
|
|
496
|
+
const pkgManager = await resolvePackageManager({
|
|
497
|
+
interactive: !this.isUnattended(),
|
|
498
|
+
output: this.output,
|
|
499
|
+
packageManager: this.flags['package-manager'],
|
|
500
|
+
targetDir: outputPath
|
|
501
|
+
});
|
|
502
|
+
// @todo
|
|
503
|
+
// trace.log({selectedOption: pkgManager, step: 'selectPackageManager', })
|
|
504
|
+
// Now for the slow part... installing dependencies
|
|
505
|
+
await installDeclaredPackages(outputPath, pkgManager, {
|
|
506
|
+
output: this.output,
|
|
507
|
+
workDir
|
|
508
|
+
});
|
|
509
|
+
const useGit = this.flags.git === undefined || Boolean(this.flags.git);
|
|
510
|
+
const commitMessage = this.flags.git;
|
|
511
|
+
// Try initializing a git repository
|
|
512
|
+
if (useGit) {
|
|
513
|
+
tryGitInit(outputPath, typeof commitMessage === 'string' ? commitMessage : undefined);
|
|
514
|
+
}
|
|
515
|
+
// Prompt for dataset import (if a dataset is defined)
|
|
516
|
+
if (shouldImport && template?.datasetUrl) {
|
|
517
|
+
const token = await getCliToken();
|
|
518
|
+
if (!token) {
|
|
519
|
+
this.error('Authentication required to import dataset', {
|
|
520
|
+
exit: 1
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
await DatasetImportCommand.run([
|
|
524
|
+
template.datasetUrl,
|
|
525
|
+
'--project',
|
|
526
|
+
projectId,
|
|
527
|
+
'--dataset',
|
|
528
|
+
datasetName,
|
|
529
|
+
'--token',
|
|
530
|
+
token
|
|
531
|
+
], {
|
|
532
|
+
root: outputPath
|
|
533
|
+
});
|
|
534
|
+
this.log('');
|
|
535
|
+
this.log('If you want to delete the imported data, use');
|
|
536
|
+
this.log(` ${chalk.cyan(`npx sanity dataset delete ${datasetName}`)}`);
|
|
537
|
+
this.log('and create a new clean dataset with');
|
|
538
|
+
this.log(` ${chalk.cyan(`npx sanity dataset create <name>`)}\n`);
|
|
539
|
+
}
|
|
540
|
+
const devCommandMap = {
|
|
541
|
+
bun: 'bun dev',
|
|
542
|
+
manual: 'npm run dev',
|
|
543
|
+
npm: 'npm run dev',
|
|
544
|
+
pnpm: 'pnpm dev',
|
|
545
|
+
yarn: 'yarn dev'
|
|
546
|
+
};
|
|
547
|
+
const devCommand = devCommandMap[pkgManager];
|
|
548
|
+
const isCurrentDir = outputPath === process.cwd();
|
|
549
|
+
const goToProjectDir = `\n(${chalk.cyan(`cd ${outputPath}`)} to navigate to your new project directory)`;
|
|
550
|
+
if (isAppTemplate) {
|
|
551
|
+
//output for custom apps here
|
|
552
|
+
this.log(`${logSymbols.success} ${chalk.green.bold('Success!')} Your custom app has been scaffolded.`);
|
|
553
|
+
if (!isCurrentDir) this.log(goToProjectDir);
|
|
554
|
+
this.log(`\n${chalk.bold('Next')}, configure the project(s) and dataset(s) your app should work with.`);
|
|
555
|
+
this.log('\nGet started in `src/App.tsx`, or refer to our documentation for a walkthrough:');
|
|
556
|
+
this.log(chalk.blue.underline('https://www.sanity.io/docs/app-sdk/sdk-configuration'));
|
|
557
|
+
if (mcpConfigured && mcpConfigured.length > 0) {
|
|
558
|
+
const message = await this.getPostInitMCPPrompt(mcpConfigured);
|
|
559
|
+
this.log(`\n${message}`);
|
|
560
|
+
this.log(`\nLearn more: ${chalk.cyan('https://mcp.sanity.io')}`);
|
|
561
|
+
this.log(`\nHave feedback? Tell us in the community: ${chalk.cyan('https://www.sanity.io/community/join')}`);
|
|
562
|
+
}
|
|
563
|
+
this.log('\n');
|
|
564
|
+
this.log(`Other helpful commands:`);
|
|
565
|
+
this.log(`npx sanity docs browse to open the documentation in a browser`);
|
|
566
|
+
this.log(`npx sanity dev to start the development server for your app`);
|
|
567
|
+
this.log(`npx sanity deploy to deploy your app`);
|
|
568
|
+
} else {
|
|
569
|
+
//output for Studios here
|
|
570
|
+
this.log(`✅ ${chalk.green.bold('Success!')} Your Studio has been created.`);
|
|
571
|
+
if (!isCurrentDir) this.log(goToProjectDir);
|
|
572
|
+
this.log(`\nGet started by running ${chalk.cyan(devCommand)} to launch your Studio's development server`);
|
|
573
|
+
if (mcpConfigured && mcpConfigured.length > 0) {
|
|
574
|
+
const message = await this.getPostInitMCPPrompt(mcpConfigured);
|
|
575
|
+
this.log(`\n${message}`);
|
|
576
|
+
this.log(`\nLearn more: ${chalk.cyan('https://mcp.sanity.io')}`);
|
|
577
|
+
this.log(`\nHave feedback? Tell us in the community: ${chalk.cyan('https://www.sanity.io/community/join')}`);
|
|
578
|
+
}
|
|
579
|
+
this.log('\n');
|
|
580
|
+
this.log(`Other helpful commands:`);
|
|
581
|
+
this.log(`npx sanity docs browse to open the documentation in a browser`);
|
|
582
|
+
this.log(`npx sanity manage to open the project settings in a browser`);
|
|
583
|
+
this.log(`npx sanity help to explore the CLI manual`);
|
|
584
|
+
}
|
|
585
|
+
if (isFirstProject) {
|
|
586
|
+
// @todo
|
|
587
|
+
// trace.log({step: 'sendCommunityInvite', selectedOption: 'yes'})
|
|
588
|
+
const DISCORD_INVITE_LINK = 'https://www.sanity.io/community/join';
|
|
589
|
+
this.log(`\nJoin the Sanity community: ${chalk.cyan(DISCORD_INVITE_LINK)}`);
|
|
590
|
+
this.log('We look forward to seeing you there!\n');
|
|
591
|
+
}
|
|
592
|
+
// @todo
|
|
593
|
+
// trace.complete()
|
|
343
594
|
}
|
|
344
595
|
checkFlagsInUnattendedMode({ createProjectName, isNextJs }) {
|
|
345
596
|
debug('Unattended mode, validating required options');
|
|
@@ -437,6 +688,9 @@ export class InitCommand extends SanityCommand {
|
|
|
437
688
|
user
|
|
438
689
|
};
|
|
439
690
|
}
|
|
691
|
+
flagOrDefault(flag, defaultValue) {
|
|
692
|
+
return typeof this.flags[flag] === 'boolean' ? this.flags[flag] : defaultValue;
|
|
693
|
+
}
|
|
440
694
|
async getOrCreateDataset(opts) {
|
|
441
695
|
const visibility = this.flags.visibility;
|
|
442
696
|
const dataset = this.flags.dataset;
|
|
@@ -537,8 +791,8 @@ export class InitCommand extends SanityCommand {
|
|
|
537
791
|
userAction: 'select'
|
|
538
792
|
};
|
|
539
793
|
}
|
|
540
|
-
async getOrCreateProject({ planId, user }) {
|
|
541
|
-
const projectId = this.flags.project;
|
|
794
|
+
async getOrCreateProject({ newProject, planId, user }) {
|
|
795
|
+
const projectId = this.flags.project || newProject;
|
|
542
796
|
const organizationId = this.flags.organization;
|
|
543
797
|
let projects;
|
|
544
798
|
let organizations;
|
|
@@ -662,7 +916,10 @@ export class InitCommand extends SanityCommand {
|
|
|
662
916
|
return undefined;
|
|
663
917
|
}
|
|
664
918
|
}
|
|
665
|
-
async
|
|
919
|
+
async getPostInitMCPPrompt(editorsNames) {
|
|
920
|
+
return fetchPostInitPrompt(new Intl.ListFormat('en').format(editorsNames));
|
|
921
|
+
}
|
|
922
|
+
async getProjectDetails({ isAppTemplate, newProject, planId, showDefaultConfigPrompt, user }) {
|
|
666
923
|
if (isAppTemplate) {
|
|
667
924
|
const organizations = await listOrganizations({
|
|
668
925
|
includeImplicitMemberships: 'true',
|
|
@@ -682,6 +939,7 @@ export class InitCommand extends SanityCommand {
|
|
|
682
939
|
}
|
|
683
940
|
debug('Prompting user to select or create a project');
|
|
684
941
|
const project = await this.getOrCreateProject({
|
|
942
|
+
newProject,
|
|
685
943
|
planId,
|
|
686
944
|
user
|
|
687
945
|
});
|
|
@@ -708,6 +966,187 @@ export class InitCommand extends SanityCommand {
|
|
|
708
966
|
projectId: project.projectId
|
|
709
967
|
};
|
|
710
968
|
}
|
|
969
|
+
async getProjectOutputPath({ initFramework, sluggedName, workDir }) {
|
|
970
|
+
const outputPath = this.flags['output-path'];
|
|
971
|
+
const specifiedPath = outputPath && path.resolve(outputPath);
|
|
972
|
+
if (this.isUnattended() || specifiedPath || this.flags.env || initFramework) {
|
|
973
|
+
return specifiedPath || workDir;
|
|
974
|
+
}
|
|
975
|
+
const inputPath = await input({
|
|
976
|
+
default: path.join(workDir, sluggedName),
|
|
977
|
+
message: 'Project output path:',
|
|
978
|
+
validate: validateEmptyPath
|
|
979
|
+
});
|
|
980
|
+
return absolutify(inputPath);
|
|
981
|
+
}
|
|
982
|
+
async initNextJs({ datasetName, detectedFramework, envFilename, mcpConfigured, projectId, workDir }) {
|
|
983
|
+
let useTypeScript = this.flagOrDefault('typescript', true);
|
|
984
|
+
if (this.promptForUndefinedFlag(this.flags.typescript)) {
|
|
985
|
+
useTypeScript = await promptForTypeScript();
|
|
986
|
+
}
|
|
987
|
+
// @todo
|
|
988
|
+
// trace.log({step: 'useTypeScript', selectedOption: useTypeScript ? 'yes' : 'no'})
|
|
989
|
+
const fileExtension = useTypeScript ? 'ts' : 'js';
|
|
990
|
+
let embeddedStudio = this.flagOrDefault('nextjs-embed-studio', true);
|
|
991
|
+
if (this.promptForUndefinedFlag(this.flags['nextjs-embed-studio'])) {
|
|
992
|
+
embeddedStudio = await promptForEmbeddedStudio();
|
|
993
|
+
}
|
|
994
|
+
let hasSrcFolder = false;
|
|
995
|
+
if (embeddedStudio) {
|
|
996
|
+
// find source path (app or src/app)
|
|
997
|
+
const appDir = 'app';
|
|
998
|
+
let srcPath = path.join(workDir, appDir);
|
|
999
|
+
if (!existsSync(srcPath)) {
|
|
1000
|
+
srcPath = path.join(workDir, 'src', appDir);
|
|
1001
|
+
hasSrcFolder = true;
|
|
1002
|
+
if (!existsSync(srcPath)) {
|
|
1003
|
+
try {
|
|
1004
|
+
await mkdir(srcPath, {
|
|
1005
|
+
recursive: true
|
|
1006
|
+
});
|
|
1007
|
+
} catch {
|
|
1008
|
+
debug('Error creating folder %s', srcPath);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
const studioPath = this.isUnattended() ? '/studio' : await promptForStudioPath();
|
|
1013
|
+
const embeddedStudioRouteFilePath = path.join(srcPath, `${studioPath}/`, `[[...tool]]/page.${fileExtension}x`);
|
|
1014
|
+
// this selects the correct template string based on whether the user is using the app or pages directory and
|
|
1015
|
+
// replaces the ":configPath:" placeholder in the template with the correct path to the sanity.config.ts file.
|
|
1016
|
+
// we account for the user-defined embeddedStudioPath (default /studio) is accounted for by creating enough "../"
|
|
1017
|
+
// relative paths to reach the root level of the project
|
|
1018
|
+
await this.writeOrOverwrite(embeddedStudioRouteFilePath, sanityStudioTemplate.replace(':configPath:', `${'../'.repeat(countNestedFolders(embeddedStudioRouteFilePath.slice(workDir.length)))}sanity.config`), workDir);
|
|
1019
|
+
const sanityConfigPath = path.join(workDir, `sanity.config.${fileExtension}`);
|
|
1020
|
+
await this.writeOrOverwrite(sanityConfigPath, sanityConfigTemplate(hasSrcFolder).replace(':route:', embeddedStudioRouteFilePath.slice(workDir.length).replace('src/', '')).replace(':basePath:', studioPath), workDir);
|
|
1021
|
+
}
|
|
1022
|
+
const sanityCliPath = path.join(workDir, `sanity.cli.${fileExtension}`);
|
|
1023
|
+
await this.writeOrOverwrite(sanityCliPath, sanityCliTemplate, workDir);
|
|
1024
|
+
let templateToUse = this.flags.template ?? 'clean';
|
|
1025
|
+
if (this.promptForUndefinedFlag(this.flags.template)) {
|
|
1026
|
+
templateToUse = await promptForNextTemplate();
|
|
1027
|
+
}
|
|
1028
|
+
await this.writeSourceFiles({
|
|
1029
|
+
fileExtension,
|
|
1030
|
+
files: sanityFolder(useTypeScript, templateToUse),
|
|
1031
|
+
folderPath: undefined,
|
|
1032
|
+
srcFolderPrefix: hasSrcFolder,
|
|
1033
|
+
workDir
|
|
1034
|
+
});
|
|
1035
|
+
let appendEnv = this.flagOrDefault('nextjs-append-env', true);
|
|
1036
|
+
if (this.promptForUndefinedFlag(this.flags['nextjs-append-env'])) {
|
|
1037
|
+
appendEnv = await promptForAppendEnv(envFilename);
|
|
1038
|
+
}
|
|
1039
|
+
if (appendEnv) {
|
|
1040
|
+
await createOrAppendEnvVars({
|
|
1041
|
+
envVars: {
|
|
1042
|
+
DATASET: datasetName,
|
|
1043
|
+
PROJECT_ID: projectId
|
|
1044
|
+
},
|
|
1045
|
+
filename: envFilename,
|
|
1046
|
+
framework: detectedFramework,
|
|
1047
|
+
log: true,
|
|
1048
|
+
output: this.output,
|
|
1049
|
+
outputPath: workDir
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
if (embeddedStudio) {
|
|
1053
|
+
const nextjsLocalDevOrigin = 'http://localhost:3000';
|
|
1054
|
+
const existingCorsOrigins = await listCorsOrigins(projectId);
|
|
1055
|
+
const hasExistingCorsOrigin = existingCorsOrigins.some((item)=>item.origin === nextjsLocalDevOrigin);
|
|
1056
|
+
if (!hasExistingCorsOrigin) {
|
|
1057
|
+
try {
|
|
1058
|
+
const createCorsRes = await createCorsOrigin({
|
|
1059
|
+
allowCredentials: true,
|
|
1060
|
+
origin: nextjsLocalDevOrigin,
|
|
1061
|
+
projectId
|
|
1062
|
+
});
|
|
1063
|
+
this.log(createCorsRes.id ? `Added ${nextjsLocalDevOrigin} to CORS origins` : `Failed to add ${nextjsLocalDevOrigin} to CORS origins`);
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
debug(`Error creating new CORS Origin ${nextjsLocalDevOrigin}: ${error}`);
|
|
1066
|
+
this.error(`Failed to add ${nextjsLocalDevOrigin} to CORS origins: ${error}`, {
|
|
1067
|
+
exit: 1
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
const chosen = await resolvePackageManager({
|
|
1073
|
+
interactive: !this.isUnattended(),
|
|
1074
|
+
output: this.output,
|
|
1075
|
+
packageManager: this.flags['package-manager'],
|
|
1076
|
+
targetDir: workDir
|
|
1077
|
+
});
|
|
1078
|
+
// @todo
|
|
1079
|
+
// trace.log({step: 'selectPackageManager', selectedOption: chosen})
|
|
1080
|
+
const packages = [
|
|
1081
|
+
'@sanity/vision@4',
|
|
1082
|
+
'sanity@4',
|
|
1083
|
+
'@sanity/image-url@1',
|
|
1084
|
+
'styled-components@6'
|
|
1085
|
+
];
|
|
1086
|
+
if (templateToUse === 'blog') {
|
|
1087
|
+
packages.push('@sanity/icons');
|
|
1088
|
+
}
|
|
1089
|
+
await installNewPackages({
|
|
1090
|
+
packageManager: chosen,
|
|
1091
|
+
packages
|
|
1092
|
+
}, {
|
|
1093
|
+
output: this.output,
|
|
1094
|
+
workDir
|
|
1095
|
+
});
|
|
1096
|
+
// will refactor this later
|
|
1097
|
+
const execOptions = {
|
|
1098
|
+
cwd: workDir,
|
|
1099
|
+
encoding: 'utf8',
|
|
1100
|
+
env: getPartialEnvWithNpmPath(workDir),
|
|
1101
|
+
stdio: 'inherit'
|
|
1102
|
+
};
|
|
1103
|
+
switch(chosen){
|
|
1104
|
+
case 'npm':
|
|
1105
|
+
{
|
|
1106
|
+
await execa('npm', [
|
|
1107
|
+
'install',
|
|
1108
|
+
'--legacy-peer-deps',
|
|
1109
|
+
'next-sanity@11'
|
|
1110
|
+
], execOptions);
|
|
1111
|
+
break;
|
|
1112
|
+
}
|
|
1113
|
+
case 'pnpm':
|
|
1114
|
+
{
|
|
1115
|
+
await execa('pnpm', [
|
|
1116
|
+
'install',
|
|
1117
|
+
'next-sanity@11'
|
|
1118
|
+
], execOptions);
|
|
1119
|
+
break;
|
|
1120
|
+
}
|
|
1121
|
+
case 'yarn':
|
|
1122
|
+
{
|
|
1123
|
+
await execa('npx', [
|
|
1124
|
+
'install-peerdeps',
|
|
1125
|
+
'--yarn',
|
|
1126
|
+
'next-sanity@11'
|
|
1127
|
+
], execOptions);
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
default:
|
|
1131
|
+
{
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
this.log(`\n${chalk.green('Success!')} Your Sanity configuration files has been added to this project`);
|
|
1136
|
+
if (mcpConfigured && mcpConfigured.length > 0) {
|
|
1137
|
+
const message = await this.getPostInitMCPPrompt(mcpConfigured);
|
|
1138
|
+
this.log(`\n${message}`);
|
|
1139
|
+
this.log(`\nLearn more: ${chalk.cyan('https://mcp.sanity.io')}`);
|
|
1140
|
+
this.log(`\nHave feedback? Tell us in the community: ${chalk.cyan('https://www.sanity.io/community/join')}`);
|
|
1141
|
+
}
|
|
1142
|
+
this.exit(0);
|
|
1143
|
+
}
|
|
1144
|
+
async promptForDatasetImport(message) {
|
|
1145
|
+
return confirm({
|
|
1146
|
+
default: true,
|
|
1147
|
+
message: message || 'This template includes a sample dataset, would you like to use it?'
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
711
1150
|
async promptForDefaultConfig() {
|
|
712
1151
|
return confirm({
|
|
713
1152
|
default: true,
|
|
@@ -748,6 +1187,37 @@ export class InitCommand extends SanityCommand {
|
|
|
748
1187
|
userAction: 'create'
|
|
749
1188
|
};
|
|
750
1189
|
}
|
|
1190
|
+
async promptForTemplate() {
|
|
1191
|
+
const template = this.flags.template;
|
|
1192
|
+
const defaultTemplate = this.isUnattended() || template ? template || 'clean' : null;
|
|
1193
|
+
if (defaultTemplate) {
|
|
1194
|
+
return defaultTemplate;
|
|
1195
|
+
}
|
|
1196
|
+
return select({
|
|
1197
|
+
choices: [
|
|
1198
|
+
{
|
|
1199
|
+
name: 'Clean project with no predefined schema types',
|
|
1200
|
+
value: 'clean'
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
name: 'Blog (schema)',
|
|
1204
|
+
value: 'blog'
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
name: 'E-commerce (Shopify)',
|
|
1208
|
+
value: 'shopify'
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
name: 'Movie project (schema + sample data)',
|
|
1212
|
+
value: 'moviedb'
|
|
1213
|
+
}
|
|
1214
|
+
],
|
|
1215
|
+
message: 'Select project template'
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
promptForUndefinedFlag(flag) {
|
|
1219
|
+
return !this.isUnattended() && flag === undefined;
|
|
1220
|
+
}
|
|
751
1221
|
async promptUserForNewOrganization(user) {
|
|
752
1222
|
const name = await input({
|
|
753
1223
|
default: user ? user.name : undefined,
|
|
@@ -863,6 +1333,54 @@ export class InitCommand extends SanityCommand {
|
|
|
863
1333
|
}
|
|
864
1334
|
}
|
|
865
1335
|
}
|
|
1336
|
+
async writeOrOverwrite(filePath, content, workDir) {
|
|
1337
|
+
if (existsSync(filePath)) {
|
|
1338
|
+
let overwrite = this.flagOrDefault('overwrite-files', false);
|
|
1339
|
+
if (this.promptForUndefinedFlag(this.flags['overwrite-files'])) {
|
|
1340
|
+
overwrite = await confirm({
|
|
1341
|
+
default: false,
|
|
1342
|
+
message: `File ${chalk.yellow(filePath.replace(workDir, ''))} already exists. Do you want to overwrite it?`
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
if (!overwrite) {
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
// make folder if not exists
|
|
1350
|
+
const folderPath = path.dirname(filePath);
|
|
1351
|
+
try {
|
|
1352
|
+
await mkdir(folderPath, {
|
|
1353
|
+
recursive: true
|
|
1354
|
+
});
|
|
1355
|
+
} catch {
|
|
1356
|
+
debug('Error creating folder %s', folderPath);
|
|
1357
|
+
}
|
|
1358
|
+
await writeFile(filePath, content, {
|
|
1359
|
+
encoding: 'utf8'
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
// write sanity folder files
|
|
1363
|
+
async writeSourceFiles({ fileExtension, files, folderPath, srcFolderPrefix, workDir }) {
|
|
1364
|
+
for (const [filePath, content] of Object.entries(files)){
|
|
1365
|
+
// check if file ends with full stop to indicate it's file and not directory (this only works with our template tree structure)
|
|
1366
|
+
if (filePath.includes('.') && typeof content === 'string') {
|
|
1367
|
+
await this.writeOrOverwrite(path.join(workDir, srcFolderPrefix ? 'src' : '', 'sanity', folderPath || '', `${filePath}${fileExtension}`), content, workDir);
|
|
1368
|
+
} else {
|
|
1369
|
+
await mkdir(path.join(workDir, srcFolderPrefix ? 'src' : '', 'sanity', filePath), {
|
|
1370
|
+
recursive: true
|
|
1371
|
+
});
|
|
1372
|
+
if (typeof content === 'object') {
|
|
1373
|
+
await this.writeSourceFiles({
|
|
1374
|
+
fileExtension,
|
|
1375
|
+
files: content,
|
|
1376
|
+
folderPath: filePath,
|
|
1377
|
+
srcFolderPrefix,
|
|
1378
|
+
workDir
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
866
1384
|
}
|
|
867
1385
|
|
|
868
1386
|
//# sourceMappingURL=init.js.map
|