sanity 3.77.3-server-side-schemas.15 → 3.77.3-server-side-schemas.16

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.
Files changed (33) hide show
  1. package/lib/_chunks-cjs/_internal.js +420 -142
  2. package/lib/_chunks-cjs/_internal.js.map +1 -1
  3. package/lib/_chunks-cjs/buildAction.js +2 -2
  4. package/lib/_chunks-cjs/buildAction.js.map +1 -1
  5. package/lib/_chunks-cjs/deleteSchemaAction.js +6 -4
  6. package/lib/_chunks-cjs/deleteSchemaAction.js.map +1 -1
  7. package/lib/_chunks-cjs/deployAction.js +3 -3
  8. package/lib/_chunks-cjs/deployAction.js.map +1 -1
  9. package/lib/_chunks-cjs/devAction.js +2 -2
  10. package/lib/_chunks-cjs/devAction.js.map +1 -1
  11. package/lib/_chunks-cjs/version.js +1 -1
  12. package/lib/_chunks-es/version.mjs +1 -1
  13. package/lib/_legacy/version.esm.js +1 -1
  14. package/lib/index.d.mts +3 -3
  15. package/lib/index.d.ts +3 -3
  16. package/lib/structure.d.mts +1 -1
  17. package/lib/structure.d.ts +1 -1
  18. package/package.json +10 -10
  19. package/src/_internal/cli/actions/manifest/extractManifestAction.ts +3 -3
  20. package/src/_internal/cli/actions/schema/deleteSchemaAction.ts +16 -7
  21. package/src/_internal/cli/actions/schema/schemaListAction.ts +23 -9
  22. package/src/_internal/cli/actions/schema/storeSchemasAction.ts +60 -13
  23. package/src/_internal/cli/commands/app/deployCommand.ts +2 -0
  24. package/src/_internal/cli/commands/index.ts +12 -4
  25. package/src/_internal/cli/commands/schema/deleteSchemaCommand.ts +1 -1
  26. package/src/_internal/cli/commands/schema/schemaListCommand.ts +1 -1
  27. package/src/_internal/cli/commands/schema/storeSchemaCommand.ts +6 -5
  28. package/lib/_chunks-cjs/extractManifestAction.js +0 -99
  29. package/lib/_chunks-cjs/extractManifestAction.js.map +0 -1
  30. package/lib/_chunks-cjs/storeSchemasAction.js +0 -147
  31. package/lib/_chunks-cjs/storeSchemasAction.js.map +0 -1
  32. package/lib/_chunks-cjs/timing.js +0 -22
  33. package/lib/_chunks-cjs/timing.js.map +0 -1
@@ -33,7 +33,7 @@ const EXTRACT_FAILURE_MESSAGE =
33
33
  "↳ Couldn't extract manifest file. Sanity Create will not be available for the studio.\n" +
34
34
  ` Disable this message with ${FEATURE_ENABLED_ENV_NAME}=false`
35
35
 
36
- interface ExtractFlags {
36
+ export interface ExtractManifestFlags {
37
37
  path?: string
38
38
  }
39
39
 
@@ -42,7 +42,7 @@ interface ExtractFlags {
42
42
  * @returns `undefined` if extract succeeded - caught error if it failed
43
43
  */
44
44
  export async function extractManifestSafe(
45
- args: CliCommandArguments<ExtractFlags>,
45
+ args: CliCommandArguments<ExtractManifestFlags>,
46
46
  context: CliCommandContext,
47
47
  ): Promise<Error | undefined> {
48
48
  if (!EXTRACT_MANIFEST_ENABLED) {
@@ -61,7 +61,7 @@ export async function extractManifestSafe(
61
61
  }
62
62
 
63
63
  async function extractManifest(
64
- args: CliCommandArguments<ExtractFlags>,
64
+ args: CliCommandArguments<ExtractManifestFlags>,
65
65
  context: CliCommandContext,
66
66
  ): Promise<void> {
67
67
  const {output, workDir} = context
@@ -2,22 +2,30 @@ import {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'
2
2
  import chalk from 'chalk'
3
3
 
4
4
  import {type ManifestWorkspaceFile} from '../../../manifest/manifestTypes'
5
- import {getManifestPath, readManifest, throwIfProjectIdMismatch} from './storeSchemasAction'
5
+ import {
6
+ getManifestPath,
7
+ readManifest,
8
+ SCHEMA_STORE_ENABLED,
9
+ throwIfProjectIdMismatch,
10
+ } from './storeSchemasAction'
6
11
 
7
12
  export interface DeleteSchemaFlags {
8
- ids: string
9
- path: string
10
- dataset: string
13
+ 'ids': string
14
+ 'manifest-dir': string
15
+ 'dataset': string
11
16
  }
12
17
 
13
18
  export default async function deleteSchemaAction(
14
19
  args: CliCommandArguments<DeleteSchemaFlags>,
15
20
  context: CliCommandContext,
16
21
  ): Promise<void> {
22
+ if (!SCHEMA_STORE_ENABLED) {
23
+ return
24
+ }
17
25
  const flags = args.extOptions
18
26
  if (typeof flags.dataset === 'boolean') throw new Error('Dataset is empty')
19
27
  if (typeof flags.ids === 'boolean') throw new Error('Ids are empty')
20
- if (typeof flags.path === 'boolean') throw new Error('Path is empty')
28
+ if (typeof flags['manifest-dir'] === 'boolean') throw new Error('Manifest directory is empty')
21
29
 
22
30
  const {apiClient, output} = context
23
31
 
@@ -36,8 +44,9 @@ export default async function deleteSchemaAction(
36
44
  return
37
45
  }
38
46
 
39
- const manifestPath = getManifestPath(context, flags.path)
40
- const manifest = readManifest(manifestPath, output)
47
+ const manifestDir = flags['manifest-dir']
48
+ const manifestPath = getManifestPath(context, manifestDir)
49
+ const manifest = await readManifest(manifestPath, context)
41
50
 
42
51
  const results = await Promise.allSettled(
43
52
  manifest.workspaces.flatMap((workspace: ManifestWorkspaceFile) => {
@@ -4,12 +4,17 @@ import chalk from 'chalk'
4
4
  import {size, sortBy, uniqBy} from 'lodash'
5
5
 
6
6
  import {type ManifestWorkspaceFile} from '../../../manifest/manifestTypes'
7
- import {getManifestPath, readManifest, throwIfProjectIdMismatch} from './storeSchemasAction'
7
+ import {
8
+ getManifestPath,
9
+ readManifest,
10
+ SCHEMA_STORE_ENABLED,
11
+ throwIfProjectIdMismatch,
12
+ } from './storeSchemasAction'
8
13
 
9
14
  export interface SchemaListFlags {
10
- json: boolean
11
- id: string
12
- path: string
15
+ 'json': boolean
16
+ 'id': string
17
+ 'manifest-dir': string
13
18
  }
14
19
 
15
20
  type PrintSchemaListArgs = {
@@ -46,11 +51,18 @@ const printSchemaList = ({
46
51
  rows.forEach((row) => output.print(printRow(row)))
47
52
  }
48
53
 
49
- export default async function fetchSchemaAction(
54
+ export default async function schemaListAction(
50
55
  args: CliCommandArguments<SchemaListFlags>,
51
56
  context: CliCommandContext,
52
57
  ): Promise<void> {
58
+ if (!SCHEMA_STORE_ENABLED) {
59
+ return
60
+ }
61
+
53
62
  const flags = args.extOptions
63
+ if (typeof flags.id === 'boolean') throw new Error('Schema ID is empty')
64
+ if (typeof flags['manifest-dir'] === 'boolean') throw new Error('Manifest directory is empty')
65
+
54
66
  const {apiClient, output} = context
55
67
  const client = apiClient({
56
68
  requireUser: true,
@@ -58,14 +70,16 @@ export default async function fetchSchemaAction(
58
70
  }).withConfig({apiVersion: 'v2024-08-01'})
59
71
 
60
72
  const projectId = client.config().projectId
73
+ const dataset = client.config().dataset
61
74
 
62
- if (!projectId) {
63
- output.error('Project ID must be defined.')
75
+ if (!projectId || !dataset) {
76
+ output.error('Project ID and dataset must be defined.')
64
77
  return
65
78
  }
66
79
 
67
- const manifestPath = getManifestPath(context, flags.path)
68
- const manifest = readManifest(manifestPath, output)
80
+ const manifestDir = flags['manifest-dir']
81
+ const manifestPath = getManifestPath(context, manifestDir)
82
+ const manifest = await readManifest(manifestPath, context)
69
83
 
70
84
  // Gather all schemas
71
85
  const results = await Promise.allSettled(
@@ -1,16 +1,23 @@
1
- import {readFileSync} from 'node:fs'
1
+ import {readFileSync, statSync} from 'node:fs'
2
2
  import path, {join, resolve} from 'node:path'
3
3
 
4
- import {type CliCommandArguments, type CliCommandContext, type CliOutputter} from '@sanity/cli'
4
+ import {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'
5
5
  import chalk from 'chalk'
6
6
  import {type Ora} from 'ora'
7
7
 
8
8
  import {type ManifestSchemaType, type ManifestWorkspaceFile} from '../../../manifest/manifestTypes'
9
- import {MANIFEST_FILENAME} from '../manifest/extractManifestAction'
9
+ import {
10
+ type ExtractManifestFlags,
11
+ extractManifestSafe,
12
+ MANIFEST_FILENAME,
13
+ } from '../manifest/extractManifestAction'
10
14
  import {SANITY_WORKSPACE_SCHEMA_TYPE} from './schemaListAction'
11
15
 
16
+ const FEATURE_ENABLED_ENV_NAME = 'SANITY_CLI_SCHEMA_STORE_ENABLED'
17
+ export const SCHEMA_STORE_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] === 'true'
18
+
12
19
  export interface StoreManifestSchemasFlags {
13
- 'path'?: string
20
+ 'manifest-dir'?: string
14
21
  'workspace'?: string
15
22
  'id-prefix'?: string
16
23
  'schema-required'?: boolean
@@ -28,14 +35,49 @@ export const getManifestPath = (context: CliCommandContext, customPath?: string)
28
35
  return manifestPath
29
36
  }
30
37
 
31
- export const readManifest = (readPath: string, output?: CliOutputter, spinner?: Ora) => {
38
+ /**
39
+ * Helper function to read and parse a manifest file with logging
40
+ */
41
+ const readAndParseManifest = (manifestPath: string, context: CliCommandContext) => {
42
+ const content = readFileSync(manifestPath, 'utf-8')
43
+ const stats = statSync(manifestPath)
44
+ const lastModified = stats.mtime.toISOString()
45
+ context.output.print(
46
+ chalk.gray(`\n↳ Read manifest from ${manifestPath} (last modified: ${lastModified})`),
47
+ )
48
+ return JSON.parse(content)
49
+ }
50
+
51
+ export const readManifest = async (readPath: string, context: CliCommandContext, spinner?: Ora) => {
52
+ const manifestPath = `${readPath}/${MANIFEST_FILENAME}`
53
+
32
54
  try {
33
- return JSON.parse(readFileSync(`${readPath}/${MANIFEST_FILENAME}`, 'utf-8'))
55
+ return readAndParseManifest(manifestPath, context)
34
56
  } catch (error) {
35
- const errorMessage = `Manifest not found at ${readPath}/${MANIFEST_FILENAME}`
36
- if (spinner) spinner.fail(errorMessage)
37
- if (output) output.error(errorMessage)
38
- throw error
57
+ // Still log that we're attempting extraction
58
+ spinner!.text = 'Manifest not found, attempting to extract it...'
59
+
60
+ await extractManifestSafe(
61
+ {
62
+ extOptions: {path: readPath},
63
+ groupOrCommand: 'extract',
64
+ argv: [],
65
+ argsWithoutOptions: [],
66
+ extraArguments: [],
67
+ } as CliCommandArguments<ExtractManifestFlags>,
68
+ context,
69
+ )
70
+
71
+ // Try reading the manifest again after extraction
72
+ try {
73
+ return readAndParseManifest(manifestPath, context)
74
+ } catch (retryError) {
75
+ const errorMessage = `Failed to read manifest at ${manifestPath}`
76
+ spinner?.fail(errorMessage)
77
+ // We should log the error too for consistency
78
+ context.output.error(errorMessage)
79
+ throw retryError
80
+ }
39
81
  }
40
82
  }
41
83
 
@@ -55,14 +97,19 @@ export default async function storeSchemasAction(
55
97
  args: CliCommandArguments<StoreManifestSchemasFlags>,
56
98
  context: CliCommandContext,
57
99
  ): Promise<Error | undefined> {
100
+ if (!SCHEMA_STORE_ENABLED) {
101
+ return undefined
102
+ }
103
+
58
104
  const flags = args.extOptions
59
105
 
60
106
  const schemaRequired = flags['schema-required']
61
107
  const workspaceName = flags.workspace
62
108
  const idPrefix = flags['id-prefix']
63
109
  const verbose = flags.verbose
110
+ const manifestDir = flags['manifest-dir']
64
111
 
65
- if (typeof flags.path === 'boolean') throw new Error('Path is empty')
112
+ if (typeof manifestDir === 'boolean') throw new Error('Manifest directory is empty')
66
113
  if (typeof idPrefix === 'boolean') throw new Error('Id prefix is empty')
67
114
  if (typeof workspaceName === 'boolean') throw new Error('Workspace is empty')
68
115
 
@@ -70,7 +117,7 @@ export default async function storeSchemasAction(
70
117
 
71
118
  const spinner = output.spinner({}).start('Storing schemas')
72
119
 
73
- const manifestPath = getManifestPath(context, flags.path)
120
+ const manifestPath = getManifestPath(context, manifestDir)
74
121
 
75
122
  try {
76
123
  const client = apiClient({
@@ -81,7 +128,7 @@ export default async function storeSchemasAction(
81
128
  const projectId = client.config().projectId
82
129
  if (!projectId) throw new Error('Project ID is not defined')
83
130
 
84
- const manifest = readManifest(manifestPath, output, spinner)
131
+ const manifest = await readManifest(manifestPath, context, spinner)
85
132
 
86
133
  let storedCount = 0
87
134
 
@@ -5,12 +5,14 @@ import {
5
5
  } from '@sanity/cli'
6
6
 
7
7
  import {type DeployStudioActionFlags} from '../../actions/deploy/deployAction'
8
+ import {SCHEMA_STORE_ENABLED} from '../../actions/schema/storeSchemasAction'
8
9
 
9
10
  const helpText = `
10
11
  Options
11
12
  --source-maps Enable source maps for built bundles (increases size of bundle)
12
13
  --no-minify Skip minifying built JavaScript (speeds up build, increases size of bundle)
13
14
  --no-build Don't build the application prior to deploy, instead deploying the version currently in \`dist/\`
15
+ ${SCHEMA_STORE_ENABLED ? '--verbose Enable verbose logging for the schema store' : ''}
14
16
  -y, --yes Unattended mode, answers "yes" to any "yes/no" prompt and otherwise uses defaults
15
17
 
16
18
  Examples
@@ -1,5 +1,6 @@
1
1
  import {type CliCommandDefinition, type CliCommandGroupDefinition} from '@sanity/cli'
2
2
 
3
+ import {SCHEMA_STORE_ENABLED} from '../actions/schema/storeSchemasAction'
3
4
  import appGroup from './app/appGroup'
4
5
  import appBuildCommand from './app/buildCommand'
5
6
  import appDeployCommand from './app/deployCommand'
@@ -62,7 +63,8 @@ import inviteUserCommand from './users/inviteUserCommand'
62
63
  import listUsersCommand from './users/listUsersCommand'
63
64
  import usersGroup from './users/usersGroup'
64
65
 
65
- const commands: (CliCommandDefinition | CliCommandGroupDefinition)[] = [
66
+ // Base commands that are always included
67
+ const baseCommands: (CliCommandDefinition | CliCommandGroupDefinition)[] = [
66
68
  appGroup,
67
69
  appDeployCommand,
68
70
  appDevCommand,
@@ -118,12 +120,18 @@ const commands: (CliCommandDefinition | CliCommandGroupDefinition)[] = [
118
120
  validateSchemaCommand,
119
121
  extractSchemaCommand,
120
122
  previewCommand,
121
- fetchSchemaCommand,
122
- storeSchemaCommand,
123
123
  execCommand,
124
124
  manifestGroup,
125
125
  extractManifestCommand,
126
- deleteSchemaCommand,
126
+ ]
127
+
128
+ // Internal schema commands that are only included when enabled
129
+ const internalSchemaCommands = [fetchSchemaCommand, storeSchemaCommand, deleteSchemaCommand]
130
+
131
+ // Include experimental commands only when the feature flag is enabled
132
+ const commands: (CliCommandDefinition | CliCommandGroupDefinition)[] = [
133
+ ...baseCommands,
134
+ ...(SCHEMA_STORE_ENABLED ? internalSchemaCommands : []),
127
135
  ]
128
136
 
129
137
  /**
@@ -10,7 +10,7 @@ const helpText = `
10
10
  Options
11
11
  --ids <schema_id_1,schema_id_2,...> comma-separated list of schema IDs to delete
12
12
  --dataset <dataset_name> delete schemas from a specific dataset
13
- --path <path> path to the manifest file if it is not in the default location
13
+ --manifest-dir <directory> directory containing your manifest file if it's not in the default location
14
14
 
15
15
  Examples
16
16
  # Delete single schema
@@ -10,7 +10,7 @@ const helpText = `
10
10
  Options
11
11
  --json get schemas as json
12
12
  --id <schema_id> fetch a specific schema by its ID
13
- --path <path> path to your manifest file if it's not in the default location
13
+ --manifest-dir <directory> directory containing your manifest file if it's not in the default location
14
14
 
15
15
  Examples
16
16
  # Get full json schemas
@@ -2,16 +2,17 @@ import {type CliCommandArguments, type CliCommandDefinition} from '@sanity/cli'
2
2
 
3
3
  import {type StoreManifestSchemasFlags} from '../../actions/schema/storeSchemasAction'
4
4
 
5
- const description = 'Store schemas into the current dataset.'
5
+ const description = 'Store schemas into workspace datasets.'
6
6
 
7
7
  const helpText = `
8
8
  **Note**: This command is experimental and subject to change.
9
9
 
10
10
  Options:
11
- --workspace The name of the workspace to fetch the stored schema for
12
- --path If you are not using the default static file path, you can specify it here.
13
- --id-prefix you can specify a custom id prefix for the stored schemas. Useful if you want to store the schema in a different path than the default one.
14
- --verbose Enable verbose logging
11
+ --workspace <workspace_name> store schema for a specific workspace
12
+ --manifest-dir <directory> directory containing your manifest file if it's not in the default location
13
+ --id-prefix <prefix> add a prefix to the schema ID
14
+ --schema-required fail if schema file is not found
15
+ --verbose print detailed information during store
15
16
 
16
17
  Examples
17
18
  # if no options are provided all workspace schemas will be stored
@@ -1,99 +0,0 @@
1
- "use strict";
2
- var node_crypto = require("node:crypto"), fs = require("node:fs/promises"), path = require("node:path"), node_worker_threads = require("node:worker_threads"), chalk = require("chalk"), dateFns = require("date-fns"), readPkgUp = require("read-pkg-up"), timing = require("./timing.js");
3
- function _interopDefaultCompat(e) {
4
- return e && typeof e == "object" && "default" in e ? e : { default: e };
5
- }
6
- var chalk__default = /* @__PURE__ */ _interopDefaultCompat(chalk), readPkgUp__default = /* @__PURE__ */ _interopDefaultCompat(readPkgUp);
7
- const MANIFEST_FILENAME = "create-manifest.json", SCHEMA_FILENAME_SUFFIX = ".create-schema.json", TOOLS_FILENAME_SUFFIX = ".create-tools.json", FEATURE_ENABLED_ENV_NAME = "SANITY_CLI_EXTRACT_MANIFEST_ENABLED", EXTRACT_MANIFEST_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] !== "false", EXTRACT_MANIFEST_LOG_ERRORS = process.env.SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS === "true", CREATE_TIMER = "create-manifest", EXTRACT_TASK_TIMEOUT_MS = dateFns.minutesToMilliseconds(2), EXTRACT_FAILURE_MESSAGE = `\u21B3 Couldn't extract manifest file. Sanity Create will not be available for the studio.
8
- Disable this message with ${FEATURE_ENABLED_ENV_NAME}=false`;
9
- async function extractManifestSafe(args, context) {
10
- if (EXTRACT_MANIFEST_ENABLED)
11
- try {
12
- await extractManifest(args, context);
13
- return;
14
- } catch (err) {
15
- return EXTRACT_MANIFEST_LOG_ERRORS && context.output.error(err), err;
16
- }
17
- }
18
- async function extractManifest(args, context) {
19
- const {
20
- output,
21
- workDir
22
- } = context, flags = args.extOptions, defaultOutputDir = path.resolve(path.join(workDir, "dist")), outputDir = path.resolve(defaultOutputDir), defaultStaticPath = path.join(outputDir, "static"), staticPath = flags.path ?? defaultStaticPath, path$1 = path.join(staticPath, MANIFEST_FILENAME), rootPkgPath = readPkgUp__default.default.sync({
23
- cwd: __dirname
24
- })?.path;
25
- if (!rootPkgPath)
26
- throw new Error("Could not find root directory for `sanity` package");
27
- const timer = timing.getTimer();
28
- timer.start(CREATE_TIMER);
29
- const spinner = output.spinner({}).start("Extracting manifest");
30
- try {
31
- const workspaceManifests = await getWorkspaceManifests({
32
- rootPkgPath,
33
- workDir
34
- });
35
- await fs.mkdir(staticPath, {
36
- recursive: !0
37
- });
38
- const workspaceFiles = await writeWorkspaceFiles(workspaceManifests, staticPath), manifest = {
39
- /**
40
- * Version history:
41
- * 1: Initial release.
42
- * 2: Added tools file.
43
- */
44
- version: 2,
45
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
46
- workspaces: workspaceFiles
47
- };
48
- await fs.writeFile(path$1, JSON.stringify(manifest, null, 2));
49
- const manifestDuration = timer.end(CREATE_TIMER);
50
- spinner.succeed(`Extracted manifest (${manifestDuration.toFixed()}ms)`);
51
- } catch (err) {
52
- throw spinner.fail(err.message), output.print(chalk__default.default.gray(EXTRACT_FAILURE_MESSAGE)), err;
53
- }
54
- }
55
- async function getWorkspaceManifests({
56
- rootPkgPath,
57
- workDir
58
- }) {
59
- const workerPath = path.join(path.dirname(rootPkgPath), "lib", "_internal", "cli", "threads", "extractManifest.js"), worker = new node_worker_threads.Worker(workerPath, {
60
- workerData: {
61
- workDir
62
- },
63
- // eslint-disable-next-line no-process-env
64
- env: process.env
65
- });
66
- let timeout = !1;
67
- const timeoutId = setTimeout(() => {
68
- timeout = !0, worker.terminate();
69
- }, EXTRACT_TASK_TIMEOUT_MS);
70
- try {
71
- return await new Promise((resolveWorkspaces, reject) => {
72
- const buffer = [];
73
- worker.addListener("message", (message) => buffer.push(message)), worker.addListener("exit", (exitCode) => {
74
- exitCode === 0 ? resolveWorkspaces(buffer) : timeout && reject(new Error(`Extract manifest was aborted after ${EXTRACT_TASK_TIMEOUT_MS}ms`));
75
- }), worker.addListener("error", reject);
76
- });
77
- } finally {
78
- clearTimeout(timeoutId);
79
- }
80
- }
81
- function writeWorkspaceFiles(manifestWorkspaces, staticPath) {
82
- const output = manifestWorkspaces.reduce((workspaces, workspace) => [...workspaces, writeWorkspaceFile(workspace, staticPath)], []);
83
- return Promise.all(output);
84
- }
85
- async function writeWorkspaceFile(workspace, staticPath) {
86
- const [schemaFilename, toolsFilename] = await Promise.all([createFile(staticPath, workspace.schema, SCHEMA_FILENAME_SUFFIX), createFile(staticPath, workspace.tools, TOOLS_FILENAME_SUFFIX)]);
87
- return {
88
- ...workspace,
89
- schema: schemaFilename,
90
- tools: toolsFilename
91
- };
92
- }
93
- const createFile = async (path$1, content, filenameSuffix) => {
94
- const stringifiedContent = JSON.stringify(content, null, 2), filename = `${node_crypto.createHash("sha1").update(stringifiedContent).digest("hex").slice(0, 8)}${filenameSuffix}`;
95
- return await fs.writeFile(path.join(path$1, filename), stringifiedContent), filename;
96
- };
97
- exports.MANIFEST_FILENAME = MANIFEST_FILENAME;
98
- exports.extractManifestSafe = extractManifestSafe;
99
- //# sourceMappingURL=extractManifestAction.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractManifestAction.js","sources":["../../src/_internal/cli/actions/manifest/extractManifestAction.ts"],"sourcesContent":["import {createHash} from 'node:crypto'\nimport {mkdir, writeFile} from 'node:fs/promises'\nimport {dirname, join, resolve} from 'node:path'\nimport {Worker} from 'node:worker_threads'\n\nimport {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'\nimport chalk from 'chalk'\nimport {minutesToMilliseconds} from 'date-fns'\nimport readPkgUp from 'read-pkg-up'\n\nimport {\n type CreateManifest,\n type CreateWorkspaceManifest,\n type ManifestWorkspaceFile,\n} from '../../../manifest/manifestTypes'\nimport {type ExtractManifestWorkerData} from '../../threads/extractManifest'\nimport {getTimer} from '../../util/timing'\n\nexport const MANIFEST_FILENAME = 'create-manifest.json'\nconst SCHEMA_FILENAME_SUFFIX = '.create-schema.json'\nconst TOOLS_FILENAME_SUFFIX = '.create-tools.json'\n\n/** Escape-hatch env flags to change action behavior */\nconst FEATURE_ENABLED_ENV_NAME = 'SANITY_CLI_EXTRACT_MANIFEST_ENABLED'\nconst EXTRACT_MANIFEST_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] !== 'false'\nconst EXTRACT_MANIFEST_LOG_ERRORS = process.env.SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS === 'true'\n\nconst CREATE_TIMER = 'create-manifest'\n\nconst EXTRACT_TASK_TIMEOUT_MS = minutesToMilliseconds(2)\n\nconst EXTRACT_FAILURE_MESSAGE =\n \"↳ Couldn't extract manifest file. Sanity Create will not be available for the studio.\\n\" +\n ` Disable this message with ${FEATURE_ENABLED_ENV_NAME}=false`\n\ninterface ExtractFlags {\n path?: string\n}\n\n/**\n * This function will never throw.\n * @returns `undefined` if extract succeeded - caught error if it failed\n */\nexport async function extractManifestSafe(\n args: CliCommandArguments<ExtractFlags>,\n context: CliCommandContext,\n): Promise<Error | undefined> {\n if (!EXTRACT_MANIFEST_ENABLED) {\n return undefined\n }\n\n try {\n await extractManifest(args, context)\n return undefined\n } catch (err) {\n if (EXTRACT_MANIFEST_LOG_ERRORS) {\n context.output.error(err)\n }\n return err\n }\n}\n\nasync function extractManifest(\n args: CliCommandArguments<ExtractFlags>,\n context: CliCommandContext,\n): Promise<void> {\n const {output, workDir} = context\n\n const flags = args.extOptions\n const defaultOutputDir = resolve(join(workDir, 'dist'))\n\n const outputDir = resolve(defaultOutputDir)\n const defaultStaticPath = join(outputDir, 'static')\n\n const staticPath = flags.path ?? defaultStaticPath\n\n const path = join(staticPath, MANIFEST_FILENAME)\n\n const rootPkgPath = readPkgUp.sync({cwd: __dirname})?.path\n if (!rootPkgPath) {\n throw new Error('Could not find root directory for `sanity` package')\n }\n\n const timer = getTimer()\n timer.start(CREATE_TIMER)\n const spinner = output.spinner({}).start('Extracting manifest')\n\n try {\n const workspaceManifests = await getWorkspaceManifests({rootPkgPath, workDir})\n await mkdir(staticPath, {recursive: true})\n\n const workspaceFiles = await writeWorkspaceFiles(workspaceManifests, staticPath)\n\n const manifest: CreateManifest = {\n /**\n * Version history:\n * 1: Initial release.\n * 2: Added tools file.\n */\n version: 2,\n createdAt: new Date().toISOString(),\n workspaces: workspaceFiles,\n }\n\n await writeFile(path, JSON.stringify(manifest, null, 2))\n const manifestDuration = timer.end(CREATE_TIMER)\n\n spinner.succeed(`Extracted manifest (${manifestDuration.toFixed()}ms)`)\n } catch (err) {\n spinner.fail(err.message)\n output.print(chalk.gray(EXTRACT_FAILURE_MESSAGE))\n throw err\n }\n}\n\nasync function getWorkspaceManifests({\n rootPkgPath,\n workDir,\n}: {\n rootPkgPath: string\n workDir: string\n}): Promise<CreateWorkspaceManifest[]> {\n const workerPath = join(\n dirname(rootPkgPath),\n 'lib',\n '_internal',\n 'cli',\n 'threads',\n 'extractManifest.js',\n )\n\n const worker = new Worker(workerPath, {\n workerData: {workDir} satisfies ExtractManifestWorkerData,\n // eslint-disable-next-line no-process-env\n env: process.env,\n })\n\n let timeout = false\n const timeoutId = setTimeout(() => {\n timeout = true\n worker.terminate()\n }, EXTRACT_TASK_TIMEOUT_MS)\n\n try {\n return await new Promise<CreateWorkspaceManifest[]>((resolveWorkspaces, reject) => {\n const buffer: CreateWorkspaceManifest[] = []\n worker.addListener('message', (message) => buffer.push(message))\n worker.addListener('exit', (exitCode) => {\n if (exitCode === 0) {\n resolveWorkspaces(buffer)\n } else if (timeout) {\n reject(new Error(`Extract manifest was aborted after ${EXTRACT_TASK_TIMEOUT_MS}ms`))\n }\n })\n worker.addListener('error', reject)\n })\n } finally {\n clearTimeout(timeoutId)\n }\n}\n\nfunction writeWorkspaceFiles(\n manifestWorkspaces: CreateWorkspaceManifest[],\n staticPath: string,\n): Promise<ManifestWorkspaceFile[]> {\n const output = manifestWorkspaces.reduce<Promise<ManifestWorkspaceFile>[]>(\n (workspaces, workspace) => {\n return [...workspaces, writeWorkspaceFile(workspace, staticPath)]\n },\n [],\n )\n return Promise.all(output)\n}\n\nasync function writeWorkspaceFile(\n workspace: CreateWorkspaceManifest,\n staticPath: string,\n): Promise<ManifestWorkspaceFile> {\n const [schemaFilename, toolsFilename] = await Promise.all([\n createFile(staticPath, workspace.schema, SCHEMA_FILENAME_SUFFIX),\n createFile(staticPath, workspace.tools, TOOLS_FILENAME_SUFFIX),\n ])\n\n return {\n ...workspace,\n schema: schemaFilename,\n tools: toolsFilename,\n }\n}\n\nconst createFile = async (path: string, content: any, filenameSuffix: string) => {\n const stringifiedContent = JSON.stringify(content, null, 2)\n const hash = createHash('sha1').update(stringifiedContent).digest('hex')\n const filename = `${hash.slice(0, 8)}${filenameSuffix}`\n\n // workspaces with identical data will overwrite each others file. This is ok, since they are identical and can be shared\n await writeFile(join(path, filename), stringifiedContent)\n\n return filename\n}\n"],"names":["MANIFEST_FILENAME","SCHEMA_FILENAME_SUFFIX","TOOLS_FILENAME_SUFFIX","FEATURE_ENABLED_ENV_NAME","EXTRACT_MANIFEST_ENABLED","process","env","EXTRACT_MANIFEST_LOG_ERRORS","SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS","CREATE_TIMER","EXTRACT_TASK_TIMEOUT_MS","minutesToMilliseconds","EXTRACT_FAILURE_MESSAGE","extractManifestSafe","args","context","extractManifest","err","output","error","workDir","flags","extOptions","defaultOutputDir","resolve","join","outputDir","defaultStaticPath","staticPath","path","rootPkgPath","readPkgUp","sync","cwd","__dirname","Error","timer","getTimer","start","spinner","workspaceManifests","getWorkspaceManifests","mkdir","recursive","workspaceFiles","writeWorkspaceFiles","manifest","version","createdAt","Date","toISOString","workspaces","writeFile","JSON","stringify","manifestDuration","end","succeed","toFixed","fail","message","print","chalk","gray","workerPath","dirname","worker","Worker","workerData","timeout","timeoutId","setTimeout","terminate","Promise","resolveWorkspaces","reject","buffer","addListener","push","exitCode","clearTimeout","manifestWorkspaces","reduce","workspace","writeWorkspaceFile","all","schemaFilename","toolsFilename","createFile","schema","tools","content","filenameSuffix","stringifiedContent","filename","createHash","update","digest","slice"],"mappings":"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"}
@@ -1,147 +0,0 @@
1
- "use strict";
2
- var fs = require("node:fs"), path = require("node:path"), chalk = require("chalk"), extractManifestAction = require("./extractManifestAction.js"), size = require("lodash/size.js"), sortBy = require("lodash/sortBy.js"), uniqBy = require("lodash/uniqBy.js");
3
- function _interopDefaultCompat(e) {
4
- return e && typeof e == "object" && "default" in e ? e : { default: e };
5
- }
6
- var path__default = /* @__PURE__ */ _interopDefaultCompat(path), chalk__default = /* @__PURE__ */ _interopDefaultCompat(chalk), size__default = /* @__PURE__ */ _interopDefaultCompat(size), sortBy__default = /* @__PURE__ */ _interopDefaultCompat(sortBy), uniqBy__default = /* @__PURE__ */ _interopDefaultCompat(uniqBy);
7
- const SANITY_WORKSPACE_SCHEMA_TYPE = "sanity.workspace.schema", printSchemaList = ({
8
- schemas,
9
- output
10
- }) => {
11
- const ordered = sortBy__default.default(schemas.map(({
12
- _createdAt: createdAt,
13
- _id: id,
14
- workspace
15
- }) => [id, workspace.name, workspace.dataset, workspace.projectId, createdAt].map(String)), ["createdAt"]), headings = ["Id", "Workspace", "Dataset", "ProjectId", "CreatedAt"], rows = ordered.reverse(), maxWidths = rows.reduce((max, row) => row.map((current, index) => Math.max(size__default.default(current), max[index])), headings.map((str) => size__default.default(str))), printRow = (row) => row.map((col, i) => `${col}`.padEnd(maxWidths[i])).join(" ");
16
- output.print(chalk__default.default.cyan(printRow(headings))), rows.forEach((row) => output.print(printRow(row)));
17
- };
18
- async function fetchSchemaAction(args, context) {
19
- const flags = args.extOptions, {
20
- apiClient,
21
- output
22
- } = context, client = apiClient({
23
- requireUser: !0,
24
- requireProject: !0
25
- }).withConfig({
26
- apiVersion: "v2024-08-01"
27
- }), projectId = client.config().projectId;
28
- if (!projectId) {
29
- output.error("Project ID must be defined.");
30
- return;
31
- }
32
- const manifestPath = getManifestPath(context, flags.path), manifest = readManifest(manifestPath, output), schemas = (await Promise.allSettled(uniqBy__default.default(manifest.workspaces, "dataset").map(async (workspace) => (throwIfProjectIdMismatch(workspace, projectId), flags.id ? await client.withConfig({
33
- dataset: workspace.dataset,
34
- projectId: workspace.projectId
35
- }).getDocument(flags.id) : await client.withConfig({
36
- dataset: workspace.dataset,
37
- projectId: workspace.projectId,
38
- useCdn: !1
39
- }).fetch("*[_type == $type]", {
40
- type: SANITY_WORKSPACE_SCHEMA_TYPE
41
- }))))).map((result, index) => {
42
- if (result.status === "rejected") {
43
- const workspace = manifest.workspaces[index];
44
- return output.error(chalk__default.default.red(`Failed to fetch schemas for workspace '${workspace.name}': ${result.reason.message}`)), [];
45
- }
46
- return result.value;
47
- }).flat();
48
- if (schemas.length === 0) {
49
- output.error("No schemas found");
50
- return;
51
- }
52
- flags.json ? output.print(`${JSON.stringify(flags.id ? schemas[0] : schemas, null, 2)}`) : printSchemaList({
53
- schemas,
54
- output
55
- });
56
- }
57
- var schemaListAction = /* @__PURE__ */ Object.freeze({
58
- __proto__: null,
59
- SANITY_WORKSPACE_SCHEMA_TYPE,
60
- default: fetchSchemaAction
61
- });
62
- const getManifestPath = (context, customPath) => {
63
- const defaultOutputDir = path.resolve(path.join(context.workDir, "dist")), outputDir = path.resolve(defaultOutputDir), defaultStaticPath = path.join(outputDir, "static"), staticPath = customPath ?? defaultStaticPath;
64
- return path__default.default.resolve(process.cwd(), staticPath);
65
- }, readManifest = (readPath, output, spinner) => {
66
- try {
67
- return JSON.parse(fs.readFileSync(`${readPath}/${extractManifestAction.MANIFEST_FILENAME}`, "utf-8"));
68
- } catch (error) {
69
- const errorMessage = `Manifest not found at ${readPath}/${extractManifestAction.MANIFEST_FILENAME}`;
70
- throw spinner && spinner.fail(errorMessage), output && output.error(errorMessage), error;
71
- }
72
- }, throwIfProjectIdMismatch = (workspace, projectId) => {
73
- if (workspace.projectId !== projectId)
74
- throw new Error(`\u21B3 No permissions to store schema for workspace ${workspace.name} with projectId: ${workspace.projectId}`);
75
- };
76
- async function storeSchemasAction(args, context) {
77
- const flags = args.extOptions, schemaRequired = flags["schema-required"], workspaceName = flags.workspace, idPrefix = flags["id-prefix"], verbose = flags.verbose;
78
- if (typeof flags.path == "boolean") throw new Error("Path is empty");
79
- if (typeof idPrefix == "boolean") throw new Error("Id prefix is empty");
80
- if (typeof workspaceName == "boolean") throw new Error("Workspace is empty");
81
- const {
82
- output,
83
- apiClient
84
- } = context, spinner = output.spinner({}).start("Storing schemas"), manifestPath = getManifestPath(context, flags.path);
85
- try {
86
- const client = apiClient({
87
- requireUser: !0,
88
- requireProject: !0
89
- }).withConfig({
90
- apiVersion: "v2024-08-01"
91
- }), projectId = client.config().projectId;
92
- if (!projectId) throw new Error("Project ID is not defined");
93
- const manifest = readManifest(manifestPath, output, spinner);
94
- let storedCount = 0, error;
95
- const saveSchema = async (workspace) => {
96
- const id = `${idPrefix ? `${idPrefix}.` : ""}${SANITY_WORKSPACE_SCHEMA_TYPE}.${workspace.name}`;
97
- try {
98
- throwIfProjectIdMismatch(workspace, projectId);
99
- const schema = JSON.parse(fs.readFileSync(`${manifestPath}/${workspace.schema}`, "utf-8"));
100
- await client.withConfig({
101
- dataset: workspace.dataset,
102
- projectId: workspace.projectId
103
- }).transaction().createOrReplace({
104
- _type: SANITY_WORKSPACE_SCHEMA_TYPE,
105
- _id: id,
106
- workspace,
107
- schema
108
- }).commit(), storedCount++, spinner.text = `Stored ${storedCount} schemas so far...`, verbose && spinner.succeed(`Schema stored for workspace '${workspace.name}'`);
109
- } catch (err) {
110
- if (error = err, spinner.fail(`Error storing schema for workspace '${workspace.name}':
111
- ${chalk__default.default.red(`${err.message}`)}`), schemaRequired) throw err;
112
- } finally {
113
- verbose && output.print(chalk__default.default.gray(`\u21B3 schemaId: ${id}, projectId: ${projectId}, dataset: ${workspace.dataset}`));
114
- }
115
- };
116
- if (workspaceName) {
117
- const workspaceToSave = manifest.workspaces.find((workspace) => workspace.name === workspaceName);
118
- if (!workspaceToSave)
119
- throw spinner.fail(`Workspace ${workspaceName} not found in manifest`), new Error(`Workspace ${workspaceName} not found in manifest: projectID: ${projectId}`);
120
- await saveSchema(workspaceToSave), spinner.succeed("Stored 1 schemas");
121
- } else
122
- await Promise.all(manifest.workspaces.map(async (workspace) => {
123
- await saveSchema(workspace);
124
- })), spinner.succeed(`Stored ${storedCount}/${manifest.workspaces.length} schemas`);
125
- if (error) throw error;
126
- return;
127
- } catch (err) {
128
- if (schemaRequired) throw err;
129
- return err;
130
- } finally {
131
- output.print(`${chalk__default.default.gray("\u21B3 List stored schemas with:")} ${chalk__default.default.cyan("sanity schema list")}`);
132
- }
133
- }
134
- var storeSchemasAction$1 = /* @__PURE__ */ Object.freeze({
135
- __proto__: null,
136
- default: storeSchemasAction,
137
- getManifestPath,
138
- readManifest,
139
- throwIfProjectIdMismatch
140
- });
141
- exports.getManifestPath = getManifestPath;
142
- exports.readManifest = readManifest;
143
- exports.schemaListAction = schemaListAction;
144
- exports.storeSchemasAction = storeSchemasAction;
145
- exports.storeSchemasAction$1 = storeSchemasAction$1;
146
- exports.throwIfProjectIdMismatch = throwIfProjectIdMismatch;
147
- //# sourceMappingURL=storeSchemasAction.js.map