prisma-effect-schema 0.1.2 → 0.1.4

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/bin.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-FMT4NBCL.js";
3
- import "./chunk-25MM3WYP.js";
2
+ import "./chunk-4XK2MZLU.js";
3
+ import "./chunk-EB2BVI3Q.js";
4
4
  //# sourceMappingURL=bin.js.map
@@ -2,7 +2,7 @@ import {
2
2
  NoOutputConfiguredError,
3
3
  generate,
4
4
  parseConfig
5
- } from "./chunk-25MM3WYP.js";
5
+ } from "./chunk-EB2BVI3Q.js";
6
6
 
7
7
  // src/generator.ts
8
8
  import { FileSystem } from "@effect/platform";
@@ -52,4 +52,4 @@ generatorHelper.generatorHandler({
52
52
  Effect.runPromise
53
53
  )
54
54
  });
55
- //# sourceMappingURL=chunk-FMT4NBCL.js.map
55
+ //# sourceMappingURL=chunk-4XK2MZLU.js.map
@@ -88,7 +88,7 @@ var UnsupportedTypeError = class extends Schema2.TaggedError()(
88
88
  ) {
89
89
  get message() {
90
90
  return dedent`
91
- ${AppTag} Unsupported Prisma type "${this.typeName}" for field "${this.fieldName}" in model "${this.modelName}".
91
+ ${AppTag} Unsupported Prisma type "${this.typeName}" for field "${this.fieldName}" in model "${this.modelName}".
92
92
  Please open an issue at https://github.com/frontcore/prisma-effect-schema/issues
93
93
  `;
94
94
  }
@@ -281,7 +281,6 @@ var sectionHeader = (title) => dedent2`
281
281
  // ============================================================================
282
282
  // ${title}
283
283
  // ============================================================================
284
-
285
284
  `;
286
285
  var ByName = () => Order.mapInput(Order.string, (item) => item.name);
287
286
  var sortByName = (items) => Arr3.sort(items, ByName());
@@ -298,9 +297,9 @@ var generateEnumSchema = (enumDef) => {
298
297
  };
299
298
  var generateEnumSchemas = (enums) => pipe3(sortByName(enums), Arr3.map(generateEnumSchema), Arr3.join("\n"));
300
299
  var generateBrandedIdSchema = ([, brandedIdName]) => dedent2`
301
- export const ${brandedIdName} = Schema.String.pipe(Schema.brand("${brandedIdName}"))
302
- export type ${brandedIdName} = typeof ${brandedIdName}.Type
303
- `;
300
+ export const ${brandedIdName} = Schema.String.pipe(Schema.brand("${brandedIdName}"))
301
+ export type ${brandedIdName} = typeof ${brandedIdName}.Type
302
+ `;
304
303
  var generateBrandedIdSchemas = (brandedIds) => pipe3(
305
304
  brandedIds,
306
305
  HashMap2.toEntries,
@@ -321,12 +320,12 @@ var generateModelSchema = (model, resolver, config) => {
321
320
  resolver,
322
321
  config.sortFields
323
322
  );
324
- const baseSchema = dedent2`
325
- export const ${model.name} = Schema.Struct({
326
- ${scalarFieldsCode}
327
- })
328
- export type ${model.name} = typeof ${model.name}.Type
329
- `;
323
+ const baseSchema = [
324
+ `export const ${model.name} = Schema.Struct({`,
325
+ scalarFieldsCode,
326
+ `})`,
327
+ `export type ${model.name} = typeof ${model.name}.Type`
328
+ ].join("\n");
330
329
  if (!config.includeRelations || !hasRelations) {
331
330
  return baseSchema;
332
331
  }
@@ -335,14 +334,15 @@ var generateModelSchema = (model, resolver, config) => {
335
334
  resolver,
336
335
  config.sortFields
337
336
  );
338
- return dedent2`
339
- ${baseSchema}
337
+ const withRelationsSchema = [
338
+ `export const ${model.name}WithRelations = Schema.Struct({`,
339
+ allFieldsCode,
340
+ `})`,
341
+ `export type ${model.name}WithRelations = typeof ${model.name}WithRelations.Type`
342
+ ].join("\n");
343
+ return `${baseSchema}
340
344
 
341
- export const ${model.name}WithRelations = Schema.Struct({
342
- ${allFieldsCode}
343
- })
344
- export type ${model.name}WithRelations = typeof ${model.name}WithRelations.Type
345
- `;
345
+ ${withRelationsSchema}`;
346
346
  };
347
347
  var generateModelSchemas = (models, makeResolver, config) => pipe3(
348
348
  sortByName(models),
@@ -370,13 +370,13 @@ var generate = (input) => {
370
370
  // Enums
371
371
  ...enums.length > 0 ? [sectionHeader("Enums"), generateEnumSchemas(enums)] : [],
372
372
  // Branded IDs
373
- ...brandedIdCount > 0 ? [sectionHeader("Branded IDs"), generateBrandedIdSchemas(brandedIds), ""] : [],
373
+ ...brandedIdCount > 0 ? [sectionHeader("Branded IDs"), generateBrandedIdSchemas(brandedIds)] : [],
374
374
  // Models
375
375
  sectionHeader("Models (scalar fields only)"),
376
376
  generateModelSchemas(models, makeResolver, config)
377
377
  ];
378
378
  return {
379
- content: sections.join(""),
379
+ content: sections.join("\n"),
380
380
  stats: {
381
381
  enumCount: enums.length,
382
382
  modelCount: models.length,
@@ -413,4 +413,4 @@ export {
413
413
  generateModelSchemas,
414
414
  generate
415
415
  };
416
- //# sourceMappingURL=chunk-25MM3WYP.js.map
416
+ //# sourceMappingURL=chunk-EB2BVI3Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/emit.ts","../src/resolver.ts","../src/templates.ts","../src/generate.ts"],"sourcesContent":["import type { GeneratorOptions } from \"@prisma/generator-helper\";\nimport { Array as Arr, Option, pipe, Schema } from \"effect\";\n\n/**\n * Prisma config values can be string | string[] - normalize to first string\n */\nconst firstString = (value: string | readonly string[]): Option.Option<string> =>\n pipe(value, Arr.ensure, Arr.head);\n\n/**\n * Schema for parsing \"true\"/\"false\" strings to booleans (handles string | string[])\n */\nconst BooleanFromString = Schema.transform(\n Schema.Union(Schema.String, Schema.Array(Schema.String)),\n Schema.Boolean,\n {\n decode: (value) => pipe(value, firstString, Option.map((s) => s === \"true\"), Option.getOrElse(() => false)),\n encode: (b) => (b ? \"true\" : \"false\"),\n }\n);\n\n/**\n * Schema for DateTime handling mode (handles string | string[])\n */\nconst DateTimeHandling = Schema.transform(\n Schema.Union(Schema.String, Schema.Array(Schema.String)),\n Schema.Literal(\"Date\", \"DateTimeString\"),\n {\n decode: (value) =>\n pipe(\n value,\n firstString,\n Option.filter((s) => s === \"DateTimeString\"),\n Option.map(() => \"DateTimeString\" as const),\n Option.getOrElse(() => \"Date\" as const)\n ),\n encode: (s) => s,\n }\n);\n\n/**\n * Generator configuration schema with defaults.\n * Parses Prisma generator config and applies defaults in one step.\n */\nexport const GeneratorConfigSchema = Schema.Struct({\n /**\n * Whether to include relation fields in the generated schemas.\n * Relations use Schema.suspend() for lazy evaluation to handle circular deps.\n * @default false\n */\n includeRelations: Schema.optionalWith(BooleanFromString, {\n default: () => false,\n }),\n\n /**\n * Whether to generate branded ID types for models with string IDs.\n * When true, generates `UserId`, `PostId`, etc. and uses them in model schemas.\n * @default true\n */\n useBrandedIds: Schema.optionalWith(BooleanFromString, {\n default: () => true,\n }),\n\n /**\n * How to handle DateTime fields.\n * - 'Date': Use Schema.Date (expects Date objects, for Prisma results)\n * - 'DateTimeString': Use Schema.Date with dateTime annotation (for API validation)\n * @default 'Date'\n */\n dateTimeHandling: Schema.optionalWith(DateTimeHandling, {\n default: () => \"Date\" as const,\n }),\n\n /**\n * Whether to sort fields alphabetically for deterministic output.\n * @default true\n */\n sortFields: Schema.optionalWith(BooleanFromString, {\n default: () => true,\n }),\n\n /**\n * Custom header to prepend to the generated file.\n * If not provided, uses a default header without timestamps.\n */\n customHeader: Schema.optionalWith(\n Schema.transform(\n Schema.Union(Schema.String, Schema.Array(Schema.String)),\n Schema.NullOr(Schema.String),\n {\n decode: (value) => pipe(value, firstString, Option.getOrElse(() => null as string | null)),\n encode: (s) => s ?? \"\",\n }\n ),\n { default: () => null }\n ),\n});\n\n/**\n * Resolved configuration type (derived from schema)\n */\nexport type GeneratorConfig = typeof GeneratorConfigSchema.Type;\n\n\n\n/**\n * Parse generator config from Prisma schema using Effect Schema\n */\nexport const parseConfig = (options: GeneratorOptions) =>\n Schema.decodeUnknown(GeneratorConfigSchema)(options.generator.config);\n","import dedent from \"dedent\";\nimport { Schema } from \"effect\";\n\nexport const AppTag = \"[prisma-effect-schema]\";\n\n/**\n * Error thrown when an unsupported Prisma type is encountered\n */\nexport class UnsupportedTypeError extends Schema.TaggedError<UnsupportedTypeError>()(\n \"UnsupportedTypeError\",\n {\n typeName: Schema.String,\n fieldName: Schema.String,\n modelName: Schema.String,\n },\n) {\n override get message(): string {\n return dedent`\n ${AppTag} Unsupported Prisma type \"${this.typeName}\" for field \"${this.fieldName}\" in model \"${this.modelName}\".\n Please open an issue at https://github.com/frontcore/prisma-effect-schema/issues\n `;\n }\n}\n\nexport class NoOutputConfiguredError extends Schema.TaggedError<NoOutputConfiguredError>()(\n \"NoOutputConfiguredError\",\n {\n cause: Schema.Unknown,\n details: Schema.String,\n },\n) {\n public static message = `${AppTag} No output path specified in generator config`;\n}\n\nexport const ConfigError = NoOutputConfiguredError;\n","/**\n * Code Emission Module\n *\n * Pure functions for transforming resolved types into Effect Schema strings.\n * Separated from resolution logic for testability and reusability.\n */\nimport { Match } from \"effect\";\nimport type { BaseType, ResolvedType, Wrapper } from \"./resolver.js\";\n\n/**\n * Emit a base type to its Effect Schema string representation\n */\nexport const emitBaseType = (base: BaseType): string =>\n Match.value(base).pipe(\n Match.tag(\"Primitive\", ({ schema }) =>\n schema === \"Json\" ? \"JsonValueSchema\" : `Schema.${schema}`\n ),\n Match.tag(\"BrandedId\", ({ name }) => name),\n Match.tag(\"Enum\", ({ name }) => name),\n Match.tag(\"Relation\", ({ modelName }) => `Schema.suspend(() => ${modelName})`),\n Match.exhaustive\n );\n\n/**\n * Apply a single wrapper to a schema string\n */\nexport const applyWrapper = (inner: string, wrapper: Wrapper): string => {\n switch (wrapper) {\n case \"Array\":\n return `Schema.Array(${inner})`;\n case \"NullOr\":\n return `Schema.NullOr(${inner})`;\n }\n};\n\n/**\n * Emit a fully resolved type (base + wrappers) to Effect Schema string.\n * Wrappers are applied left-to-right (innermost first).\n */\nexport const emit = (type: ResolvedType): string =>\n type.wrappers.reduce(applyWrapper, emitBaseType(type.base));\n","/**\n * Type Resolution Module\n *\n * Separates the \"thinking\" (what type should this field be?) from the \"writing\"\n * (how do we emit it as a string?). Returns structured data that can be tested,\n * logged, and transformed before emission.\n */\nimport type { DMMF } from \"@prisma/generator-helper\";\nimport {\n Array as Arr,\n Data,\n HashMap,\n Option,\n pipe,\n Record,\n} from \"effect\";\nimport { capitalize } from \"effect/String\";\nimport type { GeneratorConfig } from \"./config.js\";\nimport { emit } from \"./emit.js\";\nimport { UnsupportedTypeError } from \"./errors.js\";\n\n// ============================================================================\n// Resolved Types (Data.TaggedClass for structural equality + pattern matching)\n// ============================================================================\n\n/**\n * A primitive scalar type from Prisma mapped to Effect Schema\n */\nexport class Primitive extends Data.TaggedClass(\"Primitive\")<{\n readonly schema:\n | \"Int\"\n | \"String\"\n | \"Boolean\"\n | \"Number\"\n | \"Date\" // Schema.Date - for Prisma results (Date objects)\n | \"DateTimeUtc\" // Schema.DateTimeUtc - for API validation (ISO strings)\n | \"BigInt\"\n | \"Uint8Array\"\n | \"Json\"\n | \"Decimal\";\n}> {}\n\n/**\n * A branded ID type for type-safe IDs\n */\nexport class BrandedId extends Data.TaggedClass(\"BrandedId\")<{\n readonly name: string;\n}> {}\n\n/**\n * An enum type reference\n */\nexport class Enum extends Data.TaggedClass(\"Enum\")<{\n readonly name: string;\n}> {}\n\n/**\n * A relation to another model (uses Schema.suspend for circular refs)\n */\nexport class Relation extends Data.TaggedClass(\"Relation\")<{\n readonly modelName: string;\n}> {}\n\n/**\n * Union of all possible base types a field can resolve to\n */\nexport type BaseType = Primitive | BrandedId | Enum | Relation;\n\n/**\n * Wrappers that can be applied to a base type\n */\nexport type Wrapper = \"Array\" | \"NullOr\";\n\n/**\n * A fully resolved field type: base type + wrappers to apply\n */\nexport class ResolvedType extends Data.Class<{\n readonly base: BaseType;\n readonly wrappers: readonly Wrapper[];\n}> {}\n\n// ============================================================================\n// SchemaResolver Interface\n// ============================================================================\n\nexport interface SchemaResolver {\n /**\n * Resolve a field to its structured type representation.\n * Use this for testing or when you need to inspect the decision.\n */\n readonly resolve: (field: DMMF.Field) => ResolvedType;\n\n /**\n * Convenience method: resolve + emit in one call.\n * Use this for the common case where you just need the string.\n */\n readonly fieldToSchema: (field: DMMF.Field) => string;\n\n /**\n * The computed branded IDs map (modelName -> brandedIdName).\n * Exposed for generating branded ID schema declarations.\n */\n readonly brandedIds: HashMap.HashMap<string, string>;\n}\n\n// ============================================================================\n// Internal: Scalar Type Mapping\n// ============================================================================\n\ntype PrimitiveSchema = Primitive[\"schema\"];\n\n/**\n * Maps Prisma scalar types to Primitive schema names.\n * Note: String is handled separately (may become BrandedId).\n * Note: DateTime is handled separately (respects dateTimeHandling config).\n */\nconst ScalarTypeMap: Record.ReadonlyRecord<string, PrimitiveSchema> = {\n Int: \"Int\",\n Float: \"Number\",\n Boolean: \"Boolean\",\n Json: \"Json\",\n Bytes: \"Uint8Array\",\n BigInt: \"BigInt\",\n Decimal: \"Decimal\",\n};\n\n// ============================================================================\n// Branded ID Collection (uses actual PK field name for suffix)\n// ============================================================================\n\n/**\n * Collects branded IDs for models with string primary keys.\n * Uses the actual PK field name for the suffix:\n * - User.id (String @id) -> \"UserId\"\n * - Course.slug (String @id) -> \"CourseSlug\"\n */\nexport const collectBrandedIds = (\n models: readonly DMMF.Model[]\n): HashMap.HashMap<string, string> =>\n pipe(\n models,\n Arr.filterMap((model) => {\n const pkField = model.fields.find((f) => f.isId && f.type === \"String\");\n if (!pkField) return Option.none();\n \n // Use the PK field name, capitalized: \"id\" -> \"Id\", \"slug\" -> \"Slug\"\n const suffix = capitalize(pkField.name);\n return Option.some([model.name, `${model.name}${suffix}`] as const);\n }),\n HashMap.fromIterable\n );\n\n// ============================================================================\n// Foreign Key Map (relation-based, not heuristic)\n// ============================================================================\n\n/**\n * Builds a map from FK field names to their target model names.\n * Uses DMMF relation metadata (relationFromFields) for accuracy.\n * \n * Example output:\n * {\n * \"userId\": \"User\",\n * \"authorId\": \"User\",\n * \"courseSlug\": \"Course\",\n * \"avatarId\": \"File\"\n * }\n */\nexport const buildForeignKeyMap = (\n models: readonly DMMF.Model[]\n): HashMap.HashMap<string, string> =>\n pipe(\n models,\n Arr.flatMap((model) =>\n pipe(\n model.fields,\n Arr.filter((field) => field.kind === \"object\"),\n Arr.flatMap((relationField) => {\n // relationFromFields contains the FK field names for this relation\n const fkFields = relationField.relationFromFields ?? [];\n // The relation's type is the target model name\n const targetModel = relationField.type;\n \n return fkFields.map((fkField) => [fkField, targetModel] as const);\n })\n )\n ),\n HashMap.fromIterable\n );\n\n// ============================================================================\n// SchemaResolver Factory\n// ============================================================================\n\nexport interface SchemaResolverConfig {\n readonly modelName: string;\n readonly brandedIds: HashMap.HashMap<string, string>;\n readonly foreignKeys: HashMap.HashMap<string, string>;\n readonly config: GeneratorConfig;\n}\n\n/**\n * Create a SchemaResolver for a specific model.\n * Dependencies are captured at construction time.\n */\nexport const SchemaResolver = {\n make: (resolverConfig: SchemaResolverConfig): SchemaResolver => {\n const { modelName, brandedIds, foreignKeys, config } = resolverConfig;\n\n // ========================================================================\n // Branded ID Resolution (relation-based)\n // ========================================================================\n\n const resolveBrandedId = (field: DMMF.Field): Option.Option<string> => {\n if (!config.useBrandedIds) return Option.none();\n\n // Primary key uses this model's branded ID\n if (field.isId) {\n return HashMap.get(brandedIds, modelName);\n }\n\n // Foreign key - look up in FK map, then get target model's branded ID\n return pipe(\n HashMap.get(foreignKeys, field.name),\n Option.flatMap((targetModel) => HashMap.get(brandedIds, targetModel))\n );\n };\n\n // ========================================================================\n // Base Type Resolution\n // ========================================================================\n\n const resolveScalarType = (field: DMMF.Field): BaseType => {\n // Handle DateTime with config\n if (field.type === \"DateTime\") {\n return new Primitive({\n schema: config.dateTimeHandling === \"DateTimeString\" ? \"DateTimeUtc\" : \"Date\",\n });\n }\n\n // Check non-String scalar types\n const mapping = Record.get(ScalarTypeMap, field.type);\n if (Option.isSome(mapping)) {\n return new Primitive({ schema: mapping.value });\n }\n\n // String type: try branded ID, fallback to Primitive String\n if (field.type === \"String\") {\n return pipe(\n resolveBrandedId(field),\n Option.match({\n onNone: () => new Primitive({ schema: \"String\" }),\n onSome: (name) => new BrandedId({ name }),\n })\n );\n }\n\n throw new UnsupportedTypeError({\n typeName: field.type,\n fieldName: field.name,\n modelName,\n });\n };\n\n const resolveBaseType = (field: DMMF.Field): BaseType => {\n switch (field.kind) {\n case \"enum\":\n return new Enum({ name: field.type });\n case \"object\":\n return new Relation({ modelName: field.type });\n default:\n return resolveScalarType(field);\n }\n };\n\n // ========================================================================\n // Full Resolution (base + wrappers)\n // ========================================================================\n\n const resolve = (field: DMMF.Field): ResolvedType => {\n const wrappers: Wrapper[] = [];\n\n if (field.isList) {\n wrappers.push(\"Array\");\n }\n\n if (!field.isRequired) {\n wrappers.push(\"NullOr\");\n }\n\n return new ResolvedType({\n base: resolveBaseType(field),\n wrappers,\n });\n };\n\n const fieldToSchema = (field: DMMF.Field): string => emit(resolve(field));\n\n return {\n resolve,\n fieldToSchema,\n brandedIds,\n };\n },\n};\n","/**\n * Code Templates Module\n *\n * String templates for generating Effect Schema source code.\n * Separated from orchestration logic for clarity and testability.\n */\nimport type { DMMF } from \"@prisma/generator-helper\";\nimport dedent from \"dedent\";\nimport { Array as Arr, HashMap, Order, pipe } from \"effect\";\nimport type { GeneratorConfig } from \"./config.js\";\nimport type { SchemaResolver } from \"./resolver.js\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nexport const DEFAULT_HEADER = dedent`\n // This file was auto-generated by prisma-effect-schema\n // Do not edit manually - changes will be overwritten\n // https://github.com/frontcore/prisma-effect-schema\n\n import { Schema } from \"effect\"\n`;\n\nexport const JSON_VALUE_SCHEMA = dedent`\n // Recursive JSON value schema matching Prisma's JsonValue type\n type JsonValue = string | number | boolean | null | JsonArray | JsonObject\n type JsonArray = ReadonlyArray<JsonValue>\n type JsonObject = { readonly [key: string]: JsonValue }\n\n const JsonValueSchema: Schema.Schema<JsonValue> = Schema.suspend(\n (): Schema.Schema<JsonValue> =>\n Schema.Union(\n Schema.Null,\n Schema.Boolean,\n Schema.Number,\n Schema.String,\n Schema.Array(JsonValueSchema),\n Schema.Record({ key: Schema.String, value: JsonValueSchema })\n )\n )\n`;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nexport const sectionHeader = (title: string): string => dedent`\n // ============================================================================\n // ${title}\n // ============================================================================\n`;\n\nconst ByName = <T extends { name: string }>(): Order.Order<T> =>\n Order.mapInput(Order.string, (item: T) => item.name);\n\nconst sortByName = <T extends { name: string }>(items: readonly T[]): T[] =>\n Arr.sort(items, ByName());\n\n// ============================================================================\n// Enum Templates\n// ============================================================================\n\nexport const generateEnumSchema = (enumDef: DMMF.DatamodelEnum): string => {\n const values = pipe(\n sortByName(enumDef.values),\n Arr.map((v) => `\"${v.name}\"`),\n Arr.join(\", \")\n );\n\n return dedent`\n export const ${enumDef.name} = Schema.Literal(${values})\n export type ${enumDef.name} = typeof ${enumDef.name}.Type\n `;\n};\n\nexport const generateEnumSchemas = (\n enums: readonly DMMF.DatamodelEnum[]\n): string =>\n pipe(sortByName(enums), Arr.map(generateEnumSchema), Arr.join(\"\\n\"));\n\n// ============================================================================\n// Branded ID Templates\n// ============================================================================\n\nexport const generateBrandedIdSchema = ([, brandedIdName]: readonly [\n string,\n string\n]): string => dedent`\n export const ${brandedIdName} = Schema.String.pipe(Schema.brand(\"${brandedIdName}\"))\n export type ${brandedIdName} = typeof ${brandedIdName}.Type\n`;\n\nexport const generateBrandedIdSchemas = (\n brandedIds: HashMap.HashMap<string, string>\n): string =>\n pipe(\n brandedIds,\n HashMap.toEntries,\n Arr.sort(Order.mapInput(Order.string, ([key]: [string, string]) => key)),\n Arr.map(generateBrandedIdSchema),\n Arr.join(\"\\n\\n\")\n );\n\n// ============================================================================\n// Field Templates\n// ============================================================================\n\nexport const generateFieldsCode = (\n fields: readonly DMMF.Field[],\n resolver: SchemaResolver,\n sortFields: boolean\n): string =>\n pipe(\n sortFields ? sortByName(fields) : fields,\n Arr.map((field) => ` ${field.name}: ${resolver.fieldToSchema(field)}`),\n Arr.join(\",\\n\")\n );\n\n// ============================================================================\n// Model Templates\n// ============================================================================\n\nexport const generateModelSchema = (\n model: DMMF.Model,\n resolver: SchemaResolver,\n config: GeneratorConfig\n): string => {\n const scalarFields = model.fields.filter((f) => f.kind !== \"object\");\n const hasRelations = model.fields.some((f) => f.kind === \"object\");\n\n const scalarFieldsCode = generateFieldsCode(\n scalarFields,\n resolver,\n config.sortFields\n );\n\n const baseSchema = [\n `export const ${model.name} = Schema.Struct({`,\n scalarFieldsCode,\n `})`,\n `export type ${model.name} = typeof ${model.name}.Type`,\n ].join(\"\\n\");\n\n // Optionally generate schema with relations\n if (!config.includeRelations || !hasRelations) {\n return baseSchema;\n }\n\n const allFieldsCode = generateFieldsCode(\n model.fields,\n resolver,\n config.sortFields\n );\n\n const withRelationsSchema = [\n `export const ${model.name}WithRelations = Schema.Struct({`,\n allFieldsCode,\n `})`,\n `export type ${model.name}WithRelations = typeof ${model.name}WithRelations.Type`,\n ].join(\"\\n\");\n\n return `${baseSchema}\\n\\n${withRelationsSchema}`;\n};\n\nexport const generateModelSchemas = (\n models: readonly DMMF.Model[],\n makeResolver: (modelName: string) => SchemaResolver,\n config: GeneratorConfig\n): string =>\n pipe(\n sortByName(models),\n Arr.map((model) => generateModelSchema(model, makeResolver(model.name), config)),\n Arr.join(\"\\n\")\n );\n","/**\n * Effect Schema Code Generation\n *\n * Orchestrates generation of Effect Schema source code from Prisma DMMF.\n */\nimport type { DMMF } from \"@prisma/generator-helper\";\nimport { HashMap } from \"effect\";\nimport type { GeneratorConfig } from \"./config.js\";\nimport { buildForeignKeyMap, collectBrandedIds, SchemaResolver } from \"./resolver.js\";\nimport {\n DEFAULT_HEADER,\n generateBrandedIdSchemas,\n generateEnumSchemas,\n generateModelSchemas,\n JSON_VALUE_SCHEMA,\n sectionHeader,\n} from \"./templates.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GenerateInput {\n dmmf: DMMF.Document;\n config: GeneratorConfig;\n}\n\nexport interface GenerateOutput {\n content: string;\n stats: {\n enumCount: number;\n modelCount: number;\n brandedIdCount: number;\n };\n}\n\n// ============================================================================\n// Main Entry Point\n// ============================================================================\n\n/**\n * Generates Effect Schema source code from Prisma DMMF.\n */\nexport const generate = (input: GenerateInput): GenerateOutput => {\n const { dmmf, config } = input;\n const { models, enums } = dmmf.datamodel;\n\n // Collect branded IDs from models with string primary keys\n const brandedIds = config.useBrandedIds\n ? collectBrandedIds(models)\n : HashMap.empty<string, string>();\n\n // Build FK map from relation metadata\n const foreignKeys = buildForeignKeyMap(models);\n\n const brandedIdCount = HashMap.size(brandedIds);\n\n // Check if any model has Json fields (to conditionally include JsonValueSchema)\n const hasJsonFields = models.some((model) =>\n model.fields.some((field) => field.type === \"Json\")\n );\n\n // Factory for creating resolvers per model\n const makeResolver = (modelName: string) =>\n SchemaResolver.make({ modelName, brandedIds, foreignKeys, config });\n\n // Assemble sections\n const sections = [\n // Header\n config.customHeader ?? DEFAULT_HEADER,\n\n // JSON schema (only if needed)\n ...(hasJsonFields ? [\"\\n\" + JSON_VALUE_SCHEMA] : []),\n\n // Enums\n ...(enums.length > 0\n ? [sectionHeader(\"Enums\"), generateEnumSchemas(enums)]\n : []),\n\n // Branded IDs\n ...(brandedIdCount > 0\n ? [sectionHeader(\"Branded IDs\"), generateBrandedIdSchemas(brandedIds)]\n : []),\n\n // Models\n sectionHeader(\"Models (scalar fields only)\"),\n generateModelSchemas(models, makeResolver, config),\n ];\n\n return {\n content: sections.join(\"\\n\"),\n stats: {\n enumCount: enums.length,\n modelCount: models.length,\n brandedIdCount,\n },\n };\n};\n"],"mappings":";AACA,SAAS,SAAS,KAAK,QAAQ,MAAM,cAAc;AAKnD,IAAM,cAAc,CAAC,UACnB,KAAK,OAAO,IAAI,QAAQ,IAAI,IAAI;AAKlC,IAAM,oBAAoB,OAAO;AAAA,EAC/B,OAAO,MAAM,OAAO,QAAQ,OAAO,MAAM,OAAO,MAAM,CAAC;AAAA,EACvD,OAAO;AAAA,EACP;AAAA,IACE,QAAQ,CAAC,UAAU,KAAK,OAAO,aAAa,OAAO,IAAI,CAAC,MAAM,MAAM,MAAM,GAAG,OAAO,UAAU,MAAM,KAAK,CAAC;AAAA,IAC1G,QAAQ,CAAC,MAAO,IAAI,SAAS;AAAA,EAC/B;AACF;AAKA,IAAM,mBAAmB,OAAO;AAAA,EAC9B,OAAO,MAAM,OAAO,QAAQ,OAAO,MAAM,OAAO,MAAM,CAAC;AAAA,EACvD,OAAO,QAAQ,QAAQ,gBAAgB;AAAA,EACvC;AAAA,IACE,QAAQ,CAAC,UACP;AAAA,MACE;AAAA,MACA;AAAA,MACA,OAAO,OAAO,CAAC,MAAM,MAAM,gBAAgB;AAAA,MAC3C,OAAO,IAAI,MAAM,gBAAyB;AAAA,MAC1C,OAAO,UAAU,MAAM,MAAe;AAAA,IACxC;AAAA,IACF,QAAQ,CAAC,MAAM;AAAA,EACjB;AACF;AAMO,IAAM,wBAAwB,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjD,kBAAkB,OAAO,aAAa,mBAAmB;AAAA,IACvD,SAAS,MAAM;AAAA,EACjB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOD,eAAe,OAAO,aAAa,mBAAmB;AAAA,IACpD,SAAS,MAAM;AAAA,EACjB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQD,kBAAkB,OAAO,aAAa,kBAAkB;AAAA,IACtD,SAAS,MAAM;AAAA,EACjB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMD,YAAY,OAAO,aAAa,mBAAmB;AAAA,IACjD,SAAS,MAAM;AAAA,EACjB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMD,cAAc,OAAO;AAAA,IACnB,OAAO;AAAA,MACL,OAAO,MAAM,OAAO,QAAQ,OAAO,MAAM,OAAO,MAAM,CAAC;AAAA,MACvD,OAAO,OAAO,OAAO,MAAM;AAAA,MAC3B;AAAA,QACE,QAAQ,CAAC,UAAU,KAAK,OAAO,aAAa,OAAO,UAAU,MAAM,IAAqB,CAAC;AAAA,QACzF,QAAQ,CAAC,MAAM,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA,EAAE,SAAS,MAAM,KAAK;AAAA,EACxB;AACF,CAAC;AAYM,IAAM,cAAc,CAAC,YAC1B,OAAO,cAAc,qBAAqB,EAAE,QAAQ,UAAU,MAAM;;;AC7GtE,OAAO,YAAY;AACnB,SAAS,UAAAA,eAAc;AAEhB,IAAM,SAAS;AAKf,IAAM,uBAAN,cAAmCA,QAAO,YAAkC;AAAA,EACjF;AAAA,EACA;AAAA,IACE,UAAUA,QAAO;AAAA,IACjB,WAAWA,QAAO;AAAA,IAClB,WAAWA,QAAO;AAAA,EACpB;AACF,EAAE;AAAA,EACA,IAAa,UAAkB;AAC7B,WAAO;AAAA,QACH,MAAM,6BAA6B,KAAK,QAAQ,gBAAgB,KAAK,SAAS,eAAe,KAAK,SAAS;AAAA;AAAA;AAAA,EAGjH;AACF;AAEO,IAAM,0BAAN,cAAsCA,QAAO,YAAqC;AAAA,EACvF;AAAA,EACA;AAAA,IACE,OAAOA,QAAO;AAAA,IACd,SAASA,QAAO;AAAA,EAClB;AACF,EAAE;AAAA,EACA,OAAc,UAAU,GAAG,MAAM;AACnC;;;AC1BA,SAAS,aAAa;AAMf,IAAM,eAAe,CAAC,SAC3B,MAAM,MAAM,IAAI,EAAE;AAAA,EAChB,MAAM;AAAA,IAAI;AAAA,IAAa,CAAC,EAAE,OAAO,MAC/B,WAAW,SAAS,oBAAoB,UAAU,MAAM;AAAA,EAC1D;AAAA,EACA,MAAM,IAAI,aAAa,CAAC,EAAE,KAAK,MAAM,IAAI;AAAA,EACzC,MAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,MAAM,IAAI;AAAA,EACpC,MAAM,IAAI,YAAY,CAAC,EAAE,UAAU,MAAM,wBAAwB,SAAS,GAAG;AAAA,EAC7E,MAAM;AACR;AAKK,IAAM,eAAe,CAAC,OAAe,YAA6B;AACvE,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,gBAAgB,KAAK;AAAA,IAC9B,KAAK;AACH,aAAO,iBAAiB,KAAK;AAAA,EACjC;AACF;AAMO,IAAM,OAAO,CAAC,SACnB,KAAK,SAAS,OAAO,cAAc,aAAa,KAAK,IAAI,CAAC;;;AChC5D;AAAA,EACE,SAASC;AAAA,EACT;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAYpB,IAAM,YAAN,cAAwB,KAAK,YAAY,WAAW,EAYxD;AAAC;AAKG,IAAM,YAAN,cAAwB,KAAK,YAAY,WAAW,EAExD;AAAC;AAKG,IAAM,OAAN,cAAmB,KAAK,YAAY,MAAM,EAE9C;AAAC;AAKG,IAAM,WAAN,cAAuB,KAAK,YAAY,UAAU,EAEtD;AAAC;AAeG,IAAM,eAAN,cAA2B,KAAK,MAGpC;AAAC;AAqCJ,IAAM,gBAAgE;AAAA,EACpE,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AACX;AAYO,IAAM,oBAAoB,CAC/B,WAEAC;AAAA,EACE;AAAA,EACAC,KAAI,UAAU,CAAC,UAAU;AACvB,UAAM,UAAU,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,QAAQ;AACtE,QAAI,CAAC,QAAS,QAAOC,QAAO,KAAK;AAGjC,UAAM,SAAS,WAAW,QAAQ,IAAI;AACtC,WAAOA,QAAO,KAAK,CAAC,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,MAAM,EAAE,CAAU;AAAA,EACpE,CAAC;AAAA,EACD,QAAQ;AACV;AAkBK,IAAM,qBAAqB,CAChC,WAEAF;AAAA,EACE;AAAA,EACAC,KAAI;AAAA,IAAQ,CAAC,UACXD;AAAA,MACE,MAAM;AAAA,MACNC,KAAI,OAAO,CAAC,UAAU,MAAM,SAAS,QAAQ;AAAA,MAC7CA,KAAI,QAAQ,CAAC,kBAAkB;AAE7B,cAAM,WAAW,cAAc,sBAAsB,CAAC;AAEtD,cAAM,cAAc,cAAc;AAElC,eAAO,SAAS,IAAI,CAAC,YAAY,CAAC,SAAS,WAAW,CAAU;AAAA,MAClE,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EACA,QAAQ;AACV;AAiBK,IAAM,iBAAiB;AAAA,EAC5B,MAAM,CAAC,mBAAyD;AAC9D,UAAM,EAAE,WAAW,YAAY,aAAa,OAAO,IAAI;AAMvD,UAAM,mBAAmB,CAAC,UAA6C;AACrE,UAAI,CAAC,OAAO,cAAe,QAAOC,QAAO,KAAK;AAG9C,UAAI,MAAM,MAAM;AACd,eAAO,QAAQ,IAAI,YAAY,SAAS;AAAA,MAC1C;AAGA,aAAOF;AAAA,QACL,QAAQ,IAAI,aAAa,MAAM,IAAI;AAAA,QACnCE,QAAO,QAAQ,CAAC,gBAAgB,QAAQ,IAAI,YAAY,WAAW,CAAC;AAAA,MACtE;AAAA,IACF;AAMA,UAAM,oBAAoB,CAAC,UAAgC;AAEzD,UAAI,MAAM,SAAS,YAAY;AAC7B,eAAO,IAAI,UAAU;AAAA,UACnB,QAAQ,OAAO,qBAAqB,mBAAmB,gBAAgB;AAAA,QACzE,CAAC;AAAA,MACH;AAGA,YAAM,UAAU,OAAO,IAAI,eAAe,MAAM,IAAI;AACpD,UAAIA,QAAO,OAAO,OAAO,GAAG;AAC1B,eAAO,IAAI,UAAU,EAAE,QAAQ,QAAQ,MAAM,CAAC;AAAA,MAChD;AAGA,UAAI,MAAM,SAAS,UAAU;AAC3B,eAAOF;AAAA,UACL,iBAAiB,KAAK;AAAA,UACtBE,QAAO,MAAM;AAAA,YACX,QAAQ,MAAM,IAAI,UAAU,EAAE,QAAQ,SAAS,CAAC;AAAA,YAChD,QAAQ,CAAC,SAAS,IAAI,UAAU,EAAE,KAAK,CAAC;AAAA,UAC1C,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,IAAI,qBAAqB;AAAA,QAC7B,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,kBAAkB,CAAC,UAAgC;AACvD,cAAQ,MAAM,MAAM;AAAA,QAClB,KAAK;AACH,iBAAO,IAAI,KAAK,EAAE,MAAM,MAAM,KAAK,CAAC;AAAA,QACtC,KAAK;AACH,iBAAO,IAAI,SAAS,EAAE,WAAW,MAAM,KAAK,CAAC;AAAA,QAC/C;AACE,iBAAO,kBAAkB,KAAK;AAAA,MAClC;AAAA,IACF;AAMA,UAAM,UAAU,CAAC,UAAoC;AACnD,YAAM,WAAsB,CAAC;AAE7B,UAAI,MAAM,QAAQ;AAChB,iBAAS,KAAK,OAAO;AAAA,MACvB;AAEA,UAAI,CAAC,MAAM,YAAY;AACrB,iBAAS,KAAK,QAAQ;AAAA,MACxB;AAEA,aAAO,IAAI,aAAa;AAAA,QACtB,MAAM,gBAAgB,KAAK;AAAA,QAC3B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,CAAC,UAA8B,KAAK,QAAQ,KAAK,CAAC;AAExE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACzSA,OAAOC,aAAY;AACnB,SAAS,SAASC,MAAK,WAAAC,UAAS,OAAO,QAAAC,aAAY;AAQ5C,IAAM,iBAAiBH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQvB,IAAM,oBAAoBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuB1B,IAAM,gBAAgB,CAAC,UAA0BA;AAAA;AAAA,OAEjD,KAAK;AAAA;AAAA;AAIZ,IAAM,SAAS,MACb,MAAM,SAAS,MAAM,QAAQ,CAAC,SAAY,KAAK,IAAI;AAErD,IAAM,aAAa,CAA6B,UAC9CC,KAAI,KAAK,OAAO,OAAO,CAAC;AAMnB,IAAM,qBAAqB,CAAC,YAAwC;AACzE,QAAM,SAASE;AAAA,IACb,WAAW,QAAQ,MAAM;AAAA,IACzBF,KAAI,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,GAAG;AAAA,IAC5BA,KAAI,KAAK,IAAI;AAAA,EACf;AAEA,SAAOD;AAAA,mBACU,QAAQ,IAAI,qBAAqB,MAAM;AAAA,kBACxC,QAAQ,IAAI,aAAa,QAAQ,IAAI;AAAA;AAEvD;AAEO,IAAM,sBAAsB,CACjC,UAEAG,MAAK,WAAW,KAAK,GAAGF,KAAI,IAAI,kBAAkB,GAAGA,KAAI,KAAK,IAAI,CAAC;AAM9D,IAAM,0BAA0B,CAAC,CAAC,EAAE,aAAa,MAG1CD;AAAA,iBACG,aAAa,uCAAuC,aAAa;AAAA,gBAClE,aAAa,aAAa,aAAa;AAAA;AAGhD,IAAM,2BAA2B,CACtC,eAEAG;AAAA,EACE;AAAA,EACAD,SAAQ;AAAA,EACRD,KAAI,KAAK,MAAM,SAAS,MAAM,QAAQ,CAAC,CAAC,GAAG,MAAwB,GAAG,CAAC;AAAA,EACvEA,KAAI,IAAI,uBAAuB;AAAA,EAC/BA,KAAI,KAAK,MAAM;AACjB;AAMK,IAAM,qBAAqB,CAChC,QACA,UACA,eAEAE;AAAA,EACE,aAAa,WAAW,MAAM,IAAI;AAAA,EAClCF,KAAI,IAAI,CAAC,UAAU,KAAK,MAAM,IAAI,KAAK,SAAS,cAAc,KAAK,CAAC,EAAE;AAAA,EACtEA,KAAI,KAAK,KAAK;AAChB;AAMK,IAAM,sBAAsB,CACjC,OACA,UACA,WACW;AACX,QAAM,eAAe,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AACnE,QAAM,eAAe,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAEjE,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,EACT;AAEA,QAAM,aAAa;AAAA,IACjB,gBAAgB,MAAM,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,eAAe,MAAM,IAAI,aAAa,MAAM,IAAI;AAAA,EAClD,EAAE,KAAK,IAAI;AAGX,MAAI,CAAC,OAAO,oBAAoB,CAAC,cAAc;AAC7C,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB;AAAA,IACpB,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,EACT;AAEA,QAAM,sBAAsB;AAAA,IAC1B,gBAAgB,MAAM,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,eAAe,MAAM,IAAI,0BAA0B,MAAM,IAAI;AAAA,EAC/D,EAAE,KAAK,IAAI;AAEX,SAAO,GAAG,UAAU;AAAA;AAAA,EAAO,mBAAmB;AAChD;AAEO,IAAM,uBAAuB,CAClC,QACA,cACA,WAEAE;AAAA,EACE,WAAW,MAAM;AAAA,EACjBF,KAAI,IAAI,CAAC,UAAU,oBAAoB,OAAO,aAAa,MAAM,IAAI,GAAG,MAAM,CAAC;AAAA,EAC/EA,KAAI,KAAK,IAAI;AACf;;;ACxKF,SAAS,WAAAG,gBAAe;AAqCjB,IAAM,WAAW,CAAC,UAAyC;AAChE,QAAM,EAAE,MAAM,OAAO,IAAI;AACzB,QAAM,EAAE,QAAQ,MAAM,IAAI,KAAK;AAG/B,QAAM,aAAa,OAAO,gBACtB,kBAAkB,MAAM,IACxBC,SAAQ,MAAsB;AAGlC,QAAM,cAAc,mBAAmB,MAAM;AAE7C,QAAM,iBAAiBA,SAAQ,KAAK,UAAU;AAG9C,QAAM,gBAAgB,OAAO;AAAA,IAAK,CAAC,UACjC,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,MAAM;AAAA,EACpD;AAGA,QAAM,eAAe,CAAC,cACpB,eAAe,KAAK,EAAE,WAAW,YAAY,aAAa,OAAO,CAAC;AAGpE,QAAM,WAAW;AAAA;AAAA,IAEf,OAAO,gBAAgB;AAAA;AAAA,IAGvB,GAAI,gBAAgB,CAAC,OAAO,iBAAiB,IAAI,CAAC;AAAA;AAAA,IAGlD,GAAI,MAAM,SAAS,IACf,CAAC,cAAc,OAAO,GAAG,oBAAoB,KAAK,CAAC,IACnD,CAAC;AAAA;AAAA,IAGL,GAAI,iBAAiB,IACjB,CAAC,cAAc,aAAa,GAAG,yBAAyB,UAAU,CAAC,IACnE,CAAC;AAAA;AAAA,IAGL,cAAc,6BAA6B;AAAA,IAC3C,qBAAqB,QAAQ,cAAc,MAAM;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,SAAS,SAAS,KAAK,IAAI;AAAA,IAC3B,OAAO;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;","names":["Schema","Arr","Option","pipe","pipe","Arr","Option","dedent","Arr","HashMap","pipe","HashMap","HashMap"]}
package/dist/generator.js CHANGED
@@ -1,3 +1,3 @@
1
- import "./chunk-FMT4NBCL.js";
2
- import "./chunk-25MM3WYP.js";
1
+ import "./chunk-4XK2MZLU.js";
2
+ import "./chunk-EB2BVI3Q.js";
3
3
  //# sourceMappingURL=generator.js.map
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  generateModelSchema,
24
24
  generateModelSchemas,
25
25
  sectionHeader
26
- } from "./chunk-25MM3WYP.js";
26
+ } from "./chunk-EB2BVI3Q.js";
27
27
  export {
28
28
  BrandedId,
29
29
  DEFAULT_HEADER,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-effect-schema",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Prisma generator that creates Effect Schemas from your Prisma models",
5
5
  "keywords": [
6
6
  "prisma",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/emit.ts","../src/resolver.ts","../src/templates.ts","../src/generate.ts"],"sourcesContent":["import type { GeneratorOptions } from \"@prisma/generator-helper\";\nimport { Array as Arr, Option, pipe, Schema } from \"effect\";\n\n/**\n * Prisma config values can be string | string[] - normalize to first string\n */\nconst firstString = (value: string | readonly string[]): Option.Option<string> =>\n pipe(value, Arr.ensure, Arr.head);\n\n/**\n * Schema for parsing \"true\"/\"false\" strings to booleans (handles string | string[])\n */\nconst BooleanFromString = Schema.transform(\n Schema.Union(Schema.String, Schema.Array(Schema.String)),\n Schema.Boolean,\n {\n decode: (value) => pipe(value, firstString, Option.map((s) => s === \"true\"), Option.getOrElse(() => false)),\n encode: (b) => (b ? \"true\" : \"false\"),\n }\n);\n\n/**\n * Schema for DateTime handling mode (handles string | string[])\n */\nconst DateTimeHandling = Schema.transform(\n Schema.Union(Schema.String, Schema.Array(Schema.String)),\n Schema.Literal(\"Date\", \"DateTimeString\"),\n {\n decode: (value) =>\n pipe(\n value,\n firstString,\n Option.filter((s) => s === \"DateTimeString\"),\n Option.map(() => \"DateTimeString\" as const),\n Option.getOrElse(() => \"Date\" as const)\n ),\n encode: (s) => s,\n }\n);\n\n/**\n * Generator configuration schema with defaults.\n * Parses Prisma generator config and applies defaults in one step.\n */\nexport const GeneratorConfigSchema = Schema.Struct({\n /**\n * Whether to include relation fields in the generated schemas.\n * Relations use Schema.suspend() for lazy evaluation to handle circular deps.\n * @default false\n */\n includeRelations: Schema.optionalWith(BooleanFromString, {\n default: () => false,\n }),\n\n /**\n * Whether to generate branded ID types for models with string IDs.\n * When true, generates `UserId`, `PostId`, etc. and uses them in model schemas.\n * @default true\n */\n useBrandedIds: Schema.optionalWith(BooleanFromString, {\n default: () => true,\n }),\n\n /**\n * How to handle DateTime fields.\n * - 'Date': Use Schema.Date (expects Date objects, for Prisma results)\n * - 'DateTimeString': Use Schema.Date with dateTime annotation (for API validation)\n * @default 'Date'\n */\n dateTimeHandling: Schema.optionalWith(DateTimeHandling, {\n default: () => \"Date\" as const,\n }),\n\n /**\n * Whether to sort fields alphabetically for deterministic output.\n * @default true\n */\n sortFields: Schema.optionalWith(BooleanFromString, {\n default: () => true,\n }),\n\n /**\n * Custom header to prepend to the generated file.\n * If not provided, uses a default header without timestamps.\n */\n customHeader: Schema.optionalWith(\n Schema.transform(\n Schema.Union(Schema.String, Schema.Array(Schema.String)),\n Schema.NullOr(Schema.String),\n {\n decode: (value) => pipe(value, firstString, Option.getOrElse(() => null as string | null)),\n encode: (s) => s ?? \"\",\n }\n ),\n { default: () => null }\n ),\n});\n\n/**\n * Resolved configuration type (derived from schema)\n */\nexport type GeneratorConfig = typeof GeneratorConfigSchema.Type;\n\n\n\n/**\n * Parse generator config from Prisma schema using Effect Schema\n */\nexport const parseConfig = (options: GeneratorOptions) =>\n Schema.decodeUnknown(GeneratorConfigSchema)(options.generator.config);\n","import dedent from \"dedent\";\nimport { Schema } from \"effect\";\n\nexport const AppTag = \"[prisma-effect-schema]\";\n\n/**\n * Error thrown when an unsupported Prisma type is encountered\n */\nexport class UnsupportedTypeError extends Schema.TaggedError<UnsupportedTypeError>()(\n \"UnsupportedTypeError\",\n {\n typeName: Schema.String,\n fieldName: Schema.String,\n modelName: Schema.String,\n },\n) {\n override get message(): string {\n return dedent`\n ${AppTag} Unsupported Prisma type \"${this.typeName}\" for field \"${this.fieldName}\" in model \"${this.modelName}\". \n Please open an issue at https://github.com/frontcore/prisma-effect-schema/issues\n `;\n }\n}\n\nexport class NoOutputConfiguredError extends Schema.TaggedError<NoOutputConfiguredError>()(\n \"NoOutputConfiguredError\",\n {\n cause: Schema.Unknown,\n details: Schema.String,\n },\n) {\n public static message = `${AppTag} No output path specified in generator config`;\n}\n\nexport const ConfigError = NoOutputConfiguredError;\n","/**\n * Code Emission Module\n *\n * Pure functions for transforming resolved types into Effect Schema strings.\n * Separated from resolution logic for testability and reusability.\n */\nimport { Match } from \"effect\";\nimport type { BaseType, ResolvedType, Wrapper } from \"./resolver.js\";\n\n/**\n * Emit a base type to its Effect Schema string representation\n */\nexport const emitBaseType = (base: BaseType): string =>\n Match.value(base).pipe(\n Match.tag(\"Primitive\", ({ schema }) =>\n schema === \"Json\" ? \"JsonValueSchema\" : `Schema.${schema}`\n ),\n Match.tag(\"BrandedId\", ({ name }) => name),\n Match.tag(\"Enum\", ({ name }) => name),\n Match.tag(\"Relation\", ({ modelName }) => `Schema.suspend(() => ${modelName})`),\n Match.exhaustive\n );\n\n/**\n * Apply a single wrapper to a schema string\n */\nexport const applyWrapper = (inner: string, wrapper: Wrapper): string => {\n switch (wrapper) {\n case \"Array\":\n return `Schema.Array(${inner})`;\n case \"NullOr\":\n return `Schema.NullOr(${inner})`;\n }\n};\n\n/**\n * Emit a fully resolved type (base + wrappers) to Effect Schema string.\n * Wrappers are applied left-to-right (innermost first).\n */\nexport const emit = (type: ResolvedType): string =>\n type.wrappers.reduce(applyWrapper, emitBaseType(type.base));\n","/**\n * Type Resolution Module\n *\n * Separates the \"thinking\" (what type should this field be?) from the \"writing\"\n * (how do we emit it as a string?). Returns structured data that can be tested,\n * logged, and transformed before emission.\n */\nimport type { DMMF } from \"@prisma/generator-helper\";\nimport {\n Array as Arr,\n Data,\n HashMap,\n Option,\n pipe,\n Record,\n} from \"effect\";\nimport { capitalize } from \"effect/String\";\nimport type { GeneratorConfig } from \"./config.js\";\nimport { emit } from \"./emit.js\";\nimport { UnsupportedTypeError } from \"./errors.js\";\n\n// ============================================================================\n// Resolved Types (Data.TaggedClass for structural equality + pattern matching)\n// ============================================================================\n\n/**\n * A primitive scalar type from Prisma mapped to Effect Schema\n */\nexport class Primitive extends Data.TaggedClass(\"Primitive\")<{\n readonly schema:\n | \"Int\"\n | \"String\"\n | \"Boolean\"\n | \"Number\"\n | \"Date\" // Schema.Date - for Prisma results (Date objects)\n | \"DateTimeUtc\" // Schema.DateTimeUtc - for API validation (ISO strings)\n | \"BigInt\"\n | \"Uint8Array\"\n | \"Json\"\n | \"Decimal\";\n}> {}\n\n/**\n * A branded ID type for type-safe IDs\n */\nexport class BrandedId extends Data.TaggedClass(\"BrandedId\")<{\n readonly name: string;\n}> {}\n\n/**\n * An enum type reference\n */\nexport class Enum extends Data.TaggedClass(\"Enum\")<{\n readonly name: string;\n}> {}\n\n/**\n * A relation to another model (uses Schema.suspend for circular refs)\n */\nexport class Relation extends Data.TaggedClass(\"Relation\")<{\n readonly modelName: string;\n}> {}\n\n/**\n * Union of all possible base types a field can resolve to\n */\nexport type BaseType = Primitive | BrandedId | Enum | Relation;\n\n/**\n * Wrappers that can be applied to a base type\n */\nexport type Wrapper = \"Array\" | \"NullOr\";\n\n/**\n * A fully resolved field type: base type + wrappers to apply\n */\nexport class ResolvedType extends Data.Class<{\n readonly base: BaseType;\n readonly wrappers: readonly Wrapper[];\n}> {}\n\n// ============================================================================\n// SchemaResolver Interface\n// ============================================================================\n\nexport interface SchemaResolver {\n /**\n * Resolve a field to its structured type representation.\n * Use this for testing or when you need to inspect the decision.\n */\n readonly resolve: (field: DMMF.Field) => ResolvedType;\n\n /**\n * Convenience method: resolve + emit in one call.\n * Use this for the common case where you just need the string.\n */\n readonly fieldToSchema: (field: DMMF.Field) => string;\n\n /**\n * The computed branded IDs map (modelName -> brandedIdName).\n * Exposed for generating branded ID schema declarations.\n */\n readonly brandedIds: HashMap.HashMap<string, string>;\n}\n\n// ============================================================================\n// Internal: Scalar Type Mapping\n// ============================================================================\n\ntype PrimitiveSchema = Primitive[\"schema\"];\n\n/**\n * Maps Prisma scalar types to Primitive schema names.\n * Note: String is handled separately (may become BrandedId).\n * Note: DateTime is handled separately (respects dateTimeHandling config).\n */\nconst ScalarTypeMap: Record.ReadonlyRecord<string, PrimitiveSchema> = {\n Int: \"Int\",\n Float: \"Number\",\n Boolean: \"Boolean\",\n Json: \"Json\",\n Bytes: \"Uint8Array\",\n BigInt: \"BigInt\",\n Decimal: \"Decimal\",\n};\n\n// ============================================================================\n// Branded ID Collection (uses actual PK field name for suffix)\n// ============================================================================\n\n/**\n * Collects branded IDs for models with string primary keys.\n * Uses the actual PK field name for the suffix:\n * - User.id (String @id) -> \"UserId\"\n * - Course.slug (String @id) -> \"CourseSlug\"\n */\nexport const collectBrandedIds = (\n models: readonly DMMF.Model[]\n): HashMap.HashMap<string, string> =>\n pipe(\n models,\n Arr.filterMap((model) => {\n const pkField = model.fields.find((f) => f.isId && f.type === \"String\");\n if (!pkField) return Option.none();\n \n // Use the PK field name, capitalized: \"id\" -> \"Id\", \"slug\" -> \"Slug\"\n const suffix = capitalize(pkField.name);\n return Option.some([model.name, `${model.name}${suffix}`] as const);\n }),\n HashMap.fromIterable\n );\n\n// ============================================================================\n// Foreign Key Map (relation-based, not heuristic)\n// ============================================================================\n\n/**\n * Builds a map from FK field names to their target model names.\n * Uses DMMF relation metadata (relationFromFields) for accuracy.\n * \n * Example output:\n * {\n * \"userId\": \"User\",\n * \"authorId\": \"User\",\n * \"courseSlug\": \"Course\",\n * \"avatarId\": \"File\"\n * }\n */\nexport const buildForeignKeyMap = (\n models: readonly DMMF.Model[]\n): HashMap.HashMap<string, string> =>\n pipe(\n models,\n Arr.flatMap((model) =>\n pipe(\n model.fields,\n Arr.filter((field) => field.kind === \"object\"),\n Arr.flatMap((relationField) => {\n // relationFromFields contains the FK field names for this relation\n const fkFields = relationField.relationFromFields ?? [];\n // The relation's type is the target model name\n const targetModel = relationField.type;\n \n return fkFields.map((fkField) => [fkField, targetModel] as const);\n })\n )\n ),\n HashMap.fromIterable\n );\n\n// ============================================================================\n// SchemaResolver Factory\n// ============================================================================\n\nexport interface SchemaResolverConfig {\n readonly modelName: string;\n readonly brandedIds: HashMap.HashMap<string, string>;\n readonly foreignKeys: HashMap.HashMap<string, string>;\n readonly config: GeneratorConfig;\n}\n\n/**\n * Create a SchemaResolver for a specific model.\n * Dependencies are captured at construction time.\n */\nexport const SchemaResolver = {\n make: (resolverConfig: SchemaResolverConfig): SchemaResolver => {\n const { modelName, brandedIds, foreignKeys, config } = resolverConfig;\n\n // ========================================================================\n // Branded ID Resolution (relation-based)\n // ========================================================================\n\n const resolveBrandedId = (field: DMMF.Field): Option.Option<string> => {\n if (!config.useBrandedIds) return Option.none();\n\n // Primary key uses this model's branded ID\n if (field.isId) {\n return HashMap.get(brandedIds, modelName);\n }\n\n // Foreign key - look up in FK map, then get target model's branded ID\n return pipe(\n HashMap.get(foreignKeys, field.name),\n Option.flatMap((targetModel) => HashMap.get(brandedIds, targetModel))\n );\n };\n\n // ========================================================================\n // Base Type Resolution\n // ========================================================================\n\n const resolveScalarType = (field: DMMF.Field): BaseType => {\n // Handle DateTime with config\n if (field.type === \"DateTime\") {\n return new Primitive({\n schema: config.dateTimeHandling === \"DateTimeString\" ? \"DateTimeUtc\" : \"Date\",\n });\n }\n\n // Check non-String scalar types\n const mapping = Record.get(ScalarTypeMap, field.type);\n if (Option.isSome(mapping)) {\n return new Primitive({ schema: mapping.value });\n }\n\n // String type: try branded ID, fallback to Primitive String\n if (field.type === \"String\") {\n return pipe(\n resolveBrandedId(field),\n Option.match({\n onNone: () => new Primitive({ schema: \"String\" }),\n onSome: (name) => new BrandedId({ name }),\n })\n );\n }\n\n throw new UnsupportedTypeError({\n typeName: field.type,\n fieldName: field.name,\n modelName,\n });\n };\n\n const resolveBaseType = (field: DMMF.Field): BaseType => {\n switch (field.kind) {\n case \"enum\":\n return new Enum({ name: field.type });\n case \"object\":\n return new Relation({ modelName: field.type });\n default:\n return resolveScalarType(field);\n }\n };\n\n // ========================================================================\n // Full Resolution (base + wrappers)\n // ========================================================================\n\n const resolve = (field: DMMF.Field): ResolvedType => {\n const wrappers: Wrapper[] = [];\n\n if (field.isList) {\n wrappers.push(\"Array\");\n }\n\n if (!field.isRequired) {\n wrappers.push(\"NullOr\");\n }\n\n return new ResolvedType({\n base: resolveBaseType(field),\n wrappers,\n });\n };\n\n const fieldToSchema = (field: DMMF.Field): string => emit(resolve(field));\n\n return {\n resolve,\n fieldToSchema,\n brandedIds,\n };\n },\n};\n","/**\n * Code Templates Module\n *\n * String templates for generating Effect Schema source code.\n * Separated from orchestration logic for clarity and testability.\n */\nimport type { DMMF } from \"@prisma/generator-helper\";\nimport dedent from \"dedent\";\nimport { Array as Arr, HashMap, Order, pipe } from \"effect\";\nimport type { GeneratorConfig } from \"./config.js\";\nimport type { SchemaResolver } from \"./resolver.js\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nexport const DEFAULT_HEADER = dedent`\n // This file was auto-generated by prisma-effect-schema\n // Do not edit manually - changes will be overwritten\n // https://github.com/frontcore/prisma-effect-schema\n\n import { Schema } from \"effect\"\n`;\n\nexport const JSON_VALUE_SCHEMA = dedent`\n // Recursive JSON value schema matching Prisma's JsonValue type\n type JsonValue = string | number | boolean | null | JsonArray | JsonObject\n type JsonArray = ReadonlyArray<JsonValue>\n type JsonObject = { readonly [key: string]: JsonValue }\n\n const JsonValueSchema: Schema.Schema<JsonValue> = Schema.suspend(\n (): Schema.Schema<JsonValue> =>\n Schema.Union(\n Schema.Null,\n Schema.Boolean,\n Schema.Number,\n Schema.String,\n Schema.Array(JsonValueSchema),\n Schema.Record({ key: Schema.String, value: JsonValueSchema })\n )\n )\n`;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nexport const sectionHeader = (title: string): string => dedent`\n // ============================================================================\n // ${title}\n // ============================================================================\n\n`;\n\nconst ByName = <T extends { name: string }>(): Order.Order<T> =>\n Order.mapInput(Order.string, (item: T) => item.name);\n\nconst sortByName = <T extends { name: string }>(items: readonly T[]): T[] =>\n Arr.sort(items, ByName());\n\n// ============================================================================\n// Enum Templates\n// ============================================================================\n\nexport const generateEnumSchema = (enumDef: DMMF.DatamodelEnum): string => {\n const values = pipe(\n sortByName(enumDef.values),\n Arr.map((v) => `\"${v.name}\"`),\n Arr.join(\", \")\n );\n\n return dedent`\n export const ${enumDef.name} = Schema.Literal(${values})\n export type ${enumDef.name} = typeof ${enumDef.name}.Type\n `;\n};\n\nexport const generateEnumSchemas = (\n enums: readonly DMMF.DatamodelEnum[]\n): string =>\n pipe(sortByName(enums), Arr.map(generateEnumSchema), Arr.join(\"\\n\"));\n\n// ============================================================================\n// Branded ID Templates\n// ============================================================================\n\nexport const generateBrandedIdSchema = ([, brandedIdName]: readonly [\n string,\n string\n]): string =>\n dedent`\n export const ${brandedIdName} = Schema.String.pipe(Schema.brand(\"${brandedIdName}\"))\n export type ${brandedIdName} = typeof ${brandedIdName}.Type\n `;\n\nexport const generateBrandedIdSchemas = (\n brandedIds: HashMap.HashMap<string, string>\n): string =>\n pipe(\n brandedIds,\n HashMap.toEntries,\n Arr.sort(Order.mapInput(Order.string, ([key]: [string, string]) => key)),\n Arr.map(generateBrandedIdSchema),\n Arr.join(\"\\n\\n\")\n );\n\n// ============================================================================\n// Field Templates\n// ============================================================================\n\nexport const generateFieldsCode = (\n fields: readonly DMMF.Field[],\n resolver: SchemaResolver,\n sortFields: boolean\n): string =>\n pipe(\n sortFields ? sortByName(fields) : fields,\n Arr.map((field) => ` ${field.name}: ${resolver.fieldToSchema(field)}`),\n Arr.join(\",\\n\")\n );\n\n// ============================================================================\n// Model Templates\n// ============================================================================\n\nexport const generateModelSchema = (\n model: DMMF.Model,\n resolver: SchemaResolver,\n config: GeneratorConfig\n): string => {\n const scalarFields = model.fields.filter((f) => f.kind !== \"object\");\n const hasRelations = model.fields.some((f) => f.kind === \"object\");\n\n const scalarFieldsCode = generateFieldsCode(\n scalarFields,\n resolver,\n config.sortFields\n );\n\n const baseSchema = dedent`\n export const ${model.name} = Schema.Struct({\n ${scalarFieldsCode}\n })\n export type ${model.name} = typeof ${model.name}.Type\n `;\n\n // Optionally generate schema with relations\n if (!config.includeRelations || !hasRelations) {\n return baseSchema;\n }\n\n const allFieldsCode = generateFieldsCode(\n model.fields,\n resolver,\n config.sortFields\n );\n\n return dedent`\n ${baseSchema}\n\n export const ${model.name}WithRelations = Schema.Struct({\n ${allFieldsCode}\n })\n export type ${model.name}WithRelations = typeof ${model.name}WithRelations.Type\n `;\n};\n\nexport const generateModelSchemas = (\n models: readonly DMMF.Model[],\n makeResolver: (modelName: string) => SchemaResolver,\n config: GeneratorConfig\n): string =>\n pipe(\n sortByName(models),\n Arr.map((model) => generateModelSchema(model, makeResolver(model.name), config)),\n Arr.join(\"\\n\")\n );\n","/**\n * Effect Schema Code Generation\n *\n * Orchestrates generation of Effect Schema source code from Prisma DMMF.\n */\nimport type { DMMF } from \"@prisma/generator-helper\";\nimport { HashMap } from \"effect\";\nimport type { GeneratorConfig } from \"./config.js\";\nimport { buildForeignKeyMap, collectBrandedIds, SchemaResolver } from \"./resolver.js\";\nimport {\n DEFAULT_HEADER,\n generateBrandedIdSchemas,\n generateEnumSchemas,\n generateModelSchemas,\n JSON_VALUE_SCHEMA,\n sectionHeader,\n} from \"./templates.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface GenerateInput {\n dmmf: DMMF.Document;\n config: GeneratorConfig;\n}\n\nexport interface GenerateOutput {\n content: string;\n stats: {\n enumCount: number;\n modelCount: number;\n brandedIdCount: number;\n };\n}\n\n// ============================================================================\n// Main Entry Point\n// ============================================================================\n\n/**\n * Generates Effect Schema source code from Prisma DMMF.\n */\nexport const generate = (input: GenerateInput): GenerateOutput => {\n const { dmmf, config } = input;\n const { models, enums } = dmmf.datamodel;\n\n // Collect branded IDs from models with string primary keys\n const brandedIds = config.useBrandedIds\n ? collectBrandedIds(models)\n : HashMap.empty<string, string>();\n\n // Build FK map from relation metadata\n const foreignKeys = buildForeignKeyMap(models);\n\n const brandedIdCount = HashMap.size(brandedIds);\n\n // Check if any model has Json fields (to conditionally include JsonValueSchema)\n const hasJsonFields = models.some((model) =>\n model.fields.some((field) => field.type === \"Json\")\n );\n\n // Factory for creating resolvers per model\n const makeResolver = (modelName: string) =>\n SchemaResolver.make({ modelName, brandedIds, foreignKeys, config });\n\n // Assemble sections\n const sections = [\n // Header\n config.customHeader ?? DEFAULT_HEADER,\n\n // JSON schema (only if needed)\n ...(hasJsonFields ? [\"\\n\" + JSON_VALUE_SCHEMA] : []),\n\n // Enums\n ...(enums.length > 0\n ? [sectionHeader(\"Enums\"), generateEnumSchemas(enums)]\n : []),\n\n // Branded IDs\n ...(brandedIdCount > 0\n ? [sectionHeader(\"Branded IDs\"), generateBrandedIdSchemas(brandedIds), \"\"]\n : []),\n\n // Models\n sectionHeader(\"Models (scalar fields only)\"),\n generateModelSchemas(models, makeResolver, config),\n ];\n\n return {\n content: sections.join(\"\"),\n stats: {\n enumCount: enums.length,\n modelCount: models.length,\n brandedIdCount,\n },\n };\n};\n"],"mappings":"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","names":["Schema","Arr","Option","pipe","pipe","Arr","Option","dedent","Arr","HashMap","pipe","HashMap","HashMap"]}