Skip to content

Commit

Permalink
refa: use this.ctx instead of symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 17, 2024
1 parent 60e474f commit bb8e2e9
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"yakumo": "^1.0.0-beta.16",
"yakumo-esbuild": "^1.0.0-beta.6",
"yakumo-mocha": "^1.0.0-beta.2",
"yakumo-tsc": "^1.0.0-beta.3",
"yakumo-tsc": "^1.0.0-beta.4",
"yml-register": "^1.2.5"
}
}
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
}
},
"peerDependencies": {
"cordis": "^3.16.1"
"cordis": "^3.16.2"
},
"dependencies": {
"cosmokit": "^1.6.2"
Expand Down
33 changes: 17 additions & 16 deletions packages/core/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ function mergeQuery<T>(base: Query.FieldExpr<T>, query: Query.Expr<Flatten<T>> |
export class Database<S = {}, N = {}, C extends Context = Context> extends Service<undefined, C> {
static [Service.provide] = 'model'
static [Service.immediate] = true

static readonly transact = Symbol('minato.transact')
static readonly migrate = Symbol('minato.migrate')

Expand Down Expand Up @@ -142,7 +143,7 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
})
model.extend(fields, config)
if (makeArray(model.primary).every(key => key in fields)) {
defineProperty(model, 'ctx', this[Context.origin])
defineProperty(model, 'ctx', this.ctx)
}
Object.entries(fields).forEach(([key, def]: [string, Relation.Definition]) => {
if (!Relation.Type.includes(def.type)) return
Expand Down Expand Up @@ -285,7 +286,7 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
const type = this._parseField(field, transformers, undefined, value => field = value)
field.transformers = transformers

this[Context.current].effect(() => {
this.ctx.effect(() => {
this.types[name] = { ...field }
this.types[name].deftype ??= this.types[field.type]?.deftype ?? type.type as any
return () => delete this.types[name]
Expand All @@ -305,16 +306,16 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
select<K extends Keys<S>>(
table: K,
query?: Query<S[K]>,
cursor?: Relation.Include<S[K], Values<S>> | null,
include?: Relation.Include<S[K], Values<S>> | null,
): Selection<S[K]>

select(table: any, query?: any, cursor?: any) {
select(table: any, query?: any, include?: any) {
let sel = new Selection(this.getDriver(table), table, query)
if (typeof table !== 'string') return sel
const whereOnly = cursor === null
const whereOnly = include === null
const rawquery = typeof query === 'function' ? query : () => query
const modelFields = this.tables[table].fields
if (cursor) cursor = filterKeys(cursor, (key) => !!modelFields[key]?.relation)
if (include) include = filterKeys(include, (key) => !!modelFields[key]?.relation)
for (const key in { ...sel.query, ...sel.query.$not }) {
if (modelFields[key]?.relation) {
if (sel.query[key] === null && !modelFields[key].relation.required) {
Expand All @@ -333,19 +334,19 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
Object.entries(sel.query.$not[key]).forEach(([k, v]) => sel.query.$not![`${key}.${k}`] = v)
delete sel.query.$not[key]
}
if (!cursor || !Object.getOwnPropertyNames(cursor).includes(key)) {
(cursor ??= {})[key] = true
if (!include || !Object.getOwnPropertyNames(include).includes(key)) {
(include ??= {})[key] = true
}
}
}

sel.query = omit(sel.query, Object.keys(cursor ?? {}))
sel.query = omit(sel.query, Object.keys(include ?? {}))
if (Object.keys(sel.query.$not ?? {}).length) {
sel.query.$not = omit(sel.query.$not!, Object.keys(cursor ?? {}))
sel.query.$not = omit(sel.query.$not!, Object.keys(include ?? {}))
if (Object.keys(sel.query.$not).length === 0) Reflect.deleteProperty(sel.query, '$not')
}

if (cursor && typeof cursor === 'object') {
if (include && typeof include === 'object') {
if (typeof table !== 'string') throw new Error('cannot include relations on derived selection')
const extraFields: string[] = []
const applyQuery = (sel: Selection, key: string) => {
Expand All @@ -355,16 +356,16 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
: undefined
return relquery === undefined ? sel : sel.where(this.transformRelationQuery(table, sel.row, key, relquery))
}
for (const key in cursor) {
if (!cursor[key] || !modelFields[key]?.relation) continue
for (const key in include) {
if (!include[key] || !modelFields[key]?.relation) continue
const relation: Relation.Config<S> = modelFields[key]!.relation as any
if (relation.type === 'oneToOne' || relation.type === 'manyToOne') {
sel = whereOnly ? sel : sel.join(key, this.select(relation.table, {}, cursor[key]), (self, other) => Eval.and(
sel = whereOnly ? sel : sel.join(key, this.select(relation.table, {}, include[key]), (self, other) => Eval.and(
...relation.fields.map((k, i) => Eval.eq(self[k], other[relation.references[i]])),
), true)
sel = applyQuery(sel, key)
} else if (relation.type === 'oneToMany') {
sel = whereOnly ? sel : sel.join(key, this.select(relation.table, {}, cursor[key]), (self, other) => Eval.and(
sel = whereOnly ? sel : sel.join(key, this.select(relation.table, {}, include[key]), (self, other) => Eval.and(
...relation.fields.map((k, i) => Eval.eq(self[k], other[relation.references[i]])),
), true)
sel = applyQuery(sel, key)
Expand All @@ -381,7 +382,7 @@ export class Database<S = {}, N = {}, C extends Context = Context> extends Servi
field: x,
reference: y,
}] as const)
sel = whereOnly ? sel : sel.join(key, this.select(assocTable, {}, { [relation.table]: cursor[key] } as any), (self, other) => Eval.and(
sel = whereOnly ? sel : sel.join(key, this.select(assocTable, {}, { [relation.table]: include[key] } as any), (self, other) => Eval.and(
...shared.map(([k, v]) => Eval.eq(self[v.field], other[k])),
...relation.fields.map((k, i) => Eval.eq(self[k], other[references[i]])),
), true)
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/driver.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Awaitable, Dict, mapValues, remove } from 'cosmokit'
import { Context, Logger } from 'cordis'
import { Context, Logger, Service } from 'cordis'
import { Eval, Update } from './eval.ts'
import { Direction, Modifier, Selection } from './selection.ts'
import { Field, Model, Relation } from './model.ts'
import { Database } from './database.ts'
import { Type } from './type.ts'
import { Keys, Values } from './utils.ts'
import { FlatKeys, Keys, Values } from './utils.ts'

export namespace Driver {
export interface Stats {
Expand All @@ -24,7 +24,7 @@ export namespace Driver {
limit?: number
offset?: number
fields?: K[]
sort?: Dict<Direction, K>
sort?: Partial<Dict<Direction, FlatKeys<S[T]>>>
include?: Relation.Include<S[T], Values<S>>
}

Expand Down Expand Up @@ -78,6 +78,10 @@ export abstract class Driver<T = any, C extends Context = Context> {
ctx.model.refresh()
const database = Object.create(ctx.model)
database._driver = this
database[Service.tracker] = {
associate: 'database',
property: 'ctx',
}
ctx.set('database', Context.associate(database, 'database'))
})

Expand Down

0 comments on commit bb8e2e9

Please sign in to comment.