Skip to content

Commit 5630319

Browse files
committed
Added ability to load, apply and plan cloud files
1 parent 4c2759e commit 5630319

File tree

12 files changed

+114
-31
lines changed

12 files changed

+114
-31
lines changed

src/api/dashboard/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { LoginHelper } from '../../connect/login-helper.js';
2+
import { CloudDocument } from './types.js';
3+
4+
const API_BASE_URL = 'http://localhost:3000'
5+
6+
export const DashboardApiClient = {
7+
async getDocument(id: string): Promise<CloudDocument> {
8+
const login = LoginHelper.get()?.credentials;
9+
if (!login) {
10+
throw new Error('Not logged in');
11+
}
12+
13+
const res = await fetch(
14+
`${API_BASE_URL}/api/documents/${id}`,
15+
{ method: 'GET', headers: { 'Content-Type': 'application/json', 'authorization': login.accessToken } },
16+
);
17+
18+
const json = await res.json();
19+
if (!res.ok) {
20+
throw new Error(JSON.stringify(json, null, 2));
21+
}
22+
23+
return json;
24+
}
25+
}

src/api/dashboard/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Config } from 'codify-schemas';
2+
3+
export interface CloudDocument {
4+
id: string;
5+
contents: Array<Config>
6+
}

src/commands/init.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@ For more information, visit: https://docs.codifycli.com/commands/init`
3030
await InitializeOrchestrator.run({
3131
verbosityLevel: flags.debug ? 3 : 0,
3232
},this.reporter);
33+
34+
process.exit(0)
3335
}
3436
}

src/commands/login.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@ For more information, visit: https://docs.codifycli.com/commands/validate
1919
const { flags } = await this.parse(Login)
2020

2121
await LoginOrchestrator.run();
22+
23+
process.exit(0)
2224
}
2325
}

src/common/initialize-plugins.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,9 @@ export class PluginInitOrchestrator {
5252
): Promise<Project> {
5353
ctx.subprocessStarted(SubProcessName.PARSE);
5454

55-
const pathToParse = (fileOrDir === undefined)
56-
? await PluginInitOrchestrator.findCodifyJson()
57-
: fileOrDir
58-
5955
const isLoggedIn = LoginHelper.get()?.isLoggedIn ?? false;
6056

61-
if (!pathToParse && !allowEmptyProject && !isLoggedIn) {
57+
if (!fileOrDir && !allowEmptyProject && !isLoggedIn) {
6258
ctx.subprocessFinished(SubProcessName.PARSE);
6359
ctx.subprocessStarted(SubProcessName.CREATE_ROOT_FILE)
6460
const createRootCodifyFile = await reporter.promptConfirmation('\nNo codify file found. Do you want to create a root file at ~/codify.jsonc?');
@@ -77,8 +73,8 @@ export class PluginInitOrchestrator {
7773
process.exit(0);
7874
}
7975

80-
const project = pathToParse
81-
? await CodifyParser.parse(pathToParse)
76+
const project = fileOrDir
77+
? await CodifyParser.parse(fileOrDir)
8278
: Project.empty()
8379

8480
ctx.subprocessFinished(SubProcessName.PARSE);

src/parser/cloud/cloud-parser.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1+
import { Config } from 'codify-schemas';
2+
13
import { InMemoryFile, LanguageSpecificParser, ParsedConfig } from '../entities.js';
24
import { SourceMapCache } from '../source-maps.js';
35

46
export class CloudParser implements LanguageSpecificParser {
5-
parse(file: InMemoryFile, sourceMaps: SourceMapCache): ParsedConfig[] {
6-
throw new Error('Method not implemented.');
7-
}
7+
parse(file: InMemoryFile, sourceMaps: SourceMapCache): ParsedConfig[] {
8+
const contents = JSON.parse(file.contents) as Array<Config>;
9+
10+
return contents.map((content) => {
11+
const { id, type, ...config } = content;
12+
return {
13+
contents: { type, ...config },
14+
sourceMapKey: id as string,
15+
}
16+
})
17+
}
818

919
}

src/parser/entities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ export enum FileType {
2121
YAML = 'yaml',
2222
JSON5 = 'json5',
2323
JSONC = 'jsonc',
24+
CLOUD = 'cloud',
2425
}

src/parser/index.ts

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import * as fs from 'node:fs/promises';
22
import path from 'node:path';
3+
import { validate } from 'uuid'
34

45
import { InternalError } from '../common/errors.js';
56
import { ConfigBlock } from '../entities/config.js';
67
import { Project } from '../entities/project.js';
8+
import { FileUtils } from '../utils/file.js';
9+
import { CloudParser } from './cloud/cloud-parser.js';
710
import { ConfigFactory } from './config-factory.js';
811
import { FileType, InMemoryFile, ParsedConfig } from './entities.js';
912
import { JsonParser } from './json/json-parser.js';
1013
import { Json5Parser } from './json5/json-parser.js';
1114
import { JsoncParser } from './jsonc/json-parser.js';
12-
import { FileReader } from './reader.js';
15+
import { CloudReader } from './reader/cloud-reader.js';
16+
import { FileReader } from './reader/file-reader.js';
1317
import { SourceMapCache } from './source-maps.js';
1418
import { YamlParser } from './yaml/yaml-parser.js';
1519

@@ -20,13 +24,13 @@ class Parser {
2024
[FileType.JSON]: new JsonParser(),
2125
[FileType.YAML]: new YamlParser(),
2226
[FileType.JSON5]: new Json5Parser(),
23-
[FileType.JSONC]: new JsoncParser()
27+
[FileType.JSONC]: new JsoncParser(),
28+
[FileType.CLOUD]: new CloudParser(),
2429
}
2530

2631
async parse(dirOrFile: string): Promise<Project> {
27-
const absolutePath = path.resolve(dirOrFile);
2832
const sourceMaps = new SourceMapCache()
29-
const codifyFiles = await this.getFilePaths(absolutePath)
33+
const codifyFiles = await this.getFilePaths(dirOrFile)
3034

3135
const configs = await this.readFiles(codifyFiles)
3236
.then((files) => this.parseContents(files, sourceMaps))
@@ -36,28 +40,43 @@ class Parser {
3640
}
3741

3842
private async getFilePaths(dirOrFile: string): Promise<string[]> {
39-
const isDirectory = (await fs.lstat(dirOrFile)).isDirectory();
43+
// A cloud file is represented as an uuid. Skip file checks if it's a cloud file;
44+
if (validate(dirOrFile)) {
45+
return [dirOrFile];
46+
}
47+
48+
const absolutePath = path.resolve(dirOrFile);
49+
const isDirectory = (await fs.lstat(absolutePath)).isDirectory();
4050

4151
// A single file was passed in. We need to test if the file satisfies the codify file regex
4252
if (!isDirectory) {
43-
const fileName = path.basename(dirOrFile);
53+
const fileName = path.basename(absolutePath);
4454
if (!CODIFY_FILE_REGEX.test(fileName)) {
45-
throw new Error(`Invalid file path provided ${dirOrFile} ${fileName}. Expected the file to be *.codify.jsonc, *.codify.json5, *.codify.json, or *.codify.yaml `)
55+
throw new Error(`Invalid file path provided ${absolutePath} ${fileName}. Expected the file to be *.codify.jsonc, *.codify.json5, *.codify.json, or *.codify.yaml `)
4656
}
4757

48-
return [dirOrFile];
58+
return [absolutePath];
4959
}
5060

51-
const filesInDir = await fs.readdir(dirOrFile);
61+
const filesInDir = await fs.readdir(absolutePath);
5262

5363
return filesInDir
5464
.filter((name) => CODIFY_FILE_REGEX.test(name))
55-
.map((name) => path.join(dirOrFile, name))
65+
.map((name) => path.join(absolutePath, name))
5666
}
5767

5868
private readFiles(filePaths: string[]): Promise<InMemoryFile[]> {
69+
const cloudReader = new CloudReader();
70+
const fileReader = new FileReader();
71+
5972
return Promise.all(filePaths.map(
60-
(p) => FileReader.read(p)
73+
async (p) => {
74+
if (validate(p) && !(await FileUtils.fileExists(p))) {
75+
return cloudReader.read(p)
76+
}
77+
78+
return fileReader.read(p)
79+
}
6180
))
6281
}
6382

src/parser/jsonc/json-parser.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export class JsoncParser implements LanguageSpecificParser {
3030
}
3131

3232
return content.map((contents, idx) => ({
33-
contents,
34-
sourceMapKey: SourceMapCache.constructKey(file.filePath, `/${idx}`)
35-
}))
33+
contents,
34+
sourceMapKey: SourceMapCache.constructKey(file.filePath, `/${idx}`)
35+
}))
3636
}
3737

3838
private validate(content: unknown): content is Config[] {

src/parser/reader/cloud-reader.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { DashboardApiClient } from '../../api/dashboard/index.js';
2+
import { FileType, InMemoryFile } from '../entities.js';
3+
import { Reader } from './index.js';
4+
5+
export class CloudReader implements Reader {
6+
async read(filePath: string): Promise<InMemoryFile> {
7+
const document = await DashboardApiClient.getDocument(filePath);
8+
9+
return {
10+
contents: JSON.stringify(document.contents),
11+
filePath,
12+
fileType: FileType.CLOUD,
13+
}
14+
}
15+
16+
}

0 commit comments

Comments
 (0)