@lucidcms/core
Version:
The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.
1 lines • 22.8 kB
Source Map (JSON)
{"version":3,"file":"fields-table.mjs","names":[],"sources":["../../../../../src/libs/collection/schema/tables/fields-table.ts"],"sourcesContent":["import type BrickBuilder from \"../../../../libs/collection/builders/brick-builder/index.js\";\nimport type CollectionBuilder from \"../../../../libs/collection/builders/collection-builder/index.js\";\nimport type DatabaseAdapter from \"../../../../libs/db/adapter-base.js\";\nimport type {\n\tCFConfig,\n\tFieldTypes,\n\tServiceResponse,\n} from \"../../../../types.js\";\nimport { copy } from \"../../../i18n/index.js\";\nimport registeredFields from \"../../custom-fields/registered-fields.js\";\nimport {\n\tgetFieldDatabaseConfig,\n\tisCustomFieldTableType,\n\tisStorageMode,\n\tnormalizeFieldDatabaseMode,\n} from \"../../custom-fields/storage/index.js\";\nimport { relationTableMode } from \"../../custom-fields/storage/relation-table.js\";\nimport { treeTableMode } from \"../../custom-fields/storage/tree-table.js\";\nimport buildSchemaIndex from \"../../helpers/build-schema-index.js\";\nimport buildTableName from \"../../helpers/build-table-name.js\";\nimport prefixGeneratedColName from \"../../helpers/prefix-generated-column-name.js\";\nimport type {\n\tCollectionSchemaColumn,\n\tCollectionSchemaIndex,\n\tCollectionSchemaTable,\n\tTableType,\n} from \"../types.js\";\n\nconst shouldIndexField = (\n\tcollection: CollectionBuilder,\n\tfield: CFConfig<FieldTypes>,\n) => {\n\tconst hasConfiguredIndex = \"index\" in field && field.index === true;\n\tconst isListedField = collection.listing.includes(field.key);\n\n\treturn hasConfiguredIndex || isListedField;\n};\n\nconst hasCoreColumn = (columns: CollectionSchemaColumn[], name: string) =>\n\tcolumns.some((column) => column.name === name && column.source === \"core\");\n\n/**\n * Adds indexes for common collection table joins and nested-field lookups,\n * based on the core columns each generated table actually has.\n */\nconst createCoreIndexes = (props: {\n\tdb: DatabaseAdapter;\n\ttableName: string;\n\tcolumns: CollectionSchemaColumn[];\n}): CollectionSchemaIndex[] => {\n\tconst indexes: CollectionSchemaIndex[] = [];\n\n\tif (hasCoreColumn(props.columns, \"document_version_id\")) {\n\t\tindexes.push(\n\t\t\tbuildSchemaIndex({\n\t\t\t\tdb: props.db,\n\t\t\t\ttableName: props.tableName,\n\t\t\t\tcolumns: [\"document_version_id\"],\n\t\t\t\tsource: \"core\",\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (\n\t\thasCoreColumn(props.columns, \"document_id\") &&\n\t\thasCoreColumn(props.columns, \"document_version_id\")\n\t) {\n\t\tindexes.push(\n\t\t\tbuildSchemaIndex({\n\t\t\t\tdb: props.db,\n\t\t\t\ttableName: props.tableName,\n\t\t\t\tcolumns: [\"document_id\", \"document_version_id\"],\n\t\t\t\tsource: \"core\",\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (hasCoreColumn(props.columns, \"parent_id\")) {\n\t\tindexes.push(\n\t\t\tbuildSchemaIndex({\n\t\t\t\tdb: props.db,\n\t\t\t\ttableName: props.tableName,\n\t\t\t\tcolumns: [\"parent_id\"],\n\t\t\t\tsource: \"core\",\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn indexes;\n};\n\n/**\n * Creates table schemas for fields\n * Handles document fields, brick fields, and custom-field storage tables\n */\nconst createFieldTables = (props: {\n\tcollection: CollectionBuilder;\n\tfields: CFConfig<FieldTypes>[];\n\tdb: DatabaseAdapter;\n\ttype: Exclude<TableType, \"document\" | \"versions\">;\n\tdocumentTable: string;\n\tversionTable: string;\n\tbrick?: BrickBuilder;\n\tfieldPath?: string[];\n\trootTable?: string;\n\tadditionalCoreColumns?: CollectionSchemaColumn[];\n}): Awaited<\n\tServiceResponse<{\n\t\tschema: CollectionSchemaTable;\n\t\tchildTables: CollectionSchemaTable[];\n\t}>\n> => {\n\tconst tableNameRes = buildTableName(\n\t\tprops.type,\n\t\t{\n\t\t\tcollection: props.collection.key,\n\t\t\tbrick: props.brick?.key,\n\t\t\tfieldPath: props.fieldPath,\n\t\t},\n\t\tprops.db.config.tableNameByteLimit,\n\t);\n\tif (tableNameRes.error) return tableNameRes;\n\n\tlet includeIsOpen = true;\n\tif (isCustomFieldTableType(props.type)) {\n\t\tconst databaseConfig = getFieldDatabaseConfig(props.type);\n\t\tif (databaseConfig && isStorageMode(databaseConfig, \"relation-table\")) {\n\t\t\tincludeIsOpen = false;\n\t\t}\n\t}\n\n\tconst childTables: CollectionSchemaTable[] = [];\n\tconst indexes: CollectionSchemaIndex[] = [];\n\tconst columns: CollectionSchemaColumn[] = [\n\t\t{\n\t\t\tname: \"id\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"primary\"),\n\t\t\tnullable: false,\n\t\t\tprimary: true,\n\t\t},\n\t\t{\n\t\t\tname: \"collection_key\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"text\"),\n\t\t\tnullable: false,\n\t\t\tforeignKey: {\n\t\t\t\ttable: \"lucid_collections\",\n\t\t\t\tcolumn: \"key\",\n\t\t\t\tonDelete: \"cascade\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"document_id\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"integer\"),\n\t\t\tnullable: false,\n\t\t\tforeignKey: {\n\t\t\t\ttable: props.documentTable,\n\t\t\t\tcolumn: \"id\",\n\t\t\t\tonDelete: \"cascade\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"document_version_id\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"integer\"),\n\t\t\tnullable: false,\n\t\t\tforeignKey: {\n\t\t\t\ttable: props.versionTable,\n\t\t\t\tcolumn: \"id\",\n\t\t\t\tonDelete: \"cascade\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"locale\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"text\"),\n\t\t\tnullable: false,\n\t\t\tforeignKey: {\n\t\t\t\ttable: \"lucid_locales\",\n\t\t\t\tcolumn: \"code\",\n\t\t\t\tonDelete: \"cascade\",\n\t\t\t},\n\t\t},\n\t\t// used for tree-table groups position along with brick position\n\t\t{\n\t\t\tname: \"position\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"integer\"),\n\t\t\tnullable: false,\n\t\t\tdefault: 0,\n\t\t},\n\t];\n\tif (includeIsOpen) {\n\t\tcolumns.push({\n\t\t\tname: \"is_open\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"boolean\"),\n\t\t\tnullable: false,\n\t\t\tdefault: props.db.getDefault(\"boolean\", \"false\"),\n\t\t});\n\t}\n\n\t//* bricks only\n\tif (props.type === \"brick\") {\n\t\tcolumns.push({\n\t\t\tname: \"brick_type\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"text\"),\n\t\t\tnullable: false,\n\t\t});\n\t\t// used to group a single instance of a brick accross locales instead of relying on the position value for this which isnt unique*\n\t\tcolumns.push({\n\t\t\tname: \"brick_instance_id\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"text\"),\n\t\t\tnullable: false,\n\t\t});\n\t}\n\n\t//* both brick table types\n\tif (props.type === \"brick\" || props.type === \"document-fields\") {\n\t\t// a temp reference ID for linking up with repeater temp brick_id values until insertion\n\t\tcolumns.push({\n\t\t\tname: \"brick_id_ref\",\n\t\t\tsource: \"core\",\n\t\t\ttype: props.db.getDataType(\"integer\"),\n\t\t\tnullable: false,\n\t\t});\n\t}\n\tif (props.additionalCoreColumns) columns.push(...props.additionalCoreColumns);\n\n\t//* process field columns\n\tfor (const field of props.fields) {\n\t\tconst databaseConfig = registeredFields[field.type].config.database;\n\t\tconst databaseMode = normalizeFieldDatabaseMode(databaseConfig.mode);\n\n\t\tswitch (databaseMode) {\n\t\t\tcase \"ignore\": {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"tree-table\": {\n\t\t\t\tif (!(\"tableType\" in databaseConfig)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.collections.schema.table.name.format.insufficient.parts\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst treeTableChildFields = treeTableMode.getChildFieldConfigs(field);\n\t\t\t\tif (!treeTableChildFields) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.collections.schema.table.name.format.insufficient.parts\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst fieldPath = (props.fieldPath || []).concat(field.key);\n\t\t\t\tconst treeTableRoot = props.rootTable ?? tableNameRes.data.name;\n\t\t\t\tconst treeTableCoreColumns = treeTableMode\n\t\t\t\t\t.getSchemaDefinition({\n\t\t\t\t\t\tdb: props.db,\n\t\t\t\t\t\ttable: {\n\t\t\t\t\t\t\ttype: databaseConfig.tableType,\n\t\t\t\t\t\t\tparent: tableNameRes.data.name,\n\t\t\t\t\t\t\troot: treeTableRoot,\n\t\t\t\t\t\t\tdepth: fieldPath.length,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.columns.map((column) => ({\n\t\t\t\t\t\tname: column.name,\n\t\t\t\t\t\tsource: \"core\",\n\t\t\t\t\t\ttype: column.type,\n\t\t\t\t\t\tnullable: column.nullable,\n\t\t\t\t\t\tforeignKey: column.foreignKey,\n\t\t\t\t\t\tdefault: column.default,\n\t\t\t\t\t})) satisfies CollectionSchemaColumn[];\n\n\t\t\t\tconst treeTableRes = createFieldTables({\n\t\t\t\t\tcollection: props.collection,\n\t\t\t\t\tfields: treeTableChildFields,\n\t\t\t\t\tdb: props.db,\n\t\t\t\t\ttype: databaseConfig.tableType,\n\t\t\t\t\tdocumentTable: props.documentTable,\n\t\t\t\t\tversionTable: props.versionTable,\n\t\t\t\t\tbrick: props.brick,\n\t\t\t\t\tfieldPath: fieldPath,\n\t\t\t\t\trootTable: treeTableRoot,\n\t\t\t\t\tadditionalCoreColumns: treeTableCoreColumns,\n\t\t\t\t});\n\t\t\t\tif (treeTableRes.error) return treeTableRes;\n\n\t\t\t\tchildTables.push(treeTableRes.data.schema);\n\t\t\t\tchildTables.push(...treeTableRes.data.childTables);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"column\": {\n\t\t\t\t//* field keys are unique within a collection, if we ever change them to be unique within a block (base layer and tree-table tables) we need to update this\n\t\t\t\tconst fieldInstance = (props.brick || props.collection).fields.get(\n\t\t\t\t\tfield.key,\n\t\t\t\t);\n\t\t\t\tif (!fieldInstance) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.fields.lookup.not.found.with.key.in.collection.brick\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\tkey: field.key,\n\t\t\t\t\t\t\t\t\t\ttype: props.brick ? \"brick\" : \"collection\",\n\t\t\t\t\t\t\t\t\t\ttypeKey: props.brick\n\t\t\t\t\t\t\t\t\t\t\t? props.brick.key\n\t\t\t\t\t\t\t\t\t\t\t: props.collection.key,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst fieldSchemaRes = fieldInstance.getSchemaDefinition({\n\t\t\t\t\tdb: props.db,\n\t\t\t\t\ttables: {\n\t\t\t\t\t\tdocument: props.documentTable,\n\t\t\t\t\t\tversion: props.versionTable,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (fieldSchemaRes.error) return fieldSchemaRes;\n\n\t\t\t\tconst fieldColumns = fieldSchemaRes.data.columns.map((column) => ({\n\t\t\t\t\tname: prefixGeneratedColName(column.name),\n\t\t\t\t\tsource: \"field\",\n\t\t\t\t\tcanAutoRemove: false,\n\t\t\t\t\ttype: column.type,\n\t\t\t\t\tnullable: column.nullable,\n\t\t\t\t\tforeignKey: column.foreignKey,\n\t\t\t\t\tcustomField: {\n\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t},\n\t\t\t\t\t//* holding off on default value contraint on custom field columns due to sqlite/libsql adapters not supporting the alter column operation and instead having to drop+add the column again resulting in data loss.\n\t\t\t\t\t//* CF default values are a lot more likely to be edited than the others and in a way where a user wouldnt expect data loss - so until we have a solution here, no default contraints for CF exist\n\t\t\t\t\tdefault: props.db.supports(\"alterColumn\") ? column.default : null,\n\t\t\t\t})) satisfies CollectionSchemaColumn[];\n\n\t\t\t\tcolumns.push(...fieldColumns);\n\t\t\t\tindexes.push(\n\t\t\t\t\t...fieldInstance.getIndexDefinitions({\n\t\t\t\t\t\tdb: props.db,\n\t\t\t\t\t\ttable: {\n\t\t\t\t\t\t\tname: tableNameRes.data.name,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\t...columns.filter((column) => column.name === \"document_id\"),\n\t\t\t\t\t\t\t...fieldColumns,\n\t\t\t\t\t\t],\n\t\t\t\t\t\tshouldIndex: shouldIndexField(props.collection, field),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"relation-table\": {\n\t\t\t\tif (!(\"tableType\" in databaseConfig)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.collections.schema.table.name.format.insufficient.parts\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t//* field keys are unique within a collection, if we ever change them to be unique within a block (base layer and tree-table tables) we need to update this\n\t\t\t\tconst fieldInstance = (props.brick || props.collection).fields.get(\n\t\t\t\t\tfield.key,\n\t\t\t\t);\n\t\t\t\tif (!fieldInstance) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.fields.lookup.not.found.with.key.in.collection.brick\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\tkey: field.key,\n\t\t\t\t\t\t\t\t\t\ttype: props.brick ? \"brick\" : \"collection\",\n\t\t\t\t\t\t\t\t\t\ttypeKey: props.brick\n\t\t\t\t\t\t\t\t\t\t\t? props.brick.key\n\t\t\t\t\t\t\t\t\t\t\t: props.collection.key,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst fieldSchemaRes = fieldInstance.getSchemaDefinition({\n\t\t\t\t\tdb: props.db,\n\t\t\t\t\ttables: {\n\t\t\t\t\t\tdocument: props.documentTable,\n\t\t\t\t\t\tversion: props.versionTable,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (fieldSchemaRes.error) return fieldSchemaRes;\n\n\t\t\t\tconst relationFieldPath = relationTableMode.getTableFieldPath({\n\t\t\t\t\tfieldKey: field.key,\n\t\t\t\t\tfieldPath: props.fieldPath,\n\t\t\t\t});\n\t\t\t\tconst relationCoreColumns = relationTableMode\n\t\t\t\t\t.getSchemaDefinition({\n\t\t\t\t\t\tdb: props.db,\n\t\t\t\t\t\ttable: {\n\t\t\t\t\t\t\ttype: databaseConfig.tableType,\n\t\t\t\t\t\t\tparent: tableNameRes.data.name,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.columns.map((column) => ({\n\t\t\t\t\t\tname: column.name,\n\t\t\t\t\t\tsource: \"core\",\n\t\t\t\t\t\ttype: column.type,\n\t\t\t\t\t\tnullable: column.nullable,\n\t\t\t\t\t\tforeignKey: column.foreignKey,\n\t\t\t\t\t\tdefault: column.default,\n\t\t\t\t\t})) satisfies CollectionSchemaColumn[];\n\n\t\t\t\tconst relationTableRes = createFieldTables({\n\t\t\t\t\tcollection: props.collection,\n\t\t\t\t\tfields: [],\n\t\t\t\t\tdb: props.db,\n\t\t\t\t\ttype: databaseConfig.tableType,\n\t\t\t\t\tdocumentTable: props.documentTable,\n\t\t\t\t\tversionTable: props.versionTable,\n\t\t\t\t\tbrick: props.brick,\n\t\t\t\t\tfieldPath: relationFieldPath,\n\t\t\t\t\tadditionalCoreColumns: relationCoreColumns,\n\t\t\t\t});\n\t\t\t\tif (relationTableRes.error) return relationTableRes;\n\n\t\t\t\tconst relationFieldColumns = fieldSchemaRes.data.columns.map(\n\t\t\t\t\t(column) => ({\n\t\t\t\t\t\tname: prefixGeneratedColName(column.name),\n\t\t\t\t\t\tsource: \"field\",\n\t\t\t\t\t\tcanAutoRemove: false,\n\t\t\t\t\t\ttype: column.type,\n\t\t\t\t\t\tnullable: column.nullable,\n\t\t\t\t\t\tforeignKey: column.foreignKey,\n\t\t\t\t\t\tcustomField: {\n\t\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: props.db.supports(\"alterColumn\") ? column.default : null,\n\t\t\t\t\t}),\n\t\t\t\t) satisfies CollectionSchemaColumn[];\n\n\t\t\t\trelationTableRes.data.schema.columns.push(...relationFieldColumns);\n\t\t\t\trelationTableRes.data.schema.indexes = [\n\t\t\t\t\t...(relationTableRes.data.schema.indexes ?? []),\n\t\t\t\t\t...fieldInstance.getIndexDefinitions({\n\t\t\t\t\t\tdb: props.db,\n\t\t\t\t\t\ttable: {\n\t\t\t\t\t\t\tname: relationTableRes.data.schema.name,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\t...relationTableRes.data.schema.columns.filter(\n\t\t\t\t\t\t\t\t(column) => column.name === \"document_id\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t...relationFieldColumns,\n\t\t\t\t\t\t],\n\t\t\t\t\t\tshouldIndex: shouldIndexField(props.collection, field),\n\t\t\t\t\t}),\n\t\t\t\t];\n\n\t\t\t\tchildTables.push(relationTableRes.data.schema);\n\t\t\t\tchildTables.push(...relationTableRes.data.childTables);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst coreIndexes = createCoreIndexes({\n\t\tdb: props.db,\n\t\ttableName: tableNameRes.data.name,\n\t\tcolumns,\n\t});\n\tconst tableIndexes = [...coreIndexes, ...indexes];\n\n\treturn {\n\t\tdata: {\n\t\t\tschema: {\n\t\t\t\tname: tableNameRes.data.name,\n\t\t\t\trawName: tableNameRes.data.rawName,\n\t\t\t\ttype: props.type,\n\t\t\t\tkey: {\n\t\t\t\t\tcollection: props.collection.key,\n\t\t\t\t\tbrick: props.brick?.key,\n\t\t\t\t\tfieldPath: props.fieldPath,\n\t\t\t\t},\n\t\t\t\tcolumns: columns,\n\t\t\t\tindexes: tableIndexes.length > 0 ? tableIndexes : undefined,\n\t\t\t},\n\t\t\tchildTables: childTables,\n\t\t},\n\t\terror: undefined,\n\t};\n};\n\nexport default createFieldTables;\n"],"mappings":"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"}