@jakubmazanec/carson 0.2.0 → 0.2.1-unstable.9ab3865
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 +8 -8
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/template/applyTemplateRenders.d.ts +3 -2
- package/dist/template/applyTemplateRenders.js +15 -5
- package/dist/template/applyTemplateRenders.js.map +1 -1
- package/dist/template/internals/createUsingTemplateRender.js +49 -4
- package/dist/template/internals/createUsingTemplateRender.js.map +1 -1
- package/dist/template/internals/mergeUsingTemplateRender.js +26 -14
- package/dist/template/internals/mergeUsingTemplateRender.js.map +1 -1
- package/dist/workspace/Project.js +19 -14
- package/dist/workspace/Project.js.map +1 -1
- package/dist/workspace/Workspace.d.ts +3 -0
- package/dist/workspace/Workspace.js +29 -19
- package/dist/workspace/Workspace.js.map +1 -1
- package/dist/workspace/internals/containsProject.js +9 -4
- package/dist/workspace/internals/containsProject.js.map +1 -1
- package/dist/workspace/internals/containsWorkspace.d.ts +1 -0
- package/dist/workspace/internals/containsWorkspace.js +14 -0
- package/dist/workspace/internals/containsWorkspace.js.map +1 -0
- package/dist/workspace/internals.d.ts +1 -0
- package/dist/workspace/internals.js +1 -0
- package/dist/workspace/internals.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +2 -0
- package/src/template/applyTemplateRenders.ts +21 -11
- package/src/template/internals/createUsingTemplateRender.ts +42 -2
- package/src/template/internals/mergeUsingTemplateRender.ts +17 -9
- package/src/workspace/Project.ts +21 -12
- package/src/workspace/Workspace.ts +39 -22
- package/src/workspace/internals/containsProject.ts +19 -4
- package/src/workspace/internals/containsWorkspace.ts +24 -0
- package/src/workspace/internals.ts +1 -0
package/README.md
CHANGED
|
@@ -329,14 +329,14 @@ file format detection by Prettier.
|
|
|
329
329
|
Attribute `strategy` describes how exactly should the template render be written, or whether it
|
|
330
330
|
should be written at all.
|
|
331
331
|
|
|
332
|
-
| Strategy name | Example `strategy` value | Description
|
|
333
|
-
| ------------- | ------------------------ |
|
|
334
|
-
| Create | `'create'` | The template render is written to the target file, but only when the Carson template is used to create a new workspace or project; when Carson performs an update, the template files with this strategy are not even rendered. |
|
|
335
|
-
| Ensure | `'ensure'` | The template render is written to the target file, but only when the target file doesn't exist; if it does, it is left unchanged.
|
|
336
|
-
| Overwrite | `'overwrite'` | The template render is written to the target file, overwriting its existing content.
|
|
337
|
-
| Merge | `'merge'` | The template render is merged with the target file's existing content. Only simple objects, not arrays, are merged recursively. The only supported file formats are JSON and YAML.
|
|
338
|
-
| Check | `'check'` | Only the target file's existence is checked, the template render is discarded; when Carson doesn't perform an update, the template files with this strategy are not even rendered.
|
|
339
|
-
| Insert | `['insert', <string>]` | The template render is inserted between the first and last occurrence of an HTML comment containing configured string, e.g. `<!-- foobar -->`. The only supported file format is Markdown.
|
|
332
|
+
| Strategy name | Example `strategy` value | Description |
|
|
333
|
+
| ------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
334
|
+
| Create | `'create'` | The template render is written to the target file, but only when the Carson template is used to create a new workspace or project; when Carson performs an update, the template files with this strategy are not even rendered. If the target file already exists and its format is JSON or YAML, the template render is merged with the target file's existing content (otherwise it's overwritten). Only simple objects, not arrays, are merged recursively. |
|
|
335
|
+
| Ensure | `'ensure'` | The template render is written to the target file, but only when the target file doesn't exist; if it does, it is left unchanged. |
|
|
336
|
+
| Overwrite | `'overwrite'` | The template render is written to the target file, overwriting its existing content. |
|
|
337
|
+
| Merge | `'merge'` | The template render is merged with the target file's existing content. Only simple objects, not arrays, are merged recursively. The only supported file formats are JSON and YAML. If the target file doesn't exist, it is created. |
|
|
338
|
+
| Check | `'check'` | Only the target file's existence is checked, the template render is discarded; when Carson doesn't perform an update, the template files with this strategy are not even rendered. |
|
|
339
|
+
| Insert | `['insert', <string>]` | The template render is inserted between the first and last occurrence of an HTML comment containing configured string, e.g. `<!-- foobar -->`. The only supported file format is Markdown. |
|
|
340
340
|
|
|
341
341
|
The rest of the template file after the front matter is the actual EJS template. Please read
|
|
342
342
|
[`ejs` documentation](https://ejs.co/#docs) to find out in more detail how they work.
|
package/dist/constants.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export declare const CARSON_CONFIG_DIRECTORY = ".carson";
|
|
|
3
3
|
export declare const PROJECT_CONFIG_FILENAME = "project.json";
|
|
4
4
|
export declare const WORKSPACE_CONFIG_FILENAME = "workspace.json";
|
|
5
5
|
export declare const SNAPSHOTS_FILENAME = ".snapshots";
|
|
6
|
+
export declare const PROJECT_SNAPSHOT_FILENAME = "project.snapshot";
|
|
7
|
+
export declare const WORKSPACE_SNAPSHOT_FILENAME = "workspace.snapshot";
|
|
6
8
|
export declare const TEMPLATES_PATH = "templates";
|
|
7
9
|
export declare const TEMPLATE_CONFIG_FILENAME = "config.json";
|
|
8
10
|
export declare const PACKAGE_JSON_FILENAME = "package.json";
|
package/dist/constants.js
CHANGED
|
@@ -6,6 +6,8 @@ export const CARSON_CONFIG_DIRECTORY = '.carson';
|
|
|
6
6
|
export const PROJECT_CONFIG_FILENAME = 'project.json';
|
|
7
7
|
export const WORKSPACE_CONFIG_FILENAME = 'workspace.json';
|
|
8
8
|
export const SNAPSHOTS_FILENAME = '.snapshots';
|
|
9
|
+
export const PROJECT_SNAPSHOT_FILENAME = 'project.snapshot';
|
|
10
|
+
export const WORKSPACE_SNAPSHOT_FILENAME = 'workspace.snapshot';
|
|
9
11
|
export const TEMPLATES_PATH = 'templates';
|
|
10
12
|
export const TEMPLATE_CONFIG_FILENAME = 'config.json';
|
|
11
13
|
export const PACKAGE_JSON_FILENAME = 'package.json';
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts"],"sourcesContent":["import path from 'node:path';\nimport url from 'node:url';\n\nlet directory = path.dirname(url.fileURLToPath(import.meta.url));\n\nexport const PACKAGE_PATH = path.resolve(directory, '..');\n\nexport const CARSON_CONFIG_DIRECTORY = '.carson';\nexport const PROJECT_CONFIG_FILENAME = 'project.json';\nexport const WORKSPACE_CONFIG_FILENAME = 'workspace.json';\nexport const SNAPSHOTS_FILENAME = '.snapshots';\nexport const TEMPLATES_PATH = 'templates';\nexport const TEMPLATE_CONFIG_FILENAME = 'config.json';\nexport const PACKAGE_JSON_FILENAME = 'package.json';\n"],"names":["path","url","directory","dirname","fileURLToPath","PACKAGE_PATH","resolve","CARSON_CONFIG_DIRECTORY","PROJECT_CONFIG_FILENAME","WORKSPACE_CONFIG_FILENAME","SNAPSHOTS_FILENAME","TEMPLATES_PATH","TEMPLATE_CONFIG_FILENAME","PACKAGE_JSON_FILENAME"],"mappings":"AAAA,OAAOA,UAAU,YAAY;AAC7B,OAAOC,SAAS,WAAW;AAE3B,IAAIC,YAAYF,KAAKG,OAAO,CAACF,IAAIG,aAAa,CAAC,YAAYH,GAAG;AAE9D,OAAO,MAAMI,eAAeL,KAAKM,OAAO,CAACJ,WAAW,MAAM;AAE1D,OAAO,MAAMK,0BAA0B,UAAU;AACjD,OAAO,MAAMC,0BAA0B,eAAe;AACtD,OAAO,MAAMC,4BAA4B,iBAAiB;AAC1D,OAAO,MAAMC,qBAAqB,aAAa;AAC/C,OAAO,MAAMC,iBAAiB,YAAY;AAC1C,OAAO,MAAMC,2BAA2B,cAAc;AACtD,OAAO,MAAMC,wBAAwB,eAAe"}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts"],"sourcesContent":["import path from 'node:path';\nimport url from 'node:url';\n\nlet directory = path.dirname(url.fileURLToPath(import.meta.url));\n\nexport const PACKAGE_PATH = path.resolve(directory, '..');\n\nexport const CARSON_CONFIG_DIRECTORY = '.carson';\nexport const PROJECT_CONFIG_FILENAME = 'project.json';\nexport const WORKSPACE_CONFIG_FILENAME = 'workspace.json';\nexport const SNAPSHOTS_FILENAME = '.snapshots';\nexport const PROJECT_SNAPSHOT_FILENAME = 'project.snapshot';\nexport const WORKSPACE_SNAPSHOT_FILENAME = 'workspace.snapshot';\nexport const TEMPLATES_PATH = 'templates';\nexport const TEMPLATE_CONFIG_FILENAME = 'config.json';\nexport const PACKAGE_JSON_FILENAME = 'package.json';\n"],"names":["path","url","directory","dirname","fileURLToPath","PACKAGE_PATH","resolve","CARSON_CONFIG_DIRECTORY","PROJECT_CONFIG_FILENAME","WORKSPACE_CONFIG_FILENAME","SNAPSHOTS_FILENAME","PROJECT_SNAPSHOT_FILENAME","WORKSPACE_SNAPSHOT_FILENAME","TEMPLATES_PATH","TEMPLATE_CONFIG_FILENAME","PACKAGE_JSON_FILENAME"],"mappings":"AAAA,OAAOA,UAAU,YAAY;AAC7B,OAAOC,SAAS,WAAW;AAE3B,IAAIC,YAAYF,KAAKG,OAAO,CAACF,IAAIG,aAAa,CAAC,YAAYH,GAAG;AAE9D,OAAO,MAAMI,eAAeL,KAAKM,OAAO,CAACJ,WAAW,MAAM;AAE1D,OAAO,MAAMK,0BAA0B,UAAU;AACjD,OAAO,MAAMC,0BAA0B,eAAe;AACtD,OAAO,MAAMC,4BAA4B,iBAAiB;AAC1D,OAAO,MAAMC,qBAAqB,aAAa;AAC/C,OAAO,MAAMC,4BAA4B,mBAAmB;AAC5D,OAAO,MAAMC,8BAA8B,qBAAqB;AAChE,OAAO,MAAMC,iBAAiB,YAAY;AAC1C,OAAO,MAAMC,2BAA2B,cAAc;AACtD,OAAO,MAAMC,wBAAwB,eAAe"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { type TemplateRenders } from './TemplateRenders.js';
|
|
2
2
|
export type ApplyTemplateRendersOptions = {
|
|
3
3
|
templateRenders: TemplateRenders;
|
|
4
|
-
|
|
4
|
+
targetPath: string;
|
|
5
|
+
snapshotPath: string;
|
|
5
6
|
ignoreStrategies: string[];
|
|
6
7
|
};
|
|
7
8
|
/**
|
|
8
9
|
* Applies rendered Carson template to a specified path, i.e. creates and updates files based on the result of rendering each Carson template file.
|
|
9
10
|
*/
|
|
10
|
-
export declare function applyTemplateRenders({ templateRenders,
|
|
11
|
+
export declare function applyTemplateRenders({ templateRenders, targetPath, snapshotPath, ignoreStrategies, }: ApplyTemplateRendersOptions): Promise<void>;
|
|
@@ -7,13 +7,19 @@ import { createUsingTemplateRender, deleteUsingTemplateRender, insertUsingTempla
|
|
|
7
7
|
import { CARSON_CONFIG_DIRECTORY, SNAPSHOTS_FILENAME } from '../constants.js';
|
|
8
8
|
/**
|
|
9
9
|
* Applies rendered Carson template to a specified path, i.e. creates and updates files based on the result of rendering each Carson template file.
|
|
10
|
-
*/ export async function applyTemplateRenders({ templateRenders,
|
|
10
|
+
*/ export async function applyTemplateRenders({ templateRenders, targetPath, snapshotPath, ignoreStrategies }) {
|
|
11
11
|
// we need to clear Prettier cache, because we are changing file system
|
|
12
12
|
await prettier.clearConfigCache();
|
|
13
|
+
// TODO: remove all logic about legacy snapshots after Carson reaches v1
|
|
14
|
+
// use previous version of snapshot file if it exists
|
|
15
|
+
let legacySnapshotPath = path.join(targetPath, CARSON_CONFIG_DIRECTORY, SNAPSHOTS_FILENAME);
|
|
16
|
+
if (await fs.pathExists(legacySnapshotPath)) {
|
|
17
|
+
// eslint-disable-next-line no-param-reassign -- needed; also, this is temporary feature
|
|
18
|
+
snapshotPath = legacySnapshotPath;
|
|
19
|
+
}
|
|
13
20
|
// first, we read the existing snapshots and use them to undo previous changes
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let templateRenderSnapshots = await loadTemplateRenderSnapshots(templateRenderSnapshotsPath);
|
|
21
|
+
if (await fs.pathExists(snapshotPath)) {
|
|
22
|
+
let templateRenderSnapshots = await loadTemplateRenderSnapshots(snapshotPath);
|
|
17
23
|
for (let templateRenderSnapshot of templateRenderSnapshots){
|
|
18
24
|
let strategy = typeof templateRenderSnapshot.attributes.strategy === 'string' ? templateRenderSnapshot.attributes.strategy : templateRenderSnapshot.attributes.strategy[0];
|
|
19
25
|
if (ignoreStrategies.includes(strategy)) {
|
|
@@ -85,7 +91,11 @@ import { CARSON_CONFIG_DIRECTORY, SNAPSHOTS_FILENAME } from '../constants.js';
|
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));
|
|
88
|
-
await saveTemplateRenderSnapshots(templateRenders,
|
|
94
|
+
await saveTemplateRenderSnapshots(templateRenders, snapshotPath);
|
|
95
|
+
// delete legacy snapshots
|
|
96
|
+
if (await fs.pathExists(legacySnapshotPath)) {
|
|
97
|
+
await fs.rm(legacySnapshotPath);
|
|
98
|
+
}
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
//# sourceMappingURL=applyTemplateRenders.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/template/applyTemplateRenders.ts"],"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 {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';\nimport {CARSON_CONFIG_DIRECTORY, SNAPSHOTS_FILENAME} from '../constants.js';\n\nexport type ApplyTemplateRendersOptions = {\n templateRenders: TemplateRenders;\n
|
|
1
|
+
{"version":3,"sources":["../../src/template/applyTemplateRenders.ts"],"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 {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';\nimport {CARSON_CONFIG_DIRECTORY, SNAPSHOTS_FILENAME} from '../constants.js';\n\nexport type ApplyTemplateRendersOptions = {\n templateRenders: TemplateRenders;\n targetPath: string;\n snapshotPath: string;\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 // TODO: remove all logic about legacy snapshots after Carson reaches v1\n // use previous version of snapshot file if it exists\n let legacySnapshotPath = path.join(targetPath, CARSON_CONFIG_DIRECTORY, SNAPSHOTS_FILENAME);\n\n if (await fs.pathExists(legacySnapshotPath)) {\n // eslint-disable-next-line no-param-reassign -- needed; also, this is temporary feature\n snapshotPath = legacySnapshotPath;\n }\n\n // first, we read the existing snapshots and use them to undo previous changes\n if (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 await fs.ensureDir(path.join(targetPath, CARSON_CONFIG_DIRECTORY));\n\n await saveTemplateRenderSnapshots(templateRenders, snapshotPath);\n\n // delete legacy snapshots\n if (await fs.pathExists(legacySnapshotPath)) {\n await fs.rm(legacySnapshotPath);\n }\n}\n"],"names":["fs","path","prettier","CarsonTemplateError","createUsingTemplateRender","deleteUsingTemplateRender","insertUsingTemplateRender","loadTemplateRenderSnapshots","mergeUsingTemplateRender","overwriteUsingTemplateRender","saveTemplateRenderSnapshots","uninsertUsingTemplateRender","unmergeUsingTemplateRender","CARSON_CONFIG_DIRECTORY","SNAPSHOTS_FILENAME","applyTemplateRenders","templateRenders","targetPath","snapshotPath","ignoreStrategies","clearConfigCache","legacySnapshotPath","join","pathExists","templateRenderSnapshots","templateRenderSnapshot","strategy","attributes","includes","onlyDeleteWhenContentsMatch","templateRender","to","doesToExist","messageParameters","template","data","ensureDir","rm"],"mappings":"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"}
|
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
|
+
import json from 'json5';
|
|
2
3
|
import path from 'node:path';
|
|
4
|
+
import yaml from 'yaml';
|
|
5
|
+
import { merge } from './merge.js';
|
|
3
6
|
import { prettify } from './prettify.js';
|
|
4
7
|
export async function createUsingTemplateRender(templateRender, basePath) {
|
|
5
8
|
let to = path.join(basePath, templateRender.attributes.to);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
let extension = path.extname(to);
|
|
10
|
+
switch(extension){
|
|
11
|
+
case '.json':
|
|
12
|
+
{
|
|
13
|
+
if (await fs.pathExists(to)) {
|
|
14
|
+
let targetFile = await fs.readJson(to);
|
|
15
|
+
let fileToMerge = json.parse(templateRender.content);
|
|
16
|
+
let newFile = JSON.stringify(merge(targetFile, fileToMerge), null, 2);
|
|
17
|
+
await fs.writeFile(to, await prettify(newFile, to), {
|
|
18
|
+
encoding: 'utf8'
|
|
19
|
+
});
|
|
20
|
+
} else {
|
|
21
|
+
await fs.ensureDir(path.dirname(to));
|
|
22
|
+
await fs.writeFile(to, await prettify(templateRender.content, to), {
|
|
23
|
+
encoding: 'utf8'
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case '.yaml':
|
|
29
|
+
{
|
|
30
|
+
if (await fs.pathExists(to)) {
|
|
31
|
+
let targetFile = yaml.parse(await fs.readFile(to, {
|
|
32
|
+
encoding: 'utf8'
|
|
33
|
+
}));
|
|
34
|
+
let fileToMerge = yaml.parse(templateRender.content);
|
|
35
|
+
let newFile = yaml.stringify(merge(targetFile, fileToMerge));
|
|
36
|
+
await fs.writeFile(to, await prettify(newFile, to), {
|
|
37
|
+
encoding: 'utf8'
|
|
38
|
+
});
|
|
39
|
+
} else {
|
|
40
|
+
await fs.writeFile(to, await prettify(templateRender.content, to), {
|
|
41
|
+
encoding: 'utf8'
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
default:
|
|
47
|
+
{
|
|
48
|
+
await fs.ensureDir(path.dirname(to));
|
|
49
|
+
await fs.writeFile(to, await prettify(templateRender.content, to), {
|
|
50
|
+
encoding: 'utf8'
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
10
55
|
}
|
|
11
56
|
|
|
12
57
|
//# sourceMappingURL=createUsingTemplateRender.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/template/internals/createUsingTemplateRender.ts"],"sourcesContent":["import fs from 'fs-extra';\nimport path from 'node:path';\n\nimport {prettify} from './prettify.js';\nimport {type TemplateRenderSnapshot} from './TemplateRenderSnapshot.js';\nimport {type TemplateRender} from '../TemplateRender.js';\n\nexport async function createUsingTemplateRender(\n templateRender: TemplateRender | TemplateRenderSnapshot,\n basePath: string,\n) {\n let to = path.join(basePath, templateRender.attributes.to);\n\n await fs.ensureDir(path.dirname(to));\n
|
|
1
|
+
{"version":3,"sources":["../../../src/template/internals/createUsingTemplateRender.ts"],"sourcesContent":["import {type Json} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json from 'json5';\nimport path from 'node:path';\nimport yaml from 'yaml';\n\nimport {merge} from './merge.js';\nimport {prettify} from './prettify.js';\nimport {type TemplateRenderSnapshot} from './TemplateRenderSnapshot.js';\nimport {type TemplateRender} from '../TemplateRender.js';\n\nexport async function createUsingTemplateRender(\n templateRender: TemplateRender | TemplateRenderSnapshot,\n basePath: string,\n) {\n let to = path.join(basePath, templateRender.attributes.to);\n let extension = path.extname(to);\n\n switch (extension) {\n case '.json': {\n if (await fs.pathExists(to)) {\n let targetFile = (await fs.readJson(to)) as Json;\n let fileToMerge = json.parse<Json>(templateRender.content);\n let newFile = JSON.stringify(merge(targetFile, fileToMerge), null, 2);\n\n await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});\n } else {\n await fs.ensureDir(path.dirname(to));\n await fs.writeFile(to, await prettify(templateRender.content, to), {encoding: 'utf8'});\n }\n\n break;\n }\n\n case '.yaml': {\n if (await fs.pathExists(to)) {\n let targetFile = yaml.parse(await fs.readFile(to, {encoding: 'utf8'})) as unknown;\n let fileToMerge = yaml.parse(templateRender.content) as unknown;\n let newFile = yaml.stringify(merge(targetFile, fileToMerge));\n\n await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});\n } else {\n await fs.writeFile(to, await prettify(templateRender.content, to), {encoding: 'utf8'});\n }\n\n break;\n }\n\n default: {\n await fs.ensureDir(path.dirname(to));\n await fs.writeFile(to, await prettify(templateRender.content, to), {encoding: 'utf8'});\n\n break;\n }\n }\n}\n"],"names":["fs","json","path","yaml","merge","prettify","createUsingTemplateRender","templateRender","basePath","to","join","attributes","extension","extname","pathExists","targetFile","readJson","fileToMerge","parse","content","newFile","JSON","stringify","writeFile","encoding","ensureDir","dirname","readFile"],"mappings":"AACA,OAAOA,QAAQ,WAAW;AAC1B,OAAOC,UAAU,QAAQ;AACzB,OAAOC,UAAU,YAAY;AAC7B,OAAOC,UAAU,OAAO;AAExB,SAAQC,KAAK,QAAO,aAAa;AACjC,SAAQC,QAAQ,QAAO,gBAAgB;AAIvC,OAAO,eAAeC,0BACpBC,cAAuD,EACvDC,QAAgB;IAEhB,IAAIC,KAAKP,KAAKQ,IAAI,CAACF,UAAUD,eAAeI,UAAU,CAACF,EAAE;IACzD,IAAIG,YAAYV,KAAKW,OAAO,CAACJ;IAE7B,OAAQG;QACN,KAAK;YAAS;gBACZ,IAAI,MAAMZ,GAAGc,UAAU,CAACL,KAAK;oBAC3B,IAAIM,aAAc,MAAMf,GAAGgB,QAAQ,CAACP;oBACpC,IAAIQ,cAAchB,KAAKiB,KAAK,CAAOX,eAAeY,OAAO;oBACzD,IAAIC,UAAUC,KAAKC,SAAS,CAAClB,MAAMW,YAAYE,cAAc,MAAM;oBAEnE,MAAMjB,GAAGuB,SAAS,CAACd,IAAI,MAAMJ,SAASe,SAASX,KAAK;wBAACe,UAAU;oBAAM;gBACvE,OAAO;oBACL,MAAMxB,GAAGyB,SAAS,CAACvB,KAAKwB,OAAO,CAACjB;oBAChC,MAAMT,GAAGuB,SAAS,CAACd,IAAI,MAAMJ,SAASE,eAAeY,OAAO,EAAEV,KAAK;wBAACe,UAAU;oBAAM;gBACtF;gBAEA;YACF;QAEA,KAAK;YAAS;gBACZ,IAAI,MAAMxB,GAAGc,UAAU,CAACL,KAAK;oBAC3B,IAAIM,aAAaZ,KAAKe,KAAK,CAAC,MAAMlB,GAAG2B,QAAQ,CAAClB,IAAI;wBAACe,UAAU;oBAAM;oBACnE,IAAIP,cAAcd,KAAKe,KAAK,CAACX,eAAeY,OAAO;oBACnD,IAAIC,UAAUjB,KAAKmB,SAAS,CAAClB,MAAMW,YAAYE;oBAE/C,MAAMjB,GAAGuB,SAAS,CAACd,IAAI,MAAMJ,SAASe,SAASX,KAAK;wBAACe,UAAU;oBAAM;gBACvE,OAAO;oBACL,MAAMxB,GAAGuB,SAAS,CAACd,IAAI,MAAMJ,SAASE,eAAeY,OAAO,EAAEV,KAAK;wBAACe,UAAU;oBAAM;gBACtF;gBAEA;YACF;QAEA;YAAS;gBACP,MAAMxB,GAAGyB,SAAS,CAACvB,KAAKwB,OAAO,CAACjB;gBAChC,MAAMT,GAAGuB,SAAS,CAACd,IAAI,MAAMJ,SAASE,eAAeY,OAAO,EAAEV,KAAK;oBAACe,UAAU;gBAAM;gBAEpF;YACF;IACF;AACF"}
|
|
@@ -11,24 +11,36 @@ export async function mergeUsingTemplateRender(templateRender, basePath) {
|
|
|
11
11
|
switch(extension){
|
|
12
12
|
case '.json':
|
|
13
13
|
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
if (await fs.pathExists(to)) {
|
|
15
|
+
let targetFile = await fs.readJson(to);
|
|
16
|
+
let fileToMerge = json.parse(templateRender.content);
|
|
17
|
+
let newFile = JSON.stringify(merge(targetFile, fileToMerge), null, 2);
|
|
18
|
+
await fs.writeFile(to, await prettify(newFile, to), {
|
|
19
|
+
encoding: 'utf8'
|
|
20
|
+
});
|
|
21
|
+
} else {
|
|
22
|
+
await fs.writeFile(to, await prettify(templateRender.content, to), {
|
|
23
|
+
encoding: 'utf8'
|
|
24
|
+
});
|
|
25
|
+
}
|
|
20
26
|
break;
|
|
21
27
|
}
|
|
22
28
|
case '.yaml':
|
|
23
29
|
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if (await fs.pathExists(to)) {
|
|
31
|
+
let targetFile = yaml.parse(await fs.readFile(to, {
|
|
32
|
+
encoding: 'utf8'
|
|
33
|
+
}));
|
|
34
|
+
let fileToMerge = yaml.parse(templateRender.content);
|
|
35
|
+
let newFile = yaml.stringify(merge(targetFile, fileToMerge));
|
|
36
|
+
await fs.writeFile(to, await prettify(newFile, to), {
|
|
37
|
+
encoding: 'utf8'
|
|
38
|
+
});
|
|
39
|
+
} else {
|
|
40
|
+
await fs.writeFile(to, await prettify(templateRender.content, to), {
|
|
41
|
+
encoding: 'utf8'
|
|
42
|
+
});
|
|
43
|
+
}
|
|
32
44
|
break;
|
|
33
45
|
}
|
|
34
46
|
default:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/template/internals/mergeUsingTemplateRender.ts"],"sourcesContent":["import {type Json} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json from 'json5';\nimport path from 'node:path';\nimport yaml from 'yaml';\n\nimport {merge} from './merge.js';\nimport {prettify} from './prettify.js';\nimport {type TemplateRenderSnapshot} from './TemplateRenderSnapshot.js';\nimport {CarsonTemplateError} from '../CarsonTemplateError.js';\nimport {type TemplateRender} from '../TemplateRender.js';\n\nexport async function mergeUsingTemplateRender(\n templateRender: TemplateRender | TemplateRenderSnapshot,\n basePath: string,\n) {\n let to = path.join(basePath, templateRender.attributes.to);\n let extension = path.extname(to);\n\n switch (extension) {\n case '.json': {\n let targetFile = (await fs.readJson(to)) as Json;\n
|
|
1
|
+
{"version":3,"sources":["../../../src/template/internals/mergeUsingTemplateRender.ts"],"sourcesContent":["import {type Json} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json from 'json5';\nimport path from 'node:path';\nimport yaml from 'yaml';\n\nimport {merge} from './merge.js';\nimport {prettify} from './prettify.js';\nimport {type TemplateRenderSnapshot} from './TemplateRenderSnapshot.js';\nimport {CarsonTemplateError} from '../CarsonTemplateError.js';\nimport {type TemplateRender} from '../TemplateRender.js';\n\nexport async function mergeUsingTemplateRender(\n templateRender: TemplateRender | TemplateRenderSnapshot,\n basePath: string,\n) {\n let to = path.join(basePath, templateRender.attributes.to);\n let extension = path.extname(to);\n\n switch (extension) {\n case '.json': {\n if (await fs.pathExists(to)) {\n let targetFile = (await fs.readJson(to)) as Json;\n let fileToMerge = json.parse<Json>(templateRender.content);\n let newFile = JSON.stringify(merge(targetFile, fileToMerge), null, 2);\n\n await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});\n } else {\n await fs.writeFile(to, await prettify(templateRender.content, to), {encoding: 'utf8'});\n }\n\n break;\n }\n\n case '.yaml': {\n if (await fs.pathExists(to)) {\n let targetFile = yaml.parse(await fs.readFile(to, {encoding: 'utf8'})) as unknown;\n let fileToMerge = yaml.parse(templateRender.content) as unknown;\n let newFile = yaml.stringify(merge(targetFile, fileToMerge));\n\n await fs.writeFile(to, await prettify(newFile, to), {encoding: 'utf8'});\n } else {\n await fs.writeFile(to, await prettify(templateRender.content, to), {encoding: 'utf8'});\n }\n\n break;\n }\n\n default: {\n throw new CarsonTemplateError('STRATEGY_UNSUPPORTED_EXTENSION', {\n messageParameters: [\n templateRender.attributes.strategy,\n templateRender.template.path,\n extension,\n ],\n data: {\n path: templateRender.template.path,\n },\n });\n }\n }\n}\n"],"names":["fs","json","path","yaml","merge","prettify","CarsonTemplateError","mergeUsingTemplateRender","templateRender","basePath","to","join","attributes","extension","extname","pathExists","targetFile","readJson","fileToMerge","parse","content","newFile","JSON","stringify","writeFile","encoding","readFile","messageParameters","strategy","template","data"],"mappings":"AACA,OAAOA,QAAQ,WAAW;AAC1B,OAAOC,UAAU,QAAQ;AACzB,OAAOC,UAAU,YAAY;AAC7B,OAAOC,UAAU,OAAO;AAExB,SAAQC,KAAK,QAAO,aAAa;AACjC,SAAQC,QAAQ,QAAO,gBAAgB;AAEvC,SAAQC,mBAAmB,QAAO,4BAA4B;AAG9D,OAAO,eAAeC,yBACpBC,cAAuD,EACvDC,QAAgB;IAEhB,IAAIC,KAAKR,KAAKS,IAAI,CAACF,UAAUD,eAAeI,UAAU,CAACF,EAAE;IACzD,IAAIG,YAAYX,KAAKY,OAAO,CAACJ;IAE7B,OAAQG;QACN,KAAK;YAAS;gBACZ,IAAI,MAAMb,GAAGe,UAAU,CAACL,KAAK;oBAC3B,IAAIM,aAAc,MAAMhB,GAAGiB,QAAQ,CAACP;oBACpC,IAAIQ,cAAcjB,KAAKkB,KAAK,CAAOX,eAAeY,OAAO;oBACzD,IAAIC,UAAUC,KAAKC,SAAS,CAACnB,MAAMY,YAAYE,cAAc,MAAM;oBAEnE,MAAMlB,GAAGwB,SAAS,CAACd,IAAI,MAAML,SAASgB,SAASX,KAAK;wBAACe,UAAU;oBAAM;gBACvE,OAAO;oBACL,MAAMzB,GAAGwB,SAAS,CAACd,IAAI,MAAML,SAASG,eAAeY,OAAO,EAAEV,KAAK;wBAACe,UAAU;oBAAM;gBACtF;gBAEA;YACF;QAEA,KAAK;YAAS;gBACZ,IAAI,MAAMzB,GAAGe,UAAU,CAACL,KAAK;oBAC3B,IAAIM,aAAab,KAAKgB,KAAK,CAAC,MAAMnB,GAAG0B,QAAQ,CAAChB,IAAI;wBAACe,UAAU;oBAAM;oBACnE,IAAIP,cAAcf,KAAKgB,KAAK,CAACX,eAAeY,OAAO;oBACnD,IAAIC,UAAUlB,KAAKoB,SAAS,CAACnB,MAAMY,YAAYE;oBAE/C,MAAMlB,GAAGwB,SAAS,CAACd,IAAI,MAAML,SAASgB,SAASX,KAAK;wBAACe,UAAU;oBAAM;gBACvE,OAAO;oBACL,MAAMzB,GAAGwB,SAAS,CAACd,IAAI,MAAML,SAASG,eAAeY,OAAO,EAAEV,KAAK;wBAACe,UAAU;oBAAM;gBACtF;gBAEA;YACF;QAEA;YAAS;gBACP,MAAM,IAAInB,oBAAoB,kCAAkC;oBAC9DqB,mBAAmB;wBACjBnB,eAAeI,UAAU,CAACgB,QAAQ;wBAClCpB,eAAeqB,QAAQ,CAAC3B,IAAI;wBAC5BW;qBACD;oBACDiB,MAAM;wBACJ5B,MAAMM,eAAeqB,QAAQ,CAAC3B,IAAI;oBACpC;gBACF;YACF;IACF;AACF"}
|
|
@@ -7,7 +7,7 @@ import { z } from 'zod';
|
|
|
7
7
|
import { projectConfigSchema } from './ProjectConfig.js';
|
|
8
8
|
import { ProjectError } from './ProjectError.js';
|
|
9
9
|
import { saveProjectConfig } from './saveProjectConfig.js';
|
|
10
|
-
import { CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME } from '../constants.js';
|
|
10
|
+
import { CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME, PROJECT_SNAPSHOT_FILENAME } from '../constants.js';
|
|
11
11
|
import { applyTemplateRenders } from '../template/applyTemplateRenders.js';
|
|
12
12
|
import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
13
13
|
/**
|
|
@@ -56,17 +56,20 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
56
56
|
},
|
|
57
57
|
workspace
|
|
58
58
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
// if the workspace is single-project, it shares a directory with the project, so we can't insist on it being an empty directory
|
|
60
|
+
if (workspace.isMultiProject) {
|
|
61
|
+
try {
|
|
62
|
+
await ensureEmptyDirectory(project.path);
|
|
63
|
+
} catch {
|
|
64
|
+
throw new ProjectError('PROJECT_PATH_NOT_EMPTY', {
|
|
65
|
+
messageParameters: [
|
|
66
|
+
project.path
|
|
67
|
+
],
|
|
68
|
+
data: {
|
|
69
|
+
path: project.path
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
70
73
|
}
|
|
71
74
|
let templateRenders = await renderCarsonTemplate({
|
|
72
75
|
templateId,
|
|
@@ -78,7 +81,8 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
78
81
|
});
|
|
79
82
|
await applyTemplateRenders({
|
|
80
83
|
templateRenders,
|
|
81
|
-
|
|
84
|
+
targetPath: project.path,
|
|
85
|
+
snapshotPath: path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
82
86
|
ignoreStrategies: [
|
|
83
87
|
'check'
|
|
84
88
|
]
|
|
@@ -186,7 +190,8 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
186
190
|
});
|
|
187
191
|
await applyTemplateRenders({
|
|
188
192
|
templateRenders,
|
|
189
|
-
|
|
193
|
+
targetPath: this.path,
|
|
194
|
+
snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),
|
|
190
195
|
ignoreStrategies: [
|
|
191
196
|
'create'
|
|
192
197
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/workspace/Project.ts"],"sourcesContent":["import {ensureEmptyDirectory, pathToPosixPath} from '@jakubmazanec/fs-utils';\nimport {readFile, packageJsonSchema, type PackageJson} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json5 from 'json5';\nimport path from 'node:path';\nimport {z} from 'zod';\n\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';\nimport {CARSON_CONFIG_DIRECTORY, PROJECT_CONFIG_FILENAME} from '../constants.js';\nimport {applyTemplateRenders} from '../template/applyTemplateRenders.js';\nimport {renderCarsonTemplate} from '../template/renderCarsonTemplate.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 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 let templateRenders = await renderCarsonTemplate({\n templateId,\n templateData: {\n workspace,\n project,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n path: project.path,\n ignoreStrategies: ['check'],\n });\n\n await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});\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 templateRenders = await renderCarsonTemplate({\n templateId: this.config.template,\n templateData: {\n workspace: this.workspace,\n project: this,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n path: this.path,\n ignoreStrategies: ['create'],\n });\n\n await this.read();\n\n return this;\n }\n}\n"],"names":["ensureEmptyDirectory","pathToPosixPath","readFile","packageJsonSchema","fs","json5","path","z","projectConfigSchema","ProjectError","saveProjectConfig","CARSON_CONFIG_DIRECTORY","PROJECT_CONFIG_FILENAME","applyTemplateRenders","renderCarsonTemplate","Project","name","relativePath","config","packageJson","workspace","errors","constructor","projectPath","length","relative","create","templateId","projectName","args","project","template","messageParameters","data","templateRenders","templateData","ignoreStrategies","projectConfig","read","pathExists","projectConfigPath","join","doesProjectConfigExist","parser","rawString","parse","ZodError","zodError","push","zodIssues","issues","packageJsonPath","doesPackageJsonExist","update"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/workspace/Project.ts"],"sourcesContent":["import {ensureEmptyDirectory, pathToPosixPath} from '@jakubmazanec/fs-utils';\nimport {readFile, packageJsonSchema, type PackageJson} from '@jakubmazanec/zod-utils';\nimport fs from 'fs-extra';\nimport json5 from 'json5';\nimport path from 'node:path';\nimport {z} from 'zod';\n\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';\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';\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 templateId,\n templateData: {\n workspace,\n project,\n args,\n },\n });\n\n await applyTemplateRenders({\n templateRenders,\n targetPath: project.path,\n snapshotPath: path.join(project.path, CARSON_CONFIG_DIRECTORY, PROJECT_SNAPSHOT_FILENAME),\n ignoreStrategies: ['check'],\n });\n\n await saveProjectConfig({projectPath: project.path, projectConfig: {template: templateId}});\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 templateRenders = await renderCarsonTemplate({\n templateId: this.config.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: 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"],"names":["ensureEmptyDirectory","pathToPosixPath","readFile","packageJsonSchema","fs","json5","path","z","projectConfigSchema","ProjectError","saveProjectConfig","CARSON_CONFIG_DIRECTORY","PROJECT_CONFIG_FILENAME","PROJECT_SNAPSHOT_FILENAME","applyTemplateRenders","renderCarsonTemplate","Project","name","relativePath","config","packageJson","workspace","errors","constructor","projectPath","length","relative","create","templateId","projectName","args","project","template","isMultiProject","messageParameters","data","templateRenders","templateData","targetPath","snapshotPath","join","ignoreStrategies","projectConfig","read","pathExists","projectConfigPath","doesProjectConfigExist","parser","rawString","parse","ZodError","zodError","push","zodIssues","issues","packageJsonPath","doesPackageJsonExist","update"],"mappings":"AAAA,SAAQA,oBAAoB,EAAEC,eAAe,QAAO,yBAAyB;AAC7E,SAAQC,QAAQ,EAAEC,iBAAiB,QAAyB,0BAA0B;AACtF,OAAOC,QAAQ,WAAW;AAC1B,OAAOC,WAAW,QAAQ;AAC1B,OAAOC,UAAU,YAAY;AAC7B,SAAQC,CAAC,QAAO,MAAM;AAEtB,SAA4BC,mBAAmB,QAAO,qBAAqB;AAE3E,SAAQC,YAAY,QAAO,oBAAoB;AAG/C,SAAQC,iBAAiB,QAAO,yBAAyB;AAEzD,SACEC,uBAAuB,EACvBC,uBAAuB,EACvBC,yBAAyB,QACpB,kBAAkB;AACzB,SAAQC,oBAAoB,QAAO,sCAAsC;AACzE,SAAQC,oBAAoB,QAAO,sCAAsC;AAEzE;;;;CAIC,GACD,OAAO,MAAMC;IACX,kBAAkB,GAClBC,KAAc;IAEd,kBAAkB,GAClBX,KAAa;IAEb,6CAA6C,GAC7CY,aAAqB;IAErB,8EAA8E,GAC9EC,OAAsB;IAEtB,2FAA2F,GAC3FC,YAAyB;IAEzB,uCAAuC,GACvCC,UAAwB;IAExB,sDAAsD,GACtDC,SAAmD,EAAE,CAAC;IAEtDC,YAAY,EACVjB,MAAMkB,WAAW,EACjBP,IAAI,EACJE,MAAM,EACNC,WAAW,EACXC,SAAS,EACTC,MAAM,EACY,CAAE;QACpB,uHAAuH;QACvH,IAAI,CAAChB,IAAI,GAAGkB;QAEZ,IAAIP,MAAM;YACR,IAAI,CAACA,IAAI,GAAGA;QACd;QAEA,IAAIE,QAAQ;YACV,IAAI,CAACA,MAAM,GAAGA;QAChB,OAAO;YACL,IAAI,CAACA,MAAM,GAAG,CAAC;QACjB;QAEA,IAAIC,aAAa;YACf,IAAI,CAACA,WAAW,GAAGA;QACrB,OAAO;YACL,IAAI,CAACA,WAAW,GAAG,CAAC;QACtB;QAEA,IAAI,CAACC,SAAS,GAAGA;QAEjB,IAAIC,QAAQ;YACV,IAAI,CAACA,MAAM,GAAGA;QAChB;QAEA,IAAI,IAAI,CAACF,WAAW,CAACH,IAAI,EAAEQ,QAAQ;YACjC,IAAI,CAACR,IAAI,GAAG,IAAI,CAACG,WAAW,CAACH,IAAI;QACnC;QAEA,IAAI,CAACC,YAAY,GAAGjB,gBAAgBK,KAAKoB,QAAQ,CAAC,IAAI,CAACL,SAAS,CAACf,IAAI,EAAE,IAAI,CAACA,IAAI;IAClF;IAEA,aAAaqB,OAA0B,EACrCC,UAAU,EACVP,SAAS,EACTG,WAAW,EACXK,WAAW,EACXC,IAAI,EACoB,EAAuB;QAC/C,IAAIC,UAAU,IAAI,IAAI,CAAC;YACrBzB,MAAMkB;YACNP,MAAMY;YACNV,QAAQ;gBACNa,UAAUJ;YACZ;YACAP;QACF;QAEA,gIAAgI;QAChI,IAAIA,UAAUY,cAAc,EAAE;YAC5B,IAAI;gBACF,MAAMjC,qBAAqB+B,QAAQzB,IAAI;YACzC,EAAE,OAAM;gBACN,MAAM,IAAIG,aAAa,0BAA0B;oBAC/CyB,mBAAmB;wBAACH,QAAQzB,IAAI;qBAAC;oBACjC6B,MAAM;wBACJ7B,MAAMyB,QAAQzB,IAAI;oBACpB;gBACF;YACF;QACF;QAEA,IAAI8B,kBAAkB,MAAMrB,qBAAqB;YAC/Ca;YACAS,cAAc;gBACZhB;gBACAU;gBACAD;YACF;QACF;QAEA,MAAMhB,qBAAqB;YACzBsB;YACAE,YAAYP,QAAQzB,IAAI;YACxBiC,cAAcjC,KAAKkC,IAAI,CAACT,QAAQzB,IAAI,EAAEK,yBAAyBE;YAC/D4B,kBAAkB;gBAAC;aAAQ;QAC7B;QAEA,MAAM/B,kBAAkB;YAACc,aAAaO,QAAQzB,IAAI;YAAEoC,eAAe;gBAACV,UAAUJ;YAAU;QAAC;QAEzF,MAAMG,QAAQY,IAAI;QAElB,OAAOZ;IACT;IAEA,aAAaY,KACXnB,WAAmB,EACnBH,SAAuB,EACF;QACrB,IAAIU,UAAU,IAAI,IAAI,CAAC;YACrBzB,MAAMkB;YACNH;QACF;QAEA,MAAMU,QAAQY,IAAI;QAElB,OAAOZ;IACT;IAEA,MAAMY,OAAO;QACX,IAAI,CAAE,MAAMvC,GAAGwC,UAAU,CAAC,IAAI,CAACtC,IAAI,GAAI;YACrC,MAAM,IAAIG,aAAa,wBAAwB;gBAC7CyB,mBAAmB;oBAAC,IAAI,CAAC5B,IAAI;iBAAC;gBAC9B6B,MAAM;oBACJ7B,MAAM,IAAI,CAACA,IAAI;gBACjB;YACF;QACF;QAEA,IAAIgB,SAAmD,EAAE;QAEzD,sBAAsB;QACtB,IAAIuB,oBAAoBvC,KAAKkC,IAAI,CAAC,IAAI,CAAClC,IAAI,EAAEK,yBAAyBC;QACtE,IAAIkC,yBAAyB,MAAM1C,GAAGwC,UAAU,CAACC;QACjD,IAAIH;QAEJ,IAAII,wBAAwB;YAC1BJ,gBAAgB,MAAMxC,SAAS2C,mBAAmBrC,qBAAqB;gBACrEuC,QAAQ,CAACC,YAAsB3C,MAAM4C,KAAK,CAAUD;YACtD;QACF,OAAO;YACLN,gBAAgB,CAAC;QACnB;QAEA,IAAIA,yBAAyBnC,EAAE2C,QAAQ,EAAE;YACvC,IAAIC,WAAWT;YAEfpB,OAAO8B,IAAI,CACT,IAAI3C,aAAa,0BAA0B;gBACzCyB,mBAAmB;oBAACW;iBAAkB;gBACtCV,MAAM;oBACJ7B,MAAMuC;oBACNQ,WAAWF,SAASG,MAAM;gBAC5B;YACF;YAGFZ,gBAAgB,CAAC;QACnB;QAEA,oBAAoB;QACpB,IAAIa,kBAAkBjD,KAAKkC,IAAI,CAAC,IAAI,CAAClC,IAAI,EAAE;QAC3C,IAAIkD,uBAAuB,MAAMpD,GAAGwC,UAAU,CAACW;QAC/C,IAAInC;QAEJ,IAAIoC,sBAAsB;YACxBpC,cAAc,MAAMlB,SAASqD,iBAAiBpD,mBAAmB;gBAC/D4C,QAAQ,CAACC,YAAsB3C,MAAM4C,KAAK,CAAUD;YACtD;QACF,OAAO;YACL5B,cAAc,CAAC;QACjB;QAEA,IAAIA,uBAAuBb,EAAE2C,QAAQ,EAAE;YACrC,IAAIC,WAAW/B;YAEfE,OAAO8B,IAAI,CACT,IAAI3C,aAAa,wBAAwB;gBACvCyB,mBAAmB;oBAACqB;iBAAgB;gBACpCpB,MAAM;oBACJ7B,MAAMiD;oBACNF,WAAWF,SAASG,MAAM;gBAC5B;YACF;YAGFlC,cAAc,CAAC;QACjB;QAEA,IAAIA,YAAYH,IAAI,EAAEQ,QAAQ;YAC5B,IAAI,CAACR,IAAI,GAAGG,YAAYH,IAAI;QAC9B;QAEA,IAAI,CAACE,MAAM,GAAGuB;QACd,IAAI,CAACtB,WAAW,GAAGA;QACnB,IAAI,CAACE,MAAM,GAAGA;QAEd,OAAO,IAAI;IACb;IAEA,MAAMmC,OAAO,EAAC3B,IAAI,EAAuB,EAAiB;QACxD,IAAI,CAAC,IAAI,CAACX,MAAM,CAACa,QAAQ,EAAE;YACzB,MAAM,IAAIvB,aAAa,8BAA8B;gBACnDyB,mBAAmB;oBAAC5B,KAAKkC,IAAI,CAAC,IAAI,CAAClC,IAAI,EAAEK,yBAAyBC;iBAAyB;YAC7F;QACF;QAEA,IAAIwB,kBAAkB,MAAMrB,qBAAqB;YAC/Ca,YAAY,IAAI,CAACT,MAAM,CAACa,QAAQ;YAChCK,cAAc;gBACZhB,WAAW,IAAI,CAACA,SAAS;gBACzBU,SAAS,IAAI;gBACbD;YACF;QACF;QAEA,MAAMhB,qBAAqB;YACzBsB;YACAE,YAAY,IAAI,CAAChC,IAAI;YACrBiC,cAAcjC,KAAKkC,IAAI,CAAC,IAAI,CAAClC,IAAI,EAAEK,yBAAyBE;YAC5D4B,kBAAkB;gBAAC;aAAS;QAC9B;QAEA,MAAM,IAAI,CAACE,IAAI;QAEf,OAAO,IAAI;IACb;AACF"}
|
|
@@ -52,6 +52,9 @@ export declare class Workspace<M extends boolean = true> {
|
|
|
52
52
|
static read(workspacePath: string): Promise<Workspace | Workspace<false>>;
|
|
53
53
|
/**
|
|
54
54
|
* Traverses file system up from the search path and tries to find a directory that is a root of a workspace.
|
|
55
|
+
*
|
|
56
|
+
* @param searchPath Search path.
|
|
57
|
+
* @returns Workspace path, if found.
|
|
55
58
|
*/
|
|
56
59
|
static find(searchPath: string): Promise<string | undefined>;
|
|
57
60
|
/**
|
|
@@ -5,13 +5,13 @@ import fs from 'fs-extra';
|
|
|
5
5
|
import json5 from 'json5';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
-
import { compareProjectPath, containsProject, getPackageJsonWorkspaces, getRepositoryBranches, getRepositoryUrl } from './internals.js';
|
|
8
|
+
import { compareProjectPath, containsProject, containsWorkspace, getPackageJsonWorkspaces, getRepositoryBranches, getRepositoryUrl } from './internals.js';
|
|
9
9
|
import { Project } from './Project.js';
|
|
10
10
|
import { saveWorkspaceConfig } from './saveWorkspaceConfig.js';
|
|
11
11
|
import { workspaceConfigSchema } from './WorkspaceConfig.js';
|
|
12
12
|
import { WorkspaceDependencies } from './WorkspaceDependencies.js';
|
|
13
13
|
import { WorkspaceError } from './WorkspaceError.js';
|
|
14
|
-
import { CARSON_CONFIG_DIRECTORY, WORKSPACE_CONFIG_FILENAME } from '../constants.js';
|
|
14
|
+
import { CARSON_CONFIG_DIRECTORY, WORKSPACE_CONFIG_FILENAME, PACKAGE_JSON_FILENAME, WORKSPACE_SNAPSHOT_FILENAME } from '../constants.js';
|
|
15
15
|
import { applyTemplateRenders } from '../template/applyTemplateRenders.js';
|
|
16
16
|
import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
17
17
|
/**
|
|
@@ -130,7 +130,8 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
130
130
|
});
|
|
131
131
|
await applyTemplateRenders({
|
|
132
132
|
templateRenders,
|
|
133
|
-
|
|
133
|
+
targetPath: workspace.path,
|
|
134
|
+
snapshotPath: path.join(workspace.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
134
135
|
ignoreStrategies: [
|
|
135
136
|
'check'
|
|
136
137
|
]
|
|
@@ -208,25 +209,31 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
208
209
|
}
|
|
209
210
|
/**
|
|
210
211
|
* Traverses file system up from the search path and tries to find a directory that is a root of a workspace.
|
|
212
|
+
*
|
|
213
|
+
* @param searchPath Search path.
|
|
214
|
+
* @returns Workspace path, if found.
|
|
211
215
|
*/ static async find(searchPath) {
|
|
212
216
|
let startingPath = await findExistingDirectory(path.resolve(searchPath));
|
|
213
217
|
let currentPath = startingPath;
|
|
214
218
|
let singlePackageWorkspacePath;
|
|
215
219
|
let multiPackageWorkspacePath;
|
|
216
220
|
while(!(isRootPath(currentPath) || singlePackageWorkspacePath && multiPackageWorkspacePath)){
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
221
|
+
if (await containsWorkspace(currentPath)) {
|
|
222
|
+
const packageJsonPath = path.join(currentPath, PACKAGE_JSON_FILENAME);
|
|
223
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
224
|
+
const packageJson = await readFile(packageJsonPath, jsonSchema, {
|
|
225
|
+
parser: (rawString)=>json5.parse(rawString)
|
|
226
|
+
});
|
|
227
|
+
if (!(packageJson instanceof Error)) {
|
|
228
|
+
const projectGlobs = getPackageJsonWorkspaces(packageJson);
|
|
229
|
+
if (projectGlobs?.length) {
|
|
230
|
+
multiPackageWorkspacePath ??= currentPath;
|
|
231
|
+
} else {
|
|
232
|
+
singlePackageWorkspacePath ??= currentPath;
|
|
233
|
+
}
|
|
229
234
|
}
|
|
235
|
+
} else {
|
|
236
|
+
singlePackageWorkspacePath ??= currentPath;
|
|
230
237
|
}
|
|
231
238
|
}
|
|
232
239
|
currentPath = path.dirname(currentPath);
|
|
@@ -372,7 +379,8 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
372
379
|
});
|
|
373
380
|
await applyTemplateRenders({
|
|
374
381
|
templateRenders,
|
|
375
|
-
|
|
382
|
+
targetPath: this.path,
|
|
383
|
+
snapshotPath: path.join(this.path, CARSON_CONFIG_DIRECTORY, WORKSPACE_SNAPSHOT_FILENAME),
|
|
376
384
|
ignoreStrategies: [
|
|
377
385
|
'create'
|
|
378
386
|
]
|
|
@@ -489,13 +497,15 @@ import { renderCarsonTemplate } from '../template/renderCarsonTemplate.js';
|
|
|
489
497
|
}
|
|
490
498
|
}
|
|
491
499
|
this.projects = projects;
|
|
492
|
-
|
|
500
|
+
this.sortProjects();
|
|
501
|
+
this.updateDependencies();
|
|
502
|
+
} else if (await containsProject(this.path)) {
|
|
493
503
|
this.projects = [
|
|
494
504
|
await Project.read(this.path, this)
|
|
495
505
|
];
|
|
506
|
+
this.sortProjects();
|
|
507
|
+
this.updateDependencies();
|
|
496
508
|
}
|
|
497
|
-
this.sortProjects();
|
|
498
|
-
this.updateDependencies();
|
|
499
509
|
return this.projects;
|
|
500
510
|
}
|
|
501
511
|
sortProjects() {
|