@shopify/cli-kit 3.28.0 → 3.30.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 (106) hide show
  1. package/dist/api/admin.js +5 -11
  2. package/dist/api/admin.js.map +1 -1
  3. package/dist/api/common.d.ts +1 -1
  4. package/dist/api/common.js +7 -4
  5. package/dist/api/common.js.map +1 -1
  6. package/dist/api/graphql/find_org.js +2 -2
  7. package/dist/api/graphql/find_org.js.map +1 -1
  8. package/dist/api/identity.js +14 -4
  9. package/dist/api/identity.js.map +1 -1
  10. package/dist/api/partners.d.ts +0 -6
  11. package/dist/api/partners.js +0 -32
  12. package/dist/api/partners.js.map +1 -1
  13. package/dist/http/fetch.js +13 -0
  14. package/dist/http/fetch.js.map +1 -1
  15. package/dist/index.d.ts +0 -1
  16. package/dist/index.js +0 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/metadata.d.ts +2 -2
  19. package/dist/output.js +1 -3
  20. package/dist/output.js.map +1 -1
  21. package/dist/path.d.ts +4 -1
  22. package/dist/path.js +9 -1
  23. package/dist/path.js.map +1 -1
  24. package/dist/private/node/ui/components/Command.js.map +1 -1
  25. package/dist/private/node/ui/components/ConcurrentOutput.js +5 -1
  26. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  27. package/dist/{testing/fixtures/render-concurrent.d.ts → private/node/ui/components/ConcurrentOutput.test.d.ts} +0 -0
  28. package/dist/private/node/ui/components/ConcurrentOutput.test.js +53 -0
  29. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -0
  30. package/dist/private/node/ui/components/FullScreen.js +2 -2
  31. package/dist/private/node/ui/components/FullScreen.js.map +1 -1
  32. package/dist/private/node/ui/components/Link.js.map +1 -1
  33. package/dist/private/node/ui/components/Prompt.d.ts +10 -0
  34. package/dist/private/node/ui/components/Prompt.js +23 -0
  35. package/dist/private/node/ui/components/Prompt.js.map +1 -0
  36. package/dist/private/node/ui/components/Prompt.test.d.ts +1 -0
  37. package/dist/private/node/ui/components/Prompt.test.js +71 -0
  38. package/dist/private/node/ui/components/Prompt.test.js.map +1 -0
  39. package/dist/private/node/ui/components/SelectInput.d.ts +12 -0
  40. package/dist/private/node/ui/components/SelectInput.js +93 -0
  41. package/dist/private/node/ui/components/SelectInput.js.map +1 -0
  42. package/dist/private/node/ui/components/SelectInput.test.d.ts +1 -0
  43. package/dist/private/node/ui/components/SelectInput.test.js +200 -0
  44. package/dist/private/node/ui/components/SelectInput.test.js.map +1 -0
  45. package/dist/private/node/ui/components/Table.d.ts +8 -0
  46. package/dist/private/node/ui/components/Table.js +17 -0
  47. package/dist/private/node/ui/components/Table.js.map +1 -0
  48. package/dist/private/node/ui/components/TextAnimation.js +1 -1
  49. package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
  50. package/dist/private/node/ui.d.ts +2 -0
  51. package/dist/private/node/ui.js +14 -0
  52. package/dist/private/node/ui.js.map +1 -1
  53. package/dist/public/common/array.d.ts +1 -1
  54. package/dist/public/common/array.js.map +1 -1
  55. package/dist/public/node/base-command.d.ts +2 -2
  56. package/dist/public/node/base-command.js +2 -4
  57. package/dist/public/node/base-command.js.map +1 -1
  58. package/dist/public/node/checksum.d.ts +1 -1
  59. package/dist/public/node/checksum.js +1 -1
  60. package/dist/public/node/checksum.js.map +1 -1
  61. package/dist/public/node/cli.js.map +1 -1
  62. package/dist/public/node/dot-env.js.map +1 -1
  63. package/dist/public/node/error-handler.d.ts +5 -1
  64. package/dist/public/node/error-handler.js.map +1 -1
  65. package/dist/public/node/framework.js.map +1 -1
  66. package/dist/public/node/hooks/prerun.js.map +1 -1
  67. package/dist/public/node/node-package-manager.d.ts +1 -0
  68. package/dist/public/node/node-package-manager.js.map +1 -1
  69. package/dist/public/node/ruby.js +2 -2
  70. package/dist/public/node/ruby.js.map +1 -1
  71. package/dist/public/node/ui.d.ts +42 -0
  72. package/dist/public/node/ui.js +60 -6
  73. package/dist/public/node/ui.js.map +1 -1
  74. package/dist/session/exchange.js +4 -2
  75. package/dist/session/exchange.js.map +1 -1
  76. package/dist/session/validate.js +3 -13
  77. package/dist/session/validate.js.map +1 -1
  78. package/dist/session.d.ts +1 -1
  79. package/dist/session.js +3 -1
  80. package/dist/session.js.map +1 -1
  81. package/dist/string.d.ts +1 -0
  82. package/dist/string.js +3 -0
  83. package/dist/string.js.map +1 -1
  84. package/dist/system.d.ts +2 -2
  85. package/dist/system.js +17 -2
  86. package/dist/system.js.map +1 -1
  87. package/dist/testing/ui.d.ts +4 -8
  88. package/dist/testing/ui.js +17 -17
  89. package/dist/testing/ui.js.map +1 -1
  90. package/dist/tsconfig.tsbuildinfo +1 -1
  91. package/dist/ui/executor.js +7 -5
  92. package/dist/ui/executor.js.map +1 -1
  93. package/dist/ui/inquirer/autocomplete.js +13 -4
  94. package/dist/ui/inquirer/autocomplete.js.map +1 -1
  95. package/dist/ui.d.ts +6 -0
  96. package/dist/ui.js +0 -11
  97. package/dist/ui.js.map +1 -1
  98. package/package.json +35 -6
  99. package/dist/log.d.ts +0 -30
  100. package/dist/log.js +0 -169
  101. package/dist/log.js.map +0 -1
  102. package/dist/private/node/ui/error.d.ts +0 -2
  103. package/dist/private/node/ui/error.js +0 -8
  104. package/dist/private/node/ui/error.js.map +0 -1
  105. package/dist/testing/fixtures/render-concurrent.js +0 -26
  106. package/dist/testing/fixtures/render-concurrent.js.map +0 -1
@@ -27,16 +27,18 @@ export function mapper(question) {
27
27
  return {
28
28
  ...question,
29
29
  type: 'custom-select',
30
- source: getAutompleteFilterType(),
30
+ source: getAutocompleteFilterType(),
31
31
  choices: question.choices ? groupAndMapChoices(question.choices) : undefined,
32
32
  };
33
- case 'autocomplete':
33
+ case 'autocomplete': {
34
34
  inquirer.registerPrompt('autocomplete', CustomAutocomplete);
35
+ const filterType = getAutocompleteFilterType();
35
36
  return {
36
37
  ...question,
37
38
  type: 'autocomplete',
38
- source: getAutompleteFilterType(),
39
+ source: question.source ? question.source(filterType) : filterType,
39
40
  };
41
+ }
40
42
  }
41
43
  }
42
44
  function fuzzyFilter(answers, input = '') {
@@ -52,10 +54,10 @@ function fuzzyFilter(answers, input = '') {
52
54
  }
53
55
  function containsFilter(answers, input = '') {
54
56
  return new Promise((resolve) => {
55
- resolve(Object.values(answers).filter((answer) => !answer.name || answer.name.includes(input)));
57
+ resolve(Object.values(answers).filter((answer) => !answer.name || answer.name.toLowerCase().includes(input.toLowerCase())));
56
58
  });
57
59
  }
58
- function getAutompleteFilterType() {
60
+ function getAutocompleteFilterType() {
59
61
  return process.env.SHOPIFY_USE_AUTOCOMPLETE_FILTER === 'fuzzy' ? fuzzyFilter : containsFilter;
60
62
  }
61
63
  export function groupAndMapChoices(choices) {
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/ui/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import {CustomInput} from './inquirer/input.js'\nimport {CustomAutocomplete} from './inquirer/autocomplete.js'\nimport {CustomSelect} from './inquirer/select.js'\nimport {CustomPassword} from './inquirer/password.js'\nimport {Question, QuestionChoiceType} from '../ui.js'\nimport inquirer, {Answers, QuestionCollection} from 'inquirer'\nimport fuzzy from 'fuzzy'\n\nexport async function run<\n TName extends string & keyof TAnswers,\n TAnswers extends {[key in TName]: string} = {[key in TName]: string},\n>(question: unknown): Promise<TAnswers> {\n const questionName = (question as Question).name\n return (await inquirer.prompt(question as QuestionCollection<Answers>, {...(question as Question).choices}))[\n questionName\n ]\n}\n\nexport function mapper(question: Question): unknown {\n switch (question.type) {\n case 'input':\n inquirer.registerPrompt('custom-input', CustomInput)\n return {\n ...question,\n type: 'custom-input',\n }\n case 'password':\n inquirer.registerPrompt('custom-password', CustomPassword)\n return {\n ...question,\n type: 'custom-password',\n }\n case 'select':\n inquirer.registerPrompt('custom-select', CustomSelect)\n return {\n ...question,\n type: 'custom-select',\n source: getAutompleteFilterType(),\n choices: question.choices ? groupAndMapChoices(question.choices) : undefined,\n }\n case 'autocomplete':\n inquirer.registerPrompt('autocomplete', CustomAutocomplete)\n return {\n ...question,\n type: 'autocomplete',\n source: getAutompleteFilterType(),\n }\n }\n}\n\nfunction fuzzyFilter(answers: {name: string; value: string}[], input = '') {\n return new Promise((resolve) => {\n resolve(\n fuzzy\n .filter(input, Object.values(answers), {\n extract(el: {name: string; value: string}) {\n return el.name\n },\n })\n .map((el) => el.original),\n )\n })\n}\n\nfunction containsFilter(answers: {name: string; value: string}[], input = '') {\n return new Promise((resolve) => {\n resolve(Object.values(answers).filter((answer) => !answer.name || answer.name.includes(input)))\n })\n}\n\nfunction getAutompleteFilterType() {\n return process.env.SHOPIFY_USE_AUTOCOMPLETE_FILTER === 'fuzzy' ? fuzzyFilter : containsFilter\n}\n\nexport function groupAndMapChoices(choices: QuestionChoiceType[]) {\n const initialGroups: {name?: string; order: number; choices: {name: string; value: string; order?: number}[]}[] = []\n\n // Switched from choices with group information to groups with a list of choices\n const groups = choices.reduce((finalChoices, choice) => {\n const currentGroup = choice.group ?? {name: 'Other', order: Number.MAX_SAFE_INTEGER}\n const existingGroup = finalChoices.find((group) => group.name === currentGroup.name)\n if (existingGroup) {\n existingGroup.choices.push(choice)\n } else {\n finalChoices.push({...currentGroup, choices: [choice]})\n }\n return finalChoices\n }, initialGroups)\n\n const sortedGroups = groups.sort((g1, g2) => g1.order - g2.order)\n const grouped = sortedGroups.length > 1 || sortedGroups[0]!.order !== Number.MAX_SAFE_INTEGER\n\n // Mapped the group with a list of extensions to a list of inquirer choices including group separators\n return sortedGroups.flatMap((group) => {\n const finalChoices: ({type: string; line: string} | {name: string; value: string})[] = []\n if (grouped && group.name) {\n finalChoices.push({type: 'separator', line: ''})\n finalChoices.push({type: 'separator', line: group.name})\n }\n finalChoices.push(...group.choices)\n return finalChoices\n })\n}\n"]}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/ui/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import {CustomInput} from './inquirer/input.js'\nimport {CustomAutocomplete} from './inquirer/autocomplete.js'\nimport {CustomSelect} from './inquirer/select.js'\nimport {CustomPassword} from './inquirer/password.js'\nimport {PromptAnswer, Question, QuestionChoiceType} from '../ui.js'\nimport inquirer, {Answers, QuestionCollection} from 'inquirer'\nimport fuzzy from 'fuzzy'\n\nexport async function run<\n TName extends string & keyof TAnswers,\n TAnswers extends {[key in TName]: string} = {[key in TName]: string},\n>(question: unknown): Promise<TAnswers> {\n const questionName = (question as Question).name\n return (await inquirer.prompt(question as QuestionCollection<Answers>, {...(question as Question).choices}))[\n questionName\n ]\n}\n\nexport function mapper(question: Question): unknown {\n switch (question.type) {\n case 'input':\n inquirer.registerPrompt('custom-input', CustomInput)\n return {\n ...question,\n type: 'custom-input',\n }\n case 'password':\n inquirer.registerPrompt('custom-password', CustomPassword)\n return {\n ...question,\n type: 'custom-password',\n }\n case 'select':\n inquirer.registerPrompt('custom-select', CustomSelect)\n return {\n ...question,\n type: 'custom-select',\n source: getAutocompleteFilterType(),\n choices: question.choices ? groupAndMapChoices(question.choices) : undefined,\n }\n case 'autocomplete': {\n inquirer.registerPrompt('autocomplete', CustomAutocomplete)\n const filterType = getAutocompleteFilterType()\n return {\n ...question,\n type: 'autocomplete',\n source: question.source ? question.source(filterType) : filterType,\n }\n }\n }\n}\n\nfunction fuzzyFilter(answers: {name: string; value: string}[], input = ''): Promise<PromptAnswer[]> {\n return new Promise((resolve) => {\n resolve(\n fuzzy\n .filter(input, Object.values(answers), {\n extract(el: {name: string; value: string}) {\n return el.name\n },\n })\n .map((el) => el.original),\n )\n })\n}\n\nfunction containsFilter(answers: {name: string; value: string}[], input = ''): Promise<PromptAnswer[]> {\n return new Promise((resolve) => {\n resolve(\n Object.values(answers).filter(\n (answer) => !answer.name || answer.name.toLowerCase().includes(input.toLowerCase()),\n ),\n )\n })\n}\n\nfunction getAutocompleteFilterType() {\n return process.env.SHOPIFY_USE_AUTOCOMPLETE_FILTER === 'fuzzy' ? fuzzyFilter : containsFilter\n}\n\nexport function groupAndMapChoices(choices: QuestionChoiceType[]) {\n const initialGroups: {name?: string; order: number; choices: {name: string; value: string; order?: number}[]}[] = []\n\n // Switched from choices with group information to groups with a list of choices\n const groups = choices.reduce((finalChoices, choice) => {\n const currentGroup = choice.group ?? {name: 'Other', order: Number.MAX_SAFE_INTEGER}\n const existingGroup = finalChoices.find((group) => group.name === currentGroup.name)\n if (existingGroup) {\n existingGroup.choices.push(choice)\n } else {\n finalChoices.push({...currentGroup, choices: [choice]})\n }\n return finalChoices\n }, initialGroups)\n\n const sortedGroups = groups.sort((g1, g2) => g1.order - g2.order)\n const grouped = sortedGroups.length > 1 || sortedGroups[0]!.order !== Number.MAX_SAFE_INTEGER\n\n // Mapped the group with a list of extensions to a list of inquirer choices including group separators\n return sortedGroups.flatMap((group) => {\n const finalChoices: ({type: string; line: string} | {name: string; value: string})[] = []\n if (grouped && group.name) {\n finalChoices.push({type: 'separator', line: ''})\n finalChoices.push({type: 'separator', line: group.name})\n }\n finalChoices.push(...group.choices)\n return finalChoices\n })\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import colors from '../../public/node/colors.js';
2
+ import { escapeRegExp } from '../../string.js';
2
3
  import AutocompletePrompt from 'inquirer-autocomplete-prompt';
3
4
  import Paginator from 'inquirer/lib/utils/paginator.js';
4
5
  export class CustomAutocomplete extends AutocompletePrompt {
@@ -13,7 +14,7 @@ export class CustomAutocomplete extends AutocompletePrompt {
13
14
  let content = this.getQuestion();
14
15
  let bottomContent = '';
15
16
  if (this.status !== 'answered') {
16
- content += colors.gray('… ');
17
+ content += colors.gray(this.isAutocomplete && this.firstRender ? 'Type to search… ' : '… ');
17
18
  }
18
19
  if (this.status === 'answered') {
19
20
  content += `${colors.dim('·')} ${colors.magenta(this.shortAnswer || this.answerName || this.answer)}`;
@@ -86,10 +87,18 @@ function listRender(choices, pointer, searchToken) {
86
87
  line = colors.magenta(line);
87
88
  }
88
89
  if (searchToken) {
90
+ const regexified = escapeRegExp(searchToken);
89
91
  line = line
90
- .split(searchToken)
91
- .map((token) => (isSelected ? colors.magenta(token) : token))
92
- .join(colors.magenta.dim(searchToken));
92
+ .split(new RegExp(`(${regexified})`, 'ig'))
93
+ .map((token) => {
94
+ if (token.match(new RegExp(regexified, 'ig'))) {
95
+ return colors.magenta.dim(token);
96
+ }
97
+ else {
98
+ return isSelected ? colors.magenta(token) : token;
99
+ }
100
+ })
101
+ .join('');
93
102
  }
94
103
  else if (isSelected) {
95
104
  line = colors.magenta(line);
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../../../src/ui/inquirer/autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import colors from '../../public/node/colors.js'\nimport AutocompletePrompt from 'inquirer-autocomplete-prompt'\nimport DistinctChoice from 'inquirer/lib/objects/choices'\nimport inquirer from 'inquirer'\n\nimport Paginator from 'inquirer/lib/utils/paginator.js'\nimport {Interface} from 'readline'\n\nexport class CustomAutocomplete extends AutocompletePrompt {\n protected isAutocomplete: boolean\n\n constructor(questions: inquirer.Question<inquirer.Answers>, rl: Interface, answers: inquirer.Answers) {\n super(questions, rl, answers)\n this.isAutocomplete = true\n this.paginator = new Paginator(this.screen, {\n isInfinite: false,\n })\n }\n\n protected render(error?: string) {\n let content = this.getQuestion()\n let bottomContent = ''\n\n if (this.status !== 'answered') {\n content += colors.gray('… ')\n }\n\n if (this.status === 'answered') {\n content += `${colors.dim('·')} ${colors.magenta(this.shortAnswer || this.answerName || this.answer)}`\n process.stdout.write('\\u001b[?25h')\n } else if (this.searching) {\n content += this.rl.line\n bottomContent += ` ${colors.magenta.dim('Searching...')}`\n } else if (this.nbChoices) {\n const choicesStr = listRender(this.currentChoices, this.selected, this.isAutocomplete ? this.rl.line : undefined)\n content += this.isAutocomplete ? this.rl.line : ''\n const indexPosition = this.selected\n let realIndexPosition = 0\n this.currentChoices.choices.every((choice, index: number) => {\n if (index > indexPosition) {\n return false\n }\n if (choice.type === 'separator') {\n return true\n }\n const name = choice.name\n realIndexPosition += name ? name.split('\\n').length : 0\n return true\n })\n bottomContent += this.paginator.paginate(choicesStr, realIndexPosition, this.isAutocomplete ? 10 : 500)\n } else {\n content += this.rl.line\n bottomContent += ` ${colors.magenta('No matching choices')}`\n }\n\n if (error) {\n bottomContent += `\\n${colors.magenta('>> ')}${error}`\n }\n\n this.firstRender = false\n\n this.screen.render(content, bottomContent)\n }\n\n protected getQuestion(): string {\n return `${this.prefix()} ${colors.bold(this.opt.message)}${this.opt.suffix}${colors.reset(' ')}`\n }\n\n protected prefix(): string {\n const color = colors.magenta.bold\n return this.status === 'answered' ? color('✔') : color('?')\n }\n}\n\nfunction listRender(choices: DistinctChoice, pointer: number, searchToken?: string): string {\n let output = ''\n let separatorOffset = 0\n\n choices.forEach((choice, i: number) => {\n if (choice.type === 'separator') {\n separatorOffset++\n if (choice.line.includes('──────────────')) {\n output += `\\n`\n } else {\n output += ` ${colors.dim.underline(choice)}\\n`\n }\n return\n }\n\n if (choice.disabled) {\n separatorOffset++\n output += ` - ${choice.name}`\n output += ` (${typeof choice.disabled === 'string' ? choice.disabled : 'Disabled'})`\n output += '\\n'\n return\n }\n\n const isSelected = i - separatorOffset === pointer\n let line = (isSelected ? '> ' : ' ') + choice.name\n\n if (isSelected) {\n line = colors.magenta(line)\n }\n\n if (searchToken) {\n line = line\n .split(searchToken)\n .map((token) => (isSelected ? colors.magenta(token) : token))\n .join(colors.magenta.dim(searchToken))\n } else if (isSelected) {\n line = colors.magenta(line)\n }\n\n output += `${line} \\n`\n })\n\n return output.replace(/\\n$/, '')\n}\n"]}
1
+ {"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../../../src/ui/inquirer/autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import colors from '../../public/node/colors.js'\nimport {escapeRegExp} from '../../string.js'\nimport AutocompletePrompt from 'inquirer-autocomplete-prompt'\nimport DistinctChoice from 'inquirer/lib/objects/choices'\nimport inquirer from 'inquirer'\n\nimport Paginator from 'inquirer/lib/utils/paginator.js'\nimport {Interface} from 'readline'\n\nexport class CustomAutocomplete extends AutocompletePrompt {\n protected isAutocomplete: boolean\n\n constructor(questions: inquirer.Question<inquirer.Answers>, rl: Interface, answers: inquirer.Answers) {\n super(questions, rl, answers)\n this.isAutocomplete = true\n this.paginator = new Paginator(this.screen, {\n isInfinite: false,\n })\n }\n\n protected render(error?: string) {\n let content = this.getQuestion()\n let bottomContent = ''\n\n if (this.status !== 'answered') {\n content += colors.gray(this.isAutocomplete && this.firstRender ? 'Type to search… ' : '… ')\n }\n\n if (this.status === 'answered') {\n content += `${colors.dim('·')} ${colors.magenta(this.shortAnswer || this.answerName || this.answer)}`\n process.stdout.write('\\u001b[?25h')\n } else if (this.searching) {\n content += this.rl.line\n bottomContent += ` ${colors.magenta.dim('Searching...')}`\n } else if (this.nbChoices) {\n const choicesStr = listRender(this.currentChoices, this.selected, this.isAutocomplete ? this.rl.line : undefined)\n content += this.isAutocomplete ? this.rl.line : ''\n const indexPosition = this.selected\n let realIndexPosition = 0\n this.currentChoices.choices.every((choice, index: number) => {\n if (index > indexPosition) {\n return false\n }\n if (choice.type === 'separator') {\n return true\n }\n const name = choice.name\n realIndexPosition += name ? name.split('\\n').length : 0\n return true\n })\n bottomContent += this.paginator.paginate(choicesStr, realIndexPosition, this.isAutocomplete ? 10 : 500)\n } else {\n content += this.rl.line\n bottomContent += ` ${colors.magenta('No matching choices')}`\n }\n\n if (error) {\n bottomContent += `\\n${colors.magenta('>> ')}${error}`\n }\n\n this.firstRender = false\n\n this.screen.render(content, bottomContent)\n }\n\n protected getQuestion(): string {\n return `${this.prefix()} ${colors.bold(this.opt.message)}${this.opt.suffix}${colors.reset(' ')}`\n }\n\n protected prefix(): string {\n const color = colors.magenta.bold\n return this.status === 'answered' ? color('✔') : color('?')\n }\n}\n\nfunction listRender(choices: DistinctChoice, pointer: number, searchToken?: string): string {\n let output = ''\n let separatorOffset = 0\n\n choices.forEach((choice, i: number) => {\n if (choice.type === 'separator') {\n separatorOffset++\n if (choice.line.includes('──────────────')) {\n output += `\\n`\n } else {\n output += ` ${colors.dim.underline(choice)}\\n`\n }\n return\n }\n\n if (choice.disabled) {\n separatorOffset++\n output += ` - ${choice.name}`\n output += ` (${typeof choice.disabled === 'string' ? choice.disabled : 'Disabled'})`\n output += '\\n'\n return\n }\n\n const isSelected = i - separatorOffset === pointer\n let line = (isSelected ? '> ' : ' ') + choice.name\n\n if (isSelected) {\n line = colors.magenta(line)\n }\n\n if (searchToken) {\n const regexified = escapeRegExp(searchToken)\n line = line\n .split(new RegExp(`(${regexified})`, 'ig'))\n .map((token) => {\n if (token.match(new RegExp(regexified, 'ig'))) {\n return colors.magenta.dim(token)\n } else {\n return isSelected ? colors.magenta(token) : token\n }\n })\n .join('')\n } else if (isSelected) {\n line = colors.magenta(line)\n }\n\n output += `${line} \\n`\n })\n\n return output.replace(/\\n$/, '')\n}\n"]}
package/dist/ui.d.ts CHANGED
@@ -2,6 +2,11 @@ import { Listr as OriginalListr, ListrTask, ListrBaseClassOptions } from 'listr2
2
2
  export declare function newListr(tasks: ListrTask[], options?: object | ListrBaseClassOptions): OriginalListr<any, any, "verbose">;
3
3
  export declare type ListrTasks = ConstructorParameters<typeof OriginalListr>[0];
4
4
  export type { ListrTaskWrapper, ListrDefaultRenderer, ListrTask } from 'listr2';
5
+ export interface PromptAnswer {
6
+ name: string;
7
+ value: string;
8
+ }
9
+ export declare type FilterFunction = (answers: PromptAnswer[], input: string) => Promise<PromptAnswer[]>;
5
10
  interface BaseQuestion<TName extends string> {
6
11
  name: TName;
7
12
  message: string;
@@ -10,6 +15,7 @@ interface BaseQuestion<TName extends string> {
10
15
  default?: string;
11
16
  result?: (value: string) => string | boolean;
12
17
  choices?: QuestionChoiceType[];
18
+ source?: (filter: FilterFunction) => FilterFunction;
13
19
  }
14
20
  declare type TextQuestion<TName extends string> = BaseQuestion<TName> & {
15
21
  type: 'input';
package/dist/ui.js CHANGED
@@ -5,18 +5,12 @@ import colors from './public/node/colors.js';
5
5
  import { relative } from './path.js';
6
6
  import { isTerminalInteractive } from './environment/local.js';
7
7
  import { mapper as mapperUI, run as executorUI } from './ui/executor.js';
8
- import { logToFile } from './log.js';
9
8
  import { Listr as OriginalListr, ListrTaskState } from 'listr2';
10
9
  import findProcess from 'find-process';
11
10
  export function newListr(tasks, options) {
12
11
  const listr = new OriginalListr(tasks, options);
13
12
  listr.tasks.forEach((task) => {
14
13
  const loggedSubtaskTitles = [];
15
- task.subscribe((event) => {
16
- if (event.type === 'TITLE' && typeof event.data === 'string') {
17
- logToFile(event.data, 'INFO');
18
- }
19
- });
20
14
  task.renderHook$.subscribe(() => {
21
15
  if (task.hasSubtasks()) {
22
16
  const activeSubtasks = task.subtasks.filter((subtask) => {
@@ -25,7 +19,6 @@ export function newListr(tasks, options) {
25
19
  activeSubtasks.forEach((subtask) => {
26
20
  if (subtask.title && !loggedSubtaskTitles.includes(subtask.title)) {
27
21
  loggedSubtaskTitles.push(subtask.title);
28
- logToFile(subtask.title, 'INFO');
29
22
  }
30
23
  });
31
24
  }
@@ -72,13 +65,9 @@ ${token.json(questions)}
72
65
  }
73
66
  // eslint-disable-next-line no-await-in-loop
74
67
  value[question.name] = await executorUI(question);
75
- logPromptResults(question.message, value[question.name]);
76
68
  }
77
69
  return value;
78
70
  };
79
- function logPromptResults(questionName, answer) {
80
- logToFile([questionName, answer].join(' '), 'INFO');
81
- }
82
71
  export async function nonEmptyDirectoryPrompt(directory) {
83
72
  if (await exists(directory)) {
84
73
  const options = [
package/dist/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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","sourcesContent":["import {CancelExecution, Abort, AbortSilent} from './error.js'\nimport {remove, exists} from './file.js'\nimport {info, completed, content, token, logUpdate, Message, Logger, stringifyMessage, debug} from './output.js'\nimport colors from './public/node/colors.js'\nimport {relative} from './path.js'\nimport {isTerminalInteractive} from './environment/local.js'\nimport {mapper as mapperUI, run as executorUI} from './ui/executor.js'\nimport {logToFile} from './log.js'\nimport {Listr as OriginalListr, ListrTask, ListrEvent, ListrTaskState, ListrBaseClassOptions} from 'listr2'\nimport findProcess from 'find-process'\n\nexport function newListr(tasks: ListrTask[], options?: object | ListrBaseClassOptions) {\n const listr = new OriginalListr(tasks, options)\n listr.tasks.forEach((task) => {\n const loggedSubtaskTitles: string[] = []\n task.subscribe((event: ListrEvent) => {\n if (event.type === 'TITLE' && typeof event.data === 'string') {\n logToFile(event.data, 'INFO')\n }\n })\n task.renderHook$.subscribe(() => {\n if (task.hasSubtasks()) {\n const activeSubtasks = task.subtasks.filter((subtask) => {\n return [ListrTaskState.PENDING, ListrTaskState.COMPLETED].includes(subtask.state as ListrTaskState)\n })\n activeSubtasks.forEach((subtask) => {\n if (subtask.title && !loggedSubtaskTitles.includes(subtask.title)) {\n loggedSubtaskTitles.push(subtask.title)\n logToFile(subtask.title, 'INFO')\n }\n })\n }\n })\n })\n return listr\n}\n\nexport type ListrTasks = ConstructorParameters<typeof OriginalListr>[0]\nexport type {ListrTaskWrapper, ListrDefaultRenderer, ListrTask} from 'listr2'\ninterface BaseQuestion<TName extends string> {\n name: TName\n message: string\n preface?: string\n validate?: (value: string) => string | true\n default?: string\n result?: (value: string) => string | boolean\n choices?: QuestionChoiceType[]\n}\n\ntype TextQuestion<TName extends string> = BaseQuestion<TName> & {\n type: 'input'\n // a default is required, otherwise we'd show a prompt like 'undefined'\n default: string\n}\n\ntype PasswordQuestion<TName extends string> = BaseQuestion<TName> & {\n type: 'password'\n}\n\ntype SelectableQuestion<TName extends string> = BaseQuestion<TName> & {\n type: 'select' | 'autocomplete'\n choices: QuestionChoiceType[]\n}\n\nexport type Question<TName extends string = string> =\n | TextQuestion<TName>\n | SelectableQuestion<TName>\n | PasswordQuestion<TName>\n\nexport interface QuestionChoiceType {\n name: string\n value: string\n group?: {name: string; order: number}\n}\n\nconst started = (content: Message, logger: Logger) => {\n const message = `${colors.yellow('❯')} ${stringifyMessage(content)}`\n info(message, logger)\n}\n\nconst failed = (content: Message, logger: Logger) => {\n const message = `${colors.red('✖')} ${stringifyMessage(content)}`\n info(message, logger)\n}\n\n/**\n * Performs a task with the title kept up to date and stdout available to the\n * task while it runs (there is no re-writing stdout while the task runs).\n */\nexport interface TaskOptions {\n title: string\n task: () => Promise<void | {successMessage: string}>\n}\nexport const task = async ({title, task}: TaskOptions) => {\n let success\n started(title, logUpdate)\n try {\n const result = await task()\n success = result?.successMessage || title\n } catch (err) {\n failed(title, logUpdate)\n logUpdate.done()\n throw err\n }\n completed(success, logUpdate)\n logUpdate.done()\n}\nexport const prompt = async <\n TName extends string & keyof TAnswers,\n TAnswers extends {[key in TName]: string} = {[key in TName]: string},\n>(\n questions: ReadonlyArray<Question<TName>>,\n): Promise<TAnswers> => {\n if (!isTerminalInteractive() && questions.length !== 0) {\n throw new Abort(content`\nThe CLI prompted in a non-interactive terminal with the following questions:\n${token.json(questions)}\n `)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const mappedQuestions: any[] = questions.map(mapperUI)\n const value = {} as TAnswers\n for (const question of mappedQuestions) {\n if (question.preface) {\n info(question.preface)\n }\n\n // eslint-disable-next-line no-await-in-loop\n value[question.name as TName] = await executorUI(question)\n\n logPromptResults(question.message, value[question.name as TName])\n }\n return value\n}\n\nfunction logPromptResults(questionName: string, answer: string) {\n logToFile([questionName, answer].join(' '), 'INFO')\n}\n\nexport async function nonEmptyDirectoryPrompt(directory: string) {\n if (await exists(directory)) {\n const options = [\n {name: 'No, don’t delete the files', value: 'abort'},\n {name: 'Yes, delete the files', value: 'overwrite'},\n ]\n\n const relativeDirectory = relative(process.cwd(), directory)\n\n const questions: Question<'value'> = {\n type: 'select',\n name: 'value',\n message: `${relativeDirectory} is not an empty directory. Do you want to delete the existing files and continue?`,\n choices: options,\n }\n\n const choice = await prompt([questions])\n\n if (choice.value === 'abort') {\n throw new CancelExecution()\n }\n\n await remove(directory)\n }\n}\n\nexport async function terminateBlockingPortProcessPrompt(port: number, stepDescription?: string): Promise<boolean> {\n const stepDescriptionContent = stepDescription ?? 'current step'\n\n const processInfo = await findProcess('port', port)\n const formattedProcessName =\n processInfo && processInfo.length > 0 && processInfo[0]?.name\n ? ` ${content`${token.italic(`(${processInfo[0].name})`)}`.value}`\n : ''\n\n const options = [\n {name: 'Yes, terminate process in order to log in now', value: 'finish'},\n {name: `No, cancel command and try later`, value: 'cancel'},\n ]\n\n const choice = await prompt([\n {\n type: 'select',\n name: 'value',\n message: `${stepDescriptionContent} requires a port ${port} that's unavailable because it's running another process${formattedProcessName}. Terminate that process? `,\n choices: options,\n },\n ])\n return choice.value === 'finish'\n}\n\nexport const keypress = async () => {\n return new Promise((resolve, reject) => {\n const handler = (buffer: Buffer) => {\n process.stdin.setRawMode(false)\n process.stdin.pause()\n\n const bytes = Array.from(buffer)\n\n if (bytes.length && bytes[0] === 3) {\n debug('Canceled keypress, User pressed CTRL+C')\n reject(new AbortSilent())\n }\n process.nextTick(resolve)\n }\n\n process.stdin.resume()\n process.stdin.setRawMode(true)\n process.stdin.once('data', handler)\n })\n}\n"]}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,KAAK,EAAE,WAAW,EAAC,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM,WAAW,CAAA;AACxC,OAAO,EAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAmB,gBAAgB,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAChH,OAAO,MAAM,MAAM,yBAAyB,CAAA;AAC5C,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAClC,OAAO,EAAC,qBAAqB,EAAC,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAC,MAAM,IAAI,QAAQ,EAAE,GAAG,IAAI,UAAU,EAAC,MAAM,kBAAkB,CAAA;AACtE,OAAO,EAAC,KAAK,IAAI,aAAa,EAAa,cAAc,EAAwB,MAAM,QAAQ,CAAA;AAC/F,OAAO,WAAW,MAAM,cAAc,CAAA;AAEtC,MAAM,UAAU,QAAQ,CAAC,KAAkB,EAAE,OAAwC;IACnF,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC/C,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3B,MAAM,mBAAmB,GAAa,EAAE,CAAA;QACxC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE;YAC9B,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;gBACtB,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;oBACtD,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAuB,CAAC,CAAA;gBACrG,CAAC,CAAC,CAAA;gBACF,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;oBACjC,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;wBACjE,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;qBACxC;gBACH,CAAC,CAAC,CAAA;aACH;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,OAAO,KAAK,CAAA;AACd,CAAC;AAgDD,MAAM,OAAO,GAAG,CAAC,OAAgB,EAAE,MAAc,EAAE,EAAE;IACnD,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAA;IACpE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAE,MAAc,EAAE,EAAE;IAClD,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAA;IACjE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AACvB,CAAC,CAAA;AAUD,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,EAAC,KAAK,EAAE,IAAI,EAAc,EAAE,EAAE;IACvD,IAAI,OAAO,CAAA;IACX,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACzB,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAA;QAC3B,OAAO,GAAG,MAAM,EAAE,cAAc,IAAI,KAAK,CAAA;KAC1C;IAAC,OAAO,GAAG,EAAE;QACZ,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QACxB,SAAS,CAAC,IAAI,EAAE,CAAA;QAChB,MAAM,GAAG,CAAA;KACV;IACD,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAC7B,SAAS,CAAC,IAAI,EAAE,CAAA;AAClB,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAIzB,SAAyC,EACtB,EAAE;IACrB,IAAI,CAAC,qBAAqB,EAAE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAA;;EAEzB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;KAClB,CAAC,CAAA;KACH;IAED,8DAA8D;IAC9D,MAAM,eAAe,GAAU,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,EAAc,CAAA;IAC5B,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE;QACtC,IAAI,QAAQ,CAAC,OAAO,EAAE;YACpB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;SACvB;QAED,4CAA4C;QAC5C,KAAK,CAAC,QAAQ,CAAC,IAAa,CAAC,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;KAC3D;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,SAAiB;IAC7D,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE;QAC3B,MAAM,OAAO,GAAG;YACd,EAAC,IAAI,EAAE,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAC;YACpD,EAAC,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,WAAW,EAAC;SACpD,CAAA;QAED,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;QAE5D,MAAM,SAAS,GAAsB;YACnC,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG,iBAAiB,oFAAoF;YACjH,OAAO,EAAE,OAAO;SACjB,CAAA;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;QAExC,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE;YAC5B,MAAM,IAAI,eAAe,EAAE,CAAA;SAC5B;QAED,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;KACxB;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CAAC,IAAY,EAAE,eAAwB;IAC7F,MAAM,sBAAsB,GAAG,eAAe,IAAI,cAAc,CAAA;IAEhE,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACnD,MAAM,oBAAoB,GACxB,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI;QAC3D,CAAC,CAAC,IAAI,OAAO,CAAA,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;QAClE,CAAC,CAAC,EAAE,CAAA;IAER,MAAM,OAAO,GAAG;QACd,EAAC,IAAI,EAAE,+CAA+C,EAAE,KAAK,EAAE,QAAQ,EAAC;QACxE,EAAC,IAAI,EAAE,kCAAkC,EAAE,KAAK,EAAE,QAAQ,EAAC;KAC5D,CAAA;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC;QAC1B;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG,sBAAsB,oBAAoB,IAAI,2DAA2D,oBAAoB,4BAA4B;YACrK,OAAO,EAAE,OAAO;SACjB;KACF,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAA;AAClC,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,EAAE;YACjC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YAC/B,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;YAErB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAEhC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;gBAClC,KAAK,CAAC,wCAAwC,CAAC,CAAA;gBAC/C,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,CAAA;aAC1B;YACD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC3B,CAAC,CAAA;QAED,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;QACtB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QAC9B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import {CancelExecution, Abort, AbortSilent} from './error.js'\nimport {remove, exists} from './file.js'\nimport {info, completed, content, token, logUpdate, Message, Logger, stringifyMessage, debug} from './output.js'\nimport colors from './public/node/colors.js'\nimport {relative} from './path.js'\nimport {isTerminalInteractive} from './environment/local.js'\nimport {mapper as mapperUI, run as executorUI} from './ui/executor.js'\nimport {Listr as OriginalListr, ListrTask, ListrTaskState, ListrBaseClassOptions} from 'listr2'\nimport findProcess from 'find-process'\n\nexport function newListr(tasks: ListrTask[], options?: object | ListrBaseClassOptions) {\n const listr = new OriginalListr(tasks, options)\n listr.tasks.forEach((task) => {\n const loggedSubtaskTitles: string[] = []\n task.renderHook$.subscribe(() => {\n if (task.hasSubtasks()) {\n const activeSubtasks = task.subtasks.filter((subtask) => {\n return [ListrTaskState.PENDING, ListrTaskState.COMPLETED].includes(subtask.state as ListrTaskState)\n })\n activeSubtasks.forEach((subtask) => {\n if (subtask.title && !loggedSubtaskTitles.includes(subtask.title)) {\n loggedSubtaskTitles.push(subtask.title)\n }\n })\n }\n })\n })\n return listr\n}\n\nexport type ListrTasks = ConstructorParameters<typeof OriginalListr>[0]\nexport type {ListrTaskWrapper, ListrDefaultRenderer, ListrTask} from 'listr2'\n\nexport interface PromptAnswer {\n name: string\n value: string\n}\nexport type FilterFunction = (answers: PromptAnswer[], input: string) => Promise<PromptAnswer[]>\n\ninterface BaseQuestion<TName extends string> {\n name: TName\n message: string\n preface?: string\n validate?: (value: string) => string | true\n default?: string\n result?: (value: string) => string | boolean\n choices?: QuestionChoiceType[]\n source?: (filter: FilterFunction) => FilterFunction\n}\n\ntype TextQuestion<TName extends string> = BaseQuestion<TName> & {\n type: 'input'\n // a default is required, otherwise we'd show a prompt like 'undefined'\n default: string\n}\n\ntype PasswordQuestion<TName extends string> = BaseQuestion<TName> & {\n type: 'password'\n}\n\ntype SelectableQuestion<TName extends string> = BaseQuestion<TName> & {\n type: 'select' | 'autocomplete'\n choices: QuestionChoiceType[]\n}\n\nexport type Question<TName extends string = string> =\n | TextQuestion<TName>\n | SelectableQuestion<TName>\n | PasswordQuestion<TName>\n\nexport interface QuestionChoiceType {\n name: string\n value: string\n group?: {name: string; order: number}\n}\n\nconst started = (content: Message, logger: Logger) => {\n const message = `${colors.yellow('❯')} ${stringifyMessage(content)}`\n info(message, logger)\n}\n\nconst failed = (content: Message, logger: Logger) => {\n const message = `${colors.red('✖')} ${stringifyMessage(content)}`\n info(message, logger)\n}\n\n/**\n * Performs a task with the title kept up to date and stdout available to the\n * task while it runs (there is no re-writing stdout while the task runs).\n */\nexport interface TaskOptions {\n title: string\n task: () => Promise<void | {successMessage: string}>\n}\nexport const task = async ({title, task}: TaskOptions) => {\n let success\n started(title, logUpdate)\n try {\n const result = await task()\n success = result?.successMessage || title\n } catch (err) {\n failed(title, logUpdate)\n logUpdate.done()\n throw err\n }\n completed(success, logUpdate)\n logUpdate.done()\n}\nexport const prompt = async <\n TName extends string & keyof TAnswers,\n TAnswers extends {[key in TName]: string} = {[key in TName]: string},\n>(\n questions: ReadonlyArray<Question<TName>>,\n): Promise<TAnswers> => {\n if (!isTerminalInteractive() && questions.length !== 0) {\n throw new Abort(content`\nThe CLI prompted in a non-interactive terminal with the following questions:\n${token.json(questions)}\n `)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const mappedQuestions: any[] = questions.map(mapperUI)\n const value = {} as TAnswers\n for (const question of mappedQuestions) {\n if (question.preface) {\n info(question.preface)\n }\n\n // eslint-disable-next-line no-await-in-loop\n value[question.name as TName] = await executorUI(question)\n }\n return value\n}\n\nexport async function nonEmptyDirectoryPrompt(directory: string) {\n if (await exists(directory)) {\n const options = [\n {name: 'No, don’t delete the files', value: 'abort'},\n {name: 'Yes, delete the files', value: 'overwrite'},\n ]\n\n const relativeDirectory = relative(process.cwd(), directory)\n\n const questions: Question<'value'> = {\n type: 'select',\n name: 'value',\n message: `${relativeDirectory} is not an empty directory. Do you want to delete the existing files and continue?`,\n choices: options,\n }\n\n const choice = await prompt([questions])\n\n if (choice.value === 'abort') {\n throw new CancelExecution()\n }\n\n await remove(directory)\n }\n}\n\nexport async function terminateBlockingPortProcessPrompt(port: number, stepDescription?: string): Promise<boolean> {\n const stepDescriptionContent = stepDescription ?? 'current step'\n\n const processInfo = await findProcess('port', port)\n const formattedProcessName =\n processInfo && processInfo.length > 0 && processInfo[0]?.name\n ? ` ${content`${token.italic(`(${processInfo[0].name})`)}`.value}`\n : ''\n\n const options = [\n {name: 'Yes, terminate process in order to log in now', value: 'finish'},\n {name: `No, cancel command and try later`, value: 'cancel'},\n ]\n\n const choice = await prompt([\n {\n type: 'select',\n name: 'value',\n message: `${stepDescriptionContent} requires a port ${port} that's unavailable because it's running another process${formattedProcessName}. Terminate that process? `,\n choices: options,\n },\n ])\n return choice.value === 'finish'\n}\n\nexport const keypress = async () => {\n return new Promise((resolve, reject) => {\n const handler = (buffer: Buffer) => {\n process.stdin.setRawMode(false)\n process.stdin.pause()\n\n const bytes = Array.from(buffer)\n\n if (bytes.length && bytes[0] === 3) {\n debug('Canceled keypress, User pressed CTRL+C')\n reject(new AbortSilent())\n }\n process.nextTick(resolve)\n }\n\n process.stdin.resume()\n process.stdin.setRawMode(true)\n process.stdin.once('data', handler)\n })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopify/cli-kit",
3
- "version": "3.28.0",
3
+ "version": "3.30.0",
4
4
  "private": false,
5
5
  "description": "A set of utilities, interfaces, and models that are common across all the platform features",
6
6
  "keywords": [
@@ -41,6 +41,31 @@
41
41
  "eslintConfig": {
42
42
  "extends": [
43
43
  "../../.eslintrc.cjs"
44
+ ],
45
+ "overrides": [
46
+ {
47
+ "files": [
48
+ "**/node/cli.ts"
49
+ ],
50
+ "rules": {
51
+ "rulesdir/specific-imports-in-bootstrap-code": [
52
+ "error",
53
+ {
54
+ "dynamic": [
55
+ "./node-package-manager.js",
56
+ "./error-handler.js",
57
+ "../../environment/local.js",
58
+ "@oclif/core",
59
+ "../../environment/utilities.js",
60
+ "../../constants.js",
61
+ "../../path.js",
62
+ "../../system.js"
63
+ ],
64
+ "static": []
65
+ }
66
+ ]
67
+ }
68
+ }
44
69
  ]
45
70
  },
46
71
  "engine-strict": true,
@@ -55,7 +80,7 @@
55
80
  "dependencies": {
56
81
  "@bugsnag/js": "7.16.7",
57
82
  "@iarna/toml": "2.2.5",
58
- "@oclif/core": "1.9.2",
83
+ "@oclif/core": "1.21.0",
59
84
  "@types/archiver": "5.3.1",
60
85
  "abort-controller": "3.0.0",
61
86
  "archiver": "5.3.1",
@@ -92,6 +117,7 @@
92
117
  "latest-version": "6.0.0",
93
118
  "liquidjs": "9.36.0",
94
119
  "listr2": "4.0.5",
120
+ "lodash-es": "4.17.21",
95
121
  "log-update": "4.0.0",
96
122
  "macaddress": "0.5.3",
97
123
  "md5-file": "5.0.0",
@@ -108,22 +134,25 @@
108
134
  "tempy": "3.0.0",
109
135
  "term-size": "3.0.1",
110
136
  "terminal-link": "3.0.0",
137
+ "tree-kill": "1.2.2",
111
138
  "ts-error": "1.0.6",
112
139
  "unique-string": "3.0.0",
113
140
  "zod": "3.17.3"
114
141
  },
115
142
  "devDependencies": {
116
- "@types/fs-extra": "9.0.13",
117
- "@types/react": "17.0.2",
118
143
  "@types/commondir": "^1.0.0",
119
144
  "@types/cross-zip": "^4.0.0",
120
145
  "@types/diff": "^5.0.2",
146
+ "@types/fs-extra": "9.0.13",
121
147
  "@types/inquirer": "^8.2.1",
148
+ "@types/lodash-es": "^4.17.6",
149
+ "@types/react": "17.0.2",
122
150
  "@types/semver": "^7.3.9",
123
151
  "@vitest/coverage-istanbul": "^0.23.4",
152
+ "ink-testing-library": "^2.1.0",
124
153
  "node-stream-zip": "^1.15.0",
125
- "vitest": "^0.23.4",
126
- "vite": "^2.9.13"
154
+ "vite": "^2.9.13",
155
+ "vitest": "^0.23.4"
127
156
  },
128
157
  "repository": {
129
158
  "type": "git",
package/dist/log.d.ts DELETED
@@ -1,30 +0,0 @@
1
- /// <reference types="node" />
2
- import { Transform, TransformCallback, TransformOptions } from 'node:stream';
3
- interface LinesTruncatorTransformerOptions {
4
- fileSize: number;
5
- maxFileSize?: number;
6
- maxFileSizeToTruncate?: number;
7
- }
8
- export declare class LinesTruncatorTransformer extends Transform {
9
- linesToRetain: string[];
10
- lastLineCompleted: boolean;
11
- contentSize: number;
12
- options: LinesTruncatorTransformerOptions;
13
- constructor(truncatorOptions: LinesTruncatorTransformerOptions, opts?: TransformOptions);
14
- _transform(chunk: unknown, encoding: BufferEncoding, callback: TransformCallback): void;
15
- _flush(callback: TransformCallback): void;
16
- shouldTruncate(chunk: unknown): boolean;
17
- truncate(chunk: unknown): void;
18
- calculateNumLinesToRetain(): number;
19
- completeLastLine(tokens: string[]): void;
20
- }
21
- export declare function initiateLogging(options?: {
22
- logDir?: string;
23
- override?: boolean;
24
- }): Promise<void>;
25
- export declare function closeLogging(): void;
26
- export declare function logToFile(message: string, logLevel: string): void;
27
- export declare function pageLogs({ lastCommand }: {
28
- lastCommand: boolean;
29
- }): Promise<void>;
30
- export {};
package/dist/log.js DELETED
@@ -1,169 +0,0 @@
1
- import { isUnitTest } from './environment/local.js';
2
- import constants from './constants.js';
3
- import { generateRandomUUID } from './id.js';
4
- import { mkdirSync as fileMkdirSync, size as fileSize, touchSync as fileTouchSync, readSync as fileReadSync, } from './file.js';
5
- import { join as pathJoin } from './path.js';
6
- import { consoleLog, debug } from './output.js';
7
- import { page } from './system.js';
8
- import { promisify } from 'node:util';
9
- import { Stream, Transform } from 'node:stream';
10
- import { createWriteStream, createReadStream, unlinkSync } from 'node:fs';
11
- import { EOL } from 'node:os';
12
- const logFileName = 'shopify.cli.log';
13
- const maxLogFileSize = 5 * 1024 * 1024;
14
- const maxLogFileSizeToTruncate = 30 * 1024 * 1024;
15
- let logFileStream;
16
- let commandUuid;
17
- let logFilePath;
18
- export class LinesTruncatorTransformer extends Transform {
19
- constructor(truncatorOptions, opts) {
20
- super(opts);
21
- this.linesToRetain = [];
22
- this.lastLineCompleted = true;
23
- this.contentSize = 0;
24
- this.options = truncatorOptions;
25
- }
26
- _transform(chunk, encoding, callback) {
27
- if (this.shouldTruncate(chunk)) {
28
- this.truncate(chunk);
29
- }
30
- callback();
31
- }
32
- _flush(callback) {
33
- this.push(this.linesToRetain.join(EOL));
34
- callback();
35
- }
36
- shouldTruncate(chunk) {
37
- this.contentSize += chunk.toString().length;
38
- return this.options.fileSize - this.contentSize < (this.options.maxFileSizeToTruncate ?? maxLogFileSizeToTruncate);
39
- }
40
- truncate(chunk) {
41
- const tokens = chunk.toString().split(EOL);
42
- this.completeLastLine(tokens);
43
- // last splitted token will be an empty string when last character is a breakline
44
- this.lastLineCompleted = tokens[tokens.length - 1] === '';
45
- if (this.lastLineCompleted) {
46
- tokens.pop();
47
- }
48
- this.linesToRetain = this.linesToRetain.concat(tokens);
49
- const numLinesToRetain = this.calculateNumLinesToRetain();
50
- if (this.linesToRetain.length > numLinesToRetain) {
51
- this.linesToRetain = this.linesToRetain.splice(this.linesToRetain.length - numLinesToRetain);
52
- }
53
- }
54
- // Lines retained length average is used so the number of lines depends on the length of them
55
- calculateNumLinesToRetain() {
56
- return Math.floor((this.options.maxFileSize ?? maxLogFileSize) /
57
- (this.linesToRetain.map((line) => line.length).reduce((l1, l2) => l1 + l2, 0) / this.linesToRetain.length));
58
- }
59
- completeLastLine(tokens) {
60
- if (this.lastLineCompleted) {
61
- return;
62
- }
63
- const remainingToken = tokens.shift() ?? '';
64
- const incompleteToken = this.linesToRetain[this.linesToRetain.length - 1] ?? '';
65
- this.linesToRetain[this.linesToRetain.length - 1] = incompleteToken.concat(remainingToken);
66
- }
67
- }
68
- export async function initiateLogging(options = {}) {
69
- if (isUnitTest())
70
- return;
71
- commandUuid = generateRandomUUID();
72
- logFilePath = getLogFilePath(options);
73
- await truncateLogs(logFilePath);
74
- logFileStream = createWriteStream(logFilePath, { flags: 'a' });
75
- }
76
- export function closeLogging() {
77
- if (logFileExists()) {
78
- logFileStream.end();
79
- }
80
- }
81
- // DO NOT USE THIS FUNCTION DIRECTLY under normal circumstances.
82
- // It is exported purely for use in cases where output is already being logged
83
- // to the terminal but is not reflected in the logfile, e.g. Listr output.
84
- export function logToFile(message, logLevel) {
85
- // If file logging hasn't been initiated, skip it
86
- if (!logFileExists())
87
- return;
88
- const timestamp = new Date().toISOString();
89
- const logContents = `[${timestamp} ${commandUuid} ${logLevel}]: ${message}\n`;
90
- logFileStream.write(logContents);
91
- }
92
- export async function pageLogs({ lastCommand }) {
93
- const logDir = constants.paths.directories.cache.path();
94
- const logFile = pathJoin(logDir, logFileName);
95
- // Ensure file exists in case they deleted it or something
96
- fileTouchSync(logFile);
97
- if (lastCommand) {
98
- printLastCommand(logFile);
99
- }
100
- else {
101
- await page(logFile);
102
- }
103
- }
104
- function getLogFilePath(options = {}) {
105
- if (!logFilePath || options.override) {
106
- const logDir = options.logDir || constants.paths.directories.cache.path();
107
- fileMkdirSync(logDir);
108
- logFilePath = pathJoin(logDir, logFileName);
109
- fileTouchSync(logFilePath);
110
- }
111
- return logFilePath;
112
- }
113
- // Shaves off older log lines if logs are over maxLogFileSize long.
114
- async function truncateLogs(logFile) {
115
- const size = await fileSize(logFile);
116
- if (size < maxLogFileSize) {
117
- return;
118
- }
119
- debug(`Starting the truncation of the ${Math.floor(size / (1024 * 1024)).toLocaleString('en-US')}MB log file`);
120
- const tmpLogFile = logFile.concat('.tmp');
121
- const truncateLines = new LinesTruncatorTransformer({ fileSize: size });
122
- const pipeline = promisify(Stream.pipeline);
123
- await pipeline(createReadStream(logFile), truncateLines, createWriteStream(tmpLogFile));
124
- await pipeline(createReadStream(tmpLogFile), createWriteStream(logFile));
125
- unlinkSync(tmpLogFile);
126
- debug('Finished log truncation process');
127
- }
128
- function logFileExists() {
129
- return Boolean(logFileStream);
130
- }
131
- function printLastCommand(logFile) {
132
- const contents = fileReadSync(logFile).split('\n');
133
- const uuids = contents
134
- .map(logfileLineUUID)
135
- .filter((uuid) => uuid)
136
- .reverse();
137
- // 2nd unique UUID, because the currently running command will be the 1st
138
- const relevantUuid = Array.from(new Set(uuids))[1];
139
- if (relevantUuid) {
140
- consoleLog(relevantLines(contents, relevantUuid).join('\n'));
141
- }
142
- }
143
- function relevantLines(contents, relevantUuid) {
144
- // We run through the file line by line, keeping track of the most recently
145
- // encountered UUID.
146
- //
147
- // If the current line has a UUID, it's a new logged unit and should be
148
- // considered. Otherwise, the line is related to the most recent UUID.
149
- let mostRecentUuid = '';
150
- return contents.filter((line) => {
151
- const currentUuid = logfileLineUUID(line) || mostRecentUuid;
152
- mostRecentUuid = currentUuid;
153
- return currentUuid === relevantUuid;
154
- });
155
- }
156
- function logfileLineUUID(line) {
157
- // Log lines look like:
158
- //
159
- // timestamp UUID contents
160
- // ===========================================================================================
161
- // [2022-07-20T08:51:40.296Z 5288e1da-a06a-4f96-b1a6-e34fcdd7b416 DEBUG]: Running command logs
162
- // ===========================================================================================
163
- //
164
- // There may be subsequent lines if the contents section is multi-line.
165
- //
166
- const match = line.match(/^\[\S+ ([0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}) [A-Z]+\]/);
167
- return match && match[1];
168
- }
169
- //# sourceMappingURL=log.js.map
package/dist/log.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest} from './environment/local.js'\nimport constants from './constants.js'\nimport {generateRandomUUID} from './id.js'\nimport {\n mkdirSync as fileMkdirSync,\n size as fileSize,\n touchSync as fileTouchSync,\n readSync as fileReadSync,\n} from './file.js'\nimport {join as pathJoin} from './path.js'\nimport {consoleLog, debug} from './output.js'\nimport {page} from './system.js'\nimport {promisify} from 'node:util'\nimport {Stream, Transform, TransformCallback, TransformOptions} from 'node:stream'\nimport {WriteStream, createWriteStream, createReadStream, unlinkSync} from 'node:fs'\nimport {EOL} from 'node:os'\n\nconst logFileName = 'shopify.cli.log'\nconst maxLogFileSize = 5 * 1024 * 1024\nconst maxLogFileSizeToTruncate = 30 * 1024 * 1024\nlet logFileStream: WriteStream\nlet commandUuid: string\nlet logFilePath: string\n\ninterface LinesTruncatorTransformerOptions {\n fileSize: number\n maxFileSize?: number\n maxFileSizeToTruncate?: number\n}\nexport class LinesTruncatorTransformer extends Transform {\n linesToRetain: string[] = []\n lastLineCompleted = true\n contentSize = 0\n options: LinesTruncatorTransformerOptions\n\n constructor(truncatorOptions: LinesTruncatorTransformerOptions, opts?: TransformOptions) {\n super(opts)\n this.options = truncatorOptions\n }\n\n _transform(chunk: unknown, encoding: BufferEncoding, callback: TransformCallback): void {\n if (this.shouldTruncate(chunk)) {\n this.truncate(chunk)\n }\n callback()\n }\n\n _flush(callback: TransformCallback): void {\n this.push(this.linesToRetain.join(EOL))\n callback()\n }\n\n shouldTruncate(chunk: unknown): boolean {\n this.contentSize += (chunk as string).toString().length\n return this.options.fileSize - this.contentSize < (this.options.maxFileSizeToTruncate ?? maxLogFileSizeToTruncate)\n }\n\n truncate(chunk: unknown) {\n const tokens = (chunk as string).toString().split(EOL)\n\n this.completeLastLine(tokens)\n // last splitted token will be an empty string when last character is a breakline\n this.lastLineCompleted = tokens[tokens.length - 1] === ''\n if (this.lastLineCompleted) {\n tokens.pop()\n }\n this.linesToRetain = this.linesToRetain.concat(tokens)\n\n const numLinesToRetain = this.calculateNumLinesToRetain()\n if (this.linesToRetain.length > numLinesToRetain) {\n this.linesToRetain = this.linesToRetain.splice(this.linesToRetain.length - numLinesToRetain)\n }\n }\n\n // Lines retained length average is used so the number of lines depends on the length of them\n calculateNumLinesToRetain() {\n return Math.floor(\n (this.options.maxFileSize ?? maxLogFileSize) /\n (this.linesToRetain.map((line) => line.length).reduce((l1, l2) => l1 + l2, 0) / this.linesToRetain.length),\n )\n }\n\n completeLastLine(tokens: string[]) {\n if (this.lastLineCompleted) {\n return\n }\n\n const remainingToken = tokens.shift() ?? ''\n const incompleteToken = this.linesToRetain[this.linesToRetain.length - 1] ?? ''\n this.linesToRetain[this.linesToRetain.length - 1] = incompleteToken.concat(remainingToken)\n }\n}\n\nexport async function initiateLogging(options: {logDir?: string; override?: boolean} = {}) {\n if (isUnitTest()) return\n commandUuid = generateRandomUUID()\n logFilePath = getLogFilePath(options)\n await truncateLogs(logFilePath)\n logFileStream = createWriteStream(logFilePath, {flags: 'a'})\n}\n\nexport function closeLogging() {\n if (logFileExists()) {\n logFileStream.end()\n }\n}\n\n// DO NOT USE THIS FUNCTION DIRECTLY under normal circumstances.\n// It is exported purely for use in cases where output is already being logged\n// to the terminal but is not reflected in the logfile, e.g. Listr output.\nexport function logToFile(message: string, logLevel: string): void {\n // If file logging hasn't been initiated, skip it\n if (!logFileExists()) return\n const timestamp = new Date().toISOString()\n const logContents = `[${timestamp} ${commandUuid} ${logLevel}]: ${message}\\n`\n logFileStream.write(logContents)\n}\n\nexport async function pageLogs({lastCommand}: {lastCommand: boolean}) {\n const logDir = constants.paths.directories.cache.path()\n const logFile = pathJoin(logDir, logFileName)\n // Ensure file exists in case they deleted it or something\n fileTouchSync(logFile)\n if (lastCommand) {\n printLastCommand(logFile)\n } else {\n await page(logFile)\n }\n}\n\nfunction getLogFilePath(options: {logDir?: string; override?: boolean} = {}) {\n if (!logFilePath || options.override) {\n const logDir = options.logDir || constants.paths.directories.cache.path()\n fileMkdirSync(logDir)\n logFilePath = pathJoin(logDir, logFileName)\n fileTouchSync(logFilePath)\n }\n\n return logFilePath\n}\n\n// Shaves off older log lines if logs are over maxLogFileSize long.\nasync function truncateLogs(logFile: string) {\n const size = await fileSize(logFile)\n if (size < maxLogFileSize) {\n return\n }\n debug(`Starting the truncation of the ${Math.floor(size / (1024 * 1024)).toLocaleString('en-US')}MB log file`)\n const tmpLogFile = logFile.concat('.tmp')\n const truncateLines = new LinesTruncatorTransformer({fileSize: size})\n const pipeline = promisify(Stream.pipeline)\n await pipeline(createReadStream(logFile), truncateLines, createWriteStream(tmpLogFile))\n await pipeline(createReadStream(tmpLogFile), createWriteStream(logFile))\n unlinkSync(tmpLogFile)\n debug('Finished log truncation process')\n}\n\nfunction logFileExists(): boolean {\n return Boolean(logFileStream)\n}\n\nfunction printLastCommand(logFile: string): void {\n const contents = fileReadSync(logFile).split('\\n')\n const uuids = contents\n .map(logfileLineUUID)\n .filter((uuid) => uuid)\n .reverse()\n // 2nd unique UUID, because the currently running command will be the 1st\n const relevantUuid = Array.from(new Set(uuids))[1]\n if (relevantUuid) {\n consoleLog(relevantLines(contents, relevantUuid).join('\\n'))\n }\n}\n\nfunction relevantLines(contents: string[], relevantUuid: string): string[] {\n // We run through the file line by line, keeping track of the most recently\n // encountered UUID.\n //\n // If the current line has a UUID, it's a new logged unit and should be\n // considered. Otherwise, the line is related to the most recent UUID.\n let mostRecentUuid = ''\n return contents.filter((line: string) => {\n const currentUuid = logfileLineUUID(line) || mostRecentUuid\n mostRecentUuid = currentUuid\n return currentUuid === relevantUuid\n })\n}\n\nfunction logfileLineUUID(line: string): string | null {\n // Log lines look like:\n //\n // timestamp UUID contents\n // ===========================================================================================\n // [2022-07-20T08:51:40.296Z 5288e1da-a06a-4f96-b1a6-e34fcdd7b416 DEBUG]: Running command logs\n // ===========================================================================================\n //\n // There may be subsequent lines if the contents section is multi-line.\n //\n const match = line.match(/^\\[\\S+ ([0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}) [A-Z]+\\]/)\n return match && match[1]!\n}\n"]}
@@ -1,2 +0,0 @@
1
- import { Fatal } from '../../../error.js';
2
- export declare function fatalError(error: Fatal): void;
@@ -1,8 +0,0 @@
1
- import { FatalError } from './components/FatalError.js';
2
- import { renderOnce } from '../ui.js';
3
- import { consoleError } from '../../../output.js';
4
- import React from 'react';
5
- export function fatalError(error) {
6
- renderOnce(React.createElement(FatalError, { error: error }), 'error', consoleError);
7
- }
8
- //# sourceMappingURL=error.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../../src/private/node/ui/error.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAA;AAErD,OAAO,EAAC,UAAU,EAAC,MAAM,UAAU,CAAA;AACnC,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAA;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,UAAU,UAAU,CAAC,KAAY;IACrC,UAAU,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AACjE,CAAC","sourcesContent":["import {FatalError} from './components/FatalError.js'\nimport {Fatal} from '../../../error.js'\nimport {renderOnce} from '../ui.js'\nimport {consoleError} from '../../../output.js'\nimport React from 'react'\n\nexport function fatalError(error: Fatal) {\n renderOnce(<FatalError error={error} />, 'error', consoleError)\n}\n"]}