Skip to content

Commit

Permalink
feat: ignore indexes and relation field
Browse files Browse the repository at this point in the history
  • Loading branch information
Hieuzest committed Oct 13, 2024
1 parent 7bab4a9 commit 7ec6ace
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 43 deletions.
27 changes: 8 additions & 19 deletions packages/core/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,11 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
;(model.fields[key] = Field.parse('expr')).relation = relation
if (def.target) {
(relmodel.fields[def.target] ??= Field.parse('expr')).relation = inverse
disposables.unshift(() => delete relmodel.fields[def.target!])
}

if (relation.type === 'oneToOne' || relation.type === 'manyToOne') {
relation.fields.forEach((x, i) => {
if (!model.fields[x]) disposables.unshift(() => delete model.fields[x])
if (!(x in model.fields)) disposables.unshift(() => delete model.fields[x])
model.fields[x] ??= { ...relmodel.fields[relation.references[i]] } as any
if (!relation.required) {
model.fields[x]!.nullable = true
Expand Down Expand Up @@ -197,25 +196,15 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
if (Array.isArray(model.primary) || model.fields[model.primary]!.relation) {
model.primary = deduplicate(makeArray(model.primary).map(key => model.fields[key]!.relation?.fields || key).flat())
}
model.unique = model.unique.map(keys => {
if (typeof keys === 'string') {
return (model.fields[keys]!.relation?.fields && disposables.unshift(() => model.unique.splice(model.unique.indexOf(keys), 1)),
model.fields[keys]!.relation?.fields || keys)
} else {
const pred = keys.some(key => model.fields[key]!.relation?.fields)
if (pred) {
const newKeys = keys.map(key => model.fields[key]!.relation?.fields || key).flat()
disposables.unshift(() => model.unique.splice(model.unique.indexOf(newKeys), 1))
return newKeys
} else {
return keys
}
}
})
model.unique = model.unique.map(keys => typeof keys === 'string' ? model.fields[keys]!.relation?.fields || keys
: keys.map(key => model.fields[key]!.relation?.fields || key).flat())

this.prepareTasks[name] = this.prepare(name)
;(this.ctx as Context).emit('model', name)
return this.ctx.effect(() => () => disposables.splice(0).forEach(dispose => dispose()))
return this.ctx.effect(() => () => {
disposables.splice(0).forEach(dispose => dispose())
;(this.ctx as Context).emit('model', name)
})
}

private _parseField(field: any, transformers: Driver.Transformer[] = [], setInitial?: (value) => void, setField?: (value) => void): Type {
Expand Down Expand Up @@ -321,7 +310,7 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
fields: Field.Extension<S[K], N>,
callback: Model.Migration<this>,
) {
this.extend(name, fields, { callback })
return this.extend(name, fields, { callback })
}

select<T>(table: Selection<T>, query?: Query<T>): Selection<T>
Expand Down
25 changes: 9 additions & 16 deletions packages/core/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,23 +274,18 @@ export class Model<S = any> {

extend(fields: Field.Extension<S>, config?: Partial<Model.Config>): () => void
extend(fields = {}, config: Partial<Model.Config> = {}) {
const { primary, autoInc, unique = [], indexes = [], foreign = {}, callback } = config
const disposables: (() => void)[] = []
const { primary, autoInc, unique = [], indexes = [], foreign, callback } = config

this.primary = primary || this.primary
this.autoInc = autoInc || this.autoInc
unique.forEach(key => this.unique.includes(key) || (this.unique.push(key), disposables.push(() => this.unique.splice(this.unique.indexOf(key), 1))))
indexes.map(x => this.parseIndex(x)).forEach(index => (this.indexes.some(ind => deepEqual(ind, index)))
|| (this.indexes.push(index), disposables.push(() => this.indexes.splice(this.indexes.indexOf(index), 1))))
Object.keys(foreign).forEach(key => Object.hasOwn(this.foreign, key)
|| (this.foreign[key] = foreign[key], disposables.push(() => delete this.foreign[key])))
unique.forEach(key => this.unique.includes(key) || this.unique.push(key))
indexes.map(x => this.parseIndex(x)).forEach(index => (this.indexes.some(ind => deepEqual(ind, index))) || this.indexes.push(index))
Object.assign(this.foreign, foreign)

if (callback) this.migrations.set(callback, Object.keys(fields))

for (const key in fields) {
if (makeArray(this.primary).includes(key)) {
disposables.push(() => delete this.ctx?.get('model')?.tables[this.name])
}
if (Object.keys(this.fields).includes(key)) throw new TypeError(`field "${key}" already exists in table "${this.name}"`)
this.fields[key] = Field.parse(fields[key])
this.fields[key].deprecated = !!callback
}
Expand All @@ -304,12 +299,10 @@ export class Model<S = any> {
this.unique.forEach(index => this.checkIndex(index))
this.indexes.forEach(index => this.checkIndex(index))

return () => {
for (const key in fields) {
delete this.fields[key]
}
if (callback) this.migrations.delete(callback)
disposables.splice(0).forEach(dispose => dispose())
if (Object.keys(fields).some(key => makeArray(this.primary).includes(key))) {
return () => delete this.ctx?.get('model')?.tables[this.name]
} else {
return () => Object.keys(fields).forEach(key => delete this.fields[key])
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/tests/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type UnitOptions<T> = (T extends (database: Database, options?: infer R) => any
[K in keyof T as Exclude<K, Keywords>]?: false | UnitOptions<T[K]>
}

type Unit<T> = ((database: Database | ((arg: T) => Database), options: UnitOptions<T>, fork?: boolean) => void) & {
type Unit<T> = ((database: Database, options?: UnitOptions<T>) => void) & {
[K in keyof T as Exclude<K, Keywords>]: Unit<T[K]>
}

Expand Down
1 change: 0 additions & 1 deletion packages/tests/src/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ interface Tables {

function JsonTests(database: Database<Tables>) {
before(async () => {
console.log(Object.keys(database.tables))
database.extend('foo', {
id: 'unsigned',
value: 'integer',
Expand Down
47 changes: 41 additions & 6 deletions packages/tests/src/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ function MigrationTests(database: Database<Tables>) {
])

database.extend('qux', {
id: 'unsigned',
text: 'string(64)',
number: 'unsigned',
})

Expand All @@ -73,6 +71,46 @@ function MigrationTests(database: Database<Tables>) {
])
})

it('alter disposable field', async () => {
Reflect.deleteProperty(database.tables, 'qux')

database.extend('qux', {
id: 'unsigned',
text: 'string(64)',
})

await database.upsert('qux', [
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' },
])

await expect(database.get('qux', {})).to.eventually.deep.equal([
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' },
])

const dispose = database.extend('qux', {
number: 'unsigned',
})

await database.upsert('qux', [
{ id: 1, text: 'foo', number: 100 },
{ id: 2, text: 'bar', number: 200 },
])

await expect(database.get('qux', {})).to.eventually.deep.equal([
{ id: 1, text: 'foo', number: 100 },
{ id: 2, text: 'bar', number: 200 },
])

dispose()

await expect(database.get('qux', {})).to.eventually.deep.equal([
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' },
])
})

it('should migrate field', async () => {
Reflect.deleteProperty(database.tables, 'qux')

Expand Down Expand Up @@ -174,10 +212,7 @@ function MigrationTests(database: Database<Tables>) {
{ id: 2, number: 2 },
])

database.extend('qux', {
id: 'unsigned',
number: 'unsigned',
}, {
database.extend('qux', {}, {
indexes: ['number'],
})

Expand Down

0 comments on commit 7ec6ace

Please sign in to comment.