UNPKG

@cubicweb/data-provider

Version:

CubicWeb data provider implementation

194 lines (177 loc) 5.48 kB
import { EntityRawSchemaArray, Client, RelationDefinitionRawSchemaArray, Schema, Transaction, RQLQuery, getLooseSchema, } from "@cubicweb/client"; import { GetListParams, GetListResult, GetManyParams, GetManyReferenceParams, GetManyReferenceResult, GetManyResult, GetOneParams, GetOneResult, Identifier, RaRecord, } from "./types.js"; import { executeApiTransaction } from "./utils/requests.js"; import { EntityData, generateCountEntitiesRQL, generateSelectEntitiesRQL, getEntityRelationNames, resultSetToEntities, resultSetToEntity, } from "@cubicweb/rql-generator"; export const getGet = < E extends EntityRawSchemaArray, R extends RelationDefinitionRawSchemaArray<E> >( client: Client, schema: Schema<E, R> ) => { const getDefaultRelations = (entity: string) => { const relations = []; const entitySchema = getLooseSchema(schema).getEntity(entity)!; relations.push(...getEntityRelationNames(entitySchema, "attributes")); relations.push(...getEntityRelationNames(entitySchema, "subject")); return relations; }; const getList = async ( resource: E[number]["type"], { pagination, sort, filter }: GetListParams ): Promise<GetListResult<RaRecord>> => { if (typeof filter !== "string") { throw new Error("Only RQL filters are supported for now"); } const transaction = new Transaction(); const queries = generateSelectEntitiesRQL(schema, resource, { limit: pagination.perPage, offset: (pagination.page - 1) * pagination.perPage, orderBy: [{ relationName: sort.field, ascending: sort.order === "ASC" }], relations: getDefaultRelations(resource), where: new RQLQuery(filter, {}), }); transaction.push(...queries); const countQueries = generateCountEntitiesRQL(schema, resource, { where: new RQLQuery(filter, {}), }); transaction.push(...countQueries); return executeApiTransaction(client, transaction).then((result) => { const total = result.getCell(countQueries[0].cellRef(0, 0)) as number; const entities = resultSetToEntities( schema, resource, undefined, result.getResultSet(queries[0]) ); return { data: addIdToEntities(entities), total, }; }); }; const getOne = async ( resource: E[number]["type"], params: GetOneParams ): Promise<GetOneResult<RaRecord>> => { const transaction = new Transaction(); const queries = generateSelectEntitiesRQL(schema, resource, { where: { eid: getEid(params.id) }, relations: params.meta, }); transaction.push(...queries); return executeApiTransaction(client, transaction).then((result) => { const entity = resultSetToEntity( schema, resource, params.meta, result.getResultSet(queries[0]) ); return { data: addIdToEntity(entity), }; }); }; const getMany = async ( resource: E[number]["type"], params: GetManyParams ): Promise<GetManyResult<RaRecord>> => { const idList = params.ids.map(getEid); const transaction = new Transaction(); const queries = generateSelectEntitiesRQL(schema, resource, { limit: idList.length, orderBy: [{ relationName: "eid", ascending: true }], relations: getDefaultRelations(resource), where: new RQLQuery(`X eid IN (${idList.join(", ")},)`, {}), }); transaction.push(...queries); return executeApiTransaction(client, transaction).then((result) => { const entities = resultSetToEntities( schema, resource, params.meta, result.getResultSet(queries[0]) ); return { data: addIdToEntities(entities), }; }); }; const getManyReference = async ( resource: E[number]["type"], { target, id, pagination, sort, filter }: GetManyReferenceParams ): Promise<GetManyReferenceResult<RaRecord>> => { if (typeof filter !== "string") { throw new Error("Only RQL filters are supported for now"); } const transaction = new Transaction(); const filterRql = new RQLQuery( `X ${target} ${id}${filter ? ", " + filter : ""}`, {} ); const queries = generateSelectEntitiesRQL(schema, resource, { limit: pagination.perPage, offset: (pagination.page - 1) * pagination.perPage, orderBy: [{ relationName: sort.field, ascending: sort.order === "ASC" }], relations: getDefaultRelations(resource), where: filterRql, }); transaction.push(...queries); const countQueries = generateCountEntitiesRQL(schema, resource, { where: filterRql, }); transaction.push(...countQueries); return executeApiTransaction(client, transaction).then((result) => { const total = result.getCell(countQueries[0].cellRef(0, 0)) as number; const entities = resultSetToEntities( schema, resource, undefined, result.getResultSet(queries[0]) ); return { data: addIdToEntities(entities), total, }; }); }; return { getList, getOne, getMany, getManyReference }; }; function addIdToEntities(entityList: EntityData[]): RaRecord[] { return entityList.map(addIdToEntity); } function addIdToEntity(entity: EntityData): RaRecord { return { ...entity, id: entity.eid, }; } function getEid(id: Identifier) { return typeof id === "string" ? parseInt(id) : id; }