@jakubmazanec/carson 1.0.1 → 1.1.0-next.c370ab6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -1
- package/build/commands/create-project/CreateProject.js +14 -0
- package/build/commands/create-project/CreateProject.js.map +2 -2
- package/build/commands/create-project/runCreateProject.js +1 -0
- package/build/commands/create-project/runCreateProject.js.map +2 -2
- package/build/commands/create-workspace/runCreateWorkspace.js +1 -0
- package/build/commands/create-workspace/runCreateWorkspace.js.map +2 -2
- package/build/template/CarsonTemplate.d.ts +2 -0
- package/build/template/CarsonTemplateConfig.d.ts +3 -6
- package/build/template/CarsonTemplateConfig.js +3 -3
- package/build/template/CarsonTemplateConfig.js.map +2 -2
- package/build/template/applyTemplateRenders.d.ts +1 -1
- package/build/template/applyTemplateRenders.js +5 -3
- package/build/template/applyTemplateRenders.js.map +2 -2
- package/build/template/internals/readCarsonTemplate.js +1 -0
- package/build/template/internals/readCarsonTemplate.js.map +2 -2
- package/build/template/renderCarsonTemplate.d.ts +2 -1
- package/build/template/renderCarsonTemplate.js +4 -10
- package/build/template/renderCarsonTemplate.js.map +2 -2
- package/build/workspace/Project.js +10 -5
- package/build/workspace/Project.js.map +2 -2
- package/build/workspace/Workspace.js +13 -8
- package/build/workspace/Workspace.js.map +2 -2
- package/package.json +10 -9
- package/source/commands/create-project/CreateProject.tsx +19 -0
- package/source/commands/create-project/runCreateProject.ts +3 -0
- package/source/commands/create-workspace/runCreateWorkspace.ts +3 -0
- package/source/template/CarsonTemplate.ts +3 -0
- package/source/template/CarsonTemplateConfig.ts +3 -3
- package/source/template/applyTemplateRenders.ts +6 -4
- package/source/template/internals/readCarsonTemplate.ts +1 -0
- package/source/template/renderCarsonTemplate.ts +6 -11
- package/source/workspace/Project.ts +16 -5
- package/source/workspace/Workspace.ts +19 -8
package/README.md
CHANGED
|
@@ -242,6 +242,20 @@ Creates new workspace.
|
|
|
242
242
|
| --path | Path where the workspace should be created. A relative path is appended to the current working directory. |
|
|
243
243
|
| --template | ID of the Carson template used to create the workspace. |
|
|
244
244
|
|
|
245
|
+
#### `eject [<options>]`
|
|
246
|
+
|
|
247
|
+
> ⚠️ Upcoming feature!
|
|
248
|
+
|
|
249
|
+
Ejects Carson from a workspace and all of its projects. That means all `.carson` directories (that
|
|
250
|
+
contain Carson config and snapshot files) will be deleted.
|
|
251
|
+
|
|
252
|
+
You can still add projects to the workspace that has had Carson ejected, but those projects also
|
|
253
|
+
won't contain `.carson` folder.
|
|
254
|
+
|
|
255
|
+
| Option | Description |
|
|
256
|
+
| ------ | -------------------------------------------------------------------------------------------------- |
|
|
257
|
+
| --path | Path where the workspace is located. A relative path is appended to the current working directory. |
|
|
258
|
+
|
|
245
259
|
### Carson templates
|
|
246
260
|
|
|
247
261
|
Carson template is just a directory containing `*.ejs` files and `config.json` file. The purpose of
|
|
@@ -355,7 +369,9 @@ Global variables available during the rendering:
|
|
|
355
369
|
|
|
356
370
|
#### Carson template config
|
|
357
371
|
|
|
358
|
-
|
|
372
|
+
| Option | Type | Description |
|
|
373
|
+
| --------- | -------- | ------------------------------------------------------------------------ |
|
|
374
|
+
| autoEject | boolean? | If set to `true`, Carson automatically ejects after using this template. |
|
|
359
375
|
|
|
360
376
|
### Carson philosophy
|
|
361
377
|
|
|
@@ -62,6 +62,20 @@ export function CreateProject({ args, workspace }) {
|
|
|
62
62
|
value: projectPath,
|
|
63
63
|
label: path.relative(workspace.path, projectPath).replace("\\", "/")
|
|
64
64
|
}));
|
|
65
|
+
if (!possiblePaths.length) {
|
|
66
|
+
possiblePaths = workspace.projectGlobs.filter((projectGlob) => !ONLY_ONE_STAR_REGEXP.test(projectGlob)).map((projectGlob) => path.join(workspace.path, projectGlob)).map((projectPath) => ({
|
|
67
|
+
value: projectPath,
|
|
68
|
+
label: path.relative(workspace.path, projectPath).replace("\\", "/")
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
if (!possiblePaths.length) {
|
|
72
|
+
possiblePaths = [
|
|
73
|
+
{
|
|
74
|
+
value: workspace.path,
|
|
75
|
+
label: workspace.path
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
}
|
|
65
79
|
} else {
|
|
66
80
|
possiblePaths = [
|
|
67
81
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../source/commands/create-project/CreateProject.tsx"],
|
|
4
|
-
"sourcesContent": ["import {colors, type CommandArguments, Header, icons, useProgram} from '@jakubmazanec/cli';\nimport chalk from 'chalk';\nimport {Box, Text} from 'ink';\nimport path from 'node:path';\nimport {useEffect, useState} from 'react';\n\nimport {type Workspace} from '../../workspace.js';\nimport {type CommandStatus, packageNameToDirectory} from '../internals.js';\nimport {type createProjectCommand} from './createProjectCommand.js';\nimport {CreateProjectInput, type CreateProjectInputResult} from './CreateProjectInput.js';\nimport {runCreateProject} from './runCreateProject.js';\n\nconst ONLY_ONE_STAR_REGEXP = /^(?!(.*?\\*){2,}|.*? |\\*$).*?\\*.*$/;\n\nexport type CreateProjectProps = {\n args: CommandArguments<typeof createProjectCommand>;\n workspace: Workspace | Workspace<false>;\n};\n\nexport function CreateProject({args, workspace}: CreateProjectProps) {\n let [status, setStatus] = useState<CommandStatus>('not-started');\n let [subscription, setSubscription] = useState<ZenObservable.Subscription | null>(null);\n let [jobs, setJobs] = useState<string[]>([]);\n let [createProjectInputResult, setCreateProjectInputResult] = useState<CreateProjectInputResult>(\n () => ({\n projectName: {value: args.options.name ?? '', isComplete: !!args.options.name},\n projectPath: {value: '', isComplete: false},\n templateId: {value: args.options.template ?? '', isComplete: !!args.options.template},\n }),\n );\n let {exit} = useProgram();\n\n useEffect(() => {\n if (Object.entries(createProjectInputResult).every(([, result]) => result.isComplete)) {\n setStatus('in-progress');\n }\n }, [createProjectInputResult]);\n\n useEffect(() => {\n if (status === 'in-progress' && !subscription) {\n let newSubscription = runCreateProject({\n projectPath: createProjectInputResult.projectPath.value,\n templateId: createProjectInputResult.templateId.value,\n projectName: createProjectInputResult.projectName.value,\n workspace,\n args,\n }).subscribe({\n next(value) {\n setJobs((previousJobs) => [...previousJobs, value]);\n },\n error(error) {\n exit(error);\n },\n complete() {\n newSubscription.unsubscribe();\n setStatus('finished');\n },\n });\n setSubscription(newSubscription);\n }\n\n return () => {\n if (subscription) {\n subscription.unsubscribe();\n }\n };\n }, [args, createProjectInputResult, exit, status, subscription, workspace]);\n\n let possiblePaths: Array<{value: string; label: string}> = [];\n\n if (createProjectInputResult.projectName.value) {\n let destinationDirectory = packageNameToDirectory(createProjectInputResult.projectName.value);\n\n if (workspace.projectGlobs) {\n possiblePaths = workspace.projectGlobs\n .filter((projectGlob) => ONLY_ONE_STAR_REGEXP.test(projectGlob))\n .map((projectGlob) => projectGlob.replace(/\\*/, destinationDirectory))\n .map((projectGlob) => path.join(workspace.path, projectGlob))\n .map((projectPath) => ({\n value: projectPath,\n label: path.relative(workspace.path, projectPath).replace('\\\\', '/'),\n }));\n } else {\n possiblePaths = [\n {\n value: workspace.path,\n label: workspace.path,\n },\n ];\n }\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text color={colors.body}>\n {`Creating project in the workspace at ${chalk[colors.info](workspace.path)}.`}\n </Text>\n\n <CreateProjectInput\n rows={{\n projectPath: {\n choices: possiblePaths,\n },\n }}\n values={createProjectInputResult}\n marginTop={1}\n onChange={setCreateProjectInputResult}\n onComplete={setCreateProjectInputResult}\n />\n\n {status === 'in-progress' || status === 'finished' ?\n <Box marginTop={1} flexDirection=\"column\">\n <Header showSpinner={status === 'in-progress'} icon={icons.success} marginBottom={1}>\n <Text>Creating project...</Text>\n </Header>\n\n {jobs.map((job) => (\n <Text key={job}>{`${icons.info} ${job}`}</Text>\n ))}\n </Box>\n : null}\n\n {status === 'finished' ?\n <Header marginTop={1} icon={icons.success}>\n <Text>Done.</Text>\n </Header>\n : null}\n </Box>\n );\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import {colors, type CommandArguments, Header, icons, useProgram} from '@jakubmazanec/cli';\nimport chalk from 'chalk';\nimport {Box, Text} from 'ink';\nimport path from 'node:path';\nimport {useEffect, useState} from 'react';\n\nimport {type Workspace} from '../../workspace.js';\nimport {type CommandStatus, packageNameToDirectory} from '../internals.js';\nimport {type createProjectCommand} from './createProjectCommand.js';\nimport {CreateProjectInput, type CreateProjectInputResult} from './CreateProjectInput.js';\nimport {runCreateProject} from './runCreateProject.js';\n\nconst ONLY_ONE_STAR_REGEXP = /^(?!(.*?\\*){2,}|.*? |\\*$).*?\\*.*$/;\n\nexport type CreateProjectProps = {\n args: CommandArguments<typeof createProjectCommand>;\n workspace: Workspace | Workspace<false>;\n};\n\nexport function CreateProject({args, workspace}: CreateProjectProps) {\n let [status, setStatus] = useState<CommandStatus>('not-started');\n let [subscription, setSubscription] = useState<ZenObservable.Subscription | null>(null);\n let [jobs, setJobs] = useState<string[]>([]);\n let [createProjectInputResult, setCreateProjectInputResult] = useState<CreateProjectInputResult>(\n () => ({\n projectName: {value: args.options.name ?? '', isComplete: !!args.options.name},\n projectPath: {value: '', isComplete: false},\n templateId: {value: args.options.template ?? '', isComplete: !!args.options.template},\n }),\n );\n let {exit} = useProgram();\n\n useEffect(() => {\n if (Object.entries(createProjectInputResult).every(([, result]) => result.isComplete)) {\n setStatus('in-progress');\n }\n }, [createProjectInputResult]);\n\n useEffect(() => {\n if (status === 'in-progress' && !subscription) {\n let newSubscription = runCreateProject({\n projectPath: createProjectInputResult.projectPath.value,\n templateId: createProjectInputResult.templateId.value,\n projectName: createProjectInputResult.projectName.value,\n workspace,\n args,\n }).subscribe({\n next(value) {\n setJobs((previousJobs) => [...previousJobs, value]);\n },\n error(error) {\n exit(error);\n },\n complete() {\n newSubscription.unsubscribe();\n setStatus('finished');\n },\n });\n setSubscription(newSubscription);\n }\n\n return () => {\n if (subscription) {\n subscription.unsubscribe();\n }\n };\n }, [args, createProjectInputResult, exit, status, subscription, workspace]);\n\n let possiblePaths: Array<{value: string; label: string}> = [];\n\n if (createProjectInputResult.projectName.value) {\n let destinationDirectory = packageNameToDirectory(createProjectInputResult.projectName.value);\n\n if (workspace.projectGlobs) {\n possiblePaths = workspace.projectGlobs\n .filter((projectGlob) => ONLY_ONE_STAR_REGEXP.test(projectGlob))\n .map((projectGlob) => projectGlob.replace(/\\*/, destinationDirectory))\n .map((projectGlob) => path.join(workspace.path, projectGlob))\n .map((projectPath) => ({\n value: projectPath,\n label: path.relative(workspace.path, projectPath).replace('\\\\', '/'),\n }));\n\n if (!possiblePaths.length) {\n possiblePaths = workspace.projectGlobs\n .filter((projectGlob) => !ONLY_ONE_STAR_REGEXP.test(projectGlob))\n .map((projectGlob) => path.join(workspace.path, projectGlob))\n .map((projectPath) => ({\n value: projectPath,\n label: path.relative(workspace.path, projectPath).replace('\\\\', '/'),\n }));\n }\n\n if (!possiblePaths.length) {\n possiblePaths = [\n {\n value: workspace.path,\n label: workspace.path,\n },\n ];\n }\n } else {\n possiblePaths = [\n {\n value: workspace.path,\n label: workspace.path,\n },\n ];\n }\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text color={colors.body}>\n {`Creating project in the workspace at ${chalk[colors.info](workspace.path)}.`}\n </Text>\n\n <CreateProjectInput\n rows={{\n projectPath: {\n choices: possiblePaths,\n },\n }}\n values={createProjectInputResult}\n marginTop={1}\n onChange={setCreateProjectInputResult}\n onComplete={setCreateProjectInputResult}\n />\n\n {status === 'in-progress' || status === 'finished' ?\n <Box marginTop={1} flexDirection=\"column\">\n <Header showSpinner={status === 'in-progress'} icon={icons.success} marginBottom={1}>\n <Text>Creating project...</Text>\n </Header>\n\n {jobs.map((job) => (\n <Text key={job}>{`${icons.info} ${job}`}</Text>\n ))}\n </Box>\n : null}\n\n {status === 'finished' ?\n <Header marginTop={1} icon={icons.success}>\n <Text>Done.</Text>\n </Header>\n : null}\n </Box>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../source/commands/create-project/runCreateProject.ts"],
|
|
4
|
-
"sourcesContent": ["import {type CommandArguments} from '@jakubmazanec/cli';\nimport Observable from 'zen-observable';\n\nimport {type Workspace} from '../../workspace.js';\nimport {type createProjectCommand} from './createProjectCommand.js';\n\nexport type CreateProjectOptions = {\n projectPath: string;\n projectName: string;\n templateId: string;\n workspace: Workspace | Workspace<false>;\n args: CommandArguments<typeof createProjectCommand>;\n};\n\nexport type CreateProjectStatus = string;\n\nexport function runCreateProject({\n projectPath,\n templateId,\n projectName,\n workspace,\n args,\n}: CreateProjectOptions) {\n return new Observable<CreateProjectStatus>((observer) => {\n (async () => {\n observer.next('Creating files');\n\n let project = await workspace.createProject({\n projectPath,\n projectName,\n templateId,\n args,\n });\n\n observer.next('Updating the new project');\n\n await project.update({args});\n })()\n .then(() => {\n observer.complete();\n })\n .catch((error) => {\n observer.error(error);\n });\n });\n}\n"],
|
|
5
|
-
"mappings": ";AACA,OAAO,gBAAgB;AAehB,gBAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,SAAO,IAAI,WAAgC,CAAC,aAAa;AACvD,KAAC,YAAY;AACX,eAAS,KAAK,gBAAgB;AAE9B,UAAI,UAAU,MAAM,UAAU,cAAc;AAAA,QAC1C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,eAAS,KAAK,0BAA0B;
|
|
4
|
+
"sourcesContent": ["import {type CommandArguments} from '@jakubmazanec/cli';\nimport Observable from 'zen-observable';\n\nimport {type Workspace} from '../../workspace.js';\nimport {type createProjectCommand} from './createProjectCommand.js';\n\nexport type CreateProjectOptions = {\n projectPath: string;\n projectName: string;\n templateId: string;\n workspace: Workspace | Workspace<false>;\n args: CommandArguments<typeof createProjectCommand>;\n};\n\nexport type CreateProjectStatus = string;\n\nexport function runCreateProject({\n projectPath,\n templateId,\n projectName,\n workspace,\n args,\n}: CreateProjectOptions) {\n return new Observable<CreateProjectStatus>((observer) => {\n (async () => {\n observer.next('Creating files');\n\n let project = await workspace.createProject({\n projectPath,\n projectName,\n templateId,\n args,\n });\n\n observer.next('Updating the new project');\n\n // if the project doesn't have config with a template ID, it's on purpose, but it's still needed for the next update, so we'll add it manually\n project.config.template ??= templateId;\n\n await project.update({args});\n })()\n .then(() => {\n observer.complete();\n })\n .catch((error) => {\n observer.error(error);\n });\n });\n}\n"],
|
|
5
|
+
"mappings": ";AACA,OAAO,gBAAgB;AAehB,gBAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,SAAO,IAAI,WAAgC,CAAC,aAAa;AACvD,KAAC,YAAY;AACX,eAAS,KAAK,gBAAgB;AAE9B,UAAI,UAAU,MAAM,UAAU,cAAc;AAAA,QAC1C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,eAAS,KAAK,0BAA0B;AAGxC,cAAQ,OAAO,aAAa;AAE5B,YAAM,QAAQ,OAAO,EAAC,KAAI,CAAC;AAAA,IAC7B,GAAG,EACA,KAAK,MAAM;AACV,eAAS,SAAS;AAAA,IACpB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,eAAS,MAAM,KAAK;AAAA,IACtB,CAAC;AAAA,EACL,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -11,6 +11,7 @@ export function runCreateWorkspace({ workspacePath, templateId, args }) {
|
|
|
11
11
|
templateId
|
|
12
12
|
});
|
|
13
13
|
observer.next("Updating the new workspace");
|
|
14
|
+
workspace.config.template ??= templateId;
|
|
14
15
|
await workspace.update({ args });
|
|
15
16
|
})().then(() => {
|
|
16
17
|
observer.complete();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../source/commands/create-workspace/runCreateWorkspace.ts"],
|
|
4
|
-
"sourcesContent": ["import {type CommandArguments} from '@jakubmazanec/cli';\nimport Observable from 'zen-observable';\n\nimport {Workspace} from '../../workspace.js';\nimport {type createWorkspaceCommand} from './createWorkspaceCommand.js';\n\nexport type CreateWorkspaceOptions = {\n workspacePath: string;\n templateId: string;\n args: CommandArguments<typeof createWorkspaceCommand>;\n};\n\nexport type CreateWorkspaceStatus = string;\n\nexport function runCreateWorkspace({workspacePath, templateId, args}: CreateWorkspaceOptions) {\n return new Observable<CreateWorkspaceStatus>((observer) => {\n (async () => {\n observer.next('Creating files');\n\n let workspace = await Workspace.create({\n args,\n path: workspacePath,\n templateId,\n });\n\n observer.next('Updating the new workspace');\n\n await workspace.update({args});\n })()\n .then(() => {\n observer.complete();\n })\n .catch((error) => {\n observer.error(error);\n });\n });\n}\n"],
|
|
5
|
-
"mappings": ";AACA,OAAO,gBAAgB;AAEvB,SAAQ,iBAAgB;AAWjB,gBAAS,mBAAmB,EAAC,eAAe,YAAY,KAAI,GAA2B;AAC5F,SAAO,IAAI,WAAkC,CAAC,aAAa;AACzD,KAAC,YAAY;AACX,eAAS,KAAK,gBAAgB;AAE9B,UAAI,YAAY,MAAM,UAAU,OAAO;AAAA,QACrC;AAAA,QACA,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAED,eAAS,KAAK,4BAA4B;
|
|
4
|
+
"sourcesContent": ["import {type CommandArguments} from '@jakubmazanec/cli';\nimport Observable from 'zen-observable';\n\nimport {Workspace} from '../../workspace.js';\nimport {type createWorkspaceCommand} from './createWorkspaceCommand.js';\n\nexport type CreateWorkspaceOptions = {\n workspacePath: string;\n templateId: string;\n args: CommandArguments<typeof createWorkspaceCommand>;\n};\n\nexport type CreateWorkspaceStatus = string;\n\nexport function runCreateWorkspace({workspacePath, templateId, args}: CreateWorkspaceOptions) {\n return new Observable<CreateWorkspaceStatus>((observer) => {\n (async () => {\n observer.next('Creating files');\n\n let workspace = await Workspace.create({\n args,\n path: workspacePath,\n templateId,\n });\n\n observer.next('Updating the new workspace');\n\n // if the workspace doesn't have config with a template ID, it's on purpose, but it's still needed for the next update, so we'll add it manually\n workspace.config.template ??= templateId;\n\n await workspace.update({args});\n })()\n .then(() => {\n observer.complete();\n })\n .catch((error) => {\n observer.error(error);\n });\n });\n}\n"],
|
|
5
|
+
"mappings": ";AACA,OAAO,gBAAgB;AAEvB,SAAQ,iBAAgB;AAWjB,gBAAS,mBAAmB,EAAC,eAAe,YAAY,KAAI,GAA2B;AAC5F,SAAO,IAAI,WAAkC,CAAC,aAAa;AACzD,KAAC,YAAY;AACX,eAAS,KAAK,gBAAgB;AAE9B,UAAI,YAAY,MAAM,UAAU,OAAO;AAAA,QACrC;AAAA,QACA,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAED,eAAS,KAAK,4BAA4B;AAG1C,gBAAU,OAAO,aAAa;AAE9B,YAAM,UAAU,OAAO,EAAC,KAAI,CAAC;AAAA,IAC/B,GAAG,EACA,KAAK,MAAM;AACV,eAAS,SAAS;AAAA,IACpB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,eAAS,MAAM,KAAK;AAAA,IACtB,CAAC;AAAA,EACL,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const carsonTemplateConfigSchema: z.ZodObject<{
|
|
3
|
-
|
|
4
|
-
disallowSingleProjectWorkspace: z.ZodOptional<z.ZodBoolean>;
|
|
3
|
+
autoEject: z.ZodOptional<z.ZodBoolean>;
|
|
5
4
|
}, "strict", z.ZodTypeAny, {
|
|
6
|
-
|
|
7
|
-
disallowSingleProjectWorkspace?: boolean | undefined;
|
|
5
|
+
autoEject?: boolean | undefined;
|
|
8
6
|
}, {
|
|
9
|
-
|
|
10
|
-
disallowSingleProjectWorkspace?: boolean | undefined;
|
|
7
|
+
autoEject?: boolean | undefined;
|
|
11
8
|
}>;
|
|
12
9
|
/**
|
|
13
10
|
* Carson template config.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
export const carsonTemplateConfigSchema = z.object({
|
|
4
|
-
disallowMultiProjectWorkspace: z.boolean().optional(),
|
|
5
|
-
disallowSingleProjectWorkspace: z.boolean().optional()
|
|
6
|
-
|
|
4
|
+
// disallowMultiProjectWorkspace: z.boolean().optional(),
|
|
5
|
+
// disallowSingleProjectWorkspace: z.boolean().optional(),
|
|
6
|
+
autoEject: z.boolean().optional()
|
|
7
7
|
}).strict();
|
|
8
8
|
//# sourceMappingURL=CarsonTemplateConfig.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../source/template/CarsonTemplateConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import {z} from 'zod';\n\nexport const carsonTemplateConfigSchema = z\n .object({\n disallowMultiProjectWorkspace: z.boolean().optional(),\n disallowSingleProjectWorkspace: z.boolean().optional(),\n\n
|
|
5
|
-
"mappings": ";AAAA,SAAQ,SAAQ;AAET,aAAM,6BAA6B,EACvC,OAAO;AAAA
|
|
4
|
+
"sourcesContent": ["import {z} from 'zod';\n\nexport const carsonTemplateConfigSchema = z\n .object({\n // disallowMultiProjectWorkspace: z.boolean().optional(),\n // disallowSingleProjectWorkspace: z.boolean().optional(),\n\n autoEject: z.boolean().optional(),\n })\n .strict();\n\n/**\n * Carson template config.\n */\nexport type CarsonTemplateConfig = z.infer<typeof carsonTemplateConfigSchema>;\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAQ,SAAQ;AAET,aAAM,6BAA6B,EACvC,OAAO;AAAA;AAAA;AAAA,EAIN,WAAW,EAAE,QAAQ,EAAE,SAAS;AAClC,CAAC,EACA,OAAO;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -22,7 +22,7 @@ export async function applyTemplateRenders({
|
|
|
22
22
|
ignoreStrategies
|
|
23
23
|
}) {
|
|
24
24
|
await prettier.clearConfigCache();
|
|
25
|
-
if (await fs.pathExists(snapshotPath)) {
|
|
25
|
+
if (snapshotPath && await fs.pathExists(snapshotPath)) {
|
|
26
26
|
let templateRenderSnapshots = await loadTemplateRenderSnapshots(snapshotPath);
|
|
27
27
|
for (let templateRenderSnapshot of templateRenderSnapshots) {
|
|
28
28
|
let strategy = typeof templateRenderSnapshot.attributes.strategy === "string" ? templateRenderSnapshot.attributes.strategy : templateRenderSnapshot.attributes.strategy[0];
|
|
@@ -88,7 +88,9 @@ export async function applyTemplateRenders({
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
if (snapshotPath) {
|
|
92
|
+
await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));
|
|
93
|
+
await saveTemplateRenderSnapshots(templateRenders, snapshotPath);
|
|
94
|
+
}
|
|
93
95
|
}
|
|
94
96
|
//# sourceMappingURL=applyTemplateRenders.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../source/template/applyTemplateRenders.ts"],
|
|
4
|
-
"sourcesContent": ["// TODO: can this be fixed?\n/* eslint-disable complexity -- TODO */\nimport fs from 'fs-extra';\nimport path from 'node:path';\nimport prettier from 'prettier';\n\nimport {CARSON_CONFIG_DIRECTORY} from '../constants.js';\nimport {CarsonTemplateError} from './CarsonTemplateError.js';\nimport {\n createUsingTemplateRender,\n deleteUsingTemplateRender,\n insertUsingTemplateRender,\n loadTemplateRenderSnapshots,\n mergeUsingTemplateRender,\n overwriteUsingTemplateRender,\n saveTemplateRenderSnapshots,\n uninsertUsingTemplateRender,\n unmergeUsingTemplateRender,\n} from './internals.js';\nimport {type TemplateRenders} from './TemplateRenders.js';\n\nexport type ApplyTemplateRendersOptions = {\n templateRenders: TemplateRenders;\n targetPath: string;\n snapshotPath
|
|
5
|
-
"mappings": ";AAEA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,cAAc;AAErB,SAAQ,+BAA8B;AACtC,SAAQ,2BAA0B;AAClC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAaP,sBAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAgC;AAE9B,QAAM,SAAS,iBAAiB;AAGhC,MAAI,MAAM,GAAG,WAAW,YAAY,
|
|
4
|
+
"sourcesContent": ["// TODO: can this be fixed?\n/* eslint-disable complexity -- TODO */\nimport fs from 'fs-extra';\nimport path from 'node:path';\nimport prettier from 'prettier';\n\nimport {CARSON_CONFIG_DIRECTORY} from '../constants.js';\nimport {CarsonTemplateError} from './CarsonTemplateError.js';\nimport {\n createUsingTemplateRender,\n deleteUsingTemplateRender,\n insertUsingTemplateRender,\n loadTemplateRenderSnapshots,\n mergeUsingTemplateRender,\n overwriteUsingTemplateRender,\n saveTemplateRenderSnapshots,\n uninsertUsingTemplateRender,\n unmergeUsingTemplateRender,\n} from './internals.js';\nimport {type TemplateRenders} from './TemplateRenders.js';\n\nexport type ApplyTemplateRendersOptions = {\n templateRenders: TemplateRenders;\n targetPath: string;\n snapshotPath?: string | undefined;\n ignoreStrategies: string[];\n};\n\n/**\n * Applies rendered Carson template to a specified path, i.e. creates and updates files based on the result of rendering each Carson template file.\n */\nexport async function applyTemplateRenders({\n templateRenders,\n targetPath,\n snapshotPath,\n ignoreStrategies,\n}: ApplyTemplateRendersOptions) {\n // we need to clear Prettier cache, because we are changing file system\n await prettier.clearConfigCache();\n\n // first, we read the existing snapshots and use them to undo previous changes\n if (snapshotPath && (await fs.pathExists(snapshotPath))) {\n let templateRenderSnapshots = await loadTemplateRenderSnapshots(snapshotPath);\n\n for (let templateRenderSnapshot of templateRenderSnapshots) {\n let strategy =\n typeof templateRenderSnapshot.attributes.strategy === 'string' ?\n templateRenderSnapshot.attributes.strategy\n : templateRenderSnapshot.attributes.strategy[0];\n\n if (ignoreStrategies.includes(strategy)) {\n continue;\n }\n\n if (templateRenderSnapshot.attributes.strategy === 'ensure') {\n await deleteUsingTemplateRender(templateRenderSnapshot, targetPath, {\n onlyDeleteWhenContentsMatch: true,\n });\n }\n\n if (templateRenderSnapshot.attributes.strategy === 'overwrite') {\n await deleteUsingTemplateRender(templateRenderSnapshot, targetPath);\n }\n\n if (templateRenderSnapshot.attributes.strategy === 'merge') {\n await unmergeUsingTemplateRender(templateRenderSnapshot, targetPath);\n }\n\n if (templateRenderSnapshot.attributes.strategy[0] === 'insert') {\n await uninsertUsingTemplateRender(templateRenderSnapshot, targetPath);\n }\n }\n }\n\n // second, we apply strategies that create files\n for (let templateRender of templateRenders) {\n let strategy =\n typeof templateRender.attributes.strategy === 'string' ?\n templateRender.attributes.strategy\n : templateRender.attributes.strategy[0];\n\n if (ignoreStrategies.includes(strategy)) {\n continue;\n }\n\n if (templateRender.attributes.strategy === 'create') {\n await createUsingTemplateRender(templateRender, targetPath);\n }\n\n if (templateRender.attributes.strategy === 'ensure') {\n let to = path.join(targetPath, templateRender.attributes.to);\n let doesToExist = await fs.pathExists(to);\n\n if (!doesToExist) {\n await createUsingTemplateRender(templateRender, targetPath);\n }\n }\n }\n\n // third, we apply strategies that change files\n for (let templateRender of templateRenders) {\n let strategy =\n typeof templateRender.attributes.strategy === 'string' ?\n templateRender.attributes.strategy\n : templateRender.attributes.strategy[0];\n\n if (ignoreStrategies.includes(strategy)) {\n continue;\n }\n\n if (templateRender.attributes.strategy === 'overwrite') {\n await overwriteUsingTemplateRender(templateRender, targetPath);\n }\n\n if (templateRender.attributes.strategy === 'merge') {\n await mergeUsingTemplateRender(templateRender, targetPath);\n }\n\n if (templateRender.attributes.strategy[0] === 'insert') {\n await insertUsingTemplateRender(templateRender, targetPath);\n }\n\n if (templateRender.attributes.strategy === 'check') {\n let to = path.join(targetPath, templateRender.attributes.to);\n let doesToExist = await fs.pathExists(to);\n\n if (!doesToExist) {\n throw new CarsonTemplateError('STRATEGY_MISSING_FILE', {\n messageParameters: [templateRender.attributes.strategy, templateRender.template.path, to],\n data: {\n path: to,\n },\n });\n }\n }\n }\n\n if (snapshotPath) {\n await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));\n\n await saveTemplateRenderSnapshots(templateRenders, snapshotPath);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../source/template/internals/readCarsonTemplate.ts"],
|
|
4
|
-
"sourcesContent": ["import {Template} from '@jakubmazanec/template';\nimport {readFile} from '@jakubmazanec/zod-utils';\nimport glob from 'fast-glob';\nimport fs from 'fs-extra';\nimport path from 'node:path';\n\nimport {TEMPLATE_CONFIG_FILENAME, TEMPLATES_PATH} from '../../constants.js';\nimport {type CarsonTemplate} from '../CarsonTemplate.js';\nimport {carsonTemplateConfigSchema} from '../CarsonTemplateConfig.js';\nimport {CarsonTemplateError} from '../CarsonTemplateError.js';\nimport {templateAttributesSchema} from '../TemplateAttributes.js';\nimport {parseCarsonTemplateId} from './parseCarsonTemplateId.js';\nimport {resolveModule} from './resolveModule.js';\n\nexport async function readCarsonTemplate(templateId: string): Promise<CarsonTemplate> {\n let [moduleId, templateName] = parseCarsonTemplateId(templateId);\n let modulePath = await resolveModule(moduleId);\n let carsonTemplatePath = path.join(modulePath, TEMPLATES_PATH, templateName);\n\n if (await fs.pathExists(carsonTemplatePath)) {\n let templateConfigPath = path.join(carsonTemplatePath, TEMPLATE_CONFIG_FILENAME);\n let templateConfig = await readFile(templateConfigPath, carsonTemplateConfigSchema, {\n throwOnZodError: true,\n });\n let templateFilePaths = await glob('**/*.ejs', {\n cwd: carsonTemplatePath,\n dot: true,\n });\n let carsonTemplate: CarsonTemplate = {\n name: templateName,\n config: templateConfig,\n files: [],\n };\n\n for (let templateFilePath of templateFilePaths) {\n carsonTemplate.files.push(\n await Template.read(path.join(carsonTemplatePath, templateFilePath), {\n attributesSchema: templateAttributesSchema,\n }),\n );\n }\n\n return carsonTemplate;\n }\n\n throw new CarsonTemplateError('CARSON_TEMPLATE_NOT_FOUND', {\n messageParameters: [templateId, moduleId],\n });\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAQ,gBAAe;AACvB,SAAQ,gBAAe;AACvB,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,SAAQ,0BAA0B,sBAAqB;AAEvD,SAAQ,kCAAiC;AACzC,SAAQ,2BAA0B;AAClC,SAAQ,gCAA+B;AACvC,SAAQ,6BAA4B;AACpC,SAAQ,qBAAoB;AAE5B,sBAAsB,mBAAmB,YAA6C;AACpF,MAAI,CAAC,UAAU,YAAY,IAAI,sBAAsB,UAAU;AAC/D,MAAI,aAAa,MAAM,cAAc,QAAQ;AAC7C,MAAI,qBAAqB,KAAK,KAAK,YAAY,gBAAgB,YAAY;AAE3E,MAAI,MAAM,GAAG,WAAW,kBAAkB,GAAG;AAC3C,QAAI,qBAAqB,KAAK,KAAK,oBAAoB,wBAAwB;AAC/E,QAAI,iBAAiB,MAAM,SAAS,oBAAoB,4BAA4B;AAAA,MAClF,iBAAiB;AAAA,IACnB,CAAC;AACD,QAAI,oBAAoB,MAAM,KAAK,YAAY;AAAA,MAC7C,KAAK;AAAA,MACL,KAAK;AAAA,IACP,CAAC;AACD,QAAI,iBAAiC;AAAA,MACnC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO,CAAC;AAAA,IACV;AAEA,aAAS,oBAAoB,mBAAmB;AAC9C,qBAAe,MAAM;AAAA,QACnB,MAAM,SAAS,KAAK,KAAK,KAAK,oBAAoB,gBAAgB,GAAG;AAAA,UACnE,kBAAkB;AAAA,QACpB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,oBAAoB,6BAA6B;AAAA,IACzD,mBAAmB,CAAC,YAAY,QAAQ;AAAA,EAC1C,CAAC;AACH;",
|
|
4
|
+
"sourcesContent": ["import {Template} from '@jakubmazanec/template';\nimport {readFile} from '@jakubmazanec/zod-utils';\nimport glob from 'fast-glob';\nimport fs from 'fs-extra';\nimport path from 'node:path';\n\nimport {TEMPLATE_CONFIG_FILENAME, TEMPLATES_PATH} from '../../constants.js';\nimport {type CarsonTemplate} from '../CarsonTemplate.js';\nimport {carsonTemplateConfigSchema} from '../CarsonTemplateConfig.js';\nimport {CarsonTemplateError} from '../CarsonTemplateError.js';\nimport {templateAttributesSchema} from '../TemplateAttributes.js';\nimport {parseCarsonTemplateId} from './parseCarsonTemplateId.js';\nimport {resolveModule} from './resolveModule.js';\n\nexport async function readCarsonTemplate(templateId: string): Promise<CarsonTemplate> {\n let [moduleId, templateName] = parseCarsonTemplateId(templateId);\n let modulePath = await resolveModule(moduleId);\n let carsonTemplatePath = path.join(modulePath, TEMPLATES_PATH, templateName);\n\n if (await fs.pathExists(carsonTemplatePath)) {\n let templateConfigPath = path.join(carsonTemplatePath, TEMPLATE_CONFIG_FILENAME);\n let templateConfig = await readFile(templateConfigPath, carsonTemplateConfigSchema, {\n throwOnZodError: true,\n });\n let templateFilePaths = await glob('**/*.ejs', {\n cwd: carsonTemplatePath,\n dot: true,\n });\n let carsonTemplate: CarsonTemplate = {\n id: templateId,\n name: templateName,\n config: templateConfig,\n files: [],\n };\n\n for (let templateFilePath of templateFilePaths) {\n carsonTemplate.files.push(\n await Template.read(path.join(carsonTemplatePath, templateFilePath), {\n attributesSchema: templateAttributesSchema,\n }),\n );\n }\n\n return carsonTemplate;\n }\n\n throw new CarsonTemplateError('CARSON_TEMPLATE_NOT_FOUND', {\n messageParameters: [templateId, moduleId],\n });\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAQ,gBAAe;AACvB,SAAQ,gBAAe;AACvB,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,SAAQ,0BAA0B,sBAAqB;AAEvD,SAAQ,kCAAiC;AACzC,SAAQ,2BAA0B;AAClC,SAAQ,gCAA+B;AACvC,SAAQ,6BAA4B;AACpC,SAAQ,qBAAoB;AAE5B,sBAAsB,mBAAmB,YAA6C;AACpF,MAAI,CAAC,UAAU,YAAY,IAAI,sBAAsB,UAAU;AAC/D,MAAI,aAAa,MAAM,cAAc,QAAQ;AAC7C,MAAI,qBAAqB,KAAK,KAAK,YAAY,gBAAgB,YAAY;AAE3E,MAAI,MAAM,GAAG,WAAW,kBAAkB,GAAG;AAC3C,QAAI,qBAAqB,KAAK,KAAK,oBAAoB,wBAAwB;AAC/E,QAAI,iBAAiB,MAAM,SAAS,oBAAoB,4BAA4B;AAAA,MAClF,iBAAiB;AAAA,IACnB,CAAC;AACD,QAAI,oBAAoB,MAAM,KAAK,YAAY;AAAA,MAC7C,KAAK;AAAA,MACL,KAAK;AAAA,IACP,CAAC;AACD,QAAI,iBAAiC;AAAA,MACnC,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO,CAAC;AAAA,IACV;AAEA,aAAS,oBAAoB,mBAAmB;AAC9C,qBAAe,MAAM;AAAA,QACnB,MAAM,SAAS,KAAK,KAAK,KAAK,oBAAoB,gBAAgB,GAAG;AAAA,UACnE,kBAAkB;AAAA,QACpB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,oBAAoB,6BAA6B;AAAA,IACzD,mBAAmB,CAAC,YAAY,QAAQ;AAAA,EAC1C,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { type CarsonTemplate } from './CarsonTemplate.js';
|
|
1
2
|
import { type TemplateData } from './TemplateData.js';
|
|
2
3
|
import { type TemplateRenders } from './TemplateRenders.js';
|
|
3
4
|
export type RenderCarsonTemplateOptions = {
|
|
4
|
-
|
|
5
|
+
template: CarsonTemplate;
|
|
5
6
|
templateData: TemplateData;
|
|
6
7
|
};
|
|
7
8
|
/**
|
|
@@ -2,19 +2,13 @@
|
|
|
2
2
|
import { pathToPosixPath } from "@jakubmazanec/fs-utils";
|
|
3
3
|
import _ from "lodash";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
importCarsonTemplate,
|
|
7
|
-
parseCarsonTemplateId,
|
|
8
|
-
readCarsonTemplate,
|
|
9
|
-
resolveModule
|
|
10
|
-
} from "./internals.js";
|
|
5
|
+
import { importCarsonTemplate, parseCarsonTemplateId, resolveModule } from "./internals.js";
|
|
11
6
|
export async function renderCarsonTemplate(options) {
|
|
12
|
-
let [moduleId] = parseCarsonTemplateId(options.
|
|
7
|
+
let [moduleId] = parseCarsonTemplateId(options.template.id);
|
|
13
8
|
let modulePath = await resolveModule(moduleId);
|
|
14
|
-
let
|
|
15
|
-
let templateModule = await importCarsonTemplate(options.templateId);
|
|
9
|
+
let templateModule = await importCarsonTemplate(options.template.id);
|
|
16
10
|
let templateRenders = [];
|
|
17
|
-
for (let file of template.files) {
|
|
11
|
+
for (let file of options.template.files) {
|
|
18
12
|
templateRenders.push(
|
|
19
13
|
...(await file.render(
|
|
20
14
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../source/template/renderCarsonTemplate.ts"],
|
|
4
|
-
"sourcesContent": ["import {pathToPosixPath} from '@jakubmazanec/fs-utils';\nimport _ from 'lodash';\nimport path from 'node:path';\n\nimport {
|
|
5
|
-
"mappings": ";AAAA,SAAQ,uBAAsB;AAC9B,OAAO,OAAO;AACd,OAAO,UAAU;
|
|
4
|
+
"sourcesContent": ["import {pathToPosixPath} from '@jakubmazanec/fs-utils';\nimport _ from 'lodash';\nimport path from 'node:path';\n\nimport {type CarsonTemplate} from './CarsonTemplate.js';\nimport {importCarsonTemplate, parseCarsonTemplateId, resolveModule} from './internals.js';\nimport {type TemplateData} from './TemplateData.js';\nimport {type TemplateRenders} from './TemplateRenders.js';\n\nexport type RenderCarsonTemplateOptions = {\n template: CarsonTemplate;\n templateData: TemplateData;\n};\n\n/**\n * Renders a Carson template with provided template data.\n */\nexport async function renderCarsonTemplate(\n options: RenderCarsonTemplateOptions,\n): Promise<TemplateRenders> {\n let [moduleId] = parseCarsonTemplateId(options.template.id);\n let modulePath = await resolveModule(moduleId);\n let templateModule = await importCarsonTemplate(options.template.id);\n let templateRenders: TemplateRenders = [];\n\n for (let file of options.template.files) {\n templateRenders.push(\n ...(\n await file.render(\n {\n ...templateModule,\n ...options.templateData,\n },\n {disablePrettier: true},\n )\n ).map((templateRender) => ({\n ...templateRender,\n template: {\n path: pathToPosixPath(\n `${moduleId}/${path.relative(modulePath, file.path ?? modulePath)}`,\n ),\n },\n })),\n );\n }\n\n templateRenders = _.sortBy(templateRenders, [\n (templateRender) => templateRender.attributes.to,\n (templateRender) => templateRender.attributes.strategy,\n (templateRender) => templateRender.content,\n ]);\n\n return templateRenders;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAQ,uBAAsB;AAC9B,OAAO,OAAO;AACd,OAAO,UAAU;AAGjB,SAAQ,sBAAsB,uBAAuB,qBAAoB;AAYzE,sBAAsB,qBACpB,SAC0B;AAC1B,MAAI,CAAC,QAAQ,IAAI,sBAAsB,QAAQ,SAAS,EAAE;AAC1D,MAAI,aAAa,MAAM,cAAc,QAAQ;AAC7C,MAAI,iBAAiB,MAAM,qBAAqB,QAAQ,SAAS,EAAE;AACnE,MAAI,kBAAmC,CAAC;AAExC,WAAS,QAAQ,QAAQ,SAAS,OAAO;AACvC,oBAAgB;AAAA,MACd,IACE,MAAM,KAAK;AAAA,QACT;AAAA,UACE,GAAG;AAAA,UACH,GAAG,QAAQ;AAAA,QACb;AAAA,QACA,EAAC,iBAAiB,KAAI;AAAA,MACxB,GACA,IAAI,CAAC,oBAAoB;AAAA,QACzB,GAAG;AAAA,QACH,UAAU;AAAA,UACR,MAAM;AAAA,YACJ,GAAG,QAAQ,IAAI,KAAK,SAAS,YAAY,KAAK,QAAQ,UAAU,CAAC;AAAA,UACnE;AAAA,QACF;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,EACF;AAEA,oBAAkB,EAAE,OAAO,iBAAiB;AAAA,IAC1C,CAAC,mBAAmB,eAAe,WAAW;AAAA,IAC9C,CAAC,mBAAmB,eAAe,WAAW;AAAA,IAC9C,CAAC,mBAAmB,eAAe;AAAA,EACrC,CAAC;AAED,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
PROJECT_SNAPSHOT_FILENAME
|
|
12
12
|
} from "../constants.js";
|
|
13
13
|
import { applyTemplateRenders } from "../template/applyTemplateRenders.js";
|
|
14
|
+
import { readCarsonTemplate } from "../template/internals.js";
|
|
14
15
|
import { renderCarsonTemplate } from "../template/renderCarsonTemplate.js";
|
|
15
16
|
import { projectConfigSchema } from "./ProjectConfig.js";
|
|
16
17
|
import { ProjectError } from "./ProjectError.js";
|
|
@@ -88,8 +89,9 @@ export class Project {
|
|
|
88
89
|
});
|
|
89
90
|
}
|
|
90
91
|
}
|
|
92
|
+
let template = await readCarsonTemplate(templateId);
|
|
91
93
|
let templateRenders = await renderCarsonTemplate({
|
|
92
|
-
|
|
94
|
+
template,
|
|
93
95
|
templateData: {
|
|
94
96
|
workspace,
|
|
95
97
|
project,
|
|
@@ -99,10 +101,12 @@ export class Project {
|
|
|
99
101
|
await applyTemplateRenders({
|
|
100
102
|
templateRenders,
|
|
101
103
|
targetPath: project.path,
|
|
102
|
-
snapshotPath: path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
104
|
+
snapshotPath: template.config.autoEject || !workspace.config.template ? void 0 : path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
103
105
|
ignoreStrategies: ["check"]
|
|
104
106
|
});
|
|
105
|
-
|
|
107
|
+
if (!template.config.autoEject && workspace.config.template) {
|
|
108
|
+
await saveProjectConfig({ projectPath: project.path, projectConfig: { template: templateId } });
|
|
109
|
+
}
|
|
106
110
|
await project.read();
|
|
107
111
|
return project;
|
|
108
112
|
}
|
|
@@ -184,8 +188,9 @@ export class Project {
|
|
|
184
188
|
messageParameters: [path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME)]
|
|
185
189
|
});
|
|
186
190
|
}
|
|
191
|
+
let template = await readCarsonTemplate(this.config.template);
|
|
187
192
|
let templateRenders = await renderCarsonTemplate({
|
|
188
|
-
|
|
193
|
+
template,
|
|
189
194
|
templateData: {
|
|
190
195
|
workspace: this.workspace,
|
|
191
196
|
project: this,
|
|
@@ -195,7 +200,7 @@ export class Project {
|
|
|
195
200
|
await applyTemplateRenders({
|
|
196
201
|
templateRenders,
|
|
197
202
|
targetPath: this.path,
|
|
198
|
-
snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
203
|
+
snapshotPath: template.config.autoEject || !this.workspace.config.template ? void 0 : path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
199
204
|
ignoreStrategies: ["create"]
|
|
200
205
|
});
|
|
201
206
|
await this.read();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../source/workspace/Project.ts"],
|
|
4
|
-
"sourcesContent": ["import {ensureEmptyDirectory, pathToPosixPath} from '@jakubmazanec/fs-utils';\nimport {type PackageJson, packageJsonSchema, readFile} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json5 from 'json5';\nimport path from 'node:path';\nimport {z} from 'zod';\n\nimport {\n CARSON_CONFIG_DIRECTORY,\n PROJECT_CONFIG_FILENAME,\n PROJECT_SNAPSHOT_FILENAME,\n} from '../constants.js';\nimport {applyTemplateRenders} from '../template/applyTemplateRenders.js';\nimport {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';\nimport {type ProjectConfig, projectConfigSchema} from './ProjectConfig.js';\nimport {type ProjectCreateOptions} from './ProjectCreateOptions.js';\nimport {ProjectError} from './ProjectError.js';\nimport {type ProjectOptions} from './ProjectOptions.js';\nimport {type ProjectUpdateOptions} from './ProjectUpdateOptions.js';\nimport {saveProjectConfig} from './saveProjectConfig.js';\nimport {type Workspace} from './Workspace.js';\n\n/**\n * Project represent a self-contained piece of software (e.g. a package, or an app) that is part of a {@link Workspace}. Currently only Node.js projects are supported.\n *\n * @typeParam M If true, the project belongs to a multi-project workspace.\n */\nexport class Project<M extends boolean = true> {\n /** Project name. */\n name?: string;\n\n /** Project path. */\n path: string;\n\n /** Project path relative to workspace path. */\n relativePath: string;\n\n /** Project configuration; if it's not found, the default is an empty object. */\n config: ProjectConfig;\n\n /** Parsed project `package.json` file; if it's not found, the default is an empty object. */\n packageJson: PackageJson;\n\n /** Parent {@link Workspace} instance. */\n workspace: Workspace<M>;\n\n /** Errors found during reading from the file system. */\n errors: Array<InstanceType<typeof ProjectError>> = [];\n\n constructor({\n path: projectPath,\n name,\n config,\n packageJson,\n workspace,\n errors,\n }: ProjectOptions<M>) {\n // TODO: check that this path and workspace path are correct, i.e. project path must always be inside of workspace path\n this.path = projectPath;\n\n if (name) {\n this.name = name;\n }\n\n if (config) {\n this.config = config;\n } else {\n this.config = {};\n }\n\n if (packageJson) {\n this.packageJson = packageJson;\n } else {\n this.packageJson = {};\n }\n\n this.workspace = workspace;\n\n if (errors) {\n this.errors = errors;\n }\n\n if (this.packageJson.name?.length) {\n this.name = this.packageJson.name;\n }\n\n this.relativePath = pathToPosixPath(path.relative(this.workspace.path, this.path));\n }\n\n static async create<M extends boolean>({\n templateId,\n workspace,\n projectPath,\n projectName,\n args,\n }: ProjectCreateOptions<M>): Promise<Project<M>> {\n let project = new this({\n path: projectPath,\n name: projectName,\n config: {\n template: templateId,\n },\n workspace,\n });\n\n // if the workspace is single-project, it shares a directory with the project, so we can't insist on it being an empty directory\n if (workspace.isMultiProject) {\n try {\n await ensureEmptyDirectory(project.path);\n } catch {\n throw new ProjectError('PROJECT_PATH_NOT_EMPTY', {\n messageParameters: [project.path],\n data: {\n path: project.path,\n },\n });\n }\n }\n\n let templateRenders = await renderCarsonTemplate({\n
|
|
5
|
-
"mappings": ";AAAA,SAAQ,sBAAsB,uBAAsB;AACpD,SAA0B,mBAAmB,gBAAe;AAC5D,OAAO,QAAQ;AACf,OAAO,WAAW;AAClB,OAAO,UAAU;AACjB,SAAQ,SAAQ;AAEhB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAQ,4BAA2B;AACnC,SAAQ,4BAA2B;AACnC,SAA4B,2BAA0B;AAEtD,SAAQ,oBAAmB;AAG3B,SAAQ,yBAAwB;AAQzB,aAAM,QAAkC;AAAA;AAAA,EAE7C;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA,SAAmD,CAAC;AAAA,EAEpD,YAAY;AAAA,IACV,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAsB;AAEpB,SAAK,OAAO;AAEZ,QAAI,MAAM;AACR,WAAK,OAAO;AAAA,IACd;AAEA,QAAI,QAAQ;AACV,WAAK,SAAS;AAAA,IAChB,OAAO;AACL,WAAK,SAAS,CAAC;AAAA,IACjB;AAEA,QAAI,aAAa;AACf,WAAK,cAAc;AAAA,IACrB,OAAO;AACL,WAAK,cAAc,CAAC;AAAA,IACtB;AAEA,SAAK,YAAY;AAEjB,QAAI,QAAQ;AACV,WAAK,SAAS;AAAA,IAChB;AAEA,QAAI,KAAK,YAAY,MAAM,QAAQ;AACjC,WAAK,OAAO,KAAK,YAAY;AAAA,IAC/B;AAEA,SAAK,eAAe,gBAAgB,KAAK,SAAS,KAAK,UAAU,MAAM,KAAK,IAAI,CAAC;AAAA,EACnF;AAAA,EAEA,aAAa,OAA0B;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAiD;AAC/C,QAAI,UAAU,IAAI,KAAK;AAAA,MACrB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,MACA;AAAA,IACF,CAAC;AAGD,QAAI,UAAU,gBAAgB;AAC5B,UAAI;AACF,cAAM,qBAAqB,QAAQ,IAAI;AAAA,MACzC,QAAQ;AACN,cAAM,IAAI,aAAa,0BAA0B;AAAA,UAC/C,mBAAmB,CAAC,QAAQ,IAAI;AAAA,UAChC,MAAM;AAAA,YACJ,MAAM,QAAQ;AAAA,UAChB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,kBAAkB,MAAM,qBAAqB;AAAA,MAC/C;AAAA,MACA,cAAc;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,qBAAqB;AAAA,MACzB;AAAA,MACA,YAAY,QAAQ;AAAA,MACpB,
|
|
4
|
+
"sourcesContent": ["import {ensureEmptyDirectory, pathToPosixPath} from '@jakubmazanec/fs-utils';\nimport {type PackageJson, packageJsonSchema, readFile} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json5 from 'json5';\nimport path from 'node:path';\nimport {z} from 'zod';\n\nimport {\n CARSON_CONFIG_DIRECTORY,\n PROJECT_CONFIG_FILENAME,\n PROJECT_SNAPSHOT_FILENAME,\n} from '../constants.js';\nimport {applyTemplateRenders} from '../template/applyTemplateRenders.js';\nimport {readCarsonTemplate} from '../template/internals.js';\nimport {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';\nimport {type ProjectConfig, projectConfigSchema} from './ProjectConfig.js';\nimport {type ProjectCreateOptions} from './ProjectCreateOptions.js';\nimport {ProjectError} from './ProjectError.js';\nimport {type ProjectOptions} from './ProjectOptions.js';\nimport {type ProjectUpdateOptions} from './ProjectUpdateOptions.js';\nimport {saveProjectConfig} from './saveProjectConfig.js';\nimport {type Workspace} from './Workspace.js';\n\n/**\n * Project represent a self-contained piece of software (e.g. a package, or an app) that is part of a {@link Workspace}. Currently only Node.js projects are supported.\n *\n * @typeParam M If true, the project belongs to a multi-project workspace.\n */\nexport class Project<M extends boolean = true> {\n /** Project name. */\n name?: string;\n\n /** Project path. */\n path: string;\n\n /** Project path relative to workspace path. */\n relativePath: string;\n\n /** Project configuration; if it's not found, the default is an empty object. */\n config: ProjectConfig;\n\n /** Parsed project `package.json` file; if it's not found, the default is an empty object. */\n packageJson: PackageJson;\n\n /** Parent {@link Workspace} instance. */\n workspace: Workspace<M>;\n\n /** Errors found during reading from the file system. */\n errors: Array<InstanceType<typeof ProjectError>> = [];\n\n constructor({\n path: projectPath,\n name,\n config,\n packageJson,\n workspace,\n errors,\n }: ProjectOptions<M>) {\n // TODO: check that this path and workspace path are correct, i.e. project path must always be inside of workspace path\n this.path = projectPath;\n\n if (name) {\n this.name = name;\n }\n\n if (config) {\n this.config = config;\n } else {\n this.config = {};\n }\n\n if (packageJson) {\n this.packageJson = packageJson;\n } else {\n this.packageJson = {};\n }\n\n this.workspace = workspace;\n\n if (errors) {\n this.errors = errors;\n }\n\n if (this.packageJson.name?.length) {\n this.name = this.packageJson.name;\n }\n\n this.relativePath = pathToPosixPath(path.relative(this.workspace.path, this.path));\n }\n\n static async create<M extends boolean>({\n templateId,\n workspace,\n projectPath,\n projectName,\n args,\n }: ProjectCreateOptions<M>): Promise<Project<M>> {\n let project = new this({\n path: projectPath,\n name: projectName,\n config: {\n template: templateId,\n },\n workspace,\n });\n\n // if the workspace is single-project, it shares a directory with the project, so we can't insist on it being an empty directory\n if (workspace.isMultiProject) {\n try {\n await ensureEmptyDirectory(project.path);\n } catch {\n throw new ProjectError('PROJECT_PATH_NOT_EMPTY', {\n messageParameters: [project.path],\n data: {\n path: project.path,\n },\n });\n }\n }\n\n let template = await readCarsonTemplate(templateId);\n let templateRenders = await renderCarsonTemplate({\n template,\n templateData: {\n workspace,\n project,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: project.path,\n snapshotPath:\n template.config.autoEject || !workspace.config.template ?\n undefined\n : path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),\n ignoreStrategies: ['check'],\n });\n\n if (!template.config.autoEject && workspace.config.template) {\n await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});\n }\n\n await project.read();\n\n return project;\n }\n\n static async read<M extends boolean>(\n projectPath: string,\n workspace: Workspace<M>,\n ): Promise<Project<M>> {\n let project = new this({\n path: projectPath,\n workspace,\n });\n\n await project.read();\n\n return project;\n }\n\n async read() {\n if (!(await fs.pathExists(this.path))) {\n throw new ProjectError('NO_SUCH_PROJECT_PATH', {\n messageParameters: [this.path],\n data: {\n path: this.path,\n },\n });\n }\n\n let errors: Array<InstanceType<typeof ProjectError>> = [];\n\n // load project config\n let projectConfigPath = path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME);\n let doesProjectConfigExist = await fs.pathExists(projectConfigPath);\n let projectConfig: ProjectConfig | z.ZodError;\n\n if (doesProjectConfigExist) {\n projectConfig = await readFile(projectConfigPath, projectConfigSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n projectConfig = {};\n }\n\n if (projectConfig instanceof z.ZodError) {\n let zodError = projectConfig;\n\n errors.push(\n new ProjectError('INVALID_PROJECT_CONFIG', {\n messageParameters: [projectConfigPath],\n data: {\n path: projectConfigPath,\n zodIssues: zodError.issues,\n },\n }),\n );\n\n projectConfig = {};\n }\n\n // load package.json\n let packageJsonPath = path.join(this.path, 'package.json');\n let doesPackageJsonExist = await fs.pathExists(packageJsonPath);\n let packageJson: PackageJson | z.ZodError;\n\n if (doesPackageJsonExist) {\n packageJson = await readFile(packageJsonPath, packageJsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n packageJson = {};\n }\n\n if (packageJson instanceof z.ZodError) {\n let zodError = packageJson;\n\n errors.push(\n new ProjectError('INVALID_PACKAGE_JSON', {\n messageParameters: [packageJsonPath],\n data: {\n path: packageJsonPath,\n zodIssues: zodError.issues,\n },\n }),\n );\n\n packageJson = {};\n }\n\n if (packageJson.name?.length) {\n this.name = packageJson.name;\n }\n\n this.config = projectConfig;\n this.packageJson = packageJson;\n this.errors = errors;\n\n return this;\n }\n\n async update({args}: ProjectUpdateOptions): Promise<this> {\n if (!this.config.template) {\n throw new ProjectError('MISSING_CARSON_TEMPLATE_ID', {\n messageParameters: [path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME)],\n });\n }\n\n let template = await readCarsonTemplate(this.config.template);\n let templateRenders = await renderCarsonTemplate({\n template,\n templateData: {\n workspace: this.workspace,\n project: this,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: this.path,\n snapshotPath:\n template.config.autoEject || !this.workspace.config.template ?\n undefined\n : path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),\n ignoreStrategies: ['create'],\n });\n\n await this.read();\n\n return this;\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAQ,sBAAsB,uBAAsB;AACpD,SAA0B,mBAAmB,gBAAe;AAC5D,OAAO,QAAQ;AACf,OAAO,WAAW;AAClB,OAAO,UAAU;AACjB,SAAQ,SAAQ;AAEhB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAQ,4BAA2B;AACnC,SAAQ,0BAAyB;AACjC,SAAQ,4BAA2B;AACnC,SAA4B,2BAA0B;AAEtD,SAAQ,oBAAmB;AAG3B,SAAQ,yBAAwB;AAQzB,aAAM,QAAkC;AAAA;AAAA,EAE7C;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA,SAAmD,CAAC;AAAA,EAEpD,YAAY;AAAA,IACV,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAsB;AAEpB,SAAK,OAAO;AAEZ,QAAI,MAAM;AACR,WAAK,OAAO;AAAA,IACd;AAEA,QAAI,QAAQ;AACV,WAAK,SAAS;AAAA,IAChB,OAAO;AACL,WAAK,SAAS,CAAC;AAAA,IACjB;AAEA,QAAI,aAAa;AACf,WAAK,cAAc;AAAA,IACrB,OAAO;AACL,WAAK,cAAc,CAAC;AAAA,IACtB;AAEA,SAAK,YAAY;AAEjB,QAAI,QAAQ;AACV,WAAK,SAAS;AAAA,IAChB;AAEA,QAAI,KAAK,YAAY,MAAM,QAAQ;AACjC,WAAK,OAAO,KAAK,YAAY;AAAA,IAC/B;AAEA,SAAK,eAAe,gBAAgB,KAAK,SAAS,KAAK,UAAU,MAAM,KAAK,IAAI,CAAC;AAAA,EACnF;AAAA,EAEA,aAAa,OAA0B;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAiD;AAC/C,QAAI,UAAU,IAAI,KAAK;AAAA,MACrB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,MACA;AAAA,IACF,CAAC;AAGD,QAAI,UAAU,gBAAgB;AAC5B,UAAI;AACF,cAAM,qBAAqB,QAAQ,IAAI;AAAA,MACzC,QAAQ;AACN,cAAM,IAAI,aAAa,0BAA0B;AAAA,UAC/C,mBAAmB,CAAC,QAAQ,IAAI;AAAA,UAChC,MAAM;AAAA,YACJ,MAAM,QAAQ;AAAA,UAChB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,WAAW,MAAM,mBAAmB,UAAU;AAClD,QAAI,kBAAkB,MAAM,qBAAqB;AAAA,MAC/C;AAAA,MACA,cAAc;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,qBAAqB;AAAA,MACzB;AAAA,MACA,YAAY,QAAQ;AAAA,MACpB,cACE,SAAS,OAAO,aAAa,CAAC,UAAU,OAAO,WAC7C,SACA,KAAK,KAAK,QAAQ,MAAM,yBAAyB,yBAAyB;AAAA,MAC9E,kBAAkB,CAAC,OAAO;AAAA,IAC5B,CAAC;AAED,QAAI,CAAC,SAAS,OAAO,aAAa,UAAU,OAAO,UAAU;AAC3D,YAAM,kBAAkB,EAAC,aAAa,QAAQ,MAAM,eAAe,EAAC,UAAU,WAAU,EAAC,CAAC;AAAA,IAC5F;AAEA,UAAM,QAAQ,KAAK;AAEnB,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,KACX,aACA,WACqB;AACrB,QAAI,UAAU,IAAI,KAAK;AAAA,MACrB,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAED,UAAM,QAAQ,KAAK;AAEnB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO;AACX,QAAI,CAAE,MAAM,GAAG,WAAW,KAAK,IAAI,GAAI;AACrC,YAAM,IAAI,aAAa,wBAAwB;AAAA,QAC7C,mBAAmB,CAAC,KAAK,IAAI;AAAA,QAC7B,MAAM;AAAA,UACJ,MAAM,KAAK;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,SAAmD,CAAC;AAGxD,QAAI,oBAAoB,KAAK,KAAK,KAAK,MAAM,yBAAyB,uBAAuB;AAC7F,QAAI,yBAAyB,MAAM,GAAG,WAAW,iBAAiB;AAClE,QAAI;AAEJ,QAAI,wBAAwB;AAC1B,sBAAgB,MAAM,SAAS,mBAAmB,qBAAqB;AAAA,QACrE,QAAQ,CAAC,cAAsB,MAAM,MAAe,SAAS;AAAA,MAC/D,CAAC;AAAA,IACH,OAAO;AACL,sBAAgB,CAAC;AAAA,IACnB;AAEA,QAAI,yBAAyB,EAAE,UAAU;AACvC,UAAI,WAAW;AAEf,aAAO;AAAA,QACL,IAAI,aAAa,0BAA0B;AAAA,UACzC,mBAAmB,CAAC,iBAAiB;AAAA,UACrC,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,WAAW,SAAS;AAAA,UACtB;AAAA,QACF,CAAC;AAAA,MACH;AAEA,sBAAgB,CAAC;AAAA,IACnB;AAGA,QAAI,kBAAkB,KAAK,KAAK,KAAK,MAAM,cAAc;AACzD,QAAI,uBAAuB,MAAM,GAAG,WAAW,eAAe;AAC9D,QAAI;AAEJ,QAAI,sBAAsB;AACxB,oBAAc,MAAM,SAAS,iBAAiB,mBAAmB;AAAA,QAC/D,QAAQ,CAAC,cAAsB,MAAM,MAAe,SAAS;AAAA,MAC/D,CAAC;AAAA,IACH,OAAO;AACL,oBAAc,CAAC;AAAA,IACjB;AAEA,QAAI,uBAAuB,EAAE,UAAU;AACrC,UAAI,WAAW;AAEf,aAAO;AAAA,QACL,IAAI,aAAa,wBAAwB;AAAA,UACvC,mBAAmB,CAAC,eAAe;AAAA,UACnC,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,WAAW,SAAS;AAAA,UACtB;AAAA,QACF,CAAC;AAAA,MACH;AAEA,oBAAc,CAAC;AAAA,IACjB;AAEA,QAAI,YAAY,MAAM,QAAQ;AAC5B,WAAK,OAAO,YAAY;AAAA,IAC1B;AAEA,SAAK,SAAS;AACd,SAAK,cAAc;AACnB,SAAK,SAAS;AAEd,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,EAAC,KAAI,GAAwC;AACxD,QAAI,CAAC,KAAK,OAAO,UAAU;AACzB,YAAM,IAAI,aAAa,8BAA8B;AAAA,QACnD,mBAAmB,CAAC,KAAK,KAAK,KAAK,MAAM,yBAAyB,uBAAuB,CAAC;AAAA,MAC5F,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,MAAM,mBAAmB,KAAK,OAAO,QAAQ;AAC5D,QAAI,kBAAkB,MAAM,qBAAqB;AAAA,MAC/C;AAAA,MACA,cAAc;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,qBAAqB;AAAA,MACzB;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,cACE,SAAS,OAAO,aAAa,CAAC,KAAK,UAAU,OAAO,WAClD,SACA,KAAK,KAAK,KAAK,MAAM,yBAAyB,yBAAyB;AAAA,MAC3E,kBAAkB,CAAC,QAAQ;AAAA,IAC7B,CAAC;AAED,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
WORKSPACE_SNAPSHOT_FILENAME
|
|
14
14
|
} from "../constants.js";
|
|
15
15
|
import { applyTemplateRenders } from "../template/applyTemplateRenders.js";
|
|
16
|
+
import { readCarsonTemplate } from "../template/internals.js";
|
|
16
17
|
import { renderCarsonTemplate } from "../template/renderCarsonTemplate.js";
|
|
17
18
|
import {
|
|
18
19
|
compareProjectPath,
|
|
@@ -129,8 +130,9 @@ export class Workspace {
|
|
|
129
130
|
}
|
|
130
131
|
});
|
|
131
132
|
}
|
|
133
|
+
let template = await readCarsonTemplate(templateId);
|
|
132
134
|
let templateRenders = await renderCarsonTemplate({
|
|
133
|
-
|
|
135
|
+
template,
|
|
134
136
|
templateData: {
|
|
135
137
|
workspace,
|
|
136
138
|
args
|
|
@@ -139,13 +141,15 @@ export class Workspace {
|
|
|
139
141
|
await applyTemplateRenders({
|
|
140
142
|
templateRenders,
|
|
141
143
|
targetPath: workspace.path,
|
|
142
|
-
snapshotPath: path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
144
|
+
snapshotPath: template.config.autoEject ? void 0 : path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
143
145
|
ignoreStrategies: ["check"]
|
|
144
146
|
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
if (!template.config.autoEject) {
|
|
148
|
+
await saveWorkspaceConfig({
|
|
149
|
+
workspacePath: workspace.path,
|
|
150
|
+
workspaceConfig: { template: templateId }
|
|
151
|
+
});
|
|
152
|
+
}
|
|
149
153
|
return Workspace.read(workspace.path);
|
|
150
154
|
}
|
|
151
155
|
static async read(workspacePath) {
|
|
@@ -360,8 +364,9 @@ export class Workspace {
|
|
|
360
364
|
]
|
|
361
365
|
});
|
|
362
366
|
}
|
|
367
|
+
let template = await readCarsonTemplate(this.config.template);
|
|
363
368
|
let templateRenders = await renderCarsonTemplate({
|
|
364
|
-
|
|
369
|
+
template,
|
|
365
370
|
templateData: {
|
|
366
371
|
workspace: this,
|
|
367
372
|
args
|
|
@@ -370,7 +375,7 @@ export class Workspace {
|
|
|
370
375
|
await applyTemplateRenders({
|
|
371
376
|
templateRenders,
|
|
372
377
|
targetPath: this.path,
|
|
373
|
-
snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
378
|
+
snapshotPath: template.config.autoEject ? void 0 : path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
374
379
|
ignoreStrategies: ["create"]
|
|
375
380
|
});
|
|
376
381
|
await this.read();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../source/workspace/Workspace.ts"],
|
|
4
|
-
"sourcesContent": ["import {ensureEmptyDirectory, findExistingDirectory, isRootPath} from '@jakubmazanec/fs-utils';\nimport {jsonSchema, type PackageJson, packageJsonSchema, readFile} from '@jakubmazanec/zod-utils';\nimport glob from 'fast-glob';\nimport fs from 'fs-extra';\nimport json5 from 'json5';\nimport path from 'node:path';\nimport {z} from 'zod';\n\nimport {\n CARSON_CONFIG_DIRECTORY,\n PACKAGE_JSON_FILENAME,\n WORKSPACE_CONFIG_FILENAME,\n WORKSPACE_SNAPSHOT_FILENAME,\n} from '../constants.js';\nimport {applyTemplateRenders} from '../template/applyTemplateRenders.js';\nimport {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';\nimport {\n compareProjectPath,\n containsProject,\n containsWorkspace,\n getPackageJsonWorkspaces,\n getRepositoryBranches,\n getRepositoryUrl,\n} from './internals.js';\nimport {Project} from './Project.js';\nimport {saveWorkspaceConfig} from './saveWorkspaceConfig.js';\nimport {workspaceConfigSchema} from './WorkspaceConfig.js';\nimport {type WorkspaceConfig} from './WorkspaceConfig.js';\nimport {type WorkspaceCreateOptions} from './WorkspaceCreateOptions.js';\nimport {type WorkspaceCreateProjectOptions} from './WorkspaceCreateProjectOptions.js';\nimport {WorkspaceDependencies} from './WorkspaceDependencies.js';\nimport {WorkspaceError} from './WorkspaceError.js';\nimport {type WorkspaceFindAndReadOptions} from './WorkspaceFindAndReadOptions.js';\nimport {type WorkspaceOptions} from './WorkspaceOptions.js';\nimport {type WorkspacePackageJson} from './WorkspacePackageJson.js';\nimport {type WorkspaceProjectGlobs} from './WorkspaceProjectGlobs.js';\nimport {type WorkspaceProjects} from './WorkspaceProjects.js';\nimport {type WorkspaceRepository} from './WorkspaceRepository.js';\nimport {type WorkspaceUpdateOptions} from './WorkspaceUpdateOptions.js';\n\n/**\n * Workspace represent a directory, usually a git repository, that contains {@link Project} instances.\n *\n * @typeParam M If true, the workspace is multi-project workspace (so-called \"monorepo\").\n */\nexport class Workspace<M extends boolean = true> {\n /** Workspace path. */\n readonly path: string;\n\n /** Does the workspace contain a multiple projects? */\n readonly isMultiProject: M;\n\n /** Globs used to find projects. */\n projectGlobs: WorkspaceProjectGlobs<M>;\n\n /** Workspace projects. */\n projects: WorkspaceProjects<M>;\n\n /** Workspace configuration; if it's not found, the default is an empty object. */\n config: WorkspaceConfig;\n\n /** Parsed workspace `package.json` file (if the workspace contains multiple projects); if it's not found, the default is an empty object. */\n packageJson: WorkspacePackageJson<M>;\n\n /** Workspace git repository. */\n repository?: WorkspaceRepository;\n\n /** Dependencies of all projects. */\n dependencies: WorkspaceDependencies<M> = [] as unknown as WorkspaceDependencies<M>;\n\n /** Development dependencies of all projects. */\n devDependencies: WorkspaceDependencies<M> = [] as unknown as WorkspaceDependencies<M>;\n\n /** All dependencies of all projects and workspace dependencies. */\n allDependencies: WorkspaceDependencies<M> = [] as unknown as WorkspaceDependencies<M>;\n\n /** Versions of each dependency. */\n dependencyVersions: Record<string, string[]> = {};\n\n /** Errors found during reading from the file system. */\n errors: Array<InstanceType<typeof WorkspaceError>> = [];\n\n constructor(options: WorkspaceOptions<M>) {\n this.path = options.path;\n\n if (options.isMultiProject === undefined || options.isMultiProject) {\n this.isMultiProject = true as M;\n\n let projectGlobOption = (options as WorkspaceOptions<true>).projectGlobs;\n\n if (projectGlobOption) {\n this.projectGlobs = projectGlobOption as WorkspaceProjectGlobs<M>;\n } else {\n this.projectGlobs = [] as string[] as WorkspaceProjectGlobs<M>;\n }\n\n this.projects = [] as Array<Project<M>> as WorkspaceProjects<M>;\n\n let {projects} = options as WorkspaceOptions<true>;\n\n if (projects) {\n this.addProjects(projects.map((project) => new Project({...project, workspace: this})));\n }\n\n let packageJsonOption = (options as WorkspaceOptions<true>).packageJson;\n\n if (packageJsonOption) {\n this.packageJson = packageJsonOption as M extends true ? PackageJson : null;\n } else {\n let emptyPackageJson: PackageJson = {};\n\n this.packageJson = emptyPackageJson as M extends true ? PackageJson : null;\n }\n } else {\n this.isMultiProject = false as M;\n this.projectGlobs = null as M extends true ? string[] : null;\n this.packageJson = null as M extends true ? PackageJson : null;\n this.projects = [] as Array<Project<M>> as WorkspaceProjects<M>;\n\n let {projects} = options as WorkspaceOptions<false>;\n\n if (projects) {\n this.addProjects(projects.map((project) => new Project({...project, workspace: this})));\n }\n }\n\n let configOption = options.config;\n\n if (configOption) {\n this.config = configOption;\n } else {\n let emptyWorkspaceConfig: WorkspaceConfig = {};\n\n this.config = emptyWorkspaceConfig;\n }\n\n if (options.repository) {\n this.repository = options.repository;\n }\n\n if (options.errors) {\n this.errors = options.errors;\n }\n\n // add missing project globs\n if (this.isMultiProject && !(this.projectGlobs as string[]).length) {\n let packageJsonWorkspaces = getPackageJsonWorkspaces(this.packageJson as PackageJson);\n\n if (packageJsonWorkspaces) {\n this.projectGlobs = [...packageJsonWorkspaces] as M extends true ? string[] : null;\n }\n }\n\n this.sortProjects();\n this.updateDependencies();\n }\n\n /**\n * Creates new workspace within the file system.\n *\n * @param options Options.\n * @returns The new workspace.\n */\n static async create({args, path: workspacePath, templateId}: WorkspaceCreateOptions) {\n // TODO: test that workspace returned by this method has the same value of isMultiProject when the same workspace is after its creation re-read with .read()\n let workspace = new this({\n path: workspacePath,\n config: {\n template: templateId,\n },\n });\n\n try {\n await ensureEmptyDirectory(workspace.path, {allowGit: true});\n } catch {\n throw new WorkspaceError('WORKSPACE_PATH_NOT_EMPTY', {\n messageParameters: [workspace.path],\n data: {\n path: workspace.path,\n },\n });\n }\n\n let templateRenders = await renderCarsonTemplate({\n templateId,\n templateData: {\n workspace,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: workspace.path,\n snapshotPath: path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),\n ignoreStrategies: ['check'],\n });\n\n await saveWorkspaceConfig({\n workspacePath: workspace.path,\n workspaceConfig: {template: templateId},\n });\n\n return Workspace.read(workspace.path);\n }\n\n static async read(workspacePath: string): Promise<Workspace | Workspace<false>> {\n let resolvedWorkspacePath = path.resolve(workspacePath);\n\n if (!(await fs.pathExists(resolvedWorkspacePath))) {\n throw new WorkspaceError('NO_SUCH_WORKSPACE_PATH', {\n messageParameters: [resolvedWorkspacePath],\n data: {\n path: resolvedWorkspacePath,\n },\n });\n }\n\n // load root package.json\n let rootPackageJsonPath = path.join(resolvedWorkspacePath, 'package.json');\n let doesRootPackageJsonExist = await fs.pathExists(rootPackageJsonPath);\n let rootPackageJson: PackageJson | z.ZodError;\n\n if (doesRootPackageJsonExist) {\n rootPackageJson = await readFile(rootPackageJsonPath, packageJsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n rootPackageJson = {};\n }\n\n if (rootPackageJson instanceof z.ZodError) {\n rootPackageJson = {};\n\n // even if the package.json file has errors, maybe there's still a correct workspace field\n try {\n let rootJson = await readFile(rootPackageJsonPath, jsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n throwOnZodError: true,\n });\n let projectGlobs = getPackageJsonWorkspaces(rootJson);\n\n // add back to the empty package.json object\n if (projectGlobs) {\n rootPackageJson.workspaces = projectGlobs;\n }\n } catch {\n // no-op\n }\n }\n\n // add projects\n let projectGlobs = getPackageJsonWorkspaces(rootPackageJson);\n\n // we're dealing with single-project workspace\n if (!projectGlobs) {\n let workspace = new this({\n path: resolvedWorkspacePath,\n isMultiProject: false,\n });\n\n await workspace.read();\n await workspace.readProjects();\n\n return workspace;\n }\n\n // assemble workspace options\n let workspace = new this({\n path: resolvedWorkspacePath,\n isMultiProject: true,\n projectGlobs,\n packageJson: rootPackageJson,\n });\n\n await workspace.read();\n await workspace.readProjects();\n\n return workspace;\n }\n\n /**\n * Traverses file system up from the search path and tries to find a directory that is a root of a workspace.\n *\n * @param searchPath Search path.\n * @returns Workspace path, if found.\n */\n static async find(searchPath: string): Promise<string | undefined> {\n let startingPath = await findExistingDirectory(path.resolve(searchPath));\n let currentPath = startingPath;\n let singlePackageWorkspacePath: string | undefined;\n let multiPackageWorkspacePath: string | undefined;\n\n while (\n !(isRootPath(currentPath) || (singlePackageWorkspacePath && multiPackageWorkspacePath))\n ) {\n if (await containsWorkspace(currentPath)) {\n const packageJsonPath = path.join(currentPath, PACKAGE_JSON_FILENAME);\n\n if (await fs.pathExists(packageJsonPath)) {\n const packageJson = await readFile(packageJsonPath, jsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n\n if (!(packageJson instanceof Error)) {\n const projectGlobs = getPackageJsonWorkspaces(packageJson);\n\n if (projectGlobs?.length) {\n multiPackageWorkspacePath ??= currentPath;\n } else {\n singlePackageWorkspacePath ??= currentPath;\n }\n }\n } else {\n singlePackageWorkspacePath ??= currentPath;\n }\n }\n\n currentPath = path.dirname(currentPath);\n }\n\n if (multiPackageWorkspacePath) {\n return multiPackageWorkspacePath;\n } else if (singlePackageWorkspacePath) {\n return singlePackageWorkspacePath;\n }\n\n return undefined;\n }\n\n /**\n * Traverses file system up from the search path and tries to find and read a workspace.\n */\n static async findAndRead<O extends WorkspaceFindAndReadOptions | undefined = undefined>(\n searchPath: string,\n options?: O,\n ): Promise<\n O extends undefined ? Workspace | Workspace<false> | undefined\n : NonNullable<O>['throwIfNotFound'] extends true ? Workspace | Workspace<false>\n : Workspace | Workspace<false> | undefined\n > {\n let workspacePath = await Workspace.find(searchPath);\n\n if (workspacePath) {\n return Workspace.read(workspacePath) as Promise<\n O extends undefined ? Workspace | Workspace<false> | undefined\n : NonNullable<O>['throwIfNotFound'] extends true ? Workspace | Workspace<false>\n : Workspace | Workspace<false> | undefined\n >;\n } else if (options?.throwIfNotFound) {\n throw new WorkspaceError('NO_WORKSPACE_FOUND', {\n messageParameters: [searchPath],\n data: {\n path: searchPath,\n },\n });\n }\n\n return undefined as unknown as Promise<\n O extends undefined ? Workspace | Workspace<false> | undefined\n : NonNullable<O>['throwIfNotFound'] extends true ? Workspace | Workspace<false>\n : Workspace | Workspace<false> | undefined\n >;\n }\n\n async read(): Promise<this> {\n if (!(await fs.pathExists(this.path))) {\n throw new WorkspaceError('NO_SUCH_WORKSPACE_PATH', {\n messageParameters: [this.path],\n data: {\n path: this.path,\n },\n });\n }\n\n let errors: Array<InstanceType<typeof WorkspaceError>> = [];\n let repositoryUrl = await getRepositoryUrl(this.path);\n let repositoryBranches = await getRepositoryBranches(this.path);\n\n // load workspace config\n let workspaceConfigPath = path.join(\n this.path,\n CARSON_CONFIG_DIRECTORY,\n WORKSPACE_CONFIG_FILENAME,\n );\n let doesWorkspaceConfigExist = await fs.pathExists(workspaceConfigPath);\n let workspaceConfig: WorkspaceConfig | z.ZodError;\n\n if (doesWorkspaceConfigExist) {\n workspaceConfig = await readFile(workspaceConfigPath, workspaceConfigSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n workspaceConfig = {};\n }\n\n if (workspaceConfig instanceof z.ZodError) {\n let zodError = workspaceConfig;\n let workspaceError = new WorkspaceError('INVALID_WORKSPACE_CONFIG', {\n messageParameters: [workspaceConfigPath],\n data: {\n path: workspaceConfigPath,\n zodIssues: zodError.issues,\n },\n });\n\n errors.push(workspaceError);\n\n workspaceConfig = {};\n }\n\n if (this.isMultiProject) {\n // load root package.json\n let rootPackageJsonPath = path.join(this.path, 'package.json');\n let doesRootPackageJsonExist = await fs.pathExists(rootPackageJsonPath);\n let rootPackageJson: PackageJson | z.ZodError;\n\n if (doesRootPackageJsonExist) {\n rootPackageJson = await readFile(rootPackageJsonPath, packageJsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n rootPackageJson = {};\n }\n\n if (rootPackageJson instanceof z.ZodError) {\n let zodError = rootPackageJson;\n let workspaceError = new WorkspaceError('INVALID_PACKAGE_JSON', {\n messageParameters: [rootPackageJsonPath],\n data: {\n path: rootPackageJsonPath,\n zodIssues: zodError.issues,\n },\n });\n\n errors.push(workspaceError);\n\n rootPackageJson = {};\n }\n\n let projectGlobs = getPackageJsonWorkspaces(rootPackageJson);\n\n this.projectGlobs = (projectGlobs ?? []) as WorkspaceProjectGlobs<M>;\n this.packageJson = rootPackageJson as WorkspacePackageJson<M>;\n this.config = workspaceConfig;\n this.errors = errors;\n\n if (repositoryUrl) {\n this.repository = {\n url: repositoryUrl,\n branches: repositoryBranches ?? [],\n };\n } else if (repositoryBranches) {\n this.repository = {\n branches: repositoryBranches,\n };\n }\n\n await this.readProjects();\n\n return this;\n }\n\n // we're dealing with single-project workspace\n this.config = workspaceConfig;\n this.errors = errors;\n\n if (repositoryUrl) {\n this.repository = {\n url: repositoryUrl,\n branches: repositoryBranches ?? [],\n };\n } else if (repositoryBranches) {\n this.repository = {\n branches: repositoryBranches,\n };\n }\n\n await this.readProjects();\n\n return this;\n }\n\n async update({args}: WorkspaceUpdateOptions): Promise<this> {\n if (!this.config.template) {\n throw new WorkspaceError('MISSING_CARSON_TEMPLATE_ID', {\n messageParameters: [\n path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_CONFIG_FILENAME),\n ],\n });\n }\n\n let templateRenders = await renderCarsonTemplate({\n templateId: this.config.template,\n templateData: {\n workspace: this,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: this.path,\n snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),\n ignoreStrategies: ['create'],\n });\n\n await this.read();\n\n return this;\n }\n\n getProject(projectName: Project<M> | string): Project<M> | undefined {\n for (let project of this.projects) {\n if (project.name === projectName || project === projectName) {\n return project;\n }\n }\n\n return undefined;\n }\n\n async createProject({\n templateId,\n projectPath,\n projectName,\n args,\n }: WorkspaceCreateProjectOptions): Promise<Project<M>> {\n let resolvedProjectPath = path.resolve(projectPath);\n\n if (this.projects.some((project) => resolvedProjectPath === project.path)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_PATH', {\n messageParameters: [resolvedProjectPath],\n });\n }\n\n if (this.projects.some((project) => projectName === project.name)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_NAME', {messageParameters: [projectName]});\n }\n\n if (!this.isMultiProject && this.projects.length >= 1) {\n throw new WorkspaceError('TOO_MANY_PROJECTS');\n }\n\n if (!this.isMultiProject && projectPath !== this.path) {\n throw new WorkspaceError('PATH_MISMATCH');\n }\n\n let newProject = await Project.create({\n templateId,\n projectPath,\n projectName,\n args,\n workspace: this,\n });\n\n this.addProject(newProject);\n\n return newProject;\n }\n\n addProject(newProject: Project<M>): this {\n if (this.projects.some((project) => newProject.path === project.path)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_PATH', {\n messageParameters: [newProject.path],\n });\n }\n\n if (this.projects.some((project) => newProject.name === project.name)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_NAME', {messageParameters: [newProject.name]});\n }\n\n if (!this.isMultiProject && this.projects.length >= 1) {\n throw new WorkspaceError('TOO_MANY_PROJECTS');\n }\n\n if (!this.isMultiProject && newProject.path !== this.path) {\n throw new WorkspaceError('PATH_MISMATCH');\n }\n\n this.projects.push(newProject);\n this.sortProjects();\n this.updateDependencies();\n\n return this;\n }\n\n addProjects(newProjects: Array<Project<M>>): this {\n for (let newProject of newProjects) {\n if (this.projects.some((project) => newProject.path === project.path)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_PATH', {\n messageParameters: [newProject.path],\n });\n }\n\n if (this.projects.some((project) => newProject.name === project.name)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_NAME', {messageParameters: [newProject.name]});\n }\n\n if (!this.isMultiProject && this.projects.length >= 1) {\n throw new WorkspaceError('TOO_MANY_PROJECTS');\n }\n\n if (!this.isMultiProject && newProject.path !== this.path) {\n throw new WorkspaceError('PATH_MISMATCH');\n }\n\n this.projects.push(newProject);\n }\n\n this.sortProjects();\n this.updateDependencies();\n\n return this;\n }\n\n async readProjects(): Promise<Array<Project<M>>> {\n if (this.projectGlobs) {\n let projects: Array<Project<M>> = [];\n let packagePaths = await glob(this.projectGlobs, {\n cwd: this.path,\n onlyDirectories: true,\n });\n\n for (let packagePath of packagePaths) {\n let projectPath = path.join(this.path, packagePath);\n\n if (await containsProject(projectPath)) {\n let project = await Project.read(projectPath, this);\n\n projects.push(project);\n }\n }\n\n this.projects = projects;\n\n this.sortProjects();\n this.updateDependencies();\n } else if (await containsProject(this.path)) {\n this.projects = [await Project.read(this.path, this)];\n\n this.sortProjects();\n this.updateDependencies();\n }\n\n return this.projects;\n }\n\n protected sortProjects(): void {\n this.projects.sort(compareProjectPath);\n }\n\n protected updateDependencies(): void {\n this.dependencies = WorkspaceDependencies.fromWorkspace(this);\n this.devDependencies = WorkspaceDependencies.fromWorkspace(this, {\n includeOnlyDevDependencies: true,\n });\n this.allDependencies = WorkspaceDependencies.fromWorkspace(this, {\n includeDevDependencies: true,\n includeWorkspaceDependencies: true,\n });\n this.dependencyVersions = this.allDependencies.getVersions({\n useExactVersions: true,\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {ensureEmptyDirectory, findExistingDirectory, isRootPath} from '@jakubmazanec/fs-utils';\nimport {jsonSchema, type PackageJson, packageJsonSchema, readFile} from '@jakubmazanec/zod-utils';\nimport glob from 'fast-glob';\nimport fs from 'fs-extra';\nimport json5 from 'json5';\nimport path from 'node:path';\nimport {z} from 'zod';\n\nimport {\n CARSON_CONFIG_DIRECTORY,\n PACKAGE_JSON_FILENAME,\n WORKSPACE_CONFIG_FILENAME,\n WORKSPACE_SNAPSHOT_FILENAME,\n} from '../constants.js';\nimport {applyTemplateRenders} from '../template/applyTemplateRenders.js';\nimport {readCarsonTemplate} from '../template/internals.js';\nimport {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';\nimport {\n compareProjectPath,\n containsProject,\n containsWorkspace,\n getPackageJsonWorkspaces,\n getRepositoryBranches,\n getRepositoryUrl,\n} from './internals.js';\nimport {Project} from './Project.js';\nimport {saveWorkspaceConfig} from './saveWorkspaceConfig.js';\nimport {workspaceConfigSchema} from './WorkspaceConfig.js';\nimport {type WorkspaceConfig} from './WorkspaceConfig.js';\nimport {type WorkspaceCreateOptions} from './WorkspaceCreateOptions.js';\nimport {type WorkspaceCreateProjectOptions} from './WorkspaceCreateProjectOptions.js';\nimport {WorkspaceDependencies} from './WorkspaceDependencies.js';\nimport {WorkspaceError} from './WorkspaceError.js';\nimport {type WorkspaceFindAndReadOptions} from './WorkspaceFindAndReadOptions.js';\nimport {type WorkspaceOptions} from './WorkspaceOptions.js';\nimport {type WorkspacePackageJson} from './WorkspacePackageJson.js';\nimport {type WorkspaceProjectGlobs} from './WorkspaceProjectGlobs.js';\nimport {type WorkspaceProjects} from './WorkspaceProjects.js';\nimport {type WorkspaceRepository} from './WorkspaceRepository.js';\nimport {type WorkspaceUpdateOptions} from './WorkspaceUpdateOptions.js';\n\n/**\n * Workspace represent a directory, usually a git repository, that contains {@link Project} instances.\n *\n * @typeParam M If true, the workspace is multi-project workspace (so-called \"monorepo\").\n */\nexport class Workspace<M extends boolean = true> {\n /** Workspace path. */\n readonly path: string;\n\n /** Does the workspace contain a multiple projects? */\n readonly isMultiProject: M;\n\n /** Globs used to find projects. */\n projectGlobs: WorkspaceProjectGlobs<M>;\n\n /** Workspace projects. */\n projects: WorkspaceProjects<M>;\n\n /** Workspace configuration; if it's not found, the default is an empty object. */\n config: WorkspaceConfig;\n\n /** Parsed workspace `package.json` file (if the workspace contains multiple projects); if it's not found, the default is an empty object. */\n packageJson: WorkspacePackageJson<M>;\n\n /** Workspace git repository. */\n repository?: WorkspaceRepository;\n\n /** Dependencies of all projects. */\n dependencies: WorkspaceDependencies<M> = [] as unknown as WorkspaceDependencies<M>;\n\n /** Development dependencies of all projects. */\n devDependencies: WorkspaceDependencies<M> = [] as unknown as WorkspaceDependencies<M>;\n\n /** All dependencies of all projects and workspace dependencies. */\n allDependencies: WorkspaceDependencies<M> = [] as unknown as WorkspaceDependencies<M>;\n\n /** Versions of each dependency. */\n dependencyVersions: Record<string, string[]> = {};\n\n /** Errors found during reading from the file system. */\n errors: Array<InstanceType<typeof WorkspaceError>> = [];\n\n constructor(options: WorkspaceOptions<M>) {\n this.path = options.path;\n\n if (options.isMultiProject === undefined || options.isMultiProject) {\n this.isMultiProject = true as M;\n\n let projectGlobOption = (options as WorkspaceOptions<true>).projectGlobs;\n\n if (projectGlobOption) {\n this.projectGlobs = projectGlobOption as WorkspaceProjectGlobs<M>;\n } else {\n this.projectGlobs = [] as string[] as WorkspaceProjectGlobs<M>;\n }\n\n this.projects = [] as Array<Project<M>> as WorkspaceProjects<M>;\n\n let {projects} = options as WorkspaceOptions<true>;\n\n if (projects) {\n this.addProjects(projects.map((project) => new Project({...project, workspace: this})));\n }\n\n let packageJsonOption = (options as WorkspaceOptions<true>).packageJson;\n\n if (packageJsonOption) {\n this.packageJson = packageJsonOption as M extends true ? PackageJson : null;\n } else {\n let emptyPackageJson: PackageJson = {};\n\n this.packageJson = emptyPackageJson as M extends true ? PackageJson : null;\n }\n } else {\n this.isMultiProject = false as M;\n this.projectGlobs = null as M extends true ? string[] : null;\n this.packageJson = null as M extends true ? PackageJson : null;\n this.projects = [] as Array<Project<M>> as WorkspaceProjects<M>;\n\n let {projects} = options as WorkspaceOptions<false>;\n\n if (projects) {\n this.addProjects(projects.map((project) => new Project({...project, workspace: this})));\n }\n }\n\n let configOption = options.config;\n\n if (configOption) {\n this.config = configOption;\n } else {\n let emptyWorkspaceConfig: WorkspaceConfig = {};\n\n this.config = emptyWorkspaceConfig;\n }\n\n if (options.repository) {\n this.repository = options.repository;\n }\n\n if (options.errors) {\n this.errors = options.errors;\n }\n\n // add missing project globs\n if (this.isMultiProject && !(this.projectGlobs as string[]).length) {\n let packageJsonWorkspaces = getPackageJsonWorkspaces(this.packageJson as PackageJson);\n\n if (packageJsonWorkspaces) {\n this.projectGlobs = [...packageJsonWorkspaces] as M extends true ? string[] : null;\n }\n }\n\n this.sortProjects();\n this.updateDependencies();\n }\n\n /**\n * Creates new workspace within the file system.\n *\n * @param options Options.\n * @returns The new workspace.\n */\n static async create({args, path: workspacePath, templateId}: WorkspaceCreateOptions) {\n // TODO: test that workspace returned by this method has the same value of isMultiProject when the same workspace is after its creation re-read with .read()\n let workspace = new this({\n path: workspacePath,\n config: {\n template: templateId,\n },\n });\n\n try {\n await ensureEmptyDirectory(workspace.path, {allowGit: true});\n } catch {\n throw new WorkspaceError('WORKSPACE_PATH_NOT_EMPTY', {\n messageParameters: [workspace.path],\n data: {\n path: workspace.path,\n },\n });\n }\n\n let template = await readCarsonTemplate(templateId);\n let templateRenders = await renderCarsonTemplate({\n template,\n templateData: {\n workspace,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: workspace.path,\n snapshotPath:\n template.config.autoEject ?\n undefined\n : path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),\n ignoreStrategies: ['check'],\n });\n\n if (!template.config.autoEject) {\n await saveWorkspaceConfig({\n workspacePath: workspace.path,\n workspaceConfig: {template: templateId},\n });\n }\n\n return Workspace.read(workspace.path);\n }\n\n static async read(workspacePath: string): Promise<Workspace | Workspace<false>> {\n let resolvedWorkspacePath = path.resolve(workspacePath);\n\n if (!(await fs.pathExists(resolvedWorkspacePath))) {\n throw new WorkspaceError('NO_SUCH_WORKSPACE_PATH', {\n messageParameters: [resolvedWorkspacePath],\n data: {\n path: resolvedWorkspacePath,\n },\n });\n }\n\n // load root package.json\n let rootPackageJsonPath = path.join(resolvedWorkspacePath, 'package.json');\n let doesRootPackageJsonExist = await fs.pathExists(rootPackageJsonPath);\n let rootPackageJson: PackageJson | z.ZodError;\n\n if (doesRootPackageJsonExist) {\n rootPackageJson = await readFile(rootPackageJsonPath, packageJsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n rootPackageJson = {};\n }\n\n if (rootPackageJson instanceof z.ZodError) {\n rootPackageJson = {};\n\n // even if the package.json file has errors, maybe there's still a correct workspace field\n try {\n let rootJson = await readFile(rootPackageJsonPath, jsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n throwOnZodError: true,\n });\n let projectGlobs = getPackageJsonWorkspaces(rootJson);\n\n // add back to the empty package.json object\n if (projectGlobs) {\n rootPackageJson.workspaces = projectGlobs;\n }\n } catch {\n // no-op\n }\n }\n\n // add projects\n let projectGlobs = getPackageJsonWorkspaces(rootPackageJson);\n\n // we're dealing with single-project workspace\n if (!projectGlobs) {\n let workspace = new this({\n path: resolvedWorkspacePath,\n isMultiProject: false,\n });\n\n await workspace.read();\n await workspace.readProjects();\n\n return workspace;\n }\n\n // assemble workspace options\n let workspace = new this({\n path: resolvedWorkspacePath,\n isMultiProject: true,\n projectGlobs,\n packageJson: rootPackageJson,\n });\n\n await workspace.read();\n await workspace.readProjects();\n\n return workspace;\n }\n\n /**\n * Traverses file system up from the search path and tries to find a directory that is a root of a workspace.\n *\n * @param searchPath Search path.\n * @returns Workspace path, if found.\n */\n static async find(searchPath: string): Promise<string | undefined> {\n let startingPath = await findExistingDirectory(path.resolve(searchPath));\n let currentPath = startingPath;\n let singlePackageWorkspacePath: string | undefined;\n let multiPackageWorkspacePath: string | undefined;\n\n while (\n !(isRootPath(currentPath) || (singlePackageWorkspacePath && multiPackageWorkspacePath))\n ) {\n if (await containsWorkspace(currentPath)) {\n const packageJsonPath = path.join(currentPath, PACKAGE_JSON_FILENAME);\n\n if (await fs.pathExists(packageJsonPath)) {\n const packageJson = await readFile(packageJsonPath, jsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n\n if (!(packageJson instanceof Error)) {\n const projectGlobs = getPackageJsonWorkspaces(packageJson);\n\n if (projectGlobs?.length) {\n multiPackageWorkspacePath ??= currentPath;\n } else {\n singlePackageWorkspacePath ??= currentPath;\n }\n }\n } else {\n singlePackageWorkspacePath ??= currentPath;\n }\n }\n\n currentPath = path.dirname(currentPath);\n }\n\n if (multiPackageWorkspacePath) {\n return multiPackageWorkspacePath;\n } else if (singlePackageWorkspacePath) {\n return singlePackageWorkspacePath;\n }\n\n return undefined;\n }\n\n /**\n * Traverses file system up from the search path and tries to find and read a workspace.\n */\n static async findAndRead<O extends WorkspaceFindAndReadOptions | undefined = undefined>(\n searchPath: string,\n options?: O,\n ): Promise<\n O extends undefined ? Workspace | Workspace<false> | undefined\n : NonNullable<O>['throwIfNotFound'] extends true ? Workspace | Workspace<false>\n : Workspace | Workspace<false> | undefined\n > {\n let workspacePath = await Workspace.find(searchPath);\n\n if (workspacePath) {\n return Workspace.read(workspacePath) as Promise<\n O extends undefined ? Workspace | Workspace<false> | undefined\n : NonNullable<O>['throwIfNotFound'] extends true ? Workspace | Workspace<false>\n : Workspace | Workspace<false> | undefined\n >;\n } else if (options?.throwIfNotFound) {\n throw new WorkspaceError('NO_WORKSPACE_FOUND', {\n messageParameters: [searchPath],\n data: {\n path: searchPath,\n },\n });\n }\n\n return undefined as unknown as Promise<\n O extends undefined ? Workspace | Workspace<false> | undefined\n : NonNullable<O>['throwIfNotFound'] extends true ? Workspace | Workspace<false>\n : Workspace | Workspace<false> | undefined\n >;\n }\n\n async read(): Promise<this> {\n if (!(await fs.pathExists(this.path))) {\n throw new WorkspaceError('NO_SUCH_WORKSPACE_PATH', {\n messageParameters: [this.path],\n data: {\n path: this.path,\n },\n });\n }\n\n let errors: Array<InstanceType<typeof WorkspaceError>> = [];\n let repositoryUrl = await getRepositoryUrl(this.path);\n let repositoryBranches = await getRepositoryBranches(this.path);\n\n // load workspace config\n let workspaceConfigPath = path.join(\n this.path,\n CARSON_CONFIG_DIRECTORY,\n WORKSPACE_CONFIG_FILENAME,\n );\n let doesWorkspaceConfigExist = await fs.pathExists(workspaceConfigPath);\n let workspaceConfig: WorkspaceConfig | z.ZodError;\n\n if (doesWorkspaceConfigExist) {\n workspaceConfig = await readFile(workspaceConfigPath, workspaceConfigSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n workspaceConfig = {};\n }\n\n if (workspaceConfig instanceof z.ZodError) {\n let zodError = workspaceConfig;\n let workspaceError = new WorkspaceError('INVALID_WORKSPACE_CONFIG', {\n messageParameters: [workspaceConfigPath],\n data: {\n path: workspaceConfigPath,\n zodIssues: zodError.issues,\n },\n });\n\n errors.push(workspaceError);\n\n workspaceConfig = {};\n }\n\n if (this.isMultiProject) {\n // load root package.json\n let rootPackageJsonPath = path.join(this.path, 'package.json');\n let doesRootPackageJsonExist = await fs.pathExists(rootPackageJsonPath);\n let rootPackageJson: PackageJson | z.ZodError;\n\n if (doesRootPackageJsonExist) {\n rootPackageJson = await readFile(rootPackageJsonPath, packageJsonSchema, {\n parser: (rawString: string) => json5.parse<unknown>(rawString),\n });\n } else {\n rootPackageJson = {};\n }\n\n if (rootPackageJson instanceof z.ZodError) {\n let zodError = rootPackageJson;\n let workspaceError = new WorkspaceError('INVALID_PACKAGE_JSON', {\n messageParameters: [rootPackageJsonPath],\n data: {\n path: rootPackageJsonPath,\n zodIssues: zodError.issues,\n },\n });\n\n errors.push(workspaceError);\n\n rootPackageJson = {};\n }\n\n let projectGlobs = getPackageJsonWorkspaces(rootPackageJson);\n\n this.projectGlobs = (projectGlobs ?? []) as WorkspaceProjectGlobs<M>;\n this.packageJson = rootPackageJson as WorkspacePackageJson<M>;\n this.config = workspaceConfig;\n this.errors = errors;\n\n if (repositoryUrl) {\n this.repository = {\n url: repositoryUrl,\n branches: repositoryBranches ?? [],\n };\n } else if (repositoryBranches) {\n this.repository = {\n branches: repositoryBranches,\n };\n }\n\n await this.readProjects();\n\n return this;\n }\n\n // we're dealing with single-project workspace\n this.config = workspaceConfig;\n this.errors = errors;\n\n if (repositoryUrl) {\n this.repository = {\n url: repositoryUrl,\n branches: repositoryBranches ?? [],\n };\n } else if (repositoryBranches) {\n this.repository = {\n branches: repositoryBranches,\n };\n }\n\n await this.readProjects();\n\n return this;\n }\n\n async update({args}: WorkspaceUpdateOptions): Promise<this> {\n if (!this.config.template) {\n throw new WorkspaceError('MISSING_CARSON_TEMPLATE_ID', {\n messageParameters: [\n path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_CONFIG_FILENAME),\n ],\n });\n }\n\n let template = await readCarsonTemplate(this.config.template);\n let templateRenders = await renderCarsonTemplate({\n template,\n templateData: {\n workspace: this,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: this.path,\n snapshotPath:\n template.config.autoEject ?\n undefined\n : path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),\n ignoreStrategies: ['create'],\n });\n\n await this.read();\n\n return this;\n }\n\n getProject(projectName: Project<M> | string): Project<M> | undefined {\n for (let project of this.projects) {\n if (project.name === projectName || project === projectName) {\n return project;\n }\n }\n\n return undefined;\n }\n\n async createProject({\n templateId,\n projectPath,\n projectName,\n args,\n }: WorkspaceCreateProjectOptions): Promise<Project<M>> {\n let resolvedProjectPath = path.resolve(projectPath);\n\n if (this.projects.some((project) => resolvedProjectPath === project.path)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_PATH', {\n messageParameters: [resolvedProjectPath],\n });\n }\n\n if (this.projects.some((project) => projectName === project.name)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_NAME', {messageParameters: [projectName]});\n }\n\n if (!this.isMultiProject && this.projects.length >= 1) {\n throw new WorkspaceError('TOO_MANY_PROJECTS');\n }\n\n if (!this.isMultiProject && projectPath !== this.path) {\n throw new WorkspaceError('PATH_MISMATCH');\n }\n\n let newProject = await Project.create({\n templateId,\n projectPath,\n projectName,\n args,\n workspace: this,\n });\n\n this.addProject(newProject);\n\n return newProject;\n }\n\n addProject(newProject: Project<M>): this {\n if (this.projects.some((project) => newProject.path === project.path)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_PATH', {\n messageParameters: [newProject.path],\n });\n }\n\n if (this.projects.some((project) => newProject.name === project.name)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_NAME', {messageParameters: [newProject.name]});\n }\n\n if (!this.isMultiProject && this.projects.length >= 1) {\n throw new WorkspaceError('TOO_MANY_PROJECTS');\n }\n\n if (!this.isMultiProject && newProject.path !== this.path) {\n throw new WorkspaceError('PATH_MISMATCH');\n }\n\n this.projects.push(newProject);\n this.sortProjects();\n this.updateDependencies();\n\n return this;\n }\n\n addProjects(newProjects: Array<Project<M>>): this {\n for (let newProject of newProjects) {\n if (this.projects.some((project) => newProject.path === project.path)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_PATH', {\n messageParameters: [newProject.path],\n });\n }\n\n if (this.projects.some((project) => newProject.name === project.name)) {\n throw new WorkspaceError('DUPLICATE_PROJECT_NAME', {messageParameters: [newProject.name]});\n }\n\n if (!this.isMultiProject && this.projects.length >= 1) {\n throw new WorkspaceError('TOO_MANY_PROJECTS');\n }\n\n if (!this.isMultiProject && newProject.path !== this.path) {\n throw new WorkspaceError('PATH_MISMATCH');\n }\n\n this.projects.push(newProject);\n }\n\n this.sortProjects();\n this.updateDependencies();\n\n return this;\n }\n\n async readProjects(): Promise<Array<Project<M>>> {\n if (this.projectGlobs) {\n let projects: Array<Project<M>> = [];\n let packagePaths = await glob(this.projectGlobs, {\n cwd: this.path,\n onlyDirectories: true,\n });\n\n for (let packagePath of packagePaths) {\n let projectPath = path.join(this.path, packagePath);\n\n if (await containsProject(projectPath)) {\n let project = await Project.read(projectPath, this);\n\n projects.push(project);\n }\n }\n\n this.projects = projects;\n\n this.sortProjects();\n this.updateDependencies();\n } else if (await containsProject(this.path)) {\n this.projects = [await Project.read(this.path, this)];\n\n this.sortProjects();\n this.updateDependencies();\n }\n\n return this.projects;\n }\n\n protected sortProjects(): void {\n this.projects.sort(compareProjectPath);\n }\n\n protected updateDependencies(): void {\n this.dependencies = WorkspaceDependencies.fromWorkspace(this);\n this.devDependencies = WorkspaceDependencies.fromWorkspace(this, {\n includeOnlyDevDependencies: true,\n });\n this.allDependencies = WorkspaceDependencies.fromWorkspace(this, {\n includeDevDependencies: true,\n includeWorkspaceDependencies: true,\n });\n this.dependencyVersions = this.allDependencies.getVersions({\n useExactVersions: true,\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["projectGlobs", "workspace"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jakubmazanec/carson",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.1.0-next.c370ab6",
|
|
4
4
|
"description": "Tool for managing workspace and project configuration.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"typecheck": "tsc --project tsconfig.typecheck.json"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@jakubmazanec/args": "
|
|
36
|
-
"@jakubmazanec/cli": "
|
|
37
|
-
"@jakubmazanec/error": "
|
|
38
|
-
"@jakubmazanec/fs-utils": "
|
|
39
|
-
"@jakubmazanec/template": "
|
|
40
|
-
"@jakubmazanec/ts-utils": "
|
|
41
|
-
"@jakubmazanec/zod-utils": "
|
|
35
|
+
"@jakubmazanec/args": "2.0.2-next.c370ab6",
|
|
36
|
+
"@jakubmazanec/cli": "0.3.2-next.c370ab6",
|
|
37
|
+
"@jakubmazanec/error": "3.0.2-next.c370ab6",
|
|
38
|
+
"@jakubmazanec/fs-utils": "0.2.2-next.c370ab6",
|
|
39
|
+
"@jakubmazanec/template": "2.0.2-next.c370ab6",
|
|
40
|
+
"@jakubmazanec/ts-utils": "3.0.2-next.c370ab6",
|
|
41
|
+
"@jakubmazanec/zod-utils": "2.0.2-next.c370ab6",
|
|
42
42
|
"chalk": "^5.3.0",
|
|
43
43
|
"fast-glob": "^3.3.2",
|
|
44
44
|
"fflate": "^0.8.2",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"zod": "^3.22.4"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@jakubmazanec/eslint-config": "
|
|
58
|
+
"@jakubmazanec/eslint-config": "3.2.0-next.c370ab6",
|
|
59
59
|
"@types/fs-extra": "^11.0.4",
|
|
60
60
|
"@types/lodash": "^4.14.202",
|
|
61
61
|
"@types/micromatch": "^4.0.6",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"esbuild": "^0.20.1",
|
|
70
70
|
"eslint": "^8.56.0",
|
|
71
71
|
"ink": "^4.4.1",
|
|
72
|
+
"lodash": "^4.17.21",
|
|
72
73
|
"prettier": "^3.2.5",
|
|
73
74
|
"prettier-plugin-packagejson": "^2.4.12",
|
|
74
75
|
"react": "^18.2.0",
|
|
@@ -80,6 +80,25 @@ export function CreateProject({args, workspace}: CreateProjectProps) {
|
|
|
80
80
|
value: projectPath,
|
|
81
81
|
label: path.relative(workspace.path, projectPath).replace('\\', '/'),
|
|
82
82
|
}));
|
|
83
|
+
|
|
84
|
+
if (!possiblePaths.length) {
|
|
85
|
+
possiblePaths = workspace.projectGlobs
|
|
86
|
+
.filter((projectGlob) => !ONLY_ONE_STAR_REGEXP.test(projectGlob))
|
|
87
|
+
.map((projectGlob) => path.join(workspace.path, projectGlob))
|
|
88
|
+
.map((projectPath) => ({
|
|
89
|
+
value: projectPath,
|
|
90
|
+
label: path.relative(workspace.path, projectPath).replace('\\', '/'),
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!possiblePaths.length) {
|
|
95
|
+
possiblePaths = [
|
|
96
|
+
{
|
|
97
|
+
value: workspace.path,
|
|
98
|
+
label: workspace.path,
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
}
|
|
83
102
|
} else {
|
|
84
103
|
possiblePaths = [
|
|
85
104
|
{
|
|
@@ -34,6 +34,9 @@ export function runCreateProject({
|
|
|
34
34
|
|
|
35
35
|
observer.next('Updating the new project');
|
|
36
36
|
|
|
37
|
+
// if the project doesn't have config with a template ID, it's on purpose, but it's still needed for the next update, so we'll add it manually
|
|
38
|
+
project.config.template ??= templateId;
|
|
39
|
+
|
|
37
40
|
await project.update({args});
|
|
38
41
|
})()
|
|
39
42
|
.then(() => {
|
|
@@ -25,6 +25,9 @@ export function runCreateWorkspace({workspacePath, templateId, args}: CreateWork
|
|
|
25
25
|
|
|
26
26
|
observer.next('Updating the new workspace');
|
|
27
27
|
|
|
28
|
+
// if the workspace doesn't have config with a template ID, it's on purpose, but it's still needed for the next update, so we'll add it manually
|
|
29
|
+
workspace.config.template ??= templateId;
|
|
30
|
+
|
|
28
31
|
await workspace.update({args});
|
|
29
32
|
})()
|
|
30
33
|
.then(() => {
|
|
@@ -2,10 +2,10 @@ import {z} from 'zod';
|
|
|
2
2
|
|
|
3
3
|
export const carsonTemplateConfigSchema = z
|
|
4
4
|
.object({
|
|
5
|
-
disallowMultiProjectWorkspace: z.boolean().optional(),
|
|
6
|
-
disallowSingleProjectWorkspace: z.boolean().optional(),
|
|
5
|
+
// disallowMultiProjectWorkspace: z.boolean().optional(),
|
|
6
|
+
// disallowSingleProjectWorkspace: z.boolean().optional(),
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
autoEject: z.boolean().optional(),
|
|
9
9
|
})
|
|
10
10
|
.strict();
|
|
11
11
|
|
|
@@ -22,7 +22,7 @@ import {type TemplateRenders} from './TemplateRenders.js';
|
|
|
22
22
|
export type ApplyTemplateRendersOptions = {
|
|
23
23
|
templateRenders: TemplateRenders;
|
|
24
24
|
targetPath: string;
|
|
25
|
-
snapshotPath
|
|
25
|
+
snapshotPath?: string | undefined;
|
|
26
26
|
ignoreStrategies: string[];
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -39,7 +39,7 @@ export async function applyTemplateRenders({
|
|
|
39
39
|
await prettier.clearConfigCache();
|
|
40
40
|
|
|
41
41
|
// first, we read the existing snapshots and use them to undo previous changes
|
|
42
|
-
if (await fs.pathExists(snapshotPath)) {
|
|
42
|
+
if (snapshotPath && (await fs.pathExists(snapshotPath))) {
|
|
43
43
|
let templateRenderSnapshots = await loadTemplateRenderSnapshots(snapshotPath);
|
|
44
44
|
|
|
45
45
|
for (let templateRenderSnapshot of templateRenderSnapshots) {
|
|
@@ -135,7 +135,9 @@ export async function applyTemplateRenders({
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
if (snapshotPath) {
|
|
139
|
+
await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
await saveTemplateRenderSnapshots(templateRenders, snapshotPath);
|
|
142
|
+
}
|
|
141
143
|
}
|
|
@@ -2,17 +2,13 @@ import {pathToPosixPath} from '@jakubmazanec/fs-utils';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
parseCarsonTemplateId,
|
|
8
|
-
readCarsonTemplate,
|
|
9
|
-
resolveModule,
|
|
10
|
-
} from './internals.js';
|
|
5
|
+
import {type CarsonTemplate} from './CarsonTemplate.js';
|
|
6
|
+
import {importCarsonTemplate, parseCarsonTemplateId, resolveModule} from './internals.js';
|
|
11
7
|
import {type TemplateData} from './TemplateData.js';
|
|
12
8
|
import {type TemplateRenders} from './TemplateRenders.js';
|
|
13
9
|
|
|
14
10
|
export type RenderCarsonTemplateOptions = {
|
|
15
|
-
|
|
11
|
+
template: CarsonTemplate;
|
|
16
12
|
templateData: TemplateData;
|
|
17
13
|
};
|
|
18
14
|
|
|
@@ -22,13 +18,12 @@ export type RenderCarsonTemplateOptions = {
|
|
|
22
18
|
export async function renderCarsonTemplate(
|
|
23
19
|
options: RenderCarsonTemplateOptions,
|
|
24
20
|
): Promise<TemplateRenders> {
|
|
25
|
-
let [moduleId] = parseCarsonTemplateId(options.
|
|
21
|
+
let [moduleId] = parseCarsonTemplateId(options.template.id);
|
|
26
22
|
let modulePath = await resolveModule(moduleId);
|
|
27
|
-
let
|
|
28
|
-
let templateModule = await importCarsonTemplate(options.templateId);
|
|
23
|
+
let templateModule = await importCarsonTemplate(options.template.id);
|
|
29
24
|
let templateRenders: TemplateRenders = [];
|
|
30
25
|
|
|
31
|
-
for (let file of template.files) {
|
|
26
|
+
for (let file of options.template.files) {
|
|
32
27
|
templateRenders.push(
|
|
33
28
|
...(
|
|
34
29
|
await file.render(
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
PROJECT_SNAPSHOT_FILENAME,
|
|
12
12
|
} from '../constants.js';
|
|
13
13
|
import {applyTemplateRenders} from '../template/applyTemplateRenders.js';
|
|
14
|
+
import {readCarsonTemplate} from '../template/internals.js';
|
|
14
15
|
import {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';
|
|
15
16
|
import {type ProjectConfig, projectConfigSchema} from './ProjectConfig.js';
|
|
16
17
|
import {type ProjectCreateOptions} from './ProjectCreateOptions.js';
|
|
@@ -117,8 +118,9 @@ export class Project<M extends boolean = true> {
|
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
let template = await readCarsonTemplate(templateId);
|
|
120
122
|
let templateRenders = await renderCarsonTemplate({
|
|
121
|
-
|
|
123
|
+
template,
|
|
122
124
|
templateData: {
|
|
123
125
|
workspace,
|
|
124
126
|
project,
|
|
@@ -129,11 +131,16 @@ export class Project<M extends boolean = true> {
|
|
|
129
131
|
await applyTemplateRenders({
|
|
130
132
|
templateRenders,
|
|
131
133
|
targetPath: project.path,
|
|
132
|
-
snapshotPath:
|
|
134
|
+
snapshotPath:
|
|
135
|
+
template.config.autoEject || !workspace.config.template ?
|
|
136
|
+
undefined
|
|
137
|
+
: path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
133
138
|
ignoreStrategies: ['check'],
|
|
134
139
|
});
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
if (!template.config.autoEject && workspace.config.template) {
|
|
142
|
+
await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});
|
|
143
|
+
}
|
|
137
144
|
|
|
138
145
|
await project.read();
|
|
139
146
|
|
|
@@ -242,8 +249,9 @@ export class Project<M extends boolean = true> {
|
|
|
242
249
|
});
|
|
243
250
|
}
|
|
244
251
|
|
|
252
|
+
let template = await readCarsonTemplate(this.config.template);
|
|
245
253
|
let templateRenders = await renderCarsonTemplate({
|
|
246
|
-
|
|
254
|
+
template,
|
|
247
255
|
templateData: {
|
|
248
256
|
workspace: this.workspace,
|
|
249
257
|
project: this,
|
|
@@ -254,7 +262,10 @@ export class Project<M extends boolean = true> {
|
|
|
254
262
|
await applyTemplateRenders({
|
|
255
263
|
templateRenders,
|
|
256
264
|
targetPath: this.path,
|
|
257
|
-
snapshotPath:
|
|
265
|
+
snapshotPath:
|
|
266
|
+
template.config.autoEject || !this.workspace.config.template ?
|
|
267
|
+
undefined
|
|
268
|
+
: path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
258
269
|
ignoreStrategies: ['create'],
|
|
259
270
|
});
|
|
260
271
|
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
WORKSPACE_SNAPSHOT_FILENAME,
|
|
14
14
|
} from '../constants.js';
|
|
15
15
|
import {applyTemplateRenders} from '../template/applyTemplateRenders.js';
|
|
16
|
+
import {readCarsonTemplate} from '../template/internals.js';
|
|
16
17
|
import {renderCarsonTemplate} from '../template/renderCarsonTemplate.js';
|
|
17
18
|
import {
|
|
18
19
|
compareProjectPath,
|
|
@@ -181,8 +182,9 @@ export class Workspace<M extends boolean = true> {
|
|
|
181
182
|
});
|
|
182
183
|
}
|
|
183
184
|
|
|
185
|
+
let template = await readCarsonTemplate(templateId);
|
|
184
186
|
let templateRenders = await renderCarsonTemplate({
|
|
185
|
-
|
|
187
|
+
template,
|
|
186
188
|
templateData: {
|
|
187
189
|
workspace,
|
|
188
190
|
args,
|
|
@@ -192,14 +194,19 @@ export class Workspace<M extends boolean = true> {
|
|
|
192
194
|
await applyTemplateRenders({
|
|
193
195
|
templateRenders,
|
|
194
196
|
targetPath: workspace.path,
|
|
195
|
-
snapshotPath:
|
|
197
|
+
snapshotPath:
|
|
198
|
+
template.config.autoEject ?
|
|
199
|
+
undefined
|
|
200
|
+
: path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
196
201
|
ignoreStrategies: ['check'],
|
|
197
202
|
});
|
|
198
203
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
if (!template.config.autoEject) {
|
|
205
|
+
await saveWorkspaceConfig({
|
|
206
|
+
workspacePath: workspace.path,
|
|
207
|
+
workspaceConfig: {template: templateId},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
203
210
|
|
|
204
211
|
return Workspace.read(workspace.path);
|
|
205
212
|
}
|
|
@@ -490,8 +497,9 @@ export class Workspace<M extends boolean = true> {
|
|
|
490
497
|
});
|
|
491
498
|
}
|
|
492
499
|
|
|
500
|
+
let template = await readCarsonTemplate(this.config.template);
|
|
493
501
|
let templateRenders = await renderCarsonTemplate({
|
|
494
|
-
|
|
502
|
+
template,
|
|
495
503
|
templateData: {
|
|
496
504
|
workspace: this,
|
|
497
505
|
args,
|
|
@@ -501,7 +509,10 @@ export class Workspace<M extends boolean = true> {
|
|
|
501
509
|
await applyTemplateRenders({
|
|
502
510
|
templateRenders,
|
|
503
511
|
targetPath: this.path,
|
|
504
|
-
snapshotPath:
|
|
512
|
+
snapshotPath:
|
|
513
|
+
template.config.autoEject ?
|
|
514
|
+
undefined
|
|
515
|
+
: path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
505
516
|
ignoreStrategies: ['create'],
|
|
506
517
|
});
|
|
507
518
|
|