mutano 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,7 +30,7 @@ CREATE TABLE `user` (
30
30
  `username` varchar(255) NOT NULL,
31
31
  `password` varchar(255) NOT NULL,
32
32
  `profile_picture` varchar(255) DEFAULT NULL,
33
- `metadata` json NOT NULL COMMENT '@ts(Record<string, unknown>)', -- this will override the TypeScript type
33
+ `metadata` json NOT NULL COMMENT '@ts(Record<string, unknown>) @kysely(Record<string, string>)', -- this will override the TypeScript and Kysely type
34
34
  `role` enum('admin','user') NOT NULL,
35
35
  PRIMARY KEY (`id`)
36
36
  );
@@ -184,7 +184,7 @@ const output = await generate({
184
184
  destinations: [{
185
185
  type: 'zod'
186
186
  }],
187
- dryRun: true // Return content instead of writing to files
187
+ dryRun: true // Return content and don't write to files
188
188
  })
189
189
 
190
190
  // Output is an object where keys are filenames and values are file content
@@ -400,7 +400,7 @@ export interface UserTable {
400
400
  username: string;
401
401
  password: string;
402
402
  profile_picture: string | null;
403
- metadata: Json;
403
+ metadata: Record<string, unknown>; // Custom type from @kysely comment
404
404
  role: 'admin' | 'user';
405
405
  }
406
406
 
@@ -486,8 +486,7 @@ export type UserUpdate = Updateable<UserTable>;
486
486
  "type": "kysely",
487
487
  "schemaName": "Database",
488
488
  "header": "import { Generated, ColumnType } from 'kysely';\nimport { CustomTypes } from './types';",
489
- "folder": "kysely",
490
- "suffix": "db"
489
+ "outFile": "db.ts"
491
490
  }
492
491
  ],
493
492
  "tables": ["user", "log"],
@@ -513,6 +512,7 @@ export type UserUpdate = Updateable<UserTable>;
513
512
  | destinations[].header | Custom header to include at the beginning of generated files (e.g., custom imports) |
514
513
  | destinations[].folder | Specify the output directory for the generated files |
515
514
  | destinations[].suffix | Suffix to the name of a generated file (eg: `user.table.ts`) |
515
+ | destinations[].outFile | (Kysely only) Specify the output file for the generated content. All tables will be written to this file |
516
516
  | tables | Filter the tables to include only those specified |
517
517
  | ignore | Filter the tables to exclude those specified. If a table name begins and ends with "/", it will be processed as a regular expression |
518
518
  | camelCase | Convert all table names and their properties to camelcase. (eg: `profile_picture` becomes `profilePicture`) |
@@ -641,7 +641,30 @@ export interface User {
641
641
  }
642
642
  ```
643
643
 
644
- You can use complex TypeScript types in the `@ts` comment:
644
+ ### @kysely Comments
645
+
646
+ You can use the `@kysely` comment to override the Kysely type for a specific column. This is useful when you want to specify a more precise type for a field.
647
+
648
+ ```sql
649
+ CREATE TABLE `user` (
650
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
651
+ `metadata` json NOT NULL COMMENT '@kysely(Record<string, string>)',
652
+ PRIMARY KEY (`id`)
653
+ );
654
+ ```
655
+
656
+ This will generate:
657
+
658
+ ```typescript
659
+ export interface UserTable {
660
+ id: Generated<number>;
661
+ metadata: Record<string, string>;
662
+ }
663
+ ```
664
+
665
+ ## Complex TypeScript Types
666
+
667
+ You can use complex TypeScript types in the `@ts`(or `@kysely`) comment:
645
668
 
646
669
  ```sql
647
670
  CREATE TABLE `product` (
package/dist/main.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ export declare const extractTypeExpression: (comment: string, prefix: string) => string;
2
+ export declare const extractTSExpression: (comment: string) => string;
3
+ export declare const extractKyselyExpression: (comment: string) => string;
4
+ export declare const extractZodExpression: (comment: string) => string;
1
5
  export declare function getType(op: 'table' | 'insertable' | 'updateable' | 'selectable', desc: Desc, config: Config, destination: Destination, tableName?: string): string;
2
6
  export interface GenerateContentParams {
3
7
  table: string;
package/dist/main.js CHANGED
@@ -7,10 +7,10 @@ import {
7
7
  import camelCase from "camelcase";
8
8
  import fs from "fs-extra";
9
9
  import knex from "knex";
10
- const extractTSExpression = (comment) => {
11
- const start = comment.indexOf("@ts(");
10
+ const extractTypeExpression = (comment, prefix) => {
11
+ const start = comment.indexOf(prefix);
12
12
  if (start === -1) return null;
13
- const typeLen = 4;
13
+ const typeLen = prefix.length;
14
14
  let position = start + typeLen;
15
15
  let depth = 1;
16
16
  while (position < comment.length && depth > 0) {
@@ -28,24 +28,9 @@ const extractTSExpression = (comment) => {
28
28
  }
29
29
  return null;
30
30
  };
31
- function extractZodExpression(comment) {
32
- const zodStart = comment.indexOf("@zod(");
33
- if (zodStart === -1) return null;
34
- let openParens = 0;
35
- let position = zodStart + 5;
36
- while (position < comment.length) {
37
- if (comment[position] === "(") {
38
- openParens++;
39
- } else if (comment[position] === ")") {
40
- if (openParens === 0) {
41
- return comment.substring(zodStart + 5, position);
42
- }
43
- openParens--;
44
- }
45
- position++;
46
- }
47
- return null;
48
- }
31
+ const extractTSExpression = (comment) => extractTypeExpression(comment, "@ts(");
32
+ const extractKyselyExpression = (comment) => extractTypeExpression(comment, "@kysely(");
33
+ const extractZodExpression = (comment) => extractTypeExpression(comment, "@zod(");
49
34
  const prismaValidTypes = [
50
35
  "BigInt",
51
36
  "Boolean",
@@ -175,6 +160,13 @@ function getType(op, desc, config, destination, tableName) {
175
160
  const isRequiredString = destination.type === "zod" && destination.requiredString === true && op !== "selectable";
176
161
  const type = schemaType === "mysql" ? Type.split("(")[0].split(" ")[0] : Type;
177
162
  if (isTsDestination || isKyselyDestination) {
163
+ if (isKyselyDestination && config.magicComments) {
164
+ const kyselyOverrideType = extractKyselyExpression(Comment);
165
+ if (kyselyOverrideType) {
166
+ const shouldBeNullable2 = isNull || ["insertable", "updateable"].includes(op) && (hasDefaultValue || isGenerated) || op === "updateable" && !isNull && !hasDefaultValue;
167
+ return shouldBeNullable2 ? kyselyOverrideType.includes("| null") ? kyselyOverrideType : `${kyselyOverrideType} | null` : kyselyOverrideType;
168
+ }
169
+ }
178
170
  const tsOverrideType = config.magicComments ? extractTSExpression(Comment) : null;
179
171
  const shouldBeNullable = isNull || ["insertable", "updateable"].includes(op) && (hasDefaultValue || isGenerated) || op === "updateable" && !isNull && !hasDefaultValue;
180
172
  if (tsOverrideType) {
@@ -374,7 +366,16 @@ export interface ${camelCase(table, { pascalCase: true })} {`;
374
366
  const isEnum = schemaType !== "sqlite" && enumTypes[schemaType].includes(
375
367
  schemaType === "mysql" ? desc.Type.split("(")[0].split(" ")[0] : desc.Type
376
368
  );
377
- if (isJsonField) {
369
+ const kyselyOverrideType = config.magicComments ? extractKyselyExpression(desc.Comment) : null;
370
+ if (kyselyOverrideType) {
371
+ kyselyType = kyselyOverrideType;
372
+ if (isNullable && !kyselyType.includes("| null")) {
373
+ kyselyType = `${kyselyType} | null`;
374
+ }
375
+ if (isAutoIncrement || isDefaultGenerated || hasDefaultValue && (isEnum || kyselyType === "string" || kyselyType === "boolean" || kyselyType === "number" || kyselyType === "Decimal" || kyselyType.includes("boolean | null") || kyselyType.includes("string | null") || kyselyType.includes("number | null") || kyselyType.includes("Decimal | null"))) {
376
+ kyselyType = `Generated<${kyselyType}>`;
377
+ }
378
+ } else if (isJsonField) {
378
379
  kyselyType = "Json";
379
380
  } else {
380
381
  if (isNullable && !isJsonField) {
@@ -908,6 +909,10 @@ export interface ${schemaName} {
908
909
  export {
909
910
  defaultKyselyHeader,
910
911
  defaultZodHeader,
912
+ extractKyselyExpression,
913
+ extractTSExpression,
914
+ extractTypeExpression,
915
+ extractZodExpression,
911
916
  generate,
912
917
  generateContent,
913
918
  getType
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mutano",
3
3
  "type": "module",
4
- "version": "2.4.0",
4
+ "version": "2.6.0",
5
5
  "description": "Converts Prisma/MySQL/PostgreSQL/SQLite schemas to Zod/TS/Kysely interfaces",
6
6
  "author": "Alisson Cavalcante Agiani <thelinuxlich@gmail.com>",
7
7
  "license": "MIT",