@shopify/cli-kit 4.2.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.d.ts +28 -0
  2. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js +74 -0
  3. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js.map +1 -0
  4. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.d.ts +28 -0
  5. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js +92 -0
  6. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js.map +1 -0
  7. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.d.ts +26 -0
  8. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js +72 -0
  9. package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js.map +1 -0
  10. package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.d.ts +19 -0
  11. package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js +49 -0
  12. package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js.map +1 -0
  13. package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.d.ts +22 -0
  14. package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.js +78 -0
  15. package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.js.map +1 -0
  16. package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.d.ts +22 -0
  17. package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.js +82 -0
  18. package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.js.map +1 -0
  19. package/dist/private/node/api/headers.js +1 -1
  20. package/dist/private/node/api/headers.js.map +1 -1
  21. package/dist/private/node/session/store.js +10 -1
  22. package/dist/private/node/session/store.js.map +1 -1
  23. package/dist/private/node/ui/components/Alert.test.js +5 -5
  24. package/dist/private/node/ui/components/Alert.test.js.map +1 -1
  25. package/dist/private/node/ui/components/Banner.js +9 -1
  26. package/dist/private/node/ui/components/Banner.js.map +1 -1
  27. package/dist/public/common/url.js +13 -4
  28. package/dist/public/common/url.js.map +1 -1
  29. package/dist/public/common/version.d.ts +1 -1
  30. package/dist/public/common/version.js +1 -1
  31. package/dist/public/common/version.js.map +1 -1
  32. package/dist/public/node/api/admin.d.ts +2 -1
  33. package/dist/public/node/api/admin.js +4 -3
  34. package/dist/public/node/api/admin.js.map +1 -1
  35. package/dist/public/node/api/bulk-operations/cancel.d.ts +15 -0
  36. package/dist/public/node/api/bulk-operations/cancel.js +20 -0
  37. package/dist/public/node/api/bulk-operations/cancel.js.map +1 -0
  38. package/dist/public/node/api/bulk-operations/constants.d.ts +5 -0
  39. package/dist/public/node/api/bulk-operations/constants.js +6 -0
  40. package/dist/public/node/api/bulk-operations/constants.js.map +1 -0
  41. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +17 -0
  42. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +48 -0
  43. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -0
  44. package/dist/public/node/api/bulk-operations/fetch.d.ts +31 -0
  45. package/dist/public/node/api/bulk-operations/fetch.js +42 -0
  46. package/dist/public/node/api/bulk-operations/fetch.js.map +1 -0
  47. package/dist/public/node/api/bulk-operations/format-bulk-operation-status.d.ts +45 -0
  48. package/dist/public/node/api/bulk-operations/format-bulk-operation-status.js +91 -0
  49. package/dist/public/node/api/bulk-operations/format-bulk-operation-status.js.map +1 -0
  50. package/dist/public/node/api/bulk-operations/helpers.d.ts +51 -0
  51. package/dist/public/node/api/bulk-operations/helpers.js +110 -0
  52. package/dist/public/node/api/bulk-operations/helpers.js.map +1 -0
  53. package/dist/public/node/api/bulk-operations/query.d.ts +22 -0
  54. package/dist/public/node/api/bulk-operations/query.js +40 -0
  55. package/dist/public/node/api/bulk-operations/query.js.map +1 -0
  56. package/dist/public/node/api/bulk-operations/run-mutation.d.ts +16 -0
  57. package/dist/public/node/api/bulk-operations/run-mutation.js +27 -0
  58. package/dist/public/node/api/bulk-operations/run-mutation.js.map +1 -0
  59. package/dist/public/node/api/bulk-operations/run-query.d.ts +15 -0
  60. package/dist/public/node/api/bulk-operations/run-query.js +19 -0
  61. package/dist/public/node/api/bulk-operations/run-query.js.map +1 -0
  62. package/dist/public/node/api/bulk-operations/stage-file.d.ts +13 -0
  63. package/dist/public/node/api/bulk-operations/stage-file.js +89 -0
  64. package/dist/public/node/api/bulk-operations/stage-file.js.map +1 -0
  65. package/dist/public/node/api/bulk-operations/watch-bulk-operation.d.ts +26 -0
  66. package/dist/public/node/api/bulk-operations/watch-bulk-operation.js +131 -0
  67. package/dist/public/node/api/bulk-operations/watch-bulk-operation.js.map +1 -0
  68. package/dist/public/node/api/bulk-operations.d.ts +18 -0
  69. package/dist/public/node/api/bulk-operations.js +19 -0
  70. package/dist/public/node/api/bulk-operations.js.map +1 -0
  71. package/dist/public/node/constants.d.ts +1 -0
  72. package/dist/public/node/constants.js +2 -0
  73. package/dist/public/node/constants.js.map +1 -0
  74. package/dist/public/node/context/fqdn.js +46 -5
  75. package/dist/public/node/context/fqdn.js.map +1 -1
  76. package/dist/public/node/graphiql/session.d.ts +50 -0
  77. package/dist/public/node/graphiql/session.js +92 -0
  78. package/dist/public/node/graphiql/session.js.map +1 -0
  79. package/dist/public/node/graphiql/templates/graphiql.js +1 -4
  80. package/dist/public/node/graphiql/templates/graphiql.js.map +1 -1
  81. package/dist/public/node/json-schema.js +22 -6
  82. package/dist/public/node/json-schema.js.map +1 -1
  83. package/dist/public/node/monorail.d.ts +2 -1
  84. package/dist/public/node/monorail.js +1 -1
  85. package/dist/public/node/monorail.js.map +1 -1
  86. package/dist/public/node/session.d.ts +2 -1
  87. package/dist/public/node/session.js +3 -2
  88. package/dist/public/node/session.js.map +1 -1
  89. package/dist/public/node/store-auth-session.d.ts +113 -0
  90. package/dist/public/node/store-auth-session.js +257 -0
  91. package/dist/public/node/store-auth-session.js.map +1 -0
  92. package/dist/public/node/ui.d.ts +2 -6
  93. package/dist/public/node/ui.js +2 -6
  94. package/dist/public/node/ui.js.map +1 -1
  95. package/dist/tsconfig.tsbuildinfo +1 -1
  96. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../src/public/node/graphiql/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {GraphiQLAppContext, setupGraphiQLServer, TokenProvider} from './server.js'\nimport {AbortController, AbortSignal} from '../abort.js'\nimport {OutputMessage, outputContent, outputInfo, outputToken, outputWarn} from '../output.js'\nimport {openURL} from '../system.js'\nimport {getAvailableTCPPort} from '../tcp.js'\nimport {randomBytes} from 'crypto'\nimport {Writable} from 'stream'\n\nexport interface BuildGraphiQLUrlOptions {\n port: number\n key: string\n query?: string\n variables?: string\n apiVersion?: string\n}\n\nexport interface RunGraphiQLSessionOptions {\n storeFqdn: string\n tokenProvider: TokenProvider\n key: string\n port?: number\n query?: string\n variables?: string\n apiVersion?: string\n appContext?: GraphiQLAppContext\n protectMutations?: boolean\n additionalReadyMessages?: OutputMessage[]\n abortSignal?: AbortSignal\n stdout?: Writable\n}\n\n/**\n * Generates a random key suitable for authenticating a single local GraphiQL session.\n *\n * @returns A 64-character hex string.\n */\nexport function generateRandomGraphiQLKey(): string {\n return randomBytes(32).toString('hex')\n}\n\n/**\n * Builds the browser URL for a local GraphiQL session.\n *\n * @param options - The local port, key, and optional query string fields to prefill.\n * @returns The fully-qualified local GraphiQL URL.\n */\nexport function buildGraphiQLUrl(options: BuildGraphiQLUrlOptions): string {\n const url = new URL(`http://localhost:${options.port}/graphiql`)\n url.searchParams.set('key', options.key)\n if (options.query) url.searchParams.set('query', options.query)\n if (options.variables) url.searchParams.set('variables', options.variables)\n if (options.apiVersion) url.searchParams.set('api_version', options.apiVersion)\n return url.toString()\n}\n\n/**\n * Runs a local GraphiQL session until the user interrupts it or the supplied abort signal fires.\n *\n * @param options - The server, authentication, URL prefill, and output options for the session.\n */\nexport async function runGraphiQLSession(options: RunGraphiQLSessionOptions): Promise<void> {\n const port = await getAvailableTCPPort(options.port)\n const server = setupGraphiQLServer({\n stdout: options.stdout ?? process.stdout,\n port,\n storeFqdn: options.storeFqdn,\n tokenProvider: options.tokenProvider,\n key: options.key,\n appContext: options.appContext,\n protectMutations: options.protectMutations,\n })\n\n const url = buildGraphiQLUrl({\n port,\n key: options.key,\n query: options.query,\n variables: options.variables,\n apiVersion: options.apiVersion,\n })\n\n try {\n outputInfo(outputContent`GraphiQL is running at ${outputToken.link(url)}`)\n options.additionalReadyMessages?.forEach((message) => outputInfo(message))\n outputInfo('Press Ctrl+C to stop.')\n\n const opened = await openURL(url)\n if (!opened) {\n outputWarn('Browser did not open automatically. Open the URL above manually.')\n }\n\n await waitForGraphiQLAbort(options.abortSignal)\n } finally {\n server.close()\n }\n}\n\n/**\n * Resolves when the process receives SIGINT or when the supplied abort signal fires.\n *\n * @param externalSignal - Optional signal used by tests or callers to stop the session.\n */\nexport async function waitForGraphiQLAbort(externalSignal?: AbortSignal): Promise<void> {\n const controller = new AbortController()\n\n const onSigint = () => controller.abort()\n process.once('SIGINT', onSigint)\n\n try {\n await new Promise<void>((resolve) => {\n if (controller.signal.aborted || externalSignal?.aborted) {\n resolve()\n return\n }\n controller.signal.addEventListener('abort', () => resolve(), {once: true})\n externalSignal?.addEventListener('abort', () => controller.abort(), {once: true})\n })\n } finally {\n process.removeListener('SIGINT', onSigint)\n }\n}\n"]}
@@ -184,10 +184,7 @@ export function graphiqlTemplate({ apiVersion, apiVersions, appName, appUrl, key
184
184
  React.createElement(Text, { as: "span", tone: "subdued" }, scopesNoteText({ hasAppContext, protectMutations }))))),
185
185
  React.createElement("div", { id: "top-error-bar" },
186
186
  React.createElement(Banner, { tone: "critical", onDismiss: () => { }, icon: DisabledIcon },
187
- React.createElement("p", null,
188
- "The server has been stopped. Restart ",
189
- React.createElement("code", null, "dev"),
190
- " from the CLI."))))))))}
187
+ React.createElement("p", null, "The server has been stopped. Restart it from the CLI."))))))))}
191
188
  <div id="graphiql-explorer">Loading...</div>
192
189
  </div>
193
190
  <script
@@ -1 +1 @@
1
- {"version":3,"file":"graphiql.js","sourceRoot":"","sources":["../../../../../src/public/node/graphiql/templates/graphiql.tsx"],"names":[],"mappings":"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","sourcesContent":["import {platformAndArch} from '../../os.js'\nimport {MUTATIONS_BLOCKED_MESSAGE} from '../server.js'\nimport React from 'react'\nimport {renderToStaticMarkup} from 'react-dom/server'\nimport {AppProvider, Badge, Banner, BlockStack, Box, Grid, InlineStack, Link, Select, Text} from '@shopify/polaris'\nimport {AlertCircleIcon, DisabledIcon, LinkIcon} from '@shopify/polaris-icons'\n\nconst controlKey = platformAndArch().platform === 'darwin' ? 'MAC_COMMAND_KEY' : 'Ctrl'\n\nconst graphiqlIntroMessage = `\n# Welcome to GraphiQL for the Shopify Admin API! If you've used\n# GraphiQL before, you can jump to the next tab.\n#\n# GraphiQL is an in-browser tool for writing, validating, and\n# testing GraphQL queries.\n#\n# Type queries into this side of the screen, and you will see intelligent\n# typeaheads aware of the current GraphQL type schema and live syntax and\n# validation errors highlighted within the text.\n#\n# GraphQL queries typically start with a \"{\" character. Lines that start\n# with a # are ignored.\n#\n# Keyboard shortcuts:\n#\n# Prettify query: Shift-${controlKey}-P (or press the prettify button)\n#\n# Merge fragments: Shift-${controlKey}-M (or press the merge button)\n#\n# Run Query: ${controlKey}-Enter (or press the play button)\n#\n# Auto Complete: ${controlKey}-Space (or just start typing)\n#\n`\n\nexport const defaultQuery = `query shopInfo {\n shop {\n name\n url\n myshopifyDomain\n plan {\n displayName\n partnerDevelopment\n shopifyPlus\n }\n }\n}\n`.replace(/\\n/g, '\\\\n')\n\ninterface GraphiQLTemplateOptions {\n apiVersion: string\n apiVersions: string[]\n appName?: string\n appUrl?: string\n key: string\n storeFqdn: string\n protectMutations?: boolean\n}\n\nexport function graphiqlTemplate({\n apiVersion,\n apiVersions,\n appName,\n appUrl,\n key,\n storeFqdn,\n protectMutations = false,\n}: GraphiQLTemplateOptions): string {\n const hasAppContext = Boolean(appName && appUrl)\n const unauthorizedLabel = hasAppContext ? 'App uninstalled' : 'Auth invalid'\n return `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <title>GraphiQL</title>\n <link rel=\"shortcut icon\" href=\"{{url}}/graphiql/favicon.ico\" type=\"image/x-icon\" />\n <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@shopify/polaris@12.10.0/build/esm/styles.css\" />\n <style>\n body {\n height: 100%;\n margin: 0;\n width: 100%;\n overflow: hidden;\n }\n .Polaris-Page--fullWidth {\n width: 100%;\n }\n #top-bar {\n border-bottom: 1px solid var(--p-color-border);\n }\n #top-bar #top-error-bar {\n display: none;\n }\n #top-error-bar .Polaris-FullscreenBar__BackAction {\n /* hide default back button in FullscreenBar component */\n display: none;\n }\n #top-error-bar button {\n /* hide X to dismiss banner */\n display: none;\n }\n #top-bar .top-bar-section {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n }\n #top-bar .Polaris-Grid-Cell:nth-child(2) {\n justify-self: right;\n }\n #top-bar #scopes-note {\n display: inline-flex;\n align-items: center;\n height: 100%;\n }\n #top-bar .status-badge-option {\n gap: 8px;\n display: none;\n }\n #top-bar #status-badge-running {\n display: flex;\n }\n #graphiql {\n height: 100vh;\n display: flex;\n flex-direction: column;\n }\n #graphiql-explorer {\n flex-grow: 1;\n overflow: auto;\n }\n #top-bar #outbound-links a {\n line-height: 0;\n }\n #top-bar #outbound-links a:hover .Polaris-Text--root {\n text-decoration: underline;\n }\n #top-bar #outbound-links a span.Polaris-Text--root {\n max-width: max(12vw, 150px);\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n .with-shrunk-icon .Polaris-Icon {\n height: 1rem;\n width: 1rem;\n margin: 0.125rem;\n }\n @media only screen and (max-width: 1550px) {\n .top-bar-section-title {\n display: none;\n }\n }\n @media only screen and (max-width: 1150px) {\n #top-bar #outbound-links a span.Polaris-Text--root {\n max-width: max(12vw, 140px);\n }\n }\n @media only screen and (max-width: 1080px) {\n #top-bar .Polaris-Grid-Cell:nth-child(2) {\n justify-self: left;\n }\n }\n @media only screen and (max-width: 650px) {\n #top-bar #outbound-links a span.Polaris-Text--root {\n max-width: 17vw;\n }\n }\n </style>\n\n <script\n src=\"https://cdn.jsdelivr.net/npm/react@17/umd/react.development.js\"\n integrity=\"sha512-Vf2xGDzpqUOEIKO+X2rgTLWPY+65++WPwCHkX2nFMu9IcstumPsf/uKKRd5prX3wOu8Q0GBylRpsDB26R6ExOg==\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n src=\"https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.development.js\"\n integrity=\"sha512-Wr9OKCTtq1anK0hq5bY3X/AvDI5EflDSAh0mE9gma+4hl+kXdTJPKZ3TwLMBcrgUeoY0s3dq9JjhCQc7vddtFg==\"\n crossorigin=\"anonymous\"\n ></script>\n <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/graphiql@3.0.4/graphiql.min.css\" />\n </head>\n <body>\n <div id=\"graphiql\">\n ${renderToStaticMarkup(\n <AppProvider i18n={{}}>\n <div id=\"top-bar\">\n <Box background=\"bg-surface\" padding=\"400\">\n <BlockStack gap=\"300\">\n <Grid columns={{xs: 3, sm: 3, md: 3}}>\n <Grid.Cell columnSpan={{xs: 3, sm: 3, md: 3, lg: 7, xl: 7}}>\n <InlineStack gap=\"400\">\n <div id=\"status-badge\" className=\"top-bar-section\">\n <div className=\"status-badge-option\" id=\"status-badge-running\">\n <span className=\"top-bar-section-title\">Status: </span>\n <Badge tone=\"success\" progress=\"complete\">\n Running\n </Badge>\n </div>\n <div className=\"status-badge-option with-shrunk-icon\" id=\"status-badge-unauthorized\">\n <span className=\"top-bar-section-title\">Status: </span>\n <Badge tone=\"attention\" icon={AlertCircleIcon}>\n {unauthorizedLabel}\n </Badge>\n </div>\n <div className=\"status-badge-option with-shrunk-icon\" id=\"status-badge-disconnected\">\n <span className=\"top-bar-section-title\">Status: </span>\n <Badge tone=\"critical\" icon={DisabledIcon}>\n Disconnected\n </Badge>\n </div>\n </div>\n <div id=\"version-select\" className=\"top-bar-section\">\n <span className=\"top-bar-section-title\">API version: </span>\n <Select\n label=\"API version\"\n labelHidden\n options={apiVersions}\n value={apiVersion}\n onChange={() => {}}\n />\n </div>\n {linkPills({storeFqdn, appName, appUrl})}\n </InlineStack>\n </Grid.Cell>\n <Grid.Cell columnSpan={{xs: 3, sm: 3, md: 3, lg: 5, xl: 5}}>\n <div id=\"scopes-note\" className=\"top-bar-section\">\n <Text as=\"span\" tone=\"subdued\">\n {scopesNoteText({hasAppContext, protectMutations})}\n </Text>\n </div>\n </Grid.Cell>\n </Grid>\n <div id=\"top-error-bar\">\n <Banner tone=\"critical\" onDismiss={() => {}} icon={DisabledIcon}>\n <p>\n The server has been stopped. Restart <code>dev</code> from the CLI.\n </p>\n </Banner>\n </div>\n </BlockStack>\n </Box>\n </div>\n </AppProvider>,\n )}\n <div id=\"graphiql-explorer\">Loading...</div>\n </div>\n <script\n src=\"https://cdn.jsdelivr.net/npm/graphiql@3.0.4/graphiql.min.js\"\n type=\"application/javascript\"\n ></script>\n <script>\n const macCommandKey = String.fromCodePoint(8984)\n const renderGraphiQL = function(apiVersion) {\n ReactDOM.render(\n React.createElement(GraphiQL, {\n fetcher: GraphiQL.createFetcher({\n url: '{{url}}/graphiql/graphql.json?key=${encodeURIComponent(key)}&api_version=' + apiVersion,\n }),\n defaultEditorToolsVisibility: true,\n {% if query %}\n query: {{query}},\n {% endif %}\n {% if variables %}\n variables: {{variables}},\n {% endif %}\n defaultTabs: [\n {query: \"${graphiqlIntroMessage\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')}\".replace(/MAC_COMMAND_KEY/g, macCommandKey)},\n {%for query in defaultQueries%}\n {query: \"{%if query.preface %}{{query.preface}}\\\\n{% endif %}{{query.query}}\", variables: \"{{query.variables}}\"},\n {%endfor%}\n ],\n isHeadersEditorEnabled: true,\n }),\n document.getElementById('graphiql-explorer'),\n )\n }\n renderGraphiQL('${apiVersion}')\n\n // Update the version when the select changes\n document.getElementById('version-select').addEventListener('change', function(event) {\n document.querySelector('#version-select .Polaris-Select__SelectedOption').innerText = event.target.value\n renderGraphiQL(event.target.value)\n })\n\n // Start out optimistic\n let serverIsLive = true\n let appIsInstalled = true\n\n const updateBadge = function() {\n const topErrorBar = document.querySelector('#graphiql #top-error-bar')\n const statusDiv = document.querySelector('#graphiql #status-badge')\n const allBadgeDivs = Array.from(statusDiv.querySelectorAll('.status-badge-option'))\n let activeBadge = 'running'\n if (!appIsInstalled) activeBadge = 'unauthorized'\n if (!serverIsLive) activeBadge = 'disconnected'\n allBadgeDivs.forEach(function(badge) {\n if (badge.id == ('status-badge-' + activeBadge)) {\n badge.style.display = 'flex'\n } else {\n badge.style.display = 'none'\n }\n })\n topErrorBar.style.display = serverIsLive ? 'none' : 'block'\n }\n const statusInterval = setInterval(updateBadge, 1000)\n\n // Warn when the server has been stopped\n const displayErrorServerStoppedTimeouts = []\n const pingInterval = setInterval(function() {\n displayErrorServerStoppedTimeouts.push(setTimeout(function() { serverIsLive = false }, 3000))\n fetch('{{url}}/graphiql/ping')\n .then(function(response) {\n if (response.status === 200) {\n while (displayErrorServerStoppedTimeouts.length > 0) {\n const timeout = displayErrorServerStoppedTimeouts.pop()\n clearTimeout(timeout)\n }\n serverIsLive = true\n } else {\n serverIsLive = false\n }\n })\n }, 2000)\n\n // Verify the current store/app connection\n setInterval(function() {\n fetch('{{ url }}/graphiql/status?key=${encodeURIComponent(key)}')\n .then(async function(response) {\n const {status, storeFqdn, appName, appUrl} = await response.json()\n appIsInstalled = status === 'OK'\n if (storeFqdn) {\n ${\n hasAppContext\n ? `document.getElementById('outbound-links').innerHTML = \\`${renderToStaticMarkup(\n <AppProvider i18n={{}}>\n {\n // eslint-disable-next-line no-template-curly-in-string\n linkPills({storeFqdn: '${storeFqdn}', appName: '${appName}', appUrl: '${appUrl}'})\n }\n </AppProvider>,\n )}\\``\n : `document.getElementById('outbound-links').innerHTML = \\`${renderToStaticMarkup(\n <AppProvider i18n={{}}>\n {\n // eslint-disable-next-line no-template-curly-in-string\n linkPills({storeFqdn: '${storeFqdn}'})\n }\n </AppProvider>,\n )}\\``\n }\n }\n })\n }, 5000)\n </script>\n </body>\n</html>\n`\n}\n\ninterface LinkPillOptions {\n storeFqdn: string\n appName?: string\n appUrl?: string\n}\n\nfunction linkPills({storeFqdn, appName, appUrl}: LinkPillOptions) {\n return (\n <div id=\"outbound-links\" className=\"top-bar-section with-shrunk-icon\">\n <span className=\"top-bar-section-title\">Store: </span>\n <Link url={`https://${storeFqdn}/admin`} target=\"_blank\">\n <Badge tone=\"info\" icon={LinkIcon} children={storeFqdn} />\n </Link>\n {appName && appUrl ? (\n <>\n <span className=\"top-bar-section-title\">App: </span>\n <Link url={appUrl} target=\"_blank\">\n <Badge tone=\"info\" icon={LinkIcon} children={appName} />\n </Link>\n </>\n ) : null}\n </div>\n )\n}\n\nfunction scopesNoteText({\n hasAppContext,\n protectMutations,\n}: {\n hasAppContext: boolean\n protectMutations: boolean\n}): string {\n if (protectMutations) {\n return MUTATIONS_BLOCKED_MESSAGE\n }\n if (hasAppContext) {\n return \"GraphiQL runs on the same access scopes you've defined in the TOML file for your app.\"\n }\n return 'GraphiQL runs with the access scopes granted to the stored app authentication for this store.'\n}\n"]}
1
+ {"version":3,"file":"graphiql.js","sourceRoot":"","sources":["../../../../../src/public/node/graphiql/templates/graphiql.tsx"],"names":[],"mappings":"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","sourcesContent":["import {platformAndArch} from '../../os.js'\nimport {MUTATIONS_BLOCKED_MESSAGE} from '../server.js'\nimport React from 'react'\nimport {renderToStaticMarkup} from 'react-dom/server'\nimport {AppProvider, Badge, Banner, BlockStack, Box, Grid, InlineStack, Link, Select, Text} from '@shopify/polaris'\nimport {AlertCircleIcon, DisabledIcon, LinkIcon} from '@shopify/polaris-icons'\n\nconst controlKey = platformAndArch().platform === 'darwin' ? 'MAC_COMMAND_KEY' : 'Ctrl'\n\nconst graphiqlIntroMessage = `\n# Welcome to GraphiQL for the Shopify Admin API! If you've used\n# GraphiQL before, you can jump to the next tab.\n#\n# GraphiQL is an in-browser tool for writing, validating, and\n# testing GraphQL queries.\n#\n# Type queries into this side of the screen, and you will see intelligent\n# typeaheads aware of the current GraphQL type schema and live syntax and\n# validation errors highlighted within the text.\n#\n# GraphQL queries typically start with a \"{\" character. Lines that start\n# with a # are ignored.\n#\n# Keyboard shortcuts:\n#\n# Prettify query: Shift-${controlKey}-P (or press the prettify button)\n#\n# Merge fragments: Shift-${controlKey}-M (or press the merge button)\n#\n# Run Query: ${controlKey}-Enter (or press the play button)\n#\n# Auto Complete: ${controlKey}-Space (or just start typing)\n#\n`\n\nexport const defaultQuery = `query shopInfo {\n shop {\n name\n url\n myshopifyDomain\n plan {\n displayName\n partnerDevelopment\n shopifyPlus\n }\n }\n}\n`.replace(/\\n/g, '\\\\n')\n\ninterface GraphiQLTemplateOptions {\n apiVersion: string\n apiVersions: string[]\n appName?: string\n appUrl?: string\n key: string\n storeFqdn: string\n protectMutations?: boolean\n}\n\nexport function graphiqlTemplate({\n apiVersion,\n apiVersions,\n appName,\n appUrl,\n key,\n storeFqdn,\n protectMutations = false,\n}: GraphiQLTemplateOptions): string {\n const hasAppContext = Boolean(appName && appUrl)\n const unauthorizedLabel = hasAppContext ? 'App uninstalled' : 'Auth invalid'\n return `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <title>GraphiQL</title>\n <link rel=\"shortcut icon\" href=\"{{url}}/graphiql/favicon.ico\" type=\"image/x-icon\" />\n <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@shopify/polaris@12.10.0/build/esm/styles.css\" />\n <style>\n body {\n height: 100%;\n margin: 0;\n width: 100%;\n overflow: hidden;\n }\n .Polaris-Page--fullWidth {\n width: 100%;\n }\n #top-bar {\n border-bottom: 1px solid var(--p-color-border);\n }\n #top-bar #top-error-bar {\n display: none;\n }\n #top-error-bar .Polaris-FullscreenBar__BackAction {\n /* hide default back button in FullscreenBar component */\n display: none;\n }\n #top-error-bar button {\n /* hide X to dismiss banner */\n display: none;\n }\n #top-bar .top-bar-section {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n }\n #top-bar .Polaris-Grid-Cell:nth-child(2) {\n justify-self: right;\n }\n #top-bar #scopes-note {\n display: inline-flex;\n align-items: center;\n height: 100%;\n }\n #top-bar .status-badge-option {\n gap: 8px;\n display: none;\n }\n #top-bar #status-badge-running {\n display: flex;\n }\n #graphiql {\n height: 100vh;\n display: flex;\n flex-direction: column;\n }\n #graphiql-explorer {\n flex-grow: 1;\n overflow: auto;\n }\n #top-bar #outbound-links a {\n line-height: 0;\n }\n #top-bar #outbound-links a:hover .Polaris-Text--root {\n text-decoration: underline;\n }\n #top-bar #outbound-links a span.Polaris-Text--root {\n max-width: max(12vw, 150px);\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n .with-shrunk-icon .Polaris-Icon {\n height: 1rem;\n width: 1rem;\n margin: 0.125rem;\n }\n @media only screen and (max-width: 1550px) {\n .top-bar-section-title {\n display: none;\n }\n }\n @media only screen and (max-width: 1150px) {\n #top-bar #outbound-links a span.Polaris-Text--root {\n max-width: max(12vw, 140px);\n }\n }\n @media only screen and (max-width: 1080px) {\n #top-bar .Polaris-Grid-Cell:nth-child(2) {\n justify-self: left;\n }\n }\n @media only screen and (max-width: 650px) {\n #top-bar #outbound-links a span.Polaris-Text--root {\n max-width: 17vw;\n }\n }\n </style>\n\n <script\n src=\"https://cdn.jsdelivr.net/npm/react@17/umd/react.development.js\"\n integrity=\"sha512-Vf2xGDzpqUOEIKO+X2rgTLWPY+65++WPwCHkX2nFMu9IcstumPsf/uKKRd5prX3wOu8Q0GBylRpsDB26R6ExOg==\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n src=\"https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.development.js\"\n integrity=\"sha512-Wr9OKCTtq1anK0hq5bY3X/AvDI5EflDSAh0mE9gma+4hl+kXdTJPKZ3TwLMBcrgUeoY0s3dq9JjhCQc7vddtFg==\"\n crossorigin=\"anonymous\"\n ></script>\n <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/graphiql@3.0.4/graphiql.min.css\" />\n </head>\n <body>\n <div id=\"graphiql\">\n ${renderToStaticMarkup(\n <AppProvider i18n={{}}>\n <div id=\"top-bar\">\n <Box background=\"bg-surface\" padding=\"400\">\n <BlockStack gap=\"300\">\n <Grid columns={{xs: 3, sm: 3, md: 3}}>\n <Grid.Cell columnSpan={{xs: 3, sm: 3, md: 3, lg: 7, xl: 7}}>\n <InlineStack gap=\"400\">\n <div id=\"status-badge\" className=\"top-bar-section\">\n <div className=\"status-badge-option\" id=\"status-badge-running\">\n <span className=\"top-bar-section-title\">Status: </span>\n <Badge tone=\"success\" progress=\"complete\">\n Running\n </Badge>\n </div>\n <div className=\"status-badge-option with-shrunk-icon\" id=\"status-badge-unauthorized\">\n <span className=\"top-bar-section-title\">Status: </span>\n <Badge tone=\"attention\" icon={AlertCircleIcon}>\n {unauthorizedLabel}\n </Badge>\n </div>\n <div className=\"status-badge-option with-shrunk-icon\" id=\"status-badge-disconnected\">\n <span className=\"top-bar-section-title\">Status: </span>\n <Badge tone=\"critical\" icon={DisabledIcon}>\n Disconnected\n </Badge>\n </div>\n </div>\n <div id=\"version-select\" className=\"top-bar-section\">\n <span className=\"top-bar-section-title\">API version: </span>\n <Select\n label=\"API version\"\n labelHidden\n options={apiVersions}\n value={apiVersion}\n onChange={() => {}}\n />\n </div>\n {linkPills({storeFqdn, appName, appUrl})}\n </InlineStack>\n </Grid.Cell>\n <Grid.Cell columnSpan={{xs: 3, sm: 3, md: 3, lg: 5, xl: 5}}>\n <div id=\"scopes-note\" className=\"top-bar-section\">\n <Text as=\"span\" tone=\"subdued\">\n {scopesNoteText({hasAppContext, protectMutations})}\n </Text>\n </div>\n </Grid.Cell>\n </Grid>\n <div id=\"top-error-bar\">\n <Banner tone=\"critical\" onDismiss={() => {}} icon={DisabledIcon}>\n <p>The server has been stopped. Restart it from the CLI.</p>\n </Banner>\n </div>\n </BlockStack>\n </Box>\n </div>\n </AppProvider>,\n )}\n <div id=\"graphiql-explorer\">Loading...</div>\n </div>\n <script\n src=\"https://cdn.jsdelivr.net/npm/graphiql@3.0.4/graphiql.min.js\"\n type=\"application/javascript\"\n ></script>\n <script>\n const macCommandKey = String.fromCodePoint(8984)\n const renderGraphiQL = function(apiVersion) {\n ReactDOM.render(\n React.createElement(GraphiQL, {\n fetcher: GraphiQL.createFetcher({\n url: '{{url}}/graphiql/graphql.json?key=${encodeURIComponent(key)}&api_version=' + apiVersion,\n }),\n defaultEditorToolsVisibility: true,\n {% if query %}\n query: {{query}},\n {% endif %}\n {% if variables %}\n variables: {{variables}},\n {% endif %}\n defaultTabs: [\n {query: \"${graphiqlIntroMessage\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')}\".replace(/MAC_COMMAND_KEY/g, macCommandKey)},\n {%for query in defaultQueries%}\n {query: \"{%if query.preface %}{{query.preface}}\\\\n{% endif %}{{query.query}}\", variables: \"{{query.variables}}\"},\n {%endfor%}\n ],\n isHeadersEditorEnabled: true,\n }),\n document.getElementById('graphiql-explorer'),\n )\n }\n renderGraphiQL('${apiVersion}')\n\n // Update the version when the select changes\n document.getElementById('version-select').addEventListener('change', function(event) {\n document.querySelector('#version-select .Polaris-Select__SelectedOption').innerText = event.target.value\n renderGraphiQL(event.target.value)\n })\n\n // Start out optimistic\n let serverIsLive = true\n let appIsInstalled = true\n\n const updateBadge = function() {\n const topErrorBar = document.querySelector('#graphiql #top-error-bar')\n const statusDiv = document.querySelector('#graphiql #status-badge')\n const allBadgeDivs = Array.from(statusDiv.querySelectorAll('.status-badge-option'))\n let activeBadge = 'running'\n if (!appIsInstalled) activeBadge = 'unauthorized'\n if (!serverIsLive) activeBadge = 'disconnected'\n allBadgeDivs.forEach(function(badge) {\n if (badge.id == ('status-badge-' + activeBadge)) {\n badge.style.display = 'flex'\n } else {\n badge.style.display = 'none'\n }\n })\n topErrorBar.style.display = serverIsLive ? 'none' : 'block'\n }\n const statusInterval = setInterval(updateBadge, 1000)\n\n // Warn when the server has been stopped\n const displayErrorServerStoppedTimeouts = []\n const pingInterval = setInterval(function() {\n displayErrorServerStoppedTimeouts.push(setTimeout(function() { serverIsLive = false }, 3000))\n fetch('{{url}}/graphiql/ping')\n .then(function(response) {\n if (response.status === 200) {\n while (displayErrorServerStoppedTimeouts.length > 0) {\n const timeout = displayErrorServerStoppedTimeouts.pop()\n clearTimeout(timeout)\n }\n serverIsLive = true\n } else {\n serverIsLive = false\n }\n })\n }, 2000)\n\n // Verify the current store/app connection\n setInterval(function() {\n fetch('{{ url }}/graphiql/status?key=${encodeURIComponent(key)}')\n .then(async function(response) {\n const {status, storeFqdn, appName, appUrl} = await response.json()\n appIsInstalled = status === 'OK'\n if (storeFqdn) {\n ${\n hasAppContext\n ? `document.getElementById('outbound-links').innerHTML = \\`${renderToStaticMarkup(\n <AppProvider i18n={{}}>\n {\n // eslint-disable-next-line no-template-curly-in-string\n linkPills({storeFqdn: '${storeFqdn}', appName: '${appName}', appUrl: '${appUrl}'})\n }\n </AppProvider>,\n )}\\``\n : `document.getElementById('outbound-links').innerHTML = \\`${renderToStaticMarkup(\n <AppProvider i18n={{}}>\n {\n // eslint-disable-next-line no-template-curly-in-string\n linkPills({storeFqdn: '${storeFqdn}'})\n }\n </AppProvider>,\n )}\\``\n }\n }\n })\n }, 5000)\n </script>\n </body>\n</html>\n`\n}\n\ninterface LinkPillOptions {\n storeFqdn: string\n appName?: string\n appUrl?: string\n}\n\nfunction linkPills({storeFqdn, appName, appUrl}: LinkPillOptions) {\n return (\n <div id=\"outbound-links\" className=\"top-bar-section with-shrunk-icon\">\n <span className=\"top-bar-section-title\">Store: </span>\n <Link url={`https://${storeFqdn}/admin`} target=\"_blank\">\n <Badge tone=\"info\" icon={LinkIcon} children={storeFqdn} />\n </Link>\n {appName && appUrl ? (\n <>\n <span className=\"top-bar-section-title\">App: </span>\n <Link url={appUrl} target=\"_blank\">\n <Badge tone=\"info\" icon={LinkIcon} children={appName} />\n </Link>\n </>\n ) : null}\n </div>\n )\n}\n\nfunction scopesNoteText({\n hasAppContext,\n protectMutations,\n}: {\n hasAppContext: boolean\n protectMutations: boolean\n}): string {\n if (protectMutations) {\n return MUTATIONS_BLOCKED_MESSAGE\n }\n if (hasAppContext) {\n return \"GraphiQL runs on the same access scopes you've defined in the TOML file for your app.\"\n }\n return 'GraphiQL runs with the access scopes granted to the stored app authentication for this store.'\n}\n"]}
@@ -75,6 +75,22 @@ export function jsonSchemaValidate(subject, schema, handleInvalidAdditionalPrope
75
75
  rawErrors: undefined,
76
76
  };
77
77
  }
78
+ /**
79
+ * Get a more precise type name for JSON Schema error messages.
80
+ *
81
+ * @param value - The value to get the type of.
82
+ * @returns A string representing the type (e.g., 'array', 'null', 'object').
83
+ */
84
+ function getJsonSchemaValueType(value) {
85
+ if (Array.isArray(value))
86
+ return 'array';
87
+ if (value === null)
88
+ return 'null';
89
+ return typeof value;
90
+ }
91
+ function getJsonSchemaErrorValue(subject, path) {
92
+ return path.length === 0 ? subject : getPathValue(subject, path);
93
+ }
78
94
  /**
79
95
  * Converts errors from Ajv into a zod-like format.
80
96
  *
@@ -97,15 +113,15 @@ function convertJsonSchemaErrors(rawErrors, subject, schema) {
97
113
  const expectedType = Array.isArray(error.params.type)
98
114
  ? error.params.type.join(', ')
99
115
  : error.params.type;
100
- const actualType = getPathValue(subject, path.join('.'));
101
- return { path, message: `Expected ${expectedType}, received ${typeof actualType}` };
116
+ const actualType = getJsonSchemaErrorValue(subject, path);
117
+ return { path, message: `Expected ${expectedType}, received ${getJsonSchemaValueType(actualType)}` };
102
118
  }
103
119
  if (error.keyword === 'anyOf' || error.keyword === 'oneOf') {
104
120
  return { path, message: 'Invalid input' };
105
121
  }
106
122
  if (error.params.allowedValues) {
107
123
  const allowedValues = error.params.allowedValues;
108
- const actualValue = getPathValue(subject, path.join('.'));
124
+ const actualValue = getJsonSchemaErrorValue(subject, path);
109
125
  return {
110
126
  path,
111
127
  message: `Invalid enum value. Expected ${allowedValues
@@ -116,7 +132,7 @@ function convertJsonSchemaErrors(rawErrors, subject, schema) {
116
132
  if (error.params.comparison) {
117
133
  const comparison = error.params.comparison;
118
134
  const limit = error.params.limit;
119
- const actualValue = getPathValue(subject, path.join('.'));
135
+ const actualValue = getJsonSchemaErrorValue(subject, path);
120
136
  let comparisonText = comparison;
121
137
  switch (comparison) {
122
138
  case '<=':
@@ -190,7 +206,7 @@ function simplifyUnionErrors(rawErrors, subject, schema) {
190
206
  const dottedSchemaPath = unionError.schemaPath.replace('#/', '').replace(/\//g, '.');
191
207
  const unionSchemas = getPathValue(schema, dottedSchemaPath);
192
208
  // and the slice of the subject that caused the issue
193
- const subjectValue = getPathValue(subject, unionError.instancePath.split('/').slice(1).join('.'));
209
+ const subjectValue = getJsonSchemaErrorValue(subject, unionError.instancePath.split('/').slice(1));
194
210
  if (unionSchemas !== undefined && subjectValue !== undefined) {
195
211
  // we know that none of the union schemas are correct, but for each of them we can measure how wrong they are
196
212
  const correctValuesAndErrors = unionSchemas
@@ -203,7 +219,7 @@ function simplifyUnionErrors(rawErrors, subject, schema) {
203
219
  const candidatesObjectProperties = Object.keys(candidateSchemaFromUnion.properties);
204
220
  score = candidatesObjectProperties.reduce((acc, propertyName) => {
205
221
  const subSchema = candidateSchemaFromUnion.properties[propertyName];
206
- const subjectValueSlice = getPathValue(subjectValue, propertyName);
222
+ const subjectValueSlice = getJsonSchemaErrorValue(subjectValue, [propertyName]);
207
223
  const subValidator = createAjvValidator('fail', subSchema);
208
224
  if (subValidator(subjectValueSlice)) {
209
225
  return acc + 1;
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/public/node/json-schema.ts"],"names":[],"mappings":"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","sourcesContent":["import {randomUUID} from './crypto.js'\nimport {ParseConfigurationResult} from './schema.js'\nimport {getPathValue} from '../common/object.js'\n\nimport {capitalize} from '../common/string.js'\nimport {Ajv, ErrorObject, SchemaObject, ValidateFunction} from 'ajv'\nimport $RefParser from '@apidevtools/json-schema-ref-parser'\nimport cloneDeep from 'lodash/cloneDeep.js'\n\nexport type HandleInvalidAdditionalProperties = 'strip' | 'fail'\n\ntype AjvError = ErrorObject<string, Record<string, unknown>>\n\n/**\n * Normalises a JSON Schema by standardising it's internal implementation.\n *\n * We prefer to not use $ref elements in our schemas, so we inline them; it's easier then to process errors.\n *\n * @param schema - The JSON schema (as a string) to normalise.\n * @returns The normalised JSON schema.\n */\nexport async function normaliseJsonSchema(schema: string): Promise<SchemaObject> {\n // we want to modify the schema, removing any $ref elements and inlining with their source\n const parsedSchema = JSON.parse(schema)\n await $RefParser.dereference(parsedSchema, {resolve: {external: false}})\n return parsedSchema\n}\n\nfunction createAjvValidator(\n handleInvalidAdditionalProperties: HandleInvalidAdditionalProperties,\n schema: SchemaObject,\n) {\n // allowUnionTypes: Allows types like `type: [\"string\", \"number\"]`\n if (handleInvalidAdditionalProperties === 'strip') {\n // we need to let additional properties through, so that we can strip them later\n schema.additionalProperties = true\n }\n\n const ajv = new Ajv({allowUnionTypes: true, allErrors: true, verbose: true})\n ajv.addKeyword('x-taplo')\n\n const validator = ajv.compile(schema)\n\n return validator\n}\n\nconst validatorsCache = new Map<string, ValidateFunction>()\n\n/**\n * Given a subject object and a JSON schema contract, validate the subject against the contract.\n *\n * Errors are returned in a zod-like format, and processed to better handle unions.\n *\n * @param subject - The object to validate.\n * @param schema - The JSON schema to validate against.\n * @param handleInvalidAdditionalProperties - Whether to strip or fail on invalid additional properties.\n * @param identifier - The identifier of the schema being validated, used to cache the validator.\n * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format.\n */\nexport function jsonSchemaValidate(\n subject: object,\n schema: SchemaObject,\n handleInvalidAdditionalProperties: HandleInvalidAdditionalProperties,\n identifier?: string,\n): ParseConfigurationResult<unknown> & {rawErrors?: AjvError[]} {\n const subjectToModify = cloneDeep(subject)\n\n const cacheKey = identifier ?? randomUUID()\n\n const validator = validatorsCache.get(cacheKey) ?? createAjvValidator(handleInvalidAdditionalProperties, schema)\n validatorsCache.set(cacheKey, validator)\n\n validator(subjectToModify)\n\n // Errors from the contract are post-processed to be more zod-like and to deal with unions better\n let jsonSchemaErrors\n if (validator.errors && validator.errors.length > 0) {\n jsonSchemaErrors = convertJsonSchemaErrors(validator.errors, subjectToModify, schema)\n return {\n state: 'error',\n data: undefined,\n errors: jsonSchemaErrors,\n rawErrors: validator.errors,\n }\n }\n\n if (handleInvalidAdditionalProperties === 'strip') {\n const topLevelSchemaProperties = Object.keys(schema.properties ?? {})\n // strip any properties that are not in the top level schema from subjectToModify\n Object.keys(subjectToModify).forEach((key) => {\n if (!topLevelSchemaProperties.includes(key)) {\n // this isn't actually dynamic, because key came from Object.keys\n\n delete subjectToModify[key as keyof typeof subjectToModify]\n }\n })\n }\n\n return {\n state: 'ok',\n data: subjectToModify,\n errors: undefined,\n rawErrors: undefined,\n }\n}\n\n/**\n * Converts errors from Ajv into a zod-like format.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns The errors in a zod-like format.\n */\nfunction convertJsonSchemaErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject) {\n // This reduces the number of errors by simplifying errors coming from different branches of a union\n const errors = simplifyUnionErrors(rawErrors, subject, schema)\n\n // Now we can remap errors to be more zod-like\n return errors.map((error) => {\n const path: string[] = error.instancePath.split('/').slice(1)\n if (error.params.missingProperty) {\n const missingProperty = error.params.missingProperty as string\n return {path: [...path, missingProperty], message: 'Required'}\n }\n\n if (error.params.type) {\n const expectedType = Array.isArray(error.params.type)\n ? error.params.type.join(', ')\n : (error.params.type as string)\n const actualType = getPathValue(subject, path.join('.'))\n return {path, message: `Expected ${expectedType}, received ${typeof actualType}`}\n }\n\n if (error.keyword === 'anyOf' || error.keyword === 'oneOf') {\n return {path, message: 'Invalid input'}\n }\n\n if (error.params.allowedValues) {\n const allowedValues = error.params.allowedValues as string[]\n const actualValue = getPathValue(subject, path.join('.'))\n return {\n path,\n message: `Invalid enum value. Expected ${allowedValues\n .map((value) => JSON.stringify(value))\n .join(' | ')}, received ${JSON.stringify(actualValue)}`.replace(/\"/g, \"'\"),\n }\n }\n\n if (error.params.comparison) {\n const comparison = error.params.comparison as string\n const limit = error.params.limit\n const actualValue = getPathValue(subject, path.join('.'))\n\n let comparisonText = comparison\n switch (comparison) {\n case '<=':\n comparisonText = 'less than or equal to'\n break\n case '<':\n comparisonText = 'less than'\n break\n case '>=':\n comparisonText = 'greater than or equal to'\n break\n case '>':\n comparisonText = 'greater than'\n break\n }\n\n return {\n path,\n message: capitalize(`${typeof actualValue} must be ${comparisonText} ${limit}`),\n }\n }\n\n if (error.params.additionalProperty) {\n const supportedProperties = Object.keys(error.parentSchema?.properties ?? {})\n\n // if a property was already set, remove it from here\n const alreadySetProperties = Object.keys(error.data ?? {})\n const remainingProperties = supportedProperties.filter((property) => !alreadySetProperties.includes(property))\n\n if (remainingProperties.length > 0) {\n return {\n path: [...path, error.params.additionalProperty as string],\n message: `No additional properties allowed. You can set ${remainingProperties.sort().join(', ')}.`,\n }\n }\n }\n\n return {\n path,\n message: error.message,\n }\n })\n}\n\n/**\n * If a JSON schema specifies a union (anyOf, oneOf), and the subject doesn't meet any of the 'candidates' for the\n * union, then the error list received ends up being quite long: you get an error for the union property itself, and\n * then additional errors for each of the candidate branches.\n *\n * This function simplifies the error collection. By default it strips anything other than the union error itself.\n *\n * In some cases, it can be possible to identify what the intended branch of the union was -- for instance, maybe there\n * is a discriminating field like `type` that is unique between the branches. We inspect each candidate branch and if\n * one branch is less wrong than the others -- e.g. It had a valid `type`, but problems elsewhere -- then we keep the\n * errors for that branch.\n *\n * This is complex but in practise gives much more actionable errors.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns A simplified list of errors.\n */\nfunction simplifyUnionErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject): AjvError[] {\n let errors = rawErrors\n\n const resolvedUnionErrors = new Set()\n while (true) {\n const unionError = errors.filter(\n (error) =>\n (error.keyword === 'oneOf' || error.keyword === 'anyOf') && !resolvedUnionErrors.has(error.instancePath),\n )[0]\n if (unionError === undefined) {\n break\n }\n // split errors into those sharing an instance path and those not\n const unrelatedErrors = errors.filter((error) => !error.instancePath.startsWith(unionError.instancePath))\n\n // we start by assuming only the union error itself is useful, and not the errors from the candidate schemas\n let simplifiedUnionRelatedErrors: AjvError[] = [unionError]\n\n // get the schema list from where the union issue occured\n const dottedSchemaPath = unionError.schemaPath.replace('#/', '').replace(/\\//g, '.')\n const unionSchemas = getPathValue<SchemaObject[]>(schema, dottedSchemaPath)\n // and the slice of the subject that caused the issue\n const subjectValue = getPathValue(subject, unionError.instancePath.split('/').slice(1).join('.'))\n\n if (unionSchemas !== undefined && subjectValue !== undefined) {\n // we know that none of the union schemas are correct, but for each of them we can measure how wrong they are\n const correctValuesAndErrors = unionSchemas\n .map((candidateSchemaFromUnion: SchemaObject) => {\n const candidateSchemaValidator = createAjvValidator('fail', candidateSchemaFromUnion)\n candidateSchemaValidator(subjectValue)\n\n let score = 0\n if (candidateSchemaFromUnion.type === 'object') {\n // provided the schema is an object, we can measure how many properties are good\n const candidatesObjectProperties = Object.keys(candidateSchemaFromUnion.properties)\n score = candidatesObjectProperties.reduce((acc, propertyName) => {\n const subSchema = candidateSchemaFromUnion.properties[propertyName] as SchemaObject\n const subjectValueSlice = getPathValue(subjectValue, propertyName)\n\n const subValidator = createAjvValidator('fail', subSchema)\n if (subValidator(subjectValueSlice)) {\n return acc + 1\n }\n return acc\n }, score)\n }\n\n return [score, candidateSchemaValidator.errors!] as const\n })\n .sort(([scoreA], [scoreB]) => scoreA - scoreB)\n\n if (correctValuesAndErrors.length >= 2) {\n const [bestScore, bestErrors] = correctValuesAndErrors[correctValuesAndErrors.length - 1]!\n const [penultimateScore] = correctValuesAndErrors[correctValuesAndErrors.length - 2]!\n\n if (bestScore !== penultimateScore) {\n // If there's a winner, show the errors for the best schema as they'll likely be actionable.\n // We got these through a nested schema, so we need to adjust the instance path\n simplifiedUnionRelatedErrors = [\n unionError,\n ...bestErrors.map((bestError) => ({\n ...bestError,\n instancePath: unionError.instancePath + bestError.instancePath,\n })),\n ]\n }\n }\n }\n errors = [...unrelatedErrors, ...simplifiedUnionRelatedErrors]\n\n resolvedUnionErrors.add(unionError.instancePath)\n }\n return errors\n}\n"]}
1
+ {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/public/node/json-schema.ts"],"names":[],"mappings":"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","sourcesContent":["import {randomUUID} from './crypto.js'\nimport {ParseConfigurationResult} from './schema.js'\nimport {getPathValue} from '../common/object.js'\n\nimport {capitalize} from '../common/string.js'\nimport {Ajv, ErrorObject, SchemaObject, ValidateFunction} from 'ajv'\nimport $RefParser from '@apidevtools/json-schema-ref-parser'\nimport cloneDeep from 'lodash/cloneDeep.js'\n\nexport type HandleInvalidAdditionalProperties = 'strip' | 'fail'\n\ntype AjvError = ErrorObject<string, Record<string, unknown>>\n\n/**\n * Normalises a JSON Schema by standardising it's internal implementation.\n *\n * We prefer to not use $ref elements in our schemas, so we inline them; it's easier then to process errors.\n *\n * @param schema - The JSON schema (as a string) to normalise.\n * @returns The normalised JSON schema.\n */\nexport async function normaliseJsonSchema(schema: string): Promise<SchemaObject> {\n // we want to modify the schema, removing any $ref elements and inlining with their source\n const parsedSchema = JSON.parse(schema)\n await $RefParser.dereference(parsedSchema, {resolve: {external: false}})\n return parsedSchema\n}\n\nfunction createAjvValidator(\n handleInvalidAdditionalProperties: HandleInvalidAdditionalProperties,\n schema: SchemaObject,\n) {\n // allowUnionTypes: Allows types like `type: [\"string\", \"number\"]`\n if (handleInvalidAdditionalProperties === 'strip') {\n // we need to let additional properties through, so that we can strip them later\n schema.additionalProperties = true\n }\n\n const ajv = new Ajv({allowUnionTypes: true, allErrors: true, verbose: true})\n ajv.addKeyword('x-taplo')\n\n const validator = ajv.compile(schema)\n\n return validator\n}\n\nconst validatorsCache = new Map<string, ValidateFunction>()\n\n/**\n * Given a subject object and a JSON schema contract, validate the subject against the contract.\n *\n * Errors are returned in a zod-like format, and processed to better handle unions.\n *\n * @param subject - The object to validate.\n * @param schema - The JSON schema to validate against.\n * @param handleInvalidAdditionalProperties - Whether to strip or fail on invalid additional properties.\n * @param identifier - The identifier of the schema being validated, used to cache the validator.\n * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format.\n */\nexport function jsonSchemaValidate(\n subject: object,\n schema: SchemaObject,\n handleInvalidAdditionalProperties: HandleInvalidAdditionalProperties,\n identifier?: string,\n): ParseConfigurationResult<unknown> & {rawErrors?: AjvError[]} {\n const subjectToModify = cloneDeep(subject)\n\n const cacheKey = identifier ?? randomUUID()\n\n const validator = validatorsCache.get(cacheKey) ?? createAjvValidator(handleInvalidAdditionalProperties, schema)\n validatorsCache.set(cacheKey, validator)\n\n validator(subjectToModify)\n\n // Errors from the contract are post-processed to be more zod-like and to deal with unions better\n let jsonSchemaErrors\n if (validator.errors && validator.errors.length > 0) {\n jsonSchemaErrors = convertJsonSchemaErrors(validator.errors, subjectToModify, schema)\n return {\n state: 'error',\n data: undefined,\n errors: jsonSchemaErrors,\n rawErrors: validator.errors,\n }\n }\n\n if (handleInvalidAdditionalProperties === 'strip') {\n const topLevelSchemaProperties = Object.keys(schema.properties ?? {})\n // strip any properties that are not in the top level schema from subjectToModify\n Object.keys(subjectToModify).forEach((key) => {\n if (!topLevelSchemaProperties.includes(key)) {\n // this isn't actually dynamic, because key came from Object.keys\n\n delete subjectToModify[key as keyof typeof subjectToModify]\n }\n })\n }\n\n return {\n state: 'ok',\n data: subjectToModify,\n errors: undefined,\n rawErrors: undefined,\n }\n}\n\n/**\n * Get a more precise type name for JSON Schema error messages.\n *\n * @param value - The value to get the type of.\n * @returns A string representing the type (e.g., 'array', 'null', 'object').\n */\nfunction getJsonSchemaValueType(value: unknown): string {\n if (Array.isArray(value)) return 'array'\n if (value === null) return 'null'\n return typeof value\n}\n\nfunction getJsonSchemaErrorValue(subject: object, path: string[]): unknown {\n return path.length === 0 ? subject : getPathValue(subject, path)\n}\n\n/**\n * Converts errors from Ajv into a zod-like format.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns The errors in a zod-like format.\n */\nfunction convertJsonSchemaErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject) {\n // This reduces the number of errors by simplifying errors coming from different branches of a union\n const errors = simplifyUnionErrors(rawErrors, subject, schema)\n\n // Now we can remap errors to be more zod-like\n return errors.map((error) => {\n const path: string[] = error.instancePath.split('/').slice(1)\n if (error.params.missingProperty) {\n const missingProperty = error.params.missingProperty as string\n return {path: [...path, missingProperty], message: 'Required'}\n }\n\n if (error.params.type) {\n const expectedType = Array.isArray(error.params.type)\n ? error.params.type.join(', ')\n : (error.params.type as string)\n const actualType = getJsonSchemaErrorValue(subject, path)\n return {path, message: `Expected ${expectedType}, received ${getJsonSchemaValueType(actualType)}`}\n }\n\n if (error.keyword === 'anyOf' || error.keyword === 'oneOf') {\n return {path, message: 'Invalid input'}\n }\n\n if (error.params.allowedValues) {\n const allowedValues = error.params.allowedValues as string[]\n const actualValue = getJsonSchemaErrorValue(subject, path)\n return {\n path,\n message: `Invalid enum value. Expected ${allowedValues\n .map((value) => JSON.stringify(value))\n .join(' | ')}, received ${JSON.stringify(actualValue)}`.replace(/\"/g, \"'\"),\n }\n }\n\n if (error.params.comparison) {\n const comparison = error.params.comparison as string\n const limit = error.params.limit\n const actualValue = getJsonSchemaErrorValue(subject, path)\n\n let comparisonText = comparison\n switch (comparison) {\n case '<=':\n comparisonText = 'less than or equal to'\n break\n case '<':\n comparisonText = 'less than'\n break\n case '>=':\n comparisonText = 'greater than or equal to'\n break\n case '>':\n comparisonText = 'greater than'\n break\n }\n\n return {\n path,\n message: capitalize(`${typeof actualValue} must be ${comparisonText} ${limit}`),\n }\n }\n\n if (error.params.additionalProperty) {\n const supportedProperties = Object.keys(error.parentSchema?.properties ?? {})\n\n // if a property was already set, remove it from here\n const alreadySetProperties = Object.keys(error.data ?? {})\n const remainingProperties = supportedProperties.filter((property) => !alreadySetProperties.includes(property))\n\n if (remainingProperties.length > 0) {\n return {\n path: [...path, error.params.additionalProperty as string],\n message: `No additional properties allowed. You can set ${remainingProperties.sort().join(', ')}.`,\n }\n }\n }\n\n return {\n path,\n message: error.message,\n }\n })\n}\n\n/**\n * If a JSON schema specifies a union (anyOf, oneOf), and the subject doesn't meet any of the 'candidates' for the\n * union, then the error list received ends up being quite long: you get an error for the union property itself, and\n * then additional errors for each of the candidate branches.\n *\n * This function simplifies the error collection. By default it strips anything other than the union error itself.\n *\n * In some cases, it can be possible to identify what the intended branch of the union was -- for instance, maybe there\n * is a discriminating field like `type` that is unique between the branches. We inspect each candidate branch and if\n * one branch is less wrong than the others -- e.g. It had a valid `type`, but problems elsewhere -- then we keep the\n * errors for that branch.\n *\n * This is complex but in practise gives much more actionable errors.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns A simplified list of errors.\n */\nfunction simplifyUnionErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject): AjvError[] {\n let errors = rawErrors\n\n const resolvedUnionErrors = new Set()\n while (true) {\n const unionError = errors.filter(\n (error) =>\n (error.keyword === 'oneOf' || error.keyword === 'anyOf') && !resolvedUnionErrors.has(error.instancePath),\n )[0]\n if (unionError === undefined) {\n break\n }\n // split errors into those sharing an instance path and those not\n const unrelatedErrors = errors.filter((error) => !error.instancePath.startsWith(unionError.instancePath))\n\n // we start by assuming only the union error itself is useful, and not the errors from the candidate schemas\n let simplifiedUnionRelatedErrors: AjvError[] = [unionError]\n\n // get the schema list from where the union issue occured\n const dottedSchemaPath = unionError.schemaPath.replace('#/', '').replace(/\\//g, '.')\n const unionSchemas = getPathValue<SchemaObject[]>(schema, dottedSchemaPath)\n // and the slice of the subject that caused the issue\n const subjectValue = getJsonSchemaErrorValue(subject, unionError.instancePath.split('/').slice(1))\n\n if (unionSchemas !== undefined && subjectValue !== undefined) {\n // we know that none of the union schemas are correct, but for each of them we can measure how wrong they are\n const correctValuesAndErrors = unionSchemas\n .map((candidateSchemaFromUnion: SchemaObject) => {\n const candidateSchemaValidator = createAjvValidator('fail', candidateSchemaFromUnion)\n candidateSchemaValidator(subjectValue)\n\n let score = 0\n if (candidateSchemaFromUnion.type === 'object') {\n // provided the schema is an object, we can measure how many properties are good\n const candidatesObjectProperties = Object.keys(candidateSchemaFromUnion.properties)\n score = candidatesObjectProperties.reduce((acc, propertyName) => {\n const subSchema = candidateSchemaFromUnion.properties[propertyName] as SchemaObject\n const subjectValueSlice = getJsonSchemaErrorValue(subjectValue as object, [propertyName])\n\n const subValidator = createAjvValidator('fail', subSchema)\n if (subValidator(subjectValueSlice)) {\n return acc + 1\n }\n return acc\n }, score)\n }\n\n return [score, candidateSchemaValidator.errors!] as const\n })\n .sort(([scoreA], [scoreB]) => scoreA - scoreB)\n\n if (correctValuesAndErrors.length >= 2) {\n const [bestScore, bestErrors] = correctValuesAndErrors[correctValuesAndErrors.length - 1]!\n const [penultimateScore] = correctValuesAndErrors[correctValuesAndErrors.length - 2]!\n\n if (bestScore !== penultimateScore) {\n // If there's a winner, show the errors for the best schema as they'll likely be actionable.\n // We got these through a nested schema, so we need to adjust the instance path\n simplifiedUnionRelatedErrors = [\n unionError,\n ...bestErrors.map((bestError) => ({\n ...bestError,\n instancePath: unionError.instancePath + bestError.instancePath,\n })),\n ]\n }\n }\n }\n errors = [...unrelatedErrors, ...simplifiedUnionRelatedErrors]\n\n resolvedUnionErrors.add(unionError.instancePath)\n }\n return errors\n}\n"]}
@@ -2,7 +2,7 @@ import { JsonMap } from '../../private/common/json.js';
2
2
  import { DeepRequired } from '../common/ts/deep-required.js';
3
3
  export { DeepRequired };
4
4
  type Optional<T> = T | null;
5
- export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.26";
5
+ export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.28";
6
6
  export interface Schemas {
7
7
  [MONORAIL_COMMAND_TOPIC]: {
8
8
  sensitive: {
@@ -19,6 +19,7 @@ export interface Schemas {
19
19
  public: {
20
20
  business_platform_id?: Optional<number>;
21
21
  partner_id?: Optional<number>;
22
+ store_id?: Optional<number>;
22
23
  command: string;
23
24
  project_type?: Optional<string>;
24
25
  time_start: number;
@@ -2,7 +2,7 @@ import { fetch } from './http.js';
2
2
  import { outputDebug, outputContent, outputToken } from './output.js';
3
3
  const url = 'https://monorail-edge.shopifysvc.com/v1/produce';
4
4
  // This is the topic name of the main event we log to Monorail, the command tracker
5
- export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.26';
5
+ export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.28';
6
6
  const publishedCommandNames = new Set();
7
7
  /**
8
8
  * Publishes an event to Monorail.
@@ -1 +1 @@
1
- {"version":3,"file":"monorail.js","sourceRoot":"","sources":["../../../src/public/node/monorail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAMnE,MAAM,GAAG,GAAG,iDAAiD,CAAA;AAI7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAoL7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmB,EACnB,UAA8B,EAC9B,aAAoC;IAEpC,qHAAqH;IACrH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAA;IACtC,IAAI,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACnD,IAAI,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,EAAC,GAAG,UAAU,EAAE,GAAG,aAAa,EAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,EAAE,cAAc,CAAC,CAAA;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;YAC/F,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,qCAAqC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACvE,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAC,CAAA;QACtD,CAAC;QACD,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,kCAAkC,CAAA;QAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,CAAA;QACpB,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAC,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAmB,OAAU;IACnD,MAAM,MAAM,GAAG,EAAC,GAAG,OAAO,EAAC,CAAA;IAC3B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC3C,OAAO;QACL,cAAc,EAAE,iCAAiC;QACjD,qCAAqC,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC7D,kCAAkC,EAAE,WAAW,CAAC,QAAQ,EAAE;KAC3D,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {fetch} from './http.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {DeepRequired} from '../common/ts/deep-required.js'\n\nexport {DeepRequired}\n\nconst url = 'https://monorail-edge.shopifysvc.com/v1/produce'\n\ntype Optional<T> = T | null\n\n// This is the topic name of the main event we log to Monorail, the command tracker\nexport const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.26'\n\nexport interface Schemas {\n [MONORAIL_COMMAND_TOPIC]: {\n sensitive: {\n args: string\n error_message?: Optional<string>\n app_name?: Optional<string>\n metadata?: Optional<string>\n store_fqdn?: Optional<string>\n cmd_all_environment_flags?: Optional<string>\n\n // Dev related commands\n cmd_dev_tunnel_custom?: Optional<string>\n\n // Environment\n env_plugin_installed_all?: Optional<string>\n env_shopify_variables?: Optional<string>\n }\n public: {\n business_platform_id?: Optional<number>\n partner_id?: Optional<number>\n command: string\n project_type?: Optional<string>\n time_start: number\n time_end: number\n total_time: number\n success: boolean\n api_key?: Optional<string>\n cli_version: string\n uname: string\n ruby_version: string\n node_version: string\n is_employee: boolean\n store_fqdn_hash?: Optional<string>\n store_fqdn_validated?: Optional<boolean>\n store_domain?: Optional<string>\n user_id: string\n\n // Any and all commands\n cmd_all_alias_used?: Optional<string>\n cmd_all_launcher?: Optional<string>\n cmd_all_path_override?: Optional<boolean>\n cmd_all_path_override_hash?: Optional<string>\n cmd_all_plugin?: Optional<string>\n cmd_all_topic?: Optional<string>\n cmd_all_verbose?: Optional<boolean>\n cmd_all_exit?: Optional<string>\n cmd_all_force?: Optional<boolean>\n cmd_all_last_graphql_request_id?: Optional<string>\n\n cmd_all_timing_network_ms?: Optional<number>\n cmd_all_timing_prompts_ms?: Optional<number>\n cmd_all_timing_active_ms?: Optional<number>\n\n // Auto-upgrade\n env_auto_upgrade_enabled?: Optional<boolean>\n env_auto_upgrade_accepted?: Optional<boolean>\n env_auto_upgrade_skipped_reason?: Optional<string>\n env_auto_upgrade_success?: Optional<boolean>\n\n // Any extension related command\n cmd_extensions_binary_from_source?: Optional<boolean>\n\n // Scaffolding related commands\n cmd_scaffold_required_auth?: Optional<boolean>\n cmd_scaffold_template_custom?: Optional<boolean>\n cmd_scaffold_template_flavor?: Optional<string>\n cmd_scaffold_type?: Optional<string>\n cmd_scaffold_type_category?: Optional<string>\n cmd_scaffold_type_gated?: Optional<boolean>\n cmd_scaffold_type_owner?: Optional<string>\n cmd_scaffold_used_prompts_for_type?: Optional<boolean>\n\n // Used in several but not all commands\n cmd_app_dependency_installation_skipped?: Optional<boolean>\n cmd_app_reset_used?: Optional<boolean>\n cmd_app_linked_config_used?: Optional<boolean>\n cmd_app_linked_config_name?: Optional<string>\n cmd_app_linked_config_git_tracked?: Optional<boolean>\n cmd_app_all_configs_any?: Optional<boolean>\n cmd_app_all_configs_clients?: Optional<string>\n cmd_app_linked_config_source?: Optional<string>\n cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>\n cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>\n cmd_app_deployment_mode?: Optional<string>\n cmd_app_validate_json?: Optional<boolean>\n cmd_app_validate_valid?: Optional<boolean>\n cmd_app_validate_issue_count?: Optional<number>\n cmd_app_validate_file_count?: Optional<number>\n\n // Dev related commands\n cmd_dev_tunnel_type?: Optional<string>\n cmd_dev_tunnel_custom_hash?: Optional<string>\n cmd_dev_urls_updated?: Optional<boolean>\n cmd_dev_preview_url_opened?: Optional<boolean>\n cmd_dev_graphiql_opened?: Optional<boolean>\n cmd_dev_dev_preview_toggle_used?: Optional<boolean>\n\n // Create-app related commands\n cmd_create_app_template?: Optional<string>\n cmd_create_app_template_url?: Optional<string>\n\n // Deploy related commands\n cmd_deploy_flag_message_used?: Optional<boolean>\n cmd_deploy_flag_version_used?: Optional<boolean>\n cmd_deploy_flag_source_url_used?: Optional<boolean>\n cmd_deploy_confirm_new_registrations?: Optional<number>\n cmd_deploy_confirm_updated_registrations?: Optional<number>\n cmd_deploy_confirm_removed_registrations?: Optional<number>\n cmd_deploy_confirm_cancelled?: Optional<boolean>\n cmd_deploy_confirm_time_to_complete_ms?: Optional<number>\n cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>\n cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>\n cmd_deploy_confirm_include_config_used?: Optional<boolean>\n cmd_deploy_include_config_used?: Optional<boolean>\n cmd_deploy_config_modules_breakdown?: Optional<string>\n cmd_deploy_config_modules_updated?: Optional<string>\n cmd_deploy_config_modules_added?: Optional<string>\n cmd_deploy_config_modules_deleted?: Optional<string>\n\n // Release related commands\n cmd_release_confirm_cancelled?: Optional<boolean>\n\n // App setup\n app_extensions_any?: Optional<boolean>\n app_extensions_breakdown?: Optional<string>\n app_extensions_count?: Optional<number>\n app_extensions_custom_layout?: Optional<boolean>\n app_extensions_function_any?: Optional<boolean>\n app_extensions_function_count?: Optional<number>\n app_extensions_function_custom_layout?: Optional<boolean>\n app_extensions_theme_any?: Optional<boolean>\n app_extensions_theme_count?: Optional<number>\n app_extensions_theme_custom_layout?: Optional<boolean>\n app_extensions_ui_any?: Optional<boolean>\n app_extensions_ui_count?: Optional<number>\n app_extensions_ui_custom_layout?: Optional<boolean>\n app_name_hash?: Optional<string>\n app_path_hash?: Optional<string>\n app_scopes?: Optional<string>\n app_web_backend_any?: Optional<boolean>\n app_web_backend_count?: Optional<number>\n app_web_custom_layout?: Optional<boolean>\n app_web_framework?: Optional<string>\n app_web_frontend_any?: Optional<boolean>\n app_web_frontend_count?: Optional<number>\n\n // Theme related commands\n cmd_theme_timings?: Optional<string>\n cmd_theme_errors?: Optional<string>\n cmd_theme_retries?: Optional<string>\n cmd_theme_events?: Optional<string>\n\n // Environment\n env_ci?: Optional<boolean>\n env_ci_platform?: Optional<string>\n env_device_id?: Optional<string>\n env_package_manager?: Optional<string>\n env_install_package_manager?: Optional<string>\n env_package_manager_workspaces?: Optional<boolean>\n env_plugin_installed_any_custom?: Optional<boolean>\n env_plugin_installed_shopify?: Optional<string>\n env_shell?: Optional<string>\n env_web_ide?: Optional<string>\n env_cloud?: Optional<string>\n env_is_global?: Optional<boolean>\n env_auth_method?: Optional<string>\n }\n }\n [schemaId: string]: {sensitive: JsonMap; public: JsonMap}\n}\n\n// In reality, we're normally most interested in just this from Schemas, so export it for ease of use.\n// The monorail schema itself has lots of optional values as it must be backwards-compatible. For our schema we want mandatory values instead.\nexport type MonorailEventPublic = DeepRequired<Schemas[typeof MONORAIL_COMMAND_TOPIC]['public']>\nexport type MonorailEventSensitive = Schemas[typeof MONORAIL_COMMAND_TOPIC]['sensitive']\n\ntype MonorailResult = {type: 'ok'} | {type: 'error'; message: string}\n\nconst publishedCommandNames = new Set<string>()\n\n/**\n * Publishes an event to Monorail.\n *\n * @param schemaId - The schema ID of the event to publish.\n * @param publicData - The public data to publish.\n * @param sensitiveData - The sensitive data to publish.\n * @returns A result indicating whether the event was successfully published.\n */\nexport async function publishMonorailEvent<TSchemaId extends keyof Schemas, TPayload extends Schemas[TSchemaId]>(\n schemaId: TSchemaId,\n publicData: TPayload['public'],\n sensitiveData: TPayload['sensitive'],\n): Promise<MonorailResult> {\n // If a command has already been logged, never re-log it. This is to prevent duplication caused by unexpected errors.\n const commandName = publicData.command\n if (commandName && typeof commandName === 'string') {\n if (publishedCommandNames.has(commandName)) {\n return {type: 'ok'}\n }\n publishedCommandNames.add(commandName)\n }\n\n try {\n const currentTime = new Date().getTime()\n const payload = {...publicData, ...sensitiveData}\n const body = JSON.stringify({schema_id: schemaId, payload})\n const headers = buildHeaders(currentTime)\n\n const response = await fetch(url, {method: 'POST', body, headers}, 'non-blocking')\n\n if (response.status === 200) {\n outputDebug(outputContent`Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`)\n return {type: 'ok'}\n } else {\n outputDebug(`Failed to report usage analytics: ${response.statusText}`)\n return {type: 'error', message: response.statusText}\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return {type: 'error', message}\n }\n}\n\n/**\n * Sanitizies the api_key from the payload and returns a new hash.\n *\n * @param payload - The public and sensitive data.\n * @returns A copy of the payload with the api_key sanitized.\n */\nfunction sanitizePayload<T extends object>(payload: T): T {\n const result = {...payload}\n if ('api_key' in result) {\n result.api_key = '****'\n }\n\n return result\n}\n\nconst buildHeaders = (currentTime: number) => {\n return {\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Monorail-Edge-Event-Created-At-Ms': currentTime.toString(),\n 'X-Monorail-Edge-Event-Sent-At-Ms': currentTime.toString(),\n }\n}\n"]}
1
+ {"version":3,"file":"monorail.js","sourceRoot":"","sources":["../../../src/public/node/monorail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAMnE,MAAM,GAAG,GAAG,iDAAiD,CAAA;AAI7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAqL7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmB,EACnB,UAA8B,EAC9B,aAAoC;IAEpC,qHAAqH;IACrH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAA;IACtC,IAAI,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACnD,IAAI,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,EAAC,GAAG,UAAU,EAAE,GAAG,aAAa,EAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,EAAE,cAAc,CAAC,CAAA;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;YAC/F,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,qCAAqC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACvE,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAC,CAAA;QACtD,CAAC;QACD,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,kCAAkC,CAAA;QAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,CAAA;QACpB,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAC,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAmB,OAAU;IACnD,MAAM,MAAM,GAAG,EAAC,GAAG,OAAO,EAAC,CAAA;IAC3B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC3C,OAAO;QACL,cAAc,EAAE,iCAAiC;QACjD,qCAAqC,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC7D,kCAAkC,EAAE,WAAW,CAAC,QAAQ,EAAE;KAC3D,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {fetch} from './http.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {DeepRequired} from '../common/ts/deep-required.js'\n\nexport {DeepRequired}\n\nconst url = 'https://monorail-edge.shopifysvc.com/v1/produce'\n\ntype Optional<T> = T | null\n\n// This is the topic name of the main event we log to Monorail, the command tracker\nexport const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.28'\n\nexport interface Schemas {\n [MONORAIL_COMMAND_TOPIC]: {\n sensitive: {\n args: string\n error_message?: Optional<string>\n app_name?: Optional<string>\n metadata?: Optional<string>\n store_fqdn?: Optional<string>\n cmd_all_environment_flags?: Optional<string>\n\n // Dev related commands\n cmd_dev_tunnel_custom?: Optional<string>\n\n // Environment\n env_plugin_installed_all?: Optional<string>\n env_shopify_variables?: Optional<string>\n }\n public: {\n business_platform_id?: Optional<number>\n partner_id?: Optional<number>\n store_id?: Optional<number>\n command: string\n project_type?: Optional<string>\n time_start: number\n time_end: number\n total_time: number\n success: boolean\n api_key?: Optional<string>\n cli_version: string\n uname: string\n ruby_version: string\n node_version: string\n is_employee: boolean\n store_fqdn_hash?: Optional<string>\n store_fqdn_validated?: Optional<boolean>\n store_domain?: Optional<string>\n user_id: string\n\n // Any and all commands\n cmd_all_alias_used?: Optional<string>\n cmd_all_launcher?: Optional<string>\n cmd_all_path_override?: Optional<boolean>\n cmd_all_path_override_hash?: Optional<string>\n cmd_all_plugin?: Optional<string>\n cmd_all_topic?: Optional<string>\n cmd_all_verbose?: Optional<boolean>\n cmd_all_exit?: Optional<string>\n cmd_all_force?: Optional<boolean>\n cmd_all_last_graphql_request_id?: Optional<string>\n\n cmd_all_timing_network_ms?: Optional<number>\n cmd_all_timing_prompts_ms?: Optional<number>\n cmd_all_timing_active_ms?: Optional<number>\n\n // Auto-upgrade\n env_auto_upgrade_enabled?: Optional<boolean>\n env_auto_upgrade_accepted?: Optional<boolean>\n env_auto_upgrade_skipped_reason?: Optional<string>\n env_auto_upgrade_success?: Optional<boolean>\n\n // Any extension related command\n cmd_extensions_binary_from_source?: Optional<boolean>\n\n // Scaffolding related commands\n cmd_scaffold_required_auth?: Optional<boolean>\n cmd_scaffold_template_custom?: Optional<boolean>\n cmd_scaffold_template_flavor?: Optional<string>\n cmd_scaffold_type?: Optional<string>\n cmd_scaffold_type_category?: Optional<string>\n cmd_scaffold_type_gated?: Optional<boolean>\n cmd_scaffold_type_owner?: Optional<string>\n cmd_scaffold_used_prompts_for_type?: Optional<boolean>\n\n // Used in several but not all commands\n cmd_app_dependency_installation_skipped?: Optional<boolean>\n cmd_app_reset_used?: Optional<boolean>\n cmd_app_linked_config_used?: Optional<boolean>\n cmd_app_linked_config_name?: Optional<string>\n cmd_app_linked_config_git_tracked?: Optional<boolean>\n cmd_app_all_configs_any?: Optional<boolean>\n cmd_app_all_configs_clients?: Optional<string>\n cmd_app_linked_config_source?: Optional<string>\n cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>\n cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>\n cmd_app_deployment_mode?: Optional<string>\n cmd_app_validate_json?: Optional<boolean>\n cmd_app_validate_valid?: Optional<boolean>\n cmd_app_validate_issue_count?: Optional<number>\n cmd_app_validate_file_count?: Optional<number>\n\n // Dev related commands\n cmd_dev_tunnel_type?: Optional<string>\n cmd_dev_tunnel_custom_hash?: Optional<string>\n cmd_dev_urls_updated?: Optional<boolean>\n cmd_dev_preview_url_opened?: Optional<boolean>\n cmd_dev_graphiql_opened?: Optional<boolean>\n cmd_dev_dev_preview_toggle_used?: Optional<boolean>\n\n // Create-app related commands\n cmd_create_app_template?: Optional<string>\n cmd_create_app_template_url?: Optional<string>\n\n // Deploy related commands\n cmd_deploy_flag_message_used?: Optional<boolean>\n cmd_deploy_flag_version_used?: Optional<boolean>\n cmd_deploy_flag_source_url_used?: Optional<boolean>\n cmd_deploy_confirm_new_registrations?: Optional<number>\n cmd_deploy_confirm_updated_registrations?: Optional<number>\n cmd_deploy_confirm_removed_registrations?: Optional<number>\n cmd_deploy_confirm_cancelled?: Optional<boolean>\n cmd_deploy_confirm_time_to_complete_ms?: Optional<number>\n cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>\n cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>\n cmd_deploy_confirm_include_config_used?: Optional<boolean>\n cmd_deploy_include_config_used?: Optional<boolean>\n cmd_deploy_config_modules_breakdown?: Optional<string>\n cmd_deploy_config_modules_updated?: Optional<string>\n cmd_deploy_config_modules_added?: Optional<string>\n cmd_deploy_config_modules_deleted?: Optional<string>\n\n // Release related commands\n cmd_release_confirm_cancelled?: Optional<boolean>\n\n // App setup\n app_extensions_any?: Optional<boolean>\n app_extensions_breakdown?: Optional<string>\n app_extensions_count?: Optional<number>\n app_extensions_custom_layout?: Optional<boolean>\n app_extensions_function_any?: Optional<boolean>\n app_extensions_function_count?: Optional<number>\n app_extensions_function_custom_layout?: Optional<boolean>\n app_extensions_theme_any?: Optional<boolean>\n app_extensions_theme_count?: Optional<number>\n app_extensions_theme_custom_layout?: Optional<boolean>\n app_extensions_ui_any?: Optional<boolean>\n app_extensions_ui_count?: Optional<number>\n app_extensions_ui_custom_layout?: Optional<boolean>\n app_name_hash?: Optional<string>\n app_path_hash?: Optional<string>\n app_scopes?: Optional<string>\n app_web_backend_any?: Optional<boolean>\n app_web_backend_count?: Optional<number>\n app_web_custom_layout?: Optional<boolean>\n app_web_framework?: Optional<string>\n app_web_frontend_any?: Optional<boolean>\n app_web_frontend_count?: Optional<number>\n\n // Theme related commands\n cmd_theme_timings?: Optional<string>\n cmd_theme_errors?: Optional<string>\n cmd_theme_retries?: Optional<string>\n cmd_theme_events?: Optional<string>\n\n // Environment\n env_ci?: Optional<boolean>\n env_ci_platform?: Optional<string>\n env_device_id?: Optional<string>\n env_package_manager?: Optional<string>\n env_install_package_manager?: Optional<string>\n env_package_manager_workspaces?: Optional<boolean>\n env_plugin_installed_any_custom?: Optional<boolean>\n env_plugin_installed_shopify?: Optional<string>\n env_shell?: Optional<string>\n env_web_ide?: Optional<string>\n env_cloud?: Optional<string>\n env_is_global?: Optional<boolean>\n env_auth_method?: Optional<string>\n }\n }\n [schemaId: string]: {sensitive: JsonMap; public: JsonMap}\n}\n\n// In reality, we're normally most interested in just this from Schemas, so export it for ease of use.\n// The monorail schema itself has lots of optional values as it must be backwards-compatible. For our schema we want mandatory values instead.\nexport type MonorailEventPublic = DeepRequired<Schemas[typeof MONORAIL_COMMAND_TOPIC]['public']>\nexport type MonorailEventSensitive = Schemas[typeof MONORAIL_COMMAND_TOPIC]['sensitive']\n\ntype MonorailResult = {type: 'ok'} | {type: 'error'; message: string}\n\nconst publishedCommandNames = new Set<string>()\n\n/**\n * Publishes an event to Monorail.\n *\n * @param schemaId - The schema ID of the event to publish.\n * @param publicData - The public data to publish.\n * @param sensitiveData - The sensitive data to publish.\n * @returns A result indicating whether the event was successfully published.\n */\nexport async function publishMonorailEvent<TSchemaId extends keyof Schemas, TPayload extends Schemas[TSchemaId]>(\n schemaId: TSchemaId,\n publicData: TPayload['public'],\n sensitiveData: TPayload['sensitive'],\n): Promise<MonorailResult> {\n // If a command has already been logged, never re-log it. This is to prevent duplication caused by unexpected errors.\n const commandName = publicData.command\n if (commandName && typeof commandName === 'string') {\n if (publishedCommandNames.has(commandName)) {\n return {type: 'ok'}\n }\n publishedCommandNames.add(commandName)\n }\n\n try {\n const currentTime = new Date().getTime()\n const payload = {...publicData, ...sensitiveData}\n const body = JSON.stringify({schema_id: schemaId, payload})\n const headers = buildHeaders(currentTime)\n\n const response = await fetch(url, {method: 'POST', body, headers}, 'non-blocking')\n\n if (response.status === 200) {\n outputDebug(outputContent`Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`)\n return {type: 'ok'}\n } else {\n outputDebug(`Failed to report usage analytics: ${response.statusText}`)\n return {type: 'error', message: response.statusText}\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return {type: 'error', message}\n }\n}\n\n/**\n * Sanitizies the api_key from the payload and returns a new hash.\n *\n * @param payload - The public and sensitive data.\n * @returns A copy of the payload with the api_key sanitized.\n */\nfunction sanitizePayload<T extends object>(payload: T): T {\n const result = {...payload}\n if ('api_key' in result) {\n result.api_key = '****'\n }\n\n return result\n}\n\nconst buildHeaders = (currentTime: number) => {\n return {\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Monorail-Edge-Event-Created-At-Ms': currentTime.toString(),\n 'X-Monorail-Edge-Event-Sent-At-Ms': currentTime.toString(),\n }\n}\n"]}
@@ -119,9 +119,10 @@ export declare function ensureAuthenticatedThemes(store: string, password: strin
119
119
  * Ensure that we have a valid session to access the Business Platform API.
120
120
  *
121
121
  * @param scopes - Optional array of extra scopes to authenticate with.
122
+ * @param options - Optional extra options to use.
122
123
  * @returns The access token for the Business Platform API.
123
124
  */
124
- export declare function ensureAuthenticatedBusinessPlatform(scopes?: BusinessPlatformScope[]): Promise<string>;
125
+ export declare function ensureAuthenticatedBusinessPlatform(scopes?: BusinessPlatformScope[], options?: EnsureAuthenticatedAdditionalOptions): Promise<string>;
125
126
  /**
126
127
  * Logout from Shopify.
127
128
  *
@@ -176,13 +176,14 @@ ${outputToken.json(scopes)}
176
176
  * Ensure that we have a valid session to access the Business Platform API.
177
177
  *
178
178
  * @param scopes - Optional array of extra scopes to authenticate with.
179
+ * @param options - Optional extra options to use.
179
180
  * @returns The access token for the Business Platform API.
180
181
  */
181
- export async function ensureAuthenticatedBusinessPlatform(scopes = []) {
182
+ export async function ensureAuthenticatedBusinessPlatform(scopes = [], options = {}) {
182
183
  outputDebug(outputContent `Ensuring that the user is authenticated with the Business Platform API with the following scopes:
183
184
  ${outputToken.json(scopes)}
184
185
  `);
185
- const tokens = await ensureAuthenticated({ businessPlatformApi: { scopes } }, process.env);
186
+ const tokens = await ensureAuthenticated({ businessPlatformApi: { scopes } }, process.env, options);
186
187
  if (!tokens.businessPlatform) {
187
188
  throw new BugError('No business-platform token found after ensuring authenticated');
188
189
  }
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/public/node/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {shopifyFetch} from './http.js'\nimport {nonRandomUUID} from './crypto.js'\nimport {getAppAutomationToken} from './environment.js'\nimport {AbortError, BugError} from './error.js'\nimport {outputContent, outputToken, outputDebug} from './output.js'\nimport * as sessionStore from '../../private/node/session/store.js'\nimport {\n exchangeCustomPartnerToken,\n exchangeAppAutomationTokenForAppManagementAccessToken,\n exchangeAppAutomationTokenForBusinessPlatformAccessToken,\n} from '../../private/node/session/exchange.js'\nimport {\n AdminAPIScope,\n AppManagementAPIScope,\n BusinessPlatformScope,\n EnsureAuthenticatedAdditionalOptions,\n PartnersAPIScope,\n StorefrontRendererScope,\n ensureAuthenticated,\n setLastSeenAuthMethod,\n setLastSeenUserIdAfterAuth,\n} from '../../private/node/session.js'\nimport {isThemeAccessSession} from '../../private/node/api/rest.js'\n\n/**\n * Session Object to access the Admin API, includes the token and the store FQDN.\n */\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\n/**\n * Session Object for Partners API and App Management API access.\n */\nexport interface Session {\n token: string\n businessPlatformToken: string\n accountInfo: AccountInfo\n userId: string\n}\n\nexport type AccountInfo = UserAccountInfo | ServiceAccountInfo | UnknownAccountInfo\n\n/**\n * Records the user ID that should be attached to command analytics for this process.\n *\n * @param userId - User identifier to report on the command analytics event.\n */\nexport function setLastSeenUserId(userId: string): void {\n setLastSeenUserIdAfterAuth(userId)\n}\n\ninterface UserAccountInfo {\n type: 'UserAccount'\n email: string\n}\n\ninterface ServiceAccountInfo {\n type: 'ServiceAccount'\n orgName: string\n}\n\ninterface UnknownAccountInfo {\n type: 'UnknownAccount'\n}\n\n/**\n * Type guard to check if an account is a UserAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a UserAccount.\n */\nexport function isUserAccount(account: AccountInfo): account is UserAccountInfo {\n return account.type === 'UserAccount'\n}\n\n/**\n * Type guard to check if an account is a ServiceAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a ServiceAccount.\n */\nexport function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo {\n return account.type === 'ServiceAccount'\n}\n\n/**\n * Ensure that we have a valid session with no particular scopes.\n *\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The user ID.\n */\nexport async function ensureAuthenticatedUser(\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with no particular scopes`)\n const tokens = await ensureAuthenticated({}, env, options)\n return {userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(\n scopes: PartnersAPIScope[] = [],\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{token: string; userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const envToken = getAppAutomationToken()\n if (envToken) {\n const result = await exchangeCustomPartnerToken(envToken)\n return {token: result.accessToken, userId: result.userId}\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}}, env, options)\n if (!tokens.partners) {\n throw new BugError('No partners token found after ensuring authenticated')\n }\n return {token: tokens.partners, userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the App Management API.\n *\n * @param options - Optional extra options to use.\n * @param appManagementScopes - Optional array of extra scopes to authenticate with.\n * @param businessPlatformScopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @returns The access token for the App Management API.\n */\nexport async function ensureAuthenticatedAppManagementAndBusinessPlatform(\n options: EnsureAuthenticatedAdditionalOptions = {},\n appManagementScopes: AppManagementAPIScope[] = [],\n businessPlatformScopes: BusinessPlatformScope[] = [],\n env = process.env,\n): Promise<{appManagementToken: string; userId: string; businessPlatformToken: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the App Management API with the following scopes:\n${outputToken.json(appManagementScopes)}\n`)\n\n const envToken = getAppAutomationToken()\n if (envToken) {\n const appManagmentToken = await exchangeAppAutomationTokenForAppManagementAccessToken(envToken)\n const businessPlatformToken = await exchangeAppAutomationTokenForBusinessPlatformAccessToken(envToken)\n\n return {\n appManagementToken: appManagmentToken.accessToken,\n userId: appManagmentToken.userId,\n businessPlatformToken: businessPlatformToken.accessToken,\n }\n }\n\n const tokens = await ensureAuthenticated(\n {appManagementApi: {scopes: appManagementScopes}, businessPlatformApi: {scopes: businessPlatformScopes}},\n env,\n options,\n )\n if (!tokens.appManagement || !tokens.businessPlatform) {\n throw new BugError('No App Management or Business Platform token found after ensuring authenticated')\n }\n\n return {\n appManagementToken: tokens.appManagement,\n userId: tokens.userId,\n businessPlatformToken: tokens.businessPlatform,\n }\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param password - Optional password to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(\n scopes: StorefrontRendererScope[] = [],\n password: string | undefined = undefined,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<string> {\n if (password) {\n const session = {token: password, storeFqdn: ''}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return password\n }\n\n outputDebug(outputContent`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}}, process.env, options)\n if (!tokens.storefront) {\n throw new BugError('No storefront token found after ensuring authenticated')\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n *\n * @param store - Store fqdn to request auth for.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdmin(\n store: string,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${outputToken.raw(\n store,\n )}:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}}, process.env, {\n ...options,\n })\n if (!tokens.admin) {\n throw new BugError('No admin token found after ensuring authenticated')\n }\n return tokens.admin\n}\n\n/**\n * Ensure that we have a valid session to access the Theme API.\n * If a password is provided, that token will be used against Theme Access API.\n * Otherwise, it will ensure that the user is authenticated with the Admin API.\n *\n * @param store - Store fqdn to request auth for.\n * @param password - Password generated from Theme Access app.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token and store.\n */\nexport async function ensureAuthenticatedThemes(\n store: string,\n password: string | undefined,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Theme API with the following scopes:\n${outputToken.json(scopes)}\n`)\n if (password) {\n const session = {token: password, storeFqdn: store}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return session\n }\n return ensureAuthenticatedAdmin(store, scopes, options)\n}\n\n/**\n * Ensure that we have a valid session to access the Business Platform API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Business Platform API.\n */\nexport async function ensureAuthenticatedBusinessPlatform(scopes: BusinessPlatformScope[] = []): Promise<string> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Business Platform API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({businessPlatformApi: {scopes}}, process.env)\n if (!tokens.businessPlatform) {\n throw new BugError('No business-platform token found after ensuring authenticated')\n }\n return tokens.businessPlatform\n}\n\n/**\n * Logout from Shopify.\n *\n * @returns A promise that resolves when the logout is complete.\n */\nexport function logout(): Promise<void> {\n return sessionStore.remove()\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store, with access on behalf of the app.\n *\n * See `ensureAuthenticatedAdmin` for access on behalf of a user.\n *\n * @param storeFqdn - Store fqdn to request auth for.\n * @param clientId - Client ID of the app.\n * @param clientSecret - Client secret of the app.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdminAsApp(\n storeFqdn: string,\n clientId: string,\n clientSecret: string,\n): Promise<AdminSession> {\n const bodyData = {\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: 'client_credentials',\n }\n const tokenResponse = await shopifyFetch(\n `https://${storeFqdn}/admin/oauth/access_token`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(bodyData),\n },\n 'slow-request',\n )\n\n const body = await tokenResponse.text()\n\n if (tokenResponse.status === 400) {\n if (body.includes('app_not_installed')) {\n throw new AbortError(\n outputContent`App is not installed on ${outputToken.green(\n storeFqdn,\n )}. Try running ${outputToken.genericShellCommand(`shopify app dev`)} to connect your app to the shop.`,\n )\n }\n throw new AbortError(\n `Failed to get access token for app ${clientId} on store ${storeFqdn}: ${tokenResponse.statusText}`,\n )\n }\n try {\n const tokenJson = JSON.parse(body) as {access_token: string}\n return {token: tokenJson.access_token, storeFqdn}\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new AbortError(\n `Received invalid response from admin authentication service (HTTP ${tokenResponse.status}).`,\n 'The response could not be parsed as JSON. The service may be temporarily unavailable. Please try again.',\n )\n }\n throw error\n }\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/public/node/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {shopifyFetch} from './http.js'\nimport {nonRandomUUID} from './crypto.js'\nimport {getAppAutomationToken} from './environment.js'\nimport {AbortError, BugError} from './error.js'\nimport {outputContent, outputToken, outputDebug} from './output.js'\nimport * as sessionStore from '../../private/node/session/store.js'\nimport {\n exchangeCustomPartnerToken,\n exchangeAppAutomationTokenForAppManagementAccessToken,\n exchangeAppAutomationTokenForBusinessPlatformAccessToken,\n} from '../../private/node/session/exchange.js'\nimport {\n AdminAPIScope,\n AppManagementAPIScope,\n BusinessPlatformScope,\n EnsureAuthenticatedAdditionalOptions,\n PartnersAPIScope,\n StorefrontRendererScope,\n ensureAuthenticated,\n setLastSeenAuthMethod,\n setLastSeenUserIdAfterAuth,\n} from '../../private/node/session.js'\nimport {isThemeAccessSession} from '../../private/node/api/rest.js'\n\n/**\n * Session Object to access the Admin API, includes the token and the store FQDN.\n */\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\n/**\n * Session Object for Partners API and App Management API access.\n */\nexport interface Session {\n token: string\n businessPlatformToken: string\n accountInfo: AccountInfo\n userId: string\n}\n\nexport type AccountInfo = UserAccountInfo | ServiceAccountInfo | UnknownAccountInfo\n\n/**\n * Records the user ID that should be attached to command analytics for this process.\n *\n * @param userId - User identifier to report on the command analytics event.\n */\nexport function setLastSeenUserId(userId: string): void {\n setLastSeenUserIdAfterAuth(userId)\n}\n\ninterface UserAccountInfo {\n type: 'UserAccount'\n email: string\n}\n\ninterface ServiceAccountInfo {\n type: 'ServiceAccount'\n orgName: string\n}\n\ninterface UnknownAccountInfo {\n type: 'UnknownAccount'\n}\n\n/**\n * Type guard to check if an account is a UserAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a UserAccount.\n */\nexport function isUserAccount(account: AccountInfo): account is UserAccountInfo {\n return account.type === 'UserAccount'\n}\n\n/**\n * Type guard to check if an account is a ServiceAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a ServiceAccount.\n */\nexport function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo {\n return account.type === 'ServiceAccount'\n}\n\n/**\n * Ensure that we have a valid session with no particular scopes.\n *\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The user ID.\n */\nexport async function ensureAuthenticatedUser(\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with no particular scopes`)\n const tokens = await ensureAuthenticated({}, env, options)\n return {userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(\n scopes: PartnersAPIScope[] = [],\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{token: string; userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const envToken = getAppAutomationToken()\n if (envToken) {\n const result = await exchangeCustomPartnerToken(envToken)\n return {token: result.accessToken, userId: result.userId}\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}}, env, options)\n if (!tokens.partners) {\n throw new BugError('No partners token found after ensuring authenticated')\n }\n return {token: tokens.partners, userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the App Management API.\n *\n * @param options - Optional extra options to use.\n * @param appManagementScopes - Optional array of extra scopes to authenticate with.\n * @param businessPlatformScopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @returns The access token for the App Management API.\n */\nexport async function ensureAuthenticatedAppManagementAndBusinessPlatform(\n options: EnsureAuthenticatedAdditionalOptions = {},\n appManagementScopes: AppManagementAPIScope[] = [],\n businessPlatformScopes: BusinessPlatformScope[] = [],\n env = process.env,\n): Promise<{appManagementToken: string; userId: string; businessPlatformToken: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the App Management API with the following scopes:\n${outputToken.json(appManagementScopes)}\n`)\n\n const envToken = getAppAutomationToken()\n if (envToken) {\n const appManagmentToken = await exchangeAppAutomationTokenForAppManagementAccessToken(envToken)\n const businessPlatformToken = await exchangeAppAutomationTokenForBusinessPlatformAccessToken(envToken)\n\n return {\n appManagementToken: appManagmentToken.accessToken,\n userId: appManagmentToken.userId,\n businessPlatformToken: businessPlatformToken.accessToken,\n }\n }\n\n const tokens = await ensureAuthenticated(\n {appManagementApi: {scopes: appManagementScopes}, businessPlatformApi: {scopes: businessPlatformScopes}},\n env,\n options,\n )\n if (!tokens.appManagement || !tokens.businessPlatform) {\n throw new BugError('No App Management or Business Platform token found after ensuring authenticated')\n }\n\n return {\n appManagementToken: tokens.appManagement,\n userId: tokens.userId,\n businessPlatformToken: tokens.businessPlatform,\n }\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param password - Optional password to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(\n scopes: StorefrontRendererScope[] = [],\n password: string | undefined = undefined,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<string> {\n if (password) {\n const session = {token: password, storeFqdn: ''}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return password\n }\n\n outputDebug(outputContent`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}}, process.env, options)\n if (!tokens.storefront) {\n throw new BugError('No storefront token found after ensuring authenticated')\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n *\n * @param store - Store fqdn to request auth for.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdmin(\n store: string,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${outputToken.raw(\n store,\n )}:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}}, process.env, {\n ...options,\n })\n if (!tokens.admin) {\n throw new BugError('No admin token found after ensuring authenticated')\n }\n return tokens.admin\n}\n\n/**\n * Ensure that we have a valid session to access the Theme API.\n * If a password is provided, that token will be used against Theme Access API.\n * Otherwise, it will ensure that the user is authenticated with the Admin API.\n *\n * @param store - Store fqdn to request auth for.\n * @param password - Password generated from Theme Access app.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token and store.\n */\nexport async function ensureAuthenticatedThemes(\n store: string,\n password: string | undefined,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Theme API with the following scopes:\n${outputToken.json(scopes)}\n`)\n if (password) {\n const session = {token: password, storeFqdn: store}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return session\n }\n return ensureAuthenticatedAdmin(store, scopes, options)\n}\n\n/**\n * Ensure that we have a valid session to access the Business Platform API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token for the Business Platform API.\n */\nexport async function ensureAuthenticatedBusinessPlatform(\n scopes: BusinessPlatformScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<string> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Business Platform API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({businessPlatformApi: {scopes}}, process.env, options)\n if (!tokens.businessPlatform) {\n throw new BugError('No business-platform token found after ensuring authenticated')\n }\n return tokens.businessPlatform\n}\n\n/**\n * Logout from Shopify.\n *\n * @returns A promise that resolves when the logout is complete.\n */\nexport function logout(): Promise<void> {\n return sessionStore.remove()\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store, with access on behalf of the app.\n *\n * See `ensureAuthenticatedAdmin` for access on behalf of a user.\n *\n * @param storeFqdn - Store fqdn to request auth for.\n * @param clientId - Client ID of the app.\n * @param clientSecret - Client secret of the app.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdminAsApp(\n storeFqdn: string,\n clientId: string,\n clientSecret: string,\n): Promise<AdminSession> {\n const bodyData = {\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: 'client_credentials',\n }\n const tokenResponse = await shopifyFetch(\n `https://${storeFqdn}/admin/oauth/access_token`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(bodyData),\n },\n 'slow-request',\n )\n\n const body = await tokenResponse.text()\n\n if (tokenResponse.status === 400) {\n if (body.includes('app_not_installed')) {\n throw new AbortError(\n outputContent`App is not installed on ${outputToken.green(\n storeFqdn,\n )}. Try running ${outputToken.genericShellCommand(`shopify app dev`)} to connect your app to the shop.`,\n )\n }\n throw new AbortError(\n `Failed to get access token for app ${clientId} on store ${storeFqdn}: ${tokenResponse.statusText}`,\n )\n }\n try {\n const tokenJson = JSON.parse(body) as {access_token: string}\n return {token: tokenJson.access_token, storeFqdn}\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new AbortError(\n `Received invalid response from admin authentication service (HTTP ${tokenResponse.status}).`,\n 'The response could not be parsed as JSON. The service may be temporarily unavailable. Please try again.',\n )\n }\n throw error\n }\n}\n"]}