@shopify/cli-kit 3.6.2 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +61 -0
- package/dist/analytics.d.ts +11 -1
- package/dist/analytics.js +33 -23
- package/dist/analytics.js.map +1 -1
- package/dist/api/admin.js.map +1 -1
- package/dist/api/common.d.ts +1 -1
- package/dist/api/common.js +1 -1
- package/dist/api/common.js.map +1 -1
- package/dist/api/graphql/extension_specifications.js.map +1 -1
- package/dist/api/graphql/functions/app_function_set.d.ts +9 -23
- package/dist/api/graphql/functions/app_function_set.js +18 -27
- package/dist/api/graphql/functions/app_function_set.js.map +1 -1
- package/dist/api/graphql/functions/upload_url_generate.d.ts +12 -0
- package/dist/api/graphql/functions/upload_url_generate.js +11 -0
- package/dist/api/graphql/functions/upload_url_generate.js.map +1 -0
- package/dist/api/graphql/get_urls.d.ts +10 -0
- package/dist/api/graphql/get_urls.js +10 -0
- package/dist/api/graphql/get_urls.js.map +1 -0
- package/dist/api/graphql/index.d.ts +19 -14
- package/dist/api/graphql/index.js +19 -14
- package/dist/api/graphql/index.js.map +1 -1
- package/dist/api/graphql/update_draft.js.map +1 -1
- package/dist/api/graphql/update_urls.d.ts +2 -2
- package/dist/api/graphql/update_urls.js +2 -2
- package/dist/api/graphql/update_urls.js.map +1 -1
- package/dist/array.d.ts +1 -1
- package/dist/constants.d.ts +3 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/content-tokens.d.ts +44 -0
- package/dist/content-tokens.js +103 -0
- package/dist/content-tokens.js.map +1 -0
- package/dist/environment/local.d.ts +19 -2
- package/dist/environment/local.js +45 -5
- package/dist/environment/local.js.map +1 -1
- package/dist/environment/utilities.d.ts +4 -0
- package/dist/environment/utilities.js +9 -0
- package/dist/environment/utilities.js.map +1 -1
- package/dist/error.d.ts +4 -4
- package/dist/error.js +16 -4
- package/dist/error.js.map +1 -1
- package/dist/file.d.ts +9 -1
- package/dist/file.js +15 -2
- package/dist/file.js.map +1 -1
- package/dist/git.js.map +1 -1
- package/dist/github.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +180 -12
- package/dist/metadata.js +39 -6
- package/dist/metadata.js.map +1 -1
- package/dist/monorail.d.ts +48 -1
- package/dist/monorail.js +2 -1
- package/dist/monorail.js.map +1 -1
- package/dist/node/archiver.js +1 -0
- package/dist/node/archiver.js.map +1 -1
- package/dist/node/base-command.d.ts +11 -1
- package/dist/node/base-command.js +19 -4
- package/dist/node/base-command.js.map +1 -1
- package/dist/node/checksum.js.map +1 -1
- package/dist/node/cli.js +2 -2
- package/dist/node/cli.js.map +1 -1
- package/dist/node/dot-env.d.ts +9 -0
- package/dist/node/dot-env.js +31 -0
- package/dist/node/dot-env.js.map +1 -1
- package/dist/node/error-handler.d.ts +14 -2
- package/dist/node/error-handler.js +58 -13
- package/dist/node/error-handler.js.map +1 -1
- package/dist/node/hooks/prerun.js +1 -1
- package/dist/node/hooks/prerun.js.map +1 -1
- package/dist/node/node-package-manager.d.ts +12 -18
- package/dist/node/node-package-manager.js +23 -14
- package/dist/node/node-package-manager.js.map +1 -1
- package/dist/node/ruby.js +2 -1
- package/dist/node/ruby.js.map +1 -1
- package/dist/output.d.ts +22 -43
- package/dist/output.js +31 -91
- package/dist/output.js.map +1 -1
- package/dist/path.d.ts +1 -0
- package/dist/plugins/tunnel.d.ts +40 -0
- package/dist/plugins/tunnel.js +11 -0
- package/dist/plugins/tunnel.js.map +1 -0
- package/dist/plugins.d.ts +11 -13
- package/dist/plugins.js +0 -1
- package/dist/plugins.js.map +1 -1
- package/dist/session/authorize.js +1 -1
- package/dist/session/authorize.js.map +1 -1
- package/dist/session/exchange.js +1 -2
- package/dist/session/exchange.js.map +1 -1
- package/dist/session/post-auth.js +7 -1
- package/dist/session/post-auth.js.map +1 -1
- package/dist/session/redirect-listener.js +6 -5
- package/dist/session/redirect-listener.js.map +1 -1
- package/dist/session/validate.js.map +1 -1
- package/dist/session.js +1 -1
- package/dist/session.js.map +1 -1
- package/dist/store.d.ts +4 -2
- package/dist/store.js +3 -4
- package/dist/store.js.map +1 -1
- package/dist/string.d.ts +1 -0
- package/dist/string.js +3 -0
- package/dist/string.js.map +1 -1
- package/dist/system.d.ts +2 -2
- package/dist/testing/output.js +6 -6
- package/dist/testing/output.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/typing/deep-required.d.ts +12 -0
- package/dist/typing/deep-required.js +2 -0
- package/dist/typing/deep-required.js.map +1 -0
- package/dist/typing/pick-by-prefix.d.ts +12 -0
- package/dist/typing/pick-by-prefix.js +2 -0
- package/dist/typing/pick-by-prefix.js.map +1 -0
- package/dist/ui/executor.d.ts +14 -0
- package/dist/ui/executor.js +88 -0
- package/dist/ui/executor.js.map +1 -0
- package/dist/ui/inquirer/autocomplete.d.ts +11 -0
- package/dist/ui/inquirer/autocomplete.js +105 -0
- package/dist/ui/inquirer/autocomplete.js.map +1 -0
- package/dist/ui/inquirer/input.d.ts +16 -0
- package/dist/ui/inquirer/input.js +46 -0
- package/dist/ui/inquirer/input.js.map +1 -0
- package/dist/ui/inquirer/password.d.ts +7 -0
- package/dist/ui/inquirer/password.js +8 -0
- package/dist/ui/inquirer/password.js.map +1 -0
- package/dist/ui/inquirer/select.d.ts +14 -0
- package/dist/ui/inquirer/select.js +27 -0
- package/dist/ui/inquirer/select.js.map +1 -0
- package/dist/ui.d.ts +12 -23
- package/dist/ui.js +14 -61
- package/dist/ui.js.map +1 -1
- package/dist/version.d.ts +1 -0
- package/package.json +23 -13
- package/dist/api/graphql/functions/module_upload_url_generate.d.ts +0 -18
- package/dist/api/graphql/functions/module_upload_url_generate.js +0 -17
- package/dist/api/graphql/functions/module_upload_url_generate.js.map +0 -1
- package/dist/ui/autocomplete.d.ts +0 -7
- package/dist/ui/autocomplete.js +0 -43
- package/dist/ui/autocomplete.js.map +0 -1
- package/dist/ui/input.d.ts +0 -7
- package/dist/ui/input.js +0 -48
- package/dist/ui/input.js.map +0 -1
- package/dist/ui/select.d.ts +0 -6
- package/dist/ui/select.js +0 -30
- package/dist/ui/select.js.map +0 -1
package/dist/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport {Fatal, Bug, cleanSingleStackTracePath} from './error.js'\nimport {isUnitTest, isVerbose} from './environment/local.js'\nimport constants from './constants.js'\nimport {PackageManager} from './node/node-package-manager.js'\nimport {generateRandomUUID} from './id.js'\nimport {\n mkdirSync as fileMkdirSync,\n readSync as fileReadSync,\n sizeSync as fileSizeSync,\n writeSync as fileWriteSync,\n touchSync as fileTouchSync,\n} from './file.js'\nimport {join as pathJoin, relativize as relativizePath} from './path.js'\nimport {page} from './system.js'\nimport {colors} from './node/colors.js'\nimport terminalLink from 'terminal-link'\nimport StackTracey from 'stacktracey'\nimport {AbortController, AbortSignal} from 'abort-controller'\nimport cjs from 'color-json'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'node:stream'\nimport {WriteStream, createWriteStream} from 'node:fs'\n\nexport {default as logUpdate} from 'log-update'\n\nconst logFileName = 'shopify.cli.log'\nlet logFileStream: WriteStream\nlet commandUuid: string\n\nexport function initiateLogging(options: {logDir?: string} = {}) {\n if (isUnitTest()) return\n const logDir = options.logDir || constants.paths.directories.cache.path()\n commandUuid = generateRandomUUID()\n fileMkdirSync(logDir)\n const logFile = pathJoin(logDir, logFileName)\n fileTouchSync(logFile)\n truncateLogs(logFile)\n logFileStream = createWriteStream(logFile, {flags: 'a'})\n}\n\n// Shaves off the first 10,000 log lines (circa 1MB) if logs are over 5MB long.\n// Rescues in case the file hasn't been created yet.\nfunction truncateLogs(logFile: string): void {\n try {\n if (fileSizeSync(logFile) > 5 * 1024 * 1024) {\n const contents = fileReadSync(logFile)\n const splitContents = contents.split('\\n')\n const newContents = splitContents.slice(10000, splitContents.length).join('\\n')\n fileWriteSync(logFile, newContents)\n }\n // eslint-disable-next-line no-empty, no-catch-all/no-catch-all\n } catch {}\n}\n\nenum ContentTokenType {\n Raw,\n Command,\n Json,\n Path,\n Link,\n Heading,\n SubHeading,\n Italic,\n ErrorText,\n Yellow,\n Cyan,\n Magenta,\n Green,\n}\n\ninterface ContentMetadata {\n link?: string\n}\n\nexport type Logger = (message: string) => void\n\nclass ContentToken {\n type: ContentTokenType\n value: Message\n metadata: ContentMetadata\n\n constructor(value: Message, metadata: ContentMetadata = {}, type: ContentTokenType) {\n this.type = type\n this.value = value\n this.metadata = metadata\n }\n}\n\nexport const token = {\n raw: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Raw)\n },\n genericShellCommand: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Command)\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: (value: any) => {\n return new ContentToken(value, {}, ContentTokenType.Json)\n },\n path: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Path)\n },\n link: (value: Message, link: string) => {\n return new ContentToken(value, {link}, ContentTokenType.Link)\n },\n heading: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Heading)\n },\n subheading: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.SubHeading)\n },\n italic: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Italic)\n },\n errorText: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.ErrorText)\n },\n cyan: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Cyan)\n },\n yellow: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Yellow)\n },\n magenta: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Magenta)\n },\n green: (value: Message) => {\n return new ContentToken(value, {}, ContentTokenType.Green)\n },\n packagejsonScript: (packageManager: PackageManager, scriptName: string, ...scriptArgs: string[]) => {\n return new ContentToken(\n formatPackageManagerCommand(packageManager, scriptName, scriptArgs),\n {},\n ContentTokenType.Command,\n )\n },\n successIcon: () => {\n return new ContentToken('✔', {}, ContentTokenType.Green)\n },\n failIcon: () => {\n return new ContentToken('✖', {}, ContentTokenType.ErrorText)\n },\n}\n\nfunction formatPackageManagerCommand(packageManager: PackageManager, scriptName: string, scriptArgs: string[]): string {\n switch (packageManager) {\n case 'yarn': {\n const pieces = ['yarn', scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n case 'pnpm':\n case 'npm': {\n const pieces = [packageManager, 'run', scriptName]\n if (scriptArgs.length > 0) {\n pieces.push('--')\n pieces.push(...scriptArgs)\n }\n return pieces.join(' ')\n }\n }\n}\n\nexport class TokenizedString {\n value: string\n constructor(value: string) {\n this.value = value\n }\n}\n\nexport type Message = string | TokenizedString\n\nexport function content(strings: TemplateStringsArray, ...keys: (ContentToken | string)[]): TokenizedString {\n let output = ``\n strings.forEach((string, i) => {\n output += string\n if (i >= keys.length) {\n return\n }\n const token = keys[i]\n\n if (typeof token === 'string') {\n output += token\n } else {\n const enumToken = token as ContentToken\n switch (enumToken.type) {\n case ContentTokenType.Raw:\n output += enumToken.value\n break\n case ContentTokenType.Command:\n output += colors.bold(colors.yellow(stringifyMessage(enumToken.value)))\n break\n case ContentTokenType.Path:\n output += relativizePath(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.Json:\n try {\n output += cjs(stringifyMessage(enumToken.value) ?? {})\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (_) {\n output += JSON.stringify(stringifyMessage(enumToken.value) ?? {}, null, 2)\n }\n break\n case ContentTokenType.Link:\n output += terminalLink(colors.green(stringifyMessage(enumToken.value)), enumToken.metadata.link ?? '')\n break\n case ContentTokenType.Heading:\n output += colors.bold.underline(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.SubHeading:\n output += colors.underline(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.Italic:\n output += colors.italic(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.ErrorText:\n output += colors.bold.redBright(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.Yellow:\n output += colors.yellow(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.Cyan:\n output += colors.cyan(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.Magenta:\n output += colors.magenta(stringifyMessage(enumToken.value))\n break\n case ContentTokenType.Green:\n output += colors.green(stringifyMessage(enumToken.value))\n break\n }\n }\n })\n return new TokenizedString(output)\n}\n\n/** Log levels */\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'\n\n/**\n * It maps a level to a numeric value.\n * @param level {LogLevel} The level for which we'll return its numeric value.\n * @returns The numeric value of the level.\n */\nconst logLevelValue = (level: LogLevel): number => {\n switch (level) {\n case 'trace':\n return 10\n case 'debug':\n return 20\n case 'info':\n return 30\n case 'warn':\n return 40\n case 'error':\n return 50\n case 'fatal':\n return 60\n default:\n return 30\n }\n}\n\n/**\n *\n * @returns {LogLevel} It returns the log level set by the user.\n */\nexport const currentLogLevel = (): LogLevel => {\n if (isVerbose()) {\n return 'debug'\n } else {\n return 'info'\n }\n}\n\nexport const shouldOutput = (logLevel: LogLevel): boolean => {\n if (isUnitTest()) {\n return false\n }\n const currentLogLevelValue = logLevelValue(currentLogLevel())\n const messageLogLevelValue = logLevelValue(logLevel)\n return messageLogLevelValue >= currentLogLevelValue\n}\n\n// eslint-disable-next-line import/no-mutable-exports\nexport let collectedLogs: {[key: string]: string[]} = {}\n\n/**\n * This is only used during UnitTesting.\n * If we are in a testing context, instead of printing the logs to the console,\n * we will store them in a variable that can be accessed from the tests.\n * @param key {string} The key of the log.\n * @param content {string} The content of the log.\n */\nconst collectLog = (key: string, content: Message) => {\n const output = collectedLogs.output ?? []\n const data = collectedLogs[key] ?? []\n data.push(stripAnsi(stringifyMessage(content) ?? ''))\n output.push(stripAnsi(stringifyMessage(content) ?? ''))\n collectedLogs[key] = data\n collectedLogs.output = output\n}\n\nexport const clearCollectedLogs = () => {\n collectedLogs = {}\n}\n\n/**\n * Ouputs information to the user.\n * Info messages don't get additional formatting.\n * Note: Info messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const info = (content: Message, logger: Logger = consoleLog) => {\n const message = stringifyMessage(content)\n if (isUnitTest()) collectLog('info', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a success message to the user.\n * Success messages receive a special formatting to make them stand out in the console.\n * Note: Success messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const success = (content: Message, logger: Logger = consoleLog) => {\n const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`)\n if (isUnitTest()) collectLog('success', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a completed message to the user.\n * Completed message receive a special formatting to make them stand out in the console.\n * Note: Completed messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const completed = (content: Message, logger: Logger = consoleLog) => {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Ouputs debug information to the user. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: Debug messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const debug = (content: Message, logger: Logger = consoleLog) => {\n if (isUnitTest()) collectLog('debug', content)\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, message)\n}\n\n/**\n * Outputs a warning message to the user.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: Warning messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const warn = (content: Message, logger: Logger = consoleWarn) => {\n if (isUnitTest()) collectLog('warn', content)\n const message = colors.yellow(stringifyMessage(content))\n outputWhereAppropriate('warn', logger, message)\n}\n\n/**\n * Prints a new line in the terminal.\n */\nexport const newline = () => {\n console.log()\n}\n\n/**\n * Formats and outputs a fatal error.\n * Note: This API is not intended to be used internally. If you want to\n * abort the execution due to an error, raise a fatal error and let the\n * error handler handle and format it.\n * @param content {Fatal} The fatal error to be output.\n */\nexport const error = async (content: Fatal) => {\n if (!content.message) {\n return\n }\n let outputString = ''\n const message = content.message\n const padding = ' '\n const header = colors.redBright(`\\n━━━━━━ Error ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n`)\n const footer = colors.redBright('\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n')\n outputString += header\n const lines = message.split('\\n')\n for (const line of lines) {\n outputString += `${padding}${line}\\n`\n }\n if (content.tryMessage) {\n outputString += `\\n${padding}${colors.bold('What to try:')}\\n`\n const lines = content.tryMessage.split('\\n')\n for (const line of lines) {\n outputString += `${padding}${line}\\n`\n }\n }\n\n let stack = new StackTracey(content)\n stack.items.forEach((item) => {\n item.file = cleanSingleStackTracePath(item.file)\n })\n\n stack = await stack.withSourcesAsync()\n stack = stack\n .filter((entry) => {\n return !entry.file.includes('@oclif/core')\n })\n .map((item) => {\n item.calleeShort = colors.yellow(item.calleeShort)\n /** We make the paths relative to the packages/ directory */\n const fileShortComponents = item.fileShort.split('packages/')\n item.fileShort = fileShortComponents.length === 2 ? fileShortComponents[1] : fileShortComponents[0]\n return item\n })\n if (content instanceof Bug) {\n if (stack.items.length !== 0) {\n outputString += `\\n${padding}${colors.bold('Stack trace:')}\\n`\n const stackLines = stack.asTable({}).split('\\n')\n for (const stackLine of stackLines) {\n outputString += `${padding}${stackLine}\\n`\n }\n }\n }\n outputString += footer\n outputWhereAppropriate('error', consoleError, outputString)\n}\n\nexport function stringifyMessage(message: Message): string {\n if (message instanceof TokenizedString) {\n return message.value\n } else {\n return message\n }\n}\n\nconst message = (content: Message, level: LogLevel = 'info') => {\n const stringifiedMessage = stringifyMessage(content)\n outputWhereAppropriate(level, consoleLog, stringifiedMessage)\n}\n\nexport interface OutputProcess {\n /** The prefix to include in the logs\n * [vite] Output coming from Vite\n */\n prefix: string\n /**\n * A callback to invoke the process. stdout and stderr should be used\n * to send standard output and error data that gets formatted with the\n * right prefix.\n */\n action: (stdout: Writable, stderr: Writable, signal: AbortSignal) => Promise<void>\n}\n\n/**\n * Use this function when you have multiple concurrent processes that send data events\n * and we need to output them ensuring that they can visually differenciated by the user.\n *\n * @param processes {OutputProcess[]} A list of processes to run concurrently.\n */\nexport async function concurrent(\n processes: OutputProcess[],\n callback: ((signal: AbortSignal) => void) | undefined = undefined,\n) {\n const abortController = new AbortController()\n\n // eslint-disable-next-line node/callback-return\n if (callback) callback(abortController.signal)\n\n const concurrentColors = [token.yellow, token.cyan, token.magenta, token.green]\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n\n function linePrefix(prefix: string, index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n const color = concurrentColors[colorIndex]\n return color(`${prefix}${' '.repeat(prefixColumnSize - prefix.length)} ${colors.bold('|')} `)\n }\n\n try {\n await Promise.all(\n processes.map(async (process, index) => {\n const stdout = new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsiEraseCursorEscapeCharacters(chunk.toString('ascii')).split(/\\n/)\n for (const line of lines) {\n info(content`${linePrefix(process.prefix, index)}${line}`)\n }\n next()\n },\n })\n const stderr = new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsiEraseCursorEscapeCharacters(chunk.toString('ascii')).split(/\\n/)\n for (const line of lines) {\n message(content`${linePrefix(process.prefix, index)}${colors.bold(line)}`, 'error')\n }\n next()\n },\n })\n await process.action(stdout, stderr, abortController.signal)\n }),\n )\n } catch (_error) {\n // We abort any running process\n abortController.abort()\n throw _error\n }\n}\n\n/**\n * This regex can be used to find the erase cursor Ansii characters\n * to strip them from the string.\n * https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#erase-functions\n */\nconst eraseCursorAnsiRegex = [\n // Erase the entire line\n '2K',\n // Clear vertical tab stop at current line\n '1G',\n]\n .map((element) => `[\\\\u001B\\\\u009B][[\\\\]()#;?]*${element}`)\n .join('|')\n\n/**\n * The data sent through the standard pipelines of the sub-processes that we execute\n * might contain ansii escape characters to move the cursor. That causes any additional\n * formatting to break. This function takes a string and strips escape characters that\n * manage the cursor in the terminal.\n * @param value {string} String whose erase cursor escape characters will be stripped.\n * @returns {string} Stripped string.\n */\nfunction stripAnsiEraseCursorEscapeCharacters(value: string): string {\n return value.replace(/(\\n)$/, '').replace(new RegExp(eraseCursorAnsiRegex, 'g'), '')\n}\n\nfunction consoleLog(message: string): void {\n console.log(withOrWithoutStyle(message))\n}\n\nfunction consoleError(message: string): void {\n console.error(withOrWithoutStyle(message))\n}\n\nfunction consoleWarn(message: string): void {\n console.warn(withOrWithoutStyle(message))\n}\n\nfunction outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void {\n if (shouldOutput(logLevel)) {\n logger(message)\n }\n logToFile(message, logLevel.toUpperCase())\n}\n\nexport function logFileExists(): boolean {\n return Boolean(logFileStream)\n}\n\n// DO NOT USE THIS FUNCTION DIRECTLY under normal circumstances.\n// It is exported purely for use in cases where output is already being logged\n// to the terminal but is not reflected in the logfile, e.g. Listr output.\nexport function logToFile(message: string, logLevel: string): void {\n // If file logging hasn't been initiated, skip it\n if (!logFileExists()) return\n const timestamp = new Date().toISOString()\n const logContents = `[${timestamp} ${commandUuid} ${logLevel}]: ${message}\\n`\n logFileStream.write(logContents)\n}\n\nfunction withOrWithoutStyle(message: string): string {\n if (shouldDisplayColors()) {\n return message\n } else {\n return unstyled(message)\n }\n}\n\nexport function unstyled(message: string): string {\n return colors.unstyle(message)\n}\n\nexport function shouldDisplayColors(): boolean {\n return Boolean(process.stdout.isTTY || process.env.FORCE_COLOR)\n}\n\nexport async function pageLogs({lastCommand}: {lastCommand: boolean}) {\n const logDir = constants.paths.directories.cache.path()\n const logFile = pathJoin(logDir, logFileName)\n // Ensure file exists in case they deleted it or something\n fileTouchSync(logFile)\n if (lastCommand) {\n printLastCommand(logFile)\n } else {\n await page(logFile)\n }\n}\n\nfunction printLastCommand(logFile: string): void {\n const contents = fileReadSync(logFile).split('\\n')\n const uuids = contents\n .map(logfileLineUUID)\n .filter((uuid) => uuid)\n .reverse()\n // 2nd unique UUID, because the currently running command will be the 1st\n const relevantUuid = Array.from(new Set(uuids))[1]\n if (relevantUuid) {\n consoleLog(relevantLines(contents, relevantUuid).join('\\n'))\n }\n}\n\nfunction relevantLines(contents: string[], relevantUuid: string): string[] {\n // We run through the file line by line, keeping track of the most recently\n // encountered UUID.\n //\n // If the current line has a UUID, it's a new logged unit and should be\n // considered. Otherwise, the line is related to the most recent UUID.\n let mostRecentUuid = ''\n return contents.filter((line: string) => {\n const currentUuid = logfileLineUUID(line) || mostRecentUuid\n mostRecentUuid = currentUuid\n return currentUuid === relevantUuid\n })\n}\n\nfunction logfileLineUUID(line: string): string | null {\n // Log lines look like:\n //\n // timestamp UUID contents\n // ===========================================================================================\n // [2022-07-20T08:51:40.296Z 5288e1da-a06a-4f96-b1a6-e34fcdd7b416 DEBUG]: Running command logs\n // ===========================================================================================\n //\n // There may be subsequent lines if the contents section is multi-line.\n //\n const match = line.match(/^\\[\\S+ ([0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}) [A-Z]+\\]/)\n return match && match[1]\n}\n\n/**\n *\n * @param packageManager {PackageManager} The package manager that is being used.\n * @param version {string} The version to update to\n * @returns {te}\n */\nexport function getOutputUpdateCLIReminder(packageManager: PackageManager, version: string): string {\n const updateCommand = token.packagejsonScript(packageManager, 'shopify', 'upgrade')\n return content`💡 Version ${version} available! Run ${updateCommand}`.value\n}\n\n/* eslint-enable no-console */\n"]}
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport {Fatal, Bug, cleanSingleStackTracePath} from './error.js'\nimport {isUnitTest, isVerbose} from './environment/local.js'\nimport constants from './constants.js'\nimport {PackageManager} from './node/node-package-manager.js'\nimport {generateRandomUUID} from './id.js'\nimport {\n mkdirSync as fileMkdirSync,\n readSync as fileReadSync,\n sizeSync as fileSizeSync,\n writeSync as fileWriteSync,\n touchSync as fileTouchSync,\n} from './file.js'\nimport {join as pathJoin} from './path.js'\nimport {page} from './system.js'\nimport {colors} from './node/colors.js'\nimport {\n ColorContentToken,\n CommandContentToken,\n ContentToken,\n ErrorContentToken,\n HeadingContentToken,\n ItalicContentToken,\n JsonContentToken,\n LinesDiffContentToken,\n LinkContentToken,\n PathContentToken,\n RawContentToken,\n SubHeadingContentToken,\n} from './content-tokens.js'\nimport StackTracey from 'stacktracey'\nimport {AbortController, AbortSignal} from 'abort-controller'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'node:stream'\nimport {WriteStream, createWriteStream} from 'node:fs'\nimport type {Change} from 'diff'\n\nexport {default as logUpdate} from 'log-update'\n\nconst logFileName = 'shopify.cli.log'\nlet logFileStream: WriteStream\nlet commandUuid: string\n\nexport function initiateLogging(options: {logDir?: string} = {}) {\n if (isUnitTest()) return\n const logDir = options.logDir || constants.paths.directories.cache.path()\n commandUuid = generateRandomUUID()\n fileMkdirSync(logDir)\n const logFile = pathJoin(logDir, logFileName)\n fileTouchSync(logFile)\n truncateLogs(logFile)\n logFileStream = createWriteStream(logFile, {flags: 'a'})\n}\n\n// Shaves off the first 10,000 log lines (circa 1MB) if logs are over 5MB long.\n// Rescues in case the file hasn't been created yet.\nfunction truncateLogs(logFile: string): void {\n try {\n if (fileSizeSync(logFile) > 5 * 1024 * 1024) {\n const contents = fileReadSync(logFile)\n const splitContents = contents.split('\\n')\n const newContents = splitContents.slice(10000, splitContents.length).join('\\n')\n fileWriteSync(logFile, newContents)\n }\n // eslint-disable-next-line no-empty, no-catch-all/no-catch-all\n } catch {}\n}\n\nexport type Logger = (message: string) => void\n\nexport class TokenizedString {\n value: string\n constructor(value: string) {\n this.value = value\n }\n}\n\nexport type Message = string | TokenizedString\n\nexport const token = {\n raw: (value: string) => {\n return new RawContentToken(value)\n },\n genericShellCommand: (value: Message) => {\n return new CommandContentToken(value)\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: (value: any) => {\n return new JsonContentToken(value)\n },\n path: (value: Message) => {\n return new PathContentToken(value)\n },\n link: (value: Message, link: string) => {\n return new LinkContentToken(value, link)\n },\n heading: (value: Message) => {\n return new HeadingContentToken(value)\n },\n subheading: (value: Message) => {\n return new SubHeadingContentToken(value)\n },\n italic: (value: Message) => {\n return new ItalicContentToken(value)\n },\n errorText: (value: Message) => {\n return new ErrorContentToken(value)\n },\n cyan: (value: Message) => {\n return new ColorContentToken(value, colors.cyan)\n },\n yellow: (value: Message) => {\n return new ColorContentToken(value, colors.yellow)\n },\n magenta: (value: Message) => {\n return new ColorContentToken(value, colors.magenta)\n },\n green: (value: Message) => {\n return new ColorContentToken(value, colors.green)\n },\n packagejsonScript: (packageManager: PackageManager, scriptName: string, ...scriptArgs: string[]) => {\n return new CommandContentToken(formatPackageManagerCommand(packageManager, scriptName, scriptArgs))\n },\n successIcon: () => {\n return new ColorContentToken('✔', colors.green)\n },\n failIcon: () => {\n return new ErrorContentToken('✖')\n },\n linesDiff: (value: Change[]) => {\n return new LinesDiffContentToken(value)\n },\n}\n\nfunction formatPackageManagerCommand(packageManager: PackageManager, scriptName: string, scriptArgs: string[]): string {\n switch (packageManager) {\n case 'yarn': {\n const pieces = ['yarn', scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n case 'pnpm':\n case 'npm': {\n const pieces = [packageManager, 'run', scriptName]\n if (scriptArgs.length > 0) {\n pieces.push('--')\n pieces.push(...scriptArgs)\n }\n return pieces.join(' ')\n }\n }\n}\n\nexport function content(strings: TemplateStringsArray, ...keys: (ContentToken<unknown> | string)[]): TokenizedString {\n let output = ``\n strings.forEach((string, i) => {\n output += string\n if (i >= keys.length) {\n return\n }\n const token = keys[i]!\n\n if (typeof token === 'string') {\n output += token\n } else {\n const enumTokenOutput = token.output()\n\n if (Array.isArray(enumTokenOutput)) {\n enumTokenOutput.forEach((line: string) => {\n output += line\n })\n } else {\n output += enumTokenOutput\n }\n }\n })\n return new TokenizedString(output)\n}\n\n/** Log levels */\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'\n\n/**\n * It maps a level to a numeric value.\n * @param level {LogLevel} The level for which we'll return its numeric value.\n * @returns The numeric value of the level.\n */\nconst logLevelValue = (level: LogLevel): number => {\n switch (level) {\n case 'trace':\n return 10\n case 'debug':\n return 20\n case 'info':\n return 30\n case 'warn':\n return 40\n case 'error':\n return 50\n case 'fatal':\n return 60\n default:\n return 30\n }\n}\n\n/**\n *\n * @returns {LogLevel} It returns the log level set by the user.\n */\nexport const currentLogLevel = (): LogLevel => {\n if (isVerbose()) {\n return 'debug'\n } else {\n return 'info'\n }\n}\n\nexport const shouldOutput = (logLevel: LogLevel): boolean => {\n if (isUnitTest()) {\n return false\n }\n const currentLogLevelValue = logLevelValue(currentLogLevel())\n const messageLogLevelValue = logLevelValue(logLevel)\n return messageLogLevelValue >= currentLogLevelValue\n}\n\n// eslint-disable-next-line import/no-mutable-exports\nexport let collectedLogs: {[key: string]: string[]} = {}\n\n/**\n * This is only used during UnitTesting.\n * If we are in a testing context, instead of printing the logs to the console,\n * we will store them in a variable that can be accessed from the tests.\n * @param key {string} The key of the log.\n * @param content {string} The content of the log.\n */\nconst collectLog = (key: string, content: Message) => {\n const output = collectedLogs.output ?? []\n const data = collectedLogs[key] ?? []\n data.push(stripAnsi(stringifyMessage(content) ?? ''))\n output.push(stripAnsi(stringifyMessage(content) ?? ''))\n collectedLogs[key] = data\n collectedLogs.output = output\n}\n\nexport const clearCollectedLogs = () => {\n collectedLogs = {}\n}\n\n/**\n * Ouputs information to the user.\n * Info messages don't get additional formatting.\n * Note: Info messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const info = (content: Message, logger: Logger = consoleLog) => {\n const message = stringifyMessage(content)\n if (isUnitTest()) collectLog('info', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a success message to the user.\n * Success messages receive a special formatting to make them stand out in the console.\n * Note: Success messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const success = (content: Message, logger: Logger = consoleLog) => {\n const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`)\n if (isUnitTest()) collectLog('success', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a completed message to the user.\n * Completed message receive a special formatting to make them stand out in the console.\n * Note: Completed messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const completed = (content: Message, logger: Logger = consoleLog) => {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Ouputs debug information to the user. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: Debug messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const debug = (content: Message, logger: Logger = consoleLog) => {\n if (isUnitTest()) collectLog('debug', content)\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, message)\n}\n\n/**\n * Outputs a warning message to the user.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: Warning messages are sent through the standard output.\n * @param content {string} The content to be output to the user.\n * @param logger {Function} The logging function to use to output to the user.\n */\nexport const warn = (content: Message, logger: Logger = consoleWarn) => {\n if (isUnitTest()) collectLog('warn', content)\n const message = colors.yellow(stringifyMessage(content))\n outputWhereAppropriate('warn', logger, message)\n}\n\n/**\n * Prints a new line in the terminal.\n */\nexport const newline = () => {\n console.log()\n}\n\n/**\n * Formats and outputs a fatal error.\n * Note: This API is not intended to be used internally. If you want to\n * abort the execution due to an error, raise a fatal error and let the\n * error handler handle and format it.\n * @param content {Fatal} The fatal error to be output.\n */\nexport const error = async (content: Fatal) => {\n if (!content.message) {\n return\n }\n let outputString = ''\n const message = content.message\n const padding = ' '\n const header = colors.redBright(`\\n━━━━━━ Error ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n`)\n const footer = colors.redBright('\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n')\n outputString += header\n const lines = message.split('\\n')\n for (const line of lines) {\n outputString += `${padding}${line}\\n`\n }\n if (content.tryMessage) {\n outputString += `\\n${padding}${colors.bold('What to try:')}\\n`\n const lines = content.tryMessage.split('\\n')\n for (const line of lines) {\n outputString += `${padding}${line}\\n`\n }\n }\n\n let stack = new StackTracey(content)\n stack.items.forEach((item) => {\n item.file = cleanSingleStackTracePath(item.file)\n })\n\n stack = await stack.withSourcesAsync()\n stack = stack\n .filter((entry) => {\n return !entry.file.includes('@oclif/core')\n })\n .map((item) => {\n item.calleeShort = colors.yellow(item.calleeShort)\n /** We make the paths relative to the packages/ directory */\n const fileShortComponents = item.fileShort.split('packages/')\n item.fileShort = fileShortComponents.length === 2 ? fileShortComponents[1]! : fileShortComponents[0]!\n return item\n })\n if (content instanceof Bug) {\n if (stack.items.length !== 0) {\n outputString += `\\n${padding}${colors.bold('Stack trace:')}\\n`\n const stackLines = stack.asTable({}).split('\\n')\n for (const stackLine of stackLines) {\n outputString += `${padding}${stackLine}\\n`\n }\n }\n }\n outputString += footer\n outputWhereAppropriate('error', consoleError, outputString)\n}\n\nexport function stringifyMessage(message: Message): string {\n if (message instanceof TokenizedString) {\n return message.value\n } else {\n return message\n }\n}\n\nconst message = (content: Message, level: LogLevel = 'info') => {\n const stringifiedMessage = stringifyMessage(content)\n outputWhereAppropriate(level, consoleLog, stringifiedMessage)\n}\n\nexport interface OutputProcess {\n /** The prefix to include in the logs\n * [vite] Output coming from Vite\n */\n prefix: string\n /**\n * A callback to invoke the process. stdout and stderr should be used\n * to send standard output and error data that gets formatted with the\n * right prefix.\n */\n action: (stdout: Writable, stderr: Writable, signal: AbortSignal) => Promise<void>\n}\n\n/**\n * Use this function when you have multiple concurrent processes that send data events\n * and we need to output them ensuring that they can visually differenciated by the user.\n *\n * @param processes {OutputProcess[]} A list of processes to run concurrently.\n */\nexport async function concurrent(\n processes: OutputProcess[],\n callback: ((signal: AbortSignal) => void) | undefined = undefined,\n) {\n const abortController = new AbortController()\n\n // eslint-disable-next-line node/callback-return\n if (callback) callback(abortController.signal)\n\n const concurrentColors = [token.yellow, token.cyan, token.magenta, token.green]\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n\n function linePrefix(prefix: string, index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n const color = concurrentColors[colorIndex]!\n return color(`${prefix}${' '.repeat(prefixColumnSize - prefix.length)} ${colors.bold('|')} `)\n }\n\n try {\n await Promise.all(\n processes.map(async (process, index) => {\n const stdout = new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsiEraseCursorEscapeCharacters(chunk.toString('ascii')).split(/\\n/)\n for (const line of lines) {\n info(content`${linePrefix(process.prefix, index)}${line}`)\n }\n next()\n },\n })\n const stderr = new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsiEraseCursorEscapeCharacters(chunk.toString('ascii')).split(/\\n/)\n for (const line of lines) {\n message(content`${linePrefix(process.prefix, index)}${colors.bold(line)}`, 'error')\n }\n next()\n },\n })\n await process.action(stdout, stderr, abortController.signal)\n }),\n )\n } catch (_error) {\n // We abort any running process\n abortController.abort()\n throw _error\n }\n}\n\n/**\n * This regex can be used to find the erase cursor Ansii characters\n * to strip them from the string.\n * https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#erase-functions\n */\nconst eraseCursorAnsiRegex = [\n // Erase the entire line\n '2K',\n // Clear vertical tab stop at current line\n '1G',\n]\n .map((element) => `[\\\\u001B\\\\u009B][[\\\\]()#;?]*${element}`)\n .join('|')\n\n/**\n * The data sent through the standard pipelines of the sub-processes that we execute\n * might contain ansii escape characters to move the cursor. That causes any additional\n * formatting to break. This function takes a string and strips escape characters that\n * manage the cursor in the terminal.\n * @param value {string} String whose erase cursor escape characters will be stripped.\n * @returns {string} Stripped string.\n */\nfunction stripAnsiEraseCursorEscapeCharacters(value: string): string {\n return value.replace(/(\\n)$/, '').replace(new RegExp(eraseCursorAnsiRegex, 'g'), '')\n}\n\nfunction consoleLog(message: string): void {\n console.log(withOrWithoutStyle(message))\n}\n\nfunction consoleError(message: string): void {\n console.error(withOrWithoutStyle(message))\n}\n\nfunction consoleWarn(message: string): void {\n console.warn(withOrWithoutStyle(message))\n}\n\nfunction outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void {\n if (shouldOutput(logLevel)) {\n logger(message)\n }\n logToFile(message, logLevel.toUpperCase())\n}\n\nexport function logFileExists(): boolean {\n return Boolean(logFileStream)\n}\n\n// DO NOT USE THIS FUNCTION DIRECTLY under normal circumstances.\n// It is exported purely for use in cases where output is already being logged\n// to the terminal but is not reflected in the logfile, e.g. Listr output.\nexport function logToFile(message: string, logLevel: string): void {\n // If file logging hasn't been initiated, skip it\n if (!logFileExists()) return\n const timestamp = new Date().toISOString()\n const logContents = `[${timestamp} ${commandUuid} ${logLevel}]: ${message}\\n`\n logFileStream.write(logContents)\n}\n\nfunction withOrWithoutStyle(message: string): string {\n if (shouldDisplayColors()) {\n return message\n } else {\n return unstyled(message)\n }\n}\n\nexport function unstyled(message: string): string {\n return colors.unstyle(message)\n}\n\nexport function shouldDisplayColors(): boolean {\n return Boolean(process.stdout.isTTY || process.env.FORCE_COLOR)\n}\n\nexport async function pageLogs({lastCommand}: {lastCommand: boolean}) {\n const logDir = constants.paths.directories.cache.path()\n const logFile = pathJoin(logDir, logFileName)\n // Ensure file exists in case they deleted it or something\n fileTouchSync(logFile)\n if (lastCommand) {\n printLastCommand(logFile)\n } else {\n await page(logFile)\n }\n}\n\nfunction printLastCommand(logFile: string): void {\n const contents = fileReadSync(logFile).split('\\n')\n const uuids = contents\n .map(logfileLineUUID)\n .filter((uuid) => uuid)\n .reverse()\n // 2nd unique UUID, because the currently running command will be the 1st\n const relevantUuid = Array.from(new Set(uuids))[1]\n if (relevantUuid) {\n consoleLog(relevantLines(contents, relevantUuid).join('\\n'))\n }\n}\n\nfunction relevantLines(contents: string[], relevantUuid: string): string[] {\n // We run through the file line by line, keeping track of the most recently\n // encountered UUID.\n //\n // If the current line has a UUID, it's a new logged unit and should be\n // considered. Otherwise, the line is related to the most recent UUID.\n let mostRecentUuid = ''\n return contents.filter((line: string) => {\n const currentUuid = logfileLineUUID(line) || mostRecentUuid\n mostRecentUuid = currentUuid\n return currentUuid === relevantUuid\n })\n}\n\nfunction logfileLineUUID(line: string): string | null {\n // Log lines look like:\n //\n // timestamp UUID contents\n // ===========================================================================================\n // [2022-07-20T08:51:40.296Z 5288e1da-a06a-4f96-b1a6-e34fcdd7b416 DEBUG]: Running command logs\n // ===========================================================================================\n //\n // There may be subsequent lines if the contents section is multi-line.\n //\n const match = line.match(/^\\[\\S+ ([0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}) [A-Z]+\\]/)\n return match && match[1]!\n}\n\n/**\n *\n * @param packageManager {PackageManager} The package manager that is being used.\n * @param version {string} The version to update to\n * @returns {te}\n */\nexport function getOutputUpdateCLIReminder(packageManager: PackageManager, version: string): string {\n const updateCommand = token.packagejsonScript(packageManager, 'shopify', 'upgrade')\n return content`💡 Version ${version} available! Run ${updateCommand}`.value\n}\n\n/* eslint-enable no-console */\n"]}
|
package/dist/path.d.ts
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { FanoutHookFunction, PluginReturnsForHook } from '../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tunnel Plugins types
|
|
4
|
+
*
|
|
5
|
+
* Any plugin that provides tunnel functionality should implement `defineProvider`and `startTunnel`
|
|
6
|
+
*/
|
|
7
|
+
export interface HookReturnPerTunnelPlugin {
|
|
8
|
+
tunnel_start: {
|
|
9
|
+
options: {
|
|
10
|
+
port: number;
|
|
11
|
+
provider: string;
|
|
12
|
+
};
|
|
13
|
+
pluginReturns: {
|
|
14
|
+
[pluginName: string]: {
|
|
15
|
+
url: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
tunnel_provider: {
|
|
20
|
+
options: {
|
|
21
|
+
[key: string]: never;
|
|
22
|
+
};
|
|
23
|
+
pluginReturns: {
|
|
24
|
+
[pluginName: string]: {
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare type TunnelProviderFunction = FanoutHookFunction<'tunnel_provider', ''>;
|
|
31
|
+
export declare type TunnelStartFunction = FanoutHookFunction<'tunnel_start', ''>;
|
|
32
|
+
export declare type TunnelStartReturn = PluginReturnsForHook<'tunnel_start', ''>;
|
|
33
|
+
export declare type TunnelStartAction = (port: number) => Promise<TunnelStartReturn>;
|
|
34
|
+
export declare const defineProvider: (input: {
|
|
35
|
+
name: string;
|
|
36
|
+
}) => TunnelProviderFunction;
|
|
37
|
+
export declare const startTunnel: (options: {
|
|
38
|
+
provider: string;
|
|
39
|
+
action: TunnelStartAction;
|
|
40
|
+
}) => TunnelStartFunction;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const defineProvider = (input) => {
|
|
2
|
+
return async () => input;
|
|
3
|
+
};
|
|
4
|
+
export const startTunnel = (options) => {
|
|
5
|
+
return async (inputs) => {
|
|
6
|
+
if (inputs.provider !== options.provider)
|
|
7
|
+
return { url: undefined };
|
|
8
|
+
return options.action(inputs.port);
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=tunnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../src/plugins/tunnel.ts"],"names":[],"mappings":"AA2BA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAqB,EAA0B,EAAE;IAC9E,OAAO,KAAK,IAAI,EAAE,CAAC,KAAK,CAAA;AAC1B,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAsD,EAAuB,EAAE;IACzG,OAAO,KAAK,EAAE,MAAwC,EAA8B,EAAE;QACpF,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ;YAAE,OAAO,EAAC,GAAG,EAAE,SAAS,EAAC,CAAA;QACjE,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {FanoutHookFunction, PluginReturnsForHook} from '../plugins.js'\n\n/**\n * Tunnel Plugins types\n *\n * Any plugin that provides tunnel functionality should implement `defineProvider`and `startTunnel`\n */\nexport interface HookReturnPerTunnelPlugin {\n tunnel_start: {\n options: {port: number; provider: string}\n pluginReturns: {\n [pluginName: string]: {url: string | undefined}\n }\n }\n tunnel_provider: {\n options: {[key: string]: never}\n pluginReturns: {\n [pluginName: string]: {name: string}\n }\n }\n}\n\nexport type TunnelProviderFunction = FanoutHookFunction<'tunnel_provider', ''>\nexport type TunnelStartFunction = FanoutHookFunction<'tunnel_start', ''>\nexport type TunnelStartReturn = PluginReturnsForHook<'tunnel_start', ''>\nexport type TunnelStartAction = (port: number) => Promise<TunnelStartReturn>\n\nexport const defineProvider = (input: {name: string}): TunnelProviderFunction => {\n return async () => input\n}\nexport const startTunnel = (options: {provider: string; action: TunnelStartAction}): TunnelStartFunction => {\n return async (inputs: {provider: string; port: number}): Promise<TunnelStartReturn> => {\n if (inputs.provider !== options.provider) return {url: undefined}\n return options.action(inputs.port)\n }\n}\n"]}
|
package/dist/plugins.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JsonMap } from './json.js';
|
|
2
|
+
import { PickByPrefix } from './typing/pick-by-prefix.js';
|
|
3
|
+
import { MonorailEventPublic } from './monorail.js';
|
|
4
|
+
import { HookReturnPerTunnelPlugin } from './plugins/tunnel.js';
|
|
2
5
|
import { Interfaces } from '@oclif/core';
|
|
3
6
|
interface TunnelPlugin {
|
|
4
7
|
start: (options: TunnelStartOptions) => Promise<string>;
|
|
@@ -13,18 +16,15 @@ export declare function lookupTunnelPlugin(plugins: Interfaces.Plugin[]): Promis
|
|
|
13
16
|
* Responses are organised into a dictionary, keyed by plug-in name. Only plug-ins that have hooks registered for the given event, and the hooks were run successfully, are included.
|
|
14
17
|
*/
|
|
15
18
|
export declare function fanoutHooks<TPluginMap extends HookReturnsPerPlugin, TEvent extends string & keyof TPluginMap>(config: Interfaces.Config, event: TEvent, options: TPluginMap[typeof event]['options'], timeout?: number): Promise<Partial<TPluginMap[typeof event]['pluginReturns']>>;
|
|
16
|
-
|
|
19
|
+
declare type AppSpecificMonorailFields = PickByPrefix<MonorailEventPublic, 'app_', 'project_type' | 'api_key' | 'partner_id'> & PickByPrefix<MonorailEventPublic, 'cmd_extensions_'> & PickByPrefix<MonorailEventPublic, 'cmd_scaffold_'>;
|
|
20
|
+
interface HookReturnsPerPlugin extends HookReturnPerTunnelPlugin {
|
|
17
21
|
public_command_metadata: {
|
|
18
22
|
options: {
|
|
19
23
|
[key: string]: never;
|
|
20
24
|
};
|
|
21
25
|
pluginReturns: {
|
|
22
|
-
'@shopify/app': Partial<
|
|
23
|
-
|
|
24
|
-
}>;
|
|
25
|
-
[pluginName: string]: {
|
|
26
|
-
[key: string]: unknown;
|
|
27
|
-
};
|
|
26
|
+
'@shopify/app': Partial<AppSpecificMonorailFields>;
|
|
27
|
+
[pluginName: string]: JsonMap;
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
30
|
[hookName: string]: {
|
|
@@ -32,14 +32,12 @@ interface HookReturnsPerPlugin {
|
|
|
32
32
|
[key: string]: unknown;
|
|
33
33
|
};
|
|
34
34
|
pluginReturns: {
|
|
35
|
-
[key: string]:
|
|
36
|
-
[key: string]: unknown;
|
|
37
|
-
};
|
|
35
|
+
[key: string]: JsonMap;
|
|
38
36
|
};
|
|
39
37
|
};
|
|
40
38
|
}
|
|
41
|
-
declare type PluginReturnsForHook<TEvent extends keyof TPluginMap, TPluginName extends keyof TPluginMap[TEvent]['pluginReturns'], TPluginMap extends HookReturnsPerPlugin = HookReturnsPerPlugin> = TPluginMap[TEvent]['pluginReturns'][TPluginName];
|
|
39
|
+
export declare type PluginReturnsForHook<TEvent extends keyof TPluginMap, TPluginName extends keyof TPluginMap[TEvent]['pluginReturns'], TPluginMap extends HookReturnsPerPlugin = HookReturnsPerPlugin> = TPluginMap[TEvent]['pluginReturns'][TPluginName];
|
|
42
40
|
export declare type FanoutHookFunction<TEvent extends keyof TPluginMap = string, TPluginName extends keyof TPluginMap[TEvent]['pluginReturns'] = string, TPluginMap extends HookReturnsPerPlugin = HookReturnsPerPlugin> = (this: Interfaces.Hook.Context, options: TPluginMap[TEvent]['options'] & {
|
|
43
41
|
config: Interfaces.Config;
|
|
44
|
-
}) => Promise<
|
|
42
|
+
}) => Promise<PluginReturnsForHook<TEvent, TPluginName, TPluginMap>>;
|
|
45
43
|
export {};
|
package/dist/plugins.js
CHANGED
package/dist/plugins.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,aAAa,EAAC,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAC,KAAK,EAAE,OAAO,EAAC,MAAM,aAAa,CAAA;AAO1C,MAAM,cAAc,GAAG,CAAC,uBAAuB,CAAC,CAAA;AAUhD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAA4B;IACnE,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;IACrD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IACnF,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAA;IACnC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IACtF,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB,EACzB,KAAa,EACb,OAA4C,EAC5C,OAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACzD,8DAA8D;IAC9D,OAAO,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAC,MAAM,EAAE,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAQ,CAAA;AAClG,CAAC","sourcesContent":["import {join, pathToFileURL} from './path.js'\nimport {debug, content} from './output.js'\nimport {JsonMap} from './json.js'\nimport {PickByPrefix} from './typing/pick-by-prefix.js'\nimport {MonorailEventPublic} from './monorail.js'\nimport {HookReturnPerTunnelPlugin} from './plugins/tunnel.js'\nimport {Interfaces} from '@oclif/core'\n\nconst TUNNEL_PLUGINS = ['@shopify/plugin-ngrok']\n\ninterface TunnelPlugin {\n start: (options: TunnelStartOptions) => Promise<string>\n}\n\ninterface TunnelStartOptions {\n port: number\n}\n\nexport async function lookupTunnelPlugin(plugins: Interfaces.Plugin[]): Promise<TunnelPlugin | undefined> {\n debug(content`Looking up the Ngrok tunnel plugin...`)\n const tunnelPlugin = plugins.find((plugin) => TUNNEL_PLUGINS.includes(plugin.name))\n if (!tunnelPlugin) return undefined\n const tunnelPath = pathToFileURL(join(tunnelPlugin.root, 'dist/tunnel.js')).toString()\n return import(tunnelPath).catch(() => undefined)\n}\n\n/**\n * Convenience function to trigger a hook, and gather any successful responses. Failures are ignored.\n *\n * Responses are organised into a dictionary, keyed by plug-in name. Only plug-ins that have hooks registered for the given event, and the hooks were run successfully, are included.\n */\nexport async function fanoutHooks<TPluginMap extends HookReturnsPerPlugin, TEvent extends string & keyof TPluginMap>(\n config: Interfaces.Config,\n event: TEvent,\n options: TPluginMap[typeof event]['options'],\n timeout?: number,\n): Promise<Partial<TPluginMap[typeof event]['pluginReturns']>> {\n const res = await config.runHook(event, options, timeout)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Object.fromEntries(res.successes.map(({result, plugin}) => [plugin.name, result])) as any\n}\n\ntype AppSpecificMonorailFields = PickByPrefix<MonorailEventPublic, 'app_', 'project_type' | 'api_key' | 'partner_id'> &\n PickByPrefix<MonorailEventPublic, 'cmd_extensions_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_scaffold_'>\n\ninterface HookReturnsPerPlugin extends HookReturnPerTunnelPlugin {\n public_command_metadata: {\n options: {[key: string]: never}\n pluginReturns: {\n '@shopify/app': Partial<AppSpecificMonorailFields>\n [pluginName: string]: JsonMap\n }\n }\n [hookName: string]: {\n options: {[key: string]: unknown}\n pluginReturns: {[key: string]: JsonMap}\n }\n}\n\nexport type PluginReturnsForHook<\n TEvent extends keyof TPluginMap,\n TPluginName extends keyof TPluginMap[TEvent]['pluginReturns'],\n TPluginMap extends HookReturnsPerPlugin = HookReturnsPerPlugin,\n> = TPluginMap[TEvent]['pluginReturns'][TPluginName]\n\nexport type FanoutHookFunction<\n TEvent extends keyof TPluginMap = string,\n TPluginName extends keyof TPluginMap[TEvent]['pluginReturns'] = string,\n TPluginMap extends HookReturnsPerPlugin = HookReturnsPerPlugin,\n> = (\n this: Interfaces.Hook.Context,\n options: TPluginMap[TEvent]['options'] & {config: Interfaces.Config},\n) => Promise<PluginReturnsForHook<TEvent, TPluginName, TPluginMap>>\n"]}
|
|
@@ -31,7 +31,7 @@ export async function authorize(scopes, state = randomHex(30)) {
|
|
|
31
31
|
output.info('👉 Press any key to open the login page on your browser');
|
|
32
32
|
await keypress();
|
|
33
33
|
url = `${url}?${new URLSearchParams(params).toString()}`;
|
|
34
|
-
open(url);
|
|
34
|
+
await open(url);
|
|
35
35
|
const result = await listenRedirect(host, port, url);
|
|
36
36
|
if (result.state !== state) {
|
|
37
37
|
throw MismatchStateError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/session/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,2BAA2B,EAAE,SAAS,EAAC,MAAM,cAAc,CAAA;AACnE,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAC,KAAK,EAAE,eAAe,EAAC,MAAM,aAAa,CAAA;AAClD,OAAO,EAAC,QAAQ,IAAI,YAAY,EAAC,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAC,QAAQ,EAAE,kCAAkC,EAAC,MAAM,UAAU,CAAA;AACrE,OAAO,EAAC,SAAS,IAAI,eAAe,EAAC,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AAEjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,KAAK,CACzC,6GAA6G,CAC9G,CAAA;AAOD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAgB,EAAE,QAAgB,SAAS,CAAC,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,MAAM,WAAW,GAAG,UAAU,IAAI,IAAI,IAAI,EAAE,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IACjC,MAAM,gBAAgB,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEzC,MAAM,mCAAmC,CAAC,IAAI,CAAC,CAAA;IAE/C,IAAI,GAAG,GAAG,UAAU,IAAI,kBAAkB,CAAA;IAE1C,MAAM,EAAC,YAAY,EAAE,aAAa,EAAC,GAAG,2BAA2B,EAAE,CAAA;IAEnE,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,YAAY,EAAE,WAAW;QACzB,KAAK;QACL,aAAa,EAAE,MAAM;QACrB,qBAAqB,EAAE,MAAM;QAC7B,cAAc,EAAE,aAAa;KAC9B,CAAA;IAED,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IACjE,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;IACtE,MAAM,QAAQ,EAAE,CAAA;IAEhB,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAA;IACxD,IAAI,CAAC,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/session/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,2BAA2B,EAAE,SAAS,EAAC,MAAM,cAAc,CAAA;AACnE,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAC,KAAK,EAAE,eAAe,EAAC,MAAM,aAAa,CAAA;AAClD,OAAO,EAAC,QAAQ,IAAI,YAAY,EAAC,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAC,QAAQ,EAAE,kCAAkC,EAAC,MAAM,UAAU,CAAA;AACrE,OAAO,EAAC,SAAS,IAAI,eAAe,EAAC,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AAEjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,KAAK,CACzC,6GAA6G,CAC9G,CAAA;AAOD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAgB,EAAE,QAAgB,SAAS,CAAC,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,MAAM,WAAW,GAAG,UAAU,IAAI,IAAI,IAAI,EAAE,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IACjC,MAAM,gBAAgB,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEzC,MAAM,mCAAmC,CAAC,IAAI,CAAC,CAAA;IAE/C,IAAI,GAAG,GAAG,UAAU,IAAI,kBAAkB,CAAA;IAE1C,MAAM,EAAC,YAAY,EAAE,aAAa,EAAC,GAAG,2BAA2B,EAAE,CAAA;IAEnE,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,YAAY,EAAE,WAAW;QACzB,KAAK;QACL,aAAa,EAAE,MAAM;QACrB,qBAAqB,EAAE,MAAM;QAC7B,cAAc,EAAE,aAAa;KAC9B,CAAA;IAED,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IACjE,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;IACtE,MAAM,QAAQ,EAAE,CAAA;IAEhB,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAA;IACxD,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;IAEf,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IAEpD,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE;QAC1B,MAAM,kBAAkB,CAAA;KACzB;IAED,OAAO,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAC,CAAA;AAC1C,CAAC;AAED,KAAK,UAAU,mCAAmC,CAAC,IAAY;IAC7D,IAAI,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE;QAC/B,OAAM;KACP;IAED,IAAI,MAAM,kCAAkC,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE;QACpE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;KAC5B;SAAM;QACL,MAAM,IAAI,eAAe,EAAE,CAAA;KAC5B;AACH,CAAC","sourcesContent":["import {listenRedirect} from './redirect-listener.js'\nimport {clientId} from './identity.js'\nimport {generateRandomChallengePair, randomHex} from '../string.js'\nimport {open} from '../system.js'\nimport {Abort, CancelExecution} from '../error.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\nimport * as output from '../output.js'\nimport {keypress, terminateBlockingPortProcessPrompt} from '../ui.js'\nimport {checkPort as isPortAvailable} from 'get-port-please'\nimport {killPortProcess} from 'kill-port-process'\n\nexport const MismatchStateError = new Abort(\n \"The state received from the authentication doesn't match the one that initiated the authentication process.\",\n)\n\nexport interface CodeAuthResult {\n code: string\n codeVerifier: string\n}\n\nexport async function authorize(scopes: string[], state: string = randomHex(30)): Promise<CodeAuthResult> {\n const port = 3456\n const host = '127.0.0.1'\n const redirectUri = `http://${host}:${port}`\n const fqdn = await identityFqdn()\n const identityClientId = await clientId()\n\n await validateRedirectionPortAvailability(port)\n\n let url = `http://${fqdn}/oauth/authorize`\n\n const {codeVerifier, codeChallenge} = generateRandomChallengePair()\n\n const params = {\n client_id: identityClientId,\n scope: scopes.join(' '),\n redirect_uri: redirectUri,\n state,\n response_type: 'code',\n code_challenge_method: 'S256',\n code_challenge: codeChallenge,\n }\n\n output.info('\\nTo run this command, log in to Shopify Partners.')\n output.info('👉 Press any key to open the login page on your browser')\n await keypress()\n\n url = `${url}?${new URLSearchParams(params).toString()}`\n await open(url)\n\n const result = await listenRedirect(host, port, url)\n\n if (result.state !== state) {\n throw MismatchStateError\n }\n\n return {code: result.code, codeVerifier}\n}\n\nasync function validateRedirectionPortAvailability(port: number) {\n if (await isPortAvailable(port)) {\n return\n }\n\n if (await terminateBlockingPortProcessPrompt(port, 'Authentication')) {\n await killPortProcess(port)\n } else {\n throw new CancelExecution()\n }\n}\n"]}
|
package/dist/session/exchange.js
CHANGED
|
@@ -110,7 +110,7 @@ async function tokenRequest(params) {
|
|
|
110
110
|
else if (payload.error === 'invalid_request') {
|
|
111
111
|
// There's an scenario when Identity returns "invalid_request" when exchanging an identity token.
|
|
112
112
|
// This means the token is invalid. We clear the session and throw an error to let the caller know.
|
|
113
|
-
secureStore.remove();
|
|
113
|
+
await secureStore.remove();
|
|
114
114
|
throw InvalidIdentityError;
|
|
115
115
|
}
|
|
116
116
|
else {
|
|
@@ -127,7 +127,6 @@ function buildIdentityToken(result) {
|
|
|
127
127
|
scopes: result.scope.split(' '),
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
131
130
|
function buildApplicationToken(result) {
|
|
132
131
|
return {
|
|
133
132
|
accessToken: result.access_token,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/session/exchange.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApplicationToken, IdentityToken} from './schema.js'\nimport {applicationId, clientId as getIdentityClientId} from './identity.js'\nimport {CodeAuthResult} from './authorize.js'\nimport * as secureStore from './store.js'\nimport {Abort} from '../error.js'\nimport {API} from '../network/api.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\nimport {shopifyFetch} from '../http.js'\n\nexport class InvalidGrantError extends Error {}\n\nconst InvalidIdentityError = new Abort(\n '\\nError validating auth session',\n \"We've cleared the current session, please try again\",\n)\n\nexport interface ExchangeScopes {\n admin: string[]\n partners: string[]\n storefront: string[]\n}\n/**\n * Given a valid authorization code, request an identity access token.\n * This token can then be used to get API specific tokens.\n * @param codeData code and codeVerifier from the authorize endpoint\n * @param clientId\n * @param identityFqdn\n * @returns {Promise<IdentityToken>} An instance with the identity access tokens.\n */\nexport async function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n const params = {\n grant_type: 'authorization_code',\n code: codeData.code,\n redirect_uri: 'http://127.0.0.1:3456',\n client_id: clientId,\n code_verifier: codeData.codeVerifier,\n }\n\n return tokenRequest(params).then(buildIdentityToken)\n}\n\n/**\n * Given an identity token, request an application token.\n * @param token access token obtained in a previous step\n * @param store the store to use, only needed for admin API\n * @param clientId\n * @param identityFqdn\n * @returns {Promise<ApplicationSchema>} An array with the application access tokens.\n */\nexport async function exchangeAccessForApplicationTokens(\n identityToken: IdentityToken,\n scopes: ExchangeScopes,\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const token = identityToken.accessToken\n\n const partners = await requestAppToken('partners', token, scopes.partners)\n const storefront = await requestAppToken('storefront-renderer', token, scopes.storefront)\n\n const result = {\n ...partners,\n ...storefront,\n }\n\n if (store) {\n const admin = await requestAppToken('admin', token, scopes.admin, store)\n Object.assign(result, admin)\n }\n return result\n}\n\n/**\n * Given an expired access token, refresh it to get a new one.\n * @param currentToken\n * @returns\n */\nexport async function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n const params = {\n grant_type: 'refresh_token',\n access_token: currentToken.accessToken,\n refresh_token: currentToken.refreshToken,\n client_id: clientId,\n }\n return tokenRequest(params).then(buildIdentityToken)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid partners API token\n * This token does not accept extra scopes, just the cli one.\n * @param token {string} The CLI token passed as ENV variable\n * @returns {Promise<ApplicationToken>} An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<ApplicationToken> {\n const appId = applicationId('partners')\n const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access'])\n return newToken[appId]\n}\n\nasync function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const appId = applicationId(api)\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',\n requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n client_id: clientId,\n audience: appId,\n scope: scopes.join(' '),\n subject_token: token,\n ...(api === 'admin' && {destination: `https://${store}/admin`}),\n }\n\n let identifier = appId\n if (api === 'admin' && store) {\n identifier = `${store}-${appId}`\n }\n const appToken = await tokenRequest(params).then(buildApplicationToken)\n return {[identifier]: appToken}\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function tokenRequest(params: {[key: string]: string}): Promise<any> {\n const fqdn = await identityFqdn()\n const url = new URL(`https://${fqdn}/oauth/token`)\n url.search = new URLSearchParams(Object.entries(params)).toString()\n const res = await shopifyFetch('identity', url.href, {method: 'POST'})\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const payload: any = await res.json()\n if (!res.ok) {\n if (payload.error === 'invalid_grant') {\n // There's an scenario when Identity returns \"invalid_grant\" when trying to refresh the token\n // using a valid refresh token. When that happens, we take the user through the authentication flow.\n throw new InvalidGrantError(payload.error_description)\n } else if (payload.error === 'invalid_request') {\n // There's an scenario when Identity returns \"invalid_request\" when exchanging an identity token.\n // This means the token is invalid. We clear the session and throw an error to let the caller know.\n secureStore.remove()\n throw InvalidIdentityError\n } else {\n throw new Abort(payload.error_description)\n }\n }\n return payload\n}\n\nfunction buildIdentityToken(result: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n access_token: string\n // eslint-disable-next-line @typescript-eslint/naming-convention\n refresh_token: string\n // eslint-disable-next-line @typescript-eslint/naming-convention\n expires_in: number\n scope: string\n}): IdentityToken {\n return {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nfunction buildApplicationToken(result: {access_token: string; expires_in: number; scope: string}): ApplicationToken {\n return {\n accessToken: result.access_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/session/exchange.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApplicationToken, IdentityToken} from './schema.js'\nimport {applicationId, clientId as getIdentityClientId} from './identity.js'\nimport {CodeAuthResult} from './authorize.js'\nimport * as secureStore from './store.js'\nimport {Abort} from '../error.js'\nimport {API} from '../network/api.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\nimport {shopifyFetch} from '../http.js'\n\nexport class InvalidGrantError extends Error {}\n\nconst InvalidIdentityError = new Abort(\n '\\nError validating auth session',\n \"We've cleared the current session, please try again\",\n)\n\nexport interface ExchangeScopes {\n admin: string[]\n partners: string[]\n storefront: string[]\n}\n/**\n * Given a valid authorization code, request an identity access token.\n * This token can then be used to get API specific tokens.\n * @param codeData code and codeVerifier from the authorize endpoint\n * @param clientId\n * @param identityFqdn\n * @returns {Promise<IdentityToken>} An instance with the identity access tokens.\n */\nexport async function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n const params = {\n grant_type: 'authorization_code',\n code: codeData.code,\n redirect_uri: 'http://127.0.0.1:3456',\n client_id: clientId,\n code_verifier: codeData.codeVerifier,\n }\n\n return tokenRequest(params).then(buildIdentityToken)\n}\n\n/**\n * Given an identity token, request an application token.\n * @param token access token obtained in a previous step\n * @param store the store to use, only needed for admin API\n * @param clientId\n * @param identityFqdn\n * @returns {Promise<ApplicationSchema>} An array with the application access tokens.\n */\nexport async function exchangeAccessForApplicationTokens(\n identityToken: IdentityToken,\n scopes: ExchangeScopes,\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const token = identityToken.accessToken\n\n const partners = await requestAppToken('partners', token, scopes.partners)\n const storefront = await requestAppToken('storefront-renderer', token, scopes.storefront)\n\n const result = {\n ...partners,\n ...storefront,\n }\n\n if (store) {\n const admin = await requestAppToken('admin', token, scopes.admin, store)\n Object.assign(result, admin)\n }\n return result\n}\n\n/**\n * Given an expired access token, refresh it to get a new one.\n * @param currentToken\n * @returns\n */\nexport async function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n const params = {\n grant_type: 'refresh_token',\n access_token: currentToken.accessToken,\n refresh_token: currentToken.refreshToken,\n client_id: clientId,\n }\n return tokenRequest(params).then(buildIdentityToken)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid partners API token\n * This token does not accept extra scopes, just the cli one.\n * @param token {string} The CLI token passed as ENV variable\n * @returns {Promise<ApplicationToken>} An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<ApplicationToken> {\n const appId = applicationId('partners')\n const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access'])\n return newToken[appId]!\n}\n\nasync function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const appId = applicationId(api)\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',\n requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n client_id: clientId,\n audience: appId,\n scope: scopes.join(' '),\n subject_token: token,\n ...(api === 'admin' && {destination: `https://${store}/admin`}),\n }\n\n let identifier = appId\n if (api === 'admin' && store) {\n identifier = `${store}-${appId}`\n }\n const appToken = await tokenRequest(params).then(buildApplicationToken)\n return {[identifier]: appToken}\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function tokenRequest(params: {[key: string]: string}): Promise<any> {\n const fqdn = await identityFqdn()\n const url = new URL(`https://${fqdn}/oauth/token`)\n url.search = new URLSearchParams(Object.entries(params)).toString()\n const res = await shopifyFetch('identity', url.href, {method: 'POST'})\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const payload: any = await res.json()\n if (!res.ok) {\n if (payload.error === 'invalid_grant') {\n // There's an scenario when Identity returns \"invalid_grant\" when trying to refresh the token\n // using a valid refresh token. When that happens, we take the user through the authentication flow.\n throw new InvalidGrantError(payload.error_description)\n } else if (payload.error === 'invalid_request') {\n // There's an scenario when Identity returns \"invalid_request\" when exchanging an identity token.\n // This means the token is invalid. We clear the session and throw an error to let the caller know.\n await secureStore.remove()\n throw InvalidIdentityError\n } else {\n throw new Abort(payload.error_description)\n }\n }\n return payload\n}\n\nfunction buildIdentityToken(result: {\n access_token: string\n refresh_token: string\n expires_in: number\n scope: string\n}): IdentityToken {\n return {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n\nfunction buildApplicationToken(result: {access_token: string; expires_in: number; scope: string}): ApplicationToken {\n return {\n accessToken: result.access_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n"]}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { findUp, moduleDirectory } from '../path.js';
|
|
2
2
|
import { read } from '../file.js';
|
|
3
3
|
import { Bug } from '../error.js';
|
|
4
|
-
const HTMLFileNames = [
|
|
4
|
+
const HTMLFileNames = [
|
|
5
|
+
'empty-url.html',
|
|
6
|
+
'auth-error.html',
|
|
7
|
+
'missing-code.html',
|
|
8
|
+
'missing-state.html',
|
|
9
|
+
'success.html',
|
|
10
|
+
];
|
|
5
11
|
const StylesheetFilename = 'style.css';
|
|
6
12
|
const FaviconFileName = 'favicon.svg';
|
|
7
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-auth.js","sourceRoot":"","sources":["../../src/session/post-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,eAAe,EAAC,MAAM,YAAY,CAAA;AAClD,OAAO,EAAC,IAAI,EAAC,MAAM,YAAY,CAAA;AAC/B,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAE/B,MAAM,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"post-auth.js","sourceRoot":"","sources":["../../src/session/post-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,eAAe,EAAC,MAAM,YAAY,CAAA;AAClD,OAAO,EAAC,IAAI,EAAC,MAAM,YAAY,CAAA;AAC/B,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAE/B,MAAM,aAAa,GAAG;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,mBAAmB;IACnB,oBAAoB;IACpB,cAAc;CACN,CAAA;AACV,MAAM,kBAAkB,GAAG,WAAW,CAAA;AACtC,MAAM,eAAe,GAAG,aAAa,CAAA;AAErC;;;;;GAKG;AACH,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;IAC9D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,QAAQ,EAAE,EAAE;QAClD,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KACtC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,8BAA8B,EAAE,CAAA;KACvC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAqB,EAAE;IACzD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAqB,EAAE;IAC1D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,IAAqB,EAAE;IAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,IAAqB,EAAE;IAC7D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACxD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAqB,EAAE;IACvD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAA;IACtD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAqB,EAAE;IACpD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,CAAA;IACnD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,+DAA+D,CAAA;AAE7F,MAAM,CAAC,MAAM,eAAe,GAAG,kDAAkD,CAAA;AAEjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,kFAAkF,CAAA;AAEnH,MAAM,CAAC,MAAM,kBAAkB,GAAG,mFAAmF,CAAA;AAErH,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,+BAA+B,CAAC,CAAA","sourcesContent":["import {findUp, moduleDirectory} from '../path.js'\nimport {read} from '../file.js'\nimport {Bug} from '../error.js'\n\nconst HTMLFileNames = [\n 'empty-url.html',\n 'auth-error.html',\n 'missing-code.html',\n 'missing-state.html',\n 'success.html',\n] as const\nconst StylesheetFilename = 'style.css'\nconst FaviconFileName = 'favicon.svg'\n\n/**\n * Finds the full path of the given file-name from the assets folder.\n *\n * @param {string} fileName The name of the file to look for.\n * @returns {string | null} The full path of the file, or null if not found.\n */\nconst getFilePath = async (fileName: string): Promise<string> => {\n const filePath = await findUp(`assets/${fileName}`, {\n type: 'file',\n cwd: moduleDirectory(import.meta.url),\n })\n if (!filePath) {\n throw RedirectPageAssetNotFoundError()\n }\n return filePath\n}\n\nexport const getEmptyUrlHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[0])\n return read(filePath)\n}\n\nexport const getAuthErrorHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[1])\n return read(filePath)\n}\n\nexport const getMissingCodeHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[2])\n return read(filePath)\n}\n\nexport const getMissingStateHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[3])\n return read(filePath)\n}\n\nexport const getSuccessHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[4])\n return read(filePath)\n}\n\nexport const getStylesheet = async (): Promise<string> => {\n const filePath = await getFilePath(StylesheetFilename)\n return read(filePath)\n}\n\nexport const getFavicon = async (): Promise<string> => {\n const filePath = await getFilePath(FaviconFileName)\n return read(filePath)\n}\n\nexport const EmptyUrlString = 'We received the authentication redirect but the URL is empty.'\n\nexport const AuthErrorString = 'There was an issue while trying to authenticate.'\n\nexport const MissingCodeString = \"The authentication can't continue because the redirect doesn't include the code.\"\n\nexport const MissingStateString = \"The authentication can't continue because the redirect doesn't include the state.\"\n\nexport const RedirectPageAssetNotFoundError = () => new Bug(`Redirect page asset not found`)\n"]}
|
|
@@ -23,16 +23,16 @@ export class RedirectListener {
|
|
|
23
23
|
const requestUrl = request.url;
|
|
24
24
|
if (requestUrl === '/favicon.svg') {
|
|
25
25
|
const faviconFile = await getFavicon();
|
|
26
|
-
reply.header('Content-Type', 'image/svg+xml').send(faviconFile);
|
|
26
|
+
await reply.header('Content-Type', 'image/svg+xml').send(faviconFile);
|
|
27
27
|
return {};
|
|
28
28
|
}
|
|
29
29
|
else if (requestUrl === '/style.css') {
|
|
30
30
|
const stylesheetFile = await getStylesheet();
|
|
31
|
-
reply.header('Content-Type', 'text/css').send(stylesheetFile);
|
|
31
|
+
await reply.header('Content-Type', 'text/css').send(stylesheetFile);
|
|
32
32
|
return {};
|
|
33
33
|
}
|
|
34
|
-
const respond = (contents, error, state, code) => {
|
|
35
|
-
reply.header('Content-Type', 'text/html').send(contents);
|
|
34
|
+
const respond = async (contents, error, state, code) => {
|
|
35
|
+
await reply.header('Content-Type', 'text/html').send(contents);
|
|
36
36
|
callback(error, state, code);
|
|
37
37
|
return {};
|
|
38
38
|
};
|
|
@@ -79,9 +79,10 @@ export async function listenRedirect(host, port, url) {
|
|
|
79
79
|
const message = '\nAuto-open timed out. Open the login page: ';
|
|
80
80
|
info(content `${message}${token.link('Log in to Shopify Partners', url)}\n`);
|
|
81
81
|
}, ResponseTimeoutSeconds * 1000);
|
|
82
|
-
const callback =
|
|
82
|
+
const callback = (error, code, state) => {
|
|
83
83
|
clearTimeout(timeout);
|
|
84
84
|
setTimeout(() => {
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
85
86
|
redirectListener.stop();
|
|
86
87
|
if (error)
|
|
87
88
|
reject(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../src/session/redirect-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAC,KAAK,EAAE,GAAG,EAAC,MAAM,aAAa,CAAA;AACtC,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AACjD,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,MAAM,sBAAsB,GAAG,EAAE,CAAA;AACjC,MAAM,sBAAsB,GAAG,GAAG,CAAA;AAgBlC;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IA4D3B,YAAY,OAAgC;QAC1C,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/D,CAAC;IA/DO,MAAM,CAAC,YAAY,CAAC,QAA0B;QACpD,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACzD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAA;YAC9B,IAAI,UAAU,KAAK,cAAc,EAAE;gBACjC,MAAM,WAAW,GAAG,MAAM,UAAU,EAAE,CAAA;gBACtC,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../src/session/redirect-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAC,KAAK,EAAE,GAAG,EAAC,MAAM,aAAa,CAAA;AACtC,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AACjD,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,MAAM,sBAAsB,GAAG,EAAE,CAAA;AACjC,MAAM,sBAAsB,GAAG,GAAG,CAAA;AAgBlC;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IA4D3B,YAAY,OAAgC;QAC1C,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/D,CAAC;IA/DO,MAAM,CAAC,YAAY,CAAC,QAA0B;QACpD,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACzD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAA;YAC9B,IAAI,UAAU,KAAK,cAAc,EAAE;gBACjC,MAAM,WAAW,GAAG,MAAM,UAAU,EAAE,CAAA;gBACtC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBACrE,OAAO,EAAE,CAAA;aACV;iBAAM,IAAI,UAAU,KAAK,YAAY,EAAE;gBACtC,MAAM,cAAc,GAAG,MAAM,aAAa,EAAE,CAAA;gBAC5C,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;gBACnE,OAAO,EAAE,CAAA;aACV;YAED,MAAM,OAAO,GAAG,KAAK,EAAE,QAAgB,EAAE,KAAa,EAAE,KAAc,EAAE,IAAa,EAAE,EAAE;gBACvF,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;gBAC9D,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;gBAC5B,OAAO,EAAE,CAAA;YACX,CAAC,CAAA;YAED,iDAAiD;YACjD,IAAI,CAAC,UAAU,EAAE;gBACf,MAAM,IAAI,GAAG,MAAM,eAAe,EAAE,CAAA;gBACpC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAA;gBACnC,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;aAChD;YAED,mDAAmD;YACnD,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,CAAA;YACrD,IAAI,WAAW,CAAC,KAAK,IAAI,WAAW,CAAC,iBAAiB,EAAE;gBACtD,MAAM,IAAI,GAAG,MAAM,gBAAgB,EAAE,CAAA;gBACrC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,GAAG,WAAW,CAAC,iBAAiB,EAAE,CAAC,CAAA;gBACzD,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;aAChD;YAED,wCAAwC;YACxC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;gBACrB,MAAM,IAAI,GAAG,MAAM,kBAAkB,EAAE,CAAA;gBACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAA;gBACtC,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;aAChD;YAED,yCAAyC;YACzC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE;gBACtB,MAAM,IAAI,GAAG,MAAM,mBAAmB,EAAE,CAAA;gBACxC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAA;gBACvC,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;aAChD;YAED,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAA;YACnC,OAAO,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAA;QAChF,CAAC,CAAC,CAAA;QAEF,OAAO,MAAM,CAAA;IACf,CAAC;IAYD,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAC,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IAC3B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY,EAAE,GAAW;IAC1E,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,OAAO,GAAG,8CAA8C,CAAA;YAC9D,IAAI,CAAC,OAAO,CAAA,GAAG,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,4BAA4B,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;QAC7E,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC,CAAA;QAEjC,MAAM,QAAQ,GAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YACxD,YAAY,CAAC,OAAO,CAAC,CAAA;YACrB,UAAU,CAAC,GAAG,EAAE;gBACd,mEAAmE;gBACnE,gBAAgB,CAAC,IAAI,EAAE,CAAA;gBACvB,IAAI,KAAK;oBAAE,MAAM,CAAC,KAAK,CAAC,CAAA;;oBACnB,OAAO,CAAC,EAAC,IAAI,EAAE,IAAc,EAAE,KAAK,EAAE,KAAe,EAAC,CAAC,CAAA;YAC9D,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC,CAAA;QACnC,CAAC,CAAA;QAED,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAC,CAAC,CAAA;QACrE,gBAAgB,CAAC,KAAK,EAAE,CAAA;IAC1B,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import {\n getFavicon,\n getStylesheet,\n getEmptyUrlHTML,\n getAuthErrorHTML,\n getMissingCodeHTML,\n getMissingStateHTML,\n getSuccessHTML,\n EmptyUrlString,\n MissingCodeString,\n MissingStateString,\n} from './post-auth.js'\nimport {Abort, Bug} from '../error.js'\nimport {content, info, token} from '../output.js'\nimport Fastify from 'fastify'\nimport url from 'url'\n\nconst ResponseTimeoutSeconds = 10\nconst ServerStopDelaySeconds = 0.5\n\n/**\n * It represents the result of a redirect.\n */\ntype RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void\n\n/**\n * Defines the interface of the options that\n * are used to instantiate a redirect listener.\n */\ninterface RedirectListenerOptions {\n host: string\n port: number\n callback: RedirectCallback\n}\n/**\n * When the authentication completes, Identity redirects\n * the user to a URL. In the case of the CLI, the redirect\n * is to localhost passing some parameters that are necessary\n * to continue the authentication. Because of that, we need\n * an HTTP server that runs and listens to the request.\n */\nexport class RedirectListener {\n private static createServer(callback: RedirectCallback) {\n const server = Fastify().get('*', async (request, reply) => {\n const requestUrl = request.url\n if (requestUrl === '/favicon.svg') {\n const faviconFile = await getFavicon()\n await reply.header('Content-Type', 'image/svg+xml').send(faviconFile)\n return {}\n } else if (requestUrl === '/style.css') {\n const stylesheetFile = await getStylesheet()\n await reply.header('Content-Type', 'text/css').send(stylesheetFile)\n return {}\n }\n\n const respond = async (contents: string, error?: Error, state?: string, code?: string) => {\n await reply.header('Content-Type', 'text/html').send(contents)\n callback(error, state, code)\n return {}\n }\n\n // If there was an empty/malformed URL sent back.\n if (!requestUrl) {\n const file = await getEmptyUrlHTML()\n const err = new Bug(EmptyUrlString)\n return respond(file, err, undefined, undefined)\n }\n\n // If an error was returned by the Identity server.\n const queryObject = url.parse(requestUrl, true).query\n if (queryObject.error && queryObject.error_description) {\n const file = await getAuthErrorHTML()\n const err = new Abort(`${queryObject.error_description}`)\n return respond(file, err, undefined, undefined)\n }\n\n // If the code isn't present in the URL.\n if (!queryObject.code) {\n const file = await getMissingCodeHTML()\n const err = new Bug(MissingCodeString)\n return respond(file, err, undefined, undefined)\n }\n\n // If the state isn't present in the URL.\n if (!queryObject.state) {\n const file = await getMissingStateHTML()\n const err = new Bug(MissingStateString)\n return respond(file, err, undefined, undefined)\n }\n\n const file = await getSuccessHTML()\n return respond(file, undefined, `${queryObject.code}`, `${queryObject.state}`)\n })\n\n return server\n }\n\n port: number\n host: string\n server: ReturnType<typeof RedirectListener.createServer>\n\n constructor(options: RedirectListenerOptions) {\n this.port = options.port\n this.host = options.host\n this.server = RedirectListener.createServer(options.callback)\n }\n\n start(): void {\n this.server.listen({port: this.port, host: this.host}, () => {})\n }\n\n async stop(): Promise<void> {\n await this.server.close()\n }\n}\n\nexport async function listenRedirect(host: string, port: number, url: string): Promise<{code: string; state: string}> {\n const result = await new Promise<{code: string; state: string}>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const message = '\\nAuto-open timed out. Open the login page: '\n info(content`${message}${token.link('Log in to Shopify Partners', url)}\\n`)\n }, ResponseTimeoutSeconds * 1000)\n\n const callback: RedirectCallback = (error, code, state) => {\n clearTimeout(timeout)\n setTimeout(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n redirectListener.stop()\n if (error) reject(error)\n else resolve({code: code as string, state: state as string})\n }, ServerStopDelaySeconds * 1000)\n }\n\n const redirectListener = new RedirectListener({host, port, callback})\n redirectListener.start()\n })\n return result\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/session/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,eAAe,CAAA;AAE3C,OAAO,SAAS,MAAM,iBAAiB,CAAA;AAEvC,OAAO,EAAC,QAAQ,EAAE,QAAQ,EAAC,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAA;AAClC,OAAO,EAAC,aAAa,EAAC,MAAM,yBAAyB,CAAA;AAIrD;;;;;GAKG;AACH,SAAS,cAAc,CAAC,eAAyB,EAAE,QAAuB;IACxE,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAA;IACrC,IAAI,aAAa,EAAE,KAAK,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAA;IACxE,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAgB,EAChB,YAA+B,EAC/B,OAGC;IAED,IAAI,CAAC,OAAO;QAAE,OAAO,iBAAiB,CAAA;IACtC,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/D,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC1F,IAAI,CAAC,cAAc;QAAE,OAAO,iBAAiB,CAAA;IAC7C,IAAI,gBAAgB,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACvD,IAAI,gBAAgB,GAAG,KAAK,CAAA;IAE5B,IAAI,YAAY,CAAC,WAAW,EAAE;QAC5B,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;QACvC,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/session/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import {applicationId} from './identity.js'\nimport {ApplicationToken, IdentityToken} from './schema.js'\nimport constants from '../constants.js'\nimport {OAuthApplications} from '../session.js'\nimport {identity, partners} from '../api.js'\nimport {debug} from '../output.js'\nimport {firstPartyDev} from '../environment/local.js'\n\ntype ValidationResult = 'needs_refresh' | 'needs_full_auth' | 'ok'\n\n/**\n * Validate if an identity token is valid for the requested scopes\n * @param requestedScopes scopes\n * @param identity\n * @returns\n */\nfunction validateScopes(requestedScopes: string[], identity: IdentityToken) {\n const currentScopes = identity.scopes\n if (firstPartyDev() !== currentScopes.includes('employee')) return false\n return requestedScopes.every((scope) => currentScopes.includes(scope))\n}\n\n/**\n * Validate if the current session is valid or we need to refresh/re-authenticate\n * @param scopes {string[]} requested scopes to validate\n * @param applications {OAuthApplications} requested applications\n * @param session current session with identity and application tokens\n * @returns {ValidationResult} 'ok' if the session is valid, 'needs_full_auth' if we need to re-authenticate, 'needs_refresh' if we need to refresh the session\n */\nexport async function validateSession(\n scopes: string[],\n applications: OAuthApplications,\n session: {\n identity: IdentityToken\n applications: {[x: string]: ApplicationToken}\n },\n): Promise<ValidationResult> {\n if (!session) return 'needs_full_auth'\n const scopesAreValid = validateScopes(scopes, session.identity)\n const identityIsValid = await identity.validateIdentityToken(session.identity.accessToken)\n if (!scopesAreValid) return 'needs_full_auth'\n let tokensAreExpired = isTokenExpired(session.identity)\n let tokensAreRevoked = false\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n const token = session.applications[appId]!\n tokensAreRevoked = tokensAreRevoked || (await isPartnersTokenRevoked(token))\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n const token = session.applications[appId]!\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = session.applications[realAppId]!\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n debug(`\nThe validation of the token for application/identity completed with the following results:\n- It's expired: ${tokensAreExpired}\n- It's been revoked: ${tokensAreRevoked}\n- It's invalid in identity: ${!identityIsValid}\n `)\n\n if (tokensAreExpired) return 'needs_refresh'\n if (tokensAreRevoked) return 'needs_full_auth'\n if (!identityIsValid) return 'needs_full_auth'\n return 'ok'\n}\n\nfunction isTokenExpired(token: ApplicationToken): boolean {\n if (!token) return true\n return token.expiresAt < expireThreshold()\n}\n\nasync function isPartnersTokenRevoked(token: ApplicationToken) {\n if (!token) return false\n return partners.checkIfTokenIsRevoked(token.accessToken)\n}\n\nfunction expireThreshold(): Date {\n return new Date(Date.now() + constants.session.expirationTimeMarginInMinutes * 60 * 1000)\n}\n"]}
|
package/dist/session.js
CHANGED
|
@@ -161,7 +161,7 @@ export async function ensureUserHasPartnerAccount(partnersToken) {
|
|
|
161
161
|
output.info(`\nA Shopify Partners organization is needed to proceed.`);
|
|
162
162
|
output.info(`👉 Press any key to create one`);
|
|
163
163
|
await keypress();
|
|
164
|
-
open(`https://partners.shopify.com/signup`);
|
|
164
|
+
await open(`https://partners.shopify.com/signup`);
|
|
165
165
|
output.info(output.content `👉 Press any key when you have ${output.token.cyan('created the organization')}`);
|
|
166
166
|
output.warn(output.content `Make sure you've confirmed your Shopify and the Partner organization from the email`);
|
|
167
167
|
await keypress();
|