@shopify/cli-kit 3.15.0 → 3.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,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
+ {"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,EAAC,SAAS,EAAkC,MAAM,IAAI,CAAA;AAC7D,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,EAAC,YAAY,EAAS,MAAM,MAAM,CAAA;AAEzC,MAAM,sBAAsB,GAAG,EAAE,CAAA;AACjC,MAAM,sBAAsB,GAAG,GAAG,CAAA;AAgBlC;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IAgE3B,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;IAnEO,MAAM,CAAC,YAAY,CAAC,QAA0B;QACpD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAwB,EAAE,QAAwB,EAAE,EAAE;YAC5F,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAA;YAC9B,IAAI,UAAU,KAAK,cAAc,EAAE;gBACjC,MAAM,WAAW,GAAG,MAAM,UAAU,EAAE,CAAA;gBACtC,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;gBACtE,QAAQ,CAAC,GAAG,EAAE,CAAA;gBACd,OAAO,EAAE,CAAA;aACV;iBAAM,IAAI,UAAU,KAAK,YAAY,EAAE;gBACtC,MAAM,cAAc,GAAG,MAAM,aAAa,EAAE,CAAA;gBAC5C,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;gBACpE,QAAQ,CAAC,GAAG,EAAE,CAAA;gBACd,OAAO,EAAE,CAAA;aACV;YAED,MAAM,OAAO,GAAG,KAAK,EAAE,QAAgB,EAAE,KAAa,EAAE,KAAc,EAAE,IAAa,EAAE,EAAE;gBACvF,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;gBAC/D,QAAQ,CAAC,GAAG,EAAE,CAAA;gBACd,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,kEAAkE;QAClE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAA;IAC1B,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 {createApp, IncomingMessage, ServerResponse} from 'h3'\nimport url from 'url'\nimport {createServer, Server} from 'http'\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): Server {\n const app = createApp().use('*', async (request: IncomingMessage, response: ServerResponse) => {\n const requestUrl = request.url\n if (requestUrl === '/favicon.svg') {\n const faviconFile = await getFavicon()\n response.setHeader('Content-Type', 'image/svg+xml').write(faviconFile)\n response.end()\n return {}\n } else if (requestUrl === '/style.css') {\n const stylesheetFile = await getStylesheet()\n response.setHeader('Content-Type', 'text/css').write(stylesheetFile)\n response.end()\n return {}\n }\n\n const respond = async (contents: string, error?: Error, state?: string, code?: string) => {\n response.setHeader('Content-Type', 'text/html').write(contents)\n response.end()\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 // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return createServer(app)\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"]}