Skip to content

Commit

Permalink
implement EJS
Browse files Browse the repository at this point in the history
  • Loading branch information
TorstenDittmann committed Sep 12, 2021
1 parent c6f4077 commit e48e7b4
Show file tree
Hide file tree
Showing 10 changed files with 388 additions and 163 deletions.
118 changes: 64 additions & 54 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
#!/usr/bin/env node

import yargs from "yargs";
import path from "path";
import {Client, Database} from "node-appwrite";
import {hideBin} from "yargs/helpers";
import {mkdir, readFile, writeFile} from "fs/promises";
import {existsSync} from "fs";
import {exit} from "process";
import {Typescript} from "./languages/typescript.js"
import {Kotlin} from "./languages/kotlin.js"
import {Php} from "./languages/php.js";
import path, { dirname } from "path";
import { Client, Database } from "node-appwrite";
import { hideBin } from "yargs/helpers";
import { mkdir, readFile, writeFile } from "fs/promises";
import { existsSync } from "fs";
import { exit } from "process";
import { Typescript } from "./languages/typescript.js";
import { Kotlin } from "./languages/kotlin.js";
import { Php } from "./languages/php.js";
import { renderFile } from "ejs";
import { fileURLToPath } from "url";

const client = new Client();
const database = new Database(client);

const languageClasses = {
"typescript": Typescript,
"kotlin": Kotlin,
"php": Php
}
typescript: Typescript,
kotlin: Kotlin,
php: Php,
};

/**
* Load configuration for Appwrite.
* @param {string} file
* @returns {Promise<object>}
*/
const loadConfiguration = async file => {

const loadConfiguration = async (file) => {
try {
if (!existsSync(file)) {
onError("Configuration not found.")
onError("Configuration not found.");
}

const data = await readFile(file, 'utf8');
const data = await readFile(file, "utf8");
const config = JSON.parse(data);

client
Expand All @@ -42,11 +43,11 @@ const loadConfiguration = async file => {

return config;
} catch (err) {
onError(err.message)
onError(err.message);
}
}
};

const generate = async ({output, config, language}) => {
const generate = async ({ output, config, language }) => {
await loadConfiguration(config);

const selectedClass = languageClasses[language];
Expand All @@ -57,73 +58,82 @@ const generate = async ({output, config, language}) => {

/** @type {Array<object>} collections*/
const collections = (await database.listCollections()).collections;
const types = buildCollectionTypes(collections)
const types = buildCollectionTypes(collections);

if (!existsSync(output)) {
await mkdir(output, {recursive: true});
await mkdir(output, { recursive: true });
}

for (const type of types) {
const content = lang.generate(type)

try {
const destination = path.join(output, `./${type.name}${lang.getFileExtension()}`);
const content = await renderFile(path.join(fileURLToPath(dirname(import.meta.url)), `./templates/${language}.ejs`), {
...type,
getType: selectedClass.getType,
getTypeFormatted: selectedClass.getTypeFormatted,
});

const destination = path.join(
output,
`./${type.name}${lang.getFileExtension()}`
);
await writeFile(destination, content);
console.log(`Generated ${destination}`)
console.log(`Generated ${destination}`);
} catch (err) {
console.error(err.message)
console.error(err.message);
}
}
}
};

const buildCollectionTypes = (collections) => {
let types = [];
collections.forEach(collection => {
collections.forEach((collection) => {
types.push({
name: collection.name,
attributes: collection.rules.map(rule => {
return {
name: rule.key,
type: rule.type,
array: rule.array,
required: rule.required
}
}).sort((a, b) => {
return (a.required === b.required)
? 0
: a.required
? -1
: 1;
})
})
})
attributes: collection.rules
.map((rule) => {
return {
name: rule.key,
type: rule.type,
array: rule.array,
required: rule.required,
};
})
.sort((a, b) => {
return a.required === b.required ? 0 : a.required ? -1 : 1;
}),
});
});
return types;
}
};

const onError = function catchError(error) {
console.error(error)
console.error(error);
exit(1);
}
};

yargs(hideBin(process.argv))
.command("generate", "Fetches Collection and creates Typescript Definitions", () => { }, generate)
.command(
"generate",
"Fetches Collection and creates Typescript Definitions",
() => { },
generate
)
.option("output", {
alias: "o",
type: "string",
description: "Output",
default: "./"
default: "./",
})
.option("config", {
alias: "c",
type: "string",
description: "Configuration file.",
required: true
required: true,
})
.option("language", {
alias: "l",
type: "string",
description: "Output language",
default: "typescript"
default: "typescript",
})
.demandCommand(1)
.argv;
.demandCommand(1).argv;
37 changes: 14 additions & 23 deletions languages/kotlin.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
import camelCase from "camelcase";
import {Language} from "./language.js"
import {AttributeTypes} from "../attributes.js";
import { Language } from "./language.js";
import { AttributeTypes } from "../attributes.js";
import camelcase from "camelcase";

export class Kotlin extends Language {

getType(type) {
static getType(type) {
switch (type) {
case AttributeTypes.TEXT:
case AttributeTypes.EMAIL:
case AttributeTypes.URL:
case AttributeTypes.IP:
case AttributeTypes.WILDCARD:
case AttributeTypes.MARKDOWN:
return "String"
return "String";
case AttributeTypes.NUMERIC:
return "Number"
return "Number";
case AttributeTypes.BOOLEAN:
return "Boolean"
return "Boolean";
}
}

static getTypeFormatted(name) {
return camelcase(name, {pascalCase: true});
}

getTypeDefault(attribute) {
if (!attribute.required) {
return "null";
}
if (attribute.array) {
return `listOf<${this.getType(attribute.type)}>()`;
return `listOf<${Kotlin.getType(attribute.type)}>()`;
}
switch (attribute.type) {
case AttributeTypes.TEXT:
Expand All @@ -43,18 +46,6 @@ export class Kotlin extends Language {
}

getFileExtension() {
return ".kt"
}

getTypeOpenLine(name) {
return `data class ${camelCase(name, {pascalCase: true})} (\n`
}

getTypePropertyLine(attribute) {
return `\t${attribute.name}: ${attribute.array ? "List<" : ""}${this.getType(attribute.type) ?? "Any"}${attribute.array ? ">" : ""}${attribute.required ? "" : "?"}${attribute.required ? "" : ` = ${this.getTypeDefault(attribute)}`},\n`;
}

getTypeCloseLine() {
return ")\n"
return ".kt";
}
}
}
51 changes: 10 additions & 41 deletions languages/language.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ export class Language {
* @param type
* @return {string}
*/
getType(type) {
static getType(type) {
throw new TypeError("Stub.");
}

/**
* Return formatted Type Name.
* @param {string} attribute
* @returns {string}
*/
static getTypeFormatted(name) {
throw new TypeError("Stub.");
}

Expand All @@ -33,44 +42,4 @@ export class Language {
getFileExtension() {
throw new TypeError("Stub.");
}

/**
* Get a string that defines the opening line for a new type with the given name in this language.
*
* @param name
*/
getTypeOpenLine(name) {
throw new TypeError("Stub.");
}

/**
* Get a string that defines a property line for the given attribute for this language.
*
* @param attribute
*/
getTypePropertyLine(attribute) {
throw new TypeError("Stub.");
}

/**
* Get a string that closes a type definition for this language.
*
*/
getTypeCloseLine() {
throw new TypeError("Stub.");
}

/**
* Generate (as a string) a type definition with the given type for this language.
*
* @param type
* @returns {string}
*/
generate(type) {
return this.getTypeOpenLine(type.name)
+ (type.attributes.map(attr => {
return this.getTypePropertyLine(attr)
}).join(""))
+ this.getTypeCloseLine();
}
}
33 changes: 12 additions & 21 deletions languages/php.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import camelCase from "camelcase";
import {Language} from "./language.js"
import {AttributeTypes} from "../attributes.js";
import { Language } from "./language.js";
import { AttributeTypes } from "../attributes.js";
import camelcase from "camelcase";

export class Php extends Language {

getType(type) {
static getType(type) {
switch (type) {
case AttributeTypes.TEXT:
case AttributeTypes.EMAIL:
Expand All @@ -14,12 +13,16 @@ export class Php extends Language {
case AttributeTypes.MARKDOWN:
return "string";
case AttributeTypes.NUMERIC:
return "number"
return "int";
case AttributeTypes.BOOLEAN:
return "bool"
return "bool";
}
}

static getTypeFormatted(name) {
return camelcase(name, {pascalCase: true});
}

getTypeDefault(attribute) {
if (!attribute.required) {
return "null";
Expand All @@ -43,18 +46,6 @@ export class Php extends Language {
}

getFileExtension() {
return ".php"
}

getTypeOpenLine(name) {
return `<?php\nclass ${camelCase(name, {pascalCase: true})} \n{\n\tpublic function __construct(\n`
}

getTypePropertyLine(attribute) {
return `\t\tpublic ${attribute.required ? "" : "?"}${attribute.array ? "array" : this.getType(attribute.type) ?? ""} $${attribute.name}${attribute.required ? "" : ` = ${this.getTypeDefault(attribute)}`},\n`;
}

getTypeCloseLine() {
return "\t)\n}"
return ".php";
}
}
}
Loading

0 comments on commit e48e7b4

Please sign in to comment.