@liam-hq/cli
Version:
Command-line tool designed to generate a web application that displays ER diagrams. See https://liambx.com/docs/cli
2,026 lines (1,867 loc) • 3.25 MB
JavaScript
#!/usr/bin/env node
import { createRequire } from 'node:module';
import { Command } from 'commander';
import pkg from '@prisma/internals';
import { readFile } from 'node:fs/promises';
import { fileURLToPath, URL as URL$1 } from 'node:url';
import tty from 'node:tty';
import fs, { existsSync, mkdirSync, cpSync } from 'node:fs';
import path, { resolve, dirname, relative } from 'node:path';
import { glob } from 'glob';
import { exit } from 'node:process';
import inquirer from 'inquirer';
// Helper function to handle autoincrement types
function getAutoincrementType(typeName) {
switch (typeName) {
case 'Int':
return 'serial';
case 'SmallInt':
return 'smallserial';
case 'BigInt':
return 'bigserial';
default:
return typeName.toLowerCase();
}
}
// Helper function to handle native types
function handleNativeType(nativeTypeName, nativeTypeArgs, defaultValue) {
// Check for autoincrement
if (typeof defaultValue === 'string' &&
defaultValue.includes('autoincrement()')) {
return getAutoincrementType(nativeTypeName);
}
// Handle type with arguments
if (nativeTypeArgs.length > 0) {
return `${nativeTypeName.toLowerCase()}(${nativeTypeArgs.join(',')})`;
}
// Special case for DoublePrecision
if (nativeTypeName === 'DoublePrecision') {
return 'double precision';
}
return nativeTypeName.toLowerCase();
}
// Helper function to map Prisma types to PostgreSQL types
function mapPrismaTypeToPostgres(type) {
switch (type) {
case 'String':
return 'text';
case 'Boolean':
return 'boolean';
case 'Int':
return 'integer';
case 'BigInt':
return 'bigint';
case 'Float':
return 'double precision';
case 'DateTime':
return 'timestamp(3)';
case 'Json':
return 'jsonb';
case 'Decimal':
return 'decimal(65,30)';
case 'Bytes':
return 'bytea';
default:
return type;
}
}
// ref: https://www.prisma.io/docs/orm/reference/prisma-schema-reference#model-field-scalar-types
function convertToPostgresColumnType(type, nativeType, defaultValue) {
// If native type is provided, use it
if (nativeType) {
const [nativeTypeName, nativeTypeArgs] = nativeType;
return handleNativeType(nativeTypeName, nativeTypeArgs, defaultValue);
}
// Handle autoincrement without native type
if (typeof defaultValue === 'string' &&
defaultValue.includes('autoincrement()')) {
return getAutoincrementType(type);
}
// Special case for uuid default value
if (typeof defaultValue === 'string' && defaultValue.includes('uuid')) {
return 'uuid';
}
// Map Prisma type to PostgreSQL type
return mapPrismaTypeToPostgres(type);
}
// NOTE: Workaround for CommonJS module import issue with @prisma/internals
// CommonJS module can not support all module.exports as named exports
const { getDMMF } = pkg;
const getFieldRenamedRelationship = (relationship, tableFieldsRenaming) => {
const mappedPrimaryColumnName = tableFieldsRenaming[relationship.primaryTableName]?.[relationship.primaryColumnName];
if (mappedPrimaryColumnName) {
relationship.primaryColumnName = mappedPrimaryColumnName;
}
const mappedForeignColumnName = tableFieldsRenaming[relationship.foreignTableName]?.[relationship.foreignColumnName];
if (mappedForeignColumnName) {
relationship.foreignColumnName = mappedForeignColumnName;
}
return relationship;
};
const getFieldRenamedIndex = (index, tableFieldsRenaming) => {
const fieldsRenaming = tableFieldsRenaming[index.model];
if (!fieldsRenaming)
return index;
const newFields = index.fields.map((field) => ({
...field,
name: fieldsRenaming[field.name] ?? field.name,
}));
return { ...index, fields: newFields };
};
/**
* Build a mapping of field renamings from model fields
*/
function buildFieldRenamingMap(models) {
const tableFieldRenaming = {};
for (const model of models) {
for (const field of model.fields) {
if (field.dbName) {
const tableName = model.dbName || model.name;
const fieldConversions = tableFieldRenaming[tableName] ?? {};
fieldConversions[field.name] = field.dbName;
tableFieldRenaming[tableName] = fieldConversions;
}
}
}
return tableFieldRenaming;
}
function processModelField(field, model, tableFieldRenaming) {
if (field.relationName)
return { column: null, constraint: null };
const defaultValue = extractDefaultValue$2(field);
const fieldName = tableFieldRenaming[model.dbName || model.name]?.[field.name] ?? field.name;
const column = {
name: fieldName,
type: convertToPostgresColumnType(field.type, field.nativeType, defaultValue),
default: defaultValue,
notNull: field.isRequired,
unique: field.isId || field.isUnique,
primary: field.isId,
comment: field.documentation ?? null,
check: null,
};
let constraint = null;
if (field.isId) {
const constraintName = `PRIMARY_${fieldName}`;
constraint = {
type: 'PRIMARY KEY',
name: constraintName,
columnName: fieldName,
};
}
else if (field.isUnique) {
// to avoid duplicate with PRIMARY KEY constraint, it doesn't create constraint object with `field.isId`
const constraintName = `UNIQUE_${fieldName}`;
constraint = {
type: 'UNIQUE',
name: constraintName,
columnName: fieldName,
};
}
return {
column: [fieldName, column],
constraint: constraint ? [constraint.name, constraint] : null,
};
}
/**
* Process a model and create a table
*/
function processModel(model, tableFieldRenaming) {
const columns = {};
const constraints = {};
for (const field of model.fields) {
const { column, constraint } = processModelField(field, model, tableFieldRenaming);
if (column) {
columns[column[0]] = column[1];
}
if (constraint) {
constraints[constraint[0]] = constraint[1];
}
}
return {
name: model.dbName || model.name,
columns,
comment: model.documentation ?? null,
indexes: {},
constraints,
};
}
/**
* Process all models and create tables
*/
function processTables(models, tableFieldRenaming) {
const tables = {};
for (const model of models) {
tables[model.dbName || model.name] = processModel(model, tableFieldRenaming);
}
return tables;
}
/**
* Get Primary Table Name
*/
function getPrimaryTableNameByType(fieldType, models) {
return models.find((model) => model.name === fieldType)?.dbName ?? fieldType;
}
/**
* Process a relationship field
*/
function processRelationshipField(field, model, models, existingRelationships, tableFieldRenaming) {
if (!field.relationName)
return { relationship: null, constraint: null };
const existingRelationship = existingRelationships[field.relationName];
const isTargetField = field.relationToFields?.[0] &&
(field.relationToFields?.length ?? 0) > 0 &&
field.relationFromFields?.[0] &&
(field.relationFromFields?.length ?? 0) > 0;
// Get the primary table name
const primaryTableName = isTargetField && getPrimaryTableNameByType(field.type, models);
// Get the column names with fallback to empty string
const primaryColumnName = field.relationToFields?.[0] ?? '';
const foreignColumnName = field.relationFromFields?.[0] ?? '';
const _relationship = isTargetField
? {
name: field.relationName,
primaryTableName: primaryTableName || field.type,
primaryColumnName,
foreignTableName: model.dbName || model.name,
foreignColumnName,
cardinality: existingRelationship?.cardinality ?? 'ONE_TO_MANY',
updateConstraint: 'NO_ACTION',
deleteConstraint: normalizeConstraintName$2(field.relationOnDelete ?? ''),
}
: {
name: field.relationName,
primaryTableName: existingRelationship?.primaryTableName ?? '',
primaryColumnName: existingRelationship?.primaryColumnName ?? '',
foreignTableName: existingRelationship?.foreignTableName ?? '',
foreignColumnName: existingRelationship?.foreignColumnName ?? '',
cardinality: field.isList ? 'ONE_TO_MANY' : 'ONE_TO_ONE',
updateConstraint: 'NO_ACTION',
deleteConstraint: 'NO_ACTION',
};
const relationship = getFieldRenamedRelationship(_relationship, tableFieldRenaming);
const constraint = {
type: 'FOREIGN KEY',
name: relationship.name,
columnName: relationship.foreignColumnName,
targetTableName: relationship.primaryTableName,
targetColumnName: relationship.primaryColumnName,
updateConstraint: relationship.updateConstraint,
deleteConstraint: relationship.deleteConstraint,
};
return { relationship, constraint };
}
/**
* Process a single model's relationships
*/
function processModelRelationships(model, models, tables, tableFieldRenaming, processedManyToManyRelations, manyToManyRelations, existingRelationships) {
const relationships = {
...existingRelationships,
};
for (const field of model.fields) {
if (!field.relationName)
continue;
// Skip many-to-many relations as they're handled separately
if (detectAndStoreManyToManyRelation(field, model, models, processedManyToManyRelations, manyToManyRelations)) {
continue;
}
// Process regular relationship
const { relationship, constraint } = processRelationshipField(field, model, models, relationships, tableFieldRenaming);
// Add relationship to collection
if (relationship) {
relationships[relationship.name] = relationship;
}
// Add constraint to table
if (constraint && relationship) {
const table = tables[relationship.foreignTableName];
if (table) {
table.constraints[constraint.name] = constraint;
}
}
}
return relationships;
}
/**
* Process relationships for all models
*/
function processRelationships$1(models, tables, tableFieldRenaming, processedManyToManyRelations, manyToManyRelations) {
let relationships = {};
// Process each model's relationships
for (const model of models) {
relationships = processModelRelationships(model, models, tables, tableFieldRenaming, processedManyToManyRelations, manyToManyRelations, relationships);
}
return relationships;
}
/**
* Process indexes for all models
*/
function processIndexes$1(indexes, models, tables, tableFieldRenaming) {
const updatedIndexes = indexes.map((index) => {
const model = models.find((m) => m.name === index.model);
return model
? {
model: model.dbName ?? model.name,
type: index.type,
isDefinedOnField: index.isDefinedOnField,
fields: index.fields,
}
: index;
});
for (const index of updatedIndexes) {
const table = tables[index.model];
if (!table)
continue;
const indexInfo = extractIndex(getFieldRenamedIndex(index, tableFieldRenaming));
if (!indexInfo)
continue;
table.indexes[indexInfo.name] = indexInfo;
}
}
/**
* Process many-to-many relationships
*/
function processManyToManyRelationships(manyToManyRelations, tables, models) {
const relationships = {};
for (const relation of manyToManyRelations) {
const table_A = tables[relation.model1];
const table_B = tables[relation.model2];
// Skip if both tables are undefined
if (table_A === undefined && table_B === undefined)
continue;
// Get primary key info for model1 if table_A exists
const model1PrimaryKeyInfo = table_A
? getPrimaryKeyInfo(table_A, models)
: null;
// Get primary key info for model2 if table_B exists
const model2PrimaryKeyInfo = table_B
? getPrimaryKeyInfo(table_B, models)
: null;
if (model1PrimaryKeyInfo && model2PrimaryKeyInfo) {
const model1PrimaryKeyColumnType = convertToPostgresColumnType(model1PrimaryKeyInfo.type, null, null);
const model2PrimaryKeyColumnType = convertToPostgresColumnType(model2PrimaryKeyInfo.type, null, null);
const joinTableName = createManyToManyJoinTableName(relation.model1, relation.model2);
// Create join table
tables[joinTableName] = createManyToManyJoinTable(joinTableName, model1PrimaryKeyColumnType, model2PrimaryKeyColumnType);
// Add relationships for the join table
const joinTableRelationships = createManyToManyRelationships(joinTableName, relation.model1, model1PrimaryKeyInfo.name, relation.model2, model2PrimaryKeyInfo.name);
// Add the relationships to the global relationships object
Object.assign(relationships, joinTableRelationships);
}
}
return relationships;
}
/**
* Main function to parse a Prisma schema
*/
async function parsePrismaSchema(schemaString) {
const dmmf = await getDMMF({ datamodel: schemaString });
const tableGroups = {};
const errors = [];
// Track many-to-many relationships for later processing
const processedManyToManyRelations = new Set();
const manyToManyRelations = [];
// Build field renaming map
const tableFieldRenaming = buildFieldRenamingMap(dmmf.datamodel.models);
// Process models and create tables
const tables = processTables(dmmf.datamodel.models, tableFieldRenaming);
// Process relationships
const relationships = processRelationships$1(dmmf.datamodel.models, tables, tableFieldRenaming, processedManyToManyRelations, manyToManyRelations);
// Process indexes
processIndexes$1(dmmf.datamodel.indexes, dmmf.datamodel.models, tables, tableFieldRenaming);
// Process many-to-many relationships
const manyToManyRelationships = processManyToManyRelationships(manyToManyRelations, tables, dmmf.datamodel.models);
// Merge relationships
Object.assign(relationships, manyToManyRelationships);
return {
value: {
tables,
relationships,
tableGroups,
},
errors: errors,
};
}
function extractIndex(index) {
switch (index.type) {
case 'id':
return {
name: `${index.model}_pkey`,
unique: true,
columns: index.fields.map((field) => field.name),
type: '',
};
case 'unique':
return {
name: `${index.model}_${index.fields.map((field) => field.name).join('_')}_key`,
unique: true,
columns: index.fields.map((field) => field.name),
type: '',
};
case 'normal':
return {
name: `${index.model}_${index.fields.map((field) => field.name).join('_')}_idx`,
unique: false,
columns: index.fields.map((field) => field.name),
type: index.algorithm ?? '',
};
// NOTE: fulltext index is not supported for postgres
// ref: https://www.prisma.io/docs/orm/prisma-schema/data-model/indexes#full-text-indexes-mysql-and-mongodb
case 'fulltext':
return null;
default:
return null;
}
}
function extractDefaultValue$2(field) {
const value = field.default?.valueOf();
const defaultValue = value === undefined ? null : value;
// NOTE: When `@default(autoincrement())` is specified, `defaultValue` becomes an object
// like `{"name":"autoincrement","args":[]}` (DMMF.FieldDefault).
// This function handles both primitive types (`string | number | boolean`) and objects,
// returning a string like `name(args)` for objects.
// Note: `FieldDefaultScalar[]` is not supported.
if (typeof defaultValue === 'object' && defaultValue !== null) {
if ('name' in defaultValue && 'args' in defaultValue) {
return `${defaultValue.name}(${defaultValue.args})`;
}
}
return typeof defaultValue === 'string' ||
typeof defaultValue === 'number' ||
typeof defaultValue === 'boolean'
? defaultValue
: null;
}
function normalizeConstraintName$2(constraint) {
// ref: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/referential-actions
switch (constraint) {
case 'Cascade':
return 'CASCADE';
case 'Restrict':
return 'RESTRICT';
case 'SetNull':
return 'SET_NULL';
case 'SetDefault':
return 'SET_DEFAULT';
default:
return 'NO_ACTION';
}
}
/**
* Creates the name for a many-to-many join table
*/
function createManyToManyJoinTableName(model1, model2) {
return `_${model1}To${model2}`;
}
/**
* Creates a join table for a many-to-many relationship
*/
function createManyToManyJoinTable(joinTableName, table_A_ColumnType, table_B_ColumnType) {
return {
name: joinTableName,
constraints: {},
columns: {
A: {
name: 'A',
type: table_A_ColumnType,
default: null,
notNull: true,
unique: false,
primary: false,
comment: null,
check: null,
},
B: {
name: 'B',
type: table_B_ColumnType,
default: null,
notNull: true,
unique: false,
primary: false,
comment: null,
check: null,
},
},
comment: null,
indexes: {
[`${joinTableName}_AB_pkey`]: {
name: `${joinTableName}_AB_pkey`,
unique: true,
columns: ['A', 'B'],
type: '',
},
[`${joinTableName}_B_index`]: {
name: `${joinTableName}_B_index`,
unique: false,
columns: ['B'],
type: '',
},
},
};
}
/**
* Creates relationships for a many-to-many join table
*/
function createManyToManyRelationships(joinTableName, model1, primaryColumnNameOfA, model2, primaryColumnNameOfB) {
return {
[`${joinTableName}_A_fkey`]: {
name: `${joinTableName}_A_fkey`,
primaryTableName: model1,
primaryColumnName: primaryColumnNameOfA,
foreignTableName: joinTableName,
foreignColumnName: 'A',
cardinality: 'ONE_TO_MANY',
updateConstraint: 'CASCADE',
deleteConstraint: 'CASCADE',
},
[`${joinTableName}_B_fkey`]: {
name: `${joinTableName}_B_fkey`,
primaryTableName: model2,
primaryColumnName: primaryColumnNameOfB,
foreignTableName: joinTableName,
foreignColumnName: 'B',
cardinality: 'ONE_TO_MANY',
updateConstraint: 'CASCADE',
deleteConstraint: 'CASCADE',
},
};
}
/**
* Detects if a field is part of a many-to-many relation and stores it for later processing
*/
function isManyToManyField(field) {
return (field.isList &&
(!field.relationFromFields || field.relationFromFields.length === 0) &&
(!field.relationToFields || field.relationToFields.length === 0));
}
function findRelatedField(field, model, models) {
const relatedModel = models.find((m) => m.name === field.type);
if (!relatedModel)
return undefined;
return relatedModel.fields.find((f) => f.relationName === field.relationName &&
f.isList &&
f.type === model.name);
}
function getSortedModelPair(model1, model2) {
return model1.localeCompare(model2) < 0 ? [model1, model2] : [model2, model1];
}
function storeManyToManyRelation(model1, model2, field1, field2, processedRelations, manyToManyRelations) {
const [sortedModel1, sortedModel2] = getSortedModelPair(model1, model2);
const relationId = `${sortedModel1}_${sortedModel2}`;
if (!processedRelations.has(relationId)) {
processedRelations.add(relationId);
manyToManyRelations.push({
model1: sortedModel1,
model2: sortedModel2,
field1: field1,
field2: field2,
});
}
}
function detectAndStoreManyToManyRelation(field, model, models, processedRelations, manyToManyRelations) {
if (!isManyToManyField(field))
return false;
const relatedField = findRelatedField(field, model, models);
if (!relatedField)
return false;
storeManyToManyRelation(model.name, field.type, field, relatedField, processedRelations, manyToManyRelations);
return true;
}
function getPrimaryKeyInfo(table, models) {
const tableName = table?.name;
const model = models.find((m) => m.name === tableName);
if (!model) {
return null; // or throw an error if model is required
}
const tableIndexes = table?.indexes;
const primaryKeyIndex = tableIndexes[`${tableName}_pkey`];
const primaryKeyColumnName = primaryKeyIndex?.columns[0];
if (!primaryKeyColumnName) {
return null; // no primary key found
}
// Find the field in the model that matches the primary key column name
const primaryKeyField = model.fields.find((field) => field.name === primaryKeyColumnName ||
field.dbName === primaryKeyColumnName);
return primaryKeyField;
}
const processor$3 = (str) => parsePrismaSchema(str);
/*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not */
/* be modified manually. See */
/* templates/javascript/src/visitor.js.erb */
/* if you are looking to modify the */
/* template */
/*----------------------------------------------------------------------------*/
/**
* A class that knows how to walk down the tree. None of the individual visit
* methods are implemented on this visitor, so it forces the consumer to
* implement each one that they need. For a default implementation that
* continues walking the tree, see the `Visitor` class.
*
*/
class BasicVisitor {
/**
* Calls `accept` on the given node if it is not `null`, which in turn should
* call back into this visitor by calling the appropriate `visit*` method.
*
* @param {nodes.Node} node
*/
visit(node) {
node?.accept(this);
}
/**
* Visits each node in `nodes` by calling `accept` on each one.
*
* @param {nodes.Node[]} nodes
*/
visitAll(nodes) {
nodes.forEach((node) => {
node?.accept(this);
});
}
/**
* Visits the child nodes of `node` by calling `accept` on each one.
*
* @param {nodes.Node} node
*/
visitChildNodes(node) {
node.compactChildNodes().forEach((childNode) => {
childNode.accept(this);
});
}
}
/**
* A visitor is a class that provides a default implementation for every accept
* method defined on the nodes. This means it can walk a tree without the
* caller needing to define any special handling. This allows you to handle a
* subset of the tree, while still walking the whole tree.
*
* For example, to find all of the method calls that call the `foo` method, you
* could write:
*
* @example
* class FooCalls extends Visitor {
* visitCallNode(node) {
* if (node.name === "foo") {
* // Do something with the node
* }
*
* // Call super so that the visitor continues walking the tree
* super.visitCallNode(node);
* }
* }
*
*/
class Visitor extends BasicVisitor {
/**
* Visit a AliasGlobalVariableNode node.
*
* @param {nodes.AliasGlobalVariableNode} node
*/
visitAliasGlobalVariableNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a AliasMethodNode node.
*
* @param {nodes.AliasMethodNode} node
*/
visitAliasMethodNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a AlternationPatternNode node.
*
* @param {nodes.AlternationPatternNode} node
*/
visitAlternationPatternNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a AndNode node.
*
* @param {nodes.AndNode} node
*/
visitAndNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ArgumentsNode node.
*
* @param {nodes.ArgumentsNode} node
*/
visitArgumentsNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ArrayNode node.
*
* @param {nodes.ArrayNode} node
*/
visitArrayNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ArrayPatternNode node.
*
* @param {nodes.ArrayPatternNode} node
*/
visitArrayPatternNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a AssocNode node.
*
* @param {nodes.AssocNode} node
*/
visitAssocNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a AssocSplatNode node.
*
* @param {nodes.AssocSplatNode} node
*/
visitAssocSplatNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BackReferenceReadNode node.
*
* @param {nodes.BackReferenceReadNode} node
*/
visitBackReferenceReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BeginNode node.
*
* @param {nodes.BeginNode} node
*/
visitBeginNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BlockArgumentNode node.
*
* @param {nodes.BlockArgumentNode} node
*/
visitBlockArgumentNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BlockLocalVariableNode node.
*
* @param {nodes.BlockLocalVariableNode} node
*/
visitBlockLocalVariableNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BlockNode node.
*
* @param {nodes.BlockNode} node
*/
visitBlockNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BlockParameterNode node.
*
* @param {nodes.BlockParameterNode} node
*/
visitBlockParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BlockParametersNode node.
*
* @param {nodes.BlockParametersNode} node
*/
visitBlockParametersNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a BreakNode node.
*
* @param {nodes.BreakNode} node
*/
visitBreakNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CallAndWriteNode node.
*
* @param {nodes.CallAndWriteNode} node
*/
visitCallAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CallNode node.
*
* @param {nodes.CallNode} node
*/
visitCallNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CallOperatorWriteNode node.
*
* @param {nodes.CallOperatorWriteNode} node
*/
visitCallOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CallOrWriteNode node.
*
* @param {nodes.CallOrWriteNode} node
*/
visitCallOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CallTargetNode node.
*
* @param {nodes.CallTargetNode} node
*/
visitCallTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CapturePatternNode node.
*
* @param {nodes.CapturePatternNode} node
*/
visitCapturePatternNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CaseMatchNode node.
*
* @param {nodes.CaseMatchNode} node
*/
visitCaseMatchNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a CaseNode node.
*
* @param {nodes.CaseNode} node
*/
visitCaseNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassNode node.
*
* @param {nodes.ClassNode} node
*/
visitClassNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassVariableAndWriteNode node.
*
* @param {nodes.ClassVariableAndWriteNode} node
*/
visitClassVariableAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassVariableOperatorWriteNode node.
*
* @param {nodes.ClassVariableOperatorWriteNode} node
*/
visitClassVariableOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassVariableOrWriteNode node.
*
* @param {nodes.ClassVariableOrWriteNode} node
*/
visitClassVariableOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassVariableReadNode node.
*
* @param {nodes.ClassVariableReadNode} node
*/
visitClassVariableReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassVariableTargetNode node.
*
* @param {nodes.ClassVariableTargetNode} node
*/
visitClassVariableTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ClassVariableWriteNode node.
*
* @param {nodes.ClassVariableWriteNode} node
*/
visitClassVariableWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantAndWriteNode node.
*
* @param {nodes.ConstantAndWriteNode} node
*/
visitConstantAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantOperatorWriteNode node.
*
* @param {nodes.ConstantOperatorWriteNode} node
*/
visitConstantOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantOrWriteNode node.
*
* @param {nodes.ConstantOrWriteNode} node
*/
visitConstantOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantPathAndWriteNode node.
*
* @param {nodes.ConstantPathAndWriteNode} node
*/
visitConstantPathAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantPathNode node.
*
* @param {nodes.ConstantPathNode} node
*/
visitConstantPathNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantPathOperatorWriteNode node.
*
* @param {nodes.ConstantPathOperatorWriteNode} node
*/
visitConstantPathOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantPathOrWriteNode node.
*
* @param {nodes.ConstantPathOrWriteNode} node
*/
visitConstantPathOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantPathTargetNode node.
*
* @param {nodes.ConstantPathTargetNode} node
*/
visitConstantPathTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantPathWriteNode node.
*
* @param {nodes.ConstantPathWriteNode} node
*/
visitConstantPathWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantReadNode node.
*
* @param {nodes.ConstantReadNode} node
*/
visitConstantReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantTargetNode node.
*
* @param {nodes.ConstantTargetNode} node
*/
visitConstantTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ConstantWriteNode node.
*
* @param {nodes.ConstantWriteNode} node
*/
visitConstantWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a DefNode node.
*
* @param {nodes.DefNode} node
*/
visitDefNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a DefinedNode node.
*
* @param {nodes.DefinedNode} node
*/
visitDefinedNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ElseNode node.
*
* @param {nodes.ElseNode} node
*/
visitElseNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a EmbeddedStatementsNode node.
*
* @param {nodes.EmbeddedStatementsNode} node
*/
visitEmbeddedStatementsNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a EmbeddedVariableNode node.
*
* @param {nodes.EmbeddedVariableNode} node
*/
visitEmbeddedVariableNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a EnsureNode node.
*
* @param {nodes.EnsureNode} node
*/
visitEnsureNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a FalseNode node.
*
* @param {nodes.FalseNode} node
*/
visitFalseNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a FindPatternNode node.
*
* @param {nodes.FindPatternNode} node
*/
visitFindPatternNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a FlipFlopNode node.
*
* @param {nodes.FlipFlopNode} node
*/
visitFlipFlopNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a FloatNode node.
*
* @param {nodes.FloatNode} node
*/
visitFloatNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ForNode node.
*
* @param {nodes.ForNode} node
*/
visitForNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ForwardingArgumentsNode node.
*
* @param {nodes.ForwardingArgumentsNode} node
*/
visitForwardingArgumentsNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ForwardingParameterNode node.
*
* @param {nodes.ForwardingParameterNode} node
*/
visitForwardingParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ForwardingSuperNode node.
*
* @param {nodes.ForwardingSuperNode} node
*/
visitForwardingSuperNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a GlobalVariableAndWriteNode node.
*
* @param {nodes.GlobalVariableAndWriteNode} node
*/
visitGlobalVariableAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a GlobalVariableOperatorWriteNode node.
*
* @param {nodes.GlobalVariableOperatorWriteNode} node
*/
visitGlobalVariableOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a GlobalVariableOrWriteNode node.
*
* @param {nodes.GlobalVariableOrWriteNode} node
*/
visitGlobalVariableOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a GlobalVariableReadNode node.
*
* @param {nodes.GlobalVariableReadNode} node
*/
visitGlobalVariableReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a GlobalVariableTargetNode node.
*
* @param {nodes.GlobalVariableTargetNode} node
*/
visitGlobalVariableTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a GlobalVariableWriteNode node.
*
* @param {nodes.GlobalVariableWriteNode} node
*/
visitGlobalVariableWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a HashNode node.
*
* @param {nodes.HashNode} node
*/
visitHashNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a HashPatternNode node.
*
* @param {nodes.HashPatternNode} node
*/
visitHashPatternNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a IfNode node.
*
* @param {nodes.IfNode} node
*/
visitIfNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ImaginaryNode node.
*
* @param {nodes.ImaginaryNode} node
*/
visitImaginaryNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ImplicitNode node.
*
* @param {nodes.ImplicitNode} node
*/
visitImplicitNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ImplicitRestNode node.
*
* @param {nodes.ImplicitRestNode} node
*/
visitImplicitRestNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InNode node.
*
* @param {nodes.InNode} node
*/
visitInNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a IndexAndWriteNode node.
*
* @param {nodes.IndexAndWriteNode} node
*/
visitIndexAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a IndexOperatorWriteNode node.
*
* @param {nodes.IndexOperatorWriteNode} node
*/
visitIndexOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a IndexOrWriteNode node.
*
* @param {nodes.IndexOrWriteNode} node
*/
visitIndexOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a IndexTargetNode node.
*
* @param {nodes.IndexTargetNode} node
*/
visitIndexTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InstanceVariableAndWriteNode node.
*
* @param {nodes.InstanceVariableAndWriteNode} node
*/
visitInstanceVariableAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InstanceVariableOperatorWriteNode node.
*
* @param {nodes.InstanceVariableOperatorWriteNode} node
*/
visitInstanceVariableOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InstanceVariableOrWriteNode node.
*
* @param {nodes.InstanceVariableOrWriteNode} node
*/
visitInstanceVariableOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InstanceVariableReadNode node.
*
* @param {nodes.InstanceVariableReadNode} node
*/
visitInstanceVariableReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InstanceVariableTargetNode node.
*
* @param {nodes.InstanceVariableTargetNode} node
*/
visitInstanceVariableTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InstanceVariableWriteNode node.
*
* @param {nodes.InstanceVariableWriteNode} node
*/
visitInstanceVariableWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a IntegerNode node.
*
* @param {nodes.IntegerNode} node
*/
visitIntegerNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InterpolatedMatchLastLineNode node.
*
* @param {nodes.InterpolatedMatchLastLineNode} node
*/
visitInterpolatedMatchLastLineNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InterpolatedRegularExpressionNode node.
*
* @param {nodes.InterpolatedRegularExpressionNode} node
*/
visitInterpolatedRegularExpressionNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InterpolatedStringNode node.
*
* @param {nodes.InterpolatedStringNode} node
*/
visitInterpolatedStringNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InterpolatedSymbolNode node.
*
* @param {nodes.InterpolatedSymbolNode} node
*/
visitInterpolatedSymbolNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a InterpolatedXStringNode node.
*
* @param {nodes.InterpolatedXStringNode} node
*/
visitInterpolatedXStringNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ItLocalVariableReadNode node.
*
* @param {nodes.ItLocalVariableReadNode} node
*/
visitItLocalVariableReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ItParametersNode node.
*
* @param {nodes.ItParametersNode} node
*/
visitItParametersNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a KeywordHashNode node.
*
* @param {nodes.KeywordHashNode} node
*/
visitKeywordHashNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a KeywordRestParameterNode node.
*
* @param {nodes.KeywordRestParameterNode} node
*/
visitKeywordRestParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LambdaNode node.
*
* @param {nodes.LambdaNode} node
*/
visitLambdaNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LocalVariableAndWriteNode node.
*
* @param {nodes.LocalVariableAndWriteNode} node
*/
visitLocalVariableAndWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LocalVariableOperatorWriteNode node.
*
* @param {nodes.LocalVariableOperatorWriteNode} node
*/
visitLocalVariableOperatorWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LocalVariableOrWriteNode node.
*
* @param {nodes.LocalVariableOrWriteNode} node
*/
visitLocalVariableOrWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LocalVariableReadNode node.
*
* @param {nodes.LocalVariableReadNode} node
*/
visitLocalVariableReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LocalVariableTargetNode node.
*
* @param {nodes.LocalVariableTargetNode} node
*/
visitLocalVariableTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a LocalVariableWriteNode node.
*
* @param {nodes.LocalVariableWriteNode} node
*/
visitLocalVariableWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MatchLastLineNode node.
*
* @param {nodes.MatchLastLineNode} node
*/
visitMatchLastLineNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MatchPredicateNode node.
*
* @param {nodes.MatchPredicateNode} node
*/
visitMatchPredicateNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MatchRequiredNode node.
*
* @param {nodes.MatchRequiredNode} node
*/
visitMatchRequiredNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MatchWriteNode node.
*
* @param {nodes.MatchWriteNode} node
*/
visitMatchWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MissingNode node.
*
* @param {nodes.MissingNode} node
*/
visitMissingNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ModuleNode node.
*
* @param {nodes.ModuleNode} node
*/
visitModuleNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MultiTargetNode node.
*
* @param {nodes.MultiTargetNode} node
*/
visitMultiTargetNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a MultiWriteNode node.
*
* @param {nodes.MultiWriteNode} node
*/
visitMultiWriteNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a NextNode node.
*
* @param {nodes.NextNode} node
*/
visitNextNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a NilNode node.
*
* @param {nodes.NilNode} node
*/
visitNilNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a NoKeywordsParameterNode node.
*
* @param {nodes.NoKeywordsParameterNode} node
*/
visitNoKeywordsParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a NumberedParametersNode node.
*
* @param {nodes.NumberedParametersNode} node
*/
visitNumberedParametersNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a NumberedReferenceReadNode node.
*
* @param {nodes.NumberedReferenceReadNode} node
*/
visitNumberedReferenceReadNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a OptionalKeywordParameterNode node.
*
* @param {nodes.OptionalKeywordParameterNode} node
*/
visitOptionalKeywordParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a OptionalParameterNode node.
*
* @param {nodes.OptionalParameterNode} node
*/
visitOptionalParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a OrNode node.
*
* @param {nodes.OrNode} node
*/
visitOrNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ParametersNode node.
*
* @param {nodes.ParametersNode} node
*/
visitParametersNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ParenthesesNode node.
*
* @param {nodes.ParenthesesNode} node
*/
visitParenthesesNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a PinnedExpressionNode node.
*
* @param {nodes.PinnedExpressionNode} node
*/
visitPinnedExpressionNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a PinnedVariableNode node.
*
* @param {nodes.PinnedVariableNode} node
*/
visitPinnedVariableNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a PostExecutionNode node.
*
* @param {nodes.PostExecutionNode} node
*/
visitPostExecutionNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a PreExecutionNode node.
*
* @param {nodes.PreExecutionNode} node
*/
visitPreExecutionNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ProgramNode node.
*
* @param {nodes.ProgramNode} node
*/
visitProgramNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RangeNode node.
*
* @param {nodes.RangeNode} node
*/
visitRangeNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RationalNode node.
*
* @param {nodes.RationalNode} node
*/
visitRationalNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RedoNode node.
*
* @param {nodes.RedoNode} node
*/
visitRedoNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RegularExpressionNode node.
*
* @param {nodes.RegularExpressionNode} node
*/
visitRegularExpressionNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RequiredKeywordParameterNode node.
*
* @param {nodes.RequiredKeywordParameterNode} node
*/
visitRequiredKeywordParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RequiredParameterNode node.
*
* @param {nodes.RequiredParameterNode} node
*/
visitRequiredParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RescueModifierNode node.
*
* @param {nodes.RescueModifierNode} node
*/
visitRescueModifierNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RescueNode node.
*
* @param {nodes.RescueNode} node
*/
visitRescueNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RestParameterNode node.
*
* @param {nodes.RestParameterNode} node
*/
visitRestParameterNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a RetryNode node.
*
* @param {nodes.RetryNode} node
*/
visitRetryNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ReturnNode node.
*
* @param {nodes.ReturnNode} node
*/
visitReturnNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SelfNode node.
*
* @param {nodes.SelfNode} node
*/
visitSelfNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a ShareableConstantNode node.
*
* @param {nodes.ShareableConstantNode} node
*/
visitShareableConstantNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SingletonClassNode node.
*
* @param {nodes.SingletonClassNode} node
*/
visitSingletonClassNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SourceEncodingNode node.
*
* @param {nodes.SourceEncodingNode} node
*/
visitSourceEncodingNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SourceFileNode node.
*
* @param {nodes.SourceFileNode} node
*/
visitSourceFileNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SourceLineNode node.
*
* @param {nodes.SourceLineNode} node
*/
visitSourceLineNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SplatNode node.
*
* @param {nodes.SplatNode} node
*/
visitSplatNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a StatementsNode node.
*
* @param {nodes.StatementsNode} node
*/
visitStatementsNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a StringNode node.
*
* @param {nodes.StringNode} node
*/
visitStringNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SuperNode node.
*
* @param {nodes.SuperNode} node
*/
visitSuperNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a SymbolNode node.
*
* @param {nodes.SymbolNode} node
*/
visitSymbolNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a TrueNode node.
*
* @param {nodes.TrueNode} node
*/
visitTrueNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a UndefNode node.
*
* @param {nodes.UndefNode} node
*/
visitUndefNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a UnlessNode node.
*
* @param {nodes.UnlessNode} node
*/
visitUnlessNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a UntilNode node.
*
* @param {nodes.UntilNode} node
*/
visitUntilNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a WhenNode node.
*
* @param {nodes.WhenNode} node
*/
visitWhenNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a WhileNode node.
*
* @param {nodes.WhileNode} node
*/
visitWhileNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a XStringNode node.
*
* @param {nodes.XStringNode} node
*/
visitXStringNode(node) {
this.visitChildNodes(node);
}
/**
* Visit a YieldNode node.
*
* @param {nodes.YieldNode} node
*/
visitYieldNode(node) {
this.visitChildNodes(node);
}
}
/*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not */
/* be modified manually. See */
/* templates/javascript/src/nodes.js.erb *