@sanity/cli 8.0.1 → 8.0.3

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 (119) hide show
  1. package/dist/SanityHelp.js.map +1 -1
  2. package/dist/actions/backup/assertDatasetExist.js +2 -1
  3. package/dist/actions/backup/assertDatasetExist.js.map +1 -1
  4. package/dist/actions/backup/downloadAsset.js +3 -24
  5. package/dist/actions/backup/downloadAsset.js.map +1 -1
  6. package/dist/actions/backup/downloadDocument.js +11 -22
  7. package/dist/actions/backup/downloadDocument.js.map +1 -1
  8. package/dist/actions/backup/downloadStream.js +83 -0
  9. package/dist/actions/backup/downloadStream.js.map +1 -0
  10. package/dist/actions/build/buildStudio.js +3 -2
  11. package/dist/actions/build/buildStudio.js.map +1 -1
  12. package/dist/actions/build/eventListenerFactory.js +7 -6
  13. package/dist/actions/build/eventListenerFactory.js.map +1 -1
  14. package/dist/actions/build/shouldAutoUpdate.js +2 -1
  15. package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
  16. package/dist/actions/cors/filterAndValidateOrigin.js +3 -2
  17. package/dist/actions/cors/filterAndValidateOrigin.js.map +1 -1
  18. package/dist/actions/deploy/createUserApplication.js +2 -1
  19. package/dist/actions/deploy/createUserApplication.js.map +1 -1
  20. package/dist/actions/deploy/deployRunner.js +3 -2
  21. package/dist/actions/deploy/deployRunner.js.map +1 -1
  22. package/dist/actions/deploy/deployStudio.js +3 -3
  23. package/dist/actions/deploy/deployStudio.js.map +1 -1
  24. package/dist/actions/deploy/findUserApplication.js +8 -7
  25. package/dist/actions/deploy/findUserApplication.js.map +1 -1
  26. package/dist/actions/dev/servers/startAppDevServer.js +2 -1
  27. package/dist/actions/dev/servers/startAppDevServer.js.map +1 -1
  28. package/dist/actions/dev/servers/startStudioDevServer.js +3 -3
  29. package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -1
  30. package/dist/actions/documents/validate.js +5 -5
  31. package/dist/actions/documents/validate.js.map +1 -1
  32. package/dist/actions/documents/validateDocuments.worker.js +4 -1
  33. package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
  34. package/dist/actions/init/env/createOrAppendEnvVars.js +2 -1
  35. package/dist/actions/init/env/createOrAppendEnvVars.js.map +1 -1
  36. package/dist/actions/init/env/parseAndUpdateEnvVars.js +2 -2
  37. package/dist/actions/init/env/parseAndUpdateEnvVars.js.map +1 -1
  38. package/dist/actions/schema/extractSchema.js +2 -2
  39. package/dist/actions/schema/extractSchema.js.map +1 -1
  40. package/dist/actions/schema/extractSchemaWatcher.js +2 -1
  41. package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
  42. package/dist/actions/schema/uploadSchemaToLexicon.js +3 -0
  43. package/dist/actions/schema/uploadSchemaToLexicon.js.map +1 -1
  44. package/dist/actions/telemetry/telemetryDebug.js +2 -2
  45. package/dist/actions/telemetry/telemetryDebug.js.map +1 -1
  46. package/dist/actions/undeploy/runUndeploy.js +2 -2
  47. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  48. package/dist/commands/backups/list.js +5 -8
  49. package/dist/commands/backups/list.js.map +1 -1
  50. package/dist/commands/datasets/copy.js +5 -7
  51. package/dist/commands/datasets/copy.js.map +1 -1
  52. package/dist/commands/datasets/import.js +7 -10
  53. package/dist/commands/datasets/import.js.map +1 -1
  54. package/dist/commands/docs/search.js +2 -2
  55. package/dist/commands/docs/search.js.map +1 -1
  56. package/dist/commands/mcp/configure.js +2 -2
  57. package/dist/commands/mcp/configure.js.map +1 -1
  58. package/dist/commands/typegen/generate.js +6 -6
  59. package/dist/commands/typegen/generate.js.map +1 -1
  60. package/dist/exports/_internal.d.ts +50 -82
  61. package/dist/exports/index.d.ts +48 -78
  62. package/dist/exports/invokeSanityCli/index.d.ts +108 -18
  63. package/dist/exports/invokeSanityCli/index.js +2 -1
  64. package/dist/exports/invokeSanityCli/index.js.map +1 -1
  65. package/dist/exports/runtime.d.ts +3 -65
  66. package/dist/services/api.js +23 -15
  67. package/dist/services/api.js.map +1 -1
  68. package/dist/services/auth.js +4 -4
  69. package/dist/services/auth.js.map +1 -1
  70. package/dist/services/backup.js +3 -3
  71. package/dist/services/backup.js.map +1 -1
  72. package/dist/services/cors.js +3 -3
  73. package/dist/services/cors.js.map +1 -1
  74. package/dist/services/datasetAliases.js +5 -5
  75. package/dist/services/datasetAliases.js.map +1 -1
  76. package/dist/services/datasets.js +3 -3
  77. package/dist/services/datasets.js.map +1 -1
  78. package/dist/services/documents.js +1 -1
  79. package/dist/services/documents.js.map +1 -1
  80. package/dist/services/getProjectFeatures.js +1 -1
  81. package/dist/services/getProjectFeatures.js.map +1 -1
  82. package/dist/services/getUrlHeaders.js +3 -9
  83. package/dist/services/getUrlHeaders.js.map +1 -1
  84. package/dist/services/grants.js +1 -1
  85. package/dist/services/grants.js.map +1 -1
  86. package/dist/services/graphql.js +4 -3
  87. package/dist/services/graphql.js.map +1 -1
  88. package/dist/services/hooks.js +6 -6
  89. package/dist/services/hooks.js.map +1 -1
  90. package/dist/services/mcp.js +4 -4
  91. package/dist/services/mcp.js.map +1 -1
  92. package/dist/services/mediaLibraries.js +3 -3
  93. package/dist/services/mediaLibraries.js.map +1 -1
  94. package/dist/services/mintProject.js +33 -14
  95. package/dist/services/mintProject.js.map +1 -1
  96. package/dist/services/organizations.js +6 -6
  97. package/dist/services/organizations.js.map +1 -1
  98. package/dist/services/plans.js +2 -2
  99. package/dist/services/plans.js.map +1 -1
  100. package/dist/services/projects.js +7 -7
  101. package/dist/services/projects.js.map +1 -1
  102. package/dist/services/schemas.js +2 -2
  103. package/dist/services/schemas.js.map +1 -1
  104. package/dist/services/telemetry.js +2 -2
  105. package/dist/services/telemetry.js.map +1 -1
  106. package/dist/services/tokens.js +5 -5
  107. package/dist/services/tokens.js.map +1 -1
  108. package/dist/services/user.js +1 -1
  109. package/dist/services/user.js.map +1 -1
  110. package/dist/services/userApplications.js +18 -18
  111. package/dist/services/userApplications.js.map +1 -1
  112. package/dist/util/appId.js +2 -1
  113. package/dist/util/appId.js.map +1 -1
  114. package/dist/util/dates.js +125 -0
  115. package/dist/util/dates.js.map +1 -0
  116. package/dist/util/getCliVersion.js +1 -11
  117. package/dist/util/getCliVersion.js.map +1 -1
  118. package/oclif.manifest.json +1093 -1093
  119. package/package.json +12 -15
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/telemetry.ts"],"sourcesContent":["import {createHash} from 'node:crypto'\n\nimport {getCliToken, getGlobalCliClient, getUserConfig} from '@sanity/cli-core'\nimport {getCliExecutionContext} from '@sanity/cli-core/executionContext'\nimport {type TelemetryEvent} from '@sanity/telemetry'\n\nimport {telemetryDebug} from '../actions/telemetry/telemetryDebug.js'\nimport {createExpiringConfig} from '../util/createExpiringConfig.js'\n\nexport const TELEMETRY_API_VERSION = 'v2026-01-22'\n\nexport const VALID_API_STATUSES = ['granted', 'denied', 'unset'] as const\nexport type ValidApiConsentStatus = (typeof VALID_API_STATUSES)[number]\n\nexport async function sendEvents(batch: TelemetryEvent[]) {\n const client = await getGlobalCliClient({\n apiVersion: TELEMETRY_API_VERSION,\n requireUser: true,\n })\n\n const projectId = process.env.SANITY_TELEMETRY_PROJECT_ID\n\n return client.request({\n body: {batch, projectId},\n json: true,\n method: 'POST',\n uri: '/intake/batch',\n })\n}\n\nasync function getTelemetryConsent(): Promise<{\n status: ValidApiConsentStatus\n}> {\n const client = await getGlobalCliClient({\n apiVersion: TELEMETRY_API_VERSION,\n requireUser: false,\n })\n\n return client.request({tag: 'telemetry-consent', uri: '/intake/telemetry-status'})\n}\n\n/**\n * Check if the given status is a valid consent status\n *\n * @param status - The status to check\n * @returns True if the status is valid, false otherwise\n * @internal\n */\nexport function isValidApiConsentStatus(status: string): status is ValidApiConsentStatus {\n return VALID_API_STATUSES.includes(status as ValidApiConsentStatus)\n}\n\n/**\n * Check if the given response is a valid API consent response\n *\n * @param response - The response to check\n * @returns True if the response is valid, false otherwise\n * @internal\n */\nfunction isValidApiConsentResponse(response: unknown): response is {status: ValidApiConsentStatus} {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'status' in response &&\n typeof response.status === 'string' &&\n isValidApiConsentStatus(response.status)\n )\n}\n\nexport const TELEMETRY_CONSENT_CONFIG_KEY = 'telemetryConsent'\nconst FIVE_MINUTES = 1000 * 60 * 5\n\n/**\n * Get a token-scoped cache key for telemetry consent. This ensures that switching\n * users (via login/logout) always results in a cache miss, preventing one user\n * from inheriting another user's cached consent status.\n *\n * @param token - The current auth token, or undefined if not logged in\n * @returns A cache key scoped to the token\n */\nexport function getTelemetryConsentCacheKey(token: string | undefined): string {\n if (!token) {\n return TELEMETRY_CONSENT_CONFIG_KEY\n }\n\n const hash = createHash('sha256').update(token).digest('hex').slice(0, 12)\n return `${TELEMETRY_CONSENT_CONFIG_KEY}:${hash}`\n}\n\n/**\n * Fetch the telemetry consent status for the current user\n * @returns The telemetry consent status\n *\n * @internal\n */\nexport async function fetchTelemetryConsent(): Promise<{\n status: ValidApiConsentStatus\n}> {\n // Programmatic invocations must not use the host user's disk-backed consent\n // cache. The request is already authenticated with the invocation token.\n if (getCliExecutionContext()) return getTelemetryConsent()\n\n const token = await getCliToken()\n const cacheKey = getTelemetryConsentCacheKey(token)\n\n // NOTE: createExpiringConfig is instantiated on every call, so in-flight request\n // deduplication (via currentFetch) does not work across concurrent calls to\n // fetchTelemetryConsent(). Two concurrent callers will make two HTTP requests.\n // Consider moving to module-level instance if this becomes a bottleneck.\n const telemetryConsentConfig = createExpiringConfig<{\n status: ValidApiConsentStatus\n }>({\n fetchValue: () => getTelemetryConsent(),\n key: cacheKey,\n onCacheHit() {\n telemetryDebug('Retrieved telemetry consent status from cache')\n },\n onFetch() {\n telemetryDebug('Fetching telemetry consent status...')\n },\n onRevalidate() {\n telemetryDebug('Revalidating cached telemetry consent status...')\n },\n store: getUserConfig(),\n ttl: FIVE_MINUTES,\n validateValue: isValidApiConsentResponse,\n })\n\n return telemetryConsentConfig.get()\n}\n"],"names":["createHash","getCliToken","getGlobalCliClient","getUserConfig","getCliExecutionContext","telemetryDebug","createExpiringConfig","TELEMETRY_API_VERSION","VALID_API_STATUSES","sendEvents","batch","client","apiVersion","requireUser","projectId","process","env","SANITY_TELEMETRY_PROJECT_ID","request","body","json","method","uri","getTelemetryConsent","tag","isValidApiConsentStatus","status","includes","isValidApiConsentResponse","response","TELEMETRY_CONSENT_CONFIG_KEY","FIVE_MINUTES","getTelemetryConsentCacheKey","token","hash","update","digest","slice","fetchTelemetryConsent","cacheKey","telemetryConsentConfig","fetchValue","key","onCacheHit","onFetch","onRevalidate","store","ttl","validateValue","get"],"mappings":"AAAA,SAAQA,UAAU,QAAO,cAAa;AAEtC,SAAQC,WAAW,EAAEC,kBAAkB,EAAEC,aAAa,QAAO,mBAAkB;AAC/E,SAAQC,sBAAsB,QAAO,oCAAmC;AAGxE,SAAQC,cAAc,QAAO,yCAAwC;AACrE,SAAQC,oBAAoB,QAAO,kCAAiC;AAEpE,OAAO,MAAMC,wBAAwB,cAAa;AAElD,OAAO,MAAMC,qBAAqB;IAAC;IAAW;IAAU;CAAQ,CAAS;AAGzE,OAAO,eAAeC,WAAWC,KAAuB;IACtD,MAAMC,SAAS,MAAMT,mBAAmB;QACtCU,YAAYL;QACZM,aAAa;IACf;IAEA,MAAMC,YAAYC,QAAQC,GAAG,CAACC,2BAA2B;IAEzD,OAAON,OAAOO,OAAO,CAAC;QACpBC,MAAM;YAACT;YAAOI;QAAS;QACvBM,MAAM;QACNC,QAAQ;QACRC,KAAK;IACP;AACF;AAEA,eAAeC;IAGb,MAAMZ,SAAS,MAAMT,mBAAmB;QACtCU,YAAYL;QACZM,aAAa;IACf;IAEA,OAAOF,OAAOO,OAAO,CAAC;QAACM,KAAK;QAAqBF,KAAK;IAA0B;AAClF;AAEA;;;;;;CAMC,GACD,OAAO,SAASG,wBAAwBC,MAAc;IACpD,OAAOlB,mBAAmBmB,QAAQ,CAACD;AACrC;AAEA;;;;;;CAMC,GACD,SAASE,0BAA0BC,QAAiB;IAClD,OACE,OAAOA,aAAa,YACpBA,aAAa,QACb,YAAYA,YACZ,OAAOA,SAASH,MAAM,KAAK,YAC3BD,wBAAwBI,SAASH,MAAM;AAE3C;AAEA,OAAO,MAAMI,+BAA+B,mBAAkB;AAC9D,MAAMC,eAAe,OAAO,KAAK;AAEjC;;;;;;;CAOC,GACD,OAAO,SAASC,4BAA4BC,KAAyB;IACnE,IAAI,CAACA,OAAO;QACV,OAAOH;IACT;IAEA,MAAMI,OAAOlC,WAAW,UAAUmC,MAAM,CAACF,OAAOG,MAAM,CAAC,OAAOC,KAAK,CAAC,GAAG;IACvE,OAAO,GAAGP,6BAA6B,CAAC,EAAEI,MAAM;AAClD;AAEA;;;;;CAKC,GACD,OAAO,eAAeI;IAGpB,4EAA4E;IAC5E,yEAAyE;IACzE,IAAIlC,0BAA0B,OAAOmB;IAErC,MAAMU,QAAQ,MAAMhC;IACpB,MAAMsC,WAAWP,4BAA4BC;IAE7C,iFAAiF;IACjF,4EAA4E;IAC5E,+EAA+E;IAC/E,yEAAyE;IACzE,MAAMO,yBAAyBlC,qBAE5B;QACDmC,YAAY,IAAMlB;QAClBmB,KAAKH;QACLI;YACEtC,eAAe;QACjB;QACAuC;YACEvC,eAAe;QACjB;QACAwC;YACExC,eAAe;QACjB;QACAyC,OAAO3C;QACP4C,KAAKhB;QACLiB,eAAepB;IACjB;IAEA,OAAOY,uBAAuBS,GAAG;AACnC"}
1
+ {"version":3,"sources":["../../src/services/telemetry.ts"],"sourcesContent":["import {createHash} from 'node:crypto'\n\nimport {getCliToken, getGlobalCliClient, getUserConfig} from '@sanity/cli-core'\nimport {getCliExecutionContext} from '@sanity/cli-core/executionContext'\nimport {type TelemetryEvent} from '@sanity/telemetry'\n\nimport {telemetryDebug} from '../actions/telemetry/telemetryDebug.js'\nimport {createExpiringConfig} from '../util/createExpiringConfig.js'\n\nexport const TELEMETRY_API_VERSION = 'v2026-01-22'\n\nexport const VALID_API_STATUSES = ['granted', 'denied', 'unset'] as const\nexport type ValidApiConsentStatus = (typeof VALID_API_STATUSES)[number]\n\nexport async function sendEvents(batch: TelemetryEvent[]) {\n const client = await getGlobalCliClient({\n apiVersion: TELEMETRY_API_VERSION,\n requireUser: true,\n })\n\n const projectId = process.env.SANITY_TELEMETRY_PROJECT_ID\n\n return client.request({\n body: {batch, projectId},\n json: true,\n method: 'POST',\n url: '/intake/batch',\n })\n}\n\nasync function getTelemetryConsent(): Promise<{\n status: ValidApiConsentStatus\n}> {\n const client = await getGlobalCliClient({\n apiVersion: TELEMETRY_API_VERSION,\n requireUser: false,\n })\n\n return client.request({tag: 'telemetry-consent', url: '/intake/telemetry-status'})\n}\n\n/**\n * Check if the given status is a valid consent status\n *\n * @param status - The status to check\n * @returns True if the status is valid, false otherwise\n * @internal\n */\nexport function isValidApiConsentStatus(status: string): status is ValidApiConsentStatus {\n return VALID_API_STATUSES.includes(status as ValidApiConsentStatus)\n}\n\n/**\n * Check if the given response is a valid API consent response\n *\n * @param response - The response to check\n * @returns True if the response is valid, false otherwise\n * @internal\n */\nfunction isValidApiConsentResponse(response: unknown): response is {status: ValidApiConsentStatus} {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'status' in response &&\n typeof response.status === 'string' &&\n isValidApiConsentStatus(response.status)\n )\n}\n\nexport const TELEMETRY_CONSENT_CONFIG_KEY = 'telemetryConsent'\nconst FIVE_MINUTES = 1000 * 60 * 5\n\n/**\n * Get a token-scoped cache key for telemetry consent. This ensures that switching\n * users (via login/logout) always results in a cache miss, preventing one user\n * from inheriting another user's cached consent status.\n *\n * @param token - The current auth token, or undefined if not logged in\n * @returns A cache key scoped to the token\n */\nexport function getTelemetryConsentCacheKey(token: string | undefined): string {\n if (!token) {\n return TELEMETRY_CONSENT_CONFIG_KEY\n }\n\n const hash = createHash('sha256').update(token).digest('hex').slice(0, 12)\n return `${TELEMETRY_CONSENT_CONFIG_KEY}:${hash}`\n}\n\n/**\n * Fetch the telemetry consent status for the current user\n * @returns The telemetry consent status\n *\n * @internal\n */\nexport async function fetchTelemetryConsent(): Promise<{\n status: ValidApiConsentStatus\n}> {\n // Programmatic invocations must not use the host user's disk-backed consent\n // cache. The request is already authenticated with the invocation token.\n if (getCliExecutionContext()) return getTelemetryConsent()\n\n const token = await getCliToken()\n const cacheKey = getTelemetryConsentCacheKey(token)\n\n // NOTE: createExpiringConfig is instantiated on every call, so in-flight request\n // deduplication (via currentFetch) does not work across concurrent calls to\n // fetchTelemetryConsent(). Two concurrent callers will make two HTTP requests.\n // Consider moving to module-level instance if this becomes a bottleneck.\n const telemetryConsentConfig = createExpiringConfig<{\n status: ValidApiConsentStatus\n }>({\n fetchValue: () => getTelemetryConsent(),\n key: cacheKey,\n onCacheHit() {\n telemetryDebug('Retrieved telemetry consent status from cache')\n },\n onFetch() {\n telemetryDebug('Fetching telemetry consent status...')\n },\n onRevalidate() {\n telemetryDebug('Revalidating cached telemetry consent status...')\n },\n store: getUserConfig(),\n ttl: FIVE_MINUTES,\n validateValue: isValidApiConsentResponse,\n })\n\n return telemetryConsentConfig.get()\n}\n"],"names":["createHash","getCliToken","getGlobalCliClient","getUserConfig","getCliExecutionContext","telemetryDebug","createExpiringConfig","TELEMETRY_API_VERSION","VALID_API_STATUSES","sendEvents","batch","client","apiVersion","requireUser","projectId","process","env","SANITY_TELEMETRY_PROJECT_ID","request","body","json","method","url","getTelemetryConsent","tag","isValidApiConsentStatus","status","includes","isValidApiConsentResponse","response","TELEMETRY_CONSENT_CONFIG_KEY","FIVE_MINUTES","getTelemetryConsentCacheKey","token","hash","update","digest","slice","fetchTelemetryConsent","cacheKey","telemetryConsentConfig","fetchValue","key","onCacheHit","onFetch","onRevalidate","store","ttl","validateValue","get"],"mappings":"AAAA,SAAQA,UAAU,QAAO,cAAa;AAEtC,SAAQC,WAAW,EAAEC,kBAAkB,EAAEC,aAAa,QAAO,mBAAkB;AAC/E,SAAQC,sBAAsB,QAAO,oCAAmC;AAGxE,SAAQC,cAAc,QAAO,yCAAwC;AACrE,SAAQC,oBAAoB,QAAO,kCAAiC;AAEpE,OAAO,MAAMC,wBAAwB,cAAa;AAElD,OAAO,MAAMC,qBAAqB;IAAC;IAAW;IAAU;CAAQ,CAAS;AAGzE,OAAO,eAAeC,WAAWC,KAAuB;IACtD,MAAMC,SAAS,MAAMT,mBAAmB;QACtCU,YAAYL;QACZM,aAAa;IACf;IAEA,MAAMC,YAAYC,QAAQC,GAAG,CAACC,2BAA2B;IAEzD,OAAON,OAAOO,OAAO,CAAC;QACpBC,MAAM;YAACT;YAAOI;QAAS;QACvBM,MAAM;QACNC,QAAQ;QACRC,KAAK;IACP;AACF;AAEA,eAAeC;IAGb,MAAMZ,SAAS,MAAMT,mBAAmB;QACtCU,YAAYL;QACZM,aAAa;IACf;IAEA,OAAOF,OAAOO,OAAO,CAAC;QAACM,KAAK;QAAqBF,KAAK;IAA0B;AAClF;AAEA;;;;;;CAMC,GACD,OAAO,SAASG,wBAAwBC,MAAc;IACpD,OAAOlB,mBAAmBmB,QAAQ,CAACD;AACrC;AAEA;;;;;;CAMC,GACD,SAASE,0BAA0BC,QAAiB;IAClD,OACE,OAAOA,aAAa,YACpBA,aAAa,QACb,YAAYA,YACZ,OAAOA,SAASH,MAAM,KAAK,YAC3BD,wBAAwBI,SAASH,MAAM;AAE3C;AAEA,OAAO,MAAMI,+BAA+B,mBAAkB;AAC9D,MAAMC,eAAe,OAAO,KAAK;AAEjC;;;;;;;CAOC,GACD,OAAO,SAASC,4BAA4BC,KAAyB;IACnE,IAAI,CAACA,OAAO;QACV,OAAOH;IACT;IAEA,MAAMI,OAAOlC,WAAW,UAAUmC,MAAM,CAACF,OAAOG,MAAM,CAAC,OAAOC,KAAK,CAAC,GAAG;IACvE,OAAO,GAAGP,6BAA6B,CAAC,EAAEI,MAAM;AAClD;AAEA;;;;;CAKC,GACD,OAAO,eAAeI;IAGpB,4EAA4E;IAC5E,yEAAyE;IACzE,IAAIlC,0BAA0B,OAAOmB;IAErC,MAAMU,QAAQ,MAAMhC;IACpB,MAAMsC,WAAWP,4BAA4BC;IAE7C,iFAAiF;IACjF,4EAA4E;IAC5E,+EAA+E;IAC/E,yEAAyE;IACzE,MAAMO,yBAAyBlC,qBAE5B;QACDmC,YAAY,IAAMlB;QAClBmB,KAAKH;QACLI;YACEtC,eAAe;QACjB;QACAuC;YACEvC,eAAe;QACjB;QACAwC;YACExC,eAAe;QACjB;QACAyC,OAAO3C;QACP4C,KAAKhB;QACLiB,eAAepB;IACjB;IAEA,OAAOY,uBAAuBS,GAAG;AACnC"}
@@ -9,7 +9,7 @@ function getClient(token) {
9
9
  }
10
10
  });
11
11
  }
12
- async function fetchAllPages(client, uri) {
12
+ async function fetchAllPages(client, url) {
13
13
  const items = [];
14
14
  let cursor = null;
15
15
  do {
@@ -17,7 +17,7 @@ async function fetchAllPages(client, uri) {
17
17
  query: cursor === null ? {} : {
18
18
  nextCursor: cursor
19
19
  },
20
- uri
20
+ url
21
21
  });
22
22
  items.push(...response.data);
23
23
  cursor = response.nextCursor;
@@ -63,7 +63,7 @@ async function fetchAllPages(client, uri) {
63
63
  query: sendNotification === false ? {
64
64
  sendNotification: 'false'
65
65
  } : {},
66
- uri: `/access/project/${projectId}/robots`
66
+ url: `/access/project/${projectId}/robots`
67
67
  });
68
68
  }
69
69
  /**
@@ -78,7 +78,7 @@ async function fetchAllPages(client, uri) {
78
78
  const client = await getClient();
79
79
  return client.request({
80
80
  method: 'DELETE',
81
- uri: `/access/project/${projectId}/robots/${tokenId}`
81
+ url: `/access/project/${projectId}/robots/${tokenId}`
82
82
  });
83
83
  }
84
84
  /**
@@ -93,7 +93,7 @@ async function fetchAllPages(client, uri) {
93
93
  const client = await getClient(token);
94
94
  return client.request({
95
95
  method: 'POST',
96
- uri: '/access/robots/me/rotate'
96
+ url: '/access/robots/me/rotate'
97
97
  });
98
98
  }
99
99
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/tokens.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\nimport {type SanityClient} from '@sanity/client'\n\nimport {TOKENS_API_VERSION} from '../actions/tokens/constants.js'\nimport {\n type Membership,\n type Robot,\n type RobotWithToken,\n type Role,\n} from '../actions/tokens/types.js'\n\ninterface PaginatedResponse<T> {\n data: T[]\n nextCursor: string | null\n}\n\nfunction getClient(token?: string): Promise<SanityClient> {\n return getGlobalCliClient({\n apiVersion: TOKENS_API_VERSION,\n requireUser: true,\n ...(token === undefined ? {} : {token}),\n })\n}\n\nasync function fetchAllPages<T>(client: SanityClient, uri: string): Promise<T[]> {\n const items: T[] = []\n let cursor: string | null = null\n\n do {\n const response: PaginatedResponse<T> = await client.request<PaginatedResponse<T>>({\n query: cursor === null ? {} : {nextCursor: cursor},\n uri,\n })\n items.push(...response.data)\n cursor = response.nextCursor\n } while (cursor !== null)\n\n return items\n}\n\n/**\n * Get the membership granting a robot access to the given project\n * @param robot - The robot to inspect\n * @param projectId - The project ID\n * @returns The project membership, if any\n *\n * @internal\n */\nexport function getProjectMembership(robot: Robot, projectId: string): Membership | undefined {\n return robot.memberships.find(\n (membership) => membership.resourceType === 'project' && membership.resourceId === projectId,\n )\n}\n\ninterface CreateTokenOptions {\n label: string\n projectId: string\n roleName: string\n\n expiresAt?: string\n sendNotification?: boolean\n}\n\n/**\n * Add a token to a project\n * @param options - The options for adding a token to a project\n * @returns A promise that resolves to the created robot, including its secret token\n *\n * @internal\n */\nexport async function createToken(options: CreateTokenOptions): Promise<RobotWithToken> {\n const {expiresAt, label, projectId, roleName, sendNotification} = options\n\n const client = await getClient()\n\n return client.request<RobotWithToken>({\n body: {\n label,\n memberships: [{resourceId: projectId, resourceType: 'project', roleNames: [roleName]}],\n ...(expiresAt === undefined ? {} : {expiresAt}),\n },\n method: 'POST',\n query: sendNotification === false ? {sendNotification: 'false'} : {},\n uri: `/access/project/${projectId}/robots`,\n })\n}\n\ninterface DeleteTokenOptions {\n projectId: string\n tokenId: string\n}\n\n/**\n * Delete a token from a project\n * @param options - The options for deleting a token from a project; `tokenId`\n * is the id reported by `getTokens`/`createToken`\n * @returns A promise that resolves when the token is deleted\n *\n * @internal\n */\nexport async function deleteToken(options: DeleteTokenOptions): Promise<void> {\n const {projectId, tokenId} = options\n\n const client = await getClient()\n\n return client.request({\n method: 'DELETE',\n uri: `/access/project/${projectId}/robots/${tokenId}`,\n })\n}\n\n/**\n * Rotate a robot token, replacing its secret while preserving the robot,\n * its roles, and the token's expiry. The request authenticates as the robot\n * itself; the previous secret is revoked immediately.\n * @param token - The current robot token secret\n * @returns A promise that resolves to the robot with its new secret token\n *\n * @internal\n */\nexport async function rotateToken(token: string): Promise<RobotWithToken> {\n const client = await getClient(token)\n\n return client.request<RobotWithToken>({\n method: 'POST',\n uri: '/access/robots/me/rotate',\n })\n}\n\n/**\n * Get all tokens for a project. Tokens managed by an organization are\n * excluded: they cannot be managed at the project scope.\n * @param projectId - The project ID\n * @returns A promise that resolves to an array of robots\n *\n * @internal\n */\nexport async function getTokens(projectId: string): Promise<Robot[]> {\n const client = await getClient()\n\n const robots = await fetchAllPages<Robot>(client, `/access/project/${projectId}/robots`)\n\n return robots.filter((robot) => robot.managedBy?.resourceType !== 'organization')\n}\n\n/**\n * Get all roles for a project\n * @param projectId - The project ID\n * @returns A promise that resolves to an array of project roles\n *\n * @internal\n */\nexport async function getTokenRoles(projectId: string): Promise<Role[]> {\n const client = await getClient()\n\n return fetchAllPages<Role>(client, `/access/project/${projectId}/roles`)\n}\n"],"names":["getGlobalCliClient","TOKENS_API_VERSION","getClient","token","apiVersion","requireUser","undefined","fetchAllPages","client","uri","items","cursor","response","request","query","nextCursor","push","data","getProjectMembership","robot","projectId","memberships","find","membership","resourceType","resourceId","createToken","options","expiresAt","label","roleName","sendNotification","body","roleNames","method","deleteToken","tokenId","rotateToken","getTokens","robots","filter","managedBy","getTokenRoles"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,mBAAkB;AAGnD,SAAQC,kBAAkB,QAAO,iCAAgC;AAajE,SAASC,UAAUC,KAAc;IAC/B,OAAOH,mBAAmB;QACxBI,YAAYH;QACZI,aAAa;QACb,GAAIF,UAAUG,YAAY,CAAC,IAAI;YAACH;QAAK,CAAC;IACxC;AACF;AAEA,eAAeI,cAAiBC,MAAoB,EAAEC,GAAW;IAC/D,MAAMC,QAAa,EAAE;IACrB,IAAIC,SAAwB;IAE5B,GAAG;QACD,MAAMC,WAAiC,MAAMJ,OAAOK,OAAO,CAAuB;YAChFC,OAAOH,WAAW,OAAO,CAAC,IAAI;gBAACI,YAAYJ;YAAM;YACjDF;QACF;QACAC,MAAMM,IAAI,IAAIJ,SAASK,IAAI;QAC3BN,SAASC,SAASG,UAAU;IAC9B,QAASJ,WAAW,KAAK;IAEzB,OAAOD;AACT;AAEA;;;;;;;CAOC,GACD,OAAO,SAASQ,qBAAqBC,KAAY,EAAEC,SAAiB;IAClE,OAAOD,MAAME,WAAW,CAACC,IAAI,CAC3B,CAACC,aAAeA,WAAWC,YAAY,KAAK,aAAaD,WAAWE,UAAU,KAAKL;AAEvF;AAWA;;;;;;CAMC,GACD,OAAO,eAAeM,YAAYC,OAA2B;IAC3D,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAET,SAAS,EAAEU,QAAQ,EAAEC,gBAAgB,EAAC,GAAGJ;IAElE,MAAMnB,SAAS,MAAMN;IAErB,OAAOM,OAAOK,OAAO,CAAiB;QACpCmB,MAAM;YACJH;YACAR,aAAa;gBAAC;oBAACI,YAAYL;oBAAWI,cAAc;oBAAWS,WAAW;wBAACH;qBAAS;gBAAA;aAAE;YACtF,GAAIF,cAActB,YAAY,CAAC,IAAI;gBAACsB;YAAS,CAAC;QAChD;QACAM,QAAQ;QACRpB,OAAOiB,qBAAqB,QAAQ;YAACA,kBAAkB;QAAO,IAAI,CAAC;QACnEtB,KAAK,CAAC,gBAAgB,EAAEW,UAAU,OAAO,CAAC;IAC5C;AACF;AAOA;;;;;;;CAOC,GACD,OAAO,eAAee,YAAYR,OAA2B;IAC3D,MAAM,EAACP,SAAS,EAAEgB,OAAO,EAAC,GAAGT;IAE7B,MAAMnB,SAAS,MAAMN;IAErB,OAAOM,OAAOK,OAAO,CAAC;QACpBqB,QAAQ;QACRzB,KAAK,CAAC,gBAAgB,EAAEW,UAAU,QAAQ,EAAEgB,SAAS;IACvD;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeC,YAAYlC,KAAa;IAC7C,MAAMK,SAAS,MAAMN,UAAUC;IAE/B,OAAOK,OAAOK,OAAO,CAAiB;QACpCqB,QAAQ;QACRzB,KAAK;IACP;AACF;AAEA;;;;;;;CAOC,GACD,OAAO,eAAe6B,UAAUlB,SAAiB;IAC/C,MAAMZ,SAAS,MAAMN;IAErB,MAAMqC,SAAS,MAAMhC,cAAqBC,QAAQ,CAAC,gBAAgB,EAAEY,UAAU,OAAO,CAAC;IAEvF,OAAOmB,OAAOC,MAAM,CAAC,CAACrB,QAAUA,MAAMsB,SAAS,EAAEjB,iBAAiB;AACpE;AAEA;;;;;;CAMC,GACD,OAAO,eAAekB,cAActB,SAAiB;IACnD,MAAMZ,SAAS,MAAMN;IAErB,OAAOK,cAAoBC,QAAQ,CAAC,gBAAgB,EAAEY,UAAU,MAAM,CAAC;AACzE"}
1
+ {"version":3,"sources":["../../src/services/tokens.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core'\nimport {type SanityClient} from '@sanity/client'\n\nimport {TOKENS_API_VERSION} from '../actions/tokens/constants.js'\nimport {\n type Membership,\n type Robot,\n type RobotWithToken,\n type Role,\n} from '../actions/tokens/types.js'\n\ninterface PaginatedResponse<T> {\n data: T[]\n nextCursor: string | null\n}\n\nfunction getClient(token?: string): Promise<SanityClient> {\n return getGlobalCliClient({\n apiVersion: TOKENS_API_VERSION,\n requireUser: true,\n ...(token === undefined ? {} : {token}),\n })\n}\n\nasync function fetchAllPages<T>(client: SanityClient, url: string): Promise<T[]> {\n const items: T[] = []\n let cursor: string | null = null\n\n do {\n const response: PaginatedResponse<T> = await client.request<PaginatedResponse<T>>({\n query: cursor === null ? {} : {nextCursor: cursor},\n url,\n })\n items.push(...response.data)\n cursor = response.nextCursor\n } while (cursor !== null)\n\n return items\n}\n\n/**\n * Get the membership granting a robot access to the given project\n * @param robot - The robot to inspect\n * @param projectId - The project ID\n * @returns The project membership, if any\n *\n * @internal\n */\nexport function getProjectMembership(robot: Robot, projectId: string): Membership | undefined {\n return robot.memberships.find(\n (membership) => membership.resourceType === 'project' && membership.resourceId === projectId,\n )\n}\n\ninterface CreateTokenOptions {\n label: string\n projectId: string\n roleName: string\n\n expiresAt?: string\n sendNotification?: boolean\n}\n\n/**\n * Add a token to a project\n * @param options - The options for adding a token to a project\n * @returns A promise that resolves to the created robot, including its secret token\n *\n * @internal\n */\nexport async function createToken(options: CreateTokenOptions): Promise<RobotWithToken> {\n const {expiresAt, label, projectId, roleName, sendNotification} = options\n\n const client = await getClient()\n\n return client.request<RobotWithToken>({\n body: {\n label,\n memberships: [{resourceId: projectId, resourceType: 'project', roleNames: [roleName]}],\n ...(expiresAt === undefined ? {} : {expiresAt}),\n },\n method: 'POST',\n query: sendNotification === false ? {sendNotification: 'false'} : {},\n url: `/access/project/${projectId}/robots`,\n })\n}\n\ninterface DeleteTokenOptions {\n projectId: string\n tokenId: string\n}\n\n/**\n * Delete a token from a project\n * @param options - The options for deleting a token from a project; `tokenId`\n * is the id reported by `getTokens`/`createToken`\n * @returns A promise that resolves when the token is deleted\n *\n * @internal\n */\nexport async function deleteToken(options: DeleteTokenOptions): Promise<void> {\n const {projectId, tokenId} = options\n\n const client = await getClient()\n\n return client.request({\n method: 'DELETE',\n url: `/access/project/${projectId}/robots/${tokenId}`,\n })\n}\n\n/**\n * Rotate a robot token, replacing its secret while preserving the robot,\n * its roles, and the token's expiry. The request authenticates as the robot\n * itself; the previous secret is revoked immediately.\n * @param token - The current robot token secret\n * @returns A promise that resolves to the robot with its new secret token\n *\n * @internal\n */\nexport async function rotateToken(token: string): Promise<RobotWithToken> {\n const client = await getClient(token)\n\n return client.request<RobotWithToken>({\n method: 'POST',\n url: '/access/robots/me/rotate',\n })\n}\n\n/**\n * Get all tokens for a project. Tokens managed by an organization are\n * excluded: they cannot be managed at the project scope.\n * @param projectId - The project ID\n * @returns A promise that resolves to an array of robots\n *\n * @internal\n */\nexport async function getTokens(projectId: string): Promise<Robot[]> {\n const client = await getClient()\n\n const robots = await fetchAllPages<Robot>(client, `/access/project/${projectId}/robots`)\n\n return robots.filter((robot) => robot.managedBy?.resourceType !== 'organization')\n}\n\n/**\n * Get all roles for a project\n * @param projectId - The project ID\n * @returns A promise that resolves to an array of project roles\n *\n * @internal\n */\nexport async function getTokenRoles(projectId: string): Promise<Role[]> {\n const client = await getClient()\n\n return fetchAllPages<Role>(client, `/access/project/${projectId}/roles`)\n}\n"],"names":["getGlobalCliClient","TOKENS_API_VERSION","getClient","token","apiVersion","requireUser","undefined","fetchAllPages","client","url","items","cursor","response","request","query","nextCursor","push","data","getProjectMembership","robot","projectId","memberships","find","membership","resourceType","resourceId","createToken","options","expiresAt","label","roleName","sendNotification","body","roleNames","method","deleteToken","tokenId","rotateToken","getTokens","robots","filter","managedBy","getTokenRoles"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,mBAAkB;AAGnD,SAAQC,kBAAkB,QAAO,iCAAgC;AAajE,SAASC,UAAUC,KAAc;IAC/B,OAAOH,mBAAmB;QACxBI,YAAYH;QACZI,aAAa;QACb,GAAIF,UAAUG,YAAY,CAAC,IAAI;YAACH;QAAK,CAAC;IACxC;AACF;AAEA,eAAeI,cAAiBC,MAAoB,EAAEC,GAAW;IAC/D,MAAMC,QAAa,EAAE;IACrB,IAAIC,SAAwB;IAE5B,GAAG;QACD,MAAMC,WAAiC,MAAMJ,OAAOK,OAAO,CAAuB;YAChFC,OAAOH,WAAW,OAAO,CAAC,IAAI;gBAACI,YAAYJ;YAAM;YACjDF;QACF;QACAC,MAAMM,IAAI,IAAIJ,SAASK,IAAI;QAC3BN,SAASC,SAASG,UAAU;IAC9B,QAASJ,WAAW,KAAK;IAEzB,OAAOD;AACT;AAEA;;;;;;;CAOC,GACD,OAAO,SAASQ,qBAAqBC,KAAY,EAAEC,SAAiB;IAClE,OAAOD,MAAME,WAAW,CAACC,IAAI,CAC3B,CAACC,aAAeA,WAAWC,YAAY,KAAK,aAAaD,WAAWE,UAAU,KAAKL;AAEvF;AAWA;;;;;;CAMC,GACD,OAAO,eAAeM,YAAYC,OAA2B;IAC3D,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAET,SAAS,EAAEU,QAAQ,EAAEC,gBAAgB,EAAC,GAAGJ;IAElE,MAAMnB,SAAS,MAAMN;IAErB,OAAOM,OAAOK,OAAO,CAAiB;QACpCmB,MAAM;YACJH;YACAR,aAAa;gBAAC;oBAACI,YAAYL;oBAAWI,cAAc;oBAAWS,WAAW;wBAACH;qBAAS;gBAAA;aAAE;YACtF,GAAIF,cAActB,YAAY,CAAC,IAAI;gBAACsB;YAAS,CAAC;QAChD;QACAM,QAAQ;QACRpB,OAAOiB,qBAAqB,QAAQ;YAACA,kBAAkB;QAAO,IAAI,CAAC;QACnEtB,KAAK,CAAC,gBAAgB,EAAEW,UAAU,OAAO,CAAC;IAC5C;AACF;AAOA;;;;;;;CAOC,GACD,OAAO,eAAee,YAAYR,OAA2B;IAC3D,MAAM,EAACP,SAAS,EAAEgB,OAAO,EAAC,GAAGT;IAE7B,MAAMnB,SAAS,MAAMN;IAErB,OAAOM,OAAOK,OAAO,CAAC;QACpBqB,QAAQ;QACRzB,KAAK,CAAC,gBAAgB,EAAEW,UAAU,QAAQ,EAAEgB,SAAS;IACvD;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeC,YAAYlC,KAAa;IAC7C,MAAMK,SAAS,MAAMN,UAAUC;IAE/B,OAAOK,OAAOK,OAAO,CAAiB;QACpCqB,QAAQ;QACRzB,KAAK;IACP;AACF;AAEA;;;;;;;CAOC,GACD,OAAO,eAAe6B,UAAUlB,SAAiB;IAC/C,MAAMZ,SAAS,MAAMN;IAErB,MAAMqC,SAAS,MAAMhC,cAAqBC,QAAQ,CAAC,gBAAgB,EAAEY,UAAU,OAAO,CAAC;IAEvF,OAAOmB,OAAOC,MAAM,CAAC,CAACrB,QAAUA,MAAMsB,SAAS,EAAEjB,iBAAiB;AACpE;AAEA;;;;;;CAMC,GACD,OAAO,eAAekB,cAActB,SAAiB;IACnD,MAAMZ,SAAS,MAAMN;IAErB,OAAOK,cAAoBC,QAAQ,CAAC,gBAAgB,EAAEY,UAAU,MAAM,CAAC;AACzE"}
@@ -17,7 +17,7 @@ export async function getMembers(memberIds) {
17
17
  requireUser: true
18
18
  });
19
19
  return client.request({
20
- uri: `/users/${memberIds.join(',')}`
20
+ url: `/users/${memberIds.join(',')}`
21
21
  });
22
22
  }
23
23
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/user.ts"],"sourcesContent":["import {getGlobalCliClient, getProjectCliClient, type SanityOrgUser} from '@sanity/cli-core'\n\nimport {type User} from '../actions/users/types.js'\n\n/**\n * The API version to use for the users list command\n *\n * @internal\n */\nexport const USERS_API_VERSION = 'v2025-08-30'\n\nexport async function getCliUser() {\n const client = await getGlobalCliClient({\n apiVersion: USERS_API_VERSION,\n requireUser: true,\n })\n\n return client.users.getById('me') as unknown as SanityOrgUser\n}\n\nexport async function getMembers(memberIds: string[]) {\n const client = await getGlobalCliClient({\n apiVersion: USERS_API_VERSION,\n requireUser: true,\n })\n\n return client.request<User | User[]>({uri: `/users/${memberIds.join(',')}`})\n}\n\n/**\n * Get the user for a project\n * @param projectId - The ID of the project\n */\nexport async function getProjectUser(projectId: string) {\n const client = await getProjectCliClient({\n apiVersion: USERS_API_VERSION,\n projectId,\n requireUser: true,\n })\n\n return client.users.getById('me')\n}\n"],"names":["getGlobalCliClient","getProjectCliClient","USERS_API_VERSION","getCliUser","client","apiVersion","requireUser","users","getById","getMembers","memberIds","request","uri","join","getProjectUser","projectId"],"mappings":"AAAA,SAAQA,kBAAkB,EAAEC,mBAAmB,QAA2B,mBAAkB;AAI5F;;;;CAIC,GACD,OAAO,MAAMC,oBAAoB,cAAa;AAE9C,OAAO,eAAeC;IACpB,MAAMC,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYH;QACZI,aAAa;IACf;IAEA,OAAOF,OAAOG,KAAK,CAACC,OAAO,CAAC;AAC9B;AAEA,OAAO,eAAeC,WAAWC,SAAmB;IAClD,MAAMN,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYH;QACZI,aAAa;IACf;IAEA,OAAOF,OAAOO,OAAO,CAAgB;QAACC,KAAK,CAAC,OAAO,EAAEF,UAAUG,IAAI,CAAC,MAAM;IAAA;AAC5E;AAEA;;;CAGC,GACD,OAAO,eAAeC,eAAeC,SAAiB;IACpD,MAAMX,SAAS,MAAMH,oBAAoB;QACvCI,YAAYH;QACZa;QACAT,aAAa;IACf;IAEA,OAAOF,OAAOG,KAAK,CAACC,OAAO,CAAC;AAC9B"}
1
+ {"version":3,"sources":["../../src/services/user.ts"],"sourcesContent":["import {getGlobalCliClient, getProjectCliClient, type SanityOrgUser} from '@sanity/cli-core'\n\nimport {type User} from '../actions/users/types.js'\n\n/**\n * The API version to use for the users list command\n *\n * @internal\n */\nexport const USERS_API_VERSION = 'v2025-08-30'\n\nexport async function getCliUser() {\n const client = await getGlobalCliClient({\n apiVersion: USERS_API_VERSION,\n requireUser: true,\n })\n\n return client.users.getById('me') as unknown as SanityOrgUser\n}\n\nexport async function getMembers(memberIds: string[]) {\n const client = await getGlobalCliClient({\n apiVersion: USERS_API_VERSION,\n requireUser: true,\n })\n\n return client.request<User | User[]>({url: `/users/${memberIds.join(',')}`})\n}\n\n/**\n * Get the user for a project\n * @param projectId - The ID of the project\n */\nexport async function getProjectUser(projectId: string) {\n const client = await getProjectCliClient({\n apiVersion: USERS_API_VERSION,\n projectId,\n requireUser: true,\n })\n\n return client.users.getById('me')\n}\n"],"names":["getGlobalCliClient","getProjectCliClient","USERS_API_VERSION","getCliUser","client","apiVersion","requireUser","users","getById","getMembers","memberIds","request","url","join","getProjectUser","projectId"],"mappings":"AAAA,SAAQA,kBAAkB,EAAEC,mBAAmB,QAA2B,mBAAkB;AAI5F;;;;CAIC,GACD,OAAO,MAAMC,oBAAoB,cAAa;AAE9C,OAAO,eAAeC;IACpB,MAAMC,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYH;QACZI,aAAa;IACf;IAEA,OAAOF,OAAOG,KAAK,CAACC,OAAO,CAAC;AAC9B;AAEA,OAAO,eAAeC,WAAWC,SAAmB;IAClD,MAAMN,SAAS,MAAMJ,mBAAmB;QACtCK,YAAYH;QACZI,aAAa;IACf;IAEA,OAAOF,OAAOO,OAAO,CAAgB;QAACC,KAAK,CAAC,OAAO,EAAEF,UAAUG,IAAI,CAAC,MAAM;IAAA;AAC5E;AAEA;;;CAGC,GACD,OAAO,eAAeC,eAAeC,SAAiB;IACpD,MAAMX,SAAS,MAAMH,oBAAoB;QACvCI,YAAYH;QACZa;QACAT,aAAa;IACf;IAEA,OAAOF,OAAOG,KAAK,CAACC,OAAO,CAAC;AAC9B"}
@@ -4,12 +4,12 @@ import FormData from 'form-data';
4
4
  export const USER_APPLICATIONS_API_VERSION = 'v2024-08-01';
5
5
  export async function getUserApplication({ appHost, appId, isSdkApp, projectId }) {
6
6
  let query;
7
- let uri;
8
- // set the uri
7
+ let url;
8
+ // set the url
9
9
  if (isSdkApp) {
10
- uri = appId ? `/user-applications/${appId}` : '/user-applications';
10
+ url = appId ? `/user-applications/${appId}` : '/user-applications';
11
11
  } else {
12
- uri = appId ? `/projects/${projectId}/user-applications/${appId}` : `/projects/${projectId}/user-applications`;
12
+ url = appId ? `/projects/${projectId}/user-applications/${appId}` : `/projects/${projectId}/user-applications`;
13
13
  }
14
14
  // set the query
15
15
  if (isSdkApp) {
@@ -33,9 +33,9 @@ export async function getUserApplication({ appHost, appId, isSdkApp, projectId }
33
33
  try {
34
34
  const options = query ? {
35
35
  query,
36
- uri
36
+ url
37
37
  } : {
38
- uri
38
+ url
39
39
  };
40
40
  return await client.request(options);
41
41
  } catch (err) {
@@ -56,7 +56,7 @@ export async function deleteUserApplication({ applicationId, appType }) {
56
56
  query: {
57
57
  appType
58
58
  },
59
- uri: `/user-applications/${applicationId}`
59
+ url: `/user-applications/${applicationId}`
60
60
  });
61
61
  }
62
62
  export async function updateUserApplication({ applicationId, appType, body }) {
@@ -70,7 +70,7 @@ export async function updateUserApplication({ applicationId, appType, body }) {
70
70
  query: {
71
71
  appType
72
72
  },
73
- uri: `/user-applications/${applicationId}`
73
+ url: `/user-applications/${applicationId}`
74
74
  });
75
75
  }
76
76
  export async function getUserApplications(options) {
@@ -85,7 +85,7 @@ export async function getUserApplications(options) {
85
85
  query: {
86
86
  appType: 'studio'
87
87
  },
88
- uri: `/projects/${projectId}/user-applications`
88
+ url: `/projects/${projectId}/user-applications`
89
89
  });
90
90
  }
91
91
  const { organizationId } = options;
@@ -95,7 +95,7 @@ export async function getUserApplications(options) {
95
95
  appType: 'coreApp',
96
96
  organizationId: organizationId
97
97
  },
98
- uri: `/user-applications`
98
+ url: `/user-applications`
99
99
  });
100
100
  } catch (error) {
101
101
  // User doesn't have permission to view applications for the org,
@@ -113,19 +113,19 @@ export async function createUserApplication(options) {
113
113
  apiVersion: USER_APPLICATIONS_API_VERSION,
114
114
  requireUser: true
115
115
  });
116
- let uri;
116
+ let url;
117
117
  let query;
118
118
  // If we have an organizationId, we're creating a core app
119
119
  if (appType === 'coreApp') {
120
120
  const { organizationId } = options;
121
- uri = '/user-applications';
121
+ url = '/user-applications';
122
122
  query = {
123
123
  appType: 'coreApp',
124
124
  organizationId: organizationId
125
125
  };
126
126
  } else {
127
127
  const { projectId } = options;
128
- uri = `/projects/${projectId}/user-applications`;
128
+ url = `/projects/${projectId}/user-applications`;
129
129
  query = {
130
130
  appType: 'studio'
131
131
  };
@@ -134,7 +134,7 @@ export async function createUserApplication(options) {
134
134
  body,
135
135
  method: 'POST',
136
136
  query,
137
- uri
137
+ url
138
138
  });
139
139
  }
140
140
  export async function createDeployment({ applicationId, isApp, isAutoUpdating, manifest, projectId, tarball, version }) {
@@ -154,15 +154,15 @@ export async function createDeployment({ applicationId, isApp, isAutoUpdating, m
154
154
  filename: 'app.tar.gz'
155
155
  });
156
156
  }
157
- let uri;
157
+ let url;
158
158
  let query;
159
159
  if (isApp) {
160
- uri = `/user-applications/${applicationId}/deployments`;
160
+ url = `/user-applications/${applicationId}/deployments`;
161
161
  query = {
162
162
  appType: 'coreApp'
163
163
  };
164
164
  } else {
165
- uri = `/projects/${projectId}/user-applications/${applicationId}/deployments`;
165
+ url = `/projects/${projectId}/user-applications/${applicationId}/deployments`;
166
166
  query = {
167
167
  appType: 'studio'
168
168
  };
@@ -172,7 +172,7 @@ export async function createDeployment({ applicationId, isApp, isAutoUpdating, m
172
172
  headers: formData.getHeaders(),
173
173
  method: 'POST',
174
174
  query,
175
- uri
175
+ url
176
176
  });
177
177
  }
178
178
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/userApplications.ts"],"sourcesContent":["import {PassThrough} from 'node:stream'\nimport {type Gzip} from 'node:zlib'\n\nimport {type AppVisibility, debug, getGlobalCliClient} from '@sanity/cli-core'\nimport FormData from 'form-data'\nimport {type StudioManifest} from 'sanity'\n\nimport {type CoreAppManifest} from '../actions/manifest/types.js'\n\nexport const USER_APPLICATIONS_API_VERSION = 'v2024-08-01'\n\ninterface ActiveDeployment {\n createdAt: string\n deployedAt: string\n deployedBy: string\n isActiveDeployment: boolean\n isAutoUpdating: boolean | null\n size: string | null\n updatedAt: string\n version: string\n}\n\nexport interface UserApplication {\n appHost: string\n createdAt: string\n id: string\n organizationId: string | null\n projectId: string | null\n title: string | null\n type: 'coreApp' | 'studio'\n updatedAt: string\n urlType: 'external' | 'internal'\n\n activeDeployment?: ActiveDeployment | null\n /** Dashboard visibility. Defaults to `default` server-side when unset. */\n dashboardStatus?: AppVisibility\n}\n\n/** A core app always belongs to an organization. */\nexport interface UserApplicationResolved extends UserApplication {\n organizationId: string\n type: 'coreApp'\n}\n\ntype GetUserApplicationOptions =\n | {appHost?: never; appId: string; isSdkApp: true; projectId?: never}\n | {appHost?: string; appId?: string; isSdkApp: false; projectId: string}\n\nexport async function getUserApplication(options: {\n appHost?: never\n appId: string\n isSdkApp: true\n projectId?: never\n}): Promise<UserApplicationResolved | null>\nexport async function getUserApplication(options: {\n appHost?: string\n appId?: string\n isSdkApp: false\n projectId: string\n}): Promise<UserApplication | null>\nexport async function getUserApplication({\n appHost,\n appId,\n isSdkApp,\n projectId,\n}: GetUserApplicationOptions): Promise<UserApplication | null> {\n let query: Record<string, string | string[]> | undefined\n let uri: string\n\n // set the uri\n if (isSdkApp) {\n uri = appId ? `/user-applications/${appId}` : '/user-applications'\n } else {\n uri = appId\n ? `/projects/${projectId}/user-applications/${appId}`\n : `/projects/${projectId}/user-applications`\n }\n\n // set the query\n if (isSdkApp) {\n query = {appType: 'coreApp'}\n } else if (!appId) {\n // In practice, this function isn't called if we don't have at least one of appHost or appId,\n // so the default case won't be called. But leaving this ternary in for now (from old CLI code) just in case.\n query = appHost ? {appHost, appType: 'studio'} : {default: 'true'}\n }\n\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n try {\n const options = query ? {query, uri} : {uri}\n return await client.request(options)\n } catch (err) {\n if (err?.statusCode === 404) {\n return null\n }\n\n debug('Error getting user application', err)\n throw err\n }\n}\n\ninterface DeleteUserApplicationOptions {\n applicationId: string\n appType: 'coreApp' | 'studio'\n}\n\nexport async function deleteUserApplication({\n applicationId,\n appType,\n}: DeleteUserApplicationOptions): Promise<void> {\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n await client.request({\n method: 'DELETE',\n query: {appType},\n uri: `/user-applications/${applicationId}`,\n })\n}\n\ninterface UpdateUserApplicationBody {\n dashboardStatus?: AppVisibility\n title?: string\n}\n\ninterface UpdateUserApplicationOptions {\n applicationId: string\n // Updating studio properties requires further UX thought\n // (because of workspaces et al.)\n appType: 'coreApp'\n body: UpdateUserApplicationBody\n}\n\nexport async function updateUserApplication({\n applicationId,\n appType,\n body,\n}: UpdateUserApplicationOptions): Promise<UserApplicationResolved> {\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n return client.request({\n body,\n method: 'PATCH',\n query: {appType},\n uri: `/user-applications/${applicationId}`,\n })\n}\n\nexport async function getUserApplications(options: {\n appType: 'studio'\n projectId: string\n}): Promise<UserApplication[]>\nexport async function getUserApplications(options: {\n appType: 'coreApp'\n organizationId: string\n}): Promise<UserApplicationResolved[]>\nexport async function getUserApplications(\n options:\n | {\n appType: 'coreApp'\n organizationId?: string\n }\n | {\n appType: 'studio'\n projectId?: string\n },\n): Promise<UserApplication[] | null> {\n const {appType} = options\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n if (appType === 'studio') {\n const {projectId} = options as {appType: 'studio'; projectId?: string}\n return await client.request({\n query: {appType: 'studio'},\n uri: `/projects/${projectId}/user-applications`,\n })\n }\n\n const {organizationId} = options as {appType: 'coreApp'; organizationId?: string}\n\n try {\n return await client.request({\n query: {appType: 'coreApp', organizationId: organizationId!},\n uri: `/user-applications`,\n })\n } catch (error) {\n // User doesn't have permission to view applications for the org,\n // or the organization ID doesn’t exist\n if (error?.statusCode === 403) {\n throw error\n }\n\n debug('Error finding user applications', error)\n return null\n }\n}\n\nexport async function createUserApplication(options: {\n appType: 'coreApp'\n body: Pick<UserApplication, 'appHost' | 'type' | 'urlType'> & {\n dashboardStatus?: AppVisibility\n title?: string\n }\n organizationId?: string\n}): Promise<UserApplicationResolved>\nexport async function createUserApplication(options: {\n appType: 'studio'\n body: Pick<UserApplication, 'appHost' | 'type' | 'urlType'> & {\n dashboardStatus?: AppVisibility\n title?: string\n }\n projectId: string\n}): Promise<UserApplication>\nexport async function createUserApplication(options: {\n appType: 'coreApp' | 'studio'\n body: Pick<UserApplication, 'appHost' | 'type' | 'urlType'> & {\n dashboardStatus?: AppVisibility\n title?: string\n }\n organizationId?: string\n projectId?: string\n}): Promise<UserApplication> {\n const {appType, body} = options\n\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n let uri\n let query\n\n // If we have an organizationId, we're creating a core app\n if (appType === 'coreApp') {\n const {organizationId} = options as {appType: 'coreApp'; organizationId?: string}\n uri = '/user-applications'\n query = {appType: 'coreApp', organizationId: organizationId!}\n } else {\n const {projectId} = options as {appType: 'studio'; projectId?: string}\n uri = `/projects/${projectId}/user-applications`\n query = {appType: 'studio'}\n }\n\n return client.request({body, method: 'POST', query, uri})\n}\n\ninterface CreateDeploymentOptions {\n applicationId: string\n isAutoUpdating: boolean\n version: string\n\n isApp?: boolean\n\n manifest?: CoreAppManifest | StudioManifest | null\n\n projectId?: string\n\n tarball?: Gzip\n}\n\nexport async function createDeployment({\n applicationId,\n isApp,\n isAutoUpdating,\n manifest,\n projectId,\n tarball,\n version,\n}: CreateDeploymentOptions): Promise<{location: string}> {\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n const formData = new FormData()\n formData.append('isAutoUpdating', isAutoUpdating.toString())\n formData.append('version', version)\n if (manifest) {\n formData.append('manifest', JSON.stringify(manifest))\n }\n\n if (tarball) {\n formData.append('tarball', tarball, {contentType: 'application/gzip', filename: 'app.tar.gz'})\n }\n\n let uri\n let query\n\n if (isApp) {\n uri = `/user-applications/${applicationId}/deployments`\n query = {appType: 'coreApp'}\n } else {\n uri = `/projects/${projectId}/user-applications/${applicationId}/deployments`\n query = {appType: 'studio'}\n }\n\n return client.request({\n body: formData.pipe(new PassThrough()),\n headers: formData.getHeaders(),\n method: 'POST',\n query,\n uri,\n })\n}\n"],"names":["PassThrough","debug","getGlobalCliClient","FormData","USER_APPLICATIONS_API_VERSION","getUserApplication","appHost","appId","isSdkApp","projectId","query","uri","appType","default","client","apiVersion","requireUser","options","request","err","statusCode","deleteUserApplication","applicationId","method","updateUserApplication","body","getUserApplications","organizationId","error","createUserApplication","createDeployment","isApp","isAutoUpdating","manifest","tarball","version","formData","append","toString","JSON","stringify","contentType","filename","pipe","headers","getHeaders"],"mappings":"AAAA,SAAQA,WAAW,QAAO,cAAa;AAGvC,SAA4BC,KAAK,EAAEC,kBAAkB,QAAO,mBAAkB;AAC9E,OAAOC,cAAc,YAAW;AAKhC,OAAO,MAAMC,gCAAgC,cAAa;AAmD1D,OAAO,eAAeC,mBAAmB,EACvCC,OAAO,EACPC,KAAK,EACLC,QAAQ,EACRC,SAAS,EACiB;IAC1B,IAAIC;IACJ,IAAIC;IAEJ,cAAc;IACd,IAAIH,UAAU;QACZG,MAAMJ,QAAQ,CAAC,mBAAmB,EAAEA,OAAO,GAAG;IAChD,OAAO;QACLI,MAAMJ,QACF,CAAC,UAAU,EAAEE,UAAU,mBAAmB,EAAEF,OAAO,GACnD,CAAC,UAAU,EAAEE,UAAU,kBAAkB,CAAC;IAChD;IAEA,gBAAgB;IAChB,IAAID,UAAU;QACZE,QAAQ;YAACE,SAAS;QAAS;IAC7B,OAAO,IAAI,CAACL,OAAO;QACjB,6FAA6F;QAC7F,6GAA6G;QAC7GG,QAAQJ,UAAU;YAACA;YAASM,SAAS;QAAQ,IAAI;YAACC,SAAS;QAAM;IACnE;IAEA,MAAMC,SAAS,MAAMZ,mBAAmB;QACtCa,YAAYX;QACZY,aAAa;IACf;IAEA,IAAI;QACF,MAAMC,UAAUP,QAAQ;YAACA;YAAOC;QAAG,IAAI;YAACA;QAAG;QAC3C,OAAO,MAAMG,OAAOI,OAAO,CAACD;IAC9B,EAAE,OAAOE,KAAK;QACZ,IAAIA,KAAKC,eAAe,KAAK;YAC3B,OAAO;QACT;QAEAnB,MAAM,kCAAkCkB;QACxC,MAAMA;IACR;AACF;AAOA,OAAO,eAAeE,sBAAsB,EAC1CC,aAAa,EACbV,OAAO,EACsB;IAC7B,MAAME,SAAS,MAAMZ,mBAAmB;QACtCa,YAAYX;QACZY,aAAa;IACf;IAEA,MAAMF,OAAOI,OAAO,CAAC;QACnBK,QAAQ;QACRb,OAAO;YAACE;QAAO;QACfD,KAAK,CAAC,mBAAmB,EAAEW,eAAe;IAC5C;AACF;AAeA,OAAO,eAAeE,sBAAsB,EAC1CF,aAAa,EACbV,OAAO,EACPa,IAAI,EACyB;IAC7B,MAAMX,SAAS,MAAMZ,mBAAmB;QACtCa,YAAYX;QACZY,aAAa;IACf;IAEA,OAAOF,OAAOI,OAAO,CAAC;QACpBO;QACAF,QAAQ;QACRb,OAAO;YAACE;QAAO;QACfD,KAAK,CAAC,mBAAmB,EAAEW,eAAe;IAC5C;AACF;AAUA,OAAO,eAAeI,oBACpBT,OAQK;IAEL,MAAM,EAACL,OAAO,EAAC,GAAGK;IAClB,MAAMH,SAAS,MAAMZ,mBAAmB;QACtCa,YAAYX;QACZY,aAAa;IACf;IAEA,IAAIJ,YAAY,UAAU;QACxB,MAAM,EAACH,SAAS,EAAC,GAAGQ;QACpB,OAAO,MAAMH,OAAOI,OAAO,CAAC;YAC1BR,OAAO;gBAACE,SAAS;YAAQ;YACzBD,KAAK,CAAC,UAAU,EAAEF,UAAU,kBAAkB,CAAC;QACjD;IACF;IAEA,MAAM,EAACkB,cAAc,EAAC,GAAGV;IAEzB,IAAI;QACF,OAAO,MAAMH,OAAOI,OAAO,CAAC;YAC1BR,OAAO;gBAACE,SAAS;gBAAWe,gBAAgBA;YAAe;YAC3DhB,KAAK,CAAC,kBAAkB,CAAC;QAC3B;IACF,EAAE,OAAOiB,OAAO;QACd,iEAAiE;QACjE,uCAAuC;QACvC,IAAIA,OAAOR,eAAe,KAAK;YAC7B,MAAMQ;QACR;QAEA3B,MAAM,mCAAmC2B;QACzC,OAAO;IACT;AACF;AAkBA,OAAO,eAAeC,sBAAsBZ,OAQ3C;IACC,MAAM,EAACL,OAAO,EAAEa,IAAI,EAAC,GAAGR;IAExB,MAAMH,SAAS,MAAMZ,mBAAmB;QACtCa,YAAYX;QACZY,aAAa;IACf;IAEA,IAAIL;IACJ,IAAID;IAEJ,0DAA0D;IAC1D,IAAIE,YAAY,WAAW;QACzB,MAAM,EAACe,cAAc,EAAC,GAAGV;QACzBN,MAAM;QACND,QAAQ;YAACE,SAAS;YAAWe,gBAAgBA;QAAe;IAC9D,OAAO;QACL,MAAM,EAAClB,SAAS,EAAC,GAAGQ;QACpBN,MAAM,CAAC,UAAU,EAAEF,UAAU,kBAAkB,CAAC;QAChDC,QAAQ;YAACE,SAAS;QAAQ;IAC5B;IAEA,OAAOE,OAAOI,OAAO,CAAC;QAACO;QAAMF,QAAQ;QAAQb;QAAOC;IAAG;AACzD;AAgBA,OAAO,eAAemB,iBAAiB,EACrCR,aAAa,EACbS,KAAK,EACLC,cAAc,EACdC,QAAQ,EACRxB,SAAS,EACTyB,OAAO,EACPC,OAAO,EACiB;IACxB,MAAMrB,SAAS,MAAMZ,mBAAmB;QACtCa,YAAYX;QACZY,aAAa;IACf;IAEA,MAAMoB,WAAW,IAAIjC;IACrBiC,SAASC,MAAM,CAAC,kBAAkBL,eAAeM,QAAQ;IACzDF,SAASC,MAAM,CAAC,WAAWF;IAC3B,IAAIF,UAAU;QACZG,SAASC,MAAM,CAAC,YAAYE,KAAKC,SAAS,CAACP;IAC7C;IAEA,IAAIC,SAAS;QACXE,SAASC,MAAM,CAAC,WAAWH,SAAS;YAACO,aAAa;YAAoBC,UAAU;QAAY;IAC9F;IAEA,IAAI/B;IACJ,IAAID;IAEJ,IAAIqB,OAAO;QACTpB,MAAM,CAAC,mBAAmB,EAAEW,cAAc,YAAY,CAAC;QACvDZ,QAAQ;YAACE,SAAS;QAAS;IAC7B,OAAO;QACLD,MAAM,CAAC,UAAU,EAAEF,UAAU,mBAAmB,EAAEa,cAAc,YAAY,CAAC;QAC7EZ,QAAQ;YAACE,SAAS;QAAQ;IAC5B;IAEA,OAAOE,OAAOI,OAAO,CAAC;QACpBO,MAAMW,SAASO,IAAI,CAAC,IAAI3C;QACxB4C,SAASR,SAASS,UAAU;QAC5BtB,QAAQ;QACRb;QACAC;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/services/userApplications.ts"],"sourcesContent":["import {PassThrough} from 'node:stream'\nimport {type Gzip} from 'node:zlib'\n\nimport {type AppVisibility, debug, getGlobalCliClient} from '@sanity/cli-core'\nimport FormData from 'form-data'\nimport {type StudioManifest} from 'sanity'\n\nimport {type CoreAppManifest} from '../actions/manifest/types.js'\n\nexport const USER_APPLICATIONS_API_VERSION = 'v2024-08-01'\n\ninterface ActiveDeployment {\n createdAt: string\n deployedAt: string\n deployedBy: string\n isActiveDeployment: boolean\n isAutoUpdating: boolean | null\n size: string | null\n updatedAt: string\n version: string\n}\n\nexport interface UserApplication {\n appHost: string\n createdAt: string\n id: string\n organizationId: string | null\n projectId: string | null\n title: string | null\n type: 'coreApp' | 'studio'\n updatedAt: string\n urlType: 'external' | 'internal'\n\n activeDeployment?: ActiveDeployment | null\n /** Dashboard visibility. Defaults to `default` server-side when unset. */\n dashboardStatus?: AppVisibility\n}\n\n/** A core app always belongs to an organization. */\nexport interface UserApplicationResolved extends UserApplication {\n organizationId: string\n type: 'coreApp'\n}\n\ntype GetUserApplicationOptions =\n | {appHost?: never; appId: string; isSdkApp: true; projectId?: never}\n | {appHost?: string; appId?: string; isSdkApp: false; projectId: string}\n\nexport async function getUserApplication(options: {\n appHost?: never\n appId: string\n isSdkApp: true\n projectId?: never\n}): Promise<UserApplicationResolved | null>\nexport async function getUserApplication(options: {\n appHost?: string\n appId?: string\n isSdkApp: false\n projectId: string\n}): Promise<UserApplication | null>\nexport async function getUserApplication({\n appHost,\n appId,\n isSdkApp,\n projectId,\n}: GetUserApplicationOptions): Promise<UserApplication | null> {\n let query: Record<string, string | string[]> | undefined\n let url: string\n\n // set the url\n if (isSdkApp) {\n url = appId ? `/user-applications/${appId}` : '/user-applications'\n } else {\n url = appId\n ? `/projects/${projectId}/user-applications/${appId}`\n : `/projects/${projectId}/user-applications`\n }\n\n // set the query\n if (isSdkApp) {\n query = {appType: 'coreApp'}\n } else if (!appId) {\n // In practice, this function isn't called if we don't have at least one of appHost or appId,\n // so the default case won't be called. But leaving this ternary in for now (from old CLI code) just in case.\n query = appHost ? {appHost, appType: 'studio'} : {default: 'true'}\n }\n\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n try {\n const options = query ? {query, url} : {url}\n return await client.request(options)\n } catch (err) {\n if (err?.statusCode === 404) {\n return null\n }\n\n debug('Error getting user application', err)\n throw err\n }\n}\n\ninterface DeleteUserApplicationOptions {\n applicationId: string\n appType: 'coreApp' | 'studio'\n}\n\nexport async function deleteUserApplication({\n applicationId,\n appType,\n}: DeleteUserApplicationOptions): Promise<void> {\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n await client.request({\n method: 'DELETE',\n query: {appType},\n url: `/user-applications/${applicationId}`,\n })\n}\n\ninterface UpdateUserApplicationBody {\n dashboardStatus?: AppVisibility\n title?: string\n}\n\ninterface UpdateUserApplicationOptions {\n applicationId: string\n // Updating studio properties requires further UX thought\n // (because of workspaces et al.)\n appType: 'coreApp'\n body: UpdateUserApplicationBody\n}\n\nexport async function updateUserApplication({\n applicationId,\n appType,\n body,\n}: UpdateUserApplicationOptions): Promise<UserApplicationResolved> {\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n return client.request({\n body,\n method: 'PATCH',\n query: {appType},\n url: `/user-applications/${applicationId}`,\n })\n}\n\nexport async function getUserApplications(options: {\n appType: 'studio'\n projectId: string\n}): Promise<UserApplication[]>\nexport async function getUserApplications(options: {\n appType: 'coreApp'\n organizationId: string\n}): Promise<UserApplicationResolved[]>\nexport async function getUserApplications(\n options:\n | {\n appType: 'coreApp'\n organizationId?: string\n }\n | {\n appType: 'studio'\n projectId?: string\n },\n): Promise<UserApplication[] | null> {\n const {appType} = options\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n if (appType === 'studio') {\n const {projectId} = options as {appType: 'studio'; projectId?: string}\n return await client.request({\n query: {appType: 'studio'},\n url: `/projects/${projectId}/user-applications`,\n })\n }\n\n const {organizationId} = options as {appType: 'coreApp'; organizationId?: string}\n\n try {\n return await client.request({\n query: {appType: 'coreApp', organizationId: organizationId!},\n url: `/user-applications`,\n })\n } catch (error) {\n // User doesn't have permission to view applications for the org,\n // or the organization ID doesn’t exist\n if (error?.statusCode === 403) {\n throw error\n }\n\n debug('Error finding user applications', error)\n return null\n }\n}\n\nexport async function createUserApplication(options: {\n appType: 'coreApp'\n body: Pick<UserApplication, 'appHost' | 'type' | 'urlType'> & {\n dashboardStatus?: AppVisibility\n title?: string\n }\n organizationId?: string\n}): Promise<UserApplicationResolved>\nexport async function createUserApplication(options: {\n appType: 'studio'\n body: Pick<UserApplication, 'appHost' | 'type' | 'urlType'> & {\n dashboardStatus?: AppVisibility\n title?: string\n }\n projectId: string\n}): Promise<UserApplication>\nexport async function createUserApplication(options: {\n appType: 'coreApp' | 'studio'\n body: Pick<UserApplication, 'appHost' | 'type' | 'urlType'> & {\n dashboardStatus?: AppVisibility\n title?: string\n }\n organizationId?: string\n projectId?: string\n}): Promise<UserApplication> {\n const {appType, body} = options\n\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n let url\n let query\n\n // If we have an organizationId, we're creating a core app\n if (appType === 'coreApp') {\n const {organizationId} = options as {appType: 'coreApp'; organizationId?: string}\n url = '/user-applications'\n query = {appType: 'coreApp', organizationId: organizationId!}\n } else {\n const {projectId} = options as {appType: 'studio'; projectId?: string}\n url = `/projects/${projectId}/user-applications`\n query = {appType: 'studio'}\n }\n\n return client.request({body, method: 'POST', query, url})\n}\n\ninterface CreateDeploymentOptions {\n applicationId: string\n isAutoUpdating: boolean\n version: string\n\n isApp?: boolean\n\n manifest?: CoreAppManifest | StudioManifest | null\n\n projectId?: string\n\n tarball?: Gzip\n}\n\nexport async function createDeployment({\n applicationId,\n isApp,\n isAutoUpdating,\n manifest,\n projectId,\n tarball,\n version,\n}: CreateDeploymentOptions): Promise<{location: string}> {\n const client = await getGlobalCliClient({\n apiVersion: USER_APPLICATIONS_API_VERSION,\n requireUser: true,\n })\n\n const formData = new FormData()\n formData.append('isAutoUpdating', isAutoUpdating.toString())\n formData.append('version', version)\n if (manifest) {\n formData.append('manifest', JSON.stringify(manifest))\n }\n\n if (tarball) {\n formData.append('tarball', tarball, {contentType: 'application/gzip', filename: 'app.tar.gz'})\n }\n\n let url\n let query\n\n if (isApp) {\n url = `/user-applications/${applicationId}/deployments`\n query = {appType: 'coreApp'}\n } else {\n url = `/projects/${projectId}/user-applications/${applicationId}/deployments`\n query = {appType: 'studio'}\n }\n\n return client.request({\n body: formData.pipe(new PassThrough()),\n headers: formData.getHeaders(),\n method: 'POST',\n query,\n url,\n })\n}\n"],"names":["PassThrough","debug","getGlobalCliClient","FormData","USER_APPLICATIONS_API_VERSION","getUserApplication","appHost","appId","isSdkApp","projectId","query","url","appType","default","client","apiVersion","requireUser","options","request","err","statusCode","deleteUserApplication","applicationId","method","updateUserApplication","body","getUserApplications","organizationId","error","createUserApplication","createDeployment","isApp","isAutoUpdating","manifest","tarball","version","formData","append","toString","JSON","stringify","contentType","filename","pipe","headers","getHeaders"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { styleText } from 'node:util';
2
+ import { exitCodes } from '@sanity/cli-core';
2
3
  function getDeploymentAppId(cliConfig) {
3
4
  const id = cliConfig?.deployment?.appId;
4
5
  return id;
@@ -33,7 +34,7 @@ function hasDeprecatedAppId(cliConfig) {
33
34
  output.error(`${styleText('bold', 'Found both app.id (deprecated) and deployment.appId in your application configuration.')}
34
35
 
35
36
  Please remove app.id from your sanity.cli.js or sanity.cli.ts file.`, {
36
- exit: 1
37
+ exit: exitCodes.RUNTIME_ERROR
37
38
  });
38
39
  }
39
40
  // Just warn if only the old app ID config is found
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/util/appId.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type CliConfig, type Output} from '@sanity/cli-core'\n\ninterface Options {\n cliConfig: CliConfig\n output: Output\n}\n\nfunction getDeploymentAppId(cliConfig: CliConfig): string | undefined {\n const id = cliConfig?.deployment?.appId\n return id\n}\n\nfunction getDeprecatedAppId(cliConfig: CliConfig): string | undefined {\n const id = cliConfig?.app?.id\n return id\n}\n\nfunction hasNewAppId(cliConfig: CliConfig) {\n return Boolean(getDeploymentAppId(cliConfig))\n}\n\nfunction hasDeprecatedAppId(cliConfig: CliConfig) {\n return Boolean(getDeprecatedAppId(cliConfig))\n}\n\n/** The one app-id configuration problem to surface, if any. */\nexport type AppIdIssue = 'conflicting-config' | 'deprecated-config'\n\n/**\n * Decides which app-id problem a config has: both the deprecated `app.id` and\n * `deployment.appId` (a conflict), only the deprecated one, or neither. Shared\n * so the real deploy and the dry-run check reach the same verdict.\n * @internal\n */\nexport function resolveAppIdIssue(cliConfig: CliConfig): AppIdIssue | null {\n if (!hasDeprecatedAppId(cliConfig)) return null\n return hasNewAppId(cliConfig) ? 'conflicting-config' : 'deprecated-config'\n}\n\n/**\n * Checks if an SDK app uses the deprecated app.id config & throws a warning if so.\n * @remarks Throws an error if an app uses both deployment.appId and app.id\n * @internal\n */\nexport function checkForDeprecatedAppId({cliConfig, output}: Options): void {\n const issue = resolveAppIdIssue(cliConfig)\n\n // Both configs set: a real deploy can't pick one, so stop here\n if (issue === 'conflicting-config') {\n output.error(\n `${styleText('bold', 'Found both app.id (deprecated) and deployment.appId in your application configuration.')}\n\nPlease remove app.id from your sanity.cli.js or sanity.cli.ts file.`,\n {\n exit: 1,\n },\n )\n }\n\n // Just warn if only the old app ID config is found\n if (issue === 'deprecated-config') {\n output.warn(\n `${styleText('bold', 'The `app.id` config has moved to `deployment.appId`.')}\n\nPlease update \\`sanity.cli.ts\\` or \\`sanity.cli.js\\` and move:\n${styleText('red', `app: {id: \"${getDeprecatedAppId(cliConfig)}\", ... }`)}\nto\n${styleText('green', `deployment: {appId: \"${getDeprecatedAppId(cliConfig)}\", ... }`)}\n`,\n )\n }\n}\n\n/**\n * Get an application's ID\n * @remarks Favors the current implementation (deployment.appId) but will fall back to the deprecated app.id\n * @internal\n */\nexport function getAppId(cliConfig: CliConfig): string | undefined {\n const hasNew = hasNewAppId(cliConfig)\n const hasOld = hasDeprecatedAppId(cliConfig)\n\n if (hasNew) {\n return getDeploymentAppId(cliConfig)\n }\n\n if (hasOld) {\n return getDeprecatedAppId(cliConfig)\n }\n\n return undefined\n}\n"],"names":["styleText","getDeploymentAppId","cliConfig","id","deployment","appId","getDeprecatedAppId","app","hasNewAppId","Boolean","hasDeprecatedAppId","resolveAppIdIssue","checkForDeprecatedAppId","output","issue","error","exit","warn","getAppId","hasNew","hasOld","undefined"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AASnC,SAASC,mBAAmBC,SAAoB;IAC9C,MAAMC,KAAKD,WAAWE,YAAYC;IAClC,OAAOF;AACT;AAEA,SAASG,mBAAmBJ,SAAoB;IAC9C,MAAMC,KAAKD,WAAWK,KAAKJ;IAC3B,OAAOA;AACT;AAEA,SAASK,YAAYN,SAAoB;IACvC,OAAOO,QAAQR,mBAAmBC;AACpC;AAEA,SAASQ,mBAAmBR,SAAoB;IAC9C,OAAOO,QAAQH,mBAAmBJ;AACpC;AAKA;;;;;CAKC,GACD,OAAO,SAASS,kBAAkBT,SAAoB;IACpD,IAAI,CAACQ,mBAAmBR,YAAY,OAAO;IAC3C,OAAOM,YAAYN,aAAa,uBAAuB;AACzD;AAEA;;;;CAIC,GACD,OAAO,SAASU,wBAAwB,EAACV,SAAS,EAAEW,MAAM,EAAU;IAClE,MAAMC,QAAQH,kBAAkBT;IAEhC,+DAA+D;IAC/D,IAAIY,UAAU,sBAAsB;QAClCD,OAAOE,KAAK,CACV,GAAGf,UAAU,QAAQ,0FAA0F;;mEAElD,CAAC,EAC9D;YACEgB,MAAM;QACR;IAEJ;IAEA,mDAAmD;IACnD,IAAIF,UAAU,qBAAqB;QACjCD,OAAOI,IAAI,CACT,GAAGjB,UAAU,QAAQ,wDAAwD;;;AAGnF,EAAEA,UAAU,OAAO,CAAC,WAAW,EAAEM,mBAAmBJ,WAAW,QAAQ,CAAC,EAAE;;AAE1E,EAAEF,UAAU,SAAS,CAAC,qBAAqB,EAAEM,mBAAmBJ,WAAW,QAAQ,CAAC,EAAE;AACtF,CAAC;IAEC;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASgB,SAAShB,SAAoB;IAC3C,MAAMiB,SAASX,YAAYN;IAC3B,MAAMkB,SAASV,mBAAmBR;IAElC,IAAIiB,QAAQ;QACV,OAAOlB,mBAAmBC;IAC5B;IAEA,IAAIkB,QAAQ;QACV,OAAOd,mBAAmBJ;IAC5B;IAEA,OAAOmB;AACT"}
1
+ {"version":3,"sources":["../../src/util/appId.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type CliConfig, exitCodes, type Output} from '@sanity/cli-core'\n\ninterface Options {\n cliConfig: CliConfig\n output: Output\n}\n\nfunction getDeploymentAppId(cliConfig: CliConfig): string | undefined {\n const id = cliConfig?.deployment?.appId\n return id\n}\n\nfunction getDeprecatedAppId(cliConfig: CliConfig): string | undefined {\n const id = cliConfig?.app?.id\n return id\n}\n\nfunction hasNewAppId(cliConfig: CliConfig) {\n return Boolean(getDeploymentAppId(cliConfig))\n}\n\nfunction hasDeprecatedAppId(cliConfig: CliConfig) {\n return Boolean(getDeprecatedAppId(cliConfig))\n}\n\n/** The one app-id configuration problem to surface, if any. */\nexport type AppIdIssue = 'conflicting-config' | 'deprecated-config'\n\n/**\n * Decides which app-id problem a config has: both the deprecated `app.id` and\n * `deployment.appId` (a conflict), only the deprecated one, or neither. Shared\n * so the real deploy and the dry-run check reach the same verdict.\n * @internal\n */\nexport function resolveAppIdIssue(cliConfig: CliConfig): AppIdIssue | null {\n if (!hasDeprecatedAppId(cliConfig)) return null\n return hasNewAppId(cliConfig) ? 'conflicting-config' : 'deprecated-config'\n}\n\n/**\n * Checks if an SDK app uses the deprecated app.id config & throws a warning if so.\n * @remarks Throws an error if an app uses both deployment.appId and app.id\n * @internal\n */\nexport function checkForDeprecatedAppId({cliConfig, output}: Options): void {\n const issue = resolveAppIdIssue(cliConfig)\n\n // Both configs set: a real deploy can't pick one, so stop here\n if (issue === 'conflicting-config') {\n output.error(\n `${styleText('bold', 'Found both app.id (deprecated) and deployment.appId in your application configuration.')}\n\nPlease remove app.id from your sanity.cli.js or sanity.cli.ts file.`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n\n // Just warn if only the old app ID config is found\n if (issue === 'deprecated-config') {\n output.warn(\n `${styleText('bold', 'The `app.id` config has moved to `deployment.appId`.')}\n\nPlease update \\`sanity.cli.ts\\` or \\`sanity.cli.js\\` and move:\n${styleText('red', `app: {id: \"${getDeprecatedAppId(cliConfig)}\", ... }`)}\nto\n${styleText('green', `deployment: {appId: \"${getDeprecatedAppId(cliConfig)}\", ... }`)}\n`,\n )\n }\n}\n\n/**\n * Get an application's ID\n * @remarks Favors the current implementation (deployment.appId) but will fall back to the deprecated app.id\n * @internal\n */\nexport function getAppId(cliConfig: CliConfig): string | undefined {\n const hasNew = hasNewAppId(cliConfig)\n const hasOld = hasDeprecatedAppId(cliConfig)\n\n if (hasNew) {\n return getDeploymentAppId(cliConfig)\n }\n\n if (hasOld) {\n return getDeprecatedAppId(cliConfig)\n }\n\n return undefined\n}\n"],"names":["styleText","exitCodes","getDeploymentAppId","cliConfig","id","deployment","appId","getDeprecatedAppId","app","hasNewAppId","Boolean","hasDeprecatedAppId","resolveAppIdIssue","checkForDeprecatedAppId","output","issue","error","exit","RUNTIME_ERROR","warn","getAppId","hasNew","hasOld","undefined"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAwBC,SAAS,QAAoB,mBAAkB;AAOvE,SAASC,mBAAmBC,SAAoB;IAC9C,MAAMC,KAAKD,WAAWE,YAAYC;IAClC,OAAOF;AACT;AAEA,SAASG,mBAAmBJ,SAAoB;IAC9C,MAAMC,KAAKD,WAAWK,KAAKJ;IAC3B,OAAOA;AACT;AAEA,SAASK,YAAYN,SAAoB;IACvC,OAAOO,QAAQR,mBAAmBC;AACpC;AAEA,SAASQ,mBAAmBR,SAAoB;IAC9C,OAAOO,QAAQH,mBAAmBJ;AACpC;AAKA;;;;;CAKC,GACD,OAAO,SAASS,kBAAkBT,SAAoB;IACpD,IAAI,CAACQ,mBAAmBR,YAAY,OAAO;IAC3C,OAAOM,YAAYN,aAAa,uBAAuB;AACzD;AAEA;;;;CAIC,GACD,OAAO,SAASU,wBAAwB,EAACV,SAAS,EAAEW,MAAM,EAAU;IAClE,MAAMC,QAAQH,kBAAkBT;IAEhC,+DAA+D;IAC/D,IAAIY,UAAU,sBAAsB;QAClCD,OAAOE,KAAK,CACV,GAAGhB,UAAU,QAAQ,0FAA0F;;mEAElD,CAAC,EAC9D;YACEiB,MAAMhB,UAAUiB,aAAa;QAC/B;IAEJ;IAEA,mDAAmD;IACnD,IAAIH,UAAU,qBAAqB;QACjCD,OAAOK,IAAI,CACT,GAAGnB,UAAU,QAAQ,wDAAwD;;;AAGnF,EAAEA,UAAU,OAAO,CAAC,WAAW,EAAEO,mBAAmBJ,WAAW,QAAQ,CAAC,EAAE;;AAE1E,EAAEH,UAAU,SAAS,CAAC,qBAAqB,EAAEO,mBAAmBJ,WAAW,QAAQ,CAAC,EAAE;AACtF,CAAC;IAEC;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASiB,SAASjB,SAAoB;IAC3C,MAAMkB,SAASZ,YAAYN;IAC3B,MAAMmB,SAASX,mBAAmBR;IAElC,IAAIkB,QAAQ;QACV,OAAOnB,mBAAmBC;IAC5B;IAEA,IAAImB,QAAQ;QACV,OAAOf,mBAAmBJ;IAC5B;IAEA,OAAOoB;AACT"}
@@ -0,0 +1,125 @@
1
+ import { pluralize } from './pluralize.js';
2
+ const MS_IN = {
3
+ day: 86_400_000,
4
+ hour: 3_600_000,
5
+ minute: 60_000,
6
+ month: 2_592_000_000,
7
+ second: 1000,
8
+ week: 604_800_000,
9
+ year: 31_536_000_000
10
+ };
11
+ /** Largest unit first, so the first unit the duration fills is the one we report. */ const UNITS = [
12
+ {
13
+ ms: MS_IN.year,
14
+ unit: 'year'
15
+ },
16
+ {
17
+ ms: MS_IN.month,
18
+ unit: 'month'
19
+ },
20
+ {
21
+ ms: MS_IN.week,
22
+ unit: 'week'
23
+ },
24
+ {
25
+ ms: MS_IN.day,
26
+ unit: 'day'
27
+ },
28
+ {
29
+ ms: MS_IN.hour,
30
+ unit: 'hour'
31
+ },
32
+ {
33
+ ms: MS_IN.minute,
34
+ unit: 'minute'
35
+ },
36
+ {
37
+ ms: MS_IN.second,
38
+ unit: 'second'
39
+ }
40
+ ];
41
+ const relativeTime = new Intl.RelativeTimeFormat('en', {
42
+ numeric: 'always'
43
+ });
44
+ const DATE_ONLY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
45
+ function pad(value, length = 2) {
46
+ return String(value).padStart(length, '0');
47
+ }
48
+ /**
49
+ * Returns the coarsest unit the elapsed time fills and the rounded number of those
50
+ * units, or `undefined` below a second.
51
+ *
52
+ * Rounding can land the value on the boundary of the next unit up, so we promote
53
+ * rather than report `60 minutes` where `1 hour` is meant. Units aren't all whole
54
+ * multiples of each other, so the boundary is the rounded count we'd display, which
55
+ * is why 25+ days reads as `1 month` rather than `4 weeks`.
56
+ */ function selectUnit(elapsed) {
57
+ let index = UNITS.findIndex(({ ms })=>elapsed >= ms);
58
+ if (index === -1) return undefined;
59
+ while(index > 0 && Math.round(elapsed / UNITS[index].ms) >= Math.round(UNITS[index - 1].ms / UNITS[index].ms)){
60
+ index -= 1;
61
+ }
62
+ const { ms, unit } = UNITS[index];
63
+ return {
64
+ unit,
65
+ value: Math.round(elapsed / ms)
66
+ };
67
+ }
68
+ /**
69
+ * Formats a timestamp as `YYYY-MM-DD HH:mm:ss` in the local time zone. Unparseable
70
+ * timestamps are returned as-is, so a bad value from the API doesn't fail the command.
71
+ *
72
+ * @param timestamp - An ISO 8601 timestamp
73
+ * @internal
74
+ */ export function formatDateTime(timestamp) {
75
+ const date = new Date(timestamp);
76
+ if (!Number.isFinite(date.getTime())) return timestamp;
77
+ const day = `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
78
+ const time = `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
79
+ return `${day} ${time}`;
80
+ }
81
+ /**
82
+ * Formats a duration in milliseconds as an approximate, human readable length of
83
+ * time, eg `less than a minute`, `5 minutes` or `2 days`.
84
+ *
85
+ * @param ms - The duration in milliseconds
86
+ * @internal
87
+ */ export function formatDuration(ms) {
88
+ if (!Number.isFinite(ms)) return '';
89
+ const selected = selectUnit(Math.abs(ms));
90
+ if (!selected || selected.unit === 'second') return 'less than a minute';
91
+ return `${selected.value} ${pluralize(selected.unit, selected.value)}`;
92
+ }
93
+ /**
94
+ * Formats a date relative to now, eg `2 days ago` or `in 3 hours`.
95
+ *
96
+ * @param date - The date to describe
97
+ * @param now - The reference point to compare against, defaults to the current time
98
+ * @internal
99
+ */ export function formatTimeAgo(date, now = Date.now()) {
100
+ const delta = date.getTime() - now;
101
+ if (!Number.isFinite(delta)) return '';
102
+ const selected = selectUnit(Math.abs(delta));
103
+ if (!selected) return 'just now';
104
+ return relativeTime.format(delta < 0 ? -selected.value : selected.value, selected.unit);
105
+ }
106
+ /**
107
+ * Parses a `YYYY-MM-DD` date into a `Date` at local midnight. Returns `undefined`
108
+ * for anything that isn't a real calendar date in that exact format.
109
+ *
110
+ * @param value - The date string to parse
111
+ * @internal
112
+ */ export function parseDateOnly(value) {
113
+ const match = DATE_ONLY_PATTERN.exec(value);
114
+ if (!match) return undefined;
115
+ const year = Number(match[1]);
116
+ const month = Number(match[2]);
117
+ const day = Number(match[3]);
118
+ const date = new Date(year, month - 1, day);
119
+ // `new Date(2024, 1, 31)` silently rolls over into March, so reject anything
120
+ // that didn't survive the round trip
121
+ const isRoundTrip = date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
122
+ return isRoundTrip ? date : undefined;
123
+ }
124
+
125
+ //# sourceMappingURL=dates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/dates.ts"],"sourcesContent":["import {pluralize} from './pluralize.js'\n\nconst MS_IN = {\n day: 86_400_000,\n hour: 3_600_000,\n minute: 60_000,\n month: 2_592_000_000, // 30 days\n second: 1000,\n week: 604_800_000,\n year: 31_536_000_000, // 365 days\n} as const\n\n/** Largest unit first, so the first unit the duration fills is the one we report. */\nconst UNITS: {ms: number; unit: Intl.RelativeTimeFormatUnit}[] = [\n {ms: MS_IN.year, unit: 'year'},\n {ms: MS_IN.month, unit: 'month'},\n {ms: MS_IN.week, unit: 'week'},\n {ms: MS_IN.day, unit: 'day'},\n {ms: MS_IN.hour, unit: 'hour'},\n {ms: MS_IN.minute, unit: 'minute'},\n {ms: MS_IN.second, unit: 'second'},\n]\n\nconst relativeTime = new Intl.RelativeTimeFormat('en', {numeric: 'always'})\n\nconst DATE_ONLY_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\nfunction pad(value: number, length = 2): string {\n return String(value).padStart(length, '0')\n}\n\n/**\n * Returns the coarsest unit the elapsed time fills and the rounded number of those\n * units, or `undefined` below a second.\n *\n * Rounding can land the value on the boundary of the next unit up, so we promote\n * rather than report `60 minutes` where `1 hour` is meant. Units aren't all whole\n * multiples of each other, so the boundary is the rounded count we'd display, which\n * is why 25+ days reads as `1 month` rather than `4 weeks`.\n */\nfunction selectUnit(\n elapsed: number,\n): {unit: Intl.RelativeTimeFormatUnit; value: number} | undefined {\n let index = UNITS.findIndex(({ms}) => elapsed >= ms)\n if (index === -1) return undefined\n\n while (\n index > 0 &&\n Math.round(elapsed / UNITS[index].ms) >= Math.round(UNITS[index - 1].ms / UNITS[index].ms)\n ) {\n index -= 1\n }\n\n const {ms, unit} = UNITS[index]\n return {unit, value: Math.round(elapsed / ms)}\n}\n\n/**\n * Formats a timestamp as `YYYY-MM-DD HH:mm:ss` in the local time zone. Unparseable\n * timestamps are returned as-is, so a bad value from the API doesn't fail the command.\n *\n * @param timestamp - An ISO 8601 timestamp\n * @internal\n */\nexport function formatDateTime(timestamp: string): string {\n const date = new Date(timestamp)\n if (!Number.isFinite(date.getTime())) return timestamp\n\n const day = `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n const time = `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`\n return `${day} ${time}`\n}\n\n/**\n * Formats a duration in milliseconds as an approximate, human readable length of\n * time, eg `less than a minute`, `5 minutes` or `2 days`.\n *\n * @param ms - The duration in milliseconds\n * @internal\n */\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms)) return ''\n\n const selected = selectUnit(Math.abs(ms))\n if (!selected || selected.unit === 'second') return 'less than a minute'\n\n return `${selected.value} ${pluralize(selected.unit, selected.value)}`\n}\n\n/**\n * Formats a date relative to now, eg `2 days ago` or `in 3 hours`.\n *\n * @param date - The date to describe\n * @param now - The reference point to compare against, defaults to the current time\n * @internal\n */\nexport function formatTimeAgo(date: Date, now: number = Date.now()): string {\n const delta = date.getTime() - now\n if (!Number.isFinite(delta)) return ''\n\n const selected = selectUnit(Math.abs(delta))\n if (!selected) return 'just now'\n\n return relativeTime.format(delta < 0 ? -selected.value : selected.value, selected.unit)\n}\n\n/**\n * Parses a `YYYY-MM-DD` date into a `Date` at local midnight. Returns `undefined`\n * for anything that isn't a real calendar date in that exact format.\n *\n * @param value - The date string to parse\n * @internal\n */\nexport function parseDateOnly(value: string): Date | undefined {\n const match = DATE_ONLY_PATTERN.exec(value)\n if (!match) return undefined\n\n const year = Number(match[1])\n const month = Number(match[2])\n const day = Number(match[3])\n const date = new Date(year, month - 1, day)\n\n // `new Date(2024, 1, 31)` silently rolls over into March, so reject anything\n // that didn't survive the round trip\n const isRoundTrip =\n date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day\n\n return isRoundTrip ? date : undefined\n}\n"],"names":["pluralize","MS_IN","day","hour","minute","month","second","week","year","UNITS","ms","unit","relativeTime","Intl","RelativeTimeFormat","numeric","DATE_ONLY_PATTERN","pad","value","length","String","padStart","selectUnit","elapsed","index","findIndex","undefined","Math","round","formatDateTime","timestamp","date","Date","Number","isFinite","getTime","getFullYear","getMonth","getDate","time","getHours","getMinutes","getSeconds","formatDuration","selected","abs","formatTimeAgo","now","delta","format","parseDateOnly","match","exec","isRoundTrip"],"mappings":"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"}
@@ -1,24 +1,14 @@
1
1
  import path from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
2
  import { readPackageJson } from '@sanity/cli-core';
4
- import { packageDirectory } from 'package-directory';
5
3
  /**
6
4
  * Get the version of the `@sanity/cli` package.
7
5
  *
8
6
  * @internal
9
7
  * @returns The version of the `@sanity/cli` package.
10
8
  */ export async function getCliVersion() {
11
- // using the meta.url will resolve to the code running from the cli
12
- // this will find the package.json in cli package.
13
- const cliPath = await packageDirectory({
14
- cwd: fileURLToPath(import.meta.url)
15
- });
16
- if (!cliPath) {
17
- throw new Error('Unable to resolve root of @sanity/cli module');
18
- }
19
9
  let pkg;
20
10
  try {
21
- pkg = await readPackageJson(path.join(cliPath, 'package.json'));
11
+ pkg = await readPackageJson(path.join(import.meta.dirname, '..', '..', 'package.json'));
22
12
  } catch (err) {
23
13
  throw new Error(`Unable to read @sanity/cli/package.json: ${err.message}`, {
24
14
  cause: err
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/util/getCliVersion.ts"],"sourcesContent":["import path from 'node:path'\nimport {fileURLToPath} from 'node:url'\n\nimport {type PackageJson, readPackageJson} from '@sanity/cli-core'\nimport {packageDirectory} from 'package-directory'\n\n/**\n * Get the version of the `@sanity/cli` package.\n *\n * @internal\n * @returns The version of the `@sanity/cli` package.\n */\nexport async function getCliVersion(): Promise<string> {\n // using the meta.url will resolve to the code running from the cli\n // this will find the package.json in cli package.\n const cliPath = await packageDirectory({cwd: fileURLToPath(import.meta.url)})\n if (!cliPath) {\n throw new Error('Unable to resolve root of @sanity/cli module')\n }\n\n let pkg: PackageJson | undefined\n try {\n pkg = await readPackageJson(path.join(cliPath, 'package.json'))\n } catch (err) {\n throw new Error(`Unable to read @sanity/cli/package.json: ${(err as Error).message}`, {\n cause: err,\n })\n }\n\n return pkg.version\n}\n"],"names":["path","fileURLToPath","readPackageJson","packageDirectory","getCliVersion","cliPath","cwd","url","Error","pkg","join","err","message","cause","version"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAC5B,SAAQC,aAAa,QAAO,WAAU;AAEtC,SAA0BC,eAAe,QAAO,mBAAkB;AAClE,SAAQC,gBAAgB,QAAO,oBAAmB;AAElD;;;;;CAKC,GACD,OAAO,eAAeC;IACpB,mEAAmE;IACnE,kDAAkD;IAClD,MAAMC,UAAU,MAAMF,iBAAiB;QAACG,KAAKL,cAAc,YAAYM,GAAG;IAAC;IAC3E,IAAI,CAACF,SAAS;QACZ,MAAM,IAAIG,MAAM;IAClB;IAEA,IAAIC;IACJ,IAAI;QACFA,MAAM,MAAMP,gBAAgBF,KAAKU,IAAI,CAACL,SAAS;IACjD,EAAE,OAAOM,KAAK;QACZ,MAAM,IAAIH,MAAM,CAAC,yCAAyC,EAAE,AAACG,IAAcC,OAAO,EAAE,EAAE;YACpFC,OAAOF;QACT;IACF;IAEA,OAAOF,IAAIK,OAAO;AACpB"}
1
+ {"version":3,"sources":["../../src/util/getCliVersion.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type PackageJson, readPackageJson} from '@sanity/cli-core'\n\n/**\n * Get the version of the `@sanity/cli` package.\n *\n * @internal\n * @returns The version of the `@sanity/cli` package.\n */\nexport async function getCliVersion(): Promise<string> {\n let pkg: PackageJson | undefined\n try {\n pkg = await readPackageJson(path.join(import.meta.dirname, '..', '..', 'package.json'))\n } catch (err) {\n throw new Error(`Unable to read @sanity/cli/package.json: ${(err as Error).message}`, {\n cause: err,\n })\n }\n\n return pkg.version\n}\n"],"names":["path","readPackageJson","getCliVersion","pkg","join","dirname","err","Error","message","cause","version"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAA0BC,eAAe,QAAO,mBAAkB;AAElE;;;;;CAKC,GACD,OAAO,eAAeC;IACpB,IAAIC;IACJ,IAAI;QACFA,MAAM,MAAMF,gBAAgBD,KAAKI,IAAI,CAAC,YAAYC,OAAO,EAAE,MAAM,MAAM;IACzE,EAAE,OAAOC,KAAK;QACZ,MAAM,IAAIC,MAAM,CAAC,yCAAyC,EAAE,AAACD,IAAcE,OAAO,EAAE,EAAE;YACpFC,OAAOH;QACT;IACF;IAEA,OAAOH,IAAIO,OAAO;AACpB"}