@inflector/optima 1.0.20 → 1.1.1
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/dist/chunk-JTCM2KCM.js +160 -0
- package/dist/index.d.ts +6 -71
- package/dist/index.js +66 -155
- package/dist/types.d.ts +87 -0
- package/dist/types.js +44 -0
- package/package.json +7 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
var refHelpers = {
|
|
4
|
+
one: (ref) => ref,
|
|
5
|
+
many: (ref) => ref
|
|
6
|
+
};
|
|
7
|
+
var ColumnImpl = class _ColumnImpl {
|
|
8
|
+
constructor(config = {}) {
|
|
9
|
+
this.config = {};
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
next(key, value = true) {
|
|
13
|
+
return new _ColumnImpl({ ...this.config, [key]: value });
|
|
14
|
+
}
|
|
15
|
+
SQlType(val) {
|
|
16
|
+
return this.next("SQlType", val);
|
|
17
|
+
}
|
|
18
|
+
primaryKey() {
|
|
19
|
+
return this.next("primaryKey");
|
|
20
|
+
}
|
|
21
|
+
notnull() {
|
|
22
|
+
return this.next("notnull");
|
|
23
|
+
}
|
|
24
|
+
unique() {
|
|
25
|
+
return this.next("unique");
|
|
26
|
+
}
|
|
27
|
+
default(val) {
|
|
28
|
+
return this.next("default", val);
|
|
29
|
+
}
|
|
30
|
+
defaultNow() {
|
|
31
|
+
return this.next("defaultNow");
|
|
32
|
+
}
|
|
33
|
+
reference(c) {
|
|
34
|
+
const result = c(refHelpers);
|
|
35
|
+
const isManyRef = result?.[/* @__PURE__ */ Symbol.for("__refType")] === "many" || typeof result === "object" && result !== null && "__refType" in result;
|
|
36
|
+
const actualRef = result;
|
|
37
|
+
let refName = "";
|
|
38
|
+
if (actualRef?.__parent && actualRef?.__fieldName) {
|
|
39
|
+
refName = `${actualRef.__parent}.${actualRef.__fieldName}`;
|
|
40
|
+
} else {
|
|
41
|
+
const code = c.toString();
|
|
42
|
+
const match = code.match(/(?:one|many)\s*\(\s*([^)]+)\s*\)/);
|
|
43
|
+
if (match && match[1]) {
|
|
44
|
+
const refPart = match[1].trim();
|
|
45
|
+
if (refPart.includes(".")) {
|
|
46
|
+
refName = refPart;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const codeStr = c.toString();
|
|
51
|
+
const isMany = codeStr.includes("many(");
|
|
52
|
+
const nextConfig = { ...this.config, reference: { ref: refName, isMany } };
|
|
53
|
+
return new _ColumnImpl(nextConfig);
|
|
54
|
+
}
|
|
55
|
+
validate(fn) {
|
|
56
|
+
return this.next("validate", fn);
|
|
57
|
+
}
|
|
58
|
+
transform(fn) {
|
|
59
|
+
return this.next("transform", fn);
|
|
60
|
+
}
|
|
61
|
+
deprecated() {
|
|
62
|
+
return this.next("deprecated");
|
|
63
|
+
}
|
|
64
|
+
STRUCTType(val) {
|
|
65
|
+
return this.next("STRUCTType", val);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var Column = (conf) => {
|
|
69
|
+
return new ColumnImpl(conf);
|
|
70
|
+
};
|
|
71
|
+
var Int = () => Column().SQlType("INTEGER");
|
|
72
|
+
var BigInt = () => Column().SQlType("BIGINT");
|
|
73
|
+
var Float = () => Column().SQlType("FLOAT");
|
|
74
|
+
var Boolean = () => Column().SQlType(
|
|
75
|
+
"BOOLEAN"
|
|
76
|
+
);
|
|
77
|
+
var Text = () => Column().SQlType("VARCHAR");
|
|
78
|
+
var Uuid = () => Column().SQlType("VARCHAR");
|
|
79
|
+
var DateType = () => Column().SQlType("DATE");
|
|
80
|
+
var Timestamp = () => Column().SQlType("TIMESTAMP");
|
|
81
|
+
var Enum = (vals) => {
|
|
82
|
+
const isString = typeof vals[0] === "string";
|
|
83
|
+
return Column().validate((v) => vals.includes(v)).SQlType(isString ? "VARCHAR" : "INTEGER");
|
|
84
|
+
};
|
|
85
|
+
var zodToDuckDBType = (zodType) => {
|
|
86
|
+
const def = zodType?._def;
|
|
87
|
+
if (def && (def.typeName === "ZodOptional" || def.typeName === "ZodNullable")) {
|
|
88
|
+
return zodToDuckDBType(def.innerType);
|
|
89
|
+
}
|
|
90
|
+
if (def && def.typeName === "ZodDefault") {
|
|
91
|
+
return zodToDuckDBType(def.innerType);
|
|
92
|
+
}
|
|
93
|
+
if (zodType instanceof z.ZodString) return "VARCHAR";
|
|
94
|
+
if (zodType instanceof z.ZodNumber) return "INTEGER";
|
|
95
|
+
if (zodType instanceof z.ZodBoolean) return "BOOLEAN";
|
|
96
|
+
if (zodType instanceof z.ZodDate) return "TIMESTAMP";
|
|
97
|
+
if (zodType instanceof z.ZodBigInt) return "BIGINT";
|
|
98
|
+
if ("element" in (def ?? {})) {
|
|
99
|
+
const innerType = zodToDuckDBType(def.element);
|
|
100
|
+
return `${innerType}[]`;
|
|
101
|
+
}
|
|
102
|
+
if ("shape" in (def ?? {})) {
|
|
103
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
104
|
+
const structParts = Object.entries(shape).map(([key, value]) => {
|
|
105
|
+
const fieldType = zodToDuckDBType(value);
|
|
106
|
+
return `${key} ${fieldType}`;
|
|
107
|
+
});
|
|
108
|
+
return `STRUCT(${structParts.join(", ")})`;
|
|
109
|
+
}
|
|
110
|
+
return "VARCHAR";
|
|
111
|
+
};
|
|
112
|
+
var Json = (obj) => {
|
|
113
|
+
const zodObj = z.object(obj);
|
|
114
|
+
const duckDBStructString = zodToDuckDBType(zodObj);
|
|
115
|
+
const col = Column().SQlType("STRUCT");
|
|
116
|
+
return col.STRUCTType(duckDBStructString);
|
|
117
|
+
};
|
|
118
|
+
var Array = (schema) => {
|
|
119
|
+
const innerType = zodToDuckDBType(schema);
|
|
120
|
+
const col = Column().SQlType("LIST");
|
|
121
|
+
return col.STRUCTType(`${innerType}[]`);
|
|
122
|
+
};
|
|
123
|
+
var Email = () => Column().SQlType("VARCHAR").validate((v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v));
|
|
124
|
+
var Slug = () => Column().SQlType("VARCHAR").validate((v) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(v));
|
|
125
|
+
var Color = () => Column().SQlType("VARCHAR").validate((v) => /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(v));
|
|
126
|
+
var Bytes = () => Column().SQlType("BLOB");
|
|
127
|
+
var Password = () => Column().SQlType(
|
|
128
|
+
"VARCHAR"
|
|
129
|
+
);
|
|
130
|
+
var GeoPoint = () => Column().SQlType("STRUCT");
|
|
131
|
+
var GeoArea = () => Column().SQlType("STRUCT");
|
|
132
|
+
var Table = (name, fields) => {
|
|
133
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
134
|
+
Object.assign(value, { __parent: name, __fieldName: key });
|
|
135
|
+
}
|
|
136
|
+
return { ...fields, __tableName: name };
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
refHelpers,
|
|
141
|
+
Int,
|
|
142
|
+
BigInt,
|
|
143
|
+
Float,
|
|
144
|
+
Boolean,
|
|
145
|
+
Text,
|
|
146
|
+
Uuid,
|
|
147
|
+
DateType,
|
|
148
|
+
Timestamp,
|
|
149
|
+
Enum,
|
|
150
|
+
Json,
|
|
151
|
+
Array,
|
|
152
|
+
Email,
|
|
153
|
+
Slug,
|
|
154
|
+
Color,
|
|
155
|
+
Bytes,
|
|
156
|
+
Password,
|
|
157
|
+
GeoPoint,
|
|
158
|
+
GeoArea,
|
|
159
|
+
Table
|
|
160
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,82 +1,17 @@
|
|
|
1
1
|
import { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';
|
|
2
|
-
import
|
|
2
|
+
import { ColumnBuilder, Infer, ColumnConfig, InferAdd, Prettify as Prettify$1 } from './types.js';
|
|
3
|
+
export { Array, BigInt, Boolean, Bytes, Color, DateType, DefaultConfig, Email, Enum, Float, GeoArea, GeoPoint, InferColumnType, Int, Json, Many, One, ParentBrand, Password, Restrict, SetFlag, Slug, Table, Text, Timestamp, Uuid, refHelpers } from './types.js';
|
|
3
4
|
export { any, array, bigint, date, number, object, string } from 'zod';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
type Prettify$1<T> = {
|
|
9
|
-
[K in keyof T]: T[K];
|
|
10
|
-
} & {};
|
|
11
|
-
type Restrict<K extends keyof ColumnConfig> = {
|
|
12
|
-
[P in keyof ColumnConfig]: P extends K ? true : false;
|
|
13
|
-
};
|
|
14
|
-
type One<T> = T & {
|
|
15
|
-
readonly __refKind: "one";
|
|
16
|
-
};
|
|
17
|
-
type Many<T> = T & {
|
|
18
|
-
readonly __refKind: "many";
|
|
19
|
-
};
|
|
20
|
-
declare const refHelpers: {
|
|
21
|
-
one: <T>(ref: T) => One<T>;
|
|
22
|
-
many: <T>(ref: T) => Many<T>;
|
|
23
|
-
};
|
|
24
|
-
type InferColumnType<T> = T extends ColumnBuilder<infer U, any, any> ? U : never;
|
|
25
|
-
type Infer<T extends Record<string, any>> = Prettify$1<{
|
|
26
|
-
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? K : never : never]: T[K] extends ColumnBuilder<infer U, any, any> ? U : never;
|
|
27
|
-
} & // 2. Handle Optional Keys (notnull: false)
|
|
28
|
-
{
|
|
29
|
-
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? never : K : never]: T[K] extends ColumnBuilder<infer U, any, any> ? U | null : never;
|
|
30
|
-
}>;
|
|
31
|
-
type InferAdd<T extends Record<string, any>> = Prettify$1<{
|
|
32
|
-
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? K : never : never]: T[K] extends ColumnBuilder<infer U, any, any> ? U : never;
|
|
33
|
-
} & // 2. Handle Optional Keys (notnull: false)
|
|
34
|
-
{
|
|
35
|
-
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? never : K : never]?: T[K] extends ColumnBuilder<infer U, any, any> ? U | null : never;
|
|
36
|
-
}>;
|
|
37
|
-
type ColumnConfig = {
|
|
38
|
-
SQlType: boolean;
|
|
6
|
+
declare const GetFieldConfig: (f: ColumnBuilder<any, any>) => {
|
|
7
|
+
SQlType: string;
|
|
39
8
|
primaryKey: boolean;
|
|
40
9
|
notnull: boolean;
|
|
41
10
|
unique: boolean;
|
|
42
11
|
default: boolean;
|
|
43
12
|
defaultNow: boolean;
|
|
44
13
|
reference: boolean;
|
|
45
|
-
|
|
46
|
-
transform: boolean;
|
|
47
|
-
deprecated: boolean;
|
|
48
|
-
STRUCTType: boolean;
|
|
49
|
-
};
|
|
50
|
-
type ColumnBuilder<Type, Config extends ColumnConfig, RefSchema = never> = {
|
|
51
|
-
[K in keyof ColumnConfig as K extends "STRUCTType" ? never : Config[K] extends true ? never : K]: K extends "SQlType" ? (val: string) => ColumnBuilder<Type, SetFlag$1<Config, "SQlType">, RefSchema> : K extends "primaryKey" ? () => ColumnBuilder<Type, SetFlag$1<Config, "primaryKey">, RefSchema> : K extends "notnull" ? () => ColumnBuilder<Type, SetFlag$1<Config, "notnull">, RefSchema> : K extends "unique" ? () => ColumnBuilder<Type, SetFlag$1<Config, "unique">, RefSchema> : K extends "default" ? (val: Type | (() => Type)) => ColumnBuilder<Type, SetFlag$1<Config, "default">, RefSchema> : K extends "defaultNow" ? () => ColumnBuilder<Type, SetFlag$1<Config, "defaultNow">, RefSchema> : K extends "reference" ? <TRef>(ref: (helpers: typeof refHelpers) => TRef) => ColumnBuilder<Type, SetFlag$1<Config, "reference">, TRef> : K extends "validate" ? (fn: (val: Type) => boolean) => ColumnBuilder<Type, SetFlag$1<Config, "validate">, RefSchema> : K extends "transform" ? (fn: (val: Type) => Type) => ColumnBuilder<Type, SetFlag$1<Config, "transform">, RefSchema> : K extends "deprecated" ? () => ColumnBuilder<Type, SetFlag$1<Config, "deprecated">, RefSchema> : never;
|
|
52
|
-
};
|
|
53
|
-
declare const Int: () => ColumnBuilder<number, SetFlag$1<Restrict<"defaultNow">, "SQlType">, never>;
|
|
54
|
-
declare const BigInt: () => ColumnBuilder<bigint, SetFlag$1<Restrict<"defaultNow">, "SQlType">, never>;
|
|
55
|
-
declare const Float: () => ColumnBuilder<number, SetFlag$1<Restrict<"defaultNow">, "SQlType">, never>;
|
|
56
|
-
declare const Boolean: () => ColumnBuilder<boolean, SetFlag$1<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
57
|
-
declare const Text: () => ColumnBuilder<string, SetFlag$1<Restrict<"defaultNow">, "SQlType">, never>;
|
|
58
|
-
declare const Uuid: () => ColumnBuilder<string, SetFlag$1<Restrict<"defaultNow">, "SQlType">, never>;
|
|
59
|
-
declare const DateType: () => ColumnBuilder<Date, SetFlag$1<Restrict<"default">, "SQlType">, never>;
|
|
60
|
-
declare const Timestamp: () => ColumnBuilder<Date, SetFlag$1<Restrict<"default">, "SQlType">, never>;
|
|
61
|
-
declare const Enum: <T extends string | number>(vals: readonly T[]) => ColumnBuilder<T, SetFlag$1<SetFlag$1<Restrict<"defaultNow">, "validate">, "SQlType">, never>;
|
|
62
|
-
declare const Json: <T extends z.ZodRawShape = Record<string, any>>(obj: T) => ColumnBuilder<[keyof T] extends [never] ? Record<string, any> : z.core.$InferObjectOutput<T, {}>, SetFlag$1<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
63
|
-
declare const Array$1: <T extends z.ZodTypeAny>(schema: T) => ColumnBuilder<z.core.output<T>[], SetFlag$1<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
64
|
-
declare const Email: () => ColumnBuilder<string, SetFlag$1<SetFlag$1<Restrict<"defaultNow">, "SQlType">, "validate">, never>;
|
|
65
|
-
declare const Slug: () => ColumnBuilder<string, SetFlag$1<SetFlag$1<Restrict<"defaultNow">, "SQlType">, "validate">, never>;
|
|
66
|
-
declare const Color: () => ColumnBuilder<string, SetFlag$1<SetFlag$1<Restrict<"defaultNow">, "SQlType">, "validate">, never>;
|
|
67
|
-
declare const Bytes: () => ColumnBuilder<Uint8Array<ArrayBufferLike>, SetFlag$1<Restrict<"primaryKey" | "defaultNow">, "SQlType">, never>;
|
|
68
|
-
declare const Password: () => ColumnBuilder<string, SetFlag$1<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
69
|
-
declare const GeoPoint: () => ColumnBuilder<{
|
|
70
|
-
latitude: number;
|
|
71
|
-
longitude: number;
|
|
72
|
-
}, SetFlag$1<Restrict<"primaryKey" | "defaultNow">, "SQlType">, never>;
|
|
73
|
-
declare const GeoArea: () => ColumnBuilder<{
|
|
74
|
-
latitude: number;
|
|
75
|
-
longitude: number;
|
|
76
|
-
radius: number;
|
|
77
|
-
}, SetFlag$1<Restrict<"primaryKey" | "defaultNow">, "SQlType">, never>;
|
|
78
|
-
declare const Table: <Name extends string, T extends Record<string, ColumnBuilder<any, any>>>(name: Name, fields: T) => T & {
|
|
79
|
-
__tableName: Name;
|
|
14
|
+
STRUCTType?: string;
|
|
80
15
|
};
|
|
81
16
|
declare class SQLBuilder {
|
|
82
17
|
static BuildField(name: string, f: ColumnBuilder<any, any>): {
|
|
@@ -322,4 +257,4 @@ declare class OptimaDB<T extends Record<string, OptimaTable>> {
|
|
|
322
257
|
transaction<R>(fn: () => Promise<R>): Promise<R>;
|
|
323
258
|
}
|
|
324
259
|
|
|
325
|
-
export {
|
|
260
|
+
export { ColumnBuilder, ColumnConfig, type ConditionBuilder, type Extension, type FieldQuery, GetFieldConfig, Infer, InferAdd, OPS, type OpKey, OptimaDB, OptimaTable, Prettify$1 as Prettify, SQLBuilder, type TableSchema, type Where, between, cond, contains, endsWith, eq, gt, gte, inOp, is, isNot, like, lt, lte, ne, notBetween, notIn, notLike, notRegexp, regexp, startsWith };
|
package/dist/index.js
CHANGED
|
@@ -1,143 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Array as Array2,
|
|
3
|
+
BigInt,
|
|
4
|
+
Boolean,
|
|
5
|
+
Bytes,
|
|
6
|
+
Color,
|
|
7
|
+
DateType,
|
|
8
|
+
Email,
|
|
9
|
+
Enum,
|
|
10
|
+
Float,
|
|
11
|
+
GeoArea,
|
|
12
|
+
GeoPoint,
|
|
13
|
+
Int,
|
|
14
|
+
Json,
|
|
15
|
+
Password,
|
|
16
|
+
Slug,
|
|
17
|
+
Table,
|
|
18
|
+
Text,
|
|
19
|
+
Timestamp,
|
|
20
|
+
Uuid,
|
|
21
|
+
refHelpers
|
|
22
|
+
} from "./chunk-JTCM2KCM.js";
|
|
23
|
+
|
|
1
24
|
// src/database.ts
|
|
2
25
|
import { DuckDBInstance } from "@duckdb/node-api";
|
|
3
26
|
|
|
4
27
|
// src/schema.ts
|
|
5
|
-
import * as z from "zod";
|
|
6
|
-
var refHelpers = {
|
|
7
|
-
one: (ref) => ref,
|
|
8
|
-
many: (ref) => ref
|
|
9
|
-
};
|
|
10
|
-
var ColumnImpl = class _ColumnImpl {
|
|
11
|
-
constructor(config = {}) {
|
|
12
|
-
this.config = {};
|
|
13
|
-
this.config = config;
|
|
14
|
-
}
|
|
15
|
-
next(key, value = true) {
|
|
16
|
-
return new _ColumnImpl({ ...this.config, [key]: value });
|
|
17
|
-
}
|
|
18
|
-
SQlType(val) {
|
|
19
|
-
return this.next("SQlType", val);
|
|
20
|
-
}
|
|
21
|
-
primaryKey() {
|
|
22
|
-
return this.next("primaryKey");
|
|
23
|
-
}
|
|
24
|
-
notnull() {
|
|
25
|
-
return this.next("notnull");
|
|
26
|
-
}
|
|
27
|
-
unique() {
|
|
28
|
-
return this.next("unique");
|
|
29
|
-
}
|
|
30
|
-
default(val) {
|
|
31
|
-
return this.next("default", val);
|
|
32
|
-
}
|
|
33
|
-
defaultNow() {
|
|
34
|
-
return this.next("defaultNow");
|
|
35
|
-
}
|
|
36
|
-
reference(c) {
|
|
37
|
-
const result = c(refHelpers);
|
|
38
|
-
const isManyRef = result?.[/* @__PURE__ */ Symbol.for("__refType")] === "many" || typeof result === "object" && result !== null && "__refType" in result;
|
|
39
|
-
const actualRef = result;
|
|
40
|
-
let refName = "";
|
|
41
|
-
if (actualRef?.__parent && actualRef?.__fieldName) {
|
|
42
|
-
refName = `${actualRef.__parent}.${actualRef.__fieldName}`;
|
|
43
|
-
} else {
|
|
44
|
-
const code = c.toString();
|
|
45
|
-
const match = code.match(/(?:one|many)\s*\(\s*([^)]+)\s*\)/);
|
|
46
|
-
if (match && match[1]) {
|
|
47
|
-
const refPart = match[1].trim();
|
|
48
|
-
if (refPart.includes(".")) {
|
|
49
|
-
refName = refPart;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const codeStr = c.toString();
|
|
54
|
-
const isMany = codeStr.includes("many(");
|
|
55
|
-
const nextConfig = { ...this.config, reference: { ref: refName, isMany } };
|
|
56
|
-
return new _ColumnImpl(nextConfig);
|
|
57
|
-
}
|
|
58
|
-
validate(fn) {
|
|
59
|
-
return this.next("validate", fn);
|
|
60
|
-
}
|
|
61
|
-
transform(fn) {
|
|
62
|
-
return this.next("transform", fn);
|
|
63
|
-
}
|
|
64
|
-
deprecated() {
|
|
65
|
-
return this.next("deprecated");
|
|
66
|
-
}
|
|
67
|
-
STRUCTType(val) {
|
|
68
|
-
return this.next("STRUCTType", val);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
var Column = (conf) => {
|
|
72
|
-
return new ColumnImpl(conf);
|
|
73
|
-
};
|
|
74
|
-
var Int = () => Column().SQlType("INTEGER");
|
|
75
|
-
var BigInt = () => Column().SQlType("BIGINT");
|
|
76
|
-
var Float = () => Column().SQlType("FLOAT");
|
|
77
|
-
var Boolean = () => Column().SQlType(
|
|
78
|
-
"BOOLEAN"
|
|
79
|
-
);
|
|
80
|
-
var Text = () => Column().SQlType("VARCHAR");
|
|
81
|
-
var Uuid = () => Column().SQlType("VARCHAR");
|
|
82
|
-
var DateType = () => Column().SQlType("DATE");
|
|
83
|
-
var Timestamp = () => Column().SQlType("TIMESTAMP");
|
|
84
|
-
var Enum = (vals) => {
|
|
85
|
-
const isString = typeof vals[0] === "string";
|
|
86
|
-
return Column().validate((v) => vals.includes(v)).SQlType(isString ? "VARCHAR" : "INTEGER");
|
|
87
|
-
};
|
|
88
|
-
var zodToDuckDBType = (zodType) => {
|
|
89
|
-
const def = zodType?._def;
|
|
90
|
-
if (def && (def.typeName === "ZodOptional" || def.typeName === "ZodNullable")) {
|
|
91
|
-
return zodToDuckDBType(def.innerType);
|
|
92
|
-
}
|
|
93
|
-
if (def && def.typeName === "ZodDefault") {
|
|
94
|
-
return zodToDuckDBType(def.innerType);
|
|
95
|
-
}
|
|
96
|
-
if (zodType instanceof z.ZodString) return "VARCHAR";
|
|
97
|
-
if (zodType instanceof z.ZodNumber) return "INTEGER";
|
|
98
|
-
if (zodType instanceof z.ZodBoolean) return "BOOLEAN";
|
|
99
|
-
if (zodType instanceof z.ZodDate) return "TIMESTAMP";
|
|
100
|
-
if (zodType instanceof z.ZodBigInt) return "BIGINT";
|
|
101
|
-
if ("element" in (def ?? {})) {
|
|
102
|
-
const innerType = zodToDuckDBType(def.element);
|
|
103
|
-
return `${innerType}[]`;
|
|
104
|
-
}
|
|
105
|
-
if ("shape" in (def ?? {})) {
|
|
106
|
-
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
107
|
-
const structParts = Object.entries(shape).map(([key, value]) => {
|
|
108
|
-
const fieldType = zodToDuckDBType(value);
|
|
109
|
-
return `${key} ${fieldType}`;
|
|
110
|
-
});
|
|
111
|
-
return `STRUCT(${structParts.join(", ")})`;
|
|
112
|
-
}
|
|
113
|
-
return "VARCHAR";
|
|
114
|
-
};
|
|
115
|
-
var Json = (obj) => {
|
|
116
|
-
const zodObj = z.object(obj);
|
|
117
|
-
const duckDBStructString = zodToDuckDBType(zodObj);
|
|
118
|
-
const col = Column().SQlType("STRUCT");
|
|
119
|
-
return col.STRUCTType(duckDBStructString);
|
|
120
|
-
};
|
|
121
|
-
var Array2 = (schema) => {
|
|
122
|
-
const innerType = zodToDuckDBType(schema);
|
|
123
|
-
const col = Column().SQlType("LIST");
|
|
124
|
-
return col.STRUCTType(`${innerType}[]`);
|
|
125
|
-
};
|
|
126
|
-
var Email = () => Column().SQlType("VARCHAR").validate((v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v));
|
|
127
|
-
var Slug = () => Column().SQlType("VARCHAR").validate((v) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(v));
|
|
128
|
-
var Color = () => Column().SQlType("VARCHAR").validate((v) => /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(v));
|
|
129
|
-
var Bytes = () => Column().SQlType("BLOB");
|
|
130
|
-
var Password = () => Column().SQlType(
|
|
131
|
-
"VARCHAR"
|
|
132
|
-
);
|
|
133
|
-
var GeoPoint = () => Column().SQlType("STRUCT");
|
|
134
|
-
var GeoArea = () => Column().SQlType("STRUCT");
|
|
135
|
-
var Table = (name, fields) => {
|
|
136
|
-
for (const [key, value] of Object.entries(fields)) {
|
|
137
|
-
Object.assign(value, { __parent: name, __fieldName: key });
|
|
138
|
-
}
|
|
139
|
-
return { ...fields, __tableName: name };
|
|
140
|
-
};
|
|
141
28
|
var GetFieldConfig = (f) => {
|
|
142
29
|
return f.config;
|
|
143
30
|
};
|
|
@@ -898,7 +785,7 @@ var OptimaDB = class _OptimaDB {
|
|
|
898
785
|
this.Tables = tables;
|
|
899
786
|
}
|
|
900
787
|
/**
|
|
901
|
-
* Initializes the database, connects, detects schema changes,
|
|
788
|
+
* Initializes the database, connects, detects schema changes,
|
|
902
789
|
* runs migrations, and returns the DB instance.
|
|
903
790
|
*/
|
|
904
791
|
static async Open(name = ":memory:", schema, options) {
|
|
@@ -912,7 +799,10 @@ var OptimaDB = class _OptimaDB {
|
|
|
912
799
|
}
|
|
913
800
|
const existingTables = await (await connection.run(`SELECT * from duckdb_tables`)).getRowObjects();
|
|
914
801
|
const cleanSchema = SchemaMigrator.transformSchema(schema);
|
|
915
|
-
const migrationSQL = SchemaMigrator.generateSQL(
|
|
802
|
+
const migrationSQL = SchemaMigrator.generateSQL(
|
|
803
|
+
existingTables,
|
|
804
|
+
cleanSchema
|
|
805
|
+
);
|
|
916
806
|
if (migrationSQL.length > 0) {
|
|
917
807
|
await connection.run("BEGIN TRANSACTION;");
|
|
918
808
|
try {
|
|
@@ -955,7 +845,7 @@ var OptimaDB = class _OptimaDB {
|
|
|
955
845
|
this.instance.closeSync();
|
|
956
846
|
}
|
|
957
847
|
/**
|
|
958
|
-
* Runs a function within a transaction.
|
|
848
|
+
* Runs a function within a transaction.
|
|
959
849
|
* Re-throws error after rollback so caller handles logic failure.
|
|
960
850
|
*/
|
|
961
851
|
async transaction(fn) {
|
|
@@ -1006,12 +896,14 @@ var SchemaMigrator = class {
|
|
|
1006
896
|
const steps = [];
|
|
1007
897
|
for (const [tableName, fields] of Object.entries(desiredSchema)) {
|
|
1008
898
|
if (!currentSchema[tableName]) {
|
|
1009
|
-
const fieldDefs = Object.entries(fields).map(
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
899
|
+
const fieldDefs = Object.entries(fields).map(
|
|
900
|
+
([colName, config]) => {
|
|
901
|
+
let def = `"${colName}" ${config.STRUCTType ? config.STRUCTType : config.SQlType}`;
|
|
902
|
+
if (config.primaryKey) def += " PRIMARY KEY";
|
|
903
|
+
if (config.notnull) def += " NOT NULL";
|
|
904
|
+
return def;
|
|
905
|
+
}
|
|
906
|
+
);
|
|
1015
907
|
steps.push(`CREATE TABLE ${tableName} (${fieldDefs.join(", ")});`);
|
|
1016
908
|
continue;
|
|
1017
909
|
}
|
|
@@ -1022,24 +914,40 @@ var SchemaMigrator = class {
|
|
|
1022
914
|
if (config.notnull) {
|
|
1023
915
|
def += ` DEFAULT ${this.getDefaultValueForType(config.SQlType)}`;
|
|
1024
916
|
}
|
|
1025
|
-
steps.push(
|
|
917
|
+
steps.push(
|
|
918
|
+
`ALTER TABLE ${tableName} ADD COLUMN "${colName}" ${def};`
|
|
919
|
+
);
|
|
1026
920
|
if (config.notnull) {
|
|
1027
|
-
steps.push(
|
|
921
|
+
steps.push(
|
|
922
|
+
`ALTER TABLE ${tableName} ALTER "${colName}" SET NOT NULL;`
|
|
923
|
+
);
|
|
1028
924
|
}
|
|
1029
925
|
continue;
|
|
1030
926
|
}
|
|
1031
927
|
const currentCol = currentTableCols[colName];
|
|
1032
928
|
const normCurrentType = currentCol.type.replace(/\s+/g, "").toUpperCase();
|
|
1033
929
|
const normNewType = config.SQlType.replace(/\s+/g, "").toUpperCase();
|
|
1034
|
-
if (normCurrentType !== normNewType
|
|
1035
|
-
|
|
930
|
+
if (normCurrentType !== normNewType) {
|
|
931
|
+
if (normNewType.startsWith("STRUCT") || normNewType.startsWith("LIST")) {
|
|
932
|
+
steps.push(
|
|
933
|
+
`ALTER TABLE ${tableName} ALTER "${colName}" TYPE ${config.STRUCTType};`
|
|
934
|
+
);
|
|
935
|
+
} else {
|
|
936
|
+
steps.push(
|
|
937
|
+
`ALTER TABLE ${tableName} ALTER "${colName}" TYPE ${config.SQlType};`
|
|
938
|
+
);
|
|
939
|
+
}
|
|
1036
940
|
}
|
|
1037
941
|
const desiredNotNull = !!config.notnull;
|
|
1038
942
|
if (desiredNotNull !== currentCol.isNotNull) {
|
|
1039
943
|
if (desiredNotNull) {
|
|
1040
|
-
steps.push(
|
|
944
|
+
steps.push(
|
|
945
|
+
`ALTER TABLE ${tableName} ALTER "${colName}" SET NOT NULL;`
|
|
946
|
+
);
|
|
1041
947
|
} else {
|
|
1042
|
-
steps.push(
|
|
948
|
+
steps.push(
|
|
949
|
+
`ALTER TABLE ${tableName} ALTER "${colName}" DROP NOT NULL;`
|
|
950
|
+
);
|
|
1043
951
|
}
|
|
1044
952
|
}
|
|
1045
953
|
}
|
|
@@ -1098,15 +1006,17 @@ var SchemaMigrator = class {
|
|
|
1098
1006
|
*/
|
|
1099
1007
|
static getDefaultValueForType(type) {
|
|
1100
1008
|
const t = type.toUpperCase();
|
|
1101
|
-
if (t.includes("INT") || t.includes("FLOAT") || t.includes("DECIMAL") || t.includes("DOUBLE"))
|
|
1009
|
+
if (t.includes("INT") || t.includes("FLOAT") || t.includes("DECIMAL") || t.includes("DOUBLE"))
|
|
1010
|
+
return "0";
|
|
1102
1011
|
if (t.includes("BOOL")) return "FALSE";
|
|
1103
|
-
if (t.includes("STRUCT") || t.includes("MAP") || t.includes("LIST"))
|
|
1012
|
+
if (t.includes("STRUCT") || t.includes("MAP") || t.includes("LIST"))
|
|
1013
|
+
return "NULL";
|
|
1104
1014
|
return "''";
|
|
1105
1015
|
}
|
|
1106
1016
|
};
|
|
1107
1017
|
|
|
1108
1018
|
// src/index.ts
|
|
1109
|
-
import { number, string, object
|
|
1019
|
+
import { number, string, object, array, any, bigint, date } from "zod";
|
|
1110
1020
|
export {
|
|
1111
1021
|
Array2 as Array,
|
|
1112
1022
|
BigInt,
|
|
@@ -1119,6 +1029,7 @@ export {
|
|
|
1119
1029
|
Float,
|
|
1120
1030
|
GeoArea,
|
|
1121
1031
|
GeoPoint,
|
|
1032
|
+
GetFieldConfig,
|
|
1122
1033
|
Int,
|
|
1123
1034
|
Json,
|
|
1124
1035
|
OPS,
|
|
@@ -1154,7 +1065,7 @@ export {
|
|
|
1154
1065
|
notLike,
|
|
1155
1066
|
notRegexp,
|
|
1156
1067
|
number,
|
|
1157
|
-
|
|
1068
|
+
object,
|
|
1158
1069
|
refHelpers,
|
|
1159
1070
|
regexp,
|
|
1160
1071
|
startsWith,
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
|
|
3
|
+
type Prettify<T> = {
|
|
4
|
+
[K in keyof T]: T[K];
|
|
5
|
+
} & {};
|
|
6
|
+
declare const __parentBrand: unique symbol;
|
|
7
|
+
type ParentBrand<Name extends string> = {
|
|
8
|
+
[__parentBrand]: Name;
|
|
9
|
+
};
|
|
10
|
+
type One<T> = T & {
|
|
11
|
+
readonly __refKind: "one";
|
|
12
|
+
};
|
|
13
|
+
type Many<T> = T & {
|
|
14
|
+
readonly __refKind: "many";
|
|
15
|
+
};
|
|
16
|
+
declare const refHelpers: {
|
|
17
|
+
one: <T>(ref: T) => One<T>;
|
|
18
|
+
many: <T>(ref: T) => Many<T>;
|
|
19
|
+
};
|
|
20
|
+
type InferColumnType<T> = T extends ColumnBuilder<infer U, any, any> ? U : never;
|
|
21
|
+
type Infer<T extends Record<string, any>> = Prettify<{
|
|
22
|
+
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? K : never : never]: T[K] extends ColumnBuilder<infer U, any, any> ? U : never;
|
|
23
|
+
} & // 2. Handle Optional Keys (notnull: false)
|
|
24
|
+
{
|
|
25
|
+
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? never : K : never]: T[K] extends ColumnBuilder<infer U, any, any> ? U | null : never;
|
|
26
|
+
}>;
|
|
27
|
+
type InferAdd<T extends Record<string, any>> = Prettify<{
|
|
28
|
+
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? K : never : never]: T[K] extends ColumnBuilder<infer U, any, any> ? U : never;
|
|
29
|
+
} & // 2. Handle Optional Keys (notnull: false)
|
|
30
|
+
{
|
|
31
|
+
[K in keyof T as K extends `__${string}` ? never : T[K] extends ColumnBuilder<any, infer C, any> ? C["notnull"] extends true ? never : K : never]?: T[K] extends ColumnBuilder<infer U, any, any> ? U | null : never;
|
|
32
|
+
}>;
|
|
33
|
+
type ColumnConfig = {
|
|
34
|
+
SQlType: boolean;
|
|
35
|
+
primaryKey: boolean;
|
|
36
|
+
notnull: boolean;
|
|
37
|
+
unique: boolean;
|
|
38
|
+
default: boolean;
|
|
39
|
+
defaultNow: boolean;
|
|
40
|
+
reference: boolean;
|
|
41
|
+
validate: boolean;
|
|
42
|
+
transform: boolean;
|
|
43
|
+
deprecated: boolean;
|
|
44
|
+
STRUCTType: boolean;
|
|
45
|
+
};
|
|
46
|
+
type DefaultConfig = {
|
|
47
|
+
[K in keyof ColumnConfig]: false;
|
|
48
|
+
};
|
|
49
|
+
type SetFlag<C extends ColumnConfig, K extends keyof ColumnConfig> = Omit<C, K> & {
|
|
50
|
+
[P in K]: true;
|
|
51
|
+
};
|
|
52
|
+
type Restrict<K extends keyof ColumnConfig> = {
|
|
53
|
+
[P in keyof ColumnConfig]: P extends K ? true : false;
|
|
54
|
+
};
|
|
55
|
+
type ColumnBuilder<Type, Config extends ColumnConfig, RefSchema = never> = {
|
|
56
|
+
[K in keyof ColumnConfig as K extends "STRUCTType" ? never : Config[K] extends true ? never : K]: K extends "SQlType" ? (val: string) => ColumnBuilder<Type, SetFlag<Config, "SQlType">, RefSchema> : K extends "primaryKey" ? () => ColumnBuilder<Type, SetFlag<Config, "primaryKey">, RefSchema> : K extends "notnull" ? () => ColumnBuilder<Type, SetFlag<Config, "notnull">, RefSchema> : K extends "unique" ? () => ColumnBuilder<Type, SetFlag<Config, "unique">, RefSchema> : K extends "default" ? (val: Type | (() => Type)) => ColumnBuilder<Type, SetFlag<Config, "default">, RefSchema> : K extends "defaultNow" ? () => ColumnBuilder<Type, SetFlag<Config, "defaultNow">, RefSchema> : K extends "reference" ? <TRef>(ref: (helpers: typeof refHelpers) => TRef) => ColumnBuilder<Type, SetFlag<Config, "reference">, TRef> : K extends "validate" ? (fn: (val: Type) => boolean) => ColumnBuilder<Type, SetFlag<Config, "validate">, RefSchema> : K extends "transform" ? (fn: (val: Type) => Type) => ColumnBuilder<Type, SetFlag<Config, "transform">, RefSchema> : K extends "deprecated" ? () => ColumnBuilder<Type, SetFlag<Config, "deprecated">, RefSchema> : never;
|
|
57
|
+
};
|
|
58
|
+
declare const Int: () => ColumnBuilder<number, SetFlag<Restrict<"defaultNow">, "SQlType">, never>;
|
|
59
|
+
declare const BigInt: () => ColumnBuilder<bigint, SetFlag<Restrict<"defaultNow">, "SQlType">, never>;
|
|
60
|
+
declare const Float: () => ColumnBuilder<number, SetFlag<Restrict<"defaultNow">, "SQlType">, never>;
|
|
61
|
+
declare const Boolean: () => ColumnBuilder<boolean, SetFlag<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
62
|
+
declare const Text: () => ColumnBuilder<string, SetFlag<Restrict<"defaultNow">, "SQlType">, never>;
|
|
63
|
+
declare const Uuid: () => ColumnBuilder<string, SetFlag<Restrict<"defaultNow">, "SQlType">, never>;
|
|
64
|
+
declare const DateType: () => ColumnBuilder<Date, SetFlag<Restrict<"default">, "SQlType">, never>;
|
|
65
|
+
declare const Timestamp: () => ColumnBuilder<Date, SetFlag<Restrict<"default">, "SQlType">, never>;
|
|
66
|
+
declare const Enum: <T extends string | number>(vals: readonly T[]) => ColumnBuilder<T, SetFlag<SetFlag<Restrict<"defaultNow">, "validate">, "SQlType">, never>;
|
|
67
|
+
declare const Json: <T extends z.ZodRawShape = Record<string, any>>(obj: T) => ColumnBuilder<[keyof T] extends [never] ? Record<string, any> : z.core.$InferObjectOutput<T, {}>, SetFlag<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
68
|
+
declare const Array: <T extends z.ZodTypeAny>(schema: T) => ColumnBuilder<z.core.output<T>[], SetFlag<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
69
|
+
declare const Email: () => ColumnBuilder<string, SetFlag<SetFlag<Restrict<"defaultNow">, "SQlType">, "validate">, never>;
|
|
70
|
+
declare const Slug: () => ColumnBuilder<string, SetFlag<SetFlag<Restrict<"defaultNow">, "SQlType">, "validate">, never>;
|
|
71
|
+
declare const Color: () => ColumnBuilder<string, SetFlag<SetFlag<Restrict<"defaultNow">, "SQlType">, "validate">, never>;
|
|
72
|
+
declare const Bytes: () => ColumnBuilder<Uint8Array<ArrayBufferLike>, SetFlag<Restrict<"primaryKey" | "defaultNow">, "SQlType">, never>;
|
|
73
|
+
declare const Password: () => ColumnBuilder<string, SetFlag<Restrict<"primaryKey" | "unique" | "defaultNow">, "SQlType">, never>;
|
|
74
|
+
declare const GeoPoint: () => ColumnBuilder<{
|
|
75
|
+
latitude: number;
|
|
76
|
+
longitude: number;
|
|
77
|
+
}, SetFlag<Restrict<"primaryKey" | "defaultNow">, "SQlType">, never>;
|
|
78
|
+
declare const GeoArea: () => ColumnBuilder<{
|
|
79
|
+
latitude: number;
|
|
80
|
+
longitude: number;
|
|
81
|
+
radius: number;
|
|
82
|
+
}, SetFlag<Restrict<"primaryKey" | "defaultNow">, "SQlType">, never>;
|
|
83
|
+
declare const Table: <Name extends string, T extends Record<string, ColumnBuilder<any, any>>>(name: Name, fields: T) => T & {
|
|
84
|
+
__tableName: Name;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { Array, BigInt, Boolean, Bytes, Color, type ColumnBuilder, type ColumnConfig, DateType, type DefaultConfig, Email, Enum, Float, GeoArea, GeoPoint, type Infer, type InferAdd, type InferColumnType, Int, Json, type Many, type One, type ParentBrand, Password, type Prettify, type Restrict, type SetFlag, Slug, Table, Text, Timestamp, Uuid, refHelpers };
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Array,
|
|
3
|
+
BigInt,
|
|
4
|
+
Boolean,
|
|
5
|
+
Bytes,
|
|
6
|
+
Color,
|
|
7
|
+
DateType,
|
|
8
|
+
Email,
|
|
9
|
+
Enum,
|
|
10
|
+
Float,
|
|
11
|
+
GeoArea,
|
|
12
|
+
GeoPoint,
|
|
13
|
+
Int,
|
|
14
|
+
Json,
|
|
15
|
+
Password,
|
|
16
|
+
Slug,
|
|
17
|
+
Table,
|
|
18
|
+
Text,
|
|
19
|
+
Timestamp,
|
|
20
|
+
Uuid,
|
|
21
|
+
refHelpers
|
|
22
|
+
} from "./chunk-JTCM2KCM.js";
|
|
23
|
+
export {
|
|
24
|
+
Array,
|
|
25
|
+
BigInt,
|
|
26
|
+
Boolean,
|
|
27
|
+
Bytes,
|
|
28
|
+
Color,
|
|
29
|
+
DateType,
|
|
30
|
+
Email,
|
|
31
|
+
Enum,
|
|
32
|
+
Float,
|
|
33
|
+
GeoArea,
|
|
34
|
+
GeoPoint,
|
|
35
|
+
Int,
|
|
36
|
+
Json,
|
|
37
|
+
Password,
|
|
38
|
+
Slug,
|
|
39
|
+
Table,
|
|
40
|
+
Text,
|
|
41
|
+
Timestamp,
|
|
42
|
+
Uuid,
|
|
43
|
+
refHelpers
|
|
44
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inflector/optima",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Inflector",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,9 +13,14 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.js",
|
|
18
|
+
"./types": "./dist/index.d.ts",
|
|
19
|
+
"./types-source": "./src/types.ts"
|
|
20
|
+
},
|
|
16
21
|
"scripts": {
|
|
17
22
|
"dev": "bun index.ts",
|
|
18
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
23
|
+
"build": "tsup src/index.ts src/types.ts --format esm --dts --clean",
|
|
19
24
|
"prepublishOnly": "bun run build"
|
|
20
25
|
},
|
|
21
26
|
"types": "./dist/index.d.ts",
|