@sanity/cli-test 0.1.0-alpha.17 → 0.2.1

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/dist/index.d.ts CHANGED
@@ -1,38 +1,39 @@
1
- import {CliConfig} from '@sanity/cli-core'
2
- import {ClientConfig} from '@sanity/client'
3
- import {CLITelemetryStore} from '@sanity/cli-core'
4
- import {Command} from '@oclif/core'
5
- import {Config} from '@oclif/core'
6
- import {Errors} from '@oclif/core'
7
- import {Hook} from '@oclif/core/hooks'
8
- import {Hooks} from '@oclif/core/hooks'
9
- import nock from 'nock'
10
- import {ProjectRootResult} from '@sanity/cli-core'
11
- import {SanityClient} from '@sanity/client'
12
- import {SanityCommand} from '@sanity/cli-core'
13
- import {TestProject} from 'vitest/node'
14
- import {vi} from 'vitest'
1
+ import { CliConfig } from "@sanity/cli-core";
2
+ import { ClientConfig } from "@sanity/client";
3
+ import { CLITelemetryStore } from "@sanity/cli-core";
4
+ import { Command } from "@oclif/core";
5
+ import { Config } from "@oclif/core";
6
+ import { Errors } from "@oclif/core";
7
+ import { Hook } from "@oclif/core/hooks";
8
+ import { Hooks } from "@oclif/core/hooks";
9
+ import nock from "nock";
10
+ import { ProjectRootResult } from "@sanity/cli-core";
11
+ import { SanityClient } from "@sanity/client";
12
+ import { SanityCommand } from "@sanity/cli-core";
13
+ import { TestProject } from "vitest/node";
14
+ import { vi } from "vitest";
15
15
 
16
16
  declare interface CaptureOptions {
17
17
  /**
18
18
  * Whether to print the output to the console
19
19
  */
20
- print?: boolean
20
+ print?: boolean;
21
21
  /**
22
22
  * Whether to strip ANSI escape codes from the output
23
23
  */
24
- stripAnsi?: boolean
25
- testNodeEnv?: string
24
+ stripAnsi?: boolean;
25
+ testNodeEnv?: string;
26
26
  }
27
27
 
28
28
  declare interface CaptureResult<T = unknown> {
29
- stderr: string
30
- stdout: string
31
- error?: Error & Partial<Errors.CLIError>
32
- result?: T
29
+ stderr: string;
30
+ stdout: string;
31
+ error?: Error & Partial<Errors.CLIError>;
32
+ result?: T;
33
33
  }
34
34
 
35
- declare type CommandClass = (new (argv: string[], config: Config) => Command) & typeof Command
35
+ declare type CommandClass = (new (argv: string[], config: Config) => Command) &
36
+ typeof Command;
36
37
 
37
38
  /**
38
39
  * Converts Unix-style paths to platform-appropriate paths.
@@ -45,7 +46,7 @@ declare type CommandClass = (new (argv: string[], config: Config) => Command) &
45
46
  * @returns Platform-appropriate path
46
47
  * @internal
47
48
  */
48
- export declare function convertToSystemPath(pathStr: string): string
49
+ export declare function convertToSystemPath(pathStr: string): string;
49
50
 
50
51
  /**
51
52
  * Creates a real Sanity client instance for testing that makes actual HTTP requests.
@@ -79,9 +80,9 @@ export declare function convertToSystemPath(pathStr: string): string
79
80
  * ```
80
81
  */
81
82
  export declare function createTestClient(options: CreateTestClientOptions): {
82
- client: SanityClient
83
- request: ReturnType<typeof vi.fn>
84
- }
83
+ client: SanityClient;
84
+ request: ReturnType<typeof vi.fn>;
85
+ };
85
86
 
86
87
  /**
87
88
  * Options for createTestClient
@@ -92,11 +93,11 @@ export declare interface CreateTestClientOptions extends ClientConfig {
92
93
  /**
93
94
  * API version for the client
94
95
  */
95
- apiVersion: string
96
+ apiVersion: string;
96
97
  /**
97
98
  * Authentication token
98
99
  */
99
- token: string
100
+ token?: string;
100
101
  }
101
102
 
102
103
  /**
@@ -107,40 +108,41 @@ export declare interface CreateTestClientOptions extends ClientConfig {
107
108
  * @param token - The token to create
108
109
  * @returns void
109
110
  */
110
- export declare function createTestToken(token: string): void
111
+ export declare function createTestToken(token: string): void;
111
112
 
112
113
  /**
113
114
  * Default fixtures bundled with the package and their options.
114
115
  *
115
116
  * @public
116
117
  */
117
- export declare const DEFAULT_FIXTURES: Record<FixtureName, FixtureOptions>
118
+ export declare const DEFAULT_FIXTURES: Record<FixtureName, FixtureOptions>;
118
119
 
119
120
  /**
120
121
  * @deprecated Use {@link FixtureName} instead. This type alias will be removed in a future release.
121
122
  * @public
122
123
  */
123
- export declare type ExampleName = FixtureName
124
+ export declare type ExampleName = FixtureName;
124
125
 
125
126
  /**
126
127
  * Valid fixture name type.
127
128
  * @public
128
129
  */
129
130
  export declare type FixtureName =
130
- | 'basic-app'
131
- | 'basic-functions'
132
- | 'basic-studio'
133
- | 'multi-workspace-studio'
134
- | 'prebuilt-app'
135
- | 'prebuilt-studio'
136
- | 'worst-case-studio'
131
+ | "basic-app"
132
+ | "basic-functions"
133
+ | "basic-studio"
134
+ | "graphql-studio"
135
+ | "multi-workspace-studio"
136
+ | "prebuilt-app"
137
+ | "prebuilt-studio"
138
+ | "worst-case-studio";
137
139
 
138
140
  /**
139
141
  * Options for each fixture.
140
142
  * @public
141
143
  */
142
144
  export declare interface FixtureOptions {
143
- includeDist?: boolean
145
+ includeDist?: boolean;
144
146
  }
145
147
 
146
148
  /**
@@ -150,7 +152,7 @@ export declare interface FixtureOptions {
150
152
  * @returns Drive letter with backslash (e.g., 'C:\\', 'D:\\') or empty string on Unix
151
153
  * @internal
152
154
  */
153
- export declare function getCurrentDrive(): string
155
+ export declare function getCurrentDrive(): string;
154
156
 
155
157
  /**
156
158
  * Gets the path to the fixtures directory bundled with this package.
@@ -162,7 +164,7 @@ export declare function getCurrentDrive(): string
162
164
  * @returns Absolute path to the fixtures directory
163
165
  * @internal
164
166
  */
165
- export declare function getFixturesPath(): string
167
+ export declare function getFixturesPath(): string;
166
168
 
167
169
  /**
168
170
  * Gets the path to the temporary directory for test fixtures.
@@ -174,7 +176,7 @@ export declare function getFixturesPath(): string
174
176
  * @returns Absolute path to temp directory (default: initial cwd/tmp)
175
177
  * @internal
176
178
  */
177
- export declare function getTempPath(customTempDir?: string): string
179
+ export declare function getTempPath(customTempDir?: string): string;
178
180
 
179
181
  /**
180
182
  * Mocks the API calls, add some defaults so it doesn't cause too much friction
@@ -189,7 +191,7 @@ export declare function mockApi({
189
191
  projectId,
190
192
  query,
191
193
  uri,
192
- }: MockApiOptions): nock.Interceptor
194
+ }: MockApiOptions): nock.Interceptor;
193
195
 
194
196
  /**
195
197
  * @internal
@@ -198,35 +200,35 @@ export declare interface MockApiOptions {
198
200
  /**
199
201
  * Uri to mock
200
202
  */
201
- uri: string
203
+ uri: string;
202
204
  /**
203
205
  * Api host to mock, defaults to `https://api.sanity.io`
204
206
  */
205
- apiHost?: string
207
+ apiHost?: string;
206
208
  /**
207
209
  * Api version to mock, defaults to `v2025-05-14`
208
210
  */
209
- apiVersion?: string
211
+ apiVersion?: string;
210
212
  /**
211
213
  * Whether to include `tag: 'sanity.cli'` in query parameters.
212
214
  * Defaults to `true`. Set to `false` for endpoints that don't use CLI tagging.
213
215
  */
214
- includeQueryTag?: boolean
216
+ includeQueryTag?: boolean;
215
217
  /**
216
218
  * HTTP method to mock
217
219
  *
218
220
  * Defaults to 'get'
219
221
  */
220
- method?: 'delete' | 'get' | 'patch' | 'post' | 'put'
222
+ method?: "delete" | "get" | "patch" | "post" | "put";
221
223
  /**
222
224
  * Project ID to mock. When provided, constructs apiHost as `https://{projectId}.api.sanity.io`
223
225
  * Takes precedence over apiHost if both are provided.
224
226
  */
225
- projectId?: string
227
+ projectId?: string;
226
228
  /**
227
229
  * Query parameters to mock
228
230
  */
229
- query?: Record<string, string>
231
+ query?: Record<string, string>;
230
232
  }
231
233
 
232
234
  /**
@@ -255,10 +257,9 @@ export declare interface MockApiOptions {
255
257
  * expect(mockClient.getDocument).toHaveBeenCalledWith('doc1')
256
258
  * ```
257
259
  */
258
- export declare function mockSanityCommand<T extends typeof SanityCommand<typeof Command>>(
259
- CommandClass: T,
260
- options?: MockSanityCommandOptions,
261
- ): T
260
+ export declare function mockSanityCommand<
261
+ T extends typeof SanityCommand<typeof Command>,
262
+ >(CommandClass: T, options?: MockSanityCommandOptions): T;
262
263
 
263
264
  /**
264
265
  * @public
@@ -267,24 +268,24 @@ export declare interface MockSanityCommandOptions {
267
268
  /**
268
269
  * Mock CLI config (required if command uses getCliConfig or getProjectId)
269
270
  */
270
- cliConfig?: CliConfig
271
+ cliConfig?: CliConfig;
271
272
  /**
272
273
  * When provided, getCliConfig() will throw this error instead of returning a config.
273
274
  * Useful for simulating running outside a project directory.
274
275
  */
275
- cliConfigError?: Error
276
+ cliConfigError?: Error;
276
277
  /**
277
278
  * Mock whether the terminal is interactive (used by isUnattended)
278
279
  */
279
- isInteractive?: boolean
280
+ isInteractive?: boolean;
280
281
  /**
281
282
  * Mock project root result (required if command uses getProjectRoot)
282
283
  */
283
- projectRoot?: ProjectRootResult
284
+ projectRoot?: ProjectRootResult;
284
285
  /**
285
286
  * Mock authentication token (passed to API clients, bypasses getCliToken)
286
287
  */
287
- token?: string
288
+ token?: string;
288
289
  }
289
290
 
290
291
  /**
@@ -292,20 +293,22 @@ export declare interface MockSanityCommandOptions {
292
293
  * @param options - Options for mocking the telemetry store.
293
294
  * @returns The mocked telemetry store.
294
295
  */
295
- export declare const mockTelemetry: (options?: MockTelemetryOptions) => CLITelemetryStore
296
+ export declare const mockTelemetry: (
297
+ options?: MockTelemetryOptions,
298
+ ) => CLITelemetryStore;
296
299
 
297
300
  /**
298
301
  * @public
299
302
  */
300
303
  export declare interface MockTelemetryOptions {
301
- trace?: () => void
302
- updateUserProperties?: () => void
304
+ trace?: () => void;
305
+ updateUserProperties?: () => void;
303
306
  }
304
307
 
305
308
  declare interface Options {
306
- config: Config
307
- Command?: Command.Class
308
- context?: Hook.Context
309
+ config: Config;
310
+ Command?: Command.Class;
311
+ context?: Hook.Context;
309
312
  }
310
313
 
311
314
  /**
@@ -332,7 +335,10 @@ declare interface Options {
332
335
  * })
333
336
  * ```
334
337
  */
335
- export declare function setup(_: TestProject, options?: SetupTestFixturesOptions): Promise<void>
338
+ export declare function setup(
339
+ _: TestProject,
340
+ options?: SetupTestFixturesOptions,
341
+ ): Promise<void>;
336
342
 
337
343
  /**
338
344
  * Options for setupTestFixtures
@@ -351,11 +357,11 @@ export declare interface SetupTestFixturesOptions {
351
357
  * ['fixtures/*', 'dev/*']
352
358
  * ```
353
359
  */
354
- additionalFixtures?: string[]
360
+ additionalFixtures?: string[];
355
361
  /**
356
362
  * Custom temp directory path. Defaults to process.cwd()/tmp
357
363
  */
358
- tempDir?: string
364
+ tempDir?: string;
359
365
  }
360
366
 
361
367
  /**
@@ -369,7 +375,9 @@ export declare interface SetupTestFixturesOptions {
369
375
  *
370
376
  * @param options - Configuration options
371
377
  */
372
- export declare function teardown(options?: TeardownTestFixturesOptions): Promise<void>
378
+ export declare function teardown(
379
+ options?: TeardownTestFixturesOptions,
380
+ ): Promise<void>;
373
381
 
374
382
  /**
375
383
  * Options for teardownTestFixtures
@@ -380,7 +388,7 @@ export declare interface TeardownTestFixturesOptions {
380
388
  /**
381
389
  * Custom temp directory path. Defaults to process.cwd()/tmp
382
390
  */
383
- tempDir?: string
391
+ tempDir?: string;
384
392
  }
385
393
 
386
394
  /**
@@ -390,7 +398,7 @@ export declare function testCommand(
390
398
  command: CommandClass,
391
399
  args?: string[],
392
400
  options?: TestCommandOptions,
393
- ): Promise<CaptureResult<unknown>>
401
+ ): Promise<CaptureResult<unknown>>;
394
402
 
395
403
  /**
396
404
  * @public
@@ -399,16 +407,16 @@ export declare interface TestCommandOptions {
399
407
  /**
400
408
  * Options for capturing output
401
409
  */
402
- capture?: CaptureOptions
410
+ capture?: CaptureOptions;
403
411
  /**
404
412
  * Partial oclif config overrides
405
413
  */
406
- config?: Partial<Config>
414
+ config?: Partial<Config>;
407
415
  /**
408
416
  * Mock options for SanityCommand dependencies (config, project root, API clients).
409
417
  * When provided, the command is automatically wrapped with mockSanityCommand.
410
418
  */
411
- mocks?: MockSanityCommandOptions & MockTelemetryOptions
419
+ mocks?: MockSanityCommandOptions & MockTelemetryOptions;
412
420
  }
413
421
 
414
422
  /**
@@ -423,7 +431,7 @@ export declare function testCopyDirectory(
423
431
  srcDir: string,
424
432
  destDir: string,
425
433
  skip?: string[],
426
- ): Promise<void>
434
+ ): Promise<void>;
427
435
 
428
436
  /**
429
437
  * @deprecated Use {@link testFixture} instead. This function will be removed in a future release.
@@ -439,13 +447,13 @@ export declare function testCopyDirectory(
439
447
  export declare function testExample(
440
448
  exampleName: FixtureName | (string & {}),
441
449
  options?: TestFixtureOptions,
442
- ): Promise<string>
450
+ ): Promise<string>;
443
451
 
444
452
  /**
445
453
  * @deprecated Use {@link TestFixtureOptions} instead. This type alias will be removed in a future release.
446
454
  * @public
447
455
  */
448
- export declare type TestExampleOptions = TestFixtureOptions
456
+ export declare type TestExampleOptions = TestFixtureOptions;
449
457
 
450
458
  /**
451
459
  * Clones a fixture directory into a temporary directory with an isolated copy.
@@ -480,7 +488,7 @@ export declare type TestExampleOptions = TestFixtureOptions
480
488
  export declare function testFixture(
481
489
  fixtureName: FixtureName | (string & {}),
482
490
  options?: TestFixtureOptions,
483
- ): Promise<string>
491
+ ): Promise<string>;
484
492
 
485
493
  /**
486
494
  * @public
@@ -489,7 +497,7 @@ export declare interface TestFixtureOptions {
489
497
  /**
490
498
  * Custom temp directory. Defaults to process.cwd()/tmp
491
499
  */
492
- tempDir?: string
500
+ tempDir?: string;
493
501
  }
494
502
 
495
503
  /**
@@ -517,6 +525,6 @@ export declare interface TestFixtureOptions {
517
525
  export declare function testHook<T extends keyof Hooks>(
518
526
  hook: Hook<T>,
519
527
  options: Options,
520
- ): Promise<CaptureResult<Hooks[T]['return']>>
528
+ ): Promise<CaptureResult<Hooks[T]["return"]>>;
521
529
 
522
- export {}
530
+ export {};
@@ -9,6 +9,7 @@
9
9
  'basic-app': {},
10
10
  'basic-functions': {},
11
11
  'basic-studio': {},
12
+ 'graphql-studio': {},
12
13
  'multi-workspace-studio': {},
13
14
  'prebuilt-app': {
14
15
  includeDist: true
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/test/constants.ts"],"sourcesContent":["/**\n * Options for each fixture.\n * @public\n */\nexport interface FixtureOptions {\n includeDist?: boolean\n}\n\n/**\n * Default fixtures bundled with the package and their options.\n *\n * @public\n */\nexport const DEFAULT_FIXTURES: Record<FixtureName, FixtureOptions> = {\n 'basic-app': {},\n 'basic-functions': {},\n 'basic-studio': {},\n 'multi-workspace-studio': {},\n 'prebuilt-app': {includeDist: true},\n 'prebuilt-studio': {includeDist: true},\n 'worst-case-studio': {},\n} as const\n\n/**\n * Valid fixture name type.\n * @public\n */\nexport type FixtureName =\n | 'basic-app'\n | 'basic-functions'\n | 'basic-studio'\n | 'multi-workspace-studio'\n | 'prebuilt-app'\n | 'prebuilt-studio'\n | 'worst-case-studio'\n\n/**\n * @deprecated Use {@link FixtureName} instead. This type alias will be removed in a future release.\n * @public\n */\nexport type ExampleName = FixtureName\n"],"names":["DEFAULT_FIXTURES","includeDist"],"mappings":"AAAA;;;CAGC,GAKD;;;;CAIC,GACD,OAAO,MAAMA,mBAAwD;IACnE,aAAa,CAAC;IACd,mBAAmB,CAAC;IACpB,gBAAgB,CAAC;IACjB,0BAA0B,CAAC;IAC3B,gBAAgB;QAACC,aAAa;IAAI;IAClC,mBAAmB;QAACA,aAAa;IAAI;IACrC,qBAAqB,CAAC;AACxB,EAAU"}
1
+ {"version":3,"sources":["../../src/test/constants.ts"],"sourcesContent":["/**\n * Options for each fixture.\n * @public\n */\nexport interface FixtureOptions {\n includeDist?: boolean\n}\n\n/**\n * Default fixtures bundled with the package and their options.\n *\n * @public\n */\nexport const DEFAULT_FIXTURES: Record<FixtureName, FixtureOptions> = {\n 'basic-app': {},\n 'basic-functions': {},\n 'basic-studio': {},\n 'graphql-studio': {},\n 'multi-workspace-studio': {},\n 'prebuilt-app': {includeDist: true},\n 'prebuilt-studio': {includeDist: true},\n 'worst-case-studio': {},\n} as const\n\n/**\n * Valid fixture name type.\n * @public\n */\nexport type FixtureName =\n | 'basic-app'\n | 'basic-functions'\n | 'basic-studio'\n | 'graphql-studio'\n | 'multi-workspace-studio'\n | 'prebuilt-app'\n | 'prebuilt-studio'\n | 'worst-case-studio'\n\n/**\n * @deprecated Use {@link FixtureName} instead. This type alias will be removed in a future release.\n * @public\n */\nexport type ExampleName = FixtureName\n"],"names":["DEFAULT_FIXTURES","includeDist"],"mappings":"AAAA;;;CAGC,GAKD;;;;CAIC,GACD,OAAO,MAAMA,mBAAwD;IACnE,aAAa,CAAC;IACd,mBAAmB,CAAC;IACpB,gBAAgB,CAAC;IACjB,kBAAkB,CAAC;IACnB,0BAA0B,CAAC;IAC3B,gBAAgB;QAACC,aAAa;IAAI;IAClC,mBAAmB;QAACA,aAAa;IAAI;IACrC,qBAAqB,CAAC;AACxB,EAAU"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/test/createTestClient.ts"],"sourcesContent":["import {type ClientConfig, createClient, type SanityClient} from '@sanity/client'\nimport {vi} from 'vitest'\n\n/**\n * Options for createTestClient\n *\n * @public\n */\nexport interface CreateTestClientOptions extends ClientConfig {\n /**\n * API version for the client\n */\n apiVersion: string\n\n /**\n * Authentication token\n */\n token: string\n}\n\n/**\n * Creates a real Sanity client instance for testing that makes actual HTTP requests.\n * Use with mockApi() to intercept and mock the HTTP calls.\n *\n * @public\n *\n * @example\n * ```typescript\n * // Mock getGlobalCliClient to return a test client\n * vi.mock('@sanity/cli-core', async (importOriginal) => {\n * const actual = await importOriginal<typeof import('@sanity/cli-core')>()\n * const {createTestClient} = await import('@sanity/cli-test')\n *\n * return {\n * ...actual,\n * getGlobalCliClient: vi.fn().mockImplementation((opts) => {\n * return Promise.resolve(createTestClient({\n * apiVersion: opts.apiVersion,\n * }))\n * }),\n * }\n * })\n *\n * // Then use mockApi to intercept requests\n * mockApi({\n * apiVersion: 'v2025-02-19',\n * method: 'get',\n * uri: '/media-libraries',\n * }).reply(200, {data: [...]})\n * ```\n */\nexport function createTestClient(options: CreateTestClientOptions): {\n client: SanityClient\n request: ReturnType<typeof vi.fn>\n} {\n const {apiVersion, projectId, token, ...rest} = options\n\n const client = createClient({\n apiVersion,\n projectId,\n requestTagPrefix: 'sanity.cli',\n token,\n useCdn: false,\n useProjectHostname: projectId ? true : false,\n ...rest,\n })\n\n /**\n * Mock the request method of the client to return the actual response from the client\n */\n const request = vi.fn((...args: Parameters<typeof client.request>) => client.request(...args))\n\n return {\n client,\n request,\n }\n}\n"],"names":["createClient","vi","createTestClient","options","apiVersion","projectId","token","rest","client","requestTagPrefix","useCdn","useProjectHostname","request","fn","args"],"mappings":"AAAA,SAA2BA,YAAY,QAA0B,iBAAgB;AACjF,SAAQC,EAAE,QAAO,SAAQ;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BC,GACD,OAAO,SAASC,iBAAiBC,OAAgC;IAI/D,MAAM,EAACC,UAAU,EAAEC,SAAS,EAAEC,KAAK,EAAE,GAAGC,MAAK,GAAGJ;IAEhD,MAAMK,SAASR,aAAa;QAC1BI;QACAC;QACAI,kBAAkB;QAClBH;QACAI,QAAQ;QACRC,oBAAoBN,YAAY,OAAO;QACvC,GAAGE,IAAI;IACT;IAEA;;GAEC,GACD,MAAMK,UAAUX,GAAGY,EAAE,CAAC,CAAC,GAAGC,OAA4CN,OAAOI,OAAO,IAAIE;IAExF,OAAO;QACLN;QACAI;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/test/createTestClient.ts"],"sourcesContent":["import {type ClientConfig, createClient, type SanityClient} from '@sanity/client'\nimport {vi} from 'vitest'\n\n/**\n * Options for createTestClient\n *\n * @public\n */\nexport interface CreateTestClientOptions extends ClientConfig {\n /**\n * API version for the client\n */\n apiVersion: string\n\n /**\n * Authentication token\n */\n token?: string\n}\n\n/**\n * Creates a real Sanity client instance for testing that makes actual HTTP requests.\n * Use with mockApi() to intercept and mock the HTTP calls.\n *\n * @public\n *\n * @example\n * ```typescript\n * // Mock getGlobalCliClient to return a test client\n * vi.mock('@sanity/cli-core', async (importOriginal) => {\n * const actual = await importOriginal<typeof import('@sanity/cli-core')>()\n * const {createTestClient} = await import('@sanity/cli-test')\n *\n * return {\n * ...actual,\n * getGlobalCliClient: vi.fn().mockImplementation((opts) => {\n * return Promise.resolve(createTestClient({\n * apiVersion: opts.apiVersion,\n * }))\n * }),\n * }\n * })\n *\n * // Then use mockApi to intercept requests\n * mockApi({\n * apiVersion: 'v2025-02-19',\n * method: 'get',\n * uri: '/media-libraries',\n * }).reply(200, {data: [...]})\n * ```\n */\nexport function createTestClient(options: CreateTestClientOptions): {\n client: SanityClient\n request: ReturnType<typeof vi.fn>\n} {\n const {apiVersion, projectId, token, ...rest} = options\n\n const client = createClient({\n apiVersion,\n projectId,\n requestTagPrefix: 'sanity.cli',\n token,\n useCdn: false,\n useProjectHostname: projectId ? true : false,\n ...rest,\n })\n\n /**\n * Mock the request method of the client to return the actual response from the client\n */\n const request = vi.fn((...args: Parameters<typeof client.request>) => client.request(...args))\n\n return {\n client,\n request,\n }\n}\n"],"names":["createClient","vi","createTestClient","options","apiVersion","projectId","token","rest","client","requestTagPrefix","useCdn","useProjectHostname","request","fn","args"],"mappings":"AAAA,SAA2BA,YAAY,QAA0B,iBAAgB;AACjF,SAAQC,EAAE,QAAO,SAAQ;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BC,GACD,OAAO,SAASC,iBAAiBC,OAAgC;IAI/D,MAAM,EAACC,UAAU,EAAEC,SAAS,EAAEC,KAAK,EAAE,GAAGC,MAAK,GAAGJ;IAEhD,MAAMK,SAASR,aAAa;QAC1BI;QACAC;QACAI,kBAAkB;QAClBH;QACAI,QAAQ;QACRC,oBAAoBN,YAAY,OAAO;QACvC,GAAGE,IAAI;IACT;IAEA;;GAEC,GACD,MAAMK,UAAUX,GAAGY,EAAE,CAAC,CAAC,GAAGC,OAA4CN,OAAOI,OAAO,IAAIE;IAExF,OAAO;QACLN;QACAI;IACF;AACF"}
@@ -53,6 +53,9 @@ import { createTestToken } from './createTestToken.js';
53
53
  return super.getCliConfig();
54
54
  }
55
55
  getProjectRoot() {
56
+ if (options.cliConfigError && 'name' in options.cliConfigError && options.cliConfigError.name === 'ProjectRootNotFoundError') {
57
+ return Promise.reject(options.cliConfigError);
58
+ }
56
59
  if (options.projectRoot) {
57
60
  return Promise.resolve(options.projectRoot);
58
61
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/test/mockSanityCommand.ts"],"sourcesContent":["import {type Command} from '@oclif/core'\nimport {type CliConfig, type ProjectRootResult, SanityCommand} from '@sanity/cli-core'\n\nimport {convertToSystemPath} from '../utils/paths.js'\nimport {createTestToken} from './createTestToken.js'\n\n/**\n * @public\n */\nexport interface MockSanityCommandOptions {\n /**\n * Mock CLI config (required if command uses getCliConfig or getProjectId)\n */\n cliConfig?: CliConfig\n /**\n * When provided, getCliConfig() will throw this error instead of returning a config.\n * Useful for simulating running outside a project directory.\n */\n cliConfigError?: Error\n /**\n * Mock whether the terminal is interactive (used by isUnattended)\n */\n isInteractive?: boolean\n /**\n * Mock project root result (required if command uses getProjectRoot)\n */\n projectRoot?: ProjectRootResult\n /**\n * Mock authentication token (passed to API clients, bypasses getCliToken)\n */\n token?: string\n}\n\n/**\n * Creates a testable subclass of a command with mocked SanityCommand dependencies.\n *\n * @public\n *\n * @example\n * ```ts\n * // Basic config mocking\n * const TestAdd = mockSanityCommand(Add, {\n * cliConfig: { api: { projectId: 'test-project' } }\n * })\n *\n * // With mock API client\n * const mockClient = {\n * getDocument: vi.fn().mockResolvedValue({ _id: 'doc1', title: 'Test' }),\n * fetch: vi.fn().mockResolvedValue([]),\n * }\n * const TestGet = mockSanityCommand(GetDocumentCommand, {\n * cliConfig: { api: { projectId: 'test-project', dataset: 'production' } },\n * projectApiClient: mockClient,\n * })\n *\n * const {stdout} = await testCommand(TestGet, ['doc1'])\n * expect(mockClient.getDocument).toHaveBeenCalledWith('doc1')\n * ```\n */\nexport function mockSanityCommand<T extends typeof SanityCommand<typeof Command>>(\n CommandClass: T,\n options: MockSanityCommandOptions = {},\n): T {\n if (options.token) {\n createTestToken(options.token)\n }\n\n // Auto-convert paths in projectRoot to platform-appropriate format\n let projectRoot = options.projectRoot\n if (projectRoot) {\n projectRoot = {\n ...projectRoot,\n directory: convertToSystemPath(projectRoot.directory),\n path: convertToSystemPath(projectRoot.path),\n }\n }\n\n // Create a subclass that overrides methods when mocks are provided\n // Note: we use @ts-expect-error because TypeScript can't properly infer\n // the relationship between the generic CommandClass and SanityCommand\n // @ts-expect-error - TypeScript struggles with abstract class subclassing\n class MockedCommand extends CommandClass {\n protected getCliConfig(): Promise<CliConfig> {\n if (options.cliConfigError) {\n return Promise.reject(options.cliConfigError)\n }\n if (options.cliConfig) {\n return Promise.resolve(options.cliConfig)\n }\n return super.getCliConfig()\n }\n\n protected getProjectRoot(): Promise<ProjectRootResult> {\n if (options.projectRoot) {\n return Promise.resolve(options.projectRoot)\n }\n return super.getProjectRoot()\n }\n\n protected resolveIsInteractive(): boolean {\n if (options.isInteractive !== undefined) {\n return options.isInteractive\n }\n return super.resolveIsInteractive()\n }\n }\n\n return MockedCommand as T\n}\n"],"names":["convertToSystemPath","createTestToken","mockSanityCommand","CommandClass","options","token","projectRoot","directory","path","MockedCommand","getCliConfig","cliConfigError","Promise","reject","cliConfig","resolve","getProjectRoot","resolveIsInteractive","isInteractive","undefined"],"mappings":"AAGA,SAAQA,mBAAmB,QAAO,oBAAmB;AACrD,SAAQC,eAAe,QAAO,uBAAsB;AA6BpD;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASC,kBACdC,YAAe,EACfC,UAAoC,CAAC,CAAC;IAEtC,IAAIA,QAAQC,KAAK,EAAE;QACjBJ,gBAAgBG,QAAQC,KAAK;IAC/B;IAEA,mEAAmE;IACnE,IAAIC,cAAcF,QAAQE,WAAW;IACrC,IAAIA,aAAa;QACfA,cAAc;YACZ,GAAGA,WAAW;YACdC,WAAWP,oBAAoBM,YAAYC,SAAS;YACpDC,MAAMR,oBAAoBM,YAAYE,IAAI;QAC5C;IACF;IAEA,mEAAmE;IACnE,wEAAwE;IACxE,sEAAsE;IACtE,0EAA0E;IAC1E,MAAMC,sBAAsBN;QAChBO,eAAmC;YAC3C,IAAIN,QAAQO,cAAc,EAAE;gBAC1B,OAAOC,QAAQC,MAAM,CAACT,QAAQO,cAAc;YAC9C;YACA,IAAIP,QAAQU,SAAS,EAAE;gBACrB,OAAOF,QAAQG,OAAO,CAACX,QAAQU,SAAS;YAC1C;YACA,OAAO,KAAK,CAACJ;QACf;QAEUM,iBAA6C;YACrD,IAAIZ,QAAQE,WAAW,EAAE;gBACvB,OAAOM,QAAQG,OAAO,CAACX,QAAQE,WAAW;YAC5C;YACA,OAAO,KAAK,CAACU;QACf;QAEUC,uBAAgC;YACxC,IAAIb,QAAQc,aAAa,KAAKC,WAAW;gBACvC,OAAOf,QAAQc,aAAa;YAC9B;YACA,OAAO,KAAK,CAACD;QACf;IACF;IAEA,OAAOR;AACT"}
1
+ {"version":3,"sources":["../../src/test/mockSanityCommand.ts"],"sourcesContent":["import {type Command} from '@oclif/core'\nimport {type CliConfig, type ProjectRootResult, SanityCommand} from '@sanity/cli-core'\n\nimport {convertToSystemPath} from '../utils/paths.js'\nimport {createTestToken} from './createTestToken.js'\n\n/**\n * @public\n */\nexport interface MockSanityCommandOptions {\n /**\n * Mock CLI config (required if command uses getCliConfig or getProjectId)\n */\n cliConfig?: CliConfig\n /**\n * When provided, getCliConfig() will throw this error instead of returning a config.\n * Useful for simulating running outside a project directory.\n */\n cliConfigError?: Error\n /**\n * Mock whether the terminal is interactive (used by isUnattended)\n */\n isInteractive?: boolean\n /**\n * Mock project root result (required if command uses getProjectRoot)\n */\n projectRoot?: ProjectRootResult\n /**\n * Mock authentication token (passed to API clients, bypasses getCliToken)\n */\n token?: string\n}\n\n/**\n * Creates a testable subclass of a command with mocked SanityCommand dependencies.\n *\n * @public\n *\n * @example\n * ```ts\n * // Basic config mocking\n * const TestAdd = mockSanityCommand(Add, {\n * cliConfig: { api: { projectId: 'test-project' } }\n * })\n *\n * // With mock API client\n * const mockClient = {\n * getDocument: vi.fn().mockResolvedValue({ _id: 'doc1', title: 'Test' }),\n * fetch: vi.fn().mockResolvedValue([]),\n * }\n * const TestGet = mockSanityCommand(GetDocumentCommand, {\n * cliConfig: { api: { projectId: 'test-project', dataset: 'production' } },\n * projectApiClient: mockClient,\n * })\n *\n * const {stdout} = await testCommand(TestGet, ['doc1'])\n * expect(mockClient.getDocument).toHaveBeenCalledWith('doc1')\n * ```\n */\nexport function mockSanityCommand<T extends typeof SanityCommand<typeof Command>>(\n CommandClass: T,\n options: MockSanityCommandOptions = {},\n): T {\n if (options.token) {\n createTestToken(options.token)\n }\n\n // Auto-convert paths in projectRoot to platform-appropriate format\n let projectRoot = options.projectRoot\n if (projectRoot) {\n projectRoot = {\n ...projectRoot,\n directory: convertToSystemPath(projectRoot.directory),\n path: convertToSystemPath(projectRoot.path),\n }\n }\n\n // Create a subclass that overrides methods when mocks are provided\n // Note: we use @ts-expect-error because TypeScript can't properly infer\n // the relationship between the generic CommandClass and SanityCommand\n // @ts-expect-error - TypeScript struggles with abstract class subclassing\n class MockedCommand extends CommandClass {\n protected getCliConfig(): Promise<CliConfig> {\n if (options.cliConfigError) {\n return Promise.reject(options.cliConfigError)\n }\n if (options.cliConfig) {\n return Promise.resolve(options.cliConfig)\n }\n return super.getCliConfig()\n }\n\n protected getProjectRoot(): Promise<ProjectRootResult> {\n if (\n options.cliConfigError &&\n 'name' in options.cliConfigError &&\n options.cliConfigError.name === 'ProjectRootNotFoundError'\n ) {\n return Promise.reject(options.cliConfigError)\n }\n if (options.projectRoot) {\n return Promise.resolve(options.projectRoot)\n }\n return super.getProjectRoot()\n }\n\n protected resolveIsInteractive(): boolean {\n if (options.isInteractive !== undefined) {\n return options.isInteractive\n }\n return super.resolveIsInteractive()\n }\n }\n\n return MockedCommand as T\n}\n"],"names":["convertToSystemPath","createTestToken","mockSanityCommand","CommandClass","options","token","projectRoot","directory","path","MockedCommand","getCliConfig","cliConfigError","Promise","reject","cliConfig","resolve","getProjectRoot","name","resolveIsInteractive","isInteractive","undefined"],"mappings":"AAGA,SAAQA,mBAAmB,QAAO,oBAAmB;AACrD,SAAQC,eAAe,QAAO,uBAAsB;AA6BpD;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASC,kBACdC,YAAe,EACfC,UAAoC,CAAC,CAAC;IAEtC,IAAIA,QAAQC,KAAK,EAAE;QACjBJ,gBAAgBG,QAAQC,KAAK;IAC/B;IAEA,mEAAmE;IACnE,IAAIC,cAAcF,QAAQE,WAAW;IACrC,IAAIA,aAAa;QACfA,cAAc;YACZ,GAAGA,WAAW;YACdC,WAAWP,oBAAoBM,YAAYC,SAAS;YACpDC,MAAMR,oBAAoBM,YAAYE,IAAI;QAC5C;IACF;IAEA,mEAAmE;IACnE,wEAAwE;IACxE,sEAAsE;IACtE,0EAA0E;IAC1E,MAAMC,sBAAsBN;QAChBO,eAAmC;YAC3C,IAAIN,QAAQO,cAAc,EAAE;gBAC1B,OAAOC,QAAQC,MAAM,CAACT,QAAQO,cAAc;YAC9C;YACA,IAAIP,QAAQU,SAAS,EAAE;gBACrB,OAAOF,QAAQG,OAAO,CAACX,QAAQU,SAAS;YAC1C;YACA,OAAO,KAAK,CAACJ;QACf;QAEUM,iBAA6C;YACrD,IACEZ,QAAQO,cAAc,IACtB,UAAUP,QAAQO,cAAc,IAChCP,QAAQO,cAAc,CAACM,IAAI,KAAK,4BAChC;gBACA,OAAOL,QAAQC,MAAM,CAACT,QAAQO,cAAc;YAC9C;YACA,IAAIP,QAAQE,WAAW,EAAE;gBACvB,OAAOM,QAAQG,OAAO,CAACX,QAAQE,WAAW;YAC5C;YACA,OAAO,KAAK,CAACU;QACf;QAEUE,uBAAgC;YACxC,IAAId,QAAQe,aAAa,KAAKC,WAAW;gBACvC,OAAOhB,QAAQe,aAAa;YAC9B;YACA,OAAO,KAAK,CAACD;QACf;IACF;IAEA,OAAOT;AACT"}
package/dist/vitest.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {TestProject} from 'vitest/node'
1
+ import { TestProject } from "vitest/node";
2
2
 
3
3
  /**
4
4
  * Global setup function for initializing test fixtures.
@@ -24,7 +24,10 @@ import {TestProject} from 'vitest/node'
24
24
  * })
25
25
  * ```
26
26
  */
27
- export declare function setup(_: TestProject, options?: SetupTestFixturesOptions): Promise<void>
27
+ export declare function setup(
28
+ _: TestProject,
29
+ options?: SetupTestFixturesOptions,
30
+ ): Promise<void>;
28
31
 
29
32
  /**
30
33
  * Options for setupTestFixtures
@@ -43,11 +46,11 @@ declare interface SetupTestFixturesOptions {
43
46
  * ['fixtures/*', 'dev/*']
44
47
  * ```
45
48
  */
46
- additionalFixtures?: string[]
49
+ additionalFixtures?: string[];
47
50
  /**
48
51
  * Custom temp directory path. Defaults to process.cwd()/tmp
49
52
  */
50
- tempDir?: string
53
+ tempDir?: string;
51
54
  }
52
55
 
53
56
  /**
@@ -64,16 +67,16 @@ declare interface SetupTestFixturesOptions {
64
67
  * @throws If the worker files cannot be bundled
65
68
  * @throws If the watcher cannot be set up
66
69
  */
67
- export declare function setupWorkerBuild(filePaths: string[]): Promise<void>
70
+ export declare function setupWorkerBuild(filePaths: string[]): Promise<void>;
68
71
 
69
72
  /**
70
73
  * Serializer for snapshot tests to normalize line endings and Windows ^ to Unix `\`
71
74
  * @public
72
75
  */
73
76
  export declare const snapshotSerializer: {
74
- serialize: (val: string) => string
75
- test: (val: unknown) => val is string
76
- }
77
+ serialize: (val: string) => string;
78
+ test: (val: unknown) => val is string;
79
+ };
77
80
 
78
81
  /**
79
82
  * Teardown function to clean up test fixtures.
@@ -86,7 +89,9 @@ export declare const snapshotSerializer: {
86
89
  *
87
90
  * @param options - Configuration options
88
91
  */
89
- export declare function teardown(options?: TeardownTestFixturesOptions): Promise<void>
92
+ export declare function teardown(
93
+ options?: TeardownTestFixturesOptions,
94
+ ): Promise<void>;
90
95
 
91
96
  /**
92
97
  * Options for teardownTestFixtures
@@ -97,7 +102,7 @@ declare interface TeardownTestFixturesOptions {
97
102
  /**
98
103
  * Custom temp directory path. Defaults to process.cwd()/tmp
99
104
  */
100
- tempDir?: string
105
+ tempDir?: string;
101
106
  }
102
107
 
103
108
  /**
@@ -111,6 +116,6 @@ declare interface TeardownTestFixturesOptions {
111
116
  * @throws If the build contexts cannot be disposed
112
117
  * @throws If the compiled JavaScript files cannot be deleted
113
118
  */
114
- export declare function teardownWorkerBuild(): Promise<void>
119
+ export declare function teardownWorkerBuild(): Promise<void>;
115
120
 
116
- export {}
121
+ export {};
@@ -16,11 +16,11 @@
16
16
  "@sanity/sdk-react": "^2.6.0",
17
17
  "react": "^19.2.3",
18
18
  "react-dom": "^19.2.3",
19
- "sanity": "^5.13.0"
19
+ "sanity": "^5.14.1"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/react": "^19.2.9",
23
- "sanity": "^5.13.0",
23
+ "sanity": "^5.14.1",
24
24
  "typescript": "^5.9.3"
25
25
  }
26
26
  }
@@ -9,6 +9,6 @@
9
9
  "@sanity/functions": "^1.2.0"
10
10
  },
11
11
  "devDependencies": {
12
- "sanity": "^5.13.0"
12
+ "sanity": "^5.14.1"
13
13
  }
14
14
  }
@@ -15,10 +15,10 @@
15
15
  "start": "sanity start"
16
16
  },
17
17
  "dependencies": {
18
- "@sanity/vision": "^5.13.0",
18
+ "@sanity/vision": "^5.14.1",
19
19
  "react": "^19.2.3",
20
20
  "react-dom": "^19.2.3",
21
- "sanity": "^5.13.0",
21
+ "sanity": "^5.14.1",
22
22
  "styled-components": "^6.3.8"
23
23
  },
24
24
  "devDependencies": {
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "graphql-studio",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "keywords": [
6
+ "sanity"
7
+ ],
8
+ "license": "MIT",
9
+ "type": "module",
10
+ "main": "package.json",
11
+ "scripts": {
12
+ "deploy-graphql": "sanity graphql deploy"
13
+ },
14
+ "dependencies": {
15
+ "@sanity/vision": "^5.14.1",
16
+ "react": "^19.2.3",
17
+ "react-dom": "^19.2.3",
18
+ "sanity": "^5.14.1",
19
+ "styled-components": "^6.3.8"
20
+ },
21
+ "devDependencies": {
22
+ "@types/react": "^19.2.9",
23
+ "typescript": "^5.9.3"
24
+ }
25
+ }
@@ -0,0 +1,20 @@
1
+ import {defineCliConfig} from 'sanity/cli'
2
+
3
+ export default defineCliConfig({
4
+ api: {
5
+ dataset: 'production',
6
+ projectId: 'ppsg7ml5',
7
+ },
8
+ graphql: [
9
+ {
10
+ id: 'production-api',
11
+ tag: 'default',
12
+ workspace: 'production',
13
+ },
14
+ {
15
+ id: 'staging-api',
16
+ tag: 'staging',
17
+ workspace: 'staging',
18
+ },
19
+ ],
20
+ })
@@ -0,0 +1,37 @@
1
+ import {visionTool} from '@sanity/vision'
2
+ import {defineConfig} from 'sanity'
3
+ import {structureTool} from 'sanity/structure'
4
+
5
+ import {productionSchemaTypes, stagingSchemaTypes} from './schemaTypes'
6
+
7
+ export default defineConfig([
8
+ {
9
+ basePath: '/production',
10
+ name: 'production',
11
+ title: 'Production',
12
+
13
+ dataset: 'production',
14
+ projectId: 'ppsg7ml5',
15
+
16
+ plugins: [structureTool(), visionTool()],
17
+
18
+ schema: {
19
+ types: productionSchemaTypes,
20
+ },
21
+ },
22
+
23
+ {
24
+ basePath: '/staging',
25
+ name: 'staging',
26
+ title: 'Staging',
27
+
28
+ dataset: 'staging',
29
+ projectId: 'ppsg7ml5',
30
+
31
+ plugins: [structureTool(), visionTool()],
32
+
33
+ schema: {
34
+ types: stagingSchemaTypes,
35
+ },
36
+ },
37
+ ])
@@ -0,0 +1,52 @@
1
+ import {defineField, defineType} from 'sanity'
2
+
3
+ export default defineType({
4
+ name: 'author',
5
+ title: 'Author',
6
+ type: 'document',
7
+
8
+ fields: [
9
+ defineField({
10
+ name: 'name',
11
+ title: 'Name',
12
+ type: 'string',
13
+ }),
14
+ defineField({
15
+ name: 'slug',
16
+ options: {
17
+ maxLength: 96,
18
+ source: 'name',
19
+ },
20
+ title: 'Slug',
21
+ type: 'slug',
22
+ }),
23
+ defineField({
24
+ name: 'image',
25
+ options: {
26
+ hotspot: true,
27
+ },
28
+ title: 'Image',
29
+ type: 'image',
30
+ }),
31
+ defineField({
32
+ name: 'bio',
33
+ of: [
34
+ {
35
+ lists: [],
36
+ styles: [{title: 'Normal', value: 'normal'}],
37
+ title: 'Block',
38
+ type: 'block',
39
+ },
40
+ ],
41
+ title: 'Bio',
42
+ type: 'array',
43
+ }),
44
+ ],
45
+
46
+ preview: {
47
+ select: {
48
+ media: 'image',
49
+ title: 'name',
50
+ },
51
+ },
52
+ })
@@ -0,0 +1,71 @@
1
+ import {defineArrayMember, defineType} from 'sanity'
2
+
3
+ /**
4
+ * This is the schema definition for the rich text fields used for
5
+ * for this blog studio. When you import it in schemas.js it can be
6
+ * reused in other parts of the studio with:
7
+ *
8
+ * ```ts
9
+ * {
10
+ * name: 'someName',
11
+ * title: 'Some title',
12
+ * type: 'blockContent'
13
+ * }
14
+ * ```
15
+ */
16
+ export default defineType({
17
+ name: 'blockContent',
18
+ title: 'Block Content',
19
+ type: 'array',
20
+
21
+ of: [
22
+ defineArrayMember({
23
+ lists: [{title: 'Bullet', value: 'bullet'}],
24
+ // Marks let you mark up inline text in the block editor.
25
+ marks: {
26
+ // Annotations can be any object structure – e.g. a link or a footnote.
27
+ annotations: [
28
+ {
29
+ fields: [
30
+ {
31
+ name: 'href',
32
+ title: 'URL',
33
+ type: 'url',
34
+ },
35
+ ],
36
+ name: 'link',
37
+ title: 'URL',
38
+ type: 'object',
39
+ },
40
+ ],
41
+ // Decorators usually describe a single property – e.g. a typographic
42
+ // preference or highlighting by editors.
43
+ decorators: [
44
+ {title: 'Strong', value: 'strong'},
45
+ {title: 'Emphasis', value: 'em'},
46
+ ],
47
+ },
48
+ // Styles let you set what your user can mark up blocks with. These
49
+ // correspond with HTML tags, but you can set any title or value
50
+ // you want and decide how you want to deal with it where you want to
51
+ // use your content.
52
+ styles: [
53
+ {title: 'Normal', value: 'normal'},
54
+ {title: 'H1', value: 'h1'},
55
+ {title: 'H2', value: 'h2'},
56
+ {title: 'H3', value: 'h3'},
57
+ {title: 'H4', value: 'h4'},
58
+ {title: 'Quote', value: 'blockquote'},
59
+ ],
60
+ title: 'Block',
61
+ type: 'block',
62
+ }),
63
+ // You can add additional types here. Note that you can't use
64
+ // primitive types such as 'string' and 'number' in the same array
65
+ // as a block type.
66
+ defineArrayMember({
67
+ options: {hotspot: true},
68
+ type: 'image',
69
+ }),
70
+ ],
71
+ })
@@ -0,0 +1,20 @@
1
+ import {defineField, defineType} from 'sanity'
2
+
3
+ export default defineType({
4
+ name: 'category',
5
+ title: 'Category',
6
+ type: 'document',
7
+
8
+ fields: [
9
+ defineField({
10
+ name: 'title',
11
+ title: 'Title',
12
+ type: 'string',
13
+ }),
14
+ defineField({
15
+ name: 'description',
16
+ title: 'Description',
17
+ type: 'text',
18
+ }),
19
+ ],
20
+ })
@@ -0,0 +1,25 @@
1
+ import {defineField, defineType} from 'sanity'
2
+
3
+ export default defineType({
4
+ name: 'event',
5
+ title: 'Event',
6
+ type: 'document',
7
+
8
+ fields: [
9
+ defineField({
10
+ name: 'title',
11
+ title: 'Title',
12
+ type: 'string',
13
+ }),
14
+ defineField({
15
+ name: 'date',
16
+ title: 'Date',
17
+ type: 'datetime',
18
+ }),
19
+ defineField({
20
+ name: 'venue',
21
+ title: 'Venue',
22
+ type: 'string',
23
+ }),
24
+ ],
25
+ })
@@ -0,0 +1,10 @@
1
+ import author from './author'
2
+ import blockContent from './blockContent'
3
+ import category from './category'
4
+ import event from './event'
5
+ import post from './post'
6
+
7
+ // Both workspaces share post, author, category, blockContent
8
+ // Staging additionally includes event
9
+ export const productionSchemaTypes = [post, author, category, blockContent]
10
+ export const stagingSchemaTypes = [post, author, category, event, blockContent]
@@ -0,0 +1,67 @@
1
+ import {defineField, defineType} from 'sanity'
2
+
3
+ export default defineType({
4
+ name: 'post',
5
+ title: 'Post',
6
+ type: 'document',
7
+
8
+ fields: [
9
+ defineField({
10
+ name: 'title',
11
+ title: 'Title',
12
+ type: 'string',
13
+ }),
14
+ defineField({
15
+ name: 'slug',
16
+ options: {
17
+ maxLength: 96,
18
+ source: 'title',
19
+ },
20
+ title: 'Slug',
21
+ type: 'slug',
22
+ }),
23
+ defineField({
24
+ name: 'author',
25
+ title: 'Author',
26
+ to: {type: 'author'},
27
+ type: 'reference',
28
+ }),
29
+ defineField({
30
+ name: 'mainImage',
31
+ options: {
32
+ hotspot: true,
33
+ },
34
+ title: 'Main image',
35
+ type: 'image',
36
+ }),
37
+ defineField({
38
+ name: 'categories',
39
+ of: [{to: {type: 'category'}, type: 'reference'}],
40
+ title: 'Categories',
41
+ type: 'array',
42
+ }),
43
+ defineField({
44
+ name: 'publishedAt',
45
+ title: 'Published at',
46
+ type: 'datetime',
47
+ }),
48
+ defineField({
49
+ name: 'body',
50
+ title: 'Body',
51
+ type: 'blockContent',
52
+ }),
53
+ ],
54
+
55
+ preview: {
56
+ select: {
57
+ author: 'author.name',
58
+ media: 'mainImage',
59
+ title: 'title',
60
+ },
61
+
62
+ prepare(selection) {
63
+ const {author} = selection
64
+ return {...selection, subtitle: author && `by ${author}`}
65
+ },
66
+ },
67
+ })
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "module": "Preserve",
10
+ "moduleDetection": "force",
11
+ "isolatedModules": true,
12
+ "jsx": "preserve",
13
+ "incremental": true
14
+ },
15
+ "include": ["**/*.ts", "**/*.tsx"],
16
+ "exclude": ["node_modules"]
17
+ }
@@ -15,10 +15,10 @@
15
15
  "start": "sanity start"
16
16
  },
17
17
  "dependencies": {
18
- "@sanity/vision": "^5.13.0",
18
+ "@sanity/vision": "^5.14.1",
19
19
  "react": "^19.2.3",
20
20
  "react-dom": "^19.2.3",
21
- "sanity": "^5.13.0",
21
+ "sanity": "^5.14.1",
22
22
  "styled-components": "^6.3.8"
23
23
  },
24
24
  "devDependencies": {
@@ -16,11 +16,11 @@
16
16
  "@sanity/sdk-react": "^2.6.0",
17
17
  "react": "^19.2.3",
18
18
  "react-dom": "^19.2.3",
19
- "sanity": "^5.13.0"
19
+ "sanity": "^5.14.1"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/react": "^19.2.9",
23
- "sanity": "^5.13.0",
23
+ "sanity": "^5.14.1",
24
24
  "typescript": "^5.9.3"
25
25
  }
26
26
  }
@@ -15,7 +15,7 @@
15
15
  "dependencies": {
16
16
  "react": "^19.2.3",
17
17
  "react-dom": "^19.2.3",
18
- "sanity": "^5.13.0",
18
+ "sanity": "^5.14.1",
19
19
  "styled-components": "^6.3.8"
20
20
  },
21
21
  "devDependencies": {
@@ -16,10 +16,10 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@sanity/code-input": "^7.0.6",
19
- "@sanity/vision": "^5.13.0",
19
+ "@sanity/vision": "^5.14.1",
20
20
  "react": "^19.2.3",
21
21
  "react-dom": "^19.2.3",
22
- "sanity": "^5.13.0",
22
+ "sanity": "^5.14.1",
23
23
  "sanity-plugin-media": "^4.1.1",
24
24
  "styled-components": "^6.3.8",
25
25
  "vite-tsconfig-paths": "^6.0.5"
package/package.json CHANGED
@@ -1,27 +1,33 @@
1
1
  {
2
2
  "name": "@sanity/cli-test",
3
- "version": "0.1.0-alpha.17",
3
+ "version": "0.2.1",
4
4
  "description": "Sanity CLI test helpers and utilities",
5
5
  "keywords": [
6
- "sanity",
6
+ "cli",
7
7
  "cms",
8
+ "content",
8
9
  "headless",
9
10
  "realtime",
10
- "content",
11
- "cli",
11
+ "sanity",
12
12
  "tool"
13
13
  ],
14
14
  "homepage": "https://github.com/sanity-io/cli",
15
15
  "bugs": "https://github.com/sanity-io/cli/issues",
16
+ "license": "MIT",
17
+ "author": "Sanity.io <hello@sanity.io>",
16
18
  "repository": {
17
19
  "type": "git",
18
20
  "url": "git+https://github.com/sanity-io/cli.git",
19
21
  "directory": "packages/@sanity/cli-test"
20
22
  },
21
- "license": "MIT",
22
- "author": "Sanity.io <hello@sanity.io>",
23
- "sideEffects": false,
23
+ "files": [
24
+ "./dist",
25
+ "./fixtures"
26
+ ],
24
27
  "type": "module",
28
+ "sideEffects": false,
29
+ "main": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
25
31
  "exports": {
26
32
  ".": {
27
33
  "source": "./src/index.ts",
@@ -33,14 +39,11 @@
33
39
  },
34
40
  "./package.json": "./package.json"
35
41
  },
36
- "main": "./dist/index.js",
37
- "types": "./dist/index.d.ts",
38
- "files": [
39
- "./dist",
40
- "./fixtures"
41
- ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
42
45
  "dependencies": {
43
- "@swc/core": "^1.15.17",
46
+ "@swc/core": "^1.15.18",
44
47
  "ansis": "^4.2.0",
45
48
  "esbuild": "^0.27.3",
46
49
  "nock": "^14.0.11",
@@ -48,36 +51,33 @@
48
51
  "tinyglobby": "^0.2.15"
49
52
  },
50
53
  "devDependencies": {
51
- "@eslint/compat": "^2.0.2",
52
- "@oclif/core": "^4.8.2",
53
- "@sanity/client": "^7.16.0",
54
- "@sanity/pkg-utils": "^10.4.6",
54
+ "@eslint/compat": "^2.0.3",
55
+ "@oclif/core": "^4.8.3",
56
+ "@sanity/client": "^7.17.0",
57
+ "@sanity/pkg-utils": "^10.4.8",
55
58
  "@swc/cli": "^0.8.0",
56
- "@types/node": "^20.19.35",
57
- "eslint": "^9.39.3",
58
- "publint": "^0.3.17",
59
+ "@types/node": "^20.19.37",
60
+ "eslint": "^9.39.4",
61
+ "publint": "^0.3.18",
59
62
  "rimraf": "^6.0.1",
60
63
  "tsx": "^4.21.0",
61
64
  "typescript": "^5.9.3",
62
65
  "vitest": "^4.0.18",
63
66
  "yaml": "^2.8.2",
67
+ "@repo/package.config": "0.0.1",
64
68
  "@repo/tsconfig": "3.70.0",
65
- "@sanity/cli-core": "0.1.0-alpha.19",
66
- "@sanity/eslint-config-cli": "0.0.0-alpha.4",
67
- "@repo/package.config": "0.0.1"
69
+ "@sanity/cli-core": "1.0.1",
70
+ "@sanity/eslint-config-cli": "1.0.0"
68
71
  },
69
72
  "peerDependencies": {
70
73
  "@oclif/core": "^4.0.0",
71
74
  "@sanity/client": "^7.0.0",
72
75
  "vitest": ">=3.0.0 <5.0.0",
73
- "@sanity/cli-core": "0.1.0-alpha.19"
76
+ "@sanity/cli-core": "1.0.1"
74
77
  },
75
78
  "engines": {
76
79
  "node": ">=20.19.1 <22 || >=22.12"
77
80
  },
78
- "publishConfig": {
79
- "access": "public"
80
- },
81
81
  "scripts": {
82
82
  "prebuild": "pnpm run clean",
83
83
  "build": "pnpm run build:js && pnpm run copy:fixtures",