@shopify/cli-kit 3.3.3 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/api/admin.js +20 -34
- package/dist/api/admin.js.map +1 -1
- package/dist/api/common.d.ts +11 -1
- package/dist/api/common.js +50 -4
- package/dist/api/common.js.map +1 -1
- package/dist/api/identity.js +3 -3
- package/dist/api/identity.js.map +1 -1
- package/dist/api/partners.d.ts +0 -5
- package/dist/api/partners.js +22 -42
- package/dist/api/partners.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/environment/local.d.ts +1 -0
- package/dist/environment/local.js +3 -0
- package/dist/environment/local.js.map +1 -1
- package/dist/environment/service.d.ts +2 -1
- package/dist/environment/service.js +16 -0
- package/dist/environment/service.js.map +1 -1
- package/dist/error.d.ts +5 -0
- package/dist/error.js +10 -4
- package/dist/error.js.map +1 -1
- package/dist/file.d.ts +2 -0
- package/dist/file.js +13 -1
- package/dist/file.js.map +1 -1
- package/dist/git.js +12 -4
- package/dist/git.js.map +1 -1
- package/dist/http/fetch.d.ts +9 -2
- package/dist/http/fetch.js +11 -2
- package/dist/http/fetch.js.map +1 -1
- package/dist/http/graphql.d.ts +15 -0
- package/dist/http/graphql.js +12 -0
- package/dist/http/graphql.js.map +1 -0
- package/dist/http.d.ts +24 -0
- package/dist/http.js +27 -0
- package/dist/http.js.map +1 -1
- package/dist/network/service.d.ts +1 -1
- package/dist/network/service.js.map +1 -1
- package/dist/node/base-command.d.ts +1 -0
- package/dist/node/base-command.js +10 -1
- package/dist/node/base-command.js.map +1 -1
- package/dist/node/cli.d.ts +0 -2
- package/dist/node/cli.js +0 -4
- package/dist/node/cli.js.map +1 -1
- package/dist/node/error-handler.d.ts +20 -0
- package/dist/node/error-handler.js +40 -3
- package/dist/node/error-handler.js.map +1 -1
- package/dist/node/hooks/init.d.ts +2 -0
- package/dist/node/hooks/init.js +7 -0
- package/dist/node/hooks/init.js.map +1 -0
- package/dist/node/hooks/postrun.js +4 -1
- package/dist/node/hooks/postrun.js.map +1 -1
- package/dist/node/hooks/prerun.js +2 -0
- package/dist/node/hooks/prerun.js.map +1 -1
- package/dist/node/ruby.d.ts +7 -2
- package/dist/node/ruby.js +22 -7
- package/dist/node/ruby.js.map +1 -1
- package/dist/output.d.ts +18 -11
- package/dist/output.js +96 -26
- package/dist/output.js.map +1 -1
- package/dist/session/exchange.js +2 -2
- package/dist/session/exchange.js.map +1 -1
- package/dist/session/validate.js +3 -0
- package/dist/session/validate.js.map +1 -1
- package/dist/session.js +7 -1
- package/dist/session.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui.d.ts +11 -0
- package/dist/ui.js +35 -5
- package/dist/ui.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postrun.js","sourceRoot":"","sources":["../../../src/node/hooks/postrun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"postrun.js","sourceRoot":"","sources":["../../../src/node/hooks/postrun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAA;AAGrC,gGAAgG;AAChG,MAAM,CAAC,MAAM,QAAQ,GAAiB,KAAK,EAAE,OAAO,EAAE,EAAE;IACtD,MAAM,WAAW,EAAE,CAAA;IACnB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACvD,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAA;AACvC,CAAC,CAAA","sourcesContent":["import {reportEvent} from '../../analytics.js'\nimport {debug} from '../../output.js'\nimport {Hook} from '@oclif/core'\n\n// This hook is called after each successful command run. More info: https://oclif.io/docs/hooks\nexport const hookPost: Hook.Postrun = async (options) => {\n await reportEvent()\n const command = options.Command?.id?.replace(/:/g, ' ')\n debug(`Completed command ${command}`)\n}\n"]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { start } from '../../analytics.js';
|
|
2
|
+
import { debug } from '../../output.js';
|
|
2
3
|
// This hook is called before each command run. More info: https://oclif.io/docs/hooks
|
|
3
4
|
export const hook = async (options) => {
|
|
4
5
|
const cmd = options.Command.aliases.length === 0 ? options.Command.id : options.Command.aliases[0];
|
|
5
6
|
const command = cmd.replace(/:/g, ' ');
|
|
6
7
|
const args = options.argv;
|
|
8
|
+
debug(`Running command ${command}`);
|
|
7
9
|
start({ command, args });
|
|
8
10
|
};
|
|
9
11
|
//# sourceMappingURL=prerun.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../src/node/hooks/prerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../src/node/hooks/prerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAA;AACxC,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAA;AAGrC,sFAAsF;AACtF,MAAM,CAAC,MAAM,IAAI,GAAgB,KAAK,EAAE,OAAO,EAAE,EAAE;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAClG,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;IACzB,KAAK,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAA;IACnC,KAAK,CAAC,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAA;AACxB,CAAC,CAAA","sourcesContent":["import {start} from '../../analytics.js'\nimport {debug} from '../../output.js'\nimport {Hook} from '@oclif/core'\n\n// This hook is called before each command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Prerun = async (options) => {\n const cmd = options.Command.aliases.length === 0 ? options.Command.id : options.Command.aliases[0]\n const command = cmd.replace(/:/g, ' ')\n const args = options.argv\n debug(`Running command ${command}`)\n start({command, args})\n}\n"]}
|
package/dist/node/ruby.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { AdminSession } from '../session.js';
|
|
3
3
|
import { Writable } from 'node:stream';
|
|
4
|
+
interface ExecCLI2Options {
|
|
5
|
+
adminSession?: AdminSession;
|
|
6
|
+
storefrontToken?: string;
|
|
7
|
+
directory?: string;
|
|
8
|
+
}
|
|
4
9
|
/**
|
|
5
10
|
* Execute CLI 2.0 commands.
|
|
6
11
|
* Installs a version of RubyCLI as a vendor dependency in a hidden folder in the system.
|
|
7
12
|
* User must have a valid ruby+bundler environment to run any command.
|
|
8
13
|
*
|
|
9
14
|
* @param args {string[]} List of argumets to execute. (ex: ['theme', 'pull'])
|
|
10
|
-
* @param
|
|
15
|
+
* @param options {ExecCLI2Options}
|
|
11
16
|
*/
|
|
12
|
-
export declare function execCLI2(args: string[], adminSession?:
|
|
17
|
+
export declare function execCLI2(args: string[], { adminSession, storefrontToken, directory }?: ExecCLI2Options): Promise<void>;
|
|
13
18
|
interface ExecThemeCheckCLIOptions {
|
|
14
19
|
/** A list of directories in which theme-check should run */
|
|
15
20
|
directories: string[];
|
package/dist/node/ruby.js
CHANGED
|
@@ -18,18 +18,23 @@ const MinRubyGemVersion = '2.5.0';
|
|
|
18
18
|
* User must have a valid ruby+bundler environment to run any command.
|
|
19
19
|
*
|
|
20
20
|
* @param args {string[]} List of argumets to execute. (ex: ['theme', 'pull'])
|
|
21
|
-
* @param
|
|
21
|
+
* @param options {ExecCLI2Options}
|
|
22
22
|
*/
|
|
23
|
-
export async function execCLI2(args, adminSession) {
|
|
23
|
+
export async function execCLI2(args, { adminSession, storefrontToken, directory } = {}) {
|
|
24
24
|
await installCLIDependencies();
|
|
25
25
|
const env = {
|
|
26
26
|
...process.env,
|
|
27
|
+
SHOPIFY_CLI_STOREFRONT_RENDERER_AUTH_TOKEN: storefrontToken,
|
|
27
28
|
SHOPIFY_CLI_ADMIN_AUTH_TOKEN: adminSession?.token,
|
|
28
29
|
SHOPIFY_CLI_STORE: adminSession?.storeFqdn,
|
|
30
|
+
// Bundler uses this Gemfile to understand which gems are available in the
|
|
31
|
+
// environment. We use this to specify our own Gemfile for CLI2, which exists
|
|
32
|
+
// outside the user's project directory.
|
|
33
|
+
BUNDLE_GEMFILE: join(shopifyCLIDirectory(), 'Gemfile'),
|
|
29
34
|
};
|
|
30
35
|
await system.exec('bundle', ['exec', 'shopify'].concat(args), {
|
|
31
36
|
stdio: 'inherit',
|
|
32
|
-
cwd:
|
|
37
|
+
cwd: directory ?? process.cwd(),
|
|
33
38
|
env,
|
|
34
39
|
});
|
|
35
40
|
}
|
|
@@ -106,10 +111,16 @@ async function installCLIDependencies() {
|
|
|
106
111
|
{
|
|
107
112
|
title: 'Installing theme dependencies',
|
|
108
113
|
task: async () => {
|
|
114
|
+
const usingLocalCLI2 = Boolean(process.env.SHOPIFY_CLI_2_0_DIRECTORY);
|
|
109
115
|
await validateRubyEnv();
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
if (usingLocalCLI2) {
|
|
117
|
+
await bundleInstallLocalShopifyCLI();
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
await createShopifyCLIWorkingDirectory();
|
|
121
|
+
await createShopifyCLIGemfile();
|
|
122
|
+
await bundleInstallShopifyCLI();
|
|
123
|
+
}
|
|
113
124
|
},
|
|
114
125
|
},
|
|
115
126
|
], { renderer });
|
|
@@ -170,6 +181,9 @@ async function createThemeCheckGemfile() {
|
|
|
170
181
|
const gemPath = join(themeCheckDirectory(), 'Gemfile');
|
|
171
182
|
await file.write(gemPath, `source 'https://rubygems.org'\ngem 'theme-check', '${ThemeCheckVersion}'`);
|
|
172
183
|
}
|
|
184
|
+
async function bundleInstallLocalShopifyCLI() {
|
|
185
|
+
await system.exec('bundle', ['install'], { cwd: shopifyCLIDirectory() });
|
|
186
|
+
}
|
|
173
187
|
async function bundleInstallShopifyCLI() {
|
|
174
188
|
await system.exec('bundle', ['config', 'set', '--local', 'path', shopifyCLIDirectory()], { cwd: shopifyCLIDirectory() });
|
|
175
189
|
await system.exec('bundle', ['install'], { cwd: shopifyCLIDirectory() });
|
|
@@ -179,7 +193,8 @@ async function bundleInstallThemeCheck() {
|
|
|
179
193
|
await system.exec('bundle', ['install'], { cwd: themeCheckDirectory() });
|
|
180
194
|
}
|
|
181
195
|
function shopifyCLIDirectory() {
|
|
182
|
-
return
|
|
196
|
+
return (process.env.SHOPIFY_CLI_2_0_DIRECTORY ??
|
|
197
|
+
join(constants.paths.directories.cache.vendor.path(), 'ruby-cli', RubyCLIVersion));
|
|
183
198
|
}
|
|
184
199
|
function themeCheckDirectory() {
|
|
185
200
|
return join(constants.paths.directories.cache.vendor.path(), 'theme-check', ThemeCheckVersion);
|
package/dist/node/ruby.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../src/node/ruby.ts"],"names":[],"mappings":"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","sourcesContent":["import * as file from '../file.js'\nimport * as ui from '../ui.js'\nimport * as system from '../system.js'\nimport {Abort} from '../error.js'\nimport {glob, join} from '../path.js'\nimport constants from '../constants.js'\nimport {coerce} from '../semver.js'\nimport {AdminSession} from '../session.js'\nimport {content, token} from '../output.js'\nimport {Writable} from 'node:stream'\n\nconst RubyCLIVersion = '2.20.1'\nconst ThemeCheckVersion = '1.10.3'\nconst MinBundlerVersion = '2.3.8'\nconst MinRubyVersion = '2.3.0'\nconst MinRubyGemVersion = '2.5.0'\n\n/**\n * Execute CLI 2.0 commands.\n * Installs a version of RubyCLI as a vendor dependency in a hidden folder in the system.\n * User must have a valid ruby+bundler environment to run any command.\n *\n * @param args {string[]} List of argumets to execute. (ex: ['theme', 'pull'])\n * @param adminSession {AdminSession} Contains token and store to pass to CLI 2.0, which will be set as environment variables\n */\nexport async function execCLI2(args: string[], adminSession?: AdminSession) {\n await installCLIDependencies()\n const env = {\n ...process.env,\n SHOPIFY_CLI_ADMIN_AUTH_TOKEN: adminSession?.token,\n SHOPIFY_CLI_STORE: adminSession?.storeFqdn,\n }\n\n await system.exec('bundle', ['exec', 'shopify'].concat(args), {\n stdio: 'inherit',\n cwd: shopifyCLIDirectory(),\n env,\n })\n}\n\ninterface ExecThemeCheckCLIOptions {\n /** A list of directories in which theme-check should run */\n directories: string[]\n /** Arguments to pass to the theme-check CLI */\n args?: string[]\n /** Writable to send standard output content through */\n stdout: Writable\n /** Writable to send standard error content through */\n stderr: Writable\n}\n\n/**\n * A function that installs (if needed) and runs the theme-check CLI.\n * @param options {ExecThemeCheckCLIOptions} Options to customize the execution of theme-check.\n * @returns {Promise<void>} A promise that resolves or rejects depending on the result of the underlying theme-check process.\n */\nexport async function execThemeCheckCLI({\n directories,\n args,\n stdout,\n stderr,\n}: ExecThemeCheckCLIOptions): Promise<void[]> {\n await installThemeCheckCLIDependencies(stdout)\n\n const processes = directories.map(async (directory): Promise<void> => {\n // Check that there are files aside from the extension TOML config file,\n // otherwise theme-check will return a false failure.\n const files = await glob(join(directory, '/**/*'))\n const fileCount = files.filter((file) => !file.match(/\\.toml$/)).length\n if (fileCount === 0) return\n\n const customStderr = new Writable({\n write(chunk, ...args) {\n // For some reason, theme-check reports this initial status line to stderr\n // See https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/diagnostics_engine.rb#L31\n // which leads to https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/io_messenger.rb#L65\n if (chunk.toString('ascii').match(/^Checking/)) {\n stdout.write(chunk, ...args)\n } else {\n stderr.write(chunk, ...args)\n }\n },\n })\n await system.exec('bundle', ['exec', 'theme-check'].concat([directory, ...(args || [])]), {\n stdout,\n stderr: customStderr,\n cwd: themeCheckDirectory(),\n })\n })\n return Promise.all(processes)\n}\n\n/**\n * Validate Ruby Enviroment\n * Install Theme Check CLI and its dependencies\n * Shows a loading message if it's the first time installing dependencies\n * or if we are installing a new version of Theme Check CLI\n */\nasync function installThemeCheckCLIDependencies(stdout: Writable) {\n const exists = await file.exists(themeCheckDirectory())\n\n if (!exists) stdout.write('Installing theme dependencies...')\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n await validateRubyEnv()\n await createThemeCheckCLIWorkingDirectory()\n await createThemeCheckGemfile()\n await bundleInstallThemeCheck()\n },\n },\n ],\n {renderer: 'silent'},\n )\n await list.run()\n if (!exists) stdout.write('Installed theme dependencies!')\n}\n\n/**\n * Validate Ruby Enviroment\n * Install RubyCLI and its dependencies\n * Shows a loading spinner if it's the first time installing dependencies\n * or if we are installing a new version of RubyCLI\n */\nasync function installCLIDependencies() {\n const exists = await file.exists(shopifyCLIDirectory())\n const renderer = exists ? 'silent' : 'default'\n\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n await validateRubyEnv()\n await createShopifyCLIWorkingDirectory()\n await createShopifyCLIGemfile()\n await bundleInstallShopifyCLI()\n },\n },\n ],\n {renderer},\n )\n await list.run()\n}\n\nasync function validateRubyEnv() {\n await validateRuby()\n await validateRubyGems()\n await validateBundler()\n}\n\nasync function validateRuby() {\n let version\n try {\n const stdout = await system.captureOutput('ruby', ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Ruby environment not found',\n `Make sure you have Ruby installed on your system: ${\n content`${token.link('', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinRubyVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Ruby version ${content`${token.yellow(version!.raw)}`.value} is not supported`,\n `Make sure you have at least Ruby ${content`${token.yellow(MinRubyVersion)}`.value} installed on your system: ${\n content`${token.link('', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n}\n\nasync function validateRubyGems() {\n const stdout = await system.captureOutput('gem', ['-v'])\n const version = coerce(stdout)\n\n const isValid = version?.compare(MinRubyGemVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `RubyGems version ${content`${token.yellow(version!.raw)}`.value} is not supported`,\n `To update to the latest version of RubyGems, run ${\n content`${token.genericShellCommand('gem update --system')}`.value\n }`,\n )\n }\n}\n\nasync function validateBundler() {\n let version\n try {\n const stdout = await system.captureOutput('bundler', ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Bundler not found',\n `To install the latest version of Bundler, run ${\n content`${token.genericShellCommand('gem install bundler')}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinBundlerVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Bundler version ${content`${token.yellow(version!.raw)}`.value} is not supported`,\n `To update to the latest version of Bundler, run ${\n content`${token.genericShellCommand('gem install bundler')}`.value\n }`,\n )\n }\n}\n\nfunction createShopifyCLIWorkingDirectory() {\n return file.mkdir(shopifyCLIDirectory())\n}\n\nfunction createThemeCheckCLIWorkingDirectory() {\n return file.mkdir(themeCheckDirectory())\n}\n\nasync function createShopifyCLIGemfile() {\n const gemPath = join(shopifyCLIDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'shopify-cli', '${RubyCLIVersion}'`)\n}\n\nasync function createThemeCheckGemfile() {\n const gemPath = join(themeCheckDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'theme-check', '${ThemeCheckVersion}'`)\n}\n\nasync function bundleInstallShopifyCLI() {\n await system.exec('bundle', ['config', 'set', '--local', 'path', shopifyCLIDirectory()], {cwd: shopifyCLIDirectory()})\n await system.exec('bundle', ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallThemeCheck() {\n await system.exec('bundle', ['config', 'set', '--local', 'path', themeCheckDirectory()], {cwd: themeCheckDirectory()})\n await system.exec('bundle', ['install'], {cwd: themeCheckDirectory()})\n}\n\nfunction shopifyCLIDirectory() {\n return join(constants.paths.directories.cache.vendor.path(), 'ruby-cli', RubyCLIVersion)\n}\n\nfunction themeCheckDirectory() {\n return join(constants.paths.directories.cache.vendor.path(), 'theme-check', ThemeCheckVersion)\n}\n\nexport async function version(): Promise<string | undefined> {\n const parseOutput = (version: string) => version.match(/ruby (\\d+\\.\\d+\\.\\d+)/)?.[1]\n return system\n .captureOutput('ruby', ['-v'])\n .then(parseOutput)\n .catch(() => undefined)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../src/node/ruby.ts"],"names":[],"mappings":"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","sourcesContent":["import * as file from '../file.js'\nimport * as ui from '../ui.js'\nimport * as system from '../system.js'\nimport {Abort} from '../error.js'\nimport {glob, join} from '../path.js'\nimport constants from '../constants.js'\nimport {coerce} from '../semver.js'\nimport {AdminSession} from '../session.js'\nimport {content, token} from '../output.js'\nimport {Writable} from 'node:stream'\n\nconst RubyCLIVersion = '2.20.1'\nconst ThemeCheckVersion = '1.10.3'\nconst MinBundlerVersion = '2.3.8'\nconst MinRubyVersion = '2.3.0'\nconst MinRubyGemVersion = '2.5.0'\n\ninterface ExecCLI2Options {\n // Contains token and store to pass to CLI 2.0, which will be set as environment variables\n adminSession?: AdminSession\n // Contains token for storefront access to pass to CLI 2.0 as environment variable\n storefrontToken?: string\n // Directory in which to execute the command. Otherwise the current directory will be used.\n directory?: string\n}\n/**\n * Execute CLI 2.0 commands.\n * Installs a version of RubyCLI as a vendor dependency in a hidden folder in the system.\n * User must have a valid ruby+bundler environment to run any command.\n *\n * @param args {string[]} List of argumets to execute. (ex: ['theme', 'pull'])\n * @param options {ExecCLI2Options}\n */\nexport async function execCLI2(args: string[], {adminSession, storefrontToken, directory}: ExecCLI2Options = {}) {\n await installCLIDependencies()\n const env = {\n ...process.env,\n SHOPIFY_CLI_STOREFRONT_RENDERER_AUTH_TOKEN: storefrontToken,\n SHOPIFY_CLI_ADMIN_AUTH_TOKEN: adminSession?.token,\n SHOPIFY_CLI_STORE: adminSession?.storeFqdn,\n // Bundler uses this Gemfile to understand which gems are available in the\n // environment. We use this to specify our own Gemfile for CLI2, which exists\n // outside the user's project directory.\n BUNDLE_GEMFILE: join(shopifyCLIDirectory(), 'Gemfile'),\n }\n\n await system.exec('bundle', ['exec', 'shopify'].concat(args), {\n stdio: 'inherit',\n cwd: directory ?? process.cwd(),\n env,\n })\n}\n\ninterface ExecThemeCheckCLIOptions {\n /** A list of directories in which theme-check should run */\n directories: string[]\n /** Arguments to pass to the theme-check CLI */\n args?: string[]\n /** Writable to send standard output content through */\n stdout: Writable\n /** Writable to send standard error content through */\n stderr: Writable\n}\n\n/**\n * A function that installs (if needed) and runs the theme-check CLI.\n * @param options {ExecThemeCheckCLIOptions} Options to customize the execution of theme-check.\n * @returns {Promise<void>} A promise that resolves or rejects depending on the result of the underlying theme-check process.\n */\nexport async function execThemeCheckCLI({\n directories,\n args,\n stdout,\n stderr,\n}: ExecThemeCheckCLIOptions): Promise<void[]> {\n await installThemeCheckCLIDependencies(stdout)\n\n const processes = directories.map(async (directory): Promise<void> => {\n // Check that there are files aside from the extension TOML config file,\n // otherwise theme-check will return a false failure.\n const files = await glob(join(directory, '/**/*'))\n const fileCount = files.filter((file) => !file.match(/\\.toml$/)).length\n if (fileCount === 0) return\n\n const customStderr = new Writable({\n write(chunk, ...args) {\n // For some reason, theme-check reports this initial status line to stderr\n // See https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/diagnostics_engine.rb#L31\n // which leads to https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/io_messenger.rb#L65\n if (chunk.toString('ascii').match(/^Checking/)) {\n stdout.write(chunk, ...args)\n } else {\n stderr.write(chunk, ...args)\n }\n },\n })\n await system.exec('bundle', ['exec', 'theme-check'].concat([directory, ...(args || [])]), {\n stdout,\n stderr: customStderr,\n cwd: themeCheckDirectory(),\n })\n })\n return Promise.all(processes)\n}\n\n/**\n * Validate Ruby Enviroment\n * Install Theme Check CLI and its dependencies\n * Shows a loading message if it's the first time installing dependencies\n * or if we are installing a new version of Theme Check CLI\n */\nasync function installThemeCheckCLIDependencies(stdout: Writable) {\n const exists = await file.exists(themeCheckDirectory())\n\n if (!exists) stdout.write('Installing theme dependencies...')\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n await validateRubyEnv()\n await createThemeCheckCLIWorkingDirectory()\n await createThemeCheckGemfile()\n await bundleInstallThemeCheck()\n },\n },\n ],\n {renderer: 'silent'},\n )\n await list.run()\n if (!exists) stdout.write('Installed theme dependencies!')\n}\n\n/**\n * Validate Ruby Enviroment\n * Install RubyCLI and its dependencies\n * Shows a loading spinner if it's the first time installing dependencies\n * or if we are installing a new version of RubyCLI\n */\nasync function installCLIDependencies() {\n const exists = await file.exists(shopifyCLIDirectory())\n const renderer = exists ? 'silent' : 'default'\n\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n const usingLocalCLI2 = Boolean(process.env.SHOPIFY_CLI_2_0_DIRECTORY)\n await validateRubyEnv()\n if (usingLocalCLI2) {\n await bundleInstallLocalShopifyCLI()\n } else {\n await createShopifyCLIWorkingDirectory()\n await createShopifyCLIGemfile()\n await bundleInstallShopifyCLI()\n }\n },\n },\n ],\n {renderer},\n )\n await list.run()\n}\n\nasync function validateRubyEnv() {\n await validateRuby()\n await validateRubyGems()\n await validateBundler()\n}\n\nasync function validateRuby() {\n let version\n try {\n const stdout = await system.captureOutput('ruby', ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Ruby environment not found',\n `Make sure you have Ruby installed on your system: ${\n content`${token.link('', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinRubyVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Ruby version ${content`${token.yellow(version!.raw)}`.value} is not supported`,\n `Make sure you have at least Ruby ${content`${token.yellow(MinRubyVersion)}`.value} installed on your system: ${\n content`${token.link('', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n}\n\nasync function validateRubyGems() {\n const stdout = await system.captureOutput('gem', ['-v'])\n const version = coerce(stdout)\n\n const isValid = version?.compare(MinRubyGemVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `RubyGems version ${content`${token.yellow(version!.raw)}`.value} is not supported`,\n `To update to the latest version of RubyGems, run ${\n content`${token.genericShellCommand('gem update --system')}`.value\n }`,\n )\n }\n}\n\nasync function validateBundler() {\n let version\n try {\n const stdout = await system.captureOutput('bundler', ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Bundler not found',\n `To install the latest version of Bundler, run ${\n content`${token.genericShellCommand('gem install bundler')}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinBundlerVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Bundler version ${content`${token.yellow(version!.raw)}`.value} is not supported`,\n `To update to the latest version of Bundler, run ${\n content`${token.genericShellCommand('gem install bundler')}`.value\n }`,\n )\n }\n}\n\nfunction createShopifyCLIWorkingDirectory() {\n return file.mkdir(shopifyCLIDirectory())\n}\n\nfunction createThemeCheckCLIWorkingDirectory() {\n return file.mkdir(themeCheckDirectory())\n}\n\nasync function createShopifyCLIGemfile() {\n const gemPath = join(shopifyCLIDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'shopify-cli', '${RubyCLIVersion}'`)\n}\n\nasync function createThemeCheckGemfile() {\n const gemPath = join(themeCheckDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'theme-check', '${ThemeCheckVersion}'`)\n}\n\nasync function bundleInstallLocalShopifyCLI() {\n await system.exec('bundle', ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallShopifyCLI() {\n await system.exec('bundle', ['config', 'set', '--local', 'path', shopifyCLIDirectory()], {cwd: shopifyCLIDirectory()})\n await system.exec('bundle', ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallThemeCheck() {\n await system.exec('bundle', ['config', 'set', '--local', 'path', themeCheckDirectory()], {cwd: themeCheckDirectory()})\n await system.exec('bundle', ['install'], {cwd: themeCheckDirectory()})\n}\n\nfunction shopifyCLIDirectory() {\n return (\n process.env.SHOPIFY_CLI_2_0_DIRECTORY ??\n join(constants.paths.directories.cache.vendor.path(), 'ruby-cli', RubyCLIVersion)\n )\n}\n\nfunction themeCheckDirectory() {\n return join(constants.paths.directories.cache.vendor.path(), 'theme-check', ThemeCheckVersion)\n}\n\nexport async function version(): Promise<string | undefined> {\n const parseOutput = (version: string) => version.match(/ruby (\\d+\\.\\d+\\.\\d+)/)?.[1]\n return system\n .captureOutput('ruby', ['-v'])\n .then(parseOutput)\n .catch(() => undefined)\n}\n"]}
|
package/dist/output.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ import { Fatal } from './error.js';
|
|
|
3
3
|
import { PackageManager } from './node/node-package-manager.js';
|
|
4
4
|
import { AbortSignal } from 'abort-controller';
|
|
5
5
|
import { Writable } from 'node:stream';
|
|
6
|
-
export
|
|
6
|
+
export { default as logUpdate } from 'log-update';
|
|
7
|
+
export declare function initiateLogging(options?: {
|
|
7
8
|
logDir?: string;
|
|
8
|
-
filename?: string;
|
|
9
9
|
}): void;
|
|
10
10
|
declare enum ContentTokenType {
|
|
11
11
|
Raw = 0,
|
|
@@ -25,6 +25,7 @@ declare enum ContentTokenType {
|
|
|
25
25
|
interface ContentMetadata {
|
|
26
26
|
link?: string;
|
|
27
27
|
}
|
|
28
|
+
export declare type Logger = (message: string) => void;
|
|
28
29
|
declare class ContentToken {
|
|
29
30
|
type: ContentTokenType;
|
|
30
31
|
value: Message;
|
|
@@ -68,40 +69,45 @@ export declare let collectedLogs: {
|
|
|
68
69
|
};
|
|
69
70
|
export declare const clearCollectedLogs: () => void;
|
|
70
71
|
/**
|
|
71
|
-
* Ouputs information to the user.
|
|
72
|
+
* Ouputs information to the user.
|
|
72
73
|
* Info messages don't get additional formatting.
|
|
73
74
|
* Note: Info messages are sent through the standard output.
|
|
74
75
|
* @param content {string} The content to be output to the user.
|
|
76
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
75
77
|
*/
|
|
76
|
-
export declare const info: (content: Message) => void;
|
|
78
|
+
export declare const info: (content: Message, logger?: Logger) => void;
|
|
77
79
|
/**
|
|
78
80
|
* Outputs a success message to the user.
|
|
79
|
-
* Success
|
|
81
|
+
* Success messages receive a special formatting to make them stand out in the console.
|
|
80
82
|
* Note: Success messages are sent through the standard output.
|
|
81
83
|
* @param content {string} The content to be output to the user.
|
|
84
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
82
85
|
*/
|
|
83
|
-
export declare const success: (content: Message) => void;
|
|
86
|
+
export declare const success: (content: Message, logger?: Logger) => void;
|
|
84
87
|
/**
|
|
85
88
|
* Outputs a completed message to the user.
|
|
86
89
|
* Completed message receive a special formatting to make them stand out in the console.
|
|
87
90
|
* Note: Completed messages are sent through the standard output.
|
|
88
91
|
* @param content {string} The content to be output to the user.
|
|
92
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
89
93
|
*/
|
|
90
|
-
export declare const completed: (content: Message) => void;
|
|
94
|
+
export declare const completed: (content: Message, logger?: Logger) => void;
|
|
91
95
|
/**
|
|
92
96
|
* Ouputs debug information to the user. By default these output is hidden unless the user calls the CLI with --verbose.
|
|
93
97
|
* Debug messages don't get additional formatting.
|
|
94
98
|
* Note: Debug messages are sent through the standard output.
|
|
95
99
|
* @param content {string} The content to be output to the user.
|
|
100
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
96
101
|
*/
|
|
97
|
-
export declare const debug: (content: Message) => void;
|
|
102
|
+
export declare const debug: (content: Message, logger?: Logger) => void;
|
|
98
103
|
/**
|
|
99
104
|
* Outputs a warning message to the user.
|
|
100
105
|
* Warning messages receive a special formatting to make them stand out in the console.
|
|
101
106
|
* Note: Warning messages are sent through the standard output.
|
|
102
107
|
* @param content {string} The content to be output to the user.
|
|
108
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
103
109
|
*/
|
|
104
|
-
export declare const warn: (content: Message) => void;
|
|
110
|
+
export declare const warn: (content: Message, logger?: Logger) => void;
|
|
105
111
|
/**
|
|
106
112
|
* Prints a new line in the terminal.
|
|
107
113
|
*/
|
|
@@ -138,7 +144,9 @@ export declare function logFileExists(): boolean;
|
|
|
138
144
|
export declare function logToFile(message: string, logLevel: string): void;
|
|
139
145
|
export declare function unstyled(message: string): string;
|
|
140
146
|
export declare function shouldDisplayColors(): boolean;
|
|
141
|
-
export declare function pageLogs(
|
|
147
|
+
export declare function pageLogs({ lastCommand }: {
|
|
148
|
+
lastCommand: boolean;
|
|
149
|
+
}): Promise<void>;
|
|
142
150
|
/**
|
|
143
151
|
*
|
|
144
152
|
* @param packageManager {PackageManager} The package manager that is being used.
|
|
@@ -146,4 +154,3 @@ export declare function pageLogs(): Promise<void>;
|
|
|
146
154
|
* @returns {te}
|
|
147
155
|
*/
|
|
148
156
|
export declare function getOutputUpdateCLIReminder(packageManager: PackageManager, version: string): string;
|
|
149
|
-
export {};
|
package/dist/output.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import { Bug } from './error.js';
|
|
2
|
+
import { Bug, cleanSingleStackTracePath } from './error.js';
|
|
3
3
|
import { isUnitTest, isVerbose } from './environment/local.js';
|
|
4
4
|
import constants from './constants.js';
|
|
5
|
-
import {
|
|
5
|
+
import { generateRandomUUID } from './id.js';
|
|
6
|
+
import { mkdirSync as fileMkdirSync, readSync as fileReadSync, sizeSync as fileSizeSync, writeSync as fileWriteSync, touchSync as fileTouchSync, } from './file.js';
|
|
6
7
|
import { join as pathJoin, relativize as relativizePath } from './path.js';
|
|
7
8
|
import { page } from './system.js';
|
|
8
9
|
import { colors } from './node/colors.js';
|
|
@@ -14,16 +15,25 @@ import { AbortController } from 'abort-controller';
|
|
|
14
15
|
import cjs from 'color-json';
|
|
15
16
|
import stripAnsi from 'strip-ansi';
|
|
16
17
|
import { Writable } from 'node:stream';
|
|
17
|
-
|
|
18
|
-
export
|
|
18
|
+
import { createWriteStream } from 'node:fs';
|
|
19
|
+
export { default as logUpdate } from 'log-update';
|
|
20
|
+
const logFileName = 'shopify.cli.log';
|
|
21
|
+
let logFileStream;
|
|
22
|
+
let commandUuid;
|
|
23
|
+
export function initiateLogging(options = {}) {
|
|
24
|
+
if (isUnitTest())
|
|
25
|
+
return;
|
|
26
|
+
const logDir = options.logDir || constants.paths.directories.cache.path();
|
|
27
|
+
commandUuid = generateRandomUUID();
|
|
19
28
|
fileMkdirSync(logDir);
|
|
20
|
-
logFile = pathJoin(logDir,
|
|
29
|
+
const logFile = pathJoin(logDir, logFileName);
|
|
21
30
|
fileTouchSync(logFile);
|
|
22
|
-
truncateLogs();
|
|
31
|
+
truncateLogs(logFile);
|
|
32
|
+
logFileStream = createWriteStream(logFile, { flags: 'a' });
|
|
23
33
|
}
|
|
24
34
|
// Shaves off the first 10,000 log lines (circa 1MB) if logs are over 5MB long.
|
|
25
35
|
// Rescues in case the file hasn't been created yet.
|
|
26
|
-
function truncateLogs() {
|
|
36
|
+
function truncateLogs(logFile) {
|
|
27
37
|
try {
|
|
28
38
|
if (fileSizeSync(logFile) > 5 * 1024 * 1024) {
|
|
29
39
|
const contents = fileReadSync(logFile);
|
|
@@ -259,61 +269,69 @@ export const clearCollectedLogs = () => {
|
|
|
259
269
|
collectedLogs = {};
|
|
260
270
|
};
|
|
261
271
|
/**
|
|
262
|
-
* Ouputs information to the user.
|
|
272
|
+
* Ouputs information to the user.
|
|
263
273
|
* Info messages don't get additional formatting.
|
|
264
274
|
* Note: Info messages are sent through the standard output.
|
|
265
275
|
* @param content {string} The content to be output to the user.
|
|
276
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
266
277
|
*/
|
|
267
|
-
export const info = (content) => {
|
|
278
|
+
export const info = (content, logger = consoleLog) => {
|
|
279
|
+
const message = stringifyMessage(content);
|
|
268
280
|
if (isUnitTest())
|
|
269
281
|
collectLog('info', content);
|
|
270
|
-
|
|
282
|
+
outputWhereAppropriate('info', logger, message);
|
|
271
283
|
};
|
|
272
284
|
/**
|
|
273
285
|
* Outputs a success message to the user.
|
|
274
|
-
* Success
|
|
286
|
+
* Success messages receive a special formatting to make them stand out in the console.
|
|
275
287
|
* Note: Success messages are sent through the standard output.
|
|
276
288
|
* @param content {string} The content to be output to the user.
|
|
289
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
277
290
|
*/
|
|
278
|
-
export const success = (content) => {
|
|
291
|
+
export const success = (content, logger = consoleLog) => {
|
|
279
292
|
const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`);
|
|
280
293
|
if (isUnitTest())
|
|
281
294
|
collectLog('success', content);
|
|
282
|
-
outputWhereAppropriate('info',
|
|
295
|
+
outputWhereAppropriate('info', logger, message);
|
|
283
296
|
};
|
|
284
297
|
/**
|
|
285
298
|
* Outputs a completed message to the user.
|
|
286
299
|
* Completed message receive a special formatting to make them stand out in the console.
|
|
287
300
|
* Note: Completed messages are sent through the standard output.
|
|
288
301
|
* @param content {string} The content to be output to the user.
|
|
302
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
289
303
|
*/
|
|
290
|
-
export const completed = (content) => {
|
|
304
|
+
export const completed = (content, logger = consoleLog) => {
|
|
291
305
|
const message = `${colors.green('✔')} ${stringifyMessage(content)}`;
|
|
292
306
|
if (isUnitTest())
|
|
293
307
|
collectLog('completed', content);
|
|
294
|
-
outputWhereAppropriate('info',
|
|
308
|
+
outputWhereAppropriate('info', logger, message);
|
|
295
309
|
};
|
|
296
310
|
/**
|
|
297
311
|
* Ouputs debug information to the user. By default these output is hidden unless the user calls the CLI with --verbose.
|
|
298
312
|
* Debug messages don't get additional formatting.
|
|
299
313
|
* Note: Debug messages are sent through the standard output.
|
|
300
314
|
* @param content {string} The content to be output to the user.
|
|
315
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
301
316
|
*/
|
|
302
|
-
export const debug = (content) => {
|
|
317
|
+
export const debug = (content, logger = consoleLog) => {
|
|
303
318
|
if (isUnitTest())
|
|
304
319
|
collectLog('debug', content);
|
|
305
|
-
message
|
|
320
|
+
const message = colors.gray(stringifyMessage(content));
|
|
321
|
+
outputWhereAppropriate('debug', logger, message);
|
|
306
322
|
};
|
|
307
323
|
/**
|
|
308
324
|
* Outputs a warning message to the user.
|
|
309
325
|
* Warning messages receive a special formatting to make them stand out in the console.
|
|
310
326
|
* Note: Warning messages are sent through the standard output.
|
|
311
327
|
* @param content {string} The content to be output to the user.
|
|
328
|
+
* @param logger {Function} The logging function to use to output to the user.
|
|
312
329
|
*/
|
|
313
|
-
export const warn = (content) => {
|
|
330
|
+
export const warn = (content, logger = consoleWarn) => {
|
|
314
331
|
if (isUnitTest())
|
|
315
332
|
collectLog('warn', content);
|
|
316
|
-
|
|
333
|
+
const message = colors.yellow(stringifyMessage(content));
|
|
334
|
+
outputWhereAppropriate('warn', logger, message);
|
|
317
335
|
};
|
|
318
336
|
/**
|
|
319
337
|
* Prints a new line in the terminal.
|
|
@@ -349,7 +367,11 @@ export const error = async (content) => {
|
|
|
349
367
|
outputString += `${padding}${line}\n`;
|
|
350
368
|
}
|
|
351
369
|
}
|
|
352
|
-
let stack =
|
|
370
|
+
let stack = new StackTracey(content);
|
|
371
|
+
stack.items.forEach((item) => {
|
|
372
|
+
item.file = cleanSingleStackTracePath(item.file);
|
|
373
|
+
});
|
|
374
|
+
stack = await stack.withSourcesAsync();
|
|
353
375
|
stack = stack
|
|
354
376
|
.filter((entry) => {
|
|
355
377
|
return !entry.file.includes('@oclif/core');
|
|
@@ -465,14 +487,14 @@ function consoleError(message) {
|
|
|
465
487
|
function consoleWarn(message) {
|
|
466
488
|
console.warn(withOrWithoutStyle(message));
|
|
467
489
|
}
|
|
468
|
-
function outputWhereAppropriate(logLevel,
|
|
490
|
+
function outputWhereAppropriate(logLevel, logger, message) {
|
|
469
491
|
if (shouldOutput(logLevel)) {
|
|
470
|
-
|
|
492
|
+
logger(message);
|
|
471
493
|
}
|
|
472
494
|
logToFile(message, logLevel.toUpperCase());
|
|
473
495
|
}
|
|
474
496
|
export function logFileExists() {
|
|
475
|
-
return Boolean(
|
|
497
|
+
return Boolean(logFileStream);
|
|
476
498
|
}
|
|
477
499
|
// DO NOT USE THIS FUNCTION DIRECTLY under normal circumstances.
|
|
478
500
|
// It is exported purely for use in cases where output is already being logged
|
|
@@ -482,7 +504,8 @@ export function logToFile(message, logLevel) {
|
|
|
482
504
|
if (!logFileExists())
|
|
483
505
|
return;
|
|
484
506
|
const timestamp = new Date().toISOString();
|
|
485
|
-
|
|
507
|
+
const logContents = `[${timestamp} ${commandUuid} ${logLevel}]: ${message}\n`;
|
|
508
|
+
logFileStream.write(logContents);
|
|
486
509
|
}
|
|
487
510
|
function withOrWithoutStyle(message) {
|
|
488
511
|
if (shouldDisplayColors()) {
|
|
@@ -498,8 +521,55 @@ export function unstyled(message) {
|
|
|
498
521
|
export function shouldDisplayColors() {
|
|
499
522
|
return Boolean(process.stdout.isTTY || process.env.FORCE_COLOR);
|
|
500
523
|
}
|
|
501
|
-
export async function pageLogs() {
|
|
502
|
-
|
|
524
|
+
export async function pageLogs({ lastCommand }) {
|
|
525
|
+
const logDir = constants.paths.directories.cache.path();
|
|
526
|
+
const logFile = pathJoin(logDir, logFileName);
|
|
527
|
+
// Ensure file exists in case they deleted it or something
|
|
528
|
+
fileTouchSync(logFile);
|
|
529
|
+
if (lastCommand) {
|
|
530
|
+
printLastCommand(logFile);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
await page(logFile);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
function printLastCommand(logFile) {
|
|
537
|
+
const contents = fileReadSync(logFile).split('\n');
|
|
538
|
+
const uuids = contents
|
|
539
|
+
.map(logfileLineUUID)
|
|
540
|
+
.filter((uuid) => uuid)
|
|
541
|
+
.reverse();
|
|
542
|
+
// 2nd unique UUID, because the currently running command will be the 1st
|
|
543
|
+
const relevantUuid = Array.from(new Set(uuids))[1];
|
|
544
|
+
if (relevantUuid) {
|
|
545
|
+
consoleLog(relevantLines(contents, relevantUuid).join('\n'));
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function relevantLines(contents, relevantUuid) {
|
|
549
|
+
// We run through the file line by line, keeping track of the most recently
|
|
550
|
+
// encountered UUID.
|
|
551
|
+
//
|
|
552
|
+
// If the current line has a UUID, it's a new logged unit and should be
|
|
553
|
+
// considered. Otherwise, the line is related to the most recent UUID.
|
|
554
|
+
let mostRecentUuid = '';
|
|
555
|
+
return contents.filter((line) => {
|
|
556
|
+
const currentUuid = logfileLineUUID(line) || mostRecentUuid;
|
|
557
|
+
mostRecentUuid = currentUuid;
|
|
558
|
+
return currentUuid === relevantUuid;
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
function logfileLineUUID(line) {
|
|
562
|
+
// Log lines look like:
|
|
563
|
+
//
|
|
564
|
+
// timestamp UUID contents
|
|
565
|
+
// ===========================================================================================
|
|
566
|
+
// [2022-07-20T08:51:40.296Z 5288e1da-a06a-4f96-b1a6-e34fcdd7b416 DEBUG]: Running command logs
|
|
567
|
+
// ===========================================================================================
|
|
568
|
+
//
|
|
569
|
+
// There may be subsequent lines if the contents section is multi-line.
|
|
570
|
+
//
|
|
571
|
+
const match = line.match(/^\[\S+ ([0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}) [A-Z]+\]/);
|
|
572
|
+
return match && match[1];
|
|
503
573
|
}
|
|
504
574
|
/**
|
|
505
575
|
*
|