kanel-kysely
Version:
Kysely extension for Kanel
151 lines (150 loc) • 6.58 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* This is a quirky way to get Kysely interfaces. Basically, what happens is that this
* hook will filter out initializer and mutators. It takes the selector and transforms
* it into the Kysely *Table interface, by going over each property. In the end,
* it adds the New* and *Update types as per the Kysely documentation.
*
* This only works when the output from Kanel is close to the default configuration,
* if you've changed things around too much it will probably not work.
*/
const processFile = (declarations, compositeDetails, instantiatedConfig, path, makeKyselyConfig) => {
const { name: selectorName } = instantiatedConfig.getMetadata(compositeDetails, "selector", instantiatedConfig);
const { name: initializerName } = instantiatedConfig.getMetadata(compositeDetails, "initializer", instantiatedConfig);
const { name: mutatorName } = instantiatedConfig.getMetadata(compositeDetails, "mutator", instantiatedConfig);
let canInitialize = true;
let canMutate = true;
if (compositeDetails.kind !== "table" &&
compositeDetails.kind !== "compositeType") {
canInitialize = false;
canMutate = false;
}
const { tableInterfaceName, selectableName, insertableName, updatableName } = makeKyselyConfig.getKyselyItemMetadata(compositeDetails, selectorName, canInitialize, canMutate, instantiatedConfig);
const modifiedDeclarations = declarations.map((declaration) => {
if (declaration.declarationType === "interface") {
if (declaration.name === selectorName) {
const name = tableInterfaceName;
const typeImports = [...(declaration.typeImports || [])];
typeImports.push({
name: "ColumnType",
isDefault: false,
path: "kysely",
isAbsolute: true,
importAsType: true,
});
const properties = declaration.properties.map((property) => {
const columns = compositeDetails.kind === "compositeType"
? compositeDetails.attributes
: compositeDetails.columns;
const column = columns.find((column) => instantiatedConfig.getPropertyMetadata(column, compositeDetails, "selector", instantiatedConfig).name === property.name);
let baseType = property.typeName;
baseType += "[]".repeat(property.dimensions);
let selectorType = baseType;
if (property.isNullable) {
selectorType = `${selectorType} | null`;
}
let initializerType = "never";
if (canInitialize && column.generated !== "ALWAYS") {
if (baseType === "Date") {
baseType += " | string";
}
initializerType = baseType;
if (column.isNullable) {
initializerType += " | null";
}
else if (column.defaultValue ||
column.isIdentity ||
column.generated === "BY DEFAULT") {
initializerType += " | undefined";
}
}
let mutatorType = "never";
if (canMutate && column.generated !== "ALWAYS") {
mutatorType = column.isNullable ? `${baseType} | null` : baseType;
}
const typeName = `ColumnType<${selectorType}, ${initializerType}, ${mutatorType}>`;
return { ...property, typeName, dimensions: 0, isNullable: false };
});
return { ...declaration, name, properties, typeImports };
}
else if (declaration.name === initializerName) {
// Remove the initializer. We're creating a `New${x}` type below
return undefined;
// Remove the mutator. We're creating a `${x}Update` type below
}
else if (declaration.name === mutatorName) {
return undefined;
}
}
return declaration;
});
const result = modifiedDeclarations.filter(Boolean);
result.push({
declarationType: "typeDeclaration",
name: selectableName,
typeImports: [
{
name: "Selectable",
isDefault: false,
path: "kysely",
isAbsolute: true,
importAsType: true,
},
],
typeDefinition: [`Selectable<${tableInterfaceName}>`],
exportAs: "named",
});
if (compositeDetails.kind !== "compositeType") {
if (insertableName) {
result.push({
declarationType: "typeDeclaration",
name: insertableName,
typeImports: [
{
name: "Insertable",
isDefault: false,
path: "kysely",
isAbsolute: true,
importAsType: true,
},
],
typeDefinition: [`Insertable<${tableInterfaceName}>`],
exportAs: "named",
});
}
if (updatableName) {
result.push({
declarationType: "typeDeclaration",
name: updatableName,
typeImports: [
{
name: "Updateable",
isDefault: false,
path: "kysely",
isAbsolute: true,
importAsType: true,
},
],
typeDefinition: [`Updateable<${tableInterfaceName}>`],
exportAs: "named",
});
}
}
const tableImport = {
name: tableInterfaceName,
isDefault: true,
path,
isAbsolute: false,
importAsType: true,
};
const tableProperty = {
name: compositeDetails.name,
typeName: tableImport.name,
dimensions: 0,
isNullable: false,
isOptional: false,
};
return { modifiedDeclarations: result, tableImport, tableProperty };
};
exports.default = processFile;