UNPKG

prismabox

Version:

Typebox generator for prisma schema

54 lines (53 loc) 18.1 kB
#!/usr/bin/env node "use strict";var O=require("node:fs/promises"),xe=require("@prisma/generator-helper");var u=require("@sinclair/typebox"),T=require("@sinclair/typebox/value"),R=u.Type.Object({output:u.Type.String({default:"./prisma/prismabox"}),typeboxImportVariableName:u.Type.String({default:"Type"}),typeboxImportDependencyName:u.Type.String({default:"@sinclair/typebox"}),additionalProperties:u.Type.Boolean({default:!1}),inputModel:u.Type.Boolean({default:!1}),ignoreIdOnInputModel:u.Type.Boolean({default:!0}),ignoreCreatedAtOnInputModel:u.Type.Boolean({default:!0}),ignoreUpdatedAtOnInputModel:u.Type.Boolean({default:!0}),nullableName:u.Type.String({default:"__nullable__"}),allowRecursion:u.Type.Boolean({default:!0}),additionalFieldsPlain:u.Type.Optional(u.Type.Array(u.Type.String())),transformDateName:u.Type.String({default:"__transformDate__"}),useJsonTypes:u.Type.Union([u.Type.Boolean(),u.Type.Literal("transformer")],{default:!1}),importFileExtension:u.Type.String({default:""}),exportedTypePrefix:u.Type.String({default:""})},{additionalProperties:!1}),q={};function G(e){try{T.Value.Clean(R,e),T.Value.Default(R,e),q=T.Value.Decode(R,T.Value.Convert(R,e)),Object.freeze(q)}catch(t){throw console.error(T.Value.Errors(R,e).First),t}}function o(){return q}function Q(e){return e.type==="OPTIONS"}function x(e){return e.type==="TYPE_OVERWRITE"}var Me=[{type:"HIDDEN_INPUT_CREATE",keys:["@prismabox.create.input.hide","@prismabox.create.input.hidden"]},{type:"HIDDEN_INPUT_UPDATE",keys:["@prismabox.update.input.hide","@prismabox.update.input.hidden"]},{type:"HIDDEN_INPUT",keys:["@prismabox.input.hide","@prismabox.input.hidden"]},{type:"HIDDEN",keys:["@prismabox.hide","@prismabox.hidden"]},{type:"OPTIONS",keys:["@prismabox.options"]},{type:"TYPE_OVERWRITE",keys:["@prismabox.typeOverwrite"]}];function f(e){let t=[],n="",s=e??"";for(let i of s.split(` `).map(r=>r.trim()).filter(r=>r.length>0)){let r=Me.find(a=>a.keys.some(m=>i.startsWith(m)));if(r)if(r.type==="OPTIONS"){if(!i.startsWith(`${r.keys[0]}{`))throw new Error("Invalid syntax, expected opening { after prismabox.options");if(!i.endsWith("}"))throw new Error("Invalid syntax, expected closing } for prismabox.options");t.push({type:"OPTIONS",value:i.substring(r.keys[0].length+1,i.length-1)})}else if(r.type==="TYPE_OVERWRITE"){if(!i.startsWith(`${r.keys[0]}=`))throw new Error("Invalid syntax, expected = after prismabox.type");t.push({type:"TYPE_OVERWRITE",value:i.split("=")[1]})}else t.push({type:r.type});else n+=`${i} `}return n=n.trim().replaceAll("`","\\`"),{annotations:t,description:n.length>0?n:void 0,isHidden:Pe(t),isHiddenInput:Ne(t),isHiddenInputCreate:De(t),isHiddenInputUpdate:Te(t)}}function Pe(e){return e.some(t=>t.type==="HIDDEN")}function Ne(e){return e.some(t=>t.type==="HIDDEN_INPUT")}function De(e){return e.some(t=>t.type==="HIDDEN_INPUT_CREATE")}function Te(e){return e.some(t=>t.type==="HIDDEN_INPUT_UPDATE")}function p({input:e,exludeAdditionalProperties:t}={}){t===void 0&&(t=!o().additionalProperties);let n=[];for(let s of e?.annotations??[])Q(s)&&n.push(s.value);return t&&n.push(`additionalProperties: ${o().additionalProperties}`),e?.description&&n.push(`description: \`${e.description}\``),n.length>0?`{${n.join(",")}}`:""}function I(e,t=p({exludeAdditionalProperties:!0})){return`${o().typeboxImportVariableName}.Union([${e.join(",")}], ${t}) `}var c=[];function X(e){for(let t of e){let n=Oe(t);n&&c.push({name:t.name,stringRepresentation:n})}Object.freeze(c)}function Oe(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.values.map(s=>`${o().typeboxImportVariableName}.Literal('${s.name}')`);return I(n,p({input:t}))}var he=["Int","BigInt","Float","Decimal","String","DateTime","Json","Boolean","Bytes"];function b(e){return he.includes(e)}function M({fieldType:e,options:t}){if(["Int","BigInt"].includes(e))return`${o().typeboxImportVariableName}.Integer(${t})`;if(["Float","Decimal"].includes(e))return`${o().typeboxImportVariableName}.Number(${t})`;if(e==="String")return`${o().typeboxImportVariableName}.String(${t})`;if(["DateTime"].includes(e)){let n=o();if(n.useJsonTypes==="transformer")return`${o().transformDateName}(${t})`;if(n.useJsonTypes){let s=t;return s.includes("{")&&s.includes("}")?s=s.replace("{","{ format: 'date-time', "):s="{ format: 'date-time' }",`${n.typeboxImportVariableName}.String(${s})`}return`${o().typeboxImportVariableName}.Date(${t})`}if(e==="Json")return`${o().typeboxImportVariableName}.Any(${t})`;if(e==="Boolean")return`${o().typeboxImportVariableName}.Boolean(${t})`;if(e==="Bytes")return`${o().typeboxImportVariableName}.Uint8Array(${t})`;throw new Error("Invalid type for primitive generation")}function y(e,t=!1){return`${o().typeboxImportVariableName}.Partial(${e}, ${p({exludeAdditionalProperties:t})})`}var A=[];function Z(e){for(let t of e){let n=Re(t);n&&A.push({name:t.name,stringRepresentation:n})}Object.freeze(A)}function Re(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.fields.map(i=>{if(!f(i.documentation).isHidden&&!b(i.type))return`${i.name}: ${o().typeboxImportVariableName}.Boolean()`}).filter(i=>i);n.push(`_count: ${o().typeboxImportVariableName}.Boolean()`);let s=`${o().typeboxImportVariableName}.Object({${[...n].join(",")}},${p({input:t})}) `;return y(s)}var j=[];function ee(e){for(let t of e){let n=Fe(t);n&&j.push({name:t.name,stringRepresentation:n})}Object.freeze(j)}function Fe(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.fields.map(i=>{if(!f(i.documentation).isHidden&&b(i.type))return`${i.name}: ${I([`${o().typeboxImportVariableName}.Literal('asc')`,`${o().typeboxImportVariableName}.Literal('desc')`])}`}).filter(i=>i),s=`${o().typeboxImportVariableName}.Object({${[...n].join(",")}},${p({input:t})}) `;return y(s)}function $(e){return`${o().typeboxImportVariableName}.Array(${e}, ${p({exludeAdditionalProperties:!0})})`}function te(){return`import { ${o().typeboxImportVariableName}, type TSchema } from "${o().typeboxImportDependencyName}" export const ${o().nullableName} = <T extends TSchema>(schema: T) => ${o().typeboxImportVariableName}.Union([${o().typeboxImportVariableName}.Null(), schema]) `}function ne(){return`import { ${o().nullableName} } from "./${o().nullableName}${o().importFileExtension}" `}function w(e){return`${o().nullableName}(${e})`}function L(e){return`${o().typeboxImportVariableName}.Optional(${e})`}var P=[];function oe(e){for(let t of e){let n=F(t);n&&P.push({name:t.name,stringRepresentation:n})}Object.freeze(P)}function F(e,t=!1,n=!1){let s=f(e.documentation);if(s.isHidden||(t||n)&&s.isHiddenInput||t&&s.isHiddenInputCreate||n&&s.isHiddenInputUpdate)return;let i=e.fields.map(r=>{let a=f(r.documentation);if(a.isHidden||(t||n)&&a.isHiddenInput||t&&a.isHiddenInputCreate||n&&a.isHiddenInputUpdate||o().ignoreIdOnInputModel&&(t||n)&&r.isId||o().ignoreCreatedAtOnInputModel&&(t||n)&&r.name==="createdAt"&&r.hasDefaultValue||o().ignoreUpdatedAtOnInputModel&&(t||n)&&r.isUpdatedAt||(t||n)&&(r.name.toLowerCase().endsWith("id")||r.name.toLowerCase().endsWith("foreign")||r.name.toLowerCase().endsWith("foreignkey")))return;let m="";if(b(r.type)){let l=a.annotations.filter(x).at(0)?.value;l?m=l:m=M({fieldType:r.type,options:p({input:a,exludeAdditionalProperties:!1})})}else if(c.find(l=>l.name===r.type))m=c.find(l=>l.name===r.type).stringRepresentation;else return;r.isList&&(m=$(m));let d=!1;return r.isRequired||(m=w(m)),(n||t&&!r.isRequired&&!r.hasDefaultValue)&&(m=L(m),d=!0),!d&&r.hasDefaultValue&&(t||n)&&(m=L(m),d=!0),`${r.name}: ${m}`}).filter(r=>r);return`${o().typeboxImportVariableName}.Object({${[...i,t||n?[]:o().additionalFieldsPlain??[]].join(",")}},${p({input:s})}) `}var U=[];function re(e){for(let t of e){let n=F(t,!0,!1);n&&U.push({name:t.name,stringRepresentation:n})}Object.freeze(U)}var C=[];function ie(e){for(let t of e){let n=F(t,!1,!0);n&&C.push({name:t.name,stringRepresentation:n})}Object.freeze(C)}var V=[];function ae(e){for(let t of e){let n=Ve(t);n&&V.push({name:t.name,stringRepresentation:n})}Object.freeze(V)}function Ve(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.fields.map(s=>{if(f(s.documentation).isHidden||b(s.type)||c.find(a=>a.name===s.type))return;let r=P.find(a=>a.name===s.type)?.stringRepresentation;if(r)return s.isList&&(r=$(r)),s.isRequired||(r=w(r)),`${s.name}: ${r}`}).filter(s=>s);return`${o().typeboxImportVariableName}.Object({${n.join(",")}},${p({input:t})}) `}var E=[];function se(e){for(let t of e){let n=Ee(t,e);n&&E.push({name:t.name,stringRepresentation:n})}Object.freeze(E)}function Ee(e,t){let n=f(e.documentation);if(n.isHidden||n.isHiddenInput||n.isHiddenInputCreate)return;let s=e.fields.map(i=>{let r=f(i.documentation);if(r.isHidden||r.isHiddenInput||r.isHiddenInputCreate||b(i.type)||c.find(l=>l.name===i.type))return;let a="String";switch(t.find(l=>l.name===i.type)?.fields.find(l=>l.isId)?.type){case"String":a="String";break;case"Int":a="Integer";break;case"BigInt":a="Integer";break;default:throw new Error(`Unsupported ID type: ${i.type} on model ${e.name} in relation ${i.name}`)}let m=`${o().typeboxImportVariableName}.Object({ id: ${o().typeboxImportVariableName}.${a}(${p({input:r})}), },${p({input:r})})`;i.isList&&(m=$(m));let d=`${o().typeboxImportVariableName}.Object({ connect: ${m}, }, ${p()})`;return(!i.isRequired||i.isList)&&(d=`${o().typeboxImportVariableName}.Optional(${d})`),`${i.name}: ${d}`}).filter(i=>i);return`${o().typeboxImportVariableName}.Object({${s.join(",")}},${p({input:n})}) `}var H=[];function pe(e){for(let t of e){let n=He(t,e);n&&H.push({name:t.name,stringRepresentation:n})}Object.freeze(H)}function He(e,t){let n=f(e.documentation);if(n.isHidden||n.isHiddenInput||n.isHiddenInputUpdate)return;let s=e.fields.map(i=>{let r=f(i.documentation);if(r.isHidden||r.isHiddenInput||r.isHiddenInputUpdate||b(i.type)||c.find(d=>d.name===i.type))return;let a="String";switch(t.find(d=>d.name===i.type)?.fields.find(d=>d.isId)?.type){case"String":a="String";break;case"Int":a="Integer";break;case"BigInt":a="Integer";break;default:throw new Error(`Unsupported ID type: ${i.type} on model ${e.name} in relation ${i.name}`)}let m;return i.isList?m=y(`${o().typeboxImportVariableName}.Object({ connect: ${$(`${o().typeboxImportVariableName}.Object({ id: ${o().typeboxImportVariableName}.${a}(${p({input:r})}) }, ${p({input:r})})`)}, disconnect: ${$(`${o().typeboxImportVariableName}.Object({ id: ${o().typeboxImportVariableName}.${a}(${p({input:r})}) }, ${p({input:r})})`)} }, ${p({input:r})})`):i.isRequired?m=`${o().typeboxImportVariableName}.Object({ connect: ${o().typeboxImportVariableName}.Object({ id: ${o().typeboxImportVariableName}.${a}(${p({input:r})}) }, ${p({input:r})}) }, ${p({input:r})})`:m=y(`${o().typeboxImportVariableName}.Object({ connect: ${o().typeboxImportVariableName}.Object({ id: ${o().typeboxImportVariableName}.${a}(${p({input:r})}) }, ${p({input:r})}), disconnect: ${o().typeboxImportVariableName}.Boolean() }, ${p({input:r})})`),`${i.name}: ${m}`}).filter(i=>i);return y(`${o().typeboxImportVariableName}.Object({${s.join(",")}},${p({input:n})})`)}var S=[];function me(e){for(let t of e){let n=ve(t);n&&S.push({name:t.name,stringRepresentation:n})}Object.freeze(S)}function ve(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.fields.map(i=>{if(!f(i.documentation).isHidden)return`${i.name}: ${o().typeboxImportVariableName}.Boolean()`}).filter(i=>i);n.push(`_count: ${o().typeboxImportVariableName}.Boolean()`);let s=`${o().typeboxImportVariableName}.Object({${[...n].join(",")}},${p({input:t})}) `;return y(s)}function z(e,t=p({exludeAdditionalProperties:!0})){return`${o().typeboxImportVariableName}.Intersect([${e.join(",")}], ${t}) `}var N="Self",_=[];function de(e){for(let t of e){let n=Ae(t);n&&_.push({name:t.name,stringRepresentation:n})}Object.freeze(_)}function Ae(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.fields.map(s=>{let i=f(s.documentation);if(i.isHidden)return;let r="";if(b(s.type)){let a=i.annotations.filter(x).at(0)?.value;a?r=a:r=M({fieldType:s.type,options:p({exludeAdditionalProperties:!1,input:i})})}else if(c.find(a=>a.name===s.type))r=c.find(a=>a.name===s.type).stringRepresentation;else return;return s.isList&&(r=$(r)),`${s.name}: ${r}`}).filter(s=>s);return o().allowRecursion?y(`${o().typeboxImportVariableName}.Recursive(${N} =>${o().typeboxImportVariableName}.Object({${fe()},${n.join(",")}},${p({exludeAdditionalProperties:!0,input:t})}), { $id: "${e.name}"})`):y(`${o().typeboxImportVariableName}.Object({${n.join(",")}},${p({exludeAdditionalProperties:!0,input:t})})`)}var W=[];function le(e){for(let t of e){let n=je(t);n&&W.push({name:t.name,stringRepresentation:n})}Object.freeze(W)}function je(e){let t=f(e.documentation);if(t.isHidden)return;let n=e.uniqueFields.map(a=>{let m=a.join("_"),l=a.map(g=>e.fields.find(h=>h.name===g)).map(g=>{let h=f(g.documentation);if(h.isHidden)return;let v="";if(b(g.type)){let D=h.annotations.filter(x).at(0)?.value;D?v=D:v=M({fieldType:g.type,options:p({exludeAdditionalProperties:!1,input:h})})}else if(c.find(D=>D.name===g.type))v=c.find(D=>D.name===g.type).stringRepresentation;else throw new Error("Invalid type for unique composite generation");return`${g.name}: ${v}`}),Ie=`${o().typeboxImportVariableName}.Object({${l.join(",")}}, ${p({exludeAdditionalProperties:!0})})`;return`${m}: ${Ie}`}),s=e.fields.map(a=>{let m=f(a.documentation);if(m.isHidden)return;let d="";if(b(a.type)){let l=m.annotations.filter(x).at(0)?.value;l?d=l:d=M({fieldType:a.type,options:p({exludeAdditionalProperties:!1,input:m})})}else if(c.find(l=>l.name===a.type))d=c.find(l=>l.name===a.type).stringRepresentation;else return;return a.isList&&(d=$(d)),`${a.name}: ${d}`}).filter(a=>a),i=e.fields.map(a=>{let m=f(a.documentation);if(m.isHidden||!a.isUnique&&!a.isId)return;let d="";if(b(a.type)){let l=m.annotations.filter(x).at(0)?.value;l?d=l:d=M({fieldType:a.type,options:p({exludeAdditionalProperties:!1,input:m})})}else if(c.find(l=>l.name===a.type))d=c.find(l=>l.name===a.type).stringRepresentation;else return;return a.isList&&(d=$(d)),`${a.name}: ${d}`}).filter(a=>a),r=`${o().typeboxImportVariableName}.Object({${[...i,...n].join(",")}},${p({exludeAdditionalProperties:!0,input:t})})`;return o().allowRecursion?`${o().typeboxImportVariableName}.Recursive(${N} => ${z([y(r,!0),I([...i,...n].map(a=>`${o().typeboxImportVariableName}.Object({${a}})`)),y(`${o().typeboxImportVariableName}.Object({${fe()}})`,!0),y(`${o().typeboxImportVariableName}.Object({${s.join(",")}}, ${p()})`)])}, { $id: "${e.name}"})`:z([y(r,!0),I([...i,...n].map(a=>`${o().typeboxImportVariableName}.Object({${a}})`)),y(`${o().typeboxImportVariableName}.Object({${s.join(",")}})`)])}function fe(){return`AND: ${o().typeboxImportVariableName}.Union([${N}, ${$(N)}]), NOT: ${o().typeboxImportVariableName}.Union([${N}, ${$(N)}]), OR: ${$(N)}`}var J=require("node:fs/promises"),K=require("node:path");function ue(e){return e.map(t=>`export * from "./${t}${o().importFileExtension}";`).join(` `)}var ce=require("prettier");async function Y(e){try{return await(0,ce.format)(e,{parser:"typescript"})}catch(t){return console.error("Error formatting file",t),e}}function ye(){return`import { ${o().typeboxImportVariableName} } from "${o().typeboxImportDependencyName}"; export const ${o().transformDateName} = (options?: Parameters<typeof ${o().typeboxImportVariableName}.String>[0]) => ${o().typeboxImportVariableName}.Transform(${o().typeboxImportVariableName}.String({ format: 'date-time', ...options })) .Decode((value) => new Date(value)) .Encode((value) => value.toISOString()) `}function be(){return`import { ${o().transformDateName} } from "./${o().transformDateName}${o().importFileExtension}" `}function k(e){return`${o().typeboxImportVariableName}.Composite([${e.map(t=>`${o().exportedTypePrefix}${t}`).join(",")}], ${p()}) `}function B(e){return`export const ${o().exportedTypePrefix}${e.name} = ${e.stringRepresentation} `}function we(){return`import { ${o().typeboxImportVariableName} } from "${o().typeboxImportDependencyName}" `}function $e(){let e=new Map,t=(n,s)=>{for(let i of n){let r=B({...i,name:`${i.name}${s}`}),a=e.get(i.name);a?e.set(i.name,`${a} ${r}`):e.set(i.name,r)}};t(c,""),t(P,"Plain"),t(V,"Relations"),t(U,"PlainInputCreate"),t(C,"PlainInputUpdate"),t(E,"RelationsInputCreate"),t(H,"RelationsInputUpdate"),t(_,"Where"),t(W,"WhereUnique"),t(S,"Select"),t(A,"Include"),t(j,"OrderBy");for(let[n,s]of e){let i=P.find(m=>m.name===n),r=V.find(m=>m.name===n),a;if(i&&r)a=k([`${n}Plain`,`${n}Relations`]);else if(i)a=`${n}Plain`;else if(r)a=`${n}Relations`;else continue;e.set(n,`${s} ${B({name:n,stringRepresentation:a})}`)}for(let[n,s]of e)if(E.find(r=>r.name===n)){let r=k([`${n}PlainInputCreate`,`${n}RelationsInputCreate`]);e.set(n,`${s} ${B({name:`${n}InputCreate`,stringRepresentation:r})}`)}for(let[n,s]of e)if(H.find(r=>r.name===n)){let r=k([`${n}PlainInputUpdate`,`${n}RelationsInputUpdate`]);e.set(n,`${s} ${B({name:`${n}InputUpdate`,stringRepresentation:r})}`)}for(let[n,s]of e)e.set(n,`${we()} ${be()} ${ne()} ${s}`);return e.set(o().nullableName,te()),e.set(o().transformDateName,ye()),e}async function ge(){let e=Array.from($e().entries());return Promise.all([...e.map(async([t,n])=>(0,J.writeFile)((0,K.join)(o().output,`${t}.ts`),await Y(n))),(0,J.writeFile)((0,K.join)(o().output,"barrel.ts"),await Y(ue(e.map(([t])=>t))))])}(0,xe.generatorHandler)({onManifest(){return{defaultOutput:"./prismabox",prettyName:"prismabox"}},async onGenerate(e){G({...e.generator.config,output:e.generator.output?.value});try{await(0,O.access)(o().output),await(0,O.rm)(o().output,{recursive:!0})}catch{}await(0,O.mkdir)(o().output,{recursive:!0}),X(e.dmmf.datamodel.enums),oe(e.dmmf.datamodel.models),ae(e.dmmf.datamodel.models),de(e.dmmf.datamodel.models),le(e.dmmf.datamodel.models),o().inputModel&&(re(e.dmmf.datamodel.models),ie(e.dmmf.datamodel.models),se(e.dmmf.datamodel.models),pe(e.dmmf.datamodel.models)),me(e.dmmf.datamodel.models),Z(e.dmmf.datamodel.models),ee(e.dmmf.datamodel.models),await ge()}});