Skip to content

Commit 5ebacd3

Browse files
authored
Resolve configuration file against the current working directory (#146)
1 parent 270f041 commit 5ebacd3

3 files changed

Lines changed: 127 additions & 8 deletions

File tree

‎src/application/project/configuration/manager/jsonConfigurationFileManager.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export class JsonConfigurationFileManager implements ConfigurationManager {
3939

4040
private readonly fileSystem: FileSystem;
4141

42+
private readonly projectDirectory: WorkingDirectory;
43+
4244
private readonly fullValidator: Validator<ProjectConfiguration>;
4345

4446
private readonly partialValidator: Validator<PartialProjectConfiguration>;
@@ -47,14 +49,15 @@ export class JsonConfigurationFileManager implements ConfigurationManager {
4749

4850
public constructor(configuration: Configuration) {
4951
this.fileSystem = configuration.fileSystem;
52+
this.projectDirectory = configuration.projectDirectory;
5053
this.fullValidator = configuration.fullValidator;
5154
this.partialValidator = configuration.partialValidator;
5255
this.configurationFile = configuration.configurationFile;
5356
}
5457

5558
public async isInitialized(state: InitializationState = InitializationState.ANY): Promise<boolean> {
5659
if (state === InitializationState.ANY) {
57-
return this.fileSystem.exists(this.configurationFile);
60+
return this.fileSystem.exists(this.getConfigurationFilePath());
5861
}
5962

6063
const validator = state === InitializationState.FULL
@@ -159,7 +162,7 @@ export class JsonConfigurationFileManager implements ConfigurationManager {
159162
validator: Validator<T>,
160163
): Promise<LoadedFile<Omit<T, '$schema'>>> {
161164
const file: LoadedFile<T> = {
162-
path: this.configurationFile,
165+
path: this.getConfigurationFilePath(),
163166
source: null,
164167
configuration: null,
165168
};
@@ -184,6 +187,12 @@ export class JsonConfigurationFileManager implements ConfigurationManager {
184187
return file;
185188
}
186189

190+
private getConfigurationFilePath(): string {
191+
return this.fileSystem.isAbsolutePath(this.configurationFile)
192+
? this.configurationFile
193+
: this.fileSystem.joinPaths(this.projectDirectory.get(), this.configurationFile);
194+
}
195+
187196
private async validateConfiguration<T extends JsonPartialProjectConfiguration>(
188197
validator: Validator<T>,
189198
value: JsonValue,

‎src/infrastructure/application/cli/cli.ts‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,12 +2818,7 @@ export class Cli {
28182818
fullValidator: new FullCroctConfigurationValidator(),
28192819
partialValidator: new PartialCroctConfigurationValidator(),
28202820
projectDirectory: this.workingDirectory,
2821-
configurationFile: fileSystem.isAbsolutePath(this.configuration.configurationFile)
2822-
? this.configuration.configurationFile
2823-
: fileSystem.joinPaths(
2824-
this.workingDirectory.get(),
2825-
this.configuration.configurationFile,
2826-
),
2821+
configurationFile: this.configuration.configurationFile,
28272822
});
28282823

28292824
return new IndexedConfigurationManager({
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import type {FileSystem} from '@/application/fs/fileSystem';
2+
import type {Validator, ValidationResult} from '@/application/validation';
3+
import {VirtualizedWorkingDirectory} from '@/application/fs/workingDirectory/virtualizedWorkingDirectory';
4+
import type {
5+
JsonProjectConfiguration,
6+
JsonPartialProjectConfiguration,
7+
} from '@/application/project/configuration/manager/jsonConfigurationFileManager';
8+
import {JsonConfigurationFileManager} from '@/application/project/configuration/manager/jsonConfigurationFileManager';
9+
import type {ProjectConfiguration} from '@/application/project/configuration/projectConfiguration';
10+
11+
describe('JsonConfigurationFileManager', () => {
12+
const configuration: ProjectConfiguration = {
13+
organization: 'org',
14+
workspace: 'workspace',
15+
applications: {
16+
development: 'dev',
17+
},
18+
defaultLocale: 'en',
19+
locales: ['en'],
20+
slots: {},
21+
components: {},
22+
};
23+
24+
function createFileSystem(files: Map<string, string>): FileSystem {
25+
return {
26+
exists: (path: string): Promise<boolean> => Promise.resolve(files.has(path)),
27+
readTextFile: (path: string): Promise<string> => {
28+
const content = files.get(path);
29+
30+
if (content === undefined) {
31+
return Promise.reject(new Error(`File not found: ${path}`));
32+
}
33+
34+
return Promise.resolve(content);
35+
},
36+
writeTextFile: (path: string, content: string): Promise<void> => {
37+
files.set(path, content);
38+
39+
return Promise.resolve();
40+
},
41+
isAbsolutePath: (path: string): boolean => path.startsWith('/'),
42+
joinPaths: (...paths: string[]): string => paths.join('/'),
43+
} as Partial<FileSystem> as FileSystem;
44+
}
45+
46+
function createValidator<T>(): Validator<T> {
47+
return {
48+
validate: (data: unknown): ValidationResult<T> => ({
49+
valid: true,
50+
data: data as T,
51+
}),
52+
};
53+
}
54+
55+
it('should resolve the configuration file against the current project directory', async () => {
56+
const files = new Map<string, string>();
57+
const projectDirectory = new VirtualizedWorkingDirectory('/initial');
58+
59+
const manager = new JsonConfigurationFileManager({
60+
fileSystem: createFileSystem(files),
61+
projectDirectory: projectDirectory,
62+
fullValidator: createValidator<JsonProjectConfiguration>(),
63+
partialValidator: createValidator<JsonPartialProjectConfiguration>(),
64+
configurationFile: 'croct.json',
65+
});
66+
67+
projectDirectory.setCurrentDirectory('/initial/project');
68+
69+
await manager.update(configuration);
70+
71+
expect(files.has('/initial/croct.json')).toBe(false);
72+
expect(files.has('/initial/project/croct.json')).toBe(true);
73+
});
74+
75+
it('should load the configuration from the current project directory', async () => {
76+
const files = new Map<string, string>();
77+
const projectDirectory = new VirtualizedWorkingDirectory('/initial');
78+
79+
const manager = new JsonConfigurationFileManager({
80+
fileSystem: createFileSystem(files),
81+
projectDirectory: projectDirectory,
82+
fullValidator: createValidator<JsonProjectConfiguration>(),
83+
partialValidator: createValidator<JsonPartialProjectConfiguration>(),
84+
configurationFile: 'croct.json',
85+
});
86+
87+
files.set('/initial/project/croct.json', JSON.stringify(configuration));
88+
89+
await expect(manager.isInitialized()).resolves.toBe(false);
90+
91+
projectDirectory.setCurrentDirectory('/initial/project');
92+
93+
await expect(manager.isInitialized()).resolves.toBe(true);
94+
await expect(manager.load()).resolves.toEqual(configuration);
95+
});
96+
97+
it('should use an absolute configuration file path as given', async () => {
98+
const files = new Map<string, string>();
99+
const projectDirectory = new VirtualizedWorkingDirectory('/initial');
100+
101+
const manager = new JsonConfigurationFileManager({
102+
fileSystem: createFileSystem(files),
103+
projectDirectory: projectDirectory,
104+
fullValidator: createValidator<JsonProjectConfiguration>(),
105+
partialValidator: createValidator<JsonPartialProjectConfiguration>(),
106+
configurationFile: '/custom/croct.json',
107+
});
108+
109+
projectDirectory.setCurrentDirectory('/initial/project');
110+
111+
await manager.update(configuration);
112+
113+
expect(files.has('/custom/croct.json')).toBe(true);
114+
});
115+
});

0 commit comments

Comments
 (0)