import { Collection, Entity, Property } from "./MySchema"; import { FileWrite } from "./app"; import { modelModuleName } from "./ModelGenerator"; export function generateDataAccess(collections: Collection[]): FileWrite[] { return collections.map(generateDataAccessFile); } export function dataAccessModuleName(collection: Collection): string { return `${collection.name}DataAccess`; } function generateDataAccessFile(collection: Collection): FileWrite { const definitions: string[] = [ defineImports(collection), defineSave(collection), defineParseEntity(collection.entities), defineParseCollection(collection), defineLoad(collection), defineGeneral(), ]; return { location: dataAccessModuleName(collection) + ".ts", content: definitions.join("\n\n") + "\n", }; } function defineImports(collection: Collection): string { const entity = collection.entities; return `import { ${collection.name}, ${entity.name} } from "./${modelModuleName(collection)}"; import * as fs from "fs";`; } function defineSave(collection: Collection): string { return `export function save(fileName: string, collection: ${collection.name}): void { const content = JSON.stringify({ ...collection, $schema: "./${collection.name.toLowerCase()}.schema.json" }); fs.writeFileSync(fileName, content); }`; } function defineGeneral(): string { return `function parseArrayProperty<O, T>(fieldName: keyof O, itemParser: (item: any) => T, data: any): T[] { if(fieldName in data) { const valueList = data[fieldName]; if(Array.isArray(valueList)) { return valueList.map(itemParser); } } return []; } function parsePrimitiveProperty<O, T = string | number>(type: T extends string ? "string" : "number", fieldName: keyof O, defaultValue: T, obj: any): T { if(fieldName in obj) { const fieldValue = obj[fieldName]; if(typeof fieldValue === type) { return fieldValue; } } return defaultValue; } function canReadFile(path: string): boolean { try { fs.accessSync(path, fs.constants.R_OK); return true; } catch (error) { return false; } }`; } function defineParseEntity(entity: Entity): string { const propParser = entity.properties.map(p => parseStringProperty(entity.name, p)).join("\n"); return `function parse${entity.name}(data: any): ${entity.name} { return { id: parsePrimitiveProperty<${entity.name}, number>("number", "id", 0, data), ${propParser} }; }`; } function parseStringProperty(entityName: string, property: Property): string { return `\t\t${property.key}: parsePrimitiveProperty<${entityName}, string>("string", "${property.key}", "", data),`; } function defineParseCollection(collection: Collection): string { return `function parse${collection.name}(data: any): ${collection.name} { return { nextId: parsePrimitiveProperty<${collection.name}, number>("number", "nextId", 1, data), items: parseArrayProperty<${collection.name}, ${collection.entities.name}>("items", parse${collection.entities.name}, data), }; }`; } function defineLoad(collection: Collection): string { return `export function load(fileName: string): ${collection.name} { if (!canReadFile(fileName)) { return { items: [], nextId: 1, }; } const content = fs.readFileSync(fileName).toString(); const data = JSON.parse(content); return parse${collection.name}(data); }`; }