@jakubmazanec/carson 0.1.0-9029e49

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 (307) hide show
  1. package/LICENSE.md +661 -0
  2. package/README.md +237 -0
  3. package/bin/carson.js +3 -0
  4. package/dist/commands/create-project/CreateProject.d.ts +8 -0
  5. package/dist/commands/create-project/CreateProject.js +138 -0
  6. package/dist/commands/create-project/CreateProject.js.map +1 -0
  7. package/dist/commands/create-project/CreateProjectInput.d.ts +20 -0
  8. package/dist/commands/create-project/CreateProjectInput.js +31 -0
  9. package/dist/commands/create-project/CreateProjectInput.js.map +1 -0
  10. package/dist/commands/create-project/createProjectCommand.d.ts +12 -0
  11. package/dist/commands/create-project/createProjectCommand.js +31 -0
  12. package/dist/commands/create-project/createProjectCommand.js.map +1 -0
  13. package/dist/commands/create-project/runCreateProject.d.ts +13 -0
  14. package/dist/commands/create-project/runCreateProject.js +34 -0
  15. package/dist/commands/create-project/runCreateProject.js.map +1 -0
  16. package/dist/commands/create-project.d.ts +4 -0
  17. package/dist/commands/create-project.js +6 -0
  18. package/dist/commands/create-project.js.map +1 -0
  19. package/dist/commands/create-workspace/CreateWorkspace.d.ts +7 -0
  20. package/dist/commands/create-workspace/CreateWorkspace.js +102 -0
  21. package/dist/commands/create-workspace/CreateWorkspace.js.map +1 -0
  22. package/dist/commands/create-workspace/CreateWorkspaceInput.d.ts +11 -0
  23. package/dist/commands/create-workspace/CreateWorkspaceInput.js +17 -0
  24. package/dist/commands/create-workspace/CreateWorkspaceInput.js.map +1 -0
  25. package/dist/commands/create-workspace/createWorkspaceCommand.d.ts +9 -0
  26. package/dist/commands/create-workspace/createWorkspaceCommand.js +30 -0
  27. package/dist/commands/create-workspace/createWorkspaceCommand.js.map +1 -0
  28. package/dist/commands/create-workspace/runCreateWorkspace.d.ts +10 -0
  29. package/dist/commands/create-workspace/runCreateWorkspace.js +33 -0
  30. package/dist/commands/create-workspace/runCreateWorkspace.js.map +1 -0
  31. package/dist/commands/create-workspace.d.ts +4 -0
  32. package/dist/commands/create-workspace.js +6 -0
  33. package/dist/commands/create-workspace.js.map +1 -0
  34. package/dist/commands/internals/packageNameToDirectory.d.ts +1 -0
  35. package/dist/commands/internals/packageNameToDirectory.js +12 -0
  36. package/dist/commands/internals/packageNameToDirectory.js.map +1 -0
  37. package/dist/commands/internals.d.ts +1 -0
  38. package/dist/commands/internals.js +3 -0
  39. package/dist/commands/internals.js.map +1 -0
  40. package/dist/commands/update-workspace/UpdateWorkspace.d.ts +8 -0
  41. package/dist/commands/update-workspace/UpdateWorkspace.js +71 -0
  42. package/dist/commands/update-workspace/UpdateWorkspace.js.map +1 -0
  43. package/dist/commands/update-workspace/runUpdateWorkspace.d.ts +10 -0
  44. package/dist/commands/update-workspace/runUpdateWorkspace.js +25 -0
  45. package/dist/commands/update-workspace/runUpdateWorkspace.js.map +1 -0
  46. package/dist/commands/update-workspace/updateWorkspaceCommand.d.ts +6 -0
  47. package/dist/commands/update-workspace/updateWorkspaceCommand.js +25 -0
  48. package/dist/commands/update-workspace/updateWorkspaceCommand.js.map +1 -0
  49. package/dist/commands/update-workspace.d.ts +3 -0
  50. package/dist/commands/update-workspace.js +5 -0
  51. package/dist/commands/update-workspace.js.map +1 -0
  52. package/dist/commands.d.ts +3 -0
  53. package/dist/commands.js +5 -0
  54. package/dist/commands.js.map +1 -0
  55. package/dist/constants.d.ts +7 -0
  56. package/dist/constants.js +16 -0
  57. package/dist/constants.js.map +1 -0
  58. package/dist/main.d.ts +3 -0
  59. package/dist/main.js +5 -0
  60. package/dist/main.js.map +1 -0
  61. package/dist/modules.d.js +2 -0
  62. package/dist/modules.d.js.map +1 -0
  63. package/dist/run.d.ts +1 -0
  64. package/dist/run.js +18 -0
  65. package/dist/run.js.map +1 -0
  66. package/dist/template/CarsonTemplate.d.ts +9 -0
  67. package/dist/template/CarsonTemplate.js +3 -0
  68. package/dist/template/CarsonTemplate.js.map +1 -0
  69. package/dist/template/CarsonTemplateConfig.d.ts +12 -0
  70. package/dist/template/CarsonTemplateConfig.js +7 -0
  71. package/dist/template/CarsonTemplateConfig.js.map +1 -0
  72. package/dist/template/TemplateAttributes.d.ts +9 -0
  73. package/dist/template/TemplateAttributes.js +16 -0
  74. package/dist/template/TemplateAttributes.js.map +1 -0
  75. package/dist/template/TemplateData.d.ts +35 -0
  76. package/dist/template/TemplateData.js +13 -0
  77. package/dist/template/TemplateData.js.map +1 -0
  78. package/dist/template/TemplateRender.d.ts +4 -0
  79. package/dist/template/TemplateRender.js +3 -0
  80. package/dist/template/TemplateRender.js.map +1 -0
  81. package/dist/template/TemplateRenderSnapshot.d.ts +27 -0
  82. package/dist/template/TemplateRenderSnapshot.js +11 -0
  83. package/dist/template/TemplateRenderSnapshot.js.map +1 -0
  84. package/dist/template/TemplateRenderSnapshots.d.ts +27 -0
  85. package/dist/template/TemplateRenderSnapshots.js +4 -0
  86. package/dist/template/TemplateRenderSnapshots.js.map +1 -0
  87. package/dist/template/TemplateRenders.d.ts +2 -0
  88. package/dist/template/TemplateRenders.js +3 -0
  89. package/dist/template/TemplateRenders.js.map +1 -0
  90. package/dist/template/applyTemplateRenders.d.ts +8 -0
  91. package/dist/template/applyTemplateRenders.js +60 -0
  92. package/dist/template/applyTemplateRenders.js.map +1 -0
  93. package/dist/template/createFileUsingTemplateRender.d.ts +2 -0
  94. package/dist/template/createFileUsingTemplateRender.js +12 -0
  95. package/dist/template/createFileUsingTemplateRender.js.map +1 -0
  96. package/dist/template/deleteFileUsingTemplateRender.d.ts +2 -0
  97. package/dist/template/deleteFileUsingTemplateRender.js +10 -0
  98. package/dist/template/deleteFileUsingTemplateRender.js.map +1 -0
  99. package/dist/template/importCarsonTemplate.d.ts +3 -0
  100. package/dist/template/importCarsonTemplate.js +8 -0
  101. package/dist/template/importCarsonTemplate.js.map +1 -0
  102. package/dist/template/insertUsingTemplateRender.d.ts +2 -0
  103. package/dist/template/insertUsingTemplateRender.js +29 -0
  104. package/dist/template/insertUsingTemplateRender.js.map +1 -0
  105. package/dist/template/internals/merge.d.ts +4 -0
  106. package/dist/template/internals/merge.js +30 -0
  107. package/dist/template/internals/merge.js.map +1 -0
  108. package/dist/template/internals/prettify.d.ts +1 -0
  109. package/dist/template/internals/prettify.js +25 -0
  110. package/dist/template/internals/prettify.js.map +1 -0
  111. package/dist/template/internals/unmerge.d.ts +4 -0
  112. package/dist/template/internals/unmerge.js +31 -0
  113. package/dist/template/internals/unmerge.js.map +1 -0
  114. package/dist/template/internals.d.ts +3 -0
  115. package/dist/template/internals.js +5 -0
  116. package/dist/template/internals.js.map +1 -0
  117. package/dist/template/loadTemplateRenderSnapshots.d.ts +7 -0
  118. package/dist/template/loadTemplateRenderSnapshots.js +14 -0
  119. package/dist/template/loadTemplateRenderSnapshots.js.map +1 -0
  120. package/dist/template/mergeFileUsingTemplateRender.d.ts +2 -0
  121. package/dist/template/mergeFileUsingTemplateRender.js +39 -0
  122. package/dist/template/mergeFileUsingTemplateRender.js.map +1 -0
  123. package/dist/template/overwriteFileUsingTemplateRender.d.ts +2 -0
  124. package/dist/template/overwriteFileUsingTemplateRender.js +12 -0
  125. package/dist/template/overwriteFileUsingTemplateRender.js.map +1 -0
  126. package/dist/template/parseTemplateId.d.ts +1 -0
  127. package/dist/template/parseTemplateId.js +12 -0
  128. package/dist/template/parseTemplateId.js.map +1 -0
  129. package/dist/template/readCarsonTemplate.d.ts +2 -0
  130. package/dist/template/readCarsonTemplate.js +39 -0
  131. package/dist/template/readCarsonTemplate.js.map +1 -0
  132. package/dist/template/renderTemplate.d.ts +7 -0
  133. package/dist/template/renderTemplate.js +19 -0
  134. package/dist/template/renderTemplate.js.map +1 -0
  135. package/dist/template/resolveTemplateModule.d.ts +1 -0
  136. package/dist/template/resolveTemplateModule.js +9 -0
  137. package/dist/template/resolveTemplateModule.js.map +1 -0
  138. package/dist/template/saveTemplateRenderSnapshots.d.ts +2 -0
  139. package/dist/template/saveTemplateRenderSnapshots.js +23 -0
  140. package/dist/template/saveTemplateRenderSnapshots.js.map +1 -0
  141. package/dist/template/uninsertUsingTemplateRender.d.ts +2 -0
  142. package/dist/template/uninsertUsingTemplateRender.js +29 -0
  143. package/dist/template/uninsertUsingTemplateRender.js.map +1 -0
  144. package/dist/template/unmergeFileUsingTemplateRender.d.ts +2 -0
  145. package/dist/template/unmergeFileUsingTemplateRender.js +39 -0
  146. package/dist/template/unmergeFileUsingTemplateRender.js.map +1 -0
  147. package/dist/template.d.ts +20 -0
  148. package/dist/template.js +22 -0
  149. package/dist/template.js.map +1 -0
  150. package/dist/workspace/Project.d.ts +33 -0
  151. package/dist/workspace/Project.js +184 -0
  152. package/dist/workspace/Project.js.map +1 -0
  153. package/dist/workspace/ProjectConfig.d.ts +9 -0
  154. package/dist/workspace/ProjectConfig.js +6 -0
  155. package/dist/workspace/ProjectConfig.js.map +1 -0
  156. package/dist/workspace/ProjectCreateOptions.d.ts +8 -0
  157. package/dist/workspace/ProjectCreateOptions.js +3 -0
  158. package/dist/workspace/ProjectCreateOptions.js.map +1 -0
  159. package/dist/workspace/ProjectError.d.ts +8 -0
  160. package/dist/workspace/ProjectError.js +11 -0
  161. package/dist/workspace/ProjectError.js.map +1 -0
  162. package/dist/workspace/ProjectOptions.d.ts +15 -0
  163. package/dist/workspace/ProjectOptions.js +3 -0
  164. package/dist/workspace/ProjectOptions.js.map +1 -0
  165. package/dist/workspace/ProjectUpdateOptions.d.ts +3 -0
  166. package/dist/workspace/ProjectUpdateOptions.js +3 -0
  167. package/dist/workspace/ProjectUpdateOptions.js.map +1 -0
  168. package/dist/workspace/Workspace.d.ts +68 -0
  169. package/dist/workspace/Workspace.js +426 -0
  170. package/dist/workspace/Workspace.js.map +1 -0
  171. package/dist/workspace/WorkspaceConfig.d.ts +9 -0
  172. package/dist/workspace/WorkspaceConfig.js +6 -0
  173. package/dist/workspace/WorkspaceConfig.js.map +1 -0
  174. package/dist/workspace/WorkspaceCreateOptions.d.ts +5 -0
  175. package/dist/workspace/WorkspaceCreateOptions.js +3 -0
  176. package/dist/workspace/WorkspaceCreateOptions.js.map +1 -0
  177. package/dist/workspace/WorkspaceCreateProjectOptions.d.ts +6 -0
  178. package/dist/workspace/WorkspaceCreateProjectOptions.js +3 -0
  179. package/dist/workspace/WorkspaceCreateProjectOptions.js.map +1 -0
  180. package/dist/workspace/WorkspaceDependencies.d.ts +30 -0
  181. package/dist/workspace/WorkspaceDependencies.js +126 -0
  182. package/dist/workspace/WorkspaceDependencies.js.map +1 -0
  183. package/dist/workspace/WorkspaceError.d.ts +8 -0
  184. package/dist/workspace/WorkspaceError.js +13 -0
  185. package/dist/workspace/WorkspaceError.js.map +1 -0
  186. package/dist/workspace/WorkspaceOptions.d.ts +25 -0
  187. package/dist/workspace/WorkspaceOptions.js +3 -0
  188. package/dist/workspace/WorkspaceOptions.js.map +1 -0
  189. package/dist/workspace/WorkspaceOptionsProjectOptions.d.ts +7 -0
  190. package/dist/workspace/WorkspaceOptionsProjectOptions.js +3 -0
  191. package/dist/workspace/WorkspaceOptionsProjectOptions.js.map +1 -0
  192. package/dist/workspace/WorkspacePackageJson.d.ts +2 -0
  193. package/dist/workspace/WorkspacePackageJson.js +3 -0
  194. package/dist/workspace/WorkspacePackageJson.js.map +1 -0
  195. package/dist/workspace/WorkspaceProjectGlobs.d.ts +1 -0
  196. package/dist/workspace/WorkspaceProjectGlobs.js +3 -0
  197. package/dist/workspace/WorkspaceProjectGlobs.js.map +1 -0
  198. package/dist/workspace/WorkspaceProjects.d.ts +2 -0
  199. package/dist/workspace/WorkspaceProjects.js +3 -0
  200. package/dist/workspace/WorkspaceProjects.js.map +1 -0
  201. package/dist/workspace/WorkspaceRepository.d.ts +4 -0
  202. package/dist/workspace/WorkspaceRepository.js +3 -0
  203. package/dist/workspace/WorkspaceRepository.js.map +1 -0
  204. package/dist/workspace/WorkspaceUpdateOptions.d.ts +3 -0
  205. package/dist/workspace/WorkspaceUpdateOptions.js +3 -0
  206. package/dist/workspace/WorkspaceUpdateOptions.js.map +1 -0
  207. package/dist/workspace/internals/compareSemver.d.ts +8 -0
  208. package/dist/workspace/internals/compareSemver.js +27 -0
  209. package/dist/workspace/internals/compareSemver.js.map +1 -0
  210. package/dist/workspace/internals/getPackageJsonWorkspaces.d.ts +2 -0
  211. package/dist/workspace/internals/getPackageJsonWorkspaces.js +11 -0
  212. package/dist/workspace/internals/getPackageJsonWorkspaces.js.map +1 -0
  213. package/dist/workspace/internals/getRepositoryBranches.d.ts +1 -0
  214. package/dist/workspace/internals/getRepositoryBranches.js +21 -0
  215. package/dist/workspace/internals/getRepositoryBranches.js.map +1 -0
  216. package/dist/workspace/internals/getRepositoryUrl.d.ts +1 -0
  217. package/dist/workspace/internals/getRepositoryUrl.js +21 -0
  218. package/dist/workspace/internals/getRepositoryUrl.js.map +1 -0
  219. package/dist/workspace/internals.d.ts +4 -0
  220. package/dist/workspace/internals.js +6 -0
  221. package/dist/workspace/internals.js.map +1 -0
  222. package/dist/workspace/saveProjectConfig.d.ts +6 -0
  223. package/dist/workspace/saveProjectConfig.js +13 -0
  224. package/dist/workspace/saveProjectConfig.js.map +1 -0
  225. package/dist/workspace/saveWorkspaceConfig.d.ts +6 -0
  226. package/dist/workspace/saveWorkspaceConfig.js +13 -0
  227. package/dist/workspace/saveWorkspaceConfig.js.map +1 -0
  228. package/dist/workspace.d.ts +10 -0
  229. package/dist/workspace.js +12 -0
  230. package/dist/workspace.js.map +1 -0
  231. package/package.json +84 -0
  232. package/src/commands/create-project/CreateProject.tsx +130 -0
  233. package/src/commands/create-project/CreateProjectInput.ts +37 -0
  234. package/src/commands/create-project/createProjectCommand.tsx +33 -0
  235. package/src/commands/create-project/runCreateProject.ts +59 -0
  236. package/src/commands/create-project.ts +4 -0
  237. package/src/commands/create-workspace/CreateWorkspace.tsx +90 -0
  238. package/src/commands/create-workspace/CreateWorkspaceInput.ts +21 -0
  239. package/src/commands/create-workspace/createWorkspaceCommand.tsx +34 -0
  240. package/src/commands/create-workspace/runCreateWorkspace.ts +49 -0
  241. package/src/commands/create-workspace.ts +4 -0
  242. package/src/commands/internals/packageNameToDirectory.ts +13 -0
  243. package/src/commands/internals.ts +1 -0
  244. package/src/commands/update-workspace/UpdateWorkspace.tsx +59 -0
  245. package/src/commands/update-workspace/runUpdateWorkspace.ts +36 -0
  246. package/src/commands/update-workspace/updateWorkspaceCommand.tsx +27 -0
  247. package/src/commands/update-workspace.ts +3 -0
  248. package/src/commands.ts +3 -0
  249. package/src/constants.ts +21 -0
  250. package/src/main.ts +3 -0
  251. package/src/modules.d.ts +1 -0
  252. package/src/run.ts +21 -0
  253. package/src/template/CarsonTemplate.ts +11 -0
  254. package/src/template/CarsonTemplateConfig.ts +12 -0
  255. package/src/template/TemplateAttributes.ts +16 -0
  256. package/src/template/TemplateData.ts +17 -0
  257. package/src/template/TemplateRender.ts +9 -0
  258. package/src/template/TemplateRenderSnapshot.ts +13 -0
  259. package/src/template/TemplateRenderSnapshots.ts +7 -0
  260. package/src/template/TemplateRenders.ts +3 -0
  261. package/src/template/applyTemplateRenders.ts +89 -0
  262. package/src/template/createFileUsingTemplateRender.ts +12 -0
  263. package/src/template/deleteFileUsingTemplateRender.ts +15 -0
  264. package/src/template/importCarsonTemplate.ts +13 -0
  265. package/src/template/insertUsingTemplateRender.ts +33 -0
  266. package/src/template/internals/merge.ts +44 -0
  267. package/src/template/internals/prettify.ts +24 -0
  268. package/src/template/internals/unmerge.ts +48 -0
  269. package/src/template/internals.ts +3 -0
  270. package/src/template/loadTemplateRenderSnapshots.ts +18 -0
  271. package/src/template/mergeFileUsingTemplateRender.ts +39 -0
  272. package/src/template/overwriteFileUsingTemplateRender.ts +12 -0
  273. package/src/template/parseTemplateId.ts +9 -0
  274. package/src/template/readCarsonTemplate.ts +46 -0
  275. package/src/template/renderTemplate.ts +30 -0
  276. package/src/template/resolveTemplateModule.ts +9 -0
  277. package/src/template/saveTemplateRenderSnapshots.ts +34 -0
  278. package/src/template/uninsertUsingTemplateRender.ts +36 -0
  279. package/src/template/unmergeFileUsingTemplateRender.ts +42 -0
  280. package/src/template.ts +20 -0
  281. package/src/workspace/Project.ts +246 -0
  282. package/src/workspace/ProjectConfig.ts +9 -0
  283. package/src/workspace/ProjectCreateOptions.ts +9 -0
  284. package/src/workspace/ProjectError.ts +15 -0
  285. package/src/workspace/ProjectOptions.ts +17 -0
  286. package/src/workspace/ProjectUpdateOptions.ts +3 -0
  287. package/src/workspace/Workspace.ts +553 -0
  288. package/src/workspace/WorkspaceConfig.ts +9 -0
  289. package/src/workspace/WorkspaceCreateOptions.ts +5 -0
  290. package/src/workspace/WorkspaceCreateProjectOptions.ts +6 -0
  291. package/src/workspace/WorkspaceDependencies.ts +196 -0
  292. package/src/workspace/WorkspaceError.ts +18 -0
  293. package/src/workspace/WorkspaceOptions.ts +29 -0
  294. package/src/workspace/WorkspaceOptionsProjectOptions.ts +9 -0
  295. package/src/workspace/WorkspacePackageJson.ts +3 -0
  296. package/src/workspace/WorkspaceProjectGlobs.ts +1 -0
  297. package/src/workspace/WorkspaceProjects.ts +3 -0
  298. package/src/workspace/WorkspaceRepository.ts +4 -0
  299. package/src/workspace/WorkspaceUpdateOptions.ts +3 -0
  300. package/src/workspace/internals/compareSemver.ts +35 -0
  301. package/src/workspace/internals/getPackageJsonWorkspaces.ts +11 -0
  302. package/src/workspace/internals/getRepositoryBranches.ts +25 -0
  303. package/src/workspace/internals/getRepositoryUrl.ts +23 -0
  304. package/src/workspace/internals.ts +4 -0
  305. package/src/workspace/saveProjectConfig.ts +23 -0
  306. package/src/workspace/saveWorkspaceConfig.ts +30 -0
  307. package/src/workspace.ts +10 -0
@@ -0,0 +1,46 @@
1
+ import {Template} from '@jakubmazanec/template';
2
+ import {readFile} from '@jakubmazanec/zod-utils';
3
+ import glob from 'fast-glob';
4
+ import fs from 'fs-extra';
5
+ import path from 'node:path';
6
+
7
+ import {type CarsonTemplate} from './CarsonTemplate.js';
8
+ import {carsonTemplateConfigSchema} from './CarsonTemplateConfig.js';
9
+ import {parseTemplateId} from './parseTemplateId.js';
10
+ import {resolveTemplateModule} from './resolveTemplateModule.js';
11
+ import {templateAttributesSchema} from './TemplateAttributes.js';
12
+ import {TEMPLATES_PATH, TEMPLATE_CONFIG_FILENAME} from '../constants.js';
13
+
14
+ export async function readCarsonTemplate(templateId: string): Promise<CarsonTemplate> {
15
+ let [moduleId, templateName] = parseTemplateId(templateId);
16
+ let modulePath = await resolveTemplateModule(moduleId);
17
+ let carsonTemplatePath = path.join(modulePath, TEMPLATES_PATH, templateName);
18
+
19
+ if (await fs.pathExists(carsonTemplatePath)) {
20
+ let templateConfigPath = path.join(carsonTemplatePath, TEMPLATE_CONFIG_FILENAME);
21
+ let templateConfig = await readFile(templateConfigPath, carsonTemplateConfigSchema, {
22
+ throwOnZodError: true,
23
+ });
24
+ let templateFilePaths = await glob('**/*.ejs', {
25
+ cwd: carsonTemplatePath,
26
+ dot: true,
27
+ });
28
+ let carsonTemplate: CarsonTemplate = {
29
+ name: templateName,
30
+ config: templateConfig,
31
+ files: [],
32
+ };
33
+
34
+ for (let templateFilePath of templateFilePaths) {
35
+ carsonTemplate.files.push(
36
+ await Template.read(path.join(carsonTemplatePath, templateFilePath), {
37
+ attributesSchema: templateAttributesSchema,
38
+ }),
39
+ );
40
+ }
41
+
42
+ return carsonTemplate;
43
+ }
44
+
45
+ throw new Error(`Template ${templateId} was not found in module ${moduleId}!`);
46
+ }
@@ -0,0 +1,30 @@
1
+ import {importCarsonTemplate} from './importCarsonTemplate.js';
2
+ import {readCarsonTemplate} from './readCarsonTemplate.js';
3
+ import {type TemplateData} from './TemplateData.js';
4
+ import {type TemplateRenders} from './TemplateRenders.js';
5
+
6
+ export type RenderTemplateOptions = {
7
+ templateId: string;
8
+ templateData: TemplateData;
9
+ };
10
+
11
+ export async function renderTemplate(options: RenderTemplateOptions) {
12
+ let template = await readCarsonTemplate(options.templateId);
13
+ let templateModule = await importCarsonTemplate(options.templateId);
14
+ let templateRenders: TemplateRenders = [];
15
+
16
+ for (let file of template.files) {
17
+ templateRenders.push(
18
+ ...(await file.render(
19
+ {
20
+ ...templateModule,
21
+ ...options.templateData,
22
+ templateConfig: template.config,
23
+ },
24
+ {disablePrettier: true},
25
+ )),
26
+ );
27
+ }
28
+
29
+ return templateRenders;
30
+ }
@@ -0,0 +1,9 @@
1
+ import {createRequire} from 'node:module';
2
+ import path from 'node:path';
3
+
4
+ export async function resolveTemplateModule(moduleId: string) {
5
+ let require = createRequire(import.meta.url);
6
+ let modulePath = path.dirname(require.resolve(`${moduleId}/package.json`));
7
+
8
+ return modulePath;
9
+ }
@@ -0,0 +1,34 @@
1
+ import {deflateSync, strToU8} from 'fflate';
2
+ import fs from 'fs-extra';
3
+
4
+ import {type TemplateRenders} from './TemplateRenders.js';
5
+ import {type TemplateRenderSnapshots} from './TemplateRenderSnapshots.js';
6
+
7
+ export async function saveTemplateRenderSnapshots(
8
+ templateRenders: TemplateRenders,
9
+ templateRenderSnapshotsPath: string,
10
+ ) {
11
+ let templateRendersSnapshots: TemplateRenderSnapshots = [];
12
+
13
+ for (let templateRender of templateRenders) {
14
+ if (
15
+ templateRender.attributes.strategy === 'overwrite' ||
16
+ templateRender.attributes.strategy === 'merge' ||
17
+ templateRender.attributes.strategy[0] === 'insert'
18
+ ) {
19
+ templateRendersSnapshots.push({
20
+ attributes: {
21
+ to: templateRender.attributes.to,
22
+ strategy: templateRender.attributes.strategy,
23
+ },
24
+ content: templateRender.content,
25
+ });
26
+ }
27
+ }
28
+ let uncompressedSnapshots = JSON.stringify(templateRendersSnapshots);
29
+
30
+ await fs.writeFile(
31
+ templateRenderSnapshotsPath,
32
+ deflateSync(strToU8(uncompressedSnapshots), {level: 1, mem: 0}),
33
+ );
34
+ }
@@ -0,0 +1,36 @@
1
+ import fs from 'fs-extra';
2
+ import _ from 'lodash';
3
+ import path from 'node:path';
4
+
5
+ import {prettify} from './internals.js';
6
+ import {type TemplateRenderSnapshot} from './TemplateRenderSnapshot.js';
7
+
8
+ export async function uninsertUsingTemplateRender(
9
+ render: TemplateRenderSnapshot,
10
+ basePath: string,
11
+ ) {
12
+ let to = path.join(basePath, render.attributes.to);
13
+ let extension = path.extname(to);
14
+
15
+ switch (extension) {
16
+ case '.md': {
17
+ let targetFile = await fs.readFile(to, {encoding: 'utf8'});
18
+ let newContent = `<!-- ${render.attributes.strategy[1]} --><!-- ${render.attributes.strategy[1]} -->`;
19
+ let oldContentRegexp = new RegExp(
20
+ `<!--\\s*${_.escapeRegExp(
21
+ render.attributes.strategy[1],
22
+ )}\\s-->[\\s\\S]*<!--\\s*${_.escapeRegExp(render.attributes.strategy[1])}\\s-->`,
23
+ 'u',
24
+ );
25
+ let newFile = targetFile.replace(oldContentRegexp, newContent);
26
+
27
+ await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});
28
+
29
+ break;
30
+ }
31
+
32
+ default: {
33
+ throw new Error(`File extension "${extension}" is not supported!`);
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,42 @@
1
+ import {type Json} from '@jakubmazanec/zod-utils';
2
+ import fs from 'fs-extra';
3
+ import json from 'json5';
4
+ import path from 'node:path';
5
+ import yaml from 'yaml';
6
+
7
+ import {unmerge, prettify} from './internals.js';
8
+ import {type TemplateRenderSnapshot} from './TemplateRenderSnapshot.js';
9
+
10
+ export async function unmergeFileUsingTemplateRender(
11
+ render: TemplateRenderSnapshot,
12
+ outputPath: string,
13
+ ) {
14
+ let to = path.join(outputPath, render.attributes.to);
15
+ let extension = path.extname(to);
16
+
17
+ switch (extension) {
18
+ case '.json': {
19
+ let targetFile = (await fs.readJson(to)) as Json;
20
+ let fileToMerge = json.parse<Json>(render.content);
21
+ let newFile = JSON.stringify(unmerge(targetFile, fileToMerge));
22
+
23
+ await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});
24
+
25
+ break;
26
+ }
27
+
28
+ case '.yaml': {
29
+ let targetFile = yaml.parse(await fs.readFile(to, {encoding: 'utf8'})) as unknown;
30
+ let fileToMerge = yaml.parse(render.content) as unknown;
31
+ let newFile = yaml.stringify(unmerge(targetFile, fileToMerge));
32
+
33
+ await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});
34
+
35
+ break;
36
+ }
37
+
38
+ default: {
39
+ throw new Error(`File extension "${extension}" is not supported!`);
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,20 @@
1
+ export * from './template/applyTemplateRenders.js';
2
+ export * from './template/CarsonTemplate.js';
3
+ export * from './template/CarsonTemplateConfig.js';
4
+ export * from './template/createFileUsingTemplateRender.js';
5
+ export * from './template/deleteFileUsingTemplateRender.js';
6
+ export * from './template/loadTemplateRenderSnapshots.js';
7
+ export * from './template/mergeFileUsingTemplateRender.js';
8
+ export * from './template/overwriteFileUsingTemplateRender.js';
9
+ export * from './template/parseTemplateId.js';
10
+ export * from './template/readCarsonTemplate.js';
11
+ export * from './template/renderTemplate.js';
12
+ export * from './template/resolveTemplateModule.js';
13
+ export * from './template/saveTemplateRenderSnapshots.js';
14
+ export * from './template/TemplateAttributes.js';
15
+ export * from './template/TemplateData.js';
16
+ export * from './template/TemplateRender.js';
17
+ export * from './template/TemplateRenders.js';
18
+ export * from './template/TemplateRenderSnapshot.js';
19
+ export * from './template/TemplateRenderSnapshots.js';
20
+ export * from './template/unmergeFileUsingTemplateRender.js';
@@ -0,0 +1,246 @@
1
+ import {ensureEmptyDirectory, pathToPosixPath} from '@jakubmazanec/fs-utils';
2
+ import {readFile, packageJsonSchema, type PackageJson} from '@jakubmazanec/zod-utils';
3
+ import fs from 'fs-extra';
4
+ import json5 from 'json5';
5
+ import path from 'node:path';
6
+ import {z} from 'zod';
7
+
8
+ import {type ProjectConfig, projectConfigSchema} from './ProjectConfig.js';
9
+ import {type ProjectCreateOptions} from './ProjectCreateOptions.js';
10
+ import {ProjectError} from './ProjectError.js';
11
+ import {type ProjectOptions} from './ProjectOptions.js';
12
+ import {type ProjectUpdateOptions} from './ProjectUpdateOptions.js';
13
+ import {saveProjectConfig} from './saveProjectConfig.js';
14
+ import {type Workspace} from './Workspace.js';
15
+ import {CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME} from '../constants.js';
16
+ import {applyTemplateRenders} from '../template/applyTemplateRenders.js';
17
+ import {renderTemplate} from '../template/renderTemplate.js';
18
+
19
+ /**
20
+ * Project represent a self-contained piece of software (e.g. a package, or an app) that is part of a {@linkcode Workspace}. Currently only Node.js projects are supported.
21
+ *
22
+ * @typeParam M If true, the project belongs to a multi-project workspace.
23
+ */
24
+ export class Project<M extends boolean = true> {
25
+ /** Project name. */
26
+ name?: string;
27
+
28
+ /** Project path. */
29
+ path: string;
30
+
31
+ /** Project path relative to workspace path. */
32
+ relativePath: string;
33
+
34
+ /** Project configuration; if it's not found, the default is an empty object. */
35
+ config: ProjectConfig;
36
+
37
+ /** Parsed project `package.json` file; if it's not found, the default is an empty object. */
38
+ packageJson: PackageJson;
39
+
40
+ /** Parent {@linkcode Workspace} instance. */
41
+ workspace: Workspace<M>;
42
+
43
+ /** Errors found during reading from the file system. */
44
+ errors: Array<InstanceType<typeof ProjectError>> = [];
45
+
46
+ constructor({
47
+ path: projectPath,
48
+ name,
49
+ config,
50
+ packageJson,
51
+ workspace,
52
+ errors,
53
+ }: ProjectOptions<M>) {
54
+ // TODO: check that this path and workspace path are correct, i.e. project path must always be inside of workspace path
55
+ this.path = projectPath;
56
+
57
+ if (name) {
58
+ this.name = name;
59
+ }
60
+
61
+ if (config) {
62
+ this.config = config;
63
+ } else {
64
+ this.config = {};
65
+ }
66
+
67
+ if (packageJson) {
68
+ this.packageJson = packageJson;
69
+ } else {
70
+ this.packageJson = {};
71
+ }
72
+
73
+ this.workspace = workspace;
74
+
75
+ if (errors) {
76
+ this.errors = errors;
77
+ }
78
+
79
+ if (this.packageJson.name?.length) {
80
+ this.name = this.packageJson.name;
81
+ }
82
+
83
+ this.relativePath = pathToPosixPath(path.relative(this.workspace.path, this.path));
84
+ }
85
+
86
+ static async create<M extends boolean>({
87
+ templateId,
88
+ workspace,
89
+ projectPath,
90
+ projectName,
91
+ args,
92
+ }: ProjectCreateOptions<M>): Promise<Project<M>> {
93
+ let project = new this({
94
+ path: projectPath,
95
+ name: projectName,
96
+ config: {
97
+ template: templateId,
98
+ },
99
+ workspace,
100
+ });
101
+
102
+ await ensureEmptyDirectory(project.path);
103
+ await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});
104
+
105
+ let templateRenders = await renderTemplate({
106
+ templateId,
107
+ templateData: {
108
+ workspace,
109
+ project,
110
+ args,
111
+ },
112
+ });
113
+
114
+ await applyTemplateRenders({
115
+ templateRenders,
116
+ path: project.path,
117
+ ignoreCreateStrategies: false,
118
+ ignoreCheckStrategies: true,
119
+ });
120
+
121
+ await project.read();
122
+
123
+ return project;
124
+ }
125
+
126
+ static async read<M extends boolean>(
127
+ projectPath: string,
128
+ workspace: Workspace<M>,
129
+ ): Promise<Project<M>> {
130
+ let project = new this({
131
+ path: projectPath,
132
+ workspace,
133
+ });
134
+
135
+ await project.read();
136
+
137
+ return project;
138
+ }
139
+
140
+ async read() {
141
+ if (!(await fs.pathExists(this.path))) {
142
+ throw new ProjectError('NO_SUCH_PROJECT_PATH', {
143
+ messageParameters: [this.path],
144
+ data: {
145
+ path: this.path,
146
+ },
147
+ });
148
+ }
149
+
150
+ let errors: Array<InstanceType<typeof ProjectError>> = [];
151
+
152
+ // load project config
153
+ let projectConfigPath = path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME);
154
+ let doesProjectConfigExist = await fs.pathExists(projectConfigPath);
155
+ let projectConfig: ProjectConfig | z.ZodError;
156
+
157
+ if (doesProjectConfigExist) {
158
+ projectConfig = await readFile(projectConfigPath, projectConfigSchema, {
159
+ parser: (rawString: string) => json5.parse<unknown>(rawString),
160
+ });
161
+ } else {
162
+ projectConfig = {};
163
+ }
164
+
165
+ if (projectConfig instanceof z.ZodError) {
166
+ let zodError = projectConfig;
167
+
168
+ errors.push(
169
+ new ProjectError('INVALID_PROJECT_CONFIG', {
170
+ messageParameters: [projectConfigPath],
171
+ data: {
172
+ path: projectConfigPath,
173
+ zodIssues: zodError.issues,
174
+ },
175
+ }),
176
+ );
177
+
178
+ projectConfig = {};
179
+ }
180
+
181
+ // load package.json
182
+ let packageJsonPath = path.join(this.path, 'package.json');
183
+ let doesPackageJsonExist = await fs.pathExists(packageJsonPath);
184
+ let packageJson: PackageJson | z.ZodError;
185
+
186
+ if (doesPackageJsonExist) {
187
+ packageJson = await readFile(packageJsonPath, packageJsonSchema, {
188
+ parser: (rawString: string) => json5.parse<unknown>(rawString),
189
+ });
190
+ } else {
191
+ packageJson = {};
192
+ }
193
+
194
+ if (packageJson instanceof z.ZodError) {
195
+ let zodError = packageJson;
196
+
197
+ errors.push(
198
+ new ProjectError('INVALID_PACKAGE_JSON', {
199
+ messageParameters: [packageJsonPath],
200
+ data: {
201
+ path: packageJsonPath,
202
+ zodIssues: zodError.issues,
203
+ },
204
+ }),
205
+ );
206
+
207
+ packageJson = {};
208
+ }
209
+
210
+ if (packageJson.name?.length) {
211
+ this.name = packageJson.name;
212
+ }
213
+
214
+ this.config = projectConfig;
215
+ this.packageJson = packageJson;
216
+ this.errors = errors;
217
+
218
+ return this;
219
+ }
220
+
221
+ async update({args}: ProjectUpdateOptions): Promise<this> {
222
+ if (!this.config.template) {
223
+ throw new Error('Template ID is missing in the project config!');
224
+ }
225
+
226
+ let templateRenders = await renderTemplate({
227
+ templateId: this.config.template,
228
+ templateData: {
229
+ workspace: this.workspace,
230
+ project: this,
231
+ args,
232
+ },
233
+ });
234
+
235
+ await applyTemplateRenders({
236
+ templateRenders,
237
+ path: this.path,
238
+ ignoreCreateStrategies: true,
239
+ ignoreCheckStrategies: false,
240
+ });
241
+
242
+ await this.read();
243
+
244
+ return this;
245
+ }
246
+ }
@@ -0,0 +1,9 @@
1
+ import {z} from 'zod';
2
+
3
+ export const projectConfigSchema = z
4
+ .object({
5
+ template: z.string().optional(),
6
+ })
7
+ .catchall(z.unknown());
8
+
9
+ export type ProjectConfig = z.infer<typeof projectConfigSchema>;
@@ -0,0 +1,9 @@
1
+ import {type Workspace} from './Workspace.js';
2
+
3
+ export type ProjectCreateOptions<M extends boolean> = {
4
+ templateId: string;
5
+ workspace: Workspace<M>;
6
+ projectPath: string;
7
+ projectName: string;
8
+ args: Record<string, unknown>;
9
+ };
@@ -0,0 +1,15 @@
1
+ import {createCustomErrorWithData} from '@jakubmazanec/error';
2
+ import {type ZodIssue} from 'zod';
3
+
4
+ export const ProjectError = createCustomErrorWithData(
5
+ 'ProjectError',
6
+ {
7
+ INVALID_PACKAGE_JSON: 'Invalid package.json file "{0}".',
8
+ INVALID_PROJECT_CONFIG: 'Invalid project config file "{0}".',
9
+ NO_SUCH_PROJECT_PATH: 'Project path "{0}" doesn\'t exist.',
10
+ },
11
+ class ProjectErrorData {
12
+ path?: string;
13
+ zodIssues?: ZodIssue[];
14
+ },
15
+ );
@@ -0,0 +1,17 @@
1
+ import {type PackageJson} from '@jakubmazanec/zod-utils';
2
+
3
+ import {type ProjectConfig} from './ProjectConfig.js';
4
+ import {type ProjectError} from './ProjectError.js';
5
+ import {type Workspace} from './Workspace.js';
6
+
7
+ /**
8
+ * New project options.
9
+ */
10
+ export type ProjectOptions<M extends boolean> = {
11
+ path: string;
12
+ name?: string;
13
+ config?: ProjectConfig;
14
+ packageJson?: PackageJson;
15
+ workspace: Workspace<M>;
16
+ errors?: Array<InstanceType<typeof ProjectError>>;
17
+ };
@@ -0,0 +1,3 @@
1
+ export type ProjectUpdateOptions = {
2
+ args: Record<string, unknown>;
3
+ };