UNPKG

adminjs-graphql

Version:
319 lines 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports._testing = exports.GraphQLResourceAdapter = void 0; const graphql_1 = require("graphql"); const adminjs_1 = require("adminjs"); class GraphQLResourceAdapter extends adminjs_1.BaseResource { constructor(rawResource) { var _a, _b; super(rawResource); this.rawResource = rawResource; if (!rawResource.connection) { throw new Error("Uninitialized resource"); } this.connection = rawResource.connection; this.propertyMap = new Map((_b = (_a = rawResource.properties) === null || _a === void 0 ? void 0 : _a.map((prop) => [prop.path(), prop])) !== null && _b !== void 0 ? _b : []); } databaseName() { return this.connection.name; } databaseType() { return "graphql"; } id() { return this.rawResource.id; } properties() { return [...this.propertyMap.values()]; } property(path) { var _a; return (_a = this.propertyMap.get(path)) !== null && _a !== void 0 ? _a : null; } async count(filter) { try { const fieldFilter = this.mapFilter(filter); const mapping = this.rawResource.count(fieldFilter); return await this.executeMapping(mapping); } catch (error) { this.connection.reportAndThrow(error); } } async find(filter, options) { try { const fieldFilter = this.mapFilter(filter); const mapping = this.rawResource.find(fieldFilter, options); const result = await this.executeMapping(mapping); return result.map((record) => new adminjs_1.BaseRecord(record, this)); } catch (error) { this.connection.reportAndThrow(error); } } async findOne(id) { try { const mapping = this.rawResource.findOne(deflateReference(id)); const result = await this.executeMapping(mapping); if (result) { return new adminjs_1.BaseRecord(result, this); } return null; } catch (error) { this.connection.reportAndThrow(error); } } async findMany(ids) { const resolved = await Promise.all(ids.map((id) => this.findOne(id))); return resolved.filter((record) => record != null); } convertParams(params) { const converted = Object.keys(params).reduce((coerced, key) => { var _a, _b, _c; let value = params[key]; try { if (value != null) { const type = (_b = (_a = this.rawResource) === null || _a === void 0 ? void 0 : _a.typeMap) === null || _b === void 0 ? void 0 : _b.get(key); if (type instanceof graphql_1.GraphQLScalarType) { value = type.serialize(value); } } coerced[key] = value; return coerced; } catch (thrown) { const error = thrown; if (value === "" && !((_c = this.propertyMap.get(key)) === null || _c === void 0 ? void 0 : _c.isRequired())) { coerced[key] = null; return coerced; } throw new adminjs_1.ValidationError({ [key]: { type: "conversion", message: error.message, }, }); } }, {}); return converted; } validateParams(params) { var _a, _b, _c, _d, _e, _f; const errors = {}; const editProperties = (_c = (_b = (_a = this._decorated) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.editProperties) !== null && _c !== void 0 ? _c : []; for (const key of this.properties().map((p) => p.path())) { const property = (_d = this._decorated) === null || _d === void 0 ? void 0 : _d.getPropertyByKey(key); const value = params[key]; // Skip properties that are not being edited if (editProperties.length && !editProperties.includes((_e = property === null || property === void 0 ? void 0 : property.property.path()) !== null && _e !== void 0 ? _e : "")) { continue; } // Skip self ID properties if ((property === null || property === void 0 ? void 0 : property.isId()) && (property === null || property === void 0 ? void 0 : property.type()) !== "reference") { continue; } const required = (_f = property === null || property === void 0 ? void 0 : property.options.isRequired) !== null && _f !== void 0 ? _f : property === null || property === void 0 ? void 0 : property.isRequired(); if (required) { if (value === "" || value === null || value === undefined) { errors[key] = { type: "required", message: "Required field", }; } } } if (Object.keys(errors).length) { throw new adminjs_1.ValidationError(errors); } } async create(params) { var _a, _b; try { const inflated = inflateParams(this.convertParams(params)); this.validateParams(inflated); const mapping = (_b = (_a = this.rawResource).create) === null || _b === void 0 ? void 0 : _b.call(_a, inflated); if (!mapping) { throw new adminjs_1.ForbiddenError("Resource is not editable"); } return await this.executeMapping(mapping); } catch (error) { this.connection.reportAndThrow(error); } } async update(id, params) { var _a, _b; try { const inflated = inflateParams(this.convertParams(params)); this.validateParams(inflated); const mapping = (_b = (_a = this.rawResource).update) === null || _b === void 0 ? void 0 : _b.call(_a, id, inflated); if (!mapping) { throw new adminjs_1.ForbiddenError("Resource is not editable"); } return await this.executeMapping(mapping); } catch (error) { this.connection.reportAndThrow(error); } } async delete(id) { var _a, _b; try { const mapping = (_b = (_a = this.rawResource).delete) === null || _b === void 0 ? void 0 : _b.call(_a, id); if (!mapping) { throw new adminjs_1.ForbiddenError("Resource is not editable"); } await this.executeMapping(mapping); } catch (error) { this.connection.reportAndThrow(error); } } static isAdapterFor(resource) { const internalResource = resource; return internalResource.tag == "GraphQLResource"; } async executeMapping(mapping) { var _a; const queryString = typeof mapping.query === "string" ? mapping.query : (_a = mapping.query.loc) === null || _a === void 0 ? void 0 : _a.source.body; if (!queryString) { this.connection.reportAndThrow(new Error("Unexpected parsed query without body")); } const result = await this.connection.request(queryString, mapping.variables); const parsed = mapping.parseResult(result); if (!this.rawResource.makeSubproperties) { if (parsed instanceof Array) { return parsed.map((p) => deflateParams(p)); } else { return deflateParams(parsed); } } return parsed; } mapFilter(filter) { return filter.reduce((mapped, element) => { var _a; const from = typeof element.value == "string" ? element.value : element.value.from; const to = typeof element.value == "string" ? from : element.value.to; const matchOperation = element.property.type() === "string" ? "MATCH" : "EQ"; let graphQLType = (_a = this.rawResource.typeMap) === null || _a === void 0 ? void 0 : _a.get(element.path); if (graphQLType instanceof graphql_1.GraphQLObjectType) { graphQLType = graphql_1.GraphQLID; } if (!graphQLType || !(0, graphql_1.isInputType)(graphQLType)) { this.connection.reportAndThrow(new Error(`Cannot get valid GraphQL type from ${this.rawResource.id}:${element.path}`)); } const coercedFrom = convertValue(from, graphQLType); const coercedTo = convertValue(to, graphQLType); if (from === to) { mapped.push({ field: element.property.path(), is: matchOperation, to: coercedFrom, }); } else { if (from !== undefined && from != "") { mapped.push({ field: element.property.path(), is: "GTE", to: coercedFrom, }); } if (to !== undefined && to != "") { mapped.push({ field: element.property.path(), is: "LTE", to: coercedTo, }); } } return mapped; }, []); } } exports.GraphQLResourceAdapter = GraphQLResourceAdapter; function inflateParams(params) { const record = {}; for (const path of Object.keys(params)) { const steps = path.split("."); let object = record; let index = -1; while (steps.length > 1) { const step = steps.shift(); let nextObject = {}; if (step === undefined) { break; } index = parseInt(steps[0]); if (!isNaN(index)) { nextObject = []; } object[step] = object[step] || nextObject; object = object[step]; } if (object instanceof Array) { object.length = index + 1; object[index] = params[path]; } else { object[steps[0]] = params[path]; } } return record; } function deflateParams(params, IDField = "ID") { if (typeof params !== "object" || params == null) { return params; } const typed = params; const record = {}; for (const key of Object.keys(typed)) { let param = typed[key]; if (typeof param === "object" && param !== null) { const deflated = deflateParams(param); const deflatedKeys = Object.keys(deflated); if (deflatedKeys.length === 1 && IDField in deflated) { // Reference hack! param = Object.values(deflated)[0]; record[key] = param; } else { for (const subKey of deflatedKeys) { record[`${key}.${subKey}`] = deflated[subKey]; } } } else { record[key] = param; } } return record; } function deflateReference(ref) { if (typeof ref === "object" && ref !== null) { const fields = Object.values(ref); if (fields.length === 1) { return fields[0]; } } return `${ref}`; } function convertValue(value, type) { if (type instanceof graphql_1.GraphQLScalarType) { return type.serialize(value); } return value; } exports._testing = { inflateParams, deflateParams, }; //# sourceMappingURL=GraphQLResource.js.map