Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const { uidProp, uidRefProp } = this.modelClass()
walkGraph(data, (value, path) => {
if (isObject(value)) {
const { [uidProp]: id, [uidRefProp]: ref } = value
if (id) {
identifiers[id] = path.join('/')
} else if (ref) {
references[path.join('/')] = ref
}
}
})
// Now clone the data and delete all references from it, for the initial
// upsert.
const cloned = clone(data)
for (const path of Object.keys(references)) {
const parts = parseDataPath(path)
const key = parts.pop()
const parent = getDataPath(cloned, parts)
delete parent[key]
}
// TODO: The model isn't necessarily fetched with data in the same order as
// `cloned` defines, e.g. if there is sorting in the database. A solid
// implementation of this would take care of that and map entries from
// `model` back to `cloned`, so that the `setDataPath` calls below would
// still work in such cases.
const model = await this.clone().upsertGraphAndFetch(cloned, options)
// Now for each identifier, create an object containing only the final id in
// the fetched model data:
validate({ json, model, ctx, options }) {
const { jsonSchema } = ctx
if (jsonSchema) {
// We need to clone the input json if we are about to set default values.
if (
!options.mutable &&
!options.patch &&
hasDefaults(jsonSchema.properties)
) {
json = clone(json)
}
// Get the right Ajv instance for the given patch and async options
const validate = this.getAjv(options).getSchema(jsonSchema.$id)
// Use `call()` to pass ctx as context to Ajv, see passContext:
const res = validate.call(ctx, json)
const handleErrors = errors => {
if (errors) {
// NOTE: The conversion from Ajv errors to Objection errors happen in
// Model.createValidationError(), which calls Validator.parseError()
throw model.constructor.createValidationError({
type: 'ModelValidation',
errors,
options
})
}
}
inheritedData() {
// Data inherited from parent, and cloned to protect against reactive
// changes until changes are applied through setSourceData(), unless
// `sourceSchema.mutate` is true, in which case data is mutated directly.
if (
this.isTransient &&
this.clonedData === undefined &&
this.sourceData &&
this.sourceKey !== null
) {
let data = this.sourceData[this.sourceKey]
if (!this.doesMutate) {
// Use a trick to store cloned inherited data in clonedData, to make
// it reactive and prevent it from being cloned multiple times.
this.clonedData = data = clone(data)
}
if (
data === null &&
!this.isCreating &&
isObjectSource(this.sourceSchema)
) {
// If data of an object source is null, redirect to its create route.
this.$router.push({ path: 'create', append: true })
}
return data
}
return this.clonedData
},
function addEagerScope(modelClass, expr, scopes, modifiers, isRoot = true) {
if (isRoot) {
expr = clone(expr)
} else {
// Only add the scope if it's not already defined by the eager statement and
// if it's actually available as a modifier in the model's modifiers list.
for (const scope of scopes) {
if (!expr.$modify?.includes(scope) &&
(modelClass.modifiers[scope] || modifiers?.[scope])) {
expr.$modify.push(scope)
}
}
}
const relations = modelClass.getRelations()
for (const key in expr) {
// All enumerable properties that don't start with '$' are child nodes.
if (key[0] !== '$') {
const child = expr[key]
const relation = relations[child.$relation || key]
processSchema(jsonSchema, options = {}) {
const { patch, async } = options
const schema = clone(jsonSchema, value => {
if (isObject(value)) {
if (patch) {
// Remove all required keywords and formats from schema for patch
// validation.
delete value.required
if (value.format === 'required') {
delete value.format
}
}
// Convert async `validate()` keywords to `validateAsync()`:
if (isAsync(value.validate)) {
value.validateAsync = value.validate
delete value.validate
}
if (!async) {
// Remove all async keywords for synchronous validation.
beforeValidate({ json, model, ctx, options }) {
// Add validator instance, app and options to context
ctx.validator = this
ctx.app = this.app
ctx.options = options
ctx.jsonSchema = model.constructor.getJsonSchema()
const { $beforeValidate } = model
if ($beforeValidate !== objection.Model.prototype.$beforeValidate) {
// TODO: Consider adding hooks for 'before:validate' and 'after:validate',
// and if so, decide what to do about modifying / returning json-schema.
// Probably we shouldn't allow it there.
// Only clone jsonSchema if the handler actually receives it.
if ($beforeValidate.length > 0) {
ctx.jsonSchema = clone(ctx.jsonSchema)
}
const ret = model.$beforeValidate(ctx.jsonSchema, json, options)
if (ret !== undefined) {
ctx.jsonSchema = ret
}
}
}
: data => clone(data)
},