-
-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kysely schemas are not separated #620
Comments
this seems to address the problem:
|
just for reference here's my final config which also addresses naming conflicts between schemas as discussed in this issue: #589 const { makeKyselyHook } = require("kanel-kysely");
const path = require("path");
async function prefixTableNamesWithSchema(path, lines, instantiatedConfig) {
if (!path.endsWith("Schema.ts")) {
return lines;
}
const pathSegments = path.split("/");
const schemaName = pathSegments[pathSegments.length - 2];
const propertyEntryRegex = /^(\s*)(\w+): (\w+);$/;
return lines.map(line => {
const match = line.match(propertyEntryRegex);
if (match) {
const [_, indentation, propertyName, propertyType] = match;
const newPropertyName = `'${schemaName}.${propertyName}'`;
const newLine = `${indentation}${newPropertyName}: ${propertyType};`;
return newLine;
}
return line;
});
}
async function resolveDuplicateImports(filePath, lines, instantiatedConfig) {
const imports = [];
const importRegex = /^import type { (\w+) } from ['"](.+)['"];$/;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const match = line.match(importRegex);
if (match) {
const [_, importedIdentifier, modulePath] = match;
imports.push({ lineIndex: i, importedIdentifier, modulePath });
}
}
const importMap = {};
for (const imp of imports) {
const { importedIdentifier, modulePath } = imp;
if (!importMap[importedIdentifier]) {
importMap[importedIdentifier] = [];
}
importMap[importedIdentifier].push(modulePath);
}
const duplicates = {};
for (const importedIdentifier in importMap) {
const modulePaths = importMap[importedIdentifier];
if (modulePaths.length > 1) {
duplicates[importedIdentifier] = modulePaths;
}
}
if (Object.keys(duplicates).length === 0) {
return lines;
}
const aliases = {};
const schemaToAlias = {};
for (const importedIdentifier in duplicates) {
schemaToAlias[importedIdentifier] = {};
const modulePaths = duplicates[importedIdentifier];
for (const modulePath of modulePaths) {
const absoluteModulePath = path.resolve(
path.dirname(filePath),
modulePath
);
const schemaName = getSchemaNameFromModulePath(absoluteModulePath);
const alias = importedIdentifier + capitalize(schemaName);
aliases[importedIdentifier + "|" + modulePath] = alias;
schemaToAlias[importedIdentifier][schemaName] = alias;
}
}
for (const imp of imports) {
const { lineIndex, importedIdentifier, modulePath } = imp;
if (duplicates[importedIdentifier]) {
const alias = aliases[importedIdentifier + "|" + modulePath];
lines[lineIndex] =
`import type { ${importedIdentifier} as ${alias} } from '${modulePath}';`;
}
}
function capitalize(str) {
if (!str) return str;
return str.charAt(0).toUpperCase() + str.slice(1);
}
function getSchemaNameFromModulePath(absoluteModulePath) {
const pathSegments = absoluteModulePath.split(path.sep);
const modelsIndex = pathSegments.lastIndexOf("models");
if (modelsIndex >= 0 && modelsIndex + 1 < pathSegments.length) {
const schemaName = pathSegments[modelsIndex + 1];
return schemaName;
}
return null;
}
function getSchemaNameFromPropertyName(propertyName) {
const prefix = propertyName.split("_")[0];
return prefix;
}
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.startsWith("import")) continue;
const propertyMatch = line.match(/^\s*(\w+):\s*ColumnType<(.+)>;$/);
if (propertyMatch) {
const propertyName = propertyMatch[1];
const columnTypeContent = propertyMatch[2];
const types = columnTypeContent.split(",").map(t => t.trim());
const updatedTypes = types.map(type => {
if (duplicates[type]) {
const schemaName = getSchemaNameFromPropertyName(propertyName);
const alias = schemaToAlias[type][schemaName];
if (alias) {
return alias;
} else {
return type;
}
} else {
return type;
}
});
const updatedColumnTypeContent = updatedTypes.join(", ");
lines[i] = ` ${propertyName}: ColumnType<${updatedColumnTypeContent}>;`;
}
}
return lines;
}
module.exports = {
importsExtension: ".js",
preRenderHooks: [makeKyselyHook()],
postRenderHooks: [prefixTableNamesWithSchema, resolveDuplicateImports],
}; |
Awesome! I think this is the most complex custom hook I've seen here so far :-) |
yeah.. it's pretty hacky, but it gets the job done :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it seems that kanel-kysely normally merges schemas together in the Database type which make it difficult to know which table is from which schema. How can I adjust my config so that this
is turned into
I'm getting this updated type based off of kysely's instructions on how to deal with schemas: https://kysely.dev/docs/recipes/schemas
The text was updated successfully, but these errors were encountered: