diff --git a/packages/server/schema.sqlite b/packages/server/schema.sqlite index a7c412b2a2..e1754d5545 100644 Binary files a/packages/server/schema.sqlite and b/packages/server/schema.sqlite differ diff --git a/packages/server/src/services/database/types.ts b/packages/server/src/services/database/types.ts index e71b3cfbf3..c6ea089654 100644 --- a/packages/server/src/services/database/types.ts +++ b/packages/server/src/services/database/types.ts @@ -101,6 +101,7 @@ export interface WithUuid { interface DatabaseTableColumn { type: string; + defaultValue: string | number | null; } interface DatabaseTable { @@ -327,216 +328,216 @@ export interface TaskState extends WithDates { export const databaseSchema: DatabaseTables = { sessions: { - id: { type: 'string' }, - user_id: { type: 'string' }, - auth_code: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'string', defaultValue: null }, + user_id: { type: 'string', defaultValue: null }, + auth_code: { type: 'string', defaultValue: '' }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, files: { - id: { type: 'string' }, - owner_id: { type: 'string' }, - name: { type: 'string' }, - content: { type: 'any' }, - mime_type: { type: 'string' }, - size: { type: 'number' }, - is_directory: { type: 'number' }, - is_root: { type: 'number' }, - parent_id: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - source_file_id: { type: 'string' }, - content_type: { type: 'number' }, - content_id: { type: 'string' }, + id: { type: 'string', defaultValue: null }, + owner_id: { type: 'string', defaultValue: null }, + name: { type: 'string', defaultValue: null }, + content: { type: 'any', defaultValue: '' }, + mime_type: { type: 'string', defaultValue: 'application/octet-stream' }, + size: { type: 'number', defaultValue: 0 }, + is_directory: { type: 'number', defaultValue: 0 }, + is_root: { type: 'number', defaultValue: 0 }, + parent_id: { type: 'string', defaultValue: '' }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + source_file_id: { type: 'string', defaultValue: '' }, + content_type: { type: 'number', defaultValue: 1 }, + content_id: { type: 'string', defaultValue: '' }, }, api_clients: { - id: { type: 'string' }, - name: { type: 'string' }, - secret: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'string', defaultValue: null }, + name: { type: 'string', defaultValue: null }, + secret: { type: 'string', defaultValue: null }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, notifications: { - id: { type: 'string' }, - owner_id: { type: 'string' }, - level: { type: 'number' }, - key: { type: 'string' }, - message: { type: 'string' }, - read: { type: 'number' }, - canBeDismissed: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'string', defaultValue: null }, + owner_id: { type: 'string', defaultValue: null }, + level: { type: 'number', defaultValue: null }, + key: { type: 'string', defaultValue: null }, + message: { type: 'string', defaultValue: null }, + read: { type: 'number', defaultValue: 0 }, + canBeDismissed: { type: 'number', defaultValue: 1 }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, share_users: { - id: { type: 'string' }, - share_id: { type: 'string' }, - user_id: { type: 'string' }, - status: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - master_key: { type: 'string' }, + id: { type: 'string', defaultValue: null }, + share_id: { type: 'string', defaultValue: null }, + user_id: { type: 'string', defaultValue: null }, + status: { type: 'number', defaultValue: 0 }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + master_key: { type: 'string', defaultValue: '' }, }, user_items: { - id: { type: 'number' }, - user_id: { type: 'string' }, - item_id: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + user_id: { type: 'string', defaultValue: null }, + item_id: { type: 'string', defaultValue: null }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, item_resources: { - id: { type: 'number' }, - item_id: { type: 'string' }, - resource_id: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + item_id: { type: 'string', defaultValue: null }, + resource_id: { type: 'string', defaultValue: null }, }, key_values: { - id: { type: 'number' }, - key: { type: 'string' }, - type: { type: 'number' }, - value: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + key: { type: 'string', defaultValue: null }, + type: { type: 'number', defaultValue: null }, + value: { type: 'string', defaultValue: null }, }, shares: { - id: { type: 'string' }, - owner_id: { type: 'string' }, - item_id: { type: 'string' }, - type: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - folder_id: { type: 'string' }, - note_id: { type: 'string' }, - master_key_id: { type: 'string' }, - recursive: { type: 'number' }, + id: { type: 'string', defaultValue: null }, + owner_id: { type: 'string', defaultValue: null }, + item_id: { type: 'string', defaultValue: null }, + type: { type: 'number', defaultValue: null }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + folder_id: { type: 'string', defaultValue: '' }, + note_id: { type: 'string', defaultValue: '' }, + master_key_id: { type: 'string', defaultValue: '' }, + recursive: { type: 'number', defaultValue: 0 }, }, changes: { - counter: { type: 'number' }, - id: { type: 'string' }, - item_type: { type: 'number' }, - item_id: { type: 'string' }, - item_name: { type: 'string' }, - type: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - previous_item: { type: 'string' }, - user_id: { type: 'string' }, + counter: { type: 'number', defaultValue: null }, + id: { type: 'string', defaultValue: null }, + item_type: { type: 'number', defaultValue: null }, + item_id: { type: 'string', defaultValue: null }, + item_name: { type: 'string', defaultValue: '' }, + type: { type: 'number', defaultValue: null }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + previous_item: { type: 'string', defaultValue: '' }, + user_id: { type: 'string', defaultValue: '' }, }, tokens: { - id: { type: 'number' }, - value: { type: 'string' }, - user_id: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + value: { type: 'string', defaultValue: null }, + user_id: { type: 'string', defaultValue: '' }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, subscriptions: { - id: { type: 'number' }, - user_id: { type: 'string' }, - stripe_user_id: { type: 'string' }, - stripe_subscription_id: { type: 'string' }, - last_payment_time: { type: 'string' }, - last_payment_failed_time: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - is_deleted: { type: 'number' }, + id: { type: 'number', defaultValue: null }, + user_id: { type: 'string', defaultValue: null }, + stripe_user_id: { type: 'string', defaultValue: null }, + stripe_subscription_id: { type: 'string', defaultValue: null }, + last_payment_time: { type: 'string', defaultValue: null }, + last_payment_failed_time: { type: 'string', defaultValue: 0 }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + is_deleted: { type: 'number', defaultValue: 0 }, }, users: { - id: { type: 'string' }, - email: { type: 'string' }, - password: { type: 'string' }, - full_name: { type: 'string' }, - is_admin: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - email_confirmed: { type: 'number' }, - must_set_password: { type: 'number' }, - account_type: { type: 'number' }, - can_upload: { type: 'number' }, - max_item_size: { type: 'number' }, - can_share_folder: { type: 'number' }, - can_share_note: { type: 'number' }, - max_total_item_size: { type: 'string' }, - total_item_size: { type: 'string' }, - enabled: { type: 'number' }, - disabled_time: { type: 'string' }, - can_receive_folder: { type: 'number' }, + id: { type: 'string', defaultValue: null }, + email: { type: 'string', defaultValue: null }, + password: { type: 'string', defaultValue: null }, + full_name: { type: 'string', defaultValue: '' }, + is_admin: { type: 'number', defaultValue: 0 }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + email_confirmed: { type: 'number', defaultValue: 0 }, + must_set_password: { type: 'number', defaultValue: 0 }, + account_type: { type: 'number', defaultValue: 0 }, + can_upload: { type: 'number', defaultValue: 1 }, + max_item_size: { type: 'number', defaultValue: null }, + can_share_folder: { type: 'number', defaultValue: null }, + can_share_note: { type: 'number', defaultValue: null }, + max_total_item_size: { type: 'string', defaultValue: null }, + total_item_size: { type: 'string', defaultValue: 0 }, + enabled: { type: 'number', defaultValue: 1 }, + disabled_time: { type: 'string', defaultValue: 0 }, + can_receive_folder: { type: 'number', defaultValue: null }, }, user_flags: { - id: { type: 'number' }, - user_id: { type: 'string' }, - type: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + user_id: { type: 'string', defaultValue: null }, + type: { type: 'number', defaultValue: 0 }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, events: { - id: { type: 'string' }, - counter: { type: 'number' }, - type: { type: 'number' }, - name: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'string', defaultValue: null }, + counter: { type: 'number', defaultValue: null }, + type: { type: 'number', defaultValue: null }, + name: { type: 'string', defaultValue: '' }, + created_time: { type: 'string', defaultValue: null }, }, storages: { - id: { type: 'number' }, - connection_string: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + connection_string: { type: 'string', defaultValue: null }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, items: { - id: { type: 'string' }, - name: { type: 'string' }, - mime_type: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - content: { type: 'any' }, - content_size: { type: 'number' }, - jop_id: { type: 'string' }, - jop_parent_id: { type: 'string' }, - jop_share_id: { type: 'string' }, - jop_type: { type: 'number' }, - jop_encryption_applied: { type: 'number' }, - jop_updated_time: { type: 'string' }, - owner_id: { type: 'string' }, - content_storage_id: { type: 'number' }, + id: { type: 'string', defaultValue: null }, + name: { type: 'string', defaultValue: null }, + mime_type: { type: 'string', defaultValue: 'application/octet-stream' }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + content: { type: 'any', defaultValue: '' }, + content_size: { type: 'number', defaultValue: 0 }, + jop_id: { type: 'string', defaultValue: '' }, + jop_parent_id: { type: 'string', defaultValue: '' }, + jop_share_id: { type: 'string', defaultValue: '' }, + jop_type: { type: 'number', defaultValue: 0 }, + jop_encryption_applied: { type: 'number', defaultValue: 0 }, + jop_updated_time: { type: 'string', defaultValue: 0 }, + owner_id: { type: 'string', defaultValue: null }, + content_storage_id: { type: 'number', defaultValue: null }, }, user_deletions: { - id: { type: 'number' }, - user_id: { type: 'string' }, - process_data: { type: 'number' }, - process_account: { type: 'number' }, - scheduled_time: { type: 'string' }, - start_time: { type: 'string' }, - end_time: { type: 'string' }, - success: { type: 'number' }, - error: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + user_id: { type: 'string', defaultValue: null }, + process_data: { type: 'number', defaultValue: 0 }, + process_account: { type: 'number', defaultValue: 0 }, + scheduled_time: { type: 'string', defaultValue: null }, + start_time: { type: 'string', defaultValue: 0 }, + end_time: { type: 'string', defaultValue: 0 }, + success: { type: 'number', defaultValue: 0 }, + error: { type: 'string', defaultValue: '' }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, emails: { - id: { type: 'number' }, - recipient_name: { type: 'string' }, - recipient_email: { type: 'string' }, - recipient_id: { type: 'string' }, - sender_id: { type: 'number' }, - subject: { type: 'string' }, - body: { type: 'string' }, - sent_time: { type: 'string' }, - sent_success: { type: 'number' }, - error: { type: 'string' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, - key: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + recipient_name: { type: 'string', defaultValue: '' }, + recipient_email: { type: 'string', defaultValue: '' }, + recipient_id: { type: 'string', defaultValue: '' }, + sender_id: { type: 'number', defaultValue: null }, + subject: { type: 'string', defaultValue: null }, + body: { type: 'string', defaultValue: null }, + sent_time: { type: 'string', defaultValue: 0 }, + sent_success: { type: 'number', defaultValue: 0 }, + error: { type: 'string', defaultValue: '' }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, + key: { type: 'string', defaultValue: '' }, }, backup_items: { - id: { type: 'number' }, - type: { type: 'number' }, - key: { type: 'string' }, - user_id: { type: 'string' }, - content: { type: 'any' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + type: { type: 'number', defaultValue: null }, + key: { type: 'string', defaultValue: null }, + user_id: { type: 'string', defaultValue: '' }, + content: { type: 'any', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, task_states: { - id: { type: 'number' }, - task_id: { type: 'number' }, - running: { type: 'number' }, - enabled: { type: 'number' }, - updated_time: { type: 'string' }, - created_time: { type: 'string' }, + id: { type: 'number', defaultValue: null }, + task_id: { type: 'number', defaultValue: null }, + running: { type: 'number', defaultValue: 0 }, + enabled: { type: 'number', defaultValue: 1 }, + updated_time: { type: 'string', defaultValue: null }, + created_time: { type: 'string', defaultValue: null }, }, }; // AUTO-GENERATED-TYPES diff --git a/packages/server/src/tools/generateTypes.ts b/packages/server/src/tools/generateTypes.ts index f7fbd51643..86d55ed0a8 100644 --- a/packages/server/src/tools/generateTypes.ts +++ b/packages/server/src/tools/generateTypes.ts @@ -1,6 +1,6 @@ /* eslint-disable no-console */ -import sqlts, { Config } from '@rmp135/sql-ts'; +import sqlts, { Config, Table } from '@rmp135/sql-ts'; require('source-map-support').install(); @@ -90,7 +90,7 @@ function insertContentIntoFile(filePath: string, markerOpen: string, markerClose // password?: string // is_admin?: number // } -function createTypeString(table: any) { +function createTypeString(table: Table) { const colStrings = []; for (const col of table.columns) { const name = col.propertyName as string; @@ -117,11 +117,63 @@ function createTypeString(table: any) { const header = ['export interface']; header.push(table.interfaceName); + if (table.extends) header.push(`extends ${table.extends}`); return `${header.join(' ')} {\n${colStrings.join('\n')}\n}`; } +// SQLite default values are always strings regardless of the column types. So +// here we convert it to the correct type. +const formatDefaultValue = (value: string | null, type: string): null | number | string => { + if (value === null) return value; + + // From https://www.sqlite.org/datatype3.html + // + // Note that DECIMAL(10,5) is also a valid type - this is checked in the + // conditional below + const numericTypes = [ + 'INT', + 'INTEGER', + 'TINYINT', + 'SMALLINT', + 'MEDIUMINT', + 'BIGINT', + 'UNSIGNED BIG INT', + 'INT2', + 'INT8', + 'REAL', + 'DOUBLE', + 'DOUBLE PRECISION', + 'FLOAT', + 'NUMERIC', + 'BOOLEAN', + 'DATE', + 'DATETIME', + ]; + + // SQLite default values are always surrounded by double quotes or single + // quotes - eg `"3"` (for numeric value 3) or `"example"` (for string + // `example`). So here we remove the quotes, but to safe we check that they + // are actually present. + if (value.length && value[0] === '"' && value[value.length - 1] === '"') { + value = value.substring(1, value.length - 1); + } else if (value.length && value[0] === '\'' && value[value.length - 1] === '\'') { + value = value.substring(1, value.length - 1); + } + + type = type.toUpperCase(); + + if (numericTypes.includes(type) || type.startsWith('DECIMAL')) { + if (value.toLowerCase() === 'null') return null; + const output = Number(value); + if (isNaN(output)) throw new Error(`Could not convert default value: ${value}`); + return output; + } else { + return value; + } +}; + // To output: // // export const databaseSchema:DatabaseTables = { @@ -134,12 +186,14 @@ function createTypeString(table: any) { // created_time: { type: "number" }, // }, // } -function createRuntimeObject(table: any) { +function createRuntimeObject(table: Table) { const colStrings = []; for (const col of table.columns) { const name = col.propertyName; const type = col.propertyType; - colStrings.push(`\t\t${name}: { type: '${type}' },`); + let defaultValue = formatDefaultValue(col.defaultValue, col.type); + if (typeof defaultValue === 'string') defaultValue = `'${defaultValue}'`; + colStrings.push(`\t\t${name}: { type: '${type}', defaultValue: ${defaultValue} },`); } return `\t${table.name}: {\n${colStrings.join('\n')}\n\t},`;