@shopify/cli-kit 3.65.2 → 3.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/private/node/api.d.ts +10 -2
  2. package/dist/private/node/api.js +151 -14
  3. package/dist/private/node/api.js.map +1 -1
  4. package/dist/private/node/conf-store.d.ts +27 -1
  5. package/dist/private/node/conf-store.js +39 -1
  6. package/dist/private/node/conf-store.js.map +1 -1
  7. package/dist/private/node/ui/components/SelectInput.js +1 -1
  8. package/dist/private/node/ui/components/SelectInput.js.map +1 -1
  9. package/dist/public/common/string.d.ts +7 -0
  10. package/dist/public/common/string.js +11 -0
  11. package/dist/public/common/string.js.map +1 -1
  12. package/dist/public/common/version.d.ts +1 -1
  13. package/dist/public/common/version.js +1 -1
  14. package/dist/public/common/version.js.map +1 -1
  15. package/dist/public/node/api/app-dev.js +3 -1
  16. package/dist/public/node/api/app-dev.js.map +1 -1
  17. package/dist/public/node/api/business-platform.d.ts +11 -1
  18. package/dist/public/node/api/business-platform.js +35 -8
  19. package/dist/public/node/api/business-platform.js.map +1 -1
  20. package/dist/public/node/api/graphql.js +2 -2
  21. package/dist/public/node/api/graphql.js.map +1 -1
  22. package/dist/public/node/api/rest-api-throttler.d.ts +23 -0
  23. package/dist/public/node/api/rest-api-throttler.js +239 -0
  24. package/dist/public/node/api/rest-api-throttler.js.map +1 -0
  25. package/dist/public/node/custom-oclif-loader.js +2 -1
  26. package/dist/public/node/custom-oclif-loader.js.map +1 -1
  27. package/dist/public/node/fs.d.ts +5 -0
  28. package/dist/public/node/fs.js +8 -1
  29. package/dist/public/node/fs.js.map +1 -1
  30. package/dist/public/node/hooks/prerun.d.ts +4 -0
  31. package/dist/public/node/hooks/prerun.js +27 -1
  32. package/dist/public/node/hooks/prerun.js.map +1 -1
  33. package/dist/public/node/http.d.ts +3 -3
  34. package/dist/public/node/http.js +6 -3
  35. package/dist/public/node/http.js.map +1 -1
  36. package/dist/public/node/ink.d.ts +1 -1
  37. package/dist/public/node/ink.js +1 -1
  38. package/dist/public/node/ink.js.map +1 -1
  39. package/dist/public/node/node-package-manager.d.ts +8 -1
  40. package/dist/public/node/node-package-manager.js +19 -3
  41. package/dist/public/node/node-package-manager.js.map +1 -1
  42. package/dist/public/node/output.d.ts +0 -8
  43. package/dist/public/node/output.js +0 -14
  44. package/dist/public/node/output.js.map +1 -1
  45. package/dist/public/node/themes/api.d.ts +1 -1
  46. package/dist/public/node/themes/api.js +16 -8
  47. package/dist/public/node/themes/api.js.map +1 -1
  48. package/dist/public/node/themes/theme-manager.d.ts +1 -0
  49. package/dist/public/node/themes/theme-manager.js +3 -0
  50. package/dist/public/node/themes/theme-manager.js.map +1 -1
  51. package/dist/public/node/themes/types.d.ts +4 -0
  52. package/dist/public/node/themes/types.js.map +1 -1
  53. package/dist/public/node/ui.d.ts +2 -2
  54. package/dist/public/node/ui.js.map +1 -1
  55. package/dist/public/node/upgrade.d.ts +14 -0
  56. package/dist/public/node/upgrade.js +38 -0
  57. package/dist/public/node/upgrade.js.map +1 -0
  58. package/dist/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +2 -3
  60. package/dist/private/node/themes/themes-api/headers.d.ts +0 -3
  61. package/dist/private/node/themes/themes-api/headers.js +0 -29
  62. package/dist/private/node/themes/themes-api/headers.js.map +0 -1
  63. package/dist/private/node/themes/themes-api/retry.d.ts +0 -1
  64. package/dist/private/node/themes/themes-api/retry.js +0 -6
  65. package/dist/private/node/themes/themes-api/retry.js.map +0 -1
  66. package/dist/private/node/themes/themes-api/throttler.d.ts +0 -2
  67. package/dist/private/node/themes/themes-api/throttler.js +0 -82
  68. package/dist/private/node/themes/themes-api/throttler.js.map +0 -1
@@ -2,11 +2,19 @@ import { Headers } from 'form-data';
2
2
  export type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management';
3
3
  export declare const allAPIs: API[];
4
4
  interface RequestOptions<T> {
5
- request: Promise<T>;
5
+ request: () => Promise<T>;
6
6
  url: string;
7
7
  }
8
- export declare function debugLogResponseInfo<T extends {
8
+ export declare function simpleRequestWithDebugLog<T extends {
9
9
  headers: Headers;
10
10
  status: number;
11
11
  }>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown): Promise<T>;
12
+ export declare function retryAwareRequest<T extends {
13
+ headers: Headers;
14
+ status: number;
15
+ }>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown, retryOptions?: {
16
+ limitRetriesTo?: number;
17
+ defaultDelayMs?: number;
18
+ scheduleDelay: (fn: () => void, delay: number) => void;
19
+ }): Promise<T>;
12
20
  export {};
@@ -4,42 +4,179 @@ import { outputDebug } from '@shopify/cli-kit/node/output';
4
4
  import { ClientError } from 'graphql-request';
5
5
  import { performance } from 'perf_hooks';
6
6
  export const allAPIs = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management'];
7
- const interestingResponseHeaders = new Set(['cache-control', 'content-type', 'etag', 'x-request-id']);
8
- export async function debugLogResponseInfo({ request, url }, errorHandler) {
7
+ const DEFAULT_RETRY_DELAY_MS = 1000;
8
+ const DEFAULT_RETRY_LIMIT = 10;
9
+ const interestingResponseHeaders = new Set([
10
+ 'cache-control',
11
+ 'content-type',
12
+ 'etag',
13
+ 'x-request-id',
14
+ 'server-timing',
15
+ 'retry-after',
16
+ ]);
17
+ function responseHeaderIsInteresting(header) {
18
+ return interestingResponseHeaders.has(header);
19
+ }
20
+ async function makeVerboseRequest({ request, url, }) {
9
21
  const t0 = performance.now();
22
+ let duration = 0;
10
23
  const responseHeaders = {};
24
+ const sanitizedUrl = sanitizeURL(url);
11
25
  let response = {};
12
26
  try {
13
- response = await request;
27
+ response = await request();
14
28
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
29
  response.headers.forEach((value, key) => {
16
- if (interestingResponseHeaders.has(key))
30
+ if (responseHeaderIsInteresting(key))
17
31
  responseHeaders[key] = value;
18
32
  });
33
+ // eslint-disable-next-line no-catch-all/no-catch-all
19
34
  }
20
35
  catch (err) {
36
+ const t1 = performance.now();
37
+ duration = Math.round(t1 - t0);
21
38
  if (err instanceof ClientError) {
22
39
  if (err.response?.headers) {
23
40
  for (const [key, value] of err.response?.headers) {
24
- if (interestingResponseHeaders.has(key))
41
+ if (responseHeaderIsInteresting(key))
25
42
  responseHeaders[key] = value;
26
43
  }
27
44
  }
45
+ const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders);
46
+ if (err.response.errors?.some((error) => error.extensions?.code === '429') || err.response.status === 429) {
47
+ let delayMs;
48
+ try {
49
+ delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined;
50
+ // eslint-disable-next-line no-catch-all/no-catch-all
51
+ }
52
+ catch {
53
+ // ignore errors in extracting retry-after header
54
+ }
55
+ return {
56
+ status: 'can-retry',
57
+ clientError: err,
58
+ duration,
59
+ sanitizedHeaders,
60
+ sanitizedUrl,
61
+ requestId: responseHeaders['x-request-id'],
62
+ delayMs,
63
+ };
64
+ }
65
+ return {
66
+ status: 'client-error',
67
+ clientError: err,
68
+ duration,
69
+ sanitizedHeaders,
70
+ sanitizedUrl,
71
+ requestId: responseHeaders['x-request-id'],
72
+ };
28
73
  }
29
- if (errorHandler) {
30
- throw errorHandler(err, responseHeaders['x-request-id']);
74
+ return {
75
+ status: 'unknown-error',
76
+ error: err,
77
+ duration,
78
+ sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),
79
+ sanitizedUrl,
80
+ requestId: responseHeaders['x-request-id'],
81
+ };
82
+ }
83
+ const t1 = performance.now();
84
+ duration = Math.round(t1 - t0);
85
+ return {
86
+ status: 'ok',
87
+ response,
88
+ duration,
89
+ sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),
90
+ sanitizedUrl,
91
+ requestId: responseHeaders['x-request-id'],
92
+ };
93
+ }
94
+ export async function simpleRequestWithDebugLog({ request, url }, errorHandler) {
95
+ const result = await makeVerboseRequest({ request, url });
96
+ outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms
97
+ With response headers:
98
+ ${result.sanitizedHeaders}
99
+ `);
100
+ switch (result.status) {
101
+ case 'ok': {
102
+ return result.response;
103
+ }
104
+ case 'client-error': {
105
+ if (errorHandler) {
106
+ throw errorHandler(result.clientError, result.requestId);
107
+ }
108
+ else {
109
+ throw result.clientError;
110
+ }
111
+ }
112
+ case 'unknown-error': {
113
+ if (errorHandler) {
114
+ throw errorHandler(result.error, result.requestId);
115
+ }
116
+ else {
117
+ throw result.error;
118
+ }
31
119
  }
32
- else {
33
- throw err;
120
+ case 'can-retry': {
121
+ if (errorHandler) {
122
+ throw errorHandler(result.clientError, result.requestId);
123
+ }
124
+ else {
125
+ throw result.clientError;
126
+ }
34
127
  }
35
128
  }
36
- finally {
37
- const t1 = performance.now();
38
- outputDebug(`Request to ${sanitizeURL(url)} completed in ${Math.round(t1 - t0)} ms
129
+ }
130
+ export async function retryAwareRequest({ request, url }, errorHandler, retryOptions = {
131
+ scheduleDelay: setTimeout,
132
+ }) {
133
+ let retriesUsed = 0;
134
+ const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT;
135
+ let result = await makeVerboseRequest({ request, url });
136
+ outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms
39
137
  With response headers:
40
- ${sanitizedHeadersOutput(responseHeaders)}
138
+ ${result.sanitizedHeaders}
41
139
  `);
140
+ while (true) {
141
+ if (result.status === 'ok') {
142
+ if (retriesUsed > 0) {
143
+ outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`);
144
+ }
145
+ return result.response;
146
+ }
147
+ else if (result.status === 'client-error') {
148
+ if (errorHandler) {
149
+ throw errorHandler(result.clientError, result.requestId);
150
+ }
151
+ else {
152
+ throw result.clientError;
153
+ }
154
+ }
155
+ else if (result.status === 'unknown-error') {
156
+ if (errorHandler) {
157
+ throw errorHandler(result.error, result.requestId);
158
+ }
159
+ else {
160
+ throw result.error;
161
+ }
162
+ }
163
+ if (limitRetriesTo <= retriesUsed) {
164
+ outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`);
165
+ if (errorHandler) {
166
+ throw errorHandler(result.clientError, result.requestId);
167
+ }
168
+ else {
169
+ throw result.clientError;
170
+ }
171
+ }
172
+ retriesUsed += 1;
173
+ // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.
174
+ const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS;
175
+ outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`);
176
+ // eslint-disable-next-line no-await-in-loop
177
+ result = await new Promise((resolve) => retryOptions.scheduleDelay(() => {
178
+ resolve(makeVerboseRequest({ request, url }));
179
+ }, retryDelayMs));
42
180
  }
43
- return response;
44
181
  }
45
182
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAA;AAExD,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAA;AAItC,MAAM,CAAC,MAAM,OAAO,GAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,mBAAmB,EAAE,gBAAgB,CAAC,CAAA;AAOjH,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;AAErG,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAC,OAAO,EAAE,GAAG,EAAoB,EACjC,YAAiF;IAEjF,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;IAC5B,MAAM,eAAe,GAA4B,EAAE,CAAA;IACnD,IAAI,QAAQ,GAAM,EAAO,CAAA;IACzB,IAAI;QACF,QAAQ,GAAG,MAAM,OAAO,CAAA;QACxB,8DAA8D;QAC9D,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAU,EAAE,GAAQ,EAAE,EAAE;YAChD,IAAI,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACvE,CAAC,CAAC,CAAA;KACH;IAAC,OAAO,GAAG,EAAE;QACZ,IAAI,GAAG,YAAY,WAAW,EAAE;YAC9B,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE;gBACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAqC,EAAE;oBAC9E,IAAI,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC;wBAAE,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;iBACtE;aACF;SACF;QACD,IAAI,YAAY,EAAE;YAChB,MAAM,YAAY,CAAC,GAAG,EAAE,eAAe,CAAC,cAAc,CAAC,CAAC,CAAA;SACzD;aAAM;YACL,MAAM,GAAG,CAAA;SACV;KACF;YAAS;QACR,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QAC5B,WAAW,CAAC,cAAc,WAAW,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;;EAEhF,sBAAsB,CAAC,eAAe,CAAC;KACpC,CAAC,CAAA;KACH;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {outputDebug} from '@shopify/cli-kit/node/output'\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\ninterface RequestOptions<T> {\n request: Promise<T>\n url: string\n}\n\nconst interestingResponseHeaders = new Set(['cache-control', 'content-type', 'etag', 'x-request-id'])\n\nexport async function debugLogResponseInfo<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown,\n): Promise<T> {\n const t0 = performance.now()\n const responseHeaders: {[key: string]: string} = {}\n let response: T = {} as T\n try {\n response = await request\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (interestingResponseHeaders.has(key)) responseHeaders[key] = value\n })\n } catch (err) {\n if (err instanceof ClientError) {\n if (err.response?.headers) {\n for (const [key, value] of err.response?.headers as Iterable<[string, string]>) {\n if (interestingResponseHeaders.has(key)) responseHeaders[key] = value\n }\n }\n }\n if (errorHandler) {\n throw errorHandler(err, responseHeaders['x-request-id'])\n } else {\n throw err\n }\n } finally {\n const t1 = performance.now()\n outputDebug(`Request to ${sanitizeURL(url)} completed in ${Math.round(t1 - t0)} ms\nWith response headers:\n${sanitizedHeadersOutput(responseHeaders)}\n `)\n }\n return response\n}\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {outputDebug} from '@shopify/cli-kit/node/output'\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\ninterface RequestOptions<T> {\n request: () => Promise<T>\n url: string\n}\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ntype VerboseResponse<T> = {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n} & (\n | {status: 'ok'; response: T}\n | {status: 'client-error'; clientError: ClientError}\n | {status: 'unknown-error'; error: unknown}\n | {status: 'can-retry'; clientError: ClientError; delayMs: number | undefined}\n)\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>({\n request,\n url,\n}: RequestOptions<T>): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: {[key: string]: string} = {}\n const sanitizedUrl = sanitizeURL(url)\n let response: T = {} as T\n try {\n response = await request()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response?.headers) {\n for (const [key, value] of err.response?.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (err.response.errors?.some((error) => error.extensions?.code === '429') || err.response.status === 429) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown,\n): Promise<T> {\n const result = await makeVerboseRequest({request, url})\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest({request, url})\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) =>\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest({request, url}))\n }, retryDelayMs),\n )\n }\n}\n"]}
@@ -5,9 +5,12 @@ interface CacheValue<T> {
5
5
  }
6
6
  export type IntrospectionUrlKey = `identity-introspection-url-${string}`;
7
7
  export type PackageVersionKey = `npm-package-${string}`;
8
+ type MostRecentOccurrenceKey = `most-recent-occurrence-${string}`;
9
+ type ExportedKey = IntrospectionUrlKey | PackageVersionKey;
8
10
  interface Cache {
9
11
  [introspectionUrlKey: IntrospectionUrlKey]: CacheValue<string>;
10
12
  [packageVersionKey: PackageVersionKey]: CacheValue<string>;
13
+ [MostRecentOccurrenceKey: MostRecentOccurrenceKey]: CacheValue<boolean>;
11
14
  }
12
15
  export interface ConfSchema {
13
16
  sessionStore: string;
@@ -39,5 +42,28 @@ type CacheValueForKey<TKey extends keyof Cache> = NonNullable<Cache[TKey]>['valu
39
42
  * If the cached value is older than this, it will be refreshed.
40
43
  * @returns The value from the cache or the result of the function.
41
44
  */
42
- export declare function cacheRetrieveOrRepopulate(key: keyof Cache, fn: () => Promise<CacheValueForKey<typeof key>>, timeout?: number, config?: LocalStorage<ConfSchema>): Promise<CacheValueForKey<typeof key>>;
45
+ export declare function cacheRetrieveOrRepopulate(key: ExportedKey, fn: () => Promise<CacheValueForKey<typeof key>>, timeout?: number, config?: LocalStorage<ConfSchema>): Promise<CacheValueForKey<typeof key>>;
46
+ /**
47
+ * Fetch from cache if already populated, otherwise return undefined.
48
+ * @param key - The key to use for the cache.
49
+ * @returns The value from the cache or the result of the function.
50
+ */
51
+ export declare function cacheRetrieve(key: ExportedKey, config?: LocalStorage<ConfSchema>): CacheValueForKey<typeof key> | undefined;
52
+ export declare function cacheClear(config?: LocalStorage<ConfSchema>): void;
53
+ interface TimeInterval {
54
+ days?: number;
55
+ hours?: number;
56
+ minutes?: number;
57
+ seconds?: number;
58
+ }
59
+ /**
60
+ * Execute a task only if the most recent occurrence of the task is older than the specified timeout.
61
+ * @param key - The key to use for the cache.
62
+ * @param timeout - The maximum valid age of the most recent occurrence, expressed as an object with
63
+ * days, hours, minutes, and seconds properties.
64
+ * If the most recent occurrence is older than this, the task will be executed.
65
+ * @param task - The task to run if the most recent occurrence is older than the timeout.
66
+ * @returns The result of the task, or undefined if the task was not run.
67
+ */
68
+ export declare function runAtMinimumInterval(key: string, timeout: TimeInterval, task: () => Promise<void>, config?: LocalStorage<ConfSchema>): Promise<boolean | undefined>;
43
69
  export {};
@@ -1,3 +1,4 @@
1
+ import { isUnitTest } from '../../public/node/context/local.js';
1
2
  import { LocalStorage } from '../../public/node/local-storage.js';
2
3
  import { outputContent, outputDebug } from '@shopify/cli-kit/node/output';
3
4
  let _instance;
@@ -8,7 +9,7 @@ let _instance;
8
9
  */
9
10
  function cliKitStore() {
10
11
  if (!_instance) {
11
- _instance = new LocalStorage({ projectName: 'shopify-cli-kit' });
12
+ _instance = new LocalStorage({ projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}` });
12
13
  }
13
14
  return _instance;
14
15
  }
@@ -57,4 +58,41 @@ export async function cacheRetrieveOrRepopulate(key, fn, timeout, config = cliKi
57
58
  config.set('cache', cache);
58
59
  return value;
59
60
  }
61
+ /**
62
+ * Fetch from cache if already populated, otherwise return undefined.
63
+ * @param key - The key to use for the cache.
64
+ * @returns The value from the cache or the result of the function.
65
+ */
66
+ export function cacheRetrieve(key, config = cliKitStore()) {
67
+ const cache = config.get('cache') || {};
68
+ const cached = cache[key];
69
+ return cached?.value;
70
+ }
71
+ export function cacheClear(config = cliKitStore()) {
72
+ config.delete('cache');
73
+ }
74
+ function timeIntervalToMilliseconds({ days = 0, hours = 0, minutes = 0, seconds = 0 }) {
75
+ return (days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds) * 1000;
76
+ }
77
+ /**
78
+ * Execute a task only if the most recent occurrence of the task is older than the specified timeout.
79
+ * @param key - The key to use for the cache.
80
+ * @param timeout - The maximum valid age of the most recent occurrence, expressed as an object with
81
+ * days, hours, minutes, and seconds properties.
82
+ * If the most recent occurrence is older than this, the task will be executed.
83
+ * @param task - The task to run if the most recent occurrence is older than the timeout.
84
+ * @returns The result of the task, or undefined if the task was not run.
85
+ */
86
+ export async function runAtMinimumInterval(key, timeout, task, config = cliKitStore()) {
87
+ const cache = config.get('cache') || {};
88
+ const cacheKey = `most-recent-occurrence-${key}`;
89
+ const cached = cache[cacheKey];
90
+ if (cached?.value !== undefined && Date.now() - cached.timestamp < timeIntervalToMilliseconds(timeout)) {
91
+ return undefined;
92
+ }
93
+ await task();
94
+ cache[cacheKey] = { value: true, timestamp: Date.now() };
95
+ config.set('cache', cache);
96
+ return true;
97
+ }
60
98
  //# sourceMappingURL=conf-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conf-store.js","sourceRoot":"","sources":["../../../src/private/node/conf-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,oCAAoC,CAAA;AAC/D,OAAO,EAAC,aAAa,EAAE,WAAW,EAAC,MAAM,8BAA8B,CAAA;AAoBvE,IAAI,SAA+C,CAAA;AAEnD;;;;GAIG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC,SAAS,EAAE;QACd,SAAS,GAAG,IAAI,YAAY,CAAa,EAAC,WAAW,EAAE,iBAAiB,EAAC,CAAC,CAAA;KAC3E;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,SAAmC,WAAW,EAAE;IACzE,WAAW,CAAC,aAAa,CAAA,0BAA0B,CAAC,CAAA;IACpD,OAAO,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,SAAmC,WAAW,EAAE;IAC1F,WAAW,CAAC,aAAa,CAAA,0BAA0B,CAAC,CAAA;IACpD,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,SAAmC,WAAW,EAAE;IAC5E,WAAW,CAAC,aAAa,CAAA,2BAA2B,CAAC,CAAA;IACrD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;AAC/B,CAAC;AAGD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,GAAgB,EAChB,EAA+C,EAC/C,OAAgB,EAChB,MAAM,GAAG,WAAW,EAAE;IAEtB,MAAM,KAAK,GAAU,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IAEzB,IAAI,MAAM,EAAE,KAAK,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,EAAE;QACrG,OAAO,MAAM,CAAC,KAAK,CAAA;KACpB;IAED,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,CAAA;IACxB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAA;IAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC1B,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import {LocalStorage} from '../../public/node/local-storage.js'\nimport {outputContent, outputDebug} from '@shopify/cli-kit/node/output'\n\ninterface CacheValue<T> {\n value: T\n timestamp: number\n}\n\nexport type IntrospectionUrlKey = `identity-introspection-url-${string}`\nexport type PackageVersionKey = `npm-package-${string}`\n\ninterface Cache {\n [introspectionUrlKey: IntrospectionUrlKey]: CacheValue<string>\n [packageVersionKey: PackageVersionKey]: CacheValue<string>\n}\n\nexport interface ConfSchema {\n sessionStore: string\n cache?: Cache\n}\n\nlet _instance: LocalStorage<ConfSchema> | undefined\n\n/**\n * CLIKIT Store.\n *\n * @returns CLIKitStore.\n */\nfunction cliKitStore() {\n if (!_instance) {\n _instance = new LocalStorage<ConfSchema>({projectName: 'shopify-cli-kit'})\n }\n return _instance\n}\n\n/**\n * Get session.\n *\n * @returns Session.\n */\nexport function getSession(config: LocalStorage<ConfSchema> = cliKitStore()): string | undefined {\n outputDebug(outputContent`Getting session store...`)\n return config.get('sessionStore')\n}\n\n/**\n * Set session.\n *\n * @param session - Session.\n */\nexport function setSession(session: string, config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Setting session store...`)\n config.set('sessionStore', session)\n}\n\n/**\n * Remove session.\n */\nexport function removeSession(config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Removing session store...`)\n config.delete('sessionStore')\n}\n\ntype CacheValueForKey<TKey extends keyof Cache> = NonNullable<Cache[TKey]>['value']\n/**\n * Fetch from cache, or run the provided function to get the value, and cache it\n * before returning it.\n * @param key - The key to use for the cache.\n * @param fn - The function to run to get the value to cache, if a cache miss occurs.\n * @param timeout - The maximum valid age of a cached value, in milliseconds.\n * If the cached value is older than this, it will be refreshed.\n * @returns The value from the cache or the result of the function.\n */\nexport async function cacheRetrieveOrRepopulate(\n key: keyof Cache,\n fn: () => Promise<CacheValueForKey<typeof key>>,\n timeout?: number,\n config = cliKitStore(),\n): Promise<CacheValueForKey<typeof key>> {\n const cache: Cache = config.get('cache') || {}\n const cached = cache[key]\n\n if (cached?.value !== undefined && (timeout === undefined || Date.now() - cached.timestamp < timeout)) {\n return cached.value\n }\n\n const value = await fn()\n cache[key] = {value, timestamp: Date.now()}\n config.set('cache', cache)\n return value\n}\n"]}
1
+ {"version":3,"file":"conf-store.js","sourceRoot":"","sources":["../../../src/private/node/conf-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest} from '../../public/node/context/local.js'\nimport {LocalStorage} from '../../public/node/local-storage.js'\nimport {outputContent, outputDebug} from '@shopify/cli-kit/node/output'\n\ninterface CacheValue<T> {\n value: T\n timestamp: number\n}\n\nexport type IntrospectionUrlKey = `identity-introspection-url-${string}`\nexport type PackageVersionKey = `npm-package-${string}`\ntype MostRecentOccurrenceKey = `most-recent-occurrence-${string}`\n\ntype ExportedKey = IntrospectionUrlKey | PackageVersionKey\n\ninterface Cache {\n [introspectionUrlKey: IntrospectionUrlKey]: CacheValue<string>\n [packageVersionKey: PackageVersionKey]: CacheValue<string>\n [MostRecentOccurrenceKey: MostRecentOccurrenceKey]: CacheValue<boolean>\n}\n\nexport interface ConfSchema {\n sessionStore: string\n cache?: Cache\n}\n\nlet _instance: LocalStorage<ConfSchema> | undefined\n\n/**\n * CLIKIT Store.\n *\n * @returns CLIKitStore.\n */\nfunction cliKitStore() {\n if (!_instance) {\n _instance = new LocalStorage<ConfSchema>({projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}`})\n }\n return _instance\n}\n\n/**\n * Get session.\n *\n * @returns Session.\n */\nexport function getSession(config: LocalStorage<ConfSchema> = cliKitStore()): string | undefined {\n outputDebug(outputContent`Getting session store...`)\n return config.get('sessionStore')\n}\n\n/**\n * Set session.\n *\n * @param session - Session.\n */\nexport function setSession(session: string, config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Setting session store...`)\n config.set('sessionStore', session)\n}\n\n/**\n * Remove session.\n */\nexport function removeSession(config: LocalStorage<ConfSchema> = cliKitStore()): void {\n outputDebug(outputContent`Removing session store...`)\n config.delete('sessionStore')\n}\n\ntype CacheValueForKey<TKey extends keyof Cache> = NonNullable<Cache[TKey]>['value']\n\n/**\n * Fetch from cache, or run the provided function to get the value, and cache it\n * before returning it.\n * @param key - The key to use for the cache.\n * @param fn - The function to run to get the value to cache, if a cache miss occurs.\n * @param timeout - The maximum valid age of a cached value, in milliseconds.\n * If the cached value is older than this, it will be refreshed.\n * @returns The value from the cache or the result of the function.\n */\nexport async function cacheRetrieveOrRepopulate(\n key: ExportedKey,\n fn: () => Promise<CacheValueForKey<typeof key>>,\n timeout?: number,\n config = cliKitStore(),\n): Promise<CacheValueForKey<typeof key>> {\n const cache: Cache = config.get('cache') || {}\n const cached = cache[key]\n\n if (cached?.value !== undefined && (timeout === undefined || Date.now() - cached.timestamp < timeout)) {\n return cached.value\n }\n\n const value = await fn()\n cache[key] = {value, timestamp: Date.now()}\n config.set('cache', cache)\n return value\n}\n\n/**\n * Fetch from cache if already populated, otherwise return undefined.\n * @param key - The key to use for the cache.\n * @returns The value from the cache or the result of the function.\n */\nexport function cacheRetrieve(key: ExportedKey, config = cliKitStore()): CacheValueForKey<typeof key> | undefined {\n const cache: Cache = config.get('cache') || {}\n const cached = cache[key]\n return cached?.value\n}\n\nexport function cacheClear(config = cliKitStore()): void {\n config.delete('cache')\n}\n\ninterface TimeInterval {\n days?: number\n hours?: number\n minutes?: number\n seconds?: number\n}\n\nfunction timeIntervalToMilliseconds({days = 0, hours = 0, minutes = 0, seconds = 0}: TimeInterval): number {\n return (days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds) * 1000\n}\n\n/**\n * Execute a task only if the most recent occurrence of the task is older than the specified timeout.\n * @param key - The key to use for the cache.\n * @param timeout - The maximum valid age of the most recent occurrence, expressed as an object with\n * days, hours, minutes, and seconds properties.\n * If the most recent occurrence is older than this, the task will be executed.\n * @param task - The task to run if the most recent occurrence is older than the timeout.\n * @returns The result of the task, or undefined if the task was not run.\n */\nexport async function runAtMinimumInterval(\n key: string,\n timeout: TimeInterval,\n task: () => Promise<void>,\n config = cliKitStore(),\n): Promise<boolean | undefined> {\n const cache: Cache = config.get('cache') || {}\n const cacheKey: MostRecentOccurrenceKey = `most-recent-occurrence-${key}`\n const cached = cache[cacheKey]\n\n if (cached?.value !== undefined && Date.now() - cached.timestamp < timeIntervalToMilliseconds(timeout)) {\n return undefined\n }\n\n await task()\n cache[cacheKey] = {value: true, timestamp: Date.now()}\n config.set('cache', cache)\n return true\n}\n"]}
@@ -44,7 +44,7 @@ function Item({ item, previousItem, isSelected, highlightedTerm, enableShortcuts
44
44
  React.createElement(Text, { bold: true }, title))) : null,
45
45
  React.createElement(Box, { key: index, marginLeft: hasAnyGroup ? 3 : 0 },
46
46
  React.createElement(Box, { marginRight: 2 }, isSelected ? React.createElement(Text, { color: "cyan" }, `>`) : React.createElement(Text, null, " ")),
47
- React.createElement(Text, { color: labelColor }, showKey ? `(${item.key}) ${label}` : label))));
47
+ React.createElement(Text, { wrap: "end", color: labelColor }, showKey ? `(${item.key}) ${label}` : label))));
48
48
  }
49
49
  const MAX_AVAILABLE_LINES = 25;
50
50
  // eslint-disable-next-line react/function-component-definition
@@ -1 +1 @@
1
- {"version":3,"file":"SelectInput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/SelectInput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Scrollbar} from './Scrollbar.js'\nimport {useSelectState} from '../hooks/use-select-state.js'\nimport useLayout from '../hooks/use-layout.js'\nimport {handleCtrlC} from '../../ui.js'\nimport React, {useCallback, forwardRef, useEffect} from 'react'\nimport {Box, Key, useInput, Text, DOMElement} from 'ink'\nimport chalk from 'chalk'\nimport figures from 'figures'\nimport sortBy from 'lodash/sortBy.js'\n\ndeclare module 'react' {\n function forwardRef<T, P>(\n render: (props: P, ref: React.Ref<T>) => JSX.Element | null,\n ): (props: P & React.RefAttributes<T>) => JSX.Element | null\n}\nexport interface SelectInputProps<T> {\n items: Item<T>[]\n initialItems?: Item<T>[]\n onChange?: (item: Item<T> | undefined) => void\n enableShortcuts?: boolean\n focus?: boolean\n emptyMessage?: string\n defaultValue?: T\n highlightedTerm?: string\n loading?: boolean\n errorMessage?: string\n hasMorePages?: boolean\n morePagesMessage?: string\n availableLines?: number\n onSubmit?: (item: Item<T>) => void\n inputFixedAreaRef?: React.RefObject<DOMElement>\n}\n\nexport interface Item<T> {\n label: string\n value: T\n key?: string\n group?: string\n helperText?: string\n disabled?: boolean\n}\n\nfunction highlightedLabel(label: string, term: string | undefined) {\n if (!term) {\n return label\n }\n\n const regex = new RegExp(term, 'i')\n return label.replace(regex, (match) => {\n return chalk.bold(match)\n })\n}\n\nfunction validateKeys(items: Item<unknown>[]) {\n if (items.some((item) => (item.key?.length ?? 0) > 1)) {\n throw new Error('SelectInput: Keys must be a single character')\n }\n\n if (!items.every((item) => typeof item.key !== 'undefined' && item.key.length > 0)) {\n throw new Error('SelectInput: All items must have keys if one does')\n }\n}\n\ninterface ItemProps<T> {\n item: Item<T>\n previousItem: Item<T> | undefined\n items: Item<T>[]\n isSelected: boolean\n highlightedTerm?: string\n enableShortcuts: boolean\n hasAnyGroup: boolean\n index: number\n}\n\n// eslint-disable-next-line react/function-component-definition\nfunction Item<T>({\n item,\n previousItem,\n isSelected,\n highlightedTerm,\n enableShortcuts,\n items,\n hasAnyGroup,\n index,\n}: ItemProps<T>): JSX.Element {\n const label = highlightedLabel(item.label, highlightedTerm)\n let title: string | undefined\n let labelColor\n\n if (isSelected) {\n labelColor = 'cyan'\n } else if (item.disabled) {\n labelColor = 'dim'\n }\n\n if (typeof previousItem === 'undefined' || item.group !== previousItem.group) {\n title = item.group ?? (hasAnyGroup ? 'Other' : undefined)\n }\n\n const showKey = enableShortcuts && item.key && item.key.length > 0\n\n return (\n <Box\n key={index}\n flexDirection=\"column\"\n marginTop={items.indexOf(item) !== 0 && title ? 1 : 0}\n minHeight={title ? 2 : 1}\n >\n {title ? (\n <Box marginLeft={3}>\n <Text bold>{title}</Text>\n </Box>\n ) : null}\n\n <Box key={index} marginLeft={hasAnyGroup ? 3 : 0}>\n <Box marginRight={2}>{isSelected ? <Text color=\"cyan\">{`>`}</Text> : <Text> </Text>}</Box>\n <Text color={labelColor}>{showKey ? `(${item.key}) ${label}` : label}</Text>\n </Box>\n </Box>\n )\n}\n\nconst MAX_AVAILABLE_LINES = 25\n\n// eslint-disable-next-line react/function-component-definition\nfunction SelectInputInner<T>(\n {\n items: rawItems,\n initialItems = rawItems,\n onChange,\n enableShortcuts = true,\n focus = true,\n emptyMessage = 'No items to select.',\n defaultValue,\n highlightedTerm,\n loading = false,\n errorMessage,\n hasMorePages = false,\n morePagesMessage,\n availableLines = MAX_AVAILABLE_LINES,\n onSubmit,\n inputFixedAreaRef,\n }: SelectInputProps<T>,\n ref: React.ForwardedRef<DOMElement>,\n): JSX.Element | null {\n let noItems = false\n\n if (rawItems.length === 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-param-reassign\n rawItems = [{label: emptyMessage, value: null as any, disabled: true}]\n noItems = true\n }\n\n const hasAnyGroup = rawItems.some((item) => typeof item.group !== 'undefined')\n const items = sortBy(rawItems, 'group')\n const itemsHaveKeys = items.some((item) => typeof item.key !== 'undefined' && item.key.length > 0)\n\n if (itemsHaveKeys) validateKeys(items)\n\n const availableLinesToUse = Math.min(availableLines, MAX_AVAILABLE_LINES)\n\n function maximumLinesLostToGroups(items: Item<T>[]): number {\n // Calculate a safe estimate of the limit needed based on the space available\n const numberOfGroups = new Set(items.map((item) => item.group).filter((group) => group)).size\n // Add 1 to numberOfGroups because we also have a default Other group\n const maxVisibleGroups = Math.ceil(Math.min((availableLinesToUse + 1) / 3, numberOfGroups + 1))\n // If we have x visible groups, we lose 1 line to the first group + 2 lines to the rest\n return numberOfGroups > 0 ? (maxVisibleGroups - 1) * 2 + 1 : 0\n }\n\n const maxLinesLostToGroups = maximumLinesLostToGroups(items)\n const limit = Math.max(2, availableLinesToUse - maxLinesLostToGroups)\n const hasLimit = items.length > limit\n\n const state = useSelectState({\n visibleOptionCount: limit,\n options: items,\n defaultValue,\n })\n\n useEffect(() => {\n if (typeof state.value !== 'undefined' && state.previousValue !== state.value) {\n onChange?.(items.find((item) => item.value === state.value))\n }\n }, [state.previousValue, state.value, items, onChange])\n\n const handleArrows = (key: Key) => {\n if (key.upArrow) {\n state.selectPreviousOption()\n } else if (key.downArrow) {\n state.selectNextOption()\n }\n }\n\n const handleShortcuts = useCallback(\n (input: string) => {\n if (state.visibleOptions.map((item: Item<T>) => item.key).includes(input)) {\n const itemWithKey = state.visibleOptions.find((item: Item<T>) => item.key === input)\n const item = items.find((item) => item.value === itemWithKey?.value)\n\n if (itemWithKey && !itemWithKey.disabled) {\n // keep this order of operations so that there is no flickering\n if (onSubmit && item) {\n onSubmit(item)\n }\n\n state.selectOption({option: itemWithKey})\n }\n }\n },\n [items, onSubmit, state],\n )\n\n useInput(\n (input, key) => {\n handleCtrlC(input, key)\n\n if (typeof state.value !== 'undefined' && key.return) {\n const item = items.find((item) => item.value === state.value)\n\n if (item && onSubmit) {\n onSubmit(item)\n }\n }\n\n // check that no special modifier (shift, control, etc.) is being pressed\n if (enableShortcuts && input.length > 0 && Object.values(key).every((value) => value === false)) {\n handleShortcuts(input)\n } else {\n handleArrows(key)\n }\n },\n {isActive: focus},\n )\n const {twoThirds} = useLayout()\n\n if (loading) {\n return (\n <Box marginLeft={3}>\n <Text dimColor>Loading...</Text>\n </Box>\n )\n } else if (errorMessage && errorMessage.length > 0) {\n return (\n <Box marginLeft={3}>\n <Text color=\"red\">{errorMessage}</Text>\n </Box>\n )\n } else {\n const optionsHeight = initialItems.length + maximumLinesLostToGroups(initialItems)\n const minHeight = hasAnyGroup ? 5 : 2\n const sectionHeight = Math.max(minHeight, Math.min(availableLinesToUse, optionsHeight))\n\n return (\n <Box flexDirection=\"column\" ref={ref} gap={1} width={twoThirds}>\n <Box flexDirection=\"row\" height={sectionHeight} width=\"100%\">\n <Box flexDirection=\"column\" overflowY=\"hidden\" flexGrow={1}>\n {state.visibleOptions.map((item: Item<T>, index: number) => (\n <Item\n key={index}\n item={item}\n previousItem={state.visibleOptions[index - 1]}\n highlightedTerm={highlightedTerm}\n isSelected={item.value === state.value}\n items={state.visibleOptions}\n enableShortcuts={enableShortcuts}\n hasAnyGroup={hasAnyGroup}\n index={index}\n />\n ))}\n </Box>\n\n {hasLimit ? (\n <Scrollbar\n containerHeight={sectionHeight}\n visibleListSectionLength={limit}\n fullListLength={items.length}\n visibleFromIndex={state.visibleFromIndex}\n />\n ) : null}\n </Box>\n\n <Box ref={inputFixedAreaRef}>\n {noItems ? (\n <Box marginLeft={3}>\n <Text dimColor>Try again with a different keyword.</Text>\n </Box>\n ) : (\n <Box marginLeft={3} flexDirection=\"column\">\n <Text dimColor>\n {`Press ${figures.arrowUp}${figures.arrowDown} arrows to select, enter ${\n itemsHaveKeys ? 'or a shortcut ' : ''\n }to confirm.`}\n </Text>\n {hasMorePages ? (\n <Text>\n <Text bold>1-{items.length} of many</Text>\n {morePagesMessage ? ` ${morePagesMessage}` : null}\n </Text>\n ) : null}\n </Box>\n )}\n </Box>\n </Box>\n )\n }\n}\n\nexport const SelectInput = forwardRef(SelectInputInner)\n"]}
1
+ {"version":3,"file":"SelectInput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/SelectInput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Scrollbar} from './Scrollbar.js'\nimport {useSelectState} from '../hooks/use-select-state.js'\nimport useLayout from '../hooks/use-layout.js'\nimport {handleCtrlC} from '../../ui.js'\nimport React, {useCallback, forwardRef, useEffect} from 'react'\nimport {Box, Key, useInput, Text, DOMElement} from 'ink'\nimport chalk from 'chalk'\nimport figures from 'figures'\nimport sortBy from 'lodash/sortBy.js'\n\ndeclare module 'react' {\n function forwardRef<T, P>(\n render: (props: P, ref: React.Ref<T>) => JSX.Element | null,\n ): (props: P & React.RefAttributes<T>) => JSX.Element | null\n}\nexport interface SelectInputProps<T> {\n items: Item<T>[]\n initialItems?: Item<T>[]\n onChange?: (item: Item<T> | undefined) => void\n enableShortcuts?: boolean\n focus?: boolean\n emptyMessage?: string\n defaultValue?: T\n highlightedTerm?: string\n loading?: boolean\n errorMessage?: string\n hasMorePages?: boolean\n morePagesMessage?: string\n availableLines?: number\n onSubmit?: (item: Item<T>) => void\n inputFixedAreaRef?: React.RefObject<DOMElement>\n}\n\nexport interface Item<T> {\n label: string\n value: T\n key?: string\n group?: string\n helperText?: string\n disabled?: boolean\n}\n\nfunction highlightedLabel(label: string, term: string | undefined) {\n if (!term) {\n return label\n }\n\n const regex = new RegExp(term, 'i')\n return label.replace(regex, (match) => {\n return chalk.bold(match)\n })\n}\n\nfunction validateKeys(items: Item<unknown>[]) {\n if (items.some((item) => (item.key?.length ?? 0) > 1)) {\n throw new Error('SelectInput: Keys must be a single character')\n }\n\n if (!items.every((item) => typeof item.key !== 'undefined' && item.key.length > 0)) {\n throw new Error('SelectInput: All items must have keys if one does')\n }\n}\n\ninterface ItemProps<T> {\n item: Item<T>\n previousItem: Item<T> | undefined\n items: Item<T>[]\n isSelected: boolean\n highlightedTerm?: string\n enableShortcuts: boolean\n hasAnyGroup: boolean\n index: number\n}\n\n// eslint-disable-next-line react/function-component-definition\nfunction Item<T>({\n item,\n previousItem,\n isSelected,\n highlightedTerm,\n enableShortcuts,\n items,\n hasAnyGroup,\n index,\n}: ItemProps<T>): JSX.Element {\n const label = highlightedLabel(item.label, highlightedTerm)\n let title: string | undefined\n let labelColor\n\n if (isSelected) {\n labelColor = 'cyan'\n } else if (item.disabled) {\n labelColor = 'dim'\n }\n\n if (typeof previousItem === 'undefined' || item.group !== previousItem.group) {\n title = item.group ?? (hasAnyGroup ? 'Other' : undefined)\n }\n\n const showKey = enableShortcuts && item.key && item.key.length > 0\n\n return (\n <Box\n key={index}\n flexDirection=\"column\"\n marginTop={items.indexOf(item) !== 0 && title ? 1 : 0}\n minHeight={title ? 2 : 1}\n >\n {title ? (\n <Box marginLeft={3}>\n <Text bold>{title}</Text>\n </Box>\n ) : null}\n\n <Box key={index} marginLeft={hasAnyGroup ? 3 : 0}>\n <Box marginRight={2}>{isSelected ? <Text color=\"cyan\">{`>`}</Text> : <Text> </Text>}</Box>\n <Text wrap=\"end\" color={labelColor}>\n {showKey ? `(${item.key}) ${label}` : label}\n </Text>\n </Box>\n </Box>\n )\n}\n\nconst MAX_AVAILABLE_LINES = 25\n\n// eslint-disable-next-line react/function-component-definition\nfunction SelectInputInner<T>(\n {\n items: rawItems,\n initialItems = rawItems,\n onChange,\n enableShortcuts = true,\n focus = true,\n emptyMessage = 'No items to select.',\n defaultValue,\n highlightedTerm,\n loading = false,\n errorMessage,\n hasMorePages = false,\n morePagesMessage,\n availableLines = MAX_AVAILABLE_LINES,\n onSubmit,\n inputFixedAreaRef,\n }: SelectInputProps<T>,\n ref: React.ForwardedRef<DOMElement>,\n): JSX.Element | null {\n let noItems = false\n\n if (rawItems.length === 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-param-reassign\n rawItems = [{label: emptyMessage, value: null as any, disabled: true}]\n noItems = true\n }\n\n const hasAnyGroup = rawItems.some((item) => typeof item.group !== 'undefined')\n const items = sortBy(rawItems, 'group')\n const itemsHaveKeys = items.some((item) => typeof item.key !== 'undefined' && item.key.length > 0)\n\n if (itemsHaveKeys) validateKeys(items)\n\n const availableLinesToUse = Math.min(availableLines, MAX_AVAILABLE_LINES)\n\n function maximumLinesLostToGroups(items: Item<T>[]): number {\n // Calculate a safe estimate of the limit needed based on the space available\n const numberOfGroups = new Set(items.map((item) => item.group).filter((group) => group)).size\n // Add 1 to numberOfGroups because we also have a default Other group\n const maxVisibleGroups = Math.ceil(Math.min((availableLinesToUse + 1) / 3, numberOfGroups + 1))\n // If we have x visible groups, we lose 1 line to the first group + 2 lines to the rest\n return numberOfGroups > 0 ? (maxVisibleGroups - 1) * 2 + 1 : 0\n }\n\n const maxLinesLostToGroups = maximumLinesLostToGroups(items)\n const limit = Math.max(2, availableLinesToUse - maxLinesLostToGroups)\n const hasLimit = items.length > limit\n\n const state = useSelectState({\n visibleOptionCount: limit,\n options: items,\n defaultValue,\n })\n\n useEffect(() => {\n if (typeof state.value !== 'undefined' && state.previousValue !== state.value) {\n onChange?.(items.find((item) => item.value === state.value))\n }\n }, [state.previousValue, state.value, items, onChange])\n\n const handleArrows = (key: Key) => {\n if (key.upArrow) {\n state.selectPreviousOption()\n } else if (key.downArrow) {\n state.selectNextOption()\n }\n }\n\n const handleShortcuts = useCallback(\n (input: string) => {\n if (state.visibleOptions.map((item: Item<T>) => item.key).includes(input)) {\n const itemWithKey = state.visibleOptions.find((item: Item<T>) => item.key === input)\n const item = items.find((item) => item.value === itemWithKey?.value)\n\n if (itemWithKey && !itemWithKey.disabled) {\n // keep this order of operations so that there is no flickering\n if (onSubmit && item) {\n onSubmit(item)\n }\n\n state.selectOption({option: itemWithKey})\n }\n }\n },\n [items, onSubmit, state],\n )\n\n useInput(\n (input, key) => {\n handleCtrlC(input, key)\n\n if (typeof state.value !== 'undefined' && key.return) {\n const item = items.find((item) => item.value === state.value)\n\n if (item && onSubmit) {\n onSubmit(item)\n }\n }\n\n // check that no special modifier (shift, control, etc.) is being pressed\n if (enableShortcuts && input.length > 0 && Object.values(key).every((value) => value === false)) {\n handleShortcuts(input)\n } else {\n handleArrows(key)\n }\n },\n {isActive: focus},\n )\n const {twoThirds} = useLayout()\n\n if (loading) {\n return (\n <Box marginLeft={3}>\n <Text dimColor>Loading...</Text>\n </Box>\n )\n } else if (errorMessage && errorMessage.length > 0) {\n return (\n <Box marginLeft={3}>\n <Text color=\"red\">{errorMessage}</Text>\n </Box>\n )\n } else {\n const optionsHeight = initialItems.length + maximumLinesLostToGroups(initialItems)\n const minHeight = hasAnyGroup ? 5 : 2\n const sectionHeight = Math.max(minHeight, Math.min(availableLinesToUse, optionsHeight))\n\n return (\n <Box flexDirection=\"column\" ref={ref} gap={1} width={twoThirds}>\n <Box flexDirection=\"row\" height={sectionHeight} width=\"100%\">\n <Box flexDirection=\"column\" overflowY=\"hidden\" flexGrow={1}>\n {state.visibleOptions.map((item: Item<T>, index: number) => (\n <Item\n key={index}\n item={item}\n previousItem={state.visibleOptions[index - 1]}\n highlightedTerm={highlightedTerm}\n isSelected={item.value === state.value}\n items={state.visibleOptions}\n enableShortcuts={enableShortcuts}\n hasAnyGroup={hasAnyGroup}\n index={index}\n />\n ))}\n </Box>\n\n {hasLimit ? (\n <Scrollbar\n containerHeight={sectionHeight}\n visibleListSectionLength={limit}\n fullListLength={items.length}\n visibleFromIndex={state.visibleFromIndex}\n />\n ) : null}\n </Box>\n\n <Box ref={inputFixedAreaRef}>\n {noItems ? (\n <Box marginLeft={3}>\n <Text dimColor>Try again with a different keyword.</Text>\n </Box>\n ) : (\n <Box marginLeft={3} flexDirection=\"column\">\n <Text dimColor>\n {`Press ${figures.arrowUp}${figures.arrowDown} arrows to select, enter ${\n itemsHaveKeys ? 'or a shortcut ' : ''\n }to confirm.`}\n </Text>\n {hasMorePages ? (\n <Text>\n <Text bold>1-{items.length} of many</Text>\n {morePagesMessage ? ` ${morePagesMessage}` : null}\n </Text>\n ) : null}\n </Box>\n )}\n </Box>\n </Box>\n )\n }\n}\n\nexport const SelectInput = forwardRef(SelectInputInner)\n"]}
@@ -88,6 +88,13 @@ export declare function constantize(input: string): string;
88
88
  * @returns The transformed string.
89
89
  */
90
90
  export declare function formatDate(date: Date): string;
91
+ /**
92
+ * Given a date in UTC ISO String format, return a formatted string in local time like "2021-01-01 12:00:00".
93
+ *
94
+ * @param dateString - UTC ISO Date String.
95
+ * @returns The transformed string in local system time.
96
+ */
97
+ export declare function formatLocalDate(dateString: string): string;
91
98
  /**
92
99
  * Given a list of items, it returns a string with the items joined by commas and the last item joined by "and".
93
100
  * All items are wrapped in double quotes.
@@ -314,6 +314,17 @@ export function formatDate(date) {
314
314
  const timeString = components[1]?.split('.')[0] ?? date.toTimeString();
315
315
  return `${dateString} ${timeString}`;
316
316
  }
317
+ /**
318
+ * Given a date in UTC ISO String format, return a formatted string in local time like "2021-01-01 12:00:00".
319
+ *
320
+ * @param dateString - UTC ISO Date String.
321
+ * @returns The transformed string in local system time.
322
+ */
323
+ export function formatLocalDate(dateString) {
324
+ const dateObj = new Date(dateString);
325
+ const localDate = new Date(Date.UTC(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate(), dateObj.getHours(), dateObj.getMinutes(), dateObj.getSeconds()));
326
+ return formatDate(localDate);
327
+ }
317
328
  /**
318
329
  * Given a list of items, it returns a string with the items joined by commas and the last item joined by "and".
319
330
  * All items are wrapped in double quotes.
@@ -1 +1 @@
1
- {"version":3,"file":"string.js","sourceRoot":"","sources":["../../../src/public/common/string.ts"],"names":[],"mappings":"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","sourcesContent":["import {takeRandomFromArray} from './array.js'\nimport {unstyled} from '../../public/node/output.js'\nimport {Token, TokenItem} from '../../private/node/ui/components/TokenizedText.js'\nimport {camelCase, constantCase, paramCase, snakeCase, pascalCase} from 'change-case'\n\nconst SAFE_RANDOM_BUSINESS_ADJECTIVES = [\n 'commercial',\n 'profitable',\n 'amortizable',\n 'branded',\n 'integrated',\n 'synergistic',\n 'consolidated',\n 'diversified',\n 'lean',\n 'niche',\n 'premium',\n 'luxury',\n 'scalable',\n 'optimized',\n 'empowered',\n 'international',\n 'beneficial',\n 'fruitful',\n 'extensive',\n 'lucrative',\n 'modern',\n 'stable',\n 'strategic',\n 'adaptive',\n 'efficient',\n 'growing',\n 'sustainable',\n 'innovative',\n 'regional',\n 'specialized',\n 'focused',\n 'pragmatic',\n 'ethical',\n 'flexible',\n 'competitive',\n]\n\nconst SAFE_RANDOM_CREATIVE_ADJECTIVES = [\n 'bright',\n 'impactful',\n 'stylish',\n 'colorful',\n 'modern',\n 'minimal',\n 'trendy',\n 'creative',\n 'artistic',\n 'spectacular',\n 'glamorous',\n 'luxury',\n 'retro',\n 'nostalgic',\n 'comfy',\n 'polished',\n 'fabulous',\n 'balanced',\n 'monochrome',\n 'glitched',\n 'contrasted',\n 'elegant',\n 'textured',\n 'vibrant',\n 'harmonious',\n 'versatile',\n 'eclectic',\n 'futuristic',\n 'idealistic',\n 'intricate',\n 'bohemian',\n 'abstract',\n 'meticulous',\n 'refined',\n 'flamboyant',\n]\n\nconst SAFE_RANDOM_BUSINESS_NOUNS = [\n 'account',\n 'consumer',\n 'customer',\n 'enterprise',\n 'business',\n 'venture',\n 'marketplace',\n 'revenue',\n 'vertical',\n 'portfolio',\n 'negotiation',\n 'shipping',\n 'demand',\n 'supply',\n 'growth',\n 'merchant',\n 'investment',\n 'shareholder',\n 'conversion',\n 'capital',\n 'projection',\n 'upside',\n 'trade',\n 'deal',\n 'merchandise',\n 'transaction',\n 'sale',\n 'franchise',\n 'subsidiary',\n 'logistics',\n 'infrastructure',\n 'sponsorship',\n 'partnership',\n 'tax',\n 'policy',\n 'outsource',\n 'equity',\n 'strategy',\n 'valuation',\n 'benchmark',\n 'metrics',\n 'duplication',\n]\n\nconst SAFE_RANDOM_CREATIVE_NOUNS = [\n 'vibe',\n 'style',\n 'moment',\n 'mood',\n 'flavor',\n 'look',\n 'appearance',\n 'perspective',\n 'aspect',\n 'ambience',\n 'quality',\n 'backdrop',\n 'focus',\n 'tone',\n 'inspiration',\n 'imagery',\n 'aesthetics',\n 'palette',\n 'ornamentation',\n 'contrast',\n 'colorway',\n 'visuals',\n 'typography',\n 'composition',\n 'scale',\n 'symmetry',\n 'gradients',\n 'proportions',\n 'textures',\n 'harmony',\n 'shapes',\n 'patterns',\n]\n\nexport type RandomNameFamily = 'business' | 'creative'\n\n/**\n * Generates a random name by combining an adjective and noun.\n *\n * @param family - Theme to use for the random name (business or creative).\n * @returns A random name generated by combining an adjective and noun.\n */\nexport function getRandomName(family: RandomNameFamily = 'business'): string {\n const mapping = {\n business: {\n adjectives: SAFE_RANDOM_BUSINESS_ADJECTIVES,\n nouns: SAFE_RANDOM_BUSINESS_NOUNS,\n },\n creative: {\n adjectives: SAFE_RANDOM_CREATIVE_ADJECTIVES,\n nouns: SAFE_RANDOM_CREATIVE_NOUNS,\n },\n }\n return `${takeRandomFromArray(mapping[family].adjectives)}-${takeRandomFromArray(mapping[family].nouns)}`\n}\n\n/**\n * Given a string, it returns it with the first letter capitalized.\n *\n * @param str - String to capitalize.\n * @returns String with the first letter capitalized.\n */\nexport function capitalize(str: string): string {\n return str.substring(0, 1).toUpperCase() + str.substring(1)\n}\n\n/**\n * Given a list of items, it returns a pluralized string based on the amount of items.\n *\n * @param items - List of items.\n * @param plural - Supplier used when the list of items has more than one item.\n * @param singular - Supplier used when the list of items has a single item.\n * @param none - Supplier used when the list has no items.\n * @returns The {@link TokenItem} supplied by the {@link plural}, {@link singular}, or {@link none} functions.\n */\nexport function pluralize<\n T,\n TToken extends Token = Token,\n TPluralToken extends TToken = TToken,\n TSingularToken extends TToken = TToken,\n TNoneToken extends TToken = TToken,\n>(\n items: T[],\n plural: (items: T[]) => TokenItem<TPluralToken>,\n singular: (item: T) => TokenItem<TSingularToken>,\n none?: () => TokenItem<TNoneToken>,\n): TokenItem<TPluralToken | TSingularToken | TNoneToken> | string {\n if (items.length === 1) {\n return singular(items[0]!)\n }\n\n if (items.length > 1) {\n return plural(items)\n }\n\n if (none) {\n return none()\n }\n\n return ''\n}\n\n/**\n * Try to convert a string to an int, falling back to undefined if unable to.\n *\n * @param maybeInt - String to convert to an int.\n * @returns The int if it was able to convert, otherwise undefined.\n */\nexport function tryParseInt(maybeInt: string | undefined): number | undefined {\n let asInt: number | undefined\n if (maybeInt !== undefined) {\n asInt = parseInt(maybeInt, 10)\n if (isNaN(asInt)) {\n asInt = undefined\n }\n }\n return asInt\n}\n\n/**\n * Transforms a matrix of strings into a single string with the columns aligned.\n *\n * @param lines - Array of rows, where each row is an array of strings (representing columns).\n * @returns A string with the columns aligned.\n */\nexport function linesToColumns(lines: string[][]): string {\n const widths: number[] = []\n for (let i = 0; lines[0] && i < lines[0].length; i++) {\n const columnRows = lines.map((line) => line[i]!)\n widths.push(Math.max(...columnRows.map((row) => unstyled(row).length)))\n }\n const paddedLines = lines\n .map((line) => {\n return line\n .map((col, index) => {\n return `${col}${' '.repeat(widths[index]! - unstyled(col).length)}`\n })\n .join(' ')\n .trimEnd()\n })\n .join('\\n')\n return paddedLines\n}\n\n/**\n * Given a string, it transforms it to a slug (lowercase, hyphenated, no special chars, trimmed...).\n *\n * @param str - String to slugify.\n * @returns The slugified string.\n */\nexport function slugify(str: string): string {\n return str\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Given a string, it returns it with the special regex characters escaped.\n * More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping.\n *\n * @param str - String to escape.\n * @returns The escaped string.\n */\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Transform a string to camelCase.\n *\n * @param input - String to escape.\n * @returns The escaped string.\n */\nexport function camelize(input: string): string {\n return camelCase(input)\n}\n\n/**\n * Transform a string to param-case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function hyphenate(input: string): string {\n return paramCase(input)\n}\n\n/**\n * Transform a string to snake_case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function underscore(input: string): string {\n return snakeCase(input)\n}\n\n/**\n * Transform a string to CONSTANT_CASE.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function constantize(input: string): string {\n return constantCase(input)\n}\n\n/**\n * Given a date, return a formatted string like \"2021-01-01 12:00:00\".\n *\n * @param date - Date to format.\n * @returns The transformed string.\n */\nexport function formatDate(date: Date): string {\n const components = date.toISOString().split('T')\n const dateString = components[0] ?? date.toDateString()\n const timeString = components[1]?.split('.')[0] ?? date.toTimeString()\n return `${dateString} ${timeString}`\n}\n\n/**\n * Given a list of items, it returns a string with the items joined by commas and the last item joined by \"and\".\n * All items are wrapped in double quotes.\n * For example: [\"a\", \"b\", \"c\"] returns \"a\", \"b\" and \"c\".\n *\n * @param items - List of items.\n * @returns The joined string.\n */\nexport function joinWithAnd(items: string[]): string {\n if (items.length === 0) return ''\n if (items.length === 1) return `\"${items[0]}\"`\n\n return `${items\n .slice(0, -1)\n .map((item) => `\"${item}\"`)\n .join(', ')} and \"${items[items.length - 1]}\"`\n}\n\n/**\n * Given a string, it returns the PascalCase form of it.\n * Eg: \"pascal_case\" returns \"PascalCase\".\n *\n * @param str - String to PascalCase.\n * @returns String with all the first letter capitalized with no spaces.\n */\nexport function pascalize(str: string): string {\n return pascalCase(str)\n}\n\n/**\n * Given a string that represents a list of delimited tokens, it returns the normalized string representing the same\n * list, without empty elements, sorted, and with no duplicates.\n *\n * @param delimitedString - String to normalize.\n * @param delimiter - Delimiter used to split the string into tokens.\n * @returns String with the normalized list of tokens.\n */\nexport function normalizeDelimitedString(delimitedString?: string, delimiter = ','): string | undefined {\n if (!delimitedString) return\n\n const items = delimitedString.split(delimiter).map((value) => value.trim())\n const nonEmptyItems = items.filter((value) => value !== '')\n const sortedItems = nonEmptyItems.sort()\n const uniqueSortedItems = [...new Set(sortedItems)]\n\n return uniqueSortedItems.join(delimiter)\n}\n"]}
1
+ {"version":3,"file":"string.js","sourceRoot":"","sources":["../../../src/public/common/string.ts"],"names":[],"mappings":"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","sourcesContent":["import {takeRandomFromArray} from './array.js'\nimport {unstyled} from '../../public/node/output.js'\nimport {Token, TokenItem} from '../../private/node/ui/components/TokenizedText.js'\nimport {camelCase, constantCase, paramCase, snakeCase, pascalCase} from 'change-case'\n\nconst SAFE_RANDOM_BUSINESS_ADJECTIVES = [\n 'commercial',\n 'profitable',\n 'amortizable',\n 'branded',\n 'integrated',\n 'synergistic',\n 'consolidated',\n 'diversified',\n 'lean',\n 'niche',\n 'premium',\n 'luxury',\n 'scalable',\n 'optimized',\n 'empowered',\n 'international',\n 'beneficial',\n 'fruitful',\n 'extensive',\n 'lucrative',\n 'modern',\n 'stable',\n 'strategic',\n 'adaptive',\n 'efficient',\n 'growing',\n 'sustainable',\n 'innovative',\n 'regional',\n 'specialized',\n 'focused',\n 'pragmatic',\n 'ethical',\n 'flexible',\n 'competitive',\n]\n\nconst SAFE_RANDOM_CREATIVE_ADJECTIVES = [\n 'bright',\n 'impactful',\n 'stylish',\n 'colorful',\n 'modern',\n 'minimal',\n 'trendy',\n 'creative',\n 'artistic',\n 'spectacular',\n 'glamorous',\n 'luxury',\n 'retro',\n 'nostalgic',\n 'comfy',\n 'polished',\n 'fabulous',\n 'balanced',\n 'monochrome',\n 'glitched',\n 'contrasted',\n 'elegant',\n 'textured',\n 'vibrant',\n 'harmonious',\n 'versatile',\n 'eclectic',\n 'futuristic',\n 'idealistic',\n 'intricate',\n 'bohemian',\n 'abstract',\n 'meticulous',\n 'refined',\n 'flamboyant',\n]\n\nconst SAFE_RANDOM_BUSINESS_NOUNS = [\n 'account',\n 'consumer',\n 'customer',\n 'enterprise',\n 'business',\n 'venture',\n 'marketplace',\n 'revenue',\n 'vertical',\n 'portfolio',\n 'negotiation',\n 'shipping',\n 'demand',\n 'supply',\n 'growth',\n 'merchant',\n 'investment',\n 'shareholder',\n 'conversion',\n 'capital',\n 'projection',\n 'upside',\n 'trade',\n 'deal',\n 'merchandise',\n 'transaction',\n 'sale',\n 'franchise',\n 'subsidiary',\n 'logistics',\n 'infrastructure',\n 'sponsorship',\n 'partnership',\n 'tax',\n 'policy',\n 'outsource',\n 'equity',\n 'strategy',\n 'valuation',\n 'benchmark',\n 'metrics',\n 'duplication',\n]\n\nconst SAFE_RANDOM_CREATIVE_NOUNS = [\n 'vibe',\n 'style',\n 'moment',\n 'mood',\n 'flavor',\n 'look',\n 'appearance',\n 'perspective',\n 'aspect',\n 'ambience',\n 'quality',\n 'backdrop',\n 'focus',\n 'tone',\n 'inspiration',\n 'imagery',\n 'aesthetics',\n 'palette',\n 'ornamentation',\n 'contrast',\n 'colorway',\n 'visuals',\n 'typography',\n 'composition',\n 'scale',\n 'symmetry',\n 'gradients',\n 'proportions',\n 'textures',\n 'harmony',\n 'shapes',\n 'patterns',\n]\n\nexport type RandomNameFamily = 'business' | 'creative'\n\n/**\n * Generates a random name by combining an adjective and noun.\n *\n * @param family - Theme to use for the random name (business or creative).\n * @returns A random name generated by combining an adjective and noun.\n */\nexport function getRandomName(family: RandomNameFamily = 'business'): string {\n const mapping = {\n business: {\n adjectives: SAFE_RANDOM_BUSINESS_ADJECTIVES,\n nouns: SAFE_RANDOM_BUSINESS_NOUNS,\n },\n creative: {\n adjectives: SAFE_RANDOM_CREATIVE_ADJECTIVES,\n nouns: SAFE_RANDOM_CREATIVE_NOUNS,\n },\n }\n return `${takeRandomFromArray(mapping[family].adjectives)}-${takeRandomFromArray(mapping[family].nouns)}`\n}\n\n/**\n * Given a string, it returns it with the first letter capitalized.\n *\n * @param str - String to capitalize.\n * @returns String with the first letter capitalized.\n */\nexport function capitalize(str: string): string {\n return str.substring(0, 1).toUpperCase() + str.substring(1)\n}\n\n/**\n * Given a list of items, it returns a pluralized string based on the amount of items.\n *\n * @param items - List of items.\n * @param plural - Supplier used when the list of items has more than one item.\n * @param singular - Supplier used when the list of items has a single item.\n * @param none - Supplier used when the list has no items.\n * @returns The {@link TokenItem} supplied by the {@link plural}, {@link singular}, or {@link none} functions.\n */\nexport function pluralize<\n T,\n TToken extends Token = Token,\n TPluralToken extends TToken = TToken,\n TSingularToken extends TToken = TToken,\n TNoneToken extends TToken = TToken,\n>(\n items: T[],\n plural: (items: T[]) => TokenItem<TPluralToken>,\n singular: (item: T) => TokenItem<TSingularToken>,\n none?: () => TokenItem<TNoneToken>,\n): TokenItem<TPluralToken | TSingularToken | TNoneToken> | string {\n if (items.length === 1) {\n return singular(items[0]!)\n }\n\n if (items.length > 1) {\n return plural(items)\n }\n\n if (none) {\n return none()\n }\n\n return ''\n}\n\n/**\n * Try to convert a string to an int, falling back to undefined if unable to.\n *\n * @param maybeInt - String to convert to an int.\n * @returns The int if it was able to convert, otherwise undefined.\n */\nexport function tryParseInt(maybeInt: string | undefined): number | undefined {\n let asInt: number | undefined\n if (maybeInt !== undefined) {\n asInt = parseInt(maybeInt, 10)\n if (isNaN(asInt)) {\n asInt = undefined\n }\n }\n return asInt\n}\n\n/**\n * Transforms a matrix of strings into a single string with the columns aligned.\n *\n * @param lines - Array of rows, where each row is an array of strings (representing columns).\n * @returns A string with the columns aligned.\n */\nexport function linesToColumns(lines: string[][]): string {\n const widths: number[] = []\n for (let i = 0; lines[0] && i < lines[0].length; i++) {\n const columnRows = lines.map((line) => line[i]!)\n widths.push(Math.max(...columnRows.map((row) => unstyled(row).length)))\n }\n const paddedLines = lines\n .map((line) => {\n return line\n .map((col, index) => {\n return `${col}${' '.repeat(widths[index]! - unstyled(col).length)}`\n })\n .join(' ')\n .trimEnd()\n })\n .join('\\n')\n return paddedLines\n}\n\n/**\n * Given a string, it transforms it to a slug (lowercase, hyphenated, no special chars, trimmed...).\n *\n * @param str - String to slugify.\n * @returns The slugified string.\n */\nexport function slugify(str: string): string {\n return str\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Given a string, it returns it with the special regex characters escaped.\n * More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping.\n *\n * @param str - String to escape.\n * @returns The escaped string.\n */\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Transform a string to camelCase.\n *\n * @param input - String to escape.\n * @returns The escaped string.\n */\nexport function camelize(input: string): string {\n return camelCase(input)\n}\n\n/**\n * Transform a string to param-case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function hyphenate(input: string): string {\n return paramCase(input)\n}\n\n/**\n * Transform a string to snake_case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function underscore(input: string): string {\n return snakeCase(input)\n}\n\n/**\n * Transform a string to CONSTANT_CASE.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function constantize(input: string): string {\n return constantCase(input)\n}\n\n/**\n * Given a date, return a formatted string like \"2021-01-01 12:00:00\".\n *\n * @param date - Date to format.\n * @returns The transformed string.\n */\nexport function formatDate(date: Date): string {\n const components = date.toISOString().split('T')\n const dateString = components[0] ?? date.toDateString()\n const timeString = components[1]?.split('.')[0] ?? date.toTimeString()\n return `${dateString} ${timeString}`\n}\n\n/**\n * Given a date in UTC ISO String format, return a formatted string in local time like \"2021-01-01 12:00:00\".\n *\n * @param dateString - UTC ISO Date String.\n * @returns The transformed string in local system time.\n */\nexport function formatLocalDate(dateString: string): string {\n const dateObj = new Date(dateString)\n const localDate = new Date(\n Date.UTC(\n dateObj.getFullYear(),\n dateObj.getMonth(),\n dateObj.getDate(),\n dateObj.getHours(),\n dateObj.getMinutes(),\n dateObj.getSeconds(),\n ),\n )\n return formatDate(localDate)\n}\n\n/**\n * Given a list of items, it returns a string with the items joined by commas and the last item joined by \"and\".\n * All items are wrapped in double quotes.\n * For example: [\"a\", \"b\", \"c\"] returns \"a\", \"b\" and \"c\".\n *\n * @param items - List of items.\n * @returns The joined string.\n */\nexport function joinWithAnd(items: string[]): string {\n if (items.length === 0) return ''\n if (items.length === 1) return `\"${items[0]}\"`\n\n return `${items\n .slice(0, -1)\n .map((item) => `\"${item}\"`)\n .join(', ')} and \"${items[items.length - 1]}\"`\n}\n\n/**\n * Given a string, it returns the PascalCase form of it.\n * Eg: \"pascal_case\" returns \"PascalCase\".\n *\n * @param str - String to PascalCase.\n * @returns String with all the first letter capitalized with no spaces.\n */\nexport function pascalize(str: string): string {\n return pascalCase(str)\n}\n\n/**\n * Given a string that represents a list of delimited tokens, it returns the normalized string representing the same\n * list, without empty elements, sorted, and with no duplicates.\n *\n * @param delimitedString - String to normalize.\n * @param delimiter - Delimiter used to split the string into tokens.\n * @returns String with the normalized list of tokens.\n */\nexport function normalizeDelimitedString(delimitedString?: string, delimiter = ','): string | undefined {\n if (!delimitedString) return\n\n const items = delimitedString.split(delimiter).map((value) => value.trim())\n const nonEmptyItems = items.filter((value) => value !== '')\n const sortedItems = nonEmptyItems.sort()\n const uniqueSortedItems = [...new Set(sortedItems)]\n\n return uniqueSortedItems.join(delimiter)\n}\n"]}
@@ -1 +1 @@
1
- export declare const CLI_KIT_VERSION = "3.65.2";
1
+ export declare const CLI_KIT_VERSION = "3.66.0";
@@ -1,2 +1,2 @@
1
- export const CLI_KIT_VERSION = '3.65.2';
1
+ export const CLI_KIT_VERSION = '3.66.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.65.2'\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.66.0'\n"]}