mutano 2.4.0 → 2.5.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 +29 -6
- package/dist/main.d.ts +4 -0
- package/dist/main.js +27 -22
- package/package.json +1 -1
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
|
|
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:
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
|
11
|
-
const start = comment.indexOf(
|
|
10
|
+
const extractTypeExpression = (comment, prefix) => {
|
|
11
|
+
const start = comment.indexOf(prefix);
|
|
12
12
|
if (start === -1) return null;
|
|
13
|
-
const typeLen =
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
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
|
+
"version": "2.5.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",
|