@teambit/config 0.0.397 → 0.0.398

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.
@@ -1,486 +0,0 @@
1
- import { Analytics } from '@teambit/legacy/dist/analytics/analytics';
2
- import { isLegacyEnabled } from '@teambit/legacy/dist/api/consumer/lib/feature-toggle';
3
- import { COMPILER_ENV_TYPE, DEFAULT_LANGUAGE, WORKSPACE_JSONC } from '@teambit/legacy/dist/constants';
4
- import { ResolveModulesConfig } from '@teambit/legacy/dist/consumer/component/dependencies/files-dependency-builder/types/dependency-tree-type';
5
- import { AbstractVinyl } from '@teambit/legacy/dist/consumer/component/sources';
6
- import DataToPersist from '@teambit/legacy/dist/consumer/component/sources/data-to-persist';
7
- import { ExtensionDataList, ILegacyWorkspaceConfig } from '@teambit/legacy/dist/consumer/config';
8
- import { Compilers, Testers } from '@teambit/legacy/dist/consumer/config/abstract-config';
9
- import { InvalidBitJson } from '@teambit/legacy/dist/consumer/config/exceptions';
10
- import LegacyWorkspaceConfig, {
11
- WorkspaceConfigProps as LegacyWorkspaceConfigProps,
12
- } from '@teambit/legacy/dist/consumer/config/workspace-config';
13
- import { EnvType } from '@teambit/legacy/dist/legacy-extensions/env-extension-types';
14
- import logger from '@teambit/legacy/dist/logger/logger';
15
- import { PathOsBased, PathOsBasedAbsolute } from '@teambit/legacy/dist/utils/path';
16
- import { assign, parse, stringify, CommentJSONValue } from 'comment-json';
17
- import * as fs from 'fs-extra';
18
- import * as path from 'path';
19
- import { isEmpty, omit } from 'lodash';
20
-
21
- import { SetExtensionOptions } from './config';
22
- import { ExtensionAlreadyConfigured } from './exceptions';
23
- import { ConfigDirNotDefined } from './exceptions/config-dir-not-defined';
24
- import InvalidConfigFile from './exceptions/invalid-config-file';
25
- import { HostConfig } from './types';
26
-
27
- const INTERNAL_CONFIG_PROPS = ['$schema', '$schemaVersion'];
28
-
29
- export type LegacyInitProps = {
30
- standAlone?: boolean;
31
- };
32
-
33
- export type WorkspaceConfigFileProps = {
34
- // TODO: make it no optional
35
- $schema?: string;
36
- $schemaVersion?: string;
37
- } & ExtensionsDefs;
38
-
39
- export type ComponentScopeDirMapEntry = {
40
- defaultScope?: string;
41
- directory: string;
42
- };
43
-
44
- export type ComponentScopeDirMap = Array<ComponentScopeDirMapEntry>;
45
-
46
- export type WorkspaceExtensionProps = {
47
- defaultOwner?: string;
48
- defaultScope?: string;
49
- defaultDirectory?: string;
50
- components?: ComponentScopeDirMap;
51
- };
52
-
53
- export type PackageManagerClients = 'npm' | 'yarn' | undefined;
54
-
55
- export interface DependencyResolverExtensionProps {
56
- packageManager: PackageManagerClients;
57
- strictPeerDependencies?: boolean;
58
- extraArgs?: string[];
59
- packageManagerProcessOptions?: any;
60
- useWorkspaces?: boolean;
61
- manageWorkspaces?: boolean;
62
- }
63
-
64
- export type WorkspaceSettingsNewProps = {
65
- 'teambit.workspace/workspace': WorkspaceExtensionProps;
66
- 'teambit.dependencies/dependency-resolver': DependencyResolverExtensionProps;
67
- };
68
-
69
- export type WorkspaceLegacyProps = {
70
- dependenciesDirectory?: string;
71
- bindingPrefix?: string;
72
- resolveModules?: ResolveModulesConfig;
73
- saveDependenciesAsComponents?: boolean;
74
- distEntry?: string;
75
- distTarget?: string;
76
- };
77
-
78
- export type ExtensionsDefs = WorkspaceSettingsNewProps;
79
-
80
- export class WorkspaceConfig implements HostConfig {
81
- raw?: any;
82
- _path?: string;
83
- _extensions: ExtensionDataList;
84
- _legacyProps?: WorkspaceLegacyProps;
85
- isLegacy: boolean;
86
-
87
- constructor(private data?: WorkspaceConfigFileProps, private legacyConfig?: LegacyWorkspaceConfig) {
88
- this.isLegacy = Boolean(isLegacyEnabled() || legacyConfig);
89
- const isHarmony = !this.isLegacy;
90
- logger.debug(`workspace-config, isLegacy: ${this.isLegacy}`);
91
- Analytics.setExtraData('is_harmony', isHarmony);
92
- if (isHarmony) {
93
- this.raw = data;
94
- this.loadExtensions();
95
- } else {
96
- // We know we have either data or legacy config
97
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
98
- this._extensions = ExtensionDataList.fromConfigObject(transformLegacyPropsToExtensions(legacyConfig!));
99
- if (legacyConfig) {
100
- this._legacyProps = {
101
- dependenciesDirectory: legacyConfig.dependenciesDirectory,
102
- resolveModules: legacyConfig.resolveModules,
103
- saveDependenciesAsComponents: legacyConfig.saveDependenciesAsComponents,
104
- distEntry: legacyConfig.distEntry,
105
- distTarget: legacyConfig.distTarget,
106
- };
107
- }
108
- }
109
- }
110
-
111
- get path(): PathOsBased {
112
- return this._path || this.legacyConfig?.path || '';
113
- }
114
-
115
- set path(configPath: PathOsBased) {
116
- this._path = configPath;
117
- }
118
-
119
- get extensions(): ExtensionDataList {
120
- return this._extensions;
121
- }
122
-
123
- private loadExtensions() {
124
- const withoutInternalConfig = omit(this.raw, INTERNAL_CONFIG_PROPS);
125
- this._extensions = ExtensionDataList.fromConfigObject(withoutInternalConfig);
126
- }
127
-
128
- extension(extensionId: string, ignoreVersion: boolean): any {
129
- const existing = this.extensions.findExtension(extensionId, ignoreVersion);
130
- return existing?.config;
131
- }
132
-
133
- setExtension(extensionId: string, config: Record<string, any>, options: SetExtensionOptions): any {
134
- const existing = this.extension(extensionId, options.ignoreVersion);
135
- if (existing && !options.overrideExisting) {
136
- throw new ExtensionAlreadyConfigured(extensionId);
137
- }
138
- this.raw[extensionId] = config;
139
- this.loadExtensions();
140
- }
141
-
142
- /**
143
- * Create an instance of the WorkspaceConfig by an instance of the legacy config
144
- *
145
- * @static
146
- * @param {*} legacyConfig
147
- * @returns
148
- * @memberof WorkspaceConfig
149
- */
150
- static fromLegacyConfig(legacyConfig) {
151
- return new WorkspaceConfig(undefined, legacyConfig);
152
- }
153
-
154
- /**
155
- * Create an instance of the WorkspaceConfig by data
156
- *
157
- * @static
158
- * @param {WorkspaceConfigFileProps} data
159
- * @returns
160
- * @memberof WorkspaceConfig
161
- */
162
- static fromObject(data: WorkspaceConfigFileProps) {
163
- return new WorkspaceConfig(data, undefined);
164
- }
165
-
166
- /**
167
- * Create an instance of the WorkspaceConfig by the workspace config template and override values
168
- *
169
- * @static
170
- * @param {WorkspaceConfigFileProps} data values to override in the default template
171
- * @returns
172
- * @memberof WorkspaceConfig
173
- */
174
- static async create(
175
- props: WorkspaceConfigFileProps,
176
- dirPath?: PathOsBasedAbsolute,
177
- legacyInitProps?: LegacyInitProps
178
- ) {
179
- if (isLegacyEnabled() && dirPath) {
180
- if (!dirPath) throw new Error('workspace-config, dirPath is missing');
181
- // Only support here what needed for e2e tests
182
- const legacyProps: LegacyWorkspaceConfigProps = {};
183
- if (props['teambit.dependencies/dependency-resolver']) {
184
- legacyProps.packageManager = props['teambit.dependencies/dependency-resolver'].packageManager;
185
- }
186
- if (props['teambit.workspace/workspace']) {
187
- legacyProps.componentsDefaultDirectory = props['teambit.workspace/workspace'].defaultDirectory;
188
- }
189
-
190
- const standAlone = legacyInitProps?.standAlone ?? false;
191
- const legacyConfig = await LegacyWorkspaceConfig._ensure(dirPath, standAlone, legacyProps);
192
- const instance = WorkspaceConfig.fromLegacyConfig(legacyConfig);
193
- return instance;
194
- }
195
-
196
- const template = await getWorkspaceConfigTemplateParsed();
197
- // TODO: replace this assign with some kind of deepAssign that keeps the comments
198
- // right now the comments above the internal props are overrides after the assign
199
- const merged = assign(template, props);
200
- const instance = new WorkspaceConfig(merged, undefined);
201
- if (dirPath) {
202
- instance.path = WorkspaceConfig.composeWorkspaceJsoncPath(dirPath);
203
- }
204
- return instance;
205
- }
206
-
207
- /**
208
- * Ensure the given directory has a workspace config
209
- * Load if existing and create new if not
210
- *
211
- * @static
212
- * @param {PathOsBasedAbsolute} dirPath
213
- * @param {WorkspaceConfigFileProps} [workspaceConfigProps={} as any]
214
- * @returns {Promise<WorkspaceConfig>}
215
- * @memberof WorkspaceConfig
216
- */
217
- static async ensure(
218
- dirPath: PathOsBasedAbsolute,
219
- workspaceConfigProps: WorkspaceConfigFileProps = {} as any,
220
- legacyInitProps?: LegacyInitProps
221
- ): Promise<WorkspaceConfig> {
222
- try {
223
- let workspaceConfig = await this.loadIfExist(dirPath);
224
- if (workspaceConfig) {
225
- return workspaceConfig;
226
- }
227
- workspaceConfig = await this.create(workspaceConfigProps, dirPath, legacyInitProps);
228
- return workspaceConfig;
229
- } catch (err: any) {
230
- if (err instanceof InvalidBitJson || err instanceof InvalidConfigFile) {
231
- const workspaceConfig = this.create(workspaceConfigProps, dirPath);
232
- return workspaceConfig;
233
- }
234
- throw err;
235
- }
236
- }
237
-
238
- /**
239
- * A function that register to the legacy ensure function in order to transform old props structure
240
- * to the new one
241
- * @param dirPath
242
- * @param standAlone
243
- * @param legacyWorkspaceConfigProps
244
- */
245
- static async onLegacyEnsure(
246
- dirPath: PathOsBasedAbsolute,
247
- standAlone: boolean,
248
- legacyWorkspaceConfigProps: LegacyWorkspaceConfigProps = {} as any
249
- ): Promise<WorkspaceConfig> {
250
- const newProps: WorkspaceConfigFileProps = transformLegacyPropsToExtensions(legacyWorkspaceConfigProps);
251
- // TODO: gilad move to constants file
252
- newProps.$schemaVersion = '1.0.0';
253
- return WorkspaceConfig.ensure(dirPath, newProps, { standAlone });
254
- }
255
-
256
- static async reset(dirPath: PathOsBasedAbsolute, resetHard: boolean): Promise<void> {
257
- const workspaceJsoncPath = WorkspaceConfig.composeWorkspaceJsoncPath(dirPath);
258
- if (resetHard) {
259
- // Call the legacy reset hard to make sure there is no old bit.json kept
260
- await LegacyWorkspaceConfig.reset(dirPath, true);
261
- if (workspaceJsoncPath) {
262
- logger.info(`deleting the consumer bit.jsonc file at ${workspaceJsoncPath}`);
263
- await fs.remove(workspaceJsoncPath);
264
- }
265
- }
266
- }
267
-
268
- /**
269
- * Get the path of the bit.jsonc file by a containing folder
270
- *
271
- * @static
272
- * @param {PathOsBased} dirPath containing dir of the bit.jsonc file
273
- * @returns {PathOsBased}
274
- * @memberof WorkspaceConfig
275
- */
276
- static composeWorkspaceJsoncPath(dirPath: PathOsBased): PathOsBased {
277
- return path.join(dirPath, WORKSPACE_JSONC);
278
- }
279
-
280
- static async pathHasWorkspaceJsonc(dirPath: PathOsBased): Promise<boolean> {
281
- const isExist = await fs.pathExists(WorkspaceConfig.composeWorkspaceJsoncPath(dirPath));
282
- return isExist;
283
- }
284
-
285
- /**
286
- * Check if the given dir has workspace config (new or legacy)
287
- * @param dirPath
288
- */
289
- static async isExist(dirPath: PathOsBased): Promise<boolean | undefined> {
290
- const jsoncExist = await WorkspaceConfig.pathHasWorkspaceJsonc(dirPath);
291
- if (jsoncExist) {
292
- return true;
293
- }
294
- return LegacyWorkspaceConfig._isExist(dirPath);
295
- }
296
-
297
- /**
298
- * Load the workspace configuration if it's exist
299
- *
300
- * @static
301
- * @param {PathOsBased} dirPath
302
- * @returns {(Promise<WorkspaceConfig | undefined>)}
303
- * @memberof WorkspaceConfig
304
- */
305
- static async loadIfExist(dirPath: PathOsBased): Promise<WorkspaceConfig | undefined> {
306
- const jsoncExist = await WorkspaceConfig.pathHasWorkspaceJsonc(dirPath);
307
- if (jsoncExist) {
308
- const jsoncPath = WorkspaceConfig.composeWorkspaceJsoncPath(dirPath);
309
- const instance = await WorkspaceConfig._loadFromWorkspaceJsonc(jsoncPath);
310
- instance.path = jsoncPath;
311
- return instance;
312
- }
313
- const legacyConfig = await LegacyWorkspaceConfig._loadIfExist(dirPath);
314
- if (legacyConfig) {
315
- return WorkspaceConfig.fromLegacyConfig(legacyConfig);
316
- }
317
- return undefined;
318
- }
319
-
320
- static async _loadFromWorkspaceJsonc(workspaceJsoncPath: PathOsBased): Promise<WorkspaceConfig> {
321
- const contentBuffer = await fs.readFile(workspaceJsoncPath);
322
- let parsed;
323
- try {
324
- parsed = parse(contentBuffer.toString());
325
- } catch (e: any) {
326
- throw new InvalidConfigFile(workspaceJsoncPath);
327
- }
328
- return WorkspaceConfig.fromObject(parsed);
329
- }
330
-
331
- async write({ dir }: { dir?: PathOsBasedAbsolute }): Promise<void> {
332
- const calculatedDir = dir || this._path;
333
- if (!calculatedDir) {
334
- throw new ConfigDirNotDefined();
335
- }
336
- if (this.data) {
337
- const files = await this.toVinyl(calculatedDir);
338
- const dataToPersist = new DataToPersist();
339
- if (files) {
340
- dataToPersist.addManyFiles(files);
341
- return dataToPersist.persistAllToFS();
342
- }
343
- }
344
- await this.legacyConfig?.write({ workspaceDir: calculatedDir });
345
- return undefined;
346
- }
347
-
348
- async toVinyl(workspaceDir: PathOsBasedAbsolute): Promise<AbstractVinyl[] | undefined> {
349
- if (this.data) {
350
- const jsonStr = stringify(this.data, undefined, 2);
351
- const base = workspaceDir;
352
- const fullPath = workspaceDir ? WorkspaceConfig.composeWorkspaceJsoncPath(workspaceDir) : this.path;
353
- const jsonFile = new AbstractVinyl({ base, path: fullPath, contents: Buffer.from(jsonStr) });
354
- return [jsonFile];
355
- }
356
- return this.legacyConfig?.toVinyl({ workspaceDir });
357
- }
358
-
359
- _legacyPlainObject(): { [prop: string]: any } | undefined {
360
- if (this.legacyConfig) {
361
- return this.legacyConfig.toPlainObject();
362
- }
363
- return undefined;
364
- }
365
-
366
- toLegacy(): ILegacyWorkspaceConfig {
367
- const _setCompiler = (compiler) => {
368
- if (this.legacyConfig) {
369
- this.legacyConfig.setCompiler(compiler);
370
- }
371
- };
372
-
373
- const _setTester = (tester) => {
374
- if (this.legacyConfig) {
375
- this.legacyConfig.setTester(tester);
376
- }
377
- };
378
-
379
- const _getEnvsByType = (type: EnvType): Compilers | Testers | undefined => {
380
- if (type === COMPILER_ENV_TYPE) {
381
- return this.legacyConfig?.compiler;
382
- }
383
- return this.legacyConfig?.tester;
384
- };
385
-
386
- let componentsDefaultDirectory = this.extension('teambit.workspace/workspace', true)?.defaultDirectory;
387
- if (componentsDefaultDirectory && !componentsDefaultDirectory.includes('{name}')) {
388
- componentsDefaultDirectory = `${componentsDefaultDirectory}/{name}`;
389
- }
390
-
391
- return {
392
- lang: this.legacyConfig?.lang || DEFAULT_LANGUAGE,
393
- defaultScope: this.extension('teambit.workspace/workspace', true)?.defaultScope,
394
- _useWorkspaces: this.extension('teambit.dependencies/dependency-resolver', true)?.useWorkspaces,
395
- dependencyResolver: this.extension('teambit.dependencies/dependency-resolver', true),
396
- packageManager: this.extension('teambit.dependencies/dependency-resolver', true)?.packageManager,
397
- _bindingPrefix: this.extension('teambit.workspace/workspace', true)?.defaultOwner,
398
- _distEntry: this._legacyProps?.distEntry,
399
- _distTarget: this._legacyProps?.distTarget,
400
- _saveDependenciesAsComponents: this._legacyProps?.saveDependenciesAsComponents,
401
- _dependenciesDirectory: this._legacyProps?.dependenciesDirectory,
402
- componentsDefaultDirectory,
403
- _resolveModules: this._legacyProps?.resolveModules,
404
- _manageWorkspaces: this.extension('teambit.dependencies/dependency-resolver', true)?.manageWorkspaces,
405
- defaultOwner: this.extension('teambit.workspace/workspace', true)?.defaultOwner,
406
- extensions: this.extensions.toConfigObject(),
407
- // @ts-ignore
408
- path: this.path,
409
- _getEnvsByType,
410
- isLegacy: this.isLegacy,
411
- write: ({ workspaceDir }) => this.write.call(this, { dir: workspaceDir }),
412
- toVinyl: this.toVinyl.bind(this),
413
- componentsConfig: this.legacyConfig ? this.legacyConfig?.overrides : undefined,
414
- getComponentConfig: this.legacyConfig
415
- ? this.legacyConfig?.overrides.getOverrideComponentData.bind(this.legacyConfig?.overrides)
416
- : () => undefined,
417
- _legacyPlainObject: this.legacyConfig
418
- ? this.legacyConfig?.toPlainObject.bind(this.legacyConfig)
419
- : () => undefined,
420
- _compiler: this.legacyConfig?.compiler,
421
- _setCompiler,
422
- _tester: this.legacyConfig?.tester,
423
- _setTester,
424
- };
425
- }
426
- }
427
-
428
- export function transformLegacyPropsToExtensions(
429
- legacyConfig: LegacyWorkspaceConfig | LegacyWorkspaceConfigProps
430
- ): ExtensionsDefs {
431
- // TODO: move to utils
432
- const removeUndefined = (obj) => {
433
- // const res = omit(mapObjIndexed((val) => val === undefined))(obj);
434
- // return res;
435
- Object.entries(obj).forEach((e) => {
436
- if (e[1] === undefined) delete obj[e[0]];
437
- });
438
- return obj;
439
- };
440
-
441
- const workspace = removeUndefined({
442
- defaultScope: legacyConfig.defaultScope,
443
- defaultDirectory: legacyConfig.componentsDefaultDirectory,
444
- defaultOwner: legacyConfig.bindingPrefix,
445
- });
446
- const dependencyResolver = removeUndefined({
447
- packageManager: legacyConfig.packageManager,
448
- // strictPeerDependencies: false,
449
- extraArgs: legacyConfig.packageManagerArgs,
450
- packageManagerProcessOptions: legacyConfig.packageManagerProcessOptions,
451
- manageWorkspaces: legacyConfig.manageWorkspaces,
452
- useWorkspaces: legacyConfig.useWorkspaces,
453
- });
454
- const variants = legacyConfig.overrides?.overrides;
455
- const data = {};
456
- if (workspace && !isEmpty(workspace)) {
457
- data['teambit.workspace/workspace'] = workspace;
458
- }
459
- if (dependencyResolver && !isEmpty(dependencyResolver)) {
460
- data['teambit.dependencies/dependency-resolver'] = dependencyResolver;
461
- }
462
- // TODO: add variants here once we have a way to pass the deps overrides and general key vals for package.json to
463
- // TODO: new extensions (via dependency-resolver extension and pkg extensions)
464
- // TODO: transform legacy props to new one once dependency-resolver extension and pkg extensions are ready
465
- if (variants && !isEmpty(variants)) {
466
- data['teambit.workspace/variants'] = variants;
467
- }
468
- // @ts-ignore
469
- return data;
470
- }
471
-
472
- export async function getWorkspaceConfigTemplateParsed(): Promise<CommentJSONValue> {
473
- let fileContent: Buffer;
474
- try {
475
- fileContent = await fs.readFile(path.join(__dirname, 'workspace-template.jsonc'));
476
- } catch (err: any) {
477
- if (err.code !== 'ENOENT') throw err;
478
- // when the extension is compiled by tsc, it doesn't copy .jsonc files into the dists, grab it from src
479
- fileContent = await fs.readFile(path.join(__dirname, '..', 'workspace-template.jsonc'));
480
- }
481
- return parse(fileContent.toString());
482
- }
483
-
484
- export function stringifyWorkspaceConfig(workspaceConfig: CommentJSONValue): string {
485
- return stringify(workspaceConfig, undefined, 2);
486
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * this is the main configuration file of your bit workspace.
3
- * for full documentation, please see: https://harmony-docs.bit.dev/workspace/configurations
4
- **/
5
- {
6
- "$schema": "https://static.bit.dev/teambit/schemas/schema.json",
7
-
8
- /**
9
- * main configuration of the Bit workspace.
10
- **/
11
- "teambit.workspace/workspace": {
12
- /**
13
- * the name of the component workspace. used for development purposes.
14
- **/
15
- "name": "my-workspace-name",
16
-
17
- /**
18
- * set the icon to be shown on the Bit server.
19
- **/
20
- "icon": "https://static.bit.dev/bit-logo.svg",
21
-
22
- /**
23
- * default directory to place a component during `bit import` and `bit create`.
24
- * the following placeholders are available:
25
- * name - component name includes namespace, e.g. 'ui/button'.
26
- * scopeId - full scope-id includes the owner, e.g. 'teambit.compilation'.
27
- * scope - scope name only, e.g. 'compilation'.
28
- * owner - owner name in bit.dev, e.g. 'teambit'.
29
- **/
30
- "defaultDirectory": "{scope}/{name}",
31
-
32
- /**
33
- * default scope for all components in workspace.
34
- **/
35
- "defaultScope": "my-scope"
36
- },
37
-
38
- /**
39
- * main configuration for component dependency resolution.
40
- **/
41
- "teambit.dependencies/dependency-resolver": {
42
- /**
43
- * choose the package manager for Bit to use. you can choose between 'yarn', 'pnpm'
44
- */
45
- "packageManager": "teambit.dependencies/pnpm",
46
- "policy": {
47
- "dependencies": {},
48
- "peerDependencies": {}
49
- }
50
- },
51
-
52
- /**
53
- * workspace variants allow to set different subsets of configuration for components in your
54
- * workspace. this is extremely useful for upgrading, aligning and building components with a new
55
- * set of dependencies. a rule can be a directory or a component-id/namespace, in which case,
56
- * wrap the rule with curly brackets (e.g. `"{ui/*}": {}`)
57
- * see https://harmony-docs.bit.dev/aspects/variants for more info.
58
- **/
59
- "teambit.workspace/variants": {
60
- /**
61
- * "*" is a special rule which applied on all components in the workspace.
62
- **/
63
- "*": {
64
- /**
65
- * uncomment to apply the chosen environment on all components.
66
- **/
67
- // "teambit.react/react": { }
68
- }
69
- }
70
- }