@vibeorm/generator 1.3.0 → 2.0.0-alpha.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/README.md +43 -39
- package/dist/emit-dts.d.ts +22 -0
- package/dist/emit-dts.d.ts.map +1 -0
- package/dist/emit-js.d.ts +16 -0
- package/dist/emit-js.d.ts.map +1 -0
- package/dist/extension-bake.d.ts +42 -0
- package/dist/extension-bake.d.ts.map +1 -0
- package/dist/generate.d.ts +26 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1465 -0
- package/dist/index.js.map +16 -0
- package/dist/schema-view.d.ts +77 -0
- package/dist/schema-view.d.ts.map +1 -0
- package/dist/type-names.d.ts +30 -0
- package/dist/type-names.d.ts.map +1 -0
- package/dist/util.d.ts +39 -0
- package/dist/util.d.ts.map +1 -0
- package/package.json +29 -23
- package/src/generate.ts +0 -70
- package/src/generators/generate-args.ts +0 -322
- package/src/generators/generate-client.ts +0 -252
- package/src/generators/generate-delegates.ts +0 -590
- package/src/generators/generate-enums.ts +0 -28
- package/src/generators/generate-inputs.ts +0 -655
- package/src/generators/generate-models.ts +0 -130
- package/src/generators/generate-result.ts +0 -182
- package/src/generators/generate-schemas.ts +0 -474
- package/src/generators/generate-view-types.ts +0 -446
- package/src/index.ts +0 -2
- package/src/utils.ts +0 -51
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import type { Model, Schema, Field, ScalarField, EnumField, RelationField } from "@vibeorm/parser";
|
|
2
|
-
import { fileHeader, toCamelCase } from "../utils.ts";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generates the Payload types for each model.
|
|
6
|
-
* These split each model into { scalars, objects, composites }
|
|
7
|
-
* which is the foundation for select/include type narrowing.
|
|
8
|
-
*/
|
|
9
|
-
export function generateModels(params: { schema: Schema }): string {
|
|
10
|
-
const { schema } = params;
|
|
11
|
-
const parts: string[] = [fileHeader()];
|
|
12
|
-
|
|
13
|
-
// Import enums if any
|
|
14
|
-
if (schema.enums.length > 0) {
|
|
15
|
-
const enumImports = schema.enums.map((e) => e.name).join(", ");
|
|
16
|
-
parts.push(`import type { ${enumImports} } from "./enums.ts";\n`);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Generate JsonValue type.
|
|
20
|
-
//
|
|
21
|
-
// Arrays and object index signatures are `readonly` so that `readonly T[]` /
|
|
22
|
-
// `ReadonlyArray<T>` (common in typed catalogues, factories, seed scripts) can
|
|
23
|
-
// be assigned into Json columns without forcing a spread/cast at every call
|
|
24
|
-
// site. Postgres doesn't care about JS array mutability — this is a purely
|
|
25
|
-
// type-level relaxation that's strictly more permissive in argument position.
|
|
26
|
-
parts.push(`export type JsonValue = string | number | boolean | null | readonly JsonValue[] | { readonly [key: string]: JsonValue };\n`);
|
|
27
|
-
|
|
28
|
-
// InputJsonValue — looser than JsonValue, used in CreateInput/UpdateInput
|
|
29
|
-
// for Json fields (Bug 8). Accepts:
|
|
30
|
-
// - all JsonValue shapes (readonly arrays / readonly object index sigs)
|
|
31
|
-
// - any object exposing toJSON() (Date, Decimal wrappers, BigInt wrappers, …)
|
|
32
|
-
//
|
|
33
|
-
// The `toJSON` escape hatch is what lets users feed seed/factory data typed
|
|
34
|
-
// as `Record<string, unknown>` via a single intentional cast, instead of
|
|
35
|
-
// rewriting every call site. Postgres jsonb doesn't care about the JS shape —
|
|
36
|
-
// the adapter JSON.stringifies whatever it gets. Output types keep the strict
|
|
37
|
-
// `JsonValue`.
|
|
38
|
-
parts.push(`export type InputJsonObject = { readonly [key: string]: InputJsonValue | null | undefined };
|
|
39
|
-
export type InputJsonArray = ReadonlyArray<InputJsonValue | null>;
|
|
40
|
-
export type InputJsonValue =
|
|
41
|
-
| string
|
|
42
|
-
| number
|
|
43
|
-
| boolean
|
|
44
|
-
| InputJsonObject
|
|
45
|
-
| InputJsonArray
|
|
46
|
-
| { toJSON(): unknown };
|
|
47
|
-
`);
|
|
48
|
-
|
|
49
|
-
// Generate the base OperationPayload interface
|
|
50
|
-
parts.push(`export type OperationPayload = {
|
|
51
|
-
name: string;
|
|
52
|
-
scalars: Record<string, unknown>;
|
|
53
|
-
objects: Record<string, unknown>;
|
|
54
|
-
composites: Record<string, unknown>;
|
|
55
|
-
};\n`);
|
|
56
|
-
|
|
57
|
-
// Generate payload type for each model
|
|
58
|
-
for (const model of schema.models) {
|
|
59
|
-
parts.push(generatePayloadType({ model, schema }));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Generate plain model types (default selection = scalars only)
|
|
63
|
-
for (const model of schema.models) {
|
|
64
|
-
parts.push(generatePlainModelType({ model, schema }));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return parts.join("\n");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function generatePayloadType(params: { model: Model; schema: Schema }): string {
|
|
71
|
-
const { model, schema } = params;
|
|
72
|
-
|
|
73
|
-
const scalarFields = model.fields.filter(
|
|
74
|
-
(f): f is ScalarField | EnumField => f.kind === "scalar" || f.kind === "enum"
|
|
75
|
-
);
|
|
76
|
-
const relationFields = model.fields.filter(
|
|
77
|
-
(f): f is RelationField => f.kind === "relation"
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
// Scalars block
|
|
81
|
-
const scalarsEntries = scalarFields.map((f) => {
|
|
82
|
-
const tsType = f.kind === "scalar" ? f.tsType : f.enumName;
|
|
83
|
-
const nullable = f.isRequired ? "" : " | null";
|
|
84
|
-
const listPrefix = f.isList ? "" : "";
|
|
85
|
-
const listSuffix = f.isList ? "[]" : "";
|
|
86
|
-
return ` ${f.name}: ${listPrefix}${tsType}${nullable}${listSuffix};`;
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Objects block
|
|
90
|
-
const objectsEntries = relationFields.map((f) => {
|
|
91
|
-
const payloadType = `$${f.relatedModel}Payload`;
|
|
92
|
-
if (f.isList) {
|
|
93
|
-
return ` ${f.name}: ${payloadType}[];`;
|
|
94
|
-
}
|
|
95
|
-
const nullable = f.isRequired ? "" : " | null";
|
|
96
|
-
return ` ${f.name}: ${payloadType}${nullable};`;
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return `export type $${model.name}Payload = {
|
|
100
|
-
name: "${model.name}";
|
|
101
|
-
scalars: {
|
|
102
|
-
${scalarsEntries.join("\n")}
|
|
103
|
-
};
|
|
104
|
-
objects: {
|
|
105
|
-
${objectsEntries.join("\n")}
|
|
106
|
-
};
|
|
107
|
-
composites: {};
|
|
108
|
-
};
|
|
109
|
-
`;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function generatePlainModelType(params: { model: Model; schema: Schema }): string {
|
|
113
|
-
const { model } = params;
|
|
114
|
-
|
|
115
|
-
const scalarFields = model.fields.filter(
|
|
116
|
-
(f): f is ScalarField | EnumField => f.kind === "scalar" || f.kind === "enum"
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const entries = scalarFields.map((f) => {
|
|
120
|
-
const tsType = f.kind === "scalar" ? f.tsType : f.enumName;
|
|
121
|
-
const nullable = f.isRequired ? "" : " | null";
|
|
122
|
-
const listSuffix = f.isList ? "[]" : "";
|
|
123
|
-
return ` ${f.name}: ${tsType}${nullable}${listSuffix};`;
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return `export type ${model.name} = {
|
|
127
|
-
${entries.join("\n")}
|
|
128
|
-
};
|
|
129
|
-
`;
|
|
130
|
-
}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { fileHeader } from "../utils.ts";
|
|
2
|
-
import type { Schema } from "@vibeorm/parser";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generates the core type resolution engine.
|
|
6
|
-
*
|
|
7
|
-
* This produces the conditional types that narrow return types
|
|
8
|
-
* based on the select/include args passed to operations.
|
|
9
|
-
*
|
|
10
|
-
* The pattern:
|
|
11
|
-
* - No select/include → DefaultSelection (scalars only)
|
|
12
|
-
* - select: { field: true } → only selected fields
|
|
13
|
-
* - include: { relation: true } → scalars + included relations
|
|
14
|
-
* - Nested select/include in relations → recursive narrowing
|
|
15
|
-
*/
|
|
16
|
-
export function generateResult(params: { schema: Schema }): string {
|
|
17
|
-
const { schema } = params;
|
|
18
|
-
const parts: string[] = [fileHeader()];
|
|
19
|
-
|
|
20
|
-
// Import payload types
|
|
21
|
-
const payloadImports = schema.models
|
|
22
|
-
.map((m) => `$${m.name}Payload`)
|
|
23
|
-
.join(", ");
|
|
24
|
-
parts.push(
|
|
25
|
-
`import type { ${payloadImports}, OperationPayload } from "./models.ts";\n`
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
// ─── Utility Types ────────────────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
parts.push(`
|
|
31
|
-
// ─── Core Utility Types ───────────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
/** Detect if T is exactly \`any\` */
|
|
34
|
-
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
35
|
-
|
|
36
|
-
/** Flatten intersection types for cleaner hover tooltips */
|
|
37
|
-
type Compute<T> = T extends Function ? T : { [K in keyof T]: T[K] } & unknown;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Enforces strict type safety by recursively rejecting excess properties.
|
|
41
|
-
*
|
|
42
|
-
* TypeScript's structural subtyping allows objects to have extra properties
|
|
43
|
-
* when passed through generics (\`<T extends Args>\`). This utility type
|
|
44
|
-
* maps any key in A that is NOT in W to \`never\`, causing a compile-time
|
|
45
|
-
* error when unknown keys (e.g. typos in where/select/include) are used.
|
|
46
|
-
*
|
|
47
|
-
* Primitives, arrays, functions, and Dates are passed through unchanged
|
|
48
|
-
* to preserve literal types for return type narrowing via GetFindResult.
|
|
49
|
-
*/
|
|
50
|
-
export type Exact<A, W> = W extends unknown
|
|
51
|
-
? A extends W
|
|
52
|
-
? A extends Record<string, unknown>
|
|
53
|
-
? { [K in keyof A]: K extends keyof W ? Exact<A[K], W[K]> : never }
|
|
54
|
-
: A
|
|
55
|
-
: W
|
|
56
|
-
: never;
|
|
57
|
-
|
|
58
|
-
/** Extract scalar fields from a payload (default selection) */
|
|
59
|
-
type DefaultSelection<P extends OperationPayload> = P["scalars"];
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Check if a key exists in the payload's objects or composites
|
|
63
|
-
* and extract the value type.
|
|
64
|
-
*/
|
|
65
|
-
type SelectableObject<P extends OperationPayload, K extends PropertyKey> =
|
|
66
|
-
K extends keyof P["objects"] ? P["objects"][K] : never;
|
|
67
|
-
|
|
68
|
-
// ─── GetFindResult ────────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The core type that resolves the result type based on select/include args.
|
|
72
|
-
*
|
|
73
|
-
* - If no args or args is any → DefaultSelection (scalars only)
|
|
74
|
-
* - If select is provided → only selected fields (scalars + expanded relations)
|
|
75
|
-
* - If include is provided → all scalars + included relations
|
|
76
|
-
*/
|
|
77
|
-
export type GetFindResult<P extends OperationPayload, A> =
|
|
78
|
-
// If Args is any (no args passed), return default
|
|
79
|
-
IsAny<A> extends true
|
|
80
|
-
? DefaultSelection<P>
|
|
81
|
-
: A extends { select: infer S extends Record<string, unknown> }
|
|
82
|
-
? // ── SELECT branch ──
|
|
83
|
-
Compute<{
|
|
84
|
-
[K in keyof S as S[K] extends false | undefined | null
|
|
85
|
-
? never
|
|
86
|
-
: K]: K extends keyof P["scalars"]
|
|
87
|
-
? // Scalar field selected
|
|
88
|
-
P["scalars"][K]
|
|
89
|
-
: K extends keyof P["objects"]
|
|
90
|
-
? // Relation field selected
|
|
91
|
-
P["objects"][K] extends OperationPayload[]
|
|
92
|
-
? // Array relation
|
|
93
|
-
S[K] extends Record<string, unknown>
|
|
94
|
-
? GetFindResult<P["objects"][K][number], S[K]>[]
|
|
95
|
-
: DefaultSelection<P["objects"][K][number]>[]
|
|
96
|
-
: P["objects"][K] extends OperationPayload
|
|
97
|
-
? // Required single relation (checked before nullable to avoid false match)
|
|
98
|
-
S[K] extends Record<string, unknown>
|
|
99
|
-
? GetFindResult<P["objects"][K], S[K]>
|
|
100
|
-
: DefaultSelection<P["objects"][K]>
|
|
101
|
-
: P["objects"][K] extends OperationPayload | null
|
|
102
|
-
? // Nullable single relation
|
|
103
|
-
S[K] extends Record<string, unknown>
|
|
104
|
-
? GetFindResult<NonNullable<P["objects"][K]> & OperationPayload, S[K]> | null
|
|
105
|
-
: DefaultSelection<NonNullable<P["objects"][K]> & OperationPayload> | null
|
|
106
|
-
: never
|
|
107
|
-
: never;
|
|
108
|
-
}>
|
|
109
|
-
: A extends { include: infer I extends Record<string, unknown> }
|
|
110
|
-
? // ── INCLUDE branch ──
|
|
111
|
-
// All scalars + included relations
|
|
112
|
-
Compute<
|
|
113
|
-
DefaultSelection<P> & {
|
|
114
|
-
[K in keyof I as I[K] extends false | undefined | null
|
|
115
|
-
? never
|
|
116
|
-
: K]: K extends keyof P["objects"]
|
|
117
|
-
? P["objects"][K] extends OperationPayload[]
|
|
118
|
-
? // Array relation
|
|
119
|
-
I[K] extends Record<string, unknown>
|
|
120
|
-
? GetFindResult<P["objects"][K][number], I[K]>[]
|
|
121
|
-
: DefaultSelection<P["objects"][K][number]>[]
|
|
122
|
-
: P["objects"][K] extends OperationPayload
|
|
123
|
-
? // Required single relation (checked before nullable to avoid false match)
|
|
124
|
-
I[K] extends Record<string, unknown>
|
|
125
|
-
? GetFindResult<P["objects"][K], I[K]>
|
|
126
|
-
: DefaultSelection<P["objects"][K]>
|
|
127
|
-
: P["objects"][K] extends OperationPayload | null
|
|
128
|
-
? // Nullable single relation
|
|
129
|
-
I[K] extends Record<string, unknown>
|
|
130
|
-
? GetFindResult<NonNullable<P["objects"][K]> & OperationPayload, I[K]> | null
|
|
131
|
-
: DefaultSelection<NonNullable<P["objects"][K]> & OperationPayload> | null
|
|
132
|
-
: never
|
|
133
|
-
: never;
|
|
134
|
-
}
|
|
135
|
-
>
|
|
136
|
-
: // ── No select/include ──
|
|
137
|
-
DefaultSelection<P>;
|
|
138
|
-
|
|
139
|
-
// ─── Operation Result Types ───────────────────────────────────────
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Maps an operation name to the correct result cardinality.
|
|
143
|
-
*/
|
|
144
|
-
export type GetResult<
|
|
145
|
-
P extends OperationPayload,
|
|
146
|
-
A,
|
|
147
|
-
Op extends string,
|
|
148
|
-
> = {
|
|
149
|
-
findMany: GetFindResult<P, A>[];
|
|
150
|
-
findFirst: GetFindResult<P, A> | null;
|
|
151
|
-
findUnique: GetFindResult<P, A> | null;
|
|
152
|
-
findUniqueOrThrow: GetFindResult<P, A>;
|
|
153
|
-
findFirstOrThrow: GetFindResult<P, A>;
|
|
154
|
-
create: GetFindResult<P, A>;
|
|
155
|
-
createMany: { count: number };
|
|
156
|
-
createManyAndReturn: GetFindResult<P, A>[];
|
|
157
|
-
update: GetFindResult<P, A>;
|
|
158
|
-
upsert: GetFindResult<P, A>;
|
|
159
|
-
delete: GetFindResult<P, A>;
|
|
160
|
-
count: number;
|
|
161
|
-
deleteMany: { count: number };
|
|
162
|
-
updateMany: { count: number };
|
|
163
|
-
}[Op & keyof {
|
|
164
|
-
findMany: unknown;
|
|
165
|
-
findFirst: unknown;
|
|
166
|
-
findUnique: unknown;
|
|
167
|
-
findUniqueOrThrow: unknown;
|
|
168
|
-
findFirstOrThrow: unknown;
|
|
169
|
-
create: unknown;
|
|
170
|
-
createMany: unknown;
|
|
171
|
-
createManyAndReturn: unknown;
|
|
172
|
-
update: unknown;
|
|
173
|
-
upsert: unknown;
|
|
174
|
-
delete: unknown;
|
|
175
|
-
count: unknown;
|
|
176
|
-
deleteMany: unknown;
|
|
177
|
-
updateMany: unknown;
|
|
178
|
-
}];
|
|
179
|
-
`);
|
|
180
|
-
|
|
181
|
-
return parts.join("\n");
|
|
182
|
-
}
|