@sanity/cli-test 0.1.0-alpha.17 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/test/constants.js +1 -0
- package/dist/test/constants.js.map +1 -1
- package/dist/test/createTestClient.js.map +1 -1
- package/dist/test/mockSanityCommand.js +3 -0
- package/dist/test/mockSanityCommand.js.map +1 -1
- package/fixtures/graphql-studio/package.json +25 -0
- package/fixtures/graphql-studio/sanity.cli.ts +20 -0
- package/fixtures/graphql-studio/sanity.config.ts +37 -0
- package/fixtures/graphql-studio/schemaTypes/author.ts +52 -0
- package/fixtures/graphql-studio/schemaTypes/blockContent.ts +71 -0
- package/fixtures/graphql-studio/schemaTypes/category.ts +20 -0
- package/fixtures/graphql-studio/schemaTypes/event.ts +25 -0
- package/fixtures/graphql-studio/schemaTypes/index.ts +10 -0
- package/fixtures/graphql-studio/schemaTypes/post.ts +67 -0
- package/fixtures/graphql-studio/tsconfig.json +17 -0
- package/package.json +13 -13
package/dist/index.d.ts
CHANGED
|
@@ -96,7 +96,7 @@ export declare interface CreateTestClientOptions extends ClientConfig {
|
|
|
96
96
|
/**
|
|
97
97
|
* Authentication token
|
|
98
98
|
*/
|
|
99
|
-
token
|
|
99
|
+
token?: string
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
@@ -130,6 +130,7 @@ export declare type FixtureName =
|
|
|
130
130
|
| 'basic-app'
|
|
131
131
|
| 'basic-functions'
|
|
132
132
|
| 'basic-studio'
|
|
133
|
+
| 'graphql-studio'
|
|
133
134
|
| 'multi-workspace-studio'
|
|
134
135
|
| 'prebuilt-app'
|
|
135
136
|
| 'prebuilt-studio'
|
package/dist/test/constants.js
CHANGED
|
@@ -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
|
|
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,
|
|
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"}
|
|
@@ -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.13.0",
|
|
16
|
+
"react": "^19.2.3",
|
|
17
|
+
"react-dom": "^19.2.3",
|
|
18
|
+
"sanity": "^5.13.0",
|
|
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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/cli-test",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Sanity CLI test helpers and utilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"./fixtures"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@swc/core": "^1.15.
|
|
43
|
+
"@swc/core": "^1.15.18",
|
|
44
44
|
"ansis": "^4.2.0",
|
|
45
45
|
"esbuild": "^0.27.3",
|
|
46
46
|
"nock": "^14.0.11",
|
|
@@ -48,29 +48,29 @@
|
|
|
48
48
|
"tinyglobby": "^0.2.15"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@eslint/compat": "^2.0.
|
|
52
|
-
"@oclif/core": "^4.8.
|
|
53
|
-
"@sanity/client": "^7.
|
|
54
|
-
"@sanity/pkg-utils": "^10.4.
|
|
51
|
+
"@eslint/compat": "^2.0.3",
|
|
52
|
+
"@oclif/core": "^4.8.3",
|
|
53
|
+
"@sanity/client": "^7.17.0",
|
|
54
|
+
"@sanity/pkg-utils": "^10.4.8",
|
|
55
55
|
"@swc/cli": "^0.8.0",
|
|
56
|
-
"@types/node": "^20.19.
|
|
57
|
-
"eslint": "^9.39.
|
|
58
|
-
"publint": "^0.3.
|
|
56
|
+
"@types/node": "^20.19.37",
|
|
57
|
+
"eslint": "^9.39.4",
|
|
58
|
+
"publint": "^0.3.18",
|
|
59
59
|
"rimraf": "^6.0.1",
|
|
60
60
|
"tsx": "^4.21.0",
|
|
61
61
|
"typescript": "^5.9.3",
|
|
62
62
|
"vitest": "^4.0.18",
|
|
63
63
|
"yaml": "^2.8.2",
|
|
64
64
|
"@repo/tsconfig": "3.70.0",
|
|
65
|
-
"@sanity/cli-core": "
|
|
66
|
-
"@
|
|
67
|
-
"@
|
|
65
|
+
"@sanity/cli-core": "1.0.0",
|
|
66
|
+
"@repo/package.config": "0.0.1",
|
|
67
|
+
"@sanity/eslint-config-cli": "1.0.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"@oclif/core": "^4.0.0",
|
|
71
71
|
"@sanity/client": "^7.0.0",
|
|
72
72
|
"vitest": ">=3.0.0 <5.0.0",
|
|
73
|
-
"@sanity/cli-core": "
|
|
73
|
+
"@sanity/cli-core": "1.0.0"
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=20.19.1 <22 || >=22.12"
|