@shopify/cli-kit 0.0.0-nightly-20260727071221 → 0.0.0-nightly-20260729065745

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- export declare const CLI_KIT_VERSION = "0.0.0-nightly-20260727071221";
1
+ export declare const CLI_KIT_VERSION = "0.0.0-nightly-20260729065745";
@@ -1,2 +1,2 @@
1
- export const CLI_KIT_VERSION = '0.0.0-nightly-20260727071221';
1
+ export const CLI_KIT_VERSION = '0.0.0-nightly-20260729065745';
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,8BAA8B,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '0.0.0-nightly-20260727071221'\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,8BAA8B,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '0.0.0-nightly-20260729065745'\n"]}
@@ -1,7 +1,5 @@
1
1
  import { GraphQLVariables, GraphQLResponse, CacheOptions, UnauthorizedHandler } from './graphql.js';
2
2
  import { RequestModeInput } from '../http.js';
3
- import { Variables } from 'graphql-request';
4
- import { TypedDocumentNode } from '@graphql-typed-document-node/core';
5
3
  /**
6
4
  * Executes a GraphQL query against the Partners API.
7
5
  *
@@ -14,21 +12,6 @@ import { TypedDocumentNode } from '@graphql-typed-document-node/core';
14
12
  * @returns The response of the query of generic type <T>.
15
13
  */
16
14
  export declare function partnersRequest<T>(query: string, token: string, variables?: GraphQLVariables, cacheOptions?: CacheOptions, preferredBehaviour?: RequestModeInput, unauthorizedHandler?: UnauthorizedHandler): Promise<T>;
17
- export declare const generateFetchAppLogUrl: (cursor?: string, filters?: {
18
- status?: string;
19
- source?: string;
20
- }) => Promise<string>;
21
- /**
22
- * Executes a GraphQL query against the Partners API. Uses typed documents.
23
- *
24
- * @param query - GraphQL query to execute.
25
- * @param token - Partners token.
26
- * @param variables - GraphQL variables to pass to the query.
27
- * @param preferredBehaviour - Preferred behaviour for the request.
28
- * @param unauthorizedHandler - Optional handler for unauthorized requests.
29
- * @returns The response of the query of generic type <TResult>.
30
- */
31
- export declare function partnersRequestDoc<TResult, TVariables extends Variables>(query: TypedDocumentNode<TResult, TVariables>, token: string, variables?: TVariables, preferredBehaviour?: RequestModeInput, unauthorizedHandler?: UnauthorizedHandler): Promise<TResult>;
32
15
  /**
33
16
  * Sets the next deprecation date from [GraphQL response extensions](https://www.apollographql.com/docs/resources/graphql-glossary/#extensions)
34
17
  * if `response.extensions.deprecations` objects contain a `supportedUntilDate` (ISO 8601-formatted string).
@@ -1,11 +1,6 @@
1
- import { addCursorAndFiltersToAppLogsUrl } from './utilities.js';
2
- import { graphqlRequest, graphqlRequestDoc, } from './graphql.js';
1
+ import { graphqlRequest } from './graphql.js';
3
2
  import { partnersFqdn } from '../context/fqdn.js';
4
3
  import { setNextDeprecationDate } from '../../../private/node/context/deprecations-store.js';
5
- import { getPackageManager } from '../node-package-manager.js';
6
- import { cwd } from '../path.js';
7
- import { AbortError } from '../error.js';
8
- import { formatPackageManagerCommand } from '../output.js';
9
4
  import Bottleneck from 'bottleneck';
10
5
  // API Rate limiter for partners API (Limit is 10 requests per second)
11
6
  // Jobs are launched every 150ms to add an extra 50ms margin per request.
@@ -53,44 +48,6 @@ export async function partnersRequest(query, token, variables, cacheOptions, pre
53
48
  }));
54
49
  return result;
55
50
  }
56
- export const generateFetchAppLogUrl = async (cursor, filters) => {
57
- const fqdn = await partnersFqdn();
58
- const url = `https://${fqdn}/app_logs/poll`;
59
- return addCursorAndFiltersToAppLogsUrl(url, cursor, filters);
60
- };
61
- /**
62
- * Executes a GraphQL query against the Partners API. Uses typed documents.
63
- *
64
- * @param query - GraphQL query to execute.
65
- * @param token - Partners token.
66
- * @param variables - GraphQL variables to pass to the query.
67
- * @param preferredBehaviour - Preferred behaviour for the request.
68
- * @param unauthorizedHandler - Optional handler for unauthorized requests.
69
- * @returns The response of the query of generic type <TResult>.
70
- */
71
- export async function partnersRequestDoc(query, token, variables, preferredBehaviour, unauthorizedHandler) {
72
- try {
73
- const opts = await setupRequest(token);
74
- const result = limiter.schedule(() => graphqlRequestDoc({
75
- ...opts,
76
- query,
77
- variables,
78
- preferredBehaviour,
79
- unauthorizedHandler,
80
- }));
81
- return result;
82
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
- }
84
- catch (error) {
85
- if (error.errors?.[0]?.extensions?.type === 'unsupported_client_version') {
86
- const packageManager = await getPackageManager(cwd());
87
- throw new AbortError(['Upgrade your CLI version to run this command.'], null, [
88
- ['Run', { command: formatPackageManagerCommand(packageManager, 'shopify upgrade') }],
89
- ]);
90
- }
91
- throw error;
92
- }
93
- }
94
51
  /**
95
52
  * Sets the next deprecation date from [GraphQL response extensions](https://www.apollographql.com/docs/resources/graphql-glossary/#extensions)
96
53
  * if `response.extensions.deprecations` objects contain a `supportedUntilDate` (ISO 8601-formatted string).
@@ -1 +1 @@
1
- {"version":3,"file":"partners.js","sourceRoot":"","sources":["../../../../src/public/node/api/partners.ts"],"names":[],"mappings":"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","sourcesContent":["import {addCursorAndFiltersToAppLogsUrl} from './utilities.js'\nimport {\n graphqlRequest,\n GraphQLVariables,\n GraphQLResponse,\n graphqlRequestDoc,\n CacheOptions,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {partnersFqdn} from '../context/fqdn.js'\nimport {setNextDeprecationDate} from '../../../private/node/context/deprecations-store.js'\nimport {getPackageManager} from '../node-package-manager.js'\nimport {cwd} from '../path.js'\nimport {AbortError} from '../error.js'\nimport {formatPackageManagerCommand} from '../output.js'\nimport {RequestModeInput} from '../http.js'\nimport Bottleneck from 'bottleneck'\n\nimport {Variables} from 'graphql-request'\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\n// API Rate limiter for partners API (Limit is 10 requests per second)\n// Jobs are launched every 150ms to add an extra 50ms margin per request.\n// Only 10 requests can be executed concurrently.\nconst limiter = new Bottleneck({\n minTime: 150,\n maxConcurrent: 10,\n})\n\n/**\n * Sets up the request to the Partners API.\n *\n * @param token - Partners token.\n */\nasync function setupRequest(token: string) {\n const api = 'Partners'\n const fqdn = await partnersFqdn()\n const url = `https://${fqdn}/api/cli/graphql`\n return {\n token,\n api,\n url,\n responseOptions: {onResponse: handleDeprecations},\n }\n}\n\n/**\n * Executes a GraphQL query against the Partners API.\n *\n * @param query - GraphQL query to execute.\n * @param token - Partners token.\n * @param variables - GraphQL variables to pass to the query.\n * @param cacheOptions - Cache options.\n * @param preferredBehaviour - Preferred behaviour for the request.\n * @param unauthorizedHandler - Optional handler for unauthorized requests.\n * @returns The response of the query of generic type <T>.\n */\nexport async function partnersRequest<T>(\n query: string,\n token: string,\n variables?: GraphQLVariables,\n cacheOptions?: CacheOptions,\n preferredBehaviour?: RequestModeInput,\n unauthorizedHandler?: UnauthorizedHandler,\n): Promise<T> {\n const opts = await setupRequest(token)\n const result = limiter.schedule(() =>\n graphqlRequest<T>({\n ...opts,\n query,\n variables,\n cacheOptions,\n preferredBehaviour,\n unauthorizedHandler,\n }),\n )\n\n return result\n}\n\nexport const generateFetchAppLogUrl = async (\n cursor?: string,\n filters?: {\n status?: string\n source?: string\n },\n): Promise<string> => {\n const fqdn = await partnersFqdn()\n const url = `https://${fqdn}/app_logs/poll`\n return addCursorAndFiltersToAppLogsUrl(url, cursor, filters)\n}\n\n/**\n * Executes a GraphQL query against the Partners API. Uses typed documents.\n *\n * @param query - GraphQL query to execute.\n * @param token - Partners token.\n * @param variables - GraphQL variables to pass to the query.\n * @param preferredBehaviour - Preferred behaviour for the request.\n * @param unauthorizedHandler - Optional handler for unauthorized requests.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function partnersRequestDoc<TResult, TVariables extends Variables>(\n query: TypedDocumentNode<TResult, TVariables>,\n token: string,\n variables?: TVariables,\n preferredBehaviour?: RequestModeInput,\n unauthorizedHandler?: UnauthorizedHandler,\n): Promise<TResult> {\n try {\n const opts = await setupRequest(token)\n const result = limiter.schedule(() =>\n graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n preferredBehaviour,\n unauthorizedHandler,\n }),\n )\n\n return result\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (error.errors?.[0]?.extensions?.type === 'unsupported_client_version') {\n const packageManager = await getPackageManager(cwd())\n\n throw new AbortError(['Upgrade your CLI version to run this command.'], null, [\n ['Run', {command: formatPackageManagerCommand(packageManager, 'shopify upgrade')}],\n ])\n }\n\n throw error\n }\n}\n\ninterface Deprecation {\n supportedUntilDate?: string\n}\n\ninterface WithDeprecations {\n deprecations: Deprecation[]\n}\n\n/**\n * Sets the next deprecation date from [GraphQL response extensions](https://www.apollographql.com/docs/resources/graphql-glossary/#extensions)\n * if `response.extensions.deprecations` objects contain a `supportedUntilDate` (ISO 8601-formatted string).\n *\n * @param response - The response of the query.\n */\nexport function handleDeprecations<T>(response: GraphQLResponse<T>): void {\n if (!response.extensions) return\n\n const deprecationDates: Date[] = []\n for (const deprecation of (response.extensions as WithDeprecations).deprecations) {\n if (deprecation.supportedUntilDate) {\n deprecationDates.push(new Date(deprecation.supportedUntilDate))\n }\n }\n\n setNextDeprecationDate(deprecationDates)\n}\n"]}
1
+ {"version":3,"file":"partners.js","sourceRoot":"","sources":["../../../../src/public/node/api/partners.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAuE,MAAM,cAAc,CAAA;AACjH,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAC,sBAAsB,EAAC,MAAM,qDAAqD,CAAA;AAE1F,OAAO,UAAU,MAAM,YAAY,CAAA;AAEnC,sEAAsE;AACtE,yEAAyE;AACzE,iDAAiD;AACjD,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC;IAC7B,OAAO,EAAE,GAAG;IACZ,aAAa,EAAE,EAAE;CAClB,CAAC,CAAA;AAEF;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,KAAa;IACvC,MAAM,GAAG,GAAG,UAAU,CAAA;IACtB,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IACjC,MAAM,GAAG,GAAG,WAAW,IAAI,kBAAkB,CAAA;IAC7C,OAAO;QACL,KAAK;QACL,GAAG;QACH,GAAG;QACH,eAAe,EAAE,EAAC,UAAU,EAAE,kBAAkB,EAAC;KAClD,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAa,EACb,KAAa,EACb,SAA4B,EAC5B,YAA2B,EAC3B,kBAAqC,EACrC,mBAAyC;IAEzC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAA;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CACnC,cAAc,CAAI;QAChB,GAAG,IAAI;QACP,KAAK;QACL,SAAS;QACT,YAAY;QACZ,kBAAkB;QAClB,mBAAmB;KACpB,CAAC,CACH,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAUD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAI,QAA4B;IAChE,IAAI,CAAC,QAAQ,CAAC,UAAU;QAAE,OAAM;IAEhC,MAAM,gBAAgB,GAAW,EAAE,CAAA;IACnC,KAAK,MAAM,WAAW,IAAK,QAAQ,CAAC,UAA+B,CAAC,YAAY,EAAE,CAAC;QACjF,IAAI,WAAW,CAAC,kBAAkB,EAAE,CAAC;YACnC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;IAED,sBAAsB,CAAC,gBAAgB,CAAC,CAAA;AAC1C,CAAC","sourcesContent":["import {graphqlRequest, GraphQLVariables, GraphQLResponse, CacheOptions, UnauthorizedHandler} from './graphql.js'\nimport {partnersFqdn} from '../context/fqdn.js'\nimport {setNextDeprecationDate} from '../../../private/node/context/deprecations-store.js'\nimport {RequestModeInput} from '../http.js'\nimport Bottleneck from 'bottleneck'\n\n// API Rate limiter for partners API (Limit is 10 requests per second)\n// Jobs are launched every 150ms to add an extra 50ms margin per request.\n// Only 10 requests can be executed concurrently.\nconst limiter = new Bottleneck({\n minTime: 150,\n maxConcurrent: 10,\n})\n\n/**\n * Sets up the request to the Partners API.\n *\n * @param token - Partners token.\n */\nasync function setupRequest(token: string) {\n const api = 'Partners'\n const fqdn = await partnersFqdn()\n const url = `https://${fqdn}/api/cli/graphql`\n return {\n token,\n api,\n url,\n responseOptions: {onResponse: handleDeprecations},\n }\n}\n\n/**\n * Executes a GraphQL query against the Partners API.\n *\n * @param query - GraphQL query to execute.\n * @param token - Partners token.\n * @param variables - GraphQL variables to pass to the query.\n * @param cacheOptions - Cache options.\n * @param preferredBehaviour - Preferred behaviour for the request.\n * @param unauthorizedHandler - Optional handler for unauthorized requests.\n * @returns The response of the query of generic type <T>.\n */\nexport async function partnersRequest<T>(\n query: string,\n token: string,\n variables?: GraphQLVariables,\n cacheOptions?: CacheOptions,\n preferredBehaviour?: RequestModeInput,\n unauthorizedHandler?: UnauthorizedHandler,\n): Promise<T> {\n const opts = await setupRequest(token)\n const result = limiter.schedule(() =>\n graphqlRequest<T>({\n ...opts,\n query,\n variables,\n cacheOptions,\n preferredBehaviour,\n unauthorizedHandler,\n }),\n )\n\n return result\n}\n\ninterface Deprecation {\n supportedUntilDate?: string\n}\n\ninterface WithDeprecations {\n deprecations: Deprecation[]\n}\n\n/**\n * Sets the next deprecation date from [GraphQL response extensions](https://www.apollographql.com/docs/resources/graphql-glossary/#extensions)\n * if `response.extensions.deprecations` objects contain a `supportedUntilDate` (ISO 8601-formatted string).\n *\n * @param response - The response of the query.\n */\nexport function handleDeprecations<T>(response: GraphQLResponse<T>): void {\n if (!response.extensions) return\n\n const deprecationDates: Date[] = []\n for (const deprecation of (response.extensions as WithDeprecations).deprecations) {\n if (deprecation.supportedUntilDate) {\n deprecationDates.push(new Date(deprecation.supportedUntilDate))\n }\n }\n\n setNextDeprecationDate(deprecationDates)\n}\n"]}
@@ -36,13 +36,8 @@ function adaptedTreeKill(pid, killSignal, killRoot, callback) {
36
36
  const rootPid = typeof pid === 'number' ? pid.toString() : pid;
37
37
  // Security: Validate that the PID is a number to prevent command injection
38
38
  if (!/^\d+$/.test(rootPid)) {
39
- if (callback) {
40
- callback(new Error('pid must be a number'));
41
- return;
42
- }
43
- else {
44
- throw new Error('pid must be a number');
45
- }
39
+ callback(new Error('pid must be a number'));
40
+ return;
46
41
  }
47
42
  // A map from parent pid to an array of children pids
48
43
  const tree = {};
@@ -56,13 +51,11 @@ function adaptedTreeKill(pid, killSignal, killRoot, callback) {
56
51
  // Security: Use spawn instead of exec to avoid shell injection when killing processes on Windows
57
52
  const taskkill = spawn('taskkill', ['/pid', rootPid, '/T', '/F']);
58
53
  taskkill.on('close', (code) => {
59
- if (callback) {
60
- if (code === 0) {
61
- callback();
62
- }
63
- else {
64
- callback(new Error(`taskkill exited with code ${code}`));
65
- }
54
+ if (code === 0) {
55
+ callback();
56
+ }
57
+ else {
58
+ callback(new Error(`taskkill exited with code ${code}`));
66
59
  }
67
60
  });
68
61
  break;
@@ -107,20 +100,14 @@ function killAll(tree, killSignal, rootPid, killRoot, callback) {
107
100
  killed.add(pid);
108
101
  }
109
102
  });
103
+ // eslint-disable-next-line no-catch-all/no-catch-all
110
104
  }
111
105
  catch (err) {
112
- if (callback) {
113
- // @ts-ignore
114
- callback(err);
115
- return;
116
- }
117
- else {
118
- throw err;
119
- }
120
- }
121
- if (callback) {
122
- callback();
106
+ // @ts-ignore
107
+ callback(err);
108
+ return;
123
109
  }
110
+ callback();
124
111
  }
125
112
  /**
126
113
  * Kills a process.
@@ -1 +1 @@
1
- {"version":3,"file":"tree-kill.js","sourceRoot":"","sources":["../../../src/public/node/tree-kill.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable jsdoc/require-throws */\n/* eslint-disable no-restricted-imports */\n\nimport {outputDebug} from './output.js'\nimport {spawn} from 'child_process'\n\ntype ProcessTree = Record<string, string[]>\n\ntype AfterKillCallback = (error?: Error) => void\n\n/**\n * Kills the process that calls the method and all its children.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nexport function treeKill(\n pid: number | string = process.pid,\n killSignal = 'SIGTERM',\n killRoot = true,\n callback?: AfterKillCallback,\n): void {\n const after =\n callback ??\n ((error?: Error) => {\n if (error) outputDebug(`Failed to kill process ${pid}: ${error}`)\n })\n adaptedTreeKill(pid, killSignal, killRoot, after)\n}\n\n/**\n * Adapted from https://github.com/pkrumins/node-tree-kill.\n *\n * Our implementation allows to skip killing the root process. This is useful for example when\n * gracefully exiting the 'dev' process, as the default tree-kill implementation will cause it\n * to exit with a non-zero code. Instead, we want to treat it as a graceful termination.\n * In addition, we also add debug logging for better visibility in what tree-kill is doing.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction adaptedTreeKill(\n pid: number | string,\n killSignal: string,\n killRoot: boolean,\n callback: (error?: Error) => void,\n): void {\n const rootPid = typeof pid === 'number' ? pid.toString() : pid\n\n // Security: Validate that the PID is a number to prevent command injection\n if (!/^\\d+$/.test(rootPid)) {\n if (callback) {\n callback(new Error('pid must be a number'))\n return\n } else {\n throw new Error('pid must be a number')\n }\n }\n\n // A map from parent pid to an array of children pids\n const tree: ProcessTree = {}\n tree[rootPid] = []\n\n // A set of pids to visit. We use it to recursively find all the children pids\n const pidsToProcess = new Set<string>()\n pidsToProcess.add(rootPid)\n\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- default handles all Unix-like platforms\n switch (process.platform) {\n case 'win32': {\n // Security: Use spawn instead of exec to avoid shell injection when killing processes on Windows\n const taskkill = spawn('taskkill', ['/pid', rootPid, '/T', '/F'])\n taskkill.on('close', (code: number) => {\n if (callback) {\n if (code === 0) {\n callback()\n } else {\n callback(new Error(`taskkill exited with code ${code}`))\n }\n }\n })\n break\n }\n case 'darwin':\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('pgrep', ['-lfP', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n default:\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('ps', ['-o', 'pid command', '--no-headers', '--ppid', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n }\n}\n\n/**\n * Kills all processes in the process tree.\n *\n * @param tree - Process tree.\n * @param killSignal - Type of kill signal to be used.\n * @param rootPid - Pid of the root process.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction killAll(\n tree: ProcessTree,\n killSignal: string,\n rootPid: string,\n killRoot: boolean,\n callback: AfterKillCallback,\n): void {\n const killed = new Set<string>()\n try {\n Object.keys(tree).forEach(function (pid) {\n tree[pid]!.forEach(function (pidpid) {\n if (!killed.has(pidpid)) {\n killPid(pidpid, killSignal)\n killed.add(pidpid)\n }\n })\n if (pid === rootPid && killRoot && !killed.has(pid)) {\n killPid(pid, killSignal)\n killed.add(pid)\n }\n })\n } catch (err: unknown) {\n if (callback) {\n // @ts-ignore\n callback(err)\n return\n } else {\n throw err\n }\n }\n if (callback) {\n callback()\n }\n}\n\n/**\n * Kills a process.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n */\nfunction killPid(pid: string, killSignal: string) {\n try {\n process.kill(parseInt(pid, 10), killSignal)\n } catch (err) {\n // @ts-ignore\n if (err.code !== 'ESRCH') throw err\n }\n}\n\n/**\n * Builds a process tree.\n *\n * @param parentPid - Pid of the parent process.\n * @param tree - Process tree.\n * @param pidsToProcess - Pids to process.\n * @param spawnChildProcessesList - Function to spawn child processes.\n * @param cb - Callback to run after building the process tree.\n */\nfunction buildProcessTree(\n parentPid: string,\n tree: ProcessTree,\n pidsToProcess: Set<string>,\n spawnChildProcessesList: (parentPid: string) => ReturnType<typeof spawn>,\n cb: () => void,\n) {\n const ps = spawnChildProcessesList(parentPid)\n let allData = ''\n ps.stdout?.on('data', function (data: Buffer) {\n const dataStr = data.toString('ascii')\n allData += dataStr\n })\n\n const onClose = (code: number) => {\n pidsToProcess.delete(parentPid)\n\n if (code !== 0) {\n // no more parent processes\n if (pidsToProcess.size === 0) {\n cb()\n return\n }\n return\n }\n\n allData\n .trim()\n .split('\\n')\n .forEach(function (line) {\n const match = line.match(/^(\\d+)\\s(.*)$/)\n if (match) {\n const pid = match[1]!\n const cmd = match[2]!\n tree[parentPid]!.push(pid)\n tree[pid] = []\n outputDebug(`Killing process ${pid}: ${cmd}`)\n pidsToProcess.add(pid)\n buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb)\n }\n })\n }\n\n ps.on('close', onClose)\n}\n"]}
1
+ {"version":3,"file":"tree-kill.js","sourceRoot":"","sources":["../../../src/public/node/tree-kill.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,yCAAyC;AACzC,0CAA0C;AAE1C,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AACvC,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAA;AAMnC;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAuB,OAAO,CAAC,GAAG,EAClC,UAAU,GAAG,SAAS,EACtB,QAAQ,GAAG,IAAI,EACf,QAA4B;IAE5B,MAAM,KAAK,GACT,QAAQ;QACR,CAAC,CAAC,KAAa,EAAE,EAAE;YACjB,IAAI,KAAK;gBAAE,WAAW,CAAC,0BAA0B,GAAG,KAAK,KAAK,EAAE,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;IACJ,eAAe,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;AACnD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,eAAe,CACtB,GAAoB,EACpB,UAAkB,EAClB,QAAiB,EACjB,QAAiC;IAEjC,MAAM,OAAO,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;IAE9D,2EAA2E;IAC3E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAA;QAC3C,OAAM;IACR,CAAC;IAED,qDAAqD;IACrD,MAAM,IAAI,GAAgB,EAAE,CAAA;IAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;IAElB,8EAA8E;IAC9E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAA;IACvC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAE1B,qHAAqH;IACrH,QAAQ,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzB,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,iGAAiG;YACjG,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;YACjE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE;gBACpC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,QAAQ,EAAE,CAAA;gBACZ,CAAC;qBAAM,CAAC;oBACN,QAAQ,CAAC,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC,CAAA;gBAC1D,CAAC;YACH,CAAC,CAAC,CAAA;YACF,MAAK;QACP,CAAC;QACD,KAAK,QAAQ;YACX,gBAAgB,CACd,OAAO,EACP,IAAI,EACJ,aAAa,EACb,UAAU,SAAiB;gBACzB,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;YAC5C,CAAC,EACD;gBACE,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACxD,CAAC,CACF,CAAA;YACD,MAAK;QACP;YACE,gBAAgB,CACd,OAAO,EACP,IAAI,EACJ,aAAa,EACb,UAAU,SAAiB;gBACzB,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAA;YAChF,CAAC,EACD;gBACE,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACxD,CAAC,CACF,CAAA;YACD,MAAK;IACT,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,OAAO,CACd,IAAiB,EACjB,UAAkB,EAClB,OAAe,EACf,QAAiB,EACjB,QAA2B;IAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;IAChC,IAAI,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,GAAG;YACrC,IAAI,CAAC,GAAG,CAAE,CAAC,OAAO,CAAC,UAAU,MAAM;gBACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxB,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;oBAC3B,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBACpB,CAAC;YACH,CAAC,CAAC,CAAA;YACF,IAAI,GAAG,KAAK,OAAO,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpD,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;gBACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACjB,CAAC;QACH,CAAC,CAAC,CAAA;QACF,qDAAqD;IACvD,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,aAAa;QACb,QAAQ,CAAC,GAAG,CAAC,CAAA;QACb,OAAM;IACR,CAAC;IACD,QAAQ,EAAE,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,SAAS,OAAO,CAAC,GAAW,EAAE,UAAkB;IAC9C,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAA;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,aAAa;QACb,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,GAAG,CAAA;IACrC,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,gBAAgB,CACvB,SAAiB,EACjB,IAAiB,EACjB,aAA0B,EAC1B,uBAAwE,EACxE,EAAc;IAEd,MAAM,EAAE,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAA;IAC7C,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,IAAY;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QACtC,OAAO,IAAI,OAAO,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE;QAC/B,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAE/B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,2BAA2B;YAC3B,IAAI,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC7B,EAAE,EAAE,CAAA;gBACJ,OAAM;YACR,CAAC;YACD,OAAM;QACR,CAAC;QAED,OAAO;aACJ,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC;aACX,OAAO,CAAC,UAAU,IAAI;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;YACzC,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAE,CAAA;gBACrB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAE,CAAA;gBACrB,IAAI,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAA;gBACd,WAAW,CAAC,mBAAmB,GAAG,KAAK,GAAG,EAAE,CAAC,CAAA;gBAC7C,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACtB,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,uBAAuB,EAAE,EAAE,CAAC,CAAA;YACzE,CAAC;QACH,CAAC,CAAC,CAAA;IACN,CAAC,CAAA;IAED,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACzB,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable jsdoc/require-throws */\n/* eslint-disable no-restricted-imports */\n\nimport {outputDebug} from './output.js'\nimport {spawn} from 'child_process'\n\ntype ProcessTree = Record<string, string[]>\n\ntype AfterKillCallback = (error?: Error) => void\n\n/**\n * Kills the process that calls the method and all its children.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nexport function treeKill(\n pid: number | string = process.pid,\n killSignal = 'SIGTERM',\n killRoot = true,\n callback?: AfterKillCallback,\n): void {\n const after =\n callback ??\n ((error?: Error) => {\n if (error) outputDebug(`Failed to kill process ${pid}: ${error}`)\n })\n adaptedTreeKill(pid, killSignal, killRoot, after)\n}\n\n/**\n * Adapted from https://github.com/pkrumins/node-tree-kill.\n *\n * Our implementation allows to skip killing the root process. This is useful for example when\n * gracefully exiting the 'dev' process, as the default tree-kill implementation will cause it\n * to exit with a non-zero code. Instead, we want to treat it as a graceful termination.\n * In addition, we also add debug logging for better visibility in what tree-kill is doing.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction adaptedTreeKill(\n pid: number | string,\n killSignal: string,\n killRoot: boolean,\n callback: (error?: Error) => void,\n): void {\n const rootPid = typeof pid === 'number' ? pid.toString() : pid\n\n // Security: Validate that the PID is a number to prevent command injection\n if (!/^\\d+$/.test(rootPid)) {\n callback(new Error('pid must be a number'))\n return\n }\n\n // A map from parent pid to an array of children pids\n const tree: ProcessTree = {}\n tree[rootPid] = []\n\n // A set of pids to visit. We use it to recursively find all the children pids\n const pidsToProcess = new Set<string>()\n pidsToProcess.add(rootPid)\n\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- default handles all Unix-like platforms\n switch (process.platform) {\n case 'win32': {\n // Security: Use spawn instead of exec to avoid shell injection when killing processes on Windows\n const taskkill = spawn('taskkill', ['/pid', rootPid, '/T', '/F'])\n taskkill.on('close', (code: number) => {\n if (code === 0) {\n callback()\n } else {\n callback(new Error(`taskkill exited with code ${code}`))\n }\n })\n break\n }\n case 'darwin':\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('pgrep', ['-lfP', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n default:\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('ps', ['-o', 'pid command', '--no-headers', '--ppid', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n }\n}\n\n/**\n * Kills all processes in the process tree.\n *\n * @param tree - Process tree.\n * @param killSignal - Type of kill signal to be used.\n * @param rootPid - Pid of the root process.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction killAll(\n tree: ProcessTree,\n killSignal: string,\n rootPid: string,\n killRoot: boolean,\n callback: AfterKillCallback,\n): void {\n const killed = new Set<string>()\n try {\n Object.keys(tree).forEach(function (pid) {\n tree[pid]!.forEach(function (pidpid) {\n if (!killed.has(pidpid)) {\n killPid(pidpid, killSignal)\n killed.add(pidpid)\n }\n })\n if (pid === rootPid && killRoot && !killed.has(pid)) {\n killPid(pid, killSignal)\n killed.add(pid)\n }\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err: unknown) {\n // @ts-ignore\n callback(err)\n return\n }\n callback()\n}\n\n/**\n * Kills a process.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n */\nfunction killPid(pid: string, killSignal: string) {\n try {\n process.kill(parseInt(pid, 10), killSignal)\n } catch (err) {\n // @ts-ignore\n if (err.code !== 'ESRCH') throw err\n }\n}\n\n/**\n * Builds a process tree.\n *\n * @param parentPid - Pid of the parent process.\n * @param tree - Process tree.\n * @param pidsToProcess - Pids to process.\n * @param spawnChildProcessesList - Function to spawn child processes.\n * @param cb - Callback to run after building the process tree.\n */\nfunction buildProcessTree(\n parentPid: string,\n tree: ProcessTree,\n pidsToProcess: Set<string>,\n spawnChildProcessesList: (parentPid: string) => ReturnType<typeof spawn>,\n cb: () => void,\n) {\n const ps = spawnChildProcessesList(parentPid)\n let allData = ''\n ps.stdout?.on('data', function (data: Buffer) {\n const dataStr = data.toString('ascii')\n allData += dataStr\n })\n\n const onClose = (code: number) => {\n pidsToProcess.delete(parentPid)\n\n if (code !== 0) {\n // no more parent processes\n if (pidsToProcess.size === 0) {\n cb()\n return\n }\n return\n }\n\n allData\n .trim()\n .split('\\n')\n .forEach(function (line) {\n const match = line.match(/^(\\d+)\\s(.*)$/)\n if (match) {\n const pid = match[1]!\n const cmd = match[2]!\n tree[parentPid]!.push(pid)\n tree[pid] = []\n outputDebug(`Killing process ${pid}: ${cmd}`)\n pidsToProcess.add(pid)\n buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb)\n }\n })\n }\n\n ps.on('close', onClose)\n}\n"]}