Feature(s) impacted
We use a lot of enums, which are stored as integers in the database. Integers are pointless for a backoffice so we expose enum fields in FA instead.
We’re migrating to the new agent.
Adding an enum in the new agent requires one call to addField
and one call to replaceFieldWriting
with some boilerplate inside.
I figured it’d be a good way to try my hand at making a simple plugin, so here it is currently as a wip:
/**
* To be used on a collection.
* @param field Target field to turn into an enum, for example a status stored as a number
* @param enumObject The object with enum descriptors as keys, and real values as... values.
* @param enumFieldName If you want a different field name than `${field}Enum`
*/
export default function defineEnum<
K extends keyof Schema,
K2 extends TFieldName<Schema, K>,
>(
field: K2,
enumObject: Record<string, unknown>,
enumFieldName: string | null = null,
) {
return function (
_dataSource: DataSourceCustomizer<Schema>,
collection?: CollectionCustomizer<Schema, K>,
) {
if (!collection) {
throw new Error('defineEnum may only be use() on a collection')
}
collection
.addField(enumFieldName ?? `${field}Enum`, {
columnType: 'Enum',
enumValues: Object.keys(enumObject),
dependencies: [field],
getValues: (records) => {
const enumEntries = Object.entries(enumObject)
return records.map(
(r) => enumEntries.find(([, v]) => v === r[field])?.[0],
)
},
})
// @ts-expect-error TS does not detect the new field here
.replaceFieldWriting(enumFieldName ?? `${field}Enum`, (v) => ({
[field]: Object.entries(enumObject).find(([k]) => v === k)?.[1],
}))
}
}
Here is an example use:
const BandStatus = {
JustCreated: 0,
GrowingHigh: 50,
BrokenUp: 100,
} as const
export function BandCustomizer(
bands: CollectionCustomizer<Schema, 'Band'>,
) {
bands
.use(defineEnum('CurrentStatus', BandStatus))
I could probably use plugin options instead of a HOF. The reason I didn’t is because I can’t read documentation.
Observed behavior
The plugin does its job well, but I would love to improve my typing. Any tips?
Expected behavior
- The
field
parameter can be any string. It should ideally only allow field names of the collection; - The
enumObject
values can be anything (unknown
). They should ideally be only of the type of the database field. - Removing the
@ts-expect-error
would be nice, but that’s just beyond my reach.
Context
- Project / Team / Environment: N/A, this is on a migration project that is not in prod yet.
- Agent technology: nodejs
- Agent (forest package) name & version: 1.40.1
- Typescript version: 5.4.1
- Database type: MSSQL (with sequelize-typescript)
- Recent changes made on your end if any: Migration.