|
1 | 1 | {
|
2 |
| - "Model Class": { |
| 2 | + "Model Class": { |
3 | 3 | "prefix": "@model",
|
4 | 4 | "body": [
|
5 | 5 | "import type { DatabaseResult } from '@/types/database';",
|
6 |
| - "import type { ModelEntityOf, ModelGenerator, ModelMetadata, ModelMode, ModelSchemaRawOf, ModeWithResolved } from '@/types/model';", |
7 |
| - "import type { Override } from '@/types/utils';", |
| 6 | + "import type { BuildModelResult, Model, ModelBuilder, ModelBuilderInternal, ModelBuilderType, ModelGenerator, ModelInstances, ModelMetadata, ModelMode, ModelNormalizer, ModelRawData4build, ModelResolver, ModelSchemaRawOf, ModelUnwrappedInstances__DO_NOT_EXPOSE, ModeWithResolved } from '@/types/model';", |
| 7 | + "import type { ArrayElem, Brand, Nullable, Override } from '@/types/utils';", |
8 | 8 | "import type {",
|
9 | 9 | " Prisma,",
|
10 | 10 | " PrismaClient,",
|
11 | 11 | " ${1:ModelName} as SchemaRaw,",
|
12 | 12 | "} from '@prisma/client';",
|
13 | 13 | "import { Database } from '@/services/database.server';",
|
14 |
| - "import { includeKeys2select, matchWithResolved } from '@/utils/model';", |
| 14 | + "import { buildRawData, includeKeys2select, matchWithDefault, matchWithResolved, separateRawData } from '@/utils/model';", |
| 15 | + "import { err, ok } from 'neverthrow';", |
| 16 | + "import { match } from 'ts-pattern';", |
| 17 | + "import { z } from 'zod';", |
15 | 18 | "",
|
16 | 19 | "/// Metadata ///",
|
17 | 20 | "",
|
|
23 | 26 | "",
|
24 | 27 | "/// Custom Types ///",
|
25 | 28 | "",
|
26 |
| - "/* TODO */", |
| 29 | + "", |
27 | 30 | "",
|
28 | 31 | "/// Model Types ///",
|
29 | 32 | "",
|
30 | 33 | "type Schema = Override<",
|
31 | 34 | " SchemaRaw,",
|
32 | 35 | " {",
|
33 |
| - " /* TODO */", |
34 | 36 | " }",
|
35 | 37 | ">;",
|
36 | 38 | "",
|
37 | 39 | "type IncludeKey = keyof Prisma.${1:ModelName}Include;",
|
38 | 40 | "const includeKeys = [] as const satisfies IncludeKey[];",
|
39 | 41 | "",
|
40 | 42 | "interface SchemaResolvedRaw {",
|
41 |
| - " /* TODO */", |
42 | 43 | "}",
|
43 | 44 | "",
|
44 | 45 | "interface SchemaResolved {",
|
45 |
| - " _parent: {", |
46 |
| - " /* TODO */", |
47 |
| - " };", |
48 | 46 | "}",
|
49 | 47 | "",
|
| 48 | + "/// ModelTypes ///", |
| 49 | + "", |
| 50 | + "type ModelGen = ModelGenerator<typeof metadata, SchemaRaw, Schema, SchemaResolvedRaw, SchemaResolved>;", |
| 51 | + "type ThisModelImpl<M extends ModelMode = 'DEFAULT'> = Model<M, ModelGen>;", |
| 52 | + "type ThisModel<M extends ModelMode = 'DEFAULT'> = $${1:ModelName}<M>;", |
| 53 | + "interface ThisModelVariants {", |
| 54 | + " DEFAULT: ThisModel;", |
| 55 | + " WITH_RESOLVED: ThisModel<'WITH_RESOLVED'>;", |
| 56 | + "}", |
| 57 | + "type RawData = ModelRawData4build<ThisModel>;", |
| 58 | + "", |
| 59 | + "/// Normalizer ///", |
| 60 | + "", |
| 61 | + "const normalizer = ((client, builder) => ({", |
| 62 | + " schema: (__raw) => ({", |
| 63 | + " }),", |
| 64 | + " schemaResolved: (__rawResolved) => {", |
| 65 | + " const { models } = new Database(client);", |
| 66 | + " const { } = __rawResolved;", |
| 67 | + " },", |
| 68 | + "})) satisfies ModelNormalizer<ThisModel>;", |
| 69 | + "", |
50 | 70 | "/// Model ///",
|
51 | 71 | "",
|
52 |
| - "export const __${1:ModelName} = (<M extends ModelMode = 'DEFAULT'>(client: PrismaClient) => class ${1:ModelName}<Mode extends ModelMode = M> {", |
53 |
| - " public static __prisma = client;", |
| 72 | + "export class $${1:ModelName}<Mode extends ModelMode = 'DEFAULT'> implements ThisModelImpl<Mode> {", |
54 | 73 | " private dbError = Database.dbErrorWith(metadata);",
|
55 |
| - " private models = new Database(client).models", |
| 74 | + " private client;", |
| 75 | + " public declare __struct: ThisModelImpl<Mode>;", |
| 76 | + " public declare __variants: ThisModelVariants;", |
56 | 77 | "",
|
57 | 78 | " public __raw: SchemaRaw;",
|
58 | 79 | " public data: Schema;",
|
59 | 80 | " public __rawResolved: ModeWithResolved<Mode, SchemaResolvedRaw>;",
|
60 | 81 | " public dataResolved: ModeWithResolved<Mode, SchemaResolved>;",
|
61 | 82 | "",
|
62 |
| - " public constructor(__raw: SchemaRaw, __rawResolved?: SchemaResolvedRaw) {", |
63 |
| - " this.__raw = __raw;", |
64 |
| - " this.data = {", |
65 |
| - " ...__raw,", |
66 |
| - " /* TODO */", |
67 |
| - " };", |
68 |
| - "", |
69 |
| - " const { rawResolved, dataResolved } = matchWithResolved<Mode, SchemaResolvedRaw, SchemaResolved>(", |
70 |
| - " __rawResolved,", |
71 |
| - " (r) => ({", |
72 |
| - " _parent: {", |
73 |
| - " /* TODO */", |
74 |
| - " },", |
75 |
| - " }),", |
76 |
| - " );", |
| 83 | + " private constructor(", |
| 84 | + " public __prisma: PrismaClient,", |
| 85 | + " { __raw, __rawResolved }: RawData,", |
| 86 | + " private builder: ModelBuilderType,", |
| 87 | + " ) {", |
| 88 | + " const n = normalizer(__prisma, this.builder);", |
77 | 89 | "",
|
| 90 | + " this.__raw = __raw;", |
| 91 | + " this.data = n.schema(__raw);", |
| 92 | + " const { rawResolved, dataResolved } = matchWithResolved<Mode, SchemaResolvedRaw, SchemaResolved>(__rawResolved, n.schemaResolved);", |
78 | 93 | " this.__rawResolved = rawResolved;",
|
79 | 94 | " this.dataResolved = dataResolved;",
|
| 95 | + " this.client = __prisma;", |
80 | 96 | " }",
|
81 | 97 | "",
|
82 |
| - " public static from(id /* TODO */): DatabaseResult<${1:ModelName}> {", |
83 |
| - " return Database.transformResult(", |
84 |
| - " client.${2:modelName}.findUniqueOrThrow({", |
85 |
| - " where: { ${3:primaryKey}: id },", |
86 |
| - " }),", |
87 |
| - " )", |
88 |
| - " .mapErr(Database.dbErrorWith(metadata).transform('from'))", |
89 |
| - " .map((data) => new ${1:ModelName}(data));", |
| 98 | + " public static with(client: PrismaClient) {", |
| 99 | + " const __toUnwrappedInstances = ((rawData, builder) => ({", |
| 100 | + " default: new $${1:ModelName}(client, rawData, builder),", |
| 101 | + " withResolved: new $${1:ModelName}<'WITH_RESOLVED'>(client, rawData, builder),", |
| 102 | + " })) satisfies ModelUnwrappedInstances__DO_NOT_EXPOSE<ThisModel>;", |
| 103 | + "", |
| 104 | + " const toInstances = ((rawData, builder) => match(builder)", |
| 105 | + " .with({ type: 'ANONYMOUS' }, () => err({ type: 'PERMISSION_DENIED', detail: { builder }} as const))", |
| 106 | + " .with({ type: 'SELF' }, () => ok(__toUnwrappedInstances(rawData, builder)))", |
| 107 | + " .with({ type: 'MEMBER' }, () => ok(__toUnwrappedInstances(rawData, builder)))", |
| 108 | + " .exhaustive()", |
| 109 | + " ) satisfies ModelInstances<ThisModel>;", |
| 110 | + "", |
| 111 | + " const __build = {", |
| 112 | + " __with: toInstances,", |
| 113 | + " by: (rawData, memberAsBuilder) => toInstances(rawData, { type: 'MEMBER', member: memberAsBuilder }),", |
| 114 | + " bySelf: (rawData) => toInstances(rawData, { type: 'SELF' }),", |
| 115 | + " } satisfies ModelBuilderInternal<ThisModel>;", |
| 116 | + "", |
| 117 | + " return {", |
| 118 | + " __build,", |
| 119 | + " from: (${3:primaryKey}: never) => {", |
| 120 | + " const rawData = Database.transformResult(", |
| 121 | + " client.${2:modelName}.findUniqueOrThrow({", |
| 122 | + " where: { ${3:primaryKey} },", |
| 123 | + " }),", |
| 124 | + " )", |
| 125 | + " .mapErr(Database.dbErrorWith(metadata).transform('from'))", |
| 126 | + " .map(separateRawData<ThisModel, IncludeKey>(includeKeys).default);", |
| 127 | + "", |
| 128 | + " return rawData.map(buildRawData(__build).default);", |
| 129 | + " },", |
| 130 | + " fromWithResolved: (${3:primaryKey}: never) => {", |
| 131 | + " const rawData = Database.transformResult(", |
| 132 | + " client.${2:modelName}.findUniqueOrThrow({", |
| 133 | + " where: { ${3:primaryKey} },", |
| 134 | + " include: includeKeys2select(includeKeys),", |
| 135 | + " }),", |
| 136 | + " )", |
| 137 | + " .mapErr(Database.dbErrorWith(metadata).transform('fromWithResolved'))", |
| 138 | + " .map(separateRawData<ThisModel, IncludeKey>(includeKeys).withResolved);", |
| 139 | + "", |
| 140 | + " return rawData.map(buildRawData(__build).withResolved);", |
| 141 | + " },", |
| 142 | + " } satisfies ModelBuilder<ThisModel>;", |
90 | 143 | " }",
|
91 | 144 | "",
|
92 |
| - "public static fromWithResolved(id /* TODO */): DatabaseResult<Member<'WITH_RESOLVED'>> {", |
93 |
| - " return Database.transformResult(", |
94 |
| - " client.member.findUniqueOrThrow({", |
95 |
| - " where: { id },", |
96 |
| - " include: includeKeys2select(includeKeys),", |
97 |
| - " }),", |
98 |
| - " )", |
99 |
| - " .mapErr(Database.dbErrorWith(metadata).transform('fromWithResolved'))", |
100 |
| - " .map(/* TODO */)", |
101 |
| - "}", |
102 |
| - "", |
103 |
| - " public resolveRelation(): DatabaseResult<SchemaResolved> {", |
| 145 | + " public resolveRelation(): ModelResolver<Mode, ThisModel> {", |
104 | 146 | " return matchWithDefault(",
|
105 | 147 | " this.__rawResolved,",
|
106 |
| - " () => Database.transformResult(", |
107 |
| - " client.${2:modelName}.findUniqueOrThrow({", |
108 |
| - " where: { ${3:primaryKey}: this.data.id },", |
109 |
| - " include: includeKeys2select(includeKeys),", |
110 |
| - " }),", |
111 |
| - " )", |
112 |
| - " .mapErr(this.dbError.transform(this.dbError.transform('resolveRelation'))", |
113 |
| - " .map(/* TODO */)", |
114 |
| - " ));", |
| 148 | + " () => $${1:ModelName}.with(this.client).fromWithResolved(this.data.${3:primaryKey}),", |
| 149 | + " );", |
115 | 150 | " }",
|
116 | 151 | "",
|
117 |
| - " public update(_operator: ModelEntityOf<$$Member>, _data: Partial<Schema>): DatabaseResult<${1:ModelName}> {", |
| 152 | + " public update(_data: Partial<Schema>): DatabaseResult<ThisModel> {", |
118 | 153 | " throw new Error('Method not implemented.');",
|
119 | 154 | " }",
|
120 | 155 | "",
|
121 |
| - " public delete(_operator: ModelEntityOf<$$Member>): DatabaseResult<void> {", |
| 156 | + " public delete(_operator: ThisModel): DatabaseResult<void> {", |
122 | 157 | " throw new Error('Method not implemented.');",
|
123 | 158 | " }",
|
124 |
| - "}) satisfies ModelGenerator<any, typeof metadata, SchemaRaw, Schema, SchemaResolvedRaw, SchemaResolved>;", |
125 | 159 | "",
|
126 |
| - "export type $${1:ModelName}<M extends ModelMode = 'DEFAULT'> = ModelGenerator<M, typeof metadata, SchemaRaw, Schema, SchemaResolvedRaw, SchemaResolved>; & typeof __${1:ModelName}<M>", |
| 160 | + " public hoge() { }", |
| 161 | + "}", |
127 | 162 | ""
|
128 | 163 | ],
|
129 | 164 | "description": ""
|
|
0 commit comments