joist-codegen 2.4.0-next.2 → 2.4.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/EntityDbMetadata.cjs +5 -3
- package/build/EntityDbMetadata.cjs.map +1 -1
- package/build/EntityDbMetadata.d.cts +2 -0
- package/build/EntityDbMetadata.d.cts.map +1 -1
- package/build/EntityDbMetadata.d.mts +2 -0
- package/build/EntityDbMetadata.d.mts.map +1 -1
- package/build/EntityDbMetadata.js +5 -3
- package/build/EntityDbMetadata.js.map +1 -1
- package/build/config.cjs +1 -1
- package/build/config.cjs.map +1 -1
- package/build/config.js +1 -1
- package/build/config.js.map +1 -1
- package/build/generateEntityCodegenFile.cjs +5 -3
- package/build/generateEntityCodegenFile.cjs.map +1 -1
- package/build/generateEntityCodegenFile.d.cts.map +1 -1
- package/build/generateEntityCodegenFile.d.mts.map +1 -1
- package/build/generateEntityCodegenFile.js +5 -3
- package/build/generateEntityCodegenFile.js.map +1 -1
- package/build/generateMetadataFile.cjs +2 -1
- package/build/generateMetadataFile.cjs.map +1 -1
- package/build/generateMetadataFile.d.cts.map +1 -1
- package/build/generateMetadataFile.d.mts.map +1 -1
- package/build/generateMetadataFile.js +2 -1
- package/build/generateMetadataFile.js.map +1 -1
- package/build/scanEntityFiles.cjs +6 -1
- package/build/scanEntityFiles.cjs.map +1 -1
- package/build/scanEntityFiles.d.cts +1 -1
- package/build/scanEntityFiles.d.cts.map +1 -1
- package/build/scanEntityFiles.d.mts +1 -1
- package/build/scanEntityFiles.d.mts.map +1 -1
- package/build/scanEntityFiles.js +6 -1
- package/build/scanEntityFiles.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityDbMetadata.js","names":[],"sources":["../src/EntityDbMetadata.ts"],"sourcesContent":["import { camelCase, pascalCase, snakeCase } from \"change-case\";\nimport { groupBy } from \"joist-utils\";\nimport pluralize from \"pluralize\";\nimport { type Code, Import, code, imp } from \"ts-poet\";\n\nimport {\n type Config,\n fieldTypeConfig,\n getTimestampConfig,\n isFieldHasDefault,\n isFieldIgnored,\n isGetterField,\n isLargeCollection,\n isLazyField,\n isProtected,\n isReactiveField,\n isReactiveManyToMany,\n isReactiveReference,\n ormMaintainedFields,\n serdeConfig,\n softDeletesConfig,\n superstructConfig,\n zodSchemaConfig,\n} from \"./config.ts\";\nimport { type EnumMetadata, type EnumRow, type PgEnumMetadata } from \"./loadMetadata.ts\";\nimport {\n type Action,\n type Column,\n EnumType,\n type Index,\n type JSONData,\n type M2MRelation,\n M2ORelation,\n type O2MRelation,\n type Table,\n} from \"./pgMetadata.ts\";\nimport { Zod } from \"./symbols.ts\";\nimport {\n fail,\n isEnumTable,\n isJoinTable,\n isSubClassTable,\n joinTableHasId,\n mapSimpleDbTypeToTypescriptType,\n parseOrder,\n tableToEntityName,\n} from \"./utils.ts\";\n\nconst { plural, singular } = pluralize;\n\n/** All the entities + enums in our database. */\nexport interface DbMetadata {\n entities: EntityDbMetadata[];\n /** Type name i.e. `Author` to metadata. */\n entitiesByName: Record<string, EntityDbMetadata>;\n enums: EnumMetadata;\n pgEnums: PgEnumMetadata;\n joinTables: string[];\n /** Other non-joist tables in the schema. */\n otherTables: string[];\n totalTables: number;\n}\n\n/** Codegen-time metadata about a given domain entity. */\nexport type Entity = {\n name: string;\n /** The _type_ symbol pointing to the entity itself. */\n type: Import;\n /** The symbol pointing to the entity itself. */\n typeSymbol: Import;\n /** The symbol pointing to the entity itself, directly rather than via entities.ts */\n typeForMetadataFile: Import;\n /** The name of the entity's runtime metadata const. */\n metaName: string;\n /** The symbol pointing to the entity's runtime metadata const. */\n metaType: Import;\n /** The symbol pointing to the entity's EntityId type. */\n idType: Import;\n /** The symbol pointing to the entity's Order type. */\n orderType: Import;\n /** The symbol pointing to the entity's config const. */\n configConst: Import;\n optsType: Import;\n // The names of the entity's codegen'd types, i.e. `AuthorId`, that `resolveNameConflicts` rewrites\n // to `Author_Id` when they would collide with another entity/enum name. The `Import`s above\n // (`idType`/`orderType`/`optsType`) are rebuilt to match when that happens.\n /** i.e. `AuthorId` (or `Author_Id` on conflict). */\n idName: string;\n /** i.e. `AuthorFields`. */\n fieldsName: string;\n /** i.e. `AuthorOpts`. */\n optsName: string;\n /** i.e. `AuthorIdsOpts`. */\n idsOptsName: string;\n /** i.e. `AuthorFilter`. */\n filterName: string;\n /** i.e. `AuthorGraphQLFilter`. */\n graphqlFilterName: string;\n /** i.e. `AuthorOrder`. */\n orderName: string;\n /** i.e. `AuthorFactoryExtras`. */\n factoryExtrasName: string;\n /** i.e. `AuthorScope`. */\n scopeName: string;\n /** i.e. `AuthorScopes`. */\n scopesName: string;\n};\n\nexport type DatabaseColumnType =\n | \"boolean\"\n | \"int\"\n | \"uuid\"\n | \"numeric\"\n | \"smallint\"\n | \"integer\"\n | \"bigint\"\n | \"decimal\"\n | \"real\"\n | \"smallserial\"\n | \"serial\"\n | \"bigserial\"\n | \"double precision\"\n | \"text\"\n | \"citext\"\n | \"character varying\"\n | \"varchar\"\n | \"time without time zone\"\n | \"timestamp with time zone\"\n | \"timestamp without time zone\"\n | \"date\"\n | \"jsonb\"\n | \"bytea\"\n | \"tsvector\"\n | \"tstzrange\";\n\n/**\n * A logical entity field.\n *\n * I.e. it may be a physical db column, or multiple physical db columns, or a \"virtual\" field like\n * the one-to-many collection side of a many-to-one foreign key. */\ninterface Field {\n fieldName: string;\n ignore?: boolean;\n}\n\nexport type PrimitiveTypescriptType = \"boolean\" | \"string\" | \"number\" | \"Object\" | \"bigint\" | \"Uint8Array\" | Code;\n\nexport type PrimitiveField = Field & {\n kind: \"primitive\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnType: DatabaseColumnType;\n columnDefault: number | boolean | string | null;\n columnGenerated: boolean;\n /** Database nullability, unchanged by domain inheritance specialization. */\n columnNotNull: boolean;\n // The fieldType might be code for jsonb columns or primitive array columns, i.e. string[]\n fieldType: PrimitiveTypescriptType | Import;\n rawFieldType: PrimitiveTypescriptType;\n notNull: boolean;\n derived: \"orm\" | \"sync\" | \"async\" | false;\n protected: boolean;\n unique: boolean;\n superstruct: Import | undefined;\n zodSchema: Import | undefined;\n customSerde: Import | undefined;\n isArray: boolean;\n hasConfigDefault: boolean;\n lazy?: boolean;\n};\n\nexport type EnumField = Field & {\n kind: \"enum\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnType: DatabaseColumnType;\n columnDefault: number | boolean | string | null;\n columnGenerated: boolean;\n columnNotNull: boolean;\n derived: \"sync\" | \"async\" | false;\n enumName: string;\n enumType: Import;\n enumDetailType: Import;\n enumDetailsType: Import;\n enumRows: EnumRow[];\n notNull: boolean;\n isArray: boolean;\n hasConfigDefault: boolean;\n};\n\nexport type PgEnumField = Field & {\n kind: \"pg-enum\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnDefault: number | boolean | string | null;\n columnGenerated: boolean;\n columnNotNull: boolean;\n /** I.e. `favorite_shape`. */\n dbType: string;\n /** I.e. `FavoriteShape`. */\n enumName: string;\n enumType: Import;\n enumValues: string[];\n notNull: boolean;\n hasConfigDefault: boolean;\n};\n\n/** I.e. a `Book.author` reference pointing to an `Author`. */\nexport type ManyToOneField = Field & {\n kind: \"m2o\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnDefault?: number | boolean | string | null;\n columnGenerated: boolean;\n columnNotNull: boolean;\n dbType: string;\n otherFieldName: string;\n otherEntity: Entity;\n notNull: boolean;\n isDeferredAndDeferrable: boolean;\n constraintName: string;\n derived: \"async\" | false;\n hasConfigDefault: boolean;\n onDelete: Action;\n};\n\n/** I.e. a `Author.books` collection. */\nexport type OneToManyField = Field & {\n kind: \"o2m\";\n singularName: string;\n otherEntity: Entity;\n otherFieldName: string;\n otherColumnName: string;\n otherColumnNotNull: boolean;\n isLargeCollection: boolean;\n orderBy: { field: string; direction: \"ASC\" | \"DESC\" } | undefined;\n softDeletes: \"include\" | \"exclude\" | undefined;\n};\n\n/** I.e. a `Author.image` reference when `image.author_id` is unique. */\nexport type OneToOneField = Field & {\n kind: \"o2o\";\n otherEntity: Entity;\n otherFieldName: string;\n otherColumnName: string;\n otherColumnNotNull: boolean;\n};\n\nexport type ManyToManyField = Field & {\n kind: \"m2m\";\n joinTableName: string;\n singularName: string;\n columnName: string;\n otherEntity: Entity;\n otherFieldName: string;\n otherColumnName: string;\n isLargeCollection: boolean;\n isDeferredAndDeferrable: boolean;\n derived: \"async\" | \"otherSide\" | false;\n softDeletes: \"include\" | \"exclude\" | undefined;\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\n/** I.e. a `Publisher.logoColors` m2m to the `color` enum table, backed by `publisher_logo_colors`. */\nexport type ManyToManyEnumField = Field & {\n kind: \"m2mEnum\";\n joinTableName: string;\n /** The entity's FK column, e.g. `publisher_id`. */\n columnName: string;\n /** The enum's FK column, e.g. `logo_color_id`. */\n otherColumnName: string;\n enumName: string;\n enumType: Import;\n enumDetailType: Import;\n enumDetailsType: Import;\n enumRows: EnumRow[];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\n/** I.e. a `Comment.parent` reference that groups `comments.parent_book_id` and `comments.parent_book_review_id`. */\nexport type PolymorphicField = Field & {\n kind: \"poly\";\n fieldType: string; // The name of the type union, eg `CommentParent`\n notNull: boolean;\n hasConfigDefault: boolean;\n components: PolymorphicFieldComponent[];\n};\n\n/** A column such as `parent_book_id` or `parent_book_review_id`. */\nexport type PolymorphicFieldComponent = {\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n otherFieldName: string; // eg `comment` or `comments`\n otherEntity: Entity;\n isDeferredAndDeferrable: boolean;\n constraintName: string;\n notNull: false; // Added to structurally match ManyToOneField\n};\n\nexport type FieldNameOverrides = {\n fieldName?: string;\n otherFieldName?: string;\n};\n\n/** Adapts PostgreSQL catalog metadata into our specific ORM types. */\nexport class EntityDbMetadata {\n entity: Entity;\n primaryKey: PrimitiveField;\n primitives: PrimitiveField[];\n enums: EnumField[];\n pgEnums: PgEnumField[];\n manyToOnes: ManyToOneField[];\n oneToManys: OneToManyField[];\n largeOneToManys: OneToManyField[];\n oneToOnes: OneToOneField[];\n manyToManys: ManyToManyField[];\n largeManyToManys: ManyToManyField[];\n manyToManyEnums: ManyToManyEnumField[];\n polymorphics: PolymorphicField[];\n tableName: string;\n tagName: string;\n createdAt: PrimitiveField | undefined;\n updatedAt: PrimitiveField | undefined;\n deletedAt: PrimitiveField | undefined;\n baseClassName: string | undefined;\n baseType: EntityDbMetadata | undefined;\n subTypes: EntityDbMetadata[] = [];\n inheritanceType: \"sti\" | \"cti\" | undefined;\n /** This will only be set on the base meta. */\n stiDiscriminatorField?: string;\n /** This will only be set on the sub metas. */\n stiDiscriminatorValue?: number;\n abstract: boolean;\n nonDeferredFkOrder: number = -1;\n uniqueConstraints?: string[][];\n /** Gates mutation targets, not reads; false when required columns or array storage have no supported mutation mapping. */\n supportsEmExecute?: boolean;\n /** Original table fields, captured before inheritance partitions or specializes them. */\n physicalMetadata?: EntityDbMetadata;\n /** Physical columns ignored by entity fields, retained for direct SQL reads and writes. */\n ignoredColumns: PrimitiveField[];\n\n constructor(config: Config, table: Table, enums: EnumMetadata = {}) {\n this.entity = makeEntity(tableToEntityName(config, table));\n\n if (isSubClassTable(table)) {\n this.baseClassName = tableToEntityName(config, table.columns.get(\"id\").foreignKeys[0].referencedTable);\n this.inheritanceType = \"cti\";\n }\n\n this.primaryKey =\n table.columns\n .filter((c) => c.isPrimaryKey)\n .map((column) => newPrimitive(config, this.entity, column, table))[0] ||\n fail(`No primary key found for ${table.name}`);\n\n this.primitives = table.columns\n .filter((c) => !c.isPrimaryKey && !c.isForeignKey)\n .filter((c) => !isEnumArray(c) && !isPgEnum(c))\n .map((column) => newPrimitive(config, this.entity, column, table))\n .filter((f) => !f.ignore);\n\n this.enums = [\n ...table.m2oRelations\n .filter((r) => isEnumTable(config, r.targetTable))\n .map((r) => newEnumField(config, this.entity, r, enums))\n .filter((f) => !f.ignore),\n ...table.columns\n .filter((c) => isEnumArray(c))\n .map((column) => newEnumArrayField(config, this.entity, column, enums))\n .filter((f) => !f.ignore),\n ];\n this.pgEnums = table.columns\n .filter((c) => isPgEnum(c))\n .map((column) => newPgEnumField(config, this.entity, column))\n .filter((f) => !f.ignore);\n\n this.manyToOnes = table.m2oRelations\n .filter((r) => !isEnumTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => !isComponentOfPolymorphicRelation(config, r))\n .filter((r) => !isBaseClassForeignKey(r))\n .map((r) => newManyToOneField(config, this.entity, r))\n .filter((f) => !f.ignore);\n\n // We split these into regular/large...\n const allOneToManys = table.o2mRelations\n // ManyToMany join tables also show up as OneToMany tables in pg-structure\n .filter((r) => !isJoinTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => !isOneToOneRelation(r))\n .map((r) => newOneToMany(config, this.entity, r))\n // Do not generate o2m for ReactiveReferences\n .filter((f) => !isReactiveReference(config, f.otherEntity, f.otherFieldName))\n .filter((f) => !f.ignore);\n this.oneToManys = allOneToManys.filter((f) => !f.isLargeCollection);\n this.largeOneToManys = allOneToManys.filter((f) => f.isLargeCollection);\n\n this.oneToOnes = table.o2mRelations\n // ManyToMany join tables also show up as OneToMany tables in pg-structure\n .filter((r) => !isJoinTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => !isBaseClassForeignKey(r))\n .filter((r) => isOneToOneRelation(r))\n .map((r) => newOneToOne(config, this.entity, r))\n .filter((f) => !f.ignore);\n\n // We split these into regular/large\n const allManyToManys = table.m2mRelations\n // pg-structure is really loose on what it considers a m2m relationship, i.e. any entity\n // that has a foreign key to us, and a foreign key to something else, is automatically\n // considered as a join table/m2m between \"us\" and \"something else\". Filter these out\n // by looking for only true join tables, i.e. tables with only id, fk1, and fk2.\n .filter((r) => isJoinTable(config, r.joinTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n // Join tables whose \"other\" side is an enum table become EnumCollections instead.\n .filter((r) => !isEnumTable(config, r.targetTable))\n .map((r) => newManyToManyField(config, this.entity, r))\n .filter((f) => !f.ignore);\n this.manyToManys = allManyToManys.filter((f) => !f.isLargeCollection);\n this.largeManyToManys = allManyToManys.filter((f) => f.isLargeCollection);\n\n // A join table between us and an enum table, i.e. `Publisher.logoColors`.\n this.manyToManyEnums = table.m2mRelations\n .filter((r) => isJoinTable(config, r.joinTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => isEnumTable(config, r.targetTable))\n .map((r) => newManyToManyEnumField(config, this.entity, r, enums))\n .filter((f) => !f.ignore);\n\n this.polymorphics = polymorphicRelations(config, table).map((rc) =>\n newPolymorphicField(config, table, this.entity, rc),\n );\n\n const modeledColumns = new Set([\n this.primaryKey.columnName,\n ...this.primitives.map((field) => field.columnName),\n ...this.enums.map((field) => field.columnName),\n ...this.pgEnums.map((field) => field.columnName),\n ...this.manyToOnes.map((field) => field.columnName),\n ...this.polymorphics.flatMap((field) => field.components.map((component) => component.columnName)),\n ]);\n this.ignoredColumns = table.columns\n .filter((column) => !modeledColumns.has(column.name))\n .map((column) => newPhysicalColumn(config, this.entity, column));\n\n this.tableName = table.name;\n this.tagName = config.entities[this.entity.name]?.tag;\n this.abstract = config.entities[this.entity.name]?.abstract || false;\n\n const { createdAtConf, updatedAtConf, deletedAtConf } = getTimestampConfig(config);\n this.createdAt = this.primitives.find((f) => createdAtConf.names.includes(f.columnName));\n this.updatedAt = this.primitives.find((f) => updatedAtConf.names.includes(f.columnName));\n this.deletedAt = this.primitives.find((f) => deletedAtConf.names.includes(f.columnName));\n this.uniqueConstraints = inferUniqueConstraints(this, table);\n // Composite keys and unsupported physical arrays still cannot be written through mutation field names.\n this.supportsEmExecute =\n table.primaryKey?.columns.length === 1 &&\n this.primaryKey.columnName === \"id\" &&\n // Native enum and multidimensional arrays still have scalar field mappings.\n table.columns.every((column) => column.arrayDimension <= 1 && !(isArray(column) && isPgEnum(column))) &&\n // JSON/schema serdes encode one JSON value, not a SQL array. Date-mode serdes also encode one scalar.\n // Custom element mappers and Temporal array serdes have separate elementwise write paths.\n ![...this.primitives, ...this.ignoredColumns].some(\n (field) =>\n field.isArray &&\n !field.customSerde &&\n (field.columnType === \"jsonb\" ||\n (!config.temporal &&\n (field.columnType === \"date\" ||\n field.columnType === \"timestamp with time zone\" ||\n field.columnType === \"timestamp without time zone\"))),\n );\n }\n\n get name(): string {\n return this.entity.name;\n }\n\n get nonDeferredFks(): Array<ManyToOneField | PolymorphicFieldComponent> {\n return [\n ...this.manyToOnes.filter((r) => !r.isDeferredAndDeferrable),\n ...this.polymorphics.flatMap((p) => p.components).filter((c) => !c.isDeferredAndDeferrable),\n ];\n }\n\n get nonDeferredManyToManyFks(): Array<ManyToManyField> {\n return this.manyToManys.filter((r) => !r.isDeferredAndDeferrable);\n }\n}\n\nfunction isMultiColumnForeignKey(r: M2ORelation | O2MRelation | M2MRelation) {\n return r.foreignKey.columns.length > 1;\n}\n\nfunction isBaseClassForeignKey(r: M2ORelation | O2MRelation | M2MRelation) {\n return r.foreignKey.columns.length === 1 && r.foreignKey.columns[0].name === \"id\";\n}\n\nfunction isOneToOneRelation(r: O2MRelation) {\n // otherColumn will be the images.book_id in the other table\n const otherColumn = r.foreignKey.columns[0];\n // r.foreignKey.index is the index on _us_ (i.e. our Book primary key), so look up indexes in the target table\n const indexes = r.targetTable.columns.find((c) => c.name == otherColumn.name)?.uniqueIndexes || [];\n return indexes.find(isOneToOneIndex) !== undefined;\n}\n\n// If the unique index has only one column and is NOT a partial index, it's a one-to-one\nfunction isOneToOneIndex(i: Index) {\n return i.columns.length === 1 && !i.isPartial;\n}\n\n/** Infers field names from unique constraints, i.e. `(author_id, title)` becomes `author, title`. */\nfunction inferUniqueConstraints(meta: EntityDbMetadata, table: Table): string[][] {\n return table.uniqueConstraints.flatMap((constraint) => {\n if (constraint.index.isPartial) return [];\n const fields = Array.from(constraint.columns).map((column) => fieldNameForColumn(meta, column.name));\n if (fields.some((field) => field === undefined)) return [];\n return [fields as string[]];\n });\n}\n\n/** Returns the queryable field name for a unique constraint column. */\nfunction fieldNameForColumn(meta: EntityDbMetadata, columnName: string): string | undefined {\n const primitive = meta.primitives.find((field) => field.columnName === columnName);\n if (primitive && !primitive.derived && !primitive.isArray && !primitive.customSerde) return primitive.fieldName;\n\n const enumField = meta.enums.find((field) => field.columnName === columnName);\n if (enumField && !enumField.derived && !enumField.isArray) return enumField.fieldName;\n\n const pgEnum = meta.pgEnums.find((field) => field.columnName === columnName);\n if (pgEnum) return pgEnum.fieldName;\n\n const manyToOne = meta.manyToOnes.find((field) => field.columnName === columnName);\n if (manyToOne && !manyToOne.derived) return manyToOne.fieldName;\n\n return undefined;\n}\n\ntype PolymorphicRelation = { fieldName: string; notNull: boolean };\nfunction polymorphicRelations(config: Config, table: Table): PolymorphicRelation[] {\n const entity = config.entities[tableToEntityName(config, table)];\n return Object.entries(entity?.relations ?? {})\n .filter(([, r]) => r.polymorphic)\n .map(([fieldName, { polymorphic }]) => ({ fieldName, notNull: polymorphic === \"notNull\" }));\n}\n\nfunction polymorphicFieldName(config: Config, r: M2ORelation | O2MRelation) {\n const { name } = r.foreignKey.columns[0];\n const table = r.type === \"m2o\" ? r.sourceTable : r.targetTable;\n return polymorphicRelations(config, table).find((pr) => name.startsWith(`${snakeCase(pr.fieldName)}_`))?.fieldName;\n}\n\nfunction isComponentOfPolymorphicRelation(config: Config, r: M2ORelation) {\n return polymorphicFieldName(config, r) !== undefined;\n}\n\nfunction determineUserType(\n fieldType: PrimitiveTypescriptType,\n superstruct: string | undefined,\n zodSchema: string | undefined,\n userFieldType: string | undefined,\n) {\n if (fieldType === \"Object\" && superstruct) {\n return superstructType(superstruct);\n }\n\n if (fieldType === \"Object\" && zodSchema) {\n return zodSchemaType(zodSchema);\n }\n\n if (userFieldType) {\n return userFieldTypeType(userFieldType);\n }\n\n return fieldType;\n}\n\nfunction newPrimitive(config: Config, entity: Entity, column: Column, table: Table): PrimitiveField {\n const fieldName = primitiveFieldName(column.name);\n const columnName = column.name;\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const array = isArray(column);\n const fieldType = mapType(config, table.name, columnName, columnType);\n const customSerde = serdeConfig(config, entity, fieldName);\n const superstruct = superstructConfig(config, entity, fieldName);\n const zodSchema = zodSchemaConfig(config, entity, fieldName);\n const userFieldType = fieldTypeConfig(config, entity, fieldName);\n const maybeUserType = determineUserType(fieldType, superstruct, zodSchema, userFieldType);\n const unique = column.uniqueIndexes.find(isOneToOneIndex) !== undefined;\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"primitive\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnType,\n fieldType: array ? code`${maybeUserType}[]` : maybeUserType,\n rawFieldType: fieldType,\n notNull: column.notNull,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: fieldDerived(config, entity, fieldName),\n protected: isProtected(config, entity, fieldName),\n unique,\n ignore: isFieldIgnored(config, entity, fieldName, column.notNull, column.default !== null),\n superstruct: fieldType === \"Object\" && superstruct ? Import.from(superstruct) : undefined,\n zodSchema: fieldType === \"Object\" && zodSchema ? Import.from(zodSchema) : undefined,\n customSerde: customSerde ? serdeType(customSerde) : undefined,\n isArray: array,\n hasConfigDefault, // can be set to true by scanEntityFiles\n lazy: isLazyField(config, entity, fieldName),\n };\n}\n\n/** Keeps an ignored column's database type without applying entity-only field configuration. */\nfunction newPhysicalColumn(config: Config, entity: Entity, column: Column): PrimitiveField {\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const rawFieldType = column.type instanceof EnumType ? \"string\" : mapSimpleDbTypeToTypescriptType(config, columnType);\n const isArray = column.arrayDimension === 1;\n return {\n kind: \"primitive\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName: primitiveFieldName(column.name),\n columnName: column.name,\n columnType,\n fieldType: isArray ? code`${rawFieldType}[]` : rawFieldType,\n rawFieldType,\n notNull: column.notNull,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: false,\n protected: false,\n unique: false,\n superstruct: undefined,\n zodSchema: undefined,\n customSerde: undefined,\n isArray,\n hasConfigDefault: false,\n };\n}\n\nfunction fieldDerived(config: Config, entity: Entity, fieldName: string): PrimitiveField[\"derived\"] {\n if (ormMaintainedFields.includes(fieldName)) {\n return \"orm\";\n } else if (isGetterField(config, entity, fieldName)) {\n return \"sync\";\n } else if (isReactiveField(config, entity, fieldName)) {\n return \"async\";\n } else {\n return false;\n }\n}\n\nfunction fkFieldDerived(config: Config, entity: Entity, fieldName: string): ManyToOneField[\"derived\"] {\n if (isReactiveReference(config, entity, fieldName)) {\n return \"async\";\n } else {\n return false;\n }\n}\n\nfunction newEnumField(config: Config, entity: Entity, r: M2ORelation, enums: EnumMetadata): EnumField {\n const column = r.foreignKey.columns[0];\n const columnName = column.name;\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const fieldName = enumFieldName(column.name);\n const enumName = tableToEntityName(config, r.targetTable);\n const enumType = imp(`${enumName}@./entities.ts`);\n const enumDetailType = imp(`${plural(enumName)}@./entities.ts`);\n const enumDetailsType = imp(`${enumName}Details@./entities.ts`);\n const notNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName, notNull, column.default !== null);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"enum\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnType,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: fieldDerived(config, entity, fieldName) as EnumField[\"derived\"],\n enumName,\n enumType,\n enumDetailType,\n enumDetailsType,\n notNull,\n ignore,\n enumRows: enums[r.targetTable.name].rows,\n isArray: false,\n hasConfigDefault, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newEnumArrayField(config: Config, entity: Entity, column: Column, enums: EnumMetadata): EnumField {\n const columnName = column.name;\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const fieldName = enumFieldName(column.name);\n // Find the enum table name via the comment hint (instead of a FK constraint), and strip the enum= prefix\n const enumTable = column.comment!.replace(\"enum=\", \"\");\n const enumName = (enums[enumTable] || fail(`Could not find enum ${enumTable}`)).name;\n const enumType = imp(`${enumName}@./entities.ts`);\n const enumDetailType = imp(`${plural(enumName)}@./entities.ts`);\n const enumDetailsType = imp(`${enumName}Details@./entities.ts`);\n const notNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName, notNull, column.default !== null);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"enum\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnType,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: fieldDerived(config, entity, fieldName) as EnumField[\"derived\"],\n enumName,\n enumType,\n enumDetailType,\n enumDetailsType,\n notNull,\n ignore,\n enumRows: enums[enumTable].rows,\n isArray: true,\n hasConfigDefault, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newPgEnumField(config: Config, entity: Entity, column: Column): PgEnumField {\n const fieldName = primitiveFieldName(column.name);\n const columnName = column.name;\n const enumName = pascalCase(column.type.name);\n const enumType = imp(`${enumName}@./entities.ts`);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"pg-enum\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n dbType: column.type.name,\n enumType,\n enumName,\n enumValues: (column.type as EnumType).values,\n notNull: column.notNull,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n ignore: isFieldIgnored(config, entity, fieldName, column.notNull, column.default !== null),\n hasConfigDefault, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newManyToOneField(config: Config, entity: Entity, r: M2ORelation): ManyToOneField {\n const column = r.foreignKey.columns[0];\n const columnName = column.name;\n const dbType = r.foreignKey.columns[0].type.shortName!;\n const fieldName = referenceName(config, entity, r);\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const isOneToOne = column.uniqueIndexes.find(isOneToOneIndex) !== undefined;\n const otherFieldName = isOneToOne\n ? oneToOneName(config, otherEntity, entity, r)\n : collectionName(config, otherEntity, entity, r).fieldName;\n const notNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName, notNull, column.default !== null);\n const isDeferredAndDeferrable = r.foreignKey.isDeferred && r.foreignKey.isDeferrable;\n const derived = fkFieldDerived(config, entity, fieldName);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"m2o\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n otherEntity,\n otherFieldName,\n notNull,\n ignore,\n derived,\n dbType,\n isDeferredAndDeferrable,\n constraintName: r.foreignKey.name,\n hasConfigDefault, // can be set to true by scanEntityFiles\n onDelete: r.foreignKey.onDelete,\n };\n}\n\nfunction newOneToMany(config: Config, entity: Entity, r: O2MRelation): OneToManyField {\n const column = r.foreignKey.columns[0];\n // source == parent i.e. the reference of the foreign key column\n // target == child i.e. the table with the foreign key column in it\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const { singularName, fieldName } = collectionName(config, entity, otherEntity, r);\n const otherFieldName = referenceName(config, otherEntity, r);\n const orderBy =\n config.entities[entity.name]?.relations?.[fieldName]?.orderBy ?? config.entities[otherEntity.name]?.orderBy;\n return {\n kind: \"o2m\",\n fieldName,\n singularName,\n otherEntity,\n otherFieldName,\n otherColumnName: column.name,\n otherColumnNotNull: column.notNull,\n ignore: isFieldIgnored(config, entity, fieldName) || isFieldIgnored(config, otherEntity, otherFieldName),\n isLargeCollection: isLargeCollection(config, entity, fieldName),\n orderBy: parseOrder(orderBy),\n softDeletes: softDeletesConfig(config, entity, fieldName),\n };\n}\n\nfunction newOneToOne(config: Config, entity: Entity, r: O2MRelation): OneToOneField {\n const column = r.foreignKey.columns[0];\n // source == parent i.e. the reference of the foreign key column\n // target == child i.e. the table with the foreign key column in it\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const fieldName = oneToOneName(config, entity, otherEntity, r);\n const otherFieldName = referenceName(config, otherEntity, r);\n const otherColumnName = column.name;\n const otherColumnNotNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName) || isFieldIgnored(config, otherEntity, otherFieldName);\n return { kind: \"o2o\", fieldName, otherEntity, otherFieldName, otherColumnName, otherColumnNotNull, ignore };\n}\n\nfunction newManyToManyField(config: Config, entity: Entity, r: M2MRelation): ManyToManyField {\n const { foreignKey, targetForeignKey, targetTable } = r;\n const otherEntity = makeEntity(tableToEntityName(config, targetTable));\n // For foo_to_bar.some_foo_id use the `some_foo_id` column i.e. `someFoos`\n const fieldName = manyToManyName(targetForeignKey.columns[0]);\n const otherFieldName = manyToManyName(foreignKey.columns[0]);\n const isDeferredAndDeferrable = targetForeignKey.isDeferred && targetForeignKey.isDeferrable;\n\n // Determine if this m2m is derived:\n // - \"async\" if this side is explicitly marked as a ReactiveManyToMany\n // - \"otherSide\" if the OTHER side is marked as a ReactiveManyToMany (making this the read-only other side)\n // - false otherwise (regular m2m)\n const isThisSideDerived = isReactiveManyToMany(config, entity, fieldName);\n const isOtherSideDerived = isReactiveManyToMany(config, otherEntity, otherFieldName);\n const derived = isThisSideDerived ? \"async\" : isOtherSideDerived ? \"otherSide\" : false;\n\n return {\n kind: \"m2m\",\n joinTableName: r.joinTable.name,\n fieldName,\n singularName: singular(fieldName),\n columnName: foreignKey.columns[0].name,\n otherEntity,\n otherFieldName,\n otherColumnName: targetForeignKey.columns[0].name,\n ignore: isFieldIgnored(config, entity, fieldName) || isFieldIgnored(config, otherEntity, otherFieldName),\n isLargeCollection: isLargeCollection(config, entity, fieldName),\n isDeferredAndDeferrable,\n derived,\n softDeletes: softDeletesConfig(config, entity, fieldName),\n hasJoinTableId: joinTableHasId(r.joinTable),\n };\n}\n\nfunction newManyToManyEnumField(\n config: Config,\n entity: Entity,\n r: M2MRelation,\n enums: EnumMetadata,\n): ManyToManyEnumField {\n const { foreignKey, targetForeignKey, targetTable } = r;\n // For publisher_logo_colors.logo_color_id use the `logo_color_id` column i.e. `logoColors`\n const fieldName = manyToManyName(targetForeignKey.columns[0]);\n const enumName = tableToEntityName(config, targetTable);\n return {\n kind: \"m2mEnum\",\n joinTableName: r.joinTable.name,\n fieldName,\n columnName: foreignKey.columns[0].name,\n otherColumnName: targetForeignKey.columns[0].name,\n enumName,\n enumType: imp(`${enumName}@./entities.ts`),\n enumDetailType: imp(`${plural(enumName)}@./entities.ts`),\n enumDetailsType: imp(`${enumName}Details@./entities.ts`),\n enumRows: enums[targetTable.name].rows,\n ignore: isFieldIgnored(config, entity, fieldName),\n hasJoinTableId: joinTableHasId(r.joinTable),\n };\n}\n\nfunction newPolymorphicField(config: Config, table: Table, entity: Entity, pr: PolymorphicRelation) {\n const { fieldName, notNull } = pr;\n const components = table.m2oRelations\n .filter((r) => !isEnumTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => polymorphicFieldName(config, r) === fieldName)\n .map((r) => newPolymorphicFieldComponent(config, entity, r));\n const fieldType = `${entity.name}${pascalCase(fieldName)}`;\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"poly\" as const,\n fieldName,\n fieldType,\n notNull,\n components,\n hasConfigDefault, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newPolymorphicFieldComponent(config: Config, entity: Entity, r: M2ORelation): PolymorphicFieldComponent {\n const column = r.foreignKey.columns[0];\n const columnName = column.name;\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const isOneToOne = column.uniqueIndexes.find(isOneToOneIndex) !== undefined;\n const otherFieldName = isOneToOne\n ? oneToOneName(config, otherEntity, entity, r)\n : collectionName(config, otherEntity, entity, r).fieldName;\n const isDeferredAndDeferrable = r.foreignKey.isDeferred && r.foreignKey.isDeferrable;\n return {\n columnName,\n columnOwner: entity,\n otherEntity,\n otherFieldName,\n isDeferredAndDeferrable,\n constraintName: r.foreignKey.name,\n notNull: false,\n };\n}\n\nfunction isFieldNameOverrides(maybeOverride: JSONData | undefined): maybeOverride is FieldNameOverrides {\n return (\n maybeOverride !== null &&\n !Array.isArray(maybeOverride) &&\n typeof maybeOverride === \"object\" &&\n Object.keys(maybeOverride).some((k) => k === \"fieldName\" || k === \"otherFieldName\")\n );\n}\n\n/** Finds the field name for o2o side of a o2o/m2o. */\nexport function oneToOneName(\n config: Config,\n // I.e. the Book for o2o Book.image <-- `images.book_id`\n refEntity: Entity,\n // I.e. the Image for o2o Book.image <-- `images.book_id`\n keyEntity: Entity,\n r: M2ORelation | O2MRelation,\n): string {\n // If the name is overridden then use that\n const overrides = r.foreignKey.columns[0].commentData;\n if (isFieldNameOverrides(overrides) && overrides.otherFieldName) {\n return overrides.otherFieldName;\n }\n // For `comments.parent_book_review_id`, we would just use `BookReview.comment` as the name\n // For `authors.draft_current_book_id`, we would just use `Book.author` as the name\n // For `project_items.current_selection_id`, we would use `HomeownerSelection.currentProjectItem`\n const refTable = r instanceof M2ORelation ? r.targetTable : r.sourceTable;\n // Does the ref table have any m2o pointing table at the key table?\n const found = refTable.m2oRelations.find((s) => tableToEntityName(config, s.targetTable) === keyEntity.name);\n // console.log({refTable: refTable.name, keyTable: keyTable.name, found: found?.name, fieldName});\n if (!found) {\n // If there aren't any m2os, just use the raw type name like `.image` or `.comment`\n return camelCase(keyEntity.name);\n } else {\n // If there is a m2o, assume we might conflict, and use the column name to at least be unique\n // Start with `book` from `images.book_id` or `current_draft_book` from `authors.current_draft_book_id`\n let fieldName = r.foreignKey.columns[0].name.replace(idSuffix, \"\");\n // Suffix the new type that we're pointing to, to `current_draft_book_author`\n fieldName = `${fieldName}_${keyEntity.name}`;\n // And drop the `book`, to `current_draft__author`\n fieldName = fieldName.replace(refEntity.name.toLowerCase(), \"\");\n // Then camel case, to `currentDraftAuthor`\n return camelCase(fieldName);\n }\n}\n\nconst idSuffix = /_id$|Id$/;\n\nexport function referenceName(config: Config, entity: Entity, r: M2ORelation | O2MRelation): string {\n const [column] = r.foreignKey.columns;\n const overrides = column.commentData;\n return (\n polymorphicFieldName(config, r) ??\n // If the name is overridden then use that\n (isFieldNameOverrides(overrides) ? overrides.fieldName : undefined) ??\n camelCase(column.name.replace(idSuffix, \"\"))\n );\n}\n\nfunction enumFieldName(columnName: string) {\n return camelCase(columnName.replace(idSuffix, \"\"));\n}\n\nfunction primitiveFieldName(columnName: string) {\n return camelCase(columnName);\n}\n\nexport function manyToManyName(column: Column) {\n const overrides = column.commentData;\n // If the name is overridden then use that\n if (isFieldNameOverrides(overrides) && overrides.otherFieldName) {\n return overrides.otherFieldName;\n }\n return camelCase(plural(column.name.replace(idSuffix, \"\")));\n}\n\n/** Returns the collection name to use on `entity` when referring to `otherEntity`s. */\nexport function collectionName(\n config: Config,\n // I.e. the Author for o2m Author.books --> books.author_id\n singleEntity: Entity,\n // I.e. the Book for o2m Author.books --> books.author_id\n collectionEntity: Entity,\n r: M2ORelation | O2MRelation | M2MRelation,\n): { fieldName: string; singularName: string } {\n const [column] = r.foreignKey.columns;\n const overrides = column.commentData;\n // If the name is overridden then use that, but also singularize it\n if (isFieldNameOverrides(overrides) && overrides.otherFieldName) {\n const fieldName = overrides.otherFieldName;\n return { fieldName, singularName: singular(fieldName) };\n }\n // I.e. if the m2o is `books.author_id`, use `Author.books` as the collection name (we pluralize at the end).\n let singularName = collectionEntity.name;\n // Check if we have multiple FKs from collectionEntity --> singleEntity and prefix with FK name if so\n const sourceTable = r.type === \"m2o\" ? r.sourceTable : r.targetTable;\n const targetTable = r.type === \"m2o\" ? r.targetTable : r.sourceTable;\n // If `books.foo_author_id` and `books.bar_author_id` both exist\n if (r.type !== \"m2m\" && sourceTable.m2oRelations.filter((r) => r.targetTable === targetTable).length > 1) {\n // Use `fooAuthorBooks`, `barAuthorBooks`\n singularName = `${column.name.replace(idSuffix, \"\")}_${singularName}`;\n }\n // If we've guessed `Book.bookReviews` based on `book_reviews.book_id` --> `bookReviews`, strip the `Book` prefix\n if (singularName.length > singleEntity.name.length && singularName.startsWith(singleEntity.name)) {\n singularName = singularName.substring(singleEntity.name.length);\n }\n // camelize the name\n singularName = camelCase(singularName);\n // and pluralize for fieldName\n return { fieldName: plural(singularName), singularName };\n}\n\nexport function failIfOverlappingFieldNames(entity: EntityDbMetadata): void {\n const allFields = [\n entity.primaryKey,\n ...entity.primitives,\n ...entity.enums,\n ...entity.pgEnums,\n ...entity.manyToOnes,\n ...entity.oneToManys,\n ...entity.largeOneToManys,\n ...entity.oneToOnes,\n ...entity.manyToManys,\n ...entity.largeManyToManys,\n ...entity.manyToManyEnums,\n ...entity.polymorphics,\n ];\n Object.entries(groupBy(allFields, (f) => f.fieldName)).forEach(([fieldName, fields]) => {\n if (fields.length > 1) {\n throw new Error(\n `In ${entity.name}, found multiple fields named '${fieldName}': ${fields.map((f) => f.kind).join(\" \")}`,\n );\n }\n });\n}\n\nexport function makeEntity(entityName: string): Entity {\n // Default to the conventional names; `resolveNameConflicts` rewrites them if they collide.\n const names = entitySymbolNames(entityName);\n return {\n name: entityName,\n type: entityType(entityName),\n typeSymbol: entityTypeSymbol(entityName),\n typeForMetadataFile: entityTypeForMetadataFile(entityName),\n metaName: metaName(entityName),\n metaType: metaType(entityName),\n idType: entityTypeImport(entityName, names.idName),\n orderType: entityTypeImport(entityName, names.orderName),\n optsType: entityTypeImport(entityName, names.optsName),\n configConst: imp(`${camelCase(entityName)}Config@./entities.ts`, {\n definedIn: `./codegen/${entityName}Codegen.ts`,\n }),\n ...names,\n };\n}\n\n/**\n * Collapses the per-relation `otherEntity` copies down to the one primary `Entity` per name.\n *\n * `makeEntity` mints a fresh `Entity` for every relation's `otherEntity`, so each entity ends up with\n * many duplicate objects floating around. Pointing them all at the single `entitiesByName[name].entity`\n * instance means later passes (i.e. `resolveNameConflicts`) only have to update one object per name.\n *\n * Must run after inheritance, since STI/CTI specialization both adds and re-points `otherEntity`s.\n */\nexport function canonicalizeOtherEntities(db: DbMetadata): void {\n const canonical = (other: Entity) => db.entitiesByName[other.name]?.entity ?? other;\n for (const meta of db.entities) {\n for (const field of [\n ...meta.manyToOnes,\n ...meta.oneToManys,\n ...meta.largeOneToManys,\n ...meta.oneToOnes,\n ...meta.manyToManys,\n ...meta.largeManyToManys,\n ]) {\n field.otherEntity = canonical(field.otherEntity);\n }\n for (const poly of meta.polymorphics) {\n for (const comp of poly.components) comp.otherEntity = canonical(comp.otherEntity);\n }\n if (meta.physicalMetadata) {\n canonicalizeOtherEntities({ ...db, entities: [meta.physicalMetadata] });\n }\n }\n}\n\n/**\n * Rewrites codegen'd type names that collide with another exported type name.\n *\n * `makeEntity` defaults each name to the conventional `${name}<Suffix>`, but if a separate entity or\n * enum is literally named e.g. `AuthorScope` or `AuthorOrder`, our generated type of the same name\n * would collide with it, so we fall back to `Author_Scope` / `Author_Order`.\n *\n * Relies on `canonicalizeOtherEntities` having run, so mutating each primary `meta.entity` also updates\n * the `otherEntity` references that point at it (e.g. `Book.author: AuthorId` follows `Author`'s rename).\n */\nexport function resolveNameConflicts(config: Config, db: DbMetadata): void {\n // The names exported into `entities.ts` that a codegen'd type could shadow.\n const reserved = new Set<string>(db.entities.map((meta) => meta.name));\n for (const enumData of Object.values(db.enums)) {\n // An enum table exports its (singularized) type, its `Details` type/const, and its pluralized const,\n // i.e. `ChangeRequestAssetScope`, `ChangeRequestAssetScopeDetails`, and `ChangeRequestAssetScopes`.\n const enumName = tableToEntityName(config, enumData.table);\n reserved.add(enumName).add(`${enumName}Details`).add(plural(enumName));\n }\n for (const pgEnum of Object.values(db.pgEnums)) reserved.add(pgEnum.name);\n for (const meta of db.entities) {\n if (hasNameConflict(meta.name, reserved)) applyEntityNames(meta.entity, reserved);\n }\n}\n\n/** Computes the codegen'd type names for an entity, underscoring any that `reserved` already contains. */\nfunction entitySymbolNames(name: string, reserved?: Set<string>) {\n const pick = (suffix: string) => (reserved?.has(`${name}${suffix}`) ? `${name}_${suffix}` : `${name}${suffix}`);\n return {\n idName: pick(\"Id\"),\n fieldsName: pick(\"Fields\"),\n optsName: pick(\"Opts\"),\n idsOptsName: pick(\"IdsOpts\"),\n filterName: pick(\"Filter\"),\n graphqlFilterName: pick(\"GraphQLFilter\"),\n orderName: pick(\"Order\"),\n factoryExtrasName: pick(\"FactoryExtras\"),\n scopeName: pick(\"Scope\"),\n scopesName: pick(\"Scopes\"),\n };\n}\n\n/** Returns true if any of the entity's conventional type names is already taken. */\nfunction hasNameConflict(name: string, reserved: Set<string>): boolean {\n return Object.values(entitySymbolNames(name)).some((conventional) => reserved.has(conventional));\n}\n\n/** Rewrites an entity's type names (and the `Import`s built from them) to their de-conflicted form. */\nfunction applyEntityNames(entity: Entity, reserved: Set<string>): void {\n const names = entitySymbolNames(entity.name, reserved);\n Object.assign(entity, names);\n entity.idType = entityTypeImport(entity.name, names.idName);\n entity.orderType = entityTypeImport(entity.name, names.orderName);\n entity.optsType = entityTypeImport(entity.name, names.optsName);\n}\n\nfunction entityTypeImport(entityName: string, symbolName: string): Import {\n return imp(`t:${symbolName}@./entities.ts`, { definedIn: `./codegen/${entityName}Codegen.ts` });\n}\n\nfunction metaName(entityName: string): string {\n return `${camelCase(entityName)}Meta`;\n}\n\nfunction metaType(entityName: string): Import {\n return imp(`${metaName(entityName)}@./entities.ts`);\n}\n\nfunction entityType(entityName: string): Import {\n return imp(`t:${entityName}@./entities.ts`);\n}\n\nfunction entityTypeSymbol(entityName: string): Import {\n return imp(`${entityName}@./entities.ts`);\n}\n\nfunction entityTypeForMetadataFile(entityName: string): Import {\n return imp(`${entityName}@./${entityName}.ts`);\n}\n\nfunction mapType(\n config: Config,\n tableName: string,\n columnName: string,\n dbColumnType: DatabaseColumnType,\n): PrimitiveTypescriptType {\n return mapSimpleDbTypeToTypescriptType(config, dbColumnType);\n}\n\nfunction isEnumArray(c: Column): boolean {\n return c.arrayDimension === 1 && !!c.comment && c.comment.startsWith(\"enum=\");\n}\n\nfunction isArray(c: Column): boolean {\n return c.arrayDimension === 1;\n}\n\nfunction isPgEnum(c: Column): boolean {\n return c.type instanceof EnumType;\n}\n\nfunction superstructType(s: string): Import {\n // Assume it's `foo@...`, turn it into `Foo@...`\n const [symbol, ...path] = s.split(\"@\");\n return Import.from(`${pascalCase(symbol)}@${path.join(\"@\")}`);\n}\n\nfunction zodSchemaType(s: string): Code {\n const schema = Import.from(s);\n return code`${Zod}.input<typeof ${schema}>`;\n}\n\nfunction userFieldTypeType(s: string): Import {\n return Import.from(`t:${s}`);\n}\n\nfunction serdeType(s: string): Import {\n return Import.from(s);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityDbMetadata.js","names":[],"sources":["../src/EntityDbMetadata.ts"],"sourcesContent":["import { camelCase, pascalCase, snakeCase } from \"change-case\";\nimport { groupBy } from \"joist-utils\";\nimport pluralize from \"pluralize\";\nimport { type Code, Import, code, imp } from \"ts-poet\";\n\nimport {\n type Config,\n fieldTypeConfig,\n getTimestampConfig,\n isFieldHasDefault,\n isFieldIgnored,\n isGetterField,\n isLargeCollection,\n isLazyField,\n isProtected,\n isReactiveField,\n isReactiveManyToMany,\n isReactiveReference,\n ormMaintainedFields,\n serdeConfig,\n softDeletesConfig,\n superstructConfig,\n zodSchemaConfig,\n} from \"./config.ts\";\nimport { type EnumMetadata, type EnumRow, type PgEnumMetadata } from \"./loadMetadata.ts\";\nimport {\n type Action,\n type Column,\n EnumType,\n type Index,\n type JSONData,\n type M2MRelation,\n M2ORelation,\n type O2MRelation,\n type Table,\n} from \"./pgMetadata.ts\";\nimport { Zod } from \"./symbols.ts\";\nimport {\n fail,\n isEnumTable,\n isJoinTable,\n isSubClassTable,\n joinTableHasId,\n mapSimpleDbTypeToTypescriptType,\n parseOrder,\n tableToEntityName,\n} from \"./utils.ts\";\n\nconst { plural, singular } = pluralize;\n\n/** All the entities + enums in our database. */\nexport interface DbMetadata {\n entities: EntityDbMetadata[];\n /** Type name i.e. `Author` to metadata. */\n entitiesByName: Record<string, EntityDbMetadata>;\n enums: EnumMetadata;\n pgEnums: PgEnumMetadata;\n joinTables: string[];\n /** Other non-joist tables in the schema. */\n otherTables: string[];\n totalTables: number;\n}\n\n/** Codegen-time metadata about a given domain entity. */\nexport type Entity = {\n name: string;\n /** The _type_ symbol pointing to the entity itself. */\n type: Import;\n /** The symbol pointing to the entity itself. */\n typeSymbol: Import;\n /** The symbol pointing to the entity itself, directly rather than via entities.ts */\n typeForMetadataFile: Import;\n /** The name of the entity's runtime metadata const. */\n metaName: string;\n /** The symbol pointing to the entity's runtime metadata const. */\n metaType: Import;\n /** The symbol pointing to the entity's EntityId type. */\n idType: Import;\n /** The symbol pointing to the entity's Order type. */\n orderType: Import;\n /** The symbol pointing to the entity's config const. */\n configConst: Import;\n optsType: Import;\n // The names of the entity's codegen'd types, i.e. `AuthorId`, that `resolveNameConflicts` rewrites\n // to `Author_Id` when they would collide with another entity/enum name. The `Import`s above\n // (`idType`/`orderType`/`optsType`) are rebuilt to match when that happens.\n /** i.e. `AuthorId` (or `Author_Id` on conflict). */\n idName: string;\n /** i.e. `AuthorFields`. */\n fieldsName: string;\n /** i.e. `AuthorOpts`. */\n optsName: string;\n /** i.e. `AuthorIdsOpts`. */\n idsOptsName: string;\n /** i.e. `AuthorFilter`. */\n filterName: string;\n /** i.e. `AuthorGraphQLFilter`. */\n graphqlFilterName: string;\n /** i.e. `AuthorOrder`. */\n orderName: string;\n /** i.e. `AuthorFactoryExtras`. */\n factoryExtrasName: string;\n /** i.e. `AuthorScope`. */\n scopeName: string;\n /** i.e. `AuthorScopes`. */\n scopesName: string;\n};\n\nexport type DatabaseColumnType =\n | \"boolean\"\n | \"int\"\n | \"uuid\"\n | \"numeric\"\n | \"smallint\"\n | \"integer\"\n | \"bigint\"\n | \"decimal\"\n | \"real\"\n | \"smallserial\"\n | \"serial\"\n | \"bigserial\"\n | \"double precision\"\n | \"text\"\n | \"citext\"\n | \"character varying\"\n | \"varchar\"\n | \"time without time zone\"\n | \"timestamp with time zone\"\n | \"timestamp without time zone\"\n | \"date\"\n | \"jsonb\"\n | \"bytea\"\n | \"tsvector\"\n | \"tstzrange\";\n\n/**\n * A logical entity field.\n *\n * I.e. it may be a physical db column, or multiple physical db columns, or a \"virtual\" field like\n * the one-to-many collection side of a many-to-one foreign key. */\ninterface Field {\n fieldName: string;\n ignore?: boolean;\n}\n\nexport type PrimitiveTypescriptType = \"boolean\" | \"string\" | \"number\" | \"Object\" | \"bigint\" | \"Uint8Array\" | Code;\n\nexport type PrimitiveField = Field & {\n kind: \"primitive\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnType: DatabaseColumnType;\n columnDefault: number | boolean | string | null;\n columnGenerated: boolean;\n /** Database nullability, unchanged by domain inheritance specialization. */\n columnNotNull: boolean;\n // The fieldType might be code for jsonb columns or primitive array columns, i.e. string[]\n fieldType: PrimitiveTypescriptType | Import;\n rawFieldType: PrimitiveTypescriptType;\n notNull: boolean;\n derived: \"orm\" | \"sync\" | \"async\" | false;\n protected: boolean;\n unique: boolean;\n superstruct: Import | undefined;\n zodSchema: Import | undefined;\n customSerde: Import | undefined;\n isArray: boolean;\n hasConfigDefault: boolean;\n lazy?: boolean;\n};\n\nexport type EnumField = Field & {\n kind: \"enum\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnType: DatabaseColumnType;\n columnDefault: number | boolean | string | null;\n columnGenerated: boolean;\n columnNotNull: boolean;\n derived: \"sync\" | \"async\" | false;\n enumName: string;\n enumType: Import;\n enumDetailType: Import;\n enumDetailsType: Import;\n enumRows: EnumRow[];\n notNull: boolean;\n isArray: boolean;\n hasConfigDefault: boolean;\n /** Whether the entity file calls `config.transitions`, `guardTransition`, or `onTransition` on this field, set by `scanEntityFiles`. */\n hasTransitions: boolean;\n};\n\nexport type PgEnumField = Field & {\n kind: \"pg-enum\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnDefault: number | boolean | string | null;\n columnGenerated: boolean;\n columnNotNull: boolean;\n /** I.e. `favorite_shape`. */\n dbType: string;\n /** I.e. `FavoriteShape`. */\n enumName: string;\n enumType: Import;\n enumValues: string[];\n notNull: boolean;\n hasConfigDefault: boolean;\n};\n\n/** I.e. a `Book.author` reference pointing to an `Author`. */\nexport type ManyToOneField = Field & {\n kind: \"m2o\";\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n columnDefault?: number | boolean | string | null;\n columnGenerated: boolean;\n columnNotNull: boolean;\n dbType: string;\n otherFieldName: string;\n otherEntity: Entity;\n notNull: boolean;\n isDeferredAndDeferrable: boolean;\n constraintName: string;\n derived: \"async\" | false;\n hasConfigDefault: boolean;\n onDelete: Action;\n};\n\n/** I.e. a `Author.books` collection. */\nexport type OneToManyField = Field & {\n kind: \"o2m\";\n singularName: string;\n otherEntity: Entity;\n otherFieldName: string;\n otherColumnName: string;\n otherColumnNotNull: boolean;\n isLargeCollection: boolean;\n orderBy: { field: string; direction: \"ASC\" | \"DESC\" } | undefined;\n softDeletes: \"include\" | \"exclude\" | undefined;\n};\n\n/** I.e. a `Author.image` reference when `image.author_id` is unique. */\nexport type OneToOneField = Field & {\n kind: \"o2o\";\n otherEntity: Entity;\n otherFieldName: string;\n otherColumnName: string;\n otherColumnNotNull: boolean;\n};\n\nexport type ManyToManyField = Field & {\n kind: \"m2m\";\n joinTableName: string;\n singularName: string;\n columnName: string;\n otherEntity: Entity;\n otherFieldName: string;\n otherColumnName: string;\n isLargeCollection: boolean;\n isDeferredAndDeferrable: boolean;\n derived: \"async\" | \"otherSide\" | false;\n softDeletes: \"include\" | \"exclude\" | undefined;\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\n/** I.e. a `Publisher.logoColors` m2m to the `color` enum table, backed by `publisher_logo_colors`. */\nexport type ManyToManyEnumField = Field & {\n kind: \"m2mEnum\";\n joinTableName: string;\n /** The entity's FK column, e.g. `publisher_id`. */\n columnName: string;\n /** The enum's FK column, e.g. `logo_color_id`. */\n otherColumnName: string;\n enumName: string;\n enumType: Import;\n enumDetailType: Import;\n enumDetailsType: Import;\n enumRows: EnumRow[];\n /** Whether the join table has a surrogate `id` PK; if false the FK pair is the composite PK. */\n hasJoinTableId: boolean;\n};\n\n/** I.e. a `Comment.parent` reference that groups `comments.parent_book_id` and `comments.parent_book_review_id`. */\nexport type PolymorphicField = Field & {\n kind: \"poly\";\n fieldType: string; // The name of the type union, eg `CommentParent`\n notNull: boolean;\n hasConfigDefault: boolean;\n components: PolymorphicFieldComponent[];\n};\n\n/** A column such as `parent_book_id` or `parent_book_review_id`. */\nexport type PolymorphicFieldComponent = {\n columnName: string;\n /** Physical table owner, unchanged by domain inheritance specialization. */\n columnOwner: Entity;\n otherFieldName: string; // eg `comment` or `comments`\n otherEntity: Entity;\n isDeferredAndDeferrable: boolean;\n constraintName: string;\n notNull: false; // Added to structurally match ManyToOneField\n};\n\nexport type FieldNameOverrides = {\n fieldName?: string;\n otherFieldName?: string;\n};\n\n/** Adapts PostgreSQL catalog metadata into our specific ORM types. */\nexport class EntityDbMetadata {\n entity: Entity;\n primaryKey: PrimitiveField;\n primitives: PrimitiveField[];\n enums: EnumField[];\n pgEnums: PgEnumField[];\n manyToOnes: ManyToOneField[];\n oneToManys: OneToManyField[];\n largeOneToManys: OneToManyField[];\n oneToOnes: OneToOneField[];\n manyToManys: ManyToManyField[];\n largeManyToManys: ManyToManyField[];\n manyToManyEnums: ManyToManyEnumField[];\n polymorphics: PolymorphicField[];\n tableName: string;\n tagName: string;\n createdAt: PrimitiveField | undefined;\n updatedAt: PrimitiveField | undefined;\n deletedAt: PrimitiveField | undefined;\n baseClassName: string | undefined;\n baseType: EntityDbMetadata | undefined;\n subTypes: EntityDbMetadata[] = [];\n inheritanceType: \"sti\" | \"cti\" | undefined;\n /** This will only be set on the base meta. */\n stiDiscriminatorField?: string;\n /** This will only be set on the sub metas. */\n stiDiscriminatorValue?: number;\n abstract: boolean;\n nonDeferredFkOrder: number = -1;\n uniqueConstraints?: string[][];\n /** Gates mutation targets, not reads; false when required columns or array storage have no supported mutation mapping. */\n supportsEmExecute?: boolean;\n /** Original table fields, captured before inheritance partitions or specializes them. */\n physicalMetadata?: EntityDbMetadata;\n /** Physical columns ignored by entity fields, retained for direct SQL reads and writes. */\n ignoredColumns: PrimitiveField[];\n\n constructor(config: Config, table: Table, enums: EnumMetadata = {}) {\n this.entity = makeEntity(tableToEntityName(config, table));\n\n if (isSubClassTable(table)) {\n this.baseClassName = tableToEntityName(config, table.columns.get(\"id\").foreignKeys[0].referencedTable);\n this.inheritanceType = \"cti\";\n }\n\n this.primaryKey =\n table.columns\n .filter((c) => c.isPrimaryKey)\n .map((column) => newPrimitive(config, this.entity, column, table))[0] ||\n fail(`No primary key found for ${table.name}`);\n\n this.primitives = table.columns\n .filter((c) => !c.isPrimaryKey && !c.isForeignKey)\n .filter((c) => !isEnumArray(c) && !isPgEnum(c))\n .map((column) => newPrimitive(config, this.entity, column, table))\n .filter((f) => !f.ignore);\n\n this.enums = [\n ...table.m2oRelations\n .filter((r) => isEnumTable(config, r.targetTable))\n .map((r) => newEnumField(config, this.entity, r, enums))\n .filter((f) => !f.ignore),\n ...table.columns\n .filter((c) => isEnumArray(c))\n .map((column) => newEnumArrayField(config, this.entity, column, enums))\n .filter((f) => !f.ignore),\n ];\n this.pgEnums = table.columns\n .filter((c) => isPgEnum(c))\n .map((column) => newPgEnumField(config, this.entity, column))\n .filter((f) => !f.ignore);\n\n this.manyToOnes = table.m2oRelations\n .filter((r) => !isEnumTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => !isComponentOfPolymorphicRelation(config, r))\n .filter((r) => !isBaseClassForeignKey(r))\n .map((r) => newManyToOneField(config, this.entity, r))\n .filter((f) => !f.ignore);\n\n // We split these into regular/large...\n const allOneToManys = table.o2mRelations\n // ManyToMany join tables also show up as OneToMany tables in pg-structure\n .filter((r) => !isJoinTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => !isOneToOneRelation(r))\n .map((r) => newOneToMany(config, this.entity, r))\n // Do not generate o2m for ReactiveReferences\n .filter((f) => !isReactiveReference(config, f.otherEntity, f.otherFieldName))\n .filter((f) => !f.ignore);\n this.oneToManys = allOneToManys.filter((f) => !f.isLargeCollection);\n this.largeOneToManys = allOneToManys.filter((f) => f.isLargeCollection);\n\n this.oneToOnes = table.o2mRelations\n // ManyToMany join tables also show up as OneToMany tables in pg-structure\n .filter((r) => !isJoinTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => !isBaseClassForeignKey(r))\n .filter((r) => isOneToOneRelation(r))\n .map((r) => newOneToOne(config, this.entity, r))\n .filter((f) => !f.ignore);\n\n // We split these into regular/large\n const allManyToManys = table.m2mRelations\n // pg-structure is really loose on what it considers a m2m relationship, i.e. any entity\n // that has a foreign key to us, and a foreign key to something else, is automatically\n // considered as a join table/m2m between \"us\" and \"something else\". Filter these out\n // by looking for only true join tables, i.e. tables with only id, fk1, and fk2.\n .filter((r) => isJoinTable(config, r.joinTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n // Join tables whose \"other\" side is an enum table become EnumCollections instead.\n .filter((r) => !isEnumTable(config, r.targetTable))\n .map((r) => newManyToManyField(config, this.entity, r))\n .filter((f) => !f.ignore);\n this.manyToManys = allManyToManys.filter((f) => !f.isLargeCollection);\n this.largeManyToManys = allManyToManys.filter((f) => f.isLargeCollection);\n\n // A join table between us and an enum table, i.e. `Publisher.logoColors`.\n this.manyToManyEnums = table.m2mRelations\n .filter((r) => isJoinTable(config, r.joinTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => isEnumTable(config, r.targetTable))\n .map((r) => newManyToManyEnumField(config, this.entity, r, enums))\n .filter((f) => !f.ignore);\n\n this.polymorphics = polymorphicRelations(config, table).map((rc) =>\n newPolymorphicField(config, table, this.entity, rc),\n );\n\n const modeledColumns = new Set([\n this.primaryKey.columnName,\n ...this.primitives.map((field) => field.columnName),\n ...this.enums.map((field) => field.columnName),\n ...this.pgEnums.map((field) => field.columnName),\n ...this.manyToOnes.map((field) => field.columnName),\n ...this.polymorphics.flatMap((field) => field.components.map((component) => component.columnName)),\n ]);\n this.ignoredColumns = table.columns\n .filter((column) => !modeledColumns.has(column.name))\n .map((column) => newPhysicalColumn(config, this.entity, column));\n\n this.tableName = table.name;\n this.tagName = config.entities[this.entity.name]?.tag;\n this.abstract = config.entities[this.entity.name]?.abstract || false;\n\n const { createdAtConf, updatedAtConf, deletedAtConf } = getTimestampConfig(config);\n this.createdAt = this.primitives.find((f) => createdAtConf.names.includes(f.columnName));\n this.updatedAt = this.primitives.find((f) => updatedAtConf.names.includes(f.columnName));\n this.deletedAt = this.primitives.find((f) => deletedAtConf.names.includes(f.columnName));\n this.uniqueConstraints = inferUniqueConstraints(this, table);\n // Composite keys and unsupported physical arrays still cannot be written through mutation field names.\n this.supportsEmExecute =\n table.primaryKey?.columns.length === 1 &&\n this.primaryKey.columnName === \"id\" &&\n // Native enum and multidimensional arrays still have scalar field mappings.\n table.columns.every((column) => column.arrayDimension <= 1 && !(isArray(column) && isPgEnum(column))) &&\n // JSON/schema serdes encode one JSON value, not a SQL array. Date-mode serdes also encode one scalar.\n // Custom element mappers and Temporal array serdes have separate elementwise write paths.\n ![...this.primitives, ...this.ignoredColumns].some(\n (field) =>\n field.isArray &&\n !field.customSerde &&\n (field.columnType === \"jsonb\" ||\n (!config.temporal &&\n (field.columnType === \"date\" ||\n field.columnType === \"timestamp with time zone\" ||\n field.columnType === \"timestamp without time zone\"))),\n );\n }\n\n get name(): string {\n return this.entity.name;\n }\n\n get nonDeferredFks(): Array<ManyToOneField | PolymorphicFieldComponent> {\n return [\n ...this.manyToOnes.filter((r) => !r.isDeferredAndDeferrable),\n ...this.polymorphics.flatMap((p) => p.components).filter((c) => !c.isDeferredAndDeferrable),\n ];\n }\n\n get nonDeferredManyToManyFks(): Array<ManyToManyField> {\n return this.manyToManys.filter((r) => !r.isDeferredAndDeferrable);\n }\n}\n\nfunction isMultiColumnForeignKey(r: M2ORelation | O2MRelation | M2MRelation) {\n return r.foreignKey.columns.length > 1;\n}\n\nfunction isBaseClassForeignKey(r: M2ORelation | O2MRelation | M2MRelation) {\n return r.foreignKey.columns.length === 1 && r.foreignKey.columns[0].name === \"id\";\n}\n\nfunction isOneToOneRelation(r: O2MRelation) {\n // otherColumn will be the images.book_id in the other table\n const otherColumn = r.foreignKey.columns[0];\n // r.foreignKey.index is the index on _us_ (i.e. our Book primary key), so look up indexes in the target table\n const indexes = r.targetTable.columns.find((c) => c.name == otherColumn.name)?.uniqueIndexes || [];\n return indexes.find(isOneToOneIndex) !== undefined;\n}\n\n// If the unique index has only one column and is NOT a partial index, it's a one-to-one\nfunction isOneToOneIndex(i: Index) {\n return i.columns.length === 1 && !i.isPartial;\n}\n\n/** Infers field names from unique constraints, i.e. `(author_id, title)` becomes `author, title`. */\nfunction inferUniqueConstraints(meta: EntityDbMetadata, table: Table): string[][] {\n return table.uniqueConstraints.flatMap((constraint) => {\n if (constraint.index.isPartial) return [];\n const fields = Array.from(constraint.columns).map((column) => fieldNameForColumn(meta, column.name));\n if (fields.some((field) => field === undefined)) return [];\n return [fields as string[]];\n });\n}\n\n/** Returns the queryable field name for a unique constraint column. */\nfunction fieldNameForColumn(meta: EntityDbMetadata, columnName: string): string | undefined {\n const primitive = meta.primitives.find((field) => field.columnName === columnName);\n if (primitive && !primitive.derived && !primitive.customSerde) return primitive.fieldName;\n\n const enumField = meta.enums.find((field) => field.columnName === columnName);\n if (enumField && !enumField.derived && !enumField.isArray) return enumField.fieldName;\n\n const pgEnum = meta.pgEnums.find((field) => field.columnName === columnName);\n if (pgEnum) return pgEnum.fieldName;\n\n const manyToOne = meta.manyToOnes.find((field) => field.columnName === columnName);\n if (manyToOne && !manyToOne.derived) return manyToOne.fieldName;\n\n return undefined;\n}\n\ntype PolymorphicRelation = { fieldName: string; notNull: boolean };\nfunction polymorphicRelations(config: Config, table: Table): PolymorphicRelation[] {\n const entity = config.entities[tableToEntityName(config, table)];\n return Object.entries(entity?.relations ?? {})\n .filter(([, r]) => r.polymorphic)\n .map(([fieldName, { polymorphic }]) => ({ fieldName, notNull: polymorphic === \"notNull\" }));\n}\n\nfunction polymorphicFieldName(config: Config, r: M2ORelation | O2MRelation) {\n const { name } = r.foreignKey.columns[0];\n const table = r.type === \"m2o\" ? r.sourceTable : r.targetTable;\n return polymorphicRelations(config, table).find((pr) => name.startsWith(`${snakeCase(pr.fieldName)}_`))?.fieldName;\n}\n\nfunction isComponentOfPolymorphicRelation(config: Config, r: M2ORelation) {\n return polymorphicFieldName(config, r) !== undefined;\n}\n\nfunction determineUserType(\n fieldType: PrimitiveTypescriptType,\n superstruct: string | undefined,\n zodSchema: string | undefined,\n userFieldType: string | undefined,\n) {\n if (fieldType === \"Object\" && superstruct) {\n return superstructType(superstruct);\n }\n\n if (fieldType === \"Object\" && zodSchema) {\n return zodSchemaType(zodSchema);\n }\n\n if (userFieldType) {\n return userFieldTypeType(userFieldType);\n }\n\n return fieldType;\n}\n\nfunction newPrimitive(config: Config, entity: Entity, column: Column, table: Table): PrimitiveField {\n const fieldName = primitiveFieldName(column.name);\n const columnName = column.name;\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const array = isArray(column);\n const fieldType = mapType(config, table.name, columnName, columnType);\n const customSerde = serdeConfig(config, entity, fieldName);\n const superstruct = superstructConfig(config, entity, fieldName);\n const zodSchema = zodSchemaConfig(config, entity, fieldName);\n const userFieldType = fieldTypeConfig(config, entity, fieldName);\n const maybeUserType = determineUserType(fieldType, superstruct, zodSchema, userFieldType);\n const unique = column.uniqueIndexes.find(isOneToOneIndex) !== undefined;\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"primitive\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnType,\n fieldType: array ? code`${maybeUserType}[]` : maybeUserType,\n rawFieldType: fieldType,\n notNull: column.notNull,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: fieldDerived(config, entity, fieldName),\n protected: isProtected(config, entity, fieldName),\n unique,\n ignore: isFieldIgnored(config, entity, fieldName, column.notNull, column.default !== null),\n superstruct: fieldType === \"Object\" && superstruct ? Import.from(superstruct) : undefined,\n zodSchema: fieldType === \"Object\" && zodSchema ? Import.from(zodSchema) : undefined,\n customSerde: customSerde ? serdeType(customSerde) : undefined,\n isArray: array,\n hasConfigDefault, // can be set to true by scanEntityFiles\n lazy: isLazyField(config, entity, fieldName),\n };\n}\n\n/** Keeps an ignored column's database type without applying entity-only field configuration. */\nfunction newPhysicalColumn(config: Config, entity: Entity, column: Column): PrimitiveField {\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const rawFieldType = column.type instanceof EnumType ? \"string\" : mapSimpleDbTypeToTypescriptType(config, columnType);\n const isArray = column.arrayDimension === 1;\n return {\n kind: \"primitive\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName: primitiveFieldName(column.name),\n columnName: column.name,\n columnType,\n fieldType: isArray ? code`${rawFieldType}[]` : rawFieldType,\n rawFieldType,\n notNull: column.notNull,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: false,\n protected: false,\n unique: false,\n superstruct: undefined,\n zodSchema: undefined,\n customSerde: undefined,\n isArray,\n hasConfigDefault: false,\n };\n}\n\nfunction fieldDerived(config: Config, entity: Entity, fieldName: string): PrimitiveField[\"derived\"] {\n if (ormMaintainedFields.includes(fieldName)) {\n return \"orm\";\n } else if (isGetterField(config, entity, fieldName)) {\n return \"sync\";\n } else if (isReactiveField(config, entity, fieldName)) {\n return \"async\";\n } else {\n return false;\n }\n}\n\nfunction fkFieldDerived(config: Config, entity: Entity, fieldName: string): ManyToOneField[\"derived\"] {\n if (isReactiveReference(config, entity, fieldName)) {\n return \"async\";\n } else {\n return false;\n }\n}\n\nfunction newEnumField(config: Config, entity: Entity, r: M2ORelation, enums: EnumMetadata): EnumField {\n const column = r.foreignKey.columns[0];\n const columnName = column.name;\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const fieldName = enumFieldName(column.name);\n const enumName = tableToEntityName(config, r.targetTable);\n const enumType = imp(`${enumName}@./entities.ts`);\n const enumDetailType = imp(`${plural(enumName)}@./entities.ts`);\n const enumDetailsType = imp(`${enumName}Details@./entities.ts`);\n const notNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName, notNull, column.default !== null);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"enum\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnType,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: fieldDerived(config, entity, fieldName) as EnumField[\"derived\"],\n enumName,\n enumType,\n enumDetailType,\n enumDetailsType,\n notNull,\n ignore,\n enumRows: enums[r.targetTable.name].rows,\n isArray: false,\n hasConfigDefault, // can be set to true by scanEntityFiles\n hasTransitions: false, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newEnumArrayField(config: Config, entity: Entity, column: Column, enums: EnumMetadata): EnumField {\n const columnName = column.name;\n const columnType = (column.type.shortName || column.type.name) as DatabaseColumnType;\n const fieldName = enumFieldName(column.name);\n // Find the enum table name via the comment hint (instead of a FK constraint), and strip the enum= prefix\n const enumTable = column.comment!.replace(\"enum=\", \"\");\n const enumName = (enums[enumTable] || fail(`Could not find enum ${enumTable}`)).name;\n const enumType = imp(`${enumName}@./entities.ts`);\n const enumDetailType = imp(`${plural(enumName)}@./entities.ts`);\n const enumDetailsType = imp(`${enumName}Details@./entities.ts`);\n const notNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName, notNull, column.default !== null);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"enum\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnType,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n derived: fieldDerived(config, entity, fieldName) as EnumField[\"derived\"],\n enumName,\n enumType,\n enumDetailType,\n enumDetailsType,\n notNull,\n ignore,\n enumRows: enums[enumTable].rows,\n isArray: true,\n hasConfigDefault, // can be set to true by scanEntityFiles\n hasTransitions: false,\n };\n}\n\nfunction newPgEnumField(config: Config, entity: Entity, column: Column): PgEnumField {\n const fieldName = primitiveFieldName(column.name);\n const columnName = column.name;\n const enumName = pascalCase(column.type.name);\n const enumType = imp(`${enumName}@./entities.ts`);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"pg-enum\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n dbType: column.type.name,\n enumType,\n enumName,\n enumValues: (column.type as EnumType).values,\n notNull: column.notNull,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n ignore: isFieldIgnored(config, entity, fieldName, column.notNull, column.default !== null),\n hasConfigDefault, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newManyToOneField(config: Config, entity: Entity, r: M2ORelation): ManyToOneField {\n const column = r.foreignKey.columns[0];\n const columnName = column.name;\n const dbType = r.foreignKey.columns[0].type.shortName!;\n const fieldName = referenceName(config, entity, r);\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const isOneToOne = column.uniqueIndexes.find(isOneToOneIndex) !== undefined;\n const otherFieldName = isOneToOne\n ? oneToOneName(config, otherEntity, entity, r)\n : collectionName(config, otherEntity, entity, r).fieldName;\n const notNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName, notNull, column.default !== null);\n const isDeferredAndDeferrable = r.foreignKey.isDeferred && r.foreignKey.isDeferrable;\n const derived = fkFieldDerived(config, entity, fieldName);\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"m2o\",\n columnOwner: entity,\n columnNotNull: column.notNull,\n fieldName,\n columnName,\n columnDefault: column.default,\n columnGenerated: column.isGenerated,\n otherEntity,\n otherFieldName,\n notNull,\n ignore,\n derived,\n dbType,\n isDeferredAndDeferrable,\n constraintName: r.foreignKey.name,\n hasConfigDefault, // can be set to true by scanEntityFiles\n onDelete: r.foreignKey.onDelete,\n };\n}\n\nfunction newOneToMany(config: Config, entity: Entity, r: O2MRelation): OneToManyField {\n const column = r.foreignKey.columns[0];\n // source == parent i.e. the reference of the foreign key column\n // target == child i.e. the table with the foreign key column in it\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const { singularName, fieldName } = collectionName(config, entity, otherEntity, r);\n const otherFieldName = referenceName(config, otherEntity, r);\n const orderBy =\n config.entities[entity.name]?.relations?.[fieldName]?.orderBy ?? config.entities[otherEntity.name]?.orderBy;\n return {\n kind: \"o2m\",\n fieldName,\n singularName,\n otherEntity,\n otherFieldName,\n otherColumnName: column.name,\n otherColumnNotNull: column.notNull,\n ignore: isFieldIgnored(config, entity, fieldName) || isFieldIgnored(config, otherEntity, otherFieldName),\n isLargeCollection: isLargeCollection(config, entity, fieldName),\n orderBy: parseOrder(orderBy),\n softDeletes: softDeletesConfig(config, entity, fieldName),\n };\n}\n\nfunction newOneToOne(config: Config, entity: Entity, r: O2MRelation): OneToOneField {\n const column = r.foreignKey.columns[0];\n // source == parent i.e. the reference of the foreign key column\n // target == child i.e. the table with the foreign key column in it\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const fieldName = oneToOneName(config, entity, otherEntity, r);\n const otherFieldName = referenceName(config, otherEntity, r);\n const otherColumnName = column.name;\n const otherColumnNotNull = column.notNull;\n const ignore = isFieldIgnored(config, entity, fieldName) || isFieldIgnored(config, otherEntity, otherFieldName);\n return { kind: \"o2o\", fieldName, otherEntity, otherFieldName, otherColumnName, otherColumnNotNull, ignore };\n}\n\nfunction newManyToManyField(config: Config, entity: Entity, r: M2MRelation): ManyToManyField {\n const { foreignKey, targetForeignKey, targetTable } = r;\n const otherEntity = makeEntity(tableToEntityName(config, targetTable));\n // For foo_to_bar.some_foo_id use the `some_foo_id` column i.e. `someFoos`\n const fieldName = manyToManyName(targetForeignKey.columns[0]);\n const otherFieldName = manyToManyName(foreignKey.columns[0]);\n const isDeferredAndDeferrable = targetForeignKey.isDeferred && targetForeignKey.isDeferrable;\n\n // Determine if this m2m is derived:\n // - \"async\" if this side is explicitly marked as a ReactiveManyToMany\n // - \"otherSide\" if the OTHER side is marked as a ReactiveManyToMany (making this the read-only other side)\n // - false otherwise (regular m2m)\n const isThisSideDerived = isReactiveManyToMany(config, entity, fieldName);\n const isOtherSideDerived = isReactiveManyToMany(config, otherEntity, otherFieldName);\n const derived = isThisSideDerived ? \"async\" : isOtherSideDerived ? \"otherSide\" : false;\n\n return {\n kind: \"m2m\",\n joinTableName: r.joinTable.name,\n fieldName,\n singularName: singular(fieldName),\n columnName: foreignKey.columns[0].name,\n otherEntity,\n otherFieldName,\n otherColumnName: targetForeignKey.columns[0].name,\n ignore: isFieldIgnored(config, entity, fieldName) || isFieldIgnored(config, otherEntity, otherFieldName),\n isLargeCollection: isLargeCollection(config, entity, fieldName),\n isDeferredAndDeferrable,\n derived,\n softDeletes: softDeletesConfig(config, entity, fieldName),\n hasJoinTableId: joinTableHasId(r.joinTable),\n };\n}\n\nfunction newManyToManyEnumField(\n config: Config,\n entity: Entity,\n r: M2MRelation,\n enums: EnumMetadata,\n): ManyToManyEnumField {\n const { foreignKey, targetForeignKey, targetTable } = r;\n // For publisher_logo_colors.logo_color_id use the `logo_color_id` column i.e. `logoColors`\n const fieldName = manyToManyName(targetForeignKey.columns[0]);\n const enumName = tableToEntityName(config, targetTable);\n return {\n kind: \"m2mEnum\",\n joinTableName: r.joinTable.name,\n fieldName,\n columnName: foreignKey.columns[0].name,\n otherColumnName: targetForeignKey.columns[0].name,\n enumName,\n enumType: imp(`${enumName}@./entities.ts`),\n enumDetailType: imp(`${plural(enumName)}@./entities.ts`),\n enumDetailsType: imp(`${enumName}Details@./entities.ts`),\n enumRows: enums[targetTable.name].rows,\n ignore: isFieldIgnored(config, entity, fieldName),\n hasJoinTableId: joinTableHasId(r.joinTable),\n };\n}\n\nfunction newPolymorphicField(config: Config, table: Table, entity: Entity, pr: PolymorphicRelation) {\n const { fieldName, notNull } = pr;\n const components = table.m2oRelations\n .filter((r) => !isEnumTable(config, r.targetTable))\n .filter((r) => !isMultiColumnForeignKey(r))\n .filter((r) => polymorphicFieldName(config, r) === fieldName)\n .map((r) => newPolymorphicFieldComponent(config, entity, r));\n const fieldType = `${entity.name}${pascalCase(fieldName)}`;\n const hasConfigDefault = isFieldHasDefault(config, entity, fieldName);\n return {\n kind: \"poly\" as const,\n fieldName,\n fieldType,\n notNull,\n components,\n hasConfigDefault, // can be set to true by scanEntityFiles\n };\n}\n\nfunction newPolymorphicFieldComponent(config: Config, entity: Entity, r: M2ORelation): PolymorphicFieldComponent {\n const column = r.foreignKey.columns[0];\n const columnName = column.name;\n const otherEntity = makeEntity(tableToEntityName(config, r.targetTable));\n const isOneToOne = column.uniqueIndexes.find(isOneToOneIndex) !== undefined;\n const otherFieldName = isOneToOne\n ? oneToOneName(config, otherEntity, entity, r)\n : collectionName(config, otherEntity, entity, r).fieldName;\n const isDeferredAndDeferrable = r.foreignKey.isDeferred && r.foreignKey.isDeferrable;\n return {\n columnName,\n columnOwner: entity,\n otherEntity,\n otherFieldName,\n isDeferredAndDeferrable,\n constraintName: r.foreignKey.name,\n notNull: false,\n };\n}\n\nfunction isFieldNameOverrides(maybeOverride: JSONData | undefined): maybeOverride is FieldNameOverrides {\n return (\n maybeOverride !== null &&\n !Array.isArray(maybeOverride) &&\n typeof maybeOverride === \"object\" &&\n Object.keys(maybeOverride).some((k) => k === \"fieldName\" || k === \"otherFieldName\")\n );\n}\n\n/** Finds the field name for o2o side of a o2o/m2o. */\nexport function oneToOneName(\n config: Config,\n // I.e. the Book for o2o Book.image <-- `images.book_id`\n refEntity: Entity,\n // I.e. the Image for o2o Book.image <-- `images.book_id`\n keyEntity: Entity,\n r: M2ORelation | O2MRelation,\n): string {\n // If the name is overridden then use that\n const overrides = r.foreignKey.columns[0].commentData;\n if (isFieldNameOverrides(overrides) && overrides.otherFieldName) {\n return overrides.otherFieldName;\n }\n // For `comments.parent_book_review_id`, we would just use `BookReview.comment` as the name\n // For `authors.draft_current_book_id`, we would just use `Book.author` as the name\n // For `project_items.current_selection_id`, we would use `HomeownerSelection.currentProjectItem`\n const refTable = r instanceof M2ORelation ? r.targetTable : r.sourceTable;\n // Does the ref table have any m2o pointing table at the key table?\n const found = refTable.m2oRelations.find((s) => tableToEntityName(config, s.targetTable) === keyEntity.name);\n // console.log({refTable: refTable.name, keyTable: keyTable.name, found: found?.name, fieldName});\n if (!found) {\n // If there aren't any m2os, just use the raw type name like `.image` or `.comment`\n return camelCase(keyEntity.name);\n } else {\n // If there is a m2o, assume we might conflict, and use the column name to at least be unique\n // Start with `book` from `images.book_id` or `current_draft_book` from `authors.current_draft_book_id`\n let fieldName = r.foreignKey.columns[0].name.replace(idSuffix, \"\");\n // Suffix the new type that we're pointing to, to `current_draft_book_author`\n fieldName = `${fieldName}_${keyEntity.name}`;\n // And drop the `book`, to `current_draft__author`\n fieldName = fieldName.replace(refEntity.name.toLowerCase(), \"\");\n // Then camel case, to `currentDraftAuthor`\n return camelCase(fieldName);\n }\n}\n\nconst idSuffix = /_id$|Id$/;\n\nexport function referenceName(config: Config, entity: Entity, r: M2ORelation | O2MRelation): string {\n const [column] = r.foreignKey.columns;\n const overrides = column.commentData;\n return (\n polymorphicFieldName(config, r) ??\n // If the name is overridden then use that\n (isFieldNameOverrides(overrides) ? overrides.fieldName : undefined) ??\n camelCase(column.name.replace(idSuffix, \"\"))\n );\n}\n\nfunction enumFieldName(columnName: string) {\n return camelCase(columnName.replace(idSuffix, \"\"));\n}\n\nfunction primitiveFieldName(columnName: string) {\n return camelCase(columnName);\n}\n\nexport function manyToManyName(column: Column) {\n const overrides = column.commentData;\n // If the name is overridden then use that\n if (isFieldNameOverrides(overrides) && overrides.otherFieldName) {\n return overrides.otherFieldName;\n }\n return camelCase(plural(column.name.replace(idSuffix, \"\")));\n}\n\n/** Returns the collection name to use on `entity` when referring to `otherEntity`s. */\nexport function collectionName(\n config: Config,\n // I.e. the Author for o2m Author.books --> books.author_id\n singleEntity: Entity,\n // I.e. the Book for o2m Author.books --> books.author_id\n collectionEntity: Entity,\n r: M2ORelation | O2MRelation | M2MRelation,\n): { fieldName: string; singularName: string } {\n const [column] = r.foreignKey.columns;\n const overrides = column.commentData;\n // If the name is overridden then use that, but also singularize it\n if (isFieldNameOverrides(overrides) && overrides.otherFieldName) {\n const fieldName = overrides.otherFieldName;\n return { fieldName, singularName: singular(fieldName) };\n }\n // I.e. if the m2o is `books.author_id`, use `Author.books` as the collection name (we pluralize at the end).\n let singularName = collectionEntity.name;\n // Check if we have multiple FKs from collectionEntity --> singleEntity and prefix with FK name if so\n const sourceTable = r.type === \"m2o\" ? r.sourceTable : r.targetTable;\n const targetTable = r.type === \"m2o\" ? r.targetTable : r.sourceTable;\n // If `books.foo_author_id` and `books.bar_author_id` both exist\n if (r.type !== \"m2m\" && sourceTable.m2oRelations.filter((r) => r.targetTable === targetTable).length > 1) {\n // Use `fooAuthorBooks`, `barAuthorBooks`\n singularName = `${column.name.replace(idSuffix, \"\")}_${singularName}`;\n }\n // If we've guessed `Book.bookReviews` based on `book_reviews.book_id` --> `bookReviews`, strip the `Book` prefix\n if (singularName.length > singleEntity.name.length && singularName.startsWith(singleEntity.name)) {\n singularName = singularName.substring(singleEntity.name.length);\n }\n // camelize the name\n singularName = camelCase(singularName);\n // and pluralize for fieldName\n return { fieldName: plural(singularName), singularName };\n}\n\nexport function failIfOverlappingFieldNames(entity: EntityDbMetadata): void {\n const allFields = [\n entity.primaryKey,\n ...entity.primitives,\n ...entity.enums,\n ...entity.pgEnums,\n ...entity.manyToOnes,\n ...entity.oneToManys,\n ...entity.largeOneToManys,\n ...entity.oneToOnes,\n ...entity.manyToManys,\n ...entity.largeManyToManys,\n ...entity.manyToManyEnums,\n ...entity.polymorphics,\n ];\n Object.entries(groupBy(allFields, (f) => f.fieldName)).forEach(([fieldName, fields]) => {\n if (fields.length > 1) {\n throw new Error(\n `In ${entity.name}, found multiple fields named '${fieldName}': ${fields.map((f) => f.kind).join(\" \")}`,\n );\n }\n });\n}\n\nexport function makeEntity(entityName: string): Entity {\n // Default to the conventional names; `resolveNameConflicts` rewrites them if they collide.\n const names = entitySymbolNames(entityName);\n return {\n name: entityName,\n type: entityType(entityName),\n typeSymbol: entityTypeSymbol(entityName),\n typeForMetadataFile: entityTypeForMetadataFile(entityName),\n metaName: metaName(entityName),\n metaType: metaType(entityName),\n idType: entityTypeImport(entityName, names.idName),\n orderType: entityTypeImport(entityName, names.orderName),\n optsType: entityTypeImport(entityName, names.optsName),\n configConst: imp(`${camelCase(entityName)}Config@./entities.ts`, {\n definedIn: `./codegen/${entityName}Codegen.ts`,\n }),\n ...names,\n };\n}\n\n/**\n * Collapses the per-relation `otherEntity` copies down to the one primary `Entity` per name.\n *\n * `makeEntity` mints a fresh `Entity` for every relation's `otherEntity`, so each entity ends up with\n * many duplicate objects floating around. Pointing them all at the single `entitiesByName[name].entity`\n * instance means later passes (i.e. `resolveNameConflicts`) only have to update one object per name.\n *\n * Must run after inheritance, since STI/CTI specialization both adds and re-points `otherEntity`s.\n */\nexport function canonicalizeOtherEntities(db: DbMetadata): void {\n const canonical = (other: Entity) => db.entitiesByName[other.name]?.entity ?? other;\n for (const meta of db.entities) {\n for (const field of [\n ...meta.manyToOnes,\n ...meta.oneToManys,\n ...meta.largeOneToManys,\n ...meta.oneToOnes,\n ...meta.manyToManys,\n ...meta.largeManyToManys,\n ]) {\n field.otherEntity = canonical(field.otherEntity);\n }\n for (const poly of meta.polymorphics) {\n for (const comp of poly.components) comp.otherEntity = canonical(comp.otherEntity);\n }\n if (meta.physicalMetadata) {\n canonicalizeOtherEntities({ ...db, entities: [meta.physicalMetadata] });\n }\n }\n}\n\n/**\n * Rewrites codegen'd type names that collide with another exported type name.\n *\n * `makeEntity` defaults each name to the conventional `${name}<Suffix>`, but if a separate entity or\n * enum is literally named e.g. `AuthorScope` or `AuthorOrder`, our generated type of the same name\n * would collide with it, so we fall back to `Author_Scope` / `Author_Order`.\n *\n * Relies on `canonicalizeOtherEntities` having run, so mutating each primary `meta.entity` also updates\n * the `otherEntity` references that point at it (e.g. `Book.author: AuthorId` follows `Author`'s rename).\n */\nexport function resolveNameConflicts(config: Config, db: DbMetadata): void {\n // The names exported into `entities.ts` that a codegen'd type could shadow.\n const reserved = new Set<string>(db.entities.map((meta) => meta.name));\n for (const enumData of Object.values(db.enums)) {\n // An enum table exports its (singularized) type, its `Details` type/const, and its pluralized const,\n // i.e. `ChangeRequestAssetScope`, `ChangeRequestAssetScopeDetails`, and `ChangeRequestAssetScopes`.\n const enumName = tableToEntityName(config, enumData.table);\n reserved.add(enumName).add(`${enumName}Details`).add(plural(enumName));\n }\n for (const pgEnum of Object.values(db.pgEnums)) reserved.add(pgEnum.name);\n for (const meta of db.entities) {\n if (hasNameConflict(meta.name, reserved)) applyEntityNames(meta.entity, reserved);\n }\n}\n\n/** Computes the codegen'd type names for an entity, underscoring any that `reserved` already contains. */\nfunction entitySymbolNames(name: string, reserved?: Set<string>) {\n const pick = (suffix: string) => (reserved?.has(`${name}${suffix}`) ? `${name}_${suffix}` : `${name}${suffix}`);\n return {\n idName: pick(\"Id\"),\n fieldsName: pick(\"Fields\"),\n optsName: pick(\"Opts\"),\n idsOptsName: pick(\"IdsOpts\"),\n filterName: pick(\"Filter\"),\n graphqlFilterName: pick(\"GraphQLFilter\"),\n orderName: pick(\"Order\"),\n factoryExtrasName: pick(\"FactoryExtras\"),\n scopeName: pick(\"Scope\"),\n scopesName: pick(\"Scopes\"),\n };\n}\n\n/** Returns true if any of the entity's conventional type names is already taken. */\nfunction hasNameConflict(name: string, reserved: Set<string>): boolean {\n return Object.values(entitySymbolNames(name)).some((conventional) => reserved.has(conventional));\n}\n\n/** Rewrites an entity's type names (and the `Import`s built from them) to their de-conflicted form. */\nfunction applyEntityNames(entity: Entity, reserved: Set<string>): void {\n const names = entitySymbolNames(entity.name, reserved);\n Object.assign(entity, names);\n entity.idType = entityTypeImport(entity.name, names.idName);\n entity.orderType = entityTypeImport(entity.name, names.orderName);\n entity.optsType = entityTypeImport(entity.name, names.optsName);\n}\n\nfunction entityTypeImport(entityName: string, symbolName: string): Import {\n return imp(`t:${symbolName}@./entities.ts`, { definedIn: `./codegen/${entityName}Codegen.ts` });\n}\n\nfunction metaName(entityName: string): string {\n return `${camelCase(entityName)}Meta`;\n}\n\nfunction metaType(entityName: string): Import {\n return imp(`${metaName(entityName)}@./entities.ts`);\n}\n\nfunction entityType(entityName: string): Import {\n return imp(`t:${entityName}@./entities.ts`);\n}\n\nfunction entityTypeSymbol(entityName: string): Import {\n return imp(`${entityName}@./entities.ts`);\n}\n\nfunction entityTypeForMetadataFile(entityName: string): Import {\n return imp(`${entityName}@./${entityName}.ts`);\n}\n\nfunction mapType(\n config: Config,\n tableName: string,\n columnName: string,\n dbColumnType: DatabaseColumnType,\n): PrimitiveTypescriptType {\n return mapSimpleDbTypeToTypescriptType(config, dbColumnType);\n}\n\nfunction isEnumArray(c: Column): boolean {\n return c.arrayDimension === 1 && !!c.comment && c.comment.startsWith(\"enum=\");\n}\n\nfunction isArray(c: Column): boolean {\n return c.arrayDimension === 1;\n}\n\nfunction isPgEnum(c: Column): boolean {\n return c.type instanceof EnumType;\n}\n\nfunction superstructType(s: string): Import {\n // Assume it's `foo@...`, turn it into `Foo@...`\n const [symbol, ...path] = s.split(\"@\");\n return Import.from(`${pascalCase(symbol)}@${path.join(\"@\")}`);\n}\n\nfunction zodSchemaType(s: string): Code {\n const schema = Import.from(s);\n return code`${Zod}.input<typeof ${schema}>`;\n}\n\nfunction userFieldTypeType(s: string): Import {\n return Import.from(`t:${s}`);\n}\n\nfunction serdeType(s: string): Import {\n return Import.from(s);\n}\n"],"mappings":"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"}
|
package/build/config.cjs
CHANGED
|
@@ -209,7 +209,7 @@ function warnInvalidConfigEntries(config, db) {
|
|
|
209
209
|
for (const uniqueBy of entityConfig.uniqueBy || []) for (const name of uniqueBy) {
|
|
210
210
|
const field = uniqueFields.find((f) => f.fieldName === name);
|
|
211
211
|
if (!field) require_logger.logger.warn(`Found uniqueBy for non-existent or non-queryable field ${entityName}.${name}`);
|
|
212
|
-
else if (field.kind === "primitive" && (field.derived || field.
|
|
212
|
+
else if (field.kind === "primitive" && (field.derived || field.customSerde)) require_logger.logger.warn(`Found uniqueBy for unsupported primitive field ${entityName}.${name}`);
|
|
213
213
|
else if (field.kind === "enum" && (field.derived || field.isArray)) require_logger.logger.warn(`Found uniqueBy for unsupported enum field ${entityName}.${name}`);
|
|
214
214
|
}
|
|
215
215
|
}
|
package/build/config.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","names":["createFromBuffer","readFileSync","getPath","z","groupBy","getStiEntities","trueIfResolved","getLatestCodemodVersion","sortKeys","parse","join","existsSync","dirname"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, promises as fs, readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\n\nimport { createFromBuffer } from \"@dprint/formatter\";\nimport { getPath } from \"@dprint/json\";\nimport { groupBy } from \"joist-utils\";\nimport { type ParseError, parse } from \"jsonc-parser\";\nimport { z } from \"zod\";\n\nimport { getLatestCodemodVersion } from \"./codemods/index.ts\";\nimport { type DbMetadata, type Entity, type EntityDbMetadata } from \"./EntityDbMetadata.ts\";\nimport { getStiEntities } from \"./inheritance.ts\";\nimport { logger } from \"./logger.ts\";\nimport { fail, sortKeys, trueIfResolved } from \"./utils.ts\";\n\nconst jsonFormatter = createFromBuffer(readFileSync(getPath()));\n\nconst fieldConfig = z\n .object({\n // For getters & ReactiveFields\n derived: z.optional(z.union([z.literal(\"sync\"), z.literal(\"async\")])),\n protected: z.optional(z.boolean()),\n ignore: z.optional(z.boolean()),\n superstruct: z.optional(z.string()),\n zodSchema: z.optional(z.string()),\n type: z.optional(z.string()),\n serde: z.optional(z.string()),\n stiDiscriminator: z.optional(z.record(z.string(), z.string())),\n stiType: z.optional(z.union([z.string(), z.array(z.string())])),\n // Allow subclasses to mark fields as required\n notNull: z.optional(z.boolean()),\n // Allow overriding scanEntities default detection for fields with defaults added by helpers\n hasDefault: z.optional(z.boolean()),\n // Exclude a (large jsonb/text) column from the default SELECT and expose it as a lazy-loaded LazyField\n lazy: z.optional(z.boolean()),\n })\n .strict();\n\nexport type FieldConfig = z.infer<typeof fieldConfig>;\n\nconst relationConfig = z\n .object({\n // For ReactiveReferences\n derived: z.optional(z.literal(\"async\")),\n polymorphic: z.optional(z.union([z.literal(\"notNull\"), z.literal(true)])),\n large: z.optional(z.boolean()),\n orderBy: z.optional(z.string()),\n /**\n * Controls whether this collection's `.get`/`.load` hide soft-deleted entities.\n *\n * Defaults to `\"exclude\"` (soft-deleted entities are hidden); set to `\"include\"` to have\n * this specific o2m/m2m always return soft-deleted entities from `.get`/`.load`.\n */\n softDeletes: z.optional(z.union([z.literal(\"include\"), z.literal(\"exclude\")])),\n // Allow pushing m2o/m2m/o2o relations in a base type (Task) down to a subtype (TaskOld)\n stiType: z.optional(z.union([z.string(), z.array(z.string())])),\n /**\n * Allow specializing a base type relation (SmallPublisher.group: SmallPublisherGroup).\n *\n * Self-referential FKs also support `subType: \"self\"` that means each subtype will point\n * at its own subtype.\n */\n subType: z.optional(z.string()),\n /** Allow skipping self-referential fields getting a `...Recursive` relation. */\n skipRecursiveRelations: z.optional(z.boolean()),\n // Allow marking m2o FKs as required on subclasses\n notNull: z.optional(z.boolean()),\n // Allow overriding scanEntities default detection for fields with defaults added by helpers\n hasDefault: z.optional(z.boolean()),\n })\n .strict();\n\nexport type RelationConfig = z.infer<typeof relationConfig>;\n\nconst uniqueByConfig = z\n .union([z.string(), z.array(z.string()), z.array(z.array(z.string()))])\n .transform(normalizeUniqueByConfig);\n\nconst entityConfig = z\n .object({\n tag: z.string(),\n tableName: z.optional(z.string()),\n fields: z.optional(z.record(z.string(), fieldConfig)),\n relations: z.optional(z.record(z.string(), relationConfig)),\n /** Whether this entity should be abstract, e.g. for inheritance a subtype must be instantiated instead of this type. */\n abstract: z.optional(z.boolean()),\n orderBy: z.optional(z.string()),\n uniqueBy: z.optional(uniqueByConfig),\n })\n .strict();\n\nexport type EntityConfig = z.infer<typeof entityConfig>;\n\nconst timestampConfig = z\n .object({\n /** The names to check for this timestamp, i.e. `created_at` `created`, etc. */\n names: z.array(z.string()),\n /** Whether this timestamp column is required to consider a table an entity, defaults to `false`. */\n required: z.optional(z.boolean()),\n })\n .strict();\n\nexport type TimestampConfig = z.infer<typeof timestampConfig>;\n\nexport const config = z\n .object({\n /** The _build-time_ database URL for reading database metadata. */\n databaseUrl: z.optional(z.string()),\n /** Your application's request-level `Context` type. */\n contextType: z.optional(z.string()),\n /** Your application's database client's `Transaction` type. */\n transactionType: z.optional(z.string()),\n /**\n * Allows the user to specify the `updated_at` / `created_at` column names to look up, and if they're optional.\n *\n * We default to looking for `updated_at`, `updatedAt`, `created_at`, `createdAt`, and optional to true,\n * e.g. tables are not required to have both timestamp columns to be considered entities.\n *\n * These defaults are the most lenient, to facilitate running Joist against an existing schema and\n * seeing all of your entities, regardless of your previous conventions.\n */\n timestampColumns: z.optional(\n z.object({\n createdAt: z.optional(timestampConfig),\n updatedAt: z.optional(timestampConfig),\n deletedAt: z.optional(timestampConfig),\n }),\n ),\n /**\n * Allows the user to have codegen output `Temporal` types instead of the base JS `Date`\n *\n * Additionally, allows for specifying the default time zone for `Temporal` types when converting dates to/from\n * the database.\n */\n temporal: z.optional(z.union([z.boolean(), z.object({ timeZone: z.string() })])),\n /**\n * By default, we create a `flush_database` function for fast testing.\n *\n * However, if you don't want to use this, or you have your own bespoke function like we do\n * that is more application-aware, then you can disable Joist's out-of-the-box one.\n *\n * If you have more than one test database, you can set `createFlushFunction` to the array\n * of test database names, i.e. `mydb_test_1`, `mydb_test_2`, etc.\n */\n createFlushFunction: z.optional(z.union([z.boolean(), z.array(z.string())])),\n entitiesDirectory: z.string().default(\"./src/entities\"),\n codegenPlugins: z.optional(z.array(z.string())),\n entities: z.record(z.string(), entityConfig).default({}),\n ignoredTables: z.optional(z.array(z.string())),\n /** The type of entity `id` fields; defaults to `tagged-string`. */\n idType: z.optional(z.union([z.literal(\"tagged-string\"), z.literal(\"untagged-string\"), z.literal(\"number\")])),\n /** The separator between entity tags and ids; defaults to `:`, and `\"\"` disables the separator. */\n tagDelimiter: z.optional(z.string()),\n /** How we should support non-deferred foreign keys. */\n nonDeferredForeignKeys: z.optional(z.union([z.literal(\"error\"), z.literal(\"warn\"), z.literal(\"ignore\")])),\n /** Enables esm output. */\n esm: z.optional(z.boolean()),\n /** Controls the style of GraphQL pagination scaffolding. */\n paginationStyle: z.optional(z.union([z.literal(\"cursor\"), z.literal(\"limit\")])).default(\"cursor\"),\n /** Enables documentation syncing between .md files and JSDocs. */\n docs: z.optional(z.boolean()),\n /** Installs Joist's bundled Agent Skills into `.claude/skills` and `.agents/skills`; on by default, set `false` to disable. */\n skills: z.optional(z.boolean()),\n /** Output a metadata-docs.ts file with entity/field documentation available at runtime. */\n outputDocs: z.optional(z.boolean()),\n /** Auto-set by probing the project's `tsconfig.json` file. */\n allowImportingTsExtensions: z.optional(z.boolean()),\n /** The latest Joist codemod counter that has been applied to this project. */\n codemodVersion: z.number().int().min(0).default(0),\n\n /** A list of postgres schemas to use for finding tables */\n schemas: z.optional(z.array(z.string())),\n })\n .strict();\n\nexport type Config = z.infer<typeof config> & {\n // We don't persist this, and instead just use it as a cache\n __tableToEntityName?: Record<string, string>;\n};\n\nexport const ormMaintainedFields = [\"createdAt\", \"updatedAt\"];\n\n/** Ensure the user doesn't have any typos in their config. */\nexport function warnInvalidConfigEntries(config: Config, db: DbMetadata): void {\n const entitiesByName = groupBy(db.entities, (e) => e.name);\n for (const [entityName, entityConfig] of Object.entries(config.entities)) {\n const entities = entitiesByName[entityName];\n if (!entities) {\n logger.warn(`Found config for non-existent entity ${entityName}`);\n continue;\n }\n // We don't have keyBy...\n const [entity] = entities;\n\n // Check fields\n const fields = [...entity.primitives, ...entity.enums];\n for (const [name, config] of Object.entries(entityConfig.fields || {})) {\n if (config.ignore) continue;\n let field = fields.find((f) => f.fieldName === name);\n // STI types might be in the base type\n if (!field && entity.stiDiscriminatorField) {\n const stiEntities = getStiEntities(db.entities).get(entity.name)?.subTypes;\n field = stiEntities?.flatMap((st) => [...st.primitives, ...st.enums]).find((f) => f.fieldName === name);\n }\n if (!field) logger.warn(`Found config for non-existent field ${entityName}.${name}`);\n }\n\n // Check relations\n const relations = [\n ...entity.manyToOnes,\n ...entity.oneToManys,\n ...entity.manyToManys,\n ...entity.manyToManyEnums,\n ...entity.oneToOnes,\n ...entity.largeOneToManys,\n ...entity.largeManyToManys,\n ...entity.polymorphics,\n ];\n for (const [name, _] of Object.entries(entityConfig.relations || {})) {\n let relation = relations.find((r) => r.fieldName === name);\n // STI types might be in the subtypes\n if (!relation && entity.stiDiscriminatorField) {\n const stiEntities = getStiEntities(db.entities).get(entity.name)?.subTypes;\n relation = stiEntities\n ?.flatMap((entity) => [\n ...entity.manyToOnes,\n ...entity.oneToManys,\n ...entity.manyToManys,\n ...entity.oneToOnes,\n ...entity.largeOneToManys,\n ...entity.largeManyToManys,\n ...entity.polymorphics,\n ])\n ?.find((f) => f.fieldName === name);\n }\n // CTI subtype specializations (i.e. SmallPublisher.group: SmallPublisherGroup) need to look in the base type\n if (!relation && entity.baseType) {\n const baseType = entity.baseType;\n relation = [\n ...baseType.manyToOnes,\n ...baseType.oneToManys,\n ...baseType.manyToManys,\n ...baseType.oneToOnes,\n ...baseType.largeOneToManys,\n ...baseType.largeManyToManys,\n ...baseType.polymorphics,\n ].find((f) => f.fieldName === name);\n }\n\n if (!relation) logger.warn(`Found config for non-existent relation ${entityName}.${name}`);\n }\n\n const uniqueFields = [\n ...entity.primitives,\n ...entity.enums,\n ...entity.pgEnums,\n ...entity.manyToOnes,\n ...entity.polymorphics,\n ];\n for (const uniqueBy of entityConfig.uniqueBy || []) {\n for (const name of uniqueBy) {\n const field = uniqueFields.find((f) => f.fieldName === name);\n if (!field) {\n logger.warn(`Found uniqueBy for non-existent or non-queryable field ${entityName}.${name}`);\n } else if (field.kind === \"primitive\" && (field.derived || field.isArray || field.customSerde)) {\n logger.warn(`Found uniqueBy for unsupported primitive field ${entityName}.${name}`);\n } else if (field.kind === \"enum\" && (field.derived || field.isArray)) {\n logger.warn(`Found uniqueBy for unsupported enum field ${entityName}.${name}`);\n }\n }\n }\n }\n}\n\nexport function isGetterField(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.derived === \"sync\";\n}\n\nexport function isReactiveField(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.derived === \"async\";\n}\n\nexport function isReactiveReference(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.relations?.[fieldName]?.derived === \"async\";\n}\n\n/** Returns true if this m2m relation is configured as a ReactiveManyToMany (derived: async). */\nexport function isReactiveManyToMany(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.relations?.[fieldName]?.derived === \"async\";\n}\n\nexport function isProtected(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.protected === true;\n}\n\n/** Whether a column should be excluded from the default SELECT and exposed as a lazy-loaded `LazyField`. */\nexport function isLazyField(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.lazy === true;\n}\n\nexport function serdeConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.serde;\n}\n\nexport function superstructConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.superstruct;\n}\n\nexport function zodSchemaConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.zodSchema;\n}\n\nexport function fieldTypeConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.type;\n}\n\nexport function isLargeCollection(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.relations?.[fieldName]?.large === true;\n}\n\n/** Whether a collection should include (or exclude) soft-deleted entities from `.get`/`.load`. */\nexport function softDeletesConfig(\n config: Config,\n entity: Entity,\n fieldName: string,\n): \"include\" | \"exclude\" | undefined {\n return config.entities[entity.name]?.relations?.[fieldName]?.softDeletes;\n}\n\nexport function isFieldIgnored(\n config: Config,\n entity: Entity,\n fieldName: string,\n notNull: boolean = false,\n hasDefault: boolean = false,\n): boolean {\n const ignore = config.entities[entity.name]?.fields?.[fieldName]?.ignore === true;\n if (ignore && notNull && !hasDefault) {\n fail(\n `notNull field ${entity.name}.${fieldName} cannot be ignored. Alter the column to be optional or have a default value prior to ignoring it.`,\n );\n }\n return ignore;\n}\n\nexport function isFieldHasDefault(config: Config, entity: Entity, fieldName: string): boolean {\n const entityConfig = config.entities[entity.name] ?? {};\n const fieldConfig = entityConfig.fields?.[fieldName] ?? entityConfig.relations?.[fieldName] ?? {};\n return fieldConfig.hasDefault === true;\n}\n\nconst configPath = \"./joist-config.json\";\n\nexport async function loadConfig(): Promise<Config> {\n const exists = await trueIfResolved(fs.access(configPath));\n if (exists) {\n const content = await fs.readFile(configPath);\n const result = config.safeParse(stripLegacyConfigKeys(JSON.parse(content.toString())));\n if (!result.success) {\n throw new Error(\n `Invalid joist-config.json: ${result.error.issues\n .map((ze) => `${ze.path.map(String).join(\"/\")} ${ze.message}`)\n .join(\"\\n\")}`,\n );\n }\n result.data.allowImportingTsExtensions ??= projectIsUsingEsmWithImports();\n return result.data;\n }\n // Brand-new projects should not be prompted to run historical codemods.\n const initial = config.parse({ codemodVersion: getLatestCodemodVersion() });\n initial.allowImportingTsExtensions ??= projectIsUsingEsmWithImports();\n return initial;\n}\n\n/**\n * Writes the potentially-updated config entry back to `joist-config.json`.\n *\n * We format the output with prettier so it should both a) look nice and b) be deterministic,\n * such that no changes to the config show up as noops to the scm.\n */\nexport async function writeConfig(config: Config): Promise<void> {\n const sorted: Partial<Config> = sortKeys(config);\n delete sorted.__tableToEntityName;\n delete sorted.allowImportingTsExtensions;\n if (sorted.paginationStyle === \"cursor\") {\n delete sorted.paginationStyle;\n }\n const input = JSON.stringify(sorted);\n const content = jsonFormatter.formatText({ filePath: \"test.json\", fileText: input });\n await fs.writeFile(configPath, content);\n}\n\nexport function stripStiPlaceholders(config: Config, entities: EntityDbMetadata[]): void {\n // Defacto (with today's setup) the config of STI entities lives on the base entity,\n // so don't write confusing subtype-specific entries into the config file.\n // ...hopefully we don't have any code accidentally looking for the STI config...\n for (const entity of entities) {\n if (entity.inheritanceType === \"sti\" && entity.stiDiscriminatorValue) {\n delete config.entities[entity.name];\n }\n }\n}\n\n/** Applies defaults to the timestamp config. */\nexport function getTimestampConfig(config: Config): {\n updatedAtConf: Required<TimestampConfig>;\n createdAtConf: Required<TimestampConfig>;\n deletedAtConf: Required<TimestampConfig>;\n} {\n return {\n createdAtConf: {\n names: [\"created_at\", \"createdAt\"],\n required: false,\n ...config?.timestampColumns?.createdAt,\n },\n updatedAtConf: {\n names: [\"updated_at\", \"updatedAt\"],\n required: false,\n ...config?.timestampColumns?.updatedAt,\n },\n deletedAtConf: {\n names: [\"deleted_at\", \"deletedAt\"],\n required: false,\n ...config?.timestampColumns?.deletedAt,\n },\n };\n}\n\nfunction projectIsUsingEsmWithImports(): boolean {\n // Attempt to find the project's tsconfig.json in the current directory or up the directory hierarchy\n const configPath = findTsConfigFile(process.cwd());\n if (!configPath) {\n return false;\n }\n try {\n // Use jsonc-parser to parse the tsconfig.json file (not the old tsc readConfigFile which was\n // dropped in TypeScript 7), allowing for comments and trailing commas.\n const errors: ParseError[] = [];\n const parsed: unknown = parse(readFileSync(configPath, \"utf8\"), errors, { allowTrailingComma: true });\n if (errors.length > 0 || typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return false;\n const compilerOptions = (parsed as Record<string, unknown>).compilerOptions;\n return (\n typeof compilerOptions === \"object\" &&\n compilerOptions !== null &&\n !Array.isArray(compilerOptions) &&\n (compilerOptions as Record<string, unknown>).allowImportingTsExtensions === true\n );\n } catch {\n return false;\n }\n}\n\n/** Normalizes `uniqueBy` config sugar into runtime identity candidates. */\nfunction normalizeUniqueByConfig(uniqueBy: string | string[] | string[][]): string[][] {\n if (typeof uniqueBy === \"string\") return [[uniqueBy]];\n if (uniqueBy.every((field) => typeof field === \"string\")) return [uniqueBy];\n return uniqueBy;\n}\n\nfunction stripLegacyConfigKeys(raw: unknown): unknown {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n return raw;\n }\n // Accept old configs so the deprecated key disappears on the next write.\n const parsed = { ...(raw as Record<string, unknown>) };\n delete parsed.version;\n return parsed;\n}\n\n/** Finds the nearest `tsconfig.json` in `directory` or one of its ancestors. */\nfunction findTsConfigFile(directory: string): string | undefined {\n while (true) {\n const fileName = join(directory, \"tsconfig.json\");\n if (existsSync(fileName)) return fileName;\n const parent = dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.cjs","names":["createFromBuffer","readFileSync","getPath","z","groupBy","getStiEntities","trueIfResolved","getLatestCodemodVersion","sortKeys","parse","join","existsSync","dirname"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, promises as fs, readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\n\nimport { createFromBuffer } from \"@dprint/formatter\";\nimport { getPath } from \"@dprint/json\";\nimport { groupBy } from \"joist-utils\";\nimport { type ParseError, parse } from \"jsonc-parser\";\nimport { z } from \"zod\";\n\nimport { getLatestCodemodVersion } from \"./codemods/index.ts\";\nimport { type DbMetadata, type Entity, type EntityDbMetadata } from \"./EntityDbMetadata.ts\";\nimport { getStiEntities } from \"./inheritance.ts\";\nimport { logger } from \"./logger.ts\";\nimport { fail, sortKeys, trueIfResolved } from \"./utils.ts\";\n\nconst jsonFormatter = createFromBuffer(readFileSync(getPath()));\n\nconst fieldConfig = z\n .object({\n // For getters & ReactiveFields\n derived: z.optional(z.union([z.literal(\"sync\"), z.literal(\"async\")])),\n protected: z.optional(z.boolean()),\n ignore: z.optional(z.boolean()),\n superstruct: z.optional(z.string()),\n zodSchema: z.optional(z.string()),\n type: z.optional(z.string()),\n serde: z.optional(z.string()),\n stiDiscriminator: z.optional(z.record(z.string(), z.string())),\n stiType: z.optional(z.union([z.string(), z.array(z.string())])),\n // Allow subclasses to mark fields as required\n notNull: z.optional(z.boolean()),\n // Allow overriding scanEntities default detection for fields with defaults added by helpers\n hasDefault: z.optional(z.boolean()),\n // Exclude a (large jsonb/text) column from the default SELECT and expose it as a lazy-loaded LazyField\n lazy: z.optional(z.boolean()),\n })\n .strict();\n\nexport type FieldConfig = z.infer<typeof fieldConfig>;\n\nconst relationConfig = z\n .object({\n // For ReactiveReferences\n derived: z.optional(z.literal(\"async\")),\n polymorphic: z.optional(z.union([z.literal(\"notNull\"), z.literal(true)])),\n large: z.optional(z.boolean()),\n orderBy: z.optional(z.string()),\n /**\n * Controls whether this collection's `.get`/`.load` hide soft-deleted entities.\n *\n * Defaults to `\"exclude\"` (soft-deleted entities are hidden); set to `\"include\"` to have\n * this specific o2m/m2m always return soft-deleted entities from `.get`/`.load`.\n */\n softDeletes: z.optional(z.union([z.literal(\"include\"), z.literal(\"exclude\")])),\n // Allow pushing m2o/m2m/o2o relations in a base type (Task) down to a subtype (TaskOld)\n stiType: z.optional(z.union([z.string(), z.array(z.string())])),\n /**\n * Allow specializing a base type relation (SmallPublisher.group: SmallPublisherGroup).\n *\n * Self-referential FKs also support `subType: \"self\"` that means each subtype will point\n * at its own subtype.\n */\n subType: z.optional(z.string()),\n /** Allow skipping self-referential fields getting a `...Recursive` relation. */\n skipRecursiveRelations: z.optional(z.boolean()),\n // Allow marking m2o FKs as required on subclasses\n notNull: z.optional(z.boolean()),\n // Allow overriding scanEntities default detection for fields with defaults added by helpers\n hasDefault: z.optional(z.boolean()),\n })\n .strict();\n\nexport type RelationConfig = z.infer<typeof relationConfig>;\n\nconst uniqueByConfig = z\n .union([z.string(), z.array(z.string()), z.array(z.array(z.string()))])\n .transform(normalizeUniqueByConfig);\n\nconst entityConfig = z\n .object({\n tag: z.string(),\n tableName: z.optional(z.string()),\n fields: z.optional(z.record(z.string(), fieldConfig)),\n relations: z.optional(z.record(z.string(), relationConfig)),\n /** Whether this entity should be abstract, e.g. for inheritance a subtype must be instantiated instead of this type. */\n abstract: z.optional(z.boolean()),\n orderBy: z.optional(z.string()),\n uniqueBy: z.optional(uniqueByConfig),\n })\n .strict();\n\nexport type EntityConfig = z.infer<typeof entityConfig>;\n\nconst timestampConfig = z\n .object({\n /** The names to check for this timestamp, i.e. `created_at` `created`, etc. */\n names: z.array(z.string()),\n /** Whether this timestamp column is required to consider a table an entity, defaults to `false`. */\n required: z.optional(z.boolean()),\n })\n .strict();\n\nexport type TimestampConfig = z.infer<typeof timestampConfig>;\n\nexport const config = z\n .object({\n /** The _build-time_ database URL for reading database metadata. */\n databaseUrl: z.optional(z.string()),\n /** Your application's request-level `Context` type. */\n contextType: z.optional(z.string()),\n /** Your application's database client's `Transaction` type. */\n transactionType: z.optional(z.string()),\n /**\n * Allows the user to specify the `updated_at` / `created_at` column names to look up, and if they're optional.\n *\n * We default to looking for `updated_at`, `updatedAt`, `created_at`, `createdAt`, and optional to true,\n * e.g. tables are not required to have both timestamp columns to be considered entities.\n *\n * These defaults are the most lenient, to facilitate running Joist against an existing schema and\n * seeing all of your entities, regardless of your previous conventions.\n */\n timestampColumns: z.optional(\n z.object({\n createdAt: z.optional(timestampConfig),\n updatedAt: z.optional(timestampConfig),\n deletedAt: z.optional(timestampConfig),\n }),\n ),\n /**\n * Allows the user to have codegen output `Temporal` types instead of the base JS `Date`\n *\n * Additionally, allows for specifying the default time zone for `Temporal` types when converting dates to/from\n * the database.\n */\n temporal: z.optional(z.union([z.boolean(), z.object({ timeZone: z.string() })])),\n /**\n * By default, we create a `flush_database` function for fast testing.\n *\n * However, if you don't want to use this, or you have your own bespoke function like we do\n * that is more application-aware, then you can disable Joist's out-of-the-box one.\n *\n * If you have more than one test database, you can set `createFlushFunction` to the array\n * of test database names, i.e. `mydb_test_1`, `mydb_test_2`, etc.\n */\n createFlushFunction: z.optional(z.union([z.boolean(), z.array(z.string())])),\n entitiesDirectory: z.string().default(\"./src/entities\"),\n codegenPlugins: z.optional(z.array(z.string())),\n entities: z.record(z.string(), entityConfig).default({}),\n ignoredTables: z.optional(z.array(z.string())),\n /** The type of entity `id` fields; defaults to `tagged-string`. */\n idType: z.optional(z.union([z.literal(\"tagged-string\"), z.literal(\"untagged-string\"), z.literal(\"number\")])),\n /** The separator between entity tags and ids; defaults to `:`, and `\"\"` disables the separator. */\n tagDelimiter: z.optional(z.string()),\n /** How we should support non-deferred foreign keys. */\n nonDeferredForeignKeys: z.optional(z.union([z.literal(\"error\"), z.literal(\"warn\"), z.literal(\"ignore\")])),\n /** Enables esm output. */\n esm: z.optional(z.boolean()),\n /** Controls the style of GraphQL pagination scaffolding. */\n paginationStyle: z.optional(z.union([z.literal(\"cursor\"), z.literal(\"limit\")])).default(\"cursor\"),\n /** Enables documentation syncing between .md files and JSDocs. */\n docs: z.optional(z.boolean()),\n /** Installs Joist's bundled Agent Skills into `.claude/skills` and `.agents/skills`; on by default, set `false` to disable. */\n skills: z.optional(z.boolean()),\n /** Output a metadata-docs.ts file with entity/field documentation available at runtime. */\n outputDocs: z.optional(z.boolean()),\n /** Auto-set by probing the project's `tsconfig.json` file. */\n allowImportingTsExtensions: z.optional(z.boolean()),\n /** The latest Joist codemod counter that has been applied to this project. */\n codemodVersion: z.number().int().min(0).default(0),\n\n /** A list of postgres schemas to use for finding tables */\n schemas: z.optional(z.array(z.string())),\n })\n .strict();\n\nexport type Config = z.infer<typeof config> & {\n // We don't persist this, and instead just use it as a cache\n __tableToEntityName?: Record<string, string>;\n};\n\nexport const ormMaintainedFields = [\"createdAt\", \"updatedAt\"];\n\n/** Ensure the user doesn't have any typos in their config. */\nexport function warnInvalidConfigEntries(config: Config, db: DbMetadata): void {\n const entitiesByName = groupBy(db.entities, (e) => e.name);\n for (const [entityName, entityConfig] of Object.entries(config.entities)) {\n const entities = entitiesByName[entityName];\n if (!entities) {\n logger.warn(`Found config for non-existent entity ${entityName}`);\n continue;\n }\n // We don't have keyBy...\n const [entity] = entities;\n\n // Check fields\n const fields = [...entity.primitives, ...entity.enums];\n for (const [name, config] of Object.entries(entityConfig.fields || {})) {\n if (config.ignore) continue;\n let field = fields.find((f) => f.fieldName === name);\n // STI types might be in the base type\n if (!field && entity.stiDiscriminatorField) {\n const stiEntities = getStiEntities(db.entities).get(entity.name)?.subTypes;\n field = stiEntities?.flatMap((st) => [...st.primitives, ...st.enums]).find((f) => f.fieldName === name);\n }\n if (!field) logger.warn(`Found config for non-existent field ${entityName}.${name}`);\n }\n\n // Check relations\n const relations = [\n ...entity.manyToOnes,\n ...entity.oneToManys,\n ...entity.manyToManys,\n ...entity.manyToManyEnums,\n ...entity.oneToOnes,\n ...entity.largeOneToManys,\n ...entity.largeManyToManys,\n ...entity.polymorphics,\n ];\n for (const [name, _] of Object.entries(entityConfig.relations || {})) {\n let relation = relations.find((r) => r.fieldName === name);\n // STI types might be in the subtypes\n if (!relation && entity.stiDiscriminatorField) {\n const stiEntities = getStiEntities(db.entities).get(entity.name)?.subTypes;\n relation = stiEntities\n ?.flatMap((entity) => [\n ...entity.manyToOnes,\n ...entity.oneToManys,\n ...entity.manyToManys,\n ...entity.oneToOnes,\n ...entity.largeOneToManys,\n ...entity.largeManyToManys,\n ...entity.polymorphics,\n ])\n ?.find((f) => f.fieldName === name);\n }\n // CTI subtype specializations (i.e. SmallPublisher.group: SmallPublisherGroup) need to look in the base type\n if (!relation && entity.baseType) {\n const baseType = entity.baseType;\n relation = [\n ...baseType.manyToOnes,\n ...baseType.oneToManys,\n ...baseType.manyToManys,\n ...baseType.oneToOnes,\n ...baseType.largeOneToManys,\n ...baseType.largeManyToManys,\n ...baseType.polymorphics,\n ].find((f) => f.fieldName === name);\n }\n\n if (!relation) logger.warn(`Found config for non-existent relation ${entityName}.${name}`);\n }\n\n const uniqueFields = [\n ...entity.primitives,\n ...entity.enums,\n ...entity.pgEnums,\n ...entity.manyToOnes,\n ...entity.polymorphics,\n ];\n for (const uniqueBy of entityConfig.uniqueBy || []) {\n for (const name of uniqueBy) {\n const field = uniqueFields.find((f) => f.fieldName === name);\n if (!field) {\n logger.warn(`Found uniqueBy for non-existent or non-queryable field ${entityName}.${name}`);\n } else if (field.kind === \"primitive\" && (field.derived || field.customSerde)) {\n logger.warn(`Found uniqueBy for unsupported primitive field ${entityName}.${name}`);\n } else if (field.kind === \"enum\" && (field.derived || field.isArray)) {\n logger.warn(`Found uniqueBy for unsupported enum field ${entityName}.${name}`);\n }\n }\n }\n }\n}\n\nexport function isGetterField(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.derived === \"sync\";\n}\n\nexport function isReactiveField(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.derived === \"async\";\n}\n\nexport function isReactiveReference(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.relations?.[fieldName]?.derived === \"async\";\n}\n\n/** Returns true if this m2m relation is configured as a ReactiveManyToMany (derived: async). */\nexport function isReactiveManyToMany(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.relations?.[fieldName]?.derived === \"async\";\n}\n\nexport function isProtected(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.protected === true;\n}\n\n/** Whether a column should be excluded from the default SELECT and exposed as a lazy-loaded `LazyField`. */\nexport function isLazyField(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.fields?.[fieldName]?.lazy === true;\n}\n\nexport function serdeConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.serde;\n}\n\nexport function superstructConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.superstruct;\n}\n\nexport function zodSchemaConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.zodSchema;\n}\n\nexport function fieldTypeConfig(config: Config, entity: Entity, fieldName: string): string | undefined {\n return config.entities[entity.name]?.fields?.[fieldName]?.type;\n}\n\nexport function isLargeCollection(config: Config, entity: Entity, fieldName: string): boolean {\n return config.entities[entity.name]?.relations?.[fieldName]?.large === true;\n}\n\n/** Whether a collection should include (or exclude) soft-deleted entities from `.get`/`.load`. */\nexport function softDeletesConfig(\n config: Config,\n entity: Entity,\n fieldName: string,\n): \"include\" | \"exclude\" | undefined {\n return config.entities[entity.name]?.relations?.[fieldName]?.softDeletes;\n}\n\nexport function isFieldIgnored(\n config: Config,\n entity: Entity,\n fieldName: string,\n notNull: boolean = false,\n hasDefault: boolean = false,\n): boolean {\n const ignore = config.entities[entity.name]?.fields?.[fieldName]?.ignore === true;\n if (ignore && notNull && !hasDefault) {\n fail(\n `notNull field ${entity.name}.${fieldName} cannot be ignored. Alter the column to be optional or have a default value prior to ignoring it.`,\n );\n }\n return ignore;\n}\n\nexport function isFieldHasDefault(config: Config, entity: Entity, fieldName: string): boolean {\n const entityConfig = config.entities[entity.name] ?? {};\n const fieldConfig = entityConfig.fields?.[fieldName] ?? entityConfig.relations?.[fieldName] ?? {};\n return fieldConfig.hasDefault === true;\n}\n\nconst configPath = \"./joist-config.json\";\n\nexport async function loadConfig(): Promise<Config> {\n const exists = await trueIfResolved(fs.access(configPath));\n if (exists) {\n const content = await fs.readFile(configPath);\n const result = config.safeParse(stripLegacyConfigKeys(JSON.parse(content.toString())));\n if (!result.success) {\n throw new Error(\n `Invalid joist-config.json: ${result.error.issues\n .map((ze) => `${ze.path.map(String).join(\"/\")} ${ze.message}`)\n .join(\"\\n\")}`,\n );\n }\n result.data.allowImportingTsExtensions ??= projectIsUsingEsmWithImports();\n return result.data;\n }\n // Brand-new projects should not be prompted to run historical codemods.\n const initial = config.parse({ codemodVersion: getLatestCodemodVersion() });\n initial.allowImportingTsExtensions ??= projectIsUsingEsmWithImports();\n return initial;\n}\n\n/**\n * Writes the potentially-updated config entry back to `joist-config.json`.\n *\n * We format the output with prettier so it should both a) look nice and b) be deterministic,\n * such that no changes to the config show up as noops to the scm.\n */\nexport async function writeConfig(config: Config): Promise<void> {\n const sorted: Partial<Config> = sortKeys(config);\n delete sorted.__tableToEntityName;\n delete sorted.allowImportingTsExtensions;\n if (sorted.paginationStyle === \"cursor\") {\n delete sorted.paginationStyle;\n }\n const input = JSON.stringify(sorted);\n const content = jsonFormatter.formatText({ filePath: \"test.json\", fileText: input });\n await fs.writeFile(configPath, content);\n}\n\nexport function stripStiPlaceholders(config: Config, entities: EntityDbMetadata[]): void {\n // Defacto (with today's setup) the config of STI entities lives on the base entity,\n // so don't write confusing subtype-specific entries into the config file.\n // ...hopefully we don't have any code accidentally looking for the STI config...\n for (const entity of entities) {\n if (entity.inheritanceType === \"sti\" && entity.stiDiscriminatorValue) {\n delete config.entities[entity.name];\n }\n }\n}\n\n/** Applies defaults to the timestamp config. */\nexport function getTimestampConfig(config: Config): {\n updatedAtConf: Required<TimestampConfig>;\n createdAtConf: Required<TimestampConfig>;\n deletedAtConf: Required<TimestampConfig>;\n} {\n return {\n createdAtConf: {\n names: [\"created_at\", \"createdAt\"],\n required: false,\n ...config?.timestampColumns?.createdAt,\n },\n updatedAtConf: {\n names: [\"updated_at\", \"updatedAt\"],\n required: false,\n ...config?.timestampColumns?.updatedAt,\n },\n deletedAtConf: {\n names: [\"deleted_at\", \"deletedAt\"],\n required: false,\n ...config?.timestampColumns?.deletedAt,\n },\n };\n}\n\nfunction projectIsUsingEsmWithImports(): boolean {\n // Attempt to find the project's tsconfig.json in the current directory or up the directory hierarchy\n const configPath = findTsConfigFile(process.cwd());\n if (!configPath) {\n return false;\n }\n try {\n // Use jsonc-parser to parse the tsconfig.json file (not the old tsc readConfigFile which was\n // dropped in TypeScript 7), allowing for comments and trailing commas.\n const errors: ParseError[] = [];\n const parsed: unknown = parse(readFileSync(configPath, \"utf8\"), errors, { allowTrailingComma: true });\n if (errors.length > 0 || typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return false;\n const compilerOptions = (parsed as Record<string, unknown>).compilerOptions;\n return (\n typeof compilerOptions === \"object\" &&\n compilerOptions !== null &&\n !Array.isArray(compilerOptions) &&\n (compilerOptions as Record<string, unknown>).allowImportingTsExtensions === true\n );\n } catch {\n return false;\n }\n}\n\n/** Normalizes `uniqueBy` config sugar into runtime identity candidates. */\nfunction normalizeUniqueByConfig(uniqueBy: string | string[] | string[][]): string[][] {\n if (typeof uniqueBy === \"string\") return [[uniqueBy]];\n if (uniqueBy.every((field) => typeof field === \"string\")) return [uniqueBy];\n return uniqueBy;\n}\n\nfunction stripLegacyConfigKeys(raw: unknown): unknown {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n return raw;\n }\n // Accept old configs so the deprecated key disappears on the next write.\n const parsed = { ...(raw as Record<string, unknown>) };\n delete parsed.version;\n return parsed;\n}\n\n/** Finds the nearest `tsconfig.json` in `directory` or one of its ancestors. */\nfunction findTsConfigFile(directory: string): string | undefined {\n while (true) {\n const fileName = join(directory, \"tsconfig.json\");\n if (existsSync(fileName)) return fileName;\n const parent = dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n"],"mappings":"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"}
|
package/build/config.js
CHANGED
|
@@ -208,7 +208,7 @@ function warnInvalidConfigEntries(config, db) {
|
|
|
208
208
|
for (const uniqueBy of entityConfig.uniqueBy || []) for (const name of uniqueBy) {
|
|
209
209
|
const field = uniqueFields.find((f) => f.fieldName === name);
|
|
210
210
|
if (!field) logger.warn(`Found uniqueBy for non-existent or non-queryable field ${entityName}.${name}`);
|
|
211
|
-
else if (field.kind === "primitive" && (field.derived || field.
|
|
211
|
+
else if (field.kind === "primitive" && (field.derived || field.customSerde)) logger.warn(`Found uniqueBy for unsupported primitive field ${entityName}.${name}`);
|
|
212
212
|
else if (field.kind === "enum" && (field.derived || field.isArray)) logger.warn(`Found uniqueBy for unsupported enum field ${entityName}.${name}`);
|
|
213
213
|
}
|
|
214
214
|
}
|