@sanity/cli-core 1.2.1 → 1.3.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.
Files changed (50) hide show
  1. package/dist/SanityCommand.js +3 -3
  2. package/dist/SanityCommand.js.map +1 -1
  3. package/dist/{index.d.ts → _exports/index.d.ts} +247 -124
  4. package/dist/_exports/index.js +40 -0
  5. package/dist/_exports/index.js.map +1 -0
  6. package/dist/config/cli/schemas.js +50 -50
  7. package/dist/config/cli/schemas.js.map +1 -1
  8. package/dist/config/findProjectRoot.js +3 -1
  9. package/dist/config/findProjectRoot.js.map +1 -1
  10. package/dist/config/findProjectRootSync.js +3 -1
  11. package/dist/config/findProjectRootSync.js.map +1 -1
  12. package/dist/config/studio/readStudioConfig.js +13 -11
  13. package/dist/config/studio/readStudioConfig.js.map +1 -1
  14. package/dist/config/studio/readStudioConfig.worker.js +1 -1
  15. package/dist/config/studio/readStudioConfig.worker.js.map +1 -1
  16. package/dist/exitCodes.js +17 -0
  17. package/dist/exitCodes.js.map +1 -0
  18. package/dist/services/apiClient.js +2 -2
  19. package/dist/services/apiClient.js.map +1 -1
  20. package/dist/services/cliTokenCache.js +25 -0
  21. package/dist/services/cliTokenCache.js.map +1 -0
  22. package/dist/services/cliUserConfig.js +89 -48
  23. package/dist/services/cliUserConfig.js.map +1 -1
  24. package/dist/services/getCliToken.js +12 -7
  25. package/dist/services/getCliToken.js.map +1 -1
  26. package/dist/{util → telemetry}/getCliTelemetry.js +1 -1
  27. package/dist/telemetry/getCliTelemetry.js.map +1 -0
  28. package/dist/telemetry/noopTelemetry.js +23 -0
  29. package/dist/telemetry/noopTelemetry.js.map +1 -0
  30. package/dist/telemetry/readNDJSON.js.map +1 -0
  31. package/dist/util/environment/getStudioEnvironmentVariables.js +3 -1
  32. package/dist/util/environment/getStudioEnvironmentVariables.js.map +1 -1
  33. package/dist/util/readJsonFileSync.js +26 -0
  34. package/dist/util/readJsonFileSync.js.map +1 -0
  35. package/dist/util/readPackageJson.js +17 -17
  36. package/dist/util/readPackageJson.js.map +1 -1
  37. package/dist/util/resolveLocalPackage.js +6 -2
  38. package/dist/util/resolveLocalPackage.js.map +1 -1
  39. package/dist/util/writeJsonFileSync.js +19 -0
  40. package/dist/util/writeJsonFileSync.js.map +1 -0
  41. package/package.json +22 -25
  42. package/dist/index.js +0 -39
  43. package/dist/index.js.map +0 -1
  44. package/dist/util/getCliTelemetry.js.map +0 -1
  45. package/dist/util/getUserConfig.js +0 -15
  46. package/dist/util/getUserConfig.js.map +0 -1
  47. package/dist/util/readNDJSON.js.map +0 -1
  48. package/dist/util/writeJsonFile.js +0 -19
  49. package/dist/util/writeJsonFile.js.map +0 -1
  50. /package/dist/{util → telemetry}/readNDJSON.js +0 -0
@@ -1,24 +1,13 @@
1
- import { mkdir } from 'node:fs/promises';
1
+ import { mkdirSync } from 'node:fs';
2
2
  import { homedir } from 'node:os';
3
3
  import { dirname, join as joinPath } from 'node:path';
4
- import { z } from 'zod';
4
+ import { z } from 'zod/mini';
5
5
  import { debug } from '../debug.js';
6
- import { readJsonFile } from '../util/readJsonFile.js';
7
- import { writeJsonFile } from '../util/writeJsonFile.js';
6
+ import { readJsonFileSync } from '../util/readJsonFileSync.js';
7
+ import { writeJsonFileSync } from '../util/writeJsonFileSync.js';
8
+ import { clearCliTokenCache } from './cliTokenCache.js';
8
9
  const cliUserConfigSchema = {
9
- authToken: z.string().optional(),
10
- telemetryConsent: z.object({
11
- updatedAt: z.number().optional(),
12
- value: z.object({
13
- status: z.enum([
14
- 'undetermined',
15
- 'unset',
16
- 'granted',
17
- 'denied'
18
- ]),
19
- type: z.string()
20
- }).passthrough()
21
- }).optional()
10
+ authToken: z.optional(z.string())
22
11
  };
23
12
  /**
24
13
  * Set the config value for the given property.
@@ -27,27 +16,35 @@ const cliUserConfigSchema = {
27
16
  * @param prop - The property to set the value for
28
17
  * @param value - The value to set
29
18
  * @internal
30
- */ export async function setCliUserConfig(prop, value) {
31
- const config = await readConfig();
32
- const valueSchema = cliUserConfigSchema[prop];
33
- if (!valueSchema) {
34
- throw new Error(`No schema defined for config property "${prop}"`);
35
- }
36
- const { error, success } = valueSchema.safeParse(value);
37
- if (!success) {
38
- const message = error.issues.map(({ message, path })=>`[${path.join('.')}] ${message}`).join('\n');
19
+ */ export function setCliUserConfig(prop, value) {
20
+ const config = readConfig();
21
+ const result = cliUserConfigSchema[prop].safeParse(value);
22
+ if (!result.success) {
23
+ const message = result.error.issues.map(({ message, path })=>`[${path.join('.')}] ${message}`).join('\n');
39
24
  throw new Error(`Invalid value for config property "${prop}": ${message}`);
40
25
  }
41
26
  const configPath = getCliUserConfigPath();
42
- await mkdir(dirname(configPath), {
27
+ mkdirSync(dirname(configPath), {
43
28
  recursive: true
44
29
  });
45
- await writeJsonFile(configPath, {
46
- ...config,
47
- [prop]: value
48
- }, {
49
- pretty: true
50
- });
30
+ // When value is undefined, explicitly delete the key rather than relying
31
+ // on JSON.stringify silently dropping undefined values.
32
+ if (value === undefined) {
33
+ const { [prop]: _, ...rest } = config;
34
+ writeJsonFileSync(configPath, rest, {
35
+ pretty: true
36
+ });
37
+ } else {
38
+ writeJsonFileSync(configPath, {
39
+ ...config,
40
+ [prop]: value
41
+ }, {
42
+ pretty: true
43
+ });
44
+ }
45
+ // Invalidate the in-process token cache so subsequent getCliToken() calls
46
+ // pick up the new value from disk.
47
+ clearCliTokenCache();
51
48
  }
52
49
  /**
53
50
  * Get the config value for the given property
@@ -55,36 +52,80 @@ const cliUserConfigSchema = {
55
52
  * @param prop - The property to get the value for
56
53
  * @returns The value of the given property
57
54
  * @internal
58
- */ export async function getCliUserConfig(prop) {
59
- const config = await readConfig();
60
- const valueSchema = cliUserConfigSchema[prop];
61
- if (!valueSchema) {
62
- throw new Error(`No schema defined for config property "${prop}"`);
63
- }
64
- const { success } = valueSchema.safeParse(config[prop]);
65
- if (!success) {
55
+ */ export function getCliUserConfig(prop) {
56
+ const config = readConfig();
57
+ const result = cliUserConfigSchema[prop].safeParse(config[prop]);
58
+ if (!result.success) {
66
59
  debug('Ignoring invalid stored value for "%s", returning undefined', prop);
67
60
  return undefined;
68
61
  }
69
- return config[prop];
62
+ return result.data;
63
+ }
64
+ /**
65
+ * Get a key-value store backed by the CLI user configuration file
66
+ * (`~/.config/sanity/config.json`).
67
+ *
68
+ * Each call to `get`, `set`, or `delete` performs a full synchronous
69
+ * read-modify-write cycle. This is intentional: sync I/O prevents
70
+ * intra-process race conditions that occurred with the previous async
71
+ * (configstore-backed) implementation.
72
+ *
73
+ * Note: there is no file-level locking, so concurrent writes from
74
+ * separate CLI processes could still conflict. In practice this is
75
+ * unlikely since CLI config writes are rare and user-initiated.
76
+ *
77
+ * @returns A {@link ConfigStore} for the CLI config file
78
+ * @public
79
+ */ export function getUserConfig() {
80
+ return {
81
+ get (key) {
82
+ const config = readConfig();
83
+ return config[key];
84
+ },
85
+ set (key, value) {
86
+ const config = readConfig();
87
+ const configPath = getCliUserConfigPath();
88
+ mkdirSync(dirname(configPath), {
89
+ recursive: true
90
+ });
91
+ writeJsonFileSync(configPath, {
92
+ ...config,
93
+ [key]: value
94
+ }, {
95
+ pretty: true
96
+ });
97
+ if (key === 'authToken') clearCliTokenCache();
98
+ },
99
+ // No mkdirSync needed: if readConfig() succeeded the directory already exists.
100
+ delete (key) {
101
+ const config = readConfig();
102
+ if (!(key in config)) return;
103
+ const { [key]: _, ...rest } = config;
104
+ writeJsonFileSync(getCliUserConfigPath(), rest, {
105
+ pretty: true
106
+ });
107
+ if (key === 'authToken') clearCliTokenCache();
108
+ }
109
+ };
70
110
  }
71
111
  /**
72
- * Read the whole configuration from file system. If the file does not exist or could
73
- * not be loaded, an empty configuration object is returned.
112
+ * Read the whole configuration from file system. If the file does not exist,
113
+ * is corrupt, or otherwise unreadable, an empty object is returned. This is
114
+ * intentional: the config only holds recoverable data (auth tokens, telemetry
115
+ * consent) so silently resetting is preferable to blocking the user.
74
116
  *
75
117
  * @returns The whole CLI configuration.
76
118
  * @internal
77
- */ async function readConfig() {
78
- const defaultConfig = {};
119
+ */ function readConfig() {
79
120
  try {
80
- const config = await readJsonFile(getCliUserConfigPath());
121
+ const config = readJsonFileSync(getCliUserConfigPath());
81
122
  if (!config || typeof config !== 'object' || Array.isArray(config)) {
82
123
  throw new Error('Invalid config file - expected an object');
83
124
  }
84
125
  return config;
85
126
  } catch (err) {
86
127
  debug('Failed to read CLI config file: %s', err instanceof Error ? err.message : `${err}`);
87
- return defaultConfig;
128
+ return {};
88
129
  }
89
130
  }
90
131
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/cliUserConfig.ts"],"sourcesContent":["import {mkdir} from 'node:fs/promises'\nimport {homedir} from 'node:os'\nimport {dirname, join as joinPath} from 'node:path'\n\nimport {z} from 'zod'\n\nimport {debug} from '../debug.js'\nimport {readJsonFile} from '../util/readJsonFile.js'\nimport {writeJsonFile} from '../util/writeJsonFile.js'\n\nconst cliUserConfigSchema = {\n authToken: z.string().optional(),\n telemetryConsent: z\n .object({\n updatedAt: z.number().optional(),\n value: z\n .object({\n status: z.enum(['undetermined', 'unset', 'granted', 'denied']),\n type: z.string(),\n })\n .passthrough(),\n })\n .optional(),\n}\n\n/**\n * The CLI user configuration schema.\n *\n * @internal\n */\ntype CliUserConfig = z.infer<z.ZodObject<typeof cliUserConfigSchema>>\n\n/**\n * Set the config value for the given property.\n * Validates that the passed value adheres to the defined CLI config schema.\n *\n * @param prop - The property to set the value for\n * @param value - The value to set\n * @internal\n */\nexport async function setCliUserConfig<P extends keyof CliUserConfig>(\n prop: P,\n value: CliUserConfig[P],\n) {\n const config = await readConfig()\n const valueSchema = cliUserConfigSchema[prop]\n if (!valueSchema) {\n throw new Error(`No schema defined for config property \"${prop}\"`)\n }\n\n const {error, success} = valueSchema.safeParse(value)\n if (!success) {\n const message = error.issues\n .map(({message, path}) => `[${path.join('.')}] ${message}`)\n .join('\\n')\n\n throw new Error(`Invalid value for config property \"${prop}\": ${message}`)\n }\n\n const configPath = getCliUserConfigPath()\n await mkdir(dirname(configPath), {recursive: true})\n await writeJsonFile(configPath, {...config, [prop]: value}, {pretty: true})\n}\n\n/**\n * Get the config value for the given property\n *\n * @param prop - The property to get the value for\n * @returns The value of the given property\n * @internal\n */\nexport async function getCliUserConfig<P extends keyof CliUserConfig>(\n prop: P,\n): Promise<CliUserConfig[P]> {\n const config = await readConfig()\n const valueSchema = cliUserConfigSchema[prop]\n if (!valueSchema) {\n throw new Error(`No schema defined for config property \"${prop}\"`)\n }\n\n const {success} = valueSchema.safeParse(config[prop])\n if (!success) {\n debug('Ignoring invalid stored value for \"%s\", returning undefined', prop)\n return undefined as CliUserConfig[P]\n }\n\n return config[prop]\n}\n\n/**\n * Read the whole configuration from file system. If the file does not exist or could\n * not be loaded, an empty configuration object is returned.\n *\n * @returns The whole CLI configuration.\n * @internal\n */\nasync function readConfig(): Promise<CliUserConfig> {\n const defaultConfig: CliUserConfig = {}\n try {\n const config = await readJsonFile(getCliUserConfigPath())\n if (!config || typeof config !== 'object' || Array.isArray(config)) {\n throw new Error('Invalid config file - expected an object')\n }\n return config\n } catch (err: unknown) {\n debug('Failed to read CLI config file: %s', err instanceof Error ? err.message : `${err}`)\n return defaultConfig\n }\n}\n\n/**\n * Get the file system location for the CLI user configuration file.\n * Takes into account the active environment (staging vs production).\n * The file is located in the user's home directory under the `.config` directory.\n *\n * @returns The path to the CLI configuration file.\n * @internal\n */\nfunction getCliUserConfigPath() {\n const sanityEnvSuffix = process.env.SANITY_INTERNAL_ENV === 'staging' ? '-staging' : ''\n const cliConfigPath =\n process.env.SANITY_CLI_CONFIG_PATH ||\n joinPath(homedir(), '.config', `sanity${sanityEnvSuffix}`, 'config.json')\n\n return cliConfigPath\n}\n"],"names":["mkdir","homedir","dirname","join","joinPath","z","debug","readJsonFile","writeJsonFile","cliUserConfigSchema","authToken","string","optional","telemetryConsent","object","updatedAt","number","value","status","enum","type","passthrough","setCliUserConfig","prop","config","readConfig","valueSchema","Error","error","success","safeParse","message","issues","map","path","configPath","getCliUserConfigPath","recursive","pretty","getCliUserConfig","undefined","defaultConfig","Array","isArray","err","sanityEnvSuffix","process","env","SANITY_INTERNAL_ENV","cliConfigPath","SANITY_CLI_CONFIG_PATH"],"mappings":"AAAA,SAAQA,KAAK,QAAO,mBAAkB;AACtC,SAAQC,OAAO,QAAO,UAAS;AAC/B,SAAQC,OAAO,EAAEC,QAAQC,QAAQ,QAAO,YAAW;AAEnD,SAAQC,CAAC,QAAO,MAAK;AAErB,SAAQC,KAAK,QAAO,cAAa;AACjC,SAAQC,YAAY,QAAO,0BAAyB;AACpD,SAAQC,aAAa,QAAO,2BAA0B;AAEtD,MAAMC,sBAAsB;IAC1BC,WAAWL,EAAEM,MAAM,GAAGC,QAAQ;IAC9BC,kBAAkBR,EACfS,MAAM,CAAC;QACNC,WAAWV,EAAEW,MAAM,GAAGJ,QAAQ;QAC9BK,OAAOZ,EACJS,MAAM,CAAC;YACNI,QAAQb,EAAEc,IAAI,CAAC;gBAAC;gBAAgB;gBAAS;gBAAW;aAAS;YAC7DC,MAAMf,EAAEM,MAAM;QAChB,GACCU,WAAW;IAChB,GACCT,QAAQ;AACb;AASA;;;;;;;CAOC,GACD,OAAO,eAAeU,iBACpBC,IAAO,EACPN,KAAuB;IAEvB,MAAMO,SAAS,MAAMC;IACrB,MAAMC,cAAcjB,mBAAmB,CAACc,KAAK;IAC7C,IAAI,CAACG,aAAa;QAChB,MAAM,IAAIC,MAAM,CAAC,uCAAuC,EAAEJ,KAAK,CAAC,CAAC;IACnE;IAEA,MAAM,EAACK,KAAK,EAAEC,OAAO,EAAC,GAAGH,YAAYI,SAAS,CAACb;IAC/C,IAAI,CAACY,SAAS;QACZ,MAAME,UAAUH,MAAMI,MAAM,CACzBC,GAAG,CAAC,CAAC,EAACF,OAAO,EAAEG,IAAI,EAAC,GAAK,CAAC,CAAC,EAAEA,KAAK/B,IAAI,CAAC,KAAK,EAAE,EAAE4B,SAAS,EACzD5B,IAAI,CAAC;QAER,MAAM,IAAIwB,MAAM,CAAC,mCAAmC,EAAEJ,KAAK,GAAG,EAAEQ,SAAS;IAC3E;IAEA,MAAMI,aAAaC;IACnB,MAAMpC,MAAME,QAAQiC,aAAa;QAACE,WAAW;IAAI;IACjD,MAAM7B,cAAc2B,YAAY;QAAC,GAAGX,MAAM;QAAE,CAACD,KAAK,EAAEN;IAAK,GAAG;QAACqB,QAAQ;IAAI;AAC3E;AAEA;;;;;;CAMC,GACD,OAAO,eAAeC,iBACpBhB,IAAO;IAEP,MAAMC,SAAS,MAAMC;IACrB,MAAMC,cAAcjB,mBAAmB,CAACc,KAAK;IAC7C,IAAI,CAACG,aAAa;QAChB,MAAM,IAAIC,MAAM,CAAC,uCAAuC,EAAEJ,KAAK,CAAC,CAAC;IACnE;IAEA,MAAM,EAACM,OAAO,EAAC,GAAGH,YAAYI,SAAS,CAACN,MAAM,CAACD,KAAK;IACpD,IAAI,CAACM,SAAS;QACZvB,MAAM,+DAA+DiB;QACrE,OAAOiB;IACT;IAEA,OAAOhB,MAAM,CAACD,KAAK;AACrB;AAEA;;;;;;CAMC,GACD,eAAeE;IACb,MAAMgB,gBAA+B,CAAC;IACtC,IAAI;QACF,MAAMjB,SAAS,MAAMjB,aAAa6B;QAClC,IAAI,CAACZ,UAAU,OAAOA,WAAW,YAAYkB,MAAMC,OAAO,CAACnB,SAAS;YAClE,MAAM,IAAIG,MAAM;QAClB;QACA,OAAOH;IACT,EAAE,OAAOoB,KAAc;QACrBtC,MAAM,sCAAsCsC,eAAejB,QAAQiB,IAAIb,OAAO,GAAG,GAAGa,KAAK;QACzF,OAAOH;IACT;AACF;AAEA;;;;;;;CAOC,GACD,SAASL;IACP,MAAMS,kBAAkBC,QAAQC,GAAG,CAACC,mBAAmB,KAAK,YAAY,aAAa;IACrF,MAAMC,gBACJH,QAAQC,GAAG,CAACG,sBAAsB,IAClC9C,SAASH,WAAW,WAAW,CAAC,MAAM,EAAE4C,iBAAiB,EAAE;IAE7D,OAAOI;AACT"}
1
+ {"version":3,"sources":["../../src/services/cliUserConfig.ts"],"sourcesContent":["import {mkdirSync} from 'node:fs'\nimport {homedir} from 'node:os'\nimport {dirname, join as joinPath} from 'node:path'\n\nimport {z} from 'zod/mini'\n\nimport {debug} from '../debug.js'\nimport {readJsonFileSync} from '../util/readJsonFileSync.js'\nimport {writeJsonFileSync} from '../util/writeJsonFileSync.js'\nimport {clearCliTokenCache} from './cliTokenCache.js'\n\nconst cliUserConfigSchema = {\n authToken: z.optional(z.string()),\n}\n\n/**\n * Set the config value for the given property.\n * Validates that the passed value adheres to the defined CLI config schema.\n *\n * @param prop - The property to set the value for\n * @param value - The value to set\n * @internal\n */\nexport function setCliUserConfig(prop: 'authToken', value: string | undefined): void {\n const config = readConfig()\n const result = cliUserConfigSchema[prop].safeParse(value)\n if (!result.success) {\n const message = result.error.issues\n .map(({message, path}) => `[${path.join('.')}] ${message}`)\n .join('\\n')\n\n throw new Error(`Invalid value for config property \"${prop}\": ${message}`)\n }\n\n const configPath = getCliUserConfigPath()\n mkdirSync(dirname(configPath), {recursive: true})\n\n // When value is undefined, explicitly delete the key rather than relying\n // on JSON.stringify silently dropping undefined values.\n if (value === undefined) {\n const {[prop]: _, ...rest} = config\n writeJsonFileSync(configPath, rest, {pretty: true})\n } else {\n writeJsonFileSync(configPath, {...config, [prop]: value}, {pretty: true})\n }\n\n // Invalidate the in-process token cache so subsequent getCliToken() calls\n // pick up the new value from disk.\n clearCliTokenCache()\n}\n\n/**\n * Get the config value for the given property\n *\n * @param prop - The property to get the value for\n * @returns The value of the given property\n * @internal\n */\nexport function getCliUserConfig(prop: 'authToken'): string | undefined {\n const config = readConfig()\n const result = cliUserConfigSchema[prop].safeParse(config[prop])\n if (!result.success) {\n debug('Ignoring invalid stored value for \"%s\", returning undefined', prop)\n return undefined\n }\n\n return result.data\n}\n\n/**\n * A raw key-value store for CLI user configuration.\n * Unlike the typed `getCliUserConfig`/`setCliUserConfig`, this operates on\n * arbitrary keys without schema validation.\n *\n * @public\n */\nexport interface ConfigStore {\n /** Remove a key from the config file. */\n delete: (key: string) => void\n /** Read a value by key. Returns `undefined` if the key does not exist. */\n get: (key: string) => unknown\n /** Write a value by key, merging it into the existing config. */\n set: (key: string, value: unknown) => void\n}\n\n/**\n * Get a key-value store backed by the CLI user configuration file\n * (`~/.config/sanity/config.json`).\n *\n * Each call to `get`, `set`, or `delete` performs a full synchronous\n * read-modify-write cycle. This is intentional: sync I/O prevents\n * intra-process race conditions that occurred with the previous async\n * (configstore-backed) implementation.\n *\n * Note: there is no file-level locking, so concurrent writes from\n * separate CLI processes could still conflict. In practice this is\n * unlikely since CLI config writes are rare and user-initiated.\n *\n * @returns A {@link ConfigStore} for the CLI config file\n * @public\n */\nexport function getUserConfig(): ConfigStore {\n return {\n get(key: string): unknown {\n const config = readConfig()\n return config[key]\n },\n\n set(key: string, value: unknown): void {\n const config = readConfig()\n const configPath = getCliUserConfigPath()\n mkdirSync(dirname(configPath), {recursive: true})\n writeJsonFileSync(configPath, {...config, [key]: value}, {pretty: true})\n if (key === 'authToken') clearCliTokenCache()\n },\n\n // No mkdirSync needed: if readConfig() succeeded the directory already exists.\n delete(key: string): void {\n const config = readConfig()\n if (!(key in config)) return\n const {[key]: _, ...rest} = config\n writeJsonFileSync(getCliUserConfigPath(), rest, {pretty: true})\n if (key === 'authToken') clearCliTokenCache()\n },\n }\n}\n\n/**\n * Read the whole configuration from file system. If the file does not exist,\n * is corrupt, or otherwise unreadable, an empty object is returned. This is\n * intentional: the config only holds recoverable data (auth tokens, telemetry\n * consent) so silently resetting is preferable to blocking the user.\n *\n * @returns The whole CLI configuration.\n * @internal\n */\nfunction readConfig(): Record<string, unknown> {\n try {\n const config = readJsonFileSync(getCliUserConfigPath())\n if (!config || typeof config !== 'object' || Array.isArray(config)) {\n throw new Error('Invalid config file - expected an object')\n }\n return config\n } catch (err: unknown) {\n debug('Failed to read CLI config file: %s', err instanceof Error ? err.message : `${err}`)\n return {}\n }\n}\n\n/**\n * Get the file system location for the CLI user configuration file.\n * Takes into account the active environment (staging vs production).\n * The file is located in the user's home directory under the `.config` directory.\n *\n * @returns The path to the CLI configuration file.\n * @internal\n */\nfunction getCliUserConfigPath() {\n const sanityEnvSuffix = process.env.SANITY_INTERNAL_ENV === 'staging' ? '-staging' : ''\n const cliConfigPath =\n process.env.SANITY_CLI_CONFIG_PATH ||\n joinPath(homedir(), '.config', `sanity${sanityEnvSuffix}`, 'config.json')\n\n return cliConfigPath\n}\n"],"names":["mkdirSync","homedir","dirname","join","joinPath","z","debug","readJsonFileSync","writeJsonFileSync","clearCliTokenCache","cliUserConfigSchema","authToken","optional","string","setCliUserConfig","prop","value","config","readConfig","result","safeParse","success","message","error","issues","map","path","Error","configPath","getCliUserConfigPath","recursive","undefined","_","rest","pretty","getCliUserConfig","data","getUserConfig","get","key","set","delete","Array","isArray","err","sanityEnvSuffix","process","env","SANITY_INTERNAL_ENV","cliConfigPath","SANITY_CLI_CONFIG_PATH"],"mappings":"AAAA,SAAQA,SAAS,QAAO,UAAS;AACjC,SAAQC,OAAO,QAAO,UAAS;AAC/B,SAAQC,OAAO,EAAEC,QAAQC,QAAQ,QAAO,YAAW;AAEnD,SAAQC,CAAC,QAAO,WAAU;AAE1B,SAAQC,KAAK,QAAO,cAAa;AACjC,SAAQC,gBAAgB,QAAO,8BAA6B;AAC5D,SAAQC,iBAAiB,QAAO,+BAA8B;AAC9D,SAAQC,kBAAkB,QAAO,qBAAoB;AAErD,MAAMC,sBAAsB;IAC1BC,WAAWN,EAAEO,QAAQ,CAACP,EAAEQ,MAAM;AAChC;AAEA;;;;;;;CAOC,GACD,OAAO,SAASC,iBAAiBC,IAAiB,EAAEC,KAAyB;IAC3E,MAAMC,SAASC;IACf,MAAMC,SAAST,mBAAmB,CAACK,KAAK,CAACK,SAAS,CAACJ;IACnD,IAAI,CAACG,OAAOE,OAAO,EAAE;QACnB,MAAMC,UAAUH,OAAOI,KAAK,CAACC,MAAM,CAChCC,GAAG,CAAC,CAAC,EAACH,OAAO,EAAEI,IAAI,EAAC,GAAK,CAAC,CAAC,EAAEA,KAAKvB,IAAI,CAAC,KAAK,EAAE,EAAEmB,SAAS,EACzDnB,IAAI,CAAC;QAER,MAAM,IAAIwB,MAAM,CAAC,mCAAmC,EAAEZ,KAAK,GAAG,EAAEO,SAAS;IAC3E;IAEA,MAAMM,aAAaC;IACnB7B,UAAUE,QAAQ0B,aAAa;QAACE,WAAW;IAAI;IAE/C,yEAAyE;IACzE,wDAAwD;IACxD,IAAId,UAAUe,WAAW;QACvB,MAAM,EAAC,CAAChB,KAAK,EAAEiB,CAAC,EAAE,GAAGC,MAAK,GAAGhB;QAC7BT,kBAAkBoB,YAAYK,MAAM;YAACC,QAAQ;QAAI;IACnD,OAAO;QACL1B,kBAAkBoB,YAAY;YAAC,GAAGX,MAAM;YAAE,CAACF,KAAK,EAAEC;QAAK,GAAG;YAACkB,QAAQ;QAAI;IACzE;IAEA,0EAA0E;IAC1E,mCAAmC;IACnCzB;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAAS0B,iBAAiBpB,IAAiB;IAChD,MAAME,SAASC;IACf,MAAMC,SAAST,mBAAmB,CAACK,KAAK,CAACK,SAAS,CAACH,MAAM,CAACF,KAAK;IAC/D,IAAI,CAACI,OAAOE,OAAO,EAAE;QACnBf,MAAM,+DAA+DS;QACrE,OAAOgB;IACT;IAEA,OAAOZ,OAAOiB,IAAI;AACpB;AAkBA;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASC;IACd,OAAO;QACLC,KAAIC,GAAW;YACb,MAAMtB,SAASC;YACf,OAAOD,MAAM,CAACsB,IAAI;QACpB;QAEAC,KAAID,GAAW,EAAEvB,KAAc;YAC7B,MAAMC,SAASC;YACf,MAAMU,aAAaC;YACnB7B,UAAUE,QAAQ0B,aAAa;gBAACE,WAAW;YAAI;YAC/CtB,kBAAkBoB,YAAY;gBAAC,GAAGX,MAAM;gBAAE,CAACsB,IAAI,EAAEvB;YAAK,GAAG;gBAACkB,QAAQ;YAAI;YACtE,IAAIK,QAAQ,aAAa9B;QAC3B;QAEA,+EAA+E;QAC/EgC,QAAOF,GAAW;YAChB,MAAMtB,SAASC;YACf,IAAI,CAAEqB,CAAAA,OAAOtB,MAAK,GAAI;YACtB,MAAM,EAAC,CAACsB,IAAI,EAAEP,CAAC,EAAE,GAAGC,MAAK,GAAGhB;YAC5BT,kBAAkBqB,wBAAwBI,MAAM;gBAACC,QAAQ;YAAI;YAC7D,IAAIK,QAAQ,aAAa9B;QAC3B;IACF;AACF;AAEA;;;;;;;;CAQC,GACD,SAASS;IACP,IAAI;QACF,MAAMD,SAASV,iBAAiBsB;QAChC,IAAI,CAACZ,UAAU,OAAOA,WAAW,YAAYyB,MAAMC,OAAO,CAAC1B,SAAS;YAClE,MAAM,IAAIU,MAAM;QAClB;QACA,OAAOV;IACT,EAAE,OAAO2B,KAAc;QACrBtC,MAAM,sCAAsCsC,eAAejB,QAAQiB,IAAItB,OAAO,GAAG,GAAGsB,KAAK;QACzF,OAAO,CAAC;IACV;AACF;AAEA;;;;;;;CAOC,GACD,SAASf;IACP,MAAMgB,kBAAkBC,QAAQC,GAAG,CAACC,mBAAmB,KAAK,YAAY,aAAa;IACrF,MAAMC,gBACJH,QAAQC,GAAG,CAACG,sBAAsB,IAClC9C,SAASH,WAAW,WAAW,CAAC,MAAM,EAAE4C,iBAAiB,EAAE;IAE7D,OAAOI;AACT"}
@@ -1,21 +1,26 @@
1
+ import { getCachedToken, setCachedToken } from './cliTokenCache.js';
1
2
  import { getCliUserConfig } from './cliUserConfig.js';
2
- let cachedToken;
3
+ // Re-export so existing consumers don't break
4
+ export { clearCliTokenCache } from './cliTokenCache.js';
3
5
  /**
4
6
  * Get the CLI authentication token from the environment or the config file
5
7
  *
6
8
  * @returns A promise that resolves to a CLI token, or undefined if no token is found
7
9
  * @internal
8
10
  */ export async function getCliToken() {
9
- if (cachedToken !== undefined) {
10
- return cachedToken;
11
+ const cached = getCachedToken();
12
+ if (cached !== undefined) {
13
+ return cached;
11
14
  }
12
15
  const token = process.env.SANITY_AUTH_TOKEN;
13
16
  if (token) {
14
- cachedToken = token.trim();
15
- return cachedToken;
17
+ const trimmed = token.trim();
18
+ setCachedToken(trimmed);
19
+ return trimmed;
16
20
  }
17
- cachedToken = await getCliUserConfig('authToken');
18
- return cachedToken;
21
+ const configToken = getCliUserConfig('authToken');
22
+ setCachedToken(configToken);
23
+ return configToken;
19
24
  }
20
25
 
21
26
  //# sourceMappingURL=getCliToken.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/getCliToken.ts"],"sourcesContent":["import {getCliUserConfig} from './cliUserConfig.js'\n\nlet cachedToken: string | undefined\n\n/**\n * Get the CLI authentication token from the environment or the config file\n *\n * @returns A promise that resolves to a CLI token, or undefined if no token is found\n * @internal\n */\nexport async function getCliToken(): Promise<string | undefined> {\n if (cachedToken !== undefined) {\n return cachedToken\n }\n\n const token = process.env.SANITY_AUTH_TOKEN\n if (token) {\n cachedToken = token.trim()\n return cachedToken\n }\n\n cachedToken = await getCliUserConfig('authToken')\n return cachedToken\n}\n"],"names":["getCliUserConfig","cachedToken","getCliToken","undefined","token","process","env","SANITY_AUTH_TOKEN","trim"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,qBAAoB;AAEnD,IAAIC;AAEJ;;;;;CAKC,GACD,OAAO,eAAeC;IACpB,IAAID,gBAAgBE,WAAW;QAC7B,OAAOF;IACT;IAEA,MAAMG,QAAQC,QAAQC,GAAG,CAACC,iBAAiB;IAC3C,IAAIH,OAAO;QACTH,cAAcG,MAAMI,IAAI;QACxB,OAAOP;IACT;IAEAA,cAAc,MAAMD,iBAAiB;IACrC,OAAOC;AACT"}
1
+ {"version":3,"sources":["../../src/services/getCliToken.ts"],"sourcesContent":["import {getCachedToken, setCachedToken} from './cliTokenCache.js'\nimport {getCliUserConfig} from './cliUserConfig.js'\n\n// Re-export so existing consumers don't break\nexport {clearCliTokenCache} from './cliTokenCache.js'\n\n/**\n * Get the CLI authentication token from the environment or the config file\n *\n * @returns A promise that resolves to a CLI token, or undefined if no token is found\n * @internal\n */\nexport async function getCliToken(): Promise<string | undefined> {\n const cached = getCachedToken()\n if (cached !== undefined) {\n return cached\n }\n\n const token = process.env.SANITY_AUTH_TOKEN\n if (token) {\n const trimmed = token.trim()\n setCachedToken(trimmed)\n return trimmed\n }\n\n const configToken = getCliUserConfig('authToken')\n setCachedToken(configToken)\n return configToken\n}\n"],"names":["getCachedToken","setCachedToken","getCliUserConfig","clearCliTokenCache","getCliToken","cached","undefined","token","process","env","SANITY_AUTH_TOKEN","trimmed","trim","configToken"],"mappings":"AAAA,SAAQA,cAAc,EAAEC,cAAc,QAAO,qBAAoB;AACjE,SAAQC,gBAAgB,QAAO,qBAAoB;AAEnD,8CAA8C;AAC9C,SAAQC,kBAAkB,QAAO,qBAAoB;AAErD;;;;;CAKC,GACD,OAAO,eAAeC;IACpB,MAAMC,SAASL;IACf,IAAIK,WAAWC,WAAW;QACxB,OAAOD;IACT;IAEA,MAAME,QAAQC,QAAQC,GAAG,CAACC,iBAAiB;IAC3C,IAAIH,OAAO;QACT,MAAMI,UAAUJ,MAAMK,IAAI;QAC1BX,eAAeU;QACf,OAAOA;IACT;IAEA,MAAME,cAAcX,iBAAiB;IACrCD,eAAeY;IACf,OAAOA;AACT"}
@@ -1,5 +1,5 @@
1
1
  import { ux } from '@oclif/core';
2
- import { noopLogger } from '@sanity/telemetry';
2
+ import { noopLogger } from './noopTelemetry.js';
3
3
  /**
4
4
  * @public
5
5
  * Symbol used to store CLI telemetry state on globalThis.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/getCliTelemetry.ts"],"sourcesContent":["import {ux} from '@oclif/core'\n\nimport {noopLogger} from './noopTelemetry.js'\nimport {type CLITelemetryStore} from './types.js'\n\n/**\n * @public\n * Symbol used to store CLI telemetry state on globalThis.\n * Use the accessor functions instead of accessing this directly.\n */\nexport const CLI_TELEMETRY_SYMBOL = Symbol.for('sanity.cli.telemetry')\n\ntype TraceErrorReporter = (error: Error) => void\n\ninterface CliTelemetryState {\n logger: CLITelemetryStore\n\n reportTraceError?: TraceErrorReporter\n}\n\ntype GlobalWithTelemetry = typeof globalThis & {\n [CLI_TELEMETRY_SYMBOL]?: CliTelemetryState\n}\n\nfunction getState(): CliTelemetryState | undefined {\n return (globalThis as GlobalWithTelemetry)[CLI_TELEMETRY_SYMBOL]\n}\n\n/**\n * @public\n */\nexport function getCliTelemetry(): CLITelemetryStore {\n const state = getState()\n // This should never happen, but if it does, we return a noop logger to avoid errors.\n if (!state) {\n ux.warn('CLI telemetry not initialized, returning noop logger')\n return noopLogger\n }\n\n return state.logger\n}\n\n/**\n * Sets the global CLI telemetry state.\n * @internal\n */\nexport function setCliTelemetry(\n telemetry: CLITelemetryStore,\n options?: {reportTraceError?: TraceErrorReporter},\n): void {\n ;(globalThis as GlobalWithTelemetry)[CLI_TELEMETRY_SYMBOL] = {\n logger: telemetry,\n reportTraceError: options?.reportTraceError,\n }\n}\n\n/**\n * Reports an error to the CLI command trace. Called from SanityCommand.catch()\n * for real command errors (not user aborts).\n * @internal\n */\nexport function reportCliTraceError(error: Error): void {\n getState()?.reportTraceError?.(error)\n}\n\n/**\n * Clears the global CLI telemetry store.\n * @internal\n */\nexport function clearCliTelemetry(): void {\n const global = globalThis as GlobalWithTelemetry\n delete global[CLI_TELEMETRY_SYMBOL]\n}\n"],"names":["ux","noopLogger","CLI_TELEMETRY_SYMBOL","Symbol","for","getState","globalThis","getCliTelemetry","state","warn","logger","setCliTelemetry","telemetry","options","reportTraceError","reportCliTraceError","error","clearCliTelemetry","global"],"mappings":"AAAA,SAAQA,EAAE,QAAO,cAAa;AAE9B,SAAQC,UAAU,QAAO,qBAAoB;AAG7C;;;;CAIC,GACD,OAAO,MAAMC,uBAAuBC,OAAOC,GAAG,CAAC,wBAAuB;AActE,SAASC;IACP,OAAO,AAACC,UAAkC,CAACJ,qBAAqB;AAClE;AAEA;;CAEC,GACD,OAAO,SAASK;IACd,MAAMC,QAAQH;IACd,qFAAqF;IACrF,IAAI,CAACG,OAAO;QACVR,GAAGS,IAAI,CAAC;QACR,OAAOR;IACT;IAEA,OAAOO,MAAME,MAAM;AACrB;AAEA;;;CAGC,GACD,OAAO,SAASC,gBACdC,SAA4B,EAC5BC,OAAiD;;IAE/CP,UAAkC,CAACJ,qBAAqB,GAAG;QAC3DQ,QAAQE;QACRE,kBAAkBD,SAASC;IAC7B;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASC,oBAAoBC,KAAY;IAC9CX,YAAYS,mBAAmBE;AACjC;AAEA;;;CAGC,GACD,OAAO,SAASC;IACd,MAAMC,SAASZ;IACf,OAAOY,MAAM,CAAChB,qBAAqB;AACrC"}
@@ -0,0 +1,23 @@
1
+ // Inline noop implementation — avoids a runtime dependency on @sanity/telemetry
2
+ // (types-only usage keeps it as a devDependency). Explicit types ensure this
3
+ // stays structurally in sync with TelemetryLogger/TelemetryTrace.
4
+ const noopTrace = {
5
+ await: (promise)=>promise,
6
+ complete: ()=>{},
7
+ error: ()=>{},
8
+ log: ()=>{},
9
+ newContext: ()=>noopLogger,
10
+ start: ()=>{}
11
+ };
12
+ /**
13
+ * Fallback logger used when telemetry has not been initialized.
14
+ * Exported for use in tests only — do not use in plugins or external code.
15
+ * @internal
16
+ */ export const noopLogger = {
17
+ log: ()=>{},
18
+ resume: ()=>{},
19
+ trace: ()=>noopTrace,
20
+ updateUserProperties: ()=>{}
21
+ };
22
+
23
+ //# sourceMappingURL=noopTelemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/noopTelemetry.ts"],"sourcesContent":["import {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {type CLITelemetryStore, type TelemetryUserProperties} from './types.js'\n\n// Inline noop implementation — avoids a runtime dependency on @sanity/telemetry\n// (types-only usage keeps it as a devDependency). Explicit types ensure this\n// stays structurally in sync with TelemetryLogger/TelemetryTrace.\nconst noopTrace: TelemetryTrace<TelemetryUserProperties, never> = {\n await: <P extends Promise<unknown>>(promise: P): P => promise,\n complete: () => {},\n error: () => {},\n log: () => {},\n newContext: (): CLITelemetryStore => noopLogger,\n start: () => {},\n}\n\n/**\n * Fallback logger used when telemetry has not been initialized.\n * Exported for use in tests only — do not use in plugins or external code.\n * @internal\n */\nexport const noopLogger: CLITelemetryStore = {\n log: () => {},\n resume: () => {},\n trace: () => noopTrace,\n updateUserProperties: () => {},\n}\n"],"names":["noopTrace","await","promise","complete","error","log","newContext","noopLogger","start","resume","trace","updateUserProperties"],"mappings":"AAIA,gFAAgF;AAChF,6EAA6E;AAC7E,kEAAkE;AAClE,MAAMA,YAA4D;IAChEC,OAAO,CAA6BC,UAAkBA;IACtDC,UAAU,KAAO;IACjBC,OAAO,KAAO;IACdC,KAAK,KAAO;IACZC,YAAY,IAAyBC;IACrCC,OAAO,KAAO;AAChB;AAEA;;;;CAIC,GACD,OAAO,MAAMD,aAAgC;IAC3CF,KAAK,KAAO;IACZI,QAAQ,KAAO;IACfC,OAAO,IAAMV;IACbW,sBAAsB,KAAO;AAC/B,EAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/readNDJSON.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\n\n/**\n * Reads and parses an NDJSON (newline-delimited JSON) file containing telemetry events.\n *\n * @param filePath - Path to the NDJSON file\n * @returns Promise resolving to array of parsed telemetry events\n * @throws Error if file cannot be read or contains invalid JSON\n *\n * @internal\n */\nexport async function readNDJSON<T>(filePath: string): Promise<T[]> {\n const content = await readFile(filePath, 'utf8')\n\n if (!content.trim()) {\n return []\n }\n\n return content\n .trim()\n .split('\\n')\n .filter(Boolean)\n .map((line) => JSON.parse(line) as T)\n}\n"],"names":["readFile","readNDJSON","filePath","content","trim","split","filter","Boolean","map","line","JSON","parse"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AAEzC;;;;;;;;CAQC,GACD,OAAO,eAAeC,WAAcC,QAAgB;IAClD,MAAMC,UAAU,MAAMH,SAASE,UAAU;IAEzC,IAAI,CAACC,QAAQC,IAAI,IAAI;QACnB,OAAO,EAAE;IACX;IAEA,OAAOD,QACJC,IAAI,GACJC,KAAK,CAAC,MACNC,MAAM,CAACC,SACPC,GAAG,CAAC,CAACC,OAASC,KAAKC,KAAK,CAACF;AAC9B"}
@@ -27,7 +27,9 @@ import { doImport } from '../doImport.js';
27
27
  return getEnvVars(rootPath);
28
28
  } catch (err) {
29
29
  const message = err instanceof Error ? err.message : String(err);
30
- throw new Error(`Failed to import getStudioEnvironmentVariables from sanity/cli module: ${message}`);
30
+ throw new Error(`Failed to import getStudioEnvironmentVariables from sanity/cli module: ${message}`, {
31
+ cause: err
32
+ });
31
33
  }
32
34
  }
33
35
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/util/environment/getStudioEnvironmentVariables.ts"],"sourcesContent":["import {resolve} from 'node:path'\nimport {pathToFileURL} from 'node:url'\n\nimport {moduleResolve} from 'import-meta-resolve'\n\nimport {doImport} from '../doImport.js'\n\n/**\n * Loads the `getStudioEnvironmentVariables` function from the studio's\n * installed `sanity` package and returns the environment variables.\n *\n * This is used to ensure we're using the same version of environment variable\n * logic as the studio itself.\n *\n * @param rootPath - The root path of the Sanity Studio project\n * @returns Object containing studio environment variables\n * @internal\n */\nexport async function getStudioEnvironmentVariables(\n rootPath: string,\n): Promise<Record<string, string>> {\n // Create a fake config URL - doesn't have to be correct, just need the root path\n const fakeConfigUrl = pathToFileURL(resolve(rootPath, 'sanity.config.mjs'))\n\n // 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 order to ensure we're using the same version as the studio would.\n const sanityCliUrl = moduleResolve('sanity/cli', fakeConfigUrl)\n try {\n const {getStudioEnvironmentVariables: getEnvVars} = await doImport(sanityCliUrl.href)\n if (typeof getEnvVars !== 'function') {\n throw new TypeError(\n 'Expected `getStudioEnvironmentVariables` from `sanity/cli` to be a function',\n )\n }\n return getEnvVars(rootPath)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Failed to import getStudioEnvironmentVariables from sanity/cli module: ${message}`,\n )\n }\n}\n"],"names":["resolve","pathToFileURL","moduleResolve","doImport","getStudioEnvironmentVariables","rootPath","fakeConfigUrl","sanityCliUrl","getEnvVars","href","TypeError","err","message","Error","String"],"mappings":"AAAA,SAAQA,OAAO,QAAO,YAAW;AACjC,SAAQC,aAAa,QAAO,WAAU;AAEtC,SAAQC,aAAa,QAAO,sBAAqB;AAEjD,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC;;;;;;;;;;CAUC,GACD,OAAO,eAAeC,8BACpBC,QAAgB;IAEhB,iFAAiF;IACjF,MAAMC,gBAAgBL,cAAcD,QAAQK,UAAU;IAEtD,8EAA8E;IAC9E,uFAAuF;IACvF,gFAAgF;IAChF,MAAME,eAAeL,cAAc,cAAcI;IACjD,IAAI;QACF,MAAM,EAACF,+BAA+BI,UAAU,EAAC,GAAG,MAAML,SAASI,aAAaE,IAAI;QACpF,IAAI,OAAOD,eAAe,YAAY;YACpC,MAAM,IAAIE,UACR;QAEJ;QACA,OAAOF,WAAWH;IACpB,EAAE,OAAOM,KAAK;QACZ,MAAMC,UAAUD,eAAeE,QAAQF,IAAIC,OAAO,GAAGE,OAAOH;QAC5D,MAAM,IAAIE,MACR,CAAC,uEAAuE,EAAED,SAAS;IAEvF;AACF"}
1
+ {"version":3,"sources":["../../../src/util/environment/getStudioEnvironmentVariables.ts"],"sourcesContent":["import {resolve} from 'node:path'\nimport {pathToFileURL} from 'node:url'\n\nimport {moduleResolve} from 'import-meta-resolve'\n\nimport {doImport} from '../doImport.js'\n\n/**\n * Loads the `getStudioEnvironmentVariables` function from the studio's\n * installed `sanity` package and returns the environment variables.\n *\n * This is used to ensure we're using the same version of environment variable\n * logic as the studio itself.\n *\n * @param rootPath - The root path of the Sanity Studio project\n * @returns Object containing studio environment variables\n * @internal\n */\nexport async function getStudioEnvironmentVariables(\n rootPath: string,\n): Promise<Record<string, string>> {\n // Create a fake config URL - doesn't have to be correct, just need the root path\n const fakeConfigUrl = pathToFileURL(resolve(rootPath, 'sanity.config.mjs'))\n\n // 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 order to ensure we're using the same version as the studio would.\n const sanityCliUrl = moduleResolve('sanity/cli', fakeConfigUrl)\n try {\n const {getStudioEnvironmentVariables: getEnvVars} = await doImport(sanityCliUrl.href)\n if (typeof getEnvVars !== 'function') {\n throw new TypeError(\n 'Expected `getStudioEnvironmentVariables` from `sanity/cli` to be a function',\n )\n }\n return getEnvVars(rootPath)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Failed to import getStudioEnvironmentVariables from sanity/cli module: ${message}`,\n {cause: err},\n )\n }\n}\n"],"names":["resolve","pathToFileURL","moduleResolve","doImport","getStudioEnvironmentVariables","rootPath","fakeConfigUrl","sanityCliUrl","getEnvVars","href","TypeError","err","message","Error","String","cause"],"mappings":"AAAA,SAAQA,OAAO,QAAO,YAAW;AACjC,SAAQC,aAAa,QAAO,WAAU;AAEtC,SAAQC,aAAa,QAAO,sBAAqB;AAEjD,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC;;;;;;;;;;CAUC,GACD,OAAO,eAAeC,8BACpBC,QAAgB;IAEhB,iFAAiF;IACjF,MAAMC,gBAAgBL,cAAcD,QAAQK,UAAU;IAEtD,8EAA8E;IAC9E,uFAAuF;IACvF,gFAAgF;IAChF,MAAME,eAAeL,cAAc,cAAcI;IACjD,IAAI;QACF,MAAM,EAACF,+BAA+BI,UAAU,EAAC,GAAG,MAAML,SAASI,aAAaE,IAAI;QACpF,IAAI,OAAOD,eAAe,YAAY;YACpC,MAAM,IAAIE,UACR;QAEJ;QACA,OAAOF,WAAWH;IACpB,EAAE,OAAOM,KAAK;QACZ,MAAMC,UAAUD,eAAeE,QAAQF,IAAIC,OAAO,GAAGE,OAAOH;QAC5D,MAAM,IAAIE,MACR,CAAC,uEAAuE,EAAED,SAAS,EACnF;YAACG,OAAOJ;QAAG;IAEf;AACF"}
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ /**
3
+ * Read the file at the given path synchronously and parse it as JSON.
4
+ *
5
+ * @param filePath - Path to JSON file to read
6
+ * @returns The parsed file
7
+ * @internal
8
+ */ export function readJsonFileSync(filePath) {
9
+ let content;
10
+ try {
11
+ content = readFileSync(filePath, 'utf8');
12
+ } catch (err) {
13
+ throw new Error(`Failed to read "${filePath}"`, {
14
+ cause: err
15
+ });
16
+ }
17
+ try {
18
+ return JSON.parse(content);
19
+ } catch (err) {
20
+ throw new Error(`Failed to parse "${filePath}" as JSON`, {
21
+ cause: err
22
+ });
23
+ }
24
+ }
25
+
26
+ //# sourceMappingURL=readJsonFileSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/readJsonFileSync.ts"],"sourcesContent":["import {readFileSync} from 'node:fs'\n\ntype JSONValue = boolean | JSONArray | JSONObject | number | string | null\n\ntype JSONObject = {[key: string]: JSONValue}\n\ntype JSONArray = Array<JSONValue>\n\n/**\n * Read the file at the given path synchronously and parse it as JSON.\n *\n * @param filePath - Path to JSON file to read\n * @returns The parsed file\n * @internal\n */\nexport function readJsonFileSync(filePath: string): JSONValue {\n let content: string\n try {\n content = readFileSync(filePath, 'utf8')\n } catch (err: unknown) {\n throw new Error(`Failed to read \"${filePath}\"`, {cause: err})\n }\n\n try {\n return JSON.parse(content)\n } catch (err: unknown) {\n throw new Error(`Failed to parse \"${filePath}\" as JSON`, {cause: err})\n }\n}\n"],"names":["readFileSync","readJsonFileSync","filePath","content","err","Error","cause","JSON","parse"],"mappings":"AAAA,SAAQA,YAAY,QAAO,UAAS;AAQpC;;;;;;CAMC,GACD,OAAO,SAASC,iBAAiBC,QAAgB;IAC/C,IAAIC;IACJ,IAAI;QACFA,UAAUH,aAAaE,UAAU;IACnC,EAAE,OAAOE,KAAc;QACrB,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAEH,SAAS,CAAC,CAAC,EAAE;YAACI,OAAOF;QAAG;IAC7D;IAEA,IAAI;QACF,OAAOG,KAAKC,KAAK,CAACL;IACpB,EAAE,OAAOC,KAAc;QACrB,MAAM,IAAIC,MAAM,CAAC,iBAAiB,EAAEH,SAAS,SAAS,CAAC,EAAE;YAACI,OAAOF;QAAG;IACtE;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { readFile } from 'node:fs/promises';
2
- import { z } from 'zod';
2
+ import { z } from 'zod/mini';
3
3
  /**
4
4
  * Comprehensive package.json schema including all common properties.
5
5
  * Feel free to add properties to this,
@@ -11,28 +11,28 @@ import { z } from 'zod';
11
11
  name: z.string(),
12
12
  version: z.string(),
13
13
  // Dependencies (optional)
14
- dependencies: z.record(z.string(), z.string()).optional(),
15
- devDependencies: z.record(z.string(), z.string()).optional(),
16
- peerDependencies: z.record(z.string(), z.string()).optional(),
14
+ dependencies: z.optional(z.record(z.string(), z.string())),
15
+ devDependencies: z.optional(z.record(z.string(), z.string())),
16
+ peerDependencies: z.optional(z.record(z.string(), z.string())),
17
17
  // Module structure (optional)
18
- exports: z.record(z.string(), z.any()).optional(),
19
- main: z.string().optional(),
20
- types: z.string().optional(),
18
+ exports: z.optional(z.record(z.string(), z.any())),
19
+ main: z.optional(z.string()),
20
+ types: z.optional(z.string()),
21
21
  // Metadata (optional)
22
- author: z.string().optional(),
23
- description: z.string().optional(),
24
- engines: z.record(z.string(), z.string()).optional(),
25
- license: z.string().optional(),
26
- private: z.boolean().optional(),
27
- repository: z.object({
22
+ author: z.optional(z.string()),
23
+ description: z.optional(z.string()),
24
+ engines: z.optional(z.record(z.string(), z.string())),
25
+ license: z.optional(z.string()),
26
+ private: z.optional(z.boolean()),
27
+ repository: z.optional(z.object({
28
28
  type: z.string(),
29
29
  url: z.string()
30
- }).optional(),
31
- scripts: z.record(z.string(), z.string()).optional(),
32
- type: z.enum([
30
+ })),
31
+ scripts: z.optional(z.record(z.string(), z.string())),
32
+ type: z.optional(z.enum([
33
33
  'module',
34
34
  'commonjs'
35
- ]).optional()
35
+ ]))
36
36
  });
37
37
  /**
38
38
  * Read the `package.json` file at the given path
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/util/readPackageJson.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\n\nimport {z} from 'zod'\n\n/**\n * Comprehensive package.json schema including all common properties.\n * Feel free to add properties to this,\n * 🟠ℹ️ BUT ENSURE OPTIONAL STUFF IS ACTUALLY OPTIONAL ℹ️🟠\n * 🟠ℹ️ SINCE THIS IS USED IN A NUMBER OF LOCATIONS WHERE ℹ️🟠\n * 🟠ℹ️ WE CANNOT ENFORCE/GUARANTEE ANY PARTICULAR PROPS ℹ️🟠\n */\nconst packageJsonSchema = z.looseObject({\n // Required fields\n name: z.string(),\n version: z.string(),\n\n // Dependencies (optional)\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n peerDependencies: z.record(z.string(), z.string()).optional(),\n\n // Module structure (optional)\n exports: z.record(z.string(), z.any()).optional(),\n main: z.string().optional(),\n types: z.string().optional(),\n\n // Metadata (optional)\n author: z.string().optional(),\n description: z.string().optional(),\n engines: z.record(z.string(), z.string()).optional(),\n license: z.string().optional(),\n private: z.boolean().optional(),\n repository: z\n .object({\n type: z.string(),\n url: z.string(),\n })\n .optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n type: z.enum(['module', 'commonjs']).optional(),\n})\n\n/**\n * Comprehensive representation of a package.json file.\n * Consolidates all properties from previous type definitions.\n *\n * @public\n */\nexport type PackageJson = z.infer<typeof packageJsonSchema>\n\n/**\n * Options for reading package.json files\n *\n * @public\n */\nexport interface ReadPackageJsonOptions {\n /**\n * Default values to merge with the parsed package.json.\n * Parsed values take precedence over defaults.\n */\n defaults?: Partial<PackageJson>\n\n /**\n * Skip Zod schema validation. When true, the file is parsed but not validated.\n * Defaults to false.\n */\n skipSchemaValidation?: boolean\n}\n\n/**\n * Read the `package.json` file at the given path\n *\n * @param filePath - Path to package.json to read\n * @param options - Options object for controlling read behavior\n * @returns The parsed package.json\n * @public\n */\nexport async function readPackageJson(\n filePath: string | URL,\n options: ReadPackageJsonOptions = {},\n): Promise<PackageJson> {\n const {defaults = {}, skipSchemaValidation = false} = options\n\n // Read and parse the file\n let pkg: Record<string, unknown>\n try {\n pkg = JSON.parse(await readFile(filePath, 'utf8'))\n } catch (err: unknown) {\n throw new Error(`Failed to read \"${filePath}\"`, {cause: err})\n }\n\n // Merge with defaults (parsed values take precedence)\n const merged = {...defaults, ...pkg}\n\n // Validate with schema unless skipped\n let validated: PackageJson\n if (skipSchemaValidation) {\n validated = merged as PackageJson\n } else {\n const {data, error, success} = packageJsonSchema.safeParse(merged)\n if (!success) {\n throw new Error(\n `Invalid package.json at \"${filePath}\": ${error.issues.map((err) => err.message).join('\\n')}`,\n )\n }\n validated = data\n }\n\n return validated\n}\n"],"names":["readFile","z","packageJsonSchema","looseObject","name","string","version","dependencies","record","optional","devDependencies","peerDependencies","exports","any","main","types","author","description","engines","license","private","boolean","repository","object","type","url","scripts","enum","readPackageJson","filePath","options","defaults","skipSchemaValidation","pkg","JSON","parse","err","Error","cause","merged","validated","data","error","success","safeParse","issues","map","message","join"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AAEzC,SAAQC,CAAC,QAAO,MAAK;AAErB;;;;;;CAMC,GACD,MAAMC,oBAAoBD,EAAEE,WAAW,CAAC;IACtC,kBAAkB;IAClBC,MAAMH,EAAEI,MAAM;IACdC,SAASL,EAAEI,MAAM;IAEjB,0BAA0B;IAC1BE,cAAcN,EAAEO,MAAM,CAACP,EAAEI,MAAM,IAAIJ,EAAEI,MAAM,IAAII,QAAQ;IACvDC,iBAAiBT,EAAEO,MAAM,CAACP,EAAEI,MAAM,IAAIJ,EAAEI,MAAM,IAAII,QAAQ;IAC1DE,kBAAkBV,EAAEO,MAAM,CAACP,EAAEI,MAAM,IAAIJ,EAAEI,MAAM,IAAII,QAAQ;IAE3D,8BAA8B;IAC9BG,SAASX,EAAEO,MAAM,CAACP,EAAEI,MAAM,IAAIJ,EAAEY,GAAG,IAAIJ,QAAQ;IAC/CK,MAAMb,EAAEI,MAAM,GAAGI,QAAQ;IACzBM,OAAOd,EAAEI,MAAM,GAAGI,QAAQ;IAE1B,sBAAsB;IACtBO,QAAQf,EAAEI,MAAM,GAAGI,QAAQ;IAC3BQ,aAAahB,EAAEI,MAAM,GAAGI,QAAQ;IAChCS,SAASjB,EAAEO,MAAM,CAACP,EAAEI,MAAM,IAAIJ,EAAEI,MAAM,IAAII,QAAQ;IAClDU,SAASlB,EAAEI,MAAM,GAAGI,QAAQ;IAC5BW,SAASnB,EAAEoB,OAAO,GAAGZ,QAAQ;IAC7Ba,YAAYrB,EACTsB,MAAM,CAAC;QACNC,MAAMvB,EAAEI,MAAM;QACdoB,KAAKxB,EAAEI,MAAM;IACf,GACCI,QAAQ;IACXiB,SAASzB,EAAEO,MAAM,CAACP,EAAEI,MAAM,IAAIJ,EAAEI,MAAM,IAAII,QAAQ;IAClDe,MAAMvB,EAAE0B,IAAI,CAAC;QAAC;QAAU;KAAW,EAAElB,QAAQ;AAC/C;AA6BA;;;;;;;CAOC,GACD,OAAO,eAAemB,gBACpBC,QAAsB,EACtBC,UAAkC,CAAC,CAAC;IAEpC,MAAM,EAACC,WAAW,CAAC,CAAC,EAAEC,uBAAuB,KAAK,EAAC,GAAGF;IAEtD,0BAA0B;IAC1B,IAAIG;IACJ,IAAI;QACFA,MAAMC,KAAKC,KAAK,CAAC,MAAMnC,SAAS6B,UAAU;IAC5C,EAAE,OAAOO,KAAc;QACrB,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAER,SAAS,CAAC,CAAC,EAAE;YAACS,OAAOF;QAAG;IAC7D;IAEA,sDAAsD;IACtD,MAAMG,SAAS;QAAC,GAAGR,QAAQ;QAAE,GAAGE,GAAG;IAAA;IAEnC,sCAAsC;IACtC,IAAIO;IACJ,IAAIR,sBAAsB;QACxBQ,YAAYD;IACd,OAAO;QACL,MAAM,EAACE,IAAI,EAAEC,KAAK,EAAEC,OAAO,EAAC,GAAGzC,kBAAkB0C,SAAS,CAACL;QAC3D,IAAI,CAACI,SAAS;YACZ,MAAM,IAAIN,MACR,CAAC,yBAAyB,EAAER,SAAS,GAAG,EAAEa,MAAMG,MAAM,CAACC,GAAG,CAAC,CAACV,MAAQA,IAAIW,OAAO,EAAEC,IAAI,CAAC,OAAO;QAEjG;QACAR,YAAYC;IACd;IAEA,OAAOD;AACT"}
1
+ {"version":3,"sources":["../../src/util/readPackageJson.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\n\nimport {z} from 'zod/mini'\n\n/**\n * Comprehensive package.json schema including all common properties.\n * Feel free to add properties to this,\n * 🟠ℹ️ BUT ENSURE OPTIONAL STUFF IS ACTUALLY OPTIONAL ℹ️🟠\n * 🟠ℹ️ SINCE THIS IS USED IN A NUMBER OF LOCATIONS WHERE ℹ️🟠\n * 🟠ℹ️ WE CANNOT ENFORCE/GUARANTEE ANY PARTICULAR PROPS ℹ️🟠\n */\nconst packageJsonSchema = z.looseObject({\n // Required fields\n name: z.string(),\n version: z.string(),\n\n // Dependencies (optional)\n dependencies: z.optional(z.record(z.string(), z.string())),\n devDependencies: z.optional(z.record(z.string(), z.string())),\n peerDependencies: z.optional(z.record(z.string(), z.string())),\n\n // Module structure (optional)\n exports: z.optional(z.record(z.string(), z.any())),\n main: z.optional(z.string()),\n types: z.optional(z.string()),\n\n // Metadata (optional)\n author: z.optional(z.string()),\n description: z.optional(z.string()),\n engines: z.optional(z.record(z.string(), z.string())),\n license: z.optional(z.string()),\n private: z.optional(z.boolean()),\n repository: z.optional(\n z.object({\n type: z.string(),\n url: z.string(),\n }),\n ),\n scripts: z.optional(z.record(z.string(), z.string())),\n type: z.optional(z.enum(['module', 'commonjs'])),\n})\n\n/**\n * Comprehensive representation of a package.json file.\n * Consolidates all properties from previous type definitions.\n *\n * @public\n */\nexport type PackageJson = z.infer<typeof packageJsonSchema>\n\n/**\n * Options for reading package.json files\n *\n * @public\n */\nexport interface ReadPackageJsonOptions {\n /**\n * Default values to merge with the parsed package.json.\n * Parsed values take precedence over defaults.\n */\n defaults?: Partial<PackageJson>\n\n /**\n * Skip Zod schema validation. When true, the file is parsed but not validated.\n * Defaults to false.\n */\n skipSchemaValidation?: boolean\n}\n\n/**\n * Read the `package.json` file at the given path\n *\n * @param filePath - Path to package.json to read\n * @param options - Options object for controlling read behavior\n * @returns The parsed package.json\n * @public\n */\nexport async function readPackageJson(\n filePath: string | URL,\n options: ReadPackageJsonOptions = {},\n): Promise<PackageJson> {\n const {defaults = {}, skipSchemaValidation = false} = options\n\n // Read and parse the file\n let pkg: Record<string, unknown>\n try {\n pkg = JSON.parse(await readFile(filePath, 'utf8'))\n } catch (err: unknown) {\n throw new Error(`Failed to read \"${filePath}\"`, {cause: err})\n }\n\n // Merge with defaults (parsed values take precedence)\n const merged = {...defaults, ...pkg}\n\n // Validate with schema unless skipped\n let validated: PackageJson\n if (skipSchemaValidation) {\n validated = merged as PackageJson\n } else {\n const {data, error, success} = packageJsonSchema.safeParse(merged)\n if (!success) {\n throw new Error(\n `Invalid package.json at \"${filePath}\": ${error.issues.map((err) => err.message).join('\\n')}`,\n )\n }\n validated = data\n }\n\n return validated\n}\n"],"names":["readFile","z","packageJsonSchema","looseObject","name","string","version","dependencies","optional","record","devDependencies","peerDependencies","exports","any","main","types","author","description","engines","license","private","boolean","repository","object","type","url","scripts","enum","readPackageJson","filePath","options","defaults","skipSchemaValidation","pkg","JSON","parse","err","Error","cause","merged","validated","data","error","success","safeParse","issues","map","message","join"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AAEzC,SAAQC,CAAC,QAAO,WAAU;AAE1B;;;;;;CAMC,GACD,MAAMC,oBAAoBD,EAAEE,WAAW,CAAC;IACtC,kBAAkB;IAClBC,MAAMH,EAAEI,MAAM;IACdC,SAASL,EAAEI,MAAM;IAEjB,0BAA0B;IAC1BE,cAAcN,EAAEO,QAAQ,CAACP,EAAEQ,MAAM,CAACR,EAAEI,MAAM,IAAIJ,EAAEI,MAAM;IACtDK,iBAAiBT,EAAEO,QAAQ,CAACP,EAAEQ,MAAM,CAACR,EAAEI,MAAM,IAAIJ,EAAEI,MAAM;IACzDM,kBAAkBV,EAAEO,QAAQ,CAACP,EAAEQ,MAAM,CAACR,EAAEI,MAAM,IAAIJ,EAAEI,MAAM;IAE1D,8BAA8B;IAC9BO,SAASX,EAAEO,QAAQ,CAACP,EAAEQ,MAAM,CAACR,EAAEI,MAAM,IAAIJ,EAAEY,GAAG;IAC9CC,MAAMb,EAAEO,QAAQ,CAACP,EAAEI,MAAM;IACzBU,OAAOd,EAAEO,QAAQ,CAACP,EAAEI,MAAM;IAE1B,sBAAsB;IACtBW,QAAQf,EAAEO,QAAQ,CAACP,EAAEI,MAAM;IAC3BY,aAAahB,EAAEO,QAAQ,CAACP,EAAEI,MAAM;IAChCa,SAASjB,EAAEO,QAAQ,CAACP,EAAEQ,MAAM,CAACR,EAAEI,MAAM,IAAIJ,EAAEI,MAAM;IACjDc,SAASlB,EAAEO,QAAQ,CAACP,EAAEI,MAAM;IAC5Be,SAASnB,EAAEO,QAAQ,CAACP,EAAEoB,OAAO;IAC7BC,YAAYrB,EAAEO,QAAQ,CACpBP,EAAEsB,MAAM,CAAC;QACPC,MAAMvB,EAAEI,MAAM;QACdoB,KAAKxB,EAAEI,MAAM;IACf;IAEFqB,SAASzB,EAAEO,QAAQ,CAACP,EAAEQ,MAAM,CAACR,EAAEI,MAAM,IAAIJ,EAAEI,MAAM;IACjDmB,MAAMvB,EAAEO,QAAQ,CAACP,EAAE0B,IAAI,CAAC;QAAC;QAAU;KAAW;AAChD;AA6BA;;;;;;;CAOC,GACD,OAAO,eAAeC,gBACpBC,QAAsB,EACtBC,UAAkC,CAAC,CAAC;IAEpC,MAAM,EAACC,WAAW,CAAC,CAAC,EAAEC,uBAAuB,KAAK,EAAC,GAAGF;IAEtD,0BAA0B;IAC1B,IAAIG;IACJ,IAAI;QACFA,MAAMC,KAAKC,KAAK,CAAC,MAAMnC,SAAS6B,UAAU;IAC5C,EAAE,OAAOO,KAAc;QACrB,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAER,SAAS,CAAC,CAAC,EAAE;YAACS,OAAOF;QAAG;IAC7D;IAEA,sDAAsD;IACtD,MAAMG,SAAS;QAAC,GAAGR,QAAQ;QAAE,GAAGE,GAAG;IAAA;IAEnC,sCAAsC;IACtC,IAAIO;IACJ,IAAIR,sBAAsB;QACxBQ,YAAYD;IACd,OAAO;QACL,MAAM,EAACE,IAAI,EAAEC,KAAK,EAAEC,OAAO,EAAC,GAAGzC,kBAAkB0C,SAAS,CAACL;QAC3D,IAAI,CAACI,SAAS;YACZ,MAAM,IAAIN,MACR,CAAC,yBAAyB,EAAER,SAAS,GAAG,EAAEa,MAAMG,MAAM,CAACC,GAAG,CAAC,CAACV,MAAQA,IAAIW,OAAO,EAAEC,IAAI,CAAC,OAAO;QAEjG;QACAR,YAAYC;IACd;IAEA,OAAOD;AACT"}
@@ -45,7 +45,9 @@ import { doImport } from './doImport.js';
45
45
  try {
46
46
  return moduleResolve(packageName, fakeCliConfigUrl);
47
47
  } catch (error) {
48
- throw new Error(`Failed to resolve package "${packageName}" from "${workDir}": ${error instanceof Error ? error.message : String(error)}`);
48
+ throw new Error(`Failed to resolve package "${packageName}" from "${workDir}": ${error instanceof Error ? error.message : String(error)}`, {
49
+ cause: error
50
+ });
49
51
  }
50
52
  }
51
53
  /**
@@ -71,7 +73,9 @@ import { doImport } from './doImport.js';
71
73
  const module = await doImport(packageUrl.href);
72
74
  return module;
73
75
  } catch (error) {
74
- throw new Error(`Failed to resolve package "${packageName}" from "${parentUrl.href}": ${error instanceof Error ? error.message : String(error)}`);
76
+ throw new Error(`Failed to resolve package "${packageName}" from "${parentUrl.href}": ${error instanceof Error ? error.message : String(error)}`, {
77
+ cause: error
78
+ });
75
79
  }
76
80
  }
77
81
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/util/resolveLocalPackage.ts"],"sourcesContent":["import {resolve} from 'node:path'\nimport {pathToFileURL} from 'node:url'\n\nimport {moduleResolve} from 'import-meta-resolve'\n\nimport {doImport} from './doImport.js'\n\n/**\n * Resolves and imports a package from the local project's node_modules,\n * relative to the given working directory. This avoids circular dependencies\n * and ensures the correct version of the package is used.\n *\n * @param packageName - The name of the package to resolve (e.g., 'sanity')\n * @param workDir - The working directory to resolve the package from\n * @returns The imported module\n * @throws If the package cannot be resolved or imported\n *\n * @example\n * ```ts\n * const {createSchema} = await resolveLocalPackage('sanity', workDir)\n * ```\n *\n * @internal\n */\nexport async function resolveLocalPackage<T = unknown>(\n packageName: string,\n workDir: string,\n): Promise<T> {\n const packageUrl = resolveLocalPackagePath(packageName, workDir)\n const module = await doImport(packageUrl.href)\n return module as T\n}\n\n/**\n * Resolves the URL of a package from the local project's node_modules,\n * relative to the given working directory, without importing it.\n *\n * @param packageName - The name of the package to resolve (e.g., 'sanity')\n * @param workDir - The working directory to resolve the package from\n * @returns The resolved URL of the package entry point\n * @throws If the package cannot be resolved\n *\n * @example\n * ```ts\n * // Resolve a transitive dependency via its parent package:\n * const sanityUrl = resolveLocalPackagePath('sanity', workDir)\n * const uiUrl = resolveLocalPackagePathFrom('@sanity/ui', sanityUrl)\n * ```\n *\n * @internal\n */\nexport function resolveLocalPackagePath(packageName: string, workDir: string): URL {\n const fakeCliConfigUrl = pathToFileURL(resolve(workDir, 'sanity.cli.mjs'))\n\n try {\n return moduleResolve(packageName, fakeCliConfigUrl)\n } catch (error) {\n throw new Error(\n `Failed to resolve package \"${packageName}\" from \"${workDir}\": ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n\n/**\n * Resolves and imports a package relative to another resolved module URL.\n * Useful for resolving transitive dependencies that may not be directly\n * accessible from the project root (e.g., in pnpm strict mode).\n *\n * @param packageName - The name of the package to resolve\n * @param parentUrl - The URL of the parent module to resolve from\n * @returns The imported module\n * @throws If the package cannot be resolved or imported\n *\n * @example\n * ```ts\n * const sanityUrl = resolveLocalPackagePath('sanity', workDir)\n * const ui = await resolveLocalPackageFrom<typeof import('@sanity/ui')>('@sanity/ui', sanityUrl)\n * ```\n *\n * @internal\n */\nexport async function resolveLocalPackageFrom<T = unknown>(\n packageName: string,\n parentUrl: URL,\n): Promise<T> {\n try {\n const packageUrl = moduleResolve(packageName, parentUrl)\n const module = await doImport(packageUrl.href)\n return module as T\n } catch (error) {\n throw new Error(\n `Failed to resolve package \"${packageName}\" from \"${parentUrl.href}\": ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n"],"names":["resolve","pathToFileURL","moduleResolve","doImport","resolveLocalPackage","packageName","workDir","packageUrl","resolveLocalPackagePath","module","href","fakeCliConfigUrl","error","Error","message","String","resolveLocalPackageFrom","parentUrl"],"mappings":"AAAA,SAAQA,OAAO,QAAO,YAAW;AACjC,SAAQC,aAAa,QAAO,WAAU;AAEtC,SAAQC,aAAa,QAAO,sBAAqB;AAEjD,SAAQC,QAAQ,QAAO,gBAAe;AAEtC;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,eAAeC,oBACpBC,WAAmB,EACnBC,OAAe;IAEf,MAAMC,aAAaC,wBAAwBH,aAAaC;IACxD,MAAMG,SAAS,MAAMN,SAASI,WAAWG,IAAI;IAC7C,OAAOD;AACT;AAEA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASD,wBAAwBH,WAAmB,EAAEC,OAAe;IAC1E,MAAMK,mBAAmBV,cAAcD,QAAQM,SAAS;IAExD,IAAI;QACF,OAAOJ,cAAcG,aAAaM;IACpC,EAAE,OAAOC,OAAO;QACd,MAAM,IAAIC,MACR,CAAC,2BAA2B,EAAER,YAAY,QAAQ,EAAEC,QAAQ,GAAG,EAAEM,iBAAiBC,QAAQD,MAAME,OAAO,GAAGC,OAAOH,QAAQ;IAE7H;AACF;AAEA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,eAAeI,wBACpBX,WAAmB,EACnBY,SAAc;IAEd,IAAI;QACF,MAAMV,aAAaL,cAAcG,aAAaY;QAC9C,MAAMR,SAAS,MAAMN,SAASI,WAAWG,IAAI;QAC7C,OAAOD;IACT,EAAE,OAAOG,OAAO;QACd,MAAM,IAAIC,MACR,CAAC,2BAA2B,EAAER,YAAY,QAAQ,EAAEY,UAAUP,IAAI,CAAC,GAAG,EAAEE,iBAAiBC,QAAQD,MAAME,OAAO,GAAGC,OAAOH,QAAQ;IAEpI;AACF"}
1
+ {"version":3,"sources":["../../src/util/resolveLocalPackage.ts"],"sourcesContent":["import {resolve} from 'node:path'\nimport {pathToFileURL} from 'node:url'\n\nimport {moduleResolve} from 'import-meta-resolve'\n\nimport {doImport} from './doImport.js'\n\n/**\n * Resolves and imports a package from the local project's node_modules,\n * relative to the given working directory. This avoids circular dependencies\n * and ensures the correct version of the package is used.\n *\n * @param packageName - The name of the package to resolve (e.g., 'sanity')\n * @param workDir - The working directory to resolve the package from\n * @returns The imported module\n * @throws If the package cannot be resolved or imported\n *\n * @example\n * ```ts\n * const {createSchema} = await resolveLocalPackage('sanity', workDir)\n * ```\n *\n * @internal\n */\nexport async function resolveLocalPackage<T = unknown>(\n packageName: string,\n workDir: string,\n): Promise<T> {\n const packageUrl = resolveLocalPackagePath(packageName, workDir)\n const module = await doImport(packageUrl.href)\n return module as T\n}\n\n/**\n * Resolves the URL of a package from the local project's node_modules,\n * relative to the given working directory, without importing it.\n *\n * @param packageName - The name of the package to resolve (e.g., 'sanity')\n * @param workDir - The working directory to resolve the package from\n * @returns The resolved URL of the package entry point\n * @throws If the package cannot be resolved\n *\n * @example\n * ```ts\n * // Resolve a transitive dependency via its parent package:\n * const sanityUrl = resolveLocalPackagePath('sanity', workDir)\n * const uiUrl = resolveLocalPackagePathFrom('@sanity/ui', sanityUrl)\n * ```\n *\n * @internal\n */\nexport function resolveLocalPackagePath(packageName: string, workDir: string): URL {\n const fakeCliConfigUrl = pathToFileURL(resolve(workDir, 'sanity.cli.mjs'))\n\n try {\n return moduleResolve(packageName, fakeCliConfigUrl)\n } catch (error) {\n throw new Error(\n `Failed to resolve package \"${packageName}\" from \"${workDir}\": ${error instanceof Error ? error.message : String(error)}`,\n {cause: error},\n )\n }\n}\n\n/**\n * Resolves and imports a package relative to another resolved module URL.\n * Useful for resolving transitive dependencies that may not be directly\n * accessible from the project root (e.g., in pnpm strict mode).\n *\n * @param packageName - The name of the package to resolve\n * @param parentUrl - The URL of the parent module to resolve from\n * @returns The imported module\n * @throws If the package cannot be resolved or imported\n *\n * @example\n * ```ts\n * const sanityUrl = resolveLocalPackagePath('sanity', workDir)\n * const ui = await resolveLocalPackageFrom<typeof import('@sanity/ui')>('@sanity/ui', sanityUrl)\n * ```\n *\n * @internal\n */\nexport async function resolveLocalPackageFrom<T = unknown>(\n packageName: string,\n parentUrl: URL,\n): Promise<T> {\n try {\n const packageUrl = moduleResolve(packageName, parentUrl)\n const module = await doImport(packageUrl.href)\n return module as T\n } catch (error) {\n throw new Error(\n `Failed to resolve package \"${packageName}\" from \"${parentUrl.href}\": ${error instanceof Error ? error.message : String(error)}`,\n {cause: error},\n )\n }\n}\n"],"names":["resolve","pathToFileURL","moduleResolve","doImport","resolveLocalPackage","packageName","workDir","packageUrl","resolveLocalPackagePath","module","href","fakeCliConfigUrl","error","Error","message","String","cause","resolveLocalPackageFrom","parentUrl"],"mappings":"AAAA,SAAQA,OAAO,QAAO,YAAW;AACjC,SAAQC,aAAa,QAAO,WAAU;AAEtC,SAAQC,aAAa,QAAO,sBAAqB;AAEjD,SAAQC,QAAQ,QAAO,gBAAe;AAEtC;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,eAAeC,oBACpBC,WAAmB,EACnBC,OAAe;IAEf,MAAMC,aAAaC,wBAAwBH,aAAaC;IACxD,MAAMG,SAAS,MAAMN,SAASI,WAAWG,IAAI;IAC7C,OAAOD;AACT;AAEA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASD,wBAAwBH,WAAmB,EAAEC,OAAe;IAC1E,MAAMK,mBAAmBV,cAAcD,QAAQM,SAAS;IAExD,IAAI;QACF,OAAOJ,cAAcG,aAAaM;IACpC,EAAE,OAAOC,OAAO;QACd,MAAM,IAAIC,MACR,CAAC,2BAA2B,EAAER,YAAY,QAAQ,EAAEC,QAAQ,GAAG,EAAEM,iBAAiBC,QAAQD,MAAME,OAAO,GAAGC,OAAOH,QAAQ,EACzH;YAACI,OAAOJ;QAAK;IAEjB;AACF;AAEA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,eAAeK,wBACpBZ,WAAmB,EACnBa,SAAc;IAEd,IAAI;QACF,MAAMX,aAAaL,cAAcG,aAAaa;QAC9C,MAAMT,SAAS,MAAMN,SAASI,WAAWG,IAAI;QAC7C,OAAOD;IACT,EAAE,OAAOG,OAAO;QACd,MAAM,IAAIC,MACR,CAAC,2BAA2B,EAAER,YAAY,QAAQ,EAAEa,UAAUR,IAAI,CAAC,GAAG,EAAEE,iBAAiBC,QAAQD,MAAME,OAAO,GAAGC,OAAOH,QAAQ,EAChI;YAACI,OAAOJ;QAAK;IAEjB;AACF"}
@@ -0,0 +1,19 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ /**
3
+ * Serialize the given `data` as JSON and write it synchronously to the given path.
4
+ *
5
+ * @param filePath - Path to JSON file to write
6
+ * @internal
7
+ */ export function writeJsonFileSync(filePath, data, options = {}) {
8
+ const { pretty = false } = options;
9
+ try {
10
+ const stringified = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
11
+ writeFileSync(filePath, `${stringified}\n`, 'utf8');
12
+ } catch (err) {
13
+ throw new Error(`Failed to write "${filePath}"`, {
14
+ cause: err
15
+ });
16
+ }
17
+ }
18
+
19
+ //# sourceMappingURL=writeJsonFileSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/writeJsonFileSync.ts"],"sourcesContent":["import {writeFileSync} from 'node:fs'\n\n/**\n * Serialize the given `data` as JSON and write it synchronously to the given path.\n *\n * @param filePath - Path to JSON file to write\n * @internal\n */\nexport function writeJsonFileSync(\n filePath: string,\n data: unknown,\n options: {pretty?: boolean} = {},\n): void {\n const {pretty = false} = options\n try {\n const stringified = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data)\n writeFileSync(filePath, `${stringified}\\n`, 'utf8')\n } catch (err: unknown) {\n throw new Error(`Failed to write \"${filePath}\"`, {cause: err})\n }\n}\n"],"names":["writeFileSync","writeJsonFileSync","filePath","data","options","pretty","stringified","JSON","stringify","err","Error","cause"],"mappings":"AAAA,SAAQA,aAAa,QAAO,UAAS;AAErC;;;;;CAKC,GACD,OAAO,SAASC,kBACdC,QAAgB,EAChBC,IAAa,EACbC,UAA8B,CAAC,CAAC;IAEhC,MAAM,EAACC,SAAS,KAAK,EAAC,GAAGD;IACzB,IAAI;QACF,MAAME,cAAcD,SAASE,KAAKC,SAAS,CAACL,MAAM,MAAM,KAAKI,KAAKC,SAAS,CAACL;QAC5EH,cAAcE,UAAU,GAAGI,YAAY,EAAE,CAAC,EAAE;IAC9C,EAAE,OAAOG,KAAc;QACrB,MAAM,IAAIC,MAAM,CAAC,iBAAiB,EAAER,SAAS,CAAC,CAAC,EAAE;YAACS,OAAOF;QAAG;IAC9D;AACF"}