( data: InsertRowData, table: TableDefinition, requestId: string )
| 97 | * @throws Error if validation fails or capacity exceeded |
| 98 | */ |
| 99 | export async function insertRow( |
| 100 | data: InsertRowData, |
| 101 | table: TableDefinition, |
| 102 | requestId: string |
| 103 | ): Promise<TableRow> { |
| 104 | // Validate row size |
| 105 | const sizeValidation = validateRowSize(data.data) |
| 106 | if (!sizeValidation.valid) { |
| 107 | throw new Error(sizeValidation.errors.join(', ')) |
| 108 | } |
| 109 | |
| 110 | // Validate against schema |
| 111 | const schemaValidation = coerceRowToSchema(data.data, table.schema) |
| 112 | if (!schemaValidation.valid) { |
| 113 | throw new Error(`Schema validation failed: ${schemaValidation.errors.join(', ')}`) |
| 114 | } |
| 115 | |
| 116 | // Check unique constraints using optimized database query |
| 117 | const uniqueColumns = getUniqueColumns(table.schema) |
| 118 | if (uniqueColumns.length > 0) { |
| 119 | const uniqueValidation = await checkUniqueConstraintsDb(data.tableId, data.data, table.schema) |
| 120 | if (!uniqueValidation.valid) { |
| 121 | throw new Error(uniqueValidation.errors.join(', ')) |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | // Best-effort capacity check against the workspace's current plan limit. |
| 126 | const rowLimit = await assertRowCapacity({ |
| 127 | workspaceId: table.workspaceId, |
| 128 | currentRowCount: table.rowCount, |
| 129 | addedRows: 1, |
| 130 | }) |
| 131 | |
| 132 | const rowId = `row_${generateId().replace(/-/g, '')}` |
| 133 | const now = new Date() |
| 134 | |
| 135 | const row = await insertOrderedRow({ |
| 136 | tableId: data.tableId, |
| 137 | workspaceId: data.workspaceId, |
| 138 | data: data.data, |
| 139 | rowId, |
| 140 | position: data.position, |
| 141 | afterRowId: data.afterRowId, |
| 142 | beforeRowId: data.beforeRowId, |
| 143 | createdBy: data.userId, |
| 144 | now, |
| 145 | }) |
| 146 | |
| 147 | notifyTableRowUsage({ |
| 148 | workspaceId: table.workspaceId, |
| 149 | currentRowCount: table.rowCount, |
| 150 | addedRows: 1, |
| 151 | limit: rowLimit, |
| 152 | }) |
| 153 | |
| 154 | logger.info(`[${requestId}] Inserted row ${rowId} into table ${data.tableId}`) |
| 155 | |
| 156 | const insertedRow: TableRow = { |
no test coverage detected