@sanity/cli 8.22.1 → 8.24.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.
Files changed (98) hide show
  1. package/README.md +313 -0
  2. package/dist/actions/codemods/dashboard.js +136 -8
  3. package/dist/actions/codemods/dashboard.js.map +1 -1
  4. package/dist/actions/codemods/types.js.map +1 -1
  5. package/dist/actions/context/watchJob.js +9 -3
  6. package/dist/actions/context/watchJob.js.map +1 -1
  7. package/dist/actions/deploy/blueprintManaged.js +59 -0
  8. package/dist/actions/deploy/blueprintManaged.js.map +1 -0
  9. package/dist/actions/deploy/deployApp.js +117 -1
  10. package/dist/actions/deploy/deployApp.js.map +1 -1
  11. package/dist/actions/deploy/deployRunner.js.map +1 -1
  12. package/dist/actions/deploy/deployStudio.js +6 -31
  13. package/dist/actions/deploy/deployStudio.js.map +1 -1
  14. package/dist/actions/exec/runScript.worker.js +6 -2
  15. package/dist/actions/exec/runScript.worker.js.map +1 -1
  16. package/dist/actions/init/bootstrapLocalTemplate.js +35 -11
  17. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  18. package/dist/actions/init/createMediaLibraryCliConfig.js +12 -0
  19. package/dist/actions/init/createMediaLibraryCliConfig.js.map +1 -0
  20. package/dist/actions/init/determineMediaLibraryTemplate.js +14 -0
  21. package/dist/actions/init/determineMediaLibraryTemplate.js.map +1 -0
  22. package/dist/actions/init/initAction.js +35 -6
  23. package/dist/actions/init/initAction.js.map +1 -1
  24. package/dist/actions/init/initApp.js +81 -6
  25. package/dist/actions/init/initApp.js.map +1 -1
  26. package/dist/actions/init/offerAspectPull.js +81 -0
  27. package/dist/actions/init/offerAspectPull.js.map +1 -0
  28. package/dist/actions/init/project/getOrCreateDataset.js +8 -5
  29. package/dist/actions/init/project/getOrCreateDataset.js.map +1 -1
  30. package/dist/actions/init/project/getOrCreateProject.js +7 -5
  31. package/dist/actions/init/project/getOrCreateProject.js.map +1 -1
  32. package/dist/actions/init/project/getProjectDetails.js +25 -2
  33. package/dist/actions/init/project/getProjectDetails.js.map +1 -1
  34. package/dist/actions/init/project/promptUserForOrganization.js +6 -4
  35. package/dist/actions/init/project/promptUserForOrganization.js.map +1 -1
  36. package/dist/actions/init/templates/index.js +3 -0
  37. package/dist/actions/init/templates/index.js.map +1 -1
  38. package/dist/actions/init/templates/mediaLibraryConfig.js +51 -0
  39. package/dist/actions/init/templates/mediaLibraryConfig.js.map +1 -0
  40. package/dist/actions/media/aspectName.js +8 -0
  41. package/dist/actions/media/aspectName.js.map +1 -0
  42. package/dist/actions/media/aspectSync/contract.js +163 -0
  43. package/dist/actions/media/aspectSync/contract.js.map +1 -0
  44. package/dist/actions/media/aspectSync/syncAspects.js +115 -0
  45. package/dist/actions/media/aspectSync/syncAspects.js.map +1 -0
  46. package/dist/actions/media/cliConfigFields.js +192 -0
  47. package/dist/actions/media/cliConfigFields.js.map +1 -0
  48. package/dist/actions/media/pullAspects.js +225 -0
  49. package/dist/actions/media/pullAspects.js.map +1 -0
  50. package/dist/actions/media/resolveMediaLibraryId.js +83 -0
  51. package/dist/actions/media/resolveMediaLibraryId.js.map +1 -0
  52. package/dist/commands/codemod.js +1 -0
  53. package/dist/commands/codemod.js.map +1 -1
  54. package/dist/commands/context/build.js +2 -2
  55. package/dist/commands/context/build.js.map +1 -1
  56. package/dist/commands/context/entries/get.js +83 -0
  57. package/dist/commands/context/entries/get.js.map +1 -0
  58. package/dist/commands/context/entries/list.js +82 -0
  59. package/dist/commands/context/entries/list.js.map +1 -0
  60. package/dist/commands/context/entries/rebuild.js +95 -0
  61. package/dist/commands/context/entries/rebuild.js.map +1 -0
  62. package/dist/commands/context/issues/apply.js +86 -0
  63. package/dist/commands/context/issues/apply.js.map +1 -0
  64. package/dist/commands/context/issues/dismiss.js +52 -0
  65. package/dist/commands/context/issues/dismiss.js.map +1 -0
  66. package/dist/commands/context/issues/get.js +105 -0
  67. package/dist/commands/context/issues/get.js.map +1 -0
  68. package/dist/commands/context/issues/list.js +128 -0
  69. package/dist/commands/context/issues/list.js.map +1 -0
  70. package/dist/commands/context/issues/reopen.js +53 -0
  71. package/dist/commands/context/issues/reopen.js.map +1 -0
  72. package/dist/commands/context/issues/resolve.js +137 -0
  73. package/dist/commands/context/issues/resolve.js.map +1 -0
  74. package/dist/commands/context/jobs/get.js +2 -2
  75. package/dist/commands/context/jobs/get.js.map +1 -1
  76. package/dist/commands/context/query.js +92 -0
  77. package/dist/commands/context/query.js.map +1 -0
  78. package/dist/commands/deploy.js +13 -0
  79. package/dist/commands/deploy.js.map +1 -1
  80. package/dist/commands/media/prune-aspect-data.js +170 -0
  81. package/dist/commands/media/prune-aspect-data.js.map +1 -0
  82. package/dist/commands/media/pull-aspects.js +309 -0
  83. package/dist/commands/media/pull-aspects.js.map +1 -0
  84. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +17 -0
  85. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
  86. package/dist/services/context.js +96 -3
  87. package/dist/services/context.js.map +1 -1
  88. package/dist/services/mediaLibraries.js +175 -8
  89. package/dist/services/mediaLibraries.js.map +1 -1
  90. package/dist/util/searchChoices.js +52 -0
  91. package/dist/util/searchChoices.js.map +1 -0
  92. package/oclif.manifest.json +2134 -1445
  93. package/package.json +9 -8
  94. package/templates/media-library-config/README.md +52 -0
  95. package/templates/media-library-config/eslint.config.txt +52 -0
  96. package/templates/media-library-config/src/fields/caption.tsx +29 -0
  97. package/templates/media-library-config/src/fields/notes.tsx +54 -0
  98. package/templates/shopify/.gitignore +0 -26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/cli",
3
- "version": "8.22.1",
3
+ "version": "8.24.0",
4
4
  "description": "Sanity CLI tool for managing Sanity projects and organizations",
5
5
  "keywords": [
6
6
  "cli",
@@ -63,8 +63,8 @@
63
63
  "@oclif/plugin-help": "^6.2.53",
64
64
  "@oclif/plugin-not-found": "^3.2.88",
65
65
  "@sanity/blueprints": "^0.28.0",
66
- "@sanity/cli-build": "^7.0.0",
67
- "@sanity/cli-core": "^3.11.1",
66
+ "@sanity/cli-build": "^7.0.2",
67
+ "@sanity/cli-core": "^3.13.0",
68
68
  "@sanity/client": "^8.9.0",
69
69
  "@sanity/codegen": "^8.2.0",
70
70
  "@sanity/descriptors": "^1.3.0",
@@ -73,20 +73,20 @@
73
73
  "@sanity/id-utils": "^1.1.0",
74
74
  "@sanity/import": "^7.0.4",
75
75
  "@sanity/migrate": "^8.0.5",
76
- "@sanity/runtime-cli": "17.15.0",
76
+ "@sanity/runtime-cli": "^17.16.0",
77
77
  "@sanity/schema": "^6.17.0",
78
78
  "@sanity/schema-descriptor-utils": "^1.3.3",
79
79
  "@sanity/telemetry": "^1.1.0",
80
80
  "@sanity/template-validator": "^3.1.1",
81
81
  "@sanity/types": "^6.17.0",
82
- "@sanity/workbench-cli": "^2.13.0",
82
+ "@sanity/workbench-cli": "^2.14.0",
83
83
  "@sanity/worker-channels": "^2.0.0",
84
84
  "@sanity/workflow-cli": "0.36.0",
85
85
  "@sanity/workflow-engine": "0.36.0",
86
86
  "@vercel/frameworks": "3.29.0",
87
87
  "chokidar": "^5.0.0",
88
88
  "console-table-printer": "^2.15.0",
89
- "eventsource": "^5.1.1",
89
+ "eventsource": "^5.1.3",
90
90
  "execa": "^10.0.1",
91
91
  "form-data": "^4.0.5",
92
92
  "get-latest-version": "^6.0.1",
@@ -126,9 +126,10 @@
126
126
  },
127
127
  "devDependencies": {
128
128
  "@eslint/compat": "^2.1.0",
129
+ "@oxc-project/types": "0.152.0",
129
130
  "@repo/package.config": "0.0.1",
130
131
  "@repo/tsconfig": "3.70.0",
131
- "@sanity/cli-test": "21.0.1",
132
+ "@sanity/cli-test": "23.0.0",
132
133
  "@sanity/eslint-config-cli": "1.1.3",
133
134
  "@sanity/pkg-utils": "^12.3.4",
134
135
  "@swc/cli": "^0.8.1",
@@ -137,7 +138,7 @@
137
138
  "@types/jsdom": "^28.0.3",
138
139
  "@types/lodash-es": "^4.17.12",
139
140
  "@types/minimist": "^1.2.5",
140
- "@types/node": "^22.20.0",
141
+ "@types/node": "^22.20.5",
141
142
  "@types/picomatch": "^4.0.3",
142
143
  "@types/semver": "^7.7.1",
143
144
  "@types/tar-stream": "^3.1.4",
@@ -0,0 +1,52 @@
1
+ # Media Library config app
2
+
3
+ A **Media Library config app**: it defines custom fields (aspects) for your
4
+ organization's Sanity Media Library. It has no UI of its own — the CLI
5
+ bundles the field modules in `src/fields/` into a remote that the Media
6
+ Library loads to drive asset metadata editing.
7
+
8
+ ## Commands
9
+
10
+ - `npm run dev` starts the dev server and prints a Sanity Dashboard URL.
11
+ Open it, sign in, and go to the Media Library — the fields defined here
12
+ appear on assets, served live from your machine.
13
+ - `npm run build` builds the config for production.
14
+ - `npm run deploy` deploys the config to your organization.
15
+
16
+ ## Defining fields
17
+
18
+ Each field lives in `src/fields/<name>.tsx` as a default-exported
19
+ `defineField(...)` — the same API as Sanity Studio — and is registered in
20
+ `sanity.cli.ts` under `fields`. Two examples are included:
21
+
22
+ - `caption` — a plain field rendered by the Media Library's standard
23
+ controls, with validation and an initial value.
24
+ - `notes` — a field with a custom input component (`components.input`).
25
+
26
+ The `name` of a field must match its entry in `sanity.cli.ts`: it becomes
27
+ the key the field's data is stored under on assets.
28
+
29
+ ## Custom input components
30
+
31
+ Custom inputs render as **islands**: isolated React roots using this app's
32
+ own bundled `react`, `@sanity/ui`, and `sanity` copies — no version coupling
33
+ with the Media Library itself. The rules that keep an input working inside
34
+ an island are documented in `src/fields/notes.tsx`; the supported `sanity`
35
+ import surface is enforced at lint time by the override in
36
+ `eslint.config.mjs`. An import outside that surface has no provider inside
37
+ the island and fails at runtime.
38
+
39
+ ## Validation and initial values
40
+
41
+ Validation rules and `initialValue` resolvers are config code executed by
42
+ the Media Library. `initialValue` runs when a new asset is uploaded;
43
+ resolver functions receive `(params, context)` where `context` carries the
44
+ uploaded asset document and its instance document (e.g. image metadata).
45
+
46
+ ## Field modules must be loadable under plain Node.js
47
+
48
+ Field definitions are evaluated outside the browser when the config is
49
+ synchronized. Browser-only libraries that touch `window` at import time must
50
+ be loaded lazily from a component module
51
+ (`lazy(() => import('./MapInput'))`), never imported at the top of a field
52
+ module.
@@ -0,0 +1,52 @@
1
+ import studio from '@sanity/eslint-config-studio'
2
+ import tseslint from 'typescript-eslint'
3
+
4
+ export default [
5
+ ...studio,
6
+ {
7
+ files: ['src/fields/**'],
8
+ // Flat config does not merge plugin registrations across config objects,
9
+ // so the plugin must be declared here even though the studio config also
10
+ // registers it (same module instance, so no redefinition conflict).
11
+ plugins: {'@typescript-eslint': tseslint.plugin},
12
+ rules: {
13
+ // The supported `sanity` surface for Media Library field modules.
14
+ // Custom inputs render in an isolated island root: imports outside
15
+ // this list have no provider there and fail at runtime with the
16
+ // field-failure card. Type-only imports are erased at build time and
17
+ // always safe.
18
+ '@typescript-eslint/no-restricted-imports': [
19
+ 'error',
20
+ {
21
+ paths: [
22
+ {
23
+ name: 'sanity',
24
+ allowImportNames: [
25
+ 'defineField',
26
+ 'defineArrayMember',
27
+ 'defineType',
28
+ 'set',
29
+ 'unset',
30
+ 'setIfMissing',
31
+ 'useFormValue',
32
+ 'useGetFormValue',
33
+ 'useCurrentLocale',
34
+ 'useDateTimeFormat',
35
+ ],
36
+ allowTypeImports: true,
37
+ message:
38
+ 'Not part of the supported Media Library field surface. Custom inputs render in an isolated island: this import has no provider there and will show the field-failure card at runtime. Call onChange with plain patches (set/unset), never PatchEvent.',
39
+ },
40
+ ],
41
+ patterns: [
42
+ {
43
+ group: ['sanity/*'],
44
+ message:
45
+ 'Subpath imports from `sanity` are internals, not part of the supported Media Library field surface.',
46
+ },
47
+ ],
48
+ },
49
+ ],
50
+ },
51
+ },
52
+ ]
@@ -0,0 +1,29 @@
1
+ import {defineField} from 'sanity'
2
+
3
+ /**
4
+ * A plain field: no custom input component, so the Media Library renders it
5
+ * with its standard aspect-form controls. Start here — most fields never
6
+ * need a custom component. The definition uses the same `defineField` API as
7
+ * Sanity Studio; validation rules and initial values run in the Media
8
+ * Library's own runtime.
9
+ */
10
+ export default defineField({
11
+ name: 'caption',
12
+ title: 'Caption',
13
+ type: 'object',
14
+ fields: [
15
+ defineField({
16
+ name: 'text',
17
+ title: 'Text',
18
+ type: 'string',
19
+ validation: (Rule) => Rule.required().error('A caption is required'),
20
+ }),
21
+ defineField({
22
+ name: 'language',
23
+ title: 'Language',
24
+ type: 'string',
25
+ options: {list: ['en', 'de', 'no']},
26
+ initialValue: 'en',
27
+ }),
28
+ ],
29
+ })
@@ -0,0 +1,54 @@
1
+ import {Stack, Text, TextArea} from '@sanity/ui'
2
+ import type {ChangeEvent, Ref} from 'react'
3
+ import {type InputProps, defineField, set, unset} from 'sanity'
4
+
5
+ /**
6
+ * A custom input component. It renders as an *island*: an isolated React
7
+ * root using this app's own bundled `react` and `@sanity/ui` copies, so
8
+ * there is no version coupling with the Media Library host.
9
+ *
10
+ * Rules that keep an input working inside the island:
11
+ *
12
+ * - Call `onChange` with plain patches (`set(...)` / `unset()`), never
13
+ * `PatchEvent.from(...)` — patches cross the island boundary as plain
14
+ * data, and a PatchEvent instance from this bundle's `sanity` copy fails
15
+ * the host's checks.
16
+ * - Wire `elementProps.id` and `elementProps.ref` onto the focusable
17
+ * control, so host-driven focus (validation links, presence) reaches it.
18
+ * - Only import the supported `sanity` surface (enforced by the override in
19
+ * `eslint.config.mjs`); other exports have no provider inside the island
20
+ * and fail at runtime with the field-failure card.
21
+ * - Keep the module loadable under plain Node.js (field definitions are
22
+ * evaluated outside the browser when the config is synchronized):
23
+ * browser-only libraries must be imported lazily from a component module.
24
+ */
25
+ function NotesInput(props: InputProps) {
26
+ const {value, onChange, elementProps} = props
27
+ const text = typeof value === 'string' ? value : ''
28
+
29
+ return (
30
+ <Stack space={2}>
31
+ <TextArea
32
+ id={elementProps?.id}
33
+ ref={elementProps?.ref as Ref<HTMLTextAreaElement>}
34
+ value={text}
35
+ rows={4}
36
+ placeholder="Add notes..."
37
+ onChange={(event: ChangeEvent<HTMLTextAreaElement>) => {
38
+ const next = event.currentTarget.value
39
+ onChange(next ? set(next) : unset())
40
+ }}
41
+ />
42
+ <Text size={1} muted>
43
+ {text.length} characters
44
+ </Text>
45
+ </Stack>
46
+ )
47
+ }
48
+
49
+ export default defineField({
50
+ name: 'notes',
51
+ title: 'Notes',
52
+ type: 'text',
53
+ components: {input: NotesInput},
54
+ })
@@ -1,26 +0,0 @@
1
- # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
-
3
- # Dependencies
4
- /node_modules
5
- /.pnp
6
- .pnp.js
7
-
8
- # Compiled Sanity Studio
9
- /dist
10
-
11
- # Temporary Sanity runtime, generated by the CLI on every dev server start
12
- /.sanity
13
-
14
- # Logs
15
- /logs
16
- *.log
17
-
18
- # Coverage directory used by testing tools
19
- /coverage
20
-
21
- # Misc
22
- .DS_Store
23
- *.pem
24
-
25
- # Typescript
26
- *.tsbuildinfo