@stripchatdev/create-stripchat-extension 0.1.46 → 0.1.47

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 (214) hide show
  1. package/dist/bin/cli/actions/updateAction.d.ts +6 -0
  2. package/dist/bin/cli/actions/updateAction.js +33 -0
  3. package/dist/bin/cli/helpers/printCliError.d.ts +1 -0
  4. package/dist/bin/cli/helpers/printCliError.js +21 -0
  5. package/dist/bin/cli/index.js +70 -0
  6. package/dist/bin/create.d.ts +2 -0
  7. package/dist/bin/create.js +238 -0
  8. package/dist/package.json +5 -2
  9. package/dist/src/constants.d.ts +14 -9
  10. package/dist/src/constants.js +53 -8
  11. package/dist/src/dependencies/constants.d.ts +2 -0
  12. package/dist/src/dependencies/constants.js +11 -0
  13. package/dist/src/dependencies/resolveDependencies.d.ts +6 -0
  14. package/dist/src/dependencies/resolveDependencies.js +43 -0
  15. package/dist/src/dependencies/resolveDependencies.test.js +74 -0
  16. package/dist/src/helpers/error.d.ts +3 -0
  17. package/dist/src/helpers/error.js +9 -0
  18. package/dist/src/helpers/error.test.js +15 -0
  19. package/dist/src/helpers/getIsDirectoryExists.d.ts +7 -0
  20. package/dist/src/helpers/getIsDirectoryExists.js +23 -0
  21. package/dist/src/helpers/getIsDirectoryExists.test.js +34 -0
  22. package/dist/src/helpers/getIsJsxFramework.d.ts +2 -0
  23. package/dist/src/helpers/getIsJsxFramework.js +2 -0
  24. package/dist/src/helpers/getIsJsxFramework.test.js +10 -0
  25. package/dist/src/helpers/getIsTypescript.d.ts +2 -0
  26. package/dist/src/helpers/getIsTypescript.js +1 -0
  27. package/dist/src/helpers/getIsTypescript.test.js +10 -0
  28. package/dist/src/helpers/isSubPath.d.ts +1 -0
  29. package/dist/src/helpers/isSubPath.js +5 -0
  30. package/dist/src/helpers/normalizePath.d.ts +2 -0
  31. package/dist/src/helpers/normalizePath.js +4 -0
  32. package/dist/src/helpers/normalizePath.test.js +19 -0
  33. package/dist/src/migrator/executor.d.ts +9 -0
  34. package/dist/src/migrator/executor.js +112 -0
  35. package/dist/src/migrator/migration.d.ts +3 -0
  36. package/dist/src/migrator/migration.js +18 -0
  37. package/dist/src/migrator/migration.test.js +74 -0
  38. package/dist/src/migrator/migrations/migrations.test.js +97 -0
  39. package/dist/src/migrator/migrations/v2/AGENTS_md/001_recreate-with-generated-part.d.ts +2 -0
  40. package/dist/src/migrator/migrations/v2/AGENTS_md/001_recreate-with-generated-part.js +14 -0
  41. package/dist/src/migrator/migrations/v2/_project-config_json/001_create.d.ts +2 -0
  42. package/dist/src/migrator/migrations/v2/_project-config_json/001_create.js +14 -0
  43. package/dist/src/migrator/migrations/v2/vite_config_ts/001_turn_off_minify_and_assets_inline.d.ts +2 -0
  44. package/dist/src/migrator/migrations/v2/vite_config_ts/001_turn_off_minify_and_assets_inline.js +118 -0
  45. package/dist/src/migrator/planner.d.ts +5 -0
  46. package/dist/src/migrator/planner.js +65 -0
  47. package/dist/src/migrator/planner.test.js +40 -0
  48. package/dist/src/migrator/types.d.ts +29 -0
  49. package/dist/src/migrator/updates/updates.test.js +102 -0
  50. package/dist/src/migrator/updates/v2/AGENTS_md/001_update-generated-part.d.ts +2 -0
  51. package/dist/src/migrator/updates/v2/AGENTS_md/001_update-generated-part.js +38 -0
  52. package/dist/src/migrator/updates/v2/package_json/001_update-versions.d.ts +2 -0
  53. package/dist/src/migrator/updates/v2/package_json/001_update-versions.js +77 -0
  54. package/dist/src/migrator/updates/v2/package_json/002_add-cli-commands.d.ts +2 -0
  55. package/dist/src/migrator/updates/v2/package_json/002_add-cli-commands.js +61 -0
  56. package/dist/src/migrator/validators/getIsValidMigration.d.ts +2 -0
  57. package/dist/src/migrator/validators/getIsValidMigration.js +3 -0
  58. package/dist/src/migrator/validators/getIsValidMigration.test.js +13 -0
  59. package/dist/src/projectConfig/buildProjectConfig.d.ts +15 -0
  60. package/dist/src/projectConfig/buildProjectConfig.js +27 -0
  61. package/dist/src/projectConfig/detectPackageManagerRuntime.d.ts +2 -0
  62. package/dist/src/{helpers/detectPackageManager.js → projectConfig/detectPackageManagerRuntime.js} +1 -1
  63. package/dist/src/{helpers/detectPackageManager.test.js → projectConfig/detectPackageManagerRuntime.test.js} +10 -10
  64. package/dist/src/projectConfig/recoverProjectConfig.d.ts +1 -0
  65. package/dist/src/projectConfig/recoverProjectConfig.js +34 -0
  66. package/dist/src/projectConfig/recovery/detectPackageManagerFromFiles.d.ts +2 -0
  67. package/dist/src/projectConfig/recovery/detectPackageManagerFromFiles.js +16 -0
  68. package/dist/src/projectConfig/recovery/detectPackageManagerFromFiles.test.d.ts +1 -0
  69. package/dist/src/projectConfig/recovery/detectPackageManagerFromFiles.test.js +37 -0
  70. package/dist/src/projectConfig/recovery/parseAgentsMd.d.ts +10 -0
  71. package/dist/src/projectConfig/recovery/parseAgentsMd.js +52 -0
  72. package/dist/src/projectConfig/recovery/parseAgentsMd.test.d.ts +1 -0
  73. package/dist/src/projectConfig/recovery/parseAgentsMd.test.js +67 -0
  74. package/dist/src/projectConfig/recovery/resolveProjectNameFromDir.d.ts +1 -0
  75. package/dist/src/projectConfig/recovery/resolveProjectNameFromDir.js +11 -0
  76. package/dist/src/projectConfig/recovery/resolveProjectNameFromDir.test.d.ts +1 -0
  77. package/dist/src/projectConfig/recovery/resolveProjectNameFromDir.test.js +21 -0
  78. package/dist/src/projectConfig/resolveExistsProjectConfig.d.ts +2 -0
  79. package/dist/src/projectConfig/resolveExistsProjectConfig.js +34 -0
  80. package/dist/src/projectConfig/updateProjectConfig.d.ts +2 -0
  81. package/dist/src/projectConfig/updateProjectConfig.js +20 -0
  82. package/dist/src/projectConfig/validators/getIsValidProjectConfig.d.ts +2 -0
  83. package/dist/src/projectConfig/validators/getIsValidProjectConfig.js +6 -0
  84. package/dist/src/projectConfig/validators/getIsValidProjectConfig.test.d.ts +1 -0
  85. package/dist/src/projectConfig/validators/getIsValidProjectConfig.test.js +33 -0
  86. package/dist/src/projectConfig/validators/validateProjectConfig.d.ts +2 -0
  87. package/dist/src/projectConfig/validators/validateProjectConfig.js +30 -0
  88. package/dist/src/projectConfig/validators/validateProjectConfig.test.d.ts +1 -0
  89. package/dist/src/projectConfig/validators/validateProjectConfig.test.js +215 -0
  90. package/dist/src/templater/executor.d.ts +2 -0
  91. package/dist/src/templater/executor.js +22 -0
  92. package/dist/src/templater/executor.test.d.ts +1 -0
  93. package/dist/src/{executor.test.js → templater/executor.test.js} +25 -11
  94. package/dist/src/templater/helpers/getIsTypescriptOnlyFile.d.ts +1 -0
  95. package/dist/src/templater/helpers/getIsTypescriptOnlyFile.js +10 -0
  96. package/dist/src/templater/helpers/getIsTypescriptOnlyFile.test.d.ts +1 -0
  97. package/dist/src/templater/helpers/getIsTypescriptOnlyFile.test.js +25 -0
  98. package/dist/src/templater/helpers/resolveTemplateExtension.d.ts +1 -0
  99. package/dist/src/templater/helpers/resolveTemplateExtension.js +16 -0
  100. package/dist/src/templater/helpers/resolveTemplateExtension.test.d.ts +1 -0
  101. package/dist/src/{mappers → templater/mappers}/mapProjectConfigToTemplateModel.d.ts +1 -1
  102. package/dist/src/{mappers → templater/mappers}/mapProjectConfigToTemplateModel.js +6 -8
  103. package/dist/src/templater/mappers/mapProjectConfigToTemplateModel.test.d.ts +1 -0
  104. package/dist/src/{mappers → templater/mappers}/mapProjectConfigToTemplateModel.test.js +29 -23
  105. package/dist/src/templater/planner.d.ts +2 -0
  106. package/dist/src/templater/planner.js +104 -0
  107. package/dist/src/templater/planner.test.d.ts +1 -0
  108. package/dist/src/templater/planner.test.js +64 -0
  109. package/dist/src/templates/constants.d.ts +6 -0
  110. package/dist/src/templates/constants.js +11 -0
  111. package/dist/src/templates/helpers/resolveTemplatesDir.d.ts +1 -0
  112. package/dist/src/templates/helpers/resolveTemplatesDir.js +16 -0
  113. package/dist/src/templates/templates.d.ts +10 -0
  114. package/dist/src/templates/templates.js +133 -0
  115. package/dist/src/templates/templates.test.d.ts +1 -0
  116. package/dist/src/templates/templates.test.js +263 -0
  117. package/dist/src/templates/types.d.ts +21 -0
  118. package/dist/src/templates/types.js +1 -0
  119. package/dist/src/types.d.ts +28 -9
  120. package/dist/src/validators/getIsValidCategory.d.ts +2 -0
  121. package/dist/src/validators/getIsValidCategory.js +2 -0
  122. package/dist/src/validators/getIsValidCategory.test.d.ts +1 -0
  123. package/dist/src/validators/{isValidCategory.test.js → getIsValidCategory.test.js} +3 -3
  124. package/dist/src/validators/getIsValidFramework.d.ts +2 -0
  125. package/dist/src/validators/getIsValidFramework.js +2 -0
  126. package/dist/src/validators/getIsValidFramework.test.d.ts +1 -0
  127. package/dist/src/validators/{isValidFramework.test.js → getIsValidFramework.test.js} +3 -3
  128. package/dist/src/validators/getIsValidLanguage.d.ts +2 -0
  129. package/dist/src/validators/getIsValidLanguage.js +2 -0
  130. package/dist/src/validators/getIsValidLanguage.test.d.ts +1 -0
  131. package/dist/src/validators/{isValidLanguage.test.js → getIsValidLanguage.test.js} +3 -3
  132. package/dist/src/validators/getIsValidPackageManager.d.ts +2 -0
  133. package/dist/src/validators/getIsValidPackageManager.js +4 -0
  134. package/dist/src/validators/getIsValidPackageManager.test.d.ts +1 -0
  135. package/dist/src/validators/getIsValidPackageManager.test.js +11 -0
  136. package/dist/src/validators/getIsValidSlot.d.ts +2 -0
  137. package/dist/src/validators/getIsValidSlot.js +4 -0
  138. package/dist/src/validators/getIsValidSlot.test.d.ts +1 -0
  139. package/dist/src/validators/getIsValidSlot.test.js +26 -0
  140. package/dist/src/validators/validateSlots.js +40 -8
  141. package/dist/src/validators/validateSlots.test.js +125 -34
  142. package/dist/tsconfig.tsbuildinfo +1 -1
  143. package/package.json +5 -2
  144. package/templates/v1/vite.config.ts.ejs +27 -0
  145. package/templates/v2/.project-config.json.ejs +1 -0
  146. package/templates/v2/AGENTS.md.ejs +712 -0
  147. package/templates/v2/README.md.ejs +31 -0
  148. package/templates/v2/package.json.ejs +26 -0
  149. package/dist/bin/cli.js +0 -221
  150. package/dist/src/executor.d.ts +0 -2
  151. package/dist/src/executor.js +0 -22
  152. package/dist/src/helpers/detectPackageManager.d.ts +0 -2
  153. package/dist/src/helpers/isDirectory.d.ts +0 -1
  154. package/dist/src/helpers/isDirectory.js +0 -9
  155. package/dist/src/helpers/isDirectory.test.js +0 -22
  156. package/dist/src/helpers/isTypescriptOnlyFile.d.ts +0 -1
  157. package/dist/src/helpers/isTypescriptOnlyFile.js +0 -5
  158. package/dist/src/helpers/isTypescriptOnlyFile.test.js +0 -22
  159. package/dist/src/helpers/normalizeRelPath.d.ts +0 -1
  160. package/dist/src/helpers/normalizeRelPath.js +0 -1
  161. package/dist/src/helpers/normalizeRelPath.test.js +0 -19
  162. package/dist/src/helpers/resolveTemplateExtension.d.ts +0 -1
  163. package/dist/src/helpers/resolveTemplateExtension.js +0 -17
  164. package/dist/src/helpers/resolveTemplatesDir.d.ts +0 -1
  165. package/dist/src/helpers/resolveTemplatesDir.js +0 -11
  166. package/dist/src/helpers/resolveTemplatesDir.test.js +0 -21
  167. package/dist/src/planner.d.ts +0 -2
  168. package/dist/src/planner.js +0 -126
  169. package/dist/src/planner.test.js +0 -58
  170. package/dist/src/validators/index.d.ts +0 -6
  171. package/dist/src/validators/index.js +0 -6
  172. package/dist/src/validators/isValidCategory.d.ts +0 -2
  173. package/dist/src/validators/isValidCategory.js +0 -2
  174. package/dist/src/validators/isValidFramework.d.ts +0 -2
  175. package/dist/src/validators/isValidFramework.js +0 -2
  176. package/dist/src/validators/isValidLanguage.d.ts +0 -2
  177. package/dist/src/validators/isValidLanguage.js +0 -2
  178. package/dist/src/validators/validateProjectDir.d.ts +0 -1
  179. package/dist/src/validators/validateProjectDir.js +0 -6
  180. package/dist/src/validators/validateProjectDir.test.js +0 -19
  181. package/dist/bin/{cli.d.ts → cli/index.d.ts} +0 -0
  182. package/dist/src/{executor.test.d.ts → dependencies/resolveDependencies.test.d.ts} +0 -0
  183. package/dist/src/helpers/{detectPackageManager.test.d.ts → error.test.d.ts} +0 -0
  184. package/dist/src/helpers/{isDirectory.test.d.ts → getIsDirectoryExists.test.d.ts} +0 -0
  185. package/dist/src/helpers/{isTypescriptOnlyFile.test.d.ts → getIsJsxFramework.test.d.ts} +0 -0
  186. package/dist/src/helpers/{normalizeRelPath.test.d.ts → getIsTypescript.test.d.ts} +0 -0
  187. package/dist/src/helpers/{resolveTemplateExtension.test.d.ts → normalizePath.test.d.ts} +0 -0
  188. package/dist/src/{helpers/resolveTemplatesDir.test.d.ts → migrator/migration.test.d.ts} +0 -0
  189. package/dist/src/{mappers/mapProjectConfigToTemplateModel.test.d.ts → migrator/migrations/migrations.test.d.ts} +0 -0
  190. package/dist/src/{planner.test.d.ts → migrator/planner.test.d.ts} +0 -0
  191. package/dist/src/{validators/isValidCategory.test.d.ts → migrator/types.js} +0 -0
  192. package/dist/src/{validators/isValidFramework.test.d.ts → migrator/updates/updates.test.d.ts} +0 -0
  193. package/dist/src/{validators/isValidLanguage.test.d.ts → migrator/validators/getIsValidMigration.test.d.ts} +0 -0
  194. package/dist/src/{validators/validateProjectDir.test.d.ts → projectConfig/detectPackageManagerRuntime.test.d.ts} +0 -0
  195. package/dist/src/{helpers → templater/helpers}/resolveTemplateExtension.test.js +0 -0
  196. package/templates/{.gitignore.ejs → v1/.gitignore.ejs} +0 -0
  197. package/templates/{AGENTS.md.ejs → v1/AGENTS.md.ejs} +0 -0
  198. package/templates/{CLAUDE.md → v1/CLAUDE.md} +0 -0
  199. package/templates/{README.md.ejs → v1/README.md.ejs} +0 -0
  200. package/templates/{package.json.ejs → v1/package.json.ejs} +0 -0
  201. package/templates/{public → v1/public}/icon.svg +0 -0
  202. package/templates/{public → v1/public}/manifest.json.ejs +0 -0
  203. package/templates/{public → v1/public}/resolveSlotPage.js.ejs +0 -0
  204. package/templates/{src → v1/src}/slots/background/app.ts.ejs +0 -0
  205. package/templates/{src → v1/src}/slots/background/background.html.ejs +0 -0
  206. package/templates/{src → v1/src}/slots/background/main.ts.ejs +0 -0
  207. package/templates/{src/slots/slot/slot.html.ejs → v1/src/slots/slot/__SLOT_KEY__.html.ejs} +0 -0
  208. package/templates/{src → v1/src}/slots/slot/app.ts.ejs +0 -0
  209. package/templates/{src → v1/src}/slots/slot/app.tsx.ejs +0 -0
  210. package/templates/{src → v1/src}/slots/slot/main.css.ejs +0 -0
  211. package/templates/{src → v1/src}/slots/slot/main.ts.ejs +0 -0
  212. package/templates/{src → v1/src}/slots/slot/main.tsx.ejs +0 -0
  213. package/templates/{tsconfig.json.ejs → v1/tsconfig.json.ejs} +0 -0
  214. package/templates/{vite.config.ts.ejs → v2/vite.config.ts.ejs} +1 -1
@@ -0,0 +1,6 @@
1
+ export type TUpdateOptions = {
2
+ isDryRun: boolean;
3
+ projectDir: string;
4
+ templateVersion: number;
5
+ };
6
+ export declare const updateAction: (options: TUpdateOptions) => Promise<void>;
@@ -0,0 +1,33 @@
1
+ import { executeMigrations } from '../../../src/migrator/executor.js';
2
+ import { planMigrationExecution } from '../../../src/migrator/planner.js';
3
+ import { resolveExistsProjectConfig } from '../../../src/projectConfig/resolveExistsProjectConfig.js';
4
+ export const updateAction = async (options) => {
5
+ const { isDryRun, projectDir, templateVersion } = options;
6
+ const targetProjectConfig = resolveExistsProjectConfig(projectDir);
7
+ const executionPlan = planMigrationExecution(targetProjectConfig, templateVersion);
8
+ if (!executionPlan.migrationPlans.length) {
9
+ console.log('\nNo migration plan found, all managed files are up to date.');
10
+ return;
11
+ }
12
+ console.log('\nMigration plan:');
13
+ executionPlan.migrationPlans.forEach((migration) => {
14
+ console.log(` ${migration.scriptPath}`);
15
+ });
16
+ const migrationDiffs = await executeMigrations({
17
+ projectDir,
18
+ isDryRun,
19
+ executionPlan,
20
+ });
21
+ if (!migrationDiffs.length) {
22
+ console.log('\nNo files changed\n');
23
+ return;
24
+ }
25
+ console.log('\nChanged files:');
26
+ const changedFiles = new Set();
27
+ migrationDiffs.forEach((migrationDiff) => {
28
+ if (!changedFiles.has(migrationDiff.filePath)) {
29
+ changedFiles.add(migrationDiff.filePath);
30
+ console.log(` ${migrationDiff.filePath}`);
31
+ }
32
+ });
33
+ };
@@ -0,0 +1 @@
1
+ export declare const printCliError: (err: unknown) => void;
@@ -0,0 +1,21 @@
1
+ import * as process from 'node:process';
2
+ import { AppError } from '../../../src/helpers/error.js';
3
+ const isDebugMode = process.env.DEBUG === 'true';
4
+ const printErrorMessage = (message) => {
5
+ console.error(`x ${message}\n`);
6
+ };
7
+ export const printCliError = (err) => {
8
+ if (err instanceof AppError) {
9
+ printErrorMessage(err.message);
10
+ return;
11
+ }
12
+ printErrorMessage('Unexpected error occurred.');
13
+ if (err instanceof Error && isDebugMode) {
14
+ console.error(err.stack, '\n');
15
+ return;
16
+ }
17
+ if (isDebugMode) {
18
+ console.error(err);
19
+ }
20
+ return;
21
+ };
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from 'node:path';
3
+ import * as process from 'node:process';
4
+ import yargs from 'yargs';
5
+ import { hideBin } from 'yargs/helpers';
6
+ import { VERSION } from '../../src/constants.js';
7
+ import { AppError } from '../../src/helpers/error.js';
8
+ import { getIsDirectoryExists } from '../../src/helpers/getIsDirectoryExists.js';
9
+ import { LAST_TEMPLATE_VERSION } from '../../src/templates/templates.js';
10
+ import { updateAction } from './actions/updateAction.js';
11
+ import { printCliError } from './helpers/printCliError.js';
12
+ const app = yargs(hideBin(process.argv))
13
+ .strict()
14
+ .demandCommand(1, 'Command was not specified')
15
+ .showHelpOnFail(false)
16
+ .version(VERSION)
17
+ .fail((msg, err) => {
18
+ if (err) {
19
+ printCliError(err);
20
+ process.exit(1);
21
+ }
22
+ printCliError(new AppError(msg || 'Invalid command.'));
23
+ app.showHelp('error');
24
+ process.exit(1);
25
+ });
26
+ app
27
+ .command('update', 'Update managed template parts in an existing generated project.', (y) => y
28
+ .option('path', {
29
+ alias: 'p',
30
+ default: '.',
31
+ description: 'Path to the extension project',
32
+ type: 'string',
33
+ })
34
+ .option('dryRun', {
35
+ alias: 'd',
36
+ default: false,
37
+ description: 'Dry run update',
38
+ type: 'boolean',
39
+ })
40
+ .option('templateVersion', {
41
+ alias: 't',
42
+ description: 'Template version',
43
+ hidden: true,
44
+ type: 'number',
45
+ }), async (argv) => {
46
+ const isDryRun = argv.dryRun;
47
+ const projectDir = resolve(process.cwd(), argv.path);
48
+ const templateVersion = argv.templateVersion || LAST_TEMPLATE_VERSION;
49
+ const { error: projectPathError, isExists: isProjectPathExists } = getIsDirectoryExists(projectDir);
50
+ if (!isProjectPathExists) {
51
+ throw new AppError(projectPathError);
52
+ }
53
+ try {
54
+ await updateAction({
55
+ projectDir: resolve(process.cwd(), argv.path),
56
+ isDryRun,
57
+ templateVersion,
58
+ });
59
+ }
60
+ catch (err) {
61
+ console.log('\nUnable to update this project template automatically.\n' +
62
+ 'The project version is too old or has changed significantly from the generated template.\n' +
63
+ 'Please create a new project with the latest template and then move your custom files into it.\n');
64
+ throw err;
65
+ }
66
+ });
67
+ void app.parseAsync().catch((err) => {
68
+ printCliError(err);
69
+ process.exit(1);
70
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env node
2
+ import { checkbox, input, select } from '@inquirer/prompts';
3
+ import { existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { parseArgs } from 'node:util';
6
+ import packageJson from '../package.json' with { type: 'json' };
7
+ import { CATEGORIES, CATEGORY_LABELS, FRAMEWORK_LABELS, FRAMEWORKS, LANGUAGE_LABELS, LANGUAGES, SLOT_RULES_BY_CATEGORY, SLOT_LABELS, EXT_HELPER_VERSION, CLI_COMMANDS_MAP, } from '../src/constants.js';
8
+ import { AppError } from '../src/helpers/error.js';
9
+ import { buildProjectConfig } from '../src/projectConfig/buildProjectConfig.js';
10
+ import { detectPackageManagerRuntime } from '../src/projectConfig/detectPackageManagerRuntime.js';
11
+ import { executeCommands } from '../src/templater/executor.js';
12
+ import { mapProjectConfigToTemplateData } from '../src/templater/mappers/mapProjectConfigToTemplateModel.js';
13
+ import { planProject } from '../src/templater/planner.js';
14
+ import { MANAGED_TEMPLATES } from '../src/templates/constants.js';
15
+ import { LAST_TEMPLATE_VERSION, TEMPLATES_DIR } from '../src/templates/templates.js';
16
+ import { getIsValidCategory } from '../src/validators/getIsValidCategory.js';
17
+ import { getIsValidFramework } from '../src/validators/getIsValidFramework.js';
18
+ import { getIsValidLanguage } from '../src/validators/getIsValidLanguage.js';
19
+ import { validateName } from '../src/validators/validateName.js';
20
+ import { validateSlots } from '../src/validators/validateSlots.js';
21
+ const HELP = `
22
+ Usage: create-stripchat-extension [options]
23
+
24
+ Create a new Stripchat extension project.
25
+
26
+ Options:
27
+ --name <name> Project name (used as a directory and package name)
28
+ --category <category> Extension category (${CATEGORIES.join(', ')})
29
+ --slots <items> Comma-separated slots (e.g. "EXTENSION_SLOT_MAIN_GAME_FUN,EXTENSION_SLOT_RIGHT_OVERLAY") or empty string
30
+ --framework <framework> UI framework (${FRAMEWORKS.join(', ')})
31
+ --language <lang> Language (${LANGUAGES.join(', ')})
32
+ -h, --help Display this help message
33
+ -v, --version Show version number
34
+ `.trim();
35
+ const parseCliArgs = () => {
36
+ try {
37
+ const { values } = parseArgs({
38
+ args: process.argv.slice(2),
39
+ options: {
40
+ category: { type: 'string' },
41
+ framework: { type: 'string' },
42
+ help: { short: 'h', type: 'boolean' },
43
+ language: { type: 'string' },
44
+ name: { type: 'string' },
45
+ slots: { type: 'string' },
46
+ version: { short: 'v', type: 'boolean' },
47
+ templateVersion: { short: 't', type: 'string' },
48
+ },
49
+ strict: true,
50
+ });
51
+ return values;
52
+ }
53
+ catch (err) {
54
+ console.error(`Failed to parse arguments: ${err instanceof Error ? err.message : 'unknown error'}\n`);
55
+ console.log(HELP);
56
+ process.exit(1);
57
+ }
58
+ };
59
+ const resolveName = (flagValue) => {
60
+ if (flagValue) {
61
+ const result = validateName(flagValue);
62
+ if (result !== true) {
63
+ throw new AppError(result);
64
+ }
65
+ return Promise.resolve(flagValue.trim());
66
+ }
67
+ return input({
68
+ message: 'Project name:',
69
+ validate: validateName,
70
+ });
71
+ };
72
+ const resolveCategory = (flagValue) => {
73
+ if (flagValue) {
74
+ if (!getIsValidCategory(flagValue)) {
75
+ throw new AppError(`Invalid category "${flagValue}". Choose one of: ${CATEGORIES.join(', ')}`);
76
+ }
77
+ return Promise.resolve(flagValue);
78
+ }
79
+ return select({
80
+ choices: CATEGORIES.map((cat) => ({
81
+ name: CATEGORY_LABELS[cat],
82
+ value: cat,
83
+ })),
84
+ message: 'Extension category:',
85
+ });
86
+ };
87
+ const composeSlotsValidationErrorMessage = (invalid, violations, optional) => {
88
+ const errorMsgs = [];
89
+ if (invalid.length > 0) {
90
+ if (optional.length === 0) {
91
+ errorMsgs.push(`Invalid slot(s): "${invalid.join(', ')}". This category doesn't have optional slots.`);
92
+ }
93
+ else {
94
+ errorMsgs.push(`Invalid slot(s) "${invalid.join(', ')}". Choose from: ${optional.join(', ')}.`);
95
+ }
96
+ }
97
+ if (violations.length > 0) {
98
+ errorMsgs.push(violations.join(' '));
99
+ }
100
+ return errorMsgs.join(' ');
101
+ };
102
+ const validateCheckboxSlotsSelection = (category, slots) => {
103
+ const rules = SLOT_RULES_BY_CATEGORY[category];
104
+ const { invalid, violations } = validateSlots(slots, category);
105
+ if (invalid.length || violations.length) {
106
+ return composeSlotsValidationErrorMessage(invalid, violations, rules.optional);
107
+ }
108
+ return undefined;
109
+ };
110
+ const normalizePromptSlots = (value) => value.flatMap((item) => {
111
+ if (typeof item === 'string') {
112
+ return [item];
113
+ }
114
+ if (typeof item === 'object' && item !== null && 'value' in item && typeof item.value === 'string') {
115
+ return [item.value];
116
+ }
117
+ return [];
118
+ });
119
+ const resolveSlots = async (flagValue, category) => {
120
+ const requiredSlots = [...SLOT_RULES_BY_CATEGORY[category].requiredBase];
121
+ const optionalSlots = [...SLOT_RULES_BY_CATEGORY[category].optional];
122
+ if (flagValue !== undefined) {
123
+ const requestedSlots = flagValue.split(',').map((s) => s.trim()).filter(s => !!s);
124
+ const { invalid, selected: selectedSlots, violations } = validateSlots([...requiredSlots, ...requestedSlots], category);
125
+ if (violations.length || invalid.length) {
126
+ throw new AppError(composeSlotsValidationErrorMessage(invalid, violations, optionalSlots));
127
+ }
128
+ return [...requiredSlots, ...selectedSlots];
129
+ }
130
+ if (!optionalSlots.length) {
131
+ return requiredSlots;
132
+ }
133
+ const selectedSlots = await checkbox({
134
+ choices: optionalSlots.map((slot) => ({
135
+ checked: false,
136
+ name: SLOT_LABELS[slot],
137
+ value: slot,
138
+ })),
139
+ message: 'Select optional slots:',
140
+ required: false,
141
+ validate: (value) => validateCheckboxSlotsSelection(category, [...requiredSlots, ...normalizePromptSlots(value)]) ?? true,
142
+ });
143
+ return [...requiredSlots, ...selectedSlots];
144
+ };
145
+ const resolveFramework = (flagValue, category) => {
146
+ if (category === 'chat-bots') {
147
+ return Promise.resolve('vanilla');
148
+ }
149
+ if (flagValue) {
150
+ if (!getIsValidFramework(flagValue)) {
151
+ throw new AppError(`Invalid framework "${flagValue}". Choose one of: ${FRAMEWORKS.join(', ')}`);
152
+ }
153
+ return Promise.resolve(flagValue);
154
+ }
155
+ return select({
156
+ choices: FRAMEWORKS.map((framework) => ({
157
+ name: FRAMEWORK_LABELS[framework],
158
+ value: framework,
159
+ })),
160
+ message: 'UI framework:',
161
+ });
162
+ };
163
+ const resolveLanguage = (flagValue) => {
164
+ if (flagValue) {
165
+ if (!getIsValidLanguage(flagValue)) {
166
+ throw new AppError(`Invalid language "${flagValue}". Choose one of: ${LANGUAGES.join(', ')}`);
167
+ }
168
+ return Promise.resolve(flagValue);
169
+ }
170
+ return select({
171
+ choices: LANGUAGES.map((lang) => ({
172
+ name: LANGUAGE_LABELS[lang],
173
+ value: lang,
174
+ })),
175
+ message: 'Language:',
176
+ });
177
+ };
178
+ const resolveProjectDir = (projectName) => {
179
+ const dir = join(process.cwd(), projectName);
180
+ if (existsSync(dir)) {
181
+ throw new AppError(`Project dir ${dir} already exists`);
182
+ }
183
+ return dir;
184
+ };
185
+ const resolveTemplateVersion = (flagValue) => {
186
+ let templateVersion = Number(flagValue);
187
+ if (!templateVersion || !isFinite(templateVersion)) {
188
+ templateVersion = LAST_TEMPLATE_VERSION;
189
+ }
190
+ return templateVersion;
191
+ };
192
+ const main = async () => {
193
+ const opts = parseCliArgs();
194
+ if (opts.help) {
195
+ console.log(HELP);
196
+ process.exit(0);
197
+ }
198
+ if (opts.version) {
199
+ console.log(packageJson.version);
200
+ process.exit(0);
201
+ }
202
+ const name = await resolveName(opts.name);
203
+ const category = await resolveCategory(opts.category);
204
+ const slots = await resolveSlots(opts.slots, category);
205
+ const framework = await resolveFramework(opts.framework, category);
206
+ const language = await resolveLanguage(opts.language);
207
+ const projectDir = resolveProjectDir(name);
208
+ const templateVersion = resolveTemplateVersion(opts.templateVersion);
209
+ console.log(`\nCreating project in ./${name}...\n`);
210
+ const projectConfig = buildProjectConfig({
211
+ name,
212
+ category,
213
+ slots,
214
+ framework,
215
+ language,
216
+ packageManager: detectPackageManagerRuntime(),
217
+ extHelperVersion: EXT_HELPER_VERSION,
218
+ lastTemplateVersion: templateVersion,
219
+ cliCommands: CLI_COMMANDS_MAP,
220
+ managedTemplates: MANAGED_TEMPLATES,
221
+ templatesDir: TEMPLATES_DIR,
222
+ });
223
+ const templateData = mapProjectConfigToTemplateData(projectConfig);
224
+ const commands = planProject(projectDir, templateVersion, templateData);
225
+ executeCommands(commands, (command) => console.log(` Created ${command.destPath}`));
226
+ console.log('\nDone! Next steps:\n');
227
+ console.log(` cd ${name}`);
228
+ console.log(` ${templateData.packageManagerCommands.install}`);
229
+ console.log(` ${templateData.packageManagerCommands.dev}\n`);
230
+ };
231
+ main().catch((err) => {
232
+ if (err.name === 'ExitPromptError') {
233
+ console.log('\nAborted.');
234
+ process.exit(0);
235
+ }
236
+ console.error(err);
237
+ process.exit(1);
238
+ });
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stripchatdev/create-stripchat-extension",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -22,7 +22,10 @@
22
22
  "preferUnplugged": true,
23
23
  "dependencies": {
24
24
  "@inquirer/prompts": "8.3.2",
25
- "ejs": "3.1.10"
25
+ "diff": "9.0.0",
26
+ "ejs": "3.1.10",
27
+ "ts-morph": "28.0.0",
28
+ "type-fest": "5.8.0"
26
29
  },
27
30
  "devDependencies": {
28
31
  "@types/ejs": "3.1.5",
@@ -1,19 +1,24 @@
1
- import type { TCategory, TCategorySlotRules, TPackageManager, TSlot } from './types.js';
1
+ import type { TCategory, TCategorySlotRules, TPackageManager, TPackageManagerCommands, TSlot } from './types';
2
+ export declare const VERSION: string;
2
3
  export declare const EXT_HELPER_VERSION: string;
3
- export declare const CATEGORIES: TCategory[];
4
+ export declare const CATEGORIES: readonly ["games-and-fun", "sex-toys", "chat-bots", "broadcast-tools"];
4
5
  export declare const CATEGORY_LABELS: Record<TCategory, string>;
6
+ export declare const SLOTS: readonly ["EXTENSION_SLOT_MAIN_GAME_FUN", "EXTENSION_SLOT_MAIN_SEX_TOY", "EXTENSION_SLOT_RIGHT_OVERLAY", "EXTENSION_SLOT_VIDEO_DECORATIVE_OVERLAY", "EXTENSION_SLOT_MOVEABLE_OVERLAY", "EXTENSION_SLOT_BACKGROUND"];
5
7
  export declare const SLOT_RULES_BY_CATEGORY: Record<TCategory, TCategorySlotRules>;
6
- export declare const REQUIRED_SLOTS_BY_CATEGORY: Record<TCategory, TSlot[]>;
7
- export declare const SELECTABLE_SLOTS_BY_CATEGORY: Record<TCategory, TSlot[]>;
8
8
  export declare const SLOT_LABELS: Record<TSlot, string>;
9
9
  export declare const FRAMEWORKS: readonly ["preact", "vanilla"];
10
10
  export declare const FRAMEWORK_LABELS: Record<(typeof FRAMEWORKS)[number], string>;
11
11
  export declare const LANGUAGES: readonly ["ts", "js"];
12
12
  export declare const LANGUAGE_LABELS: Record<(typeof LANGUAGES)[number], string>;
13
13
  export declare const JSX_FRAMEWORKS: string[];
14
- export declare const PACKAGE_MANAGER_COMMANDS_MAP: Record<TPackageManager, {
15
- build: string;
16
- dev: string;
17
- install: string;
18
- }>;
14
+ export declare const PACKAGE_MANAGERS: readonly ["npm", "yarn", "pnpm", "bun"];
15
+ export declare const PACKAGE_MANAGER_LOCK_FILE_MAP: Record<TPackageManager, string>;
16
+ export declare const PACKAGE_MANAGER_COMMANDS_MAP: Record<TPackageManager, TPackageManagerCommands>;
17
+ export declare const CLI_COMMANDS_MAP: Record<string, string>;
19
18
  export declare const TS_ONLY_FILES: string[];
19
+ export declare const PROJECT_CONFIG_REL_PATH = ".project-config.json";
20
+ export declare const AGENTS_MD_REL_PATH = "AGENTS.md";
21
+ export declare const PACKAGE_JSON_REL_PATH = "package.json";
22
+ export declare const VITE_CONFIG_REL_PATH_BY_LANGUAGE: Record<(typeof LANGUAGES)[number], string>;
23
+ export declare const AGENTS_TEMPLATE_START = "<!-- AUTO-GENERATED SECTION START -->";
24
+ export declare const AGENTS_TEMPLATE_END = "<!-- AUTO-GENERATED SECTION END -->";
@@ -1,5 +1,5 @@
1
- // All packages use the same versioning
2
- import packageJson from '../package.json' with { type: 'json' };
1
+ import packageJson from '../package.json';
2
+ export const VERSION = packageJson.version;
3
3
  export const EXT_HELPER_VERSION = packageJson.version;
4
4
  export const CATEGORIES = ['games-and-fun', 'sex-toys', 'chat-bots', 'broadcast-tools'];
5
5
  export const CATEGORY_LABELS = {
@@ -8,6 +8,14 @@ export const CATEGORY_LABELS = {
8
8
  'chat-bots': 'Chat Bots',
9
9
  'broadcast-tools': 'Broadcast Tools',
10
10
  };
11
+ export const SLOTS = [
12
+ 'EXTENSION_SLOT_MAIN_GAME_FUN',
13
+ 'EXTENSION_SLOT_MAIN_SEX_TOY',
14
+ 'EXTENSION_SLOT_RIGHT_OVERLAY',
15
+ 'EXTENSION_SLOT_VIDEO_DECORATIVE_OVERLAY',
16
+ 'EXTENSION_SLOT_MOVEABLE_OVERLAY',
17
+ 'EXTENSION_SLOT_BACKGROUND',
18
+ ];
11
19
  export const SLOT_RULES_BY_CATEGORY = {
12
20
  'games-and-fun': {
13
21
  groups: [
@@ -44,8 +52,6 @@ export const SLOT_RULES_BY_CATEGORY = {
44
52
  requiredBase: ['EXTENSION_SLOT_BACKGROUND'],
45
53
  },
46
54
  };
47
- export const REQUIRED_SLOTS_BY_CATEGORY = Object.fromEntries(Object.entries(SLOT_RULES_BY_CATEGORY).map(([category, rules]) => [category, rules.requiredBase]));
48
- export const SELECTABLE_SLOTS_BY_CATEGORY = Object.fromEntries(Object.entries(SLOT_RULES_BY_CATEGORY).map(([category, rules]) => [category, rules.optional]));
49
55
  export const SLOT_LABELS = {
50
56
  EXTENSION_SLOT_BACKGROUND: 'background',
51
57
  EXTENSION_SLOT_MAIN_GAME_FUN: 'mainGameFun',
@@ -65,10 +71,49 @@ export const LANGUAGE_LABELS = {
65
71
  ts: 'TypeScript (Recommended)',
66
72
  };
67
73
  export const JSX_FRAMEWORKS = ['preact'];
74
+ export const PACKAGE_MANAGERS = ['npm', 'yarn', 'pnpm', 'bun'];
75
+ export const PACKAGE_MANAGER_LOCK_FILE_MAP = {
76
+ 'npm': 'package-lock.json',
77
+ 'yarn': 'yarn.lock',
78
+ 'pnpm': 'pnpm-lock.yaml',
79
+ 'bun': 'bun.lock',
80
+ };
68
81
  export const PACKAGE_MANAGER_COMMANDS_MAP = {
69
- npm: { build: 'npm run build', dev: 'npm run dev', install: 'npm install' },
70
- yarn: { build: 'yarn build', dev: 'yarn dev', install: 'yarn' },
71
- pnpm: { build: 'pnpm build', dev: 'pnpm dev', install: 'pnpm install' },
72
- bun: { build: 'bun run build', dev: 'bun dev', install: 'bun install' },
82
+ npm: {
83
+ build: 'npm run build',
84
+ dev: 'npm run dev',
85
+ install: 'npm install',
86
+ templateUpdate: 'npm run template:update',
87
+ },
88
+ yarn: {
89
+ build: 'yarn build',
90
+ dev: 'yarn dev',
91
+ install: 'yarn',
92
+ templateUpdate: 'npm run template:update',
93
+ },
94
+ pnpm: {
95
+ build: 'pnpm build',
96
+ dev: 'pnpm dev',
97
+ install: 'pnpm install',
98
+ templateUpdate: 'npm run template:update',
99
+ },
100
+ bun: {
101
+ build: 'bun run build',
102
+ dev: 'bun dev',
103
+ install: 'bun install',
104
+ templateUpdate: 'npm run template:update',
105
+ },
106
+ };
107
+ export const CLI_COMMANDS_MAP = {
108
+ 'template:update': `npm exec --package=@stripchatdev/create-stripchat-extension@${packageJson.version} -- cli update`,
73
109
  };
74
110
  export const TS_ONLY_FILES = ['tsconfig.json'];
111
+ export const PROJECT_CONFIG_REL_PATH = '.project-config.json';
112
+ export const AGENTS_MD_REL_PATH = 'AGENTS.md';
113
+ export const PACKAGE_JSON_REL_PATH = 'package.json';
114
+ export const VITE_CONFIG_REL_PATH_BY_LANGUAGE = {
115
+ js: 'vite.config.js',
116
+ ts: 'vite.config.ts',
117
+ };
118
+ export const AGENTS_TEMPLATE_START = '<!-- AUTO-GENERATED SECTION START -->';
119
+ export const AGENTS_TEMPLATE_END = '<!-- AUTO-GENERATED SECTION END -->';
@@ -0,0 +1,2 @@
1
+ export declare const DEPENDENCIES: Record<string, string>;
2
+ export declare const DEV_DEPENDENCIES: Record<string, string>;
@@ -0,0 +1,11 @@
1
+ import packageJson from '../../package.json' with { type: 'json' };
2
+ export const DEPENDENCIES = {
3
+ '@stripchatdev/ext-helper': packageJson.version,
4
+ 'preact': '10.25.4',
5
+ };
6
+ export const DEV_DEPENDENCIES = {
7
+ 'vite': '6.4.2',
8
+ 'typescript': '5.8.2',
9
+ '@preact/preset-vite': '2.10.5',
10
+ '@stripchatdev/create-stripchat-extension': packageJson.version,
11
+ };
@@ -0,0 +1,6 @@
1
+ import type { TFramework, TLanguage, TPackageDependenciesMap } from '../types.js';
2
+ export declare const resolveMainDependencies: (framework: TFramework) => TPackageDependenciesMap;
3
+ export declare const resolveDependencies: (language: TLanguage, framework: TFramework) => {
4
+ dependencies: TPackageDependenciesMap;
5
+ devDependencies: TPackageDependenciesMap;
6
+ };
@@ -0,0 +1,43 @@
1
+ import { getIsJsxFramework } from '../helpers/getIsJsxFramework.js';
2
+ import { getIsTypescript } from '../helpers/getIsTypescript.js';
3
+ import { DEPENDENCIES, DEV_DEPENDENCIES } from './constants.js';
4
+ export const resolveMainDependencies = (framework) => {
5
+ const depsMap = {};
6
+ const isJsx = getIsJsxFramework(framework);
7
+ for (const packageName in DEPENDENCIES) {
8
+ const packageVersion = DEPENDENCIES[packageName];
9
+ if (!packageVersion) {
10
+ continue;
11
+ }
12
+ if (packageName === 'preact' && !isJsx) {
13
+ continue;
14
+ }
15
+ depsMap[packageName] = packageVersion;
16
+ }
17
+ return depsMap;
18
+ };
19
+ const resolveDevDependencies = (language, framework) => {
20
+ const depsMap = {};
21
+ const isTypescript = getIsTypescript(language);
22
+ const isJsx = getIsJsxFramework(framework);
23
+ for (const packageName in DEV_DEPENDENCIES) {
24
+ const packageVersion = DEV_DEPENDENCIES[packageName];
25
+ if (!packageVersion) {
26
+ continue;
27
+ }
28
+ if (packageName === 'typescript' && !isTypescript) {
29
+ continue;
30
+ }
31
+ if (packageName === '@preact/preset-vite' && !isJsx) {
32
+ continue;
33
+ }
34
+ depsMap[packageName] = packageVersion;
35
+ }
36
+ return depsMap;
37
+ };
38
+ export const resolveDependencies = (language, framework) => {
39
+ return {
40
+ dependencies: resolveMainDependencies(framework),
41
+ devDependencies: resolveDevDependencies(language, framework),
42
+ };
43
+ };
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { DEPENDENCIES, DEV_DEPENDENCIES } from './constants.js';
3
+ import { resolveDependencies } from './resolveDependencies.js';
4
+ const EXPECTED_EXT_HELPER = DEPENDENCIES['@stripchatdev/ext-helper'];
5
+ const EXPECTED_VITE = DEV_DEPENDENCIES.vite;
6
+ const EXPECTED_TYPESCRIPT = DEV_DEPENDENCIES.typescript;
7
+ const EXPECTED_PREACT = DEPENDENCIES.preact;
8
+ const EXPECTED_PREACT_PRESET_VITE = DEV_DEPENDENCIES['@preact/preset-vite'];
9
+ const EXPECTED_CREATE_STRIPCHAT_EXTENSION = DEV_DEPENDENCIES['@stripchatdev/create-stripchat-extension'];
10
+ const TEST_CASES = [
11
+ {
12
+ framework: 'vanilla',
13
+ language: 'js',
14
+ expected: {
15
+ dependencies: {
16
+ '@stripchatdev/ext-helper': EXPECTED_EXT_HELPER,
17
+ },
18
+ devDependencies: {
19
+ vite: EXPECTED_VITE,
20
+ '@stripchatdev/create-stripchat-extension': EXPECTED_CREATE_STRIPCHAT_EXTENSION,
21
+ },
22
+ },
23
+ },
24
+ {
25
+ framework: 'vanilla',
26
+ language: 'ts',
27
+ expected: {
28
+ dependencies: {
29
+ '@stripchatdev/ext-helper': EXPECTED_EXT_HELPER,
30
+ },
31
+ devDependencies: {
32
+ typescript: EXPECTED_TYPESCRIPT,
33
+ vite: EXPECTED_VITE,
34
+ '@stripchatdev/create-stripchat-extension': EXPECTED_CREATE_STRIPCHAT_EXTENSION,
35
+ },
36
+ },
37
+ },
38
+ {
39
+ framework: 'preact',
40
+ language: 'js',
41
+ expected: {
42
+ dependencies: {
43
+ '@stripchatdev/ext-helper': EXPECTED_EXT_HELPER,
44
+ preact: EXPECTED_PREACT,
45
+ },
46
+ devDependencies: {
47
+ '@preact/preset-vite': EXPECTED_PREACT_PRESET_VITE,
48
+ vite: EXPECTED_VITE,
49
+ '@stripchatdev/create-stripchat-extension': EXPECTED_CREATE_STRIPCHAT_EXTENSION,
50
+ },
51
+ },
52
+ },
53
+ {
54
+ framework: 'preact',
55
+ language: 'ts',
56
+ expected: {
57
+ dependencies: {
58
+ '@stripchatdev/ext-helper': EXPECTED_EXT_HELPER,
59
+ preact: EXPECTED_PREACT,
60
+ },
61
+ devDependencies: {
62
+ '@preact/preset-vite': EXPECTED_PREACT_PRESET_VITE,
63
+ typescript: EXPECTED_TYPESCRIPT,
64
+ vite: EXPECTED_VITE,
65
+ '@stripchatdev/create-stripchat-extension': EXPECTED_CREATE_STRIPCHAT_EXTENSION,
66
+ },
67
+ },
68
+ },
69
+ ];
70
+ describe('resolveDependencies', () => {
71
+ it.each(TEST_CASES)('$language + $framework dependencies', ({ expected, framework, language }) => {
72
+ expect(resolveDependencies(language, framework)).toEqual(expected);
73
+ });
74
+ });
@@ -0,0 +1,3 @@
1
+ export declare class AppError extends Error {
2
+ constructor(message: string, cause?: Error);
3
+ }