diff --git a/packages/plugin-sdk/CHANGELOG.md b/packages/plugin-sdk/CHANGELOG.md index ab93f3fd0..fe9090843 100644 --- a/packages/plugin-sdk/CHANGELOG.md +++ b/packages/plugin-sdk/CHANGELOG.md @@ -7,6 +7,7 @@ - `execCommand` timeout errors no longer include the command, which could hold a sudo password - `termix-plugin validate` fails when a plugin ships migrations for some database engines but not all three - `termix-plugin migrations` loads the table definitions from a path with a `#` or other URL characters in it +- Text, json and encrypted columns are `longtext` on MySQL in new migrations, so they are no longer capped at 64KB. Existing migrations keep `text` - `i18next`, `react-dom`, `react-i18next` and `sonner` are optional peer dependencies, so npm stops installing them into backend-only plugins ## 1.0.4 diff --git a/packages/plugin-sdk/src/db.ts b/packages/plugin-sdk/src/db.ts index 2e31b0ec3..918ef7285 100644 --- a/packages/plugin-sdk/src/db.ts +++ b/packages/plugin-sdk/src/db.ts @@ -69,7 +69,7 @@ function builder(column: PluginColumn): Builder { export const id = () => builder({ type: "id", primaryKey: true, notNull: true }); -/** Unbounded string. Never indexable: MySQL cannot index TEXT. */ +/** Unbounded string, LONGTEXT on MySQL. Never indexable: MySQL cannot index TEXT. */ export const text = () => builder({ type: "text" }); /** Bounded string. Indexable on every engine. */ diff --git a/packages/plugin-sdk/src/ddl.ts b/packages/plugin-sdk/src/ddl.ts index a188d051c..fac788076 100644 --- a/packages/plugin-sdk/src/ddl.ts +++ b/packages/plugin-sdk/src/ddl.ts @@ -80,11 +80,13 @@ function columnType( // though it was declared unbounded. defineTable refuses to index a // text/json column, so in practice this only catches a primary key. if (keyed && dialect !== "sqlite") return `varchar(${KEY_LENGTH})`; + // MySQL TEXT stops at 64KB, so free text, json and secrets go long. + if (dialect === "mysql" && column.type !== "timestamp") return "longtext"; return "text"; } } -/** Column types that are TEXT on MySQL when nothing keys them. */ +/** Column types that are TEXT or LONGTEXT on MySQL when nothing keys them. */ const TEXT_ON_MYSQL: ReadonlySet = new Set([ "text", "json", diff --git a/src/backend/tests/plugins/table-ddl.test.ts b/src/backend/tests/plugins/table-ddl.test.ts index 2cb41d285..14f6c5aae 100644 --- a/src/backend/tests/plugins/table-ddl.test.ts +++ b/src/backend/tests/plugins/table-ddl.test.ts @@ -184,9 +184,9 @@ describe("createTableSql", () => { \`user_id\` varchar(255) NOT NULL, \`host_id\` int NOT NULL, \`title\` varchar(200) NOT NULL, - \`body\` text, - \`meta\` text, - \`secret\` text, + \`body\` longtext, + \`meta\` longtext, + \`secret\` longtext, \`pinned\` boolean DEFAULT false, \`position\` int DEFAULT 0, \`size\` bigint, @@ -286,9 +286,9 @@ describe("adoptTableSql", () => { expect(mysql[1]).toBe("RENAME TABLE `fleets` TO `p_fleets_fleets`;"); }); - it("writes a TEXT default as an expression on MySQL", () => { + it("writes a long text default as an expression on MySQL", () => { expect(adoptTableSql("mysql", "fleets", adopted)[0]).toContain( - "`name` text NOT NULL DEFAULT ('x')", + "`name` longtext NOT NULL DEFAULT ('x')", ); expect(createTableSql("sqlite", "fleets", adopted)[0]).toContain( "\"name\" text NOT NULL DEFAULT 'x'",