Skip to content

Commit 8ffa49a

Browse files
committed
feat: Refactored resolver to be completely separate from the parser
1 parent 2dc4c84 commit 8ffa49a

File tree

15 files changed

+239
-42
lines changed

15 files changed

+239
-42
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/common/initialize-plugins.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { CODIFY_FILE_REGEX, CodifyParser } from '../parser/index.js';
1111
import { PluginManager, ResourceDefinitionMap } from '../plugins/plugin-manager.js';
1212
import { Reporter } from '../ui/reporters/reporter.js';
1313
import { FileUtils } from '../utils/file.js';
14+
import { CodifyResolver } from '../resolver/index.js';
1415

1516
export interface InitializeArgs {
1617
path?: string;
@@ -60,11 +61,18 @@ export class PluginInitOrchestrator {
6061
return CodifyParser.parseJson(args.codifyConfigs);
6162
}
6263

63-
const codifyPath = await PluginInitOrchestrator.resolveCodify(args, reporter);
64+
ctx.subprocessStarted(SubProcessName.RESOLVE);
65+
66+
const codifyFile = await CodifyResolver.resolveFile(args.path ?? process.cwd(), {
67+
allowTemplates: args.allowTemplates,
68+
reporter,
69+
});
70+
71+
ctx.subprocessFinished(SubProcessName.RESOLVE);
6472
ctx.subprocessStarted(SubProcessName.PARSE);
6573

66-
const project = codifyPath
67-
? await CodifyParser.parse(codifyPath)
74+
const project = codifyFile
75+
? await CodifyParser.parse(codifyFile)
6876
: Project.empty()
6977

7078
ctx.subprocessFinished(SubProcessName.PARSE);

src/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ export const config = {
1414
supabaseUrl: 'https://kdctbvqvqjfquplxhqrm.supabase.co',
1515

1616
isBeta: VERSION.includes('beta'),
17+
18+
fileRegex: /^(.*)?codify(.*)?(.json|.yaml|.json5|.jsonc)$/,
1719
}

src/events/context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export enum SubProcessName {
3535
APPLYING_RESOURCE = 'apply_resource',
3636
GENERATE_PLAN = 'generate_plan',
3737
INITIALIZE_PLUGINS = 'initialize_plugins',
38+
RESOLVE = 'resolve',
3839
PARSE = 'parse',
3940
CREATE_ROOT_FILE = 'create_root_file',
4041
VALIDATE = 'validate',

src/parser/index.ts

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@ import { ConfigBlock } from '../entities/config.js';
55
import { Project } from '../entities/project.js';
66
import { ConfigFactory } from './config-factory.js';
77
import { FileType, InMemoryFile, ParsedConfig } from './entities.js';
8-
import { MultipleFilesError, NoCodifyFileError } from './errors.js';
98
import { JsonParser } from './json/json-parser.js';
109
import { Json5Parser } from './json5/json-parser.js';
1110
import { JsoncParser } from './jsonc/json-parser.js';
1211
import { RemoteParser } from './remote/remote-parser.js';
13-
import { CodifyResolver, ResolverResult, ResolverType } from './resolvers.js';
12+
import { ResolverType } from './resolvers.js';
1413
import { SourceMapCache } from './source-maps.js';
1514
import { YamlParser } from './yaml/yaml-parser.js';
1615

17-
export const CODIFY_FILE_REGEX = /^(.*)?codify(.*)?(.json|.yaml|.json5|.jsonc)$/;
1816

1917
export interface ParserArgs {
2018
allowEmptyProject?: boolean;
@@ -57,12 +55,10 @@ class Parser {
5755
* @param location
5856
* @param args
5957
*/
60-
async parse(location: string, args?: ParserArgs, isLoggedIn = false): Promise<Project> {
58+
async parse(file: InMemoryFile, args?: ParserArgs): Promise<Project> {
6159
const sourceMaps = new SourceMapCache()
6260

63-
const { configs, file } = await this.resolveFiles(location, args, isLoggedIn)
64-
.then((result) => this.validateResolver(result))
65-
.then((files) => this.parseContents(files, sourceMaps))
61+
const { configs } = await Promise.resolve(this.parseContents(file, sourceMaps))
6662
.then((config) => this.createConfigBlocks(config, sourceMaps))
6763

6864
return Project.create(configs, file.path, sourceMaps);
@@ -79,35 +75,6 @@ class Parser {
7975
return Project.create(configBlocks.configs, undefined, sourceMaps);
8076
}
8177

82-
private async resolveFiles(location: string, args?: ParserArgs, isLoggedIn = false): Promise<ResolverResult> {
83-
if (args?.resolverType) {
84-
return CodifyResolver.runResolver(location, args.resolverType);
85-
}
86-
87-
if (args?.path) {
88-
return CodifyResolver.resolveLocal(args?.path)
89-
}
90-
91-
return CodifyResolver.run(location, [
92-
ResolverType.LOCAL,
93-
(isLoggedIn) ? ResolverType.REMOTE_DOCUMENT_ID : null,
94-
(isLoggedIn) ? ResolverType.REMOTE_DOCUMENT : null,
95-
(args?.allowTemplates) ? ResolverType.TEMPLATE : null,
96-
]);
97-
}
98-
99-
private async validateResolver(result: ResolverResult): Promise<InMemoryFile> {
100-
if (result.files.length === 0) {
101-
throw new NoCodifyFileError(result);
102-
}
103-
104-
if (result.files.length > 1) {
105-
throw new MultipleFilesError(result);
106-
}
107-
108-
return result.files[0];
109-
}
110-
11178
private parseContents(file: InMemoryFile, sourceMaps: SourceMapCache): ParseResult {
11279
const parser = this.languageSpecificParsers[file.fileType];
11380
if (!parser) {

src/resolver/index.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { LoginHelper } from '../connect/login-helper.js';
2+
import { InMemoryFile } from '../parser/entities.js';
3+
import { Reporter } from '../ui/reporters/reporter.js';
4+
import { MultipleFilesError, NoCodifyFileError } from './errors.js';
5+
import { CodifyResolverRunner, ResolverResult } from './runners.js';
6+
7+
export enum ResolverType {
8+
LOCAL = 'LOCAL',
9+
REMOTE_DOCUMENT_ID = 'REMOTE_DOCUMENT_ID',
10+
REMOTE_DOCUMENT = 'REMOTE_DOCUMENT',
11+
TEMPLATE = 'TEMPLATE',
12+
REMOTE_DEFAULT_DOCUMENT = 'REMOTE_DEFAULT_DOCUMENT',
13+
}
14+
15+
interface ResolverArgs {
16+
resolverType?: ResolverType;
17+
path?: string;
18+
allowTemplates?: boolean;
19+
reporter?: Reporter;
20+
}
21+
22+
/**
23+
* Resolver for resolving and getting the contents of files based on a location. It operated in a fall through manner,
24+
* where it tries different resolvers until it finds a match (starting with the LOCAL resolver).
25+
*/
26+
export class CodifyResolver {
27+
28+
/**
29+
* Order:
30+
* 1. If a path is provided, parse it and look for the location within the path
31+
* 3. If it is a path (relative or absolute) then search for that directory or file
32+
* 4. If the path is an uuid (try to match it with a UUID) on the user's account (if they are logged in)
33+
* 5. Attempt to search for the name on the user's account (if they are logged in)
34+
* 6. Attempt to resolve to a public template (if allowTemplate is enabled)
35+
* Error out and tell the user that the following file could not be found
36+
*
37+
*
38+
* @param location
39+
* @param args
40+
*/
41+
static async resolveFile(location: string, args?: ResolverArgs): Promise<InMemoryFile> {
42+
return CodifyResolver.run(location, args)
43+
.then((result) => this.narrow(result))
44+
}
45+
46+
private static async run(location: string, args?: ResolverArgs): Promise<ResolverResult> {
47+
if (args?.resolverType) {
48+
return CodifyResolverRunner.runResolver(location, args.resolverType);
49+
}
50+
51+
if (args?.path) {
52+
return CodifyResolverRunner.resolveLocal(args?.path)
53+
}
54+
55+
const isLoggedIn = LoginHelper.get()?.isLoggedIn;
56+
57+
return CodifyResolverRunner.run(location, [
58+
ResolverType.LOCAL,
59+
(isLoggedIn) ? ResolverType.REMOTE_DOCUMENT_ID : null,
60+
(isLoggedIn) ? ResolverType.REMOTE_DOCUMENT : null,
61+
(args?.allowTemplates) ? ResolverType.TEMPLATE : null,
62+
(isLoggedIn) ? ResolverType.REMOTE_DEFAULT_DOCUMENT : null,
63+
]);
64+
}
65+
66+
private static async narrow(result: ResolverResult, args?: ResolverArgs): Promise<InMemoryFile> {
67+
if (result.files.length === 0) {
68+
throw new NoCodifyFileError(result);
69+
}
70+
71+
if (result.files.length > 1) {
72+
if (!args?.reporter) {
73+
throw new MultipleFilesError(result);
74+
}
75+
76+
const reporter = args?.reporter;
77+
const index = await reporter.promptOptions(
78+
'Multiple matching Codify files found',
79+
result.files.map((file) => result.location + file.path),
80+
);
81+
82+
return result.files[index];
83+
}
84+
85+
return result.files[0];
86+
}
87+
88+
}
File renamed without changes.

0 commit comments

Comments
 (0)