@shopify/cli-kit 3.38.0 → 3.39.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/dist/private/common/json.d.ts +2 -2
- package/dist/private/common/lodash.d.ts +4 -4
- package/dist/private/common/ts/overloaded-parameters.d.ts +5 -5
- package/dist/private/node/api/headers.d.ts +1 -1
- package/dist/private/node/api.d.ts +1 -1
- package/dist/private/node/constants.d.ts +2 -2
- package/dist/private/node/environment/service.d.ts +1 -1
- package/dist/private/node/error-handler.d.ts +2 -0
- package/dist/private/node/error-handler.js +5 -0
- package/dist/private/node/error-handler.js.map +1 -0
- package/dist/private/node/session/exchange.d.ts +1 -1
- package/dist/private/node/session/redirect-listener.d.ts +1 -1
- package/dist/private/node/session/redirect-listener.js +5 -5
- package/dist/private/node/session/redirect-listener.js.map +1 -1
- package/dist/private/node/session/schema.d.ts +3 -3
- package/dist/private/node/session/validate.d.ts +1 -1
- package/dist/private/node/session.d.ts +4 -4
- package/dist/private/node/ui/components/AutocompletePrompt.d.ts +9 -2
- package/dist/private/node/ui/components/AutocompletePrompt.js +8 -4
- package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +62 -8
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.d.ts +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.d.ts +2 -2
- package/dist/private/node/ui/components/SelectInput.d.ts +3 -1
- package/dist/private/node/ui/components/SelectInput.js +8 -2
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.test.js +26 -0
- package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
- package/dist/private/node/ui/components/Table/Row.d.ts +1 -1
- package/dist/private/node/ui/components/Table/ScalarDict.d.ts +1 -1
- package/dist/private/node/ui/components/Table/Table.d.ts +1 -1
- package/dist/private/node/ui/components/Tasks.d.ts +5 -1
- package/dist/private/node/ui/components/Tasks.js +31 -6
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.test.js +259 -19
- package/dist/private/node/ui/components/Tasks.test.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.d.ts +2 -2
- package/dist/private/node/ui.d.ts +1 -1
- package/dist/public/common/string.d.ts +1 -1
- package/dist/{private → public}/common/ts/deep-required.d.ts +2 -1
- package/dist/{private → public}/common/ts/deep-required.js +0 -0
- package/dist/public/common/ts/deep-required.js.map +1 -0
- package/dist/public/common/ts/pick-by-prefix.d.ts +2 -1
- package/dist/public/common/ts/pick-by-prefix.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/api/http.d.ts +1 -0
- package/dist/public/node/api/http.js +1 -1
- package/dist/public/node/archiver.d.ts +20 -6
- package/dist/public/node/archiver.js +14 -13
- package/dist/public/node/archiver.js.map +1 -1
- package/dist/public/node/crypto.d.ts +1 -1
- package/dist/public/node/dot-env.js +2 -0
- package/dist/public/node/dot-env.js.map +1 -1
- package/dist/public/node/environment/local.d.ts +1 -1
- package/dist/public/node/environment/spin.d.ts +1 -1
- package/dist/public/node/error-handler.d.ts +1 -2
- package/dist/public/node/error-handler.js +12 -2
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/fs.d.ts +24 -4
- package/dist/public/node/fs.js +31 -2
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/git.d.ts +9 -1
- package/dist/public/node/git.js +31 -1
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/http.d.ts +9 -1
- package/dist/public/node/http.js +34 -0
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/metadata.d.ts +7 -7
- package/dist/public/node/monorail.d.ts +6 -6
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/node-package-manager.d.ts +5 -5
- package/dist/public/node/os.d.ts +2 -2
- package/dist/public/node/output.d.ts +4 -4
- package/dist/public/node/path.d.ts +1 -1
- package/dist/public/node/plugins/tunnel.d.ts +5 -5
- package/dist/public/node/plugins.d.ts +4 -4
- package/dist/public/node/result.d.ts +1 -1
- package/dist/public/node/ruby.d.ts +1 -1
- package/dist/public/node/session.d.ts +1 -1
- package/dist/public/node/system.d.ts +1 -1
- package/dist/public/node/ui.d.ts +10 -5
- package/dist/public/node/ui.js +4 -3
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui.d.ts +6 -20
- package/dist/ui.js +1 -21
- package/dist/ui.js.map +1 -1
- package/package.json +6 -7
- package/dist/private/common/ts/deep-required.js.map +0 -1
- package/dist/private/node/simple-definitions.d.ts +0 -4
- package/dist/private/node/simple-definitions.js +0 -2
- package/dist/private/node/simple-definitions.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface JsonMap {
|
|
2
2
|
[key: string]: AnyJson;
|
|
3
3
|
}
|
|
4
|
-
|
|
5
|
-
export
|
|
4
|
+
type JsonArray = undefined[] | null[] | boolean[] | number[] | string[] | JsonMap[] | Date[];
|
|
5
|
+
export type AnyJson = undefined | null | boolean | number | string | JsonMap | Date | JsonArray | JsonArray[];
|
|
6
6
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type PartialShallow<T> = {
|
|
2
2
|
[P in keyof T]?: T[P] extends object ? object : T[P];
|
|
3
3
|
};
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
4
|
+
export type PropertyName = string | number | symbol;
|
|
5
|
+
export type IterateeShorthand<T> = PropertyName | [PropertyName, unknown] | PartialShallow<T>;
|
|
6
|
+
export type ValueIteratee<T> = ((value: T) => unknown) | IterateeShorthand<T>;
|
|
7
7
|
export interface Dictionary<T> {
|
|
8
8
|
[index: string]: T;
|
|
9
9
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
type OverloadProps<TOverload> = Pick<TOverload, keyof TOverload>;
|
|
2
|
+
type OverloadUnionRecursive<TOverload, TPartialOverload = unknown> = TOverload extends (...args: infer TArgs) => infer TReturn ? TPartialOverload extends TOverload ? never : OverloadUnionRecursive<TPartialOverload & TOverload, TPartialOverload & ((...args: TArgs) => TReturn) & OverloadProps<TOverload>> | ((...args: TArgs) => TReturn) : never;
|
|
3
|
+
type OverloadUnion<TOverload extends (...args: any[]) => any> = Exclude<OverloadUnionRecursive<(() => never) & TOverload>, TOverload extends () => never ? never : () => never>;
|
|
4
|
+
export type OverloadParameters<T extends (...args: any[]) => any> = Parameters<OverloadUnion<T>>;
|
|
5
|
+
export type OverloadReturnType<T extends (...args: any[]) => any> = ReturnType<OverloadUnion<T>>;
|
|
6
6
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type API = 'admin' | 'storefront-renderer' | 'partners';
|
|
2
2
|
export declare const allAPIs: API[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/private/node/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,QAAQ,CAAA;AAEpC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9C,MAAM,EAAC,OAAO,EAAE,OAAO,EAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;AAEjD,OAAO,EAAC,OAAO,EAAC,CAAA","sourcesContent":["import {createRequire} from 'module'\n\nconst require = createRequire(import.meta.url)\nconst {default: Bugsnag} = require('@bugsnag/js')\n\nexport {Bugsnag}\n"]}
|
|
@@ -38,7 +38,7 @@ export declare function refreshAccessToken(currentToken: IdentityToken): Promise
|
|
|
38
38
|
* @returns An instance with the application access tokens.
|
|
39
39
|
*/
|
|
40
40
|
export declare function exchangeCustomPartnerToken(token: string): Promise<ApplicationToken>;
|
|
41
|
-
export
|
|
41
|
+
export type IdentityDeviceError = 'authorization_pending' | 'access_denied' | 'expired_token' | 'slow_down' | 'unknown_failure';
|
|
42
42
|
/**
|
|
43
43
|
* Given a deviceCode obtained after starting a device identity flow, request an identity token.
|
|
44
44
|
* @param deviceCode - The device code obtained after starting a device identity flow
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* It represents the result of a redirect.
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
type RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void;
|
|
5
5
|
/**
|
|
6
6
|
* Defines the interface of the options that
|
|
7
7
|
* are used to instantiate a redirect listener.
|
|
@@ -14,11 +14,6 @@ const ServerStopDelaySeconds = 0.5;
|
|
|
14
14
|
* an HTTP server that runs and listens to the request.
|
|
15
15
|
*/
|
|
16
16
|
export class RedirectListener {
|
|
17
|
-
constructor(options) {
|
|
18
|
-
this.port = options.port;
|
|
19
|
-
this.host = options.host;
|
|
20
|
-
this.server = RedirectListener.createServer(options.callback);
|
|
21
|
-
}
|
|
22
17
|
static createServer(callback) {
|
|
23
18
|
const app = createApp().use('*', async (request, response) => {
|
|
24
19
|
const requestUrl = request.url;
|
|
@@ -74,6 +69,11 @@ export class RedirectListener {
|
|
|
74
69
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
75
70
|
return createServer(app);
|
|
76
71
|
}
|
|
72
|
+
constructor(options) {
|
|
73
|
+
this.port = options.port;
|
|
74
|
+
this.host = options.host;
|
|
75
|
+
this.server = RedirectListener.createServer(options.callback);
|
|
76
|
+
}
|
|
77
77
|
start() {
|
|
78
78
|
this.server.listen({ port: this.port, host: this.host }, () => { });
|
|
79
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../../../src/private/node/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,UAAU,EAAE,QAAQ,EAAC,MAAM,+BAA+B,CAAA;AAClE,OAAO,EAAC,aAAa,EAAE,UAAU,EAAE,WAAW,EAAC,MAAM,gCAAgC,CAAA;AACrF,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;
|
|
1
|
+
{"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../../../src/private/node/session/redirect-listener.ts"],"names":[],"mappings":"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","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 {AbortError, BugError} from '../../../public/node/error.js'\nimport {outputContent, outputInfo, outputToken} from '../../../public/node/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?.includes('favicon')) {\n const faviconFile = await getFavicon()\n response.setHeader('Content-Type', 'image/svg+xml')\n response.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')\n response.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')\n response.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 BugError(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 AbortError(`${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 BugError(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 BugError(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 outputInfo(outputContent`${message}${outputToken.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"]}
|
|
@@ -169,7 +169,7 @@ export declare const SessionSchema: schema.ZodObject<{}, "strip", schema.ZodObje
|
|
|
169
169
|
};
|
|
170
170
|
};
|
|
171
171
|
}>;
|
|
172
|
-
export
|
|
173
|
-
export
|
|
174
|
-
export
|
|
172
|
+
export type Session = schema.infer<typeof SessionSchema>;
|
|
173
|
+
export type IdentityToken = schema.infer<typeof IdentityTokenSchema>;
|
|
174
|
+
export type ApplicationToken = schema.infer<typeof ApplicationTokenSchema>;
|
|
175
175
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ApplicationToken, IdentityToken } from './schema.js';
|
|
2
2
|
import { OAuthApplications } from '../session.js';
|
|
3
|
-
|
|
3
|
+
type ValidationResult = 'needs_refresh' | 'needs_full_auth' | 'ok';
|
|
4
4
|
/**
|
|
5
5
|
* Validate if the current session is valid or we need to refresh/re-authenticate
|
|
6
6
|
* @param scopes - requested scopes to validate
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import { AdminSession } from '@shopify/cli-kit/node/session';
|
|
3
3
|
/**
|
|
4
4
|
* A scope supported by the Shopify Admin API.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
type AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string;
|
|
7
7
|
/**
|
|
8
8
|
* It represents the options to authenticate against the Shopify Admin API.
|
|
9
9
|
*/
|
|
@@ -16,7 +16,7 @@ interface AdminAPIOAuthOptions {
|
|
|
16
16
|
/**
|
|
17
17
|
* A scope supported by the Partners API.
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
type PartnersAPIScope = 'cli' | string;
|
|
20
20
|
interface PartnersAPIOAuthOptions {
|
|
21
21
|
/** List of scopes to request permissions for. */
|
|
22
22
|
scopes: PartnersAPIScope[];
|
|
@@ -24,7 +24,7 @@ interface PartnersAPIOAuthOptions {
|
|
|
24
24
|
/**
|
|
25
25
|
* A scope supported by the Storefront Renderer API.
|
|
26
26
|
*/
|
|
27
|
-
|
|
27
|
+
type StorefrontRendererScope = 'devtools' | string;
|
|
28
28
|
interface StorefrontRendererAPIOAuthOptions {
|
|
29
29
|
/** List of scopes to request permissions for. */
|
|
30
30
|
scopes: StorefrontRendererScope[];
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { Props as SelectProps, Item as SelectItem } from './SelectInput.js';
|
|
2
2
|
import { Props as InfoTableProps } from './Prompts/InfoTable.js';
|
|
3
3
|
import React, { ReactElement } from 'react';
|
|
4
|
+
export interface SearchResults<T> {
|
|
5
|
+
data: SelectItem<T>[];
|
|
6
|
+
meta?: {
|
|
7
|
+
hasNextPage: boolean;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
4
10
|
export interface Props<T> {
|
|
5
11
|
message: string;
|
|
6
12
|
choices: SelectProps<T>['items'];
|
|
7
13
|
onSubmit: (value: T) => void;
|
|
8
14
|
infoTable?: InfoTableProps['table'];
|
|
9
|
-
|
|
15
|
+
hasMorePages?: boolean;
|
|
16
|
+
search: (term: string) => Promise<SearchResults<T>>;
|
|
10
17
|
}
|
|
11
|
-
declare function AutocompletePrompt<T>({ message, choices: initialChoices, infoTable, onSubmit, search, }: React.PropsWithChildren<Props<T>>): ReactElement | null;
|
|
18
|
+
declare function AutocompletePrompt<T>({ message, choices: initialChoices, infoTable, onSubmit, search, hasMorePages: initialHasMorePages, }: React.PropsWithChildren<Props<T>>): ReactElement | null;
|
|
12
19
|
export { AutocompletePrompt };
|
|
@@ -16,7 +16,7 @@ var PromptState;
|
|
|
16
16
|
PromptState["Error"] = "error";
|
|
17
17
|
})(PromptState || (PromptState = {}));
|
|
18
18
|
const PAGE_SIZE = 25;
|
|
19
|
-
function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSubmit, search, }) {
|
|
19
|
+
function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSubmit, search, hasMorePages: initialHasMorePages = false, }) {
|
|
20
20
|
const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE);
|
|
21
21
|
const [answer, setAnswer] = useState(paginatedInitialChoices[0]);
|
|
22
22
|
const { exit: unmountInk } = useApp();
|
|
@@ -26,9 +26,11 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
26
26
|
const { stdout } = useStdout();
|
|
27
27
|
const [height, setHeight] = useState(0);
|
|
28
28
|
const canSearch = initialChoices.length >= PAGE_SIZE;
|
|
29
|
+
const [hasMorePages, setHasMorePages] = useState(initialHasMorePages);
|
|
29
30
|
const paginatedSearch = useCallback(async (term) => {
|
|
30
31
|
const results = await search(term);
|
|
31
|
-
|
|
32
|
+
results.data = results.data.slice(0, PAGE_SIZE);
|
|
33
|
+
return results;
|
|
32
34
|
}, []);
|
|
33
35
|
const measuredRef = useCallback((node) => {
|
|
34
36
|
if (node !== null) {
|
|
@@ -65,9 +67,11 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
65
67
|
// choices instead
|
|
66
68
|
if (searchTermRef.current.length === 0) {
|
|
67
69
|
setSearchResults(paginatedInitialChoices);
|
|
70
|
+
setHasMorePages(initialHasMorePages);
|
|
68
71
|
}
|
|
69
72
|
else {
|
|
70
|
-
setSearchResults(result);
|
|
73
|
+
setSearchResults(result.data);
|
|
74
|
+
setHasMorePages(result.meta?.hasNextPage ?? false);
|
|
71
75
|
}
|
|
72
76
|
setPromptState(PromptState.Idle);
|
|
73
77
|
})
|
|
@@ -105,7 +109,7 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
|
|
|
105
109
|
setAnswer(item);
|
|
106
110
|
}, enableShortcuts: false, emptyMessage: "No results found.", highlightedTerm: searchTerm, loading: promptState === PromptState.Loading, errorMessage: promptState === PromptState.Error
|
|
107
111
|
? 'There has been an error while searching. Please try again later.'
|
|
108
|
-
: undefined })))));
|
|
112
|
+
: undefined, hasMorePages: hasMorePages, morePagesMessage: "Find what you're looking for by typing its name." })))));
|
|
109
113
|
}
|
|
110
114
|
export { AutocompletePrompt };
|
|
111
115
|
//# sourceMappingURL=AutocompletePrompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import SelectInput, {Props as SelectProps, Item as SelectItem, Item} from './SelectInput.js'\nimport InfoTable, {Props as InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport React, {ReactElement, useCallback, useRef, useState} from 'react'\nimport {Box, measureElement, Text, useApp, useInput, useStdout} from 'ink'\nimport figures from 'figures'\nimport {debounce} from '@shopify/cli-kit/common/function'\nimport ansiEscapes from 'ansi-escapes'\n\nexport interface Props<T> {\n message: string\n choices: SelectProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n search: (term: string) => Promise<SelectItem<T>[]>\n}\n\nenum PromptState {\n Idle = 'idle',\n Loading = 'loading',\n Submitted = 'submitted',\n Error = 'error',\n}\n\nconst PAGE_SIZE = 25\n\nfunction AutocompletePrompt<T>({\n message,\n choices: initialChoices,\n infoTable,\n onSubmit,\n search,\n}: React.PropsWithChildren<Props<T>>): ReactElement | null {\n const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE)\n const [answer, setAnswer] = useState<SelectItem<T> | undefined>(paginatedInitialChoices[0])\n const {exit: unmountInk} = useApp()\n const [promptState, setPromptState] = useState<PromptState>(PromptState.Idle)\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(paginatedInitialChoices.slice(0, PAGE_SIZE))\n const {stdout} = useStdout()\n const [height, setHeight] = useState(0)\n const canSearch = initialChoices.length >= PAGE_SIZE\n\n const paginatedSearch = useCallback(async (term: string) => {\n const results = await search(term)\n return results.slice(0, PAGE_SIZE)\n }, [])\n\n const measuredRef = useCallback(\n (node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setHeight(height)\n }\n },\n [searchResults, promptState],\n )\n\n useInput(\n useCallback(\n (input, key) => {\n handleCtrlC(input, key)\n\n if (key.return && promptState === PromptState.Idle && answer) {\n // -1 is for the last row with the terminal cursor\n if (stdout && height >= stdout.rows - 1) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n setPromptState(PromptState.Submitted)\n setSearchTerm('')\n unmountInk()\n onSubmit(answer.value)\n }\n },\n [answer, onSubmit, height, promptState],\n ),\n )\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n const debounceSearch = useCallback(\n debounce((term) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(paginatedInitialChoices)\n } else {\n setSearchResults(result)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current!)\n })\n }, 300),\n [],\n )\n\n return (\n <Box flexDirection=\"column\" marginBottom={1} ref={measuredRef}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <Text>{messageWithPunctuation(message)}</Text>\n {promptState !== PromptState.Submitted && canSearch && (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(paginatedInitialChoices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n )}\n </Box>\n\n {infoTable && promptState !== PromptState.Submitted && (\n <Box marginLeft={7} marginTop={1}>\n <InfoTable table={infoTable} />\n </Box>\n )}\n\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box marginRight={2}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Text color=\"cyan\">{answer!.label}</Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <SelectInput\n items={searchResults}\n onChange={(item: Item<T> | undefined) => {\n setAnswer(item)\n }}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n />\n </Box>\n )}\n </Box>\n )\n}\n\nexport {AutocompletePrompt}\n"]}
|
|
1
|
+
{"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import SelectInput, {Props as SelectProps, Item as SelectItem, Item} from './SelectInput.js'\nimport InfoTable, {Props as InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport React, {ReactElement, useCallback, useRef, useState} from 'react'\nimport {Box, measureElement, Text, useApp, useInput, useStdout} from 'ink'\nimport figures from 'figures'\nimport {debounce} from '@shopify/cli-kit/common/function'\nimport ansiEscapes from 'ansi-escapes'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface Props<T> {\n message: string\n choices: SelectProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n}\n\nenum PromptState {\n Idle = 'idle',\n Loading = 'loading',\n Submitted = 'submitted',\n Error = 'error',\n}\n\nconst PAGE_SIZE = 25\n\nfunction AutocompletePrompt<T>({\n message,\n choices: initialChoices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n}: React.PropsWithChildren<Props<T>>): ReactElement | null {\n const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE)\n const [answer, setAnswer] = useState<SelectItem<T> | undefined>(paginatedInitialChoices[0])\n const {exit: unmountInk} = useApp()\n const [promptState, setPromptState] = useState<PromptState>(PromptState.Idle)\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(paginatedInitialChoices.slice(0, PAGE_SIZE))\n const {stdout} = useStdout()\n const [height, setHeight] = useState(0)\n const canSearch = initialChoices.length >= PAGE_SIZE\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n\n const paginatedSearch = useCallback(async (term: string) => {\n const results = await search(term)\n results.data = results.data.slice(0, PAGE_SIZE)\n return results\n }, [])\n\n const measuredRef = useCallback(\n (node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setHeight(height)\n }\n },\n [searchResults, promptState],\n )\n\n useInput(\n useCallback(\n (input, key) => {\n handleCtrlC(input, key)\n\n if (key.return && promptState === PromptState.Idle && answer) {\n // -1 is for the last row with the terminal cursor\n if (stdout && height >= stdout.rows - 1) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n setPromptState(PromptState.Submitted)\n setSearchTerm('')\n unmountInk()\n onSubmit(answer.value)\n }\n },\n [answer, onSubmit, height, promptState],\n ),\n )\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n const debounceSearch = useCallback(\n debounce((term) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(paginatedInitialChoices)\n setHasMorePages(initialHasMorePages)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current!)\n })\n }, 300),\n [],\n )\n\n return (\n <Box flexDirection=\"column\" marginBottom={1} ref={measuredRef}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <Text>{messageWithPunctuation(message)}</Text>\n {promptState !== PromptState.Submitted && canSearch && (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(paginatedInitialChoices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n )}\n </Box>\n\n {infoTable && promptState !== PromptState.Submitted && (\n <Box marginLeft={7} marginTop={1}>\n <InfoTable table={infoTable} />\n </Box>\n )}\n\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box marginRight={2}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Text color=\"cyan\">{answer!.label}</Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <SelectInput\n items={searchResults}\n onChange={(item: Item<T> | undefined) => {\n setAnswer(item)\n }}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n />\n </Box>\n )}\n </Box>\n )\n}\n\nexport {AutocompletePrompt}\n"]}
|
|
@@ -67,7 +67,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
67
67
|
{ label: 'third', value: 'third' },
|
|
68
68
|
];
|
|
69
69
|
const infoTable = { Add: ['new-ext'], Remove: ['integrated-demand-ext', 'order-discount'] };
|
|
70
|
-
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: items, infoTable: infoTable, onSubmit: onEnter, search: () => Promise.resolve(
|
|
70
|
+
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: items, infoTable: infoTable, onSubmit: onEnter, search: () => Promise.resolve({
|
|
71
|
+
data: [],
|
|
72
|
+
}) }));
|
|
71
73
|
await waitForInputsToBeReady();
|
|
72
74
|
await sendInputAndWaitForChange(renderInstance, ARROW_DOWN);
|
|
73
75
|
await sendInputAndWaitForChange(renderInstance, ENTER);
|
|
@@ -91,7 +93,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
91
93
|
{ label: 'ninth', value: 'ninth' },
|
|
92
94
|
{ label: 'tenth', value: 'tenth' },
|
|
93
95
|
];
|
|
94
|
-
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: items, onSubmit: () => { }, search: () => Promise.resolve(
|
|
96
|
+
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: items, onSubmit: () => { }, search: () => Promise.resolve({
|
|
97
|
+
data: [],
|
|
98
|
+
}) }));
|
|
95
99
|
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
96
100
|
"? Associate your project with the org Castile Ventures?
|
|
97
101
|
|
|
@@ -126,7 +130,7 @@ describe('AutocompletePrompt', async () => {
|
|
|
126
130
|
Add: ['new-ext'],
|
|
127
131
|
Remove: ['integrated-demand-ext', 'order-discount'],
|
|
128
132
|
};
|
|
129
|
-
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: items, infoTable: infoTable, onSubmit: () => { }, search: () => Promise.resolve([]) }));
|
|
133
|
+
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: items, infoTable: infoTable, onSubmit: () => { }, search: () => Promise.resolve({ data: [] }) }));
|
|
130
134
|
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
131
135
|
"? Associate your project with the org Castile Ventures?
|
|
132
136
|
|
|
@@ -146,7 +150,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
146
150
|
});
|
|
147
151
|
test("doesn't submit if there are no choices", async () => {
|
|
148
152
|
const onEnter = vi.fn();
|
|
149
|
-
const searchPromise = Promise.resolve(
|
|
153
|
+
const searchPromise = Promise.resolve({
|
|
154
|
+
data: [],
|
|
155
|
+
});
|
|
150
156
|
const search = () => {
|
|
151
157
|
return searchPromise;
|
|
152
158
|
};
|
|
@@ -166,7 +172,7 @@ describe('AutocompletePrompt', async () => {
|
|
|
166
172
|
test('has a loading state', async () => {
|
|
167
173
|
const onEnter = vi.fn();
|
|
168
174
|
const searchPromise = new Promise((resolve) => {
|
|
169
|
-
setTimeout(() => resolve([{ label: 'a', value: 'b' }]), 2000);
|
|
175
|
+
setTimeout(() => resolve({ data: [{ label: 'a', value: 'b' }] }), 2000);
|
|
170
176
|
});
|
|
171
177
|
const search = () => {
|
|
172
178
|
return searchPromise;
|
|
@@ -187,7 +193,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
187
193
|
test('allows searching with pagination', async () => {
|
|
188
194
|
const onEnter = vi.fn();
|
|
189
195
|
const search = async (term) => {
|
|
190
|
-
return
|
|
196
|
+
return {
|
|
197
|
+
data: DATABASE.filter((item) => item.label.includes(term)),
|
|
198
|
+
};
|
|
191
199
|
};
|
|
192
200
|
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: DATABASE, onSubmit: onEnter, search: search }));
|
|
193
201
|
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
@@ -336,7 +344,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
336
344
|
const onEnter = vi.fn();
|
|
337
345
|
const search = async (term) => {
|
|
338
346
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
339
|
-
return
|
|
347
|
+
return {
|
|
348
|
+
data: DATABASE.filter((item) => item.label.includes(term)),
|
|
349
|
+
};
|
|
340
350
|
};
|
|
341
351
|
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: DATABASE, onSubmit: onEnter, search: search }));
|
|
342
352
|
await waitForInputsToBeReady();
|
|
@@ -398,7 +408,9 @@ describe('AutocompletePrompt', async () => {
|
|
|
398
408
|
});
|
|
399
409
|
test('immediately shows the initial items if the search is empty', async () => {
|
|
400
410
|
const search = (term) => {
|
|
401
|
-
return Promise.resolve(
|
|
411
|
+
return Promise.resolve({
|
|
412
|
+
data: DATABASE.filter((item) => item.label.includes(term)),
|
|
413
|
+
});
|
|
402
414
|
};
|
|
403
415
|
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: DATABASE, onSubmit: () => { }, search: search }));
|
|
404
416
|
await waitForInputsToBeReady();
|
|
@@ -469,5 +481,47 @@ describe('AutocompletePrompt', async () => {
|
|
|
469
481
|
"
|
|
470
482
|
`);
|
|
471
483
|
});
|
|
484
|
+
test('shows a message that indicates there are more results than shown', async () => {
|
|
485
|
+
const search = (_term) => {
|
|
486
|
+
return Promise.resolve({
|
|
487
|
+
data: DATABASE,
|
|
488
|
+
meta: { hasNextPage: true },
|
|
489
|
+
});
|
|
490
|
+
};
|
|
491
|
+
const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Associate your project with the org Castile Ventures?", choices: DATABASE, onSubmit: () => { }, hasMorePages: true, search: search }));
|
|
492
|
+
expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
|
|
493
|
+
"? Associate your project with the org Castile Ventures? [36m[7mT[27m[2mype to search...[22m[39m
|
|
494
|
+
|
|
495
|
+
[36m>[39m [36mfirst[39m
|
|
496
|
+
second
|
|
497
|
+
third
|
|
498
|
+
fourth
|
|
499
|
+
fifth
|
|
500
|
+
sixth
|
|
501
|
+
seventh
|
|
502
|
+
eighth
|
|
503
|
+
ninth
|
|
504
|
+
tenth
|
|
505
|
+
eleventh
|
|
506
|
+
twelfth
|
|
507
|
+
thirteenth
|
|
508
|
+
fourteenth
|
|
509
|
+
fifteenth
|
|
510
|
+
sixteenth
|
|
511
|
+
seventeenth
|
|
512
|
+
eighteenth
|
|
513
|
+
nineteenth
|
|
514
|
+
twentieth
|
|
515
|
+
twenty-first
|
|
516
|
+
twenty-second
|
|
517
|
+
twenty-third
|
|
518
|
+
twenty-fourth
|
|
519
|
+
twenty-fifth
|
|
520
|
+
|
|
521
|
+
[1m1-25 of many[22m Find what you're looking for by typing its name.
|
|
522
|
+
[2mPress ↑↓ arrows to select, enter to confirm[22m
|
|
523
|
+
"
|
|
524
|
+
`);
|
|
525
|
+
});
|
|
472
526
|
});
|
|
473
527
|
//# sourceMappingURL=AutocompletePrompt.test.js.map
|