@teambit/config 0.0.0-0073f7d9944278e4b4a2f976f27cefc5909c8e11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/config.aspect.d.ts +3 -0
  2. package/dist/config.aspect.js +21 -0
  3. package/dist/config.aspect.js.map +1 -0
  4. package/dist/config.main.runtime.d.ts +43 -0
  5. package/dist/config.main.runtime.js +169 -0
  6. package/dist/config.main.runtime.js.map +1 -0
  7. package/dist/esm.mjs +12 -0
  8. package/dist/exceptions/extension-already-configured.d.ts +5 -0
  9. package/dist/exceptions/extension-already-configured.js +22 -0
  10. package/dist/exceptions/extension-already-configured.js.map +1 -0
  11. package/dist/exceptions/index.d.ts +1 -0
  12. package/dist/exceptions/index.js +20 -0
  13. package/dist/exceptions/index.js.map +1 -0
  14. package/dist/exceptions/invalid-config-file.d.ts +6 -0
  15. package/dist/exceptions/invalid-config-file.js +36 -0
  16. package/dist/exceptions/invalid-config-file.js.map +1 -0
  17. package/dist/index.d.ts +4 -0
  18. package/dist/index.js +64 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/preview-1753756156048.js +7 -0
  21. package/dist/readme.md +3 -0
  22. package/dist/schema.json +156 -0
  23. package/dist/types.d.ts +21 -0
  24. package/dist/types.js +3 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/workspace-config.d.ts +129 -0
  27. package/dist/workspace-config.js +464 -0
  28. package/dist/workspace-config.js.map +1 -0
  29. package/dist/workspace-template.jsonc +71 -0
  30. package/esm.mjs +12 -0
  31. package/exceptions/extension-already-configured.ts +7 -0
  32. package/exceptions/index.ts +1 -0
  33. package/exceptions/invalid-config-file.ts +11 -0
  34. package/package.json +70 -0
  35. package/readme.md +3 -0
  36. package/schema.json +156 -0
  37. package/types/asset.d.ts +41 -0
  38. package/types/style.d.ts +42 -0
  39. package/workspace-template.jsonc +71 -0
@@ -0,0 +1,21 @@
1
+ import { ExtensionDataEntry, ExtensionDataList } from '@teambit/legacy.extension-data';
2
+ import { PathOsBased, PathOsBasedAbsolute } from '@teambit/toolbox.path.path';
3
+ import { SetExtensionOptions } from './config.main.runtime';
4
+ export type WriteOptions = {
5
+ dir?: PathOsBasedAbsolute;
6
+ };
7
+ /**
8
+ * An interface implemented by component host (workspace / scope) config file
9
+ * This used to be able to abstract the workspace/scope config.
10
+ */
11
+ export interface HostConfig {
12
+ /**
13
+ * Path to the actual file
14
+ */
15
+ path: PathOsBased;
16
+ extensions: ExtensionDataList;
17
+ extension: (extensionId: string, ignoreVersion: boolean) => ExtensionDataEntry;
18
+ setExtension(extensionId: string, config: Record<string, any>, options: SetExtensionOptions): void;
19
+ write(opts: WriteOptions): Promise<void>;
20
+ }
21
+ export type ConfigType = 'workspace' | 'scope';
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import { ExtensionDataEntry, ExtensionDataList } from '@teambit/legacy.extension-data';\nimport { PathOsBased, PathOsBasedAbsolute } from '@teambit/toolbox.path.path';\n\nimport { SetExtensionOptions } from './config.main.runtime';\n\nexport type WriteOptions = {\n dir?: PathOsBasedAbsolute;\n};\n\n/**\n * An interface implemented by component host (workspace / scope) config file\n * This used to be able to abstract the workspace/scope config.\n */\nexport interface HostConfig {\n /**\n * Path to the actual file\n */\n path: PathOsBased;\n\n extensions: ExtensionDataList;\n\n extension: (extensionId: string, ignoreVersion: boolean) => ExtensionDataEntry;\n\n setExtension(extensionId: string, config: Record<string, any>, options: SetExtensionOptions): void;\n\n write(opts: WriteOptions): Promise<void>;\n}\n\nexport type ConfigType = 'workspace' | 'scope';\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,129 @@
1
+ import { ComponentID } from '@teambit/component-id';
2
+ import { AbstractVinyl } from '@teambit/component.sources';
3
+ import { ILegacyWorkspaceConfig } from '@teambit/legacy.consumer-config';
4
+ import { ExtensionDataList } from '@teambit/legacy.extension-data';
5
+ import { PathOsBased, PathOsBasedAbsolute } from '@teambit/legacy.utils';
6
+ import { SetExtensionOptions } from './config.main.runtime';
7
+ import { HostConfig } from './types';
8
+ export type LegacyInitProps = {
9
+ standAlone?: boolean;
10
+ };
11
+ export type WorkspaceConfigFileProps = {
12
+ $schema?: string;
13
+ $schemaVersion?: string;
14
+ } & WorkspaceSettingsNewProps;
15
+ export type ComponentScopeDirMapEntry = {
16
+ defaultScope?: string;
17
+ directory: string;
18
+ };
19
+ export type ComponentScopeDirMap = Array<ComponentScopeDirMapEntry>;
20
+ export type WorkspaceExtensionProps = {
21
+ name?: string;
22
+ defaultScope?: string;
23
+ defaultDirectory?: string;
24
+ components?: ComponentScopeDirMap;
25
+ };
26
+ export type PackageManagerClients = 'npm' | 'yarn' | undefined;
27
+ export interface DependencyResolverExtensionProps {
28
+ packageManager: PackageManagerClients;
29
+ strictPeerDependencies?: boolean;
30
+ extraArgs?: string[];
31
+ packageManagerProcessOptions?: any;
32
+ useWorkspaces?: boolean;
33
+ manageWorkspaces?: boolean;
34
+ externalPackageManager?: boolean;
35
+ }
36
+ export type WorkspaceSettingsNewProps = {
37
+ 'teambit.workspace/workspace': WorkspaceExtensionProps;
38
+ 'teambit.dependencies/dependency-resolver': DependencyResolverExtensionProps;
39
+ };
40
+ export declare class WorkspaceConfig implements HostConfig {
41
+ private data;
42
+ private _path;
43
+ private scopePath?;
44
+ raw?: any;
45
+ _extensions: ExtensionDataList;
46
+ isLegacy: boolean;
47
+ constructor(data: WorkspaceConfigFileProps, _path: PathOsBasedAbsolute, scopePath?: PathOsBasedAbsolute | undefined);
48
+ get path(): PathOsBased;
49
+ get extensions(): ExtensionDataList;
50
+ get extensionsIds(): string[];
51
+ private loadExtensions;
52
+ extension(extensionId: string, ignoreVersion: boolean): any;
53
+ setExtension(extensionId: string, config: Record<string, any>, options: SetExtensionOptions): any;
54
+ renameExtensionInRaw(oldExtId: string, newExtId: string): boolean;
55
+ removeExtension(extCompId: ComponentID): boolean;
56
+ getExistingKeyIgnoreVersion(id: ComponentID): string | undefined;
57
+ /**
58
+ * Create an instance of the WorkspaceConfig by data
59
+ *
60
+ * @static
61
+ * @param {WorkspaceConfigFileProps} data
62
+ * @returns
63
+ * @memberof WorkspaceConfig
64
+ */
65
+ static fromObject(data: WorkspaceConfigFileProps, workspaceJsoncPath: PathOsBased, scopePath?: PathOsBasedAbsolute): WorkspaceConfig;
66
+ /**
67
+ * Create an instance of the WorkspaceConfig by the workspace config template and override values
68
+ *
69
+ * @static
70
+ * @param {WorkspaceConfigFileProps} data values to override in the default template
71
+ * @returns
72
+ * @memberof WorkspaceConfig
73
+ */
74
+ static create(props: WorkspaceConfigFileProps, dirPath: PathOsBasedAbsolute, scopePath: PathOsBasedAbsolute, generator?: string): Promise<WorkspaceConfig>;
75
+ /**
76
+ * Ensure the given directory has a workspace config
77
+ * Load if existing and create new if not
78
+ *
79
+ * @static
80
+ * @param {PathOsBasedAbsolute} dirPath
81
+ * @param {WorkspaceConfigFileProps} [workspaceConfigProps={} as any]
82
+ * @returns {Promise<WorkspaceConfig>}
83
+ * @memberof WorkspaceConfig
84
+ */
85
+ static ensure(dirPath: PathOsBasedAbsolute, scopePath: PathOsBasedAbsolute, workspaceConfigProps?: WorkspaceConfigFileProps, generator?: string): Promise<WorkspaceConfig>;
86
+ static reset(dirPath: PathOsBasedAbsolute, resetHard: boolean): Promise<void>;
87
+ /**
88
+ * Get the path of the workspace.jsonc file by a containing folder
89
+ *
90
+ * @static
91
+ * @param {PathOsBased} dirPath containing dir of the workspace.jsonc file
92
+ * @returns {PathOsBased}
93
+ * @memberof WorkspaceConfig
94
+ */
95
+ static composeWorkspaceJsoncPath(dirPath: PathOsBased): PathOsBased;
96
+ static pathHasWorkspaceJsonc(dirPath: PathOsBased): Promise<boolean>;
97
+ /**
98
+ * Check if the given dir has workspace config (new or legacy)
99
+ * @param dirPath
100
+ */
101
+ static isExist(dirPath: PathOsBased): Promise<boolean | undefined>;
102
+ /**
103
+ * Load the workspace configuration if it's exist
104
+ *
105
+ * @static
106
+ * @param {PathOsBased} dirPath
107
+ * @returns {(Promise<WorkspaceConfig | undefined>)}
108
+ * @memberof WorkspaceConfig
109
+ */
110
+ static loadIfExist(dirPath: PathOsBased, scopePath?: PathOsBasedAbsolute): Promise<WorkspaceConfig | undefined>;
111
+ static _loadFromWorkspaceJsonc(workspaceJsoncPath: PathOsBased, scopePath?: string): Promise<WorkspaceConfig>;
112
+ write({ dir, reasonForChange }?: {
113
+ dir?: PathOsBasedAbsolute;
114
+ reasonForChange?: string;
115
+ }): Promise<void>;
116
+ backupConfigFile(reasonForChange?: string): Promise<void>;
117
+ private getBackupDir;
118
+ getBackupHistoryDir(): string;
119
+ getBackupMetadataFilePath(): string;
120
+ private getParsedHistoryMetadata;
121
+ toVinyl(workspaceDir: PathOsBasedAbsolute): Promise<AbstractVinyl[] | undefined>;
122
+ toLegacy(): ILegacyWorkspaceConfig;
123
+ /**
124
+ * Validates that external package manager configuration is compatible with other settings
125
+ */
126
+ validateExternalPackageManagerConfig(): void;
127
+ }
128
+ export declare function getWorkspaceConfigTemplateParsed(): Promise<Record<string, any>>;
129
+ export declare function stringifyWorkspaceConfig(workspaceConfig: Record<string, any>): string;
@@ -0,0 +1,464 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.WorkspaceConfig = void 0;
7
+ exports.getWorkspaceConfigTemplateParsed = getWorkspaceConfigTemplateParsed;
8
+ exports.stringifyWorkspaceConfig = stringifyWorkspaceConfig;
9
+ function _legacy() {
10
+ const data = require("@teambit/legacy.constants");
11
+ _legacy = function () {
12
+ return data;
13
+ };
14
+ return data;
15
+ }
16
+ function _component() {
17
+ const data = require("@teambit/component.sources");
18
+ _component = function () {
19
+ return data;
20
+ };
21
+ return data;
22
+ }
23
+ function _legacy2() {
24
+ const data = require("@teambit/legacy.consumer-config");
25
+ _legacy2 = function () {
26
+ return data;
27
+ };
28
+ return data;
29
+ }
30
+ function _legacy3() {
31
+ const data = require("@teambit/legacy.extension-data");
32
+ _legacy3 = function () {
33
+ return data;
34
+ };
35
+ return data;
36
+ }
37
+ function _legacy4() {
38
+ const data = require("@teambit/legacy.logger");
39
+ _legacy4 = function () {
40
+ return data;
41
+ };
42
+ return data;
43
+ }
44
+ function _legacy5() {
45
+ const data = require("@teambit/legacy.consumer");
46
+ _legacy5 = function () {
47
+ return data;
48
+ };
49
+ return data;
50
+ }
51
+ function _commentJson() {
52
+ const data = require("comment-json");
53
+ _commentJson = function () {
54
+ return data;
55
+ };
56
+ return data;
57
+ }
58
+ function fs() {
59
+ const data = _interopRequireWildcard(require("fs-extra"));
60
+ fs = function () {
61
+ return data;
62
+ };
63
+ return data;
64
+ }
65
+ function path() {
66
+ const data = _interopRequireWildcard(require("path"));
67
+ path = function () {
68
+ return data;
69
+ };
70
+ return data;
71
+ }
72
+ function _lodash() {
73
+ const data = require("lodash");
74
+ _lodash = function () {
75
+ return data;
76
+ };
77
+ return data;
78
+ }
79
+ function _workspace() {
80
+ const data = require("@teambit/workspace");
81
+ _workspace = function () {
82
+ return data;
83
+ };
84
+ return data;
85
+ }
86
+ function _exceptions() {
87
+ const data = require("./exceptions");
88
+ _exceptions = function () {
89
+ return data;
90
+ };
91
+ return data;
92
+ }
93
+ function _invalidConfigFile() {
94
+ const data = _interopRequireDefault(require("./exceptions/invalid-config-file"));
95
+ _invalidConfigFile = function () {
96
+ return data;
97
+ };
98
+ return data;
99
+ }
100
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
101
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
102
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
103
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
104
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
105
+ const INTERNAL_CONFIG_PROPS = ['$schema', '$schemaVersion', 'require'];
106
+ class WorkspaceConfig {
107
+ constructor(data, _path, scopePath) {
108
+ this.data = data;
109
+ this._path = _path;
110
+ this.scopePath = scopePath;
111
+ _defineProperty(this, "raw", void 0);
112
+ _defineProperty(this, "_extensions", void 0);
113
+ _defineProperty(this, "isLegacy", void 0);
114
+ this.raw = data;
115
+ this.loadExtensions();
116
+ }
117
+ get path() {
118
+ return this._path;
119
+ }
120
+ get extensions() {
121
+ return this._extensions;
122
+ }
123
+ get extensionsIds() {
124
+ return Object.keys((0, _lodash().omit)(this.raw, INTERNAL_CONFIG_PROPS));
125
+ }
126
+ loadExtensions() {
127
+ const withoutInternalConfig = (0, _lodash().omit)(this.raw, INTERNAL_CONFIG_PROPS);
128
+ this._extensions = _legacy3().ExtensionDataList.fromConfigObject(withoutInternalConfig);
129
+ }
130
+ extension(extensionId, ignoreVersion) {
131
+ const existing = this.extensions.findExtension(extensionId, ignoreVersion);
132
+ return existing?.config;
133
+ }
134
+ setExtension(extensionId, config, options) {
135
+ const existing = this.extension(extensionId, options.ignoreVersion);
136
+ if (existing) {
137
+ if (options.mergeIntoExisting) {
138
+ // Use assign from comment-json to preserve comments when merging
139
+ (0, _commentJson().assign)(this.raw[extensionId], config);
140
+ this.loadExtensions();
141
+ return;
142
+ } else if (!options.overrideExisting) {
143
+ throw new (_exceptions().ExtensionAlreadyConfigured)(extensionId);
144
+ }
145
+ }
146
+ this.raw[extensionId] = config;
147
+ this.loadExtensions();
148
+ }
149
+ renameExtensionInRaw(oldExtId, newExtId) {
150
+ let isChanged = false;
151
+ if (this.raw[oldExtId]) {
152
+ this.raw[newExtId] = this.raw[oldExtId];
153
+ delete this.raw[oldExtId];
154
+ isChanged = true;
155
+ }
156
+ const generatorEnvs = this.raw?.['teambit.generator/generator']?.envs;
157
+ if (generatorEnvs && generatorEnvs.includes(oldExtId)) {
158
+ generatorEnvs.splice(generatorEnvs.indexOf(oldExtId), 1, newExtId);
159
+ isChanged = true;
160
+ }
161
+ return isChanged;
162
+ }
163
+ removeExtension(extCompId) {
164
+ const extId = extCompId.toStringWithoutVersion();
165
+ let isChanged = false;
166
+ const existingKey = this.getExistingKeyIgnoreVersion(extCompId);
167
+ if (existingKey) {
168
+ delete this.raw[existingKey];
169
+ isChanged = true;
170
+ }
171
+ const generatorEnvs = this.raw?.['teambit.generator/generator']?.envs;
172
+ if (generatorEnvs && generatorEnvs.includes(extId)) {
173
+ generatorEnvs.splice(generatorEnvs.indexOf(extId), 1);
174
+ isChanged = true;
175
+ }
176
+ if (isChanged) this.loadExtensions();
177
+ return isChanged;
178
+ }
179
+ getExistingKeyIgnoreVersion(id) {
180
+ const idStr = id.toStringWithoutVersion();
181
+ if (this.raw[idStr]) return idStr;
182
+ const keys = Object.keys(this.raw);
183
+ return keys.find(key => key.startsWith(`${idStr}@`));
184
+ }
185
+
186
+ /**
187
+ * Create an instance of the WorkspaceConfig by data
188
+ *
189
+ * @static
190
+ * @param {WorkspaceConfigFileProps} data
191
+ * @returns
192
+ * @memberof WorkspaceConfig
193
+ */
194
+ static fromObject(data, workspaceJsoncPath, scopePath) {
195
+ return new WorkspaceConfig(data, workspaceJsoncPath, scopePath);
196
+ }
197
+
198
+ /**
199
+ * Create an instance of the WorkspaceConfig by the workspace config template and override values
200
+ *
201
+ * @static
202
+ * @param {WorkspaceConfigFileProps} data values to override in the default template
203
+ * @returns
204
+ * @memberof WorkspaceConfig
205
+ */
206
+ static async create(props, dirPath, scopePath, generator) {
207
+ const template = await getWorkspaceConfigTemplateParsed();
208
+ // previously, we just did `assign(template, props)`, but it was replacing the entire workspace config with the "props".
209
+ // so for example, if the props only had defaultScope, it was removing the defaultDirectory.
210
+ const workspaceAspectConf = (0, _commentJson().assign)(template[_workspace().WorkspaceAspect.id], props[_workspace().WorkspaceAspect.id]);
211
+
212
+ // When external package manager mode is enabled, set conflicting properties to false in the template
213
+ const depResolverConf = (0, _commentJson().assign)(template['teambit.dependencies/dependency-resolver'], props['teambit.dependencies/dependency-resolver']);
214
+ if (depResolverConf.externalPackageManager) {
215
+ // Override template defaults to be compatible with external package manager mode
216
+ template['teambit.dependencies/dependency-resolver'] = template['teambit.dependencies/dependency-resolver'] || {};
217
+ template['teambit.dependencies/dependency-resolver'].rootComponent = false;
218
+ }
219
+ const merged = (0, _commentJson().assign)(template, {
220
+ [_workspace().WorkspaceAspect.id]: workspaceAspectConf,
221
+ 'teambit.dependencies/dependency-resolver': depResolverConf
222
+ });
223
+ if (generator) {
224
+ const generators = generator.split(',').map(g => g.trim());
225
+ merged['teambit.generator/generator'] = {
226
+ envs: generators
227
+ };
228
+ }
229
+ const workspaceConfig = new WorkspaceConfig(merged, WorkspaceConfig.composeWorkspaceJsoncPath(dirPath), scopePath);
230
+
231
+ // Validate external package manager configuration
232
+ workspaceConfig.validateExternalPackageManagerConfig();
233
+ return workspaceConfig;
234
+ }
235
+
236
+ /**
237
+ * Ensure the given directory has a workspace config
238
+ * Load if existing and create new if not
239
+ *
240
+ * @static
241
+ * @param {PathOsBasedAbsolute} dirPath
242
+ * @param {WorkspaceConfigFileProps} [workspaceConfigProps={} as any]
243
+ * @returns {Promise<WorkspaceConfig>}
244
+ * @memberof WorkspaceConfig
245
+ */
246
+ static async ensure(dirPath, scopePath, workspaceConfigProps = {}, generator) {
247
+ try {
248
+ let workspaceConfig = await this.loadIfExist(dirPath, scopePath);
249
+ if (workspaceConfig) {
250
+ return workspaceConfig;
251
+ }
252
+ workspaceConfig = await this.create(workspaceConfigProps, dirPath, scopePath, generator);
253
+ return workspaceConfig;
254
+ } catch (err) {
255
+ if (err instanceof _invalidConfigFile().default) {
256
+ const workspaceConfig = this.create(workspaceConfigProps, dirPath, scopePath, generator);
257
+ return workspaceConfig;
258
+ }
259
+ throw err;
260
+ }
261
+ }
262
+ static async reset(dirPath, resetHard) {
263
+ const workspaceJsoncPath = WorkspaceConfig.composeWorkspaceJsoncPath(dirPath);
264
+ if (resetHard && workspaceJsoncPath) {
265
+ _legacy4().logger.info(`deleting the consumer workspace.jsonc file at ${workspaceJsoncPath}`);
266
+ await fs().remove(workspaceJsoncPath);
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Get the path of the workspace.jsonc file by a containing folder
272
+ *
273
+ * @static
274
+ * @param {PathOsBased} dirPath containing dir of the workspace.jsonc file
275
+ * @returns {PathOsBased}
276
+ * @memberof WorkspaceConfig
277
+ */
278
+ static composeWorkspaceJsoncPath(dirPath) {
279
+ return path().join(dirPath, _legacy().WORKSPACE_JSONC);
280
+ }
281
+ static async pathHasWorkspaceJsonc(dirPath) {
282
+ const isExist = await fs().pathExists(WorkspaceConfig.composeWorkspaceJsoncPath(dirPath));
283
+ return isExist;
284
+ }
285
+
286
+ /**
287
+ * Check if the given dir has workspace config (new or legacy)
288
+ * @param dirPath
289
+ */
290
+ static async isExist(dirPath) {
291
+ const jsoncExist = await WorkspaceConfig.pathHasWorkspaceJsonc(dirPath);
292
+ if (jsoncExist) {
293
+ return true;
294
+ }
295
+ return _legacy2().LegacyWorkspaceConfig._isExist(dirPath);
296
+ }
297
+
298
+ /**
299
+ * Load the workspace configuration if it's exist
300
+ *
301
+ * @static
302
+ * @param {PathOsBased} dirPath
303
+ * @returns {(Promise<WorkspaceConfig | undefined>)}
304
+ * @memberof WorkspaceConfig
305
+ */
306
+ static async loadIfExist(dirPath, scopePath) {
307
+ const jsoncExist = await WorkspaceConfig.pathHasWorkspaceJsonc(dirPath);
308
+ if (jsoncExist) {
309
+ const jsoncPath = WorkspaceConfig.composeWorkspaceJsoncPath(dirPath);
310
+ const instance = await WorkspaceConfig._loadFromWorkspaceJsonc(jsoncPath, scopePath);
311
+ return instance;
312
+ }
313
+ return undefined;
314
+ }
315
+ static async _loadFromWorkspaceJsonc(workspaceJsoncPath, scopePath) {
316
+ const contentBuffer = await fs().readFile(workspaceJsoncPath);
317
+ let parsed;
318
+ try {
319
+ parsed = (0, _commentJson().parse)(contentBuffer.toString());
320
+ } catch {
321
+ throw new (_invalidConfigFile().default)(workspaceJsoncPath);
322
+ }
323
+ const workspaceConfig = WorkspaceConfig.fromObject(parsed, workspaceJsoncPath, scopePath);
324
+
325
+ // Validate external package manager configuration
326
+ workspaceConfig.validateExternalPackageManagerConfig();
327
+ return workspaceConfig;
328
+ }
329
+ async write({
330
+ dir,
331
+ reasonForChange
332
+ } = {}) {
333
+ const getCalculatedDir = () => {
334
+ if (dir) return dir;
335
+ return path().dirname(this._path);
336
+ };
337
+ const calculatedDir = getCalculatedDir();
338
+ const files = await this.toVinyl(calculatedDir);
339
+ const dataToPersist = new (_component().DataToPersist)();
340
+ if (files) {
341
+ dataToPersist.addManyFiles(files);
342
+ await this.backupConfigFile(reasonForChange);
343
+ await dataToPersist.persistAllToFS();
344
+ }
345
+ }
346
+ async backupConfigFile(reasonForChange) {
347
+ if (!this.scopePath) {
348
+ _legacy4().logger.error(`unable to backup workspace.jsonc file without scope path`);
349
+ return;
350
+ }
351
+ try {
352
+ const baseDir = this.getBackupHistoryDir();
353
+ await fs().ensureDir(baseDir);
354
+ const fileId = (0, _legacy5().currentDateAndTimeToFileName)();
355
+ const backupPath = path().join(baseDir, fileId);
356
+ await fs().copyFile(this._path, backupPath);
357
+ const metadataFile = this.getBackupMetadataFilePath();
358
+ await fs().appendFile(metadataFile, `${fileId} ${reasonForChange || ''}\n`);
359
+ } catch (err) {
360
+ if (err.code === 'ENOENT') return; // no such file or directory, meaning the .bitmap file doesn't exist (yet)
361
+ // it's a nice to have feature. don't kill the process if something goes wrong.
362
+ _legacy4().logger.error(`failed to backup workspace.jsonc`, err);
363
+ }
364
+ }
365
+ getBackupDir() {
366
+ if (!this.scopePath) throw new Error('unable to get backup dir without scope path');
367
+ return path().join(this.scopePath, 'workspace-config-history');
368
+ }
369
+ getBackupHistoryDir() {
370
+ return path().join(this.getBackupDir(), 'files');
371
+ }
372
+ getBackupMetadataFilePath() {
373
+ return path().join(this.getBackupDir(), 'metadata.txt');
374
+ }
375
+ async getParsedHistoryMetadata() {
376
+ let fileContent;
377
+ try {
378
+ fileContent = await fs().readFile(this.getBackupMetadataFilePath(), 'utf-8');
379
+ } catch (err) {
380
+ if (err.code === 'ENOENT') return {}; // no such file or directory, meaning the history-metadata file doesn't exist (yet)
381
+ }
382
+ const lines = fileContent?.split('\n') || [];
383
+ const metadata = {};
384
+ lines.forEach(line => {
385
+ const [fileId, ...reason] = line.split(' ');
386
+ if (!fileId) return;
387
+ metadata[fileId] = reason.join(' ');
388
+ });
389
+ return metadata;
390
+ }
391
+ async toVinyl(workspaceDir) {
392
+ const jsonStr = `${(0, _commentJson().stringify)(this.data, undefined, 2)}\n`;
393
+ const base = workspaceDir;
394
+ const fullPath = workspaceDir ? WorkspaceConfig.composeWorkspaceJsoncPath(workspaceDir) : this.path;
395
+ const jsonFile = new (_component().AbstractVinyl)({
396
+ base,
397
+ path: fullPath,
398
+ contents: Buffer.from(jsonStr)
399
+ });
400
+ return [jsonFile];
401
+ }
402
+ toLegacy() {
403
+ let componentsDefaultDirectory = this.extension('teambit.workspace/workspace', true)?.defaultDirectory;
404
+ if (componentsDefaultDirectory && !componentsDefaultDirectory.includes('{name}')) {
405
+ componentsDefaultDirectory = `${componentsDefaultDirectory}/{name}`;
406
+ }
407
+ return {
408
+ lang: _legacy().DEFAULT_LANGUAGE,
409
+ defaultScope: this.extension('teambit.workspace/workspace', true)?.defaultScope,
410
+ _useWorkspaces: this.extension('teambit.dependencies/dependency-resolver', true)?.useWorkspaces,
411
+ dependencyResolver: this.extension('teambit.dependencies/dependency-resolver', true),
412
+ packageManager: this.extension('teambit.dependencies/dependency-resolver', true)?.packageManager,
413
+ componentsDefaultDirectory,
414
+ _manageWorkspaces: this.extension('teambit.dependencies/dependency-resolver', true)?.manageWorkspaces,
415
+ extensions: this.extensions.toConfigObject(),
416
+ // @ts-ignore
417
+ path: this.path,
418
+ isLegacy: false,
419
+ write: ({
420
+ workspaceDir
421
+ }) => this.write.call(this, {
422
+ dir: workspaceDir
423
+ }),
424
+ toVinyl: this.toVinyl.bind(this),
425
+ _legacyPlainObject: () => undefined
426
+ };
427
+ }
428
+
429
+ /**
430
+ * Validates that external package manager configuration is compatible with other settings
431
+ */
432
+ validateExternalPackageManagerConfig() {
433
+ const depResolverExt = this.extension('teambit.dependencies/dependency-resolver', true);
434
+ if (!depResolverExt?.externalPackageManager) {
435
+ return; // No validation needed if external package manager is not enabled
436
+ }
437
+ const conflicts = [];
438
+
439
+ // Check dependency-resolver aspect conflicts
440
+ if (depResolverExt?.rootComponent === true) {
441
+ conflicts.push('rootComponent cannot be true when externalPackageManager is enabled');
442
+ }
443
+ if (conflicts.length > 0) {
444
+ throw new Error(`External package manager mode is incompatible with the following settings:\n${conflicts.map(c => ` - ${c}`).join('\n')}\n\nPlease set these properties to false or remove them from your workspace.jsonc`);
445
+ }
446
+ }
447
+ }
448
+ exports.WorkspaceConfig = WorkspaceConfig;
449
+ async function getWorkspaceConfigTemplateParsed() {
450
+ let fileContent;
451
+ try {
452
+ fileContent = await fs().readFile(path().join(__dirname, 'workspace-template.jsonc'));
453
+ } catch (err) {
454
+ if (err.code !== 'ENOENT') throw err;
455
+ // when the extension is compiled by tsc, it doesn't copy .jsonc files into the dists, grab it from src
456
+ fileContent = await fs().readFile(path().join(__dirname, '..', 'workspace-template.jsonc'));
457
+ }
458
+ return (0, _commentJson().parse)(fileContent.toString());
459
+ }
460
+ function stringifyWorkspaceConfig(workspaceConfig) {
461
+ return (0, _commentJson().stringify)(workspaceConfig, undefined, 2);
462
+ }
463
+
464
+ //# sourceMappingURL=workspace-config.js.map