UNPKG

@lucidcms/core

Version:

The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.

1 lines 5.88 kB
{"version":3,"file":"nullify-references.mjs","names":[],"sources":["../../../../../../src/libs/collection/custom-fields/fields/relation/nullify-references.ts"],"sourcesContent":["import type {\n\tCFConfig,\n\tFieldTypes,\n\tLucidBrickTableName,\n\tServiceFn,\n} from \"../../../../../types.js\";\nimport prefixGeneratedColName from \"../../../helpers/prefix-generated-column-name.js\";\nimport { getBricksTableSchema } from \"../../../schema/runtime/runtime-schema-selectors.js\";\nimport type { CollectionSchemaTable } from \"../../../schema/types.js\";\nimport { relationFieldConfig } from \"./config.js\";\nimport { normalizeRelationCollections } from \"./utils/normalize-relation-collections.js\";\n\ntype FieldConfig = CFConfig<FieldTypes>;\n\n/**\n * Returns true when the field can reference the deleted collection.\n */\nconst canReferenceCollection = (\n\tfield: FieldConfig,\n\ttargetCollectionKey: string,\n): boolean => {\n\treturn (\n\t\tfield.type === \"relation\" &&\n\t\tnormalizeRelationCollections(field.collection).includes(targetCollectionKey)\n\t);\n};\n\n/**\n * Finds the relation table generated for a relation custom field.\n */\nconst findRelationTable = (props: {\n\tschemas: CollectionSchemaTable<LucidBrickTableName>[];\n\tcollectionKey: string;\n\tbrickKey?: string;\n\tfieldKey: string;\n}): LucidBrickTableName | null => {\n\tconst relationSchema = props.schemas.find((schema) => {\n\t\tif (schema.key.collection !== props.collectionKey) return false;\n\t\tif (schema.type !== relationFieldConfig.database.tableType) return false;\n\t\tif (schema.key.brick !== props.brickKey) return false;\n\n\t\tconst fieldPath = schema.key.fieldPath;\n\t\treturn fieldPath?.length === 1 && fieldPath[0] === props.fieldKey;\n\t});\n\n\treturn relationSchema?.name ?? null;\n};\n\n/**\n * Recursively collects relation tables that reference the deleted collection.\n */\nconst collectReferenceTargets = (props: {\n\tfields: FieldConfig[];\n\tschemas: CollectionSchemaTable<LucidBrickTableName>[];\n\tcollectionKey: string;\n\ttargetCollectionKey: string;\n\tbrickKey?: string;\n\ttargets: Set<LucidBrickTableName>;\n}): void => {\n\tfor (const field of props.fields) {\n\t\tif (canReferenceCollection(field, props.targetCollectionKey)) {\n\t\t\tconst relationTable = findRelationTable({\n\t\t\t\tschemas: props.schemas,\n\t\t\t\tcollectionKey: props.collectionKey,\n\t\t\t\tbrickKey: props.brickKey,\n\t\t\t\tfieldKey: field.key,\n\t\t\t});\n\t\t\tif (relationTable) {\n\t\t\t\tprops.targets.add(relationTable);\n\t\t\t}\n\t\t}\n\n\t\tif (field.type !== \"repeater\") continue;\n\n\t\tcollectReferenceTargets({\n\t\t\tfields: field.fields,\n\t\t\tschemas: props.schemas,\n\t\t\tcollectionKey: props.collectionKey,\n\t\t\ttargetCollectionKey: props.targetCollectionKey,\n\t\t\tbrickKey: props.brickKey,\n\t\t\ttargets: props.targets,\n\t\t});\n\t}\n};\n\n/**\n * Deletes all stored relation rows that point at a deleted document.\n */\nconst nullifyRelationReferences: ServiceFn<\n\t[\n\t\t{\n\t\t\tdocumentId: number;\n\t\t\tcollectionKey: string;\n\t\t},\n\t],\n\tundefined\n> = async (context, data) => {\n\tconst referenceTargets = new Set<LucidBrickTableName>();\n\n\tfor (const collection of context.config.collections) {\n\t\tconst bricksTableSchemaRes = await getBricksTableSchema(\n\t\t\tcontext,\n\t\t\tcollection.key,\n\t\t);\n\t\tif (bricksTableSchemaRes.error) return bricksTableSchemaRes;\n\n\t\tcollectReferenceTargets({\n\t\t\tfields: collection.persistedFieldTree,\n\t\t\tschemas: bricksTableSchemaRes.data,\n\t\t\tcollectionKey: collection.key,\n\t\t\ttargetCollectionKey: data.collectionKey,\n\t\t\ttargets: referenceTargets,\n\t\t});\n\n\t\tfor (const brick of collection.brickInstances) {\n\t\t\tcollectReferenceTargets({\n\t\t\t\tfields: brick.persistedFieldTree,\n\t\t\t\tschemas: bricksTableSchemaRes.data,\n\t\t\t\tcollectionKey: collection.key,\n\t\t\t\ttargetCollectionKey: data.collectionKey,\n\t\t\t\tbrickKey: brick.key,\n\t\t\t\ttargets: referenceTargets,\n\t\t\t});\n\t\t}\n\t}\n\n\tconst relationDocumentColumn = prefixGeneratedColName(\"document_id\");\n\tconst relationCollectionColumn = prefixGeneratedColName(\"collection_key\");\n\n\tfor (const table of referenceTargets) {\n\t\tawait context.db.client\n\t\t\t.deleteFrom(table)\n\t\t\t.where(relationDocumentColumn, \"=\", data.documentId)\n\t\t\t.where(relationCollectionColumn, \"=\", data.collectionKey)\n\t\t\t.execute();\n\t}\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: undefined,\n\t};\n};\n\nexport default nullifyRelationReferences;\n"],"mappings":"0SAiBA,MAAM,GACL,EACA,IAGC,EAAM,OAAS,YACf,EAA6B,EAAM,UAAU,CAAC,CAAC,SAAS,CAAmB,EAOvE,EAAqB,GAMH,EAAM,QAAQ,KAAM,GAAW,CAGrD,GAFI,EAAO,IAAI,aAAe,EAAM,eAChC,EAAO,OAAS,EAAoB,SAAS,WAC7C,EAAO,IAAI,QAAU,EAAM,SAAU,MAAO,GAEhD,IAAM,EAAY,EAAO,IAAI,UAC7B,OAAO,GAAW,SAAW,GAAK,EAAU,KAAO,EAAM,QAC1D,CAEoB,CAAC,EAAE,MAAQ,KAM1B,EAA2B,GAOrB,CACX,IAAK,IAAM,KAAS,EAAM,OAAQ,CACjC,GAAI,EAAuB,EAAO,EAAM,mBAAmB,EAAG,CAC7D,IAAM,EAAgB,EAAkB,CACvC,QAAS,EAAM,QACf,cAAe,EAAM,cACrB,SAAU,EAAM,SAChB,SAAU,EAAM,GACjB,CAAC,EACG,GACH,EAAM,QAAQ,IAAI,CAAa,CAEjC,CAEI,EAAM,OAAS,YAEnB,EAAwB,CACvB,OAAQ,EAAM,OACd,QAAS,EAAM,QACf,cAAe,EAAM,cACrB,oBAAqB,EAAM,oBAC3B,SAAU,EAAM,SAChB,QAAS,EAAM,OAChB,CAAC,CACF,CACD,EAKM,EAQF,MAAO,EAAS,IAAS,CAC5B,IAAM,EAAmB,IAAI,IAE7B,IAAK,IAAM,KAAc,EAAQ,OAAO,YAAa,CACpD,IAAM,EAAuB,MAAM,EAClC,EACA,EAAW,GACZ,EACA,GAAI,EAAqB,MAAO,OAAO,EAEvC,EAAwB,CACvB,OAAQ,EAAW,mBACnB,QAAS,EAAqB,KAC9B,cAAe,EAAW,IAC1B,oBAAqB,EAAK,cAC1B,QAAS,CACV,CAAC,EAED,IAAK,IAAM,KAAS,EAAW,eAC9B,EAAwB,CACvB,OAAQ,EAAM,mBACd,QAAS,EAAqB,KAC9B,cAAe,EAAW,IAC1B,oBAAqB,EAAK,cAC1B,SAAU,EAAM,IAChB,QAAS,CACV,CAAC,CAEH,CAEA,IAAM,EAAyB,EAAuB,aAAa,EAC7D,EAA2B,EAAuB,gBAAgB,EAExE,IAAK,IAAM,KAAS,EACnB,MAAM,EAAQ,GAAG,OACf,WAAW,CAAK,CAAC,CACjB,MAAM,EAAwB,IAAK,EAAK,UAAU,CAAC,CACnD,MAAM,EAA0B,IAAK,EAAK,aAAa,CAAC,CACxD,QAAQ,EAGX,MAAO,CACN,MAAO,IAAA,GACP,KAAM,IAAA,EACP,CACD"}