@sanity/cli-core 0.0.2-alpha.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 (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/SanityCommand.d.ts +56 -0
  4. package/dist/SanityCommand.js +72 -0
  5. package/dist/SanityCommand.js.map +1 -0
  6. package/dist/config/__tests__/cliToken.test.js +74 -0
  7. package/dist/config/__tests__/cliToken.test.js.map +1 -0
  8. package/dist/config/__tests__/cliUserConfig.test.js +131 -0
  9. package/dist/config/__tests__/cliUserConfig.test.js.map +1 -0
  10. package/dist/config/__tests__/findProjectRoot.test.js +159 -0
  11. package/dist/config/__tests__/findProjectRoot.test.js.map +1 -0
  12. package/dist/config/cli/getCliConfig.d.ts +16 -0
  13. package/dist/config/cli/getCliConfig.js +67 -0
  14. package/dist/config/cli/getCliConfig.js.map +1 -0
  15. package/dist/config/cli/getCliConfig.worker.d.ts +1 -0
  16. package/dist/config/cli/getCliConfig.worker.js +14 -0
  17. package/dist/config/cli/getCliConfig.worker.js.map +1 -0
  18. package/dist/config/cli/schemas.d.ts +204 -0
  19. package/dist/config/cli/schemas.js +77 -0
  20. package/dist/config/cli/schemas.js.map +1 -0
  21. package/dist/config/cli/types.d.ts +13 -0
  22. package/dist/config/cli/types.js +3 -0
  23. package/dist/config/cli/types.js.map +1 -0
  24. package/dist/config/findProjectRoot.d.ts +14 -0
  25. package/dist/config/findProjectRoot.js +56 -0
  26. package/dist/config/findProjectRoot.js.map +1 -0
  27. package/dist/config/studio/getStudioConfig.d.ts +14 -0
  28. package/dist/config/studio/getStudioConfig.js +16 -0
  29. package/dist/config/studio/getStudioConfig.js.map +1 -0
  30. package/dist/config/studio/readStudioConfig.d.ts +190 -0
  31. package/dist/config/studio/readStudioConfig.js +45 -0
  32. package/dist/config/studio/readStudioConfig.js.map +1 -0
  33. package/dist/config/studio/readStudioConfig.worker.d.ts +1 -0
  34. package/dist/config/studio/readStudioConfig.worker.js +64 -0
  35. package/dist/config/studio/readStudioConfig.worker.js.map +1 -0
  36. package/dist/config/util/findAppConfigPath.d.ts +8 -0
  37. package/dist/config/util/findAppConfigPath.js +22 -0
  38. package/dist/config/util/findAppConfigPath.js.map +1 -0
  39. package/dist/config/util/findConfigsPaths.d.ts +16 -0
  40. package/dist/config/util/findConfigsPaths.js +21 -0
  41. package/dist/config/util/findConfigsPaths.js.map +1 -0
  42. package/dist/config/util/findStudioConfigPath.d.ts +9 -0
  43. package/dist/config/util/findStudioConfigPath.js +31 -0
  44. package/dist/config/util/findStudioConfigPath.js.map +1 -0
  45. package/dist/config/util/isSanityV2StudioRoot.d.ts +8 -0
  46. package/dist/config/util/isSanityV2StudioRoot.js +19 -0
  47. package/dist/config/util/isSanityV2StudioRoot.js.map +1 -0
  48. package/dist/config/util/recursivelyResolveProjectRoot.d.ts +27 -0
  49. package/dist/config/util/recursivelyResolveProjectRoot.js +28 -0
  50. package/dist/config/util/recursivelyResolveProjectRoot.js.map +1 -0
  51. package/dist/debug.d.ts +15 -0
  52. package/dist/debug.js +15 -0
  53. package/dist/debug.js.map +1 -0
  54. package/dist/index.d.ts +28 -0
  55. package/dist/index.js +27 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/loaders/studio/stubs.d.ts +254 -0
  58. package/dist/loaders/studio/stubs.js +257 -0
  59. package/dist/loaders/studio/stubs.js.map +1 -0
  60. package/dist/loaders/studio/studioWorkerLoader.worker.d.ts +1 -0
  61. package/dist/loaders/studio/studioWorkerLoader.worker.js +117 -0
  62. package/dist/loaders/studio/studioWorkerLoader.worker.js.map +1 -0
  63. package/dist/loaders/studio/studioWorkerTask.d.ts +40 -0
  64. package/dist/loaders/studio/studioWorkerTask.js +69 -0
  65. package/dist/loaders/studio/studioWorkerTask.js.map +1 -0
  66. package/dist/loaders/tsx/tsxWorkerLoader.worker.d.ts +1 -0
  67. package/dist/loaders/tsx/tsxWorkerLoader.worker.js +12 -0
  68. package/dist/loaders/tsx/tsxWorkerLoader.worker.js.map +1 -0
  69. package/dist/loaders/tsx/tsxWorkerTask.d.ts +28 -0
  70. package/dist/loaders/tsx/tsxWorkerTask.js +61 -0
  71. package/dist/loaders/tsx/tsxWorkerTask.js.map +1 -0
  72. package/dist/services/apiClient.d.ts +39 -0
  73. package/dist/services/apiClient.js +88 -0
  74. package/dist/services/apiClient.js.map +1 -0
  75. package/dist/services/cliUserConfig.d.ts +57 -0
  76. package/dist/services/cliUserConfig.js +103 -0
  77. package/dist/services/cliUserConfig.js.map +1 -0
  78. package/dist/services/getCliToken.d.ts +7 -0
  79. package/dist/services/getCliToken.js +21 -0
  80. package/dist/services/getCliToken.js.map +1 -0
  81. package/dist/types.d.ts +7 -0
  82. package/dist/types.js +3 -0
  83. package/dist/types.js.map +1 -0
  84. package/dist/util/NotFoundError.d.ts +20 -0
  85. package/dist/util/NotFoundError.js +27 -0
  86. package/dist/util/NotFoundError.js.map +1 -0
  87. package/dist/util/__tests__/createExpiringConfig.test.js +309 -0
  88. package/dist/util/__tests__/createExpiringConfig.test.js.map +1 -0
  89. package/dist/util/createExpiringConfig.d.ts +32 -0
  90. package/dist/util/createExpiringConfig.js +35 -0
  91. package/dist/util/createExpiringConfig.js.map +1 -0
  92. package/dist/util/fileExists.d.ts +9 -0
  93. package/dist/util/fileExists.js +13 -0
  94. package/dist/util/fileExists.js.map +1 -0
  95. package/dist/util/generateHelpUrl.d.ts +8 -0
  96. package/dist/util/generateHelpUrl.js +11 -0
  97. package/dist/util/generateHelpUrl.js.map +1 -0
  98. package/dist/util/getSanityEnvVar.d.ts +19 -0
  99. package/dist/util/getSanityEnvVar.js +24 -0
  100. package/dist/util/getSanityEnvVar.js.map +1 -0
  101. package/dist/util/getSanityUrl.d.ts +5 -0
  102. package/dist/util/getSanityUrl.js +8 -0
  103. package/dist/util/getSanityUrl.js.map +1 -0
  104. package/dist/util/getUserConfig.d.ts +2 -0
  105. package/dist/util/getUserConfig.js +15 -0
  106. package/dist/util/getUserConfig.js.map +1 -0
  107. package/dist/util/isCi.d.ts +1 -0
  108. package/dist/util/isCi.js +7 -0
  109. package/dist/util/isCi.js.map +1 -0
  110. package/dist/util/isHttpError.d.ts +29 -0
  111. package/dist/util/isHttpError.js +18 -0
  112. package/dist/util/isHttpError.js.map +1 -0
  113. package/dist/util/isInteractive.d.ts +1 -0
  114. package/dist/util/isInteractive.js +5 -0
  115. package/dist/util/isInteractive.js.map +1 -0
  116. package/dist/util/isRecord.d.ts +8 -0
  117. package/dist/util/isRecord.js +11 -0
  118. package/dist/util/isRecord.js.map +1 -0
  119. package/dist/util/isTrueish.d.ts +1 -0
  120. package/dist/util/isTrueish.js +10 -0
  121. package/dist/util/isTrueish.js.map +1 -0
  122. package/dist/util/readJsonFile.d.ts +8 -0
  123. package/dist/util/readJsonFile.js +26 -0
  124. package/dist/util/readJsonFile.js.map +1 -0
  125. package/dist/util/safeStructuredClone.d.ts +8 -0
  126. package/dist/util/safeStructuredClone.js +40 -0
  127. package/dist/util/safeStructuredClone.js.map +1 -0
  128. package/dist/util/writeJsonFile.d.ts +9 -0
  129. package/dist/util/writeJsonFile.js +19 -0
  130. package/dist/util/writeJsonFile.js.map +1 -0
  131. package/dist/ux/colorizeJson.d.ts +1 -0
  132. package/dist/ux/colorizeJson.js +32 -0
  133. package/dist/ux/colorizeJson.js.map +1 -0
  134. package/dist/ux/formatObject.d.ts +1 -0
  135. package/dist/ux/formatObject.js +9 -0
  136. package/dist/ux/formatObject.js.map +1 -0
  137. package/dist/ux/logSymbols.d.ts +1 -0
  138. package/dist/ux/logSymbols.js +3 -0
  139. package/dist/ux/logSymbols.js.map +1 -0
  140. package/dist/ux/printKeyValue.d.ts +1 -0
  141. package/dist/ux/printKeyValue.js +16 -0
  142. package/dist/ux/printKeyValue.js.map +1 -0
  143. package/dist/ux/spinner.d.ts +1 -0
  144. package/dist/ux/spinner.js +3 -0
  145. package/dist/ux/spinner.js.map +1 -0
  146. package/dist/ux/timer.d.ts +12 -0
  147. package/dist/ux/timer.js +29 -0
  148. package/dist/ux/timer.js.map +1 -0
  149. package/package.json +81 -0
@@ -0,0 +1,117 @@
1
+ import { resolve } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { isMainThread } from 'node:worker_threads';
4
+ import { moduleResolve } from 'import-meta-resolve';
5
+ import { createServer, loadEnv, mergeConfig } from 'vite';
6
+ import { ViteNodeRunner } from 'vite-node/client';
7
+ import { ViteNodeServer } from 'vite-node/server';
8
+ import { installSourcemapsSupport } from 'vite-node/source-map';
9
+ import { getCliConfig } from '../../config/cli/getCliConfig.js';
10
+ import { isRecord } from '../../util/isRecord.js';
11
+ import { isNotFoundError } from '../../util/NotFoundError.js';
12
+ import * as stubs from './stubs.js';
13
+ if (isMainThread) {
14
+ throw new Error('Should be child of thread, not the main thread');
15
+ }
16
+ const rootPath = process.env.STUDIO_WORKER_STUDIO_ROOT_PATH;
17
+ if (!rootPath) {
18
+ throw new Error('Missing `STUDIO_WORKER_STUDIO_ROOT_PATH` environment variable');
19
+ }
20
+ const workerScriptPath = process.env.STUDIO_WORKER_TASK_FILE;
21
+ if (!workerScriptPath) {
22
+ throw new Error('Missing `STUDIO_WORKER_TASK_FILE` environment variable');
23
+ }
24
+ const mockStubs = stubs;
25
+ const mockedGlobalThis = globalThis;
26
+ for(const key in stubs){
27
+ if (!(key in mockedGlobalThis)) {
28
+ mockedGlobalThis[key] = mockStubs[key];
29
+ }
30
+ }
31
+ // Doesn't have to be correct, just need the root path to be
32
+ const fakeConfigUrl = pathToFileURL(resolve(rootPath, 'sanity.config.mjs'));
33
+ // We'll load `getStudioEnvironmentVariables` from the `sanity/cli` module installed
34
+ // relative to where the studio is located, instead of resolving from where this CLI is
35
+ // running in, in order to ensure we're using the same version as the studio would.
36
+ const sanityCliUrl = await moduleResolve('sanity/cli', fakeConfigUrl);
37
+ const { getStudioEnvironmentVariables } = await import(sanityCliUrl.href);
38
+ if (typeof getStudioEnvironmentVariables !== 'function') {
39
+ throw new TypeError('Expected `getStudioEnvironmentVariables` from `sanity/cli` to be a function');
40
+ }
41
+ const defaultViteConfig = {
42
+ build: {
43
+ target: 'node'
44
+ },
45
+ configFile: false,
46
+ define: {
47
+ ...getStudioEnvironmentVariables({
48
+ jsonEncode: true,
49
+ prefix: 'process.env.'
50
+ })
51
+ },
52
+ logLevel: 'error',
53
+ optimizeDeps: {
54
+ disabled: true
55
+ },
56
+ root: rootPath,
57
+ server: {
58
+ hmr: false,
59
+ watch: null
60
+ }
61
+ };
62
+ // Allow the CLI config (`sanity.cli.(js|ts)`) to define a `vite` property which can
63
+ // extend/modify the default vite configuration for the studio.
64
+ let cliConfig;
65
+ try {
66
+ cliConfig = await getCliConfig(rootPath);
67
+ } catch (err) {
68
+ if (!isNotFoundError(err)) {
69
+ console.warn('[warn] Failed to load CLI config:', err);
70
+ }
71
+ }
72
+ let viteConfig = defaultViteConfig;
73
+ if (typeof cliConfig?.vite === 'function') {
74
+ viteConfig = await cliConfig.vite(viteConfig, {
75
+ command: 'build',
76
+ isSsrBuild: true,
77
+ mode: 'production'
78
+ });
79
+ } else if (isRecord(cliConfig?.vite)) {
80
+ viteConfig = mergeConfig(viteConfig, cliConfig.vite);
81
+ }
82
+ // Vite will build the files we give it - targetting Node.js instead of the browser.
83
+ // We include the inject plugin in order to provide the stubs for the undefined global APIs.
84
+ const server = await createServer(viteConfig);
85
+ // Bit of a hack, but seems necessary based on the `node-vite` binary implementation
86
+ await server.pluginContainer.buildStart({});
87
+ // Load environment variables from `.env` files in the same way as Vite does.
88
+ // Note that Sanity also provides environment variables through `process.env.*` for compat reasons,
89
+ // and so we need to do the same here.
90
+ // @todo is this in line with sanity?
91
+ const env = loadEnv(server.config.mode, server.config.envDir, '');
92
+ for(const key in env){
93
+ process.env[key] ??= env[key];
94
+ }
95
+ // Now we're providing the glue that ensures node-specific loading and execution works.
96
+ const node = new ViteNodeServer(server);
97
+ // Should make it easier to debug any crashes in the imported code…
98
+ installSourcemapsSupport({
99
+ getSourceMap: (source)=>node.getSourceMap(source)
100
+ });
101
+ const runner = new ViteNodeRunner({
102
+ base: server.config.base,
103
+ async fetchModule (id) {
104
+ return node.fetchModule(id);
105
+ },
106
+ resolveId (id, importer) {
107
+ return node.resolveId(id, importer);
108
+ },
109
+ root: server.config.root
110
+ });
111
+ // Copied from `vite-node` - it appears that this applies the `define` config from
112
+ // vite, but it also takes a surprisingly long time to execute. Not clear at this
113
+ // point why this is, so we should investigate whether it's necessary or not.
114
+ await runner.executeId('/@vite/env');
115
+ await runner.executeId(workerScriptPath);
116
+
117
+ //# sourceMappingURL=studioWorkerLoader.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/loaders/studio/studioWorkerLoader.worker.ts"],"sourcesContent":["import {resolve} from 'node:path'\nimport {pathToFileURL} from 'node:url'\nimport {isMainThread} from 'node:worker_threads'\n\nimport {moduleResolve} from 'import-meta-resolve'\nimport {createServer, type InlineConfig, loadEnv, mergeConfig} from 'vite'\nimport {ViteNodeRunner} from 'vite-node/client'\nimport {ViteNodeServer} from 'vite-node/server'\nimport {installSourcemapsSupport} from 'vite-node/source-map'\n\nimport {getCliConfig} from '../../config/cli/getCliConfig.js'\nimport {type CliConfig} from '../../config/cli/types.js'\nimport {isRecord} from '../../util/isRecord.js'\nimport {isNotFoundError} from '../../util/NotFoundError.js'\nimport * as stubs from './stubs.js'\n\nif (isMainThread) {\n throw new Error('Should be child of thread, not the main thread')\n}\n\nconst rootPath = process.env.STUDIO_WORKER_STUDIO_ROOT_PATH\nif (!rootPath) {\n throw new Error('Missing `STUDIO_WORKER_STUDIO_ROOT_PATH` environment variable')\n}\n\nconst workerScriptPath = process.env.STUDIO_WORKER_TASK_FILE\nif (!workerScriptPath) {\n throw new Error('Missing `STUDIO_WORKER_TASK_FILE` environment variable')\n}\n\nconst mockStubs = stubs as Record<string, unknown>\nconst mockedGlobalThis: Record<string, unknown> = globalThis\nfor (const key in stubs) {\n if (!(key in mockedGlobalThis)) {\n mockedGlobalThis[key] = mockStubs[key]\n }\n}\n\n// Doesn't have to be correct, just need the root path to be\nconst fakeConfigUrl = pathToFileURL(resolve(rootPath, 'sanity.config.mjs'))\n\n// We'll load `getStudioEnvironmentVariables` from the `sanity/cli` module installed\n// relative to where the studio is located, instead of resolving from where this CLI is\n// running in, in order to ensure we're using the same version as the studio would.\nconst sanityCliUrl = await moduleResolve('sanity/cli', fakeConfigUrl)\nconst {getStudioEnvironmentVariables} = await import(sanityCliUrl.href)\nif (typeof getStudioEnvironmentVariables !== 'function') {\n throw new TypeError('Expected `getStudioEnvironmentVariables` from `sanity/cli` to be a function')\n}\n\nconst defaultViteConfig: InlineConfig = {\n build: {target: 'node'},\n configFile: false, // @todo Should use `vite` prop from `sanity.cli.ts` (if any)\n define: {\n ...getStudioEnvironmentVariables({jsonEncode: true, prefix: 'process.env.'}),\n },\n logLevel: 'error',\n optimizeDeps: {disabled: true}, // @todo is this necessary? cant remember why was added\n root: rootPath,\n server: {\n hmr: false,\n watch: null,\n },\n}\n\n// Allow the CLI config (`sanity.cli.(js|ts)`) to define a `vite` property which can\n// extend/modify the default vite configuration for the studio.\nlet cliConfig: CliConfig | undefined\ntry {\n cliConfig = await getCliConfig(rootPath)\n} catch (err) {\n if (!isNotFoundError(err)) {\n console.warn('[warn] Failed to load CLI config:', err)\n }\n}\n\nlet viteConfig = defaultViteConfig\nif (typeof cliConfig?.vite === 'function') {\n viteConfig = (await cliConfig.vite(viteConfig, {\n command: 'build',\n isSsrBuild: true,\n mode: 'production',\n })) as InlineConfig\n} else if (isRecord(cliConfig?.vite)) {\n viteConfig = mergeConfig(viteConfig, cliConfig.vite)\n}\n\n// Vite will build the files we give it - targetting Node.js instead of the browser.\n// We include the inject plugin in order to provide the stubs for the undefined global APIs.\nconst server = await createServer(viteConfig)\n\n// Bit of a hack, but seems necessary based on the `node-vite` binary implementation\nawait server.pluginContainer.buildStart({})\n\n// Load environment variables from `.env` files in the same way as Vite does.\n// Note that Sanity also provides environment variables through `process.env.*` for compat reasons,\n// and so we need to do the same here.\n// @todo is this in line with sanity?\nconst env = loadEnv(server.config.mode, server.config.envDir, '')\nfor (const key in env) {\n process.env[key] ??= env[key]\n}\n\n// Now we're providing the glue that ensures node-specific loading and execution works.\nconst node = new ViteNodeServer(server)\n\n// Should make it easier to debug any crashes in the imported code…\ninstallSourcemapsSupport({\n getSourceMap: (source) => node.getSourceMap(source),\n})\n\nconst runner = new ViteNodeRunner({\n base: server.config.base,\n async fetchModule(id) {\n return node.fetchModule(id)\n },\n resolveId(id, importer) {\n return node.resolveId(id, importer)\n },\n root: server.config.root,\n})\n\n// Copied from `vite-node` - it appears that this applies the `define` config from\n// vite, but it also takes a surprisingly long time to execute. Not clear at this\n// point why this is, so we should investigate whether it's necessary or not.\nawait runner.executeId('/@vite/env')\n\nawait runner.executeId(workerScriptPath)\n"],"names":["resolve","pathToFileURL","isMainThread","moduleResolve","createServer","loadEnv","mergeConfig","ViteNodeRunner","ViteNodeServer","installSourcemapsSupport","getCliConfig","isRecord","isNotFoundError","stubs","Error","rootPath","process","env","STUDIO_WORKER_STUDIO_ROOT_PATH","workerScriptPath","STUDIO_WORKER_TASK_FILE","mockStubs","mockedGlobalThis","globalThis","key","fakeConfigUrl","sanityCliUrl","getStudioEnvironmentVariables","href","TypeError","defaultViteConfig","build","target","configFile","define","jsonEncode","prefix","logLevel","optimizeDeps","disabled","root","server","hmr","watch","cliConfig","err","console","warn","viteConfig","vite","command","isSsrBuild","mode","pluginContainer","buildStart","config","envDir","node","getSourceMap","source","runner","base","fetchModule","id","resolveId","importer","executeId"],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type WorkerOptions } from 'node:worker_threads';
2
+ import { type RequireProps } from '../../types.js';
3
+ /**
4
+ * Options for the studio worker task
5
+ *
6
+ * @internal
7
+ */
8
+ interface StudioWorkerTaskOptions extends RequireProps<WorkerOptions, 'name'> {
9
+ studioRootPath: string;
10
+ }
11
+ /**
12
+ * Executes a worker file in a Sanity Studio browser context.
13
+ *
14
+ * This uses a combination of vite for "bundling" + jsdom for emulating a browser
15
+ * environment under the hood, which means that the same thing that will work in vite
16
+ * _should_ work in the worker - to a degree. If the user has defined any typescript
17
+ * path aliases, these will have to be added as aliases to the vite config - the same
18
+ * behavior as you would see with regular vite. Other things that are accounted for:
19
+ *
20
+ * - TypeScript support (+JSX, enums and other "compilation needed" features)
21
+ * - CSS, font and other file imports will resolve to a file path
22
+ * - CSS module imports will resolve to a javascript object of class names
23
+ * - Environment variables are available both as `import.meta.env` and `process.env`,
24
+ * and `.env` files are loaded in the same way that they would in a Sanity studio.
25
+ * - Browser globals not available in a Node.js environment but _are_ provided by JSDOM
26
+ * are defined directly to the Node environment as globals. While this polutes the
27
+ * global namespace, it is done only in the worker thread.
28
+ * - Certain browser globals that are _not_ available in JSDOM are also provided to the
29
+ * global namespace - things like `requestIdleCallback`, `IntersectionObserver` etc.
30
+ * These are provided with a minimal stub implementation to make them not crash.
31
+ *
32
+ * @param filePath - Path to the worker file (`.ts` works and is encouraged)
33
+ * @param options - Options to pass to the worker
34
+ * @returns A promise that resolves with the message from the worker
35
+ * @throws If the file does not exist
36
+ * @throws If the worker exits with a non-zero code
37
+ * @internal
38
+ */
39
+ export declare function studioWorkerTask(filePath: URL, options: StudioWorkerTaskOptions): Promise<unknown>;
40
+ export {};
@@ -0,0 +1,69 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { isRecord } from '../../util/isRecord.js';
3
+ /**
4
+ * Executes a worker file in a Sanity Studio browser context.
5
+ *
6
+ * This uses a combination of vite for "bundling" + jsdom for emulating a browser
7
+ * environment under the hood, which means that the same thing that will work in vite
8
+ * _should_ work in the worker - to a degree. If the user has defined any typescript
9
+ * path aliases, these will have to be added as aliases to the vite config - the same
10
+ * behavior as you would see with regular vite. Other things that are accounted for:
11
+ *
12
+ * - TypeScript support (+JSX, enums and other "compilation needed" features)
13
+ * - CSS, font and other file imports will resolve to a file path
14
+ * - CSS module imports will resolve to a javascript object of class names
15
+ * - Environment variables are available both as `import.meta.env` and `process.env`,
16
+ * and `.env` files are loaded in the same way that they would in a Sanity studio.
17
+ * - Browser globals not available in a Node.js environment but _are_ provided by JSDOM
18
+ * are defined directly to the Node environment as globals. While this polutes the
19
+ * global namespace, it is done only in the worker thread.
20
+ * - Certain browser globals that are _not_ available in JSDOM are also provided to the
21
+ * global namespace - things like `requestIdleCallback`, `IntersectionObserver` etc.
22
+ * These are provided with a minimal stub implementation to make them not crash.
23
+ *
24
+ * @param filePath - Path to the worker file (`.ts` works and is encouraged)
25
+ * @param options - Options to pass to the worker
26
+ * @returns A promise that resolves with the message from the worker
27
+ * @throws If the file does not exist
28
+ * @throws If the worker exits with a non-zero code
29
+ * @internal
30
+ */ export function studioWorkerTask(filePath, options) {
31
+ return new Promise((resolve, reject)=>{
32
+ if (!/\.worker\.(js|ts)$/.test(filePath.pathname)) {
33
+ throw new Error('Studio worker tasks must include `.worker.(js|ts)` in path');
34
+ }
35
+ const worker = new Worker(new URL('studioWorkerLoader.worker.js', import.meta.url), {
36
+ ...options,
37
+ env: {
38
+ ...isRecord(options.env) ? options.env : process.env,
39
+ STUDIO_WORKER_STUDIO_ROOT_PATH: options.studioRootPath,
40
+ STUDIO_WORKER_TASK_FILE: filePath.pathname
41
+ }
42
+ });
43
+ worker.addListener('error', function onWorkerError(err) {
44
+ reject(new Error(`Fail to load file through worker: ${err.message}`));
45
+ cleanup();
46
+ });
47
+ worker.addListener('exit', function onWorkerExit(code) {
48
+ if (code > 0) {
49
+ reject(new Error(`Worker exited with code ${code}`));
50
+ }
51
+ });
52
+ worker.addListener('messageerror', function onWorkerMessageError(err) {
53
+ reject(new Error(`Fail to parse message from worker: ${err}`));
54
+ cleanup();
55
+ });
56
+ worker.addListener('message', function onWorkerMessage(message) {
57
+ resolve(message);
58
+ cleanup();
59
+ });
60
+ function cleanup() {
61
+ // Allow the worker a _bit_ of time to clean up, but ensure that we don't have
62
+ // lingering processes hanging around forever if the worker doesn't exit on its
63
+ // own.
64
+ setImmediate(()=>worker.terminate());
65
+ }
66
+ });
67
+ }
68
+
69
+ //# sourceMappingURL=studioWorkerTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/loaders/studio/studioWorkerTask.ts"],"sourcesContent":["import {Worker, type WorkerOptions} from 'node:worker_threads'\n\nimport {type RequireProps} from '../../types.js'\nimport {isRecord} from '../../util/isRecord.js'\n\n/**\n * Options for the studio worker task\n *\n * @internal\n */\ninterface StudioWorkerTaskOptions extends RequireProps<WorkerOptions, 'name'> {\n studioRootPath: string\n}\n\n/**\n * Executes a worker file in a Sanity Studio browser context.\n *\n * This uses a combination of vite for \"bundling\" + jsdom for emulating a browser\n * environment under the hood, which means that the same thing that will work in vite\n * _should_ work in the worker - to a degree. If the user has defined any typescript\n * path aliases, these will have to be added as aliases to the vite config - the same\n * behavior as you would see with regular vite. Other things that are accounted for:\n *\n * - TypeScript support (+JSX, enums and other \"compilation needed\" features)\n * - CSS, font and other file imports will resolve to a file path\n * - CSS module imports will resolve to a javascript object of class names\n * - Environment variables are available both as `import.meta.env` and `process.env`,\n * and `.env` files are loaded in the same way that they would in a Sanity studio.\n * - Browser globals not available in a Node.js environment but _are_ provided by JSDOM\n * are defined directly to the Node environment as globals. While this polutes the\n * global namespace, it is done only in the worker thread.\n * - Certain browser globals that are _not_ available in JSDOM are also provided to the\n * global namespace - things like `requestIdleCallback`, `IntersectionObserver` etc.\n * These are provided with a minimal stub implementation to make them not crash.\n *\n * @param filePath - Path to the worker file (`.ts` works and is encouraged)\n * @param options - Options to pass to the worker\n * @returns A promise that resolves with the message from the worker\n * @throws If the file does not exist\n * @throws If the worker exits with a non-zero code\n * @internal\n */\nexport function studioWorkerTask(\n filePath: URL,\n options: StudioWorkerTaskOptions,\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (!/\\.worker\\.(js|ts)$/.test(filePath.pathname)) {\n throw new Error('Studio worker tasks must include `.worker.(js|ts)` in path')\n }\n\n const worker = new Worker(new URL('studioWorkerLoader.worker.js', import.meta.url), {\n ...options,\n env: {\n ...(isRecord(options.env) ? options.env : process.env),\n STUDIO_WORKER_STUDIO_ROOT_PATH: options.studioRootPath,\n STUDIO_WORKER_TASK_FILE: filePath.pathname,\n },\n })\n\n worker.addListener('error', function onWorkerError(err) {\n reject(new Error(`Fail to load file through worker: ${err.message}`))\n cleanup()\n })\n worker.addListener('exit', function onWorkerExit(code) {\n if (code > 0) {\n reject(new Error(`Worker exited with code ${code}`))\n }\n })\n worker.addListener('messageerror', function onWorkerMessageError(err) {\n reject(new Error(`Fail to parse message from worker: ${err}`))\n cleanup()\n })\n worker.addListener('message', function onWorkerMessage(message) {\n resolve(message)\n cleanup()\n })\n\n function cleanup() {\n // Allow the worker a _bit_ of time to clean up, but ensure that we don't have\n // lingering processes hanging around forever if the worker doesn't exit on its\n // own.\n setImmediate(() => worker.terminate())\n }\n })\n}\n"],"names":["Worker","isRecord","studioWorkerTask","filePath","options","Promise","resolve","reject","test","pathname","Error","worker","URL","url","env","process","STUDIO_WORKER_STUDIO_ROOT_PATH","studioRootPath","STUDIO_WORKER_TASK_FILE","addListener","onWorkerError","err","message","cleanup","onWorkerExit","code","onWorkerMessageError","onWorkerMessage","setImmediate","terminate"],"mappings":"AAAA,SAAQA,MAAM,QAA2B,sBAAqB;AAG9D,SAAQC,QAAQ,QAAO,yBAAwB;AAW/C;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,OAAO,SAASC,iBACdC,QAAa,EACbC,OAAgC;IAEhC,OAAO,IAAIC,QAAQ,CAACC,SAASC;QAC3B,IAAI,CAAC,qBAAqBC,IAAI,CAACL,SAASM,QAAQ,GAAG;YACjD,MAAM,IAAIC,MAAM;QAClB;QAEA,MAAMC,SAAS,IAAIX,OAAO,IAAIY,IAAI,gCAAgC,YAAYC,GAAG,GAAG;YAClF,GAAGT,OAAO;YACVU,KAAK;gBACH,GAAIb,SAASG,QAAQU,GAAG,IAAIV,QAAQU,GAAG,GAAGC,QAAQD,GAAG;gBACrDE,gCAAgCZ,QAAQa,cAAc;gBACtDC,yBAAyBf,SAASM,QAAQ;YAC5C;QACF;QAEAE,OAAOQ,WAAW,CAAC,SAAS,SAASC,cAAcC,GAAG;YACpDd,OAAO,IAAIG,MAAM,CAAC,kCAAkC,EAAEW,IAAIC,OAAO,EAAE;YACnEC;QACF;QACAZ,OAAOQ,WAAW,CAAC,QAAQ,SAASK,aAAaC,IAAI;YACnD,IAAIA,OAAO,GAAG;gBACZlB,OAAO,IAAIG,MAAM,CAAC,wBAAwB,EAAEe,MAAM;YACpD;QACF;QACAd,OAAOQ,WAAW,CAAC,gBAAgB,SAASO,qBAAqBL,GAAG;YAClEd,OAAO,IAAIG,MAAM,CAAC,mCAAmC,EAAEW,KAAK;YAC5DE;QACF;QACAZ,OAAOQ,WAAW,CAAC,WAAW,SAASQ,gBAAgBL,OAAO;YAC5DhB,QAAQgB;YACRC;QACF;QAEA,SAASA;YACP,8EAA8E;YAC9E,+EAA+E;YAC/E,OAAO;YACPK,aAAa,IAAMjB,OAAOkB,SAAS;QACrC;IACF;AACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { tsImport } from 'tsx/esm/api';
2
+ const workerScript = process.env.TSX_WORKER_TASK_SCRIPT;
3
+ if (workerScript) {
4
+ await tsImport(workerScript, {
5
+ parentURL: import.meta.url,
6
+ tsconfig: process.env.TSX_TSCONFIG_PATH
7
+ });
8
+ } else {
9
+ throw new Error('`TX_WORKER_TASK_SCRIPT` not defined');
10
+ }
11
+
12
+ //# sourceMappingURL=tsxWorkerLoader.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/loaders/tsx/tsxWorkerLoader.worker.ts"],"sourcesContent":["import {tsImport} from 'tsx/esm/api'\n\nconst workerScript = process.env.TSX_WORKER_TASK_SCRIPT\n\nif (workerScript) {\n await tsImport(workerScript, {\n parentURL: import.meta.url,\n tsconfig: process.env.TSX_TSCONFIG_PATH,\n })\n} else {\n throw new Error('`TX_WORKER_TASK_SCRIPT` not defined')\n}\n"],"names":["tsImport","workerScript","process","env","TSX_WORKER_TASK_SCRIPT","parentURL","url","tsconfig","TSX_TSCONFIG_PATH","Error"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,cAAa;AAEpC,MAAMC,eAAeC,QAAQC,GAAG,CAACC,sBAAsB;AAEvD,IAAIH,cAAc;IAChB,MAAMD,SAASC,cAAc;QAC3BI,WAAW,YAAYC,GAAG;QAC1BC,UAAUL,QAAQC,GAAG,CAACK,iBAAiB;IACzC;AACF,OAAO;IACL,MAAM,IAAIC,MAAM;AAClB"}
@@ -0,0 +1,28 @@
1
+ import { URL } from 'node:url';
2
+ import { type WorkerOptions } from 'node:worker_threads';
3
+ import { type RequireProps } from '../../types.js';
4
+ /**
5
+ * Options for the tsx worker task
6
+ *
7
+ * @internal
8
+ */
9
+ interface TsxWorkerTaskOptions extends RequireProps<WorkerOptions, 'name'> {
10
+ rootPath: string;
11
+ }
12
+ /**
13
+ * Executes a worker file with tsx registered. This means you can import other
14
+ * typescript with fairly rich syntax, and still have that only apply to the worker
15
+ * thread instead of the full parent process. The worker should emit a message when
16
+ * complete using `parentPort`. Once it has received a single message will resolve the
17
+ * returned promise with that message. If you are expecting multiple messages, you will
18
+ * have to implement another method ;)
19
+ *
20
+ * @param filePath - Path to the worker file
21
+ * @param options - Options to pass to the worker
22
+ * @returns A promise that resolves with the message from the worker
23
+ * @throws If the file does not exist
24
+ * @throws If the worker exits with a non-zero code
25
+ * @internal
26
+ */
27
+ export declare function tsxWorkerTask<T = unknown>(filePath: URL, options: TsxWorkerTaskOptions): Promise<T>;
28
+ export {};
@@ -0,0 +1,61 @@
1
+ import { URL } from 'node:url';
2
+ import { Worker } from 'node:worker_threads';
3
+ import { getTsconfig } from 'get-tsconfig';
4
+ import { isRecord } from '../../util/isRecord.js';
5
+ /**
6
+ * Executes a worker file with tsx registered. This means you can import other
7
+ * typescript with fairly rich syntax, and still have that only apply to the worker
8
+ * thread instead of the full parent process. The worker should emit a message when
9
+ * complete using `parentPort`. Once it has received a single message will resolve the
10
+ * returned promise with that message. If you are expecting multiple messages, you will
11
+ * have to implement another method ;)
12
+ *
13
+ * @param filePath - Path to the worker file
14
+ * @param options - Options to pass to the worker
15
+ * @returns A promise that resolves with the message from the worker
16
+ * @throws If the file does not exist
17
+ * @throws If the worker exits with a non-zero code
18
+ * @internal
19
+ */ export function tsxWorkerTask(filePath, options) {
20
+ const tsconfig = getTsconfig(options.rootPath);
21
+ const env = {
22
+ ...isRecord(options.env) ? options.env : process.env,
23
+ ...tsconfig?.path ? {
24
+ TSX_TSCONFIG_PATH: tsconfig.path
25
+ } : {},
26
+ TSX_WORKER_TASK_SCRIPT: filePath.pathname
27
+ };
28
+ const worker = new Worker(new URL('tsxWorkerLoader.worker.js', import.meta.url), {
29
+ ...options,
30
+ env
31
+ });
32
+ return new Promise((resolve, reject)=>{
33
+ worker.addListener('error', function onWorkerError(err) {
34
+ reject(new Error(`Failed to load file through worker: ${err.message}`, {
35
+ cause: err
36
+ }));
37
+ cleanup();
38
+ });
39
+ worker.addListener('exit', function onWorkerExit(code) {
40
+ if (code > 0) {
41
+ reject(new Error(`Worker exited with code ${code}`));
42
+ }
43
+ });
44
+ worker.addListener('messageerror', function onWorkerMessageError(err) {
45
+ reject(new Error(`Fail to parse message from worker: ${err}`));
46
+ cleanup();
47
+ });
48
+ worker.addListener('message', function onWorkerMessage(message) {
49
+ resolve(message);
50
+ cleanup();
51
+ });
52
+ function cleanup() {
53
+ // Allow the worker a _bit_ of time to clean up, but ensure that we don't have
54
+ // lingering processes hanging around forever if the worker doesn't exit on its
55
+ // own.
56
+ setImmediate(()=>worker.terminate());
57
+ }
58
+ });
59
+ }
60
+
61
+ //# sourceMappingURL=tsxWorkerTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/loaders/tsx/tsxWorkerTask.ts"],"sourcesContent":["import {URL} from 'node:url'\nimport {Worker, type WorkerOptions} from 'node:worker_threads'\n\nimport {getTsconfig} from 'get-tsconfig'\n\nimport {type RequireProps} from '../../types.js'\nimport {isRecord} from '../../util/isRecord.js'\n\n/**\n * Options for the tsx worker task\n *\n * @internal\n */\ninterface TsxWorkerTaskOptions extends RequireProps<WorkerOptions, 'name'> {\n rootPath: string\n}\n\n/**\n * Executes a worker file with tsx registered. This means you can import other\n * typescript with fairly rich syntax, and still have that only apply to the worker\n * thread instead of the full parent process. The worker should emit a message when\n * complete using `parentPort`. Once it has received a single message will resolve the\n * returned promise with that message. If you are expecting multiple messages, you will\n * have to implement another method ;)\n *\n * @param filePath - Path to the worker file\n * @param options - Options to pass to the worker\n * @returns A promise that resolves with the message from the worker\n * @throws If the file does not exist\n * @throws If the worker exits with a non-zero code\n * @internal\n */\nexport function tsxWorkerTask<T = unknown>(\n filePath: URL,\n options: TsxWorkerTaskOptions,\n): Promise<T> {\n const tsconfig = getTsconfig(options.rootPath)\n\n const env = {\n ...(isRecord(options.env) ? options.env : process.env),\n ...(tsconfig?.path ? {TSX_TSCONFIG_PATH: tsconfig.path} : {}),\n TSX_WORKER_TASK_SCRIPT: filePath.pathname,\n }\n\n const worker = new Worker(new URL('tsxWorkerLoader.worker.js', import.meta.url), {\n ...options,\n env,\n })\n\n return new Promise((resolve, reject) => {\n worker.addListener('error', function onWorkerError(err) {\n reject(new Error(`Failed to load file through worker: ${err.message}`, {cause: err}))\n cleanup()\n })\n worker.addListener('exit', function onWorkerExit(code) {\n if (code > 0) {\n reject(new Error(`Worker exited with code ${code}`))\n }\n })\n worker.addListener('messageerror', function onWorkerMessageError(err) {\n reject(new Error(`Fail to parse message from worker: ${err}`))\n cleanup()\n })\n worker.addListener('message', function onWorkerMessage(message) {\n resolve(message)\n cleanup()\n })\n\n function cleanup() {\n // Allow the worker a _bit_ of time to clean up, but ensure that we don't have\n // lingering processes hanging around forever if the worker doesn't exit on its\n // own.\n setImmediate(() => worker.terminate())\n }\n })\n}\n"],"names":["URL","Worker","getTsconfig","isRecord","tsxWorkerTask","filePath","options","tsconfig","rootPath","env","process","path","TSX_TSCONFIG_PATH","TSX_WORKER_TASK_SCRIPT","pathname","worker","url","Promise","resolve","reject","addListener","onWorkerError","err","Error","message","cause","cleanup","onWorkerExit","code","onWorkerMessageError","onWorkerMessage","setImmediate","terminate"],"mappings":"AAAA,SAAQA,GAAG,QAAO,WAAU;AAC5B,SAAQC,MAAM,QAA2B,sBAAqB;AAE9D,SAAQC,WAAW,QAAO,eAAc;AAGxC,SAAQC,QAAQ,QAAO,yBAAwB;AAW/C;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,cACdC,QAAa,EACbC,OAA6B;IAE7B,MAAMC,WAAWL,YAAYI,QAAQE,QAAQ;IAE7C,MAAMC,MAAM;QACV,GAAIN,SAASG,QAAQG,GAAG,IAAIH,QAAQG,GAAG,GAAGC,QAAQD,GAAG;QACrD,GAAIF,UAAUI,OAAO;YAACC,mBAAmBL,SAASI,IAAI;QAAA,IAAI,CAAC,CAAC;QAC5DE,wBAAwBR,SAASS,QAAQ;IAC3C;IAEA,MAAMC,SAAS,IAAId,OAAO,IAAID,IAAI,6BAA6B,YAAYgB,GAAG,GAAG;QAC/E,GAAGV,OAAO;QACVG;IACF;IAEA,OAAO,IAAIQ,QAAQ,CAACC,SAASC;QAC3BJ,OAAOK,WAAW,CAAC,SAAS,SAASC,cAAcC,GAAG;YACpDH,OAAO,IAAII,MAAM,CAAC,oCAAoC,EAAED,IAAIE,OAAO,EAAE,EAAE;gBAACC,OAAOH;YAAG;YAClFI;QACF;QACAX,OAAOK,WAAW,CAAC,QAAQ,SAASO,aAAaC,IAAI;YACnD,IAAIA,OAAO,GAAG;gBACZT,OAAO,IAAII,MAAM,CAAC,wBAAwB,EAAEK,MAAM;YACpD;QACF;QACAb,OAAOK,WAAW,CAAC,gBAAgB,SAASS,qBAAqBP,GAAG;YAClEH,OAAO,IAAII,MAAM,CAAC,mCAAmC,EAAED,KAAK;YAC5DI;QACF;QACAX,OAAOK,WAAW,CAAC,WAAW,SAASU,gBAAgBN,OAAO;YAC5DN,QAAQM;YACRE;QACF;QAEA,SAASA;YACP,8EAA8E;YAC9E,+EAA+E;YAC/E,OAAO;YACPK,aAAa,IAAMhB,OAAOiB,SAAS;QACrC;IACF;AACF"}
@@ -0,0 +1,39 @@
1
+ import { type SanityClient } from '@sanity/client';
2
+ /**
3
+ * @internal
4
+ */
5
+ export interface GlobalCliClientOptions {
6
+ /**
7
+ * The API version to use for this client.
8
+ */
9
+ apiVersion: string;
10
+ /**
11
+ * Whether to require a user to be authenticated to use this client.
12
+ * Default: `false`.
13
+ * Throws an error if `true` and user is not authenticated.
14
+ */
15
+ requireUser?: boolean;
16
+ }
17
+ /**
18
+ * Create a "global" (unscoped) Sanity API client.
19
+ *
20
+ * @param options - The options to use for the client.
21
+ * @returns Promise that resolves to a configured Sanity API client.
22
+ */
23
+ export declare function getGlobalCliClient({ apiVersion, requireUser, }: GlobalCliClientOptions): Promise<SanityClient>;
24
+ /**
25
+ * @internal
26
+ */
27
+ export interface ProjectCliClientOptions {
28
+ apiVersion: string;
29
+ projectId: string;
30
+ dataset?: string;
31
+ requireUser?: boolean;
32
+ }
33
+ /**
34
+ * Create a "global" (unscoped) Sanity API client.
35
+ *
36
+ * @param options - The options to use for the client.
37
+ * @returns Promise that resolves to a configured Sanity API client.
38
+ */
39
+ export declare function getProjectCliClient({ apiVersion, dataset, projectId, requireUser, }: ProjectCliClientOptions): Promise<SanityClient>;
@@ -0,0 +1,88 @@
1
+ import { ux } from '@oclif/core';
2
+ import { createClient, requester as defaultRequester } from '@sanity/client';
3
+ import { generateHelpUrl } from '../util/generateHelpUrl.js';
4
+ import { isHttpError } from '../util/isHttpError.js';
5
+ import { getCliToken } from './getCliToken.js';
6
+ const apiHosts = {
7
+ staging: 'https://api.sanity.work'
8
+ };
9
+ const CLI_REQUEST_TAG_PREFIX = 'sanity.cli';
10
+ /**
11
+ * Create a "global" (unscoped) Sanity API client.
12
+ *
13
+ * @param options - The options to use for the client.
14
+ * @returns Promise that resolves to a configured Sanity API client.
15
+ */ export async function getGlobalCliClient({ apiVersion, requireUser }) {
16
+ const requester = defaultRequester.clone();
17
+ requester.use(authErrors());
18
+ const sanityEnv = process.env.SANITY_INTERNAL_ENV || 'production';
19
+ const token = await getCliToken();
20
+ const apiHost = apiHosts[sanityEnv];
21
+ if (requireUser && !token) {
22
+ throw new Error('You must login first - run "sanity login"');
23
+ }
24
+ return createClient({
25
+ ...apiHost ? {
26
+ apiHost
27
+ } : {},
28
+ apiVersion,
29
+ requester,
30
+ requestTagPrefix: CLI_REQUEST_TAG_PREFIX,
31
+ token,
32
+ useCdn: false,
33
+ useProjectHostname: false
34
+ });
35
+ }
36
+ /**
37
+ * Create a "global" (unscoped) Sanity API client.
38
+ *
39
+ * @param options - The options to use for the client.
40
+ * @returns Promise that resolves to a configured Sanity API client.
41
+ */ export async function getProjectCliClient({ apiVersion, dataset, projectId, requireUser }) {
42
+ const requester = defaultRequester.clone();
43
+ requester.use(authErrors());
44
+ const sanityEnv = process.env.SANITY_INTERNAL_ENV || 'production';
45
+ const token = await getCliToken();
46
+ const apiHost = apiHosts[sanityEnv];
47
+ if (requireUser && !token) {
48
+ throw new Error('You must login first - run "sanity login"');
49
+ }
50
+ return createClient({
51
+ ...apiHost ? {
52
+ apiHost
53
+ } : {},
54
+ apiVersion,
55
+ dataset,
56
+ projectId,
57
+ requester,
58
+ requestTagPrefix: CLI_REQUEST_TAG_PREFIX,
59
+ token,
60
+ useCdn: false,
61
+ useProjectHostname: true
62
+ });
63
+ }
64
+ /**
65
+ * `get-it` middleware that checks for 401 authentication errors and extends the error with more
66
+ * helpful guidance on what to do next.
67
+ *
68
+ * @returns get-it middleware with `onError` handler
69
+ * @internal
70
+ */ function authErrors() {
71
+ return {
72
+ onError: (err)=>{
73
+ if (!err || !isReqResError(err)) {
74
+ return err;
75
+ }
76
+ const statusCode = isHttpError(err) && err.response.body.statusCode;
77
+ if (statusCode === 401) {
78
+ err.message = `${err.message}. You may need to login again with ${ux.colorize('cyan', 'sanity login')}.\nFor more information, see ${generateHelpUrl('cli-errors')}.`;
79
+ }
80
+ return err;
81
+ }
82
+ };
83
+ }
84
+ function isReqResError(err) {
85
+ return Object.prototype.hasOwnProperty.call(err, 'response');
86
+ }
87
+
88
+ //# sourceMappingURL=apiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/services/apiClient.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {\n type ClientError,\n createClient,\n requester as defaultRequester,\n type SanityClient,\n type ServerError,\n} from '@sanity/client'\n\nimport {generateHelpUrl} from '../util/generateHelpUrl.js'\nimport {isHttpError} from '../util/isHttpError.js'\nimport {getCliToken} from './getCliToken.js'\n\nconst apiHosts: Record<string, string | undefined> = {\n staging: 'https://api.sanity.work',\n}\n\nconst CLI_REQUEST_TAG_PREFIX = 'sanity.cli'\n\n/**\n * @internal\n */\nexport interface GlobalCliClientOptions {\n /**\n * The API version to use for this client.\n */\n apiVersion: string\n\n /**\n * Whether to require a user to be authenticated to use this client.\n * Default: `false`.\n * Throws an error if `true` and user is not authenticated.\n */\n requireUser?: boolean\n}\n\n/**\n * Create a \"global\" (unscoped) Sanity API client.\n *\n * @param options - The options to use for the client.\n * @returns Promise that resolves to a configured Sanity API client.\n */\nexport async function getGlobalCliClient({\n apiVersion,\n requireUser,\n}: GlobalCliClientOptions): Promise<SanityClient> {\n const requester = defaultRequester.clone()\n requester.use(authErrors())\n\n const sanityEnv = process.env.SANITY_INTERNAL_ENV || 'production'\n\n const token = await getCliToken()\n const apiHost = apiHosts[sanityEnv]\n\n if (requireUser && !token) {\n throw new Error('You must login first - run \"sanity login\"')\n }\n\n return createClient({\n ...(apiHost ? {apiHost} : {}),\n apiVersion,\n requester,\n requestTagPrefix: CLI_REQUEST_TAG_PREFIX,\n token,\n useCdn: false,\n useProjectHostname: false,\n })\n}\n\n/**\n * @internal\n */\nexport interface ProjectCliClientOptions {\n apiVersion: string\n projectId: string\n\n dataset?: string\n\n requireUser?: boolean\n}\n\n/**\n * Create a \"global\" (unscoped) Sanity API client.\n *\n * @param options - The options to use for the client.\n * @returns Promise that resolves to a configured Sanity API client.\n */\nexport async function getProjectCliClient({\n apiVersion,\n dataset,\n projectId,\n requireUser,\n}: ProjectCliClientOptions): Promise<SanityClient> {\n const requester = defaultRequester.clone()\n requester.use(authErrors())\n\n const sanityEnv = process.env.SANITY_INTERNAL_ENV || 'production'\n\n const token = await getCliToken()\n const apiHost = apiHosts[sanityEnv]\n\n if (requireUser && !token) {\n throw new Error('You must login first - run \"sanity login\"')\n }\n\n return createClient({\n ...(apiHost ? {apiHost} : {}),\n apiVersion,\n dataset,\n projectId,\n requester,\n requestTagPrefix: CLI_REQUEST_TAG_PREFIX,\n token,\n useCdn: false,\n useProjectHostname: true,\n })\n}\n\n/**\n * `get-it` middleware that checks for 401 authentication errors and extends the error with more\n * helpful guidance on what to do next.\n *\n * @returns get-it middleware with `onError` handler\n * @internal\n */\nfunction authErrors() {\n return {\n onError: (err: Error | null) => {\n if (!err || !isReqResError(err)) {\n return err\n }\n\n const statusCode = isHttpError(err) && err.response.body.statusCode\n if (statusCode === 401) {\n err.message = `${err.message}. You may need to login again with ${ux.colorize('cyan', 'sanity login')}.\\nFor more information, see ${generateHelpUrl('cli-errors')}.`\n }\n\n return err\n },\n }\n}\n\nfunction isReqResError(err: Error): err is ClientError | ServerError {\n return Object.prototype.hasOwnProperty.call(err, 'response')\n}\n"],"names":["ux","createClient","requester","defaultRequester","generateHelpUrl","isHttpError","getCliToken","apiHosts","staging","CLI_REQUEST_TAG_PREFIX","getGlobalCliClient","apiVersion","requireUser","clone","use","authErrors","sanityEnv","process","env","SANITY_INTERNAL_ENV","token","apiHost","Error","requestTagPrefix","useCdn","useProjectHostname","getProjectCliClient","dataset","projectId","onError","err","isReqResError","statusCode","response","body","message","colorize","Object","prototype","hasOwnProperty","call"],"mappings":"AAAA,SAAQA,EAAE,QAAO,cAAa;AAC9B,SAEEC,YAAY,EACZC,aAAaC,gBAAgB,QAGxB,iBAAgB;AAEvB,SAAQC,eAAe,QAAO,6BAA4B;AAC1D,SAAQC,WAAW,QAAO,yBAAwB;AAClD,SAAQC,WAAW,QAAO,mBAAkB;AAE5C,MAAMC,WAA+C;IACnDC,SAAS;AACX;AAEA,MAAMC,yBAAyB;AAmB/B;;;;;CAKC,GACD,OAAO,eAAeC,mBAAmB,EACvCC,UAAU,EACVC,WAAW,EACY;IACvB,MAAMV,YAAYC,iBAAiBU,KAAK;IACxCX,UAAUY,GAAG,CAACC;IAEd,MAAMC,YAAYC,QAAQC,GAAG,CAACC,mBAAmB,IAAI;IAErD,MAAMC,QAAQ,MAAMd;IACpB,MAAMe,UAAUd,QAAQ,CAACS,UAAU;IAEnC,IAAIJ,eAAe,CAACQ,OAAO;QACzB,MAAM,IAAIE,MAAM;IAClB;IAEA,OAAOrB,aAAa;QAClB,GAAIoB,UAAU;YAACA;QAAO,IAAI,CAAC,CAAC;QAC5BV;QACAT;QACAqB,kBAAkBd;QAClBW;QACAI,QAAQ;QACRC,oBAAoB;IACtB;AACF;AAcA;;;;;CAKC,GACD,OAAO,eAAeC,oBAAoB,EACxCf,UAAU,EACVgB,OAAO,EACPC,SAAS,EACThB,WAAW,EACa;IACxB,MAAMV,YAAYC,iBAAiBU,KAAK;IACxCX,UAAUY,GAAG,CAACC;IAEd,MAAMC,YAAYC,QAAQC,GAAG,CAACC,mBAAmB,IAAI;IAErD,MAAMC,QAAQ,MAAMd;IACpB,MAAMe,UAAUd,QAAQ,CAACS,UAAU;IAEnC,IAAIJ,eAAe,CAACQ,OAAO;QACzB,MAAM,IAAIE,MAAM;IAClB;IAEA,OAAOrB,aAAa;QAClB,GAAIoB,UAAU;YAACA;QAAO,IAAI,CAAC,CAAC;QAC5BV;QACAgB;QACAC;QACA1B;QACAqB,kBAAkBd;QAClBW;QACAI,QAAQ;QACRC,oBAAoB;IACtB;AACF;AAEA;;;;;;CAMC,GACD,SAASV;IACP,OAAO;QACLc,SAAS,CAACC;YACR,IAAI,CAACA,OAAO,CAACC,cAAcD,MAAM;gBAC/B,OAAOA;YACT;YAEA,MAAME,aAAa3B,YAAYyB,QAAQA,IAAIG,QAAQ,CAACC,IAAI,CAACF,UAAU;YACnE,IAAIA,eAAe,KAAK;gBACtBF,IAAIK,OAAO,GAAG,GAAGL,IAAIK,OAAO,CAAC,mCAAmC,EAAEnC,GAAGoC,QAAQ,CAAC,QAAQ,gBAAgB,6BAA6B,EAAEhC,gBAAgB,cAAc,CAAC,CAAC;YACvK;YAEA,OAAO0B;QACT;IACF;AACF;AAEA,SAASC,cAAcD,GAAU;IAC/B,OAAOO,OAAOC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACV,KAAK;AACnD"}
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+ declare const cliUserConfigSchema: {
3
+ authToken: z.ZodOptional<z.ZodString>;
4
+ telemetryConsent: z.ZodOptional<z.ZodObject<{
5
+ updatedAt: z.ZodOptional<z.ZodNumber>;
6
+ value: z.ZodObject<{
7
+ status: z.ZodEnum<["undetermined", "unset", "granted", "denied"]>;
8
+ type: z.ZodString;
9
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
10
+ status: z.ZodEnum<["undetermined", "unset", "granted", "denied"]>;
11
+ type: z.ZodString;
12
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
13
+ status: z.ZodEnum<["undetermined", "unset", "granted", "denied"]>;
14
+ type: z.ZodString;
15
+ }, z.ZodTypeAny, "passthrough">>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ value: {
18
+ type: string;
19
+ status: "undetermined" | "unset" | "granted" | "denied";
20
+ } & {
21
+ [k: string]: unknown;
22
+ };
23
+ updatedAt?: number | undefined;
24
+ }, {
25
+ value: {
26
+ type: string;
27
+ status: "undetermined" | "unset" | "granted" | "denied";
28
+ } & {
29
+ [k: string]: unknown;
30
+ };
31
+ updatedAt?: number | undefined;
32
+ }>>;
33
+ };
34
+ /**
35
+ * The CLI user configuration schema.
36
+ *
37
+ * @internal
38
+ */
39
+ type CliUserConfig = z.infer<z.ZodObject<typeof cliUserConfigSchema>>;
40
+ /**
41
+ * Set the config value for the given property.
42
+ * Validates that the passed value adheres to the defined CLI config schema.
43
+ *
44
+ * @param prop - The property to set the value for
45
+ * @param value - The value to set
46
+ * @internal
47
+ */
48
+ export declare function setConfig<P extends keyof CliUserConfig>(prop: P, value: CliUserConfig[P]): Promise<void>;
49
+ /**
50
+ * Get the config value for the given property
51
+ *
52
+ * @param prop - The property to get the value for
53
+ * @returns The value of the given property
54
+ * @internal
55
+ */
56
+ export declare function getConfig<P extends keyof CliUserConfig>(prop: P): Promise<CliUserConfig[P]>;
57
+ export {};