123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /**
- * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
- import { Database, Filter, Column } from './schema';
- import { indentString } from '../../../mol-util/string';
- import { FieldPath } from '../../../mol-io/reader/cif/schema';
- function header(name: string, info: string, moldataImportPath: string) {
- return `/**
- * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * Code-generated '${name}' schema file. ${info}
- *
- * @author molstar/ciftools package
- */
- import { Database, Column } from '${moldataImportPath}/db';
- import Schema = Column.Schema;`;
- }
- function footer(name: string) {
- return `
- export type ${name}_Schema = typeof ${name}_Schema;
- export interface ${name}_Database extends Database<${name}_Schema> {};`;
- }
- function getTypeShorthands(schema: Database, fields?: Filter) {
- const types = new Set<string>();
- Object.keys(schema.tables).forEach(table => {
- if (fields && !fields[table]) return;
- const { columns } = schema.tables[table];
- Object.keys(columns).forEach(columnName => {
- if (fields && !fields[table][columnName]) return;
- const col = schema.tables[table].columns[columnName];
- if (col.type === 'enum') types.add(col.subType);
- types.add(col.type);
- });
- });
- const shorthands: string[] = [];
- types.forEach(type => {
- switch (type) {
- case 'str': shorthands.push('const str = Schema.str;'); break;
- case 'ustr': shorthands.push('const ustr = Schema.ustr;'); break;
- case 'lstr': shorthands.push('const lstr = Schema.lstr;'); break;
- case 'int': shorthands.push('const int = Schema.int;'); break;
- case 'float': shorthands.push('const float = Schema.float;'); break;
- case 'coord': shorthands.push('const coord = Schema.coord;'); break;
- case 'enum': shorthands.push('const Aliased = Schema.Aliased;'); break;
- case 'matrix': shorthands.push('const Matrix = Schema.Matrix;'); break;
- case 'vector': shorthands.push('const Vector = Schema.Vector;'); break;
- case 'list': shorthands.push('const List = Schema.List;'); break;
- }
- });
- return shorthands.join('\n');
- }
- function getTypeDef(c: Column): string {
- switch (c.type) {
- case 'str': return 'str';
- case 'int': return 'int';
- case 'float': return 'float';
- case 'coord': return 'coord';
- case 'enum':
- return `Aliased<'${c.values.map(v => v.replace(/'/g, '\\\'')).join(`' | '`)}'>(${c.subType})`;
- case 'matrix':
- return `Matrix(${c.rows}, ${c.columns})`;
- case 'vector':
- return `Vector(${c.length})`;
- case 'list':
- if (c.subType === 'int') {
- return `List('${c.separator}', x => parseInt(x, 10))`;
- } else if (c.subType === 'float' || c.subType === 'coord') {
- return `List('${c.separator}', x => parseFloat(x))`;
- } else {
- return `List('${c.separator}', x => x)`;
- }
- }
- }
- const reSafePropertyName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
- function safePropertyString(name: string) { return name.match(reSafePropertyName) ? name : `'${name}'`; }
- function doc(description: string, spacesCount: number) {
- const spaces = ' '.repeat(spacesCount);
- return [
- `${spaces}/**`,
- `${indentString(description, 1, `${spaces} * `)}`.replace(/ +\n/g, '\n'),
- `${spaces} */`
- ].join('\n');
- }
- export function generate(name: string, info: string, schema: Database, fields: Filter | undefined, moldataImportPath: string, addAliases: boolean) {
- const codeLines: string[] = [];
- if (fields) {
- Object.keys(fields).forEach(table => {
- if (table in schema.tables) {
- const schemaTable = schema.tables[table];
- Object.keys(fields[table]).forEach(column => {
- if (!(column in schemaTable.columns)) {
- console.log(`filter field '${table}.${column}' not found in schema`);
- }
- });
- } else {
- console.log(`filter category '${table}' not found in schema`);
- }
- });
- }
- codeLines.push(`export const ${name}_Schema = {`);
- Object.keys(schema.tables).forEach(table => {
- if (fields && !fields[table]) return;
- const { description, columns } = schema.tables[table];
- if (description) codeLines.push(doc(description, 4));
- codeLines.push(` ${safePropertyString(table)}: {`);
- Object.keys(columns).forEach(columnName => {
- if (fields && !fields[table][columnName]) return;
- const c = columns[columnName];
- const typeDef = getTypeDef(c);
- if (c.description) codeLines.push(doc(c.description, 8));
- codeLines.push(` ${safePropertyString(columnName)}: ${typeDef},`);
- });
- codeLines.push(' },');
- });
- codeLines.push('};');
- if (addAliases) {
- codeLines.push('');
- codeLines.push(`export const ${name}_Aliases = {`);
- Object.keys(schema.aliases).forEach(path => {
- const [table, columnName] = path.split('.');
- if (fields && !fields[table]) return;
- if (fields && !fields[table][columnName]) return;
- const filteredAliases = new Set<string>();
- schema.aliases[path].forEach(p => {
- if (!FieldPath.equal(p, path)) filteredAliases.add(FieldPath.canonical(p));
- });
- if (filteredAliases.size === 0) return;
- codeLines.push(` ${safePropertyString(path)}: [`);
- filteredAliases.forEach(alias => {
- codeLines.push(` '${alias}',`);
- });
- codeLines.push(' ],');
- });
- codeLines.push('};');
- }
- return `${header(name, info, moldataImportPath)}\n\n${getTypeShorthands(schema, fields)}\n\n${codeLines.join('\n')}\n${footer(name)}`;
- }
|